diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-02-10 01:22:11 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2014-02-10 01:22:11 +0000 |
commit | 13e4073c821ea2f90aeac5f1754e784b2ade1c24 (patch) | |
tree | d7e5dfc803c3eeaa25fea398af1883c2f8ded244 /sys/dev | |
parent | 613b89f5524c312e1fd94ef9b1a27e3f6c373380 (diff) |
radeon: workaround pinning failure on low ram gpu
From Jerome Glisse
9043b83c07a1899bbb094fb4f1c889aab4756a6a in ubuntu 3.8
97b6ff6be9da7675aab339334fda996d6c5077d9 in mainline linux
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/drm/radeon/radeon_legacy_crtc.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/sys/dev/pci/drm/radeon/radeon_legacy_crtc.c b/sys/dev/pci/drm/radeon/radeon_legacy_crtc.c index 4c2c1ab73f0..c4236800b75 100644 --- a/sys/dev/pci/drm/radeon/radeon_legacy_crtc.c +++ b/sys/dev/pci/drm/radeon/radeon_legacy_crtc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radeon_legacy_crtc.c,v 1.2 2013/12/05 13:29:56 kettenis Exp $ */ +/* $OpenBSD: radeon_legacy_crtc.c,v 1.3 2014/02/10 01:22:10 jsg Exp $ */ /* * Copyright 2007-8 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. @@ -423,6 +423,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; @@ -431,6 +432,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); |