diff options
author | 2014-02-10 01:22:10 +0000 | |
---|---|---|
committer | 2014-02-10 01:22:10 +0000 | |
commit | c252e55e5a953951bfb5dcdf17be34bd6ba61a95 (patch) | |
tree | 537f8619a7d34483c9d1886ae007bc3ab2a30cc8 | |
parent | radeon/i2c: do not count reg index in number of i2c byte we are writing. (diff) | |
download | wireguard-openbsd-c252e55e5a953951bfb5dcdf17be34bd6ba61a95.tar.xz wireguard-openbsd-c252e55e5a953951bfb5dcdf17be34bd6ba61a95.zip |
radeon: workaround pinning failure on low ram gpu
From Jerome Glisse
9043b83c07a1899bbb094fb4f1c889aab4756a6a in ubuntu 3.8
97b6ff6be9da7675aab339334fda996d6c5077d9 in mainline linux
-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); |