aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/cpuidle.c31
-rw-r--r--drivers/cpuidle/governors/menu.c23
2 files changed, 47 insertions, 7 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index dbefe15bd582..a50710843378 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -74,6 +74,17 @@ static void cpuidle_idle_call(void)
74 */ 74 */
75 hrtimer_peek_ahead_timers(); 75 hrtimer_peek_ahead_timers();
76#endif 76#endif
77
78 /*
79 * Call the device's prepare function before calling the
80 * governor's select function. ->prepare gives the device's
81 * cpuidle driver a chance to update any dynamic information
82 * of its cpuidle states for the current idle period, e.g.
83 * state availability, latencies, residencies, etc.
84 */
85 if (dev->prepare)
86 dev->prepare(dev);
87
77 /* ask the governor for the next state */ 88 /* ask the governor for the next state */
78 next_state = cpuidle_curr_governor->select(dev); 89 next_state = cpuidle_curr_governor->select(dev);
79 if (need_resched()) { 90 if (need_resched()) {
@@ -282,6 +293,26 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
282 293
283 poll_idle_init(dev); 294 poll_idle_init(dev);
284 295
296 /*
297 * cpuidle driver should set the dev->power_specified bit
298 * before registering the device if the driver provides
299 * power_usage numbers.
300 *
301 * For those devices whose ->power_specified is not set,
302 * we fill in power_usage with decreasing values as the
303 * cpuidle code has an implicit assumption that state Cn
304 * uses less power than C(n-1).
305 *
306 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
307 * an power value of -1. So we use -2, -3, etc, for other
308 * c-states.
309 */
310 if (!dev->power_specified) {
311 int i;
312 for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
313 dev->states[i].power_usage = -1 - i;
314 }
315
285 per_cpu(cpuidle_devices, dev->cpu) = dev; 316 per_cpu(cpuidle_devices, dev->cpu) = dev;
286 list_add(&dev->device_list, &cpuidle_detected_devices); 317 list_add(&dev->device_list, &cpuidle_detected_devices);
287 if ((ret = cpuidle_add_sysfs(sys_dev))) { 318 if ((ret = cpuidle_add_sysfs(sys_dev))) {
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1b128702d300..c2408bbe9c2e 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -234,6 +234,7 @@ static int menu_select(struct cpuidle_device *dev)
234{ 234{
235 struct menu_device *data = &__get_cpu_var(menu_devices); 235 struct menu_device *data = &__get_cpu_var(menu_devices);
236 int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); 236 int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
237 unsigned int power_usage = -1;
237 int i; 238 int i;
238 int multiplier; 239 int multiplier;
239 240
@@ -278,19 +279,27 @@ static int menu_select(struct cpuidle_device *dev)
278 if (data->expected_us > 5) 279 if (data->expected_us > 5)
279 data->last_state_idx = CPUIDLE_DRIVER_STATE_START; 280 data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
280 281
281 282 /*
282 /* find the deepest idle state that satisfies our constraints */ 283 * Find the idle state with the lowest power while satisfying
284 * our constraints.
285 */
283 for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { 286 for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) {
284 struct cpuidle_state *s = &dev->states[i]; 287 struct cpuidle_state *s = &dev->states[i];
285 288
289 if (s->flags & CPUIDLE_FLAG_IGNORE)
290 continue;
286 if (s->target_residency > data->predicted_us) 291 if (s->target_residency > data->predicted_us)
287 break; 292 continue;
288 if (s->exit_latency > latency_req) 293 if (s->exit_latency > latency_req)
289 break; 294 continue;
290 if (s->exit_latency * multiplier > data->predicted_us) 295 if (s->exit_latency * multiplier > data->predicted_us)
291 break; 296 continue;
292 data->exit_us = s->exit_latency; 297
293 data->last_state_idx = i; 298 if (s->power_usage < power_usage) {
299 power_usage = s->power_usage;
300 data->last_state_idx = i;
301 data->exit_us = s->exit_latency;
302 }
294 } 303 }
295 304
296 return data->last_state_idx; 305 return data->last_state_idx;