[PATCH v3] arm64: topology: Fix false warning in counters_read_on_cpu() for same-CPU reads
From: Sumit Gupta
Date: Thu Feb 26 2026 - 07:03:06 EST
The counters_read_on_cpu() function warns when called with IRQs
disabled to prevent deadlock in smp_call_function_single(). However,
this warning is spurious when reading counters on the current CPU,
since no IPI is needed for same CPU reads.
Commit 12eb8f4fff24 ("cpufreq: CPPC: Update FIE arch_freq_scale in
ticks for non-PCC regs") changed the CPPC Frequency Invariance Engine
to read AMU counters directly from the scheduler tick for non-PCC
register spaces (like FFH), instead of deferring to a kthread. This
means counters_read_on_cpu() is now called with IRQs disabled from the
tick handler, triggering the warning.
Fix this by restructuring the logic: when IRQs are disabled (tick
context), call the function directly for same-CPU reads. Otherwise
use smp_call_function_single().
Fixes: 997c021abc6e ("cpufreq: CPPC: Update FIE arch_freq_scale in ticks for non-PCC regs")
Suggested-by: Will Deacon <will@xxxxxxxxxx>
Signed-off-by: Sumit Gupta <sumitg@xxxxxxxxxx>
---
v2 -> v3:
- If irqs_disabled(), then call directly for same-CPU counter reads.
Otherwise use smp_call_function_single(). (Will)
- Remove get_cpu()/put_cpu(). (Will)
v1 -> v2:
- Rebased on v7.0-rc1
- Updated Fixes tag to match upstream commit SHA
[1] https://lore.kernel.org/lkml/20260127080700.3565546-1-sumitg@xxxxxxxxxx/
[2] https://lore.kernel.org/lkml/20260224092714.1242141-1-sumitg@xxxxxxxxxx/
---
arch/arm64/kernel/topology.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 3fe1faab0362..b32f13358fbb 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -400,16 +400,25 @@ static inline
int counters_read_on_cpu(int cpu, smp_call_func_t func, u64 *val)
{
/*
- * Abort call on counterless CPU or when interrupts are
- * disabled - can lead to deadlock in smp sync call.
+ * Abort call on counterless CPU.
*/
if (!cpu_has_amu_feat(cpu))
return -EOPNOTSUPP;
- if (WARN_ON_ONCE(irqs_disabled()))
- return -EPERM;
-
- smp_call_function_single(cpu, func, val, 1);
+ if (irqs_disabled()) {
+ /*
+ * When IRQs are disabled (tick path: sched_tick ->
+ * topology_scale_freq_tick or cppc_scale_freq_tick), only local
+ * CPU counter reads are allowed. Remote CPU counter read would
+ * require smp_call_function_single() which is unsafe with IRQs
+ * disabled.
+ */
+ if (WARN_ON_ONCE(cpu != smp_processor_id()))
+ return -EPERM;
+ func(val);
+ } else {
+ smp_call_function_single(cpu, func, val, 1);
+ }
return 0;
}
--
2.34.1