hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I73EPL
--------------------------------
As ARM AMU's document says, all counters are subject to any changes in clock frequency, including clock stopping caused by the WFI and WFE instructions.
Therefore, using smp_call_on_cpu() to trigger target CPU to read self's AMU counters, which ensures the counters are working properly during calculation.
Signed-off-by: Zeng Heng zengheng4@huawei.com --- arch/arm64/kernel/cpufeature.c | 1 + drivers/cpufreq/cppc_cpufreq.c | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 77e841d396e5..3b746db0f40c 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -1588,6 +1588,7 @@ bool cpu_has_amu_feat(int cpu) { return cpumask_test_cpu(cpu, &amu_cpus); } +EXPORT_SYMBOL(cpu_has_amu_feat);
int get_cpu_with_amu_feat(void) { diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index f29e8d0553a8..f7f3632dcf31 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -350,23 +350,37 @@ static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu, return cppc_cpufreq_perf_to_khz(cpu, delivered_perf); }
-static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) +static int cppc_get_perf_ctrs_sample(void *val) { - struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; - struct cppc_cpudata *cpu = all_cpu_data[cpunum]; + int cpunum = smp_processor_id(); + struct cppc_perf_fb_ctrs *fb_ctrs = val; int ret;
- ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0); + ret = cppc_get_perf_ctrs(cpunum, fb_ctrs); if (ret) return ret;
udelay(2); /* 2usec delay between sampling */
- ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t1); + return cppc_get_perf_ctrs(cpunum, fb_ctrs + 1); +} + +static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) +{ + struct cppc_perf_fb_ctrs fb_ctrs[2] = {0}; + struct cppc_cpudata *cpu = all_cpu_data[cpunum]; + int ret; + + if (cpu_has_amu_feat(cpunum)) + ret = smp_call_on_cpu(cpunum, cppc_get_perf_ctrs_sample, + fb_ctrs, false); + else + ret = cppc_get_perf_ctrs_sample(fb_ctrs); + if (ret) return ret;
- return cppc_get_rate_from_fbctrs(cpu, fb_ctrs_t0, fb_ctrs_t1); + return cppc_get_rate_from_fbctrs(cpu, fb_ctrs[0], fb_ctrs[1]); }
static int cppc_cpufreq_set_boost(struct cpufreq_policy *policy, int state)