Message ID | 1417529192-11579-4-git-send-email-morten.rasmussen@arm.com (mailing list archive) |
---|---|
State | RFC, archived |
Headers | show |
On 2 December 2014 at 15:06, Morten Rasmussen <morten.rasmussen@arm.com> wrote: > From: Morten Rasmussen <Morten.Rasmussen@arm.com> > > Architectures that don't have any other means for tracking cpu frequency > changes need a callback from cpufreq to implement a scaling factor to > enable scale-invariant per-entity load-tracking in the scheduler. > > To compute the scale invariance correction factor the architecture would > need to know both the max frequency and the current frequency. This > patch defines weak functions for setting both from cpufreq. > > Related architecture specific functions use weak function definitions. > The same approach is followed here. > > These callbacks can be used to implement frequency scaling of cpu > capacity later. > > Cc: Rafael J. Wysocki <rjw@rjwysocki.net> > Cc: Viresh Kumar <viresh.kumar@linaro.org> > Signed-off-by: Morten Rasmussen <morten.rasmussen@arm.com> > --- > drivers/cpufreq/cpufreq.c | 10 +++++++++- > 1 file changed, 9 insertions(+), 1 deletion(-) > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > index 644b54e..1b17608 100644 > --- a/drivers/cpufreq/cpufreq.c > +++ b/drivers/cpufreq/cpufreq.c > @@ -278,6 +278,10 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) > } > #endif > > +void __weak arch_scale_set_curr_freq(int cpu, unsigned long freq) {} > + > +void __weak arch_scale_set_max_freq(int cpu, unsigned long freq) {} > + > static void __cpufreq_notify_transition(struct cpufreq_policy *policy, > struct cpufreq_freqs *freqs, unsigned int state) > { > @@ -315,6 +319,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, > pr_debug("FREQ: %lu - CPU: %lu\n", > (unsigned long)freqs->new, (unsigned long)freqs->cpu); > trace_cpu_frequency(freqs->new, freqs->cpu); > + arch_scale_set_curr_freq(freqs->cpu, freqs->new); You must ensure that arch_scale_set_curr_freq will be called at least once per CPU in order to ensure that you have a defined current frequency. If cpufreq don't have to change the frequency of a CPU, you will never set the current frequency and the notification handler will never be called. A typical example is a CPU booting at max frequency and we use the performance governor; The CPU frequency is already the right one so cpufreq will not change it and you will never call arch_scale_set_curr_freq. The current frequency will be at least undefined or set to 0 for ARM platform (according to patch 04) and the arch_scale_freq_capacity will return 0 Regards, Vincent > srcu_notifier_call_chain(&cpufreq_transition_notifier_list, > CPUFREQ_POSTCHANGE, freqs); > if (likely(policy) && likely(policy->cpu == freqs->cpu)) > @@ -2164,7 +2169,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, > struct cpufreq_policy *new_policy) > { > struct cpufreq_governor *old_gov; > - int ret; > + int ret, cpu; > > pr_debug("setting new policy for CPU %u: %u - %u kHz\n", > new_policy->cpu, new_policy->min, new_policy->max); > @@ -2202,6 +2207,9 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, > policy->min = new_policy->min; > policy->max = new_policy->max; > > + for_each_cpu(cpu, policy->cpus) > + arch_scale_set_max_freq(cpu, policy->max); > + > pr_debug("new min and max freqs are %u - %u kHz\n", > policy->min, policy->max); > > -- > 1.9.1 > > -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 644b54e..1b17608 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -278,6 +278,10 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) } #endif +void __weak arch_scale_set_curr_freq(int cpu, unsigned long freq) {} + +void __weak arch_scale_set_max_freq(int cpu, unsigned long freq) {} + static void __cpufreq_notify_transition(struct cpufreq_policy *policy, struct cpufreq_freqs *freqs, unsigned int state) { @@ -315,6 +319,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy, pr_debug("FREQ: %lu - CPU: %lu\n", (unsigned long)freqs->new, (unsigned long)freqs->cpu); trace_cpu_frequency(freqs->new, freqs->cpu); + arch_scale_set_curr_freq(freqs->cpu, freqs->new); srcu_notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs); if (likely(policy) && likely(policy->cpu == freqs->cpu)) @@ -2164,7 +2169,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_policy *new_policy) { struct cpufreq_governor *old_gov; - int ret; + int ret, cpu; pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, new_policy->min, new_policy->max); @@ -2202,6 +2207,9 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, policy->min = new_policy->min; policy->max = new_policy->max; + for_each_cpu(cpu, policy->cpus) + arch_scale_set_max_freq(cpu, policy->max); + pr_debug("new min and max freqs are %u - %u kHz\n", policy->min, policy->max);