|
@@ -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;
|
|
|
/*
|