diff options
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 37c0ff6c805c..43a54fd6bfa2 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -34,7 +34,7 @@ | |||
34 | static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer); | 34 | static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer); |
35 | static DEFINE_PER_CPU(int, hrtimer_status); | 35 | static DEFINE_PER_CPU(int, hrtimer_status); |
36 | /* menu hrtimer mode */ | 36 | /* menu hrtimer mode */ |
37 | enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT}; | 37 | enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL}; |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Concepts and ideas behind the menu governor | 40 | * Concepts and ideas behind the menu governor |
@@ -116,6 +116,13 @@ enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT}; | |||
116 | * | 116 | * |
117 | */ | 117 | */ |
118 | 118 | ||
119 | /* | ||
120 | * The C-state residency is so long that is is worthwhile to exit | ||
121 | * from the shallow C-state and re-enter into a deeper C-state. | ||
122 | */ | ||
123 | static unsigned int perfect_cstate_ms __read_mostly = 30; | ||
124 | module_param(perfect_cstate_ms, uint, 0000); | ||
125 | |||
119 | struct menu_device { | 126 | struct menu_device { |
120 | int last_state_idx; | 127 | int last_state_idx; |
121 | int needs_update; | 128 | int needs_update; |
@@ -216,6 +223,16 @@ EXPORT_SYMBOL_GPL(menu_hrtimer_cancel); | |||
216 | static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer) | 223 | static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer) |
217 | { | 224 | { |
218 | int cpu = smp_processor_id(); | 225 | int cpu = smp_processor_id(); |
226 | struct menu_device *data = &per_cpu(menu_devices, cpu); | ||
227 | |||
228 | /* In general case, the expected residency is much larger than | ||
229 | * deepest C-state target residency, but prediction logic still | ||
230 | * predicts a small predicted residency, so the prediction | ||
231 | * history is totally broken if the timer is triggered. | ||
232 | * So reset the correction factor. | ||
233 | */ | ||
234 | if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL) | ||
235 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; | ||
219 | 236 | ||
220 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; | 237 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; |
221 | 238 | ||
@@ -353,6 +370,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
353 | /* not deepest C-state chosen for low predicted residency */ | 370 | /* not deepest C-state chosen for low predicted residency */ |
354 | if (low_predicted) { | 371 | if (low_predicted) { |
355 | unsigned int timer_us = 0; | 372 | unsigned int timer_us = 0; |
373 | unsigned int perfect_us = 0; | ||
356 | 374 | ||
357 | /* | 375 | /* |
358 | * Set a timer to detect whether this sleep is much | 376 | * Set a timer to detect whether this sleep is much |
@@ -363,12 +381,26 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
363 | */ | 381 | */ |
364 | timer_us = 2 * (data->predicted_us + MAX_DEVIATION); | 382 | timer_us = 2 * (data->predicted_us + MAX_DEVIATION); |
365 | 383 | ||
384 | perfect_us = perfect_cstate_ms * 1000; | ||
385 | |||
366 | if (repeat && (4 * timer_us < data->expected_us)) { | 386 | if (repeat && (4 * timer_us < data->expected_us)) { |
367 | hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), | 387 | hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), |
368 | HRTIMER_MODE_REL_PINNED); | 388 | HRTIMER_MODE_REL_PINNED); |
369 | /* In repeat case, menu hrtimer is started */ | 389 | /* In repeat case, menu hrtimer is started */ |
370 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT; | 390 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT; |
391 | } else if (perfect_us < data->expected_us) { | ||
392 | /* | ||
393 | * The next timer is long. This could be because | ||
394 | * we did not make a useful prediction. | ||
395 | * In that case, it makes sense to re-enter | ||
396 | * into a deeper C-state after some time. | ||
397 | */ | ||
398 | hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), | ||
399 | HRTIMER_MODE_REL_PINNED); | ||
400 | /* In general case, menu hrtimer is started */ | ||
401 | per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL; | ||
371 | } | 402 | } |
403 | |||
372 | } | 404 | } |
373 | 405 | ||
374 | return data->last_state_idx; | 406 | return data->last_state_idx; |