Re: [PATCH 6/8] drm/msm/a6xx: Reset preemption records across suspend
From: Connor Abbott
Date: Sat Oct 24 2026 - 14:30:15 EST
On Sat, Oct 24, 2026 at 6:31 AM Akhil P Oommen <akhilpo@xxxxxxxxxxxxxxxx> wrote:
>
> The preemption records are initialised only once at probe time. On every
> resume, a6xx_preempt_hw_init() and a8xx_preempt_hw_init() refresh only a
> subset of the fields (rptr, wptr, rptr_addr, info, data, rbase). Whatever
> else the CP wrote into the record before the GPU was power-collapsed
> is left in place and gets consumed again by the CP on the next preemption,
> now carrying stale context state.
>
> To fix this, zero the whole preemption record on suspend and fully
> initialise every field in the hw_init path.
>
> Fixes: e7ae83da4a28 ("drm/msm/a6xx: Implement preemption for a7xx targets")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Akhil P Oommen <akhilpo@xxxxxxxxxxxxxxxx>
Thanks, this gets the AQE working on my glymur laptop (Slim 7x).
Tested-by: Connor Abbott <cwabbott0@xxxxxxxxx>
> ---
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 ++
> drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 1 +
> drivers/gpu/drm/msm/adreno/a6xx_preempt.c | 37 ++++++++++++++++++-------------
> drivers/gpu/drm/msm/adreno/a8xx_preempt.c | 11 ++++++---
> 4 files changed, 32 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 92e8c8abb86d..3e4afaa5345f 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -2248,6 +2248,7 @@ static int a6xx_gmu_pm_suspend(struct msm_gpu *gpu)
> for (i = 0; i < gpu->nr_rings; i++)
> a6xx_gpu->shadow[i] = 0;
>
> + a6xx_preempt_record_reset(gpu);
> gpu->suspend_count++;
>
> return 0;
> @@ -2287,6 +2288,7 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
> for (i = 0; i < gpu->nr_rings; i++)
> a6xx_gpu->shadow[i] = 0;
>
> + a6xx_preempt_record_reset(gpu);
> gpu->suspend_count++;
>
> return 0;
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> index 79912a33e17c..62a19e22e230 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
> @@ -305,6 +305,7 @@ void a6xx_preempt_hw_init(struct msm_gpu *gpu);
> void a6xx_preempt_trigger(struct msm_gpu *gpu);
> void a6xx_preempt_irq(struct msm_gpu *gpu);
> void a6xx_preempt_fini(struct msm_gpu *gpu);
> +void a6xx_preempt_record_reset(struct msm_gpu *gpu);
> void a6xx_emit_set_pseudo_reg(struct msm_ringbuffer *ring,
> struct a6xx_gpu *a6xx_gpu, struct msm_gpu_submitqueue *queue);
> int a6xx_preempt_submitqueue_setup(struct msm_gpu *gpu,
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> index 1e599d4ddea1..df8d4f3e8d4c 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_preempt.c
> @@ -140,12 +140,17 @@ void a6xx_preempt_hw_init(struct msm_gpu *gpu)
> for (i = 0; i < gpu->nr_rings; i++) {
> struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[i];
>
> - record_ptr->wptr = 0;
> - record_ptr->rptr = 0;
> - record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
> + record_ptr->magic = A6XX_PREEMPT_RECORD_MAGIC;
> record_ptr->info = 0;
> + record_ptr->errno = 0;
> record_ptr->data = 0;
> + record_ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
> + record_ptr->rptr = 0;
> + record_ptr->wptr = 0;
> + record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
> record_ptr->rbase = gpu->rb[i]->iova;
> + record_ptr->counter = 0;
> + record_ptr->bv_rptr_addr = rbmemptr(gpu->rb[i], bv_rptr);
> }
>
> /* Write a 0 to signal that we aren't switching pagetables */
> @@ -163,6 +168,19 @@ void a6xx_preempt_hw_init(struct msm_gpu *gpu)
> a6xx_gpu->cur_ring = gpu->rb[0];
> }
>
> +void a6xx_preempt_record_reset(struct msm_gpu *gpu)
> +{
> + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
> + int i;
> +
> + if (gpu->nr_rings == 1)
> + return;
> +
> + for (i = 0; i < gpu->nr_rings; i++)
> + memset(a6xx_gpu->preempt[i], 0, a6xx_gpu->preempt_bo[i]->size);
> +}
> +
> void a6xx_preempt_trigger(struct msm_gpu *gpu)
> {
> struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
> @@ -302,8 +320,6 @@ static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
> a6xx_gpu->preempt_iova[ring->id] = iova;
> a6xx_gpu->preempt[ring->id] = ptr;
>
> - struct a6xx_preempt_record *record_ptr = ptr;
> -
> ptr = msm_gem_kernel_new(gpu->dev,
> PREEMPT_SMMU_INFO_SIZE,
> MSM_BO_WC | MSM_BO_MAP_PRIV | MSM_BO_GPU_READONLY,
> @@ -329,17 +345,6 @@ static int preempt_init_ring(struct a6xx_gpu *a6xx_gpu,
> smmu_info_ptr->asid = 0xdecafbad;
> smmu_info_ptr->context_idr = 0;
>
> - /* Set up the defaults on the preemption record */
> - record_ptr->magic = A6XX_PREEMPT_RECORD_MAGIC;
> - record_ptr->info = 0;
> - record_ptr->data = 0;
> - record_ptr->rptr = 0;
> - record_ptr->wptr = 0;
> - record_ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
> - record_ptr->rbase = ring->iova;
> - record_ptr->counter = 0;
> - record_ptr->bv_rptr_addr = rbmemptr(ring, bv_rptr);
> -
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/msm/adreno/a8xx_preempt.c b/drivers/gpu/drm/msm/adreno/a8xx_preempt.c
> index 6cb53a071801..0e0503ed54a1 100644
> --- a/drivers/gpu/drm/msm/adreno/a8xx_preempt.c
> +++ b/drivers/gpu/drm/msm/adreno/a8xx_preempt.c
> @@ -121,12 +121,17 @@ void a8xx_preempt_hw_init(struct msm_gpu *gpu)
> for (i = 0; i < gpu->nr_rings; i++) {
> struct a6xx_preempt_record *record_ptr = a6xx_gpu->preempt[i];
>
> - record_ptr->wptr = 0;
> - record_ptr->rptr = 0;
> - record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
> + record_ptr->magic = A6XX_PREEMPT_RECORD_MAGIC;
> record_ptr->info = 0;
> + record_ptr->errno = 0;
> record_ptr->data = 0;
> + record_ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
> + record_ptr->rptr = 0;
> + record_ptr->wptr = 0;
> + record_ptr->rptr_addr = shadowptr(a6xx_gpu, gpu->rb[i]);
> record_ptr->rbase = gpu->rb[i]->iova;
> + record_ptr->counter = 0;
> + record_ptr->bv_rptr_addr = rbmemptr(gpu->rb[i], bv_rptr);
> }
>
> /* Write a 0 to signal that we aren't switching pagetables */
>
> --
> 2.55.0
>