summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2018-05-09 13:17:52 +0300
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-05-14 23:58:44 +0300
commit919b7308fcc452cd4e282bab389c33384a9f3790 (patch)
treeaff8f55a43ae45af67ba91efde1a1f70ef798a02
parent4f688748c958deb947759773be6dffe6b44d084d (diff)
downloadlinux-919b7308fcc452cd4e282bab389c33384a9f3790.tar.xz
PM / Domains: Allow a better error handling of dev_pm_domain_attach()
The callers of dev_pm_domain_attach() currently checks the returned error code for -EPROBE_DEFER and needs to ignore other error codes. This is an unnecessary limitation, which also leads to a rather strange behaviour in the error path. Address this limitation, by changing the return codes from acpi_dev_pm_attach() and genpd_dev_pm_attach(). More precisely, let them return 0, when no PM domain is needed for the device and then return 1, in case the device was successfully attached to its PM domain. In this way, dev_pm_domain_attach(), gets a better understanding of what happens in the attach attempts and also allowing its caller to better act on real errors codes. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/device_pm.c6
-rw-r--r--drivers/base/power/common.c7
-rw-r--r--drivers/base/power/domain.c19
-rw-r--r--include/linux/acpi.h2
-rw-r--r--include/linux/pm_domain.h4
5 files changed, 20 insertions, 18 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index d00630016176..a7c2673ffd36 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1257,7 +1257,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
struct acpi_device *adev = ACPI_COMPANION(dev);
if (!adev)
- return -ENODEV;
+ return 0;
/*
* Only attach the power domain to the first device if the
@@ -1265,7 +1265,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
* management twice.
*/
if (!acpi_device_is_first_physical_node(adev, dev))
- return -EBUSY;
+ return 0;
acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
dev_pm_domain_set(dev, &acpi_general_pm_domain);
@@ -1275,7 +1275,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
}
dev->pm_domain->detach = acpi_dev_pm_detach;
- return 0;
+ return 1;
}
EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
#endif /* CONFIG_PM */
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index f3cf61f58f25..5e4b481595bd 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -98,7 +98,8 @@ EXPORT_SYMBOL_GPL(dev_pm_put_subsys_data);
* Callers must ensure proper synchronization of this function with power
* management callbacks.
*
- * Returns 0 on successfully attached PM domain or negative error code.
+ * Returns 0 on successfully attached PM domain and when it found that the
+ * device don't need a PM domain, else a negative error code.
*/
int dev_pm_domain_attach(struct device *dev, bool power_on)
{
@@ -108,10 +109,10 @@ int dev_pm_domain_attach(struct device *dev, bool power_on)
return -EEXIST;
ret = acpi_dev_pm_attach(dev, power_on);
- if (ret)
+ if (!ret)
ret = genpd_dev_pm_attach(dev);
- return ret;
+ return ret < 0 ? ret : 0;
}
EXPORT_SYMBOL_GPL(dev_pm_domain_attach);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index b816adbe1e62..455ecea6c812 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2180,10 +2180,11 @@ static void genpd_dev_pm_sync(struct device *dev)
* Parse device's OF node to find a PM domain specifier. If such is found,
* attaches the device to retrieved pm_domain ops.
*
- * Returns 0 on successfully attached PM domain or negative error code. Note
- * that if a power-domain exists for the device, but it cannot be found or
- * turned on, then return -EPROBE_DEFER to ensure that the device is not
- * probed and to re-try again later.
+ * Returns 1 on successfully attached PM domain, 0 when the device don't need a
+ * PM domain or a negative error code in case of failures. Note that if a
+ * power-domain exists for the device, but it cannot be found or turned on,
+ * then return -EPROBE_DEFER to ensure that the device is not probed and to
+ * re-try again later.
*/
int genpd_dev_pm_attach(struct device *dev)
{
@@ -2192,12 +2193,12 @@ int genpd_dev_pm_attach(struct device *dev)
int ret;
if (!dev->of_node)
- return -ENODEV;
+ return 0;
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
"#power-domain-cells", 0, &pd_args);
if (ret < 0)
- return ret;
+ return 0;
mutex_lock(&gpd_list_lock);
pd = genpd_get_from_provider(&pd_args);
@@ -2218,7 +2219,7 @@ int genpd_dev_pm_attach(struct device *dev)
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to add to PM domain %s: %d",
pd->name, ret);
- goto out;
+ return ret;
}
dev->pm_domain->detach = genpd_dev_pm_detach;
@@ -2230,8 +2231,8 @@ int genpd_dev_pm_attach(struct device *dev)
if (ret)
genpd_remove_device(pd, dev);
-out:
- return ret ? -EPROBE_DEFER : 0;
+
+ return ret ? -EPROBE_DEFER : 1;
}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 15bfb15c2fa5..c01675b3d93f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -899,7 +899,7 @@ static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
{
- return -ENODEV;
+ return 0;
}
#endif
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 04dbef9847d3..ab1854863a8c 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -280,7 +280,7 @@ static inline int of_genpd_parse_idle_states(struct device_node *dn,
static inline int genpd_dev_pm_attach(struct device *dev)
{
- return -ENODEV;
+ return 0;
}
static inline
@@ -297,7 +297,7 @@ 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;
+ return 0;
}
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
static inline void dev_pm_domain_set(struct device *dev,