MGS-7915 gpu: Add shader and tiler utilization

Add shader and tiler time in debugfs dvfs_utilization
so that gputop can add shader and tiler utilization in page 4.

Signed-off-by: Chingling Wang <chingling.wang@nxp.com>
Reviewed-by: Jiyu Yang <jiyu.yang@nxp.com>
Acked-by: Jason Liu <jason.hui.liu@nxp.com>
This commit is contained in:
Chingling Wang 2024-10-29 15:05:43 -07:00 committed by Jason Liu
parent 6a6a1513df
commit 91e187c982
4 changed files with 82 additions and 21 deletions

View File

@ -159,6 +159,10 @@ struct kbasep_pm_metrics {
u64 time_idle;
#if MALI_USE_CSF
u64 time_in_protm;
u64 shader_frag_time_busy;
u64 shader_time_busy;
u64 tiler_time_busy;
#else
u32 busy_cl[2];
u32 busy_gl;

View File

@ -22,7 +22,6 @@
/*
* Metrics for power management
*/
#include <mali_kbase.h>
#include <mali_kbase_config_defaults.h>
#include <mali_kbase_pm.h>
@ -102,28 +101,67 @@ static enum hrtimer_restart dvfs_callback(struct hrtimer *timer)
int kbasep_pm_metrics_init(struct kbase_device *kbdev)
{
#if MALI_USE_CSF
struct kbase_ipa_control_perf_counter perf_counter;
struct kbase_ipa_control_perf_counter perf_counter[7];
int err;
/* One counter group */
const size_t NUM_PERF_COUNTERS = 1;
const size_t NUM_PERF_COUNTERS = 4;
KBASE_DEBUG_ASSERT(kbdev != NULL);
kbdev->pm.backend.metrics.kbdev = kbdev;
kbdev->pm.backend.metrics.time_period_start = ktime_get_raw();
perf_counter.scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
perf_counter[0].scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
/* Normalize values by GPU frequency */
perf_counter.gpu_norm = true;
perf_counter[0].gpu_norm = true;
/* We need the GPU_ACTIVE counter, which is in the CSHW group */
perf_counter.type = KBASE_IPA_CORE_TYPE_CSHW;
perf_counter[0].type = KBASE_IPA_CORE_TYPE_CSHW;
/* We need the GPU_ACTIVE counter */
perf_counter.idx = GPU_ACTIVE_CNT_IDX;
perf_counter[0].idx = GPU_ACTIVE_CNT_IDX;
err = kbase_ipa_control_register(kbdev, &perf_counter, NUM_PERF_COUNTERS,
//init perf_counter[1] for shader core
perf_counter[1].scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
/* Normalize values by GPU frequency */
perf_counter[1].gpu_norm = true;
/* We need the shader counter */
perf_counter[1].type = KBASE_IPA_CORE_TYPE_SHADER;
/* We need the shader frag active counter */
perf_counter[1].idx = FRAG_ACTIVE_CNT_IDX;
//init perf_counter[2] for shader core
perf_counter[2].scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
/* Normalize values by GPU frequency */
perf_counter[2].gpu_norm = true;
/* We need the shader counter */
perf_counter[2].type = KBASE_IPA_CORE_TYPE_SHADER;
/* We need the shader counter */
perf_counter[2].idx = COMPUTE_ACTIVE_CNT_IDX;
//init perf_counter[3] for Tiler core
perf_counter[3].scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
/* Normalize values by GPU frequency */
perf_counter[3].gpu_norm = true;
/* We need the counter */
perf_counter[3].type = KBASE_IPA_CORE_TYPE_TILER;
/* We need the shader counter */
perf_counter[3].idx = TILER_ACTIVE_CNT_IDX;
//init perf_counter[1] for shader core
perf_counter[3].scaling_factor = GPU_ACTIVE_SCALING_FACTOR;
err = kbase_ipa_control_register(kbdev, &perf_counter[0], NUM_PERF_COUNTERS,
&kbdev->pm.backend.metrics.ipa_control_client);
if (err) {
dev_err(kbdev->dev, "Failed to register IPA with kbase_ipa_control: err=%d", err);
@ -184,7 +222,7 @@ KBASE_EXPORT_TEST_API(kbasep_pm_metrics_term);
static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev)
{
int err;
u64 gpu_active_counter;
u64 gpu_active_counter[4];
u64 protected_time;
ktime_t now;
@ -194,7 +232,7 @@ static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev)
* info.
*/
err = kbase_ipa_control_query(kbdev, kbdev->pm.backend.metrics.ipa_control_client,
&gpu_active_counter, 1, &protected_time);
&gpu_active_counter[0], 4, &protected_time);
/* Read the timestamp after reading the GPU_ACTIVE counter value.
* This ensures the time gap between the 2 reads is consistent for
@ -239,11 +277,11 @@ static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev)
u64 const MARGIN_NS =
IPA_CONTROL_TIMER_DEFAULT_VALUE_MS * NSEC_PER_MSEC * 3 / 2;
if (gpu_active_counter > (diff_ns + MARGIN_NS)) {
dev_info(
if (gpu_active_counter[0] > (diff_ns + MARGIN_NS)) {
dev_dbg(
kbdev->dev,
"GPU activity takes longer than time interval: %llu ns > %llu ns",
(unsigned long long)gpu_active_counter,
(unsigned long long)gpu_active_counter[0],
(unsigned long long)diff_ns);
}
}
@ -263,17 +301,26 @@ static void kbase_pm_get_dvfs_utilisation_calc(struct kbase_device *kbdev)
* the chances of overflows.
*/
protected_time >>= KBASE_PM_TIME_SHIFT;
gpu_active_counter >>= KBASE_PM_TIME_SHIFT;
gpu_active_counter += protected_time;
gpu_active_counter[0] >>= KBASE_PM_TIME_SHIFT;
gpu_active_counter[1] >>= KBASE_PM_TIME_SHIFT;
gpu_active_counter[2] >>= KBASE_PM_TIME_SHIFT;
gpu_active_counter[3] >>= KBASE_PM_TIME_SHIFT;
gpu_active_counter[0] += protected_time;
/* Ensure the following equations don't go wrong if ns_time is
* slightly larger than gpu_active_counter somehow
*/
gpu_active_counter = MIN(gpu_active_counter, ns_time);
gpu_active_counter[0] = MIN(gpu_active_counter[0], ns_time);
gpu_active_counter[1] = MIN(gpu_active_counter[1], ns_time);
gpu_active_counter[2] = MIN(gpu_active_counter[2], ns_time);
gpu_active_counter[3] = MIN(gpu_active_counter[3], ns_time);
kbdev->pm.backend.metrics.values.time_busy += gpu_active_counter;
kbdev->pm.backend.metrics.values.time_idle += ns_time - gpu_active_counter;
kbdev->pm.backend.metrics.values.time_busy += gpu_active_counter[0];
kbdev->pm.backend.metrics.values.shader_frag_time_busy += gpu_active_counter[1];
kbdev->pm.backend.metrics.values.shader_time_busy += gpu_active_counter[1]+gpu_active_counter[2];
kbdev->pm.backend.metrics.values.tiler_time_busy += gpu_active_counter[3];
kbdev->pm.backend.metrics.values.time_idle += ns_time - gpu_active_counter[0];
/* Also make time in protected mode available explicitly,
* so users of this data have this info, too.
@ -338,6 +385,10 @@ void kbase_pm_get_dvfs_metrics(struct kbase_device *kbdev, struct kbasep_pm_metr
#if MALI_USE_CSF
diff->time_in_protm = cur->time_in_protm - last->time_in_protm;
diff->shader_frag_time_busy = cur->shader_frag_time_busy - last->shader_frag_time_busy;
diff->shader_time_busy = cur->shader_time_busy - last->shader_time_busy;
diff->tiler_time_busy = cur->tiler_time_busy - last->tiler_time_busy;
#else
diff->busy_cl[0] = cur->busy_cl[0] - last->busy_cl[0];
diff->busy_cl[1] = cur->busy_cl[1] - last->busy_cl[1];

View File

@ -1260,6 +1260,9 @@ struct kbase_csf_scheduler {
/* Index of the GPU_ACTIVE counter within the CSHW counter block */
#define GPU_ACTIVE_CNT_IDX (4)
#define FRAG_ACTIVE_CNT_IDX (4)
#define COMPUTE_ACTIVE_CNT_IDX (22)
#define TILER_ACTIVE_CNT_IDX (4)
/*
* Maximum number of sessions that can be managed by the IPA Control component.

View File

@ -39,10 +39,13 @@ static int kbasep_dvfs_utilization_debugfs_show(struct seq_file *file, void *dat
CSTD_UNUSED(data);
#if MALI_USE_CSF
seq_printf(file, "busy_time: %llu idle_time: %llu protm_time: %llu \n",
seq_printf(file, "busy_time: %llu idle_time: %llu protm_time: %llu shader_busy_time: %llu shader_frag_busy_time: %llu tiler_busy_time: %llu\n",
kbdev->pm.backend.metrics.values.time_busy,
kbdev->pm.backend.metrics.values.time_idle,
kbdev->pm.backend.metrics.values.time_in_protm);
kbdev->pm.backend.metrics.values.time_in_protm,
kbdev->pm.backend.metrics.values.shader_time_busy,
kbdev->pm.backend.metrics.values.shader_frag_time_busy,
kbdev->pm.backend.metrics.values.tiler_time_busy);
#else
seq_printf(file, "busy_time: %u idle_time: %u\n",