aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2010-05-08 18:47:37 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-12 18:03:10 -0400
commit2d49835cc4126fb2a029ad7a9d8804cffa2fc9f1 (patch)
tree9df3d32563a2068a6cfc8eeff483853fef67a0a5
parent3fc72e6eeef7e8a1b8499886fcebd25b4deee909 (diff)
cpuidle: Fix incorrect optimization
commit 1c6fe0364fa7bf28248488753ee0afb6b759cd04 upstream. 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> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-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 73655aeb3a60..f8e57c6303f2 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -101,7 +101,6 @@ struct menu_device {
101 101
102 unsigned int expected_us; 102 unsigned int expected_us;
103 u64 predicted_us; 103 u64 predicted_us;
104 unsigned int measured_us;
105 unsigned int exit_us; 104 unsigned int exit_us;
106 unsigned int bucket; 105 unsigned int bucket;
107 u64 correction_factor[BUCKETS]; 106 u64 correction_factor[BUCKETS];
@@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev)
187 int i; 186 int i;
188 int multiplier; 187 int multiplier;
189 188
190 data->last_state_idx = 0;
191 data->exit_us = 0;
192
193 if (data->needs_update) { 189 if (data->needs_update) {
194 menu_update(dev); 190 menu_update(dev);
195 data->needs_update = 0; 191 data->needs_update = 0;
196 } 192 }
197 193
194 data->last_state_idx = 0;
195 data->exit_us = 0;
196
198 /* Special case when user has set very strict latency requirement */ 197 /* Special case when user has set very strict latency requirement */
199 if (unlikely(latency_req == 0)) 198 if (unlikely(latency_req == 0))
200 return 0; 199 return 0;
@@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev)
294 new_factor = data->correction_factor[data->bucket] 293 new_factor = data->correction_factor[data->bucket]
295 * (DECAY - 1) / DECAY; 294 * (DECAY - 1) / DECAY;
296 295
297 if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING) 296 if (data->expected_us > 0 && measured_us < MAX_INTERESTING)
298 new_factor += RESOLUTION * measured_us / data->expected_us; 297 new_factor += RESOLUTION * measured_us / data->expected_us;
299 else 298 else
300 /* 299 /*