aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpuidle/governors
diff options
context:
space:
mode:
authorRik van Riel <riel@redhat.com>2016-03-16 12:14:00 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-03-16 21:40:32 -0400
commite132b9b3bc7f19e9b158e42b323881d5dee5ecf3 (patch)
treea0a6110382cfc74e379542505edbc0466894f6de /drivers/cpuidle/governors
parent3b99669b75db04e411bb298591224a9e8e4f57fb (diff)
cpuidle: menu: use high confidence factors only when considering polling
The menu governor uses five different factors to pick the idle state: - the user configured latency_req - the time until the next timer (next_timer_us) - the typical sleep interval, as measured recently - an estimate of sleep time by dividing next_timer_us by an observed factor - a load corrected version of the above, divided again by load Only the first three items are known with enough confidence that we can use them to consider polling, instead of an actual CPU idle state, because the cost of being wrong about polling can be excessive power use. The latter two are used in the menu governor's main selection loop, and can result in choosing a shallower idle state when the system is expected to be busy again soon. This pushes a busy system in the "performance" direction of the performance<>power tradeoff, when choosing between idle states, but stays more strictly on the "power" state when deciding between polling and C1. Signed-off-by: Rik van Riel <riel@redhat.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpuidle/governors')
-rw-r--r--drivers/cpuidle/governors/menu.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 27fc733cb5b9..00c5f891e352 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 */
199static void get_typical_interval(struct menu_device *data) 199static 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,39 @@ 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 data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1;
328 /* 319 /*
329 * We want to default to C1 (hlt), not to busy polling 320 * We want to default to C1 (hlt), not to busy polling
330 * unless the timer is happening really really soon. 321 * unless the timer is happening really really soon, or
322 * C1's exit latency exceeds the user configured limit.
331 */ 323 */
332 if (interactivity_req > 20 && 324 if (expected_interval > drv->states[CPUIDLE_DRIVER_STATE_START].target_residency &&
325 latency_req > drv->states[CPUIDLE_DRIVER_STATE_START].exit_latency &&
333 !drv->states[CPUIDLE_DRIVER_STATE_START].disabled && 326 !drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
334 dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) 327 !dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable)
335 data->last_state_idx = CPUIDLE_DRIVER_STATE_START; 328 data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
336 } else { 329 } else {
337 data->last_state_idx = CPUIDLE_DRIVER_STATE_START; 330 data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
338 } 331 }
339 332
340 /* 333 /*
334 * Use the lowest expected idle interval to pick the idle state.
335 */
336 data->predicted_us = min(data->predicted_us, expected_interval);
337
338 /*
339 * Use the performance multiplier and the user-configurable
340 * latency_req to determine the maximum exit latency.
341 */
342 interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load);
343 if (latency_req > interactivity_req)
344 latency_req = interactivity_req;
345
346 /*
341 * Find the idle state with the lowest power while satisfying 347 * Find the idle state with the lowest power while satisfying
342 * our constraints. 348 * our constraints.
343 */ 349 */