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

Commit 4eb92977 authored by Dietmar Eggemann's avatar Dietmar Eggemann Committed by Dmitry Shmidt
Browse files

ANDROID: cpufreq: Max freq invariant scheduler load-tracking and cpu capacity support



Implements cpufreq_scale_max_freq_capacity() to provide the scheduler
with a maximum frequency scaling correction factor for more accurate
load-tracking and cpu capacity handling by being able to deal with
frequency capping.

This scaling factor describes the influence of running a cpu with a
current maximum frequency lower than the absolute possible maximum
frequency on load tracking and cpu capacity.

The factor is:

	current_max_freq(cpu) << SCHED_CAPACITY_SHIFT / max_freq(cpu)

In fact, max_freq_scale should be a struct cpufreq_policy data member.
But this would require that the scheduler hot path (__update_load_avg())
would have to grab the cpufreq lock. This can be avoided by using per-cpu
data initialized to SCHED_CAPACITY_SCALE for max_freq_scale.

Signed-off-by: default avatarDietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: default avatarAndres Oportus <andresoportus@google.com>
parent f69e2dc5
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -306,12 +306,14 @@ 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_scale) = SCHED_CAPACITY_SCALE;

static void
scale_freq_capacity(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs)
{
	unsigned long cur = freqs ? freqs->new : policy->cur;
	unsigned long scale = (cur << SCHED_CAPACITY_SHIFT) / policy->max;
	struct cpufreq_cpuinfo *cpuinfo = &policy->cpuinfo;
	int cpu;

	pr_debug("cpus %*pbl cur/cur max freq %lu/%u kHz freq scale %lu\n",
@@ -319,6 +321,18 @@ scale_freq_capacity(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs)

	for_each_cpu(cpu, policy->cpus)
		per_cpu(freq_scale, cpu) = scale;

	if (freqs)
		return;

	scale = (policy->max << SCHED_CAPACITY_SHIFT) / cpuinfo->max_freq;

	pr_debug("cpus %*pbl cur max/max freq %u/%u kHz max freq scale %lu\n",
		 cpumask_pr_args(policy->cpus), policy->max, cpuinfo->max_freq,
		 scale);

	for_each_cpu(cpu, policy->cpus)
		per_cpu(max_freq_scale, cpu) = scale;
}

unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu)
@@ -326,6 +340,11 @@ unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu)
	return per_cpu(freq_scale, cpu);
}

unsigned long cpufreq_scale_max_freq_capacity(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)
{
+1 −0
Original line number Diff line number Diff line
@@ -889,4 +889,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(int cpu);
#endif /* _LINUX_CPUFREQ_H */