diff options
| -rw-r--r-- | drivers/cpuidle/governors/menu.c | 29 | 
1 files changed, 22 insertions, 7 deletions
| diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 267982e471e0..1bfe03ceb236 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -352,13 +352,28 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,  	 */  	data->predicted_us = min(data->predicted_us, expected_interval); -	/* -	 * 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; +	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; +	}  	expected_interval = data->predicted_us;  	/* | 
