diff mbox

radeon: workaround pining failure on low ram gpu

Message ID 1384271476-2122-1-git-send-email-j.glisse@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jerome Glisse Nov. 12, 2013, 3:51 p.m. UTC
From: Jerome Glisse <jglisse@redhat.com>

GPU with low amount of ram can fails at pining new framebuffer before
unpining old one. On such failure, retry with unping old one before
pining new one allowing to work around the issue. This is somewhat
ugly but only affect those old GPU we care about.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
---
 drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

Comments

Alex Deucher Nov. 14, 2013, 3:38 p.m. UTC | #1
On Tue, Nov 12, 2013 at 10:51 AM,  <j.glisse@gmail.com> wrote:
> From: Jerome Glisse <jglisse@redhat.com>
>
> GPU with low amount of ram can fails at pining new framebuffer before
> unpining old one. On such failure, retry with unping old one before
> pining new one allowing to work around the issue. This is somewhat
> ugly but only affect those old GPU we care about.
>
> Signed-off-by: Jerome Glisse <jglisse@redhat.com>

Added to my queue and added stable cc.

Thanks!

> ---
>  drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> index 0c7b8c6..0b158f9 100644
> --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
> @@ -422,6 +422,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
>         /* Pin framebuffer & get tilling informations */
>         obj = radeon_fb->obj;
>         rbo = gem_to_radeon_bo(obj);
> +retry:
>         r = radeon_bo_reserve(rbo, false);
>         if (unlikely(r != 0))
>                 return r;
> @@ -430,6 +431,33 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
>                                      &base);
>         if (unlikely(r != 0)) {
>                 radeon_bo_unreserve(rbo);
> +
> +               /* On old GPU like RN50 with little vram pining can fails because
> +                * current fb is taking all space needed. So instead of unpining
> +                * the old buffer after pining the new one, first unpin old one
> +                * and then retry pining new one.
> +                *
> +                * As only master can set mode only master can pin and it is
> +                * unlikely the master client will race with itself especialy
> +                * on those old gpu with single crtc.
> +                *
> +                * We don't shutdown the display controller because new buffer
> +                * will end up in same spot.
> +                */
> +               if (!atomic && fb && fb != crtc->fb) {
> +                       struct radeon_bo *old_rbo;
> +                       unsigned long nsize, osize;
> +
> +                       old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj);
> +                       osize = radeon_bo_size(old_rbo);
> +                       nsize = radeon_bo_size(rbo);
> +                       if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) {
> +                               radeon_bo_unpin(old_rbo);
> +                               radeon_bo_unreserve(old_rbo);
> +                               fb = NULL;
> +                               goto retry;
> +                       }
> +               }
>                 return -EINVAL;
>         }
>         radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
> --
> 1.8.3.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 0c7b8c6..0b158f9 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -422,6 +422,7 @@  int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 	/* Pin framebuffer & get tilling informations */
 	obj = radeon_fb->obj;
 	rbo = gem_to_radeon_bo(obj);
+retry:
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -430,6 +431,33 @@  int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 				     &base);
 	if (unlikely(r != 0)) {
 		radeon_bo_unreserve(rbo);
+
+		/* On old GPU like RN50 with little vram pining can fails because
+		 * current fb is taking all space needed. So instead of unpining
+		 * the old buffer after pining the new one, first unpin old one
+		 * and then retry pining new one.
+		 *
+		 * As only master can set mode only master can pin and it is
+		 * unlikely the master client will race with itself especialy
+		 * on those old gpu with single crtc.
+		 *
+		 * We don't shutdown the display controller because new buffer
+		 * will end up in same spot.
+		 */
+		if (!atomic && fb && fb != crtc->fb) {
+			struct radeon_bo *old_rbo;
+			unsigned long nsize, osize;
+
+			old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj);
+			osize = radeon_bo_size(old_rbo);
+			nsize = radeon_bo_size(rbo);
+			if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) {
+				radeon_bo_unpin(old_rbo);
+				radeon_bo_unreserve(old_rbo);
+				fb = NULL;
+				goto retry;
+			}
+		}
 		return -EINVAL;
 	}
 	radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);