prepare for preparing for atomic (v2)
Subsystems (13)
cover prepare for preparing for atomic (v2)
As suggested by Daniel, splitting out ww_mutex conversion and a few other bits out. Updated connection_mutex which fixes a few things, plus split up addition of extended property types from adding object property and pull in addition of _restore_fbdev_mode_unlocked() as it does not depend on atomic.
Can be found at:
http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-prep
git://people.freedesktop.org/~robclark/linux atomic-prep
Daniel Vetter (1):
drm: Split connection_mutex out of mode_config.mutex (v3)
Rob Clark (7):
drm: helpers to find mode objects
drm: add extended property types
drm: add object property type
drm: add signed-range property type
drm: spiff out FB refcnting traces
drm: convert crtc and connection_mutex to ww_mutex (v3)
drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/drm_crtc.c | 295 +++++++++++++++++++---------- drivers/gpu/drm/drm_crtc_helper.c | 1 + drivers/gpu/drm/drm_edid.c | 2 + drivers/gpu/drm/drm_fb_cma_helper.c | 9 +- drivers/gpu/drm/drm_fb_helper.c | 55 ++++-- drivers/gpu/drm/drm_modeset_lock.c | 179 +++++++++++++++++ drivers/gpu/drm/drm_plane_helper.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/gma500/psb_drv.c | 4 +- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/intel_crt.c | 5 +- drivers/gpu/drm/i915/intel_display.c | 60 ++++-- drivers/gpu/drm/i915/intel_dp.c | 15 +- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_fbdev.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/i915/intel_tv.c | 5 +- drivers/gpu/drm/msm/msm_drv.c | 7 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +- drivers/gpu/drm/omapdrm/omap_fb.c | 1 + drivers/gpu/drm/radeon/radeon_connectors.c | 1 + drivers/gpu/drm/tegra/fb.c | 7 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- include/drm/drmP.h | 5 - include/drm/drm_crtc.h | 81 +++++++- include/drm/drm_fb_helper.h | 1 + include/drm/drm_modeset_lock.h | 103 ++++++++++ include/uapi/drm/drm_mode.h | 15 ++ 35 files changed, 716 insertions(+), 212 deletions(-) create mode 100644 drivers/gpu/drm/drm_modeset_lock.c create mode 100644 include/drm/drm_modeset_lock.h
Signature · 1 line
1.9.3
PATCH 1/8 drm: helpers to find mode objects
Add a few more useful helpers to find mode objects.
--- drivers/gpu/drm/drm_crtc.c | 90 +++++++++++++++------------------------------- include/drm/drm_crtc.h | 33 +++++++++++++++++ 2 files changed, 61 insertions(+), 62 deletions(-)
drivers/gpu/drm/drm_crtc.c +28 -62
@@ -1711,7 +1711,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 ))
@@ -1719,13 +1718,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;
@@ -1779,7 +1776,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 ;
@@ -1803,13 +1799,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,mutex_lock (&dev->mode_config.mutex); - 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;
@@ -1924,7 +1918,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 ;
@@ -1932,13 +1925,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;
@@ -2036,7 +2027,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 ;
@@ -2045,13 +2035,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;
@@ -2104,7 +2092,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 ;
@@ -2119,14 +2106,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) {
@@ -2143,15 +2128,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) {
@@ -2338,7 +2321,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 ;
@@ -2356,14 +2338,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) {
@@ -2446,15 +2426,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));
@@ -2486,7 +2464,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 ;
@@ -2496,12 +2473,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);mutex_lock (&crtc->mutex);if (req->flags &DRM_MODE_CURSOR_BO ) {
@@ -3458,7 +3434,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 ;
@@ -3477,12 +3452,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 (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) {list_for_each_entry (prop_enum, &property->enum_blob_list, head)
@@ -3610,7 +3584,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 ;
@@ -3620,12 +3593,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;
@@ -4007,7 +3979,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;
@@ -4017,12 +3988,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 ;
@@ -4081,7 +4051,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;
@@ -4091,12 +4060,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) {
@@ -4149,7 +4117,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 ;
@@ -4163,10 +4130,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);mutex_lock (&crtc->mutex);if (crtc->primary->fb ==NULL ) {
include/drm/drm_crtc.h +33 -0
@@ -1063,6 +1063,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) {
@@ -1079,6 +1088,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.3
Re: [PATCH 1/8] 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]>
Still a pile of these in drivers and still a perfect use-case for cocci. Patch itself looks good.
-Daniel
Quoted 381 lines
--- drivers/gpu/drm/drm_crtc.c | 90 +++++++++++++++------------------------------- include/drm/drm_crtc.h | 33 +++++++++++++++++ 2 files changed, 61 insertions(+), 62 deletions(-)drivers/gpu/drm/drm_crtc.c +28
-62@@ -1711,7 +1711,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 ))@@ -1719,13 +1718,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;@@ -1779,7 +1776,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 ;@@ -1803,13 +1799,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,mutex_lock (&dev->mode_config.mutex); - 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;@@ -1924,7 +1918,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 ;@@ -1932,13 +1925,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;@@ -2036,7 +2027,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 ;@@ -2045,13 +2035,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;@@ -2104,7 +2092,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 ;@@ -2119,14 +2106,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) {@@ -2143,15 +2128,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) {@@ -2338,7 +2321,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 ;@@ -2356,14 +2338,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) {@@ -2446,15 +2426,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));@@ -2486,7 +2464,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 ;@@ -2496,12 +2473,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);mutex_lock (&crtc->mutex);if (req->flags &DRM_MODE_CURSOR_BO ) {@@ -3458,7 +3434,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 ;@@ -3477,12 +3452,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 (property->flags & (DRM_MODE_PROP_ENUM |DRM_MODE_PROP_BITMASK )) {list_for_each_entry (prop_enum, &property->enum_blob_list, head)@@ -3610,7 +3584,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 ;@@ -3620,12 +3593,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;@@ -4007,7 +3979,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;@@ -4017,12 +3988,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 ;@@ -4081,7 +4051,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;@@ -4091,12 +4060,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) {@@ -4149,7 +4117,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 ;@@ -4163,10 +4130,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);mutex_lock (&crtc->mutex);if (crtc->primary->fb ==NULL ) {include/drm/drm_crtc.h +33
-0@@ -1063,6 +1063,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) {@@ -1079,6 +1088,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.3
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 2/8 drm: add extended property types
In reply to Rob ClarkIf we continue to use bitmask for type, we will quickly run out of room to add new types. Split this up so existing part of bitmask range continues to function as before, but reserve a chunk of the remaining space for an integer type-id. Wrap this all up in some type-check helpers to keep the backwards-compat uglyness contained.
--- drivers/gpu/drm/drm_crtc.c | 26 +++++++++++++++++--------- include/drm/drm_crtc.h | 17 +++++++++++++++++ include/uapi/drm/drm_mode.h | 13 +++++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-)
drivers/gpu/drm/drm_crtc.c +17 -9
@@ -3113,6 +3113,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, }list_add_tail (&property->head, &dev->mode_config.property_list); + +WARN_ON (!drm_property_type_valid (property)); +return property; fail:kfree (property->values);
@@ -3270,14 +3273,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)) {
@@ -3458,10 +3463,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, goto done; } -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++; }
@@ -3483,7 +3489,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;
@@ -3505,7 +3512,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;
@@ -3659,17 +3666,18 @@ 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 {
include/drm/drm_crtc.h +17 -0
@@ -931,6 +931,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);
include/uapi/drm/drm_mode.h +13 -0
@@ -251,6 +251,19 @@ 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) +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ];
Signature · 1 line
1.9.3
Re: [PATCH 2/8] drm: add extended property types
Quoted 7 lines · Rob Clark
If we continue to use bitmask for type, we will quickly run out of room to add new types. Split this up so existing part of bitmask range continues to function as before, but reserve a chunk of the remaining space for an integer type-id. Wrap this all up in some type-check helpers to keep the backwards-compat uglyness contained.
Signed-off-by Rob Clark <[email protected]>
I kinda liked David's idea to just continue the enumeration, but instead of continuing with flags we'll just start at last_flag+1, +2, ...
With or without that this is Reviewed-by: Daniel Vetter <[email protected]>
Quoted 149 lines
--- drivers/gpu/drm/drm_crtc.c | 26 +++++++++++++++++--------- include/drm/drm_crtc.h | 17 +++++++++++++++++ include/uapi/drm/drm_mode.h | 13 +++++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-)drivers/gpu/drm/drm_crtc.c +17
-9@@ -3113,6 +3113,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, }list_add_tail (&property->head, &dev->mode_config.property_list); + +WARN_ON (!drm_property_type_valid (property)); +return property; fail:kfree (property->values);@@ -3270,14 +3273,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)) {@@ -3458,10 +3463,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, goto done; } -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++; }@@ -3483,7 +3489,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;@@ -3505,7 +3512,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;@@ -3659,17 +3666,18 @@ 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 {include/drm/drm_crtc.h +17
-0@@ -931,6 +931,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);include/uapi/drm/drm_mode.h +13
-0@@ -251,6 +251,19 @@ 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) +struct drm_mode_property_enum {__u64 value;char name[DRM_PROP_NAME_LEN ];Signature · 1 line
1.9.3
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 3/8 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 | 61 +++++++++++++++++++++++++++++++++++++++------ include/drm/drm_crtc.h | 5 ++++ include/uapi/drm/drm_mode.h | 1 + 3 files changed, 60 insertions(+), 7 deletions(-)
drivers/gpu/drm/drm_crtc.c +54 -7
@@ -389,6 +389,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
@@ -396,7 +411,9 @@ void drm_mode_object_put(struct drm_device *dev,* @type: type of the mode object * * Note that framebuffers cannot be looked up with this functions - since those -* are reference counted, they need special treatment. +* are reference counted, they need special treatment. Even with +* DRM_MODE_OBJECT_ANY (although that will simply return NULL +* rather than WARN_ON()). */ struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type)
@@ -406,13 +423,10 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,/* 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 || (obj->type != type) || (obj->id != id)) + obj =_object_find (dev, id, type); +/* don't leak out unref'd fb's */ +if (obj && (obj->type ==DRM_MODE_OBJECT_FB )) obj =NULL ; -mutex_unlock (&dev->mode_config.idr_mutex); -return obj; }EXPORT_SYMBOL (drm_mode_object_find);
@@ -3093,6 +3107,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)
@@ -3253,6 +3269,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
@@ -3680,6 +3713,20 @@ static bool drm_property_change_is_valid(struct drm_property *property, }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 )) { +struct drm_mode_object *obj; +/* a zero value for an object property translates to null: */ +if (value ==0 ) +return true; +/* +* NOTE: use _object_find() directly to bypass restriction on +* looking up refcnt'd objects (ie. fb's). For a refcnt'd +* object this could race against object finalization, so it +* simply tells us that the object *was* valid. Which is good +* enough. +*/ + obj =_object_find (property->dev, value, property->values[0 ]); +return obj !=NULL ; }else {int i;for (i =0 ; i < property->num_values; i++)
include/drm/drm_crtc.h +5 -0
@@ -50,6 +50,7 @@ struct drm_clip_rect;#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;
@@ -190,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; };
@@ -981,6 +983,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);
@@ -997,6 +1001,7 @@ 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); +/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);
include/uapi/drm/drm_mode.h +1 -0
@@ -263,6 +263,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)struct drm_mode_property_enum {__u64 value;
Signature · 1 line
1.9.3
Re: [PATCH 3/8] drm: add object property type
Quoted 4 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]>
Quoted 166 lines
--- drivers/gpu/drm/drm_crtc.c | 61 +++++++++++++++++++++++++++++++++++++++------ include/drm/drm_crtc.h | 5 ++++ include/uapi/drm/drm_mode.h | 1 + 3 files changed, 60 insertions(+), 7 deletions(-)drivers/gpu/drm/drm_crtc.c +54
-7@@ -389,6 +389,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 @@ -396,7 +411,9 @@ void drm_mode_object_put(struct drm_device *dev,* @type: type of the mode object * * Note that framebuffers cannot be looked up with this functions - since those -* are reference counted, they need special treatment. +* are reference counted, they need special treatment. Even with +* DRM_MODE_OBJECT_ANY (although that will simply return NULL +* rather than WARN_ON()). */ struct drm_mode_object *drm_mode_object_find (struct drm_device *dev,uint32_t id,uint32_t type)@@ -406,13 +423,10 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,/* 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 || (obj->type != type) || (obj->id != id)) + obj =_object_find (dev, id, type); +/* don't leak out unref'd fb's */ +if (obj && (obj->type ==DRM_MODE_OBJECT_FB )) obj =NULL ; -mutex_unlock (&dev->mode_config.idr_mutex); -return obj; }EXPORT_SYMBOL (drm_mode_object_find);@@ -3093,6 +3107,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)@@ -3253,6 +3269,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 @@ -3680,6 +3713,20 @@ static bool drm_property_change_is_valid(struct drm_property *property, }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 )) { +struct drm_mode_object *obj; +/* a zero value for an object property translates to null: */ +if (value ==0 ) +return true; +/* +* NOTE: use _object_find() directly to bypass restriction on +* looking up refcnt'd objects (ie. fb's). For a refcnt'd +* object this could race against object finalization, so it +* simply tells us that the object *was* valid. Which is good +* enough. +*/ + obj =_object_find (property->dev, value, property->values[0 ]); +return obj !=NULL ; }else {int i;for (i =0 ; i < property->num_values; i++)include/drm/drm_crtc.h +5
-0@@ -50,6 +50,7 @@ struct drm_clip_rect;#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;@@ -190,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; };@@ -981,6 +983,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);@@ -997,6 +1001,7 @@ 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); +/* IOCTLs */ extern int drm_mode_getresources (struct drm_device *dev,void *data,struct drm_file *file_priv);include/uapi/drm/drm_mode.h +1
-0@@ -263,6 +263,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)struct drm_mode_property_enum {__u64 value;Signature · 1 line
1.9.3
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 4/8 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
@@ -3232,6 +3232,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
@@ -3254,21 +3270,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) {
@@ -3704,6 +3719,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 ,
@@ -983,6 +992,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.3
PATCH 5/8 drm: spiff out FB refcnting traces
In reply to Rob ClarkI find myself making this change locally whenever debugging FB reference counting. Which seems a bit silly.
--- drivers/gpu/drm/drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_crtc.c +3 -3
@@ -532,7 +532,7 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);*/ void drm_framebuffer_unreference (struct drm_framebuffer *fb) { -DRM_DEBUG ("FB ID: %d\n" , fb->base.id); +DRM_DEBUG ("%p: FB ID: %d (%d)\n" , fb, fb->base.id,atomic_read (&fb->refcount.refcount));kref_put (&fb->refcount, drm_framebuffer_free); }EXPORT_SYMBOL (drm_framebuffer_unreference);
@@ -545,7 +545,7 @@ EXPORT_SYMBOL(drm_framebuffer_unreference);*/ void drm_framebuffer_reference (struct drm_framebuffer *fb) { -DRM_DEBUG ("FB ID: %d\n" , fb->base.id); +DRM_DEBUG ("%p: FB ID: %d (%d)\n" , fb, fb->base.id,atomic_read (&fb->refcount.refcount));kref_get (&fb->refcount); }EXPORT_SYMBOL (drm_framebuffer_reference);
@@ -557,7 +557,7 @@ static void drm_framebuffer_free_bug(struct kref *kref)static void __drm_framebuffer_unreference (struct drm_framebuffer *fb) { -DRM_DEBUG ("FB ID: %d\n" , fb->base.id); +DRM_DEBUG ("%p: FB ID: %d (%d)\n" , fb, fb->base.id,atomic_read (&fb->refcount.refcount));kref_put (&fb->refcount, drm_framebuffer_free_bug); }
Signature · 1 line
1.9.3
PATCH 6/8 drm: Split connection_mutex out of mode_config.mutex (v3)
In reply to Rob ClarkFrom: Daniel Vetter <[email protected]>
After the split-out of crtc locks from the big mode_config.mutex there's still two major areas it protects:
- Various connector probe states, like connector->status, EDID properties, probed mode lists and similar information.
- The links from connector->encoder and encoder->crtc and other modeset-relevant connector state (e.g. properties which control the panel fitter).
The later is used by modeset operations. But they don't really care about the former since it's allowed to e.g. enable a disconnected VGA output or with a mode not in the probed list.
Thus far this hasn't been a problem, but for the atomic modeset conversion Rob Clark needs to convert all modeset relevant locks into w/w locks. This is required because the order of acquisition is determined by how userspace supplies the atomic modeset data. This has run into troubles in the detect path since the i915 load detect code needs _both_ protections offered by the mode_config.mutex: It updates probe state and it needs to change the modeset configuration to enable the temporary load detect pipe.
The big deal here is that for the probe/detect users of this lock a plain mutex fits best, but for atomic modesets we really want a w/w mutex. To fix this lets split out a new connection_mutex lock for the modeset relevant parts.
For simplicity I've decided to only add one additional lock for all connector/encoder links and modeset configuration states. We have piles of different modeset objects in addition to those (like bridges or panels), so adding per-object locks would be much more effort.
Also, we're guaranteed (at least for now) to do a full modeset if we need to acquire this lock. Which means that fine-grained locking is fairly irrelevant compared to the amount of time the full modeset will take.
I've done a full audit, and there's just a few things that justify special focus:
- Locking in drm_sysfs.c is almost completely absent. We should sprinkle mode_config.connection_mutex over this file a bit, but since it already lacks mode_config.mutex this patch wont make the situation any worse. This is material for a follow-up patch.
- omap has a omap_framebuffer_flush function which walks the connector->encoder->crtc links and is called from many contexts. Some look like they don't acquire mode_config.mutex, so this is already racy. Again fixing this is material for a separate patch.
- The radeon hot_plug function to retrain DP links looks at connector->dpms. Currently this happens without any locking, so is already racy. I think radeon_hotplug_work_func should gain mutex_lock/unlock calls for the mode_config.connection_mutex.
- Same applies to i915's intel_dp_hot_plug. But again, this is already racy.
- i915 load_detect code needs to acquire this lock. Which means the w/w dance due to Rob's work will be nicely contained to _just_ this function.
I've added fixme comments everywhere where it looks suspicious but in the sysfs code. After a quick irc discussion with Dave Airlie it sounds like the lack of locking in there is due to sysfs cleanup fun at module unload.
v1: original (only compile tested)
v2: missing mutex_init(), etc (from Rob Clark)
v3: i915 needs more care in the conversion:
- Protect the edp pp logic with the connection_mutex.
- Use connection_mutex in the backlight code due to get_pipe_from_connector.
- Use drm_modeset_lock_all in suspend/resume paths.
- Update lock checks in the overlay code.
--- drivers/gpu/drm/drm_crtc.c | 8 ++++++++ drivers/gpu/drm/drm_crtc_helper.c | 2 ++ drivers/gpu/drm/drm_edid.c | 2 ++ drivers/gpu/drm/drm_plane_helper.c | 7 +++++++ drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 16 ++++++++++++---- drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++------- 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/omapdrm/omap_fb.c | 1 + drivers/gpu/drm/radeon/radeon_connectors.c | 1 + include/drm/drm_crtc.h | 1 + 14 files changed, 54 insertions(+), 23 deletions(-)
drivers/gpu/drm/drm_crtc.c +8 -0
@@ -54,6 +54,8 @@ void drm_modeset_lock_all(struct drm_device *dev)mutex_lock (&dev->mode_config.mutex); +mutex_lock (&dev->mode_config.connection_mutex); +list_for_each_entry (crtc, &dev->mode_config.crtc_list, head)mutex_lock_nest_lock (&crtc->mutex, &dev->mode_config.mutex); }
@@ -72,6 +74,8 @@ void drm_modeset_unlock_all(struct drm_device *dev)list_for_each_entry (crtc, &dev->mode_config.crtc_list, head)mutex_unlock (&crtc->mutex); +mutex_unlock (&dev->mode_config.connection_mutex); +mutex_unlock (&dev->mode_config.mutex); }EXPORT_SYMBOL (drm_modeset_unlock_all);
@@ -93,6 +97,7 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)list_for_each_entry (crtc, &dev->mode_config.crtc_list, head)WARN_ON (!mutex_is_locked (&crtc->mutex)); +WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex));WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); }EXPORT_SYMBOL (drm_warn_on_modeset_not_all_locked);
@@ -1812,6 +1817,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,DRM_DEBUG_KMS ("[CONNECTOR:%d:?]\n" , out_resp->connector_id);mutex_lock (&dev->mode_config.mutex); +mutex_lock (&dev->mode_config.connection_mutex); connector =drm_connector_find (dev, out_resp->connector_id);if (!connector) {
@@ -1910,6 +1916,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->count_encoders = encoders_count; out: +mutex_unlock (&dev->mode_config.connection_mutex);mutex_unlock (&dev->mode_config.mutex);return ret;
@@ -4659,6 +4666,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);void drm_mode_config_init (struct drm_device *dev) {mutex_init (&dev->mode_config.mutex); +mutex_init (&dev->mode_config.connection_mutex);mutex_init (&dev->mode_config.idr_mutex);mutex_init (&dev->mode_config.fb_lock);INIT_LIST_HEAD (&dev->mode_config.fb_list);
drivers/gpu/drm/drm_crtc_helper.c +2 -0
@@ -89,6 +89,8 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)struct drm_device *dev = encoder->dev;WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); +list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder == encoder)return true;
drivers/gpu/drm/drm_edid.c +2 -0
@@ -3299,6 +3299,8 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder,struct drm_connector *connector;struct drm_device *dev = encoder->dev; +WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); +list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder == encoder && connector->eld[0 ])return connector;
drivers/gpu/drm/drm_plane_helper.c +7 -0
@@ -54,6 +54,13 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,struct drm_connector *connector;int count =0 ; +/* +* Note: Once we change the plane hooks to more fine-grained locking we +* need to grab the connection_mutex here to be able to make these +* checks. +*/ +WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); +list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder && connector->encoder->crtc == crtc) {if (connector_list !=NULL && count < num_connectors)
drivers/gpu/drm/i915/i915_debugfs.c +2 -2
@@ -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_all (dev);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_all (dev);return ret; }
drivers/gpu/drm/i915/i915_drv.c +2 -2
@@ -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_all (dev);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_all (dev);intel_modeset_suspend_hw (dev); }
drivers/gpu/drm/i915/intel_display.c +12 -4
@@ -7988,6 +7988,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, connector->base.id,drm_get_connector_name (connector), encoder->base.id, drm_get_encoder_name(encoder)); +mutex_lock (&dev->mode_config.connection_mutex); +/* * Algorithm gets a little messy: *
@@ -8030,7 +8032,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,*/ if (!crtc) {DRM_DEBUG_KMS ("no pipe available for load-detect\n" ); -return false; + goto fail_unlock_connector; }mutex_lock (&crtc->mutex);
@@ -8084,6 +8086,9 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,else intel_crtc->new_config =NULL ;mutex_unlock (&crtc->mutex); +fail_unlock_connector: +mutex_unlock (&dev->mode_config.connection_mutex); +return false; }
@@ -8113,6 +8118,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, }mutex_unlock (&crtc->mutex); +mutex_unlock (&connector->dev->mode_config.connection_mutex);return ; }
@@ -8121,6 +8127,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, connector->funcs->dpms (connector, old->dpms_mode);mutex_unlock (&crtc->mutex); +mutex_unlock (&connector->dev->mode_config.connection_mutex); } static int i9xx_pll_refclk(struct drm_device *dev,
@@ -10577,8 +10584,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)enum pipe intel_get_pipe_from_connector (struct intel_connector *connector) {struct drm_encoder *encoder = connector->base.encoder; +struct drm_device *dev = connector->base.dev; -WARN_ON (!mutex_is_locked (&connector->base.dev->mode_config.mutex)); +WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex));if (!encoder)return INVALID_PIPE ;
@@ -11336,9 +11344,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_all (dev);intel_modeset_setup_hw_state (dev, false); -mutex_unlock (&dev->mode_config.mutex); +drm_modeset_unlock_all (dev);list_for_each_entry (crtc, &dev->mode_config.crtc_list, base.head) {
drivers/gpu/drm/i915/intel_dp.c +8 -7
@@ -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 (!mutex_is_locked (&dev->mode_config.connection_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); +mutex_lock (&dev->mode_config.connection_mutex);edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.mutex); +mutex_unlock (&dev->mode_config.connection_mutex); }static void edp_panel_vdd_off (struct intel_dp *intel_dp,bool sync)
@@ -2953,6 +2953,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)u8 sink_irq_vector;u8 link_status[DP_LINK_STATUS_SIZE ]; +/* FIXME: This access isn't protected by any locks. */ if (!intel_encoder->connectors_active)return ;
@@ -3383,9 +3384,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); +mutex_lock (&dev->mode_config.connection_mutex);edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.mutex); +mutex_unlock (&dev->mode_config.connection_mutex); }kfree (intel_dig_port); }
@@ -3964,9 +3965,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); +mutex_lock (&dev->mode_config.connection_mutex);edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.mutex); +mutex_unlock (&dev->mode_config.connection_mutex); }drm_sysfs_connector_remove (connector);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); +mutex_lock (&dev->mode_config.connection_mutex);/* * 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); +mutex_unlock (&dev->mode_config.connection_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 (!mutex_is_locked (&dev->mode_config.connection_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 (!mutex_is_locked (&dev->mode_config.connection_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); +mutex_lock (&dev->mode_config.connection_mutex);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); +mutex_unlock (&dev->mode_config.connection_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); +mutex_lock (&dev->mode_config.connection_mutex); ret =intel_panel_get_backlight (connector); -mutex_unlock (&dev->mode_config.mutex); +mutex_unlock (&dev->mode_config.connection_mutex);intel_runtime_pm_put (dev_priv);return ret;
drivers/gpu/drm/omapdrm/omap_fb.c +1 -0
@@ -346,6 +346,7 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,VERB ("flush: %d,%d %dx%d, fb=%p" , x, y, w, h, fb); +/* FIXME: This is racy - no protection against modeset config changes. */ while ((connector =omap_framebuffer_get_next_connector (fb, connector))) {/* only consider connectors that are part of a chain */ if (connector->encoder && connector->encoder->crtc) {
drivers/gpu/drm/radeon/radeon_connectors.c +1 -0
@@ -48,6 +48,7 @@ void radeon_connector_hotplug(struct drm_connector *connector)radeon_hpd_set_polarity (rdev, radeon_connector->hpd.hpd);/* if the connector is already off, don't turn it back on */ +/* FIXME: This access isn't protected by any locks. */ if (connector->dpms !=DRM_MODE_DPMS_ON )return ;
include/drm/drm_crtc.h +1 -0
@@ -738,6 +738,7 @@ struct drm_mode_group {*/ struct drm_mode_config {struct mutex mutex;/* protects configuration (mode lists etc.) */ +struct mutex connection_mutex;/* protects connector->encoder and encoder->crtc links */ 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 */
Signature · 1 line
1.9.3
PATCH 7/8 drm: convert crtc and connection_mutex to ww_mutex (v3)
In reply to Rob ClarkFor atomic, it will be quite necessary to not need 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 and drm_modeset_acquire_ctx to track acquired locks.
Atomic will use this to keep track of which locks have been acquired in a transaction.
v1: original
v2: remove a few things not needed until atomic, for now
v3: update for v3 of connection_mutex patch..
--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_crtc.c | 85 +++++++++++----- drivers/gpu/drm/drm_crtc_helper.c | 3 +- drivers/gpu/drm/drm_fb_helper.c | 4 + drivers/gpu/drm/drm_modeset_lock.c | 179 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_plane_helper.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 5 +- drivers/gpu/drm/i915/intel_display.c | 58 +++++++---- drivers/gpu/drm/i915/intel_dp.c | 14 +-- drivers/gpu/drm/i915/intel_drv.h | 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/i915/intel_tv.c | 5 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- include/drm/drmP.h | 5 - include/drm/drm_crtc.h | 15 +-- include/drm/drm_modeset_lock.h | 103 +++++++++++++++++++ 20 files changed, 434 insertions(+), 88 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_plane_helper.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_crtc.c +63 -22
192 lines not on this page · raw message
drivers/gpu/drm/drm_crtc_helper.c +1 -2
@@ -89,8 +89,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)struct drm_device *dev = encoder->dev;WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); -WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); - +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder == encoder)return true;
drivers/gpu/drm/drm_fb_helper.c +4 -0
@@ -331,6 +331,10 @@ static bool drm_fb_helper_force_kernel_mode(void)if (dev->switch_power_state ==DRM_SWITCH_POWER_OFF )continue ; +/* 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)) { error = true;continue ;
drivers/gpu/drm/drm_modeset_lock.c new file +179 -0
179 lines not on this page · raw message
drivers/gpu/drm/drm_plane_helper.c +1 -1
@@ -59,7 +59,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,* need to grab the connection_mutex here to be able to make these * checks. */ -WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder && connector->encoder->crtc == crtc) {
drivers/gpu/drm/i915/intel_crt.c +3 -2
@@ -630,6 +630,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)enum intel_display_power_domain power_domain;enum drm_connector_status status;struct intel_load_detect_pipe tmp; +struct drm_modeset_acquire_ctx ctx;intel_runtime_pm_get (dev_priv);
@@ -673,12 +674,12 @@ intel_crt_detect(struct drm_connector *connector, bool force) }/* for pre-945g platforms use load detect */ -if (intel_get_load_detect_pipe (connector,NULL , &tmp)) { +if (intel_get_load_detect_pipe (connector,NULL , &tmp, &ctx)) {if (intel_crt_detect_ddc (connector)) status = connector_status_connected;else status =intel_crt_load_detect (crt); -intel_release_load_detect_pipe (connector, &tmp); +intel_release_load_detect_pipe (connector, &tmp, &ctx); }else status = connector_status_unknown;
drivers/gpu/drm/i915/intel_display.c +38 -20
148 lines not on this page · raw message
drivers/gpu/drm/i915/intel_dp.c +7 -7
@@ -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.connection_mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex); }static void edp_panel_vdd_off (struct intel_dp *intel_dp,bool sync)
@@ -3384,9 +3384,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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex); }kfree (intel_dig_port); }
@@ -3965,9 +3965,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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex); }drm_sysfs_connector_remove (connector);drm_connector_cleanup (connector);
drivers/gpu/drm/i915/intel_drv.h +4 -2
@@ -721,9 +721,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, struct intel_digital_port *dport);bool intel_get_load_detect_pipe (struct drm_connector *connector,struct drm_display_mode *mode, -struct intel_load_detect_pipe *old); +struct intel_load_detect_pipe *old, +struct drm_modeset_acquire_ctx *ctx);void intel_release_load_detect_pipe (struct drm_connector *connector, -struct intel_load_detect_pipe *old); +struct intel_load_detect_pipe *old, +struct drm_modeset_acquire_ctx *ctx);int intel_pin_and_fence_fb_obj (struct drm_device *dev,struct drm_i915_gem_object *obj,struct intel_ring_buffer *pipelined);
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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_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.connection_mutex)); +BUG_ON (!drm_modeset_is_locked (&dev->mode_config.connection_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.connection_mutex)); +BUG_ON (!drm_modeset_is_locked (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL ); ret =intel_panel_get_backlight (connector); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_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/i915/intel_tv.c +3 -2
@@ -1321,10 +1321,11 @@ intel_tv_detect(struct drm_connector *connector, bool force)if (force) {struct intel_load_detect_pipe tmp; +struct drm_modeset_acquire_ctx ctx; -if (intel_get_load_detect_pipe (connector, &mode, &tmp)) { +if (intel_get_load_detect_pipe (connector, &mode, &tmp, &ctx)) { type =intel_tv_detect_type (intel_tv, connector); -intel_release_load_detect_pipe (connector, &tmp); +intel_release_load_detect_pipe (connector, &tmp, &ctx); }else return connector_status_unknown; }else
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);
@@ -465,7 +465,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 ();/*
@@ -510,7 +510,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,
@@ -518,7 +518,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/vmwgfx/vmwgfx_kms.c +4 -4
@@ -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 ; }
include/drm/drmP.h +0 -5
@@ -1184,11 +1184,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_crtc.h +9 -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 ;
@@ -205,6 +206,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 ;
@@ -280,6 +285,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
@@ -314,7 +320,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;
@@ -738,7 +744,8 @@ struct drm_mode_group {*/ struct drm_mode_config {struct mutex mutex;/* protects configuration (mode lists etc.) */ -struct mutex connection_mutex;/* protects connector->encoder and encoder->crtc links */ +struct drm_modeset_lock connection_mutex;/* protects connector->encoder and encoder->crtc links */ +struct drm_modeset_acquire_ctx *acquire_ctx;/* for legacy _lock_all() / _unlock_all() */ 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 */
@@ -839,10 +846,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 +103 -0
103 lines not on this page · raw message
Signature · 1 line
1.9.3
Re: [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
Quoted 8 lines · Rob Clark
For atomic, it will be quite necessary to not need to care so much about locking order. And 'state' gives us a convenient place to stash a
ww_ctxfor 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_lockanddrm_modeset_acquire_ctxto track acquired locks.
Quoted 8 lines
Atomic will use this to keep track of which locks have been acquired in a transaction.
v1: original
v2: remove a few things not needed until atomic, for now
v3: update for v3 ofconnection_mutexpatch..Signed-off-by Rob Clark <[email protected]>
Still meh about the lock_all_crtcs helper, imo that one should die. But one todo you've missed from my fixup patch is to add kerneldoc for all the locking helpers (maybe that convinces you to inline lock_all_crtcs ;-) and pull it into the drm docbook template. Otherwise nothing stuck out any more.
-Daniel
Quoted 1,119 lines
--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_crtc.c | 85 +++++++++++----- drivers/gpu/drm/drm_crtc_helper.c | 3 +- drivers/gpu/drm/drm_fb_helper.c | 4 + drivers/gpu/drm/drm_modeset_lock.c | 179 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_plane_helper.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 5 +- drivers/gpu/drm/i915/intel_display.c | 58 +++++++---- drivers/gpu/drm/i915/intel_dp.c | 14 +-- drivers/gpu/drm/i915/intel_drv.h | 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/i915/intel_tv.c | 5 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- include/drm/drmP.h | 5 - include/drm/drm_crtc.h | 15 +-- include/drm/drm_modeset_lock.h | 103 +++++++++++++++++++ 20 files changed, 434 insertions(+), 88 deletions(-) create mode 100644 drivers/gpu/drm/drm_modeset_lock.c create mode 100644 include/drm/drm_modeset_lock.hdrivers/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_modeset_lock.o drm-$(CONFIG_COMPAT) += drm_ioc32.o drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.odrivers/gpu/drm/drm_crtc.c +63
-22@@ -37,6 +37,7 @@#include <drm/drm_crtc.h> #include <drm/drm_edid.h> #include <drm/drm_fourcc.h> +#include <drm/drm_modeset_lock.h> #include "drm_crtc_internal.h" @@ -50,14 +51,42 @@*/ void drm_modeset_lock_all (struct drm_device *dev) { -struct drm_crtc *crtc; +struct drm_mode_config *config = &dev->mode_config; +struct drm_modeset_acquire_ctx *ctx; +int ret; -mutex_lock (&dev->mode_config.mutex); + ctx =kzalloc (sizeof (*ctx),GFP_KERNEL ); +if (WARN_ON (!ctx)) +return ; -mutex_lock (&dev->mode_config.connection_mutex); +mutex_lock (&config->mutex); -list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) -mutex_lock_nest_lock (&crtc->mutex, &dev->mode_config.mutex); +drm_modeset_acquire_init (ctx,0 ); + +retry: + ret =drm_modeset_lock (&config->connection_mutex, ctx); +if (ret) + goto fail; + ret =drm_modeset_lock_all_crtcs (dev, ctx); +if (ret) + goto fail; + +WARN_ON (config->acquire_ctx); + +/* now we hold the locks, so now that it is safe, stash the +* ctx for drm_modeset_unlock_all(): +*/ + config->acquire_ctx = ctx; + +drm_warn_on_modeset_not_all_locked (dev); + +return ; + +fail: +if (ret == -EDEADLK ) { +drm_modeset_backoff (ctx); + goto retry; + } }EXPORT_SYMBOL (drm_modeset_lock_all);@@ -69,12 +98,17 @@ EXPORT_SYMBOL(drm_modeset_lock_all);*/ void drm_modeset_unlock_all (struct drm_device *dev) { -struct drm_crtc *crtc; +struct drm_mode_config *config = &dev->mode_config; +struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx; -list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) -mutex_unlock (&crtc->mutex); +if (WARN_ON (!ctx)) +return ; + + config->acquire_ctx =NULL ; +drm_modeset_drop_locks (ctx); +drm_modeset_acquire_fini (ctx); -mutex_unlock (&dev->mode_config.connection_mutex); +kfree (ctx);mutex_unlock (&dev->mode_config.mutex); }@@ -95,9 +129,9 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)return ;list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) -WARN_ON (!mutex_is_locked (&crtc->mutex)); +WARN_ON (!drm_modeset_is_locked (&crtc->mutex)); -WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); }EXPORT_SYMBOL (drm_warn_on_modeset_not_all_locked);@@ -690,6 +724,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) }EXPORT_SYMBOL (drm_framebuffer_remove); +DEFINE_WW_CLASS (crtc_ww_class); +/** * drm_crtc_init_with_planes - Initialise a new CRTC object with * specified primary and cursor planes. @@ -709,6 +745,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,void *cursor, const struct drm_crtc_funcs *funcs) { + struct drm_mode_config *config = &dev->mode_config;int ret; crtc->dev = dev;@@ -716,8 +753,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, crtc->invert_dimensions = false;drm_modeset_lock_all (dev); -mutex_init (&crtc->mutex); -mutex_lock_nest_lock (&crtc->mutex, &dev->mode_config.mutex); +drm_modeset_lock_init (&crtc->mutex); +/* dropped by _unlock_all(): */ +drm_modeset_lock (&crtc->mutex, config->acquire_ctx); ret =drm_mode_object_get (dev, &crtc->base,DRM_MODE_OBJECT_CRTC );if (ret)@@ -725,8 +763,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, crtc->base.properties = &crtc->properties; -list_add_tail (&crtc->head, &dev->mode_config.crtc_list); - dev->mode_config.num_crtc++; +list_add_tail (&crtc->head, &config->crtc_list); + config->num_crtc++; crtc->primary = primary;if (primary)@@ -754,6 +792,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)kfree (crtc->gamma_store); crtc->gamma_store =NULL ; +drm_modeset_lock_fini (&crtc->mutex); +drm_mode_object_put (dev, &crtc->base);list_del (&crtc->head); dev->mode_config.num_crtc--;@@ -1817,7 +1857,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,DRM_DEBUG_KMS ("[CONNECTOR:%d:?]\n" , out_resp->connector_id);mutex_lock (&dev->mode_config.mutex); -mutex_lock (&dev->mode_config.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL ); connector =drm_connector_find (dev, out_resp->connector_id);if (!connector) {@@ -1916,7 +1956,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, out_resp->count_encoders = encoders_count; out: -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex);mutex_unlock (&dev->mode_config.mutex);return ret;@@ -2500,7 +2540,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,return -ENOENT ; } -mutex_lock (&crtc->mutex); +drm_modeset_lock (&crtc->mutex,NULL );if (req->flags &DRM_MODE_CURSOR_BO ) {if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { ret = -ENXIO ;@@ -2524,7 +2564,7 @@ static int drm_mode_cursor_common(struct drm_device *dev, } } out: -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);return ret;@@ -4217,7 +4257,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,if (!crtc)return -ENOENT ; -mutex_lock (&crtc->mutex); +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 @@ -4301,7 +4341,7 @@ out:drm_framebuffer_unreference (fb);if (old_fb)drm_framebuffer_unreference (old_fb); -mutex_unlock (&crtc->mutex); +drm_modeset_unlock (&crtc->mutex);return ret; }@@ -4666,7 +4706,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);void drm_mode_config_init (struct drm_device *dev) {mutex_init (&dev->mode_config.mutex); -mutex_init (&dev->mode_config.connection_mutex); +drm_modeset_lock_init (&dev->mode_config.connection_mutex);mutex_init (&dev->mode_config.idr_mutex);mutex_init (&dev->mode_config.fb_lock);INIT_LIST_HEAD (&dev->mode_config.fb_list);@@ -4766,5 +4806,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) }idr_destroy (&dev->mode_config.crtc_idr); +drm_modeset_lock_fini (&dev->mode_config.connection_mutex); }EXPORT_SYMBOL (drm_mode_config_cleanup);drivers/gpu/drm/drm_crtc_helper.c +1
-2@@ -89,8 +89,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)struct drm_device *dev = encoder->dev;WARN_ON (!mutex_is_locked (&dev->mode_config.mutex)); -WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); - +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder == encoder)return true;drivers/gpu/drm/drm_fb_helper.c +4
-0@@ -331,6 +331,10 @@ static bool drm_fb_helper_force_kernel_mode(void)if (dev->switch_power_state ==DRM_SWITCH_POWER_OFF )continue ; +/* 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)) { error = true;continue ;drivers/gpu/drm/drm_modeset_lock.c new file +179
-0@@ -0,0 +1,179 @@ +/* +* Copyright (C) 2014 Red Hat +* Author: Rob Clark <[email protected]> +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_modeset_lock.h> + + +void drm_modeset_acquire_init (struct drm_modeset_acquire_ctx *ctx, +uint32_t flags) +{ +ww_acquire_init (&ctx->ww_ctx, &crtc_ww_class); +INIT_LIST_HEAD (&ctx->locked); +} +EXPORT_SYMBOL (drm_modeset_acquire_init); + +void drm_modeset_acquire_fini (struct drm_modeset_acquire_ctx *ctx) +{ +ww_acquire_fini (&ctx->ww_ctx); +} +EXPORT_SYMBOL (drm_modeset_acquire_fini); + +void drm_modeset_drop_locks (struct drm_modeset_acquire_ctx *ctx) +{ +WARN_ON (ctx->contended); +while (!list_empty (&ctx->locked)) { +struct drm_modeset_lock *lock; + + lock =list_first_entry (&ctx->locked, + struct drm_modeset_lock, head); + +drm_modeset_unlock (lock); + } +} +EXPORT_SYMBOL (drm_modeset_drop_locks); + +static inline int modeset_lock (struct drm_modeset_lock *lock, +struct drm_modeset_acquire_ctx *ctx, +bool interruptible,bool slow) +{ +int ret; + +WARN_ON (ctx->contended); + +if (interruptible && slow) { + ret =ww_mutex_lock_slow_interruptible (&lock->mutex, &ctx->ww_ctx); + }else if (interruptible) { + ret =ww_mutex_lock_interruptible (&lock->mutex, &ctx->ww_ctx); + }else if (slow) { +ww_mutex_lock_slow (&lock->mutex, &ctx->ww_ctx); + ret =0 ; + }else { + ret =ww_mutex_lock (&lock->mutex, &ctx->ww_ctx); + } +if (!ret) { +WARN_ON (!list_empty (&lock->head)); +list_add (&lock->head, &ctx->locked); + }else if (ret == -EALREADY ) { +/* we already hold the lock.. this is fine. For atomic +* we will need to be able to drm_modeset_lock() things +* without having to keep track of what is already locked +* or not. +*/ + ret =0 ; + }else if (ret == -EDEADLK ) { + ctx->contended = lock; + } + +return ret; +} + +static int modeset_backoff (struct drm_modeset_acquire_ctx *ctx, +bool interruptible) +{ +struct drm_modeset_lock *contended = ctx->contended; + + ctx->contended =NULL ; + +if (WARN_ON (!contended)) +return 0 ; + +drm_modeset_drop_locks (ctx); + +return modeset_lock (contended, ctx, interruptible, true); +} + +void drm_modeset_backoff (struct drm_modeset_acquire_ctx *ctx) +{ +modeset_backoff (ctx, false); +} +EXPORT_SYMBOL (drm_modeset_backoff); + +int drm_modeset_backoff_interruptable (struct drm_modeset_acquire_ctx *ctx) +{ +return modeset_backoff (ctx, true); +} +EXPORT_SYMBOL (drm_modeset_backoff_interruptable); + +/** +* drm_modeset_lock - take modeset lock +* @lock: lock to take +* @ctx: acquire ctx +* +* If ctx is not NULL, then then it's acquire context is used +* and the lock does not need to be explicitly unlocked, it +* will be automatically unlocked when the atomic update is +* complete +*/ +int drm_modeset_lock (struct drm_modeset_lock *lock, +struct drm_modeset_acquire_ctx *ctx) +{ +if (ctx) +return modeset_lock (lock, ctx, false, false); + +ww_mutex_lock (&lock->mutex,NULL ); +return 0 ; +} +EXPORT_SYMBOL (drm_modeset_lock); + +int drm_modeset_lock_interruptible (struct drm_modeset_lock *lock, +struct drm_modeset_acquire_ctx *ctx) +{ +if (ctx) +return modeset_lock (lock, ctx, true, false); + +return ww_mutex_lock_interruptible (&lock->mutex,NULL ); +} +EXPORT_SYMBOL (drm_modeset_lock_interruptible); + +/** +* drm_modeset_unlock - drop modeset lock +* @lock: lock to release +*/ +void drm_modeset_unlock (struct drm_modeset_lock *lock) +{ +list_del_init (&lock->head); +ww_mutex_unlock (&lock->mutex); +} +EXPORT_SYMBOL (drm_modeset_unlock); + +/** +* drm_modeset_lock_all_crtcs - helper to drm_modeset_lock() all CRTCs +*/ +int drm_modeset_lock_all_crtcs (struct drm_device *dev, +struct drm_modeset_acquire_ctx *ctx) +{ +struct drm_mode_config *config = &dev->mode_config; +struct drm_crtc *crtc; +int ret =0 ; + +list_for_each_entry (crtc, &config->crtc_list, head) { + ret =drm_modeset_lock (&crtc->mutex, ctx); +if (ret) +return ret; + } + +return 0 ; +} +EXPORT_SYMBOL (drm_modeset_lock_all_crtcs);drivers/gpu/drm/drm_plane_helper.c +1
-1@@ -59,7 +59,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,* need to grab the connection_mutex here to be able to make these * checks. */ -WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));list_for_each_entry (connector, &dev->mode_config.connector_list, head)if (connector->encoder && connector->encoder->crtc == crtc) {drivers/gpu/drm/i915/intel_crt.c +3
-2@@ -630,6 +630,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)enum intel_display_power_domain power_domain;enum drm_connector_status status;struct intel_load_detect_pipe tmp; +struct drm_modeset_acquire_ctx ctx;intel_runtime_pm_get (dev_priv);@@ -673,12 +674,12 @@ intel_crt_detect(struct drm_connector *connector, bool force) }/* for pre-945g platforms use load detect */ -if (intel_get_load_detect_pipe (connector,NULL , &tmp)) { +if (intel_get_load_detect_pipe (connector,NULL , &tmp, &ctx)) {if (intel_crt_detect_ddc (connector)) status = connector_status_connected;else status =intel_crt_load_detect (crt); -intel_release_load_detect_pipe (connector, &tmp); +intel_release_load_detect_pipe (connector, &tmp, &ctx); }else status = connector_status_unknown;drivers/gpu/drm/i915/intel_display.c +38
-20@@ -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); } }@@ -7972,7 +7972,8 @@ mode_fits_in_fbdev(struct drm_device *dev,bool intel_get_load_detect_pipe (struct drm_connector *connector,struct drm_display_mode *mode, -struct intel_load_detect_pipe *old) +struct intel_load_detect_pipe *old, +struct drm_modeset_acquire_ctx *ctx) {struct intel_crtc *intel_crtc; struct intel_encoder *intel_encoder =@@ -7982,13 +7983,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,struct drm_crtc *crtc =NULL ;struct drm_device *dev = encoder->dev;struct drm_framebuffer *fb; -int i =-1 ; +struct drm_mode_config *config = &dev->mode_config; +int ret, i =-1 ;DRM_DEBUG_KMS ("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n" , connector->base.id,drm_get_connector_name (connector), encoder->base.id,drm_get_encoder_name (encoder)); -mutex_lock (&dev->mode_config.connection_mutex); +drm_modeset_acquire_init (ctx,0 ); + +retry: + ret =drm_modeset_lock (&config->connection_mutex, ctx); +if (ret) + goto fail_unlock;/* * Algorithm gets a little messy: @@ -8004,7 +8011,9 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,if (encoder->crtc) { crtc = encoder->crtc; -mutex_lock (&crtc->mutex); + ret =drm_modeset_lock (&crtc->mutex, ctx); +if (ret) + goto fail_unlock; old->dpms_mode = connector->dpms; old->load_detect_temp = false;@@ -8017,7 +8026,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, }/* Find an unused one (if possible) */ -list_for_each_entry (possible_crtc, &dev->mode_config.crtc_list, head) { +list_for_each_entry (possible_crtc, &config->crtc_list, head) { i++;if (!(encoder->possible_crtcs & (1 << i)))continue ;@@ -8032,10 +8041,12 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,*/ if (!crtc) {DRM_DEBUG_KMS ("no pipe available for load-detect\n" ); - goto fail_unlock_connector; + goto fail_unlock; } -mutex_lock (&crtc->mutex); + ret =drm_modeset_lock (&crtc->mutex, ctx); +if (ret) + goto fail_unlock; intel_encoder->new_crtc =to_intel_crtc (crtc);to_intel_connector (connector)->new_encoder = intel_encoder;@@ -8085,15 +8096,21 @@ 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); -fail_unlock_connector: -mutex_unlock (&dev->mode_config.connection_mutex); +fail_unlock: +if (ret == -EDEADLK ) { +drm_modeset_backoff (ctx); + goto retry; + } + +drm_modeset_drop_locks (ctx); +drm_modeset_acquire_fini (ctx);return false; }void intel_release_load_detect_pipe (struct drm_connector *connector, -struct intel_load_detect_pipe *old) +struct intel_load_detect_pipe *old, +struct drm_modeset_acquire_ctx *ctx) {struct intel_encoder *intel_encoder =intel_attached_encoder (connector);@@ -8117,8 +8134,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,drm_framebuffer_unreference (old->release_fb); } -mutex_unlock (&crtc->mutex); -mutex_unlock (&connector->dev->mode_config.connection_mutex); + goto unlock;return ; }@@ -8126,8 +8142,9 @@ 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); -mutex_unlock (&connector->dev->mode_config.connection_mutex); +unlock: +drm_modeset_drop_locks (ctx); +drm_modeset_acquire_fini (ctx); } static int i9xx_pll_refclk(struct drm_device *dev,@@ -10586,7 +10603,7 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)struct drm_encoder *encoder = connector->base.encoder;struct drm_device *dev = connector->base.dev; -WARN_ON (!mutex_is_locked (&dev->mode_config.connection_mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_mutex));if (!encoder)return INVALID_PIPE ;@@ -11386,6 +11403,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)struct intel_connector *connector;struct drm_connector *crt =NULL ;struct intel_load_detect_pipe load_detect_temp; +struct drm_modeset_acquire_ctx ctx;/* We can't just switch on the pipe A, we need to set things up with a * proper mode and output configuration. As a gross hack, enable pipe A @@ -11402,8 +11420,8 @@ static void intel_enable_pipe_a(struct drm_device *dev)if (!crt)return ; -if (intel_get_load_detect_pipe (crt,NULL , &load_detect_temp)) -intel_release_load_detect_pipe (crt, &load_detect_temp); +if (intel_get_load_detect_pipe (crt,NULL , &load_detect_temp, &ctx)) +intel_release_load_detect_pipe (crt, &load_detect_temp, &ctx); }drivers/gpu/drm/i915/intel_dp.c +7
-7@@ -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.connection_mutex)); +WARN_ON (!drm_modeset_is_locked (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex); }static void edp_panel_vdd_off (struct intel_dp *intel_dp,bool sync)@@ -3384,9 +3384,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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex); }kfree (intel_dig_port); }@@ -3965,9 +3965,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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL );edp_panel_vdd_off_sync (intel_dp); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_mutex); }drm_sysfs_connector_remove (connector);drm_connector_cleanup (connector);drivers/gpu/drm/i915/intel_drv.h +4
-2@@ -721,9 +721,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, struct intel_digital_port *dport);bool intel_get_load_detect_pipe (struct drm_connector *connector,struct drm_display_mode *mode, -struct intel_load_detect_pipe *old); +struct intel_load_detect_pipe *old, +struct drm_modeset_acquire_ctx *ctx);void intel_release_load_detect_pipe (struct drm_connector *connector, -struct intel_load_detect_pipe *old); +struct intel_load_detect_pipe *old, +struct drm_modeset_acquire_ctx *ctx);int intel_pin_and_fence_fb_obj (struct drm_device *dev,struct drm_i915_gem_object *obj,struct intel_ring_buffer *pipelined);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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_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.connection_mutex)); +BUG_ON (!drm_modeset_is_locked (&dev->mode_config.connection_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.connection_mutex)); +BUG_ON (!drm_modeset_is_locked (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_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.connection_mutex); +drm_modeset_lock (&dev->mode_config.connection_mutex,NULL ); ret =intel_panel_get_backlight (connector); -mutex_unlock (&dev->mode_config.connection_mutex); +drm_modeset_unlock (&dev->mode_config.connection_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/i915/intel_tv.c +3
-2@@ -1321,10 +1321,11 @@ intel_tv_detect(struct drm_connector *connector, bool force)if (force) {struct intel_load_detect_pipe tmp; +struct drm_modeset_acquire_ctx ctx; -if (intel_get_load_detect_pipe (connector, &mode, &tmp)) { +if (intel_get_load_detect_pipe (connector, &mode, &tmp, &ctx)) { type =intel_tv_detect_type (intel_tv, connector); -intel_release_load_detect_pipe (connector, &tmp); +intel_release_load_detect_pipe (connector, &tmp, &ctx); }else return connector_status_unknown; }else 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);@@ -465,7 +465,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 ();/* @@ -510,7 +510,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,@@ -518,7 +518,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/vmwgfx/vmwgfx_kms.c +4
-4@@ -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 ; }include/drm/drmP.h +0
-5@@ -1184,11 +1184,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_crtc.h +9
-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 ;@@ -205,6 +206,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 ;@@ -280,6 +285,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 @@ -314,7 +320,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;@@ -738,7 +744,8 @@ struct drm_mode_group {*/ struct drm_mode_config {struct mutex mutex;/* protects configuration (mode lists etc.) */ -struct mutex connection_mutex;/* protects connector->encoder and encoder->crtc links */ +struct drm_modeset_lock connection_mutex;/* protects connector->encoder and encoder->crtc links */ +struct drm_modeset_acquire_ctx *acquire_ctx;/* for legacy _lock_all() / _unlock_all() */ 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 */ @@ -839,10 +846,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 +103
-0@@ -0,0 +1,103 @@ +/* +* Copyright (C) 2014 Red Hat +* Author: Rob Clark <[email protected]> +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef DRM_MODESET_LOCK_H_ +#define DRM_MODESET_LOCK_H_ + +#include <linux/ww_mutex.h> + +struct drm_modeset_lock ; + +struct drm_modeset_acquire_ctx { + +struct ww_acquire_ctx ww_ctx; + +/* contended lock: if a lock is contended you should only call +* drm_modeset_backoff() which drops locks and slow-locks the +* contended lock. +*/ +struct drm_modeset_lock *contended; + +/* list of 'struct drm_modeset_lock': */ +struct list_head locked; +}; + +/** +* drm_modeset_lock - used for locking modeset resources. +* @mutex: resource locking +* @atomic_pending: is this resource part of a still-pending +* atomic update +* @head: used to hold it's place on state->locked list when +* part of an atomic update +* +* Used for locking CRTCs and other modeset resources. +*/ +struct drm_modeset_lock { +/** +* modeset lock +*/ +struct ww_mutex mutex; + +/** +* Resources that are locked as part of an atomic update are added +* to a list (so we know what to unlock at the end). +*/ +struct list_head head; +}; + +extern struct ww_class crtc_ww_class; + +void drm_modeset_acquire_init (struct drm_modeset_acquire_ctx *ctx, +uint32_t flags); +void drm_modeset_acquire_fini (struct drm_modeset_acquire_ctx *ctx); +void drm_modeset_drop_locks (struct drm_modeset_acquire_ctx *ctx); +void drm_modeset_backoff (struct drm_modeset_acquire_ctx *ctx); +int drm_modeset_backoff_interruptable (struct drm_modeset_acquire_ctx *ctx); + +static inline void drm_modeset_lock_init (struct drm_modeset_lock *lock) +{ +ww_mutex_init (&lock->mutex, &crtc_ww_class); +INIT_LIST_HEAD (&lock->head); +} + +static inline void drm_modeset_lock_fini (struct drm_modeset_lock *lock) +{ +WARN_ON (!list_empty (&lock->head)); +} + +static inline bool drm_modeset_is_locked (struct drm_modeset_lock *lock) +{ +return ww_mutex_is_locked (&lock->mutex); +} + +int drm_modeset_lock (struct drm_modeset_lock *lock, +struct drm_modeset_acquire_ctx *ctx); +int drm_modeset_lock_interruptible (struct drm_modeset_lock *lock, +struct drm_modeset_acquire_ctx *ctx); +void drm_modeset_unlock (struct drm_modeset_lock *lock); + +struct drm_device ; +int drm_modeset_lock_all_crtcs (struct drm_device *dev, +struct drm_modeset_acquire_ctx *ctx); + +#endif /* DRM_MODESET_LOCK_H_ */ Signature · 1 line
1.9.3
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Dave Airlie
maintainerRe: [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
Quoted 16 lines · Daniel Vetter
Quoted 15 lines · Rob Clark
For atomic, it will be quite necessary to not need to care so much about locking order. And 'state' gives us a convenient place to stash a
ww_ctxfor 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_lockanddrm_modeset_acquire_ctxto track acquired locks.Atomic will use this to keep track of which locks have been acquired in a transaction.
v1: original
v2: remove a few things not needed until atomic, for now
v3: update for v3 ofconnection_mutexpatch..
Quoted 7 lines
Quoted 1 line
Signed-off-by Rob Clark <[email protected]>Still meh about the
lock_all_crtcshelper, imo that one should die. But one todo you've missed from my fixup patch is to add kerneldoc for all the locking helpers (maybe that convinces you to inlinelock_all_crtcs;-) and pull it into the drm docbook template. Otherwise nothing stuck out any more.
I'm happy to apply this one if we get some kerneldoc into it.
I've applied the previous patches to drm-next, there was one conflict in i915, but I think I fixed it up okay, f7ef3fa77fa85b3a8a15b464efd56d0314a3231c was what it was conflicting with.
Dave.
Re: [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
Quoted 25 lines · Dave Airlie
Quoted 16 lines · Daniel Vetter
Quoted 15 lines · Rob Clark
For atomic, it will be quite necessary to not need to care so much about locking order. And 'state' gives us a convenient place to stash a
ww_ctxfor 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_lockanddrm_modeset_acquire_ctxto track acquired locks.Atomic will use this to keep track of which locks have been acquired in a transaction.
v1: original
v2: remove a few things not needed until atomic, for now
v3: update for v3 ofconnection_mutexpatch..Quoted 7 lines
Quoted 1 line
Signed-off-by Rob Clark <[email protected]>Still meh about the
lock_all_crtcshelper, imo that one should die. But one todo you've missed from my fixup patch is to add kerneldoc for all the locking helpers (maybe that convinces you to inlinelock_all_crtcs;-) and pull it into the drm docbook template. Otherwise nothing stuck out any more.
Quoted 5 lines
I'm happy to apply this one if we get some kerneldoc into it.
I've applied the previous patches to drm-next, there was one conflict in i915, but I think I fixed it up okay,
f7ef3fa77fa85b3a8a15b464efd56d0314a3231cwas what it was conflicting with.
Yeah, I've done the modeset_lock_all specifically because of that conflict, so looks good. Could have dropped the braces too ;-) -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 8/8 drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
In reply to Rob ClarkAll drm_fb_helper_restore_fbdev_mode() call sites, save one, do the same locking. Simplify this into drm_fb_helper_restore_fbdev_mode_unlocked().
--- drivers/gpu/drm/armada/armada_fbdev.c | 4 +-- drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++---- drivers/gpu/drm/drm_fb_helper.c | 51 +++++++++++++++++++++++-------- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +-- drivers/gpu/drm/gma500/psb_drv.c | 4 +-- drivers/gpu/drm/i915/intel_fbdev.c | 6 +--- drivers/gpu/drm/msm/msm_drv.c | 7 ++--- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +-- drivers/gpu/drm/tegra/fb.c | 7 ++--- include/drm/drm_fb_helper.h | 1 + 10 files changed, 50 insertions(+), 47 deletions(-)
drivers/gpu/drm/armada/armada_fbdev.c +1 -3
@@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev) {struct armada_private *priv = dev->dev_private; -drm_modeset_lock_all (dev);if (priv->fbdev) -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev); }void armada_fbdev_fini (struct drm_device *dev)
drivers/gpu/drm/drm_fb_cma_helper.c +2 -7
@@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);*/ void drm_fbdev_cma_restore_mode (struct drm_fbdev_cma *fbdev_cma) { -if (fbdev_cma) { -struct drm_device *dev = fbdev_cma->fb_helper.dev; - -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (&fbdev_cma->fb_helper); -drm_modeset_unlock_all (dev); - } +if (fbdev_cma) +drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev_cma->fb_helper); }EXPORT_SYMBOL_GPL (drm_fbdev_cma_restore_mode);
drivers/gpu/drm/drm_fb_helper.c +38 -13
77 lines not on this page · raw message
drivers/gpu/drm/exynos/exynos_drm_fbdev.c +1 -3
@@ -375,7 +375,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)if (!private || !private->fb_helper)return ; -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (private->fb_helper); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (private->fb_helper); }
drivers/gpu/drm/gma500/psb_drv.c +1 -3
@@ -112,11 +112,9 @@ static void psb_driver_lastclose(struct drm_device *dev)struct drm_psb_private *dev_priv = dev->dev_private;struct psb_fbdev *fbdev = dev_priv->fbdev; -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (&fbdev->psb_fb_helper); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev->psb_fb_helper);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); -drm_modeset_unlock_all (dev);return ; }
drivers/gpu/drm/i915/intel_fbdev.c +1 -5
@@ -683,11 +683,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)if (!dev_priv->fbdev)return ; -drm_modeset_lock_all (dev); - - ret =drm_fb_helper_restore_fbdev_mode (&dev_priv->fbdev->helper); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (&dev_priv->fbdev->helper);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); - -drm_modeset_unlock_all (dev); }
drivers/gpu/drm/msm/msm_drv.c +2 -5
@@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)static void msm_lastclose (struct drm_device *dev) {struct msm_drm_private *priv = dev->dev_private; -if (priv->fbdev) { -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); - } +if (priv->fbdev) +drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev); }static irqreturn_t msm_irq (int irq,void *arg)
drivers/gpu/drm/omapdrm/omap_drv.c +1 -3
@@ -588,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev) } } -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev);if (ret)DBG ("failed to restore crtc mode" ); }
drivers/gpu/drm/tegra/fb.c +2 -5
@@ -346,11 +346,8 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)void tegra_fbdev_restore_mode (struct tegra_fbdev *fbdev) { -if (fbdev) { -drm_modeset_lock_all (fbdev->base.dev); -drm_fb_helper_restore_fbdev_mode (&fbdev->base); -drm_modeset_unlock_all (fbdev->base.dev); - } +if (fbdev) +drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev->base); }static void tegra_fb_output_poll_changed (struct drm_device *drm)
include/drm/drm_fb_helper.h +1 -0
@@ -109,6 +109,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info);bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper); +bool drm_fb_helper_restore_fbdev_mode_unlocked (struct drm_fb_helper *fb_helper);void drm_fb_helper_fill_var (struct fb_info *info,struct drm_fb_helper *fb_helper,uint32_t fb_width,uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
Signature · 1 line
1.9.3
Re: [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
Quoted 4 lines · Rob Clark
All
drm_fb_helper_restore_fbdev_mode()call sites, save one, do the same locking. Simplify this intodrm_fb_helper_restore_fbdev_mode_unlocked().Signed-off-by Rob Clark <[email protected]>
Presuming I'm not blind the last such user is in the fb helper itself for the panic handler. Should we drop the EXPORT_SYMBOL for the helper?
If we do that we might as well drop the _unlocked prefix and just remove locking from drivers ...
-Daniel
Quoted 247 lines
--- drivers/gpu/drm/armada/armada_fbdev.c | 4 +-- drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++---- drivers/gpu/drm/drm_fb_helper.c | 51 +++++++++++++++++++++++-------- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +-- drivers/gpu/drm/gma500/psb_drv.c | 4 +-- drivers/gpu/drm/i915/intel_fbdev.c | 6 +--- drivers/gpu/drm/msm/msm_drv.c | 7 ++--- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +-- drivers/gpu/drm/tegra/fb.c | 7 ++--- include/drm/drm_fb_helper.h | 1 + 10 files changed, 50 insertions(+), 47 deletions(-)drivers/gpu/drm/armada/armada_fbdev.c +1
-3@@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev) {struct armada_private *priv = dev->dev_private; -drm_modeset_lock_all (dev);if (priv->fbdev) -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev); }void armada_fbdev_fini (struct drm_device *dev)drivers/gpu/drm/drm_fb_cma_helper.c +2
-7@@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);*/ void drm_fbdev_cma_restore_mode (struct drm_fbdev_cma *fbdev_cma) { -if (fbdev_cma) { -struct drm_device *dev = fbdev_cma->fb_helper.dev; - -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (&fbdev_cma->fb_helper); -drm_modeset_unlock_all (dev); - } +if (fbdev_cma) +drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev_cma->fb_helper); }EXPORT_SYMBOL_GPL (drm_fbdev_cma_restore_mode);drivers/gpu/drm/drm_fb_helper.c +38
-13@@ -273,15 +273,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) }EXPORT_SYMBOL (drm_fb_helper_debug_leave); -/** -* drm_fb_helper_restore_fbdev_mode - restore fbdev configuration -* @fb_helper: fbcon to restore -* -* This should be called from driver's drm ->lastclose callback -* when implementing an fbcon on top of kms using this helper. This ensures that -* the user isn't greeted with a black screen when e.g. X dies. -*/ -bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper) +static bool restore_fbdev_mode (struct drm_fb_helper *fb_helper) {struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;@@ -311,8 +303,44 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) }return error; } +/** +* drm_fb_helper_restore_fbdev_mode - restore fbdev configuration +* @fb_helper: fbcon to restore +* @lockless: true in drm_fb_helper_force_kernel_mode() path, to avoid +* blocking in panic case, everywhere else should use false +* +* This should be called from driver's drm ->lastclose callback +* when implementing an fbcon on top of kms using this helper. This ensures that +* the user isn't greeted with a black screen when e.g. X dies. +* +* Use this variant if you need to bypass locking (panic), or already +* hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked() +*/ +bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper) +{ +return restore_fbdev_mode (fb_helper); +}EXPORT_SYMBOL (drm_fb_helper_restore_fbdev_mode); +/** +* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration +* @fb_helper: fbcon to restore +* +* This should be called from driver's drm ->lastclose callback +* when implementing an fbcon on top of kms using this helper. This ensures that +* the user isn't greeted with a black screen when e.g. X dies. +*/ +bool drm_fb_helper_restore_fbdev_mode_unlocked (struct drm_fb_helper *fb_helper) +{ +struct drm_device *dev = fb_helper->dev; +bool ret; +drm_modeset_lock_all (dev); + ret =restore_fbdev_mode (fb_helper); +drm_modeset_unlock_all (dev); +return ret; +} +EXPORT_SYMBOL (drm_fb_helper_restore_fbdev_mode_unlocked); +/* * restore fbcon display for all kms driver's using this helper, used for sysrq * and panic handling. @@ -824,7 +852,6 @@ EXPORT_SYMBOL(drm_fb_helper_check_var);int drm_fb_helper_set_par (struct fb_info *info) {struct drm_fb_helper *fb_helper = info->par; -struct drm_device *dev = fb_helper->dev;struct fb_var_screeninfo *var = &info->var;if (var->pixclock !=0 ) {@@ -832,9 +859,7 @@ int drm_fb_helper_set_par(struct fb_info *info)return -EINVAL ; } -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (fb_helper); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (fb_helper);if (fb_helper->delayed_hotplug) { fb_helper->delayed_hotplug = false;drivers/gpu/drm/exynos/exynos_drm_fbdev.c +1
-3@@ -375,7 +375,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)if (!private || !private->fb_helper)return ; -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (private->fb_helper); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (private->fb_helper); }drivers/gpu/drm/gma500/psb_drv.c +1
-3@@ -112,11 +112,9 @@ static void psb_driver_lastclose(struct drm_device *dev)struct drm_psb_private *dev_priv = dev->dev_private;struct psb_fbdev *fbdev = dev_priv->fbdev; -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (&fbdev->psb_fb_helper); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev->psb_fb_helper);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); -drm_modeset_unlock_all (dev);return ; }drivers/gpu/drm/i915/intel_fbdev.c +1
-5@@ -683,11 +683,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)if (!dev_priv->fbdev)return ; -drm_modeset_lock_all (dev); - - ret =drm_fb_helper_restore_fbdev_mode (&dev_priv->fbdev->helper); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (&dev_priv->fbdev->helper);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); - -drm_modeset_unlock_all (dev); }drivers/gpu/drm/msm/msm_drv.c +2
-5@@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)static void msm_lastclose (struct drm_device *dev) {struct msm_drm_private *priv = dev->dev_private; -if (priv->fbdev) { -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); - } +if (priv->fbdev) +drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev); }static irqreturn_t msm_irq (int irq,void *arg)drivers/gpu/drm/omapdrm/omap_drv.c +1
-3@@ -588,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev) } } -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev);if (ret)DBG ("failed to restore crtc mode" ); }drivers/gpu/drm/tegra/fb.c +2
-5@@ -346,11 +346,8 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)void tegra_fbdev_restore_mode (struct tegra_fbdev *fbdev) { -if (fbdev) { -drm_modeset_lock_all (fbdev->base.dev); -drm_fb_helper_restore_fbdev_mode (&fbdev->base); -drm_modeset_unlock_all (fbdev->base.dev); - } +if (fbdev) +drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev->base); }static void tegra_fb_output_poll_changed (struct drm_device *drm)include/drm/drm_fb_helper.h +1
-0@@ -109,6 +109,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info);bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper); +bool drm_fb_helper_restore_fbdev_mode_unlocked (struct drm_fb_helper *fb_helper);void drm_fb_helper_fill_var (struct fb_info *info,struct drm_fb_helper *fb_helper,uint32_t fb_width,uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,Signature · 1 line
1.9.3
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
Quoted 8 lines · Daniel Vetter
Quoted 4 lines · Rob Clark
All
drm_fb_helper_restore_fbdev_mode()call sites, save one, do the same locking. Simplify this intodrm_fb_helper_restore_fbdev_mode_unlocked().Signed-off-by Rob Clark <[email protected]>Presuming I'm not blind the last such user is in the fb helper itself for the panic handler. Should we drop the
EXPORT_SYMBOLfor the helper?
only reason I could think of for leaving (and for keeping the _unlocked suffix) was to catch merge issues.. leaving same name but with locking removed, it would compile fine and fail at runtime ;-)
I can remove the prototype and EXPORT_SYMBOL I suppose just to be extra sure we catch everything (because once we start doing things atomically, it won't work if drivers still wrap it with their own _lock_all())
BR,
-R
Quoted 256 lines
If we do that we might as well drop the
_unlockedprefix and just remove locking from drivers ...
-DanielQuoted 245 lines
--- drivers/gpu/drm/armada/armada_fbdev.c | 4 +-- drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++---- drivers/gpu/drm/drm_fb_helper.c | 51 +++++++++++++++++++++++-------- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +-- drivers/gpu/drm/gma500/psb_drv.c | 4 +-- drivers/gpu/drm/i915/intel_fbdev.c | 6 +--- drivers/gpu/drm/msm/msm_drv.c | 7 ++--- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +-- drivers/gpu/drm/tegra/fb.c | 7 ++--- include/drm/drm_fb_helper.h | 1 + 10 files changed, 50 insertions(+), 47 deletions(-)drivers/gpu/drm/armada/armada_fbdev.c +1
-3@@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev) {struct armada_private *priv = dev->dev_private; -drm_modeset_lock_all (dev);if (priv->fbdev) -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev); }void armada_fbdev_fini (struct drm_device *dev)drivers/gpu/drm/drm_fb_cma_helper.c +2
-7@@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);*/ void drm_fbdev_cma_restore_mode (struct drm_fbdev_cma *fbdev_cma) { -if (fbdev_cma) { -struct drm_device *dev = fbdev_cma->fb_helper.dev; - -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (&fbdev_cma->fb_helper); -drm_modeset_unlock_all (dev); - } +if (fbdev_cma) +drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev_cma->fb_helper); }EXPORT_SYMBOL_GPL (drm_fbdev_cma_restore_mode);drivers/gpu/drm/drm_fb_helper.c +38
-13@@ -273,15 +273,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) }EXPORT_SYMBOL (drm_fb_helper_debug_leave); -/** -* drm_fb_helper_restore_fbdev_mode - restore fbdev configuration -* @fb_helper: fbcon to restore -* -* This should be called from driver's drm ->lastclose callback -* when implementing an fbcon on top of kms using this helper. This ensures that -* the user isn't greeted with a black screen when e.g. X dies. -*/ -bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper) +static bool restore_fbdev_mode (struct drm_fb_helper *fb_helper) {struct drm_device *dev = fb_helper->dev;struct drm_plane *plane;@@ -311,8 +303,44 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) }return error; } +/** +* drm_fb_helper_restore_fbdev_mode - restore fbdev configuration +* @fb_helper: fbcon to restore +* @lockless: true in drm_fb_helper_force_kernel_mode() path, to avoid +* blocking in panic case, everywhere else should use false +* +* This should be called from driver's drm ->lastclose callback +* when implementing an fbcon on top of kms using this helper. This ensures that +* the user isn't greeted with a black screen when e.g. X dies. +* +* Use this variant if you need to bypass locking (panic), or already +* hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked() +*/ +bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper) +{ +return restore_fbdev_mode (fb_helper); +}EXPORT_SYMBOL (drm_fb_helper_restore_fbdev_mode); +/** +* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration +* @fb_helper: fbcon to restore +* +* This should be called from driver's drm ->lastclose callback +* when implementing an fbcon on top of kms using this helper. This ensures that +* the user isn't greeted with a black screen when e.g. X dies. +*/ +bool drm_fb_helper_restore_fbdev_mode_unlocked (struct drm_fb_helper *fb_helper) +{ +struct drm_device *dev = fb_helper->dev; +bool ret; +drm_modeset_lock_all (dev); + ret =restore_fbdev_mode (fb_helper); +drm_modeset_unlock_all (dev); +return ret; +} +EXPORT_SYMBOL (drm_fb_helper_restore_fbdev_mode_unlocked); +/* * restore fbcon display for all kms driver's using this helper, used for sysrq * and panic handling. @@ -824,7 +852,6 @@ EXPORT_SYMBOL(drm_fb_helper_check_var);int drm_fb_helper_set_par (struct fb_info *info) {struct drm_fb_helper *fb_helper = info->par; -struct drm_device *dev = fb_helper->dev;struct fb_var_screeninfo *var = &info->var;if (var->pixclock !=0 ) {@@ -832,9 +859,7 @@ int drm_fb_helper_set_par(struct fb_info *info)return -EINVAL ; } -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (fb_helper); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (fb_helper);if (fb_helper->delayed_hotplug) { fb_helper->delayed_hotplug = false;drivers/gpu/drm/exynos/exynos_drm_fbdev.c +1
-3@@ -375,7 +375,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)if (!private || !private->fb_helper)return ; -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (private->fb_helper); -drm_modeset_unlock_all (dev); +drm_fb_helper_restore_fbdev_mode_unlocked (private->fb_helper); }drivers/gpu/drm/gma500/psb_drv.c +1
-3@@ -112,11 +112,9 @@ static void psb_driver_lastclose(struct drm_device *dev)struct drm_psb_private *dev_priv = dev->dev_private;struct psb_fbdev *fbdev = dev_priv->fbdev; -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (&fbdev->psb_fb_helper); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev->psb_fb_helper);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); -drm_modeset_unlock_all (dev);return ; }drivers/gpu/drm/i915/intel_fbdev.c +1
-5@@ -683,11 +683,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)if (!dev_priv->fbdev)return ; -drm_modeset_lock_all (dev); - - ret =drm_fb_helper_restore_fbdev_mode (&dev_priv->fbdev->helper); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (&dev_priv->fbdev->helper);if (ret)DRM_DEBUG ("failed to restore crtc mode\n" ); - -drm_modeset_unlock_all (dev); }drivers/gpu/drm/msm/msm_drv.c +2
-5@@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)static void msm_lastclose (struct drm_device *dev) {struct msm_drm_private *priv = dev->dev_private; -if (priv->fbdev) { -drm_modeset_lock_all (dev); -drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); - } +if (priv->fbdev) +drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev); }static irqreturn_t msm_irq (int irq,void *arg)drivers/gpu/drm/omapdrm/omap_drv.c +1
-3@@ -588,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev) } } -drm_modeset_lock_all (dev); - ret =drm_fb_helper_restore_fbdev_mode (priv->fbdev); -drm_modeset_unlock_all (dev); + ret =drm_fb_helper_restore_fbdev_mode_unlocked (priv->fbdev);if (ret)DBG ("failed to restore crtc mode" ); }drivers/gpu/drm/tegra/fb.c +2
-5@@ -346,11 +346,8 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)void tegra_fbdev_restore_mode (struct tegra_fbdev *fbdev) { -if (fbdev) { -drm_modeset_lock_all (fbdev->base.dev); -drm_fb_helper_restore_fbdev_mode (&fbdev->base); -drm_modeset_unlock_all (fbdev->base.dev); - } +if (fbdev) +drm_fb_helper_restore_fbdev_mode_unlocked (&fbdev->base); }static void tegra_fb_output_poll_changed (struct drm_device *drm)include/drm/drm_fb_helper.h +1
-1@@ -109,6 +109,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info);bool drm_fb_helper_restore_fbdev_mode (struct drm_fb_helper *fb_helper); +bool drm_fb_helper_restore_fbdev_mode_unlocked (struct drm_fb_helper *fb_helper);void drm_fb_helper_fill_var (struct fb_info *info,struct drm_fb_helper *fb_helper,uint32_t fb_width,uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, --Quoted 2 lines
1.9.3
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Quoted 5 lines · Rob Clark
As suggested by Daniel, splitting out
ww_mutexconversion and a few other bits out. Updatedconnection_mutexwhich fixes a few things, plus split up addition of extended property types from adding object property and pull in addition of_restore_fbdev_mode_unlocked()as it does not depend on atomic.
Just a quick note for merging: I prefer we don't pull this into 3.16, at least not the locking changes. Due to the rushed merge window I didn't have any chances yet to give the connection_mutex patch a real spin in drm-intel-nightly, and none of the other drm driver maintainers have chimed in about it yet either.
-Daniel
Quoted 60 lines
Can be found at:
http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-prep
git://people.freedesktop.org/~robclark/linuxatomic-prepDaniel Vetter (1):
drm: Splitconnection_mutexout of mode_config.mutex (v3)Rob Clark (7):
drm: helpers to find mode objects
drm: add extended property types
drm: add object property type
drm: add signed-range property type
drm: spiff out FB refcnting traces
drm: convert crtc andconnection_mutextoww_mutex(v3)
drm: adddrm_fb_helper_restore_fbdev_mode_unlocked()drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/drm_crtc.c | 295 +++++++++++++++++++---------- drivers/gpu/drm/drm_crtc_helper.c | 1 + drivers/gpu/drm/drm_edid.c | 2 + drivers/gpu/drm/drm_fb_cma_helper.c | 9 +- drivers/gpu/drm/drm_fb_helper.c | 55 ++++-- drivers/gpu/drm/drm_modeset_lock.c | 179 +++++++++++++++++ drivers/gpu/drm/drm_plane_helper.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/gma500/psb_drv.c | 4 +- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/intel_crt.c | 5 +- drivers/gpu/drm/i915/intel_display.c | 60 ++++-- drivers/gpu/drm/i915/intel_dp.c | 15 +- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_fbdev.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/i915/intel_tv.c | 5 +- drivers/gpu/drm/msm/msm_drv.c | 7 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +- drivers/gpu/drm/omapdrm/omap_fb.c | 1 + drivers/gpu/drm/radeon/radeon_connectors.c | 1 + drivers/gpu/drm/tegra/fb.c | 7 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- include/drm/drmP.h | 5 - include/drm/drm_crtc.h | 81 +++++++- include/drm/drm_fb_helper.h | 1 + include/drm/drm_modeset_lock.h | 103 ++++++++++ include/uapi/drm/drm_mode.h | 15 ++ 35 files changed, 716 insertions(+), 212 deletions(-) create mode 100644 drivers/gpu/drm/drm_modeset_lock.c create mode 100644 include/drm/drm_modeset_lock.hSignature · 1 line
1.9.3
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Quoted 7 lines · Daniel Vetter
Quoted 5 lines · Rob Clark
As suggested by Daniel, splitting out
ww_mutexconversion and a few other bits out. Updatedconnection_mutexwhich fixes a few things, plus split up addition of extended property types from adding object property and pull in addition of_restore_fbdev_mode_unlocked()as it does not depend on atomic.
Quoted 5 lines
Just a quick note for merging: I prefer we don't pull this into 3.16, at least not the locking changes. Due to the rushed merge window I didn't have any chances yet to give the
connection_mutexpatch a real spin in drm-intel-nightly, and none of the other drm driver maintainers have chimed in about it yet either.
Well, it is at least worth a try.. I'd hate for another merge window to go by without at least making some progress towards atomic.
Perhaps the other driver maintainers could have a look at the locking change and lend their r-b and/or t-b?
I think the locking changes should be sound.. maybe we have to fix up one or two things during the -rc's, but not like the concept to split out connection_mutex, or usage of ww_mutex, is fundamentally broken.
The other drivers make somewhat less heavy use of mode_config.mutex directly, and should be protected from the change by drm_modeset_lock_all().. most of the other references outside of i915 are gma500/vmwgfx, plus few places that need to grab it to call drm_framebuffer_unreference() (which perhaps deserves a drm_framebuffer_unreference_unlocked() helper).
BR,
-R
Quoted 67 lines
-Daniel
Quoted 57 lines
Can be found at:
http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-prep
git://people.freedesktop.org/~robclark/linuxatomic-prepDaniel Vetter (1):
drm: Splitconnection_mutexout of mode_config.mutex (v3)Rob Clark (7):
drm: helpers to find mode objects
drm: add extended property types
drm: add object property type
drm: add signed-range property type
drm: spiff out FB refcnting traces
drm: convert crtc andconnection_mutextoww_mutex(v3)
drm: adddrm_fb_helper_restore_fbdev_mode_unlocked()drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/armada/armada_fbdev.c | 4 +- drivers/gpu/drm/drm_crtc.c | 295 +++++++++++++++++++---------- drivers/gpu/drm/drm_crtc_helper.c | 1 + drivers/gpu/drm/drm_edid.c | 2 + drivers/gpu/drm/drm_fb_cma_helper.c | 9 +- drivers/gpu/drm/drm_fb_helper.c | 55 ++++-- drivers/gpu/drm/drm_modeset_lock.c | 179 +++++++++++++++++ drivers/gpu/drm/drm_plane_helper.c | 7 + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +- drivers/gpu/drm/gma500/psb_drv.c | 4 +- drivers/gpu/drm/i915/i915_debugfs.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/intel_crt.c | 5 +- drivers/gpu/drm/i915/intel_display.c | 60 ++++-- drivers/gpu/drm/i915/intel_dp.c | 15 +- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_fbdev.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/i915/intel_tv.c | 5 +- drivers/gpu/drm/msm/msm_drv.c | 7 +- drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +- drivers/gpu/drm/omapdrm/omap_drv.c | 4 +- drivers/gpu/drm/omapdrm/omap_fb.c | 1 + drivers/gpu/drm/radeon/radeon_connectors.c | 1 + drivers/gpu/drm/tegra/fb.c | 7 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- include/drm/drmP.h | 5 - include/drm/drm_crtc.h | 81 +++++++- include/drm/drm_fb_helper.h | 1 + include/drm/drm_modeset_lock.h | 103 ++++++++++ include/uapi/drm/drm_mode.h | 15 ++ 35 files changed, 716 insertions(+), 212 deletions(-) create mode 100644 drivers/gpu/drm/drm_modeset_lock.c create mode 100644 include/drm/drm_modeset_lock.hQuoted 3 lines
--
1.9.3--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch