aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
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}