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)
