Re: [PATCH] cpuidle: menu: Handle stopped tick more aggressively
Hi Rafael, I love your patch! Perhaps something to improve: url: https://github.com/0day-ci/linux/commits/Rafael-J-Wysocki/cpuidle-menu-Handle-stopped-tick-more-aggressively/20180811-191914 base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next smatch warnings: drivers/cpuidle/governors/menu.c:374 menu_select() error: uninitialized symbol 'first_idx'. # https://github.com/0day-ci/linux/commit/5f9f09809ebd1b4f7820c9925a0cbd417bd3a823 git remote add linux-review https://github.com/0day-ci/linux git remote update linux-review git checkout 5f9f09809ebd1b4f7820c9925a0cbd417bd3a823 vim +/first_idx +374 drivers/cpuidle/governors/menu.c 1f85f87d4 Arjan van de Ven 2010-05-24 276 4f86d3a8e Len Brown 2007-10-03 277 /** 4f86d3a8e Len Brown 2007-10-03 278 * menu_select - selects the next idle state to enter 46bcfad7a Deepthi Dharwar 2011-10-28 279 * @drv: cpuidle driver containing state data 4f86d3a8e Len Brown 2007-10-03 280 * @dev: the CPU 45f1ff59e Rafael J. Wysocki 2018-03-22 281 * @stop_tick: indication on whether or not to stop the tick 4f86d3a8e Len Brown 2007-10-03 282 */ 45f1ff59e Rafael J. Wysocki 2018-03-22 283 static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, 45f1ff59e Rafael J. Wysocki 2018-03-22 284 bool *stop_tick) 4f86d3a8e Len Brown 2007-10-03 285 { 229b6863b Christoph Lameter 2014-08-17 286 struct menu_device *data = this_cpu_ptr(_devices); 0fc784fb0 Rafael J. Wysocki 2018-05-30 287 int latency_req = cpuidle_governor_latency_req(dev->cpu); 4f86d3a8e Len Brown 2007-10-03 288 int i; 3ed09c945 Nicholas Piggin 2017-06-26 289 int first_idx; 3ed09c945 Nicholas Piggin 2017-06-26 290 int idx; 96e95182e tuukka.tikka...@linaro.org2014-02-24 291 unsigned int interactivity_req; e132b9b3b Rik van Riel 2016-03-16 292 unsigned int expected_interval; 372ba8cb4 Mel Gorman2014-08-06 293 unsigned long nr_iowaiters, cpu_load; 296bb1e51 Rafael J. Wysocki 2018-04-05 294 ktime_t delta_next; 4f86d3a8e Len Brown 2007-10-03 295 672917dcc Corrado Zoccolo 2009-09-21 296 if (data->needs_update) { 46bcfad7a Deepthi Dharwar 2011-10-28 297 menu_update(drv, dev); 672917dcc Corrado Zoccolo 2009-09-21 298 data->needs_update = 0; 672917dcc Corrado Zoccolo 2009-09-21 299 } 672917dcc Corrado Zoccolo 2009-09-21 300 69d25870f Arjan van de Ven 2009-09-21 301 /* Special case when user has set very strict latency requirement */ 45f1ff59e Rafael J. Wysocki 2018-03-22 302 if (unlikely(latency_req == 0)) { 45f1ff59e Rafael J. Wysocki 2018-03-22 303 *stop_tick = false; a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 304 return 0; 45f1ff59e Rafael J. Wysocki 2018-03-22 305 } a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 306 69d25870f Arjan van de Ven 2009-09-21 307 /* determine the expected residency time, round up */ 296bb1e51 Rafael J. Wysocki 2018-04-05 308 data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(_next)); 69d25870f Arjan van de Ven 2009-09-21 309 5f9f09809 Rafael J. Wysocki 2018-08-10 310 /* 5f9f09809 Rafael J. Wysocki 2018-08-10 311 * If the tick is already stopped, the cost of possible short idle 5f9f09809 Rafael J. Wysocki 2018-08-10 312 * duration misprediction is much higher, because the CPU may be stuck 5f9f09809 Rafael J. Wysocki 2018-08-10 313 * in a shallow idle state for a long time as a result of it. In that 5f9f09809 Rafael J. Wysocki 2018-08-10 314 * case say we might mispredict and use the known time till the closest 5f9f09809 Rafael J. Wysocki 2018-08-10 315 * timer event for the idle state selection. 5f9f09809 Rafael J. Wysocki 2018-08-10 316 */ 5f9f09809 Rafael J. Wysocki 2018-08-10 317 if (tick_nohz_tick_stopped()) { 5f9f09809 Rafael J. Wysocki 2018-08-10 318 data->predicted_us = ktime_to_us(delta_next); 5f9f09809 Rafael J. Wysocki 2018-08-10 319 goto select; ^^^ We hit this goto 5f9f09809 Rafael J. Wysocki 2018-08-10 320 } 5f9f09809 Rafael J.
Re: [PATCH] cpuidle: menu: Handle stopped tick more aggressively
Hi Rafael, I love your patch! Perhaps something to improve: url: https://github.com/0day-ci/linux/commits/Rafael-J-Wysocki/cpuidle-menu-Handle-stopped-tick-more-aggressively/20180811-191914 base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next smatch warnings: drivers/cpuidle/governors/menu.c:374 menu_select() error: uninitialized symbol 'first_idx'. # https://github.com/0day-ci/linux/commit/5f9f09809ebd1b4f7820c9925a0cbd417bd3a823 git remote add linux-review https://github.com/0day-ci/linux git remote update linux-review git checkout 5f9f09809ebd1b4f7820c9925a0cbd417bd3a823 vim +/first_idx +374 drivers/cpuidle/governors/menu.c 1f85f87d4 Arjan van de Ven 2010-05-24 276 4f86d3a8e Len Brown 2007-10-03 277 /** 4f86d3a8e Len Brown 2007-10-03 278 * menu_select - selects the next idle state to enter 46bcfad7a Deepthi Dharwar 2011-10-28 279 * @drv: cpuidle driver containing state data 4f86d3a8e Len Brown 2007-10-03 280 * @dev: the CPU 45f1ff59e Rafael J. Wysocki 2018-03-22 281 * @stop_tick: indication on whether or not to stop the tick 4f86d3a8e Len Brown 2007-10-03 282 */ 45f1ff59e Rafael J. Wysocki 2018-03-22 283 static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, 45f1ff59e Rafael J. Wysocki 2018-03-22 284 bool *stop_tick) 4f86d3a8e Len Brown 2007-10-03 285 { 229b6863b Christoph Lameter 2014-08-17 286 struct menu_device *data = this_cpu_ptr(_devices); 0fc784fb0 Rafael J. Wysocki 2018-05-30 287 int latency_req = cpuidle_governor_latency_req(dev->cpu); 4f86d3a8e Len Brown 2007-10-03 288 int i; 3ed09c945 Nicholas Piggin 2017-06-26 289 int first_idx; 3ed09c945 Nicholas Piggin 2017-06-26 290 int idx; 96e95182e tuukka.tikka...@linaro.org2014-02-24 291 unsigned int interactivity_req; e132b9b3b Rik van Riel 2016-03-16 292 unsigned int expected_interval; 372ba8cb4 Mel Gorman2014-08-06 293 unsigned long nr_iowaiters, cpu_load; 296bb1e51 Rafael J. Wysocki 2018-04-05 294 ktime_t delta_next; 4f86d3a8e Len Brown 2007-10-03 295 672917dcc Corrado Zoccolo 2009-09-21 296 if (data->needs_update) { 46bcfad7a Deepthi Dharwar 2011-10-28 297 menu_update(drv, dev); 672917dcc Corrado Zoccolo 2009-09-21 298 data->needs_update = 0; 672917dcc Corrado Zoccolo 2009-09-21 299 } 672917dcc Corrado Zoccolo 2009-09-21 300 69d25870f Arjan van de Ven 2009-09-21 301 /* Special case when user has set very strict latency requirement */ 45f1ff59e Rafael J. Wysocki 2018-03-22 302 if (unlikely(latency_req == 0)) { 45f1ff59e Rafael J. Wysocki 2018-03-22 303 *stop_tick = false; a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 304 return 0; 45f1ff59e Rafael J. Wysocki 2018-03-22 305 } a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 306 69d25870f Arjan van de Ven 2009-09-21 307 /* determine the expected residency time, round up */ 296bb1e51 Rafael J. Wysocki 2018-04-05 308 data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(_next)); 69d25870f Arjan van de Ven 2009-09-21 309 5f9f09809 Rafael J. Wysocki 2018-08-10 310 /* 5f9f09809 Rafael J. Wysocki 2018-08-10 311 * If the tick is already stopped, the cost of possible short idle 5f9f09809 Rafael J. Wysocki 2018-08-10 312 * duration misprediction is much higher, because the CPU may be stuck 5f9f09809 Rafael J. Wysocki 2018-08-10 313 * in a shallow idle state for a long time as a result of it. In that 5f9f09809 Rafael J. Wysocki 2018-08-10 314 * case say we might mispredict and use the known time till the closest 5f9f09809 Rafael J. Wysocki 2018-08-10 315 * timer event for the idle state selection. 5f9f09809 Rafael J. Wysocki 2018-08-10 316 */ 5f9f09809 Rafael J. Wysocki 2018-08-10 317 if (tick_nohz_tick_stopped()) { 5f9f09809 Rafael J. Wysocki 2018-08-10 318 data->predicted_us = ktime_to_us(delta_next); 5f9f09809 Rafael J. Wysocki 2018-08-10 319 goto select; ^^^ We hit this goto 5f9f09809 Rafael J. Wysocki 2018-08-10 320 } 5f9f09809 Rafael J.
Re: [PATCH] cpuidle: menu: Handle stopped tick more aggressively
Hi Rafael, I love your patch! Perhaps something to improve: [auto build test WARNING on pm/linux-next] [also build test WARNING on v4.18-rc8 next-20180810] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Rafael-J-Wysocki/cpuidle-menu-Handle-stopped-tick-more-aggressively/20180811-191914 base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next config: mips-allyesconfig (attached as .config) compiler: mips-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.2.0 make.cross ARCH=mips Note: it may well be a FALSE warning. FWIW you are at least aware of it now. http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings All warnings (new ones prefixed by >>): drivers/cpuidle/governors/menu.c: In function 'menu_select': >> drivers/cpuidle/governors/menu.c:289:6: warning: 'first_idx' may be used >> uninitialized in this function [-Wmaybe-uninitialized] int first_idx; ^ vim +/first_idx +289 drivers/cpuidle/governors/menu.c 1f85f87d4 Arjan van de Ven 2010-05-24 276 4f86d3a8e Len Brown 2007-10-03 277 /** 4f86d3a8e Len Brown 2007-10-03 278 * menu_select - selects the next idle state to enter 46bcfad7a Deepthi Dharwar 2011-10-28 279 * @drv: cpuidle driver containing state data 4f86d3a8e Len Brown 2007-10-03 280 * @dev: the CPU 45f1ff59e Rafael J. Wysocki 2018-03-22 281 * @stop_tick: indication on whether or not to stop the tick 4f86d3a8e Len Brown 2007-10-03 282 */ 45f1ff59e Rafael J. Wysocki 2018-03-22 283 static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, 45f1ff59e Rafael J. Wysocki 2018-03-22 284 bool *stop_tick) 4f86d3a8e Len Brown 2007-10-03 285 { 229b6863b Christoph Lameter 2014-08-17 286 struct menu_device *data = this_cpu_ptr(_devices); 0fc784fb0 Rafael J. Wysocki 2018-05-30 287 int latency_req = cpuidle_governor_latency_req(dev->cpu); 4f86d3a8e Len Brown 2007-10-03 288 int i; 3ed09c945 Nicholas Piggin 2017-06-26 @289 int first_idx; 3ed09c945 Nicholas Piggin 2017-06-26 290 int idx; 96e95182e tuukka.tikka...@linaro.org2014-02-24 291 unsigned int interactivity_req; e132b9b3b Rik van Riel 2016-03-16 292 unsigned int expected_interval; 372ba8cb4 Mel Gorman2014-08-06 293 unsigned long nr_iowaiters, cpu_load; 296bb1e51 Rafael J. Wysocki 2018-04-05 294 ktime_t delta_next; 4f86d3a8e Len Brown 2007-10-03 295 672917dcc Corrado Zoccolo 2009-09-21 296 if (data->needs_update) { 46bcfad7a Deepthi Dharwar 2011-10-28 297 menu_update(drv, dev); 672917dcc Corrado Zoccolo 2009-09-21 298 data->needs_update = 0; 672917dcc Corrado Zoccolo 2009-09-21 299 } 672917dcc Corrado Zoccolo 2009-09-21 300 69d25870f Arjan van de Ven 2009-09-21 301 /* Special case when user has set very strict latency requirement */ 45f1ff59e Rafael J. Wysocki 2018-03-22 302 if (unlikely(latency_req == 0)) { 45f1ff59e Rafael J. Wysocki 2018-03-22 303 *stop_tick = false; a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 304 return 0; 45f1ff59e Rafael J. Wysocki 2018-03-22 305 } a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 306 69d25870f Arjan van de Ven 2009-09-21 307 /* determine the expected residency time, round up */ 296bb1e51 Rafael J. Wysocki 2018-04-05 308 data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(_next)); 69d25870f Arjan van de Ven 2009-09-21 309 5f9f09809 Rafael J. Wysocki 2018-08-10 310 /* 5f9f09809 Rafael J. Wysocki 2018-08-10 311 * If the tick is already stopped, the cost of possible short idle 5f9f09809 Rafael J. Wysocki 2018-08-10 312 * duration misprediction is much higher, because the CPU may be stuck 5f9f09809 Rafael J. Wysocki 2018-08-10 313 * in a shallow idle state for a long time as a result of it. In that 5f9f09809 Rafael J. Wysocki 2018-08-10 314 * case say we might mispredict and use the known time till the closest 5f9f09809 Rafael J. Wysocki
Re: [PATCH] cpuidle: menu: Handle stopped tick more aggressively
Hi Rafael, I love your patch! Perhaps something to improve: [auto build test WARNING on pm/linux-next] [also build test WARNING on v4.18-rc8 next-20180810] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Rafael-J-Wysocki/cpuidle-menu-Handle-stopped-tick-more-aggressively/20180811-191914 base: https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next config: mips-allyesconfig (attached as .config) compiler: mips-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.2.0 make.cross ARCH=mips Note: it may well be a FALSE warning. FWIW you are at least aware of it now. http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings All warnings (new ones prefixed by >>): drivers/cpuidle/governors/menu.c: In function 'menu_select': >> drivers/cpuidle/governors/menu.c:289:6: warning: 'first_idx' may be used >> uninitialized in this function [-Wmaybe-uninitialized] int first_idx; ^ vim +/first_idx +289 drivers/cpuidle/governors/menu.c 1f85f87d4 Arjan van de Ven 2010-05-24 276 4f86d3a8e Len Brown 2007-10-03 277 /** 4f86d3a8e Len Brown 2007-10-03 278 * menu_select - selects the next idle state to enter 46bcfad7a Deepthi Dharwar 2011-10-28 279 * @drv: cpuidle driver containing state data 4f86d3a8e Len Brown 2007-10-03 280 * @dev: the CPU 45f1ff59e Rafael J. Wysocki 2018-03-22 281 * @stop_tick: indication on whether or not to stop the tick 4f86d3a8e Len Brown 2007-10-03 282 */ 45f1ff59e Rafael J. Wysocki 2018-03-22 283 static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, 45f1ff59e Rafael J. Wysocki 2018-03-22 284 bool *stop_tick) 4f86d3a8e Len Brown 2007-10-03 285 { 229b6863b Christoph Lameter 2014-08-17 286 struct menu_device *data = this_cpu_ptr(_devices); 0fc784fb0 Rafael J. Wysocki 2018-05-30 287 int latency_req = cpuidle_governor_latency_req(dev->cpu); 4f86d3a8e Len Brown 2007-10-03 288 int i; 3ed09c945 Nicholas Piggin 2017-06-26 @289 int first_idx; 3ed09c945 Nicholas Piggin 2017-06-26 290 int idx; 96e95182e tuukka.tikka...@linaro.org2014-02-24 291 unsigned int interactivity_req; e132b9b3b Rik van Riel 2016-03-16 292 unsigned int expected_interval; 372ba8cb4 Mel Gorman2014-08-06 293 unsigned long nr_iowaiters, cpu_load; 296bb1e51 Rafael J. Wysocki 2018-04-05 294 ktime_t delta_next; 4f86d3a8e Len Brown 2007-10-03 295 672917dcc Corrado Zoccolo 2009-09-21 296 if (data->needs_update) { 46bcfad7a Deepthi Dharwar 2011-10-28 297 menu_update(drv, dev); 672917dcc Corrado Zoccolo 2009-09-21 298 data->needs_update = 0; 672917dcc Corrado Zoccolo 2009-09-21 299 } 672917dcc Corrado Zoccolo 2009-09-21 300 69d25870f Arjan van de Ven 2009-09-21 301 /* Special case when user has set very strict latency requirement */ 45f1ff59e Rafael J. Wysocki 2018-03-22 302 if (unlikely(latency_req == 0)) { 45f1ff59e Rafael J. Wysocki 2018-03-22 303 *stop_tick = false; a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 304 return 0; 45f1ff59e Rafael J. Wysocki 2018-03-22 305 } a2bd92023 venkatesh.pallip...@intel.com 2008-07-30 306 69d25870f Arjan van de Ven 2009-09-21 307 /* determine the expected residency time, round up */ 296bb1e51 Rafael J. Wysocki 2018-04-05 308 data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(_next)); 69d25870f Arjan van de Ven 2009-09-21 309 5f9f09809 Rafael J. Wysocki 2018-08-10 310 /* 5f9f09809 Rafael J. Wysocki 2018-08-10 311 * If the tick is already stopped, the cost of possible short idle 5f9f09809 Rafael J. Wysocki 2018-08-10 312 * duration misprediction is much higher, because the CPU may be stuck 5f9f09809 Rafael J. Wysocki 2018-08-10 313 * in a shallow idle state for a long time as a result of it. In that 5f9f09809 Rafael J. Wysocki 2018-08-10 314 * case say we might mispredict and use the known time till the closest 5f9f09809 Rafael J. Wysocki
[PATCH] cpuidle: menu: Handle stopped tick more aggressively
From: Rafael J. Wysocki Commit 87c9fe6ee495 (cpuidle: menu: Avoid selecting shallow states with stopped tick) missed the case when the target residencies of deep idle states of CPUs are above the tick boundary which may cause the CPU to get stuck in a shallow idle state for a long time. Say there are two CPU idle states available: one shallow, with the target residency much below the tick boundary and one deep, with the target residency significantly above the tick boundary. In that case, if the tick has been stopped already and the expected next timer event is relatively far in the future, the governor will assume the idle duration to be equal to TICK_USEC and it will select the idle state for the CPU accordingly. However, that will cause the shallow state to be selected even though it would have been more energy-efficient to select the deep one. To address this issue, modify the governor to always assume idle duration to be equal to the time till the closest timer event if the tick is not running which will cause the selected idle states to always match the known CPU wakeup time. Also make it always indicate that the tick should be stopped in that case for consistency. Fixes: 87c9fe6ee495 (cpuidle: menu: Avoid selecting shallow states with stopped tick) Reported-by: Leo Yan Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 49 ++- 1 file changed, 23 insertions(+), 26 deletions(-) Index: linux-pm/drivers/cpuidle/governors/menu.c === --- linux-pm.orig/drivers/cpuidle/governors/menu.c +++ linux-pm/drivers/cpuidle/governors/menu.c @@ -307,6 +307,18 @@ static int menu_select(struct cpuidle_dr /* determine the expected residency time, round up */ data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(_next)); + /* +* If the tick is already stopped, the cost of possible short idle +* duration misprediction is much higher, because the CPU may be stuck +* in a shallow idle state for a long time as a result of it. In that +* case say we might mispredict and use the known time till the closest +* timer event for the idle state selection. +*/ + if (tick_nohz_tick_stopped()) { + data->predicted_us = ktime_to_us(delta_next); + goto select; + } + get_iowait_load(_iowaiters, _load); data->bucket = which_bucket(data->next_timer_us, nr_iowaiters); @@ -344,29 +356,15 @@ static int menu_select(struct cpuidle_dr */ data->predicted_us = min(data->predicted_us, expected_interval); - if (tick_nohz_tick_stopped()) { - /* -* If the tick is already stopped, the cost of possible short -* idle duration misprediction is much higher, because the CPU -* may be stuck in a shallow idle state for a long time as a -* result of it. In that case say we might mispredict and try -* to force the CPU into a state for which we would have stopped -* the tick, unless a timer is going to expire really soon -* anyway. -*/ - if (data->predicted_us < TICK_USEC) - data->predicted_us = min_t(unsigned int, TICK_USEC, - ktime_to_us(delta_next)); - } else { - /* -* Use the performance multiplier and the user-configurable -* latency_req to determine the maximum exit latency. -*/ - interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); - if (latency_req > interactivity_req) - latency_req = interactivity_req; - } + /* +* Use the performance multiplier and the user-configurable latency_req +* to determine the maximum exit latency. +*/ + interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); + if (latency_req > interactivity_req) + latency_req = interactivity_req; +select: expected_interval = data->predicted_us; /* * Find the idle state with the lowest power while satisfying @@ -403,14 +401,13 @@ static int menu_select(struct cpuidle_dr * Don't stop the tick if the selected state is a polling one or if the * expected idle duration is shorter than the tick period length. */ - if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || - expected_interval < TICK_USEC) { + if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || + expected_interval < TICK_USEC) && !tick_nohz_tick_stopped()) { unsigned int delta_next_us = ktime_to_us(delta_next); *stop_tick = false; - if
[PATCH] cpuidle: menu: Handle stopped tick more aggressively
From: Rafael J. Wysocki Commit 87c9fe6ee495 (cpuidle: menu: Avoid selecting shallow states with stopped tick) missed the case when the target residencies of deep idle states of CPUs are above the tick boundary which may cause the CPU to get stuck in a shallow idle state for a long time. Say there are two CPU idle states available: one shallow, with the target residency much below the tick boundary and one deep, with the target residency significantly above the tick boundary. In that case, if the tick has been stopped already and the expected next timer event is relatively far in the future, the governor will assume the idle duration to be equal to TICK_USEC and it will select the idle state for the CPU accordingly. However, that will cause the shallow state to be selected even though it would have been more energy-efficient to select the deep one. To address this issue, modify the governor to always assume idle duration to be equal to the time till the closest timer event if the tick is not running which will cause the selected idle states to always match the known CPU wakeup time. Also make it always indicate that the tick should be stopped in that case for consistency. Fixes: 87c9fe6ee495 (cpuidle: menu: Avoid selecting shallow states with stopped tick) Reported-by: Leo Yan Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/menu.c | 49 ++- 1 file changed, 23 insertions(+), 26 deletions(-) Index: linux-pm/drivers/cpuidle/governors/menu.c === --- linux-pm.orig/drivers/cpuidle/governors/menu.c +++ linux-pm/drivers/cpuidle/governors/menu.c @@ -307,6 +307,18 @@ static int menu_select(struct cpuidle_dr /* determine the expected residency time, round up */ data->next_timer_us = ktime_to_us(tick_nohz_get_sleep_length(_next)); + /* +* If the tick is already stopped, the cost of possible short idle +* duration misprediction is much higher, because the CPU may be stuck +* in a shallow idle state for a long time as a result of it. In that +* case say we might mispredict and use the known time till the closest +* timer event for the idle state selection. +*/ + if (tick_nohz_tick_stopped()) { + data->predicted_us = ktime_to_us(delta_next); + goto select; + } + get_iowait_load(_iowaiters, _load); data->bucket = which_bucket(data->next_timer_us, nr_iowaiters); @@ -344,29 +356,15 @@ static int menu_select(struct cpuidle_dr */ data->predicted_us = min(data->predicted_us, expected_interval); - if (tick_nohz_tick_stopped()) { - /* -* If the tick is already stopped, the cost of possible short -* idle duration misprediction is much higher, because the CPU -* may be stuck in a shallow idle state for a long time as a -* result of it. In that case say we might mispredict and try -* to force the CPU into a state for which we would have stopped -* the tick, unless a timer is going to expire really soon -* anyway. -*/ - if (data->predicted_us < TICK_USEC) - data->predicted_us = min_t(unsigned int, TICK_USEC, - ktime_to_us(delta_next)); - } else { - /* -* Use the performance multiplier and the user-configurable -* latency_req to determine the maximum exit latency. -*/ - interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); - if (latency_req > interactivity_req) - latency_req = interactivity_req; - } + /* +* Use the performance multiplier and the user-configurable latency_req +* to determine the maximum exit latency. +*/ + interactivity_req = data->predicted_us / performance_multiplier(nr_iowaiters, cpu_load); + if (latency_req > interactivity_req) + latency_req = interactivity_req; +select: expected_interval = data->predicted_us; /* * Find the idle state with the lowest power while satisfying @@ -403,14 +401,13 @@ static int menu_select(struct cpuidle_dr * Don't stop the tick if the selected state is a polling one or if the * expected idle duration is shorter than the tick period length. */ - if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || - expected_interval < TICK_USEC) { + if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || + expected_interval < TICK_USEC) && !tick_nohz_tick_stopped()) { unsigned int delta_next_us = ktime_to_us(delta_next); *stop_tick = false; - if