Message ID | 1384271476-2122-1-git-send-email-j.glisse@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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 --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);