Skip to content

Commit 7627929

Browse files
Waldemar Rymarkiewiczrafaeljw
authored andcommitted
PM / OPP: Fix get sharing CPUs when hotplug is used
We fail dev_pm_opp_of_get_sharing_cpus() when possible CPU device does not exist. This can happen on platforms where not all possible CPUs are available at start up ie. hotplugged out. The CPU device is not registered in the system so we are not able to check struct device to set the sharing CPUs bitmask properly. Example (real use case): 2 physical MIPS cores, 4 VPE, cpu0/2 run Linux and cpu1/3 are not available for Linux at boot up. cpufreq-dt driver + OPP v2 fail to register opp_table due to the fact there is no struct device for cpu1 (remains offline at bootup). To solve the bug, stop using device struct to check device_node. Instead get CPU device_node directly from device tree with of_get_cpu_node(). Signed-off-by: Waldemar Rymarkiewicz <[email protected]> Acked-by: Viresh Kumar <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 5b60697 commit 7627929

File tree

1 file changed

+17
-12
lines changed
  • drivers/base/power/opp

1 file changed

+17
-12
lines changed

drivers/base/power/opp/of.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,15 +248,22 @@ void dev_pm_opp_of_remove_table(struct device *dev)
248248
}
249249
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
250250

251-
/* Returns opp descriptor node for a device, caller must do of_node_put() */
252-
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
251+
/* Returns opp descriptor node for a device node, caller must
252+
* do of_node_put() */
253+
static struct device_node *_opp_of_get_opp_desc_node(struct device_node *np)
253254
{
254255
/*
255256
* There should be only ONE phandle present in "operating-points-v2"
256257
* property.
257258
*/
258259

259-
return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
260+
return of_parse_phandle(np, "operating-points-v2", 0);
261+
}
262+
263+
/* Returns opp descriptor node for a device, caller must do of_node_put() */
264+
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
265+
{
266+
return _opp_of_get_opp_desc_node(dev->of_node);
260267
}
261268
EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
262269

@@ -576,8 +583,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
576583
int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
577584
struct cpumask *cpumask)
578585
{
579-
struct device_node *np, *tmp_np;
580-
struct device *tcpu_dev;
586+
struct device_node *np, *tmp_np, *cpu_np;
581587
int cpu, ret = 0;
582588

583589
/* Get OPP descriptor node */
@@ -597,19 +603,18 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
597603
if (cpu == cpu_dev->id)
598604
continue;
599605

600-
tcpu_dev = get_cpu_device(cpu);
601-
if (!tcpu_dev) {
602-
dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
606+
cpu_np = of_get_cpu_node(cpu, NULL);
607+
if (!cpu_np) {
608+
dev_err(cpu_dev, "%s: failed to get cpu%d node\n",
603609
__func__, cpu);
604-
ret = -ENODEV;
610+
ret = -ENOENT;
605611
goto put_cpu_node;
606612
}
607613

608614
/* Get OPP descriptor node */
609-
tmp_np = dev_pm_opp_of_get_opp_desc_node(tcpu_dev);
615+
tmp_np = _opp_of_get_opp_desc_node(cpu_np);
610616
if (!tmp_np) {
611-
dev_err(tcpu_dev, "%s: Couldn't find opp node.\n",
612-
__func__);
617+
pr_err("%pOF: Couldn't find opp node\n", cpu_np);
613618
ret = -ENOENT;
614619
goto put_cpu_node;
615620
}

0 commit comments

Comments
 (0)