aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
authorCorrado Zoccolo <czoccolo@gmail.com>2009-09-21 20:04:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:45 -0400
commit672917dcc781ead7652a8b11b1fba14e38ac15b8 (patch)
treec504b7f60737ba8d82eabfa662585d463ae5ea66 /drivers/cpuidle
parent69d25870f20c4b2563304f2b79c5300dd60a067e (diff)
cpuidle: menu governor: reduce latency on exit
Move the state residency accounting and statistics computation off the hot exit path. On exit, the need to recompute statistics is recorded, and new statistics will be computed when menu_select is called again. The expected effect is to reduce processor wakeup latency from sleep (C-states). We are speaking of few hundreds of cycles reduction out of a several microseconds latency (determined by the hardware transition), so it is difficult to measure. Signed-off-by: Corrado Zoccolo <czoccolo@gmail.com> Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Cc: Len Brown <len.brown@intel.com> Cc: Adam Belay <abelay@novell.com Acked-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/governors/menu.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 9f3d77532ab9..68104434ebb5 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -96,6 +96,7 @@
96 96
97struct menu_device { 97struct menu_device {
98 int last_state_idx; 98 int last_state_idx;
99 int needs_update;
99 100
100 unsigned int expected_us; 101 unsigned int expected_us;
101 u64 predicted_us; 102 u64 predicted_us;
@@ -166,6 +167,8 @@ static inline int performance_multiplier(void)
166 167
167static DEFINE_PER_CPU(struct menu_device, menu_devices); 168static DEFINE_PER_CPU(struct menu_device, menu_devices);
168 169
170static void menu_update(struct cpuidle_device *dev);
171
169/** 172/**
170 * menu_select - selects the next idle state to enter 173 * menu_select - selects the next idle state to enter
171 * @dev: the CPU 174 * @dev: the CPU
@@ -180,6 +183,11 @@ static int menu_select(struct cpuidle_device *dev)
180 data->last_state_idx = 0; 183 data->last_state_idx = 0;
181 data->exit_us = 0; 184 data->exit_us = 0;
182 185
186 if (data->needs_update) {
187 menu_update(dev);
188 data->needs_update = 0;
189 }
190
183 /* Special case when user has set very strict latency requirement */ 191 /* Special case when user has set very strict latency requirement */
184 if (unlikely(latency_req == 0)) 192 if (unlikely(latency_req == 0))
185 return 0; 193 return 0;
@@ -231,7 +239,7 @@ static int menu_select(struct cpuidle_device *dev)
231} 239}
232 240
233/** 241/**
234 * menu_reflect - attempts to guess what happened after entry 242 * menu_reflect - records that data structures need update
235 * @dev: the CPU 243 * @dev: the CPU
236 * 244 *
237 * NOTE: it's important to be fast here because this operation will add to 245 * NOTE: it's important to be fast here because this operation will add to
@@ -240,6 +248,16 @@ static int menu_select(struct cpuidle_device *dev)
240static void menu_reflect(struct cpuidle_device *dev) 248static void menu_reflect(struct cpuidle_device *dev)
241{ 249{
242 struct menu_device *data = &__get_cpu_var(menu_devices); 250 struct menu_device *data = &__get_cpu_var(menu_devices);
251 data->needs_update = 1;
252}
253
254/**
255 * menu_update - attempts to guess what happened after entry
256 * @dev: the CPU
257 */
258static void menu_update(struct cpuidle_device *dev)
259{
260 struct menu_device *data = &__get_cpu_var(menu_devices);
243 int last_idx = data->last_state_idx; 261 int last_idx = data->last_state_idx;
244 unsigned int last_idle_us = cpuidle_get_last_residency(dev); 262 unsigned int last_idle_us = cpuidle_get_last_residency(dev);
245 struct cpuidle_state *target = &dev->states[last_idx]; 263 struct cpuidle_state *target = &dev->states[last_idx];