[PATCH 16/17] drm: more conservative locking

Rob Clark robdclark at gmail.com
Sat May 24 11:30:25 PDT 2014


TODO possibly just squash this back into "convert crtc/plane to
atomic"..

This reintroduces drm_modeset_lock_all() in a places that had not been
converted to more fine grained locking (setcrtc, setplane, etc).  This
makes the locking equivalent to before.

Note that since mode_config.mutex is a drm_modeset_lock, the lock is
automatically dropped at the end of the atomic update.

Signed-off-by: Rob Clark <robdclark at gmail.com>
---
 drivers/gpu/drm/drm_crtc.c      | 21 +++++++++++++++++++++
 drivers/gpu/drm/drm_fb_helper.c | 18 +++++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 972af76..4e3b527 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -709,14 +709,22 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 	 * in this manner.
 	 */
 	if (atomic_read(&fb->refcount.refcount) > 1) {
+		struct drm_mode_config *config = &dev->mode_config;
 		struct drm_atomic_state *state;
+		int ret;
 
+retry:
 		state = dev->driver->atomic_begin(dev, 0);
 		if (IS_ERR(state)) {
 			DRM_ERROR("failed to disable crtc and/or plane when fb was deleted\n");
 			return;
 		}
 
+		ret = drm_modeset_lock(&config->mutex, &state->acquire_ctx) ||
+				drm_modeset_lock_all_crtcs(dev, &state->acquire_ctx);
+		if (ret)
+			goto out;
+
 		/* remove from any plane */
 		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
 			if (plane->fb == fb)
@@ -729,7 +737,10 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
 		else
 			dev->driver->atomic_commit(dev, state);
 
+out:
 		dev->driver->atomic_end(dev, state);
+		if (ret == -EDEADLK)
+			goto retry;
 	}
 
 	drm_framebuffer_unreference(fb);
@@ -2595,6 +2606,11 @@ retry:
 	if (IS_ERR(state))
 		return PTR_ERR(state);
 
+	ret = drm_modeset_lock(&config->mutex, &state->acquire_ctx) ||
+			drm_modeset_lock_all_crtcs(dev, &state->acquire_ctx);
+	if (ret)
+		goto out;
+
 	plane = drm_plane_find(dev, plane_req->plane_id);
 	if (!plane) {
 		DRM_DEBUG_KMS("Unknown plane ID %d\n",
@@ -2810,6 +2826,11 @@ retry:
 	if (IS_ERR(state))
 		return PTR_ERR(state);
 
+	ret = drm_modeset_lock(&config->mutex, &state->acquire_ctx) ||
+			drm_modeset_lock_all_crtcs(dev, &state->acquire_ctx);
+	if (ret)
+		goto out;
+
 	/* If connectors change, we need to check if we need to steal one
 	 * from another CRTC..  setcrtc makes this implicit, but atomic
 	 * treats it as an error so we need to handle here:
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 3815e1a..4dc22cf 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -287,11 +288,13 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper,
 		bool lockless)
 {
 	struct drm_device *dev = fb_helper->dev;
+	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_plane *plane;
 	bool error = false;
 	struct drm_atomic_state *state;
-	int i;
+	int ret, i;
 
+retry:
 	state = dev->driver->atomic_begin(dev, lockless ?
 			DRM_MODE_ATOMIC_NOLOCK : 0);
 	if (IS_ERR(state)) {
@@ -299,6 +302,11 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper,
 		return true;
 	}
 
+	ret = drm_modeset_lock(&config->mutex, &state->acquire_ctx) ||
+			drm_modeset_lock_all_crtcs(dev, &state->acquire_ctx);
+	if (ret)
+		goto out;
+
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
 		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
 			drm_plane_force_disable(plane, state);
@@ -309,7 +317,12 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper,
 	else
 		dev->driver->atomic_commit(dev, state);
 
+out:
 	dev->driver->atomic_end(dev, state);
+	if (ret == -EDEADLK)
+		goto retry;
+
+	drm_modeset_lock_all(dev);
 
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
@@ -326,6 +339,9 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper,
 		if (ret)
 			error = true;
 	}
+
+	drm_modeset_unlock_all(dev);
+
 	return error;
 }
 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
-- 
1.9.0



More information about the dri-devel mailing list