linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2] PM / Domains: Fix potential deadlock while adding/removing subdomains
@ 2016-01-20 11:07 Ulf Hansson
  2016-01-24  1:20 ` Rafael J. Wysocki
  0 siblings, 1 reply; 5+ messages in thread
From: Ulf Hansson @ 2016-01-20 11:07 UTC (permalink / raw)
  To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, linux-pm
  Cc: Len Brown, Pavel Machek, Geert Uytterhoeven, Lina Iyer,
	Lorenzo Pieralisi, Axel Haslam, Marc Titinger, Marek Szyprowski

We must preserve the same order of how we acquire and release the lock for
genpd, as otherwise we may encounter deadlocks.

The power on phase of a genpd starts by acquiring its lock. Then it walks
the hierarchy of its parent domains to be able to power on these first, as
per design of genpd.

>From a locking perspective this means the locks of the parents becomes
acquired after the lock of the subdomain.

Let's fix pm_genpd_add|remove_subdomain() to maintain the same order of
acquiring/releasing the genpd lock as being applied in the power on/off
sequence.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---

Changes in v2:
	Fix lockdep warning.

---
 drivers/base/power/domain.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 6ac9a7f..676d762 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1339,8 +1339,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 	if (!link)
 		return -ENOMEM;
 
-	mutex_lock(&genpd->lock);
-	mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
+	mutex_lock(&subdomain->lock);
+	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
 
 	if (genpd->status == GPD_STATE_POWER_OFF
 	    &&  subdomain->status != GPD_STATE_POWER_OFF) {
@@ -1363,8 +1363,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 		genpd_sd_counter_inc(genpd);
 
  out:
-	mutex_unlock(&subdomain->lock);
 	mutex_unlock(&genpd->lock);
+	mutex_unlock(&subdomain->lock);
 	if (ret)
 		kfree(link);
 	return ret;
@@ -1385,7 +1385,8 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
-	mutex_lock(&genpd->lock);
+	mutex_lock(&subdomain->lock);
+	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
 
 	if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
 		pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
@@ -1398,22 +1399,19 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
 		if (link->slave != subdomain)
 			continue;
 
-		mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
-
 		list_del(&link->master_node);
 		list_del(&link->slave_node);
 		kfree(link);
 		if (subdomain->status != GPD_STATE_POWER_OFF)
 			genpd_sd_counter_dec(genpd);
 
-		mutex_unlock(&subdomain->lock);
-
 		ret = 0;
 		break;
 	}
 
 out:
 	mutex_unlock(&genpd->lock);
+	mutex_unlock(&subdomain->lock);
 
 	return ret;
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-01-26 16:28 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-20 11:07 [PATCH V2] PM / Domains: Fix potential deadlock while adding/removing subdomains Ulf Hansson
2016-01-24  1:20 ` Rafael J. Wysocki
2016-01-26 13:13   ` Geert Uytterhoeven
2016-01-26 14:59     ` Ulf Hansson
2016-01-26 16:29       ` Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).