From faed3d4dfe37b9ca0afb10a63854a1c9fa05bc4f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 7 Oct 2021 16:59:53 -0700 Subject: [PATCH] freedreno/drm: Move pipe unref after fence removal Dropping the final pipe ref could in turn drop the final ref to one of a couple other bo's, which in turn could indirectly recurse back into cleanup_fences() on the same bo, resulting in a double decrement of bo->nr_fences and underflow to a large positive #. This happens because free'ing a bo back to the bo cache periodically calls fd_bo_cache_cleanup() and any bo's that have not been re-used can be really free'd, which in turn calls cleanup_fences(). Fixes: 7dabd624649 ("freedreno/drm: Userspace fences") Signed-off-by: Rob Clark Part-of: --- src/freedreno/drm/freedreno_bo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index 3854c8146ba..15491b965dd 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -320,7 +320,8 @@ cleanup_fences(struct fd_bo *bo, bool expired) if (expired && fd_fence_before(f->pipe->control->fence, f->fence)) continue; - fd_pipe_del_locked(f->pipe); + struct fd_pipe *pipe = f->pipe; + bo->nr_fences--; if (bo->nr_fences > 0) { @@ -328,6 +329,8 @@ cleanup_fences(struct fd_bo *bo, bool expired) bo->fences[i] = bo->fences[bo->nr_fences]; i--; } + + fd_pipe_del_locked(pipe); } }