提交 1c6fe036 编写于 作者: A Arjan van de Ven 提交者: Linus Torvalds

cpuidle: Fix incorrect optimization

commit 672917dc ("cpuidle: menu governor: reduce latency on exit")
added an optimization, where the analysis on the past idle period moved
from the end of idle, to the beginning of the new idle.

Unfortunately, this optimization had a bug where it zeroed one key
variable for new use, that is needed for the analysis.  The fix is
simple, zero the variable after doing the work from the previous idle.

During the audit of the code that found this issue, another issue was
also found; the ->measured_us data structure member is never set, a
local variable is always used instead.
Signed-off-by: NArjan van de Ven <arjan@linux.intel.com>
Cc: Corrado Zoccolo <czoccolo@gmail.com>
Cc: stable@kernel.org
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 f1c448e0
...@@ -100,7 +100,6 @@ struct menu_device { ...@@ -100,7 +100,6 @@ struct menu_device {
int needs_update; int needs_update;
unsigned int expected_us; unsigned int expected_us;
unsigned int measured_us;
u64 predicted_us; u64 predicted_us;
unsigned int exit_us; unsigned int exit_us;
unsigned int bucket; unsigned int bucket;
...@@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev) ...@@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev)
int i; int i;
int multiplier; int multiplier;
data->last_state_idx = 0;
data->exit_us = 0;
if (data->needs_update) { if (data->needs_update) {
menu_update(dev); menu_update(dev);
data->needs_update = 0; data->needs_update = 0;
} }
data->last_state_idx = 0;
data->exit_us = 0;
/* Special case when user has set very strict latency requirement */ /* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0)) if (unlikely(latency_req == 0))
return 0; return 0;
...@@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev) ...@@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev)
new_factor = data->correction_factor[data->bucket] new_factor = data->correction_factor[data->bucket]
* (DECAY - 1) / DECAY; * (DECAY - 1) / DECAY;
if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING) if (data->expected_us > 0 && measured_us < MAX_INTERESTING)
new_factor += RESOLUTION * measured_us / data->expected_us; new_factor += RESOLUTION * measured_us / data->expected_us;
else else
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册