Skip to content

Commit c258183

Browse files
committed
Merge branch 'for-next/cpufreq' into for-next/core
* for-next/cpufreq: arm64: topology: Do not warn on missing AMU in cpuhp_topology_online() arm64: topology: Handle AMU FIE setup on CPU hotplug cpufreq: Add new helper function returning cpufreq policy arm64: topology: Skip already covered CPUs when setting freq source
2 parents 8694115 + 747d5b6 commit c258183

4 files changed

Lines changed: 82 additions & 4 deletions

File tree

arch/arm64/kernel/topology.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ static void amu_fie_setup(const struct cpumask *cpus)
272272

273273
cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus);
274274

275-
topology_set_scale_freq_source(&amu_sfd, amu_fie_cpus);
275+
topology_set_scale_freq_source(&amu_sfd, cpus);
276276

277277
pr_debug("CPUs[%*pbl]: counters will be used for FIE.",
278278
cpumask_pr_args(cpus));
@@ -284,7 +284,7 @@ static int init_amu_fie_callback(struct notifier_block *nb, unsigned long val,
284284
struct cpufreq_policy *policy = data;
285285

286286
if (val == CPUFREQ_CREATE_POLICY)
287-
amu_fie_setup(policy->related_cpus);
287+
amu_fie_setup(policy->cpus);
288288

289289
/*
290290
* We don't need to handle CPUFREQ_REMOVE_POLICY event as the AMU
@@ -303,10 +303,70 @@ static struct notifier_block init_amu_fie_notifier = {
303303
.notifier_call = init_amu_fie_callback,
304304
};
305305

306+
static int cpuhp_topology_online(unsigned int cpu)
307+
{
308+
struct cpufreq_policy *policy = cpufreq_cpu_policy(cpu);
309+
310+
/* Those are cheap checks */
311+
312+
/*
313+
* Skip this CPU if:
314+
* - it has no cpufreq policy assigned yet,
315+
* - no policy exists that spans CPUs with AMU counters, or
316+
* - it was already handled.
317+
*/
318+
if (unlikely(!policy) || !cpumask_available(amu_fie_cpus) ||
319+
cpumask_test_cpu(cpu, amu_fie_cpus))
320+
return 0;
321+
322+
/*
323+
* Only proceed if all already-online CPUs in this policy
324+
* support AMU counters.
325+
*/
326+
if (unlikely(!cpumask_subset(policy->cpus, amu_fie_cpus)))
327+
return 0;
328+
329+
/*
330+
* If the new online CPU cannot pass this check, all the CPUs related to
331+
* the same policy should be clear from amu_fie_cpus mask, otherwise they
332+
* may use different source of the freq scale.
333+
*/
334+
if (!freq_counters_valid(cpu)) {
335+
topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_ARCH,
336+
policy->related_cpus);
337+
cpumask_andnot(amu_fie_cpus, amu_fie_cpus, policy->related_cpus);
338+
return 0;
339+
}
340+
341+
cpumask_set_cpu(cpu, amu_fie_cpus);
342+
343+
topology_set_scale_freq_source(&amu_sfd, cpumask_of(cpu));
344+
345+
pr_debug("CPU[%u]: counter will be used for FIE.", cpu);
346+
347+
return 0;
348+
}
349+
306350
static int __init init_amu_fie(void)
307351
{
308-
return cpufreq_register_notifier(&init_amu_fie_notifier,
352+
int ret;
353+
354+
ret = cpufreq_register_notifier(&init_amu_fie_notifier,
309355
CPUFREQ_POLICY_NOTIFIER);
356+
if (ret)
357+
return ret;
358+
359+
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
360+
"arm64/topology:online",
361+
cpuhp_topology_online,
362+
NULL);
363+
if (ret < 0) {
364+
cpufreq_unregister_notifier(&init_amu_fie_notifier,
365+
CPUFREQ_POLICY_NOTIFIER);
366+
return ret;
367+
}
368+
369+
return 0;
310370
}
311371
core_initcall(init_amu_fie);
312372

drivers/base/arch_topology.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ EXPORT_PER_CPU_SYMBOL_GPL(capacity_freq_ref);
3434

3535
static bool supports_scale_freq_counters(const struct cpumask *cpus)
3636
{
37-
return cpumask_subset(cpus, &scale_freq_counters_mask);
37+
int i;
38+
39+
for_each_cpu(i, cpus) {
40+
if (cpumask_test_cpu(i, &scale_freq_counters_mask))
41+
return true;
42+
}
43+
44+
return false;
3845
}
3946

4047
bool topology_scale_freq_invariant(void)

drivers/cpufreq/cpufreq.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
198198
}
199199
EXPORT_SYMBOL_GPL(cpufreq_cpu_get_raw);
200200

201+
struct cpufreq_policy *cpufreq_cpu_policy(unsigned int cpu)
202+
{
203+
return per_cpu(cpufreq_cpu_data, cpu);
204+
}
205+
EXPORT_SYMBOL_GPL(cpufreq_cpu_policy);
206+
201207
unsigned int cpufreq_generic_get(unsigned int cpu)
202208
{
203209
struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);

include/linux/cpufreq.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,18 @@ struct cpufreq_freqs {
203203

204204
#ifdef CONFIG_CPU_FREQ
205205
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
206+
struct cpufreq_policy *cpufreq_cpu_policy(unsigned int cpu);
206207
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
207208
void cpufreq_cpu_put(struct cpufreq_policy *policy);
208209
#else
209210
static inline struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
210211
{
211212
return NULL;
212213
}
214+
static inline struct cpufreq_policy *cpufreq_cpu_policy(unsigned int cpu)
215+
{
216+
return NULL;
217+
}
213218
static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
214219
{
215220
return NULL;

0 commit comments

Comments
 (0)