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: Ionela Voinescu <ionela.voinescu@arm.com> Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com> [Trivial cherry-pick issue in cpufreq.c] Signed-off-by: Quentin Perret <quentin.perret@arm.com> Change-Id: I59e52861ee260755ab0518fe1f7183a2e4e3d0fc
This commit is contained in:
committed by
Quentin Perret
parent
6c401bf9b0
commit
c4ed8aa44d
@@ -18,6 +18,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)
|
||||
@@ -27,8 +29,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);
|
||||
|
||||
@@ -159,6 +159,12 @@ __weak void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq,
|
||||
}
|
||||
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);
|
||||
|
||||
/*
|
||||
* This is a generic cpufreq init() routine which can be used by cpufreq
|
||||
* drivers of SMP systems. It will do following:
|
||||
@@ -2244,6 +2250,8 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
|
||||
policy->max = new_policy->max;
|
||||
trace_cpu_frequency_limits(policy);
|
||||
|
||||
arch_set_max_freq_scale(policy->cpus, policy->max);
|
||||
|
||||
policy->cached_target_freq = UINT_MAX;
|
||||
|
||||
pr_debug("new min and max freqs are %u - %u kHz\n",
|
||||
|
||||
@@ -33,4 +33,12 @@ unsigned long topology_get_freq_scale(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_ */
|
||||
|
||||
@@ -955,6 +955,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;
|
||||
|
||||
Reference in New Issue
Block a user