From 168e1040e746ae88623a2171af0decaad69358f5 Mon Sep 17 00:00:00 2001 From: Ramakrishna Gottimukkula Date: Wed, 26 Jul 2017 23:33:28 +0530 Subject: [PATCH] cpufreq: interactive: fix to come out of hysteresis mode If policy max is set to less than or equal to hispeed_freq, governor can get stuck in hysteresis mode as long as cpufreq_interactive_timer keeps coming with in hysteresis period (max_freq_hysteresis). This is because governor updates hysteresis start time (max_freq_hyst_start_time) everytime new frequency is greater than or equal to policy max and jump_to_max_no_ts flag is false. Irrespective of load new frequency in this case will always end up at least at hispeed_freq due to hysteresis. As policy max is set to less than or equal to hispeed_freq, this will result in updating max_freq_hyst_start_time if jump_to_max_no_ts is false. This will end up restarting hysteresis period. This mode will break only if timer gets delivered after hysteresis period. Otherwise it keeps extending. To come out of this, don't update max_freq_hyst_start_time if new frequency is bumped up to hispeed_freq due to hysteresis even though the required frequency as per load is less than policy max and hispeed_freq. Change-Id: Ib1e9e612036afeb12acd86e603b019e227920d85 Signed-off-by: Ramakrishna Gottimukkula --- drivers/cpufreq/cpufreq_interactive.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index b91e115462ae..abbee61c99c8 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -479,6 +479,7 @@ static void cpufreq_interactive_timer(unsigned long data) bool skip_hispeed_logic, skip_min_sample_time; bool jump_to_max_no_ts = false; bool jump_to_max = false; + bool start_hyst = true; if (!down_read_trylock(&ppol->enable_sem)) return; @@ -588,8 +589,12 @@ static void cpufreq_interactive_timer(unsigned long data) } if (now - ppol->max_freq_hyst_start_time < - tunables->max_freq_hysteresis) + tunables->max_freq_hysteresis) { + if (new_freq < ppol->policy->max && + ppol->policy->max <= tunables->hispeed_freq) + start_hyst = false; new_freq = max(tunables->hispeed_freq, new_freq); + } if (!skip_hispeed_logic && ppol->target_freq >= tunables->hispeed_freq && @@ -646,7 +651,7 @@ static void cpufreq_interactive_timer(unsigned long data) ppol->floor_validate_time = now; } - if (new_freq >= ppol->policy->max && !jump_to_max_no_ts) + if (start_hyst && new_freq >= ppol->policy->max && !jump_to_max_no_ts) ppol->max_freq_hyst_start_time = now; if (ppol->target_freq == new_freq &&