summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2014-02-10 01:22:11 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2014-02-10 01:22:11 +0000
commit13e4073c821ea2f90aeac5f1754e784b2ade1c24 (patch)
treed7e5dfc803c3eeaa25fea398af1883c2f8ded244 /sys/dev
parent613b89f5524c312e1fd94ef9b1a27e3f6c373380 (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.c30
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);