diff options
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index a8b31b0ca57f..cf7f2f0e4ef5 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -123,10 +123,10 @@ struct menu_device { | |||
123 | int needs_update; | 123 | int needs_update; |
124 | 124 | ||
125 | unsigned int expected_us; | 125 | unsigned int expected_us; |
126 | u64 predicted_us; | 126 | unsigned int predicted_us; |
127 | unsigned int exit_us; | 127 | unsigned int exit_us; |
128 | unsigned int bucket; | 128 | unsigned int bucket; |
129 | u64 correction_factor[BUCKETS]; | 129 | unsigned int correction_factor[BUCKETS]; |
130 | unsigned int intervals[INTERVALS]; | 130 | unsigned int intervals[INTERVALS]; |
131 | int interval_ptr; | 131 | int interval_ptr; |
132 | }; | 132 | }; |
@@ -321,8 +321,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
321 | if (data->correction_factor[data->bucket] == 0) | 321 | if (data->correction_factor[data->bucket] == 0) |
322 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; | 322 | data->correction_factor[data->bucket] = RESOLUTION * DECAY; |
323 | 323 | ||
324 | /* Make sure to round up for half microseconds */ | 324 | /* |
325 | data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], | 325 | * Force the result of multiplication to be 64 bits even if both |
326 | * operands are 32 bits. | ||
327 | * Make sure to round up for half microseconds. | ||
328 | */ | ||
329 | data->predicted_us = div_round64((uint64_t)data->expected_us * | ||
330 | data->correction_factor[data->bucket], | ||
326 | RESOLUTION * DECAY); | 331 | RESOLUTION * DECAY); |
327 | 332 | ||
328 | get_typical_interval(data); | 333 | get_typical_interval(data); |
@@ -388,7 +393,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
388 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); | 393 | unsigned int last_idle_us = cpuidle_get_last_residency(dev); |
389 | struct cpuidle_state *target = &drv->states[last_idx]; | 394 | struct cpuidle_state *target = &drv->states[last_idx]; |
390 | unsigned int measured_us; | 395 | unsigned int measured_us; |
391 | u64 new_factor; | 396 | unsigned int new_factor; |
392 | 397 | ||
393 | /* | 398 | /* |
394 | * Ugh, this idle state doesn't support residency measurements, so we | 399 | * Ugh, this idle state doesn't support residency measurements, so we |
@@ -409,10 +414,9 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
409 | measured_us -= data->exit_us; | 414 | measured_us -= data->exit_us; |
410 | 415 | ||
411 | 416 | ||
412 | /* update our correction ratio */ | 417 | /* Update our correction ratio */ |
413 | 418 | new_factor = data->correction_factor[data->bucket]; | |
414 | new_factor = data->correction_factor[data->bucket] | 419 | new_factor -= new_factor / DECAY; |
415 | * (DECAY - 1) / DECAY; | ||
416 | 420 | ||
417 | if (data->expected_us > 0 && measured_us < MAX_INTERESTING) | 421 | if (data->expected_us > 0 && measured_us < MAX_INTERESTING) |
418 | new_factor += RESOLUTION * measured_us / data->expected_us; | 422 | new_factor += RESOLUTION * measured_us / data->expected_us; |
@@ -425,9 +429,11 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
425 | 429 | ||
426 | /* | 430 | /* |
427 | * We don't want 0 as factor; we always want at least | 431 | * We don't want 0 as factor; we always want at least |
428 | * a tiny bit of estimated time. | 432 | * a tiny bit of estimated time. Fortunately, due to rounding, |
433 | * new_factor will stay nonzero regardless of measured_us values | ||
434 | * and the compiler can eliminate this test as long as DECAY > 1. | ||
429 | */ | 435 | */ |
430 | if (new_factor == 0) | 436 | if (DECAY == 1 && unlikely(new_factor == 0)) |
431 | new_factor = 1; | 437 | new_factor = 1; |
432 | 438 | ||
433 | data->correction_factor[data->bucket] = new_factor; | 439 | data->correction_factor[data->bucket] = new_factor; |