prepare for atomic/nuclear modeset/pageflip
Subsystems (20)
cover prepare for atomic/nuclear modeset/pageflip
One more time, with feeling..
Previous revision of series:
http://lists.freedesktop.org/archives/dri-devel/2014-March/055806.html
And if you prefer, in git form:
http://cgit.freedesktop.org/~robclark/linux/log/?h=cold-fusiongit://people.freedesktop.org/~robclark/linux cold-fusion
This series does not include the actual atomic ioctl, but it does include all the needed infrastructure changes.
Compared to previous revision, I've split out drm_modeset_acquire_ctx from drm_atomic_state, so that we can ww acquire mode_config and crtc locks outside of atomic transactions. (Which keeps lockdep happy wrt. drm_modeset_lock_all().) I also got to the point in juggling things around where I wanted to let the compiler type checking do it's job, so 's/void *state/struct drm_atomic_state *state/g'.
At this point, I've tested this on i915 (few different generation laptops), radeon, and msm. And of course w/ ww debug (deadlock in- jection) enabled. So I think all the locking related paths should be covered.
I believe Thierry has tested a slighly older revision on tegra. I would of course appreciate more testing on other drivers for which I don't have the hw. But I think it is pretty much ready to go. I do still owe some docs updates, I will send some patches for that in the near future, but didn't want to hold up giving others a chance to start banging on this.
Rob Clark (14):
drm: fix typo
drm: add atomic fxns
drm: convert crtc and mode_config to ww_mutex
drm: add object property type
drm: add signed-range property type
drm: helpers to find mode objects
drm: split propvals out and blob property support
drm: allow FB's in drm_mode_object_find
drm: convert plane to properties/state
drm: convert crtc to properties/state
drm: push locking down into restore_fbdev_mode drm/msm: add atomic support
drm: spiff out FB refcnting traces
drm: more conservative locking
Sean Paul (1):
drm: Fix up the atomic legacy paths so they work
Ville Syrjälä (2):
drm: Allow drm_mode_object_find() to look up an object of any type
drm: Refactor object property check code
drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/armada/armada_crtc.c | 14 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/armada/armada_output.c | 3 +- drivers/gpu/drm/armada/armada_overlay.c | 14 +- drivers/gpu/drm/ast/ast_drv.c | 6 + drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_drv.c | 6 + drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 720 +++++++++++++ drivers/gpu/drm/drm_crtc.c | 1534 ++++++++++++++++++--------- drivers/gpu/drm/drm_crtc_helper.c | 6 +- drivers/gpu/drm/drm_fb_cma_helper.c | 15 +- drivers/gpu/drm/drm_fb_helper.c | 69 +- drivers/gpu/drm/drm_modes.c | 4 +- drivers/gpu/drm/drm_modeset_lock.c | 159 +++ drivers/gpu/drm/drm_plane_helper.c | 2 + drivers/gpu/drm/drm_probe_helper.c | 10 +- drivers/gpu/drm/drm_sysfs.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 11 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 8 +- drivers/gpu/drm/exynos/exynos_drm_plane.c | 11 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/cdv_intel_dp.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 16 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 12 +- drivers/gpu/drm/gma500/oaktrail_lvds.c | 6 +- drivers/gpu/drm/gma500/psb_drv.c | 11 +- drivers/gpu/drm/gma500/psb_drv.h | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 16 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 23 +- drivers/gpu/drm/i2c/ch7006_drv.c | 4 +- drivers/gpu/drm/i915/i915_debugfs.c | 12 +- drivers/gpu/drm/i915/i915_drv.c | 16 +- drivers/gpu/drm/i915/i915_irq.c | 6 +- drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 24 +- drivers/gpu/drm/i915/intel_dp.c | 25 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_fbdev.c | 6 +- drivers/gpu/drm/i915/intel_hdmi.c | 7 +- drivers/gpu/drm/i915/intel_lvds.c | 10 +- drivers/gpu/drm/i915/intel_opregion.c | 4 +- drivers/gpu/drm/i915/intel_overlay.c | 4 +- drivers/gpu/drm/i915/intel_panel.c | 8 +- drivers/gpu/drm/i915/intel_sdvo.c | 23 +- drivers/gpu/drm/i915/intel_sprite.c | 3 +- drivers/gpu/drm/i915/intel_tv.c | 12 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 7 + drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 70 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 14 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 69 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 6 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 14 +- drivers/gpu/drm/msm/msm_atomic.c | 141 +++ drivers/gpu/drm/msm/msm_drv.c | 33 +- drivers/gpu/drm/msm/msm_drv.h | 8 + drivers/gpu/drm/msm/msm_gem.c | 24 +- drivers/gpu/drm/msm/msm_gem.h | 13 + drivers/gpu/drm/msm/msm_kms.h | 1 + drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/dispnv04/overlay.c | 13 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 3 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 7 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 7 + drivers/gpu/drm/nouveau/nouveau_drm.h | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 26 +- drivers/gpu/drm/omapdrm/omap_drv.c | 16 +- drivers/gpu/drm/omapdrm/omap_drv.h | 4 +- drivers/gpu/drm/omapdrm/omap_plane.c | 14 +- drivers/gpu/drm/qxl/qxl_display.c | 6 +- drivers/gpu/drm/qxl/qxl_drv.c | 9 + drivers/gpu/drm/radeon/radeon_connectors.c | 9 +- drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/radeon/radeon_drv.c | 9 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 12 +- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 6 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 + drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + drivers/gpu/drm/tegra/fb.c | 7 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 5 +- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 + drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/udl/udl_connector.c | 6 +- drivers/gpu/drm/udl/udl_drv.c | 8 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 26 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drmP.h | 85 +- include/drm/drm_atomic.h | 170 +++ include/drm/drm_crtc.h | 326 +++++- include/drm/drm_fb_helper.h | 3 +- include/drm/drm_modeset_lock.h | 130 +++ include/uapi/drm/drm_mode.h | 18 + 117 files changed, 3401 insertions(+), 882 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic.c create mode 100644 drivers/gpu/drm/drm_modeset_lock.c create mode 100644 drivers/gpu/drm/msm/msm_atomic.c create mode 100644 include/drm/drm_atomic.h create mode 100644 include/drm/drm_modeset_lock.h
Signature · 6 lines
1.9.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/17 drm: fix typo
--- drivers/gpu/drm/drm_crtc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/drm_crtc_helper.c +1 -1
@@ -147,7 +147,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)list_for_each_entry (encoder, &dev->mode_config.encoder_list, head) {if (!drm_helper_encoder_in_use (encoder)) {drm_encoder_disable (encoder); -/* disconnector encoder from any connector */ +/* disconnect encoder from any connector */ encoder->crtc =NULL ; } }
Signature · 1 line
1.9.0
PATCH 2/17 drm: add atomic fxns
In reply to Rob ClarkThe 'atomic' mechanism allows for multiple properties to be updated, checked, and commited atomically. This will be the basis of atomic- modeset and nuclear-pageflip.
The basic flow is:
state = dev->atomic_begin();
for (... one or more ...)
obj->set_property(obj, state, prop, value);
if (dev->atomic_check(state))
dev->atomic_commit(state);
dev->atomic_end(state);The split of check and commit steps is to allow for ioctls with a test-only flag (which would skip the commit step).
--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/armada/armada_crtc.c | 3 +- drivers/gpu/drm/armada/armada_output.c | 3 +- drivers/gpu/drm/armada/armada_overlay.c | 3 +- drivers/gpu/drm/ast/ast_drv.c | 6 ++ drivers/gpu/drm/ast/ast_drv.h | 1 + drivers/gpu/drm/cirrus/cirrus_drv.c | 6 ++ drivers/gpu/drm/cirrus/cirrus_drv.h | 1 + drivers/gpu/drm/drm_atomic.c | 142 +++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 144 +++++++++++++++++----------- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 ++ drivers/gpu/drm/exynos/exynos_drm_plane.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_crt.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 4 +- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 4 +- drivers/gpu/drm/gma500/psb_drv.c | 7 ++ drivers/gpu/drm/gma500/psb_drv.h | 1 + drivers/gpu/drm/gma500/psb_intel_drv.h | 4 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 4 +- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 8 ++ drivers/gpu/drm/i915/intel_crt.c | 4 +- drivers/gpu/drm/i915/intel_dp.c | 4 +- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_hdmi.c | 4 +- drivers/gpu/drm/i915/intel_lvds.c | 4 +- drivers/gpu/drm/i915/intel_sdvo.c | 4 +- drivers/gpu/drm/i915/intel_tv.c | 6 +- drivers/gpu/drm/mgag200/mgag200_drv.c | 7 ++ drivers/gpu/drm/mgag200/mgag200_drv.h | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 3 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 3 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 3 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 3 +- drivers/gpu/drm/msm/msm_drv.c | 6 ++ drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/nouveau/dispnv04/overlay.c | 5 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 7 ++ drivers/gpu/drm/nouveau/nouveau_drm.h | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 6 +- drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++ drivers/gpu/drm/omapdrm/omap_drv.h | 4 +- drivers/gpu/drm/omapdrm/omap_plane.c | 3 +- drivers/gpu/drm/qxl/qxl_display.c | 4 +- drivers/gpu/drm/qxl/qxl_drv.c | 9 ++ drivers/gpu/drm/radeon/radeon_connectors.c | 9 +- drivers/gpu/drm/radeon/radeon_drv.c | 9 ++ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 7 ++ drivers/gpu/drm/rcar-du/rcar_du_plane.c | 4 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 7 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.c | 6 ++ drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 3 +- drivers/gpu/drm/udl/udl_connector.c | 6 +- drivers/gpu/drm/udl/udl_drv.c | 8 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- include/drm/drmP.h | 80 ++++++++++++++++ include/drm/drm_atomic.h | 107 +++++++++++++++++++++ include/drm/drm_crtc.h | 15 ++- 66 files changed, 652 insertions(+), 102 deletions(-) create mode 100644 drivers/gpu/drm/drm_atomic.c create mode 100644 include/drm/drm_atomic.h
drivers/gpu/drm/Makefile +1 -1
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ drm_rect.o drm_vma_manager.o drm_flip_work.o \ - drm_plane_helper.o + drm_plane_helper.o drm_atomic.o drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drivers/gpu/drm/armada/armada_crtc.c +2 -1
@@ -961,7 +961,8 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,static int armada_drm_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {struct armada_private *priv = crtc->dev->dev_private;struct armada_crtc *dcrtc =drm_to_armada_crtc (crtc);
drivers/gpu/drm/armada/armada_output.c +2 -1
@@ -54,7 +54,8 @@ static void armada_drm_connector_destroy(struct drm_connector *conn) }static int armada_drm_connector_set_property (struct drm_connector *conn, -struct drm_property *property,uint64_t value) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data) {struct armada_connector *dconn =drm_to_armada_conn (conn);
drivers/gpu/drm/armada/armada_overlay.c +2 -1
@@ -283,7 +283,8 @@ static void armada_plane_destroy(struct drm_plane *plane) }static int armada_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane);
drivers/gpu/drm/ast/ast_drv.c +6 -0
@@ -215,6 +215,12 @@ static struct drm_driver driver = { .dumb_map_offset = ast_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, };static int __init ast_init (void )
drivers/gpu/drm/ast/ast_drv.h +1 -0
@@ -29,6 +29,7 @@#define __AST_DRV_H__#include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h>
drivers/gpu/drm/cirrus/cirrus_drv.c +6 -0
@@ -137,6 +137,12 @@ static struct drm_driver driver = { .dumb_create = cirrus_dumb_create, .dumb_map_offset = cirrus_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, };static const struct dev_pm_ops cirrus_pm_ops = {
drivers/gpu/drm/cirrus/cirrus_drv.h +1 -0
@@ -14,6 +14,7 @@#include <video/vga.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h>
drivers/gpu/drm/drm_atomic.c new file +142 -0
142 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +89 -55
204 lines not on this page · raw message
drivers/gpu/drm/exynos/exynos_drm_crtc.c +3 -1
@@ -281,8 +281,10 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) }static int exynos_drm_crtc_set_property (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_device *dev = crtc->dev;struct exynos_drm_private *dev_priv = dev->dev_private;
drivers/gpu/drm/exynos/exynos_drm_drv.c +7 -0
@@ -14,6 +14,7 @@#include <linux/pm_runtime.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <linux/anon_inodes.h>
@@ -341,6 +342,12 @@ static struct drm_driver exynos_drm_driver = { .dumb_create = exynos_drm_gem_dumb_create, .dumb_map_offset = exynos_drm_gem_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = exynos_dmabuf_prime_export,
drivers/gpu/drm/exynos/exynos_drm_plane.c +3 -1
@@ -212,8 +212,10 @@ static void exynos_plane_destroy(struct drm_plane *plane) }static int exynos_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);
drivers/gpu/drm/gma500/cdv_intel_crt.c +3 -1
@@ -205,8 +205,10 @@ static int cdv_intel_crt_get_modes(struct drm_connector *connector) }static int cdv_intel_crt_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {return 0 ; }
drivers/gpu/drm/gma500/cdv_intel_dp.c +3 -1
@@ -1645,8 +1645,10 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector)static int cdv_intel_dp_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_psb_private *dev_priv = connector->dev->dev_private;struct gma_encoder *encoder =gma_attached_encoder (connector);
drivers/gpu/drm/gma500/cdv_intel_hdmi.c +3 -1
@@ -150,8 +150,10 @@ static enum drm_connector_status cdv_hdmi_detect( }static int cdv_hdmi_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/cdv_intel_lvds.c +3 -1
@@ -452,8 +452,10 @@ static void cdv_intel_lvds_destroy(struct drm_connector *connector) }static int cdv_intel_lvds_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/mdfld_dsi_output.c +3 -1
@@ -243,8 +243,10 @@ mdfld_dsi_connector_detect(struct drm_connector *connector, bool force) }static int mdfld_dsi_connector_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/psb_drv.c +7 -0
@@ -489,6 +489,13 @@ static struct drm_driver driver = { .disable_vblank = psb_disable_vblank, .get_vblank_counter = psb_get_vblank_counter, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .gem_free_object = psb_gem_free_object, .gem_vm_ops = &psb_gem_vm_ops,
drivers/gpu/drm/gma500/psb_drv.h +1 -0
@@ -25,6 +25,7 @@#include <drm/drmP.h> #include <drm/drm_global.h> #include <drm/gma_drm.h> +#include <drm/drm_atomic.h> #include "psb_reg.h" #include "psb_intel_drv.h" #include "gma_display.h"
drivers/gpu/drm/gma500/psb_intel_drv.h +3 -1
@@ -254,8 +254,10 @@ extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,extern int psb_intel_lvds_mode_valid (struct drm_connector *connector,struct drm_display_mode *mode);extern int psb_intel_lvds_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value); +uint64_t value, +void *blob_data);extern void psb_intel_lvds_destroy (struct drm_connector *connector);extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
drivers/gpu/drm/gma500/psb_intel_lvds.c +3 -1
@@ -569,8 +569,10 @@ void psb_intel_lvds_destroy(struct drm_connector *connector) }int psb_intel_lvds_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_encoder *encoder = connector->encoder;
drivers/gpu/drm/gma500/psb_intel_sdvo.c +3 -1
@@ -1705,8 +1705,10 @@ static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)static int psb_intel_sdvo_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct psb_intel_sdvo *psb_intel_sdvo =intel_attached_sdvo (connector);struct psb_intel_sdvo_connector *psb_intel_sdvo_connector =to_psb_intel_sdvo_connector (connector);
drivers/gpu/drm/i915/i915_drv.c +8 -0
@@ -1119,6 +1119,14 @@ static struct drm_driver driver = { .dumb_create = i915_gem_dumb_create, .dumb_map_offset = i915_gem_mmap_gtt, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .ioctls = i915_ioctls, .fops = &i915_driver_fops, .name = DRIVER_NAME,
drivers/gpu/drm/i915/intel_crt.c +3 -1
@@ -724,8 +724,10 @@ out: }static int intel_crt_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {return 0 ; }
drivers/gpu/drm/i915/intel_dp.c +3 -1
@@ -3270,8 +3270,10 @@ intel_dp_detect_audio(struct drm_connector *connector)static int intel_dp_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct drm_i915_private *dev_priv = connector->dev->dev_private;struct intel_connector *intel_connector =to_intel_connector (connector);
drivers/gpu/drm/i915/intel_drv.h +1 -0
@@ -31,6 +31,7 @@#include "i915_drv.h" #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_helper.h> #include <drm/drm_dp_helper.h>
drivers/gpu/drm/i915/intel_hdmi.c +3 -1
@@ -1044,8 +1044,10 @@ intel_hdmi_detect_audio(struct drm_connector *connector)static int intel_hdmi_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct intel_hdmi *intel_hdmi =intel_attached_hdmi (connector); struct intel_digital_port *intel_dig_port =
drivers/gpu/drm/i915/intel_lvds.c +3 -1
@@ -486,8 +486,10 @@ static void intel_lvds_destroy(struct drm_connector *connector) }static int intel_lvds_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct intel_connector *intel_connector =to_intel_connector (connector);struct drm_device *dev = connector->dev;
drivers/gpu/drm/i915/intel_sdvo.c +3 -1
@@ -2052,8 +2052,10 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)static int intel_sdvo_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {struct intel_sdvo *intel_sdvo =intel_attached_sdvo (connector);struct intel_sdvo_connector *intel_sdvo_connector =to_intel_sdvo_connector (connector);
drivers/gpu/drm/i915/intel_tv.c +4 -2
@@ -1444,8 +1444,10 @@ intel_tv_destroy(struct drm_connector *connector)static int -intel_tv_set_property (struct drm_connector *connector,struct drm_property *property, -uint64_t val) +intel_tv_set_property (struct drm_connector *connector, +struct drm_atomic_state *state, +struct drm_property *property, +uint64_t val,void *blob_data) {struct drm_device *dev = connector->dev;struct intel_tv *intel_tv =intel_attached_tv (connector);
drivers/gpu/drm/mgag200/mgag200_drv.c +7 -0
@@ -103,6 +103,13 @@ static struct drm_driver driver = { .dumb_create = mgag200_dumb_create, .dumb_map_offset = mgag200_dumb_mmap_offset, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, };static struct pci_driver mgag200_pci_driver = {
drivers/gpu/drm/mgag200/mgag200_drv.h +1 -0
@@ -16,6 +16,7 @@#include <video/vga.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_placement.h>
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +2 -1
@@ -468,7 +468,8 @@ static int mdp4_crtc_page_flip(struct drm_crtc *crtc, }static int mdp4_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +2 -1
@@ -85,7 +85,8 @@ void mdp4_plane_install_properties(struct drm_plane *plane, }int mdp4_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +2 -1
@@ -386,7 +386,8 @@ static int mdp5_crtc_page_flip(struct drm_crtc *crtc, }static int mdp5_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +2 -1
@@ -100,7 +100,8 @@ void mdp5_plane_install_properties(struct drm_plane *plane, }int mdp5_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {// XXX return -EINVAL ;
drivers/gpu/drm/msm/msm_drv.c +6 -0
@@ -815,6 +815,12 @@ static struct drm_driver msm_driver = { .gem_prime_import_sg_table = msm_gem_prime_import_sg_table, .gem_prime_vmap = msm_gem_prime_vmap, .gem_prime_vunmap = msm_gem_prime_vunmap, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, #ifdef CONFIG_DEBUG_FS .debugfs_init = msm_debugfs_init, .debugfs_cleanup = msm_debugfs_cleanup,
drivers/gpu/drm/msm/msm_drv.h +1 -0
@@ -50,6 +50,7 @@ static inline struct device *msm_iommu_get_ctx(const char *ctx_name)#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_atomic.h> #include <drm/msm_drm.h> struct msm_kms ;
drivers/gpu/drm/nouveau/dispnv04/overlay.c +3 -2
@@ -221,8 +221,9 @@ nv10_set_params(struct nouveau_plane *plane)static int nv_set_property (struct drm_plane *plane, -struct drm_property *property, -uint64_t value) +struct drm_atomic_state *state, +struct drm_property *property, +uint64_t value,void *blob_data) {struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane;
drivers/gpu/drm/nouveau/nouveau_connector.c +2 -1
@@ -447,7 +447,8 @@ nouveau_connector_force(struct drm_connector *connector)static int nouveau_connector_set_property (struct drm_connector *connector, -struct drm_property *property,uint64_t value) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data) {struct nouveau_display *disp =nouveau_display (connector->dev);struct nouveau_connector *nv_connector =nouveau_connector (connector);
drivers/gpu/drm/nouveau/nouveau_drm.c +7 -0
@@ -858,6 +858,13 @@ driver = { .dumb_map_offset = nouveau_display_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .name = DRIVER_NAME, .desc =DRIVER_DESC , #ifdef GIT_REVISION
drivers/gpu/drm/nouveau/nouveau_drm.h +1 -0
@@ -29,6 +29,7 @@#include <subdev/vm.h> #include <drmP.h> +#include <drm/drm_atomic.h> #include <drm/nouveau_drm.h> #include <drm/ttm/ttm_bo_api.h>
drivers/gpu/drm/omapdrm/omap_crtc.c +4 -2
@@ -382,7 +382,8 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, }static int omap_crtc_set_property (struct drm_crtc *crtc, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {struct omap_crtc *omap_crtc =to_omap_crtc (crtc);struct omap_drm_private *priv = crtc->dev->dev_private;
@@ -392,7 +393,8 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, !!(val & ((1LL <<DRM_ROTATE_90 ) | (1LL <<DRM_ROTATE_270 ))); } -return omap_plane_set_property (omap_crtc->plane, property, val); +return omap_plane_set_property (omap_crtc->plane, state, + property, val, blob_data); }static const struct drm_crtc_funcs omap_crtc_funcs = {
drivers/gpu/drm/omapdrm/omap_drv.c +6 -0
@@ -651,6 +651,12 @@ static struct drm_driver omap_drm_driver = { .dumb_create = omap_gem_dumb_create, .dumb_map_offset = omap_gem_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .ioctls = ioctls, .num_ioctls = DRM_OMAP_NUM_IOCTLS, .fops = &omapdriver_fops,
drivers/gpu/drm/omapdrm/omap_drv.h +3 -1
@@ -25,6 +25,7 @@#include <linux/types.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/omap_drm.h> #include <linux/platform_data/omap_drm.h>
@@ -178,7 +179,8 @@ int omap_plane_mode_set(struct drm_plane *plane,void omap_plane_install_properties (struct drm_plane *plane,struct drm_mode_object *obj);int omap_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val); +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data);struct drm_encoder *omap_encoder_init (struct drm_device *dev,struct omap_dss_device *dssdev);
drivers/gpu/drm/omapdrm/omap_plane.c +2 -1
@@ -336,7 +336,8 @@ void omap_plane_install_properties(struct drm_plane *plane, }int omap_plane_set_property (struct drm_plane *plane, -struct drm_property *property,uint64_t val) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private;
drivers/gpu/drm/qxl/qxl_display.c +3 -1
@@ -819,8 +819,10 @@ static enum drm_connector_status qxl_conn_detect( }static int qxl_conn_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {DRM_DEBUG ("\n" );return 0 ;
drivers/gpu/drm/qxl/qxl_drv.c +9 -0
@@ -34,6 +34,7 @@#include "drmP.h" #include "drm/drm.h" #include "drm_crtc_helper.h" +#include "drm_atomic.h" #include "qxl_drv.h" #include "qxl_object.h"
@@ -220,6 +221,14 @@ static struct drm_driver qxl_driver = { .dumb_create = qxl_mode_dumb_create, .dumb_map_offset = qxl_mode_dumb_mmap, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, +#if defined(CONFIG_DEBUG_FS ) .debugfs_init = qxl_debugfs_init, .debugfs_cleanup = qxl_debugfs_takedown,
drivers/gpu/drm/radeon/radeon_connectors.c +6 -3
@@ -359,8 +359,9 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn } } -static int radeon_connector_set_property (struct drm_connector *connector,struct drm_property *property, -uint64_t val) +static int radeon_connector_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {struct drm_device *dev = connector->dev;struct radeon_device *rdev = dev->dev_private;
@@ -682,8 +683,10 @@ static void radeon_connector_destroy(struct drm_connector *connector) }static int radeon_lvds_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct drm_device *dev = connector->dev;struct radeon_encoder *radeon_encoder;
drivers/gpu/drm/radeon/radeon_drv.c +9 -0
@@ -34,6 +34,7 @@#include "radeon_drv.h" #include <drm/drm_pciids.h> +#include <drm/drm_atomic.h> #include <linux/console.h> #include <linux/module.h> #include <linux/pm_runtime.h>
@@ -545,6 +546,14 @@ static struct drm_driver kms_driver = { .dumb_create = radeon_mode_dumb_create, .dumb_map_offset = radeon_mode_dumb_mmap, .dumb_destroy = drm_gem_dumb_destroy, + + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .fops = &radeon_driver_kms_fops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
drivers/gpu/drm/rcar-du/rcar_du_drv.c +7 -0
@@ -21,6 +21,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -175,6 +176,12 @@ static struct drm_driver rcar_du_driver = { .dumb_create = rcar_du_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .fops = &rcar_du_fops, .name = "rcar-du", .desc = "Renesas R-Car Display Unit",
drivers/gpu/drm/rcar-du/rcar_du_plane.c +3 -1
@@ -397,8 +397,10 @@ done: }static int rcar_du_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t value) +uint64_t value, +void *blob_data) {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group;
drivers/gpu/drm/shmobile/shmob_drm_drv.c +7 -0
@@ -21,6 +21,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_gem_cma_helper.h> #include "shmob_drm_crtc.h"
@@ -285,6 +286,12 @@ static struct drm_driver shmob_drm_driver = { .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, .fops = &shmob_drm_fops, .name = "shmob-drm", .desc = "Renesas SH Mobile DRM",
drivers/gpu/drm/tilcdc/tilcdc_drv.c +6 -0
@@ -519,6 +519,12 @@ static struct drm_driver tilcdc_driver = { .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, #ifdef CONFIG_DEBUG_FS .debugfs_init = tilcdc_debugfs_init, .debugfs_cleanup = tilcdc_debugfs_cleanup,
drivers/gpu/drm/tilcdc/tilcdc_drv.h +1 -0
@@ -31,6 +31,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
drivers/gpu/drm/tilcdc/tilcdc_slave.c +2 -1
@@ -206,7 +206,8 @@ static struct drm_encoder *slave_connector_best_encoder( }static int slave_connector_set_property (struct drm_connector *connector, -struct drm_property *property,uint64_t value) +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data) {struct drm_encoder *encoder =to_slave_connector (connector)->encoder; return get_slave_funcs(encoder)->set_property(encoder,
drivers/gpu/drm/udl/udl_connector.c +3 -3
@@ -115,9 +115,9 @@ udl_best_single_encoder(struct drm_connector *connector)return encoder; } -static int udl_connector_set_property (struct drm_connector *connector, -struct drm_property *property, -uint64_t val) +static int udl_connector_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) {return 0 ; }
drivers/gpu/drm/udl/udl_drv.c +8 -0
@@ -9,6 +9,7 @@#include <linux/module.h> #include <drm/drm_usb.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "udl_drv.h" static struct drm_driver driver;
@@ -88,6 +89,13 @@ static struct drm_driver driver = { .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = udl_gem_prime_import, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE,
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +7 -0
@@ -1433,6 +1433,13 @@ static struct drm_driver driver = { .prime_fd_to_handle = vmw_prime_fd_to_handle, .prime_handle_to_fd = vmw_prime_handle_to_fd, + .atomic_begin = drm_atomic_begin, + .atomic_set_event = drm_atomic_set_event, + .atomic_check = drm_atomic_check, + .atomic_commit = drm_atomic_commit, + .atomic_end = drm_atomic_end, + .atomic_funcs = &drm_atomic_funcs, + .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC,
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +1 -0
@@ -30,6 +30,7 @@#include "vmwgfx_reg.h" #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/vmwgfx_drm.h> #include <drm/drm_hashtab.h> #include <linux/suspend.h>
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +3 -1
@@ -2007,8 +2007,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, }int vmw_du_connector_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val) +uint64_t val, +void *blob_data) {return 0 ; }
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +3 -1
@@ -141,8 +141,10 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force);int vmw_du_connector_fill_modes (struct drm_connector *connector,uint32_t max_width,uint32_t max_height);int vmw_du_connector_set_property (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, -uint64_t val); +uint64_t val, +void *blob_data);/*
include/drm/drmP.h +80 -0
86 lines not on this page · raw message
include/drm/drm_atomic.h new file +107 -0
107 lines not on this page · raw message
include/drm/drm_crtc.h +11 -4
@@ -200,6 +200,8 @@ struct drm_encoder;struct drm_pending_vblank_event ;struct drm_plane ;struct drm_bridge ; +struct drm_atomic_state ; +struct drm_atomic_funcs ;/** * drm_crtc_funcs - control CRTCs for a given device
@@ -262,7 +264,9 @@ struct drm_crtc_funcs { uint32_t flags);int (*set_property)(struct drm_crtc *crtc, -struct drm_property *property,uint64_t val); +struct drm_atomic_state *state, +struct drm_property *property,uint64_t val, +void *blob_data); };/**
@@ -375,8 +379,9 @@ struct drm_connector_funcs {enum drm_connector_status (*detect)(struct drm_connector *connector,bool force);int (*fill_modes)(struct drm_connector *connector,uint32_t max_width,uint32_t max_height); -int (*set_property)(struct drm_connector *connector,struct drm_property *property, -uint64_t val); +int (*set_property)(struct drm_connector *connector, +struct drm_atomic_state *state, +struct drm_property *property,uint64_t val,void *blob_data);void (*destroy)(struct drm_connector *connector);void (*force)(struct drm_connector *connector); };
@@ -541,7 +546,9 @@ struct drm_plane_funcs {void (*destroy)(struct drm_plane *plane);int (*set_property)(struct drm_plane *plane, -struct drm_property *property,uint64_t val); +struct drm_atomic_state *state, +struct drm_property *property,uint64_t val, +void *blob_data); };enum drm_plane_type {
Signature · 1 line
1.9.0
PATCH 3/17 drm: convert crtc and mode_config to ww_mutex
In reply to Rob ClarkFor atomic, it will be quite convenient to not have to care so much about locking order. And 'state' gives us a convenient place to stash a ww_ctx for any sort of update that needs to grab multiple crtc locks.
Because we will want to eventually make locking even more fine grained (giving locks to planes, connectors, etc), split out drm_modeset_lock so that the atomic state won't eventually have to keep separate lists of locked planes/crtcs/etc.
The state keeps track of which locks it has aquired, and for the benefit of NONBLOCK operations, supports transfering "locked" resources to driver worker/thread to complete the asynchronous state change.
--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_atomic.c | 140 ++++++++++++++++++++++++-- drivers/gpu/drm/drm_crtc.c | 88 ++++++++++++----- drivers/gpu/drm/drm_crtc_helper.c | 4 +- drivers/gpu/drm/drm_fb_cma_helper.c | 6 +- drivers/gpu/drm/drm_fb_helper.c | 18 ++-- drivers/gpu/drm/drm_modes.c | 4 +- drivers/gpu/drm/drm_modeset_lock.c | 159 ++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_probe_helper.c | 10 +- drivers/gpu/drm/drm_sysfs.c | 4 +- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 6 +- drivers/gpu/drm/gma500/oaktrail_lvds.c | 6 +- drivers/gpu/drm/gma500/psb_intel_lvds.c | 6 +- drivers/gpu/drm/i915/i915_debugfs.c | 12 +-- drivers/gpu/drm/i915/i915_drv.c | 8 +- drivers/gpu/drm/i915/i915_irq.c | 6 +- drivers/gpu/drm/i915/intel_display.c | 20 ++-- drivers/gpu/drm/i915/intel_dp.c | 18 ++-- drivers/gpu/drm/i915/intel_lvds.c | 6 +- drivers/gpu/drm/i915/intel_opregion.c | 4 +- drivers/gpu/drm/i915/intel_overlay.c | 4 +- drivers/gpu/drm/i915/intel_panel.c | 8 +- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 4 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 4 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/omapdrm/omap_plane.c | 4 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 ++--- include/drm/drmP.h | 5 - include/drm/drm_atomic.h | 7 ++ include/drm/drm_crtc.h | 19 ++-- include/drm/drm_modeset_lock.h | 130 ++++++++++++++++++++++++ include/uapi/drm/drm_mode.h | 3 + 35 files changed, 614 insertions(+), 143 deletions(-) create mode 100644 drivers/gpu/drm/drm_modeset_lock.c create mode 100644 include/drm/drm_modeset_lock.h
drivers/gpu/drm/Makefile +1 -1
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ drm_rect.o drm_vma_manager.o drm_flip_work.o \ - drm_plane_helper.o drm_atomic.o + drm_plane_helper.o drm_atomic.o drm_modeset_lock.o drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drivers/gpu/drm/drm_atomic.c +134 -6
182 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +63 -25
212 lines not on this page · raw message
drivers/gpu/drm/drm_crtc_helper.c +2 -2
@@ -88,7 +88,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)struct drm_connector *connector;struct drm_device *dev = encoder->dev; -WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.mutex));list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder == encoder)return true;
@@ -112,7 +112,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)struct drm_encoder *encoder;struct drm_device *dev = crtc->dev; -WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.mutex));list_for_each_entry (encoder, &dev->mode_config.encoder_list, head)if (encoder->crtc == crtc &&drm_helper_encoder_in_use (encoder))return true;
drivers/gpu/drm/drm_fb_cma_helper.c +3 -3
@@ -211,13 +211,13 @@ int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)struct drm_framebuffer *fb;int ret; - ret =mutex_lock_interruptible (&dev->mode_config.mutex); + ret =drm_modeset_lock_interruptible (&dev->mode_config.mutex,NULL );if (ret)return ret; ret =mutex_lock_interruptible (&dev->struct_mutex);if (ret) { -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return ret; }
@@ -225,7 +225,7 @@ int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)drm_fb_cma_describe (fb, m);mutex_unlock (&dev->struct_mutex); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return 0 ; }
drivers/gpu/drm/drm_fb_helper.c +11 -7
@@ -331,7 +331,11 @@ static bool drm_fb_helper_force_kernel_mode(void)if (dev->switch_power_state ==DRM_SWITCH_POWER_OFF )continue ; -if (!mutex_trylock (&dev->mode_config.mutex)) { +/* NOTE: we use lockless flag below to avoid grabbing other +* modeset locks. So just trylock the underlying mutex +* directly: +*/ +if (!mutex_trylock (&dev->mode_config.mutex.mutex.base)) { error = true;continue ; }
@@ -340,7 +344,7 @@ static bool drm_fb_helper_force_kernel_mode(void)if (ret) error = true; -mutex_unlock (&dev->mode_config.mutex); +mutex_unlock (&dev->mode_config.mutex.mutex.base); }return error; }
@@ -1557,11 +1561,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)drm_fb_helper_parse_command_line (fb_helper); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL ); count =drm_fb_helper_probe_connector_modes (fb_helper, dev->mode_config.max_width, dev->mode_config.max_height); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);/* * we shouldn't end up with no modes here. */
@@ -1601,10 +1605,10 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)if (!fb_helper->fb)return 0 ; -mutex_lock (&fb_helper->dev->mode_config.mutex); +drm_modeset_lock (&fb_helper->dev->mode_config.mutex,NULL );if (!drm_fb_helper_is_bound (fb_helper)) { fb_helper->delayed_hotplug = true; -mutex_unlock (&fb_helper->dev->mode_config.mutex); +drm_modeset_unlock (&fb_helper->dev->mode_config.mutex);return 0 ; }DRM_DEBUG_KMS ("\n" );
@@ -1613,7 +1617,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) max_height = fb_helper->fb->height;drm_fb_helper_probe_connector_modes (fb_helper, max_width, max_height); -mutex_unlock (&fb_helper->dev->mode_config.mutex); +drm_modeset_unlock (&fb_helper->dev->mode_config.mutex);drm_modeset_lock_all (dev);drm_setup_crtcs (fb_helper);
drivers/gpu/drm/drm_modes.c +2 -2
@@ -116,7 +116,7 @@ EXPORT_SYMBOL(drm_mode_destroy);void drm_mode_probed_add (struct drm_connector *connector,struct drm_display_mode *mode) { -WARN_ON (!mutex_is_locked (&connector->dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&connector->dev->mode_config.mutex));list_add_tail (&mode->head, &connector->probed_modes); }
@@ -1029,7 +1029,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector,struct drm_display_mode *pmode, *pt;int found_it; -WARN_ON (!mutex_is_locked (&connector->dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&connector->dev->mode_config.mutex));list_for_each_entry_safe (pmode, pt, &connector->probed_modes, head) {
drivers/gpu/drm/drm_modeset_lock.c new file +159 -0
159 lines not on this page · raw message
drivers/gpu/drm/drm_probe_helper.c +5 -5
@@ -93,7 +93,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connectint mode_flags =0 ;bool verbose_prune = true; -WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.mutex));DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , connector->base.id,drm_get_connector_name (connector));
@@ -255,7 +255,7 @@ static void output_poll_execute(struct work_struct *work)if (!drm_kms_helper_poll)return ; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );list_for_each_entry (connector, &dev->mode_config.connector_list, head) {/* Ignore forced connectors. */
@@ -293,7 +293,7 @@ static void output_poll_execute(struct work_struct *work) } } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);if (changed)drm_kms_helper_hotplug_event (dev);
@@ -419,7 +419,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)if (!dev->mode_config.poll_enabled)return false; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );list_for_each_entry (connector, &dev->mode_config.connector_list, head) {/* Only handle HPD capable connectors. */
@@ -438,7 +438,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) changed = true; } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);if (changed)drm_kms_helper_hotplug_event (dev);
drivers/gpu/drm/drm_sysfs.c +2 -2
@@ -173,12 +173,12 @@ static ssize_t status_show(struct device *device,enum drm_connector_status status;int ret; - ret =mutex_lock_interruptible (&connector->dev->mode_config.mutex); + ret =drm_modeset_lock_interruptible (&connector->dev->mode_config.mutex,NULL );if (ret)return ret; status = connector->funcs->detect (connector, true); -mutex_unlock (&connector->dev->mode_config.mutex); +drm_modeset_unlock (&connector->dev->mode_config.mutex);return snprintf (buf,PAGE_SIZE ,"%s\n" ,drm_get_connector_status_name (status));
drivers/gpu/drm/exynos/exynos_drm_fbdev.c +2 -2
@@ -242,7 +242,7 @@ bool exynos_drm_fbdev_is_anything_connected(struct drm_device *dev)struct drm_connector *connector;bool ret = false; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );list_for_each_entry (connector, &dev->mode_config.connector_list, head) {if (connector->status != connector_status_connected)continue ;
@@ -250,7 +250,7 @@ bool exynos_drm_fbdev_is_anything_connected(struct drm_device *dev) ret = true;break ; } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return ret; }
drivers/gpu/drm/gma500/cdv_intel_lvds.c +3 -3
@@ -714,7 +714,7 @@ void cdv_intel_lvds_init(struct drm_device *dev,* Attempt to get the fixed panel mode from DDC. Assume that the * preferred mode is the right one. */ -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );psb_intel_ddc_get_modes (connector, &gma_encoder->ddc_bus->adapter);list_for_each_entry (scan, &connector->probed_modes, head) {
@@ -775,12 +775,12 @@ void cdv_intel_lvds_init(struct drm_device *dev, } out: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);drm_sysfs_connector_add (connector);return ; failed_find: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);printk (KERN_ERR "Failed find\n" );if (gma_encoder->ddc_bus)psb_intel_i2c_destroy (gma_encoder->ddc_bus);
drivers/gpu/drm/gma500/oaktrail_lvds.c +3 -3
@@ -359,7 +359,7 @@ void oaktrail_lvds_init(struct drm_device *dev,* if closed, act like it's not there for now */ -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL ); i2c_adap =i2c_get_adapter (dev_priv->ops->i2c_bus);if (i2c_adap ==NULL )dev_err (dev->dev,"No ddc adapter available!\n" );
@@ -402,13 +402,13 @@ void oaktrail_lvds_init(struct drm_device *dev, } out: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);drm_sysfs_connector_add (connector);return ; failed_find: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);dev_dbg (dev->dev,"No LVDS modes found, disabling.\n" );if (gma_encoder->ddc_bus)
drivers/gpu/drm/gma500/psb_intel_lvds.c +3 -3
@@ -779,7 +779,7 @@ void psb_intel_lvds_init(struct drm_device *dev,* Attempt to get the fixed panel mode from DDC. Assume that the * preferred mode is the right one. */ -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );psb_intel_ddc_get_modes (connector, &lvds_priv->ddc_bus->adapter);list_for_each_entry (scan, &connector->probed_modes, head) {if (scan->type &DRM_MODE_TYPE_PREFERRED ) {
@@ -830,12 +830,12 @@ void psb_intel_lvds_init(struct drm_device *dev,* actually having one. */ out: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);drm_sysfs_connector_add (connector);return ; failed_find: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);if (lvds_priv->ddc_bus)psb_intel_i2c_destroy (lvds_priv->ddc_bus); failed_ddc:
drivers/gpu/drm/i915/i915_debugfs.c +6 -6
@@ -1635,7 +1635,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)#ifdef CONFIG_DRM_I915_FBDEV struct drm_i915_private *dev_priv = dev->dev_private; -int ret =mutex_lock_interruptible (&dev->mode_config.mutex); +int ret =drm_modeset_lock_interruptible (&dev->mode_config.mutex,NULL );if (ret)return ret;
@@ -1650,7 +1650,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) atomic_read(&fb->base.refcount.refcount));describe_obj (m, fb->obj);seq_putc (m,'\n' ); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);#endif mutex_lock (&dev->mode_config.fb_lock);
@@ -1681,7 +1681,7 @@ static int i915_context_status(struct seq_file *m, void *unused)struct i915_hw_context *ctx;int ret, i; - ret =mutex_lock_interruptible (&dev->mode_config.mutex); + ret =drm_modeset_lock_interruptible (&dev->mode_config.mutex,NULL );if (ret)return ret;
@@ -1711,7 +1711,7 @@ static int i915_context_status(struct seq_file *m, void *unused)seq_putc (m,'\n' ); } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return 0 ; }
@@ -2573,7 +2573,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, *source =INTEL_PIPE_CRC_SOURCE_PIPE ; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );list_for_each_entry (encoder, &dev->mode_config.encoder_list, base.head) {if (!encoder->base.crtc)
@@ -2609,7 +2609,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe,break ; } } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return ret; }
drivers/gpu/drm/i915/i915_drv.c +4 -4
@@ -475,10 +475,10 @@ static int i915_drm_freeze(struct drm_device *dev)* Disable CRTCs directly since we want to preserve sw state * for _thaw. */ -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) dev_priv->display.crtc_disable (crtc); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);intel_modeset_suspend_hw (dev); }
@@ -546,14 +546,14 @@ static void intel_resume_hotplug(struct drm_device *dev)struct drm_mode_config *mode_config = &dev->mode_config;struct intel_encoder *encoder; -mutex_lock (&mode_config->mutex); +drm_modeset_lock (&mode_config->mutex,NULL );DRM_DEBUG_KMS ("running encoder hotplug functions\n" );list_for_each_entry (encoder, &mode_config->encoder_list, base.head)if (encoder->hot_plug) encoder->hot_plug (encoder); -mutex_unlock (&mode_config->mutex); +drm_modeset_unlock (&mode_config->mutex);/* Just fire off a uevent and let userspace tell us what to do */ drm_helper_hpd_irq_event (dev);
drivers/gpu/drm/i915/i915_irq.c +3 -3
@@ -940,7 +940,7 @@ static bool intel_hpd_irq_event(struct drm_device *dev, {enum drm_connector_status old_status; -WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.mutex)); old_status = connector->status; connector->status = connector->funcs->detect (connector, false);
@@ -979,7 +979,7 @@ static void i915_hotplug_work_func(struct work_struct *work)if (!dev_priv->enable_hotplug_processing)return ; -mutex_lock (&mode_config->mutex); +drm_modeset_lock (&mode_config->mutex,NULL );DRM_DEBUG_KMS ("running encoder hotplug functions\n" );spin_lock_irqsave (&dev_priv->irq_lock, irqflags);
@@ -1026,7 +1026,7 @@ static void i915_hotplug_work_func(struct work_struct *work) changed = true; } } -mutex_unlock (&mode_config->mutex); +drm_modeset_unlock (&mode_config->mutex);if (changed)drm_kms_helper_hotplug_event (dev);
drivers/gpu/drm/i915/intel_display.c +10 -10
@@ -2363,7 +2363,7 @@ void intel_display_handle_reset(struct drm_device *dev)list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {struct intel_crtc *intel_crtc =to_intel_crtc (crtc); -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );/* * FIXME: Once we have proper support for primary planes (and * disabling them without disabling the entire crtc) allow again
@@ -2374,7 +2374,7 @@ void intel_display_handle_reset(struct drm_device *dev) crtc->primary->fb, crtc->x, crtc->y); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); } }
@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL ); old->dpms_mode = connector->dpms; old->load_detect_temp = false;
@@ -8033,7 +8033,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,return false; } -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL ); intel_encoder->new_crtc =to_intel_crtc (crtc);to_intel_connector (connector)->new_encoder = intel_encoder;
@@ -8083,7 +8083,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, intel_crtc->new_config = &intel_crtc->config; else intel_crtc->new_config = NULL; -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);return false; }
@@ -8112,7 +8112,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,drm_framebuffer_unreference (old->release_fb); } -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);return ; }
@@ -8120,7 +8120,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,if (old->dpms_mode !=DRM_MODE_DPMS_ON ) connector->funcs->dpms (connector, old->dpms_mode); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); } static int i9xx_pll_refclk(struct drm_device *dev,
@@ -10578,7 +10578,7 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) {struct drm_encoder *encoder = connector->base.encoder; -WARN_ON (!mutex_is_locked (&connector->base.dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&connector->base.dev->mode_config.mutex));if (!encoder)return INVALID_PIPE ;
@@ -11336,9 +11336,9 @@ void intel_modeset_init(struct drm_device *dev)/* Just in case the BIOS is doing something questionable. */ intel_disable_fbc (dev); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );intel_modeset_setup_hw_state (dev, false); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);list_for_each_entry (crtc, &dev->mode_config.crtc_list, base.head) {
drivers/gpu/drm/i915/intel_dp.c +9 -9
@@ -1131,7 +1131,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)u32 pp;u32 pp_stat_reg, pp_ctrl_reg; -WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.mutex));if (!intel_dp->want_panel_vdd &&edp_have_panel_vdd (intel_dp)) { struct intel_digital_port *intel_dig_port =
@@ -1168,9 +1168,9 @@ static void edp_panel_vdd_work(struct work_struct *__work) struct intel_dp, panel_vdd_work);struct drm_device *dev =intel_dp_to_dev (intel_dp); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }static void edp_panel_vdd_off (struct intel_dp *intel_dp,bool sync)
@@ -3385,9 +3385,9 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)drm_encoder_cleanup (encoder);if (is_edp (intel_dp)) {cancel_delayed_work_sync (&intel_dp->panel_vdd_work); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }kfree (intel_dig_port); }
@@ -3829,7 +3829,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,/* We now know it's not a ghost, init power sequence regs. */ intel_dp_init_panel_power_sequencer_registers (dev, intel_dp, power_seq); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL ); edid =drm_get_edid (connector, &intel_dp->aux.ddc);if (edid) {if (drm_add_edid_modes (connector, edid)) {
@@ -3863,7 +3863,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,if (fixed_mode) fixed_mode->type |=DRM_MODE_TYPE_PREFERRED ; } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);intel_panel_init (&intel_connector->panel, fixed_mode, downclock_mode);intel_panel_setup_backlight (connector);
@@ -3966,9 +3966,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,drm_dp_aux_unregister_i2c_bus (&intel_dp->aux);if (is_edp (intel_dp)) {cancel_delayed_work_sync (&intel_dp->panel_vdd_work); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }drm_sysfs_connector_remove (connector);drm_connector_cleanup (connector);
drivers/gpu/drm/i915/intel_lvds.c +3 -3
@@ -997,7 +997,7 @@ void intel_lvds_init(struct drm_device *dev)* Attempt to get the fixed panel mode from DDC. Assume that the * preferred mode is the right one. */ -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL ); edid =drm_get_edid (connector,intel_gmbus_get_adapter (dev_priv, pin));if (edid) {if (drm_add_edid_modes (connector, edid)) {
@@ -1091,7 +1091,7 @@ void intel_lvds_init(struct drm_device *dev) goto failed; out: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); lvds_encoder->is_dual_link =compute_is_dual_link_lvds (lvds_encoder); DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
@@ -1121,7 +1121,7 @@ out:return ; failed: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);DRM_DEBUG_KMS ("No LVDS modes found, disabling.\n" );drm_connector_cleanup (connector);
drivers/gpu/drm/i915/intel_opregion.c +2 -2
@@ -410,7 +410,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)if (bclp >255 )return ASLC_BACKLIGHT_FAILED ; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );/* * Update backlight on all connectors that support backlight (usually
@@ -421,7 +421,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)intel_panel_set_backlight (intel_connector, bclp,255 );iowrite32 (DIV_ROUND_UP (bclp *100 ,255 ) |ASLE_CBLV_VALID , &asle->cblv); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return 0 ;
drivers/gpu/drm/i915/intel_overlay.c +2 -2
@@ -688,7 +688,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,u32 swidth, swidthsw, sheight, ostride;BUG_ON (!mutex_is_locked (&dev->struct_mutex)); -BUG_ON (!mutex_is_locked (&dev->mode_config.mutex)); +BUG_ON (!drm_modeset_is_locked (&dev->mode_config.mutex));BUG_ON (!overlay); ret =intel_overlay_release_old_vid (overlay);
@@ -793,7 +793,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)int ret;BUG_ON (!mutex_is_locked (&dev->struct_mutex)); -BUG_ON (!mutex_is_locked (&dev->mode_config.mutex)); +BUG_ON (!drm_modeset_is_locked (&dev->mode_config.mutex)); ret =intel_overlay_recover_from_interrupt (overlay);if (ret !=0 )
drivers/gpu/drm/i915/intel_panel.c +4 -4
@@ -823,12 +823,12 @@ static int intel_backlight_device_update_status(struct backlight_device *bd)struct intel_connector *connector =bl_get_data (bd);struct drm_device *dev = connector->base.dev; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );DRM_DEBUG_KMS ("updating intel_backlight, brightness=%d/%d\n" , bd->props.brightness, bd->props.max_brightness);intel_panel_set_backlight (connector, bd->props.brightness, bd->props.max_brightness); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return 0 ; }
@@ -840,9 +840,9 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)int ret;intel_runtime_pm_get (dev_priv); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL ); ret =intel_panel_get_backlight (connector); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);intel_runtime_pm_put (dev_priv);return ret;
drivers/gpu/drm/i915/intel_sprite.c +1 -1
@@ -55,7 +55,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vblint scanline, min, max, vblank_start;DEFINE_WAIT (wait); -WARN_ON (!mutex_is_locked (&crtc->base.mutex)); +WARN_ON (!drm_modeset_is_locked (&crtc->base.mutex)); vblank_start = mode->crtc_vblank_start;if (mode->flags &DRM_MODE_FLAG_INTERLACE )
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +2 -2
@@ -198,9 +198,9 @@ static void unref_fb_worker(struct drm_flip_work *work, void *val) container_of(work, struct mdp4_crtc, unref_fb_work);struct drm_device *dev = mdp4_crtc->base.dev; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );drm_framebuffer_unreference (val); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }static void unref_cursor_worker (struct drm_flip_work *work,void *val)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +2 -2
@@ -186,9 +186,9 @@ static void unref_fb_worker(struct drm_flip_work *work, void *val) container_of(work, struct mdp5_crtc, unref_fb_work);struct drm_device *dev = mdp5_crtc->base.dev; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );drm_framebuffer_unreference (val); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }static void mdp5_crtc_destroy (struct drm_crtc *crtc)
drivers/gpu/drm/omapdrm/omap_crtc.c +5 -5
@@ -319,13 +319,13 @@ static void page_flip_worker(struct work_struct *work)struct drm_display_mode *mode = &crtc->mode;struct drm_gem_object *bo; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );omap_plane_mode_set (omap_crtc->plane, crtc, crtc->primary->fb,0 ,0 , mode->hdisplay, mode->vdisplay, crtc->x <<16 , crtc->y <<16 , mode->hdisplay <<16 , mode->vdisplay <<16 , vblank_cb, crtc); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); bo =omap_framebuffer_bo (crtc->primary->fb,0 );drm_gem_object_unreference_unlocked (bo);
@@ -467,7 +467,7 @@ static void apply_worker(struct work_struct *work)* the callbacks and list modification all serialized * with respect to modesetting ioctls from userspace. */ -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );dispc_runtime_get ();/*
@@ -512,7 +512,7 @@ static void apply_worker(struct work_struct *work) out:dispc_runtime_put (); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex); } int omap_crtc_apply(struct drm_crtc *crtc,
@@ -520,7 +520,7 @@ int omap_crtc_apply(struct drm_crtc *crtc, {struct omap_crtc *omap_crtc =to_omap_crtc (crtc); -WARN_ON (!mutex_is_locked (&crtc->mutex)); +WARN_ON (!drm_modeset_is_locked (&crtc->mutex));/* no need to queue it again if it is already queued: */ if (apply->queued)
drivers/gpu/drm/omapdrm/omap_plane.c +2 -2
@@ -72,9 +72,9 @@ static void unpin_worker(struct drm_flip_work *work, void *val)struct drm_device *dev = omap_plane->base.dev;omap_framebuffer_unpin (val); -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );drm_framebuffer_unreference (val); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }/* update which fb (if any) is pinned for scanout */
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +2 -2
@@ -45,9 +45,9 @@ static void unref_worker(struct drm_flip_work *work, void *val) container_of(work, struct tilcdc_crtc, unref_work);struct drm_device *dev = tilcdc_crtc->base.dev; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );drm_framebuffer_unreference (val); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }static void set_scanout (struct drm_crtc *crtc,int n)
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +11 -11
@@ -187,7 +187,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,* can do this since the caller in the drm core doesn't check anything * which is protected by any looks. */ -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);drm_modeset_lock_all (dev_priv->dev);/* A lot of the code assumes this */
@@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ret =0 ; out:drm_modeset_unlock_all (dev_priv->dev); -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );return ret; }
@@ -273,7 +273,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)* can do this since the caller in the drm core doesn't check anything * which is protected by any looks. */ -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);drm_modeset_lock_all (dev_priv->dev); vmw_cursor_update_position(dev_priv, shown,
@@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) du->cursor_y + du->hotspot_y);drm_modeset_unlock_all (dev_priv->dev); -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );return 0 ; }
@@ -387,7 +387,7 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)struct vmw_display_unit *du;struct drm_crtc *crtc; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) { du =vmw_crtc_to_du (crtc);
@@ -401,7 +401,7 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) 64, 64, du->hotspot_x, du->hotspot_y); } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex); }/*
@@ -1506,7 +1506,7 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,int ret =0 ; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );if (arg->flags &DRM_VMW_CURSOR_BYPASS_ALL ) {list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {
@@ -1515,7 +1515,7 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data, du->hotspot_y = arg->yhot; } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return 0 ; }
@@ -1532,7 +1532,7 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data, du->hotspot_y = arg->yhot; out: -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return ret; }
@@ -1682,7 +1682,7 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,struct vmw_display_unit *du;struct drm_connector *con; -mutex_lock (&dev->mode_config.mutex); +drm_modeset_lock (&dev->mode_config.mutex,NULL );#if 0 {
@@ -1712,7 +1712,7 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, con->status =vmw_du_connector_detect (con, true); } -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock (&dev->mode_config.mutex);return 0 ; }
include/drm/drmP.h +0 -5
@@ -1264,11 +1264,6 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)return ret; } -static inline bool drm_modeset_is_locked (struct drm_device *dev) -{ -return mutex_is_locked (&dev->mode_config.mutex); -} -static inline bool drm_is_render_client (const struct drm_file *file_priv) {return file_priv->minor->type ==DRM_MINOR_RENDER ;
include/drm/drm_atomic.h +7 -0
@@ -80,6 +80,8 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_pending_vblank_event *event);int drm_atomic_check (struct drm_device *dev,struct drm_atomic_state *state);int drm_atomic_commit (struct drm_device *dev,struct drm_atomic_state *state); +int drm_atomic_commit_unlocked (struct drm_device *dev, +struct drm_atomic_state *state);void drm_atomic_end (struct drm_device *dev,struct drm_atomic_state *state);/**
@@ -89,6 +91,11 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; + +bool committed; +bool checked;/* just for debugging */ + +struct drm_modeset_acquire_ctx acquire_ctx; }; static inline void
include/drm/drm_crtc.h +13 -6
@@ -33,6 +33,7 @@#include <linux/hdmi.h> #include <drm/drm_mode.h> #include <drm/drm_fourcc.h> +#include <drm/drm_modeset_lock.h> struct drm_device ;struct drm_mode_set ;
@@ -194,6 +195,10 @@ struct drm_property {struct list_head enum_blob_list; }; +void drm_modeset_lock_all (struct drm_device *dev); +void drm_modeset_unlock_all (struct drm_device *dev); +void drm_warn_on_modeset_not_all_locked (struct drm_device *dev); +struct drm_crtc ;struct drm_connector ;struct drm_encoder ;
@@ -273,6 +278,7 @@ struct drm_crtc_funcs {* drm_crtc - central CRTC control structure * @dev: parent DRM device * @head: list management +* @mutex: per-CRTC locking * @base: base KMS object for ID tracking etc. * @primary: primary plane for this CRTC * @cursor: cursor plane for this CRTC
@@ -307,7 +313,7 @@ struct drm_crtc {* state, ...) and a write lock for everything which can be update * without a full modeset (fb, cursor data, ...) */ -struct mutex mutex; +struct drm_modeset_lock mutex;struct drm_mode_object base;
@@ -729,7 +735,12 @@ struct drm_mode_group {* global restrictions are also here, e.g. dimension restrictions. */ struct drm_mode_config { -struct mutex mutex;/* protects configuration (mode lists etc.) */ + +/* protects configuration (mode lists etc.): */ +struct drm_modeset_lock mutex; +/* the current acquire ctx (for drm_modeset_lock_all()) */ +struct drm_modeset_acquire_ctx *acquire_ctx; +struct mutex idr_mutex;/* for IDR management */ struct idr crtc_idr;/* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ /* this is limited to one for now */
@@ -830,10 +841,6 @@ struct drm_prop_enum_list {char *name; }; -extern void drm_modeset_lock_all (struct drm_device *dev); -extern void drm_modeset_unlock_all (struct drm_device *dev); -extern void drm_warn_on_modeset_not_all_locked (struct drm_device *dev); - extern int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, struct drm_plane *primary,
include/drm/drm_modeset_lock.h new file +130 -0
130 lines not on this page · raw message
include/uapi/drm/drm_mode.h +3 -0
@@ -496,4 +496,7 @@ struct drm_mode_destroy_dumb { uint32_t handle; }; +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_NOLOCK 0x8000/* only used internally */ +#endif
Signature · 1 line
1.9.0
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
drivers/gpu/drm/i915/intel_display.c bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 6 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +1
-1@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );
This is pretty much the reason why I think switching the mode_config.mutex to a ww_mutex is a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.
My original design behind the crtc->mutex and mode_config.mutex split was that as long as the connector->crtc links didn't change you can get away with the crtc lock. setplane made a bit a mess out of this, but strictly speaking as long as you acquire all crtc locks involved in a potential plane switch (which ww_mtuxes can do) it'll be fine. Since noticing whether any connector properties change should be doable upfront I think we should try _really_ hard to keep the mode_config.mutex a plain mutex which wraps all the more fine-grained locks and is a catch-all for everything else but crtcs/planes. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 5 lines · Daniel Vetter
Quoted 4 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +0
-0@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc;
Quoted 10 lines
Review bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 2 lines
(quoted diff) +1
-1- mutex_lock(&crtc->mutex); + drm_modeset_lock(&crtc->mutex, NULL);This is pretty much the reason why I think switching the mode_config.mutex to a
ww_mutexis a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.
which is the call-path to here from mode_config.mutex? Is it possible to just move the locking to a higher level for a drm_modeset_lock_all()?
Quoted 9 lines
My original design behind the
crtc->mutexand mode_config.mutex split was that as long as theconnector->crtclinks didn't change you can get away with the crtc lock. setplane made a bit a mess out of this, but strictly speaking as long as you acquire all crtc locks involved in a potential plane switch (whichww_mtuxescan do) it'll be fine. Since noticing whether any connector properties change should be doable upfront I think we should try _really_ hard to keep the mode_config.mutex a plain mutex which wraps all the more fine-grained locks and is a catch-all for everything else but crtcs/planes.
That is basically how it was in one of the earlier iterations of atomic.. but didn't hold mode_config.mutex in a lot of places where it was previously held.. and while I do want to make locking more fine grained I didn't want to try and do it at the same time as landing all these other changes.
BR,
-R
Quoted 5 lines
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 17 lines · Rob Clark
Quoted 5 lines · Daniel Vetter
Quoted 4 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +0
-0@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc;Quoted 10 lines
Review bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 2 lines
(quoted diff) +1
-1- mutex_lock(&crtc->mutex); + drm_modeset_lock(&crtc->mutex, NULL);This is pretty much the reason why I think switching the mode_config.mutex to a
ww_mutexis a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.
Quoted 3 lines
which is the call-path to here from mode_config.mutex? Is it possible to just move the locking to a higher level for a
drm_modeset_lock_all()?
Connector probing. And the entire point of crtc locks was to _not_ block all screen updates while we poke for a new edid or do load balancing. If you want to test this you need a gen3/4 with tv-out (native, not through sdvo) or a gen2 or i915g/gm with vga.
Quoted 10 lines
Quoted 9 lines
My original design behind the
crtc->mutexand mode_config.mutex split was that as long as theconnector->crtclinks didn't change you can get away with the crtc lock. setplane made a bit a mess out of this, but strictly speaking as long as you acquire all crtc locks involved in a potential plane switch (whichww_mtuxescan do) it'll be fine. Since noticing whether any connector properties change should be doable upfront I think we should try _really_ hard to keep the mode_config.mutex a plain mutex which wraps all the more fine-grained locks and is a catch-all for everything else but crtcs/planes.
Quoted 5 lines
That is basically how it was in one of the earlier iterations of atomic.. but didn't hold mode_config.mutex in a lot of places where it was previously held.. and while I do want to make locking more fine grained I didn't want to try and do it at the same time as landing all these other changes.
Hm, maybe we should land the locking stuff first? I.e. just convert crtc->mutex into a ww_mutex, and then add more fine-grained locking to e.g. setplane by only grabbing the locks of the involved crtcs with the w/w logic. We might need an additional plane mutex to make it work. Iirc Ville had some patches for just this.
I'm arguing this since locking at the current interface I have a really hard time seeing how we're going to implement this in i915. Still reading around though.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 18 lines · Daniel Vetter
Quoted 17 lines · Rob Clark
Quoted 15 lines · Daniel Vetter
drivers/gpu/drm/i915/intel_display.c bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 6 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +1
-1@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );This is pretty much the reason why I think switching the mode_config.mutex to a
ww_mutexis a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.
Quoted 8 lines
Quoted 3 lines
which is the call-path to here from mode_config.mutex? Is it possible to just move the locking to a higher level for a
drm_modeset_lock_all()?Connector probing. And the entire point of crtc locks was to _not_ block all screen updates while we poke for a new edid or do load balancing. If you want to test this you need a gen3/4 with tv-out (native, not through sdvo) or a gen2 or i915g/gm with vga.
hmm, I guess I'm still not quite seeing the issue. For non-atomic paths, we are grabbing mode_config and/or crtc mutex as bare mutexes in same spots as we did before. So if it worked before without nested_lock stuff it should still work now.
BR,
-R
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 29 lines · Rob Clark
Quoted 18 lines · Daniel Vetter
Quoted 17 lines · Rob Clark
Quoted 15 lines · Daniel Vetter
drivers/gpu/drm/i915/intel_display.c bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 6 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +1
-1@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );This is pretty much the reason why I think switching the mode_config.mutex to a
ww_mutexis a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.Quoted 8 lines
Quoted 3 lines
which is the call-path to here from mode_config.mutex? Is it possible to just move the locking to a higher level for a
drm_modeset_lock_all()?Connector probing. And the entire point of crtc locks was to _not_ block all screen updates while we poke for a new edid or do load balancing. If you want to test this you need a gen3/4 with tv-out (native, not through sdvo) or a gen2 or i915g/gm with vga.
Quoted 4 lines
hmm, I guess I'm still not quite seeing the issue. For non-atomic paths, we are grabbing
mode_configand/or crtc mutex as bare mutexes in same spots as we did before. So if it worked before withoutnested_lockstuff it should still work now.
Thread A is doing output probing.
Thread B is doing atomic modeset
Grabs mode_config.mutex
Grabs crtc_A->ww_mutex
Tries to grab crtc_A->ww_mutex,
blocks since normal ww_mutex_lock
Tries to grab mode_config.mutex with ww acuiquire context, blocks since current holder hasn't acquired the mutex with a ww ticket
-> Deadlock.
You really can't mix lock nesting with w/w and lock nesting with a static hierarchy. It's all or nothing.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 37 lines · Daniel Vetter
Quoted 29 lines · Rob Clark
Quoted 18 lines · Daniel Vetter
Quoted 17 lines · Rob Clark
Quoted 15 lines · Daniel Vetter
drivers/gpu/drm/i915/intel_display.c bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 6 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +1
-1@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );This is pretty much the reason why I think switching the mode_config.mutex to a
ww_mutexis a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.Quoted 8 lines
Quoted 3 lines
which is the call-path to here from mode_config.mutex? Is it possible to just move the locking to a higher level for a
drm_modeset_lock_all()?Connector probing. And the entire point of crtc locks was to _not_ block all screen updates while we poke for a new edid or do load balancing. If you want to test this you need a gen3/4 with tv-out (native, not through sdvo) or a gen2 or i915g/gm with vga.
Quoted 4 lines
hmm, I guess I'm still not quite seeing the issue. For non-atomic paths, we are grabbing
mode_configand/or crtc mutex as bare mutexes in same spots as we did before. So if it worked before withoutnested_lockstuff it should still work now.Thread A is doing output probing.
Quoted 8 lines
Thread B is doing atomic modeset
Grabs mode_config.mutex
Grabs crtc_A->ww_mutexTries to grab
crtc_A->ww_mutex,
blocks since normalww_mutex_lock
.. blocks since normal ww_mutex_lock without acquire ticket.
Otherwise it's a bit unclear.
-Daniel
Quoted 15 lines
Tries to grab mode_config.mutex with ww acuiquire context, blocks since current holder hasn't acquired the mutex with a ww ticket
-> Deadlock.
You really can't mix lock nesting with w/w and lock nesting with a static hierarchy. It's all or nothing.
-DanielSignature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
In reply to Daniel VetterQuoted 43 lines · Daniel Vetter
Quoted 29 lines · Rob Clark
Quoted 18 lines · Daniel Vetter
Quoted 17 lines · Rob Clark
Quoted 15 lines · Daniel Vetter
drivers/gpu/drm/i915/intel_display.c bool intel_get_load_detect_pipe(struct drm_connector *connector, · line 8005
Quoted 6 lines · Rob Clark
drivers/gpu/drm/i915/intel_display.c +1
-1@@ -8002,7 +8002,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );This is pretty much the reason why I think switching the mode_config.mutex to a
ww_mutexis a bad idea: This call here nests within the mode_config.mutex and so must be acquired. Wiring the acquire context through everything is going to be fairly horrible, especially since you must be able to bail out when trying to lock with an axquire context.Quoted 8 lines
Quoted 3 lines
which is the call-path to here from mode_config.mutex? Is it possible to just move the locking to a higher level for a
drm_modeset_lock_all()?Connector probing. And the entire point of crtc locks was to _not_ block all screen updates while we poke for a new edid or do load balancing. If you want to test this you need a gen3/4 with tv-out (native, not through sdvo) or a gen2 or i915g/gm with vga.
Quoted 4 lines
hmm, I guess I'm still not quite seeing the issue. For non-atomic paths, we are grabbing
mode_configand/or crtc mutex as bare mutexes in same spots as we did before. So if it worked before withoutnested_lockstuff it should still work now.Thread A is doing output probing.
Thread B is doing atomic modeset
Grabs mode_config.mutex
Grabs crtc_A->ww_mutex
Quoted 7 lines
Tries to grab
crtc_A->ww_mutex,
blocks since normalww_mutex_lockTries to grab mode_config.mutex with ww acuiquire context, blocks since current holder hasn't acquired the mutex with a ww ticket
hmm, ok, I had thought this case, thread B would get -EDEADLK because lock was held, and not his acquire ctx. If that is not the case, then I would propose this:
All places doing things the old way, must grab mode_config.mutex first currently. And we use mode_config.mutex to protect mode_config.acquire_ctx. So all the lower spots grabbing individual crtc mutexes can safely use mode_config.acquire_ctx.
Then the only headache is propagating -EDEADLK up the call stack. If we are lucky, the all already propagate -EINTR, etc.
BR,
-R
Quoted 10 lines
-> Deadlock.
You really can't mix lock nesting with w/w and lock nesting with a static hierarchy. It's all or nothing.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 11 lines · Rob Clark
hmm, ok, I had thought this case, thread B would get
-EDEADLKbecause lock was held, and not his acquire ctx. If that is not the case, then I would propose this:All places doing things the old way, must grab mode_config.mutex first currently. And we use mode_config.mutex to protect mode_config.acquire_ctx. So all the lower spots grabbing individual crtc mutexes can safely use mode_config.acquire_ctx.
Then the only headache is propagating
-EDEADLKup the call stack. If we are lucky, the all already propagate-EINTR, etc.
The output poll work most definitely doesn't propagate -EINTR. Like I've said, this will be painful. And imo doing this also makes the kms locking into quite a mess overall.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 10 lines · Daniel Vetter
Quoted 9 lines · Rob Clark
hmm, ok, I had thought this case, thread B would get
-EDEADLKbecause lock was held, and not his acquire ctx. If that is not the case, then I would propose this:All places doing things the old way, must grab mode_config.mutex first currently. And we use mode_config.mutex to protect mode_config.acquire_ctx. So all the lower spots grabbing individual crtc mutexes can safely use mode_config.acquire_ctx.
Quoted 6 lines
Quoted 2 lines
Then the only headache is propagating
-EDEADLKup the call stack. If we are lucky, the all already propagate-EINTR, etc.The output poll work most definitely doesn't propagate
-EINTR. Like I've said, this will be painful. And imo doing this also makes the kms locking into quite a mess overall.
Well, we could hold mode_config.mutex as a traditional mutex around atomic operations. What you loose out would be now _NONBLOCK operations could conceivable call into driver paths without mode_config.mutex held. This was the advantage of converting mode_config.mutex as well. Granted, it is slightly theoretical because until we expose atomic ioctl it would only apply to page_flip (which was not holding mode_config.mutex). And we also want to get rid of mode_config.mutex in these paths too.
Otoh, if we want to make locking more fine grained, more use of ww_mutex seems like the best way. And if that means adding a return value to a fxn here/there and propagating errors properly, maybe we should just go ahead and do that. It sounds like the right long term solution anyways.
BR,
-R
Quoted 5 lines
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 27 lines · Rob Clark
Quoted 10 lines · Daniel Vetter
Quoted 9 lines · Rob Clark
hmm, ok, I had thought this case, thread B would get
-EDEADLKbecause lock was held, and not his acquire ctx. If that is not the case, then I would propose this:All places doing things the old way, must grab mode_config.mutex first currently. And we use mode_config.mutex to protect mode_config.acquire_ctx. So all the lower spots grabbing individual crtc mutexes can safely use mode_config.acquire_ctx.
Quoted 6 lines
Quoted 2 lines
Then the only headache is propagating
-EDEADLKup the call stack. If we are lucky, the all already propagate-EINTR, etc.The output poll work most definitely doesn't propagate
-EINTR. Like I've said, this will be painful. And imo doing this also makes the kms locking into quite a mess overall.Well, we could hold mode_config.mutex as a traditional mutex around atomic operations. What you loose out would be now
_NONBLOCKoperations could conceivable call into driver paths without mode_config.mutex held. This was the advantage of converting mode_config.mutex as well. Granted, it is slightly theoretical because until we expose atomic ioctl it would only apply topage_flip(which was not holding mode_config.mutex). And we also want to get rid of mode_config.mutex in these paths too.
Quoted 5 lines
Otoh, if we want to make locking more fine grained, more use of
ww_mutexseems like the best way. And if that means adding a return value to a fxn here/there and propagating errors properly, maybe we should just go ahead and do that. It sounds like the right long term solution anyways.
Yeah, I'm starting to lean towards trying to elide mode_config.mutex completely from the atomic paths (and modesets in general). I think the only bits we really need is adding ww mutexes to planes _and_ to connectors. The atomic would _only_ ever acquire ww mutexes, and we would be able to guarante that most of them are only held short times so that we don't need to bother with trylocking them for NONBLOCK. That should simply the atomic logic a bit I hope.
So that, and a full subsystem audit unfortunately :( -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 42 lines · Daniel Vetter
Quoted 27 lines · Rob Clark
Quoted 10 lines · Daniel Vetter
Quoted 9 lines · Rob Clark
hmm, ok, I had thought this case, thread B would get
-EDEADLKbecause lock was held, and not his acquire ctx. If that is not the case, then I would propose this:All places doing things the old way, must grab mode_config.mutex first currently. And we use mode_config.mutex to protect mode_config.acquire_ctx. So all the lower spots grabbing individual crtc mutexes can safely use mode_config.acquire_ctx.
Quoted 6 lines
Quoted 2 lines
Then the only headache is propagating
-EDEADLKup the call stack. If we are lucky, the all already propagate-EINTR, etc.The output poll work most definitely doesn't propagate
-EINTR. Like I've said, this will be painful. And imo doing this also makes the kms locking into quite a mess overall.Well, we could hold mode_config.mutex as a traditional mutex around atomic operations. What you loose out would be now
_NONBLOCKoperations could conceivable call into driver paths without mode_config.mutex held. This was the advantage of converting mode_config.mutex as well. Granted, it is slightly theoretical because until we expose atomic ioctl it would only apply topage_flip(which was not holding mode_config.mutex). And we also want to get rid of mode_config.mutex in these paths too.Quoted 5 lines
Otoh, if we want to make locking more fine grained, more use of
ww_mutexseems like the best way. And if that means adding a return value to a fxn here/there and propagating errors properly, maybe we should just go ahead and do that. It sounds like the right long term solution anyways.Yeah, I'm starting to lean towards trying to elide mode_config.mutex completely from the atomic paths (and modesets in general). I think the only bits we really need is adding ww mutexes to planes _and_ to connectors. The atomic would _only_ ever acquire ww mutexes, and we would be able to guarante that most of them are only held short times so that we don't need to bother with trylocking them for NONBLOCK. That should simply the atomic logic a bit I hope.
Quoted 1 line
So that, and a full subsystem audit unfortunately :(
well, getting rid of any global lock from atomic path is, I hope, the eventual goal. But we are *really* late already with atomic, and too many other things backing up on top of this. I suppose I should have a closer look at the detect paths, to just see how hairy the alternative of adding error propagation would be. Although maybe not today (it is supposed to be a holiday here.. and I've already spent enough of the weekend on atomic ;-))
Just to get *something* merged to unblock driver work and maybe get people starting to think about plumbing this through userspace (xrandr atomic modeset, for example), maybe the way to go is just revert mode_config.mutex to a traditional mutex for now. The weird cases only start to come up with real atomic ioctls, and we could use a driver flag to opt-in to that on a per driver basis.
BR,
-R
Quoted 5 lines
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 03/17] drm: convert crtc and mode_config to ww_mutex
Quoted 53 lines · Rob Clark
Quoted 42 lines · Daniel Vetter
Quoted 27 lines · Rob Clark
Quoted 10 lines · Daniel Vetter
Quoted 9 lines · Rob Clark
hmm, ok, I had thought this case, thread B would get
-EDEADLKbecause lock was held, and not his acquire ctx. If that is not the case, then I would propose this:All places doing things the old way, must grab mode_config.mutex first currently. And we use mode_config.mutex to protect mode_config.acquire_ctx. So all the lower spots grabbing individual crtc mutexes can safely use mode_config.acquire_ctx.
Quoted 6 lines
Quoted 2 lines
Then the only headache is propagating
-EDEADLKup the call stack. If we are lucky, the all already propagate-EINTR, etc.The output poll work most definitely doesn't propagate
-EINTR. Like I've said, this will be painful. And imo doing this also makes the kms locking into quite a mess overall.Well, we could hold mode_config.mutex as a traditional mutex around atomic operations. What you loose out would be now
_NONBLOCKoperations could conceivable call into driver paths without mode_config.mutex held. This was the advantage of converting mode_config.mutex as well. Granted, it is slightly theoretical because until we expose atomic ioctl it would only apply topage_flip(which was not holding mode_config.mutex). And we also want to get rid of mode_config.mutex in these paths too.Quoted 5 lines
Otoh, if we want to make locking more fine grained, more use of
ww_mutexseems like the best way. And if that means adding a return value to a fxn here/there and propagating errors properly, maybe we should just go ahead and do that. It sounds like the right long term solution anyways.Yeah, I'm starting to lean towards trying to elide mode_config.mutex completely from the atomic paths (and modesets in general). I think the only bits we really need is adding ww mutexes to planes _and_ to connectors. The atomic would _only_ ever acquire ww mutexes, and we would be able to guarante that most of them are only held short times so that we don't need to bother with trylocking them for NONBLOCK. That should simply the atomic logic a bit I hope.
Quoted 1 line
So that, and a full subsystem audit unfortunately :(
well, getting rid of any global lock from atomic path is, I hope, the eventual goal. But we are *really* late already with atomic, and too many other things backing up on top of this. I suppose I should have a closer look at the detect paths, to just see how hairy the alternative of adding error propagation would be. Although maybe not today (it is supposed to be a holiday here.. and I've already spent enough of the weekend on atomic ;-))
Quoted 6 lines
Just to get *something* merged to unblock driver work and maybe get people starting to think about plumbing this through userspace (xrandr atomic modeset, for example), maybe the way to go is just revert mode_config.mutex to a traditional mutex for now. The weird cases only start to come up with real atomic ioctls, and we could use a driver flag to opt-in to that on a per driver basis.
This will result in people raving about regressions, which from a maintainer pov I'll reject. If we want to chicken out of this question I'd vote for an drm_modeset_lock_all for the atomic paths, which also isn't really helpful. I don't really think there's an easy answer.
Wrt unblocking driver work: In i915 we keep on plunging ahead without the interface stuff thus far. And wrt unblocking everything else: I hear a lot of people screaming about the lack of atomic updates, but at least within Intel not many people throwing resources at it. So my impression is that it can't be that bad really.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 4/17 drm: add object property type
In reply to Rob ClarkAn object property is an id (idr) for a drm mode object. This will allow a property to be used set/get a framebuffer, CRTC, etc.
--- drivers/gpu/drm/drm_crtc.c | 60 +++++++++++++++++++++++++++++++++++---------- include/drm/drm_crtc.h | 27 ++++++++++++++++++++ include/uapi/drm/drm_mode.h | 14 +++++++++++ 3 files changed, 88 insertions(+), 13 deletions(-)
drivers/gpu/drm/drm_crtc.c +47 -13
@@ -3142,6 +3142,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,if (!property)return NULL ; + property->dev = dev; +if (num_values) { property->values =kzalloc (sizeof (uint64_t )*num_values,GFP_KERNEL );if (!property->values)
@@ -3162,6 +3164,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, }list_add_tail (&property->head, &dev->mode_config.property_list); + +BUG_ON (!drm_property_type_valid (property)); +return property; fail:kfree (property->values);
@@ -3299,6 +3304,23 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags }EXPORT_SYMBOL (drm_property_create_range); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type) +{ +struct drm_property *property; + + flags |=DRM_MODE_PROP_OBJECT ; + + property =drm_property_create (dev, flags, name,1 ); +if (!property) +return NULL ; + + property->values[0 ] = type; + +return property; +} +EXPORT_SYMBOL (drm_property_create_object); +/** * drm_property_add_enum - add a possible value to an enumeration property * @property: enumeration property to change
@@ -3319,14 +3341,16 @@ int drm_property_add_enum(struct drm_property *property, int index, {struct drm_property_enum *prop_enum; -if (!(property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK ))) +if (!(drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )))return -EINVAL ;/* * Bitmask enum properties have the additional constraint of values * from 0 to 63 */ -if ((property->flags &DRM_MODE_PROP_BITMASK ) && (value >63 )) +if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK ) && + (value >63 ))return -EINVAL ;if (!list_empty (&property->enum_blob_list)) {
@@ -3509,10 +3533,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } property =obj_to_property (obj); -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {list_for_each_entry (prop_enum, &property->enum_blob_list, head) enum_count++; - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {list_for_each_entry (prop_blob, &property->enum_blob_list, head) blob_count++; }
@@ -3534,7 +3559,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } out_resp->count_values = value_count; -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied =0 ; enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long )out_resp->enum_blob_ptr;
@@ -3556,7 +3582,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_enum_blobs = enum_count; } -if (property->flags &DRM_MODE_PROP_BLOB ) { +if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { copied =0 ; blob_id_ptr = (uint32_t __user *)(unsigned long )out_resp->enum_blob_ptr;
@@ -3712,19 +3738,25 @@ static bool drm_property_change_is_valid(struct drm_property *property, {if (property->flags &DRM_MODE_PROP_IMMUTABLE )return false; -if (property->flags &DRM_MODE_PROP_RANGE ) { + +if (drm_property_type_is (property,DRM_MODE_PROP_RANGE )) {if (value < property->values[0 ] || value > property->values[1 ])return false;return true; - }else if (property->flags &DRM_MODE_PROP_BITMASK ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {int i;uint64_t valid_mask =0 ;for (i =0 ; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]);return !(value & ~valid_mask); - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {/* Only the driver knows */ return true; + }else if (drm_property_type_is (property,DRM_MODE_PROP_OBJECT )) { +/* a zero value for an object property translates to null: */ +if (value ==0 ) +return true; +return drm_property_get_obj (property, value) !=NULL ; }else {int i;for (i =0 ; i < property->num_values; i++)
@@ -3815,9 +3847,9 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,return ret; } -static int drm_mode_set_obj_prop (struct drm_device *dev, -struct drm_mode_object *obj,struct drm_atomic_state *state, -struct drm_property *property,uint64_t value,void *blob_data) +static int drm_mode_set_obj_prop (struct drm_mode_object *obj, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data) {if (drm_property_change_is_valid (property, value)) {switch (obj->type) {
@@ -3831,6 +3863,8 @@ static int drm_mode_set_obj_prop(struct drm_device *dev,return drm_mode_plane_set_obj_prop (obj_to_plane (obj), state, property, value, blob_data); } + }else { +DRM_DEBUG ("invalid value: %s = %llx\n" , property->name, value); }return -EINVAL ;
@@ -3866,7 +3900,7 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev,return -ENOENT ; property =obj_to_property (prop_obj); -return drm_mode_set_obj_prop (dev, arg_obj, state, property, +return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data); }
include/drm/drm_crtc.h +27 -0
@@ -191,6 +191,7 @@ struct drm_property {char name[DRM_PROP_NAME_LEN ];uint32_t num_values;uint64_t *values; +struct drm_device *dev;struct list_head enum_blob_list; };
@@ -941,6 +942,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev);extern int drm_mode_connector_update_edid_property (struct drm_connector *connector,struct edid *edid); + +static inline bool drm_property_type_is (struct drm_property *property, +uint32_t type) +{ +/* instanceof for props.. handles extended type vs original types: */ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) == type; +return property->flags & type; +} + +static inline bool drm_property_type_valid (struct drm_property *property) +{ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return !(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +return !!(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +} +extern int drm_object_property_set_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t val);
@@ -974,6 +992,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,struct drm_property *drm_property_create_range (struct drm_device *dev,int flags,const char *name,uint64_t min,uint64_t max); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type);extern void drm_property_destroy (struct drm_device *dev,struct drm_property *property);extern int drm_property_add_enum (struct drm_property *property,int index,uint64_t value,const char *name);
@@ -990,6 +1010,13 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size);extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); + +static inline struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return drm_mode_object_find (property->dev, value, property->values[0 ]); +} +/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);
include/uapi/drm/drm_mode.h +14 -0
@@ -251,6 +251,20 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_BLOB (1<<4)#define DRM_MODE_PROP_BITMASK (1<<5)/* bitmask of enumerated types */ +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, +* grab a chunk of the bits to use as integer type id. +*/ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE (n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ];
Signature · 1 line
1.9.0
Re: [PATCH 04/17] drm: add object property type
Quoted 125 lines · Rob Clark
An object property is an id (idr) for a drm mode object. This will allow a property to be used set/get a framebuffer, CRTC, etc.
Signed-off-by Rob Clark <[email protected]>--- drivers/gpu/drm/drm_crtc.c | 60 +++++++++++++++++++++++++++++++++++---------- include/drm/drm_crtc.h | 27 ++++++++++++++++++++ include/uapi/drm/drm_mode.h | 14 +++++++++++ 3 files changed, 88 insertions(+), 13 deletions(-)drivers/gpu/drm/drm_crtc.c +35
-8@@ -3142,6 +3142,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,if (!property)return NULL ; + property->dev = dev; +if (num_values) { property->values =kzalloc (sizeof (uint64_t )*num_values,GFP_KERNEL );if (!property->values)@@ -3162,6 +3164,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, }list_add_tail (&property->head, &dev->mode_config.property_list); + +BUG_ON (!drm_property_type_valid (property)); +return property; fail:kfree (property->values);@@ -3299,6 +3304,23 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags }EXPORT_SYMBOL (drm_property_create_range); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type) +{ +struct drm_property *property; + + flags |=DRM_MODE_PROP_OBJECT ; + + property =drm_property_create (dev, flags, name,1 ); +if (!property) +return NULL ; + + property->values[0 ] = type; + +return property; +} +EXPORT_SYMBOL (drm_property_create_object); +/** * drm_property_add_enum - add a possible value to an enumeration property * @property: enumeration property to change @@ -3319,14 +3341,16 @@ int drm_property_add_enum(struct drm_property *property, int index, {struct drm_property_enum *prop_enum; -if (!(property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK ))) +if (!(drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )))return -EINVAL ;/* * Bitmask enum properties have the additional constraint of values * from 0 to 63 */ -if ((property->flags &DRM_MODE_PROP_BITMASK ) && (value >63 )) +if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK ) && + (value >63 ))return -EINVAL ;if (!list_empty (&property->enum_blob_list)) {@@ -3509,10 +3533,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } property =obj_to_property (obj); -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {list_for_each_entry (prop_enum, &property->enum_blob_list, head) enum_count++; - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {list_for_each_entry (prop_blob, &property->enum_blob_list, head) blob_count++; }@@ -3534,7 +3559,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } out_resp->count_values = value_count; -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied =0 ; enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long )out_resp->enum_blob_ptr;@@ -3556,7 +3582,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_enum_blobs = enum_count; } -if (property->flags &DRM_MODE_PROP_BLOB ) { +if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { copied =0 ; blob_id_ptr = (uint32_t __user *)(unsigned long )out_resp->enum_blob_ptr;@@ -3712,19 +3738,25 @@ static bool drm_property_change_is_valid(struct drm_property *property, {if (property->flags &DRM_MODE_PROP_IMMUTABLE )return false; -if (property->flags &DRM_MODE_PROP_RANGE ) { + +if (drm_property_type_is (property,DRM_MODE_PROP_RANGE )) {if (value < property->values[0 ] || value > property->values[1 ])return false;return true; - }else if (property->flags &DRM_MODE_PROP_BITMASK ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {int i;uint64_t valid_mask =0 ;for (i =0 ; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]);
drivers/gpu/drm/drm_crtc.c static bool drm_property_change_is_valid(struct drm_property *property, · line 3759
Quoted 10 lines
drivers/gpu/drm/drm_crtc.c +6
-1return !(value & ~valid_mask); - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {/* Only the driver knows */ return true; + }else if (drm_property_type_is (property,DRM_MODE_PROP_OBJECT )) { +/* a zero value for an object property translates to null: */ +if (value ==0 ) +return true; +return drm_property_get_obj (property, value) !=NULL ;
Ok, so this usage is indeed safe for framebuffers since you only compare the pointer against NULL. But you can't ever access this pointer since it might disappear any time after you've dropped the idr lock. I think what you actually want here is a new interface drm_mode_object_exists which just returns a bool.
That won't expose any risky things to callers and we can still keep the restriction that calling drm_mode_object_get for framebuffers is a BUG. -Daniel
Quoted 121 lines
drivers/gpu/drm/drm_crtc.c +6
-4}else {int i;for (i =0 ; i < property->num_values; i++)@@ -3815,9 +3847,9 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,return ret; } -static int drm_mode_set_obj_prop (struct drm_device *dev, -struct drm_mode_object *obj,struct drm_atomic_state *state, -struct drm_property *property,uint64_t value,void *blob_data) +static int drm_mode_set_obj_prop (struct drm_mode_object *obj, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data) {if (drm_property_change_is_valid (property, value)) {switch (obj->type) {@@ -3831,6 +3863,8 @@ static int drm_mode_set_obj_prop(struct drm_device *dev,return drm_mode_plane_set_obj_prop (obj_to_plane (obj), state, property, value, blob_data); } + }else { +DRM_DEBUG ("invalid value: %s = %llx\n" , property->name, value); }return -EINVAL ;@@ -3866,7 +3900,7 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev,return -ENOENT ; property =obj_to_property (prop_obj); -return drm_mode_set_obj_prop (dev, arg_obj, state, property, +return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data); }include/drm/drm_crtc.h +27
-0@@ -191,6 +191,7 @@ struct drm_property {char name[DRM_PROP_NAME_LEN ];uint32_t num_values;uint64_t *values; +struct drm_device *dev;struct list_head enum_blob_list; };@@ -941,6 +942,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev);extern int drm_mode_connector_update_edid_property (struct drm_connector *connector,struct edid *edid); + +static inline bool drm_property_type_is (struct drm_property *property, +uint32_t type) +{ +/* instanceof for props.. handles extended type vs original types: */ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) == type; +return property->flags & type; +} + +static inline bool drm_property_type_valid (struct drm_property *property) +{ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return !(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +return !!(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +} +extern int drm_object_property_set_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t val);@@ -974,6 +992,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,struct drm_property *drm_property_create_range (struct drm_device *dev,int flags,const char *name,uint64_t min,uint64_t max); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type);extern void drm_property_destroy (struct drm_device *dev,struct drm_property *property);extern int drm_property_add_enum (struct drm_property *property,int index,uint64_t value,const char *name);@@ -990,6 +1010,13 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size);extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); + +static inline struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return drm_mode_object_find (property->dev, value, property->values[0 ]); +} +/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);include/uapi/drm/drm_mode.h +14
-0@@ -251,6 +251,20 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_BLOB (1<<4)#define DRM_MODE_PROP_BITMASK (1<<5)/* bitmask of enumerated types */ +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, +* grab a chunk of the bits to use as integer type id. +*/ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE (n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ];Signature · 1 line
1.9.0
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 04/17] drm: add object property type
Quoted 13 lines · Daniel Vetter
drivers/gpu/drm/drm_crtc.c static bool drm_property_change_is_valid(struct drm_property *property, · line 3759
Quoted 5 lines · Rob Clark
drivers/gpu/drm/drm_crtc.c +5
-0+ }else if (drm_property_type_is (property,DRM_MODE_PROP_OBJECT )) { +/* a zero value for an object property translates to null: */ +if (value ==0 ) +return true; +return drm_property_get_obj (property, value) !=NULL ;Ok, so this usage is indeed safe for framebuffers since you only compare the pointer against NULL. But you can't ever access this pointer since it might disappear any time after you've dropped the idr lock. I think what you actually want here is a new interface
drm_mode_object_existswhich just returns a bool.
Quoted 2 lines
That won't expose any risky things to callers and we can still keep the restriction that calling
drm_mode_object_getfor framebuffers is a BUG.
s/object_get/object_find/ I've meant ofc.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 04/17] drm: add object property type
In reply to Daniel VetterQuoted 134 lines · Daniel Vetter
Quoted 133 lines · Rob Clark
An object property is an id (idr) for a drm mode object. This will allow a property to be used set/get a framebuffer, CRTC, etc.
Signed-off-by Rob Clark <[email protected]>--- drivers/gpu/drm/drm_crtc.c | 60 +++++++++++++++++++++++++++++++++++---------- include/drm/drm_crtc.h | 27 ++++++++++++++++++++ include/uapi/drm/drm_mode.h | 14 +++++++++++ 3 files changed, 88 insertions(+), 13 deletions(-)drivers/gpu/drm/drm_crtc.c +39
-9@@ -3142,6 +3142,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,if (!property)return NULL ; + property->dev = dev; +if (num_values) { property->values =kzalloc (sizeof (uint64_t )*num_values,GFP_KERNEL );if (!property->values)@@ -3162,6 +3164,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, }list_add_tail (&property->head, &dev->mode_config.property_list); + +BUG_ON (!drm_property_type_valid (property)); +return property; fail:kfree (property->values);@@ -3299,6 +3304,23 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags }EXPORT_SYMBOL (drm_property_create_range); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type) +{ +struct drm_property *property; + + flags |=DRM_MODE_PROP_OBJECT ; + + property =drm_property_create (dev, flags, name,1 ); +if (!property) +return NULL ; + + property->values[0 ] = type; + +return property; +} +EXPORT_SYMBOL (drm_property_create_object); +/** * drm_property_add_enum - add a possible value to an enumeration property * @property: enumeration property to change @@ -3319,14 +3341,16 @@ int drm_property_add_enum(struct drm_property *property, int index, {struct drm_property_enum *prop_enum; -if (!(property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK ))) +if (!(drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )))return -EINVAL ;/* * Bitmask enum properties have the additional constraint of values * from 0 to 63 */ -if ((property->flags &DRM_MODE_PROP_BITMASK ) && (value >63 )) +if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK ) && + (value >63 ))return -EINVAL ;if (!list_empty (&property->enum_blob_list)) {@@ -3509,10 +3533,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } property =obj_to_property (obj); -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {list_for_each_entry (prop_enum, &property->enum_blob_list, head) enum_count++; - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {list_for_each_entry (prop_blob, &property->enum_blob_list, head) blob_count++; }@@ -3534,7 +3559,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, } out_resp->count_values = value_count; -if (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) { +if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) || +drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied =0 ; enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long )out_resp->enum_blob_ptr;@@ -3556,7 +3582,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_enum_blobs = enum_count; } -if (property->flags &DRM_MODE_PROP_BLOB ) { +if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { copied =0 ; blob_id_ptr = (uint32_t __user *)(unsigned long )out_resp->enum_blob_ptr;@@ -3712,19 +3738,25 @@ static bool drm_property_change_is_valid(struct drm_property *property, {if (property->flags &DRM_MODE_PROP_IMMUTABLE )return false; -if (property->flags &DRM_MODE_PROP_RANGE ) { + +if (drm_property_type_is (property,DRM_MODE_PROP_RANGE )) {if (value < property->values[0 ] || value > property->values[1 ])return false;return true; - }else if (property->flags &DRM_MODE_PROP_BITMASK ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {int i;uint64_t valid_mask =0 ;for (i =0 ; i < property->num_values; i++) valid_mask |= (1ULL << property->values[i]);return !(value & ~valid_mask); - }else if (property->flags &DRM_MODE_PROP_BLOB ) { + }else if (drm_property_type_is (property,DRM_MODE_PROP_BLOB )) {/* Only the driver knows */ return true; + }else if (drm_property_type_is (property,DRM_MODE_PROP_OBJECT )) { +/* a zero value for an object property translates to null: */ +if (value ==0 )
Quoted 8 lines
drivers/gpu/drm/drm_crtc.c static bool drm_property_change_is_valid(struct drm_property *property, · line 3759
Quoted 2 lines
drivers/gpu/drm/drm_crtc.c +2
-0+return true; +return drm_property_get_obj (property, value) !=NULL ;Ok, so this usage is indeed safe for framebuffers since you only compare the pointer against NULL. But you can't ever access this pointer since it might disappear any time after you've dropped the idr lock. I think what you actually want here is a new interface
drm_mode_object_existswhich just returns a bool.
Hmm, I think I'll just drop drm_property_get_obj() and call directly _object_find() here, I think. Unless we come up with other spots that need a drm_mode_object_exists(). That would avoid potential future misunderstandings.
BR,
-R
Quoted 130 lines
That won't expose any risky things to callers and we can still keep the restriction that calling
drm_mode_object_getfor framebuffers is a BUG. -DanielQuoted 119 lines
drivers/gpu/drm/drm_crtc.c +6
-4}else {int i;for (i =0 ; i < property->num_values; i++)@@ -3815,9 +3847,9 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,return ret; } -static int drm_mode_set_obj_prop (struct drm_device *dev, -struct drm_mode_object *obj,struct drm_atomic_state *state, -struct drm_property *property,uint64_t value,void *blob_data) +static int drm_mode_set_obj_prop (struct drm_mode_object *obj, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data) {if (drm_property_change_is_valid (property, value)) {switch (obj->type) {@@ -3831,6 +3863,8 @@ static int drm_mode_set_obj_prop(struct drm_device *dev,return drm_mode_plane_set_obj_prop (obj_to_plane (obj), state, property, value, blob_data); } + }else { +DRM_DEBUG ("invalid value: %s = %llx\n" , property->name, value); }return -EINVAL ;@@ -3866,7 +3900,7 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev,return -ENOENT ; property =obj_to_property (prop_obj); -return drm_mode_set_obj_prop (dev, arg_obj, state, property, +return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data); }include/drm/drm_crtc.h +27
-0@@ -191,6 +191,7 @@ struct drm_property {char name[DRM_PROP_NAME_LEN ];uint32_t num_values;uint64_t *values; +struct drm_device *dev;struct list_head enum_blob_list; };@@ -941,6 +942,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev);extern int drm_mode_connector_update_edid_property (struct drm_connector *connector,struct edid *edid); + +static inline bool drm_property_type_is (struct drm_property *property, +uint32_t type) +{ +/* instanceof for props.. handles extended type vs original types: */ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) == type; +return property->flags & type; +} + +static inline bool drm_property_type_valid (struct drm_property *property) +{ +if (property->flags &DRM_MODE_PROP_EXTENDED_TYPE ) +return !(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +return !!(property->flags &DRM_MODE_PROP_LEGACY_TYPE ); +} +extern int drm_object_property_set_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t val);@@ -974,6 +992,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,struct drm_property *drm_property_create_range (struct drm_device *dev,int flags,const char *name,uint64_t min,uint64_t max); +struct drm_property *drm_property_create_object (struct drm_device *dev, +int flags,const char *name,uint32_t type);extern void drm_property_destroy (struct drm_device *dev,struct drm_property *property);extern int drm_property_add_enum (struct drm_property *property,int index,uint64_t value,const char *name);@@ -990,6 +1010,13 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size);extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); + +static inline struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return drm_mode_object_find (property->dev, value, property->values[0 ]); +} +/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);include/uapi/drm/drm_mode.h +14
-1@@ -251,6 +251,20 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_BLOB (1<<4)#define DRM_MODE_PROP_BITMASK (1<<5)/* bitmask of enumerated types */ +/* non-extended types: legacy bitmask, one bit per type: */ +#define DRM_MODE_PROP_LEGACY_TYPE ( \ + DRM_MODE_PROP_RANGE | \ + DRM_MODE_PROP_ENUM | \ + DRM_MODE_PROP_BLOB | \ + DRM_MODE_PROP_BITMASK) + +/* extended-types: rather than continue to consume a bit per type, +* grab a chunk of the bits to use as integer type id. +*/ +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 +#define DRM_MODE_PROP_TYPE (n) ((n) << 6) +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ]; --Quoted 2 lines
1.9.0
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 5/17 drm: add signed-range property type
In reply to Rob ClarkLike range, but values are signed.
--- drivers/gpu/drm/drm_crtc.c | 45 +++++++++++++++++++++++++++++++++------------ include/drm/drm_crtc.h | 12 ++++++++++++ include/uapi/drm/drm_mode.h | 1 + 3 files changed, 46 insertions(+), 12 deletions(-)
drivers/gpu/drm/drm_crtc.c +33 -12
@@ -3267,6 +3267,22 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev, }EXPORT_SYMBOL (drm_property_create_bitmask); +static struct drm_property *property_create_range (struct drm_device *dev, +int flags,const char *name, +uint64_t min,uint64_t max) +{ +struct drm_property *property; + + property =drm_property_create (dev, flags, name,2 ); +if (!property) +return NULL ; + + property->values[0 ] = min; + property->values[1 ] = max; + +return property; +} +/** * drm_property_create - create a new ranged property type * @dev: drm device
@@ -3289,21 +3305,20 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flagsconst char *name, uint64_t min, uint64_t max) { - struct drm_property *property; - - flags |=DRM_MODE_PROP_RANGE ; - - property =drm_property_create (dev, flags, name,2 ); -if (!property) -return NULL ; - - property->values[0 ] = min; - property->values[1 ] = max; - -return property; + return property_create_range(dev, DRM_MODE_PROP_RANGE | flags, +name ,min ,max ); }EXPORT_SYMBOL (drm_property_create_range); +struct drm_property *drm_property_create_signed_range (struct drm_device *dev, +int flags,const char *name, +int64_t min,int64_t max) +{ +return property_create_range (dev,DRM_MODE_PROP_SIGNED_RANGE | flags, + name,I642U64 (min),I642U64 (max)); +} +EXPORT_SYMBOL (drm_property_create_signed_range); +struct drm_property *drm_property_create_object (struct drm_device *dev,int flags,const char *name,uint32_t type) {
@@ -3743,6 +3758,12 @@ static bool drm_property_change_is_valid(struct drm_property *property,if (value < property->values[0 ] || value > property->values[1 ])return false;return true; + }else if (drm_property_type_is (property,DRM_MODE_PROP_SIGNED_RANGE )) { +int64_t svalue =U642I64 (value); +if (svalue <U642I64 (property->values[0 ]) || + svalue >U642I64 (property->values[1 ])) +return false; +return true; }else if (drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {int i;uint64_t valid_mask =0 ;
include/drm/drm_crtc.h +12 -0
@@ -65,6 +65,15 @@ struct drm_object_properties {uint64_t values[DRM_OBJECT_MAX_PROPERTY ]; }; +static inline int64_t U642I64 (uint64_t val) +{ +return (int64_t )*((int64_t *)&val); +} +static inline uint64_t I642U64 (int64_t val) +{ +return (uint64_t )*((uint64_t *)&val); +} +enum drm_connector_force {DRM_FORCE_UNSPECIFIED ,DRM_FORCE_OFF ,
@@ -992,6 +1001,9 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,struct drm_property *drm_property_create_range (struct drm_device *dev,int flags,const char *name,uint64_t min,uint64_t max); +struct drm_property *drm_property_create_signed_range (struct drm_device *dev, +int flags,const char *name, +int64_t min,int64_t max);struct drm_property *drm_property_create_object (struct drm_device *dev,int flags,const char *name,uint32_t type);extern void drm_property_destroy (struct drm_device *dev,struct drm_property *property);
include/uapi/drm/drm_mode.h +1 -0
@@ -264,6 +264,7 @@ struct drm_mode_get_connector {#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0#define DRM_MODE_PROP_TYPE (n) ((n) << 6)#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) +#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)struct drm_mode_property_enum {__u64 value;
Signature · 1 line
1.9.0
PATCH 6/17 drm: helpers to find mode objects
In reply to Rob ClarkAdd a few more useful helpers to find mode objects.
--- drivers/gpu/drm/drm_crtc.c | 97 ++++++++++++++-------------------------------- include/drm/drm_crtc.h | 33 ++++++++++++++++ 2 files changed, 63 insertions(+), 67 deletions(-)
drivers/gpu/drm/drm_crtc.c +30 -67
@@ -1736,7 +1736,6 @@ int drm_mode_getcrtc(struct drm_device *dev, {struct drm_mode_crtc *crtc_resp = data;struct drm_crtc *crtc; -struct drm_mode_object *obj;int ret =0 ;if (!drm_core_check_feature (dev,DRIVER_MODESET ))
@@ -1744,13 +1743,11 @@ int drm_mode_getcrtc(struct drm_device *dev,drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_resp->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_resp->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); crtc_resp->x = crtc->x; crtc_resp->y = crtc->y;
@@ -1804,7 +1801,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_connector *out_resp = data; -struct drm_mode_object *obj;struct drm_connector *connector;struct drm_display_mode *mode;int mode_count =0 ;
@@ -1828,13 +1824,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,drm_modeset_lock (&dev->mode_config.mutex,NULL ); - obj =drm_mode_object_find (dev, out_resp->connector_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_resp->connector_id); +if (!connector) { ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj); props_count = connector->properties.count;
@@ -1949,7 +1943,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_encoder *enc_resp = data; -struct drm_mode_object *obj;struct drm_encoder *encoder;int ret =0 ;
@@ -1957,13 +1950,11 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, enc_resp->encoder_id, -DRM_MODE_OBJECT_ENCODER ); -if (!obj) { + encoder =drm_encoder_find (dev, enc_resp->encoder_id); +if (!encoder) { ret = -ENOENT ; goto out; } - encoder =obj_to_encoder (obj);if (encoder->crtc) enc_resp->crtc_id = encoder->crtc->base.id;
@@ -2061,7 +2052,6 @@ int drm_mode_getplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_plane *plane_resp = data; -struct drm_mode_object *obj;struct drm_plane *plane;uint32_t __user *format_ptr;int ret =0 ;
@@ -2070,13 +2060,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, plane_resp->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_resp->plane_id); +if (!plane) { ret = -ENOENT ; goto out; } - plane =obj_to_plane (obj);if (plane->crtc) plane_resp->crtc_id = plane->crtc->base.id;
@@ -2129,7 +2117,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; -struct drm_mode_object *obj;struct drm_plane *plane;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;
@@ -2144,14 +2131,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,* First, find the plane, crtc, and fb objects. If not available, * we don't bother to call the driver. */ - obj =drm_mode_object_find (dev, plane_req->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_req->plane_id); +if (!plane) {DRM_DEBUG_KMS ("Unknown plane ID %d\n" , plane_req->plane_id);return -ENOENT ; } - plane =obj_to_plane (obj);/* No fb means shut it down */ if (!plane_req->fb_id) {
@@ -2168,15 +2153,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, plane_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, plane_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , plane_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); fb =drm_framebuffer_lookup (dev, plane_req->fb_id);if (!fb) {
@@ -2363,7 +2346,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, {struct drm_mode_config *config = &dev->mode_config;struct drm_mode_crtc *crtc_req = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_connector **connector_set =NULL , *connector;struct drm_framebuffer *fb =NULL ;
@@ -2381,14 +2363,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,return -ERANGE ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , crtc_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);DRM_DEBUG_KMS ("[CRTC:%d]\n" , crtc->base.id);if (crtc_req->mode_valid) {
@@ -2471,15 +2451,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, out_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_id); +if (!connector) {DRM_DEBUG_KMS ("Connector id %d unknown\n" , out_id); ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj);DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , connector->base.id,drm_get_connector_name (connector));
@@ -2511,7 +2489,6 @@ static int drm_mode_cursor_common(struct drm_device *dev,struct drm_mode_cursor2 *req, struct drm_file *file_priv) { - struct drm_mode_object *obj; struct drm_crtc *crtc;int ret =0 ;
@@ -2521,12 +2498,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))return -EINVAL ; - obj =drm_mode_object_find (dev, req->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , req->crtc_id);return -ENOENT ; } - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (req->flags &DRM_MODE_CURSOR_BO ) {
@@ -3522,7 +3498,6 @@ EXPORT_SYMBOL(drm_object_property_get_value);int drm_mode_getproperty_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_property *out_resp = data;struct drm_property *property;int enum_count =0 ;
@@ -3541,12 +3516,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->prop_id,DRM_MODE_OBJECT_PROPERTY ); -if (!obj) { + property =drm_property_find (dev, out_resp->prop_id); +if (!property) { ret = -ENOENT ; goto done; } - property =obj_to_property (obj);if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) ||drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {
@@ -3676,7 +3650,6 @@ static void drm_property_destroy_blob(struct drm_device *dev,int drm_mode_getblob_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_blob *out_resp = data;struct drm_property_blob *blob;int ret =0 ;
@@ -3686,12 +3659,11 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->blob_id,DRM_MODE_OBJECT_BLOB ); -if (!obj) { + blob =drm_property_blob_find (dev, out_resp->blob_id); +if (!blob) { ret = -ENOENT ; goto done; } - blob =obj_to_blob (obj);if (out_resp->length == blob->length) { blob_ptr = (void __user *)(unsigned long )out_resp->data;
@@ -3898,7 +3870,6 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, uint32_t prop_id, uint64_t value, void *blob_data) { struct drm_mode_object *arg_obj; -struct drm_mode_object *prop_obj;struct drm_property *property;int i;
@@ -3915,11 +3886,9 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev,if (i == arg_obj->properties->count)return -EINVAL ; - prop_obj =drm_mode_object_find (dev, prop_id, -DRM_MODE_OBJECT_PROPERTY ); -if (!prop_obj) + property =drm_property_find (dev, prop_id); +if (!property)return -ENOENT ; - property =obj_to_property (prop_obj);return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data);
@@ -4126,7 +4095,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;
@@ -4136,12 +4104,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);if (crtc->funcs->gamma_set ==NULL ) { ret = -ENOSYS ;
@@ -4200,7 +4167,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;
@@ -4210,12 +4176,11 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);/* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) {
@@ -4268,7 +4233,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_page_flip *page_flip = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;struct drm_pending_vblank_event *e =NULL ;
@@ -4282,10 +4246,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,if ((page_flip->flags &DRM_MODE_PAGE_FLIP_ASYNC ) && !dev->mode_config.async_page_flip)return -EINVAL ; - obj =drm_mode_object_find (dev, page_flip->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) + crtc =drm_crtc_find (dev, page_flip->crtc_id); +if (!crtc)return -ENOENT ; - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (crtc->primary->fb ==NULL ) {
include/drm/drm_crtc.h +33 -0
@@ -1112,6 +1112,15 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);extern const char *drm_get_format_name (uint32_t format);/* Helpers */ + +static inline struct drm_plane *drm_plane_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PLANE ); +return mo ?obj_to_plane (mo) :NULL ; +} +static inline struct drm_crtc *drm_crtc_find (struct drm_device *dev,uint32_t id) {
@@ -1128,6 +1137,30 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,return mo ?obj_to_encoder (mo) :NULL ; } +static inline struct drm_connector *drm_connector_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_CONNECTOR ); +return mo ?obj_to_connector (mo) :NULL ; +} + +static inline struct drm_property *drm_property_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PROPERTY ); +return mo ?obj_to_property (mo) :NULL ; +} + +static inline struct drm_property_blob * +drm_property_blob_find (struct drm_device *dev,uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_BLOB ); +return mo ?obj_to_blob (mo) :NULL ; +} +/* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane (plane, planelist) \ list_for_each_entry(plane, planelist, head) \
Signature · 1 line
1.9.0
Re: [PATCH 06/17] drm: helpers to find mode objects
Quoted 3 lines · Rob Clark
Add a few more useful helpers to find mode objects.
Signed-off-by Rob Clark <[email protected]>
There's a pile more in drivers for these. I like this, but imo we should also convert drivers while at it. Also, docbook is missing. And since it's a cleanup I think it's better to do this first, directly on top of drm-next. The patch itself looks good.
-Daniel
Quoted 403 lines
--- drivers/gpu/drm/drm_crtc.c | 97 ++++++++++++++-------------------------------- include/drm/drm_crtc.h | 33 ++++++++++++++++ 2 files changed, 63 insertions(+), 67 deletions(-)drivers/gpu/drm/drm_crtc.c +30
-67@@ -1736,7 +1736,6 @@ int drm_mode_getcrtc(struct drm_device *dev, {struct drm_mode_crtc *crtc_resp = data;struct drm_crtc *crtc; -struct drm_mode_object *obj;int ret =0 ;if (!drm_core_check_feature (dev,DRIVER_MODESET ))@@ -1744,13 +1743,11 @@ int drm_mode_getcrtc(struct drm_device *dev,drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_resp->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_resp->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); crtc_resp->x = crtc->x; crtc_resp->y = crtc->y;@@ -1804,7 +1801,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_connector *out_resp = data; -struct drm_mode_object *obj;struct drm_connector *connector;struct drm_display_mode *mode;int mode_count =0 ;@@ -1828,13 +1824,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,drm_modeset_lock (&dev->mode_config.mutex,NULL ); - obj =drm_mode_object_find (dev, out_resp->connector_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_resp->connector_id); +if (!connector) { ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj); props_count = connector->properties.count;@@ -1949,7 +1943,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_encoder *enc_resp = data; -struct drm_mode_object *obj;struct drm_encoder *encoder;int ret =0 ;@@ -1957,13 +1950,11 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, enc_resp->encoder_id, -DRM_MODE_OBJECT_ENCODER ); -if (!obj) { + encoder =drm_encoder_find (dev, enc_resp->encoder_id); +if (!encoder) { ret = -ENOENT ; goto out; } - encoder =obj_to_encoder (obj);if (encoder->crtc) enc_resp->crtc_id = encoder->crtc->base.id;@@ -2061,7 +2052,6 @@ int drm_mode_getplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_plane *plane_resp = data; -struct drm_mode_object *obj;struct drm_plane *plane;uint32_t __user *format_ptr;int ret =0 ;@@ -2070,13 +2060,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, plane_resp->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_resp->plane_id); +if (!plane) { ret = -ENOENT ; goto out; } - plane =obj_to_plane (obj);if (plane->crtc) plane_resp->crtc_id = plane->crtc->base.id;@@ -2129,7 +2117,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; -struct drm_mode_object *obj;struct drm_plane *plane;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;@@ -2144,14 +2131,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,* First, find the plane, crtc, and fb objects. If not available, * we don't bother to call the driver. */ - obj =drm_mode_object_find (dev, plane_req->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_req->plane_id); +if (!plane) {DRM_DEBUG_KMS ("Unknown plane ID %d\n" , plane_req->plane_id);return -ENOENT ; } - plane =obj_to_plane (obj);/* No fb means shut it down */ if (!plane_req->fb_id) {@@ -2168,15 +2153,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, plane_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, plane_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , plane_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); fb =drm_framebuffer_lookup (dev, plane_req->fb_id);if (!fb) {@@ -2363,7 +2346,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, {struct drm_mode_config *config = &dev->mode_config;struct drm_mode_crtc *crtc_req = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_connector **connector_set =NULL , *connector;struct drm_framebuffer *fb =NULL ;@@ -2381,14 +2363,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,return -ERANGE ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , crtc_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);DRM_DEBUG_KMS ("[CRTC:%d]\n" , crtc->base.id);if (crtc_req->mode_valid) {@@ -2471,15 +2451,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, out_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_id); +if (!connector) {DRM_DEBUG_KMS ("Connector id %d unknown\n" , out_id); ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj);DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , connector->base.id,drm_get_connector_name (connector));@@ -2511,7 +2489,6 @@ static int drm_mode_cursor_common(struct drm_device *dev,struct drm_mode_cursor2 *req, struct drm_file *file_priv) { - struct drm_mode_object *obj; struct drm_crtc *crtc;int ret =0 ;@@ -2521,12 +2498,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))return -EINVAL ; - obj =drm_mode_object_find (dev, req->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , req->crtc_id);return -ENOENT ; } - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (req->flags &DRM_MODE_CURSOR_BO ) {@@ -3522,7 +3498,6 @@ EXPORT_SYMBOL(drm_object_property_get_value);int drm_mode_getproperty_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_property *out_resp = data;struct drm_property *property;int enum_count =0 ;@@ -3541,12 +3516,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->prop_id,DRM_MODE_OBJECT_PROPERTY ); -if (!obj) { + property =drm_property_find (dev, out_resp->prop_id); +if (!property) { ret = -ENOENT ; goto done; } - property =obj_to_property (obj);if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) ||drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {@@ -3676,7 +3650,6 @@ static void drm_property_destroy_blob(struct drm_device *dev,int drm_mode_getblob_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_blob *out_resp = data;struct drm_property_blob *blob;int ret =0 ;@@ -3686,12 +3659,11 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->blob_id,DRM_MODE_OBJECT_BLOB ); -if (!obj) { + blob =drm_property_blob_find (dev, out_resp->blob_id); +if (!blob) { ret = -ENOENT ; goto done; } - blob =obj_to_blob (obj);if (out_resp->length == blob->length) { blob_ptr = (void __user *)(unsigned long )out_resp->data;@@ -3898,7 +3870,6 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, uint32_t prop_id, uint64_t value, void *blob_data) { struct drm_mode_object *arg_obj; -struct drm_mode_object *prop_obj;struct drm_property *property;int i;@@ -3915,11 +3886,9 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev,if (i == arg_obj->properties->count)return -EINVAL ; - prop_obj =drm_mode_object_find (dev, prop_id, -DRM_MODE_OBJECT_PROPERTY ); -if (!prop_obj) + property =drm_property_find (dev, prop_id); +if (!property)return -ENOENT ; - property =obj_to_property (prop_obj);return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data);@@ -4126,7 +4095,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;@@ -4136,12 +4104,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);if (crtc->funcs->gamma_set ==NULL ) { ret = -ENOSYS ;@@ -4200,7 +4167,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;@@ -4210,12 +4176,11 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);/* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) {@@ -4268,7 +4233,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_page_flip *page_flip = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;struct drm_pending_vblank_event *e =NULL ;@@ -4282,10 +4246,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,if ((page_flip->flags &DRM_MODE_PAGE_FLIP_ASYNC ) && !dev->mode_config.async_page_flip)return -EINVAL ; - obj =drm_mode_object_find (dev, page_flip->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) + crtc =drm_crtc_find (dev, page_flip->crtc_id); +if (!crtc)return -ENOENT ; - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (crtc->primary->fb ==NULL ) {include/drm/drm_crtc.h +33
-0@@ -1112,6 +1112,15 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);extern const char *drm_get_format_name (uint32_t format);/* Helpers */ + +static inline struct drm_plane *drm_plane_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PLANE ); +return mo ?obj_to_plane (mo) :NULL ; +} +static inline struct drm_crtc *drm_crtc_find (struct drm_device *dev,uint32_t id) {@@ -1128,6 +1137,30 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,return mo ?obj_to_encoder (mo) :NULL ; } +static inline struct drm_connector *drm_connector_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_CONNECTOR ); +return mo ?obj_to_connector (mo) :NULL ; +} + +static inline struct drm_property *drm_property_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PROPERTY ); +return mo ?obj_to_property (mo) :NULL ; +} + +static inline struct drm_property_blob * +drm_property_blob_find (struct drm_device *dev,uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_BLOB ); +return mo ?obj_to_blob (mo) :NULL ; +} +/* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane (plane, planelist) \ list_for_each_entry(plane, planelist, head) \Signature · 1 line
1.9.0
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 06/17] drm: helpers to find mode objects
Quoted 9 lines · Daniel Vetter
Quoted 3 lines · Rob Clark
Add a few more useful helpers to find mode objects.
Signed-off-by Rob Clark <[email protected]>There's a pile more in drivers for these. I like this, but imo we should also convert drivers while at it. Also, docbook is missing. And since it's a cleanup I think it's better to do this first, directly on top of drm-next. The patch itself looks good.
Aside: This is a pretty perfect case for coccinelle since it'll match object_find users no matter how crazily they're split up. And you can remove the unused local variable with it too (but that part is a bit more fuzz).
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 06/17] drm: helpers to find mode objects
In reply to Daniel VetterQuoted 9 lines · Daniel Vetter
Quoted 3 lines · Rob Clark
Add a few more useful helpers to find mode objects.
Signed-off-by Rob Clark <[email protected]>There's a pile more in drivers for these. I like this, but imo we should also convert drivers while at it. Also, docbook is missing. And since it's a cleanup I think it's better to do this first, directly on top of drm-next. The patch itself looks good.
Yeah, the intent was to go back and add missing docbook as follow-up patches, to try to get this into a shape where it could be merged earlier.
I can have a go at coccinelle too for follow-up patches.
BR,
-R
Quoted 410 lines
-Daniel
Quoted 401 lines
--- drivers/gpu/drm/drm_crtc.c | 97 ++++++++++++++-------------------------------- include/drm/drm_crtc.h | 33 ++++++++++++++++ 2 files changed, 63 insertions(+), 67 deletions(-)drivers/gpu/drm/drm_crtc.c +30
-67@@ -1736,7 +1736,6 @@ int drm_mode_getcrtc(struct drm_device *dev, {struct drm_mode_crtc *crtc_resp = data;struct drm_crtc *crtc; -struct drm_mode_object *obj;int ret =0 ;if (!drm_core_check_feature (dev,DRIVER_MODESET ))@@ -1744,13 +1743,11 @@ int drm_mode_getcrtc(struct drm_device *dev,drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_resp->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_resp->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); crtc_resp->x = crtc->x; crtc_resp->y = crtc->y;@@ -1804,7 +1801,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_connector *out_resp = data; -struct drm_mode_object *obj;struct drm_connector *connector;struct drm_display_mode *mode;int mode_count =0 ;@@ -1828,13 +1824,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,drm_modeset_lock (&dev->mode_config.mutex,NULL ); - obj =drm_mode_object_find (dev, out_resp->connector_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_resp->connector_id); +if (!connector) { ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj); props_count = connector->properties.count;@@ -1949,7 +1943,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_encoder *enc_resp = data; -struct drm_mode_object *obj;struct drm_encoder *encoder;int ret =0 ;@@ -1957,13 +1950,11 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, enc_resp->encoder_id, -DRM_MODE_OBJECT_ENCODER ); -if (!obj) { + encoder =drm_encoder_find (dev, enc_resp->encoder_id); +if (!encoder) { ret = -ENOENT ; goto out; } - encoder =obj_to_encoder (obj);if (encoder->crtc) enc_resp->crtc_id = encoder->crtc->base.id;@@ -2061,7 +2052,6 @@ int drm_mode_getplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_get_plane *plane_resp = data; -struct drm_mode_object *obj;struct drm_plane *plane;uint32_t __user *format_ptr;int ret =0 ;@@ -2070,13 +2060,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, plane_resp->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_resp->plane_id); +if (!plane) { ret = -ENOENT ; goto out; } - plane =obj_to_plane (obj);if (plane->crtc) plane_resp->crtc_id = plane->crtc->base.id;@@ -2129,7 +2117,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; -struct drm_mode_object *obj;struct drm_plane *plane;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;@@ -2144,14 +2131,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,* First, find the plane, crtc, and fb objects. If not available, * we don't bother to call the driver. */ - obj =drm_mode_object_find (dev, plane_req->plane_id, -DRM_MODE_OBJECT_PLANE ); -if (!obj) { + plane =drm_plane_find (dev, plane_req->plane_id); +if (!plane) {DRM_DEBUG_KMS ("Unknown plane ID %d\n" , plane_req->plane_id);return -ENOENT ; } - plane =obj_to_plane (obj);/* No fb means shut it down */ if (!plane_req->fb_id) {@@ -2168,15 +2153,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, plane_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, plane_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , plane_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj); fb =drm_framebuffer_lookup (dev, plane_req->fb_id);if (!fb) {@@ -2363,7 +2346,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, {struct drm_mode_config *config = &dev->mode_config;struct drm_mode_crtc *crtc_req = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_connector **connector_set =NULL , *connector;struct drm_framebuffer *fb =NULL ;@@ -2381,14 +2363,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,return -ERANGE ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_req->crtc_id, -DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , crtc_req->crtc_id); ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);DRM_DEBUG_KMS ("[CRTC:%d]\n" , crtc->base.id);if (crtc_req->mode_valid) {@@ -2471,15 +2451,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - obj =drm_mode_object_find (dev, out_id, -DRM_MODE_OBJECT_CONNECTOR ); -if (!obj) { + connector =drm_connector_find (dev, out_id); +if (!connector) {DRM_DEBUG_KMS ("Connector id %d unknown\n" , out_id); ret = -ENOENT ; goto out; } - connector =obj_to_connector (obj);DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , connector->base.id,drm_get_connector_name (connector));@@ -2511,7 +2489,6 @@ static int drm_mode_cursor_common(struct drm_device *dev,struct drm_mode_cursor2 *req, struct drm_file *file_priv) { - struct drm_mode_object *obj; struct drm_crtc *crtc;int ret =0 ;@@ -2521,12 +2498,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))return -EINVAL ; - obj =drm_mode_object_find (dev, req->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, req->crtc_id); +if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , req->crtc_id);return -ENOENT ; } - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (req->flags &DRM_MODE_CURSOR_BO ) {@@ -3522,7 +3498,6 @@ EXPORT_SYMBOL(drm_object_property_get_value);int drm_mode_getproperty_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_property *out_resp = data;struct drm_property *property;int enum_count =0 ;@@ -3541,12 +3516,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->prop_id,DRM_MODE_OBJECT_PROPERTY ); -if (!obj) { + property =drm_property_find (dev, out_resp->prop_id); +if (!property) { ret = -ENOENT ; goto done; } - property =obj_to_property (obj);if (drm_property_type_is (property,DRM_MODE_PROP_ENUM ) ||drm_property_type_is (property,DRM_MODE_PROP_BITMASK )) {@@ -3676,7 +3650,6 @@ static void drm_property_destroy_blob(struct drm_device *dev,int drm_mode_getblob_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv) { -struct drm_mode_object *obj;struct drm_mode_get_blob *out_resp = data;struct drm_property_blob *blob;int ret =0 ;@@ -3686,12 +3659,11 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, out_resp->blob_id,DRM_MODE_OBJECT_BLOB ); -if (!obj) { + blob =drm_property_blob_find (dev, out_resp->blob_id); +if (!blob) { ret = -ENOENT ; goto done; } - blob =obj_to_blob (obj);if (out_resp->length == blob->length) { blob_ptr = (void __user *)(unsigned long )out_resp->data;@@ -3898,7 +3870,6 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, uint32_t prop_id, uint64_t value, void *blob_data) { struct drm_mode_object *arg_obj; -struct drm_mode_object *prop_obj;struct drm_property *property;int i;@@ -3915,11 +3886,9 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev,if (i == arg_obj->properties->count)return -EINVAL ; - prop_obj =drm_mode_object_find (dev, prop_id, -DRM_MODE_OBJECT_PROPERTY ); -if (!prop_obj) + property =drm_property_find (dev, prop_id); +if (!property)return -ENOENT ; - property =obj_to_property (prop_obj);return drm_mode_set_obj_prop (arg_obj, state, property, value, blob_data);@@ -4126,7 +4095,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;@@ -4136,12 +4104,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);if (crtc->funcs->gamma_set ==NULL ) { ret = -ENOSYS ;@@ -4200,7 +4167,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_lut *crtc_lut = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;void *r_base, *g_base, *b_base;int size;@@ -4210,12 +4176,11 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,return -EINVAL ;drm_modeset_lock_all (dev); - obj =drm_mode_object_find (dev, crtc_lut->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) { + crtc =drm_crtc_find (dev, crtc_lut->crtc_id); +if (!crtc) { ret = -ENOENT ; goto out; } - crtc =obj_to_crtc (obj);/* memcpy into gamma store */ if (crtc_lut->gamma_size != crtc->gamma_size) {@@ -4268,7 +4233,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_page_flip *page_flip = data; -struct drm_mode_object *obj;struct drm_crtc *crtc;struct drm_framebuffer *fb =NULL , *old_fb =NULL ;struct drm_pending_vblank_event *e =NULL ;@@ -4282,10 +4246,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,if ((page_flip->flags &DRM_MODE_PAGE_FLIP_ASYNC ) && !dev->mode_config.async_page_flip)return -EINVAL ; - obj =drm_mode_object_find (dev, page_flip->crtc_id,DRM_MODE_OBJECT_CRTC ); -if (!obj) + crtc =drm_crtc_find (dev, page_flip->crtc_id); +if (!crtc)return -ENOENT ; - crtc =obj_to_crtc (obj);drm_modeset_lock (&crtc->mutex,NULL );if (crtc->primary->fb ==NULL ) {include/drm/drm_crtc.h +33
-1@@ -1112,6 +1112,15 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);extern const char *drm_get_format_name (uint32_t format);/* Helpers */ + +static inline struct drm_plane *drm_plane_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PLANE ); +return mo ?obj_to_plane (mo) :NULL ; +} +static inline struct drm_crtc *drm_crtc_find (struct drm_device *dev,uint32_t id) {@@ -1128,6 +1137,30 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,return mo ?obj_to_encoder (mo) :NULL ; } +static inline struct drm_connector *drm_connector_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_CONNECTOR ); +return mo ?obj_to_connector (mo) :NULL ; +} + +static inline struct drm_property *drm_property_find (struct drm_device *dev, +uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_PROPERTY ); +return mo ?obj_to_property (mo) :NULL ; +} + +static inline struct drm_property_blob * +drm_property_blob_find (struct drm_device *dev,uint32_t id) +{ +struct drm_mode_object *mo; + mo =drm_mode_object_find (dev, id,DRM_MODE_OBJECT_BLOB ); +return mo ?obj_to_blob (mo) :NULL ; +} +/* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane (plane, planelist) \ list_for_each_entry(plane, planelist, head) \ --Quoted 2 lines
1.9.0
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 7/17 drm: split propvals out and blob property support
In reply to Rob ClarkSplit property values out into a different struct, so we can later move property values into state structs. This will allow the property values to stay in sync w/ the state updates which are either discarded or atomically committed.
And since we are touching all the same code, add support for mutable blob properties, which will also be needed for atomic modeset.
--- drivers/gpu/drm/drm_crtc.c | 79 +++++++++++++++++++++-------- drivers/gpu/drm/drm_fb_helper.c | 3 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 3 +- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 3 +- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 6 ++- drivers/gpu/drm/gma500/mdfld_dsi_output.c | 8 +-- drivers/gpu/drm/gma500/psb_intel_lvds.c | 6 ++- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 19 +++++-- drivers/gpu/drm/i2c/ch7006_drv.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 3 +- drivers/gpu/drm/i915/intel_dp.c | 3 +- drivers/gpu/drm/i915/intel_hdmi.c | 3 +- drivers/gpu/drm/i915/intel_sdvo.c | 19 +++++-- drivers/gpu/drm/i915/intel_tv.c | 6 ++- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 3 +- drivers/gpu/drm/nouveau/nouveau_connector.c | 4 +- drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++- drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 3 +- drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 3 +- drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 4 +- include/drm/drm_crtc.h | 11 +++- 21 files changed, 142 insertions(+), 57 deletions(-)
drivers/gpu/drm/drm_crtc.c +58 -21
@@ -123,6 +123,14 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) }EXPORT_SYMBOL (drm_warn_on_modeset_not_all_locked); +static int drm_mode_set_obj_prop (struct drm_mode_object *obj, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +static struct drm_property_blob *drm_property_create_blob (struct drm_device *dev, +int length,void *data); +static void drm_property_destroy_blob (struct drm_device *dev, +struct drm_property_blob *blob); +/* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN (fnname, list) \ const char *fnname(int val) \
@@ -755,6 +763,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, goto out; crtc->base.properties = &crtc->properties; + crtc->base.propvals = &crtc->propvals;list_add_tail (&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++;
@@ -859,6 +868,7 @@ int drm_connector_init(struct drm_device *dev, goto out; connector->base.properties = &connector->properties; + connector->base.propvals = &connector->propvals; connector->dev = dev; connector->funcs = funcs; connector->connector_type = connector_type;
@@ -1077,6 +1087,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, goto out; plane->base.properties = &plane->properties; + plane->base.propvals = &plane->propvals; plane->dev = dev; plane->funcs = funcs; plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
@@ -1894,7 +1905,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, goto out; } -if (put_user (connector->properties.values[i], +if (put_user (connector->propvals.values[i], prop_values + copied)) { ret = -EFAULT ; goto out;
@@ -3418,7 +3429,7 @@ void drm_object_attach_property(struct drm_mode_object *obj, } obj->properties->ids[count] = property->base.id; - obj->properties->values[count] = init_val; + obj->propvals->values[count] = init_val; obj->properties->count++; }EXPORT_SYMBOL (drm_object_attach_property);
@@ -3437,13 +3448,27 @@ EXPORT_SYMBOL(drm_object_attach_property);* Zero on success, error code on failure. */ int drm_object_property_set_value (struct drm_mode_object *obj, -struct drm_property *property,uint64_t val) +struct drm_object_property_values *propvals, +struct drm_property *property,uint64_t val, +void *blob_data) {int i;for (i =0 ; i < obj->properties->count; i++) {if (obj->properties->ids[i] == property->base.id) { - obj->properties->values[i] = val; +struct drm_device *dev = property->dev; +if (property->flags &DRM_MODE_PROP_BLOB ) { +struct drm_property_blob *blob, *old_blob =NULL ; + old_blob =drm_property_blob_find (dev, propvals->values[i]); + blob =drm_property_create_blob (dev, val, blob_data); +if (!blob) +return -ENOMEM ; + propvals->values[i] = blob->base.id; +if (old_blob) +drm_property_destroy_blob (dev, old_blob); + }else { + propvals->values[i] = val; + }return 0 ; } }
@@ -3473,7 +3498,7 @@ int drm_object_property_get_value(struct drm_mode_object *obj,for (i =0 ; i < obj->properties->count; i++) {if (obj->properties->ids[i] == property->base.id) { - *val = obj->properties->values[i]; + *val = obj->propvals->values[i];return 0 ; } }
@@ -3694,27 +3719,35 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, struct edid *edid) {struct drm_device *dev = connector->dev; -int ret, size; +struct drm_mode_object *obj = &connector->base; +struct drm_property *edid_prop = dev->mode_config.edid_property; +int i, ret, size; -if (connector->edid_blob_ptr) -drm_property_destroy_blob (dev, connector->edid_blob_ptr); +/* property_blob will be recreated by drm_object_property_set_value(): */ + connector->edid_blob_ptr =NULL ;/* Delete edid, when there is none. */ if (!edid) { - connector->edid_blob_ptr =NULL ; - ret =drm_object_property_set_value (&connector->base, dev->mode_config.edid_property,0 ); + ret =drm_object_property_set_value (obj, + &connector->propvals, edid_prop,0 ,NULL );return ret; } size =EDID_LENGTH * (1 + edid->extensions); - connector->edid_blob_ptr =drm_property_create_blob (connector->dev, - size, edid); -if (!connector->edid_blob_ptr) -return -EINVAL ; - ret =drm_object_property_set_value (&connector->base, - dev->mode_config.edid_property, - connector->edid_blob_ptr->base.id); + ret =drm_object_property_set_value (obj, + &connector->propvals, edid_prop, size, edid); +if (ret) +return ret; + +/* find the blob object created for us by drm_object_property_set_value(): */ +for (i =0 ; i < obj->properties->count; i++) { +if (obj->properties->ids[i] == edid_prop->base.id) { + connector->edid_blob_ptr =drm_property_blob_find (dev, + connector->propvals.values[i]); +break ; + } + }return ret; }
@@ -3806,7 +3839,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,/* store the property value if successful */ if (!ret) -drm_object_property_set_value (&connector->base, property, value); +drm_object_property_set_value (&connector->base, + &connector->propvals, property, value, blob_data); +return ret; }
@@ -3820,7 +3855,8 @@ static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc, ret = crtc->funcs->set_property (crtc, state, property, value, blob_data);if (!ret) -drm_object_property_set_value (&crtc->base, property, value); +drm_object_property_set_value (&crtc->base, &crtc->propvals, + property, value,NULL );return ret; }
@@ -3835,7 +3871,8 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane, ret = plane->funcs->set_property (plane, state, property, value, blob_data);if (!ret) -drm_object_property_set_value (&plane->base, property, value); +drm_object_property_set_value (&plane->base, &plane->propvals, + property, value,NULL );return ret; }
@@ -3951,7 +3988,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, ret = -EFAULT ; goto out; } -if (put_user (obj->properties->values[i], +if (put_user (obj->propvals->values[i], prop_values_ptr + copied)) { ret = -EFAULT ; goto out;
drivers/gpu/drm/drm_fb_helper.c +2 -1
@@ -451,7 +451,8 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) connector = fb_helper->connector_info[j]->connector; connector->funcs->dpms (connector, dpms_mode);drm_object_property_set_value (&connector->base, - dev->mode_config.dpms_property, dpms_mode); + &connector->propvals, + dev->mode_config.dpms_property, dpms_mode,NULL ); } }drm_modeset_unlock_all (dev);
drivers/gpu/drm/gma500/cdv_intel_dp.c +2 -1
@@ -1655,7 +1655,8 @@ cdv_intel_dp_set_property(struct drm_connector *connector,struct cdv_intel_dp *intel_dp = encoder->dev_priv;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
drivers/gpu/drm/gma500/cdv_intel_hdmi.c +2 -1
@@ -184,7 +184,8 @@ static int cdv_hdmi_set_property(struct drm_connector *connector,return 0 ;if (drm_object_property_set_value (&connector->base, - property, value)) + &connector->propvals, + property, value, blob_data))return -1 ; centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
drivers/gpu/drm/gma500/cdv_intel_lvds.c +4 -2
@@ -486,8 +486,9 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,return 0 ;if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data))return -1 ; if (crtc->saved_mode.hdisplay != 0 &&
@@ -501,8 +502,9 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector, } }else if (!strcmp (property->name,"backlight" ) && encoder) {if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data))return -1 ;else gma_backlight_set (encoder->dev, value);
drivers/gpu/drm/gma500/mdfld_dsi_output.c +5 -3
@@ -276,7 +276,8 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, goto set_prop_done;if (drm_object_property_set_value (&connector->base, - property, value)) + &connector->propvals, + property, value, blob_data)) goto set_prop_error; centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
@@ -300,8 +301,9 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, } } }else if (!strcmp (property->name,"backlight" ) && encoder) { -if (drm_object_property_set_value (&connector->base, property, - value)) +if (drm_object_property_set_value (&connector->base, + &connector->propvals, + property, value, blob_data)) goto set_prop_error;else gma_backlight_set (encoder->dev, value);
drivers/gpu/drm/gma500/psb_intel_lvds.c +4 -2
@@ -606,8 +606,9 @@ int psb_intel_lvds_set_property(struct drm_connector *connector, goto set_prop_done;if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data)) goto set_prop_error; if (crtc->saved_mode.hdisplay != 0 &&
@@ -621,8 +622,9 @@ int psb_intel_lvds_set_property(struct drm_connector *connector, } }else if (!strcmp (property->name,"backlight" )) {if (drm_object_property_set_value (&connector->base, + &connector->propvals, property, - value)) + value, blob_data)) goto set_prop_error;else gma_backlight_set (encoder->dev, value);
drivers/gpu/drm/gma500/psb_intel_sdvo.c +14 -5
@@ -1717,7 +1717,8 @@ psb_intel_sdvo_set_property(struct drm_connector *connector,uint8_t cmd;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
@@ -1773,7 +1774,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, temp_value = val;if (psb_intel_sdvo_connector->left == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->right, val); + &connector->propvals, + psb_intel_sdvo_connector->right, + val, blob_data);if (psb_intel_sdvo_connector->left_margin == temp_value)return 0 ;
@@ -1785,7 +1788,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (psb_intel_sdvo_connector->right == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->left, val); + &connector->propvals, + psb_intel_sdvo_connector->left, + val, blob_data);if (psb_intel_sdvo_connector->right_margin == temp_value)return 0 ;
@@ -1797,7 +1802,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (psb_intel_sdvo_connector->top == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->bottom, val); + &connector->propvals, + psb_intel_sdvo_connector->bottom, + val, blob_data);if (psb_intel_sdvo_connector->top_margin == temp_value)return 0 ;
@@ -1809,7 +1816,9 @@ psb_intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (psb_intel_sdvo_connector->bottom == property) {drm_object_property_set_value (&connector->base, - psb_intel_sdvo_connector->top, val); + &connector->propvals, + psb_intel_sdvo_connector->top, + val, blob_data);if (psb_intel_sdvo_connector->bottom_margin == temp_value)return 0 ;
drivers/gpu/drm/i2c/ch7006_drv.c +2 -2
@@ -214,9 +214,9 @@ static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encodelse priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown; -drm_object_property_set_value (&connector->base, +drm_object_property_set_value (&connector->base, &connector->propvals, encoder->dev->mode_config.tv_subconnector_property, - priv->subconnector); + priv->subconnector,NULL );return priv->subconnector ? connector_status_connected : connector_status_disconnected;
drivers/gpu/drm/i915/intel_display.c +2 -1
@@ -9494,8 +9494,9 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) connector->dpms =DRM_MODE_DPMS_ON ;drm_object_property_set_value (&connector->base, + &connector->propvals, dpms_property, -DRM_MODE_DPMS_ON ); +DRM_MODE_DPMS_ON ,NULL ); intel_encoder =to_intel_encoder (connector->encoder); intel_encoder->connectors_active = true;
drivers/gpu/drm/i915/intel_dp.c +2 -1
@@ -3281,7 +3281,8 @@ intel_dp_set_property(struct drm_connector *connector,struct intel_dp *intel_dp =enc_to_intel_dp (&intel_encoder->base);int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
drivers/gpu/drm/i915/intel_hdmi.c +2 -1
@@ -1055,7 +1055,8 @@ intel_hdmi_set_property(struct drm_connector *connector,struct drm_i915_private *dev_priv = connector->dev->dev_private;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
drivers/gpu/drm/i915/intel_sdvo.c +14 -5
@@ -2064,7 +2064,8 @@ intel_sdvo_set_property(struct drm_connector *connector,uint8_t cmd;int ret; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret)return ret;
@@ -2141,7 +2142,9 @@ intel_sdvo_set_property(struct drm_connector *connector, temp_value = val;if (intel_sdvo_connector->left == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->right, val); + &connector->propvals, + intel_sdvo_connector->right, + val, blob_data);if (intel_sdvo_connector->left_margin == temp_value)return 0 ;
@@ -2153,7 +2156,9 @@ intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (intel_sdvo_connector->right == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->left, val); + &connector->propvals, + intel_sdvo_connector->left, + val, blob_data);if (intel_sdvo_connector->right_margin == temp_value)return 0 ;
@@ -2165,7 +2170,9 @@ intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (intel_sdvo_connector->top == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->bottom, val); + &connector->propvals, + intel_sdvo_connector->bottom, + val, blob_data);if (intel_sdvo_connector->top_margin == temp_value)return 0 ;
@@ -2177,7 +2184,9 @@ intel_sdvo_set_property(struct drm_connector *connector, goto set_value; }else if (intel_sdvo_connector->bottom == property) {drm_object_property_set_value (&connector->base, - intel_sdvo_connector->top, val); + &connector->propvals, + intel_sdvo_connector->top, + val, blob_data);if (intel_sdvo_connector->bottom_margin == temp_value)return 0 ;
drivers/gpu/drm/i915/intel_tv.c +4 -2
@@ -1297,7 +1297,8 @@ static void intel_tv_find_better_format(struct drm_connector *connector) intel_tv->tv_format = tv_mode->name;drm_object_property_set_value (&connector->base, - connector->dev->mode_config.tv_mode_property, i); + &connector->propvals, + connector->dev->mode_config.tv_mode_property, i,NULL ); }/**
@@ -1455,7 +1456,8 @@ intel_tv_set_property(struct drm_connector *connector,int ret =0 ;bool changed = false; - ret =drm_object_property_set_value (&connector->base, property, val); + ret =drm_object_property_set_value (&connector->base, + &connector->propvals, property, val, blob_data);if (ret <0 ) goto out;
drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +2 -1
@@ -196,8 +196,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) }drm_object_property_set_value (&connector->base, + &connector->propvals, conf->tv_subconnector_property, - tv_enc->subconnector); + tv_enc->subconnector,NULL );if (!reliable) {return connector_status_unknown;
drivers/gpu/drm/nouveau/nouveau_connector.c +3 -1
@@ -227,10 +227,12 @@ nouveau_connector_set_encoder(struct drm_connector *connector,if (nv_connector->type ==DCB_CONNECTOR_DVI_I ) {drm_object_property_set_value (&connector->base, + &connector->propvals, dev->mode_config.dvi_i_subconnector_property, nv_encoder->dcb->type ==DCB_OUTPUT_TMDS ?DRM_MODE_SUBCONNECTOR_DVID : -DRM_MODE_SUBCONNECTOR_DVIA ); +DRM_MODE_SUBCONNECTOR_DVIA , +NULL ); } }
drivers/gpu/drm/omapdrm/omap_drv.c +4 -2
@@ -579,12 +579,14 @@ static void dev_lastclose(struct drm_device *dev)*/ for (i =0 ; i < priv->num_crtcs; i++) {drm_object_property_set_value (&priv->crtcs[i]->base, - priv->rotation_prop,0 ); + &priv->crtcs[i]->propvals, + priv->rotation_prop,0 ,NULL ); }for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - priv->rotation_prop,0 ); + &priv->planes[i]->propvals, + priv->rotation_prop,0 ,NULL ); } }
drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c +2 -1
@@ -111,7 +111,8 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF );drm_object_property_set_value (&connector->base, - rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ); + &connector->propvals, + rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ,NULL ); ret =drm_mode_connector_attach_encoder (connector, &renc->encoder);if (ret <0 )
drivers/gpu/drm/rcar-du/rcar_du_vgacon.c +2 -1
@@ -76,7 +76,8 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF );drm_object_property_set_value (&connector->base, - rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ); + &connector->propvals, + rcdu->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ,NULL ); ret =drm_mode_connector_attach_encoder (connector, &renc->encoder);if (ret <0 )
drivers/gpu/drm/shmobile/shmob_drm_crtc.c +2 -2
@@ -741,8 +741,8 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev, connector->encoder = encoder;drm_helper_connector_dpms (connector,DRM_MODE_DPMS_OFF ); -drm_object_property_set_value (&connector->base, - sdev->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ); +drm_object_property_set_value (&connector->base, &connector->propvals, + sdev->ddev->mode_config.dpms_property,DRM_MODE_DPMS_OFF ,NULL );return 0 ;
include/drm/drm_crtc.h +10 -1
@@ -41,6 +41,7 @@ struct drm_framebuffer;struct drm_object_properties ;struct drm_file ;struct drm_clip_rect ; +struct drm_object_property_values ;#define DRM_MODE_OBJECT_CRTC 0xcccccccc#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
@@ -56,12 +57,16 @@ struct drm_mode_object {uint32_t id;uint32_t type;struct drm_object_properties *properties; +struct drm_object_property_values *propvals; };#define DRM_OBJECT_MAX_PROPERTY 24struct drm_object_properties {int count;uint32_t ids[DRM_OBJECT_MAX_PROPERTY ]; +}; + +struct drm_object_property_values {uint64_t values[DRM_OBJECT_MAX_PROPERTY ]; };
@@ -361,6 +366,7 @@ struct drm_crtc {void *helper_private;struct drm_object_properties properties; +struct drm_object_property_values propvals; };
@@ -520,6 +526,7 @@ struct drm_connector {struct drm_property_blob *edid_blob_ptr;struct drm_object_properties properties; +struct drm_object_property_values propvals;uint8_t polled;/* DRM_CONNECTOR_POLL_* */
@@ -603,6 +610,7 @@ struct drm_plane {const struct drm_plane_funcs *funcs;struct drm_object_properties properties; +struct drm_object_property_values propvals;enum drm_plane_type type; };
@@ -969,8 +977,9 @@ static inline bool drm_property_type_valid(struct drm_property *property) }extern int drm_object_property_set_value (struct drm_mode_object *obj, +struct drm_object_property_values *propvals,struct drm_property *property, -uint64_t val); +uint64_t val,void *blob_data);extern int drm_object_property_get_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t *value);
Signature · 1 line
1.9.0
PATCH 8/17 drm: Allow drm_mode_object_find() to look up an object of any type
In reply to Rob ClarkFrom: Ville Syrjälä <[email protected]>
To avoid having to pass object types from userspace for atomic mode setting ioctl, allow drm_mode_object_find() to look up an object of any type. This will only work as long as the all object types share the ID space.
--- drivers/gpu/drm/drm_crtc.c | 3 ++- include/drm/drm_crtc.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_crtc.c +2 -1
@@ -463,7 +463,8 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,mutex_lock (&dev->mode_config.idr_mutex); obj =idr_find (&dev->mode_config.crtc_idr, id); -if (!obj || (obj->type != type) || (obj->id != id)) +if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || + (obj->id != id)) obj =NULL ;mutex_unlock (&dev->mode_config.idr_mutex);
include/drm/drm_crtc.h +1 -0
@@ -52,6 +52,7 @@ struct drm_object_property_values;#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee#define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd +#define DRM_MODE_OBJECT_ANY 0struct drm_mode_object {uint32_t id;
Signature · 6 lines
1.9.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 9/17 drm: Refactor object property check code
In reply to Rob ClarkFrom: Ville Syrjälä <[email protected]>
Refactor the code to check whether an object has a specific property to a new function.
v1: original
v2: rebase on atomic -- Rob Clark
v3: EINVAL->ENOENT
--- drivers/gpu/drm/drm_crtc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
drivers/gpu/drm/drm_crtc.c +14 -11
@@ -3901,6 +3901,19 @@ static int drm_mode_set_obj_prop(struct drm_mode_object *obj,return -EINVAL ; } +static bool object_has_prop (const struct drm_mode_object *obj,u32 prop_id) +{ +int i; + +if (!obj->properties) +return false; + +for (i =0 ; i < obj->properties->count; i++) +if (obj->properties->ids[i] == prop_id) +return true; +return false; +} +/* call with mode_config mutex held */ static int drm_mode_set_obj_prop_id(struct drm_device *dev, struct drm_atomic_state *state,
@@ -3909,20 +3922,10 @@ static int drm_mode_set_obj_prop_id(struct drm_device *dev, {struct drm_mode_object *arg_obj;struct drm_property *property; -int i; arg_obj =drm_mode_object_find (dev, obj_id, obj_type); -if (!arg_obj) +if (!(arg_obj &&object_has_prop (arg_obj, prop_id)))return -ENOENT ; -if (!arg_obj->properties) -return -EINVAL ; - -for (i =0 ; i < arg_obj->properties->count; i++) -if (arg_obj->properties->ids[i] == prop_id) -break ; - -if (i == arg_obj->properties->count) -return -EINVAL ; property =drm_property_find (dev, prop_id);if (!property)
Signature · 6 lines
1.9.0 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 10/17 drm: allow FB's in drm_mode_object_find
In reply to Rob ClarkWe do actually want to permit FB's in atomic case, since FB will be looked up like any other object property value in a few code paths (like property value validation).
So split out into an internal function without the WARN_ON() which we can use in those special cases.
--- drivers/gpu/drm/drm_crtc.c | 33 ++++++++++++++++++++++----------- include/drm/drm_crtc.h | 6 ------ 2 files changed, 22 insertions(+), 17 deletions(-)
drivers/gpu/drm/drm_crtc.c +22 -11
@@ -443,6 +443,21 @@ void drm_mode_object_put(struct drm_device *dev,mutex_unlock (&dev->mode_config.idr_mutex); } +static struct drm_mode_object *_object_find (struct drm_device *dev, +uint32_t id,uint32_t type) +{ +struct drm_mode_object *obj =NULL ; + +mutex_lock (&dev->mode_config.idr_mutex); + obj =idr_find (&dev->mode_config.crtc_idr, id); +if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || + (obj->id != id)) + obj =NULL ; +mutex_unlock (&dev->mode_config.idr_mutex); + +return obj; +} +/** * drm_mode_object_find - look up a drm object with static lifetime * @dev: drm device
@@ -455,23 +470,19 @@ void drm_mode_object_put(struct drm_device *dev,struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type) { -struct drm_mode_object *obj =NULL ; -/* Framebuffers are reference counted and need their own lookup * function.*/ WARN_ON (type ==DRM_MODE_OBJECT_FB ); - -mutex_lock (&dev->mode_config.idr_mutex); - obj =idr_find (&dev->mode_config.crtc_idr, id); -if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || - (obj->id != id)) - obj =NULL ; -mutex_unlock (&dev->mode_config.idr_mutex); - -return obj; +return _object_find (dev, id, type); }EXPORT_SYMBOL (drm_mode_object_find); +static struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return _object_find (property->dev, value, property->values[0 ]); +} +/** * drm_framebuffer_init - initialize a framebuffer * @dev: DRM device
include/drm/drm_crtc.h +0 -6
@@ -1033,12 +1033,6 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); -static inline struct drm_mode_object * -drm_property_get_obj (struct drm_property *property,uint64_t value) -{ -return drm_mode_object_find (property->dev, value, property->values[0 ]); -} -/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);
Signature · 1 line
1.9.0
Re: [PATCH 10/17] drm: allow FB's in drm_mode_object_find
Quoted 8 lines · Rob Clark
We do actually want to permit FB's in atomic case, since FB will be looked up like any other object property value in a few code paths (like property value validation).
So split out into an internal function without the
WARN_ON()which we can use in those special cases.Signed-off-by Rob Clark <[email protected]>
See my other mail, but Nack. Imo you want a drm_mode_object_exists instead, which just returns a bool. Gives you want you want and is safe. -Daniel
Quoted 82 lines
--- drivers/gpu/drm/drm_crtc.c | 33 ++++++++++++++++++++++----------- include/drm/drm_crtc.h | 6 ------ 2 files changed, 22 insertions(+), 17 deletions(-)drivers/gpu/drm/drm_crtc.c +22
-11@@ -443,6 +443,21 @@ void drm_mode_object_put(struct drm_device *dev,mutex_unlock (&dev->mode_config.idr_mutex); } +static struct drm_mode_object *_object_find (struct drm_device *dev, +uint32_t id,uint32_t type) +{ +struct drm_mode_object *obj =NULL ; + +mutex_lock (&dev->mode_config.idr_mutex); + obj =idr_find (&dev->mode_config.crtc_idr, id); +if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || + (obj->id != id)) + obj =NULL ; +mutex_unlock (&dev->mode_config.idr_mutex); + +return obj; +} +/** * drm_mode_object_find - look up a drm object with static lifetime * @dev: drm device @@ -455,23 +470,19 @@ void drm_mode_object_put(struct drm_device *dev,struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type) { -struct drm_mode_object *obj =NULL ; -/* Framebuffers are reference counted and need their own lookup * function.*/ WARN_ON (type ==DRM_MODE_OBJECT_FB ); - -mutex_lock (&dev->mode_config.idr_mutex); - obj =idr_find (&dev->mode_config.crtc_idr, id); -if (!obj || (type !=DRM_MODE_OBJECT_ANY && obj->type != type) || - (obj->id != id)) - obj =NULL ; -mutex_unlock (&dev->mode_config.idr_mutex); - -return obj; +return _object_find (dev, id, type); }EXPORT_SYMBOL (drm_mode_object_find); +static struct drm_mode_object * +drm_property_get_obj (struct drm_property *property,uint64_t value) +{ +return _object_find (property->dev, value, property->values[0 ]); +} +/** * drm_framebuffer_init - initialize a framebuffer * @dev: DRM device include/drm/drm_crtc.h +0
-6@@ -1033,12 +1033,6 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,extern struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type); -static inline struct drm_mode_object * -drm_property_get_obj (struct drm_property *property,uint64_t value) -{ -return drm_mode_object_find (property->dev, value, property->values[0 ]); -} -/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);Signature · 1 line
1.9.0
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 11/17 drm: convert plane to properties/state
In reply to Rob ClarkBreak the mutable state of a plane out into a separate structure and use atomic properties mechanism to set plane attributes. This makes it easier to have some helpers for plane->set_property() and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multiple set_property() calls and for easy atomic commit or roll- back.
The same should be done for CRTC, encoder, and connector, but this patch only includes the first part (plane).
--- drivers/gpu/drm/armada/armada_overlay.c | 11 +- drivers/gpu/drm/drm_atomic.c | 225 ++++++++++++++- drivers/gpu/drm/drm_crtc.c | 433 ++++++++++++++++++++--------- drivers/gpu/drm/drm_fb_helper.c | 17 +- drivers/gpu/drm/drm_plane_helper.c | 2 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 7 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 8 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + include/drm/drm_atomic.h | 29 +- include/drm/drm_crtc.h | 114 +++++++- 16 files changed, 725 insertions(+), 153 deletions(-)
drivers/gpu/drm/armada/armada_overlay.c +10 -1
@@ -7,6 +7,7 @@* published by the Free Software Foundation. */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h"
@@ -288,7 +289,12 @@ static int armada_plane_set_property(struct drm_plane *plane, {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane); +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);bool update_attr = false; +int ret =0 ; + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == priv->colorkey_prop) {#define CCC (v) ((v) << 24 | (v) << 16 | (v) << 8)
@@ -342,13 +348,16 @@ static int armada_plane_set_property(struct drm_plane *plane, }else if (property == priv->saturation_prop) { dplane->prop.saturation = val; update_attr = true; + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }if (update_attr && dplane->base.crtc)armada_ovl_update_attr (&dplane->prop,drm_to_armada_crtc (dplane->base.crtc)); -return 0 ; +return ret; }static const struct drm_plane_funcs armada_plane_funcs = {
drivers/gpu/drm/drm_atomic.c +223 -2
273 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +297 -136
556 lines not on this page · raw message
drivers/gpu/drm/drm_fb_helper.c +16 -1
@@ -286,13 +286,28 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; +void *state;int i;drm_warn_on_modeset_not_all_locked (dev); + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to restore fbdev mode\n" ); +return true; + } +list_for_each_entry (plane, &dev->mode_config.plane_list, head)if (plane->type !=DRM_PLANE_TYPE_PRIMARY ) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to restore fbdev mode\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state);for (i =0 ; i < fb_helper->crtc_count; i++) {struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
drivers/gpu/drm/drm_plane_helper.c +2 -0
@@ -26,6 +26,7 @@#include <linux/list.h> #include <drm/drmP.h> #include <drm/drm_rect.h> +#include <drm/drm_atomic.h> #define SUBPIXEL_MASK 0xffff
@@ -234,6 +235,7 @@ EXPORT_SYMBOL(drm_primary_helper_destroy);const struct drm_plane_funcs drm_primary_helper_funcs = { .update_plane = drm_primary_helper_update, .disable_plane = drm_primary_helper_disable, + .set_property = drm_atomic_plane_set_property, .destroy = drm_primary_helper_destroy, };EXPORT_SYMBOL (drm_primary_helper_funcs);
drivers/gpu/drm/exynos/exynos_drm_plane.c +6 -1
@@ -10,6 +10,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h"
@@ -220,13 +221,17 @@ static int exynos_plane_set_property(struct drm_plane *plane,struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);struct exynos_drm_private *dev_priv = dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == dev_priv->plane_zpos_property) { exynos_plane->overlay.zpos = val;return 0 ; } -return -EINVAL ; +return drm_plane_set_property (plane, pstate, property, val, blob_data); }static struct drm_plane_funcs exynos_plane_funcs = {
drivers/gpu/drm/i915/intel_sprite.c +1 -0
@@ -1190,6 +1190,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, .destroy = intel_destroy_plane, + .set_property = drm_atomic_plane_set_property, };static uint32_t ilk_plane_formats[] = {
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +4 -2
@@ -88,8 +88,10 @@ int mdp4_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp4_plane_funcs = {
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +4 -2
@@ -103,8 +103,10 @@ int mdp5_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp5_plane_funcs = {
drivers/gpu/drm/nouveau/dispnv04/overlay.c +7 -1
@@ -24,6 +24,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h>
@@ -226,6 +227,10 @@ nv_set_property(struct drm_plane *plane, uint64_t value, void *blob_data) { struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == nv_plane->props.colorkey) nv_plane->colorkey = value;
@@ -240,7 +245,8 @@ nv_set_property(struct drm_plane *plane,else if (property == nv_plane->props.iturbt_709) nv_plane->iturbt_709 = value;else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);if (nv_plane->set_params) nv_plane->set_params (nv_plane);
drivers/gpu/drm/omapdrm/omap_drv.c +1 -1
@@ -585,7 +585,7 @@ static void dev_lastclose(struct drm_device *dev)for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - &priv->planes[i]->propvals, + &priv->planes[i]->state->propvals, priv->rotation_prop,0 ,NULL ); } }
drivers/gpu/drm/omapdrm/omap_plane.c +7 -0
@@ -341,8 +341,12 @@ int omap_plane_set_property(struct drm_plane *plane, {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);int ret = -EINVAL ; +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +if (property == priv->rotation_prop) {DBG ("%s: rotation: %02x" , omap_plane->name, (uint32_t )val); omap_plane->win.rotation = val;
@@ -351,6 +355,9 @@ int omap_plane_set_property(struct drm_plane *plane,DBG ("%s: zorder: %02x" , omap_plane->name, (uint32_t )val); omap_plane->info.zorder = val; ret =apply (plane); + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }return ret;
drivers/gpu/drm/rcar-du/rcar_du_plane.c +7 -1
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -404,6 +405,10 @@ static int rcar_du_plane_set_property(struct drm_plane *plane, {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == rgrp->planes.alpha)rcar_du_plane_set_alpha (rplane, value);
@@ -412,7 +417,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,else if (property == rgrp->planes.zpos)rcar_du_plane_set_zpos (rplane, value);else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);return 0 ; }
drivers/gpu/drm/shmobile/shmob_drm_plane.c +2 -0
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -228,6 +229,7 @@ static void shmob_drm_plane_destroy(struct drm_plane *plane)static const struct drm_plane_funcs shmob_drm_plane_funcs = { .update_plane = shmob_drm_plane_update, .disable_plane = shmob_drm_plane_disable, + .set_property = drm_atomic_plane_set_property, .destroy = shmob_drm_plane_destroy, };
include/drm/drm_atomic.h +28 -1
@@ -68,7 +68,8 @@* struct drm_atomic_funcs - helper funcs used by the atomic helpers */ struct drm_atomic_funcs { -int dummy;/* for now */ +int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); +int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;
@@ -84,6 +85,30 @@ int drm_atomic_commit_unlocked(struct drm_device *dev, struct drm_atomic_state *state);void drm_atomic_end (struct drm_device *dev,struct drm_atomic_state *state); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data); +struct drm_plane_state *drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state); + +static inline int +drm_atomic_check_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->check_plane_state (plane, pstate); +} + +static inline int +drm_atomic_commit_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->commit_plane_state (plane, pstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */
@@ -91,6 +116,8 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; +struct drm_plane **planes; +struct drm_plane_state **pstates;bool committed;bool checked;/* just for debugging */
include/drm/drm_crtc.h +110 -4
170 lines not on this page · raw message
Signature · 1 line
1.9.0
Re: [PATCH 11/17] drm: convert plane to properties/state
Quoted 9 lines · Rob Clark
Break the mutable state of a plane out into a separate structure and use atomic properties mechanism to set plane attributes. This makes it easier to have some helpers for
plane->set_property()and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multipleset_property()calls and for easy atomic commit or roll- back.
Quoted 4 lines
The same should be done for CRTC, encoder, and connector, but this patch only includes the first part (plane).
Signed-off-by Rob Clark <[email protected]>
Imo s/plane->id/plane->index/ since plane_id can be too easily confused with the mode object id used for the idr lookup. We already have drm_crtc_index, so this is established convention already.
A few comments below.
Quoted 190 lines
--- drivers/gpu/drm/armada/armada_overlay.c | 11 +- drivers/gpu/drm/drm_atomic.c | 225 ++++++++++++++- drivers/gpu/drm/drm_crtc.c | 433 ++++++++++++++++++++--------- drivers/gpu/drm/drm_fb_helper.c | 17 +- drivers/gpu/drm/drm_plane_helper.c | 2 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 7 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 8 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + include/drm/drm_atomic.h | 29 +- include/drm/drm_crtc.h | 114 +++++++- 16 files changed, 725 insertions(+), 153 deletions(-)drivers/gpu/drm/armada/armada_overlay.c +10
-1@@ -7,6 +7,7 @@* published by the Free Software Foundation. */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h" @@ -288,7 +289,12 @@ static int armada_plane_set_property(struct drm_plane *plane, {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane); +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);bool update_attr = false; +int ret =0 ; + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == priv->colorkey_prop) {#define CCC (v) ((v) << 24 | (v) << 16 | (v) << 8)@@ -342,13 +348,16 @@ static int armada_plane_set_property(struct drm_plane *plane, }else if (property == priv->saturation_prop) { dplane->prop.saturation = val; update_attr = true; + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }if (update_attr && dplane->base.crtc)armada_ovl_update_attr (&dplane->prop,drm_to_armada_crtc (dplane->base.crtc)); -return 0 ; +return ret; }static const struct drm_plane_funcs armada_plane_funcs = {drivers/gpu/drm/drm_atomic.c +71
-2@@ -24,6 +24,7 @@#include <drm/drmP.h> #include <drm/drm_atomic.h> +#include <drm/drm_plane_helper.h> /** * drm_atomic_begin - start a sequence of atomic updates @@ -46,10 +47,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, uint32_t flags) {struct drm_atomic_state *state; +int nplanes = dev->mode_config.num_total_plane;int sz;void *ptr; sz =sizeof (*state); + sz += (sizeof (state->planes) +sizeof (state->pstates)) * nplanes; ptr =kzalloc (sz,GFP_KERNEL );@@ -65,6 +68,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, state->dev = dev; state->flags = flags; + state->planes = ptr; + ptr = &state->planes[nplanes]; + + state->pstates = ptr; + ptr = &state->pstates[nplanes]; +return state; }EXPORT_SYMBOL (drm_atomic_begin);@@ -101,8 +110,20 @@ EXPORT_SYMBOL(drm_atomic_set_event);int drm_atomic_check (struct drm_device *dev,struct drm_atomic_state *state) {struct drm_atomic_state *a = state; +int nplanes = dev->mode_config.num_total_plane; +int i, ret =0 ; + +for (i =0 ; i < nplanes; i++) { +if (a->planes[i]) { + ret =drm_atomic_check_plane_state (a->planes[i], a->pstates[i]); +if (ret) +break ; + } + } + a->acquire_ctx.frozen = true; -return 0 ;/* for now */ + +return ret; }EXPORT_SYMBOL (drm_atomic_check);@@ -180,6 +201,18 @@ fail:static void commit_locks (struct drm_atomic_state *a,struct ww_acquire_ctx *ww_ctx) { +struct drm_device *dev = a->dev; +int nplanes = dev->mode_config.num_total_plane; +int i; + +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = a->planes[i]; +if (plane) { + plane->state->state =NULL ; +drm_plane_destroy_state (plane, a->pstates[i]); + } + } +/* and properly release them (clear in_atomic, remove from list): */ drm_modeset_drop_locks (&a->acquire_ctx);ww_acquire_fini (ww_ctx);@@ -189,7 +222,17 @@ static void commit_locks(struct drm_atomic_state *a,static int atomic_commit (struct drm_atomic_state *a,struct ww_acquire_ctx *ww_ctx) { -int ret =0 ; +int nplanes = a->dev->mode_config.num_total_plane; +int i, ret =0 ; + +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = a->planes[i]; +if (plane) { + ret =drm_atomic_commit_plane_state (plane, a->pstates[i]); +if (ret) +break ; + } + }commit_locks (a, ww_ctx);@@ -264,7 +307,185 @@ void _drm_atomic_state_free(struct kref *kref) }EXPORT_SYMBOL (_drm_atomic_state_free); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) +{ +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); +} +EXPORT_SYMBOL (drm_atomic_plane_set_property); + +static void init_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate,struct drm_atomic_state *state) +{ +/* snapshot current state: */ + *pstate = *plane->state; + pstate->state = state; +if (pstate->fb) +drm_framebuffer_reference (pstate->fb); +} + +struct drm_plane_state * +drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state) +{ +struct drm_atomic_state *a = state;
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 345
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+struct drm_plane_state *pstate; +int ret; + + pstate = a->pstates[plane->id]; + +if (!pstate) { +struct drm_modeset_acquire_ctx *ctx = &a->acquire_ctx; + +/* grab lock of current crtc.. if crtc is NULL then grab all: */ +if (plane->state->crtc)
Looking here looks fishy - who's preventing someone else from touching plane->state while we don't yet hold any locks? Or do I miss something big here?
Quoted 65 lines
drivers/gpu/drm/drm_atomic.c +65
-0+ ret =drm_modeset_lock (&plane->state->crtc->mutex, ctx); + else + ret =drm_modeset_lock_all_crtcs (plane->dev, ctx); +if (ret) +return ERR_PTR (ret); + + pstate =drm_plane_create_state (plane); +if (!pstate) +return ERR_PTR (-ENOMEM ); +init_plane_state (plane, pstate, state); + a->planes[plane->id] = plane; + a->pstates[plane->id] = pstate; + } + +return pstate; +} +EXPORT_SYMBOL (drm_atomic_get_plane_state); + +static void +swap_plane_state (struct drm_plane *plane,struct drm_atomic_state *a) +{ +struct drm_plane_state *pstate = a->pstates[plane->id]; + +/* clear transient state (only valid during atomic update): */ + pstate->update_plane = false; + pstate->new_fb = false; + +swap (plane->state, a->pstates[plane->id]); + plane->base.propvals = &plane->state->propvals; +} + +/* For primary plane, if the driver implements ->page_flip(), then +* we can use that. But drivers can now choose not to bother with +* implementing page_flip(). +*/ +static bool can_flip (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_crtc *crtc = pstate->crtc; +return (plane == crtc->primary) && crtc->funcs->page_flip && + !pstate->update_plane; +} + +/* clear crtc/fb, ie. after disable_plane(). But takes care to keep +* the property state in sync. Once we get rid of plane->crtc/fb ptrs +* and just use state, we can get rid of this fxn: +*/ +static void +reset_plane (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_mode_config *config = &plane->dev->mode_config; +drm_plane_set_property (plane, pstate, config->prop_fb_id,0 ,NULL ); +drm_plane_set_property (plane, pstate, config->prop_crtc_id,0 ,NULL ); + plane->crtc =NULL ; + plane->fb =NULL ; +} + +static int +commit_plane_state (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_atomic_state *a = pstate->state; +struct drm_framebuffer *old_fb = plane->fb; +struct drm_framebuffer *fb = pstate->fb; +bool enabled = pstate->crtc && fb; +int ret =0 ; +
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 420
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+if (fb) +drm_framebuffer_reference (fb); + +if (!enabled) { +if ((plane->type ==DRM_PLANE_TYPE_PRIMARY ) && + (plane->funcs == &drm_primary_helper_funcs)) { +/* primary plane helpers don't like ->disable_plane().. +* so this hack for now until someone comes up with +* something better: +*/
Imo that's something we could check for in ->check and reject early.
Quoted 9 lines
drivers/gpu/drm/drm_atomic.c +9
-0+ ret =0 ; + }else { + ret = plane->funcs->disable_plane (plane); +reset_plane (plane, pstate); + } + }else { +struct drm_crtc *crtc = pstate->crtc; +if (pstate->update_plane || + (pstate->new_fb && !can_flip (plane, pstate))) {
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 439
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+ ret = plane->funcs->update_plane (plane, crtc, pstate->fb, + pstate->crtc_x, pstate->crtc_y, + pstate->crtc_w, pstate->crtc_h, + pstate->src_x, pstate->src_y, + pstate->src_w, pstate->src_h); +if (ret ==0 ) { +/* +* For page_flip(), the driver does this, but for +* update_plane() it doesn't.. hurray \o/ +*/
Imo a patch to unify this first wouldn't hurt ...
Quoted 12 lines
drivers/gpu/drm/drm_atomic.c +12
-0+ plane->crtc = crtc; + plane->fb = fb; + fb =NULL ;/* don't unref */ + } + + }else if (pstate->new_fb) { + ret = crtc->funcs->page_flip (crtc, fb,NULL , a->flags); +if (ret ==0 ) { +/* +* Warn if the driver hasn't properly updated the plane->fb +* field to reflect that the new framebuffer is now used. +* Failing to do so will screw with the reference counting
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 461
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+* on framebuffers. +*/ +WARN_ON (plane->fb != fb); + fb =NULL ;/* don't unref */ + } + }else { + old_fb =NULL ; + ret =0 ; + } + }
This entire logic here kinda raises the question about transitioning drivers to the atomic interfaces. For modeset operations it might work fairly well since everything but i915 uses the crtc helpers and so can be converted fairly easily.
But doing nuclear pageflips, even more so if we want completion events is an entire new deal. No idea how that should work really.
Quoted 675 lines
drivers/gpu/drm/drm_atomic.c +26
-0+ +if (ret) { +/* Keep the old fb, don't unref it. */ + old_fb =NULL ; + }else { +/* on success, update state and fb refcnting: */ +/* NOTE: if we ensure no driver sets plane->state->fb = NULL +* on disable, we can move this up a level and not duplicate +* nearly the same thing for both update_plane and disable_plane +* cases.. I leave it like this for now to be paranoid due to +* the slightly different ordering in the two cases in the +* original code. +*/ +swap_plane_state (plane, pstate->state); + } + + +if (fb) +drm_framebuffer_unreference (fb); +if (old_fb) +drm_framebuffer_unreference (old_fb); + +return ret; +}const struct drm_atomic_funcs drm_atomic_funcs = { + .check_plane_state = drm_plane_check_state, + .commit_plane_state = commit_plane_state, };EXPORT_SYMBOL (drm_atomic_funcs);drivers/gpu/drm/drm_crtc.c +297
-136@@ -712,6 +712,18 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)* in this manner. */ if (atomic_read (&fb->refcount.refcount) >1 ) { +void *state; + + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to disable crtc and/or plane when fb was deleted\n" ); +return ; + } + +/* TODO once CRTC is converted to state/properties, we can push the +* locking down into drm_atomic_commit(), since that is where +* the actual changes take place.. +*/ drm_modeset_lock_all (dev);/* remove from any CRTC */ list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {@@ -728,8 +740,17 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)list_for_each_entry (plane, &dev->mode_config.plane_list, head) {if (plane->fb == fb) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); } + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to disable crtc and/or plane when fb was deleted\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state); +drm_modeset_unlock_all (dev); }@@ -1090,18 +1111,23 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, enum drm_plane_type type) { + struct drm_mode_config *config = &dev->mode_config;int ret; +/* this is now required: */ +WARN_ON (!funcs->set_property); +drm_modeset_lock_all (dev); ret =drm_mode_object_get (dev, &plane->base,DRM_MODE_OBJECT_PLANE );if (ret) goto out; + plane->funcs = funcs; + plane->state =drm_plane_create_state (plane); plane->base.properties = &plane->properties; - plane->base.propvals = &plane->propvals; + plane->base.propvals = &plane->state->propvals; plane->dev = dev; - plane->funcs = funcs; plane->format_types =kmalloc (sizeof (uint32_t ) * format_count,GFP_KERNEL );if (!plane->format_types) {@@ -1116,15 +1142,27 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->possible_crtcs = possible_crtcs; plane->type = type; -list_add_tail (&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_total_plane++; +list_add_tail (&plane->head, &config->plane_list); + plane->id = config->num_total_plane; + config->num_total_plane++;if (plane->type ==DRM_PLANE_TYPE_OVERLAY ) - dev->mode_config.num_overlay_plane++; + config->num_overlay_plane++;drm_object_attach_property (&plane->base, - dev->mode_config.plane_type_property, + config->plane_type_property, plane->type); +drm_object_attach_property (&plane->base, config->prop_fb_id,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_id,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_x,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_y,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_w,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_h,0 ); +drm_object_attach_property (&plane->base, config->prop_src_x,0 ); +drm_object_attach_property (&plane->base, config->prop_src_y,0 ); +drm_object_attach_property (&plane->base, config->prop_src_w,0 ); +drm_object_attach_property (&plane->base, config->prop_src_h,0 ); + out:drm_modeset_unlock_all (dev);@@ -1185,10 +1223,151 @@ void drm_plane_cleanup(struct drm_plane *plane) dev->mode_config.num_total_plane--;if (plane->type ==DRM_PLANE_TYPE_OVERLAY ) dev->mode_config.num_overlay_plane--; +drm_plane_destroy_state (plane, plane->state);drm_modeset_unlock_all (dev); }EXPORT_SYMBOL (drm_plane_cleanup); +int drm_plane_check_state (struct drm_plane *plane, +struct drm_plane_state *state) +{ +unsigned int fb_width, fb_height; +struct drm_framebuffer *fb = state->fb; +int i; + +/* disabling the plane is allowed: */ +if (!fb) +return 0 ; + + fb_width = fb->width <<16 ; + fb_height = fb->height <<16 ; + +/* Check whether this plane supports the fb pixel format. */ +for (i =0 ; i < plane->format_count; i++) +if (fb->pixel_format == plane->format_types[i]) +break ; +if (i == plane->format_count) { +DRM_DEBUG_KMS ("Invalid pixel format 0x%08x\n" , fb->pixel_format); +return -EINVAL ; + } + +/* Make sure source coordinates are inside the fb. */ +if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { +DRM_DEBUG_KMS ("Invalid source coordinates " +"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , + state->src_w >>16 , + ((state->src_w &0xffff ) *15625 ) >>10 , + state->src_h >>16 , + ((state->src_h &0xffff ) *15625 ) >>10 , + state->src_x >>16 , + ((state->src_x &0xffff ) *15625 ) >>10 , + state->src_y >>16 , + ((state->src_y &0xffff ) *15625 ) >>10 ); +return -ENOSPC ; + } + +/* Give drivers some help against integer overflows */ +if (state->crtc_w >INT_MAX || + state->crtc_x >INT_MAX - (int32_t ) state->crtc_w || + state->crtc_h >INT_MAX || + state->crtc_y >INT_MAX - (int32_t ) state->crtc_h) { +DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , + state->crtc_w, state->crtc_h, + state->crtc_x, state->crtc_y); +return -ERANGE ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_plane_check_state); + +void drm_plane_commit_state (struct drm_plane *plane, +struct drm_plane_state *state) +{ + plane->state = state; + plane->base.propvals = &state->propvals; +} +EXPORT_SYMBOL (drm_plane_commit_state); + +int drm_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state, +struct drm_property *property, +uint64_t value,void *blob_data) +{ +struct drm_device *dev = plane->dev; +struct drm_mode_config *config = &dev->mode_config; + +drm_object_property_set_value (&plane->base, + &state->propvals, property, value, blob_data); + +if (property == config->prop_fb_id) { +struct drm_framebuffer *old_fb = state->fb; +/* +* NOTE: the ref to the fb could have been lost between +* drm_property_change_is_valid() and now. The upshot +* is that drm_framebuffer_lookup() could return NULL +* and we'd disable the plane. +* +* We *could* return an error in that case. But if (for +* example) _setcrtc() raced with _rmfb() and _rmfb() +* came after, it would disable what was enabled in the +* _setcrtc(). Which is the same end result that we get +* here, just skipping briefly setting the mode. +*/ + state->fb =drm_framebuffer_lookup (dev, value); +if (old_fb) +drm_framebuffer_unreference (old_fb); + state->new_fb = true; + }else if (property == config->prop_crtc_id) { +struct drm_mode_object *obj =drm_property_get_obj (property, value); +struct drm_crtc *crtc = obj ?obj_to_crtc (obj) :NULL ; +/* take the lock of the incoming crtc as well, moving +* plane between crtcs is synchronized on both incoming +* and outgoing crtc. +*/ +if (crtc) { +struct drm_atomic_state *a = state->state; +int ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ret; + } + state->crtc = crtc; + state->update_plane = true; + }else if (property == config->prop_crtc_x) { + state->crtc_x =U642I64 (value); + state->update_plane = true; + }else if (property == config->prop_crtc_y) { + state->crtc_y =U642I64 (value); + state->update_plane = true; + }else if (property == config->prop_crtc_w) { + state->crtc_w = value; + state->update_plane = true; + }else if (property == config->prop_crtc_h) { + state->crtc_h = value; + state->update_plane = true; + }else if (property == config->prop_src_x) { + state->src_x = value; + state->update_plane = true; + }else if (property == config->prop_src_y) { + state->src_y = value; + state->update_plane = true; + }else if (property == config->prop_src_w) { + state->src_w = value; + state->update_plane = true; + }else if (property == config->prop_src_h) { + state->src_h = value; + state->update_plane = true; + }else { +return -EINVAL ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_plane_set_property); +/** * drm_plane_force_disable - Forcibly disable a plane * @plane: plane to disable @@ -1198,43 +1377,93 @@ EXPORT_SYMBOL(drm_plane_cleanup);* Used when the plane's current framebuffer is destroyed, * and when restoring fbdev mode. */ -void drm_plane_force_disable (struct drm_plane *plane) +void drm_plane_force_disable (struct drm_plane *plane, +struct drm_atomic_state *state) { -struct drm_framebuffer *old_fb = plane->fb; -int ret; +struct drm_mode_config *config = &plane->dev->mode_config; -if (!old_fb) -return ; - - ret = plane->funcs->disable_plane (plane); -if (ret) { -DRM_ERROR ("failed to disable plane with busy fb\n" ); -return ; - } -/* disconnect the plane from the fb and crtc: */ -__drm_framebuffer_unreference (old_fb); - plane->fb =NULL ; - plane->crtc =NULL ; +/* should turn off the crtc */ +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_id,0 ,NULL ); +drm_mode_plane_set_obj_prop (plane, state, + config->prop_fb_id,0 ,NULL ); }EXPORT_SYMBOL (drm_plane_force_disable);static int drm_mode_create_standard_connector_properties (struct drm_device *dev) { -struct drm_property *edid; -struct drm_property *dpms; +struct drm_property *prop;/* * Standard properties (apply to all connectors) */ - edid =drm_property_create (dev,DRM_MODE_PROP_BLOB | + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB |DRM_MODE_PROP_IMMUTABLE ,"EDID" ,0 ); - dev->mode_config.edid_property = edid; +if (!prop) +return -ENOMEM ; + dev->mode_config.edid_property = prop; - dpms =drm_property_create_enum (dev,0 , + prop =drm_property_create_enum (dev,0 ,"DPMS" , drm_dpms_enum_list,ARRAY_SIZE (drm_dpms_enum_list)); - dev->mode_config.dpms_property = dpms; +if (!prop) +return -ENOMEM ; + dev->mode_config.dpms_property = prop; + + + prop =drm_property_create_range (dev,0 ,"SRC_X" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_x = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_Y" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_y = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_W" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_w = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_H" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_h = prop; + + prop =drm_property_create_signed_range (dev,0 ,"CRTC_X" , +INT_MIN ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_x = prop; + + prop =drm_property_create_signed_range (dev,0 ,"CRTC_Y" , +INT_MIN ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_y = prop; + + prop =drm_property_create_range (dev,0 ,"CRTC_W" ,0 ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_w = prop; + + prop =drm_property_create_range (dev,0 ,"CRTC_H" ,0 ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_h = prop; + + prop =drm_property_create_object (dev,0 ,"FB_ID" ,DRM_MODE_OBJECT_FB ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_fb_id = prop; + + prop =drm_property_create_object (dev,0 , +"CRTC_ID" ,DRM_MODE_OBJECT_CRTC ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_id = prop;return 0 ; }@@ -2140,20 +2369,19 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; +struct drm_mode_config *config = &dev->mode_config;struct drm_plane *plane; -struct drm_crtc *crtc; -struct drm_framebuffer *fb =NULL , *old_fb =NULL ; +struct drm_atomic_state *state;int ret =0 ; -unsigned int fb_width, fb_height; -int i;if (!drm_core_check_feature (dev,DRIVER_MODESET ))return -EINVAL ; -/* -* First, find the plane, crtc, and fb objects. If not available, -* we don't bother to call the driver. -*/ +retry: + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) +return PTR_ERR (state); + plane =drm_plane_find (dev, plane_req->plane_id);if (!plane) { DRM_DEBUG_KMS("Unknown plane ID %d\n",@@ -2161,104 +2389,37 @@ int drm_mode_setplane(struct drm_device *dev, void *data,return -ENOENT ; } -/* No fb means shut it down */ -if (!plane_req->fb_id) { -drm_modeset_lock_all (dev); - old_fb = plane->fb; - ret = plane->funcs->disable_plane (plane); -if (!ret) { - plane->crtc =NULL ; - plane->fb =NULL ; - }else { - old_fb =NULL ; - } -drm_modeset_unlock_all (dev); - goto out; - } - - crtc =drm_crtc_find (dev, plane_req->crtc_id); -if (!crtc) { -DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , - plane_req->crtc_id); - ret = -ENOENT ; - goto out; - } - - fb =drm_framebuffer_lookup (dev, plane_req->fb_id); -if (!fb) { -DRM_DEBUG_KMS ("Unknown framebuffer ID %d\n" , - plane_req->fb_id); - ret = -ENOENT ; - goto out; - } - -/* Check whether this plane supports the fb pixel format. */ -for (i =0 ; i < plane->format_count; i++) -if (fb->pixel_format == plane->format_types[i]) -break ; -if (i == plane->format_count) { -DRM_DEBUG_KMS ("Invalid pixel format %s\n" , -drm_get_format_name (fb->pixel_format)); - ret = -EINVAL ; - goto out; - } - - fb_width = fb->width <<16 ; - fb_height = fb->height <<16 ; - -/* Make sure source coordinates are inside the fb. */ -if (plane_req->src_w > fb_width || - plane_req->src_x > fb_width - plane_req->src_w || - plane_req->src_h > fb_height || - plane_req->src_y > fb_height - plane_req->src_h) { -DRM_DEBUG_KMS ("Invalid source coordinates " -"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , - plane_req->src_w >>16 , - ((plane_req->src_w &0xffff ) *15625 ) >>10 , - plane_req->src_h >>16 , - ((plane_req->src_h &0xffff ) *15625 ) >>10 , - plane_req->src_x >>16 , - ((plane_req->src_x &0xffff ) *15625 ) >>10 , - plane_req->src_y >>16 , - ((plane_req->src_y &0xffff ) *15625 ) >>10 ); - ret = -ENOSPC ; - goto out; - } - -/* Give drivers some help against integer overflows */ -if (plane_req->crtc_w >INT_MAX || - plane_req->crtc_x >INT_MAX - (int32_t ) plane_req->crtc_w || - plane_req->crtc_h >INT_MAX || - plane_req->crtc_y >INT_MAX - (int32_t ) plane_req->crtc_h) { -DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , - plane_req->crtc_w, plane_req->crtc_h, - plane_req->crtc_x, plane_req->crtc_y); - ret = -ERANGE ; + ret = +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_id, plane_req->crtc_id,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_fb_id, plane_req->fb_id,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_x,I642U64 (plane_req->crtc_x),NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_y,I642U64 (plane_req->crtc_y),NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_w, plane_req->crtc_w,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_h, plane_req->crtc_h,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_w, plane_req->src_w,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_h, plane_req->src_h,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_x, plane_req->src_x,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_y, plane_req->src_y,NULL ) || + dev->driver->atomic_check (dev, state); +if (ret) goto out; - } -drm_modeset_lock_all (dev); - old_fb = plane->fb; - ret = plane->funcs->update_plane (plane, crtc, fb, - plane_req->crtc_x, plane_req->crtc_y, - plane_req->crtc_w, plane_req->crtc_h, - plane_req->src_x, plane_req->src_y, - plane_req->src_w, plane_req->src_h); -if (!ret) { - plane->crtc = crtc; - plane->fb = fb; - fb =NULL ; - }else { - old_fb =NULL ; - } -drm_modeset_unlock_all (dev); + ret = dev->driver->atomic_commit (dev, state); out: -if (fb) -drm_framebuffer_unreference (fb); -if (old_fb) -drm_framebuffer_unreference (old_fb); - + dev->driver->atomic_end (dev, state); +if (ret == -EDEADLK ) + goto retry;return ret; }@@ -3833,7 +3994,7 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,return drm_mode_obj_set_property_ioctl (dev, &obj_set_prop, file_priv); } -static int drm_mode_connector_set_obj_prop (struct drm_connector *connector, +int drm_mode_connector_set_obj_prop (struct drm_connector *connector,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3856,8 +4017,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,return ret; } +EXPORT_SYMBOL (drm_mode_connector_set_obj_prop); -static int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc, +int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3872,8 +4034,9 @@ static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc,return ret; } +EXPORT_SYMBOL (drm_mode_crtc_set_obj_prop); -static int drm_mode_plane_set_obj_prop (struct drm_plane *plane, +int drm_mode_plane_set_obj_prop (struct drm_plane *plane,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3882,12 +4045,10 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,if (plane->funcs->set_property) ret = plane->funcs->set_property (plane, state, property, value, blob_data); -if (!ret) -drm_object_property_set_value (&plane->base, &plane->propvals, - property, value,NULL );return ret; } +EXPORT_SYMBOL (drm_mode_plane_set_obj_prop); static int drm_mode_set_obj_prop(struct drm_mode_object *obj, struct drm_atomic_state *state, struct drm_property *property,drivers/gpu/drm/drm_fb_helper.c +16
-1@@ -286,13 +286,28 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; +void *state;int i;drm_warn_on_modeset_not_all_locked (dev); + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to restore fbdev mode\n" ); +return true; + } +list_for_each_entry (plane, &dev->mode_config.plane_list, head)if (plane->type !=DRM_PLANE_TYPE_PRIMARY ) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to restore fbdev mode\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state);for (i =0 ; i < fb_helper->crtc_count; i++) {struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;drivers/gpu/drm/drm_plane_helper.c +2
-0@@ -26,6 +26,7 @@#include <linux/list.h> #include <drm/drmP.h> #include <drm/drm_rect.h> +#include <drm/drm_atomic.h> #define SUBPIXEL_MASK 0xffff@@ -234,6 +235,7 @@ EXPORT_SYMBOL(drm_primary_helper_destroy);const struct drm_plane_funcs drm_primary_helper_funcs = { .update_plane = drm_primary_helper_update, .disable_plane = drm_primary_helper_disable, + .set_property = drm_atomic_plane_set_property, .destroy = drm_primary_helper_destroy, };EXPORT_SYMBOL (drm_primary_helper_funcs);drivers/gpu/drm/exynos/exynos_drm_plane.c +4
-0@@ -10,6 +10,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h" @@ -220,13 +221,17 @@ static int exynos_plane_set_property(struct drm_plane *plane,struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);struct exynos_drm_private *dev_priv = dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate))
drivers/gpu/drm/exynos/exynos_drm_plane.c static int exynos_plane_set_property(struct drm_plane *plane, · line 235
Quoted 10 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c +2
-1+return PTR_ERR (pstate);if (property == dev_priv->plane_zpos_property) { exynos_plane->overlay.zpos = val;return 0 ; } -return -EINVAL ; +return drm_plane_set_property (plane, pstate, property, val, blob_data); }
Imo the interfaces here are a bit wonky - most drivers have the exact same structure of allocating a plane state object if it's not there and setting the property. Imo we should push this down a bit and have type-specific set_prop interfaces which take the state-specific state object. Core properties would be fully handled in the core. Which means that driver don't need to implement set_prop callbacks if they don't have any special properties on top of the core stuff. Much less boilerplate that way.
This would also give us a strong incentive to have common properties for e.g. blending since we could simply pimp the core with them, and leave drivers to just register the properties if they support them. If they have additional restrictions they only need to implement the ->check hook, which has the awesome advantage that they can deal with a real structure instead of abstract prop arrays.
E.g. we could add a plane->supports_blending bool which would enabled/disable the default blending/Z-order properties for updating.
Quoted 413 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c +0
-0static struct drm_plane_funcs exynos_plane_funcs = {drivers/gpu/drm/i915/intel_sprite.c +1
-0@@ -1190,6 +1190,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, .destroy = intel_destroy_plane, + .set_property = drm_atomic_plane_set_property, };static uint32_t ilk_plane_formats[] = {drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +4
-2@@ -88,8 +88,10 @@ int mdp4_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp4_plane_funcs = {drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +4
-2@@ -103,8 +103,10 @@ int mdp5_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp5_plane_funcs = {drivers/gpu/drm/nouveau/dispnv04/overlay.c +7
-1@@ -24,6 +24,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> @@ -226,6 +227,10 @@ nv_set_property(struct drm_plane *plane, uint64_t value, void *blob_data) { struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == nv_plane->props.colorkey) nv_plane->colorkey = value;@@ -240,7 +245,8 @@ nv_set_property(struct drm_plane *plane,else if (property == nv_plane->props.iturbt_709) nv_plane->iturbt_709 = value;else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);if (nv_plane->set_params) nv_plane->set_params (nv_plane);drivers/gpu/drm/omapdrm/omap_drv.c +1
-1@@ -585,7 +585,7 @@ static void dev_lastclose(struct drm_device *dev)for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - &priv->planes[i]->propvals, + &priv->planes[i]->state->propvals, priv->rotation_prop,0 ,NULL ); } }drivers/gpu/drm/omapdrm/omap_plane.c +7
-0@@ -341,8 +341,12 @@ int omap_plane_set_property(struct drm_plane *plane, {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);int ret = -EINVAL ; +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +if (property == priv->rotation_prop) {DBG ("%s: rotation: %02x" , omap_plane->name, (uint32_t )val); omap_plane->win.rotation = val;@@ -351,6 +355,9 @@ int omap_plane_set_property(struct drm_plane *plane,DBG ("%s: zorder: %02x" , omap_plane->name, (uint32_t )val); omap_plane->info.zorder = val; ret =apply (plane); + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }return ret;drivers/gpu/drm/rcar-du/rcar_du_plane.c +7
-1@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -404,6 +405,10 @@ static int rcar_du_plane_set_property(struct drm_plane *plane, {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == rgrp->planes.alpha)rcar_du_plane_set_alpha (rplane, value);@@ -412,7 +417,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,else if (property == rgrp->planes.zpos)rcar_du_plane_set_zpos (rplane, value);else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);return 0 ; }drivers/gpu/drm/shmobile/shmob_drm_plane.c +2
-0@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -228,6 +229,7 @@ static void shmob_drm_plane_destroy(struct drm_plane *plane)static const struct drm_plane_funcs shmob_drm_plane_funcs = { .update_plane = shmob_drm_plane_update, .disable_plane = shmob_drm_plane_disable, + .set_property = drm_atomic_plane_set_property, .destroy = shmob_drm_plane_destroy, };include/drm/drm_atomic.h +28
-1@@ -68,7 +68,8 @@* struct drm_atomic_funcs - helper funcs used by the atomic helpers */ struct drm_atomic_funcs { -int dummy;/* for now */ +int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); +int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;@@ -84,6 +85,30 @@ int drm_atomic_commit_unlocked(struct drm_device *dev, struct drm_atomic_state *state);void drm_atomic_end (struct drm_device *dev,struct drm_atomic_state *state); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data); +struct drm_plane_state *drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state); + +static inline int +drm_atomic_check_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->check_plane_state (plane, pstate); +} + +static inline int +drm_atomic_commit_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->commit_plane_state (plane, pstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */ @@ -91,6 +116,8 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; +struct drm_plane **planes; +struct drm_plane_state **pstates;bool committed;bool checked;/* just for debugging */ include/drm/drm_crtc.h +110
-4@@ -569,7 +569,10 @@ struct drm_plane_funcs {int (*disable_plane)(struct drm_plane *plane);void (*destroy)(struct drm_plane *plane); -int (*set_property)(struct drm_plane *plane, +struct drm_plane_state *(*create_state)(struct drm_plane *plane); +void (*destroy_state)(struct drm_plane *plane, +struct drm_plane_state *pstate); +int (*set_property)(struct drm_plane *plane,struct drm_atomic_state *state,struct drm_property *property,uint64_t val,void *blob_data);@@ -582,6 +585,48 @@ enum drm_plane_type { };/** +* drm_plane_state - mutable plane state +* @update_plane: if full update_plane() is needed (vs pageflip) +* @new_fb: has the fb been changed +* @crtc: currently bound CRTC +* @fb: currently bound fb +* @crtc_x: left position of visible portion of plane on crtc +* @crtc_y: upper position of visible portion of plane on crtc +* @crtc_w: width of visible portion of plane on crtc +* @crtc_h: height of visible portion of plane on crtc +* @src_x: left position of visible portion of plane within +* plane (in 16.16) +* @src_y: upper position of visible portion of plane within +* plane (in 16.16) +* @src_w: width of visible portion of plane (in 16.16) +* @src_h: height of visible portion of plane (in 16.16) +* @propvals: property values +* @state: current global/toplevel state object (for atomic) while an +* update is in progress, NULL otherwise. +*/ +struct drm_plane_state { +bool update_plane :1 ; +bool new_fb :1 ; + +struct drm_crtc *crtc; +struct drm_framebuffer *fb; + +/* Signed dest location allows it to be partially off screen */ +int32_t crtc_x, crtc_y; +uint32_t crtc_w, crtc_h; + +/* Source values are 16.16 fixed point */ +uint32_t src_x, src_y; +uint32_t src_h, src_w; + +bool enabled; + +struct drm_object_property_values propvals; + +struct drm_atomic_state *state; +}; + +/** * drm_plane - central DRM plane control structure * @dev: DRM device this plane belongs to * @head: for list management @@ -591,6 +636,8 @@ enum drm_plane_type {* @format_count: number of formats supported * @crtc: currently bound CRTC * @fb: currently bound fb +* @id: plane number, 0..n +* @state: the mutable state * @funcs: helper functions * @properties: property tracking for this plane * @type: type of plane (overlay, primary, cursor) @@ -608,10 +655,17 @@ struct drm_plane {struct drm_crtc *crtc;struct drm_framebuffer *fb; +int id; + +/* +* State that can be updated from userspace, and atomically +* commited or rolled back: +*/ +struct drm_plane_state *state; +const struct drm_plane_funcs *funcs;struct drm_object_properties properties; -struct drm_object_property_values propvals;enum drm_plane_type type; };@@ -807,8 +861,20 @@ struct drm_mode_config {bool poll_running;struct delayed_work output_poll_work; -/* pointers to standard properties */ +/* just so blob properties can always be in a list: */ struct list_head property_blob_list; + +/* pointers to standard properties */ +struct drm_property *prop_src_x; +struct drm_property *prop_src_y; +struct drm_property *prop_src_w; +struct drm_property *prop_src_h; +struct drm_property *prop_crtc_x; +struct drm_property *prop_crtc_y; +struct drm_property *prop_crtc_w; +struct drm_property *prop_crtc_h; +struct drm_property *prop_fb_id; +struct drm_property *prop_crtc_id;struct drm_property *edid_property;struct drm_property *dpms_property;struct drm_property *plane_type_property;@@ -930,11 +996,20 @@ extern int drm_plane_init(struct drm_device *dev, const uint32_t *formats, uint32_t format_count, bool is_primary);extern void drm_plane_cleanup (struct drm_plane *plane); -extern void drm_plane_force_disable (struct drm_plane *plane); +extern void drm_plane_force_disable (struct drm_plane *plane, +struct drm_atomic_state *state);extern int drm_crtc_check_viewport (const struct drm_crtc *crtc,int x,int y,const struct drm_display_mode *mode,const struct drm_framebuffer *fb); +extern int drm_plane_check_state (struct drm_plane *plane, +struct drm_plane_state *state); +extern void drm_plane_commit_state (struct drm_plane *plane, +struct drm_plane_state *state); +extern int drm_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state, +struct drm_property *property, +uint64_t value,void *blob_data);extern void drm_encoder_cleanup (struct drm_encoder *encoder);@@ -984,6 +1059,17 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,extern int drm_object_property_get_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t *value); + +int drm_mode_connector_set_obj_prop (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +int drm_mode_plane_set_obj_prop (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +extern int drm_framebuffer_init (struct drm_device *dev,struct drm_framebuffer *fb,const struct drm_framebuffer_funcs *funcs);@@ -1165,6 +1251,26 @@ drm_property_blob_find(struct drm_device *dev, uint32_t id)return mo ?obj_to_blob (mo) :NULL ; } +static inline struct drm_plane_state * +drm_plane_create_state (struct drm_plane *plane) +{ +if (plane->funcs->create_state) +return plane->funcs->create_state (plane); +return kzalloc (sizeof (struct drm_plane_state ),GFP_KERNEL ); +} + +static inline void +drm_plane_destroy_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +if (pstate->fb) +drm_framebuffer_unreference (pstate->fb); +if (plane->funcs->destroy_state) + plane->funcs->destroy_state (plane, pstate); +else +kfree (pstate); +} +/* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane (plane, planelist) \ list_for_each_entry(plane, planelist, head) \Signature · 1 line
1.9.0
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 11/17] drm: convert plane to properties/state
Quoted 10 lines · Daniel Vetter
Quoted 9 lines · Rob Clark
Break the mutable state of a plane out into a separate structure and use atomic properties mechanism to set plane attributes. This makes it easier to have some helpers for
plane->set_property()and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multipleset_property()calls and for easy atomic commit or roll- back.
Quoted 8 lines
Quoted 4 lines
The same should be done for CRTC, encoder, and connector, but this patch only includes the first part (plane).
Signed-off-by Rob Clark <[email protected]>Imo s/plane->id/plane->index/ since
plane_idcan be too easily confused with the mode object id used for the idr lookup. We already havedrm_crtc_index, so this is established convention already.
fair enough.. I suppose I could do the same in crtc.
Quoted 198 lines
A few comments below.
Quoted 196 lines
--- drivers/gpu/drm/armada/armada_overlay.c | 11 +- drivers/gpu/drm/drm_atomic.c | 225 ++++++++++++++- drivers/gpu/drm/drm_crtc.c | 433 ++++++++++++++++++++--------- drivers/gpu/drm/drm_fb_helper.c | 17 +- drivers/gpu/drm/drm_plane_helper.c | 2 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 7 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 8 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + include/drm/drm_atomic.h | 29 +- include/drm/drm_crtc.h | 114 +++++++- 16 files changed, 725 insertions(+), 153 deletions(-)drivers/gpu/drm/armada/armada_overlay.c +10
-1@@ -7,6 +7,7 @@* published by the Free Software Foundation. */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h" @@ -288,7 +289,12 @@ static int armada_plane_set_property(struct drm_plane *plane, {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane); +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);bool update_attr = false; +int ret =0 ; + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == priv->colorkey_prop) {#define CCC (v) ((v) << 24 | (v) << 16 | (v) << 8)@@ -342,13 +348,16 @@ static int armada_plane_set_property(struct drm_plane *plane, }else if (property == priv->saturation_prop) { dplane->prop.saturation = val; update_attr = true; + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }if (update_attr && dplane->base.crtc)armada_ovl_update_attr (&dplane->prop,drm_to_armada_crtc (dplane->base.crtc)); -return 0 ; +return ret; }static const struct drm_plane_funcs armada_plane_funcs = {drivers/gpu/drm/drm_atomic.c +77
-2@@ -24,6 +24,7 @@#include <drm/drmP.h> #include <drm/drm_atomic.h> +#include <drm/drm_plane_helper.h> /** * drm_atomic_begin - start a sequence of atomic updates @@ -46,10 +47,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, uint32_t flags) {struct drm_atomic_state *state; +int nplanes = dev->mode_config.num_total_plane;int sz;void *ptr; sz =sizeof (*state); + sz += (sizeof (state->planes) +sizeof (state->pstates)) * nplanes; ptr =kzalloc (sz,GFP_KERNEL );@@ -65,6 +68,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, state->dev = dev; state->flags = flags; + state->planes = ptr; + ptr = &state->planes[nplanes]; + + state->pstates = ptr; + ptr = &state->pstates[nplanes]; +return state; }EXPORT_SYMBOL (drm_atomic_begin);@@ -101,8 +110,20 @@ EXPORT_SYMBOL(drm_atomic_set_event);int drm_atomic_check (struct drm_device *dev,struct drm_atomic_state *state) {struct drm_atomic_state *a = state; +int nplanes = dev->mode_config.num_total_plane; +int i, ret =0 ; + +for (i =0 ; i < nplanes; i++) { +if (a->planes[i]) { + ret =drm_atomic_check_plane_state (a->planes[i], a->pstates[i]); +if (ret) +break ; + } + } + a->acquire_ctx.frozen = true; -return 0 ;/* for now */ + +return ret; }EXPORT_SYMBOL (drm_atomic_check);@@ -180,6 +201,18 @@ fail:static void commit_locks (struct drm_atomic_state *a,struct ww_acquire_ctx *ww_ctx) { +struct drm_device *dev = a->dev; +int nplanes = dev->mode_config.num_total_plane; +int i; + +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = a->planes[i]; +if (plane) { + plane->state->state =NULL ; +drm_plane_destroy_state (plane, a->pstates[i]); + } + } +/* and properly release them (clear in_atomic, remove from list): */ drm_modeset_drop_locks (&a->acquire_ctx);ww_acquire_fini (ww_ctx);@@ -189,7 +222,17 @@ static void commit_locks(struct drm_atomic_state *a,static int atomic_commit (struct drm_atomic_state *a,struct ww_acquire_ctx *ww_ctx) { -int ret =0 ; +int nplanes = a->dev->mode_config.num_total_plane; +int i, ret =0 ; + +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = a->planes[i]; +if (plane) { + ret =drm_atomic_commit_plane_state (plane, a->pstates[i]); +if (ret) +break ; + } + }commit_locks (a, ww_ctx);@@ -264,7 +307,185 @@ void _drm_atomic_state_free(struct kref *kref) }EXPORT_SYMBOL (_drm_atomic_state_free); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) +{ +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); +} +EXPORT_SYMBOL (drm_atomic_plane_set_property); + +static void init_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate,struct drm_atomic_state *state) +{ +/* snapshot current state: */ + *pstate = *plane->state; + pstate->state = state; +if (pstate->fb) +drm_framebuffer_reference (pstate->fb); +} + +struct drm_plane_state * +drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state) +{ +struct drm_atomic_state *a = state; +struct drm_plane_state *pstate; +int ret; + + pstate = a->pstates[plane->id]; + +if (!pstate) {
Quoted 8 lines
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 345
Quoted 4 lines
drivers/gpu/drm/drm_atomic.c +4
-0+struct drm_modeset_acquire_ctx *ctx = &a->acquire_ctx; + +/* grab lock of current crtc.. if crtc is NULL then grab all: */ +if (plane->state->crtc)Looking here looks fishy - who's preventing someone else from touching
plane->statewhile we don't yet hold any locks? Or do I miss something big here?
Yeah, probably should hoist that out into a local variable to avoid problems on transition to null crtc. I don't think it can happen at the moment, but when we start to relax locking it could
Quoted 69 lines
Quoted 69 lines
drivers/gpu/drm/drm_atomic.c +69
-0+ ret =drm_modeset_lock (&plane->state->crtc->mutex, ctx); + else + ret =drm_modeset_lock_all_crtcs (plane->dev, ctx); +if (ret) +return ERR_PTR (ret); + + pstate =drm_plane_create_state (plane); +if (!pstate) +return ERR_PTR (-ENOMEM ); +init_plane_state (plane, pstate, state); + a->planes[plane->id] = plane; + a->pstates[plane->id] = pstate; + } + +return pstate; +} +EXPORT_SYMBOL (drm_atomic_get_plane_state); + +static void +swap_plane_state (struct drm_plane *plane,struct drm_atomic_state *a) +{ +struct drm_plane_state *pstate = a->pstates[plane->id]; + +/* clear transient state (only valid during atomic update): */ + pstate->update_plane = false; + pstate->new_fb = false; + +swap (plane->state, a->pstates[plane->id]); + plane->base.propvals = &plane->state->propvals; +} + +/* For primary plane, if the driver implements ->page_flip(), then +* we can use that. But drivers can now choose not to bother with +* implementing page_flip(). +*/ +static bool can_flip (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_crtc *crtc = pstate->crtc; +return (plane == crtc->primary) && crtc->funcs->page_flip && + !pstate->update_plane; +} + +/* clear crtc/fb, ie. after disable_plane(). But takes care to keep +* the property state in sync. Once we get rid of plane->crtc/fb ptrs +* and just use state, we can get rid of this fxn: +*/ +static void +reset_plane (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_mode_config *config = &plane->dev->mode_config; +drm_plane_set_property (plane, pstate, config->prop_fb_id,0 ,NULL ); +drm_plane_set_property (plane, pstate, config->prop_crtc_id,0 ,NULL ); + plane->crtc =NULL ; + plane->fb =NULL ; +} + +static int +commit_plane_state (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_atomic_state *a = pstate->state; +struct drm_framebuffer *old_fb = plane->fb; +struct drm_framebuffer *fb = pstate->fb; +bool enabled = pstate->crtc && fb; +int ret =0 ; + +if (fb) +drm_framebuffer_reference (fb); + +if (!enabled) {
Quoted 8 lines
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 420
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+if ((plane->type ==DRM_PLANE_TYPE_PRIMARY ) && + (plane->funcs == &drm_primary_helper_funcs)) { +/* primary plane helpers don't like ->disable_plane().. +* so this hack for now until someone comes up with +* something better: +*/ Imo that's something we could check for in ->check and reject early.
well, we aren't actually treating it as a failure. If we did want to treat it as an error, then yes, we should fail it in ->check(). I'm going to let someone who actually uses primary planes helpers decide how they want it and change it if necessary.
Quoted 20 lines
Quoted 9 lines
drivers/gpu/drm/drm_atomic.c +9
-0+ ret =0 ; + }else { + ret = plane->funcs->disable_plane (plane); +reset_plane (plane, pstate); + } + }else { +struct drm_crtc *crtc = pstate->crtc; +if (pstate->update_plane || + (pstate->new_fb && !can_flip (plane, pstate))) {drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 439
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+ ret = plane->funcs->update_plane (plane, crtc, pstate->fb, + pstate->crtc_x, pstate->crtc_y, + pstate->crtc_w, pstate->crtc_h, + pstate->src_x, pstate->src_y, + pstate->src_w, pstate->src_h); +if (ret ==0 ) { +/* +* For page_flip(), the driver does this, but for +* update_plane() it doesn't.. hurray \o/ +*/
Quoted 1 line
Imo a patch to unify this first wouldn't hurt ...
I was kinda leaning more towards introducing a new API with unified behaviour, and deprecating the old eventually. Doing it all at once and not having someone who is more expert in each different drivers, seems like too big a chance to introduce problems.
I kinda want to more to an api that is more like atomic_commit() on a per object basis (ie. {crtc,plane,etc}->atomic_commit()). Then driver can hook in to the commit process at device level (dev->atomic_commit()) and/or per-object level as needed.
So yes, I want to unify.. but by building on top of atomic and deprecating the old.
Quoted 24 lines
Quoted 13 lines
drivers/gpu/drm/drm_atomic.c +12
-0+ plane->crtc = crtc; + plane->fb = fb; + fb =NULL ;/* don't unref */ + } + + }else if (pstate->new_fb) { + ret = crtc->funcs->page_flip (crtc, fb,NULL , a->flags); +if (ret ==0 ) { +/* +* Warn if the driver hasn't properly updated the plane->fb +* field to reflect that the new framebuffer is now used. +* Failing to do so will screw with the reference counting drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 461
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+* on framebuffers. +*/ +WARN_ON (plane->fb != fb); + fb =NULL ;/* don't unref */ + } + }else { + old_fb =NULL ; + ret =0 ; + } + }
Quoted 7 lines
This entire logic here kinda raises the question about transitioning drivers to the atomic interfaces. For modeset operations it might work fairly well since everything but i915 uses the crtc helpers and so can be converted fairly easily.
But doing nuclear pageflips, even more so if we want completion events is an entire new deal. No idea how that should work really.
Currently we only have completion events on CRTCs, but we are going to need no APIs internally for completion events on planes. Which might end up being the motivation for plane->atomic_commit() API.
At an rate, that should not hold up this patchset, or even adding atomic ioctl itself (as long as we don't expose new events yet, which is something we could leave out of the first version).
Quoted 682 lines
Quoted 682 lines
drivers/gpu/drm/drm_atomic.c +26
-0+ +if (ret) { +/* Keep the old fb, don't unref it. */ + old_fb =NULL ; + }else { +/* on success, update state and fb refcnting: */ +/* NOTE: if we ensure no driver sets plane->state->fb = NULL +* on disable, we can move this up a level and not duplicate +* nearly the same thing for both update_plane and disable_plane +* cases.. I leave it like this for now to be paranoid due to +* the slightly different ordering in the two cases in the +* original code. +*/ +swap_plane_state (plane, pstate->state); + } + + +if (fb) +drm_framebuffer_unreference (fb); +if (old_fb) +drm_framebuffer_unreference (old_fb); + +return ret; +}const struct drm_atomic_funcs drm_atomic_funcs = { + .check_plane_state = drm_plane_check_state, + .commit_plane_state = commit_plane_state, };EXPORT_SYMBOL (drm_atomic_funcs);drivers/gpu/drm/drm_crtc.c +297
-136@@ -712,6 +712,18 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)* in this manner. */ if (atomic_read (&fb->refcount.refcount) >1 ) { +void *state; + + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to disable crtc and/or plane when fb was deleted\n" ); +return ; + } + +/* TODO once CRTC is converted to state/properties, we can push the +* locking down into drm_atomic_commit(), since that is where +* the actual changes take place.. +*/ drm_modeset_lock_all (dev);/* remove from any CRTC */ list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {@@ -728,8 +740,17 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)list_for_each_entry (plane, &dev->mode_config.plane_list, head) {if (plane->fb == fb) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); } + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to disable crtc and/or plane when fb was deleted\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state); +drm_modeset_unlock_all (dev); }@@ -1090,18 +1111,23 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, enum drm_plane_type type) { + struct drm_mode_config *config = &dev->mode_config;int ret; +/* this is now required: */ +WARN_ON (!funcs->set_property); +drm_modeset_lock_all (dev); ret =drm_mode_object_get (dev, &plane->base,DRM_MODE_OBJECT_PLANE );if (ret) goto out; + plane->funcs = funcs; + plane->state =drm_plane_create_state (plane); plane->base.properties = &plane->properties; - plane->base.propvals = &plane->propvals; + plane->base.propvals = &plane->state->propvals; plane->dev = dev; - plane->funcs = funcs; plane->format_types =kmalloc (sizeof (uint32_t ) * format_count,GFP_KERNEL );if (!plane->format_types) {@@ -1116,15 +1142,27 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->possible_crtcs = possible_crtcs; plane->type = type; -list_add_tail (&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_total_plane++; +list_add_tail (&plane->head, &config->plane_list); + plane->id = config->num_total_plane; + config->num_total_plane++;if (plane->type ==DRM_PLANE_TYPE_OVERLAY ) - dev->mode_config.num_overlay_plane++; + config->num_overlay_plane++;drm_object_attach_property (&plane->base, - dev->mode_config.plane_type_property, + config->plane_type_property, plane->type); +drm_object_attach_property (&plane->base, config->prop_fb_id,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_id,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_x,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_y,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_w,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_h,0 ); +drm_object_attach_property (&plane->base, config->prop_src_x,0 ); +drm_object_attach_property (&plane->base, config->prop_src_y,0 ); +drm_object_attach_property (&plane->base, config->prop_src_w,0 ); +drm_object_attach_property (&plane->base, config->prop_src_h,0 ); + out:drm_modeset_unlock_all (dev);@@ -1185,10 +1223,151 @@ void drm_plane_cleanup(struct drm_plane *plane) dev->mode_config.num_total_plane--;if (plane->type ==DRM_PLANE_TYPE_OVERLAY ) dev->mode_config.num_overlay_plane--; +drm_plane_destroy_state (plane, plane->state);drm_modeset_unlock_all (dev); }EXPORT_SYMBOL (drm_plane_cleanup); +int drm_plane_check_state (struct drm_plane *plane, +struct drm_plane_state *state) +{ +unsigned int fb_width, fb_height; +struct drm_framebuffer *fb = state->fb; +int i; + +/* disabling the plane is allowed: */ +if (!fb) +return 0 ; + + fb_width = fb->width <<16 ; + fb_height = fb->height <<16 ; + +/* Check whether this plane supports the fb pixel format. */ +for (i =0 ; i < plane->format_count; i++) +if (fb->pixel_format == plane->format_types[i]) +break ; +if (i == plane->format_count) { +DRM_DEBUG_KMS ("Invalid pixel format 0x%08x\n" , fb->pixel_format); +return -EINVAL ; + } + +/* Make sure source coordinates are inside the fb. */ +if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { +DRM_DEBUG_KMS ("Invalid source coordinates " +"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , + state->src_w >>16 , + ((state->src_w &0xffff ) *15625 ) >>10 , + state->src_h >>16 , + ((state->src_h &0xffff ) *15625 ) >>10 , + state->src_x >>16 , + ((state->src_x &0xffff ) *15625 ) >>10 , + state->src_y >>16 , + ((state->src_y &0xffff ) *15625 ) >>10 ); +return -ENOSPC ; + } + +/* Give drivers some help against integer overflows */ +if (state->crtc_w >INT_MAX || + state->crtc_x >INT_MAX - (int32_t ) state->crtc_w || + state->crtc_h >INT_MAX || + state->crtc_y >INT_MAX - (int32_t ) state->crtc_h) { +DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , + state->crtc_w, state->crtc_h, + state->crtc_x, state->crtc_y); +return -ERANGE ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_plane_check_state); + +void drm_plane_commit_state (struct drm_plane *plane, +struct drm_plane_state *state) +{ + plane->state = state; + plane->base.propvals = &state->propvals; +} +EXPORT_SYMBOL (drm_plane_commit_state); + +int drm_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state, +struct drm_property *property, +uint64_t value,void *blob_data) +{ +struct drm_device *dev = plane->dev; +struct drm_mode_config *config = &dev->mode_config; + +drm_object_property_set_value (&plane->base, + &state->propvals, property, value, blob_data); + +if (property == config->prop_fb_id) { +struct drm_framebuffer *old_fb = state->fb; +/* +* NOTE: the ref to the fb could have been lost between +* drm_property_change_is_valid() and now. The upshot +* is that drm_framebuffer_lookup() could return NULL +* and we'd disable the plane. +* +* We *could* return an error in that case. But if (for +* example) _setcrtc() raced with _rmfb() and _rmfb() +* came after, it would disable what was enabled in the +* _setcrtc(). Which is the same end result that we get +* here, just skipping briefly setting the mode. +*/ + state->fb =drm_framebuffer_lookup (dev, value); +if (old_fb) +drm_framebuffer_unreference (old_fb); + state->new_fb = true; + }else if (property == config->prop_crtc_id) { +struct drm_mode_object *obj =drm_property_get_obj (property, value); +struct drm_crtc *crtc = obj ?obj_to_crtc (obj) :NULL ; +/* take the lock of the incoming crtc as well, moving +* plane between crtcs is synchronized on both incoming +* and outgoing crtc. +*/ +if (crtc) { +struct drm_atomic_state *a = state->state; +int ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ret; + } + state->crtc = crtc; + state->update_plane = true; + }else if (property == config->prop_crtc_x) { + state->crtc_x =U642I64 (value); + state->update_plane = true; + }else if (property == config->prop_crtc_y) { + state->crtc_y =U642I64 (value); + state->update_plane = true; + }else if (property == config->prop_crtc_w) { + state->crtc_w = value; + state->update_plane = true; + }else if (property == config->prop_crtc_h) { + state->crtc_h = value; + state->update_plane = true; + }else if (property == config->prop_src_x) { + state->src_x = value; + state->update_plane = true; + }else if (property == config->prop_src_y) { + state->src_y = value; + state->update_plane = true; + }else if (property == config->prop_src_w) { + state->src_w = value; + state->update_plane = true; + }else if (property == config->prop_src_h) { + state->src_h = value; + state->update_plane = true; + }else { +return -EINVAL ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_plane_set_property); +/** * drm_plane_force_disable - Forcibly disable a plane * @plane: plane to disable @@ -1198,43 +1377,93 @@ EXPORT_SYMBOL(drm_plane_cleanup);* Used when the plane's current framebuffer is destroyed, * and when restoring fbdev mode. */ -void drm_plane_force_disable (struct drm_plane *plane) +void drm_plane_force_disable (struct drm_plane *plane, +struct drm_atomic_state *state) { -struct drm_framebuffer *old_fb = plane->fb; -int ret; +struct drm_mode_config *config = &plane->dev->mode_config; -if (!old_fb) -return ; - - ret = plane->funcs->disable_plane (plane); -if (ret) { -DRM_ERROR ("failed to disable plane with busy fb\n" ); -return ; - } -/* disconnect the plane from the fb and crtc: */ -__drm_framebuffer_unreference (old_fb); - plane->fb =NULL ; - plane->crtc =NULL ; +/* should turn off the crtc */ +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_id,0 ,NULL ); +drm_mode_plane_set_obj_prop (plane, state, + config->prop_fb_id,0 ,NULL ); }EXPORT_SYMBOL (drm_plane_force_disable);static int drm_mode_create_standard_connector_properties (struct drm_device *dev) { -struct drm_property *edid; -struct drm_property *dpms; +struct drm_property *prop;/* * Standard properties (apply to all connectors) */ - edid =drm_property_create (dev,DRM_MODE_PROP_BLOB | + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB |DRM_MODE_PROP_IMMUTABLE ,"EDID" ,0 ); - dev->mode_config.edid_property = edid; +if (!prop) +return -ENOMEM ; + dev->mode_config.edid_property = prop; - dpms =drm_property_create_enum (dev,0 , + prop =drm_property_create_enum (dev,0 ,"DPMS" , drm_dpms_enum_list,ARRAY_SIZE (drm_dpms_enum_list)); - dev->mode_config.dpms_property = dpms; +if (!prop) +return -ENOMEM ; + dev->mode_config.dpms_property = prop; + + + prop =drm_property_create_range (dev,0 ,"SRC_X" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_x = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_Y" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_y = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_W" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_w = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_H" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_h = prop; + + prop =drm_property_create_signed_range (dev,0 ,"CRTC_X" , +INT_MIN ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_x = prop; + + prop =drm_property_create_signed_range (dev,0 ,"CRTC_Y" , +INT_MIN ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_y = prop; + + prop =drm_property_create_range (dev,0 ,"CRTC_W" ,0 ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_w = prop; + + prop =drm_property_create_range (dev,0 ,"CRTC_H" ,0 ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_h = prop; + + prop =drm_property_create_object (dev,0 ,"FB_ID" ,DRM_MODE_OBJECT_FB ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_fb_id = prop; + + prop =drm_property_create_object (dev,0 , +"CRTC_ID" ,DRM_MODE_OBJECT_CRTC ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_id = prop;return 0 ; }@@ -2140,20 +2369,19 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; +struct drm_mode_config *config = &dev->mode_config;struct drm_plane *plane; -struct drm_crtc *crtc; -struct drm_framebuffer *fb =NULL , *old_fb =NULL ; +struct drm_atomic_state *state;int ret =0 ; -unsigned int fb_width, fb_height; -int i;if (!drm_core_check_feature (dev,DRIVER_MODESET ))return -EINVAL ; -/* -* First, find the plane, crtc, and fb objects. If not available, -* we don't bother to call the driver. -*/ +retry: + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) +return PTR_ERR (state); + plane =drm_plane_find (dev, plane_req->plane_id);if (!plane) { DRM_DEBUG_KMS("Unknown plane ID %d\n",@@ -2161,104 +2389,37 @@ int drm_mode_setplane(struct drm_device *dev, void *data,return -ENOENT ; } -/* No fb means shut it down */ -if (!plane_req->fb_id) { -drm_modeset_lock_all (dev); - old_fb = plane->fb; - ret = plane->funcs->disable_plane (plane); -if (!ret) { - plane->crtc =NULL ; - plane->fb =NULL ; - }else { - old_fb =NULL ; - } -drm_modeset_unlock_all (dev); - goto out; - } - - crtc =drm_crtc_find (dev, plane_req->crtc_id); -if (!crtc) { -DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , - plane_req->crtc_id); - ret = -ENOENT ; - goto out; - } - - fb =drm_framebuffer_lookup (dev, plane_req->fb_id); -if (!fb) { -DRM_DEBUG_KMS ("Unknown framebuffer ID %d\n" , - plane_req->fb_id); - ret = -ENOENT ; - goto out; - } - -/* Check whether this plane supports the fb pixel format. */ -for (i =0 ; i < plane->format_count; i++) -if (fb->pixel_format == plane->format_types[i]) -break ; -if (i == plane->format_count) { -DRM_DEBUG_KMS ("Invalid pixel format %s\n" , -drm_get_format_name (fb->pixel_format)); - ret = -EINVAL ; - goto out; - } - - fb_width = fb->width <<16 ; - fb_height = fb->height <<16 ; - -/* Make sure source coordinates are inside the fb. */ -if (plane_req->src_w > fb_width || - plane_req->src_x > fb_width - plane_req->src_w || - plane_req->src_h > fb_height || - plane_req->src_y > fb_height - plane_req->src_h) { -DRM_DEBUG_KMS ("Invalid source coordinates " -"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , - plane_req->src_w >>16 , - ((plane_req->src_w &0xffff ) *15625 ) >>10 , - plane_req->src_h >>16 , - ((plane_req->src_h &0xffff ) *15625 ) >>10 , - plane_req->src_x >>16 , - ((plane_req->src_x &0xffff ) *15625 ) >>10 , - plane_req->src_y >>16 , - ((plane_req->src_y &0xffff ) *15625 ) >>10 ); - ret = -ENOSPC ; - goto out; - } - -/* Give drivers some help against integer overflows */ -if (plane_req->crtc_w >INT_MAX || - plane_req->crtc_x >INT_MAX - (int32_t ) plane_req->crtc_w || - plane_req->crtc_h >INT_MAX || - plane_req->crtc_y >INT_MAX - (int32_t ) plane_req->crtc_h) { -DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , - plane_req->crtc_w, plane_req->crtc_h, - plane_req->crtc_x, plane_req->crtc_y); - ret = -ERANGE ; + ret = +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_id, plane_req->crtc_id,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_fb_id, plane_req->fb_id,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_x,I642U64 (plane_req->crtc_x),NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_y,I642U64 (plane_req->crtc_y),NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_w, plane_req->crtc_w,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_h, plane_req->crtc_h,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_w, plane_req->src_w,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_h, plane_req->src_h,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_x, plane_req->src_x,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_y, plane_req->src_y,NULL ) || + dev->driver->atomic_check (dev, state); +if (ret) goto out; - } -drm_modeset_lock_all (dev); - old_fb = plane->fb; - ret = plane->funcs->update_plane (plane, crtc, fb, - plane_req->crtc_x, plane_req->crtc_y, - plane_req->crtc_w, plane_req->crtc_h, - plane_req->src_x, plane_req->src_y, - plane_req->src_w, plane_req->src_h); -if (!ret) { - plane->crtc = crtc; - plane->fb = fb; - fb =NULL ; - }else { - old_fb =NULL ; - } -drm_modeset_unlock_all (dev); + ret = dev->driver->atomic_commit (dev, state); out: -if (fb) -drm_framebuffer_unreference (fb); -if (old_fb) -drm_framebuffer_unreference (old_fb); - + dev->driver->atomic_end (dev, state); +if (ret == -EDEADLK ) + goto retry;return ret; }@@ -3833,7 +3994,7 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,return drm_mode_obj_set_property_ioctl (dev, &obj_set_prop, file_priv); } -static int drm_mode_connector_set_obj_prop (struct drm_connector *connector, +int drm_mode_connector_set_obj_prop (struct drm_connector *connector,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3856,8 +4017,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,return ret; } +EXPORT_SYMBOL (drm_mode_connector_set_obj_prop); -static int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc, +int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3872,8 +4034,9 @@ static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc,return ret; } +EXPORT_SYMBOL (drm_mode_crtc_set_obj_prop); -static int drm_mode_plane_set_obj_prop (struct drm_plane *plane, +int drm_mode_plane_set_obj_prop (struct drm_plane *plane,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3882,12 +4045,10 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,if (plane->funcs->set_property) ret = plane->funcs->set_property (plane, state, property, value, blob_data); -if (!ret) -drm_object_property_set_value (&plane->base, &plane->propvals, - property, value,NULL );return ret; } +EXPORT_SYMBOL (drm_mode_plane_set_obj_prop); static int drm_mode_set_obj_prop(struct drm_mode_object *obj, struct drm_atomic_state *state, struct drm_property *property,drivers/gpu/drm/drm_fb_helper.c +16
-1@@ -286,13 +286,28 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; +void *state;int i;drm_warn_on_modeset_not_all_locked (dev); + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to restore fbdev mode\n" ); +return true; + } +list_for_each_entry (plane, &dev->mode_config.plane_list, head)if (plane->type !=DRM_PLANE_TYPE_PRIMARY ) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to restore fbdev mode\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state);for (i =0 ; i < fb_helper->crtc_count; i++) {struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;drivers/gpu/drm/drm_plane_helper.c +2
-0@@ -26,6 +26,7 @@#include <linux/list.h> #include <drm/drmP.h> #include <drm/drm_rect.h> +#include <drm/drm_atomic.h> #define SUBPIXEL_MASK 0xffff@@ -234,6 +235,7 @@ EXPORT_SYMBOL(drm_primary_helper_destroy);const struct drm_plane_funcs drm_primary_helper_funcs = { .update_plane = drm_primary_helper_update, .disable_plane = drm_primary_helper_disable, + .set_property = drm_atomic_plane_set_property, .destroy = drm_primary_helper_destroy, };EXPORT_SYMBOL (drm_primary_helper_funcs);drivers/gpu/drm/exynos/exynos_drm_plane.c +5
-0@@ -10,6 +10,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h" @@ -220,13 +221,17 @@ static int exynos_plane_set_property(struct drm_plane *plane,struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);struct exynos_drm_private *dev_priv = dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == dev_priv->plane_zpos_property) { exynos_plane->overlay.zpos = val;return 0 ; }
Quoted 11 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c static int exynos_plane_set_property(struct drm_plane *plane, · line 235
Quoted 3 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c +1
-1-return -EINVAL ; +return drm_plane_set_property (plane, pstate, property, val, blob_data); }Imo the interfaces here are a bit wonky - most drivers have the exact same structure of allocating a plane state object if it's not there and setting the property. Imo we should push this down a bit and have type-specific
set_propinterfaces which take the state-specific state object. Core properties would be fully handled in the core. Which means that driver don't need to implementset_propcallbacks if they don't have any special properties on top of the core stuff. Much less boilerplate that way.
Drivers which do not have any custom properties already just directly use drm_{plane,crtc}_set_property().
Basically, a vanilla driver with no planes, no custom properties, and no inter-crtc dependencies could plug in helpers everywhere a be "fully atomic"(TM).
BR,
-R
Quoted 428 lines
This would also give us a strong incentive to have common properties for e.g. blending since we could simply pimp the core with them, and leave drivers to just register the properties if they support them. If they have additional restrictions they only need to implement the ->check hook, which has the awesome advantage that they can deal with a real structure instead of abstract prop arrays.
E.g. we could add a
plane->supports_blendingbool which would enabled/disable the default blending/Z-order properties for updating.Quoted 411 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c +0
-0static struct drm_plane_funcs exynos_plane_funcs = {drivers/gpu/drm/i915/intel_sprite.c +1
-0@@ -1190,6 +1190,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, .destroy = intel_destroy_plane, + .set_property = drm_atomic_plane_set_property, };static uint32_t ilk_plane_formats[] = {drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +4
-2@@ -88,8 +88,10 @@ int mdp4_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp4_plane_funcs = {drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +4
-2@@ -103,8 +103,10 @@ int mdp5_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp5_plane_funcs = {drivers/gpu/drm/nouveau/dispnv04/overlay.c +7
-1@@ -24,6 +24,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> @@ -226,6 +227,10 @@ nv_set_property(struct drm_plane *plane, uint64_t value, void *blob_data) { struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == nv_plane->props.colorkey) nv_plane->colorkey = value;@@ -240,7 +245,8 @@ nv_set_property(struct drm_plane *plane,else if (property == nv_plane->props.iturbt_709) nv_plane->iturbt_709 = value;else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);if (nv_plane->set_params) nv_plane->set_params (nv_plane);drivers/gpu/drm/omapdrm/omap_drv.c +1
-1@@ -585,7 +585,7 @@ static void dev_lastclose(struct drm_device *dev)for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - &priv->planes[i]->propvals, + &priv->planes[i]->state->propvals, priv->rotation_prop,0 ,NULL ); } }drivers/gpu/drm/omapdrm/omap_plane.c +7
-0@@ -341,8 +341,12 @@ int omap_plane_set_property(struct drm_plane *plane, {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);int ret = -EINVAL ; +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +if (property == priv->rotation_prop) {DBG ("%s: rotation: %02x" , omap_plane->name, (uint32_t )val); omap_plane->win.rotation = val;@@ -351,6 +355,9 @@ int omap_plane_set_property(struct drm_plane *plane,DBG ("%s: zorder: %02x" , omap_plane->name, (uint32_t )val); omap_plane->info.zorder = val; ret =apply (plane); + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }return ret;drivers/gpu/drm/rcar-du/rcar_du_plane.c +7
-1@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -404,6 +405,10 @@ static int rcar_du_plane_set_property(struct drm_plane *plane, {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == rgrp->planes.alpha)rcar_du_plane_set_alpha (rplane, value);@@ -412,7 +417,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,else if (property == rgrp->planes.zpos)rcar_du_plane_set_zpos (rplane, value);else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);return 0 ; }drivers/gpu/drm/shmobile/shmob_drm_plane.c +2
-0@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -228,6 +229,7 @@ static void shmob_drm_plane_destroy(struct drm_plane *plane)static const struct drm_plane_funcs shmob_drm_plane_funcs = { .update_plane = shmob_drm_plane_update, .disable_plane = shmob_drm_plane_disable, + .set_property = drm_atomic_plane_set_property, .destroy = shmob_drm_plane_destroy, };include/drm/drm_atomic.h +28
-1@@ -68,7 +68,8 @@* struct drm_atomic_funcs - helper funcs used by the atomic helpers */ struct drm_atomic_funcs { -int dummy;/* for now */ +int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); +int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;@@ -84,6 +85,30 @@ int drm_atomic_commit_unlocked(struct drm_device *dev, struct drm_atomic_state *state);void drm_atomic_end (struct drm_device *dev,struct drm_atomic_state *state); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data); +struct drm_plane_state *drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state); + +static inline int +drm_atomic_check_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->check_plane_state (plane, pstate); +} + +static inline int +drm_atomic_commit_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->commit_plane_state (plane, pstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */ @@ -91,6 +116,8 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; +struct drm_plane **planes; +struct drm_plane_state **pstates;bool committed;bool checked;/* just for debugging */ include/drm/drm_crtc.h +110
-5@@ -569,7 +569,10 @@ struct drm_plane_funcs {int (*disable_plane)(struct drm_plane *plane);void (*destroy)(struct drm_plane *plane); -int (*set_property)(struct drm_plane *plane, +struct drm_plane_state *(*create_state)(struct drm_plane *plane); +void (*destroy_state)(struct drm_plane *plane, +struct drm_plane_state *pstate); +int (*set_property)(struct drm_plane *plane,struct drm_atomic_state *state,struct drm_property *property,uint64_t val,void *blob_data);@@ -582,6 +585,48 @@ enum drm_plane_type { };/** +* drm_plane_state - mutable plane state +* @update_plane: if full update_plane() is needed (vs pageflip) +* @new_fb: has the fb been changed +* @crtc: currently bound CRTC +* @fb: currently bound fb +* @crtc_x: left position of visible portion of plane on crtc +* @crtc_y: upper position of visible portion of plane on crtc +* @crtc_w: width of visible portion of plane on crtc +* @crtc_h: height of visible portion of plane on crtc +* @src_x: left position of visible portion of plane within +* plane (in 16.16) +* @src_y: upper position of visible portion of plane within +* plane (in 16.16) +* @src_w: width of visible portion of plane (in 16.16) +* @src_h: height of visible portion of plane (in 16.16) +* @propvals: property values +* @state: current global/toplevel state object (for atomic) while an +* update is in progress, NULL otherwise. +*/ +struct drm_plane_state { +bool update_plane :1 ; +bool new_fb :1 ; + +struct drm_crtc *crtc; +struct drm_framebuffer *fb; + +/* Signed dest location allows it to be partially off screen */ +int32_t crtc_x, crtc_y; +uint32_t crtc_w, crtc_h; + +/* Source values are 16.16 fixed point */ +uint32_t src_x, src_y; +uint32_t src_h, src_w; + +bool enabled; + +struct drm_object_property_values propvals; + +struct drm_atomic_state *state; +}; + +/** * drm_plane - central DRM plane control structure * @dev: DRM device this plane belongs to * @head: for list management @@ -591,6 +636,8 @@ enum drm_plane_type {* @format_count: number of formats supported * @crtc: currently bound CRTC * @fb: currently bound fb +* @id: plane number, 0..n +* @state: the mutable state * @funcs: helper functions * @properties: property tracking for this plane * @type: type of plane (overlay, primary, cursor) @@ -608,10 +655,17 @@ struct drm_plane {struct drm_crtc *crtc;struct drm_framebuffer *fb; +int id; + +/* +* State that can be updated from userspace, and atomically +* commited or rolled back: +*/ +struct drm_plane_state *state; +const struct drm_plane_funcs *funcs;struct drm_object_properties properties; -struct drm_object_property_values propvals;enum drm_plane_type type; };@@ -807,8 +861,20 @@ struct drm_mode_config {bool poll_running;struct delayed_work output_poll_work; -/* pointers to standard properties */ +/* just so blob properties can always be in a list: */ struct list_head property_blob_list; + +/* pointers to standard properties */ +struct drm_property *prop_src_x; +struct drm_property *prop_src_y; +struct drm_property *prop_src_w; +struct drm_property *prop_src_h; +struct drm_property *prop_crtc_x; +struct drm_property *prop_crtc_y; +struct drm_property *prop_crtc_w; +struct drm_property *prop_crtc_h; +struct drm_property *prop_fb_id; +struct drm_property *prop_crtc_id;struct drm_property *edid_property;struct drm_property *dpms_property;struct drm_property *plane_type_property;@@ -930,11 +996,20 @@ extern int drm_plane_init(struct drm_device *dev, const uint32_t *formats, uint32_t format_count, bool is_primary);extern void drm_plane_cleanup (struct drm_plane *plane); -extern void drm_plane_force_disable (struct drm_plane *plane); +extern void drm_plane_force_disable (struct drm_plane *plane, +struct drm_atomic_state *state);extern int drm_crtc_check_viewport (const struct drm_crtc *crtc,int x,int y,const struct drm_display_mode *mode,const struct drm_framebuffer *fb); +extern int drm_plane_check_state (struct drm_plane *plane, +struct drm_plane_state *state); +extern void drm_plane_commit_state (struct drm_plane *plane, +struct drm_plane_state *state); +extern int drm_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state, +struct drm_property *property, +uint64_t value,void *blob_data);extern void drm_encoder_cleanup (struct drm_encoder *encoder);@@ -984,6 +1059,17 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,extern int drm_object_property_get_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t *value); + +int drm_mode_connector_set_obj_prop (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +int drm_mode_plane_set_obj_prop (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +extern int drm_framebuffer_init (struct drm_device *dev,struct drm_framebuffer *fb,const struct drm_framebuffer_funcs *funcs);@@ -1165,6 +1251,26 @@ drm_property_blob_find(struct drm_device *dev, uint32_t id)return mo ?obj_to_blob (mo) :NULL ; } +static inline struct drm_plane_state * +drm_plane_create_state (struct drm_plane *plane) +{ +if (plane->funcs->create_state) +return plane->funcs->create_state (plane); +return kzalloc (sizeof (struct drm_plane_state ),GFP_KERNEL ); +} + +static inline void +drm_plane_destroy_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +if (pstate->fb) +drm_framebuffer_unreference (pstate->fb); +if (plane->funcs->destroy_state) + plane->funcs->destroy_state (plane, pstate); +else +kfree (pstate); +} +/* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane (plane, planelist) \ list_for_each_entry(plane, planelist, head) \ --Quoted 2 lines
1.9.0
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 11/17] drm: convert plane to properties/state
Quoted 14 lines · Rob Clark
Quoted 13 lines · Daniel Vetter
Quoted 12 lines · Rob Clark
Break the mutable state of a plane out into a separate structure and use atomic properties mechanism to set plane attributes. This makes it easier to have some helpers for
plane->set_property()and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multipleset_property()calls and for easy atomic commit or roll- back.The same should be done for CRTC, encoder, and connector, but this patch only includes the first part (plane).
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Signed-off-by Rob Clark <[email protected]>Imo s/plane->id/plane->index/ since
plane_idcan be too easily confused with the mode object id used for the idr lookup. We already havedrm_crtc_index, so this is established convention already.fair enough.. I suppose I could do the same in crtc.
I've forgotten to mention: We then should replace drm_crtc_index with crtc->index since that helper is redundant.
Quoted 207 lines
Quoted 198 lines
A few comments below.
Quoted 196 lines
--- drivers/gpu/drm/armada/armada_overlay.c | 11 +- drivers/gpu/drm/drm_atomic.c | 225 ++++++++++++++- drivers/gpu/drm/drm_crtc.c | 433 ++++++++++++++++++++--------- drivers/gpu/drm/drm_fb_helper.c | 17 +- drivers/gpu/drm/drm_plane_helper.c | 2 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 7 +- drivers/gpu/drm/i915/intel_sprite.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/overlay.c | 8 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 7 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 8 +- drivers/gpu/drm/shmobile/shmob_drm_plane.c | 2 + include/drm/drm_atomic.h | 29 +- include/drm/drm_crtc.h | 114 +++++++- 16 files changed, 725 insertions(+), 153 deletions(-)drivers/gpu/drm/armada/armada_overlay.c +10
-1@@ -7,6 +7,7 @@* published by the Free Software Foundation. */ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h" @@ -288,7 +289,12 @@ static int armada_plane_set_property(struct drm_plane *plane, {struct armada_private *priv = plane->dev->dev_private;struct armada_plane *dplane =drm_to_armada_plane (plane); +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);bool update_attr = false; +int ret =0 ; + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == priv->colorkey_prop) {#define CCC (v) ((v) << 24 | (v) << 16 | (v) << 8)@@ -342,13 +348,16 @@ static int armada_plane_set_property(struct drm_plane *plane, }else if (property == priv->saturation_prop) { dplane->prop.saturation = val; update_attr = true; + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }if (update_attr && dplane->base.crtc)armada_ovl_update_attr (&dplane->prop,drm_to_armada_crtc (dplane->base.crtc)); -return 0 ; +return ret; }static const struct drm_plane_funcs armada_plane_funcs = {drivers/gpu/drm/drm_atomic.c +77
-2@@ -24,6 +24,7 @@#include <drm/drmP.h> #include <drm/drm_atomic.h> +#include <drm/drm_plane_helper.h> /** * drm_atomic_begin - start a sequence of atomic updates @@ -46,10 +47,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, uint32_t flags) {struct drm_atomic_state *state; +int nplanes = dev->mode_config.num_total_plane;int sz;void *ptr; sz =sizeof (*state); + sz += (sizeof (state->planes) +sizeof (state->pstates)) * nplanes; ptr =kzalloc (sz,GFP_KERNEL );@@ -65,6 +68,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, state->dev = dev; state->flags = flags; + state->planes = ptr; + ptr = &state->planes[nplanes]; + + state->pstates = ptr; + ptr = &state->pstates[nplanes]; +return state; }EXPORT_SYMBOL (drm_atomic_begin);@@ -101,8 +110,20 @@ EXPORT_SYMBOL(drm_atomic_set_event);int drm_atomic_check (struct drm_device *dev,struct drm_atomic_state *state) {struct drm_atomic_state *a = state; +int nplanes = dev->mode_config.num_total_plane; +int i, ret =0 ; + +for (i =0 ; i < nplanes; i++) { +if (a->planes[i]) { + ret =drm_atomic_check_plane_state (a->planes[i], a->pstates[i]); +if (ret) +break ; + } + } + a->acquire_ctx.frozen = true; -return 0 ;/* for now */ + +return ret; }EXPORT_SYMBOL (drm_atomic_check);@@ -180,6 +201,18 @@ fail:static void commit_locks (struct drm_atomic_state *a,struct ww_acquire_ctx *ww_ctx) { +struct drm_device *dev = a->dev; +int nplanes = dev->mode_config.num_total_plane; +int i; + +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = a->planes[i]; +if (plane) { + plane->state->state =NULL ; +drm_plane_destroy_state (plane, a->pstates[i]); + } + } +/* and properly release them (clear in_atomic, remove from list): */ drm_modeset_drop_locks (&a->acquire_ctx);ww_acquire_fini (ww_ctx);@@ -189,7 +222,17 @@ static void commit_locks(struct drm_atomic_state *a,static int atomic_commit (struct drm_atomic_state *a,struct ww_acquire_ctx *ww_ctx) { -int ret =0 ; +int nplanes = a->dev->mode_config.num_total_plane; +int i, ret =0 ; + +for (i =0 ; i < nplanes; i++) { +struct drm_plane *plane = a->planes[i]; +if (plane) { + ret =drm_atomic_commit_plane_state (plane, a->pstates[i]); +if (ret) +break ; + } + }commit_locks (a, ww_ctx);@@ -264,7 +307,185 @@ void _drm_atomic_state_free(struct kref *kref) }EXPORT_SYMBOL (_drm_atomic_state_free); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) +{ +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); +} +EXPORT_SYMBOL (drm_atomic_plane_set_property); + +static void init_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate,struct drm_atomic_state *state) +{ +/* snapshot current state: */ + *pstate = *plane->state; + pstate->state = state; +if (pstate->fb) +drm_framebuffer_reference (pstate->fb); +} + +struct drm_plane_state * +drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state) +{ +struct drm_atomic_state *a = state; +struct drm_plane_state *pstate; +int ret; + + pstate = a->pstates[plane->id]; + +if (!pstate) {Quoted 8 lines
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 345
Quoted 4 lines
drivers/gpu/drm/drm_atomic.c +4
-0+struct drm_modeset_acquire_ctx *ctx = &a->acquire_ctx; + +/* grab lock of current crtc.. if crtc is NULL then grab all: */ +if (plane->state->crtc)Looking here looks fishy - who's preventing someone else from touching
plane->statewhile we don't yet hold any locks? Or do I miss something big here?
Quoted 3 lines
Yeah, probably should hoist that out into a local variable to avoid problems on transition to null crtc. I don't think it can happen at the moment, but when we start to relax locking it could
So what if some manages to race a 2nd atomic modeset and flips out the plane->state from underneath you're now chasing a freed structure?
Trying to be clever and attempting to do this without locks is imo just not worth the (review) pain to keep it race-free.
Quoted 79 lines
Quoted 70 lines
Quoted 70 lines
drivers/gpu/drm/drm_atomic.c +69
-0+ ret =drm_modeset_lock (&plane->state->crtc->mutex, ctx); + else + ret =drm_modeset_lock_all_crtcs (plane->dev, ctx); +if (ret) +return ERR_PTR (ret); + + pstate =drm_plane_create_state (plane); +if (!pstate) +return ERR_PTR (-ENOMEM ); +init_plane_state (plane, pstate, state); + a->planes[plane->id] = plane; + a->pstates[plane->id] = pstate; + } + +return pstate; +} +EXPORT_SYMBOL (drm_atomic_get_plane_state); + +static void +swap_plane_state (struct drm_plane *plane,struct drm_atomic_state *a) +{ +struct drm_plane_state *pstate = a->pstates[plane->id]; + +/* clear transient state (only valid during atomic update): */ + pstate->update_plane = false; + pstate->new_fb = false; + +swap (plane->state, a->pstates[plane->id]); + plane->base.propvals = &plane->state->propvals; +} + +/* For primary plane, if the driver implements ->page_flip(), then +* we can use that. But drivers can now choose not to bother with +* implementing page_flip(). +*/ +static bool can_flip (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_crtc *crtc = pstate->crtc; +return (plane == crtc->primary) && crtc->funcs->page_flip && + !pstate->update_plane; +} + +/* clear crtc/fb, ie. after disable_plane(). But takes care to keep +* the property state in sync. Once we get rid of plane->crtc/fb ptrs +* and just use state, we can get rid of this fxn: +*/ +static void +reset_plane (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_mode_config *config = &plane->dev->mode_config; +drm_plane_set_property (plane, pstate, config->prop_fb_id,0 ,NULL ); +drm_plane_set_property (plane, pstate, config->prop_crtc_id,0 ,NULL ); + plane->crtc =NULL ; + plane->fb =NULL ; +} + +static int +commit_plane_state (struct drm_plane *plane,struct drm_plane_state *pstate) +{ +struct drm_atomic_state *a = pstate->state; +struct drm_framebuffer *old_fb = plane->fb; +struct drm_framebuffer *fb = pstate->fb; +bool enabled = pstate->crtc && fb; +int ret =0 ; + +if (fb) +drm_framebuffer_reference (fb); + +if (!enabled) {Quoted 8 lines
drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 420
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+if ((plane->type ==DRM_PLANE_TYPE_PRIMARY ) && + (plane->funcs == &drm_primary_helper_funcs)) { +/* primary plane helpers don't like ->disable_plane().. +* so this hack for now until someone comes up with +* something better: +*/ Imo that's something we could check for in ->check and reject early.
Quoted 4 lines
well, we aren't actually treating it as a failure. If we did want to treat it as an error, then yes, we should fail it in ->check(). I'm going to let someone who actually uses primary planes helpers decide how they want it and change it if necessary.
Atm all drivers use the primary plane helpers. And I guess for a long time most will stick to them, so I think we should have an answer here. Rejecting the modeset sounds like the right one, since after all arbitrary driver restrictions is what we have the ->check hook for.
Quoted 27 lines
Quoted 20 lines
Quoted 9 lines
drivers/gpu/drm/drm_atomic.c +9
-0+ ret =0 ; + }else { + ret = plane->funcs->disable_plane (plane); +reset_plane (plane, pstate); + } + }else { +struct drm_crtc *crtc = pstate->crtc; +if (pstate->update_plane || + (pstate->new_fb && !can_flip (plane, pstate))) {drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 439
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+ ret = plane->funcs->update_plane (plane, crtc, pstate->fb, + pstate->crtc_x, pstate->crtc_y, + pstate->crtc_w, pstate->crtc_h, + pstate->src_x, pstate->src_y, + pstate->src_w, pstate->src_h); +if (ret ==0 ) { +/* +* For page_flip(), the driver does this, but for +* update_plane() it doesn't.. hurray \o/ +*/ Quoted 1 line
Imo a patch to unify this first wouldn't hurt ...
I was kinda leaning more towards introducing a new API with unified behaviour, and deprecating the old eventually. Doing it all at once and not having someone who is more expert in each different drivers, seems like too big a chance to introduce problems.
Quoted 7 lines
I kinda want to more to an api that is more like
atomic_commit()on a per object basis (ie. {crtc,plane,etc}->atomic_commit()). Then driver can hook in to the commit process at device level (dev->atomic_commit()) and/or per-object level as needed.So yes, I want to unify.. but by building on top of atomic and deprecating the old.
I only meant to unify the refcounting and updating rules for obj->fb and similar. Like I've done for update_plane and set_crtc as part of Matt's primary plane work. Unifying all the flip interfaces is seriously out of scope ;-)
Also I really don't think you can make atomic pageflips work in a generic fashion with per-obj callbacks. After all the entire point is to have an atomic, global update, and the means (or lack thereof) the hw provides to make this happen will be different everywhere.
Atomic modesets (i.e. "do we have sufficient plls for this output config") are a bit different and for those it might work. But that should clearly be part of some helper library.
Yet another reason why imo it's really important to make a clear disdinction between atomic modesets (which we can mostly do for everyone using crtc helpers) and atomic/nuclear pageflips (for which we completely lack the unified driver interface and for which a per-obj ->commit hook is imo useless).
Quoted 31 lines
Quoted 23 lines
Quoted 12 lines
drivers/gpu/drm/drm_atomic.c +12
-0+ plane->crtc = crtc; + plane->fb = fb; + fb =NULL ;/* don't unref */ + } + + }else if (pstate->new_fb) { + ret = crtc->funcs->page_flip (crtc, fb,NULL , a->flags); +if (ret ==0 ) { +/* +* Warn if the driver hasn't properly updated the plane->fb +* field to reflect that the new framebuffer is now used. +* Failing to do so will screw with the reference counting drivers/gpu/drm/drm_atomic.c void _drm_atomic_state_free(struct kref *kref) · line 461
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+* on framebuffers. +*/ +WARN_ON (plane->fb != fb); + fb =NULL ;/* don't unref */ + } + }else { + old_fb =NULL ; + ret =0 ; + } + }Quoted 7 lines
This entire logic here kinda raises the question about transitioning drivers to the atomic interfaces. For modeset operations it might work fairly well since everything but i915 uses the crtc helpers and so can be converted fairly easily.
But doing nuclear pageflips, even more so if we want completion events is an entire new deal. No idea how that should work really.
Quoted 7 lines
Currently we only have completion events on CRTCs, but we are going to need no APIs internally for completion events on planes. Which might end up being the motivation for
plane->atomic_commit()API.At an rate, that should not hold up this patchset, or even adding atomic ioctl itself (as long as we don't expose new events yet, which is something we could leave out of the first version).
Hm, what's the use-case for per-plane completion events? Userspace can always multiplex it when they want, and one single nuclear pageflip certainly shouldn't result in different vblank events for different planes on the same crtc. Otherwise it's just not atomic enough ;-)
Imo the pain we gain in making this generic (I've commented about this in other places) doesn't justify the possible gain. Especially since I don't see a real use case.
I think we should have a NUCLEAR_FLIP option in the atomic ioctl which requests that:
- all updates happen on one vblank
- all updates happen asynchronously
and promises that the update only concerns one crtc. All drivers without support for it (i.e. atm everything, hopefully soonish i915 will have support for this) would then reject this.
Which means that for the start atomic updates would only work for modesets, but I also think that's about as good as it gets without driver-specific work anyway.
Quoted 694 lines
Quoted 682 lines
Quoted 682 lines
drivers/gpu/drm/drm_atomic.c +26
-0+ +if (ret) { +/* Keep the old fb, don't unref it. */ + old_fb =NULL ; + }else { +/* on success, update state and fb refcnting: */ +/* NOTE: if we ensure no driver sets plane->state->fb = NULL +* on disable, we can move this up a level and not duplicate +* nearly the same thing for both update_plane and disable_plane +* cases.. I leave it like this for now to be paranoid due to +* the slightly different ordering in the two cases in the +* original code. +*/ +swap_plane_state (plane, pstate->state); + } + + +if (fb) +drm_framebuffer_unreference (fb); +if (old_fb) +drm_framebuffer_unreference (old_fb); + +return ret; +}const struct drm_atomic_funcs drm_atomic_funcs = { + .check_plane_state = drm_plane_check_state, + .commit_plane_state = commit_plane_state, };EXPORT_SYMBOL (drm_atomic_funcs);drivers/gpu/drm/drm_crtc.c +297
-136@@ -712,6 +712,18 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)* in this manner. */ if (atomic_read (&fb->refcount.refcount) >1 ) { +void *state; + + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to disable crtc and/or plane when fb was deleted\n" ); +return ; + } + +/* TODO once CRTC is converted to state/properties, we can push the +* locking down into drm_atomic_commit(), since that is where +* the actual changes take place.. +*/ drm_modeset_lock_all (dev);/* remove from any CRTC */ list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) {@@ -728,8 +740,17 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)list_for_each_entry (plane, &dev->mode_config.plane_list, head) {if (plane->fb == fb) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); } + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to disable crtc and/or plane when fb was deleted\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state); +drm_modeset_unlock_all (dev); }@@ -1090,18 +1111,23 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, const uint32_t *formats, uint32_t format_count, enum drm_plane_type type) { + struct drm_mode_config *config = &dev->mode_config;int ret; +/* this is now required: */ +WARN_ON (!funcs->set_property); +drm_modeset_lock_all (dev); ret =drm_mode_object_get (dev, &plane->base,DRM_MODE_OBJECT_PLANE );if (ret) goto out; + plane->funcs = funcs; + plane->state =drm_plane_create_state (plane); plane->base.properties = &plane->properties; - plane->base.propvals = &plane->propvals; + plane->base.propvals = &plane->state->propvals; plane->dev = dev; - plane->funcs = funcs; plane->format_types =kmalloc (sizeof (uint32_t ) * format_count,GFP_KERNEL );if (!plane->format_types) {@@ -1116,15 +1142,27 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, plane->possible_crtcs = possible_crtcs; plane->type = type; -list_add_tail (&plane->head, &dev->mode_config.plane_list); - dev->mode_config.num_total_plane++; +list_add_tail (&plane->head, &config->plane_list); + plane->id = config->num_total_plane; + config->num_total_plane++;if (plane->type ==DRM_PLANE_TYPE_OVERLAY ) - dev->mode_config.num_overlay_plane++; + config->num_overlay_plane++;drm_object_attach_property (&plane->base, - dev->mode_config.plane_type_property, + config->plane_type_property, plane->type); +drm_object_attach_property (&plane->base, config->prop_fb_id,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_id,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_x,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_y,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_w,0 ); +drm_object_attach_property (&plane->base, config->prop_crtc_h,0 ); +drm_object_attach_property (&plane->base, config->prop_src_x,0 ); +drm_object_attach_property (&plane->base, config->prop_src_y,0 ); +drm_object_attach_property (&plane->base, config->prop_src_w,0 ); +drm_object_attach_property (&plane->base, config->prop_src_h,0 ); + out:drm_modeset_unlock_all (dev);@@ -1185,10 +1223,151 @@ void drm_plane_cleanup(struct drm_plane *plane) dev->mode_config.num_total_plane--;if (plane->type ==DRM_PLANE_TYPE_OVERLAY ) dev->mode_config.num_overlay_plane--; +drm_plane_destroy_state (plane, plane->state);drm_modeset_unlock_all (dev); }EXPORT_SYMBOL (drm_plane_cleanup); +int drm_plane_check_state (struct drm_plane *plane, +struct drm_plane_state *state) +{ +unsigned int fb_width, fb_height; +struct drm_framebuffer *fb = state->fb; +int i; + +/* disabling the plane is allowed: */ +if (!fb) +return 0 ; + + fb_width = fb->width <<16 ; + fb_height = fb->height <<16 ; + +/* Check whether this plane supports the fb pixel format. */ +for (i =0 ; i < plane->format_count; i++) +if (fb->pixel_format == plane->format_types[i]) +break ; +if (i == plane->format_count) { +DRM_DEBUG_KMS ("Invalid pixel format 0x%08x\n" , fb->pixel_format); +return -EINVAL ; + } + +/* Make sure source coordinates are inside the fb. */ +if (state->src_w > fb_width || + state->src_x > fb_width - state->src_w || + state->src_h > fb_height || + state->src_y > fb_height - state->src_h) { +DRM_DEBUG_KMS ("Invalid source coordinates " +"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , + state->src_w >>16 , + ((state->src_w &0xffff ) *15625 ) >>10 , + state->src_h >>16 , + ((state->src_h &0xffff ) *15625 ) >>10 , + state->src_x >>16 , + ((state->src_x &0xffff ) *15625 ) >>10 , + state->src_y >>16 , + ((state->src_y &0xffff ) *15625 ) >>10 ); +return -ENOSPC ; + } + +/* Give drivers some help against integer overflows */ +if (state->crtc_w >INT_MAX || + state->crtc_x >INT_MAX - (int32_t ) state->crtc_w || + state->crtc_h >INT_MAX || + state->crtc_y >INT_MAX - (int32_t ) state->crtc_h) { +DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , + state->crtc_w, state->crtc_h, + state->crtc_x, state->crtc_y); +return -ERANGE ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_plane_check_state); + +void drm_plane_commit_state (struct drm_plane *plane, +struct drm_plane_state *state) +{ + plane->state = state; + plane->base.propvals = &state->propvals; +} +EXPORT_SYMBOL (drm_plane_commit_state); + +int drm_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state, +struct drm_property *property, +uint64_t value,void *blob_data) +{ +struct drm_device *dev = plane->dev; +struct drm_mode_config *config = &dev->mode_config; + +drm_object_property_set_value (&plane->base, + &state->propvals, property, value, blob_data); + +if (property == config->prop_fb_id) { +struct drm_framebuffer *old_fb = state->fb; +/* +* NOTE: the ref to the fb could have been lost between +* drm_property_change_is_valid() and now. The upshot +* is that drm_framebuffer_lookup() could return NULL +* and we'd disable the plane. +* +* We *could* return an error in that case. But if (for +* example) _setcrtc() raced with _rmfb() and _rmfb() +* came after, it would disable what was enabled in the +* _setcrtc(). Which is the same end result that we get +* here, just skipping briefly setting the mode. +*/ + state->fb =drm_framebuffer_lookup (dev, value); +if (old_fb) +drm_framebuffer_unreference (old_fb); + state->new_fb = true; + }else if (property == config->prop_crtc_id) { +struct drm_mode_object *obj =drm_property_get_obj (property, value); +struct drm_crtc *crtc = obj ?obj_to_crtc (obj) :NULL ; +/* take the lock of the incoming crtc as well, moving +* plane between crtcs is synchronized on both incoming +* and outgoing crtc. +*/ +if (crtc) { +struct drm_atomic_state *a = state->state; +int ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ret; + } + state->crtc = crtc; + state->update_plane = true; + }else if (property == config->prop_crtc_x) { + state->crtc_x =U642I64 (value); + state->update_plane = true; + }else if (property == config->prop_crtc_y) { + state->crtc_y =U642I64 (value); + state->update_plane = true; + }else if (property == config->prop_crtc_w) { + state->crtc_w = value; + state->update_plane = true; + }else if (property == config->prop_crtc_h) { + state->crtc_h = value; + state->update_plane = true; + }else if (property == config->prop_src_x) { + state->src_x = value; + state->update_plane = true; + }else if (property == config->prop_src_y) { + state->src_y = value; + state->update_plane = true; + }else if (property == config->prop_src_w) { + state->src_w = value; + state->update_plane = true; + }else if (property == config->prop_src_h) { + state->src_h = value; + state->update_plane = true; + }else { +return -EINVAL ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_plane_set_property); +/** * drm_plane_force_disable - Forcibly disable a plane * @plane: plane to disable @@ -1198,43 +1377,93 @@ EXPORT_SYMBOL(drm_plane_cleanup);* Used when the plane's current framebuffer is destroyed, * and when restoring fbdev mode. */ -void drm_plane_force_disable (struct drm_plane *plane) +void drm_plane_force_disable (struct drm_plane *plane, +struct drm_atomic_state *state) { -struct drm_framebuffer *old_fb = plane->fb; -int ret; +struct drm_mode_config *config = &plane->dev->mode_config; -if (!old_fb) -return ; - - ret = plane->funcs->disable_plane (plane); -if (ret) { -DRM_ERROR ("failed to disable plane with busy fb\n" ); -return ; - } -/* disconnect the plane from the fb and crtc: */ -__drm_framebuffer_unreference (old_fb); - plane->fb =NULL ; - plane->crtc =NULL ; +/* should turn off the crtc */ +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_id,0 ,NULL ); +drm_mode_plane_set_obj_prop (plane, state, + config->prop_fb_id,0 ,NULL ); }EXPORT_SYMBOL (drm_plane_force_disable);static int drm_mode_create_standard_connector_properties (struct drm_device *dev) { -struct drm_property *edid; -struct drm_property *dpms; +struct drm_property *prop;/* * Standard properties (apply to all connectors) */ - edid =drm_property_create (dev,DRM_MODE_PROP_BLOB | + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB |DRM_MODE_PROP_IMMUTABLE ,"EDID" ,0 ); - dev->mode_config.edid_property = edid; +if (!prop) +return -ENOMEM ; + dev->mode_config.edid_property = prop; - dpms =drm_property_create_enum (dev,0 , + prop =drm_property_create_enum (dev,0 ,"DPMS" , drm_dpms_enum_list,ARRAY_SIZE (drm_dpms_enum_list)); - dev->mode_config.dpms_property = dpms; +if (!prop) +return -ENOMEM ; + dev->mode_config.dpms_property = prop; + + + prop =drm_property_create_range (dev,0 ,"SRC_X" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_x = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_Y" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_y = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_W" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_w = prop; + + prop =drm_property_create_range (dev,0 ,"SRC_H" ,0 ,UINT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_src_h = prop; + + prop =drm_property_create_signed_range (dev,0 ,"CRTC_X" , +INT_MIN ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_x = prop; + + prop =drm_property_create_signed_range (dev,0 ,"CRTC_Y" , +INT_MIN ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_y = prop; + + prop =drm_property_create_range (dev,0 ,"CRTC_W" ,0 ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_w = prop; + + prop =drm_property_create_range (dev,0 ,"CRTC_H" ,0 ,INT_MAX ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_h = prop; + + prop =drm_property_create_object (dev,0 ,"FB_ID" ,DRM_MODE_OBJECT_FB ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_fb_id = prop; + + prop =drm_property_create_object (dev,0 , +"CRTC_ID" ,DRM_MODE_OBJECT_CRTC ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_crtc_id = prop;return 0 ; }@@ -2140,20 +2369,19 @@ int drm_mode_setplane(struct drm_device *dev, void *data, struct drm_file *file_priv) {struct drm_mode_set_plane *plane_req = data; +struct drm_mode_config *config = &dev->mode_config;struct drm_plane *plane; -struct drm_crtc *crtc; -struct drm_framebuffer *fb =NULL , *old_fb =NULL ; +struct drm_atomic_state *state;int ret =0 ; -unsigned int fb_width, fb_height; -int i;if (!drm_core_check_feature (dev,DRIVER_MODESET ))return -EINVAL ; -/* -* First, find the plane, crtc, and fb objects. If not available, -* we don't bother to call the driver. -*/ +retry: + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) +return PTR_ERR (state); + plane =drm_plane_find (dev, plane_req->plane_id);if (!plane) { DRM_DEBUG_KMS("Unknown plane ID %d\n",@@ -2161,104 +2389,37 @@ int drm_mode_setplane(struct drm_device *dev, void *data,return -ENOENT ; } -/* No fb means shut it down */ -if (!plane_req->fb_id) { -drm_modeset_lock_all (dev); - old_fb = plane->fb; - ret = plane->funcs->disable_plane (plane); -if (!ret) { - plane->crtc =NULL ; - plane->fb =NULL ; - }else { - old_fb =NULL ; - } -drm_modeset_unlock_all (dev); - goto out; - } - - crtc =drm_crtc_find (dev, plane_req->crtc_id); -if (!crtc) { -DRM_DEBUG_KMS ("Unknown crtc ID %d\n" , - plane_req->crtc_id); - ret = -ENOENT ; - goto out; - } - - fb =drm_framebuffer_lookup (dev, plane_req->fb_id); -if (!fb) { -DRM_DEBUG_KMS ("Unknown framebuffer ID %d\n" , - plane_req->fb_id); - ret = -ENOENT ; - goto out; - } - -/* Check whether this plane supports the fb pixel format. */ -for (i =0 ; i < plane->format_count; i++) -if (fb->pixel_format == plane->format_types[i]) -break ; -if (i == plane->format_count) { -DRM_DEBUG_KMS ("Invalid pixel format %s\n" , -drm_get_format_name (fb->pixel_format)); - ret = -EINVAL ; - goto out; - } - - fb_width = fb->width <<16 ; - fb_height = fb->height <<16 ; - -/* Make sure source coordinates are inside the fb. */ -if (plane_req->src_w > fb_width || - plane_req->src_x > fb_width - plane_req->src_w || - plane_req->src_h > fb_height || - plane_req->src_y > fb_height - plane_req->src_h) { -DRM_DEBUG_KMS ("Invalid source coordinates " -"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n" , - plane_req->src_w >>16 , - ((plane_req->src_w &0xffff ) *15625 ) >>10 , - plane_req->src_h >>16 , - ((plane_req->src_h &0xffff ) *15625 ) >>10 , - plane_req->src_x >>16 , - ((plane_req->src_x &0xffff ) *15625 ) >>10 , - plane_req->src_y >>16 , - ((plane_req->src_y &0xffff ) *15625 ) >>10 ); - ret = -ENOSPC ; - goto out; - } - -/* Give drivers some help against integer overflows */ -if (plane_req->crtc_w >INT_MAX || - plane_req->crtc_x >INT_MAX - (int32_t ) plane_req->crtc_w || - plane_req->crtc_h >INT_MAX || - plane_req->crtc_y >INT_MAX - (int32_t ) plane_req->crtc_h) { -DRM_DEBUG_KMS ("Invalid CRTC coordinates %ux%u+%d+%d\n" , - plane_req->crtc_w, plane_req->crtc_h, - plane_req->crtc_x, plane_req->crtc_y); - ret = -ERANGE ; + ret = +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_id, plane_req->crtc_id,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_fb_id, plane_req->fb_id,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_x,I642U64 (plane_req->crtc_x),NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_y,I642U64 (plane_req->crtc_y),NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_w, plane_req->crtc_w,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_crtc_h, plane_req->crtc_h,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_w, plane_req->src_w,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_h, plane_req->src_h,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_x, plane_req->src_x,NULL ) || +drm_mode_plane_set_obj_prop (plane, state, + config->prop_src_y, plane_req->src_y,NULL ) || + dev->driver->atomic_check (dev, state); +if (ret) goto out; - } -drm_modeset_lock_all (dev); - old_fb = plane->fb; - ret = plane->funcs->update_plane (plane, crtc, fb, - plane_req->crtc_x, plane_req->crtc_y, - plane_req->crtc_w, plane_req->crtc_h, - plane_req->src_x, plane_req->src_y, - plane_req->src_w, plane_req->src_h); -if (!ret) { - plane->crtc = crtc; - plane->fb = fb; - fb =NULL ; - }else { - old_fb =NULL ; - } -drm_modeset_unlock_all (dev); + ret = dev->driver->atomic_commit (dev, state); out: -if (fb) -drm_framebuffer_unreference (fb); -if (old_fb) -drm_framebuffer_unreference (old_fb); - + dev->driver->atomic_end (dev, state); +if (ret == -EDEADLK ) + goto retry;return ret; }@@ -3833,7 +3994,7 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev,return drm_mode_obj_set_property_ioctl (dev, &obj_set_prop, file_priv); } -static int drm_mode_connector_set_obj_prop (struct drm_connector *connector, +int drm_mode_connector_set_obj_prop (struct drm_connector *connector,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3856,8 +4017,9 @@ static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,return ret; } +EXPORT_SYMBOL (drm_mode_connector_set_obj_prop); -static int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc, +int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3872,8 +4034,9 @@ static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc,return ret; } +EXPORT_SYMBOL (drm_mode_crtc_set_obj_prop); -static int drm_mode_plane_set_obj_prop (struct drm_plane *plane, +int drm_mode_plane_set_obj_prop (struct drm_plane *plane,struct drm_atomic_state *state,struct drm_property *property,uint64_t value,void *blob_data) {@@ -3882,12 +4045,10 @@ static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,if (plane->funcs->set_property) ret = plane->funcs->set_property (plane, state, property, value, blob_data); -if (!ret) -drm_object_property_set_value (&plane->base, &plane->propvals, - property, value,NULL );return ret; } +EXPORT_SYMBOL (drm_mode_plane_set_obj_prop); static int drm_mode_set_obj_prop(struct drm_mode_object *obj, struct drm_atomic_state *state, struct drm_property *property,drivers/gpu/drm/drm_fb_helper.c +16
-1@@ -286,13 +286,28 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; +void *state;int i;drm_warn_on_modeset_not_all_locked (dev); + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) { +DRM_ERROR ("failed to restore fbdev mode\n" ); +return true; + } +list_for_each_entry (plane, &dev->mode_config.plane_list, head)if (plane->type !=DRM_PLANE_TYPE_PRIMARY ) -drm_plane_force_disable (plane); +drm_plane_force_disable (plane, state); + +/* just disabling stuff shouldn't fail, hopefully: */ +if (dev->driver->atomic_check (dev, state)) +DRM_ERROR ("failed to restore fbdev mode\n" ); +else + dev->driver->atomic_commit (dev, state); + + dev->driver->atomic_end (dev, state);for (i =0 ; i < fb_helper->crtc_count; i++) {struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;drivers/gpu/drm/drm_plane_helper.c +2
-0@@ -26,6 +26,7 @@#include <linux/list.h> #include <drm/drmP.h> #include <drm/drm_rect.h> +#include <drm/drm_atomic.h> #define SUBPIXEL_MASK 0xffff@@ -234,6 +235,7 @@ EXPORT_SYMBOL(drm_primary_helper_destroy);const struct drm_plane_funcs drm_primary_helper_funcs = { .update_plane = drm_primary_helper_update, .disable_plane = drm_primary_helper_disable, + .set_property = drm_atomic_plane_set_property, .destroy = drm_primary_helper_destroy, };EXPORT_SYMBOL (drm_primary_helper_funcs);drivers/gpu/drm/exynos/exynos_drm_plane.c +5
-0@@ -10,6 +10,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/exynos_drm.h> #include "exynos_drm_drv.h" @@ -220,13 +221,17 @@ static int exynos_plane_set_property(struct drm_plane *plane,struct drm_device *dev = plane->dev;struct exynos_plane *exynos_plane =to_exynos_plane (plane);struct exynos_drm_private *dev_priv = dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == dev_priv->plane_zpos_property) { exynos_plane->overlay.zpos = val;return 0 ; }Quoted 11 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c static int exynos_plane_set_property(struct drm_plane *plane, · line 235
Quoted 3 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c +1
-1-return -EINVAL ; +return drm_plane_set_property (plane, pstate, property, val, blob_data); }Imo the interfaces here are a bit wonky - most drivers have the exact same structure of allocating a plane state object if it's not there and setting the property. Imo we should push this down a bit and have type-specific
set_propinterfaces which take the state-specific state object. Core properties would be fully handled in the core. Which means that driver don't need to implementset_propcallbacks if they don't have any special properties on top of the core stuff. Much less boilerplate that way.
Quoted 6 lines
Drivers which do not have any custom properties already just directly use drm_{plane,crtc}_set_property().
Basically, a vanilla driver with no planes, no custom properties, and no inter-crtc dependencies could plug in helpers everywhere a be "fully atomic"(TM).
My critique is two-fold:
- It looks like the core property parsing is helper code which can be overriden. We very much don't want that, since we want to expose a common set of kms operations that work everywhere.
- Since the callbacks are not object specific there's a bit too much casting going on for my taste.
- For drivers that do have driver props we could move the allocation error handling into the core. Which is imo a Very Good Thing(tm).
Cheers, Daniel
Quoted 432 lines
BR,
-RQuoted 428 lines
This would also give us a strong incentive to have common properties for e.g. blending since we could simply pimp the core with them, and leave drivers to just register the properties if they support them. If they have additional restrictions they only need to implement the ->check hook, which has the awesome advantage that they can deal with a real structure instead of abstract prop arrays.
E.g. we could add a
plane->supports_blendingbool which would enabled/disable the default blending/Z-order properties for updating.Quoted 411 lines
drivers/gpu/drm/exynos/exynos_drm_plane.c +0
-0static struct drm_plane_funcs exynos_plane_funcs = {drivers/gpu/drm/i915/intel_sprite.c +1
-0@@ -1190,6 +1190,7 @@ static const struct drm_plane_funcs intel_plane_funcs = { .update_plane = intel_update_plane, .disable_plane = intel_disable_plane, .destroy = intel_destroy_plane, + .set_property = drm_atomic_plane_set_property, };static uint32_t ilk_plane_formats[] = {drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +4
-2@@ -88,8 +88,10 @@ int mdp4_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp4_plane_funcs = {drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +4
-2@@ -103,8 +103,10 @@ int mdp5_plane_set_property(struct drm_plane *plane, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_plane_state *pstate = drm_atomic_get_plane_state(plane, state); +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +return drm_plane_set_property (plane, pstate, property, val, blob_data); } static const struct drm_plane_funcs mdp5_plane_funcs = {drivers/gpu/drm/nouveau/dispnv04/overlay.c +7
-1@@ -24,6 +24,7 @@*/ #include <drm/drmP.h> +#include <drm/drm_atomic.h> #include <drm/drm_crtc.h> #include <drm/drm_fourcc.h> @@ -226,6 +227,10 @@ nv_set_property(struct drm_plane *plane, uint64_t value, void *blob_data) { struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == nv_plane->props.colorkey) nv_plane->colorkey = value;@@ -240,7 +245,8 @@ nv_set_property(struct drm_plane *plane,else if (property == nv_plane->props.iturbt_709) nv_plane->iturbt_709 = value;else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);if (nv_plane->set_params) nv_plane->set_params (nv_plane);drivers/gpu/drm/omapdrm/omap_drv.c +1
-1@@ -585,7 +585,7 @@ static void dev_lastclose(struct drm_device *dev)for (i =0 ; i < priv->num_planes; i++) {drm_object_property_set_value (&priv->planes[i]->base, - &priv->planes[i]->propvals, + &priv->planes[i]->state->propvals, priv->rotation_prop,0 ,NULL ); } }drivers/gpu/drm/omapdrm/omap_plane.c +7
-0@@ -341,8 +341,12 @@ int omap_plane_set_property(struct drm_plane *plane, {struct omap_plane *omap_plane =to_omap_plane (plane);struct omap_drm_private *priv = plane->dev->dev_private; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state);int ret = -EINVAL ; +if (IS_ERR (pstate)) +return PTR_ERR (pstate); +if (property == priv->rotation_prop) {DBG ("%s: rotation: %02x" , omap_plane->name, (uint32_t )val); omap_plane->win.rotation = val;@@ -351,6 +355,9 @@ int omap_plane_set_property(struct drm_plane *plane,DBG ("%s: zorder: %02x" , omap_plane->name, (uint32_t )val); omap_plane->info.zorder = val; ret =apply (plane); + }else { + ret =drm_plane_set_property (plane, pstate, property, + val, blob_data); }return ret;drivers/gpu/drm/rcar-du/rcar_du_plane.c +7
-1@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -404,6 +405,10 @@ static int rcar_du_plane_set_property(struct drm_plane *plane, {struct rcar_du_plane *rplane =to_rcar_plane (plane);struct rcar_du_group *rgrp = rplane->group; +struct drm_plane_state *pstate =drm_atomic_get_plane_state (plane, state); + +if (IS_ERR (pstate)) +return PTR_ERR (pstate);if (property == rgrp->planes.alpha)rcar_du_plane_set_alpha (rplane, value);@@ -412,7 +417,8 @@ static int rcar_du_plane_set_property(struct drm_plane *plane,else if (property == rgrp->planes.zpos)rcar_du_plane_set_zpos (rplane, value);else -return -EINVAL ; +return drm_plane_set_property (plane, pstate, + property, value, blob_data);return 0 ; }drivers/gpu/drm/shmobile/shmob_drm_plane.c +2
-0@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -228,6 +229,7 @@ static void shmob_drm_plane_destroy(struct drm_plane *plane)static const struct drm_plane_funcs shmob_drm_plane_funcs = { .update_plane = shmob_drm_plane_update, .disable_plane = shmob_drm_plane_disable, + .set_property = drm_atomic_plane_set_property, .destroy = shmob_drm_plane_destroy, };include/drm/drm_atomic.h +28
-1@@ -68,7 +68,8 @@* struct drm_atomic_funcs - helper funcs used by the atomic helpers */ struct drm_atomic_funcs { -int dummy;/* for now */ +int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); +int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;@@ -84,6 +85,30 @@ int drm_atomic_commit_unlocked(struct drm_device *dev, struct drm_atomic_state *state);void drm_atomic_end (struct drm_device *dev,struct drm_atomic_state *state); +int drm_atomic_plane_set_property (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data); +struct drm_plane_state *drm_atomic_get_plane_state (struct drm_plane *plane, +struct drm_atomic_state *state); + +static inline int +drm_atomic_check_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->check_plane_state (plane, pstate); +} + +static inline int +drm_atomic_commit_plane_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +const struct drm_atomic_funcs *funcs = + plane->dev->driver->atomic_funcs; +return funcs->commit_plane_state (plane, pstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */ @@ -91,6 +116,8 @@ struct drm_atomic_state {struct kref refcount;struct drm_device *dev;uint32_t flags; +struct drm_plane **planes; +struct drm_plane_state **pstates;bool committed;bool checked;/* just for debugging */ include/drm/drm_crtc.h +110
-5@@ -569,7 +569,10 @@ struct drm_plane_funcs {int (*disable_plane)(struct drm_plane *plane);void (*destroy)(struct drm_plane *plane); -int (*set_property)(struct drm_plane *plane, +struct drm_plane_state *(*create_state)(struct drm_plane *plane); +void (*destroy_state)(struct drm_plane *plane, +struct drm_plane_state *pstate); +int (*set_property)(struct drm_plane *plane,struct drm_atomic_state *state,struct drm_property *property,uint64_t val,void *blob_data);@@ -582,6 +585,48 @@ enum drm_plane_type { };/** +* drm_plane_state - mutable plane state +* @update_plane: if full update_plane() is needed (vs pageflip) +* @new_fb: has the fb been changed +* @crtc: currently bound CRTC +* @fb: currently bound fb +* @crtc_x: left position of visible portion of plane on crtc +* @crtc_y: upper position of visible portion of plane on crtc +* @crtc_w: width of visible portion of plane on crtc +* @crtc_h: height of visible portion of plane on crtc +* @src_x: left position of visible portion of plane within +* plane (in 16.16) +* @src_y: upper position of visible portion of plane within +* plane (in 16.16) +* @src_w: width of visible portion of plane (in 16.16) +* @src_h: height of visible portion of plane (in 16.16) +* @propvals: property values +* @state: current global/toplevel state object (for atomic) while an +* update is in progress, NULL otherwise. +*/ +struct drm_plane_state { +bool update_plane :1 ; +bool new_fb :1 ; + +struct drm_crtc *crtc; +struct drm_framebuffer *fb; + +/* Signed dest location allows it to be partially off screen */ +int32_t crtc_x, crtc_y; +uint32_t crtc_w, crtc_h; + +/* Source values are 16.16 fixed point */ +uint32_t src_x, src_y; +uint32_t src_h, src_w; + +bool enabled; + +struct drm_object_property_values propvals; + +struct drm_atomic_state *state; +}; + +/** * drm_plane - central DRM plane control structure * @dev: DRM device this plane belongs to * @head: for list management @@ -591,6 +636,8 @@ enum drm_plane_type {* @format_count: number of formats supported * @crtc: currently bound CRTC * @fb: currently bound fb +* @id: plane number, 0..n +* @state: the mutable state * @funcs: helper functions * @properties: property tracking for this plane * @type: type of plane (overlay, primary, cursor) @@ -608,10 +655,17 @@ struct drm_plane {struct drm_crtc *crtc;struct drm_framebuffer *fb; +int id; + +/* +* State that can be updated from userspace, and atomically +* commited or rolled back: +*/ +struct drm_plane_state *state; +const struct drm_plane_funcs *funcs;struct drm_object_properties properties; -struct drm_object_property_values propvals;enum drm_plane_type type; };@@ -807,8 +861,20 @@ struct drm_mode_config {bool poll_running;struct delayed_work output_poll_work; -/* pointers to standard properties */ +/* just so blob properties can always be in a list: */ struct list_head property_blob_list; + +/* pointers to standard properties */ +struct drm_property *prop_src_x; +struct drm_property *prop_src_y; +struct drm_property *prop_src_w; +struct drm_property *prop_src_h; +struct drm_property *prop_crtc_x; +struct drm_property *prop_crtc_y; +struct drm_property *prop_crtc_w; +struct drm_property *prop_crtc_h; +struct drm_property *prop_fb_id; +struct drm_property *prop_crtc_id;struct drm_property *edid_property;struct drm_property *dpms_property;struct drm_property *plane_type_property;@@ -930,11 +996,20 @@ extern int drm_plane_init(struct drm_device *dev, const uint32_t *formats, uint32_t format_count, bool is_primary);extern void drm_plane_cleanup (struct drm_plane *plane); -extern void drm_plane_force_disable (struct drm_plane *plane); +extern void drm_plane_force_disable (struct drm_plane *plane, +struct drm_atomic_state *state);extern int drm_crtc_check_viewport (const struct drm_crtc *crtc,int x,int y,const struct drm_display_mode *mode,const struct drm_framebuffer *fb); +extern int drm_plane_check_state (struct drm_plane *plane, +struct drm_plane_state *state); +extern void drm_plane_commit_state (struct drm_plane *plane, +struct drm_plane_state *state); +extern int drm_plane_set_property (struct drm_plane *plane, +struct drm_plane_state *state, +struct drm_property *property, +uint64_t value,void *blob_data);extern void drm_encoder_cleanup (struct drm_encoder *encoder);@@ -984,6 +1059,17 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,extern int drm_object_property_get_value (struct drm_mode_object *obj,struct drm_property *property,uint64_t *value); + +int drm_mode_connector_set_obj_prop (struct drm_connector *connector, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +int drm_mode_crtc_set_obj_prop (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +int drm_mode_plane_set_obj_prop (struct drm_plane *plane, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t value,void *blob_data); +extern int drm_framebuffer_init (struct drm_device *dev,struct drm_framebuffer *fb,const struct drm_framebuffer_funcs *funcs);@@ -1165,6 +1251,26 @@ drm_property_blob_find(struct drm_device *dev, uint32_t id)return mo ?obj_to_blob (mo) :NULL ; } +static inline struct drm_plane_state * +drm_plane_create_state (struct drm_plane *plane) +{ +if (plane->funcs->create_state) +return plane->funcs->create_state (plane); +return kzalloc (sizeof (struct drm_plane_state ),GFP_KERNEL ); +} + +static inline void +drm_plane_destroy_state (struct drm_plane *plane, +struct drm_plane_state *pstate) +{ +if (pstate->fb) +drm_framebuffer_unreference (pstate->fb); +if (plane->funcs->destroy_state) + plane->funcs->destroy_state (plane, pstate); +else +kfree (pstate); +} +/* Plane list iterator for legacy (overlay only) planes. */ #define drm_for_each_legacy_plane (plane, planelist) \ list_for_each_entry(plane, planelist, head) \ --Quoted 2 lines
1.9.0
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 12/17 drm: convert crtc to properties/state
In reply to Rob ClarkBreak the mutable state of a crtc out into a separate structure and use atomic properties mechanism to set crtc attributes. This makes it easier to have some helpers for crtc->set_property() and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multiple set_property() calls and for easy atomic commit or roll- back.
--- drivers/gpu/drm/armada/armada_crtc.c | 11 +- drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 231 ++++++++++- drivers/gpu/drm/drm_crtc.c | 598 ++++++++++++++++++----------- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 12 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 + drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drm_atomic.h | 29 ++ include/drm/drm_crtc.h | 103 ++++- 27 files changed, 785 insertions(+), 243 deletions(-)
drivers/gpu/drm/armada/armada_crtc.c +10 -1
@@ -9,6 +9,7 @@#include <linux/clk.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h"
@@ -966,7 +967,12 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, {struct armada_private *priv = crtc->dev->dev_private;struct armada_crtc *dcrtc =drm_to_armada_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state);bool update_csc = false; +int ret =0 ; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->csc_yuv_prop) { dcrtc->csc_yuv_mode = val;
@@ -974,6 +980,9 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, }else if (property == priv->csc_rgb_prop) { dcrtc->csc_rgb_mode = val; update_csc = true; + }else { + ret =drm_crtc_set_property (crtc, cstate, property, + val, blob_data); }if (update_csc) {
@@ -984,7 +993,7 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,writel_relaxed (val, dcrtc->base +LCD_SPU_IOPAD_CONTROL ); } -return 0 ; +return ret; }static struct drm_crtc_funcs armada_crtc_funcs = {
drivers/gpu/drm/ast/ast_mode.c +1 -0
@@ -632,6 +632,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { .cursor_move = ast_cursor_move, .reset = ast_crtc_reset, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .gamma_set = ast_crtc_gamma_set, .destroy = ast_crtc_destroy, };
drivers/gpu/drm/cirrus/cirrus_mode.c +1 -0
@@ -366,6 +366,7 @@ static void cirrus_crtc_destroy(struct drm_crtc *crtc)static const struct drm_crtc_funcs cirrus_crtc_funcs = { .gamma_set = cirrus_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = cirrus_crtc_destroy, };
drivers/gpu/drm/drm_atomic.c +228 -3
322 lines not on this page · raw message
drivers/gpu/drm/drm_crtc.c +384 -214
774 lines not on this page · raw message
drivers/gpu/drm/drm_fb_helper.c +1 -1
@@ -286,7 +286,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; -void *state; +struct drm_atomic_state *state;int i;drm_warn_on_modeset_not_all_locked (dev);
drivers/gpu/drm/exynos/exynos_drm_crtc.c +6 -1
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "exynos_drm_crtc.h" #include "exynos_drm_drv.h"
@@ -289,6 +290,10 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,struct drm_device *dev = crtc->dev;struct exynos_drm_private *dev_priv = dev->dev_private;struct exynos_drm_crtc *exynos_crtc =to_exynos_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == dev_priv->crtc_mode_property) {enum exynos_crtc_mode mode = val;
@@ -313,7 +318,7 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,return 0 ; } -return -EINVAL ; +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }static struct drm_crtc_funcs exynos_crtc_funcs = {
drivers/gpu/drm/gma500/cdv_intel_display.c +1 -0
@@ -989,6 +989,7 @@ const struct drm_crtc_funcs cdv_intel_crtc_funcs = { .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, .set_config = gma_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = gma_crtc_destroy, };
drivers/gpu/drm/gma500/psb_intel_display.c +1 -0
@@ -444,6 +444,7 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = { .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, .set_config = gma_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = gma_crtc_destroy, };
drivers/gpu/drm/i915/intel_display.c +1 -0
@@ -10430,6 +10430,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, .set_config = intel_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, };
drivers/gpu/drm/mgag200/mgag200_mode.c +1 -0
@@ -1296,6 +1296,7 @@ static const struct drm_crtc_funcs mga_crtc_funcs = { .cursor_move = mga_crtc_cursor_move, .gamma_set = mga_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = mga_crtc_destroy, };
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +4 -2
@@ -471,8 +471,10 @@ static int mdp4_crtc_set_property(struct drm_crtc *crtc, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_crtc_state *cstate = drm_atomic_get_crtc_state(crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }#define CURSOR_WIDTH 64
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +4 -2
@@ -389,8 +389,10 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_crtc_state *cstate = drm_atomic_get_crtc_state(crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); } static const struct drm_crtc_funcs mdp5_crtc_funcs = {
drivers/gpu/drm/nouveau/dispnv04/crtc.c +1 -0
@@ -1086,6 +1086,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = { .cursor_move = nv04_crtc_cursor_move, .gamma_set = nv_crtc_gamma_set, .set_config = nouveau_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = nouveau_crtc_page_flip, .destroy = nv_crtc_destroy, };
drivers/gpu/drm/nouveau/nv50_display.c +1 -0
@@ -1329,6 +1329,7 @@ static const struct drm_crtc_funcs nv50_crtc_func = { .cursor_move = nv50_crtc_cursor_move, .gamma_set = nv50_crtc_gamma_set, .set_config = nouveau_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = nv50_crtc_destroy, .page_flip = nouveau_crtc_page_flip, };
drivers/gpu/drm/omapdrm/omap_crtc.c +10 -2
@@ -387,14 +387,22 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, {struct omap_crtc *omap_crtc =to_omap_crtc (crtc);struct omap_drm_private *priv = crtc->dev->dev_private; +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); +int ret; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->rotation_prop) { - crtc->invert_dimensions = + cstate->invert_dimensions = !!(val & ((1LL <<DRM_ROTATE_90 ) | (1LL <<DRM_ROTATE_270 ))); } -return omap_plane_set_property (omap_crtc->plane, state, + ret =omap_plane_set_property (omap_crtc->plane, state, property, val, blob_data); +if (ret) + ret =drm_crtc_set_property (crtc, cstate, property, val, blob_data); +return ret; }static const struct drm_crtc_funcs omap_crtc_funcs = {
drivers/gpu/drm/omapdrm/omap_drv.c +1 -1
@@ -579,7 +579,7 @@ static void dev_lastclose(struct drm_device *dev)*/ for (i =0 ; i < priv->num_crtcs; i++) {drm_object_property_set_value (&priv->crtcs[i]->base, - &priv->crtcs[i]->propvals, + &priv->crtcs[i]->state->propvals, priv->rotation_prop,0 ,NULL ); }
drivers/gpu/drm/qxl/qxl_display.c +2 -0
@@ -29,6 +29,7 @@#include "qxl_drv.h" #include "qxl_object.h" #include "drm_crtc_helper.h" +#include "drm_atomic.h" static bool qxl_head_enabled (struct qxl_head *head) {
@@ -373,6 +374,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { .cursor_set2 = qxl_crtc_cursor_set2, .cursor_move = qxl_crtc_cursor_move, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = qxl_crtc_destroy, };
drivers/gpu/drm/radeon/radeon_display.c +2 -0
@@ -32,6 +32,7 @@#include <linux/pm_runtime.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_edid.h> #include <linux/gcd.h>
@@ -546,6 +547,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = { .cursor_move = radeon_crtc_cursor_move, .gamma_set = radeon_crtc_gamma_set, .set_config = radeon_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = radeon_crtc_destroy, .page_flip = radeon_crtc_page_flip, };
drivers/gpu/drm/rcar-du/rcar_du_crtc.c +2 -0
@@ -17,6 +17,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -527,6 +528,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,static const struct drm_crtc_funcs crtc_funcs = { .destroy = drm_crtc_cleanup, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = rcar_du_crtc_page_flip, };
drivers/gpu/drm/shmobile/shmob_drm_crtc.c +2 -0
@@ -17,6 +17,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
@@ -506,6 +507,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,static const struct drm_crtc_funcs crtc_funcs = { .destroy = drm_crtc_cleanup, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = shmob_drm_crtc_page_flip, };
drivers/gpu/drm/tilcdc/tilcdc_crtc.c +1 -0
@@ -411,6 +411,7 @@ static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,static const struct drm_crtc_funcs tilcdc_crtc_funcs = { .destroy = tilcdc_crtc_destroy, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = tilcdc_crtc_page_flip, };
drivers/gpu/drm/udl/udl_modeset.c +2 -0
@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "udl_drv.h" /*
@@ -383,6 +384,7 @@ static struct drm_crtc_helper_funcs udl_helper_funcs = {static const struct drm_crtc_funcs udl_crtc_funcs = { .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = udl_crtc_destroy, };
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +1 -0
@@ -300,6 +300,7 @@ static struct drm_crtc_funcs vmw_legacy_crtc_funcs = { .cursor_move = vmw_du_crtc_cursor_move, .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_ldu_crtc_destroy, + .set_property = drm_atomic_crtc_set_property, .set_config = vmw_ldu_crtc_set_config, };
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +1 -0
@@ -397,6 +397,7 @@ static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_sou_crtc_destroy, .set_config = vmw_sou_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = vmw_du_page_flip, };
include/drm/drm_atomic.h +29 -0
@@ -70,6 +70,9 @@struct drm_atomic_funcs {int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate);int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); + +int (*check_crtc_state)(struct drm_crtc *crtc,struct drm_crtc_state *cstate); +int (*commit_crtc_state)(struct drm_crtc *crtc,struct drm_crtc_state *cstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;
@@ -109,6 +112,30 @@ drm_atomic_commit_plane_state(struct drm_plane *plane,return funcs->commit_plane_state (plane, pstate); } +int drm_atomic_crtc_set_property (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data); +struct drm_crtc_state *drm_atomic_get_crtc_state (struct drm_crtc *crtc, +struct drm_atomic_state *state); + +static inline int +drm_atomic_check_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +const struct drm_atomic_funcs *funcs = + crtc->dev->driver->atomic_funcs; +return funcs->check_crtc_state (crtc, cstate); +} + +static inline int +drm_atomic_commit_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +const struct drm_atomic_funcs *funcs = + crtc->dev->driver->atomic_funcs; +return funcs->commit_crtc_state (crtc, cstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */
@@ -118,6 +145,8 @@ struct drm_atomic_state {uint32_t flags;struct drm_plane **planes;struct drm_plane_state **pstates; +struct drm_crtc **crtcs; +struct drm_crtc_state **cstates;bool committed;bool checked;/* just for debugging */
include/drm/drm_crtc.h +87 -16
186 lines not on this page · raw message
Signature · 1 line
1.9.0
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 10 lines · Rob Clark
Break the mutable state of a crtc out into a separate structure and use atomic properties mechanism to set crtc attributes. This makes it easier to have some helpers for
crtc->set_property()and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multipleset_property()calls and for easy atomic commit or roll- back.Signed-off-by Rob Clark <[email protected]>
Same comments about interface design as for the plane patch apply here. One additional comment below.
Quoted 136 lines
--- drivers/gpu/drm/armada/armada_crtc.c | 11 +- drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 231 ++++++++++- drivers/gpu/drm/drm_crtc.c | 598 ++++++++++++++++++----------- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 12 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 + drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drm_atomic.h | 29 ++ include/drm/drm_crtc.h | 103 ++++- 27 files changed, 785 insertions(+), 243 deletions(-)drivers/gpu/drm/armada/armada_crtc.c +10
-1@@ -9,6 +9,7 @@#include <linux/clk.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h" @@ -966,7 +967,12 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, {struct armada_private *priv = crtc->dev->dev_private;struct armada_crtc *dcrtc =drm_to_armada_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state);bool update_csc = false; +int ret =0 ; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->csc_yuv_prop) { dcrtc->csc_yuv_mode = val;@@ -974,6 +980,9 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, }else if (property == priv->csc_rgb_prop) { dcrtc->csc_rgb_mode = val; update_csc = true; + }else { + ret =drm_crtc_set_property (crtc, cstate, property, + val, blob_data); }if (update_csc) {@@ -984,7 +993,7 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,writel_relaxed (val, dcrtc->base +LCD_SPU_IOPAD_CONTROL ); } -return 0 ; +return ret; }static struct drm_crtc_funcs armada_crtc_funcs = {drivers/gpu/drm/ast/ast_mode.c +1
-0@@ -632,6 +632,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { .cursor_move = ast_cursor_move, .reset = ast_crtc_reset, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .gamma_set = ast_crtc_gamma_set, .destroy = ast_crtc_destroy, };drivers/gpu/drm/cirrus/cirrus_mode.c +1
-0@@ -366,6 +366,7 @@ static void cirrus_crtc_destroy(struct drm_crtc *crtc)static const struct drm_crtc_funcs cirrus_crtc_funcs = { .gamma_set = cirrus_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = cirrus_crtc_destroy, };drivers/gpu/drm/drm_atomic.c +10
-1@@ -48,11 +48,13 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, {struct drm_atomic_state *state;int nplanes = dev->mode_config.num_total_plane; +int ncrtcs = dev->mode_config.num_crtc;int sz;void *ptr; sz =sizeof (*state); sz += (sizeof (state->planes) +sizeof (state->pstates)) * nplanes; + sz += (sizeof (state->crtcs) +sizeof (state->cstates)) * ncrtcs; ptr =kzalloc (sz,GFP_KERNEL );@@ -74,6 +76,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, state->pstates = ptr; ptr = &state->pstates[nplanes]; + state->crtcs = ptr; + ptr = &state->crtcs[ncrtcs]; + + state->cstates = ptr; + ptr = &state->cstates[ncrtcs]; +return state; }EXPORT_SYMBOL (drm_atomic_begin);@@ -92,7 +100,18 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_object *obj, struct drm_pending_vblank_event *event) { - return -EINVAL; /* for now */ + switch (obj->type) { + case DRM_MODE_OBJECT_CRTC: {
drivers/gpu/drm/drm_atomic.c int drm_atomic_set_event(struct drm_device *dev, · line 114
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+struct drm_crtc_state *cstate = +drm_atomic_get_crtc_state (obj_to_crtc (obj), state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); + cstate->event = event; +return 0 ; + } +default : +return -EINVAL ; + }
Hm, I think if we only want completion events on crtcs (which I agree on) then we should make the set_event interface more specific by passing struct drm_crtc * and only call it for crtcs.
Quoted 154 lines
drivers/gpu/drm/drm_atomic.c +76
-2}EXPORT_SYMBOL (drm_atomic_set_event);@@ -111,6 +130,7 @@ int drm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) {struct drm_atomic_state *a = state;int nplanes = dev->mode_config.num_total_plane; +int ncrtcs = dev->mode_config.num_crtc;int i, ret =0 ;for (i =0 ; i < nplanes; i++) {@@ -120,6 +140,13 @@ int drm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)break ; } } +for (i =0 ; i < ncrtcs; i++) { +if (a->crtcs[i]) { + ret =drm_atomic_check_crtc_state (a->crtcs[i], a->cstates[i]); +if (ret) +break ; + } + } a->acquire_ctx.frozen = true;@@ -203,6 +230,7 @@ static void commit_locks(struct drm_atomic_state *a, {struct drm_device *dev = a->dev;int nplanes = dev->mode_config.num_total_plane; +int ncrtcs = dev->mode_config.num_crtc;int i;for (i =0 ; i < nplanes; i++) {@@ -213,6 +241,14 @@ static void commit_locks(struct drm_atomic_state *a, } } +for (i =0 ; i < ncrtcs; i++) { +struct drm_crtc *crtc = a->crtcs[i]; +if (crtc) { + crtc->state->state =NULL ; +drm_crtc_destroy_state (crtc, a->cstates[i]); + } + } +/* and properly release them (clear in_atomic, remove from list): */ drm_modeset_drop_locks (&a->acquire_ctx);ww_acquire_fini (ww_ctx);@@ -223,8 +259,18 @@ static int atomic_commit(struct drm_atomic_state *a, struct ww_acquire_ctx *ww_ctx) {int nplanes = a->dev->mode_config.num_total_plane; +int ncrtcs = a->dev->mode_config.num_crtc;int i, ret =0 ; +for (i =0 ; i < ncrtcs; i++) { +struct drm_crtc *crtc = a->crtcs[i]; +if (crtc) { + ret =drm_atomic_commit_crtc_state (crtc, a->cstates[i]); +if (ret) +break ; + } + } +for (i =0 ; i < nplanes; i++) {struct drm_plane *plane = a->planes[i];if (plane) {@@ -403,6 +449,7 @@ static int commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) { struct drm_atomic_state *a = pstate->state; +struct drm_crtc_state *cstate =NULL ;struct drm_framebuffer *old_fb = plane->fb;struct drm_framebuffer *fb = pstate->fb;bool enabled = pstate->crtc && fb;@@ -425,8 +472,11 @@ commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) } }else {struct drm_crtc *crtc = pstate->crtc; + cstate =drm_atomic_get_crtc_state (crtc, pstate->state);if (pstate->update_plane || (pstate->new_fb && !can_flip (plane, pstate))) { +/* TODO pass event to update_plane().. */ +WARN_ON (cstate->event); ret = plane->funcs->update_plane(plane, crtc, pstate->fb, pstate->crtc_x, pstate->crtc_y, pstate->crtc_w, pstate->crtc_h,@@ -443,7 +493,7 @@ commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) } }else if (pstate->new_fb) { - ret = crtc->funcs->page_flip (crtc, fb,NULL , a->flags); + ret = crtc->funcs->page_flip (crtc, fb, cstate->event, a->flags);if (ret ==0 ) {/* * Warn if the driver hasn't properly updated the plane->fb @@ -473,9 +523,10 @@ commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate)* original code. */ swap_plane_state (plane, pstate->state); +if (cstate) + cstate->event =NULL ; } -if (fb)drm_framebuffer_unreference (fb);if (old_fb)@@ -484,8 +535,182 @@ commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate)return ret; } +int drm_atomic_crtc_set_property (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data) +{ +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); +} +EXPORT_SYMBOL (drm_atomic_crtc_set_property); + +static void init_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate,struct drm_atomic_state *state) +{ +/* snapshot current state: */ + *cstate = *crtc->state; + cstate->state = state; + +if (cstate->connector_ids) { +int sz = cstate->num_connector_ids *sizeof (cstate->connector_ids[0 ]); + cstate->connector_ids =kmemdup (cstate->connector_ids, sz,GFP_KERNEL ); + } + +/* this should never happen.. but make sure! */ +WARN_ON (cstate->event); + cstate->event =NULL ; +} + +struct drm_crtc_state * +drm_atomic_get_crtc_state (struct drm_crtc *crtc,struct drm_atomic_state *a) +{ +struct drm_crtc_state *cstate; +int ret; + + cstate = a->cstates[crtc->id]; + +if (!cstate) { + ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + cstate =drm_crtc_create_state (crtc);
drivers/gpu/drm/drm_atomic.c commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) · line 589
Quoted 10 lines
drivers/gpu/drm/drm_atomic.c +10
-0+if (!cstate) +return ERR_PTR (-ENOMEM ); +init_crtc_state (crtc, cstate, a); + a->crtcs[crtc->id] = crtc; + a->cstates[crtc->id] = cstate; + +/* we'll need it later, so make sure we have state +* for primary plane too: +*/ +drm_atomic_get_plane_state (crtc->primary, a);
I haven't figured out why. With primary planes I don't really see a need for this. If we need it to implement the legacy setcrtc interface, then that should be done there, not here.
Quoted 1,511 lines
drivers/gpu/drm/drm_atomic.c +122
-0+ } +return cstate; +} +EXPORT_SYMBOL (drm_atomic_get_crtc_state); + +static void +swap_crtc_state (struct drm_crtc *crtc,struct drm_atomic_state *a) +{ +struct drm_crtc_state *cstate = a->cstates[crtc->id]; +struct drm_device *dev = crtc->dev; +struct drm_pending_vblank_event *event = cstate->event; + +if (event) { +/* hrm, need to sort out a better way to send events for +* other-than-pageflip.. but modeset is not async, so: +*/ +unsigned long flags; +spin_lock_irqsave (&dev->event_lock, flags); +drm_send_vblank_event (dev, crtc->id, event); + cstate->event =NULL ; +spin_unlock_irqrestore (&dev->event_lock, flags); + } + +/* clear transient state (only valid during atomic update): */ + cstate->set_config = false; + cstate->connectors_change = false; + +swap (crtc->state, a->cstates[crtc->id]); + crtc->base.propvals = &crtc->state->propvals; +} + +static struct drm_connector **get_connector_set (struct drm_device *dev, +uint32_t *connector_ids,uint32_t num_connector_ids) +{ +struct drm_connector **connector_set =NULL ; +int i; + + connector_set =kmalloc (num_connector_ids * +sizeof (struct drm_connector *), +GFP_KERNEL ); +if (!connector_set) +return NULL ; + +for (i =0 ; i < num_connector_ids; i++) + connector_set[i] =drm_connector_find (dev, connector_ids[i]); + +return connector_set; +} + +static int set_config (struct drm_crtc *crtc,struct drm_crtc_state *cstate) +{ +struct drm_device *dev = crtc->dev; +struct drm_plane_state *pstate = +drm_atomic_get_plane_state (crtc->primary, cstate->state); +struct drm_framebuffer *fb = pstate->fb; +struct drm_connector **connector_set =get_connector_set (crtc->dev, + cstate->connector_ids, cstate->num_connector_ids); +struct drm_display_mode *mode =drm_crtc_get_mode (crtc, cstate); +struct drm_mode_set set = { + .crtc = crtc, + .x = pstate->src_x >>16 , + .y = pstate->src_y >>16 , + .mode = mode, + .num_connectors = cstate->num_connector_ids, + .connectors = connector_set, + .fb = fb, + }; +int ret; + +if (IS_ERR (mode)) { + ret =PTR_ERR (mode); +return ret; + } + +if (fb) +drm_framebuffer_reference (fb); + + ret =drm_mode_set_config_internal (&set); +if (!ret) { +swap_crtc_state (crtc, cstate->state); + pstate->new_fb = pstate->update_plane = false; + } + +if (fb) +drm_framebuffer_unreference (fb); + +kfree (connector_set); +if (mode) +drm_mode_destroy (dev, mode); +return ret; +} + +static int +commit_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +struct drm_plane_state *pstate = +drm_atomic_get_plane_state (crtc->primary, cstate->state); +int ret = -EINVAL ; + +if (cstate->set_config) +return set_config (crtc, cstate); + +if (!pstate->fb) { +/* disable */ +struct drm_mode_set set = { + .crtc = crtc, + .fb =NULL , + }; + + ret =drm_mode_set_config_internal (&set); +if (!ret) { +swap_crtc_state (crtc, cstate->state); + } + } + +return ret; +} +const struct drm_atomic_funcs drm_atomic_funcs = { .check_plane_state = drm_plane_check_state, .commit_plane_state = commit_plane_state, + + .check_crtc_state = drm_crtc_check_state, + .commit_crtc_state = commit_crtc_state, };EXPORT_SYMBOL (drm_atomic_funcs);drivers/gpu/drm/drm_crtc.c +384
-214@@ -689,10 +689,7 @@ EXPORT_SYMBOL(drm_framebuffer_cleanup);void drm_framebuffer_remove (struct drm_framebuffer *fb) {struct drm_device *dev = fb->dev; -struct drm_crtc *crtc;struct drm_plane *plane; -struct drm_mode_set set; -int ret;WARN_ON (!list_empty (&fb->filp_head));@@ -712,7 +709,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)* in this manner. */ if (atomic_read (&fb->refcount.refcount) >1 ) { -void *state; +struct drm_atomic_state *state; state = dev->driver->atomic_begin (dev,0 );if (IS_ERR (state)) {@@ -720,24 +717,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)return ; } -/* TODO once CRTC is converted to state/properties, we can push the -* locking down into drm_atomic_commit(), since that is where -* the actual changes take place.. -*/ -drm_modeset_lock_all (dev); -/* remove from any CRTC */ -list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) { -if (crtc->primary->fb == fb) { -/* should turn off the crtc */ -memset (&set,0 ,sizeof (struct drm_mode_set )); - set.crtc = crtc; - set.fb =NULL ; - ret =drm_mode_set_config_internal (&set); -if (ret) -DRM_ERROR ("failed to reset crtc %p when fb was deleted\n" , crtc); - } - } - +/* remove from any plane */ list_for_each_entry (plane, &dev->mode_config.plane_list, head) {if (plane->fb == fb)drm_plane_force_disable (plane, state);@@ -750,8 +730,6 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) dev->driver->atomic_commit (dev, state); dev->driver->atomic_end (dev, state); - -drm_modeset_unlock_all (dev); }drm_framebuffer_unreference (fb);@@ -782,9 +760,13 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,struct drm_mode_config *config = &dev->mode_config;int ret; +/* this is now required: */ +WARN_ON (!funcs->set_property); + crtc->dev = dev; crtc->funcs = funcs; - crtc->invert_dimensions = false; + crtc->state =drm_crtc_create_state (crtc); + crtc->state->invert_dimensions = false;drm_modeset_lock_all (dev);drm_modeset_lock_init (&crtc->mutex);@@ -796,14 +778,17 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, goto out; crtc->base.properties = &crtc->properties; - crtc->base.propvals = &crtc->propvals; + crtc->base.propvals = &crtc->state->propvals;list_add_tail (&crtc->head, &dev->mode_config.crtc_list); dev->mode_config.num_crtc++; crtc->primary = primary;if (primary) - primary->possible_crtcs =1 <<drm_crtc_index (crtc); + primary->possible_crtcs =1 << crtc->id; + +drm_object_attach_property (&crtc->base, config->prop_mode,0 ); +drm_object_attach_property (&crtc->base, config->prop_connector_ids,0 ); out:drm_modeset_unlock_all (dev);@@ -832,31 +817,245 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)drm_mode_object_put (dev, &crtc->base);list_del (&crtc->head); dev->mode_config.num_crtc--; + +drm_crtc_destroy_state (crtc, crtc->state); }EXPORT_SYMBOL (drm_crtc_cleanup); -/** -* drm_crtc_index - find the index of a registered CRTC -* @crtc: CRTC to find index for -* -* Given a registered CRTC, return the index of that CRTC within a DRM -* device's list of CRTCs. -*/ -unsigned int drm_crtc_index (struct drm_crtc *crtc) +/* get display-mode from user-mode */ +struct drm_display_mode *drm_crtc_get_mode (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) { -unsigned int index =0 ; -struct drm_crtc *tmp; +struct drm_display_mode *mode =NULL ; +if (cstate->mode_valid) { +struct drm_device *dev = crtc->dev; +int ret; -list_for_each_entry (tmp, &crtc->dev->mode_config.crtc_list, head) { -if (tmp == crtc) -return index; + mode =drm_mode_create (dev); +if (!mode) +return ERR_PTR (-ENOMEM ); + + ret =drm_crtc_convert_umode (mode, &cstate->mode); +if (ret) { +DRM_DEBUG_KMS ("Invalid mode\n" ); +drm_mode_destroy (dev, mode); +return ERR_PTR (ret); + } - index++; +drm_mode_set_crtcinfo (mode,CRTC_INTERLACE_HALVE_V ); } +return mode; +} -BUG (); +static int connector_idx (struct drm_crtc_state *state, +uint32_t connector_id) +{ +int i; +for (i =0 ; i < state->num_connector_ids; i++) +if (state->connector_ids[i] == connector_id) +return i; +return -1 ; +} + +static int remove_connector (struct drm_crtc *ocrtc, +struct drm_crtc_state *ostate,struct drm_atomic_state *state, +int idx) +{ +struct drm_mode_config *config = &ocrtc->dev->mode_config; +uint32_t *new_connector_ids; +int a, b; + +/* before deletion point: */ + a = idx *sizeof (ostate->connector_ids[0 ]); + +/* after deletion point: */ + b = (ostate->num_connector_ids -1 - idx) * +sizeof (ostate->connector_ids[0 ]); + + new_connector_ids =kmalloc (a+b,GFP_KERNEL ); +if (!new_connector_ids) +return -ENOMEM ; + +memcpy (new_connector_ids, ostate->connector_ids, a); +memcpy (&new_connector_ids[idx], + &ostate->connector_ids[idx +1 ], b); + +return drm_mode_crtc_set_obj_prop (ocrtc, state, + config->prop_connector_ids, a + b, + new_connector_ids); } -EXPORT_SYMBOL (drm_crtc_index); + +static int check_connectors (struct drm_crtc *crtc, +struct drm_atomic_state *state,bool fix, +uint32_t *connector_ids,uint32_t num_connector_ids) +{ +struct drm_mode_config *config = &crtc->dev->mode_config; +struct drm_crtc *ocrtc;/* other connector */ + +list_for_each_entry (ocrtc, &config->crtc_list, head) { +struct drm_crtc_state *ostate;/* other state */ +unsigned i; + +if (ocrtc == crtc) +continue ; + + ostate =drm_atomic_get_crtc_state (crtc, state); +if (IS_ERR (ostate)) +return PTR_ERR (ostate); + +for (i =0 ; i < num_connector_ids; i++) { +struct drm_connector *connector; +uint32_t cid = connector_ids[i]; +int idx; + +retry: + idx =connector_idx (ostate, cid); +if (idx <0 ) +continue ; + +if (fix) { +int ret =remove_connector (ocrtc, + ostate, state, idx); +if (ret) +return ret; + goto retry; + } + + connector =drm_connector_find (crtc->dev, cid); +DRM_DEBUG_KMS ("[CONNECTOR:%d:%s] already in use\n" , + connector->base.id, +drm_get_connector_name (connector)); +return -EINVAL ; + } + } + +return 0 ; +} + +int drm_crtc_check_state (struct drm_crtc *crtc, +struct drm_crtc_state *state) +{ +struct drm_plane *primary = crtc->primary; +struct drm_plane_state *pstate = +drm_atomic_get_plane_state (primary, state->state); +struct drm_framebuffer *fb = pstate->fb; +int hdisplay, vdisplay; +struct drm_display_mode *mode =drm_crtc_get_mode (crtc, state); +unsigned x, y; + +if (IS_ERR (mode)) +return PTR_ERR (mode); + +/* disabling the crtc is allowed: */ +if (!(fb && state->mode_valid)) +return 0 ; + + hdisplay = state->mode.hdisplay; + vdisplay = state->mode.vdisplay; + +if (mode &&drm_mode_is_stereo (mode)) { +struct drm_display_mode adjusted = *mode; + +drm_mode_set_crtcinfo (&adjusted,CRTC_STEREO_DOUBLE ); + hdisplay = adjusted.crtc_hdisplay; + vdisplay = adjusted.crtc_vdisplay; + } + +if (state->invert_dimensions) +swap (hdisplay, vdisplay); + + x = pstate->src_x >>16 ; + y = pstate->src_y >>16 ; + +if (hdisplay > fb->width || + vdisplay > fb->height || + x > fb->width - hdisplay || + y > fb->height - vdisplay) { +DRM_DEBUG_KMS ("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n" , + fb->width, fb->height, hdisplay, vdisplay, + x, y, state->invert_dimensions ?" (inverted)" :"" ); +return -ENOSPC ; + } + +if (crtc->enabled && !state->set_config) { +if (primary->state->fb->pixel_format != fb->pixel_format) { +DRM_DEBUG_KMS ("Page flip is not allowed to " +"change frame buffer format.\n" ); +return -EINVAL ; + } + } + +if (state->num_connector_ids ==0 ) { +DRM_DEBUG_KMS ("Count connectors is 0 but mode set\n" ); +return -EINVAL ; + } + +if (state->connectors_change) { +int ret =check_connectors (crtc, state->state, false, + state->connector_ids, state->num_connector_ids); +if (ret) +return ret; + } + +if (mode) +drm_mode_destroy (crtc->dev, mode); + +return 0 ; +} +EXPORT_SYMBOL (drm_crtc_check_state); + +void drm_crtc_commit_state (struct drm_crtc *crtc, +struct drm_crtc_state *state) +{ + crtc->state = state; + crtc->base.propvals = &state->propvals; +} +EXPORT_SYMBOL (drm_crtc_commit_state); + +int drm_crtc_set_property (struct drm_crtc *crtc, +struct drm_crtc_state *state, +struct drm_property *property, +uint64_t value,void *blob_data) +{ +struct drm_device *dev = crtc->dev; +struct drm_mode_config *config = &dev->mode_config; + +/* grab primary plane state now, to ensure locks are held, etc. */ +drm_atomic_get_plane_state (crtc->primary, state->state); + +drm_object_property_set_value (&crtc->base, + &state->propvals, property, value, blob_data); + +if (property == config->prop_mode) { +if (!blob_data) { +memset (&state->mode,0 ,sizeof (state->mode)); + state->mode_valid = false; + }else { +/* check size: */ +if (value <sizeof (struct drm_mode_modeinfo )) +return -EINVAL ; + state->mode = *(struct drm_mode_modeinfo *)blob_data; + state->mode_valid = true; + } + state->set_config = true; + }else if (property == config->prop_connector_ids) { +/* if connector-id's changing, we need to have all the locks: */ +struct drm_atomic_state *a = state->state; +int ret =drm_modeset_lock_all_crtcs (crtc->dev, &a->acquire_ctx); +if (ret) +return ret; + state->connectors_change = true; + state->num_connector_ids = value /sizeof (state->connector_ids[0 ]); +kfree (state->connector_ids); + state->connector_ids = blob_data; + state->set_config = true; + }else { +return -EINVAL ; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_crtc_set_property);/* * drm_mode_remove - remove and free a mode @@ -1239,6 +1438,10 @@ int drm_plane_check_state(struct drm_plane *plane,if (!fb)return 0 ; +/* we'll need this later during commit: */ +if (state->crtc) +drm_atomic_get_crtc_state (state->crtc, state->state); + fb_width = fb->width <<16 ; fb_height = fb->height <<16 ;@@ -1465,6 +1668,16 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev)return -ENOMEM ; dev->mode_config.prop_crtc_id = prop; + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB ,"CONNECTOR_IDS" ,0 ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_connector_ids = prop; + + prop =drm_property_create (dev,DRM_MODE_PROP_BLOB ,"MODE" ,0 ); +if (!prop) +return -ENOMEM ; + dev->mode_config.prop_mode = prop; +return 0 ; }@@ -1754,7 +1967,7 @@ static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,* Returns: * Zero on success, errno on failure. */ -static int drm_crtc_convert_umode (struct drm_display_mode *out, +int drm_crtc_convert_umode (struct drm_display_mode *out,const struct drm_mode_modeinfo *in) {if (in->clock >INT_MAX || in->vrefresh >INT_MAX )@@ -2001,8 +2214,8 @@ int drm_mode_getcrtc(struct drm_device *dev, goto out; } - crtc_resp->x = crtc->x; - crtc_resp->y = crtc->y; + crtc_resp->x = crtc->primary->state->src_x >>16 ; + crtc_resp->y = crtc->primary->state->src_y >>16 ; crtc_resp->gamma_size = crtc->gamma_size;if (crtc->primary->fb) crtc_resp->fb_id = crtc->primary->fb->base.id;@@ -2495,7 +2708,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, vdisplay = adjusted.crtc_vdisplay; } -if (crtc->invert_dimensions) +if (crtc->state->invert_dimensions)swap (hdisplay, vdisplay); if (hdisplay > fb->width ||@@ -2504,7 +2717,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, y > fb->height - vdisplay) {DRM_DEBUG_KMS ("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n" , fb->width, fb->height, hdisplay, vdisplay, x, y, - crtc->invert_dimensions ?" (inverted)" :"" ); + crtc->state->invert_dimensions ?" (inverted)" :"" );return -ENOSPC ; }@@ -2531,22 +2744,15 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,struct drm_mode_config *config = &dev->mode_config;struct drm_mode_crtc *crtc_req = data;struct drm_crtc *crtc; -struct drm_connector **connector_set =NULL , *connector; -struct drm_framebuffer *fb =NULL ; -struct drm_display_mode *mode =NULL ; -struct drm_mode_set set; -uint32_t __user *set_connectors_ptr; +uint32_t fb_id =-1 ; +uint32_t *connector_ids =NULL ; +struct drm_atomic_state *state =NULL ;int ret;int i;if (!drm_core_check_feature (dev,DRIVER_MODESET ))return -EINVAL ; -/* For some reason crtc x/y offsets are signed internally. */ -if (crtc_req->x >INT_MAX || crtc_req->y >INT_MAX ) -return -ERANGE ; - -drm_modeset_lock_all (dev); crtc =drm_crtc_find (dev, crtc_req->crtc_id);if (!crtc) {DRM_DEBUG_KMS ("Unknown CRTC ID %d\n" , crtc_req->crtc_id);@@ -2564,55 +2770,15 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, ret = -EINVAL ; goto out; } - fb = crtc->primary->fb; -/* Make refcounting symmetric with the lookup path. */ -drm_framebuffer_reference (fb); + fb_id = crtc->primary->fb->base.id; }else { - fb =drm_framebuffer_lookup (dev, crtc_req->fb_id); -if (!fb) { -DRM_DEBUG_KMS ("Unknown FB ID%d\n" , - crtc_req->fb_id); - ret = -ENOENT ; - goto out; - } - } - - mode =drm_mode_create (dev); -if (!mode) { - ret = -ENOMEM ; - goto out; + fb_id = crtc_req->fb_id; } - - ret =drm_crtc_convert_umode (mode, &crtc_req->mode); -if (ret) { -DRM_DEBUG_KMS ("Invalid mode\n" ); - goto out; - } - -drm_mode_set_crtcinfo (mode,CRTC_INTERLACE_HALVE_V ); - - ret =drm_crtc_check_viewport (crtc, crtc_req->x, crtc_req->y, - mode, fb); -if (ret) - goto out; - - } - -if (crtc_req->count_connectors ==0 && mode) { -DRM_DEBUG_KMS ("Count connectors is 0 but mode set\n" ); - ret = -EINVAL ; - goto out; - } - -if (crtc_req->count_connectors >0 && (!mode || !fb)) { -DRM_DEBUG_KMS ("Count connectors is %d but no mode or fb set\n" , - crtc_req->count_connectors); - ret = -EINVAL ; - goto out; }if (crtc_req->count_connectors >0 ) { -u32 out_id; +uint32_t __user *set_connectors_ptr = + (uint32_t __user *)(unsigned long )crtc_req->set_connectors_ptr;/* Avoid unbounded kernel memory allocation */ if (crtc_req->count_connectors > config->num_connector) {@@ -2620,52 +2786,65 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, goto out; } - connector_set =kmalloc (crtc_req->count_connectors * -sizeof (struct drm_connector *), + connector_ids =kmalloc (crtc_req->count_connectors * +sizeof (connector_ids[0 ]),GFP_KERNEL ); -if (!connector_set) { +if (!connector_ids) { ret = -ENOMEM ; goto out; }for (i =0 ; i < crtc_req->count_connectors; i++) { - set_connectors_ptr = (uint32_t __user *)(unsigned long )crtc_req->set_connectors_ptr; +u32 out_id; +if (get_user (out_id, &set_connectors_ptr[i])) { ret = -EFAULT ; goto out; } - - connector =drm_connector_find (dev, out_id); -if (!connector) { -DRM_DEBUG_KMS ("Connector id %d unknown\n" , - out_id); - ret = -ENOENT ; - goto out; - } -DRM_DEBUG_KMS ("[CONNECTOR:%d:%s]\n" , - connector->base.id, -drm_get_connector_name (connector)); - - connector_set[i] = connector; + connector_ids[i] = out_id; } } - set.crtc = crtc; - set.x = crtc_req->x; - set.y = crtc_req->y; - set.mode = mode; - set.connectors = connector_set; - set.num_connectors = crtc_req->count_connectors; - set.fb = fb; - ret =drm_mode_set_config_internal (&set); +retry: + state = dev->driver->atomic_begin (dev,0 ); +if (IS_ERR (state)) +return PTR_ERR (state); -out: -if (fb) -drm_framebuffer_unreference (fb); +/* If connectors change, we need to check if we need to steal one +* from another CRTC.. setcrtc makes this implicit, but atomic +* treats it as an error so we need to handle here: +*/ + ret =check_connectors (crtc, state, true, + connector_ids, crtc_req->count_connectors); +if (ret) + goto out; -kfree (connector_set); -drm_mode_destroy (dev, mode); -drm_modeset_unlock_all (dev); + ret = +drm_mode_crtc_set_obj_prop (crtc, state, + config->prop_mode,sizeof (crtc_req->mode), &crtc_req->mode) || +drm_mode_crtc_set_obj_prop (crtc, state, + config->prop_connector_ids, + crtc_req->count_connectors *sizeof (connector_ids[0 ]), + connector_ids) || +drm_mode_plane_set_obj_prop (crtc->primary, state, + config->prop_crtc_id, crtc->base.id,NULL ) || +drm_mode_plane_set_obj_prop (crtc->primary, state, + config->prop_fb_id, fb_id,NULL ) || +drm_mode_plane_set_obj_prop (crtc->primary, state, + config->prop_src_x, crtc_req->x <<16 ,NULL ) || +drm_mode_plane_set_obj_prop (crtc->primary, state, + config->prop_src_y, crtc_req->y <<16 ,NULL ) || + dev->driver->atomic_check (dev, state); +if (ret) + goto out; + + ret = dev->driver->atomic_commit (dev, state); + +out: +if (state) + dev->driver->atomic_end (dev, state); +if (ret == -EDEADLK ) + goto retry;return ret; }@@ -4028,9 +4207,6 @@ int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc,if (crtc->funcs->set_property) ret = crtc->funcs->set_property (crtc, state, property, value, blob_data); -if (!ret) -drm_object_property_set_value (&crtc->base, &crtc->propvals, - property, value,NULL );return ret; }@@ -4424,6 +4600,51 @@ out:return ret; } +static struct drm_pending_vblank_event *create_vblank_event ( +struct drm_device *dev,struct drm_file *file_priv,uint64_t user_data) +{ +struct drm_pending_vblank_event *e =NULL ; +unsigned long flags; + +spin_lock_irqsave (&dev->event_lock, flags); +if (file_priv->event_space <sizeof e->event) { +spin_unlock_irqrestore (&dev->event_lock, flags); + goto out; + } + file_priv->event_space -=sizeof e->event; +spin_unlock_irqrestore (&dev->event_lock, flags); + + e =kzalloc (sizeof *e,GFP_KERNEL ); +if (e ==NULL ) { +spin_lock_irqsave (&dev->event_lock, flags); + file_priv->event_space +=sizeof e->event; +spin_unlock_irqrestore (&dev->event_lock, flags); + goto out; + } + + e->event.base.type =DRM_EVENT_FLIP_COMPLETE ; + e->event.base.length =sizeof e->event; + e->event.user_data = user_data; + e->base.event = &e->event.base; + e->base.file_priv = file_priv; + e->base.destroy = + (void (*) (struct drm_pending_event *)) kfree; + +out: +return e; +} + +static void destroy_vblank_event (struct drm_device *dev, +struct drm_file *file_priv,struct drm_pending_vblank_event *e) +{ +unsigned long flags; + +spin_lock_irqsave (&dev->event_lock, flags); + file_priv->event_space +=sizeof e->event; +spin_unlock_irqrestore (&dev->event_lock, flags); +kfree (e); +} +/** * drm_mode_page_flip_ioctl - schedule an asynchronous fb update * @dev: DRM device @@ -4446,10 +4667,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_mode_crtc_page_flip *page_flip = data; +struct drm_mode_config *config = &dev->mode_config;struct drm_crtc *crtc; -struct drm_framebuffer *fb =NULL , *old_fb =NULL ;struct drm_pending_vblank_event *e =NULL ; -unsigned long flags; +struct drm_atomic_state *state;int ret = -EINVAL ; if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||@@ -4463,92 +4684,41 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,if (!crtc)return -ENOENT ; -drm_modeset_lock (&crtc->mutex,NULL ); -if (crtc->primary->fb ==NULL ) { -/* The framebuffer is currently unbound, presumably -* due to a hotplug event, that userspace has not -* yet discovered. -*/ - ret = -EBUSY ; - goto out; - } - -if (crtc->funcs->page_flip ==NULL ) - goto out; - - fb =drm_framebuffer_lookup (dev, page_flip->fb_id); -if (!fb) { - ret = -ENOENT ; - goto out; - } - - ret =drm_crtc_check_viewport (crtc, crtc->x, crtc->y, &crtc->mode, fb); -if (ret) - goto out; - -if (crtc->primary->fb->pixel_format != fb->pixel_format) { -DRM_DEBUG_KMS ("Page flip is not allowed to change frame buffer format.\n" ); - ret = -EINVAL ; - goto out; - } +retry: + state = dev->driver->atomic_begin (dev, + page_flip->flags |DRM_MODE_ATOMIC_NONBLOCK ); +if (IS_ERR (state)) +return PTR_ERR (state);if (page_flip->flags &DRM_MODE_PAGE_FLIP_EVENT ) { - ret = -ENOMEM ; -spin_lock_irqsave (&dev->event_lock, flags); -if (file_priv->event_space <sizeof e->event) { -spin_unlock_irqrestore (&dev->event_lock, flags); + e =create_vblank_event (dev, file_priv, page_flip->user_data); +if (!e) { + ret = -ENOMEM ; goto out; } - file_priv->event_space -=sizeof e->event; -spin_unlock_irqrestore (&dev->event_lock, flags); - - e =kzalloc (sizeof *e,GFP_KERNEL ); -if (e ==NULL ) { -spin_lock_irqsave (&dev->event_lock, flags); - file_priv->event_space +=sizeof e->event; -spin_unlock_irqrestore (&dev->event_lock, flags); + ret = dev->driver->atomic_set_event (dev, state, &crtc->base, e); +if (ret) { goto out; } - - e->event.base.type =DRM_EVENT_FLIP_COMPLETE ; - e->event.base.length =sizeof e->event; - e->event.user_data = page_flip->user_data; - e->base.event = &e->event.base; - e->base.file_priv = file_priv; - e->base.destroy = - (void (*) (struct drm_pending_event *)) kfree; } - old_fb = crtc->primary->fb; - ret = crtc->funcs->page_flip (crtc, fb, e, page_flip->flags); -if (ret) { -if (page_flip->flags &DRM_MODE_PAGE_FLIP_EVENT ) { -spin_lock_irqsave (&dev->event_lock, flags); - file_priv->event_space +=sizeof e->event; -spin_unlock_irqrestore (&dev->event_lock, flags); -kfree (e); - } -/* Keep the old fb, don't unref it. */ - old_fb =NULL ; - }else { -/* -* Warn if the driver hasn't properly updated the crtc->fb -* field to reflect that the new framebuffer is now used. -* Failing to do so will screw with the reference counting -* on framebuffers. -*/ -WARN_ON (crtc->primary->fb != fb); -/* Unref only the old framebuffer. */ - fb =NULL ; - } + ret =drm_mode_plane_set_obj_prop (crtc->primary, state, + config->prop_fb_id, page_flip->fb_id,NULL ); +if (ret) + goto out; -out: -if (fb) -drm_framebuffer_unreference (fb); -if (old_fb) -drm_framebuffer_unreference (old_fb); -drm_modeset_unlock (&crtc->mutex); + ret = dev->driver->atomic_check (dev, state); +if (ret) + goto out; + + ret = dev->driver->atomic_commit (dev, state); +out: +if (ret && e) +destroy_vblank_event (dev, file_priv, e); + dev->driver->atomic_end (dev, state); +if (ret == -EDEADLK ) + goto retry;return ret; }drivers/gpu/drm/drm_fb_helper.c +1
-1@@ -286,7 +286,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;bool error = false; -void *state; +struct drm_atomic_state *state;int i;drm_warn_on_modeset_not_all_locked (dev);drivers/gpu/drm/exynos/exynos_drm_crtc.c +6
-1@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "exynos_drm_crtc.h" #include "exynos_drm_drv.h" @@ -289,6 +290,10 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,struct drm_device *dev = crtc->dev;struct exynos_drm_private *dev_priv = dev->dev_private;struct exynos_drm_crtc *exynos_crtc =to_exynos_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == dev_priv->crtc_mode_property) {enum exynos_crtc_mode mode = val;@@ -313,7 +318,7 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,return 0 ; } -return -EINVAL ; +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }static struct drm_crtc_funcs exynos_crtc_funcs = {drivers/gpu/drm/gma500/cdv_intel_display.c +1
-0@@ -989,6 +989,7 @@ const struct drm_crtc_funcs cdv_intel_crtc_funcs = { .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, .set_config = gma_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = gma_crtc_destroy, };drivers/gpu/drm/gma500/psb_intel_display.c +1
-0@@ -444,6 +444,7 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = { .cursor_move = gma_crtc_cursor_move, .gamma_set = gma_crtc_gamma_set, .set_config = gma_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = gma_crtc_destroy, };drivers/gpu/drm/i915/intel_display.c +1
-0@@ -10430,6 +10430,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .cursor_move = intel_crtc_cursor_move, .gamma_set = intel_crtc_gamma_set, .set_config = intel_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, };drivers/gpu/drm/mgag200/mgag200_mode.c +1
-0@@ -1296,6 +1296,7 @@ static const struct drm_crtc_funcs mga_crtc_funcs = { .cursor_move = mga_crtc_cursor_move, .gamma_set = mga_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = mga_crtc_destroy, };drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +4
-2@@ -471,8 +471,10 @@ static int mdp4_crtc_set_property(struct drm_crtc *crtc, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_crtc_state *cstate = drm_atomic_get_crtc_state(crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); }#define CURSOR_WIDTH 64drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +4
-2@@ -389,8 +389,10 @@ static int mdp5_crtc_set_property(struct drm_crtc *crtc, struct drm_atomic_state *state, struct drm_property *property, uint64_t val, void *blob_data) { - // XXX - return -EINVAL; + struct drm_crtc_state *cstate = drm_atomic_get_crtc_state(crtc, state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate); +return drm_crtc_set_property (crtc, cstate, property, val, blob_data); } static const struct drm_crtc_funcs mdp5_crtc_funcs = {drivers/gpu/drm/nouveau/dispnv04/crtc.c +1
-0@@ -1086,6 +1086,7 @@ static const struct drm_crtc_funcs nv04_crtc_funcs = { .cursor_move = nv04_crtc_cursor_move, .gamma_set = nv_crtc_gamma_set, .set_config = nouveau_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = nouveau_crtc_page_flip, .destroy = nv_crtc_destroy, };drivers/gpu/drm/nouveau/nv50_display.c +1
-0@@ -1329,6 +1329,7 @@ static const struct drm_crtc_funcs nv50_crtc_func = { .cursor_move = nv50_crtc_cursor_move, .gamma_set = nv50_crtc_gamma_set, .set_config = nouveau_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = nv50_crtc_destroy, .page_flip = nouveau_crtc_page_flip, };drivers/gpu/drm/omapdrm/omap_crtc.c +10
-2@@ -387,14 +387,22 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, {struct omap_crtc *omap_crtc =to_omap_crtc (crtc);struct omap_drm_private *priv = crtc->dev->dev_private; +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state); +int ret; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->rotation_prop) { - crtc->invert_dimensions = + cstate->invert_dimensions = !!(val & ((1LL <<DRM_ROTATE_90 ) | (1LL <<DRM_ROTATE_270 ))); } -return omap_plane_set_property (omap_crtc->plane, state, + ret =omap_plane_set_property (omap_crtc->plane, state, property, val, blob_data); +if (ret) + ret =drm_crtc_set_property (crtc, cstate, property, val, blob_data); +return ret; }static const struct drm_crtc_funcs omap_crtc_funcs = {drivers/gpu/drm/omapdrm/omap_drv.c +1
-1@@ -579,7 +579,7 @@ static void dev_lastclose(struct drm_device *dev)*/ for (i =0 ; i < priv->num_crtcs; i++) {drm_object_property_set_value (&priv->crtcs[i]->base, - &priv->crtcs[i]->propvals, + &priv->crtcs[i]->state->propvals, priv->rotation_prop,0 ,NULL ); }drivers/gpu/drm/qxl/qxl_display.c +2
-0@@ -29,6 +29,7 @@#include "qxl_drv.h" #include "qxl_object.h" #include "drm_crtc_helper.h" +#include "drm_atomic.h" static bool qxl_head_enabled (struct qxl_head *head) {@@ -373,6 +374,7 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { .cursor_set2 = qxl_crtc_cursor_set2, .cursor_move = qxl_crtc_cursor_move, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = qxl_crtc_destroy, };drivers/gpu/drm/radeon/radeon_display.c +2
-0@@ -32,6 +32,7 @@#include <linux/pm_runtime.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_edid.h> #include <linux/gcd.h> @@ -546,6 +547,7 @@ static const struct drm_crtc_funcs radeon_crtc_funcs = { .cursor_move = radeon_crtc_cursor_move, .gamma_set = radeon_crtc_gamma_set, .set_config = radeon_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = radeon_crtc_destroy, .page_flip = radeon_crtc_page_flip, };drivers/gpu/drm/rcar-du/rcar_du_crtc.c +2
-0@@ -17,6 +17,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -527,6 +528,7 @@ static int rcar_du_crtc_page_flip(struct drm_crtc *crtc,static const struct drm_crtc_funcs crtc_funcs = { .destroy = drm_crtc_cleanup, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = rcar_du_crtc_page_flip, };drivers/gpu/drm/shmobile/shmob_drm_crtc.c +2
-0@@ -17,6 +17,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -506,6 +507,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,static const struct drm_crtc_funcs crtc_funcs = { .destroy = drm_crtc_cleanup, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = shmob_drm_crtc_page_flip, };drivers/gpu/drm/tilcdc/tilcdc_crtc.c +1
-0@@ -411,6 +411,7 @@ static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,static const struct drm_crtc_funcs tilcdc_crtc_funcs = { .destroy = tilcdc_crtc_destroy, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = tilcdc_crtc_page_flip, };drivers/gpu/drm/udl/udl_modeset.c +2
-0@@ -14,6 +14,7 @@#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "udl_drv.h" /* @@ -383,6 +384,7 @@ static struct drm_crtc_helper_funcs udl_helper_funcs = {static const struct drm_crtc_funcs udl_crtc_funcs = { .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = udl_crtc_destroy, };drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +1
-0@@ -300,6 +300,7 @@ static struct drm_crtc_funcs vmw_legacy_crtc_funcs = { .cursor_move = vmw_du_crtc_cursor_move, .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_ldu_crtc_destroy, + .set_property = drm_atomic_crtc_set_property, .set_config = vmw_ldu_crtc_set_config, };drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +1
-0@@ -397,6 +397,7 @@ static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_sou_crtc_destroy, .set_config = vmw_sou_crtc_set_config, + .set_property = drm_atomic_crtc_set_property, .page_flip = vmw_du_page_flip, };include/drm/drm_atomic.h +29
-0@@ -70,6 +70,9 @@struct drm_atomic_funcs {int (*check_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate);int (*commit_plane_state)(struct drm_plane *plane,struct drm_plane_state *pstate); + +int (*check_crtc_state)(struct drm_crtc *crtc,struct drm_crtc_state *cstate); +int (*commit_crtc_state)(struct drm_crtc *crtc,struct drm_crtc_state *cstate); };const extern struct drm_atomic_funcs drm_atomic_funcs;@@ -109,6 +112,30 @@ drm_atomic_commit_plane_state(struct drm_plane *plane,return funcs->commit_plane_state (plane, pstate); } +int drm_atomic_crtc_set_property (struct drm_crtc *crtc, +struct drm_atomic_state *state,struct drm_property *property, +uint64_t val,void *blob_data); +struct drm_crtc_state *drm_atomic_get_crtc_state (struct drm_crtc *crtc, +struct drm_atomic_state *state); + +static inline int +drm_atomic_check_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +const struct drm_atomic_funcs *funcs = + crtc->dev->driver->atomic_funcs; +return funcs->check_crtc_state (crtc, cstate); +} + +static inline int +drm_atomic_commit_crtc_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +const struct drm_atomic_funcs *funcs = + crtc->dev->driver->atomic_funcs; +return funcs->commit_crtc_state (crtc, cstate); +} +/** * struct drm_atomic_state - the state object used by atomic helpers */ @@ -118,6 +145,8 @@ struct drm_atomic_state {uint32_t flags;struct drm_plane **planes;struct drm_plane_state **pstates; +struct drm_crtc **crtcs; +struct drm_crtc_state **cstates;bool committed;bool checked;/* just for debugging */ include/drm/drm_crtc.h +87
-16@@ -284,6 +284,10 @@ struct drm_crtc_funcs {struct drm_pending_vblank_event *event, uint32_t flags); +struct drm_crtc_state *(*create_state)(struct drm_crtc *crtc); +void (*destroy_state)(struct drm_crtc *crtc, +struct drm_crtc_state *cstate); + int (*set_property)(struct drm_crtc *crtc, struct drm_atomic_state *state, struct drm_property *property, uint64_t val,@@ -291,21 +295,52 @@ struct drm_crtc_funcs { };/** +* drm_crtc_state - mutable crtc state +* @invert_dimensions: for purposes of error checking crtc vs fb sizes, +* invert the width/height of the crtc. This is used if the driver +* is performing 90 or 270 degree rotated scanout +* @mode_valid: a valid mode has been set +* @set_config: needs modeset (crtc->set_config()) +* @connectors_change: the connector-ids array has changed +* @num_connector_ids: the number of connector-ids +* @connector_ids: array of connector ids +* @mode: current mode timings +* @event: pending pageflip event +* @propvals: property values +* @state: current global/toplevel state object (for atomic) while an +* update is in progress, NULL otherwise. +*/ +struct drm_crtc_state { +bool invert_dimensions :1 ; +bool mode_valid :1 ; + +/* transient state, only valid during atomic operation: */ +bool set_config :1 ; +bool connectors_change :1 ; + +uint8_t num_connector_ids; +uint32_t *connector_ids; +struct drm_mode_modeinfo mode; + +struct drm_pending_vblank_event *event; + +struct drm_object_property_values propvals; + +struct drm_atomic_state *state; +}; + +/** * drm_crtc - central CRTC control structure * @dev: parent DRM device * @head: list management +* @id: CRTC number, 0..n * @mutex: per-CRTC locking * @base: base KMS object for ID tracking etc. * @primary: primary plane for this CRTC * @cursor: cursor plane for this CRTC +* @state: the mutable state * @enabled: is this CRTC enabled? -* @mode: current mode timings * @hwmode: mode timings as programmed to hw regs -* @invert_dimensions: for purposes of error checking crtc vs fb sizes, -* invert the width/height of the crtc. This is used if the driver -* is performing 90 or 270 degree rotated scanout -* @x: x position on screen -* @y: y position on screen * @funcs: CRTC control functions * @gamma_size: size of gamma ramp * @gamma_store: gamma ramp values @@ -322,6 +357,8 @@ struct drm_crtc {struct drm_device *dev;struct list_head head; +int id; +/** * crtc mutex * @@ -337,23 +374,19 @@ struct drm_crtc {struct drm_plane *primary;struct drm_plane *cursor; +struct drm_crtc_state *state; +/* Temporary tracking of the old fb while a modeset is ongoing. Used * by drm_mode_set_config_internal to implement correct refcounting. */ struct drm_framebuffer *old_fb;bool enabled; -/* Requested mode from modesetting. */ -struct drm_display_mode mode; -/* Programmed mode in hw, after adjustments for encoders, * crtc, panel scaling etc. Needed for timestamping etc. */ struct drm_display_mode hwmode; -bool invert_dimensions; - -int x, y;const struct drm_crtc_funcs *funcs;/* CRTC gamma size for reporting to userspace */ @@ -367,9 +400,15 @@ struct drm_crtc {void *helper_private;struct drm_object_properties properties; -struct drm_object_property_values propvals; -}; +/* These are (temporary) duplicate information from what is in the +* drm_crtc_state struct.. keeping duplicate copy here makes the +* switch to atomic far less intrusive. Once all the drivers and +* the crtc/fb helpers are updated, then we can remove these: +*/ +int x, y; +struct drm_display_mode mode; +};/** * drm_connector_funcs - control connectors on a given device @@ -875,6 +914,8 @@ struct drm_mode_config {struct drm_property *prop_crtc_h;struct drm_property *prop_fb_id;struct drm_property *prop_crtc_id; +struct drm_property *prop_connector_ids; +struct drm_property *prop_mode;struct drm_property *edid_property;struct drm_property *dpms_property;struct drm_property *plane_type_property;@@ -935,7 +976,8 @@ extern int drm_crtc_init(struct drm_device *dev,struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs);extern void drm_crtc_cleanup (struct drm_crtc *crtc); -extern unsigned int drm_crtc_index (struct drm_crtc *crtc); +struct drm_display_mode *drm_crtc_get_mode (struct drm_crtc *crtc, +struct drm_crtc_state *cstate);/** * drm_crtc_mask - find the mask of a registered CRTC @@ -946,9 +988,18 @@ extern unsigned int drm_crtc_index(struct drm_crtc *crtc);*/ static inline uint32_t drm_crtc_mask (struct drm_crtc *crtc) { -return 1 <<drm_crtc_index (crtc); +return 1 << crtc->id; } +extern int drm_crtc_check_state (struct drm_crtc *crtc, +struct drm_crtc_state *state); +extern void drm_crtc_commit_state (struct drm_crtc *crtc, +struct drm_crtc_state *state); +extern int drm_crtc_set_property (struct drm_crtc *crtc, +struct drm_crtc_state *state, +struct drm_property *property, +uint64_t value,void *blob_data); +extern void drm_connector_ida_init (void );extern void drm_connector_ida_destroy (void ); extern int drm_connector_init(struct drm_device *dev,@@ -1024,6 +1075,7 @@ extern const char *drm_get_tv_select_name(int val);extern void drm_fb_release (struct drm_file *file_priv);extern int drm_mode_group_init_legacy_group (struct drm_device *dev,struct drm_mode_group *group);extern void drm_mode_group_destroy (struct drm_mode_group *group); +extern int drm_crtc_convert_umode (struct drm_display_mode *out,const struct drm_mode_modeinfo *in);extern bool drm_probe_ddc (struct i2c_adapter *adapter);extern struct edid *drm_get_edid (struct drm_connector *connector,struct i2c_adapter *adapter);@@ -1251,6 +1303,25 @@ drm_property_blob_find(struct drm_device *dev, uint32_t id)return mo ?obj_to_blob (mo) :NULL ; } +static inline struct drm_crtc_state * +drm_crtc_create_state (struct drm_crtc *crtc) +{ +if (crtc->funcs->create_state) +return crtc->funcs->create_state (crtc); +return kzalloc (sizeof (struct drm_crtc_state ),GFP_KERNEL ); +} + +static inline void +drm_crtc_destroy_state (struct drm_crtc *crtc, +struct drm_crtc_state *cstate) +{ +kfree (cstate->connector_ids); +if (crtc->funcs->destroy_state) + crtc->funcs->destroy_state (crtc, cstate); +else +kfree (cstate); +} +static inline struct drm_plane_state *drm_plane_create_state (struct drm_plane *plane) {Signature · 1 line
1.9.0
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 20 lines · Daniel Vetter
Quoted 20 lines
drivers/gpu/drm/drm_atomic.c +20
-0+struct drm_crtc_state * +drm_atomic_get_crtc_state (struct drm_crtc *crtc,struct drm_atomic_state *a) +{ +struct drm_crtc_state *cstate; +int ret; + + cstate = a->cstates[crtc->id]; + +if (!cstate) { + ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + cstate =drm_crtc_create_state (crtc); +if (!cstate) +return ERR_PTR (-ENOMEM ); +init_crtc_state (crtc, cstate, a); + a->crtcs[crtc->id] = crtc; + a->cstates[crtc->id] = cstate; +
Quoted 8 lines
drivers/gpu/drm/drm_atomic.c commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) · line 589
Quoted 4 lines
drivers/gpu/drm/drm_atomic.c +4
-0+/* we'll need it later, so make sure we have state +* for primary plane too: +*/ +drm_atomic_get_plane_state (crtc->primary, a);I haven't figured out why. With primary planes I don't really see a need for this. If we need it to implement the legacy setcrtc interface, then that should be done there, not here.
well, if you sort out how to disable primary helper plane, then yes, you are right :-)
see commit_crtc_state()
BR,
-R
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 31 lines · Rob Clark
Quoted 20 lines · Daniel Vetter
Quoted 20 lines
drivers/gpu/drm/drm_atomic.c +20
-0+struct drm_crtc_state * +drm_atomic_get_crtc_state (struct drm_crtc *crtc,struct drm_atomic_state *a) +{ +struct drm_crtc_state *cstate; +int ret; + + cstate = a->cstates[crtc->id]; + +if (!cstate) { + ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + cstate =drm_crtc_create_state (crtc); +if (!cstate) +return ERR_PTR (-ENOMEM ); +init_crtc_state (crtc, cstate, a); + a->crtcs[crtc->id] = crtc; + a->cstates[crtc->id] = cstate; +Quoted 8 lines
drivers/gpu/drm/drm_atomic.c commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) · line 589
Quoted 4 lines
drivers/gpu/drm/drm_atomic.c +4
-0+/* we'll need it later, so make sure we have state +* for primary plane too: +*/ +drm_atomic_get_plane_state (crtc->primary, a);I haven't figured out why. With primary planes I don't really see a need for this. If we need it to implement the legacy setcrtc interface, then that should be done there, not here.
Quoted 4 lines
well, if you sort out how to disable primary helper plane, then yes, you are right :-)
see
commit_crtc_state()
Imo bail when we have a crtc with NULL primary plane in crtc_commit (and wont disable the entire crtc ofc).
Also I think your current commit_crtc should be pushed down into the crtc helpers - it's not going to do any good for i915. But I guess until we have a real user of the atomic interface (i.e. updates more than 1 crtc) like the fb helper code we don't need this yet.
But as soon as we update more than one crtc we _must_ push it down into the crtc helpers or the i915 machinery - if you try to enable crtcs which need resources from crtcs which aren't yet off this is simply going to fail.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 37 lines · Daniel Vetter
Quoted 31 lines · Rob Clark
Quoted 20 lines · Daniel Vetter
Quoted 20 lines
drivers/gpu/drm/drm_atomic.c +20
-0+struct drm_crtc_state * +drm_atomic_get_crtc_state (struct drm_crtc *crtc,struct drm_atomic_state *a) +{ +struct drm_crtc_state *cstate; +int ret; + + cstate = a->cstates[crtc->id]; + +if (!cstate) { + ret =drm_modeset_lock (&crtc->mutex, &a->acquire_ctx); +if (ret) +return ERR_PTR (ret); + + cstate =drm_crtc_create_state (crtc); +if (!cstate) +return ERR_PTR (-ENOMEM ); +init_crtc_state (crtc, cstate, a); + a->crtcs[crtc->id] = crtc; + a->cstates[crtc->id] = cstate; +Quoted 8 lines
drivers/gpu/drm/drm_atomic.c commit_plane_state(struct drm_plane *plane, struct drm_plane_state *pstate) · line 589
Quoted 4 lines
drivers/gpu/drm/drm_atomic.c +4
-0+/* we'll need it later, so make sure we have state +* for primary plane too: +*/ +drm_atomic_get_plane_state (crtc->primary, a);I haven't figured out why. With primary planes I don't really see a need for this. If we need it to implement the legacy setcrtc interface, then that should be done there, not here.
Quoted 4 lines
well, if you sort out how to disable primary helper plane, then yes, you are right :-)
see
commit_crtc_state()
Quoted 7 lines
Imo bail when we have a crtc with NULL primary plane in
crtc_commit(and wont disable the entire crtc ofc).Also I think your current
commit_crtcshould be pushed down into the crtc helpers - it's not going to do any good for i915. But I guess until we have a real user of the atomic interface (i.e. updates more than 1 crtc) like the fb helper code we don't need this yet.
it is in helpers (if we rename drm_atomic_funcs -> drm_atomic_helper_funcs, which is basically what it is).
I suspect what you actually want is to split up atomic_commit() so you can do the loop over all the planes and crtcs internally.
BR,
-R
Quoted 9 lines
But as soon as we update more than one crtc we _must_ push it down into the crtc helpers or the i915 machinery - if you try to enable crtcs which need resources from crtcs which aren't yet off this is simply going to fail.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 12/17] drm: convert crtc to properties/state
In reply to Daniel VetterQuoted 155 lines · Daniel Vetter
Quoted 10 lines · Rob Clark
Break the mutable state of a crtc out into a separate structure and use atomic properties mechanism to set crtc attributes. This makes it easier to have some helpers for
crtc->set_property()and for checking for invalid params. The idea is that individual drivers can wrap the state struct in their own struct which adds driver specific parameters, for easy build-up of state across multipleset_property()calls and for easy atomic commit or roll- back.Signed-off-by Rob Clark <[email protected]>Same comments about interface design as for the plane patch apply here. One additional comment below.
Quoted 140 lines
--- drivers/gpu/drm/armada/armada_crtc.c | 11 +- drivers/gpu/drm/ast/ast_mode.c | 1 + drivers/gpu/drm/cirrus/cirrus_mode.c | 1 + drivers/gpu/drm/drm_atomic.c | 231 ++++++++++- drivers/gpu/drm/drm_crtc.c | 598 ++++++++++++++++++----------- drivers/gpu/drm/drm_fb_helper.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 1 + drivers/gpu/drm/gma500/psb_intel_display.c | 1 + drivers/gpu/drm/i915/intel_display.c | 1 + drivers/gpu/drm/mgag200/mgag200_mode.c | 1 + drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | 6 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 +- drivers/gpu/drm/nouveau/dispnv04/crtc.c | 1 + drivers/gpu/drm/nouveau/nv50_display.c | 1 + drivers/gpu/drm/omapdrm/omap_crtc.c | 12 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/qxl/qxl_display.c | 2 + drivers/gpu/drm/radeon/radeon_display.c | 2 + drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 2 + drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 1 + drivers/gpu/drm/udl/udl_modeset.c | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 + include/drm/drm_atomic.h | 29 ++ include/drm/drm_crtc.h | 103 ++++- 27 files changed, 785 insertions(+), 243 deletions(-)drivers/gpu/drm/armada/armada_crtc.c +10
-1@@ -9,6 +9,7 @@#include <linux/clk.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_atomic.h> #include "armada_crtc.h" #include "armada_drm.h" #include "armada_fb.h" @@ -966,7 +967,12 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, {struct armada_private *priv = crtc->dev->dev_private;struct armada_crtc *dcrtc =drm_to_armada_crtc (crtc); +struct drm_crtc_state *cstate =drm_atomic_get_crtc_state (crtc, state);bool update_csc = false; +int ret =0 ; + +if (IS_ERR (cstate)) +return PTR_ERR (cstate);if (property == priv->csc_yuv_prop) { dcrtc->csc_yuv_mode = val;@@ -974,6 +980,9 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc, }else if (property == priv->csc_rgb_prop) { dcrtc->csc_rgb_mode = val; update_csc = true; + }else { + ret =drm_crtc_set_property (crtc, cstate, property, + val, blob_data); }if (update_csc) {@@ -984,7 +993,7 @@ armada_drm_crtc_set_property(struct drm_crtc *crtc,writel_relaxed (val, dcrtc->base +LCD_SPU_IOPAD_CONTROL ); } -return 0 ; +return ret; }static struct drm_crtc_funcs armada_crtc_funcs = {drivers/gpu/drm/ast/ast_mode.c +1
-0@@ -632,6 +632,7 @@ static const struct drm_crtc_funcs ast_crtc_funcs = { .cursor_move = ast_cursor_move, .reset = ast_crtc_reset, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .gamma_set = ast_crtc_gamma_set, .destroy = ast_crtc_destroy, };drivers/gpu/drm/cirrus/cirrus_mode.c +1
-0@@ -366,6 +366,7 @@ static void cirrus_crtc_destroy(struct drm_crtc *crtc)static const struct drm_crtc_funcs cirrus_crtc_funcs = { .gamma_set = cirrus_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .set_property = drm_atomic_crtc_set_property, .destroy = cirrus_crtc_destroy, };drivers/gpu/drm/drm_atomic.c +14
-1@@ -48,11 +48,13 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, {struct drm_atomic_state *state;int nplanes = dev->mode_config.num_total_plane; +int ncrtcs = dev->mode_config.num_crtc;int sz;void *ptr; sz =sizeof (*state); sz += (sizeof (state->planes) +sizeof (state->pstates)) * nplanes; + sz += (sizeof (state->crtcs) +sizeof (state->cstates)) * ncrtcs; ptr =kzalloc (sz,GFP_KERNEL );@@ -74,6 +76,12 @@ struct drm_atomic_state *drm_atomic_begin(struct drm_device *dev, state->pstates = ptr; ptr = &state->pstates[nplanes]; + state->crtcs = ptr; + ptr = &state->crtcs[ncrtcs]; + + state->cstates = ptr; + ptr = &state->cstates[ncrtcs]; +return state; }EXPORT_SYMBOL (drm_atomic_begin);@@ -92,7 +100,18 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_object *obj, struct drm_pending_vblank_event *event) { - return -EINVAL; /* for now */ + switch (obj->type) { + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc_state *cstate = +drm_atomic_get_crtc_state (obj_to_crtc (obj), state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate);
Quoted 8 lines
drivers/gpu/drm/drm_atomic.c int drm_atomic_set_event(struct drm_device *dev, · line 114
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+ cstate->event = event; +return 0 ; + } +default : +return -EINVAL ; + }Hm, I think if we only want completion events on crtcs (which I agree on)
I don't. Unless you have a nice way of passing some kind of "fbs now available for rendering" list back to userland in the single crtc event. Last time I looked making the drm event stuff deal with variable length events looked more painful than just adding per plane events. But I must admit that I didn't really try to do it.
Signature · 2 lines
Ville Syrjälä Intel OTC
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 22 lines · Ville Syrjälä
Quoted 12 lines · Daniel Vetter
Quoted 11 lines · Rob Clark
drivers/gpu/drm/drm_atomic.c +6
-1@@ -92,7 +100,18 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_object *obj, struct drm_pending_vblank_event *event) { - return -EINVAL; /* for now */ + switch (obj->type) { + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc_state *cstate = +drm_atomic_get_crtc_state (obj_to_crtc (obj), state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate);Quoted 8 lines
drivers/gpu/drm/drm_atomic.c int drm_atomic_set_event(struct drm_device *dev, · line 114
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+ cstate->event = event; +return 0 ; + } +default : +return -EINVAL ; + }Hm, I think if we only want completion events on crtcs (which I agree on)
Quoted 5 lines
I don't. Unless you have a nice way of passing some kind of "fbs now available for rendering" list back to userland in the single crtc event. Last time I looked making the drm event stuff deal with variable length events looked more painful than just adding per plane events. But I must admit that I didn't really try to do it.
Hm, why can't userspace keep a list of fb ids involved in a given crtc pageflip around and index those with the cookie we pass around?
I really don't see why the kernel has to implement a half-baked event multiplexer (which just copies the same thing n times), while userspace is perfectly capable of doing that itself?
Now if the timestamps would be genuinely different then I'd agree, but then that's not an atomic update.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 32 lines · Daniel Vetter
Quoted 22 lines · Ville Syrjälä
Quoted 12 lines · Daniel Vetter
Quoted 11 lines · Rob Clark
drivers/gpu/drm/drm_atomic.c +6
-1@@ -92,7 +100,18 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_object *obj, struct drm_pending_vblank_event *event) { - return -EINVAL; /* for now */ + switch (obj->type) { + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc_state *cstate = +drm_atomic_get_crtc_state (obj_to_crtc (obj), state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate);Quoted 8 lines
drivers/gpu/drm/drm_atomic.c int drm_atomic_set_event(struct drm_device *dev, · line 114
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+ cstate->event = event; +return 0 ; + } +default : +return -EINVAL ; + }Hm, I think if we only want completion events on crtcs (which I agree on)
Quoted 5 lines
I don't. Unless you have a nice way of passing some kind of "fbs now available for rendering" list back to userland in the single crtc event. Last time I looked making the drm event stuff deal with variable length events looked more painful than just adding per plane events. But I must admit that I didn't really try to do it.
Hm, why can't userspace keep a list of fb ids involved in a given crtc pageflip around and index those with the cookie we pass around?
Quoted 6 lines
I really don't see why the kernel has to implement a half-baked event multiplexer (which just copies the same thing n times), while userspace is perfectly capable of doing that itself?
Now if the timestamps would be genuinely different then I'd agree, but then that's not an atomic update.
I do kinda think userspace would want to know somehow if an fb is going to be really late and explicitly submit an older fb. If you were resizing, for example, I don't think the driver could make the call to leave one plane displaying an older fb.
But I do think we can bikeshed about that in parallel with getting the inital atomic infrastructure merged.
BR,
-R
Quoted 5 lines
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 12/17] drm: convert crtc to properties/state
In reply to Daniel VetterQuoted 32 lines · Daniel Vetter
Quoted 22 lines · Ville Syrjälä
Quoted 12 lines · Daniel Vetter
Quoted 11 lines · Rob Clark
drivers/gpu/drm/drm_atomic.c +6
-1@@ -92,7 +100,18 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_object *obj, struct drm_pending_vblank_event *event) { - return -EINVAL; /* for now */ + switch (obj->type) { + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc_state *cstate = +drm_atomic_get_crtc_state (obj_to_crtc (obj), state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate);Quoted 8 lines
drivers/gpu/drm/drm_atomic.c int drm_atomic_set_event(struct drm_device *dev, · line 114
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+ cstate->event = event; +return 0 ; + } +default : +return -EINVAL ; + }Hm, I think if we only want completion events on crtcs (which I agree on)
Quoted 5 lines
I don't. Unless you have a nice way of passing some kind of "fbs now available for rendering" list back to userland in the single crtc event. Last time I looked making the drm event stuff deal with variable length events looked more painful than just adding per plane events. But I must admit that I didn't really try to do it.
Hm, why can't userspace keep a list of fb ids involved in a given crtc pageflip around and index those with the cookie we pass around?
Quoted 6 lines
I really don't see why the kernel has to implement a half-baked event multiplexer (which just copies the same thing n times), while userspace is perfectly capable of doing that itself?
Now if the timestamps would be genuinely different then I'd agree, but then that's not an atomic update.
User space can't do it if flips get issued faster than the vrefresh rate. I still want my "moar fps" triple buffering mode.
Signature · 2 lines
Ville Syrjälä Intel OTC
Re: [PATCH 12/17] drm: convert crtc to properties/state
Quoted 37 lines · Ville Syrjälä
Quoted 36 lines · Daniel Vetter
Quoted 22 lines · Ville Syrjälä
Quoted 12 lines · Daniel Vetter
Quoted 11 lines · Rob Clark
drivers/gpu/drm/drm_atomic.c +6
-1@@ -92,7 +100,18 @@ int drm_atomic_set_event(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_object *obj, struct drm_pending_vblank_event *event) { - return -EINVAL; /* for now */ + switch (obj->type) { + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc_state *cstate = +drm_atomic_get_crtc_state (obj_to_crtc (obj), state); +if (IS_ERR (cstate)) +return PTR_ERR (cstate);Quoted 8 lines
drivers/gpu/drm/drm_atomic.c int drm_atomic_set_event(struct drm_device *dev, · line 114
Quoted 6 lines
drivers/gpu/drm/drm_atomic.c +6
-0+ cstate->event = event; +return 0 ; + } +default : +return -EINVAL ; + }Hm, I think if we only want completion events on crtcs (which I agree on)
Quoted 5 lines
I don't. Unless you have a nice way of passing some kind of "fbs now available for rendering" list back to userland in the single crtc event. Last time I looked making the drm event stuff deal with variable length events looked more painful than just adding per plane events. But I must admit that I didn't really try to do it.
Hm, why can't userspace keep a list of fb ids involved in a given crtc pageflip around and index those with the cookie we pass around?
I really don't see why the kernel has to implement a half-baked event multiplexer (which just copies the same thing n times), while userspace is perfectly capable of doing that itself?
Quoted 5 lines
Quoted 2 lines
Now if the timestamps would be genuinely different then I'd agree, but then that's not an atomic update.
User space can't do it if flips get issued faster than the vrefresh rate. I still want my "moar fps" triple buffering mode.
Hm right, I forget about this every time it comes up. Imo we should postpone this to when it actually gets implemented - usualy preemptive generalism just ends up hurting everyone for now real good. For the current logic we could ditch all the indirection and callbacks really and simply require that the ->commit hook sends out the crtc even if it's there.
And even if we add per-plane events we don't need new hooks imo. Just adding an event pointer to the plane state structure and firing off those events together with the crtc one in drivers should be good enough.
The proposed set_event callback plus implementation otoh are serious overkill.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch