drm: fb refcounting for dirtyfb_ioctl
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 10 Dec 2012 23:38:18 +0000 (00:38 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sun, 20 Jan 2013 21:17:06 +0000 (22:17 +0100)
We only need to ensure that the fb stays around for long enough. While
at it, only grab the modeset locks when we need them (since most
drivers don't implement the dirty callback, this should help jitter
and stalls when using the generic modeset driver).

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

index cba8c8bb789c868a81c58b0eac5767a1ab47ae40..d4f8fa5b3c187666aea5ead12dec8a58dcc696ab 100644 (file)
@@ -2580,14 +2580,9 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       drm_modeset_lock_all(dev);
        fb = drm_framebuffer_lookup(dev, r->fb_id);
-       if (!fb) {
-               ret = -EINVAL;
-               goto out_err1;
-       }
-       /* fb is protect by the mode_config lock, so drop the ref immediately */
-       drm_framebuffer_unreference(fb);
+       if (!fb)
+               return -EINVAL;
 
        num_clips = r->num_clips;
        clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
@@ -2625,17 +2620,19 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        }
 
        if (fb->funcs->dirty) {
+               drm_modeset_lock_all(dev);
                ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
                                       clips, num_clips);
+               drm_modeset_unlock_all(dev);
        } else {
                ret = -ENOSYS;
-               goto out_err2;
        }
 
 out_err2:
        kfree(clips);
 out_err1:
-       drm_modeset_unlock_all(dev);
+       drm_framebuffer_unreference(fb);
+
        return ret;
 }