From f49624fc97d3ca8362774f1a2d81f153b10f7a13 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 13 Nov 2023 21:24:16 +0200 Subject: [PATCH] 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 Part-of: --- 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)