mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-03 17:40:04 +00:00
![Lukasz Luba](/assets/img/avatar_default.png)
Energy Aware Scheduling (EAS) needs to predict the decisions made by SchedUtil. The map_util_freq() exists to do that. There are corner cases where the max allowed frequency might be reduced (due to thermal). SchedUtil as a CPUFreq governor, is aware of that but EAS is not. This patch aims to address it. SchedUtil stores the maximum allowed frequency in 'sugov_policy::next_freq' field. EAS has to predict that value, which is the real used frequency. That value is made after a call to cpufreq_driver_resolve_freq() which clamps to the CPUFreq policy limits. In the existing code EAS is not able to predict that real frequency. This leads to energy estimation errors. To avoid wrong energy estimation in EAS (due to frequency miss prediction) make sure that the step which calculates Performance Domain frequency, is also aware of the allowed CPU capacity. Furthermore, modify map_util_freq() to not extend the frequency value. Instead, use map_util_perf() to extend the util value in both places: SchedUtil and EAS, but for EAS clamp it to max allowed CPU capacity. In the end, we achieve the same desirable behavior for both subsystems and alignment in regards to the real CPU frequency. Signed-off-by: Lukasz Luba <lukasz.luba@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> (For the schedutil part) Link: https://lore.kernel.org/r/20210614191238.23224-1-lukasz.luba@arm.com
38 lines
983 B
C
38 lines
983 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _LINUX_SCHED_CPUFREQ_H
|
|
#define _LINUX_SCHED_CPUFREQ_H
|
|
|
|
#include <linux/types.h>
|
|
|
|
/*
|
|
* Interface between cpufreq drivers and the scheduler:
|
|
*/
|
|
|
|
#define SCHED_CPUFREQ_IOWAIT (1U << 0)
|
|
|
|
#ifdef CONFIG_CPU_FREQ
|
|
struct cpufreq_policy;
|
|
|
|
struct update_util_data {
|
|
void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
|
|
};
|
|
|
|
void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
|
|
void (*func)(struct update_util_data *data, u64 time,
|
|
unsigned int flags));
|
|
void cpufreq_remove_update_util_hook(int cpu);
|
|
bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy);
|
|
|
|
static inline unsigned long map_util_freq(unsigned long util,
|
|
unsigned long freq, unsigned long cap)
|
|
{
|
|
return freq * util / cap;
|
|
}
|
|
|
|
static inline unsigned long map_util_perf(unsigned long util)
|
|
{
|
|
return util + (util >> 2);
|
|
}
|
|
#endif /* CONFIG_CPU_FREQ */
|
|
|
|
#endif /* _LINUX_SCHED_CPUFREQ_H */
|