From: Konrad Dybcio <[email protected]> Add a read-only debugfs file, ifpc_count, that reports how many times the GMU has entered IFPC.
The count is accumulated from the GMU XOCLK_4 power counter. The counter is selected in hw_init, and the delta is folded into the total from the busy callback, so the value advances whenever devfreq samples the GPU. Signed-off-by: Konrad Dybcio <[email protected]> --- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/adreno/a6xx_debugfs.c | 23 +++++++++++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 30 ++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 10 ++++++++++ drivers/gpu/drm/msm/adreno/a8xx_gpu.c | 9 +++++++++ 5 files changed, 73 insertions(+) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 1e246616f83f..afd42e5bda00 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -30,6 +30,7 @@ adreno-y := \ adreno/a8xx_preempt.o \ adreno-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ + adreno/a6xx_debugfs.o \ adreno-$(CONFIG_DRM_MSM_GPU_STATE) += adreno/a6xx_gpu_state.o diff --git a/drivers/gpu/drm/msm/adreno/a6xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a6xx_debugfs.c new file mode 100644 index 000000000000..a3f622cb189f --- /dev/null +++ b/drivers/gpu/drm/msm/adreno/a6xx_debugfs.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <linux/types.h> +#include <linux/debugfs.h> + +#include <drm/drm_file.h> + +#include "a6xx_gpu.h" + +void a6xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + if (!minor) + return; + + if (!(adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC)) + return; + + debugfs_create_u32("ifpc_count", 0444, minor->debugfs_root, + &a6xx_gpu->ifpc_count); +} diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 48d3ee4d55d9..e7c3da5d3ac6 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1338,6 +1338,11 @@ static int hw_init(struct msm_gpu *gpu) GENMASK(7, 0), 0x4); } + if (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) { + a6xx_gpu->ifpc_counter_last = + gmu_read(&a6xx_gpu->gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L); + } + /* Select CP0 to always count cycles */ gpu_write(gpu, REG_A6XX_CP_PERFCTR_CP_SEL(0), PERF_CP_ALWAYS_COUNT); @@ -2334,6 +2339,17 @@ static void a6xx_destroy(struct msm_gpu *gpu) kfree(a6xx_gpu); } +void a6xx_ifpc_count_update(struct a6xx_gpu *a6xx_gpu, u32 cur) +{ + /* A counter below the last sample means the GMU restarted it */ + if (cur >= a6xx_gpu->ifpc_counter_last) + a6xx_gpu->ifpc_count += cur - a6xx_gpu->ifpc_counter_last; + else + a6xx_gpu->ifpc_count += cur; + + a6xx_gpu->ifpc_counter_last = cur; +} + static u64 a6xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); @@ -2347,6 +2363,11 @@ static u64 a6xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); + if (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) + a6xx_ifpc_count_update(a6xx_gpu, + gmu_read(&a6xx_gpu->gmu, + REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L)); + return busy_cycles; } @@ -2818,6 +2839,9 @@ const struct adreno_gpu_funcs a6xx_gpu_funcs = { #if defined(CONFIG_DRM_MSM_GPU_STATE) .gpu_state_get = a6xx_gpu_state_get, .gpu_state_put = a6xx_gpu_state_put, +#endif +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = a6xx_debugfs_init, #endif .create_vm = a6xx_create_vm, .create_private_vm = a6xx_create_private_vm, @@ -2889,6 +2913,9 @@ const struct adreno_gpu_funcs a7xx_gpu_funcs = { #if defined(CONFIG_DRM_MSM_GPU_STATE) .gpu_state_get = a6xx_gpu_state_get, .gpu_state_put = a6xx_gpu_state_put, +#endif +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = a6xx_debugfs_init, #endif .create_vm = a6xx_create_vm, .create_private_vm = a6xx_create_private_vm, @@ -2921,6 +2948,9 @@ const struct adreno_gpu_funcs a8xx_gpu_funcs = { .gpu_busy = a8xx_gpu_busy, .gpu_get_freq = a6xx_gmu_get_freq, .gpu_set_freq = a6xx_gpu_set_freq, +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = a6xx_debugfs_init, +#endif .create_vm = a6xx_create_vm, .create_private_vm = a6xx_create_private_vm, .get_rptr = a6xx_get_rptr, diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index 79912a33e17c..8f0cb168a535 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h @@ -139,6 +139,10 @@ struct a6xx_gpu { spinlock_t aperture_lock; u32 slice_mask; + + /* Total GMU IFPC entries, accumulated from the XOCLK_4 counter */ + u32 ifpc_count; + u32 ifpc_counter_last; }; #define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base) @@ -254,6 +258,12 @@ struct a7xx_cp_smmu_info { #define A6XX_PROTECT_RDONLY(_reg, _len) \ ((((_len) & 0x3FFF) << 18) | ((_reg) & 0x3FFFF)) +#ifdef CONFIG_DEBUG_FS +void a6xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor); +#endif + +void a6xx_ifpc_count_update(struct a6xx_gpu *a6xx_gpu, u32 cur); + extern const struct adreno_gpu_funcs a6xx_gpu_funcs; extern const struct adreno_gpu_funcs a6xx_gmuwrapper_funcs; extern const struct adreno_gpu_funcs a7xx_gpu_funcs; diff --git a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c index f892731cd3d3..ba81a1c9c551 100644 --- a/drivers/gpu/drm/msm/adreno/a8xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a8xx_gpu.c @@ -680,6 +680,10 @@ static int hw_init(struct msm_gpu *gpu) gmu_write(&a6xx_gpu->gmu, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_SELECT_XOCLK_1, FIELD_PREP(GENMASK(7, 0), 0x4)); + if (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) + a6xx_gpu->ifpc_counter_last = + gmu_read(gmu, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L); + /* Select CP0 to always count cycles */ gpu_write(gpu, REG_A8XX_CP_PERFCTR_CP_SEL(0), 1); @@ -1354,6 +1358,11 @@ u64 a8xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) REG_A8XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, REG_A8XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); + if (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) + a6xx_ifpc_count_update(a6xx_gpu, + gmu_read(&a6xx_gpu->gmu, + REG_A8XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_4_L)); + return busy_cycles; } -- 2.56.0
