[PATCH 22/37] drm: nest modeset locks within fpriv->fbs_lock

Daniel Vetter daniel.vetter at ffwll.ch
Wed Dec 12 05:07:02 PST 2012


Atm we still need to unconditionally take the modeset locks in the
rmfb paths. But eventually we only want to take them if there are
other users around as a slow-path. This way sane userspace avoids
blocking on edid reads and other stuff in rmfb if it ensures that the
fb isn't used anywhere by a crtc/plane.

We can do a quick check for such other users once framebuffers are
properly refcounting by locking at the refcount - if it's more than 1,
there are other users left. Again, rmfb racing against other ioctls
isn't a real problem, userspace is allowed to shoot its foot.

This patch just prepares this by moving the modeset locks to nest
within fpriv->fbs_lock. Now the distinction between the fbs_lock and
the device-global fb_lock is clear, since we need to hold the fbs_lock
outside of any modeset_locks in fb_release.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/drm_crtc.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 20ccdc4..33e95bb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2266,13 +2266,13 @@ int drm_mode_addfb(struct drm_device *dev,
 		drm_modeset_unlock_all(dev);
 		return PTR_ERR(fb);
 	}
+	drm_modeset_unlock_all(dev);
 
 	mutex_lock(&file_priv->fbs_lock);
 	or->fb_id = fb->base.id;
 	list_add(&fb->filp_head, &file_priv->fbs);
 	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
 	mutex_unlock(&file_priv->fbs_lock);
-	drm_modeset_unlock_all(dev);
 
 	return ret;
 }
@@ -2449,6 +2449,7 @@ int drm_mode_addfb2(struct drm_device *dev,
 		drm_modeset_unlock_all(dev);
 		return PTR_ERR(fb);
 	}
+	drm_modeset_unlock_all(dev);
 
 	mutex_lock(&file_priv->fbs_lock);
 	r->fb_id = fb->base.id;
@@ -2456,7 +2457,6 @@ int drm_mode_addfb2(struct drm_device *dev,
 	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
 	mutex_unlock(&file_priv->fbs_lock);
 
-	drm_modeset_unlock_all(dev);
 
 	return ret;
 }
@@ -2651,7 +2651,6 @@ void drm_fb_release(struct drm_file *priv)
 	struct drm_device *dev = priv->minor->dev;
 	struct drm_framebuffer *fb, *tfb;
 
-	drm_modeset_lock_all(dev);
 	mutex_lock(&priv->fbs_lock);
 	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
 
@@ -2663,10 +2662,11 @@ void drm_fb_release(struct drm_file *priv)
 		list_del_init(&fb->filp_head);
 
 		/* This will also drop the fpriv->fbs reference. */
+		drm_modeset_lock_all(dev);
 		drm_framebuffer_remove(fb);
+		drm_modeset_unlock_all(dev);
 	}
 	mutex_unlock(&priv->fbs_lock);
-	drm_modeset_unlock_all(dev);
 }
 
 /**
-- 
1.7.10.4



More information about the dri-devel mailing list