[PATCH 2/3] drm/msm/a6xx: free all preempt buffers on teardown
From: Fan Wu
Date: Wed Jun 17 2026 - 09:22:43 EST
a6xx_destroy() never calls a6xx_preempt_fini(), so on teardown the
preemption GEM buffers leak: the per-ring preempt_bo and preempt_smmu_bo
(allocated in preempt_init_ring()) and the single preempt_postamble_bo
(allocated in a6xx_preempt_init()). a6xx_preempt_fini() only released
preempt_bo, and only on the a6xx_preempt_init() error path.
Complete a6xx_preempt_fini() to also release preempt_smmu_bo and
preempt_postamble_bo, and call it from a6xx_destroy(). Because
a6xx_preempt_fini() is now reached on both the init-error path and
normal teardown, null each pointer after msm_gem_kernel_put() so a
second invocation is a no-op rather than a double-free.
msm_gem_kernel_put() is already NULL-safe, and msm_gem_kernel_new()
only stores the GEM object on success, so pointers that were never
allocated stay NULL.
This bug was found by static analysis.
Fixes: e7ae83da4a28 ("drm/msm/a6xx: Implement preemption for a7xx targets")
Fixes: 50117cad0c50 ("drm/msm/a6xx: Use posamble to reset counters on preemption")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Fan Wu <fanwu01@xxxxxxxxxx>
---
drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 1 +
drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 8 +++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 7c25c763071f..d14c3e8d879a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2444,6 +2444,7 @@ static void a6xx_destroy(struct msm_gpu *gpu)
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
timer_shutdown_sync(&a6xx_gpu->preempt_timer);
+ a6xx_preempt_fini(gpu);
if (a6xx_gpu->sqe_bo) {
msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->vm);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
index ae315640e689..42e51234fb85 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
@@ -424,8 +424,14 @@ void a6xx_preempt_fini(struct msm_gpu *gpu)
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
int i;
- for (i = 0; i < gpu->nr_rings; i++)
+ for (i = 0; i < gpu->nr_rings; i++) {
msm_gem_kernel_put(a6xx_gpu->preempt_bo[i], gpu->vm);
+ a6xx_gpu->preempt_bo[i] = NULL;
+ msm_gem_kernel_put(a6xx_gpu->preempt_smmu_bo[i], gpu->vm);
+ a6xx_gpu->preempt_smmu_bo[i] = NULL;
+ }
+ msm_gem_kernel_put(a6xx_gpu->preempt_postamble_bo, gpu->vm);
+ a6xx_gpu->preempt_postamble_bo = NULL;
}
/* Initialize the preemption watchdog timer at GPU allocation so that it is
--
2.34.1