aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2017-12-20 04:35:43 -0500
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2017-12-20 08:49:06 -0500
commitce0769e0ea4b3e192466243a1a9fd39acf214f1e (patch)
treeb1ae3ef6f6f9f4822d0d742b1a4f53cf32f54fea
parent2c08cd7c20968ddf71feeac2265b4741d2b3fdde (diff)
drm/plane: Make framebuffer refcounting the responsibility of setplane_internal callers
lock_all_ctx in setplane_internal may return -EINTR, and __setplane_internal could return -EDEADLK. Making more special cases for fb would make the code even harder to read, so the easiest solution is not taking over the fb refcount, and making callers responsible for dropping the ref. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102707 Fixes: 13736ba3b38b ("drm/legacy: Convert setplane ioctl locking to interruptible.") Testcase: kms_atomic_interruptible Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171220093545.613-2-maarten.lankhorst@linux.intel.com Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_plane.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 37a93cdffb4a..2c90519576a3 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -558,11 +558,10 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
558} 558}
559 559
560/* 560/*
561 * setplane_internal - setplane handler for internal callers 561 * __setplane_internal - setplane handler for internal callers
562 * 562 *
563 * Note that we assume an extra reference has already been taken on fb. If the 563 * This function will take a reference on the new fb for the plane
564 * update fails, this reference will be dropped before return; if it succeeds, 564 * on success.
565 * the previous framebuffer (if any) will be unreferenced instead.
566 * 565 *
567 * src_{x,y,w,h} are provided in 16.16 fixed point format 566 * src_{x,y,w,h} are provided in 16.16 fixed point format
568 */ 567 */
@@ -630,14 +629,12 @@ static int __setplane_internal(struct drm_plane *plane,
630 if (!ret) { 629 if (!ret) {
631 plane->crtc = crtc; 630 plane->crtc = crtc;
632 plane->fb = fb; 631 plane->fb = fb;
633 fb = NULL; 632 drm_framebuffer_get(plane->fb);
634 } else { 633 } else {
635 plane->old_fb = NULL; 634 plane->old_fb = NULL;
636 } 635 }
637 636
638out: 637out:
639 if (fb)
640 drm_framebuffer_put(fb);
641 if (plane->old_fb) 638 if (plane->old_fb)
642 drm_framebuffer_put(plane->old_fb); 639 drm_framebuffer_put(plane->old_fb);
643 plane->old_fb = NULL; 640 plane->old_fb = NULL;
@@ -685,6 +682,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
685 struct drm_plane *plane; 682 struct drm_plane *plane;
686 struct drm_crtc *crtc = NULL; 683 struct drm_crtc *crtc = NULL;
687 struct drm_framebuffer *fb = NULL; 684 struct drm_framebuffer *fb = NULL;
685 int ret;
688 686
689 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 687 if (!drm_core_check_feature(dev, DRIVER_MODESET))
690 return -EINVAL; 688 return -EINVAL;
@@ -717,15 +715,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
717 } 715 }
718 } 716 }
719 717
720 /* 718 ret = setplane_internal(plane, crtc, fb,
721 * setplane_internal will take care of deref'ing either the old or new 719 plane_req->crtc_x, plane_req->crtc_y,
722 * framebuffer depending on success. 720 plane_req->crtc_w, plane_req->crtc_h,
723 */ 721 plane_req->src_x, plane_req->src_y,
724 return setplane_internal(plane, crtc, fb, 722 plane_req->src_w, plane_req->src_h);
725 plane_req->crtc_x, plane_req->crtc_y, 723
726 plane_req->crtc_w, plane_req->crtc_h, 724 if (fb)
727 plane_req->src_x, plane_req->src_y, 725 drm_framebuffer_put(fb);
728 plane_req->src_w, plane_req->src_h); 726
727 return ret;
729} 728}
730 729
731static int drm_mode_cursor_universal(struct drm_crtc *crtc, 730static int drm_mode_cursor_universal(struct drm_crtc *crtc,
@@ -788,13 +787,12 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
788 src_h = fb->height << 16; 787 src_h = fb->height << 16;
789 } 788 }
790 789
791 /*
792 * setplane_internal will take care of deref'ing either the old or new
793 * framebuffer depending on success.
794 */
795 ret = __setplane_internal(crtc->cursor, crtc, fb, 790 ret = __setplane_internal(crtc->cursor, crtc, fb,
796 crtc_x, crtc_y, crtc_w, crtc_h, 791 crtc_x, crtc_y, crtc_w, crtc_h,
797 0, 0, src_w, src_h, ctx); 792 0, 0, src_w, src_h, ctx);
793
794 if (fb)
795 drm_framebuffer_put(fb);
798 796
799 /* Update successful; save new cursor position, if necessary */ 797 /* Update successful; save new cursor position, if necessary */
800 if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { 798 if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {