Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b619def authored by Dietmar Eggemann's avatar Dietmar Eggemann Committed by Quentin Perret
Browse files

cpufreq: implement max frequency capping



Implements the Max Frequency Capping Engine (MFCE) getter function
cpufreq_scale_max_freq_capacity() to provide the scheduler with a
maximum frequency scaling correction factor for more accurate cpu
capacity handling by being able to deal with max frequency capping.

This scaling factor describes the influence of running a cpu with a
current maximum frequency (policy) lower than the maximum possible
frequency (cpuinfo).

The factor is:

  policy_max_freq(cpu) << SCHED_CAPACITY_SHIFT / cpuinfo_max_freq(cpu)

It also implements the MFCE setter function scale_max_freq_capacity()
which is called from cpufreq_set_policy().

Change-Id: I38ef736cfa587520cf4f97012be25cbb0c5af04d
Signed-off-by: default avatarDietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: default avatarChris Redpath <chris.redpath@arm.com>
parent da6833cf
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -315,6 +315,8 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
 *********************************************************************/

static DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
static DEFINE_PER_CPU(unsigned long, max_freq_cpu);
static DEFINE_PER_CPU(unsigned long, max_freq_scale) = SCHED_CAPACITY_SCALE;

static void
scale_freq_capacity(const cpumask_t *cpus, unsigned long cur_freq,
@@ -323,8 +325,10 @@ scale_freq_capacity(const cpumask_t *cpus, unsigned long cur_freq,
	unsigned long scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq;
	int cpu;

	for_each_cpu(cpu, cpus)
	for_each_cpu(cpu, cpus) {
		per_cpu(freq_scale, cpu) = scale;
		per_cpu(max_freq_cpu, cpu) = max_freq;
	}

	pr_debug("cpus %*pbl cur freq/max freq %lu/%lu kHz freq scale %lu\n",
		 cpumask_pr_args(cpus), cur_freq, max_freq, scale);
@@ -335,6 +339,34 @@ unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu)
	return per_cpu(freq_scale, cpu);
}

static void
scale_max_freq_capacity(const cpumask_t *cpus, unsigned long policy_max_freq)
{
	unsigned long scale, max_freq;
	int cpu = cpumask_first(cpus);

	if (cpu >= nr_cpu_ids)
		return;

	max_freq = per_cpu(max_freq_cpu, cpu);

	if (!max_freq)
		return;

	scale = (policy_max_freq << SCHED_CAPACITY_SHIFT) / max_freq;

	for_each_cpu(cpu, cpus)
		per_cpu(max_freq_scale, cpu) = scale;

	pr_debug("cpus %*pbl policy max freq/max freq %lu/%lu kHz max freq scale %lu\n",
		 cpumask_pr_args(cpus), policy_max_freq, max_freq, scale);
}

unsigned long cpufreq_scale_max_freq_capacity(struct sched_domain *sd, int cpu)
{
	return per_cpu(max_freq_scale, cpu);
}

static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
		struct cpufreq_freqs *freqs, unsigned int state)
{
@@ -2238,6 +2270,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
			CPUFREQ_NOTIFY, new_policy);

	scale_max_freq_capacity(policy->cpus, policy->max);

	policy->min = new_policy->min;
	policy->max = new_policy->max;
	trace_cpu_frequency_limits(policy->max, policy->min, policy->cpu);
+1 −0
Original line number Diff line number Diff line
@@ -932,4 +932,5 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,

struct sched_domain;
unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu);
unsigned long cpufreq_scale_max_freq_capacity(struct sched_domain *sd, int cpu);
#endif /* _LINUX_CPUFREQ_H */