diff options
Diffstat (limited to 'drivers/cpuidle/governors/menu.c')
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 27fc733cb5b9..03d38c291de6 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -196,7 +196,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev); | |||
196 | * of points is below a threshold. If it is... then use the | 196 | * of points is below a threshold. If it is... then use the |
197 | * average of these 8 points as the estimated value. | 197 | * average of these 8 points as the estimated value. |
198 | */ | 198 | */ |
199 | static void get_typical_interval(struct menu_device *data) | 199 | static unsigned int get_typical_interval(struct menu_device *data) |
200 | { | 200 | { |
201 | int i, divisor; | 201 | int i, divisor; |
202 | unsigned int max, thresh, avg; | 202 | unsigned int max, thresh, avg; |
@@ -253,9 +253,7 @@ again: | |||
253 | if (likely(variance <= U64_MAX/36)) { | 253 | if (likely(variance <= U64_MAX/36)) { |
254 | if ((((u64)avg*avg > variance*36) && (divisor * 4 >= INTERVALS * 3)) | 254 | if ((((u64)avg*avg > variance*36) && (divisor * 4 >= INTERVALS * 3)) |
255 | || variance <= 400) { | 255 | || variance <= 400) { |
256 | if (data->next_timer_us > avg) | 256 | return avg; |
257 | data->predicted_us = avg; | ||
258 | return; | ||
259 | } | 257 | } |
260 | } | 258 | } |
261 | 259 | ||
@@ -269,7 +267,7 @@ again: | |||
269 | * with sporadic activity with a bunch of short pauses. | 267 | * with sporadic activity with a bunch of short pauses. |
270 | */ | 268 | */ |
271 | if ((divisor * 4) <= INTERVALS * 3) | 269 | if ((divisor * 4) <= INTERVALS * 3) |
272 | return; | 270 | return UINT_MAX; |
273 | 271 | ||
274 | thresh = max - 1; | 272 | thresh = max - 1; |
275 | goto again; | 273 | goto again; |
@@ -286,6 +284,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
286 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 284 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
287 | int i; | 285 | int i; |
288 | unsigned int interactivity_req; | 286 | unsigned int interactivity_req; |
287 | unsigned int expected_interval; | ||
289 | unsigned long nr_iowaiters, cpu_load; | 288 | unsigned long nr_iowaiters, cpu_load; |
290 | 289 | ||
291 | if (data->needs_update) { | 290 | if (data->needs_update) { |
@@ -312,32 +311,43 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
312 | data->correction_factor[data->bucket], | 311 | data->correction_factor[data->bucket], |
313 | RESOLUTION * DECAY); | 312 | RESOLUTION * DECAY); |
314 | 313 | ||
315 | get_typical_interval(data); | 314 | expected_interval = get_typical_interval(data); |
316 | 315 | expected_interval = min(expected_interval, data->next_timer_us); | |
317 | /* | ||
318 | * Performance multiplier defines a minimum predicted idle | ||
319 | * duration / latency ratio. Adjust the latency limit if | ||
320 | * necessary. | ||
321 | */ | ||
322 | interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); | ||
323 | if (latency_req > interactivity_req) | ||
324 | latency_req = interactivity_req; | ||
325 | 316 | ||
326 | if (CPUIDLE_DRIVER_STATE_START > 0) { | 317 | if (CPUIDLE_DRIVER_STATE_START > 0) { |
327 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1; | 318 | struct cpuidle_state *s = &drv->states[CPUIDLE_DRIVER_STATE_START]; |
319 | unsigned int polling_threshold; | ||
320 | |||
328 | /* | 321 | /* |
329 | * We want to default to C1 (hlt), not to busy polling | 322 | * We want to default to C1 (hlt), not to busy polling |
330 | * unless the timer is happening really really soon. | 323 | * unless the timer is happening really really soon, or |
324 | * C1's exit latency exceeds the user configured limit. | ||
331 | */ | 325 | */ |
332 | if (interactivity_req > 20 && | 326 | polling_threshold = max_t(unsigned int, 20, s->target_residency); |
333 | !drv->states[CPUIDLE_DRIVER_STATE_START].disabled && | 327 | if (data->next_timer_us > polling_threshold && |
334 | dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) | 328 | latency_req > s->exit_latency && !s->disabled && |
329 | !dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable) | ||
335 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 330 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
331 | else | ||
332 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1; | ||
336 | } else { | 333 | } else { |
337 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 334 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
338 | } | 335 | } |
339 | 336 | ||
340 | /* | 337 | /* |
338 | * Use the lowest expected idle interval to pick the idle state. | ||
339 | */ | ||
340 | data->predicted_us = min(data->predicted_us, expected_interval); | ||
341 | |||
342 | /* | ||
343 | * Use the performance multiplier and the user-configurable | ||
344 | * latency_req to determine the maximum exit latency. | ||
345 | */ | ||
346 | interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); | ||
347 | if (latency_req > interactivity_req) | ||
348 | latency_req = interactivity_req; | ||
349 | |||
350 | /* | ||
341 | * Find the idle state with the lowest power while satisfying | 351 | * Find the idle state with the lowest power while satisfying |
342 | * our constraints. | 352 | * our constraints. |
343 | */ | 353 | */ |