[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250805093330.3715444-4-zhenglifeng1@huawei.com>
Date: Tue, 5 Aug 2025 17:33:30 +0800
From: Lifeng Zheng <zhenglifeng1@...wei.com>
To: <catalin.marinas@....com>, <will@...nel.org>, <rafael@...nel.org>,
<viresh.kumar@...aro.org>, <beata.michalska@....com>, <sudeep.holla@....com>
CC: <linux-arm-kernel@...ts.infradead.org>, <linux-pm@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <linuxarm@...wei.com>,
<jonathan.cameron@...wei.com>, <vincent.guittot@...aro.org>,
<yangyicong@...ilicon.com>, <zhanjie9@...ilicon.com>, <lihuisong@...wei.com>,
<yubowen8@...wei.com>, <linhongye@...artners.com>, <zhenglifeng1@...wei.com>
Subject: [PATCH v3 3/3] arm64: topology: Setup AMU FIE for online CPUs only
When boot with maxcpu=1 restrict, and LPI(Low Power Idle States) is on,
only CPU0 will go online. The support AMU flag of CPU0 will be set but the
flags of other CPUs will not. This will cause AMU FIE set up fail for CPU0
when it shares a cpufreq policy with other CPU(s). After that, when other
CPUs are finally online and the support AMU flags of them are set, they'll
never have a chance to set up AMU FIE, even though they're eligible.
To solve this problem, the process of setting up AMU FIE needs to be
modified as follows:
1. Set up AMU FIE only for the online CPUs.
2. Try to set up AMU FIE each time a CPU goes online and do the
freq_counters_valid() check. If this check fails, clear scale freq source
of all the CPUs related to the same policy, in case they use different
source of the freq scale.
Signed-off-by: Lifeng Zheng <zhenglifeng1@...wei.com>
---
arch/arm64/kernel/topology.c | 54 ++++++++++++++++++++++++++++++++++--
1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 9317a618bb87..b68621b3c071 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -385,7 +385,7 @@ static int init_amu_fie_callback(struct notifier_block *nb, unsigned long val,
struct cpufreq_policy *policy = data;
if (val == CPUFREQ_CREATE_POLICY)
- amu_fie_setup(policy->related_cpus);
+ amu_fie_setup(policy->cpus);
/*
* We don't need to handle CPUFREQ_REMOVE_POLICY event as the AMU
@@ -404,10 +404,60 @@ static struct notifier_block init_amu_fie_notifier = {
.notifier_call = init_amu_fie_callback,
};
+static int cpuhp_topology_online(unsigned int cpu)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get_raw_no_check(cpu);
+
+ /*
+ * If the online CPUs are not all AMU FIE CPUs or the new one is already
+ * an AMU FIE one, no need to set it.
+ */
+ if (!policy || !cpumask_available(amu_fie_cpus) ||
+ !cpumask_subset(policy->cpus, amu_fie_cpus) ||
+ cpumask_test_cpu(cpu, amu_fie_cpus))
+ return 0;
+
+ /*
+ * If the new online CPU cannot pass this check, all the CPUs related to
+ * the same policy should be clear from amu_fie_cpus mask, otherwise they
+ * may use different source of the freq scale.
+ */
+ if (!freq_counters_valid(cpu)) {
+ topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_ARCH,
+ policy->related_cpus);
+ cpumask_andnot(amu_fie_cpus, amu_fie_cpus, policy->related_cpus);
+ return 0;
+ }
+
+ cpumask_set_cpu(cpu, amu_fie_cpus);
+
+ topology_set_scale_freq_source(&amu_sfd, cpumask_of(cpu));
+
+ pr_debug("CPU[%u]: counter will be used for FIE.", cpu);
+
+ return 0;
+}
+
static int __init init_amu_fie(void)
{
- return cpufreq_register_notifier(&init_amu_fie_notifier,
+ int ret;
+
+ ret = cpufreq_register_notifier(&init_amu_fie_notifier,
CPUFREQ_POLICY_NOTIFIER);
+ if (ret)
+ return ret;
+
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "arm64/topology:online",
+ cpuhp_topology_online,
+ NULL);
+ if (ret < 0) {
+ cpufreq_unregister_notifier(&init_amu_fie_notifier,
+ CPUFREQ_POLICY_NOTIFIER);
+ return ret;
+ }
+
+ return 0;
}
core_initcall(init_amu_fie);
--
2.33.0
Powered by blists - more mailing lists