On Wed, 9 Jul 2025 at 17:47, Daniel Lezcano <daniel.lezcano@xxxxxxxxxx> wrote: > > 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: 1c4b2932bd62 ("cpuidle: psci: Enable the hierarchical topology for s2idle on PREEMPT_RT") > Cc: Raghavendra Kakarla <quic_rkakarla@xxxxxxxxxxx> > Signed-off-by: Daniel Lezcano <daniel.lezcano@xxxxxxxxxx> Applied for fixes and by adding a stable-tag, thanks! Kind regards Uffe > --- > drivers/cpuidle/cpuidle-psci.c | 23 ++++++++++++----------- > 1 file changed, 12 insertions(+), 11 deletions(-) > > diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c > index 4e1ba35deda9..b19bc60cc627 100644 > --- a/drivers/cpuidle/cpuidle-psci.c > +++ b/drivers/cpuidle/cpuidle-psci.c > @@ -45,7 +45,6 @@ struct psci_cpuidle_domain_state { > static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data); > static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state); > static bool psci_cpuidle_use_syscore; > -static bool psci_cpuidle_use_cpuhp; > > void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx, > u32 state) > @@ -124,8 +123,12 @@ static int psci_idle_cpuhp_up(unsigned int cpu) > { > struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev); > > - if (pd_dev) > - pm_runtime_get_sync(pd_dev); > + if (pd_dev) { > + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) > + pm_runtime_get_sync(pd_dev); > + else > + dev_pm_genpd_resume(pd_dev); > + } > > return 0; > } > @@ -135,7 +138,11 @@ static int psci_idle_cpuhp_down(unsigned int cpu) > struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev); > > if (pd_dev) { > - pm_runtime_put_sync(pd_dev); > + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) > + pm_runtime_put_sync(pd_dev); > + else > + dev_pm_genpd_suspend(pd_dev); > + > /* Clear domain state to start fresh at next online. */ > psci_clear_domain_state(); > } > @@ -196,9 +203,6 @@ static void psci_idle_init_cpuhp(void) > { > int err; > > - if (!psci_cpuidle_use_cpuhp) > - return; > - > err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING, > "cpuidle/psci:online", > psci_idle_cpuhp_up, > @@ -259,10 +263,8 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv, > * s2ram and s2idle. > */ > drv->states[state_count - 1].enter_s2idle = psci_enter_s2idle_domain_idle_state; > - if (!IS_ENABLED(CONFIG_PREEMPT_RT)) { > + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) > drv->states[state_count - 1].enter = psci_enter_domain_idle_state; > - psci_cpuidle_use_cpuhp = true; > - } > > return 0; > } > @@ -339,7 +341,6 @@ static void psci_cpu_deinit_idle(int cpu) > > dt_idle_detach_cpu(data->dev); > psci_cpuidle_use_syscore = false; > - psci_cpuidle_use_cpuhp = false; > } > > static int psci_idle_init_cpu(struct device *dev, int cpu) > -- > 2.43.0 >