From 04bae4e2267d49eb9cfec403acd0462b8d00d637 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 31 Jul 2023 21:03:09 +0200 Subject: 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 Reviewed-and-tested-by: Kajetan Puchalski --- drivers/cpuidle/governors/teo.c | 56 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'drivers/cpuidle') diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c index 2cdc711679a5..1b76db3689d0 100644 --- a/drivers/cpuidle/governors/teo.c +++ b/drivers/cpuidle/governors/teo.c @@ -382,12 +382,13 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, /* Check if there is any choice in the first place. */ if (drv->state_count < 2) { idx = 0; - goto end; + goto out_tick; } + if (!dev->states_usage[0].disable) { idx = 0; if (drv->states[1].target_residency_ns > duration_ns) - goto end; + goto out_tick; } 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, * anyway. */ if ((!idx && !(drv->states[0].flags & CPUIDLE_FLAG_POLLING) && - teo_time_ok(duration_ns)) || dev->states_usage[1].disable) + teo_time_ok(duration_ns)) || dev->states_usage[1].disable) { idx = 0; - else /* Assume that state 1 is not a polling one and use it. */ - idx = 1; - + goto out_tick; + } + /* Assume that state 1 is not a polling one and use it. */ + idx = 1; goto end; } @@ -459,8 +461,15 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, /* Avoid unnecessary overhead. */ if (idx < 0) { idx = 0; /* No states enabled, must use 0. */ - goto end; - } else if (idx == idx0) { + goto out_tick; + } + + if (idx == idx0) { + /* + * This is the first enabled idle state, so use it, but do not + * allow the tick to be stopped it is shallow enough. + */ + duration_ns = drv->states[idx].target_residency_ns; goto end; } @@ -566,24 +575,25 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, end: /* - * 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. + * Allow the tick to be stopped unless the selected state is a polling + * one or the expected idle duration is shorter than the tick period + * length. */ - if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || - duration_ns < TICK_NSEC) && !tick_nohz_tick_stopped()) { - *stop_tick = false; + if ((!(drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && + duration_ns >= TICK_NSEC) || tick_nohz_tick_stopped()) + return idx; - /* - * The tick is not going to be stopped, so if the target - * residency of the state to be returned is not within the time - * till the closest timer including the tick, try to correct - * that. - */ - if (idx > idx0 && - drv->states[idx].target_residency_ns > delta_tick) - idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false); - } + /* + * The tick is not going to be stopped, so if the target residency of + * the state to be returned is not within the time till the closest + * timer including the tick, try to correct that. + */ + if (idx > idx0 && + drv->states[idx].target_residency_ns > delta_tick) + idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false); +out_tick: + *stop_tick = false; return idx; } -- cgit v1.2.3