summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2008-03-24 13:01:35 +1100
committerBen Skeggs <[email protected]>2008-03-24 13:06:29 +1100
commit46a7f297a1477b9b59a5a11bf090db0ecbdf1ed7 (patch)
tree8429ce6afc61281cde5c63139229fa1de01f6d7b
parent17491ea27ffa6b48e31c0ad6ad6f795dd000c476 (diff)
nouveau: fix infinite wait on space for userbuf.
A recent commit removed a bug which essentially caused a sync after each use of a user buffer. In fixing it, the scratch area can now become fragmented under some circumstances leading to nouveau_bo_tmp() waiting forever for a large enough block of free space. This fixes ppracer, gl-117 and probably a heap of other apps.
-rw-r--r--src/gallium/winsys/dri/nouveau/nouveau_bo.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/gallium/winsys/dri/nouveau/nouveau_bo.c b/src/gallium/winsys/dri/nouveau/nouveau_bo.c
index 46c0759dbb4..792eaaa79e5 100644
--- a/src/gallium/winsys/dri/nouveau/nouveau_bo.c
+++ b/src/gallium/winsys/dri/nouveau/nouveau_bo.c
@@ -88,6 +88,26 @@ nouveau_bo_tmp_del(void *priv)
nouveau_resource_free(&r);
}
+static unsigned
+nouveau_bo_tmp_max(struct nouveau_device_priv *nvdev)
+{
+ struct nouveau_resource *r = nvdev->sa_heap;
+ unsigned max = 0;
+
+ while (r) {
+ if (r->in_use && !nouveau_fence(r->priv)->emitted) {
+ r = r->next;
+ continue;
+ }
+
+ if (max < r->size)
+ max = r->size;
+ r = r->next;
+ }
+
+ return max;
+}
+
static struct nouveau_resource *
nouveau_bo_tmp(struct nouveau_channel *chan, unsigned size,
struct nouveau_fence *fence)
@@ -103,6 +123,11 @@ nouveau_bo_tmp(struct nouveau_channel *chan, unsigned size,
assert(ref);
while (nouveau_resource_alloc(nvdev->sa_heap, size, ref, &r)) {
+ if (nouveau_bo_tmp_max(nvdev) < size) {
+ nouveau_fence_ref(NULL, &ref);
+ return NULL;
+ }
+
nouveau_fence_flush(chan);
}
nouveau_fence_signal_cb(ref, nouveau_bo_tmp_del, r);