diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index f7adb452cb4..f1c72543be6 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -254,26 +254,43 @@ fd_bo_ref(struct fd_bo *bo) return bo; } -void -fd_bo_del(struct fd_bo *bo) +static void +bo_del_or_recycle(struct fd_bo *bo) { struct fd_device *dev = bo->dev; + simple_mtx_assert_locked(&table_lock); + + if ((bo->bo_reuse == BO_CACHE) && + (fd_bo_cache_free(&dev->bo_cache, bo) == 0)) + return; + + if ((bo->bo_reuse == RING_CACHE) && + (fd_bo_cache_free(&dev->ring_cache, bo) == 0)) + return; + + bo_del(bo); +} + +void +fd_bo_del_locked(struct fd_bo *bo) +{ + simple_mtx_assert_locked(&table_lock); + + if (!p_atomic_dec_zero(&bo->refcnt)) + return; + + bo_del_or_recycle(bo); +} + +void +fd_bo_del(struct fd_bo *bo) +{ if (!p_atomic_dec_zero(&bo->refcnt)) return; simple_mtx_lock(&table_lock); - - if ((bo->bo_reuse == BO_CACHE) && - (fd_bo_cache_free(&dev->bo_cache, bo) == 0)) - goto out; - if ((bo->bo_reuse == RING_CACHE) && - (fd_bo_cache_free(&dev->ring_cache, bo) == 0)) - goto out; - - bo_del(bo); - -out: + bo_del_or_recycle(bo); simple_mtx_unlock(&table_lock); } diff --git a/src/freedreno/drm/freedreno_pipe.c b/src/freedreno/drm/freedreno_pipe.c index c0e069f7e2e..b7e633f8f5e 100644 --- a/src/freedreno/drm/freedreno_pipe.c +++ b/src/freedreno/drm/freedreno_pipe.c @@ -84,6 +84,15 @@ fd_pipe_del(struct fd_pipe *pipe) pipe->funcs->destroy(pipe); } +void +fd_pipe_del_locked(struct fd_pipe *pipe) +{ + simple_mtx_assert_locked(&table_lock); + if (!p_atomic_dec_zero(&pipe->refcnt)) + return; + pipe->funcs->destroy(pipe); +} + int fd_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, uint64_t *value) { diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index c9f77fb2c1a..d20cc7822db 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -137,7 +137,9 @@ struct fd_bo *fd_bo_cache_alloc(struct fd_bo_cache *cache, uint32_t *size, int fd_bo_cache_free(struct fd_bo_cache *cache, struct fd_bo *bo); /* for where @table_lock is already held: */ +void fd_bo_del_locked(struct fd_bo *bo); void fd_device_del_locked(struct fd_device *dev); +void fd_pipe_del_locked(struct fd_pipe *pipe); struct fd_pipe_funcs { struct fd_ringbuffer *(*ringbuffer_new_object)(struct fd_pipe *pipe,