aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-12-10 18:59:24 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-20 16:17:08 -0500
commit6c2a75325c800de286166c693e0cd33c3a1c5ec8 (patch)
treeee9fd562cb9f11e944b2146e59b0f3561492400b /drivers/gpu/drm/drm_crtc.c
parent4ccf097f1935321f03ad36218588a9e446006b6a (diff)
drm: refcounting for sprite framebuffers
Now plane->fb holds a reference onto it's framebuffer. Nothing too fancy going on here: - Extract __drm_framebuffer_unreference to be called when we know we're not dropping the last reference, e.g. useful in the fb cleanup code. - Reduce the locked sections in the set_plane ioctl to only protect plane->fb/plane->crtc and the driver callback (i.e. hw state). Everything either doesn't disappear (crtc, plane) or is refcounted (fb), and all the data we check is invariant over the respective object's lifetimes. Reviewed-by: Rob Clark <rob@ti.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d4f8fa5b3c18..64ef12079528 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -445,6 +445,12 @@ static void drm_framebuffer_free_bug(struct kref *kref)
445 BUG(); 445 BUG();
446} 446}
447 447
448static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
449{
450 DRM_DEBUG("FB ID: %d\n", fb->base.id);
451 kref_put(&fb->refcount, drm_framebuffer_free_bug);
452}
453
448/* dev->mode_config.fb_lock must be held! */ 454/* dev->mode_config.fb_lock must be held! */
449static void __drm_framebuffer_unregister(struct drm_device *dev, 455static void __drm_framebuffer_unregister(struct drm_device *dev,
450 struct drm_framebuffer *fb) 456 struct drm_framebuffer *fb)
@@ -455,7 +461,7 @@ static void __drm_framebuffer_unregister(struct drm_device *dev,
455 461
456 fb->base.id = 0; 462 fb->base.id = 0;
457 463
458 kref_put(&fb->refcount, drm_framebuffer_free_bug); 464 __drm_framebuffer_unreference(fb);
459} 465}
460 466
461/** 467/**
@@ -544,6 +550,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
544 if (ret) 550 if (ret)
545 DRM_ERROR("failed to disable plane with busy fb\n"); 551 DRM_ERROR("failed to disable plane with busy fb\n");
546 /* disconnect the plane from the fb and crtc: */ 552 /* disconnect the plane from the fb and crtc: */
553 __drm_framebuffer_unreference(plane->fb);
547 plane->fb = NULL; 554 plane->fb = NULL;
548 plane->crtc = NULL; 555 plane->crtc = NULL;
549 } 556 }
@@ -1850,7 +1857,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
1850 struct drm_mode_object *obj; 1857 struct drm_mode_object *obj;
1851 struct drm_plane *plane; 1858 struct drm_plane *plane;
1852 struct drm_crtc *crtc; 1859 struct drm_crtc *crtc;
1853 struct drm_framebuffer *fb; 1860 struct drm_framebuffer *fb = NULL, *old_fb = NULL;
1854 int ret = 0; 1861 int ret = 0;
1855 unsigned int fb_width, fb_height; 1862 unsigned int fb_width, fb_height;
1856 int i; 1863 int i;
@@ -1858,8 +1865,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
1858 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1865 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1859 return -EINVAL; 1866 return -EINVAL;
1860 1867
1861 drm_modeset_lock_all(dev);
1862
1863 /* 1868 /*
1864 * First, find the plane, crtc, and fb objects. If not available, 1869 * First, find the plane, crtc, and fb objects. If not available,
1865 * we don't bother to call the driver. 1870 * we don't bother to call the driver.
@@ -1869,16 +1874,18 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
1869 if (!obj) { 1874 if (!obj) {
1870 DRM_DEBUG_KMS("Unknown plane ID %d\n", 1875 DRM_DEBUG_KMS("Unknown plane ID %d\n",
1871 plane_req->plane_id); 1876 plane_req->plane_id);
1872 ret = -ENOENT; 1877 return -ENOENT;
1873 goto out;
1874 } 1878 }
1875 plane = obj_to_plane(obj); 1879 plane = obj_to_plane(obj);
1876 1880
1877 /* No fb means shut it down */ 1881 /* No fb means shut it down */
1878 if (!plane_req->fb_id) { 1882 if (!plane_req->fb_id) {
1883 drm_modeset_lock_all(dev);
1884 old_fb = plane->fb;
1879 plane->funcs->disable_plane(plane); 1885 plane->funcs->disable_plane(plane);
1880 plane->crtc = NULL; 1886 plane->crtc = NULL;
1881 plane->fb = NULL; 1887 plane->fb = NULL;
1888 drm_modeset_unlock_all(dev);
1882 goto out; 1889 goto out;
1883 } 1890 }
1884 1891
@@ -1899,8 +1906,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
1899 ret = -ENOENT; 1906 ret = -ENOENT;
1900 goto out; 1907 goto out;
1901 } 1908 }
1902 /* fb is protect by the mode_config lock, so drop the ref immediately */
1903 drm_framebuffer_unreference(fb);
1904 1909
1905 /* Check whether this plane supports the fb pixel format. */ 1910 /* Check whether this plane supports the fb pixel format. */
1906 for (i = 0; i < plane->format_count; i++) 1911 for (i = 0; i < plane->format_count; i++)
@@ -1946,18 +1951,25 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
1946 goto out; 1951 goto out;
1947 } 1952 }
1948 1953
1954 drm_modeset_lock_all(dev);
1949 ret = plane->funcs->update_plane(plane, crtc, fb, 1955 ret = plane->funcs->update_plane(plane, crtc, fb,
1950 plane_req->crtc_x, plane_req->crtc_y, 1956 plane_req->crtc_x, plane_req->crtc_y,
1951 plane_req->crtc_w, plane_req->crtc_h, 1957 plane_req->crtc_w, plane_req->crtc_h,
1952 plane_req->src_x, plane_req->src_y, 1958 plane_req->src_x, plane_req->src_y,
1953 plane_req->src_w, plane_req->src_h); 1959 plane_req->src_w, plane_req->src_h);
1954 if (!ret) { 1960 if (!ret) {
1961 old_fb = plane->fb;
1962 fb = NULL;
1955 plane->crtc = crtc; 1963 plane->crtc = crtc;
1956 plane->fb = fb; 1964 plane->fb = fb;
1957 } 1965 }
1966 drm_modeset_unlock_all(dev);
1958 1967
1959out: 1968out:
1960 drm_modeset_unlock_all(dev); 1969 if (fb)
1970 drm_framebuffer_unreference(fb);
1971 if (old_fb)
1972 drm_framebuffer_unreference(old_fb);
1961 1973
1962 return ret; 1974 return ret;
1963} 1975}