aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r--drivers/cpuidle/governors/menu.c28
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;