[PATCH v3 16/16] drm/msm/a6xx: Allow IFPC with perfcntr stream

Rob Clark
2026-05-04T19:08:51Z

Now that the dynamic pwrup reglist has SEL reg values to restore
appended, so that SEL regs are restored on IFPC exit, we can stop
completely disabling IFPC while global counter sampling is active.

To accomplish this, we re-use sysprof_setup() with a force_on param
to inhibit IFPC specifically while the counter regs are being read,
while leaving IFPC enabled the rest of the time.

Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
---
drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 4 ++--
drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 2 +-
drivers/gpu/drm/msm/msm_gpu.h | 10 ++--------
drivers/gpu/drm/msm/msm_perfcntr.c | 8 ++++++++
drivers/gpu/drm/msm/msm_submitqueue.c | 2 +-
5 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index aba08fb76249..3fe0f1cda46a 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2034,9 +2034,9 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
return irq;
}

-void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu)
+void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu, bool force_on)
{
- bool sysprof = msm_gpu_sysprof_no_ifpc(gpu);
+ bool sysprof = msm_gpu_sysprof_no_ifpc(gpu) | force_on;
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index f3cc9478b079..eecc71843bed 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -280,7 +280,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
-void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu);
+void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu, bool force_on);

void a6xx_preempt_init(struct msm_gpu *gpu);
void a6xx_preempt_hw_init(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 67f1e84eb631..93124c032dd4 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -93,7 +93,7 @@ struct msm_gpu_funcs {
* for cmdstream that is buffered in this FIFO upstream of the CP fw.
*/
bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
- void (*sysprof_setup)(struct msm_gpu *gpu);
+ void (*sysprof_setup)(struct msm_gpu *gpu, bool force_on);

/* Configure perfcntr SELect regs: */
void (*perfcntr_configure)(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
@@ -378,13 +378,7 @@ msm_gpu_sysprof_no_perfcntr_zap(struct msm_gpu *gpu)
static inline bool
msm_gpu_sysprof_no_ifpc(struct msm_gpu *gpu)
{
- /*
- * For now, this is the same condition as disabling perfcntr clears
- * on context switch. But once kernel perfcntr IFPC support is in
- * place, we will only need to disable IFPC for legacy userspace
- * setting SYSPROF param.
- */
- return msm_gpu_sysprof_no_perfcntr_zap(gpu);
+ return refcount_read(&gpu->sysprof_active) > 1;
}

/*
diff --git a/drivers/gpu/drm/msm/msm_perfcntr.c b/drivers/gpu/drm/msm/msm_perfcntr.c
index 39bec201d5c9..d8ec65fa25f0 100644
--- a/drivers/gpu/drm/msm/msm_perfcntr.c
+++ b/drivers/gpu/drm/msm/msm_perfcntr.c
@@ -256,6 +256,10 @@ sample_worker(struct kthread_work *work)
return;
}

+ /* Inhibit IFPC while accessing registers: */
+ if (gpu->funcs->sysprof_setup)
+ gpu->funcs->sysprof_setup(gpu, true);
+
if (gpu->funcs->perfcntr_flush)
gpu->funcs->perfcntr_flush(gpu);

@@ -290,6 +294,10 @@ sample_worker(struct kthread_work *work)
}
}

+ /* Re-enable IFPC: */
+ if (gpu->funcs->sysprof_setup)
+ gpu->funcs->sysprof_setup(gpu, false);
+
smp_store_release(&stream->fifo.head, head);
wake_up_all(&stream->poll_wq);
}
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c
index a58fe41602c6..1a5a77b28016 100644
--- a/drivers/gpu/drm/msm/msm_submitqueue.c
+++ b/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -42,7 +42,7 @@ int msm_context_set_sysprof(struct msm_context *ctx, struct msm_gpu *gpu, int sy

/* Some gpu families require additional setup for sysprof */
if (gpu->funcs->sysprof_setup)
- gpu->funcs->sysprof_setup(gpu);
+ gpu->funcs->sysprof_setup(gpu, false);

ctx->sysprof = sysprof;

--
2.54.0