aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWaldemar Rymarkiewicz <waldemarx.rymarkiewicz@intel.com>2017-07-27 06:01:17 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-08-01 08:10:55 -0400
commit762792913f8c71fb4807b25540347e4ace1b5b95 (patch)
tree8c025e238e33eb328d08aabf18e8fb10885da423
parent5b60697cd89cf5a438b2984e11859228e5ec1c6b (diff)
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 <waldemarx.rymarkiewicz@intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/base/power/opp/of.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c
index 6f0497b377c7..0b718886479b 100644
--- a/drivers/base/power/opp/of.c
+++ b/drivers/base/power/opp/of.c
@@ -248,15 +248,22 @@ void dev_pm_opp_of_remove_table(struct device *dev)
248} 248}
249EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table); 249EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
250 250
251/* Returns opp descriptor node for a device, caller must do of_node_put() */ 251/* Returns opp descriptor node for a device node, caller must
252struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev) 252 * do of_node_put() */
253static struct device_node *_opp_of_get_opp_desc_node(struct device_node *np)
253{ 254{
254 /* 255 /*
255 * There should be only ONE phandle present in "operating-points-v2" 256 * There should be only ONE phandle present in "operating-points-v2"
256 * property. 257 * property.
257 */ 258 */
258 259
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() */
264struct 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);
260} 267}
261EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node); 268EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
262 269
@@ -576,8 +583,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
576int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, 583int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
577 struct cpumask *cpumask) 584 struct cpumask *cpumask)
578{ 585{
579 struct device_node *np, *tmp_np; 586 struct device_node *np, *tmp_np, *cpu_np;
580 struct device *tcpu_dev;
581 int cpu, ret = 0; 587 int cpu, ret = 0;
582 588
583 /* Get OPP descriptor node */ 589 /* Get OPP descriptor node */
@@ -597,19 +603,18 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
597 if (cpu == cpu_dev->id) 603 if (cpu == cpu_dev->id)
598 continue; 604 continue;
599 605
600 tcpu_dev = get_cpu_device(cpu); 606 cpu_np = of_get_cpu_node(cpu, NULL);
601 if (!tcpu_dev) { 607 if (!cpu_np) {
602 dev_err(cpu_dev, "%s: failed to get cpu%d device\n", 608 dev_err(cpu_dev, "%s: failed to get cpu%d node\n",
603 __func__, cpu); 609 __func__, cpu);
604 ret = -ENODEV; 610 ret = -ENOENT;
605 goto put_cpu_node; 611 goto put_cpu_node;
606 } 612 }
607 613
608 /* Get OPP descriptor node */ 614 /* 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);
610 if (!tmp_np) { 616 if (!tmp_np) {
611 dev_err(tcpu_dev, "%s: Couldn't find opp node.\n", 617 pr_err("%pOF: Couldn't find opp node\n", cpu_np);
612 __func__);
613 ret = -ENOENT; 618 ret = -ENOENT;
614 goto put_cpu_node; 619 goto put_cpu_node;
615 } 620 }