drm/msm/a6xx+: Add support to configure perfcntrs

Add support to configure counter SELect regs.  In some cases the reg
writes need to happen while the GPU is idle.  And for a7xx+, in some
cases SEL regs need to be configured from BV or BR aperture.  The
easiest way to deal with this is to configure from the RB.

Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
Reviewed-by: Anna Maniscalco <anna.maniscalco2000@gmail.com>
Reviewed-by: Akhil P Oommen <akhilpo@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/728215/
Message-ID: <20260526145137.160554-12-robin.clark@oss.qualcomm.com>
This commit is contained in:
Rob Clark 2026-05-26 07:50:45 -07:00
parent 0219563363
commit 5eedc8c2d0
3 changed files with 74 additions and 0 deletions

View File

@ -2458,6 +2458,71 @@ static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
return progress;
}
static void
a6xx_perfcntr_configure(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
const struct msm_perfcntr_stream *stream)
{
enum adreno_pipe pipe = PIPE_NONE;
for (unsigned i = 0; i < stream->nr_groups; i++) {
unsigned group_idx = msm_perfcntr_group_idx(stream, i);
unsigned base = msm_perfcntr_counter_base(stream, group_idx);
const struct msm_perfcntr_group *group =
&gpu->perfcntr_groups[group_idx];
struct msm_perfcntr_group_state *group_state =
gpu->perfcntrs->groups[group_idx];
if (group->pipe != pipe) {
pipe = group->pipe;
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
if (pipe == PIPE_BR) {
OUT_RING(ring, CP_SET_THREAD_BR);
} else if (pipe == PIPE_BV) {
OUT_RING(ring, CP_SET_THREAD_BV);
} else {
OUT_RING(ring, CP_SET_THREAD_BOTH);
}
}
const struct msm_perfcntr_counter *counter = &group->counters[base];
unsigned nr = group_state->allocated_counters;
OUT_PKT4(ring, counter->select_reg, nr);
for (unsigned c = 0; c < nr; c++)
OUT_RING(ring, group_state->countables[c]);
for (unsigned s = 0; s < ARRAY_SIZE(counter->slice_select_regs); s++) {
if (!counter->slice_select_regs[s])
break;
OUT_PKT4(ring, counter->slice_select_regs[s], nr);
for (unsigned c = 0; c < nr; c++)
OUT_RING(ring, group_state->countables[c]);
}
}
if (pipe != PIPE_NONE) {
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
OUT_RING(ring, CP_SET_THREAD_BOTH);
}
OUT_PKT7(ring, CP_MEM_WRITE, 3);
OUT_RING(ring, lower_32_bits(rbmemptr(ring, perfcntr_fence)));
OUT_RING(ring, upper_32_bits(rbmemptr(ring, perfcntr_fence)));
OUT_RING(ring, stream->sel_fence);
a6xx_flush_yield(gpu, ring);
/* Check to see if we need to start preemption */
if (adreno_is_a8xx(to_adreno_gpu(gpu)))
a8xx_preempt_trigger(gpu);
else
a6xx_preempt_trigger(gpu);
}
static u32 fuse_to_supp_hw(const struct adreno_info *info, u32 fuse)
{
if (!info->speedbins)
@ -2675,6 +2740,7 @@ const struct adreno_gpu_funcs a6xx_gpu_funcs = {
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
.sysprof_setup = a6xx_gmu_sysprof_setup,
.perfcntr_configure = a6xx_perfcntr_configure,
},
.init = a6xx_gpu_init,
.get_timestamp = a6xx_gmu_get_timestamp,
@ -2708,6 +2774,7 @@ const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs = {
.create_private_vm = a6xx_create_private_vm,
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
.perfcntr_configure = a6xx_perfcntr_configure,
},
.init = a6xx_gpu_init,
.get_timestamp = a6xx_get_timestamp,
@ -2744,6 +2811,7 @@ const struct adreno_gpu_funcs a7xx_gpu_funcs = {
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
.sysprof_setup = a6xx_gmu_sysprof_setup,
.perfcntr_configure = a6xx_perfcntr_configure,
},
.init = a6xx_gpu_init,
.get_timestamp = a6xx_gmu_get_timestamp,
@ -2774,6 +2842,7 @@ const struct adreno_gpu_funcs a8xx_gpu_funcs = {
.get_rptr = a6xx_get_rptr,
.progress = a8xx_progress,
.sysprof_setup = a6xx_gmu_sysprof_setup,
.perfcntr_configure = a6xx_perfcntr_configure,
},
.init = a6xx_gpu_init,
.get_timestamp = a8xx_gmu_get_timestamp,

View File

@ -45,6 +45,9 @@ struct msm_perfcntr_stream {
/** @nr_groups: # of counter groups with enabled counters */
uint32_t nr_groups;
/** @sel_fence: Fence for SEL reg programming */
uint32_t sel_fence;
/**
* @group_idx: array of nr_groups
*

View File

@ -37,6 +37,8 @@ struct msm_rbmemptrs {
volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT];
volatile u64 ttbr0;
volatile u32 context_idr;
volatile u32 perfcntr_fence;
};
struct msm_cp_state {