[PATCH v2] arm64: topology: add source check in arch_cpu_idle_enter()
seanwang1 <[email protected]>
| Newsgroups | dev.linux.lists.driver-core,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
arch_cpu_idle_enter() directly calls amu_scale_freq_tick() to update arch_freq_scale when a CPU enters idle. This bypasses the sft_data pointer check that topology_clear_scale_freq_source() relies on. As a result, even after calling topology_clear_scale_freq_source() with SCALE_FREQ_SOURCE_ARCH to disable AMU-based frequency scaling, the arch_freq_scale value can still be modified by AMU counters when the CPU goes idle through the arch_cpu_idle_enter() path. Add topology_scale_freq_source() helper to check whether a specific frequency scaling source is currently registered for a CPU. Use it in arch_cpu_idle_enter() to verify that AMU is the active source before calling amu_scale_freq_tick(). This ensures that topology_clear_scale_freq_source() properly disables AMU updates in both the tick path (already handled by topology_scale_freq_tick()) and the idle path. Co-developed-by: Xuewen Yan <[email protected]> Signed-off-by: Sean Wang <[email protected]> Signed-off-by: Xuewen Yan <[email protected]> --- arch/arm64/kernel/topology.c | 3 +++ drivers/base/arch_topology.c | 14 ++++++++++++++ include/linux/arch_topology.h | 1 + 3 files changed, 18 insertions(+) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index b32f13358fbb..cae5da68d5ec 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -173,6 +173,9 @@ void arch_cpu_idle_enter(void) if (!amu_fie_cpu_supported(cpu)) return; + if (!topology_scale_freq_source(SCALE_FREQ_SOURCE_ARCH, cpu)) + return; + /* Kick in AMU update but only if one has not happened already */ if (housekeeping_cpu(cpu, HK_TYPE_TICK) && time_is_before_jiffies(per_cpu(cpu_amu_samples.last_scale_update, cpu))) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 8c5e47c28d9a..dfc2574a5588 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -127,6 +127,20 @@ void topology_clear_scale_freq_source(enum scale_freq_source source, } EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source); +bool topology_scale_freq_source(enum scale_freq_source source, unsigned int cpu) +{ + struct scale_freq_data *sfd; + bool ret; + + rcu_read_lock_sched(); + sfd = rcu_dereference_sched(*per_cpu_ptr(&sft_data, cpu)); + ret = (sfd && sfd->source == source); + rcu_read_unlock_sched(); + + return ret; +} +EXPORT_SYMBOL_GPL(topology_scale_freq_source); + void topology_scale_freq_tick(void) { struct scale_freq_data *sfd = rcu_dereference_sched(*this_cpu_ptr(&sft_data)); diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index ebd7f8935f96..803382f599a2 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -48,6 +48,7 @@ struct scale_freq_data { void topology_scale_freq_tick(void); void topology_set_scale_freq_source(struct scale_freq_data *data, const struct cpumask *cpus); void topology_clear_scale_freq_source(enum scale_freq_source source, const struct cpumask *cpus); +bool topology_scale_freq_source(enum scale_freq_source source, unsigned int cpu); DECLARE_PER_CPU(unsigned long, hw_pressure); -- 2.25.1