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:
Junjie Wu 2015-08-26 17:47:21 -07:00 committed by David Keitel
parent cd2c4e5106
commit 512bf81410

View file

@ -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 &&