diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 8c58b71c2727c..bca370783a7ed 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -174,7 +175,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(&pdev->dev); } - pdev->dev.pm_domain = &omap_device_pm_domain; + dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain); if (device_active) { omap_device_enable(pdev); @@ -186,7 +187,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) - pdev->dev.pm_domain = &omap_device_fail_pm_domain; + dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain); return ret; } @@ -705,7 +706,7 @@ int omap_device_register(struct platform_device *pdev) { pr_debug("omap_device: %s: registering\n", pdev->name); - pdev->dev.pm_domain = &omap_device_pm_domain; + dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain); return platform_device_add(pdev); } diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 93d160661f4c9..300225d8ff47e 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -642,11 +643,11 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, switch (action) { case BUS_NOTIFY_BOUND_DRIVER: if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - pdev->dev.pm_domain = &acpi_lpss_pm_domain; + dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain); break; case BUS_NOTIFY_UNBOUND_DRIVER: if (pdata->dev_desc->flags & LPSS_SAVE_CTX) - pdev->dev.pm_domain = NULL; + dev_pm_domain_set(&pdev->dev, NULL); break; case BUS_NOTIFY_ADD_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) @@ -655,6 +656,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, case BUS_NOTIFY_DEL_DEVICE: if (pdata->dev_desc->flags & LPSS_LTR) sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); + break; default: break; } diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 6c5096591c376..4d98dde3f4f86 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1058,7 +1059,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off) struct acpi_device *adev = ACPI_COMPANION(dev); if (adev && dev->pm_domain == &acpi_general_pm_domain) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); acpi_remove_pm_notifier(adev); if (power_off) { /* @@ -1115,7 +1116,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); - dev->pm_domain = &acpi_general_pm_domain; + dev_pm_domain_set(dev, &acpi_general_pm_domain); if (power_on) { acpi_dev_pm_full_power(adev); 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 308e9ffa4abf1..f8a64db56b443 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -12,8 +12,11 @@ #include #include #include +#include #include #include +#include +#include #ifdef CONFIG_PM @@ -323,7 +326,7 @@ static int pm_clk_notify(struct notifier_block *nb, if (error) break; - dev->pm_domain = clknb->pm_domain; + dev_pm_domain_set(dev, clknb->pm_domain); if (clknb->con_ids[0]) { for (con_id = clknb->con_ids; *con_id; con_id++) pm_clk_add(dev, *con_id); @@ -336,7 +339,7 @@ static int pm_clk_notify(struct notifier_block *nb, if (dev->pm_domain != clknb->pm_domain) break; - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); pm_clk_destroy(dev); break; } diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index b0f138806bbc4..e939e99e1ed95 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -134,3 +134,24 @@ void dev_pm_domain_detach(struct device *dev, bool power_off) dev->pm_domain->detach(dev, power_off); } EXPORT_SYMBOL_GPL(dev_pm_domain_detach); + +/** + * dev_pm_domain_set - Set PM domain of a device. + * @dev: Device whose PM domain is to be set. + * @pd: PM domain to be set, or NULL. + * + * Sets the PM domain the device belongs to. The PM domain of a device needs + * to be set before its probe finishes (it's bound to a driver). + * + * This function must be called with the device lock held. + */ +void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd) +{ + if (dev->pm_domain == pd) + return; + + WARN(device_is_bound(dev), + "PM domains can only be changed for unbound devices\n"); + dev->pm_domain = pd; +} +EXPORT_SYMBOL_GPL(dev_pm_domain_set); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index fb83d4acd400e..5f7306731e73c 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1449,7 +1449,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, spin_lock_irq(&dev->power.lock); - dev->pm_domain = &genpd->domain; + dev_pm_domain_set(dev, &genpd->domain); if (dev->power.subsys_data->domain_data) { gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); } else { @@ -1529,7 +1529,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, spin_lock_irq(&dev->power.lock); - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); pdd = dev->power.subsys_data->domain_data; list_del_init(&pdd->list_node); gpd_data = to_gpd_data(pdd); diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 37ac7b5dbd066..2ce5d7ed02dd0 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -652,17 +652,17 @@ int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain * domain->ops.runtime_suspend = vga_switcheroo_runtime_suspend; domain->ops.runtime_resume = vga_switcheroo_runtime_resume; - dev->pm_domain = domain; + dev_pm_domain_set(dev, domain); return 0; } - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); return -EINVAL; } EXPORT_SYMBOL(vga_switcheroo_init_domain_pm_ops); void vga_switcheroo_fini_domain_pm_ops(struct device *dev) { - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); } EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops); @@ -702,10 +702,10 @@ int vga_switcheroo_init_domain_pm_optimus_hdmi_audio(struct device *dev, struct domain->ops = *dev->bus->pm; domain->ops.runtime_resume = vga_switcheroo_runtime_resume_hdmi_audio; - dev->pm_domain = domain; + dev_pm_domain_set(dev, domain); return 0; } - dev->pm_domain = NULL; + dev_pm_domain_set(dev, NULL); return -EINVAL; } EXPORT_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 f3225b1643abb..7352b44c17bfb 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -439,7 +440,7 @@ static inline void mei_me_set_pm_domain(struct mei_device *dev) dev->pg_domain.ops.runtime_resume = mei_me_pm_runtime_resume; dev->pg_domain.ops.runtime_idle = mei_me_pm_runtime_idle; - pdev->dev.pm_domain = &dev->pg_domain; + dev_pm_domain_set(&pdev->dev, &dev->pg_domain); } } @@ -451,7 +452,7 @@ static inline void mei_me_set_pm_domain(struct mei_device *dev) static inline void mei_me_unset_pm_domain(struct mei_device *dev) { /* stop using pm callbacks if any */ - dev->dev->pm_domain = NULL; + dev_pm_domain_set(dev->dev, NULL); } #endif /* CONFIG_PM_RUNTIME */ diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index bee1c6fb7e75c..21738d8a60a97 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -387,7 +388,7 @@ static inline void mei_txe_set_pm_domain(struct mei_device *dev) dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume; dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle; - pdev->dev.pm_domain = &dev->pg_domain; + dev_pm_domain_set(&pdev->dev, &dev->pg_domain); } } @@ -399,7 +400,7 @@ static inline void mei_txe_set_pm_domain(struct mei_device *dev) static inline void mei_txe_unset_pm_domain(struct mei_device *dev) { /* stop using pm callbacks if any */ - dev->dev->pm_domain = NULL; + dev_pm_domain_set(dev->dev, NULL); } #endif /* CONFIG_PM_RUNTIME */ diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 2e0e06daf8c06..2b02b024e8e4a 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -306,12 +306,15 @@ static inline int of_genpd_add_provider_onecell(struct device_node *np, #ifdef CONFIG_PM extern int dev_pm_domain_attach(struct device *dev, bool power_on); extern void dev_pm_domain_detach(struct device *dev, bool power_off); +extern void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd); #else static inline int dev_pm_domain_attach(struct device *dev, bool power_on) { return -ENODEV; } static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {} +static inline void dev_pm_domain_set(struct device *dev, + struct dev_pm_domain *pd) {} #endif #endif /* _LINUX_PM_DOMAIN_H */