Skip to content

Commit 12acb34

Browse files
maulik-k-shahstorulf
authored andcommitted
cpuidle: psci: Move enabling OSI mode after power domains creation
A switch from OSI to PC mode is only possible if all CPUs other than the calling one are OFF, either through a call to CPU_OFF or not yet booted. Currently OSI mode is enabled before power domains are created. In cases where CPUidle states are not using hierarchical CPU topology the bail out path tries to switch back to PC mode which gets denied by firmware since other CPUs are online at this point and creates inconsistent state as firmware is in OSI mode and Linux in PC mode. This change moves enabling OSI mode after power domains are created, this would makes sure that hierarchical CPU topology is used before switching firmware to OSI mode. Cc: stable@vger.kernel.org Fixes: 70c179b ("cpuidle: psci: Allow PM domain to be initialized even if no OSI mode") Signed-off-by: Maulik Shah <quic_mkshah@quicinc.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 9a8fa00 commit 12acb34

File tree

1 file changed

+13
-26
lines changed

1 file changed

+13
-26
lines changed

drivers/cpuidle/cpuidle-psci-domain.c

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,6 @@ static void psci_pd_remove(void)
120120
}
121121
}
122122

123-
static bool psci_pd_try_set_osi_mode(void)
124-
{
125-
int ret;
126-
127-
if (!psci_has_osi_support())
128-
return false;
129-
130-
ret = psci_set_osi_mode(true);
131-
if (ret)
132-
return false;
133-
134-
return true;
135-
}
136-
137123
static void psci_cpuidle_domain_sync_state(struct device *dev)
138124
{
139125
/*
@@ -152,15 +138,12 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
152138
{
153139
struct device_node *np = pdev->dev.of_node;
154140
struct device_node *node;
155-
bool use_osi;
141+
bool use_osi = psci_has_osi_support();
156142
int ret = 0, pd_count = 0;
157143

158144
if (!np)
159145
return -ENODEV;
160146

161-
/* If OSI mode is supported, let's try to enable it. */
162-
use_osi = psci_pd_try_set_osi_mode();
163-
164147
/*
165148
* Parse child nodes for the "#power-domain-cells" property and
166149
* initialize a genpd/genpd-of-provider pair when it's found.
@@ -170,33 +153,37 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
170153
continue;
171154

172155
ret = psci_pd_init(node, use_osi);
173-
if (ret)
174-
goto put_node;
156+
if (ret) {
157+
of_node_put(node);
158+
goto exit;
159+
}
175160

176161
pd_count++;
177162
}
178163

179164
/* Bail out if not using the hierarchical CPU topology. */
180165
if (!pd_count)
181-
goto no_pd;
166+
return 0;
182167

183168
/* Link genpd masters/subdomains to model the CPU topology. */
184169
ret = dt_idle_pd_init_topology(np);
185170
if (ret)
186171
goto remove_pd;
187172

173+
/* let's try to enable OSI. */
174+
ret = psci_set_osi_mode(use_osi);
175+
if (ret)
176+
goto remove_pd;
177+
188178
pr_info("Initialized CPU PM domain topology using %s mode\n",
189179
use_osi ? "OSI" : "PC");
190180
return 0;
191181

192-
put_node:
193-
of_node_put(node);
194182
remove_pd:
183+
dt_idle_pd_remove_topology(np);
195184
psci_pd_remove();
185+
exit:
196186
pr_err("failed to create CPU PM domains ret=%d\n", ret);
197-
no_pd:
198-
if (use_osi)
199-
psci_set_osi_mode(false);
200187
return ret;
201188
}
202189

0 commit comments

Comments
 (0)