Skip to content

Commit 621a88d

Browse files
dlezcanostorulf
authored andcommitted
cpuidle: psci: Fix cpuhotplug routine with PREEMPT_RT=y
Currently cpu hotplug with the PREEMPT_RT option set in the kernel is not supported because the underlying generic power domain functions used in the cpu hotplug callbacks are incompatible from a lock point of view. This situation prevents the suspend to idle to reach the deepest idle state for the "cluster" as identified in the undermentioned commit. Use the compatible ones when PREEMPT_RT is enabled and remove the boolean disabling the hotplug callbacks with this option. With this change the platform can reach the deepest idle state allowing at suspend time to consume less power. Tested-on Lenovo T14s with the following script: echo 0 > /sys/devices/system/cpu/cpu3/online BEFORE=$(cat /sys/kernel/debug/pm_genpd/power-domain-cpu-cluster0/idle_states | grep S0 | awk '{ print $3 }') ; rtcwake -s 1 -m mem; AFTER=$(cat /sys/kernel/debug/pm_genpd/power-domain-cpu-cluster0/idle_states | grep S0 | awk '{ print $3 }'); if [ $BEFORE -lt $AFTER ]; then echo "Test successful" else echo "Test failed" fi echo 1 > /sys/devices/system/cpu/cpu3/online Fixes: 1c4b293 ("cpuidle: psci: Enable the hierarchical topology for s2idle on PREEMPT_RT") Cc: Raghavendra Kakarla <[email protected]> Signed-off-by: Daniel Lezcano <[email protected]> Reviewed-by: Sudeep Holla <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 500ba33 commit 621a88d

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
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)

0 commit comments

Comments
 (0)