diff options
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index f0995dd2469f..b347c101c1f7 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -387,32 +387,40 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
387 | { | 387 | { |
388 | struct menu_device *data = &__get_cpu_var(menu_devices); | 388 | struct menu_device *data = &__get_cpu_var(menu_devices); |
389 | int last_idx = data->last_state_idx; | 389 | int last_idx = data->last_state_idx; |
390 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); | ||
391 | struct cpuidle_state *target = &drv->states[last_idx]; | 390 | struct cpuidle_state *target = &drv->states[last_idx]; |
392 | unsigned int measured_us; | 391 | unsigned int measured_us; |
393 | unsigned int new_factor; | 392 | unsigned int new_factor; |
394 | 393 | ||
395 | /* | 394 | /* |
396 | * Ugh, this idle state doesn't support residency measurements, so we | 395 | * Try to figure out how much time passed between entry to low |
397 | * are basically lost in the dark. As a compromise, assume we slept | 396 | * power state and occurrence of the wakeup event. |
398 | * for the whole expected time. | 397 | * |
398 | * If the entered idle state didn't support residency measurements, | ||
399 | * we are basically lost in the dark how much time passed. | ||
400 | * As a compromise, assume we slept for the whole expected time. | ||
401 | * | ||
402 | * Any measured amount of time will include the exit latency. | ||
403 | * Since we are interested in when the wakeup begun, not when it | ||
404 | * was completed, we must substract the exit latency. However, if | ||
405 | * the measured amount of time is less than the exit latency, | ||
406 | * assume the state was never reached and the exit latency is 0. | ||
399 | */ | 407 | */ |
400 | if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID))) | 408 | if (unlikely(!(target->flags & CPUIDLE_FLAG_TIME_VALID))) { |
401 | last_idle_us = data->next_timer_us; | 409 | /* Use timer value as is */ |
402 | 410 | measured_us = data->next_timer_us; | |
403 | 411 | ||
404 | measured_us = last_idle_us; | 412 | } else { |
413 | /* Use measured value */ | ||
414 | measured_us = cpuidle_get_last_residency(dev); | ||
405 | 415 | ||
406 | /* | 416 | /* Deduct exit latency */ |
407 | * We correct for the exit latency; we are assuming here that the | 417 | if (measured_us > target->exit_latency) |
408 | * exit latency happens after the event that we're interested in. | 418 | measured_us -= target->exit_latency; |
409 | */ | ||
410 | if (measured_us > target->exit_latency) | ||
411 | measured_us -= target->exit_latency; | ||
412 | 419 | ||
413 | /* Make sure our coefficients do not exceed unity */ | 420 | /* Make sure our coefficients do not exceed unity */ |
414 | if (measured_us > data->next_timer_us) | 421 | if (measured_us > data->next_timer_us) |
415 | measured_us = data->next_timer_us; | 422 | measured_us = data->next_timer_us; |
423 | } | ||
416 | 424 | ||
417 | /* Update our correction ratio */ | 425 | /* Update our correction ratio */ |
418 | new_factor = data->correction_factor[data->bucket]; | 426 | new_factor = data->correction_factor[data->bucket]; |
@@ -439,7 +447,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
439 | data->correction_factor[data->bucket] = new_factor; | 447 | data->correction_factor[data->bucket] = new_factor; |
440 | 448 | ||
441 | /* update the repeating-pattern data */ | 449 | /* update the repeating-pattern data */ |
442 | data->intervals[data->interval_ptr++] = last_idle_us; | 450 | data->intervals[data->interval_ptr++] = measured_us; |
443 | if (data->interval_ptr >= INTERVALS) | 451 | if (data->interval_ptr >= INTERVALS) |
444 | data->interval_ptr = 0; | 452 | data->interval_ptr = 0; |
445 | } | 453 | } |