Skip to content

Commit 2a5482c

Browse files
committed
Merge tag 'cpuidle-psci-v6.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm
Pull cpuidle psci fixes from Ulf Hansson: "A couple of cpuidle-psci fixes. Usually, this is managed by arm-soc maintainers or Rafael, although due to a busy period I have stepped in to help out: - Fix the error path to prevent reverting from OSI back to PC mode" * tag 'cpuidle-psci-v6.5-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm: cpuidle: psci: Move enabling OSI mode after power domains creation cpuidle: dt_idle_genpd: Add helper function to remove genpd topology
2 parents 9b1b1b7 + 12acb34 commit 2a5482c

File tree

3 files changed

+44
-26
lines changed

3 files changed

+44
-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

drivers/cpuidle/dt_idle_genpd.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,30 @@ int dt_idle_pd_init_topology(struct device_node *np)
152152
return 0;
153153
}
154154

155+
int dt_idle_pd_remove_topology(struct device_node *np)
156+
{
157+
struct device_node *node;
158+
struct of_phandle_args child, parent;
159+
int ret;
160+
161+
for_each_child_of_node(np, node) {
162+
if (of_parse_phandle_with_args(node, "power-domains",
163+
"#power-domain-cells", 0, &parent))
164+
continue;
165+
166+
child.np = node;
167+
child.args_count = 0;
168+
ret = of_genpd_remove_subdomain(&parent, &child);
169+
of_node_put(parent.np);
170+
if (ret) {
171+
of_node_put(node);
172+
return ret;
173+
}
174+
}
175+
176+
return 0;
177+
}
178+
155179
struct device *dt_idle_attach_cpu(int cpu, const char *name)
156180
{
157181
struct device *dev;

drivers/cpuidle/dt_idle_genpd.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct generic_pm_domain *dt_idle_pd_alloc(struct device_node *np,
1414

1515
int dt_idle_pd_init_topology(struct device_node *np);
1616

17+
int dt_idle_pd_remove_topology(struct device_node *np);
18+
1719
struct device *dt_idle_attach_cpu(int cpu, const char *name);
1820

1921
void dt_idle_detach_cpu(struct device *dev);
@@ -36,6 +38,11 @@ static inline int dt_idle_pd_init_topology(struct device_node *np)
3638
return 0;
3739
}
3840

41+
static inline int dt_idle_pd_remove_topology(struct device_node *np)
42+
{
43+
return 0;
44+
}
45+
3946
static inline struct device *dt_idle_attach_cpu(int cpu, const char *name)
4047
{
4148
return NULL;

0 commit comments

Comments
 (0)