[PATCH v4 5/6] drivers: firmware: psci: Allow hierarchical topology in PC mode

From: Maulik Shah
Date: Wed Feb 05 2020 - 07:27:04 EST


From: Ulf Hansson <ulf.hansson@xxxxxxxxxx>

If the hierarchical CPU topology is used, but the OS initiated mode isn't
supported, we need to rely solely on the regular cpuidle framework to
manage the idle state selection.

Remove current limitation of hierarchical topology to be used in OSI mode
only.

Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
[applied to new path, updated commit text]
Signed-off-by: Maulik Shah <mkshah@xxxxxxxxxxxxxx>
---
drivers/cpuidle/cpuidle-psci-domain.c | 32 +++++++++++++++-----------------
drivers/cpuidle/cpuidle-psci.c | 34 ++++++++++++++++------------------
2 files changed, 31 insertions(+), 35 deletions(-)

diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c
index 423f03b..fcab330 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -125,11 +125,14 @@ static int __init psci_pd_init(struct device_node *np)
* Parse the domain idle states and let genpd manage the state selection
* for those being compatible with "domain-idle-state".
*/
- ret = psci_pd_parse_states(np, &states, &state_count);
- if (ret)
- goto free_name;

- pd->free_states = psci_pd_free_states;
+ if (psci_has_osi_support()) {
+ ret = psci_pd_parse_states(np, &states, &state_count);
+ if (ret)
+ goto free_name;
+ pd->free_states = psci_pd_free_states;
+ }
+
pd->name = kbasename(pd->name);
pd->power_off = psci_pd_power_off;
pd->states = states;
@@ -236,10 +239,6 @@ static int __init psci_idle_init_domains(void)
if (!np)
return -ENODEV;

- /* Currently limit the hierarchical topology to be used in OSI mode. */
- if (!psci_has_osi_support())
- goto out;
-
/*
* Parse child nodes for the "#power-domain-cells" property and
* initialize a genpd/genpd-of-provider pair when it's found.
@@ -265,14 +264,16 @@ static int __init psci_idle_init_domains(void)
goto remove_pd;

/* Try to enable OSI mode. */
- ret = psci_set_osi_mode();
- if (ret) {
- pr_warn("failed to enable OSI mode: %d\n", ret);
- psci_pd_remove_topology(np);
- goto remove_pd;
+ if (psci_has_osi_support()) {
+ ret = psci_set_osi_mode();
+ if (ret) {
+ pr_warn("failed to enable OSI mode: %d\n", ret);
+ psci_pd_remove_topology(np);
+ goto remove_pd;
+ } else
+ osi_mode_enabled = true;
}

- osi_mode_enabled = true;
of_node_put(np);
pr_info("Initialized CPU PM domain topology\n");
return pd_count;
@@ -293,9 +294,6 @@ struct device __init *psci_dt_attach_cpu(int cpu)
{
struct device *dev;

- if (!osi_mode_enabled)
- return NULL;
-
dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
if (IS_ERR_OR_NULL(dev))
return dev;
diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c
index edd7a54..16d8baa 100644
--- a/drivers/cpuidle/cpuidle-psci.c
+++ b/drivers/cpuidle/cpuidle-psci.c
@@ -193,24 +193,22 @@ static int __init psci_dt_cpu_init_idle(struct cpuidle_driver *drv,
goto free_mem;
}

- /* Currently limit the hierarchical topology to be used in OSI mode. */
- if (psci_has_osi_support()) {
- data->dev = psci_dt_attach_cpu(cpu);
- if (IS_ERR(data->dev)) {
- ret = PTR_ERR(data->dev);
- goto free_mem;
- }
-
- /*
- * Using the deepest state for the CPU to trigger a potential
- * selection of a shared state for the domain, assumes the
- * domain states are all deeper states.
- */
- if (data->dev) {
- drv->states[state_count - 1].enter =
- psci_enter_domain_idle_state;
- psci_cpuidle_use_cpuhp = true;
- }
+ data->dev = psci_dt_attach_cpu(cpu);
+ if (IS_ERR(data->dev)) {
+ ret = PTR_ERR(data->dev);
+ goto free_mem;
+ }
+
+ /*
+ * Using the deepest state for the CPU to trigger a potential
+ * selection of a shared state for the domain, assumes the
+ * domain states are all deeper states.
+ */
+
+ if (data->dev) {
+ drv->states[state_count - 1].enter =
+ psci_enter_domain_idle_state;
+ psci_cpuidle_use_cpuhp = true;
}

/* Idle states parsed correctly, store them in the per-cpu struct. */
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation