drm: push modeset_lock_all into ->fb_create driver callbacks
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 10 Dec 2012 23:09:12 +0000 (00:09 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sun, 20 Jan 2013 21:17:04 +0000 (22:17 +0100)
And drop it where it's not needed. Most driver just lookup the gem
object, allocate an fb struct, fill in all the useful fields and then
register it with drm_framebuffer_init.

All of these operations are already separately locked, and since we
only put the fb into the fpriv->fbs list _after_ having called
->fb_create, we can't also race with rmfb. We can otoh race with other
ioctls that put the framebuffer to use, but all drivers have been
reorganized already to call drm_framebuffer_init last in the fb
creation sequence.

So essentially, we can completely remove any modeset locks from the
addfb ioctl paths. Yeah!

Also, reference-counting is solid - we get a reference from fb_create
which we transfer to the fpriv->fbs list. And after unlocking the
fpriv->fbs_lock we don't touch the framebuffer any longer. Furthermore
drm_framebuffer_init has added a 2nd reference for the idr lookup, and
any access through that table will do it's own refcounting.

Reviewed-by: Rob Clark <rob@ti.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_crtc.c

index 09e02a7023f9cc45841657d557117edea7ee96b1..2e6103c5d63252ff80ebba280d72010f7ed64ad4 100644 (file)
@@ -2271,18 +2271,12 @@ int drm_mode_addfb(struct drm_device *dev,
        if ((config->min_height > r.height) || (r.height > config->max_height))
                return -EINVAL;
 
-       drm_modeset_lock_all(dev);
-
-       /* TODO check buffer is sufficiently large */
-       /* TODO setup destructor callback */
-
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("could not create framebuffer\n");
                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;
@@ -2457,15 +2451,12 @@ int drm_mode_addfb2(struct drm_device *dev,
        if (ret)
                return ret;
 
-       drm_modeset_lock_all(dev);
-
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("could not create framebuffer\n");
                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;