All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cpufreq: Avoid fallback values in cpuinfo_avg_freq
@ 2026-10-19  6:53 Jackie Liu
  0 siblings, 0 replies; only message in thread
From: Jackie Liu @ 2026-10-19  6:53 UTC (permalink / raw)
  To: tglx; +Cc: mingo, bp, dave.hansen, x86, linux-pm

From: Jackie Liu <liuyun01@kylinos.cn>

On x86, arch_freq_get_on_cpu() can return the requested or nominal
frequency when hardware feedback is unavailable. cpuinfo_avg_freq then
reports fallback values as hardware averages, even without APERF/MPERF.

Use a separate sampling hook for the attribute and its support probe:
return -EOPNOTSUPP without APERF/MPERF and -EAGAIN for zero MPERF deltas
or stale samples. Preserve the scaling_cur_freq and /proc/cpuinfo fallback
and the existing ARM64 AMU implementation.

Fixes: fbb4a4759b54 ("cpufreq: Introduce an optional cpuinfo_avg_freq sysfs entry")
Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
---
 arch/x86/kernel/cpu/aperfmperf.c | 18 +++++++++++++-----
 drivers/cpufreq/cpufreq.c        |  9 +++++++--
 include/linux/cpufreq.h          |  1 +
 3 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/cpu/aperfmperf.c b/arch/x86/kernel/cpu/aperfmperf.c
index 7ffc78d5ebf2..fa8376d9ce94 100644
--- a/arch/x86/kernel/cpu/aperfmperf.c
+++ b/arch/x86/kernel/cpu/aperfmperf.c
@@ -503,15 +503,15 @@ void arch_scale_freq_tick(void)
  */
 #define MAX_SAMPLE_AGE	((unsigned long)HZ / 50)
 
-int arch_freq_get_on_cpu(int cpu)
+int arch_freq_get_avg_on_cpu(int cpu)
 {
 	struct aperfmperf *s = per_cpu_ptr(&cpu_samples, cpu);
-	unsigned int seq, freq;
+	unsigned int seq;
 	unsigned long last;
 	u64 acnt, mcnt;
 
 	if (!cpu_feature_enabled(X86_FEATURE_APERFMPERF))
-		goto fallback;
+		return -EOPNOTSUPP;
 
 	do {
 		seq = raw_read_seqcount_begin(&s->seq);
@@ -525,11 +525,19 @@ int arch_freq_get_on_cpu(int cpu)
 	 * which covers idle and NOHZ full CPUs.
 	 */
 	if (!mcnt || (jiffies - last) > MAX_SAMPLE_AGE)
-		goto fallback;
+		return -EAGAIN;
 
 	return div64_u64((cpu_khz * acnt), mcnt);
+}
+
+int arch_freq_get_on_cpu(int cpu)
+{
+	int avg_freq = arch_freq_get_avg_on_cpu(cpu);
+	unsigned int freq;
+
+	if (avg_freq >= 0)
+		return avg_freq;
 
-fallback:
 	freq = cpufreq_quick_get(cpu);
 	return freq ? freq : cpu_khz;
 }
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 54dde8419bdc..2e44b6ee14c9 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -705,9 +705,14 @@ __weak int arch_freq_get_on_cpu(int cpu)
 	return -EOPNOTSUPP;
 }
 
+__weak int arch_freq_get_avg_on_cpu(int cpu)
+{
+	return arch_freq_get_on_cpu(cpu);
+}
+
 static inline bool cpufreq_avg_freq_supported(struct cpufreq_policy *policy)
 {
-	return arch_freq_get_on_cpu(policy->cpu) != -EOPNOTSUPP;
+	return arch_freq_get_avg_on_cpu(policy->cpu) != -EOPNOTSUPP;
 }
 
 static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
@@ -769,7 +774,7 @@ static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy,
 static ssize_t show_cpuinfo_avg_freq(struct cpufreq_policy *policy,
 				     char *buf)
 {
-	int avg_freq = arch_freq_get_on_cpu(policy->cpu);
+	int avg_freq = arch_freq_get_avg_on_cpu(policy->cpu);
 
 	if (avg_freq > 0)
 		return sysfs_emit(buf, "%u\n", avg_freq);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index d3d0d9d02aa4..925a3d3b6c31 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -1228,6 +1228,7 @@ static inline int of_perf_domain_get_sharing_cpumask(int pcpu, const char *list_
 #endif
 
 extern int arch_freq_get_on_cpu(int cpu);
+extern int arch_freq_get_avg_on_cpu(int cpu);
 
 #ifndef arch_set_freq_scale
 static __always_inline
-- 
2.56.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-19  6:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19  6:53 [PATCH] cpufreq: Avoid fallback values in cpuinfo_avg_freq Jackie Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.