Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: Add a cpufreq pressure feedback for the scheduler

Provide to the scheduler a feedback about the temporary max available
capacity. Unlike arch_update_thermal_pressure(), this doesn't need to be
filtered as the pressure will happen for dozens of ms or more.

Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Tested-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Qais Yousef <qyousef@layalina.io>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
Reviewed-by: Dhruva Gole <d-gole@ti.com>
Acked-by: Rafael J. Wysocki <rafael@kernel.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Link: https://lore.kernel.org/r/20240326091616.3696851-2-vincent.guittot@linaro.org

authored by

Vincent Guittot and committed by
Ingo Molnar
75d65931 cd18bec6

+46
+36
drivers/cpufreq/cpufreq.c
··· 2582 2582 } 2583 2583 EXPORT_SYMBOL(cpufreq_get_policy); 2584 2584 2585 + DEFINE_PER_CPU(unsigned long, cpufreq_pressure); 2586 + 2587 + /** 2588 + * cpufreq_update_pressure() - Update cpufreq pressure for CPUs 2589 + * @policy: cpufreq policy of the CPUs. 2590 + * 2591 + * Update the value of cpufreq pressure for all @cpus in the policy. 2592 + */ 2593 + static void cpufreq_update_pressure(struct cpufreq_policy *policy) 2594 + { 2595 + unsigned long max_capacity, capped_freq, pressure; 2596 + u32 max_freq; 2597 + int cpu; 2598 + 2599 + cpu = cpumask_first(policy->related_cpus); 2600 + max_freq = arch_scale_freq_ref(cpu); 2601 + capped_freq = policy->max; 2602 + 2603 + /* 2604 + * Handle properly the boost frequencies, which should simply clean 2605 + * the cpufreq pressure value. 2606 + */ 2607 + if (max_freq <= capped_freq) { 2608 + pressure = 0; 2609 + } else { 2610 + max_capacity = arch_scale_cpu_capacity(cpu); 2611 + pressure = max_capacity - 2612 + mult_frac(max_capacity, capped_freq, max_freq); 2613 + } 2614 + 2615 + for_each_cpu(cpu, policy->related_cpus) 2616 + WRITE_ONCE(per_cpu(cpufreq_pressure, cpu), pressure); 2617 + } 2618 + 2585 2619 /** 2586 2620 * cpufreq_set_policy - Modify cpufreq policy parameters. 2587 2621 * @policy: Policy object to modify. ··· 2670 2636 policy->min = __resolve_freq(policy, policy->min, CPUFREQ_RELATION_L); 2671 2637 policy->max = __resolve_freq(policy, policy->max, CPUFREQ_RELATION_H); 2672 2638 trace_cpu_frequency_limits(policy); 2639 + 2640 + cpufreq_update_pressure(policy); 2673 2641 2674 2642 policy->cached_target_freq = UINT_MAX; 2675 2643
+10
include/linux/cpufreq.h
··· 241 241 void cpufreq_enable_fast_switch(struct cpufreq_policy *policy); 242 242 void cpufreq_disable_fast_switch(struct cpufreq_policy *policy); 243 243 bool has_target_index(void); 244 + 245 + DECLARE_PER_CPU(unsigned long, cpufreq_pressure); 246 + static inline unsigned long cpufreq_get_pressure(int cpu) 247 + { 248 + return READ_ONCE(per_cpu(cpufreq_pressure, cpu)); 249 + } 244 250 #else 245 251 static inline unsigned int cpufreq_get(unsigned int cpu) 246 252 { ··· 270 264 } 271 265 static inline void disable_cpufreq(void) { } 272 266 static inline void cpufreq_update_limits(unsigned int cpu) { } 267 + static inline unsigned long cpufreq_get_pressure(int cpu) 268 + { 269 + return 0; 270 + } 273 271 #endif 274 272 275 273 #ifdef CONFIG_CPU_FREQ_STAT