From patchwork Wed Jan 27 08:10:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 60595 Delivered-To: patches@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp2439670lbb; Wed, 27 Jan 2016 00:10:44 -0800 (PST) X-Received: by 10.112.35.162 with SMTP id i2mr10038530lbj.107.1453882244476; Wed, 27 Jan 2016 00:10:44 -0800 (PST) Return-Path: Received: from mail-lb0-x234.google.com (mail-lb0-x234.google.com. [2a00:1450:4010:c04::234]) by mx.google.com with ESMTPS id d141si2572697lfd.107.2016.01.27.00.10.44 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Jan 2016 00:10:44 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c04::234 as permitted sender) client-ip=2a00:1450:4010:c04::234; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 2a00:1450:4010:c04::234 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dkim=pass header.i=@linaro.org Received: by mail-lb0-x234.google.com with SMTP id bc4so703770lbc.2 for ; Wed, 27 Jan 2016 00:10:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=toftI+520uz75wvu+hhjP/3O/qupCWxfJWXfG1MBRtk=; b=Qv+DmZ47mtWpVyWt0SxImZTLJvjnwQ6BK5zMe1A6U03ILj+cGoynEsnvcoToQVEZrS 2Ma/bum9BeTUAZ3AoQSpdMV/qsvFE7PC7PzZKqMbeQxbEjaRS5N4bPVaoVuJN6E15jJo 1J5uuL4hmvDSqqgLcoVoNxi7J56Qx98MhF1Vw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=toftI+520uz75wvu+hhjP/3O/qupCWxfJWXfG1MBRtk=; b=SSOFeGdRh76Gidtfmh6lA3F1apbxNLqrcGBBf33z339MEIAv+INhdmw74J7PH4NcUG pQkN4Ym08FheAg6lnp6tvFV7p84Tg5jW645sQe19Ue3zOVg14nP8OVje1YM1sk7q/jXE lNSd7+HjeuUQDWV1KaH49elWyD1TLS35TFdsBHZYZ8Amb2AY6sgb3+i/sM04ICOVaoA/ GWPqKp1dfhfDQgfOTsEGbtL5spycOtxpYUm8EN+/jHHA9COqAIB4/ZHFBxZefJO0YFgE WoYpT5F0m8/Ja2KmpWo9Tl16wBGpE2ZNMFKBz8vVKZzig0b21LszncdHaiplBoCk/CxR LU2w== X-Gm-Message-State: AG10YOQ6k+/Q4c5Xb5qmpVkUVzA1Zp2pP7j4Zp9UjGp0d5ya//a7Bm6Lvp0pR/9NdaResV1yjq0= X-Received: by 10.112.17.9 with SMTP id k9mr10168834lbd.47.1453882243921; Wed, 27 Jan 2016 00:10:43 -0800 (PST) Return-Path: Received: from localhost.localdomain (c-83-233-167-104.cust.bredband2.com. [83.233.167.104]) by smtp.gmail.com with ESMTPSA id rp10sm649689lbb.13.2016.01.27.00.10.42 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 27 Jan 2016 00:10:43 -0800 (PST) From: Ulf Hansson To: "Rafael J. Wysocki" , Kevin Hilman , Ulf Hansson , linux-pm@vger.kernel.org Cc: Len Brown , Pavel Machek , Geert Uytterhoeven , Lina Iyer , Lorenzo Pieralisi , Axel Haslam , Marc Titinger , Marek Szyprowski Subject: [RESEND PATCH V2] PM / Domains: Fix potential deadlock while adding/removing subdomains Date: Wed, 27 Jan 2016 09:10:37 +0100 Message-Id: <1453882237-2816-1-git-send-email-ulf.hansson@linaro.org> X-Mailer: git-send-email 1.9.1 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 --- Changes in v2: Fix lockdep warning. --- drivers/base/power/domain.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) -- 1.9.1 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; }