summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2018-04-26 10:53:00 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-03 11:24:47 +0200
commitb7ac0389770aacc2dc91d17dc44fd4dcc1438faf (patch)
treefefdc5dae3ae5453cf220cdafba2a0410249e3dd
parent8ae5d476a3b7bd7938abcd0f926925c7c81fd79b (diff)
downloadlinux-stable-b7ac0389770aacc2dc91d17dc44fd4dcc1438faf.tar.gz
linux-stable-b7ac0389770aacc2dc91d17dc44fd4dcc1438faf.tar.bz2
linux-stable-b7ac0389770aacc2dc91d17dc44fd4dcc1438faf.zip
PM / Domains: Fix error path during attach in genpd
commit 72038df3c580c4c326b83c86149d7ac34007532a upstream. In case the PM domain fails to be powered on in genpd_dev_pm_attach(), it returns -EPROBE_DEFER, but keeping the device attached to its PM domain. This leads to problems when the next attempt to attach is re-tried. More precisely, in that situation an -EEXIST error code is returned, because the device already has its PM domain pointer assigned, from the first attempt. Now, because of the sloppy error handling by the existing callers of dev_pm_domain_attach(), probing is allowed to continue when -EEXIST is returned. However, in such case there are no guarantees that the PM domain is powered on by genpd, which may lead to hangs when buses/drivers tried to access their devices. Let's fix this behaviour, simply by detaching the device when powering on fails in genpd_dev_pm_attach(). Cc: v4.11+ <stable@vger.kernel.org> # v4.11+ Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/power/domain.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index b3b78079aa9f..c276ba1c0a19 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2162,6 +2162,9 @@ int genpd_dev_pm_attach(struct device *dev)
genpd_lock(pd);
ret = genpd_power_on(pd, 0);
genpd_unlock(pd);
+
+ if (ret)
+ genpd_remove_device(pd, dev);
out:
return ret ? -EPROBE_DEFER : 0;
}