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

Commit b6a1f3e4 authored by Dietmar Eggemann's avatar Dietmar Eggemann Committed by Ionela Voinescu
Browse files

ANDROID: implement max frequency capping



Implements the Max Frequency Capping Engine (MFCE) getter function
topology_get_max_freq_scale() 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 arch_set_max_freq_scale()
which is called from cpufreq_set_policy().

Signed-off-by: default avatarDietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: default avatarIonela Voinescu <ionela.voinescu@arm.com>
Change-Id: I59e52861ee260755ab0518fe1f7183a2e4e3d0fc
parent 44791a47
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <linux/cpuset.h>

DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
DEFINE_PER_CPU(unsigned long, max_cpu_freq);
DEFINE_PER_CPU(unsigned long, max_freq_scale) = SCHED_CAPACITY_SCALE;

void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,
			 unsigned long max_freq)
@@ -34,8 +36,29 @@ void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,

	scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq;

	for_each_cpu(i, cpus)
	for_each_cpu(i, cpus) {
		per_cpu(freq_scale, i) = scale;
		per_cpu(max_cpu_freq, i) = max_freq;
	}
}

void arch_set_max_freq_scale(struct cpumask *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_cpu_freq, 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;
}

static DEFINE_MUTEX(cpu_scale_mutex);
+9 −0
Original line number Diff line number Diff line
@@ -2237,6 +2237,9 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,

	policy->min = new_policy->min;
	policy->max = new_policy->max;

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

	trace_cpu_frequency_limits(policy->max, policy->min, policy->cpu);

	policy->cached_target_freq = UINT_MAX;
@@ -2447,6 +2450,12 @@ __weak void arch_set_freq_scale(struct cpumask *cpus,
}
EXPORT_SYMBOL_GPL(arch_set_freq_scale);

__weak void arch_set_max_freq_scale(struct cpumask *cpus,
				    unsigned long policy_max_freq)
{
}
EXPORT_SYMBOL_GPL(arch_set_max_freq_scale);

/*********************************************************************
 *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
 *********************************************************************/
+8 −0
Original line number Diff line number Diff line
@@ -37,4 +37,12 @@ unsigned long topology_get_freq_scale(struct sched_domain *sd, int cpu)
	return per_cpu(freq_scale, cpu);
}

DECLARE_PER_CPU(unsigned long, max_freq_scale);

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

#endif /* _LINUX_ARCH_TOPOLOGY_H_ */
+2 −0
Original line number Diff line number Diff line
@@ -922,6 +922,8 @@ extern unsigned int arch_freq_get_on_cpu(int cpu);

extern void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,
				unsigned long max_freq);
extern void arch_set_max_freq_scale(struct cpumask *cpus,
				    unsigned long policy_max_freq);

/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;