mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] sched/cpufreq: Reevaluate frequency before tickless idle
@ 2026-08-24 13:18 Christian Loehle
  2026-08-24 14:07 ` Christian Loehle
  2026-08-25  2:51 ` Hongyan Xia
  0 siblings, 2 replies; 6+ messages in thread
From: Christian Loehle @ 2026-08-24 13:18 UTC (permalink / raw)
  To: linux-kernel, linux-pm, rafael, viresh.kumar, mingo, peterz,
	vincent.guittot, daniel.lezcano
  Cc: anna-maria, frederic, tglx, dietmar.eggemann, jstultz, qyousef,
	hongyan.xia, sibi.sankar, lukasz.luba, morten.rasmussen,
	Christian Loehle

sugov_hold_freq() can preserve a UCLAMP_MIN-driven high frequency when
the runqueue goes idle. If cpuidle then stops the tick, no later
utilization update is guaranteed and a CPU using WFI can remain at an
unnecessarily high voltage for the entire idle period.

Issue a final cpufreq update when the idle tick actually transitions to
stopped and force single-policy schedutil past its rate limit. Keep the
existing hold behavior when the tick is retained.

Signed-off-by: Christian Loehle <christian.loehle@arm.com>
---
 include/linux/sched/cpufreq.h    |  1 +
 kernel/sched/cpufreq_schedutil.c |  5 ++++-
 kernel/sched/idle.c              | 29 +++++++++++++++++++++++++++--
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/include/linux/sched/cpufreq.h b/include/linux/sched/cpufreq.h
index bdd31ab93bc5..0814f6c79315 100644
--- a/include/linux/sched/cpufreq.h
+++ b/include/linux/sched/cpufreq.h
@@ -9,6 +9,7 @@
  */
 
 #define SCHED_CPUFREQ_IOWAIT	(1U << 0)
+#define SCHED_CPUFREQ_IDLE	(1U << 1)
 
 #ifdef CONFIG_CPU_FREQ
 struct cpufreq_policy;
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index a1782755efcc..90bf8d8bffb7 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -100,7 +100,7 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
 
 		return true;
 	} else if (sg_policy->need_freq_update) {
-		/* ignore_dl_rate_limit() wants a new frequency to be found. */
+		/* A forced update needs a new frequency to be found. */
 		return true;
 	}
 
@@ -407,6 +407,9 @@ static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu,
 	sugov_iowait_boost(sg_cpu, time, flags);
 	sg_cpu->last_update = time;
 
+	if (flags & SCHED_CPUFREQ_IDLE)
+		sg_cpu->sg_policy->need_freq_update = true;
+
 	ignore_dl_rate_limit(sg_cpu);
 
 	if (!sugov_should_update_freq(sg_cpu->sg_policy, time))
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index eb73b65ce6c4..36f8840d0562 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -161,10 +161,35 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
 	return cpuidle_enter(drv, dev, next_state);
 }
 
+static void idle_stop_tick(void)
+{
+#ifdef CONFIG_CPU_FREQ
+	bool was_stopped = tick_nohz_tick_stopped();
+#endif
+
+	tick_nohz_idle_stop_tick();
+
+#ifdef CONFIG_CPU_FREQ
+	/*
+	 * Run one last cpufreq update before entering idle with the tick
+	 * stopped, because no later update is guaranteed.
+	 */
+	if (!was_stopped && tick_nohz_tick_stopped()) {
+		struct rq *rq = this_rq();
+		struct rq_flags rf;
+
+		rq_lock(rq, &rf);
+		update_rq_clock(rq);
+		cpufreq_update_util(rq, SCHED_CPUFREQ_IDLE);
+		rq_unlock(rq, &rf);
+	}
+#endif
+}
+
 static void idle_call_stop_or_retain_tick(bool stop_tick)
 {
 	if (stop_tick || tick_nohz_tick_stopped())
-		tick_nohz_idle_stop_tick();
+		idle_stop_tick();
 	else
 		tick_nohz_idle_retain_tick();
 }
@@ -225,7 +250,7 @@ static void cpuidle_idle_call(bool stop_tick)
 			max_latency_ns = dev->forced_idle_latency_limit_ns;
 		}
 
-		tick_nohz_idle_stop_tick();
+		idle_stop_tick();
 
 		next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns);
 		call_cpuidle(drv, dev, next_state);
-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-25 17:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-24 13:18 [PATCH] sched/cpufreq: Reevaluate frequency before tickless idle Christian Loehle
2026-08-24 14:07 ` Christian Loehle
2026-08-25  2:51 ` Hongyan Xia
2026-08-25  9:00   ` Christian Loehle
2026-08-25 12:52     ` Vincent Guittot
2026-08-25 17:58       ` Christian Loehle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®