Module: Mesa
Branch: main
Commit: f49624fc97d3ca8362774f1a2d81f153b10f7a13
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=f49624fc97d3ca8362774f1a2d81f153b10f7a13

Author: Dmitry Baryshkov <[email protected]>
Date:   Mon Nov 13 21:24:16 2023 +0200

freedreno/drm: fallback to default BO allocation if heap alloc fails

Allow fd_bo_heap_alloc() to return NULL if the heap is exausted (or
fragmented) instead of segfaulting. Then handle the error properly in
bo_new().

Signed-off-by: Dmitry Baryshkov <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26787>

---

 src/freedreno/drm/freedreno_bo.c      |  8 +++++---
 src/freedreno/drm/freedreno_bo_heap.c | 16 +++++++++++-----
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c
index 30410544565..d0e871e17ea 100644
--- a/src/freedreno/drm/freedreno_bo.c
+++ b/src/freedreno/drm/freedreno_bo.c
@@ -141,9 +141,11 @@ bo_new(struct fd_device *dev, uint32_t size, uint32_t 
flags,
 
    if (size < FD_BO_HEAP_BLOCK_SIZE) {
       if ((flags == 0) && dev->default_heap)
-         return fd_bo_heap_alloc(dev->default_heap, size);
-      if ((flags == RING_FLAGS) && dev->ring_heap)
-         return fd_bo_heap_alloc(dev->ring_heap, size);
+         bo = fd_bo_heap_alloc(dev->default_heap, size);
+      else if ((flags == RING_FLAGS) && dev->ring_heap)
+         bo = fd_bo_heap_alloc(dev->ring_heap, size);
+      if (bo)
+         return bo;
    }
 
    /* demote cached-coherent to WC if not supported: */
diff --git a/src/freedreno/drm/freedreno_bo_heap.c 
b/src/freedreno/drm/freedreno_bo_heap.c
index dc1af739d23..64c498255e6 100644
--- a/src/freedreno/drm/freedreno_bo_heap.c
+++ b/src/freedreno/drm/freedreno_bo_heap.c
@@ -211,10 +211,6 @@ fd_bo_heap_alloc(struct fd_bo_heap *heap, uint32_t size)
 {
    heap_clean(heap, true);
 
-   struct sa_bo *s = calloc(1, sizeof(*s));
-
-   s->heap = heap;
-
    /* util_vma does not like zero byte allocations, which we get, for
     * ex, with the initial query buffer allocation on pre-a5xx:
     */
@@ -229,7 +225,17 @@ fd_bo_heap_alloc(struct fd_bo_heap *heap, uint32_t size)
     * (The 8k threshold is just a random guess, but seems to work ok)
     */
    heap->heap.alloc_high = (size <= 8 * 1024);
-   s->offset = util_vma_heap_alloc(&heap->heap, size, SUBALLOC_ALIGNMENT);
+   uint64_t offset = util_vma_heap_alloc(&heap->heap, size, 
SUBALLOC_ALIGNMENT);
+   if (!offset) {
+      simple_mtx_unlock(&heap->lock);
+      return NULL;
+   }
+
+   struct sa_bo *s = calloc(1, sizeof(*s));
+
+   s->heap = heap;
+   s->offset = offset;
+
    assert((s->offset / FD_BO_HEAP_BLOCK_SIZE) == (s->offset + size - 1) / 
FD_BO_HEAP_BLOCK_SIZE);
    unsigned idx = block_idx(s);
    if (HEAP_DEBUG)

Reply via email to