summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2010-05-08 15:47:37 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-09 18:35:36 -0700
commit1c6fe0364fa7bf28248488753ee0afb6b759cd04 (patch)
tree8bb0caf5efc652c18354a8694fc1e235f216d6ab
parentf1c448e0a9e99c76f4ece368714fb35a40a8daba (diff)
downloadlinux-3.10-1c6fe0364fa7bf28248488753ee0afb6b759cd04.tar.gz
linux-3.10-1c6fe0364fa7bf28248488753ee0afb6b759cd04.tar.bz2
linux-3.10-1c6fe0364fa7bf28248488753ee0afb6b759cd04.zip
cpuidle: Fix incorrect optimization
commit 672917dcc78 ("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: Arjan van de Ven <arjan@linux.intel.com> Cc: Corrado Zoccolo <czoccolo@gmail.com> Cc: stable@kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/cpuidle/governors/menu.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1aea7157d8f..f8e57c6303f 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -100,7 +100,6 @@ struct menu_device {
int needs_update;
unsigned int expected_us;
- unsigned int measured_us;
u64 predicted_us;
unsigned int exit_us;
unsigned int bucket;
@@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev)
int i;
int multiplier;
- data->last_state_idx = 0;
- data->exit_us = 0;
-
if (data->needs_update) {
menu_update(dev);
data->needs_update = 0;
}
+ data->last_state_idx = 0;
+ data->exit_us = 0;
+
/* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0))
return 0;
@@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev)
new_factor = data->correction_factor[data->bucket]
* (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;
else
/*