Commit c2581836 authored by Will Deacon's avatar Will Deacon
Browse files

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
parents 86941154 747d5b67
Loading
Loading
Loading
Loading
+63 −3
Original line number Diff line number Diff line
@@ -272,7 +272,7 @@ static void amu_fie_setup(const struct cpumask *cpus)

	cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus);

	topology_set_scale_freq_source(&amu_sfd, amu_fie_cpus);
	topology_set_scale_freq_source(&amu_sfd, cpus);

	pr_debug("CPUs[%*pbl]: counters will be used for FIE.",
		 cpumask_pr_args(cpus));
@@ -284,7 +284,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
@@ -303,10 +303,70 @@ 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_policy(cpu);

	/* Those are cheap checks */

	/*
	 * Skip this CPU if:
	 *  - it has no cpufreq policy assigned yet,
	 *  - no policy exists that spans CPUs with AMU counters, or
	 *  - it was already handled.
	 */
	if (unlikely(!policy) || !cpumask_available(amu_fie_cpus) ||
	    cpumask_test_cpu(cpu, amu_fie_cpus))
		return 0;

	/*
	 * Only proceed if all already-online CPUs in this policy
	 * support AMU counters.
	 */
	if (unlikely(!cpumask_subset(policy->cpus, 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);

+8 −1
Original line number Diff line number Diff line
@@ -34,7 +34,14 @@ EXPORT_PER_CPU_SYMBOL_GPL(capacity_freq_ref);

static bool supports_scale_freq_counters(const struct cpumask *cpus)
{
	return cpumask_subset(cpus, &scale_freq_counters_mask);
	int i;

	for_each_cpu(i, cpus) {
		if (cpumask_test_cpu(i, &scale_freq_counters_mask))
			return true;
	}

	return false;
}

bool topology_scale_freq_invariant(void)
+6 −0
Original line number Diff line number Diff line
@@ -198,6 +198,12 @@ struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
}
EXPORT_SYMBOL_GPL(cpufreq_cpu_get_raw);

struct cpufreq_policy *cpufreq_cpu_policy(unsigned int cpu)
{
	return per_cpu(cpufreq_cpu_data, cpu);
}
EXPORT_SYMBOL_GPL(cpufreq_cpu_policy);

unsigned int cpufreq_generic_get(unsigned int cpu)
{
	struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
+5 −0
Original line number Diff line number Diff line
@@ -203,6 +203,7 @@ struct cpufreq_freqs {

#ifdef CONFIG_CPU_FREQ
struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
struct cpufreq_policy *cpufreq_cpu_policy(unsigned int cpu);
struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
void cpufreq_cpu_put(struct cpufreq_policy *policy);
#else
@@ -210,6 +211,10 @@ static inline struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
{
	return NULL;
}
static inline struct cpufreq_policy *cpufreq_cpu_policy(unsigned int cpu)
{
	return NULL;
}
static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
{
	return NULL;