aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2013-11-12 10:51:16 -0500
committerAlex Deucher <alexander.deucher@amd.com>2013-11-15 15:29:33 -0500
commit97b6ff6be9da7675aab339334fda996d6c5077d9 (patch)
tree717bf1938ad3eba008d734246baa20b68fa5ab68
parentfae009d15a44e5f1d938340facf4b8bc7dc69a09 (diff)
radeon: workaround pinning failure on low ram gpu
GPU with low amount of ram can fails at pinning new framebuffer before unpinning old one. On such failure, retry with unpinning old one before pinning 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> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 0c7b8c66301b..0b158f98d287 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,
422 /* Pin framebuffer & get tilling informations */ 422 /* Pin framebuffer & get tilling informations */
423 obj = radeon_fb->obj; 423 obj = radeon_fb->obj;
424 rbo = gem_to_radeon_bo(obj); 424 rbo = gem_to_radeon_bo(obj);
425retry:
425 r = radeon_bo_reserve(rbo, false); 426 r = radeon_bo_reserve(rbo, false);
426 if (unlikely(r != 0)) 427 if (unlikely(r != 0))
427 return r; 428 return r;
@@ -430,6 +431,33 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
430 &base); 431 &base);
431 if (unlikely(r != 0)) { 432 if (unlikely(r != 0)) {
432 radeon_bo_unreserve(rbo); 433 radeon_bo_unreserve(rbo);
434
435 /* On old GPU like RN50 with little vram pining can fails because
436 * current fb is taking all space needed. So instead of unpining
437 * the old buffer after pining the new one, first unpin old one
438 * and then retry pining new one.
439 *
440 * As only master can set mode only master can pin and it is
441 * unlikely the master client will race with itself especialy
442 * on those old gpu with single crtc.
443 *
444 * We don't shutdown the display controller because new buffer
445 * will end up in same spot.
446 */
447 if (!atomic && fb && fb != crtc->fb) {
448 struct radeon_bo *old_rbo;
449 unsigned long nsize, osize;
450
451 old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj);
452 osize = radeon_bo_size(old_rbo);
453 nsize = radeon_bo_size(rbo);
454 if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) {
455 radeon_bo_unpin(old_rbo);
456 radeon_bo_unreserve(old_rbo);
457 fb = NULL;
458 goto retry;
459 }
460 }
433 return -EINVAL; 461 return -EINVAL;
434 } 462 }
435 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); 463 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);