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

Commit 0f96d867 authored by Ionela Voinescu's avatar Ionela Voinescu Committed by Quentin Perret
Browse files

cpufreq: add scaled minimum capacity tracking for policy changes



When the minimum frequency available to a policy is modified either
by userspace or by external actors setting a minimum frequency for a
voltage domain to control behaviour of some connected component, we
expect that the cpufreq policy will be updated to reflect this.

If we wish to use this information to guide energy estimation and
scheduling decisions, we need to track it.
Implement cpufreq_scale_min_freq_capacity() to provide the scheduler
with a minimum frequency scaling correction factor for more accurate
cpu capacity information.
This scaling factor describes the influence of running a cpu with a
current policy minimum frequency higher than the minimum possible
frequency.

The factor is:
	current_min_freq(cpu) << SCHED_CAPACITY_SHIFT / max_freq(cpu)

This factor is computed in scale_min_freq_capacity and returned,
per cpu, in cpufreq_scale_min_freq_capacity.

Change-Id: I66237025a7c0bce6bfd6e973ea22b8d3f6c41827
Signed-off-by: default avatarChris Redpath <chris.redpath@arm.com>
Signed-off-by: default avatarIonela Voinescu <ionela.voinescu@arm.com>
parent bcf1c9d8
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -317,6 +317,7 @@ 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 DEFINE_PER_CPU(unsigned long, min_freq_scale);

static void
scale_freq_capacity(const cpumask_t *cpus, unsigned long cur_freq,
@@ -367,6 +368,34 @@ unsigned long cpufreq_scale_max_freq_capacity(struct sched_domain *sd, int cpu)
	return per_cpu(max_freq_scale, cpu);
}

static void
scale_min_freq_capacity(const cpumask_t *cpus, unsigned long policy_min_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_min_freq << SCHED_CAPACITY_SHIFT) / max_freq;

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

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

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

static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
		struct cpufreq_freqs *freqs, unsigned int state)
{
@@ -2271,6 +2300,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
			CPUFREQ_NOTIFY, new_policy);

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

	policy->min = new_policy->min;
	policy->max = new_policy->max;
+1 −0
Original line number Diff line number Diff line
@@ -933,4 +933,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);
unsigned long cpufreq_scale_min_freq_capacity(struct sched_domain *sd, int cpu);
#endif /* _LINUX_CPUFREQ_H */