Skip to content

Commit 7abc678

Browse files
committed
Merge tag 'pmdomain-v6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm
Pull pmdomain / cpuidle-psci fixes from Ulf Hansson: "pmdomain core: - Respect CPU latency QoS limit in the genpd governor for CPUs cpuidle-psci: - Fix cpuhotplug support for PREEMPT_RT" * tag 'pmdomain-v6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: cpuidle: psci: Fix cpuhotplug routine with PREEMPT_RT=y pmdomain: governor: Consider CPU latency tolerance from pm_domain_cpu_gov
2 parents 16e1497 + 621a88d commit 7abc678

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

drivers/cpuidle/cpuidle-psci.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ struct psci_cpuidle_domain_state {
4545
static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
4646
static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state);
4747
static bool psci_cpuidle_use_syscore;
48-
static bool psci_cpuidle_use_cpuhp;
4948

5049
void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
5150
u32 state)
@@ -124,8 +123,12 @@ static int psci_idle_cpuhp_up(unsigned int cpu)
124123
{
125124
struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
126125

127-
if (pd_dev)
128-
pm_runtime_get_sync(pd_dev);
126+
if (pd_dev) {
127+
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
128+
pm_runtime_get_sync(pd_dev);
129+
else
130+
dev_pm_genpd_resume(pd_dev);
131+
}
129132

130133
return 0;
131134
}
@@ -135,7 +138,11 @@ static int psci_idle_cpuhp_down(unsigned int cpu)
135138
struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);
136139

137140
if (pd_dev) {
138-
pm_runtime_put_sync(pd_dev);
141+
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
142+
pm_runtime_put_sync(pd_dev);
143+
else
144+
dev_pm_genpd_suspend(pd_dev);
145+
139146
/* Clear domain state to start fresh at next online. */
140147
psci_clear_domain_state();
141148
}
@@ -196,9 +203,6 @@ static void psci_idle_init_cpuhp(void)
196203
{
197204
int err;
198205

199-
if (!psci_cpuidle_use_cpuhp)
200-
return;
201-
202206
err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING,
203207
"cpuidle/psci:online",
204208
psci_idle_cpuhp_up,
@@ -259,10 +263,8 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv,
259263
* s2ram and s2idle.
260264
*/
261265
drv->states[state_count - 1].enter_s2idle = psci_enter_s2idle_domain_idle_state;
262-
if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
266+
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
263267
drv->states[state_count - 1].enter = psci_enter_domain_idle_state;
264-
psci_cpuidle_use_cpuhp = true;
265-
}
266268

267269
return 0;
268270
}
@@ -339,7 +341,6 @@ static void psci_cpu_deinit_idle(int cpu)
339341

340342
dt_idle_detach_cpu(data->dev);
341343
psci_cpuidle_use_syscore = false;
342-
psci_cpuidle_use_cpuhp = false;
343344
}
344345

345346
static int psci_idle_init_cpu(struct device *dev, int cpu)

drivers/pmdomain/governor.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/pm_domain.h>
99
#include <linux/pm_qos.h>
1010
#include <linux/hrtimer.h>
11+
#include <linux/cpu.h>
1112
#include <linux/cpuidle.h>
1213
#include <linux/cpumask.h>
1314
#include <linux/ktime.h>
@@ -349,6 +350,8 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
349350
struct cpuidle_device *dev;
350351
ktime_t domain_wakeup, next_hrtimer;
351352
ktime_t now = ktime_get();
353+
struct device *cpu_dev;
354+
s64 cpu_constraint, global_constraint;
352355
s64 idle_duration_ns;
353356
int cpu, i;
354357

@@ -359,6 +362,7 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
359362
if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN))
360363
return true;
361364

365+
global_constraint = cpu_latency_qos_limit();
362366
/*
363367
* Find the next wakeup for any of the online CPUs within the PM domain
364368
* and its subdomains. Note, we only need the genpd->cpus, as it already
@@ -372,8 +376,16 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
372376
if (ktime_before(next_hrtimer, domain_wakeup))
373377
domain_wakeup = next_hrtimer;
374378
}
379+
380+
cpu_dev = get_cpu_device(cpu);
381+
if (cpu_dev) {
382+
cpu_constraint = dev_pm_qos_raw_resume_latency(cpu_dev);
383+
if (cpu_constraint < global_constraint)
384+
global_constraint = cpu_constraint;
385+
}
375386
}
376387

388+
global_constraint *= NSEC_PER_USEC;
377389
/* The minimum idle duration is from now - until the next wakeup. */
378390
idle_duration_ns = ktime_to_ns(ktime_sub(domain_wakeup, now));
379391
if (idle_duration_ns <= 0)
@@ -389,8 +401,10 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
389401
*/
390402
i = genpd->state_idx;
391403
do {
392-
if (idle_duration_ns >= (genpd->states[i].residency_ns +
393-
genpd->states[i].power_off_latency_ns)) {
404+
if ((idle_duration_ns >= (genpd->states[i].residency_ns +
405+
genpd->states[i].power_off_latency_ns)) &&
406+
(global_constraint >= (genpd->states[i].power_on_latency_ns +
407+
genpd->states[i].power_off_latency_ns))) {
394408
genpd->state_idx = i;
395409
genpd->gd->last_enter = now;
396410
genpd->gd->reflect_residency = true;

0 commit comments

Comments
 (0)