From 8a679b90b2130dd3970ed41f3a18df6030b71b1c Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 5 Oct 2015 16:45:30 +0200 Subject: [PATCH] FROMLIST: 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. BUG=chrome-os-partner:46491 TEST=boot glados Signed-off-by: Tomeu Vizoso (am from https://patchwork.kernel.org/patch/7328141/) Signed-off-by: Derek Basehore Change-Id: I2eaf04084337c9a9b6f7f188f94d7ebada8dbb57 Reviewed-on: https://chromium-review.googlesource.com/305814 Commit-Ready: Derek Basehore Tested-by: Derek Basehore Reviewed-by: Eric Caruso --- arch/arm/mach-omap2/omap_device.c | 7 ++++--- drivers/acpi/acpi_lpss.c | 6 ++++-- drivers/acpi/device_pm.c | 5 +++-- drivers/base/power/clock_ops.c | 7 +++++-- drivers/base/power/common.c | 21 +++++++++++++++++++++ drivers/base/power/domain.c | 4 ++-- drivers/gpu/vga/vga_switcheroo.c | 10 +++++----- drivers/misc/mei/pci-me.c | 5 +++-- drivers/misc/mei/pci-txe.c | 5 +++-- include/linux/pm_domain.h | 3 +++ 10 files changed, 53 insertions(+), 20 deletions(-) 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 */