Re: [PATCH] cpufreq: fix cpufreq_get() can't get correct CPU frequency

From: zhengzucheng
Date: Mon Mar 14 2022 - 22:30:33 EST




On 2022/3/11 23:52, Rafael J. Wysocki wrote:
On Fri, Mar 11, 2022 at 9:11 AM z00314508 <zhengzucheng@xxxxxxxxxx> wrote:
From: Zucheng Zheng <zhengzucheng@xxxxxxxxxx>

On some specific platforms, the cpufreq driver does not define
cpufreq_driver.get() routine (eg:x86 intel_pstate driver), as a
I guess you mean the cpufreq driver ->get callback.

No, intel_pstate doesn't implement it, because it cannot reliably
return the current CPU frequency.

result, the cpufreq_get() can't get the correct CPU frequency.
No, it can't, if intel_pstate is the driver, but what's the problem?
This function is only called in one place in the kernel and not on x8
even.

Modern x86 processors include the hardware needed to accurately
calculate frequency over an interval -- APERF, MPERF and the TSC.
You can compute the average frequency over an interval, but ->get is
expected to return the actual current frequency at the time call time.

Here we use arch_freq_get_on_cpu() in preference to any driver
driver-specific cpufreq_driver.get() routine to get CPU frequency.

Fixes: f8475cef9008 ("x86: use common aperfmperf_khz_on_cpu() to calculate KHz using APERF/MPERF")
No kidding.

Signed-off-by: Zucheng Zheng <zhengzucheng@xxxxxxxxxx>
---
drivers/cpufreq/cpufreq.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 80f535cc8a75..d777257b4454 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1806,10 +1806,14 @@ unsigned int cpufreq_get(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
unsigned int ret_freq = 0;
+ unsigned int freq;

if (policy) {
down_read(&policy->rwsem);
- if (cpufreq_driver->get)
+ freq = arch_freq_get_on_cpu(policy->cpu);
+ if (freq)
+ ret_freq = freq;
+ else if (cpufreq_driver->get)
Again, what problem exactly does this address?
Thank you for review.

In some scenarios, cpufreq driver ->get is not defined,
some driver get the CPU frequency by calling cpufreq_get() will return 0.
The modification to this problem is inspired by the implementation of the show_scaling_cur_freq().

ret_freq = __cpufreq_get(policy);
up_read(&policy->rwsem);

--
.