cpufreq: interactive: Allow frequency drop during max_freq_hysteresis
max_freq_hysteresis keeps CPU at policy->max even after load goes away. This is necessary for some workloads where heavy task start and stop often. However, in case heavy task indeed stops, it's not very power friendly to stay at policy->max for extended period. Instead of keeping CPU at policy->max, drop frequency optimistically. If a heavy load starts back up again and hit go_hispeed_load within max_freq_hysteresis period, directly ramp back up to policy->max. Change-Id: I5edf6d765a3599a5b26e13e584bd237e932593f0 Signed-off-by: Junjie Wu <junjiew@codeaurora.org>
This commit is contained in:
parent
cd2c4e5106
commit
512bf81410
1 changed files with 29 additions and 17 deletions
|
@ -470,6 +470,8 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
|
|||
unsigned long max_cpu;
|
||||
int i, fcpu;
|
||||
struct cpufreq_govinfo govinfo;
|
||||
bool skip_hispeed_logic, skip_min_sample_time;
|
||||
bool policy_max_fast_restore = false;
|
||||
|
||||
if (!down_read_trylock(&ppol->enable_sem))
|
||||
return;
|
||||
|
@ -532,7 +534,20 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
|
|||
cpu_load = loadadjfreq / ppol->target_freq;
|
||||
tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime;
|
||||
|
||||
if (tunables->ignore_hispeed_on_notif && is_notif) {
|
||||
skip_hispeed_logic = tunables->ignore_hispeed_on_notif && is_notif;
|
||||
skip_min_sample_time = tunables->fast_ramp_down && is_notif;
|
||||
if (now - ppol->max_freq_hyst_start_time <
|
||||
tunables->max_freq_hysteresis &&
|
||||
cpu_load >= tunables->go_hispeed_load &&
|
||||
ppol->target_freq < ppol->policy->max) {
|
||||
skip_hispeed_logic = true;
|
||||
skip_min_sample_time = true;
|
||||
policy_max_fast_restore = true;
|
||||
}
|
||||
|
||||
if (policy_max_fast_restore) {
|
||||
new_freq = ppol->policy->max;
|
||||
} else if (skip_hispeed_logic) {
|
||||
new_freq = choose_freq(ppol, loadadjfreq);
|
||||
} else if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) {
|
||||
if (ppol->target_freq < tunables->hispeed_freq) {
|
||||
|
@ -550,7 +565,11 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
|
|||
new_freq = tunables->hispeed_freq;
|
||||
}
|
||||
|
||||
if ((!tunables->ignore_hispeed_on_notif || !is_notif) &&
|
||||
if (now - ppol->max_freq_hyst_start_time <
|
||||
tunables->max_freq_hysteresis)
|
||||
new_freq = max(tunables->hispeed_freq, new_freq);
|
||||
|
||||
if (!skip_hispeed_logic &&
|
||||
ppol->target_freq >= tunables->hispeed_freq &&
|
||||
new_freq > ppol->target_freq &&
|
||||
now - ppol->hispeed_validate_time <
|
||||
|
@ -573,22 +592,11 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
|
|||
|
||||
new_freq = ppol->freq_table[index].frequency;
|
||||
|
||||
if ((!tunables->fast_ramp_down || !is_notif) &&
|
||||
new_freq < ppol->target_freq &&
|
||||
now - ppol->max_freq_hyst_start_time <
|
||||
tunables->max_freq_hysteresis) {
|
||||
trace_cpufreq_interactive_notyet(max_cpu, cpu_load,
|
||||
ppol->target_freq, ppol->policy->cur, new_freq);
|
||||
spin_unlock_irqrestore(&ppol->target_freq_lock, flags);
|
||||
goto rearm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not scale below floor_freq unless we have been at or above the
|
||||
* floor frequency for the minimum sample time since last validated.
|
||||
*/
|
||||
if ((!tunables->fast_ramp_down || !is_notif) &&
|
||||
new_freq < ppol->floor_freq) {
|
||||
if (!skip_min_sample_time && new_freq < ppol->floor_freq) {
|
||||
if (now - ppol->floor_validate_time <
|
||||
tunables->min_sample_time) {
|
||||
trace_cpufreq_interactive_notyet(
|
||||
|
@ -604,15 +612,19 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
|
|||
* or above the selected frequency for a minimum of min_sample_time,
|
||||
* if not boosted to hispeed_freq. If boosted to hispeed_freq then we
|
||||
* allow the speed to drop as soon as the boostpulse duration expires
|
||||
* (or the indefinite boost is turned off).
|
||||
* (or the indefinite boost is turned off). If policy->max is restored
|
||||
* for max_freq_hysteresis, don't extend the timestamp. Otherwise, it
|
||||
* could incorrectly extended the duration of max_freq_hysteresis by
|
||||
* min_sample_time.
|
||||
*/
|
||||
|
||||
if (!tunables->boosted || new_freq > tunables->hispeed_freq) {
|
||||
if ((!tunables->boosted || new_freq > tunables->hispeed_freq)
|
||||
&& !policy_max_fast_restore) {
|
||||
ppol->floor_freq = new_freq;
|
||||
ppol->floor_validate_time = now;
|
||||
}
|
||||
|
||||
if (new_freq == ppol->policy->max)
|
||||
if (new_freq == ppol->policy->max && !policy_max_fast_restore)
|
||||
ppol->max_freq_hyst_start_time = now;
|
||||
|
||||
if (ppol->target_freq == new_freq &&
|
||||
|
|
Loading…
Add table
Reference in a new issue