Commit f9901f64 authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Rafael J. Wysocki

cpuidle: psci: Do not suspend topology CPUs on PREEMPT_RT

The runtime Power Management of CPU topology is not compatible with
PREEMPT_RT:

 1. Core cpuidle path disables IRQs.
 2. Core cpuidle calls cpuidle-psci.
 3. cpuidle-psci in __psci_enter_domain_idle_state() calls
    pm_runtime_put_sync_suspend() and pm_runtime_get_sync() which use
    spinlocks (which are sleeping on PREEMPT_RT).

Deep sleep modes are not a priority of Realtime kernels because the
latencies might become unpredictable.  On the other hand the PSCI CPU
idle power domain is a parent of other devices and power domain
controllers, thus it cannot be simply skipped (e.g. on Qualcomm SM8250).

Disable the idle callbacks in cpuidle-psci and mark the domain as
always on.  This is a trade-off between making PREEMPT_RT working and
still having a proper power domain hierarchy in the system.
Signed-off-by: default avatarKrzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Tested-by: default avatarAdrien Thierry <athierry@redhat.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 41204a60
...@@ -24,6 +24,14 @@ config ARM_PSCI_CPUIDLE ...@@ -24,6 +24,14 @@ config ARM_PSCI_CPUIDLE
It provides an idle driver that is capable of detecting and It provides an idle driver that is capable of detecting and
managing idle states through the PSCI firmware interface. managing idle states through the PSCI firmware interface.
The driver has limitations when used with PREEMPT_RT:
- If the idle states are described with the non-hierarchical layout,
all idle states are still available.
- If the idle states are described with the hierarchical layout,
only the idle states defined per CPU are available, but not the ones
being shared among a group of CPUs (aka cluster idle states).
config ARM_PSCI_CPUIDLE_DOMAIN config ARM_PSCI_CPUIDLE_DOMAIN
bool "PSCI CPU idle Domain" bool "PSCI CPU idle Domain"
depends on ARM_PSCI_CPUIDLE depends on ARM_PSCI_CPUIDLE
......
...@@ -64,8 +64,11 @@ static int psci_pd_init(struct device_node *np, bool use_osi) ...@@ -64,8 +64,11 @@ static int psci_pd_init(struct device_node *np, bool use_osi)
pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN; pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN;
/* Allow power off when OSI has been successfully enabled. */ /*
if (use_osi) * Allow power off when OSI has been successfully enabled.
* PREEMPT_RT is not yet ready to enter domain idle states.
*/
if (use_osi && !IS_ENABLED(CONFIG_PREEMPT_RT))
pd->power_off = psci_pd_power_off; pd->power_off = psci_pd_power_off;
else else
pd->flags |= GENPD_FLAG_ALWAYS_ON; pd->flags |= GENPD_FLAG_ALWAYS_ON;
......
...@@ -231,6 +231,9 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv, ...@@ -231,6 +231,9 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv,
if (!psci_has_osi_support()) if (!psci_has_osi_support())
return 0; return 0;
if (IS_ENABLED(CONFIG_PREEMPT_RT))
return 0;
data->dev = psci_dt_attach_cpu(cpu); data->dev = psci_dt_attach_cpu(cpu);
if (IS_ERR_OR_NULL(data->dev)) if (IS_ERR_OR_NULL(data->dev))
return PTR_ERR_OR_ZERO(data->dev); return PTR_ERR_OR_ZERO(data->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment