aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu.vizoso@collabora.com>2016-01-07 10:46:13 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-01-07 19:12:06 -0500
commit989561de9b5112999475b406557d9c7e9e59c041 (patch)
tree1c4257ef719116fecbea9ecdd14febb6af2c336b
parent6b9cb42752dafba3761dde0002ca58ca518b6311 (diff)
PM / Domains: add setter for dev.pm_domain
Adds a function that sets the pointer to dev_pm_domain in struct device and that warns if the device has already finished probing. The reason why we want to enforce that is because in the general case that can cause problems and also that we can simplify code quite a bit if we can always assume that. This patch also changes all current code that directly sets the dev.pm_domain pointer. Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--arch/arm/mach-omap2/omap_device.c7
-rw-r--r--drivers/acpi/acpi_lpss.c5
-rw-r--r--drivers/acpi/device_pm.c5
-rw-r--r--drivers/base/power/clock_ops.c5
-rw-r--r--drivers/base/power/common.c21
-rw-r--r--drivers/base/power/domain.c6
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c11
-rw-r--r--drivers/misc/mei/pci-me.c5
-rw-r--r--drivers/misc/mei/pci-txe.c5
-rw-r--r--include/linux/pm_domain.h3
10 files changed, 54 insertions, 19 deletions
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 72ebc4c16bae..220822bcfe3f 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -32,6 +32,7 @@
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/clk.h> 33#include <linux/clk.h>
34#include <linux/clkdev.h> 34#include <linux/clkdev.h>
35#include <linux/pm_domain.h>
35#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
36#include <linux/of.h> 37#include <linux/of.h>
37#include <linux/notifier.h> 38#include <linux/notifier.h>
@@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
168 r->name = dev_name(&pdev->dev); 169 r->name = dev_name(&pdev->dev);
169 } 170 }
170 171
171 pdev->dev.pm_domain = &omap_device_pm_domain; 172 dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
172 173
173 if (device_active) { 174 if (device_active) {
174 omap_device_enable(pdev); 175 omap_device_enable(pdev);
@@ -180,7 +181,7 @@ odbfd_exit1:
180odbfd_exit: 181odbfd_exit:
181 /* if data/we are at fault.. load up a fail handler */ 182 /* if data/we are at fault.. load up a fail handler */
182 if (ret) 183 if (ret)
183 pdev->dev.pm_domain = &omap_device_fail_pm_domain; 184 dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain);
184 185
185 return ret; 186 return ret;
186} 187}
@@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev)
701{ 702{
702 pr_debug("omap_device: %s: registering\n", pdev->name); 703 pr_debug("omap_device: %s: registering\n", pdev->name);
703 704
704 pdev->dev.pm_domain = &omap_device_pm_domain; 705 dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
705 return platform_device_add(pdev); 706 return platform_device_add(pdev);
706} 707}
707 708
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index 047281a6ae11..c570b1d9f094 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -18,6 +18,7 @@
18#include <linux/mutex.h> 18#include <linux/mutex.h>
19#include <linux/platform_device.h> 19#include <linux/platform_device.h>
20#include <linux/platform_data/clk-lpss.h> 20#include <linux/platform_data/clk-lpss.h>
21#include <linux/pm_domain.h>
21#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23 24
@@ -875,13 +876,14 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,
875 876
876 switch (action) { 877 switch (action) {
877 case BUS_NOTIFY_BIND_DRIVER: 878 case BUS_NOTIFY_BIND_DRIVER:
878 pdev->dev.pm_domain = &acpi_lpss_pm_domain; 879 dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain);
879 break; 880 break;
880 case BUS_NOTIFY_DRIVER_NOT_BOUND: 881 case BUS_NOTIFY_DRIVER_NOT_BOUND:
881 case BUS_NOTIFY_UNBOUND_DRIVER: 882 case BUS_NOTIFY_UNBOUND_DRIVER:
882 pdev->dev.pm_domain = NULL; 883 pdev->dev.pm_domain = NULL;
883 break; 884 break;
884 case BUS_NOTIFY_ADD_DEVICE: 885 case BUS_NOTIFY_ADD_DEVICE:
886 dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain);
885 if (pdata->dev_desc->flags & LPSS_LTR) 887 if (pdata->dev_desc->flags & LPSS_LTR)
886 return sysfs_create_group(&pdev->dev.kobj, 888 return sysfs_create_group(&pdev->dev.kobj,
887 &lpss_attr_group); 889 &lpss_attr_group);
@@ -889,6 +891,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,
889 case BUS_NOTIFY_DEL_DEVICE: 891 case BUS_NOTIFY_DEL_DEVICE:
890 if (pdata->dev_desc->flags & LPSS_LTR) 892 if (pdata->dev_desc->flags & LPSS_LTR)
891 sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); 893 sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
894 dev_pm_domain_set(&pdev->dev, NULL);
892 break; 895 break;
893 default: 896 default:
894 break; 897 break;
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 08a02cdc737c..cd2c3d6d40e0 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -22,6 +22,7 @@
22#include <linux/export.h> 22#include <linux/export.h>
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <linux/pm_qos.h> 24#include <linux/pm_qos.h>
25#include <linux/pm_domain.h>
25#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
26 27
27#include "internal.h" 28#include "internal.h"
@@ -1059,7 +1060,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off)
1059 struct acpi_device *adev = ACPI_COMPANION(dev); 1060 struct acpi_device *adev = ACPI_COMPANION(dev);
1060 1061
1061 if (adev && dev->pm_domain == &acpi_general_pm_domain) { 1062 if (adev && dev->pm_domain == &acpi_general_pm_domain) {
1062 dev->pm_domain = NULL; 1063 dev_pm_domain_set(dev, NULL);
1063 acpi_remove_pm_notifier(adev); 1064 acpi_remove_pm_notifier(adev);
1064 if (power_off) { 1065 if (power_off) {
1065 /* 1066 /*
@@ -1111,7 +1112,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
1111 return -EBUSY; 1112 return -EBUSY;
1112 1113
1113 acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); 1114 acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
1114 dev->pm_domain = &acpi_general_pm_domain; 1115 dev_pm_domain_set(dev, &acpi_general_pm_domain);
1115 if (power_on) { 1116 if (power_on) {
1116 acpi_dev_pm_full_power(adev); 1117 acpi_dev_pm_full_power(adev);
1117 acpi_device_wakeup(adev, ACPI_STATE_S0, false); 1118 acpi_device_wakeup(adev, ACPI_STATE_S0, false);
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c
index c39b8617280f..272a52ebafc0 100644
--- a/drivers/base/power/clock_ops.c
+++ b/drivers/base/power/clock_ops.c
@@ -15,6 +15,7 @@
15#include <linux/clkdev.h> 15#include <linux/clkdev.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/err.h> 17#include <linux/err.h>
18#include <linux/pm_domain.h>
18#include <linux/pm_runtime.h> 19#include <linux/pm_runtime.h>
19 20
20#ifdef CONFIG_PM_CLK 21#ifdef CONFIG_PM_CLK
@@ -348,7 +349,7 @@ static int pm_clk_notify(struct notifier_block *nb,
348 if (error) 349 if (error)
349 break; 350 break;
350 351
351 dev->pm_domain = clknb->pm_domain; 352 dev_pm_domain_set(dev, clknb->pm_domain);
352 if (clknb->con_ids[0]) { 353 if (clknb->con_ids[0]) {
353 for (con_id = clknb->con_ids; *con_id; con_id++) 354 for (con_id = clknb->con_ids; *con_id; con_id++)
354 pm_clk_add(dev, *con_id); 355 pm_clk_add(dev, *con_id);
@@ -361,7 +362,7 @@ static int pm_clk_notify(struct notifier_block *nb,
361 if (dev->pm_domain != clknb->pm_domain) 362 if (dev->pm_domain != clknb->pm_domain)
362 break; 363 break;
363 364
364 dev->pm_domain = NULL; 365 dev_pm_domain_set(dev, NULL);
365 pm_clk_destroy(dev); 366 pm_clk_destroy(dev);
366 break; 367 break;
367 } 368 }
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index f48e33385b3e..02812bcabcac 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -128,3 +128,24 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
128 dev->pm_domain->detach(dev, power_off); 128 dev->pm_domain->detach(dev, power_off);
129} 129}
130EXPORT_SYMBOL_GPL(dev_pm_domain_detach); 130EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
131
132/**
133 * dev_pm_domain_set - Set PM domain of a device.
134 * @dev: Device whose PM domain is to be set.
135 * @pd: PM domain to be set, or NULL.
136 *
137 * Sets the PM domain the device belongs to. The PM domain of a device needs
138 * to be set before its probe finishes (it's bound to a driver).
139 *
140 * This function must be called with the device lock held.
141 */
142void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd)
143{
144 if (dev->pm_domain == pd)
145 return;
146
147 WARN(device_is_bound(dev),
148 "PM domains can only be changed for unbound devices\n");
149 dev->pm_domain = pd;
150}
151EXPORT_SYMBOL_GPL(dev_pm_domain_set);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 167418e73445..abbac6fe8fd5 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1177,10 +1177,11 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
1177 } 1177 }
1178 1178
1179 dev->power.subsys_data->domain_data = &gpd_data->base; 1179 dev->power.subsys_data->domain_data = &gpd_data->base;
1180 dev->pm_domain = &genpd->domain;
1181 1180
1182 spin_unlock_irq(&dev->power.lock); 1181 spin_unlock_irq(&dev->power.lock);
1183 1182
1183 dev_pm_domain_set(dev, &genpd->domain);
1184
1184 return gpd_data; 1185 return gpd_data;
1185 1186
1186 err_free: 1187 err_free:
@@ -1194,9 +1195,10 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
1194static void genpd_free_dev_data(struct device *dev, 1195static void genpd_free_dev_data(struct device *dev,
1195 struct generic_pm_domain_data *gpd_data) 1196 struct generic_pm_domain_data *gpd_data)
1196{ 1197{
1198 dev_pm_domain_set(dev, NULL);
1199
1197 spin_lock_irq(&dev->power.lock); 1200 spin_lock_irq(&dev->power.lock);
1198 1201
1199 dev->pm_domain = NULL;
1200 dev->power.subsys_data->domain_data = NULL; 1202 dev->power.subsys_data->domain_data = NULL;
1201 1203
1202 spin_unlock_irq(&dev->power.lock); 1204 spin_unlock_irq(&dev->power.lock);
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 41edd5a3f100..7b95ed2fb49b 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -36,6 +36,7 @@
36#include <linux/fs.h> 36#include <linux/fs.h>
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/pci.h> 38#include <linux/pci.h>
39#include <linux/pm_domain.h>
39#include <linux/pm_runtime.h> 40#include <linux/pm_runtime.h>
40#include <linux/seq_file.h> 41#include <linux/seq_file.h>
41#include <linux/uaccess.h> 42#include <linux/uaccess.h>
@@ -918,17 +919,17 @@ int vga_switcheroo_init_domain_pm_ops(struct device *dev,
918 domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend; 919 domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend;
919 domain->ops.runtime_resume = vga_switcheroo_runtime_resume; 920 domain->ops.runtime_resume = vga_switcheroo_runtime_resume;
920 921
921 dev->pm_domain = domain; 922 dev_pm_domain_set(dev, domain);
922 return 0; 923 return 0;
923 } 924 }
924 dev->pm_domain = NULL; 925 dev_pm_domain_set(dev, NULL);
925 return -EINVAL; 926 return -EINVAL;
926} 927}
927EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops); 928EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops);
928 929
929void vga_switcheroo_fini_domain_pm_ops(struct device *dev) 930void vga_switcheroo_fini_domain_pm_ops(struct device *dev)
930{ 931{
931 dev->pm_domain = NULL; 932 dev_pm_domain_set(dev, NULL);
932} 933}
933EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); 934EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
934 935
@@ -989,10 +990,10 @@ vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev,
989 domain->ops.runtime_resume = 990 domain->ops.runtime_resume =
990 vga_switcheroo_runtime_resume_hdmi_audio; 991 vga_switcheroo_runtime_resume_hdmi_audio;
991 992
992 dev->pm_domain = domain; 993 dev_pm_domain_set(dev, domain);
993 return 0; 994 return 0;
994 } 995 }
995 dev->pm_domain = NULL; 996 dev_pm_domain_set(dev, NULL);
996 return -EINVAL; 997 return -EINVAL;
997} 998}
998EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio); 999EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_optimus_hdmi_audio);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 27678d8154e0..75fc9c688df8 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -31,6 +31,7 @@
31#include <linux/jiffies.h> 31#include <linux/jiffies.h>
32#include <linux/interrupt.h> 32#include <linux/interrupt.h>
33 33
34#include <linux/pm_domain.h>
34#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
35 36
36#include <linux/mei.h> 37#include <linux/mei.h>
@@ -436,7 +437,7 @@ static inline void mei_me_set_pm_domain(struct mei_device *dev)
436 dev->pg_domain.ops.runtime_resume = mei_me_pm_runtime_resume; 437 dev->pg_domain.ops.runtime_resume = mei_me_pm_runtime_resume;
437 dev->pg_domain.ops.runtime_idle = mei_me_pm_runtime_idle; 438 dev->pg_domain.ops.runtime_idle = mei_me_pm_runtime_idle;
438 439
439 pdev->dev.pm_domain = &dev->pg_domain; 440 dev_pm_domain_set(&pdev->dev, &dev->pg_domain);
440 } 441 }
441} 442}
442 443
@@ -448,7 +449,7 @@ static inline void mei_me_set_pm_domain(struct mei_device *dev)
448static inline void mei_me_unset_pm_domain(struct mei_device *dev) 449static inline void mei_me_unset_pm_domain(struct mei_device *dev)
449{ 450{
450 /* stop using pm callbacks if any */ 451 /* stop using pm callbacks if any */
451 dev->dev->pm_domain = NULL; 452 dev_pm_domain_set(dev->dev, NULL);
452} 453}
453 454
454static const struct dev_pm_ops mei_me_pm_ops = { 455static const struct dev_pm_ops mei_me_pm_ops = {
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index 0882c0201907..71f8a7475717 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -27,6 +27,7 @@
27#include <linux/jiffies.h> 27#include <linux/jiffies.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/workqueue.h> 29#include <linux/workqueue.h>
30#include <linux/pm_domain.h>
30#include <linux/pm_runtime.h> 31#include <linux/pm_runtime.h>
31 32
32#include <linux/mei.h> 33#include <linux/mei.h>
@@ -388,7 +389,7 @@ static inline void mei_txe_set_pm_domain(struct mei_device *dev)
388 dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume; 389 dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume;
389 dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle; 390 dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle;
390 391
391 pdev->dev.pm_domain = &dev->pg_domain; 392 dev_pm_domain_set(&pdev->dev, &dev->pg_domain);
392 } 393 }
393} 394}
394 395
@@ -400,7 +401,7 @@ static inline void mei_txe_set_pm_domain(struct mei_device *dev)
400static inline void mei_txe_unset_pm_domain(struct mei_device *dev) 401static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
401{ 402{
402 /* stop using pm callbacks if any */ 403 /* stop using pm callbacks if any */
403 dev->dev->pm_domain = NULL; 404 dev_pm_domain_set(dev->dev, NULL);
404} 405}
405 406
406static const struct dev_pm_ops mei_txe_pm_ops = { 407static const struct dev_pm_ops mei_txe_pm_ops = {
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index ba4ced38efae..db21d3995f7e 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -240,12 +240,15 @@ static inline int of_genpd_add_provider_onecell(struct device_node *np,
240#ifdef CONFIG_PM 240#ifdef CONFIG_PM
241extern int dev_pm_domain_attach(struct device *dev, bool power_on); 241extern int dev_pm_domain_attach(struct device *dev, bool power_on);
242extern void dev_pm_domain_detach(struct device *dev, bool power_off); 242extern void dev_pm_domain_detach(struct device *dev, bool power_off);
243extern void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
243#else 244#else
244static inline int dev_pm_domain_attach(struct device *dev, bool power_on) 245static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
245{ 246{
246 return -ENODEV; 247 return -ENODEV;
247} 248}
248static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {} 249static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
250static inline void dev_pm_domain_set(struct device *dev,
251 struct dev_pm_domain *pd) {}
249#endif 252#endif
250 253
251#endif /* _LINUX_PM_DOMAIN_H */ 254#endif /* _LINUX_PM_DOMAIN_H */