Skip to content

Commit 04bae4e

Browse files
committed
cpuidle: teo: Avoid stopping the tick unnecessarily when bailing out
When teo_select() is going to return early in some special cases, make it avoid stopping the tick if the idle state to be returned is shallow. In particular, never stop the tick if state 0 is to be returned. Link: https://lore.kernel.org/linux-pm/CAJZ5v0jJxHj65r2HXBTd3wfbZtsg=_StzwO1kA5STDnaPe_dWA@mail.gmail.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-and-tested-by: Kajetan Puchalski <kajetan.puchalski@arm.com>
1 parent 3f0b096 commit 04bae4e

File tree

1 file changed

+33
-23
lines changed
  • drivers/cpuidle/governors

1 file changed

+33
-23
lines changed

drivers/cpuidle/governors/teo.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -382,12 +382,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
382382
/* Check if there is any choice in the first place. */
383383
if (drv->state_count < 2) {
384384
idx = 0;
385-
goto end;
385+
goto out_tick;
386386
}
387+
387388
if (!dev->states_usage[0].disable) {
388389
idx = 0;
389390
if (drv->states[1].target_residency_ns > duration_ns)
390-
goto end;
391+
goto out_tick;
391392
}
392393

393394
cpu_data->utilized = teo_cpu_is_utilized(dev->cpu, cpu_data);
@@ -408,11 +409,12 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
408409
* anyway.
409410
*/
410411
if ((!idx && !(drv->states[0].flags & CPUIDLE_FLAG_POLLING) &&
411-
teo_time_ok(duration_ns)) || dev->states_usage[1].disable)
412+
teo_time_ok(duration_ns)) || dev->states_usage[1].disable) {
412413
idx = 0;
413-
else /* Assume that state 1 is not a polling one and use it. */
414-
idx = 1;
415-
414+
goto out_tick;
415+
}
416+
/* Assume that state 1 is not a polling one and use it. */
417+
idx = 1;
416418
goto end;
417419
}
418420

@@ -459,8 +461,15 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
459461
/* Avoid unnecessary overhead. */
460462
if (idx < 0) {
461463
idx = 0; /* No states enabled, must use 0. */
462-
goto end;
463-
} else if (idx == idx0) {
464+
goto out_tick;
465+
}
466+
467+
if (idx == idx0) {
468+
/*
469+
* This is the first enabled idle state, so use it, but do not
470+
* allow the tick to be stopped it is shallow enough.
471+
*/
472+
duration_ns = drv->states[idx].target_residency_ns;
464473
goto end;
465474
}
466475

@@ -566,24 +575,25 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
566575

567576
end:
568577
/*
569-
* Don't stop the tick if the selected state is a polling one or if the
570-
* expected idle duration is shorter than the tick period length.
578+
* Allow the tick to be stopped unless the selected state is a polling
579+
* one or the expected idle duration is shorter than the tick period
580+
* length.
571581
*/
572-
if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
573-
duration_ns < TICK_NSEC) && !tick_nohz_tick_stopped()) {
574-
*stop_tick = false;
582+
if ((!(drv->states[idx].flags & CPUIDLE_FLAG_POLLING) &&
583+
duration_ns >= TICK_NSEC) || tick_nohz_tick_stopped())
584+
return idx;
575585

576-
/*
577-
* The tick is not going to be stopped, so if the target
578-
* residency of the state to be returned is not within the time
579-
* till the closest timer including the tick, try to correct
580-
* that.
581-
*/
582-
if (idx > idx0 &&
583-
drv->states[idx].target_residency_ns > delta_tick)
584-
idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false);
585-
}
586+
/*
587+
* The tick is not going to be stopped, so if the target residency of
588+
* the state to be returned is not within the time till the closest
589+
* timer including the tick, try to correct that.
590+
*/
591+
if (idx > idx0 &&
592+
drv->states[idx].target_residency_ns > delta_tick)
593+
idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false);
586594

595+
out_tick:
596+
*stop_tick = false;
587597
return idx;
588598
}
589599

0 commit comments

Comments
 (0)