@@ -407,50 +407,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
407407 * better choice.
408408 */
409409 if (2 * idx_intercept_sum > cpu_data -> total - idx_hit_sum ) {
410- int min_idx = idx0 ;
411-
412- if (tick_nohz_tick_stopped ()) {
413- /*
414- * Look for the shallowest idle state below the current
415- * candidate one whose target residency is at least
416- * equal to the tick period length.
417- */
418- while (min_idx < idx &&
419- drv -> states [min_idx ].target_residency_ns < TICK_NSEC )
420- min_idx ++ ;
421-
422- /*
423- * Avoid selecting a state with a lower index, but with
424- * the same target residency as the current candidate
425- * one.
426- */
427- if (drv -> states [min_idx ].target_residency_ns ==
428- drv -> states [idx ].target_residency_ns )
429- goto constraint ;
430- }
431-
432- /*
433- * If the minimum state index is greater than or equal to the
434- * index of the state with the maximum intercepts metric and
435- * the corresponding state is enabled, there is no need to look
436- * at the deeper states.
437- */
438- if (min_idx >= intercept_max_idx &&
439- !dev -> states_usage [min_idx ].disable ) {
440- idx = min_idx ;
441- goto constraint ;
442- }
443-
444410 /*
445411 * Look for the deepest enabled idle state, at most as deep as
446412 * the one with the maximum intercepts metric, whose target
447413 * residency had not been greater than the idle duration in over
448414 * a half of the relevant cases in the past.
449- *
450- * Take the possible duration limitation present if the tick
451- * has been stopped already into account.
452415 */
453- for (i = idx - 1 , intercept_sum = 0 ; i >= min_idx ; i -- ) {
416+ for (i = idx - 1 , intercept_sum = 0 ; i >= idx0 ; i -- ) {
454417 intercept_sum += cpu_data -> state_bins [i ].intercepts ;
455418
456419 if (dev -> states_usage [i ].disable )
@@ -463,7 +426,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
463426 }
464427 }
465428
466- constraint :
467429 /*
468430 * If there is a latency constraint, it may be necessary to select an
469431 * idle state shallower than the current candidate one.
@@ -472,13 +434,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
472434 idx = constraint_idx ;
473435
474436 /*
475- * If either the candidate state is state 0 or its target residency is
476- * low enough, there is basically nothing more to do, but if the sleep
477- * length is not updated, the subsequent wakeup will be counted as an
478- * "intercept" which may be problematic in the cases when timer wakeups
479- * are dominant. Namely, it may effectively prevent deeper idle states
480- * from being selected at one point even if no imminent timers are
481- * scheduled.
437+ * If the tick has not been stopped and either the candidate state is
438+ * state 0 or its target residency is low enough, there is basically
439+ * nothing more to do, but if the sleep length is not updated, the
440+ * subsequent wakeup will be counted as an "intercept". That may be
441+ * problematic in the cases when timer wakeups are dominant because it
442+ * may effectively prevent deeper idle states from being selected at one
443+ * point even if no imminent timers are scheduled.
482444 *
483445 * However, frequent timers in the RESIDENCY_THRESHOLD_NS range on one
484446 * CPU are unlikely (user space has a default 50 us slack value for
@@ -494,14 +456,39 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
494456 * shallow idle states regardless of the wakeup type, so the sleep
495457 * length need not be known in that case.
496458 */
497- if ((!idx || drv -> states [idx ].target_residency_ns < RESIDENCY_THRESHOLD_NS ) &&
459+ if (!tick_nohz_tick_stopped () && (!idx ||
460+ drv -> states [idx ].target_residency_ns < RESIDENCY_THRESHOLD_NS ) &&
498461 (2 * cpu_data -> short_idles >= cpu_data -> total ||
499462 latency_req < LATENCY_THRESHOLD_NS ))
500463 goto out_tick ;
501464
502465 duration_ns = tick_nohz_get_sleep_length (& delta_tick );
503466 cpu_data -> sleep_length_ns = duration_ns ;
504467
468+ /*
469+ * If the tick has been stopped and the closest timer is too far away,
470+ * update the selection to prevent the CPU from getting stuck in a
471+ * shallow idle state for too long.
472+ */
473+ if (tick_nohz_tick_stopped () && duration_ns > SAFE_TIMER_RANGE_NS &&
474+ drv -> states [idx ].target_residency_ns < TICK_NSEC ) {
475+ /*
476+ * Look for the deepest enabled idle state with exit latency
477+ * within the PM QoS limit and with target residency within
478+ * duration_ns.
479+ */
480+ for (i = constraint_idx ; i > idx ; i -- ) {
481+ if (dev -> states_usage [i ].disable )
482+ continue ;
483+
484+ if (drv -> states [i ].target_residency_ns <= duration_ns ) {
485+ idx = i ;
486+ break ;
487+ }
488+ }
489+ return idx ;
490+ }
491+
505492 if (!idx )
506493 goto out_tick ;
507494
0 commit comments