Skip to content

Commit 99b4244

Browse files
Ulf Hanssonrafaeljw
authored andcommitted
sched: idle: Respect the CPU system wakeup QoS limit for s2idle
A CPU system wakeup QoS limit may have been requested by user space. To avoid breaking this constraint when entering a low power state during s2idle, let's start to take into account the QoS limit. Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Dhruva Gole <d-gole@ti.com> Reviewed-by: Kevin Hilman (TI) <khilman@baylibre.com> Tested-by: Kevin Hilman (TI) <khilman@baylibre.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://patch.msgid.link/20251125112650.329269-5-ulf.hansson@linaro.org Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent e2e4695 commit 99b4244

3 files changed

Lines changed: 18 additions & 12 deletions

File tree

drivers/cpuidle/cpuidle.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,20 +184,22 @@ static noinstr void enter_s2idle_proper(struct cpuidle_driver *drv,
184184
* cpuidle_enter_s2idle - Enter an idle state suitable for suspend-to-idle.
185185
* @drv: cpuidle driver for the given CPU.
186186
* @dev: cpuidle device for the given CPU.
187+
* @latency_limit_ns: Idle state exit latency limit
187188
*
188189
* If there are states with the ->enter_s2idle callback, find the deepest of
189190
* them and enter it with frozen tick.
190191
*/
191-
int cpuidle_enter_s2idle(struct cpuidle_driver *drv, struct cpuidle_device *dev)
192+
int cpuidle_enter_s2idle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
193+
u64 latency_limit_ns)
192194
{
193195
int index;
194196

195197
/*
196-
* Find the deepest state with ->enter_s2idle present, which guarantees
197-
* that interrupts won't be enabled when it exits and allows the tick to
198-
* be frozen safely.
198+
* Find the deepest state with ->enter_s2idle present that meets the
199+
* specified latency limit, which guarantees that interrupts won't be
200+
* enabled when it exits and allows the tick to be frozen safely.
199201
*/
200-
index = find_deepest_state(drv, dev, U64_MAX, 0, true);
202+
index = find_deepest_state(drv, dev, latency_limit_ns, 0, true);
201203
if (index > 0) {
202204
enter_s2idle_proper(drv, dev, index);
203205
local_irq_enable();

include/linux/cpuidle.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,15 +248,17 @@ extern int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
248248
struct cpuidle_device *dev,
249249
u64 latency_limit_ns);
250250
extern int cpuidle_enter_s2idle(struct cpuidle_driver *drv,
251-
struct cpuidle_device *dev);
251+
struct cpuidle_device *dev,
252+
u64 latency_limit_ns);
252253
extern void cpuidle_use_deepest_state(u64 latency_limit_ns);
253254
#else
254255
static inline int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
255256
struct cpuidle_device *dev,
256257
u64 latency_limit_ns)
257258
{return -ENODEV; }
258259
static inline int cpuidle_enter_s2idle(struct cpuidle_driver *drv,
259-
struct cpuidle_device *dev)
260+
struct cpuidle_device *dev,
261+
u64 latency_limit_ns)
260262
{return -ENODEV; }
261263
static inline void cpuidle_use_deepest_state(u64 latency_limit_ns)
262264
{

kernel/sched/idle.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,13 @@ void __cpuidle default_idle_call(void)
131131
}
132132

133133
static int call_cpuidle_s2idle(struct cpuidle_driver *drv,
134-
struct cpuidle_device *dev)
134+
struct cpuidle_device *dev,
135+
u64 max_latency_ns)
135136
{
136137
if (current_clr_polling_and_test())
137138
return -EBUSY;
138139

139-
return cpuidle_enter_s2idle(drv, dev);
140+
return cpuidle_enter_s2idle(drv, dev, max_latency_ns);
140141
}
141142

142143
static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
@@ -205,12 +206,13 @@ static void cpuidle_idle_call(void)
205206
u64 max_latency_ns;
206207

207208
if (idle_should_enter_s2idle()) {
209+
max_latency_ns = cpu_wakeup_latency_qos_limit() *
210+
NSEC_PER_USEC;
208211

209-
entered_state = call_cpuidle_s2idle(drv, dev);
212+
entered_state = call_cpuidle_s2idle(drv, dev,
213+
max_latency_ns);
210214
if (entered_state > 0)
211215
goto exit_idle;
212-
213-
max_latency_ns = U64_MAX;
214216
} else {
215217
max_latency_ns = dev->forced_idle_latency_limit_ns;
216218
}

0 commit comments

Comments
 (0)