On Sat, Oct 24, 2026 at 6:31 AM Akhil P Oommen <[email protected]> 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: [email protected] > Signed-off-by: Akhil P Oommen <[email protected]>
Thanks, this gets the AQE working on my glymur laptop (Slim 7x). Tested-by: Connor Abbott <[email protected]> > --- > 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 >
