nouveau: fix infinite wait on space for userbuf.
authorBen Skeggs <skeggsb@gmail.com>
Mon, 24 Mar 2008 02:01:35 +0000 (13:01 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Mon, 24 Mar 2008 02:06:29 +0000 (13:06 +1100)
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.

src/gallium/winsys/dri/nouveau/nouveau_bo.c

index 46c0759dbb4e8d46d1b4bde138c7eda0c09e9f31..792eaaa79e543f4f6f9b9849bbb0662e09d286c3 100644 (file)
@@ -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);