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: Dietmar Eggemann <dietmar.eggemann@arm.com>
This commit is contained in:
committed by
Leo Yan
parent
8296e78e5e
commit
b03f1ba3d5
@@ -352,12 +352,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",
|
||||
@@ -365,6 +367,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)
|
||||
@@ -372,6 +386,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)
|
||||
{
|
||||
|
||||
@@ -619,4 +619,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 */
|
||||
|
||||
Reference in New Issue
Block a user