From patchwork Mon Sep 12 11:01:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Hunter X-Patchwork-Id: 9326177 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8AC2A60231 for ; Mon, 12 Sep 2016 11:05:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7B34D289C3 for ; Mon, 12 Sep 2016 11:05:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F4AD28CC6; Mon, 12 Sep 2016 11:05:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 68693289C3 for ; Mon, 12 Sep 2016 11:05:52 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bjP20-0005bA-HW; Mon, 12 Sep 2016 11:04:08 +0000 Received: from hqemgate15.nvidia.com ([216.228.121.64]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bjP00-0004D1-Tp for linux-arm-kernel@lists.infradead.org; Mon, 12 Sep 2016 11:02:08 +0000 Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate15.nvidia.com id ; Mon, 12 Sep 2016 04:01:41 -0700 Received: from HQMAIL101.nvidia.com ([172.20.187.10]) by hqnvupgp07.nvidia.com (PGP Universal service); Mon, 12 Sep 2016 03:56:36 -0700 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Mon, 12 Sep 2016 03:56:36 -0700 Received: from HQMAIL108.nvidia.com (172.18.146.13) by HQMAIL101.nvidia.com (172.20.187.10) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Mon, 12 Sep 2016 11:01:23 +0000 Received: from hqnvemgw02.nvidia.com (172.16.227.111) by HQMAIL108.nvidia.com (172.18.146.13) with Microsoft SMTP Server id 15.0.1210.3 via Frontend Transport; Mon, 12 Sep 2016 11:01:22 +0000 Received: from jonathanh-lm.nvidia.com (Not Verified[10.21.132.115]) by hqnvemgw02.nvidia.com with Trustwave SEG (v7, 5, 5, 8150) id ; Mon, 12 Sep 2016 04:01:22 -0700 From: Jon Hunter To: "Rafael J. Wysocki" , Kevin Hilman , Ulf Hansson Subject: [PATCH V2 07/10] PM / Domains: Prepare for adding support to remove PM domains Date: Mon, 12 Sep 2016 12:01:11 +0100 Message-ID: <1473678074-15126-8-git-send-email-jonathanh@nvidia.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com> References: <1473678074-15126-1-git-send-email-jonathanh@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160912_040205_090211_D3CD6B49 X-CRM114-Status: GOOD ( 15.99 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Krzysztof Kozlowski , linux-pm@vger.kernel.org, Alexander Aring , Jon Hunter , Eric Anholt , Thierry Reding , Kukjin Kim , linux-tegra@vger.kernel.org, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP In order to remove PM domains safely from the list of PM domains, it is necessary to adding locking for the PM domain list around any places where devices or subdomains are added to a PM domain. There are places where a reference to a PM domain is obtained via calling of_genpd_get_from_provider() before adding the device or the subdomain. In these cases a lock for the PM domain list needs to be held around the call to of_genpd_get_from_provider() and the call to add the device/subdomain. To avoid deadlocks by multiple attempts to obtain the PM domain list lock, add functions genpd_add_device() and genpd_add_subdomain() which require the user to hold the PM domain list lock when calling. Signed-off-by: Jon Hunter Acked-by: Ulf Hansson --- drivers/base/power/domain.c | 97 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 24 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index fc9f11c26eec..1bd8d412db06 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1060,14 +1060,8 @@ static void genpd_free_dev_data(struct device *dev, dev_pm_put_subsys_data(dev); } -/** - * __pm_genpd_add_device - Add a device to an I/O PM domain. - * @genpd: PM domain to add the device to. - * @dev: Device to be added. - * @td: Set of PM QoS timing parameters to attach to the device. - */ -int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, - struct gpd_timing_data *td) +static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, + struct gpd_timing_data *td) { struct generic_pm_domain_data *gpd_data; int ret = 0; @@ -1107,6 +1101,24 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, return ret; } + +/** + * __pm_genpd_add_device - Add a device to an I/O PM domain. + * @genpd: PM domain to add the device to. + * @dev: Device to be added. + * @td: Set of PM QoS timing parameters to attach to the device. + */ +int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, + struct gpd_timing_data *td) +{ + int ret; + + mutex_lock(&gpd_list_lock); + ret = genpd_add_device(genpd, dev, td); + mutex_unlock(&gpd_list_lock); + + return ret; +} EXPORT_SYMBOL_GPL(__pm_genpd_add_device); /** @@ -1160,13 +1172,8 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, } EXPORT_SYMBOL_GPL(pm_genpd_remove_device); -/** - * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. - * @genpd: Master PM domain to add the subdomain to. - * @subdomain: Subdomain to be added. - */ -int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, - struct generic_pm_domain *subdomain) +static int genpd_add_subdomain(struct generic_pm_domain *genpd, + struct generic_pm_domain *subdomain) { struct gpd_link *link, *itr; int ret = 0; @@ -1209,6 +1216,23 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, kfree(link); return ret; } + +/** + * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. + * @genpd: Master PM domain to add the subdomain to. + * @subdomain: Subdomain to be added. + */ +int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, + struct generic_pm_domain *subdomain) +{ + int ret; + + mutex_lock(&gpd_list_lock); + ret = genpd_add_subdomain(genpd, subdomain); + mutex_unlock(&gpd_list_lock); + + return ret; +} EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain); /** @@ -1571,12 +1595,22 @@ static struct generic_pm_domain *genpd_get_from_provider( int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev) { struct generic_pm_domain *genpd; + int ret; + + mutex_lock(&gpd_list_lock); genpd = genpd_get_from_provider(genpdspec); - if (IS_ERR(genpd)) - return PTR_ERR(genpd); + if (IS_ERR(genpd)) { + ret = PTR_ERR(genpd); + goto out; + } + + ret = genpd_add_device(genpd, dev, NULL); - return pm_genpd_add_device(genpd, dev); +out: + mutex_unlock(&gpd_list_lock); + + return ret; } EXPORT_SYMBOL_GPL(of_genpd_add_device); @@ -1593,16 +1627,28 @@ int of_genpd_add_subdomain(struct of_phandle_args *parent_spec, struct of_phandle_args *subdomain_spec) { struct generic_pm_domain *parent, *subdomain; + int ret; + + mutex_lock(&gpd_list_lock); parent = genpd_get_from_provider(parent_spec); - if (IS_ERR(parent)) - return PTR_ERR(parent); + if (IS_ERR(parent)) { + ret = PTR_ERR(parent); + goto out; + } subdomain = genpd_get_from_provider(subdomain_spec); - if (IS_ERR(subdomain)) - return PTR_ERR(subdomain); + if (IS_ERR(subdomain)) { + ret = PTR_ERR(subdomain); + goto out; + } + + ret = genpd_add_subdomain(parent, subdomain); - return pm_genpd_add_subdomain(parent, subdomain); +out: + mutex_unlock(&gpd_list_lock); + + return ret; } EXPORT_SYMBOL_GPL(of_genpd_add_subdomain); @@ -1701,9 +1747,11 @@ int genpd_dev_pm_attach(struct device *dev) return -ENOENT; } + mutex_lock(&gpd_list_lock); pd = genpd_get_from_provider(&pd_args); of_node_put(pd_args.np); if (IS_ERR(pd)) { + mutex_unlock(&gpd_list_lock); dev_dbg(dev, "%s() failed to find PM domain: %ld\n", __func__, PTR_ERR(pd)); return -EPROBE_DEFER; @@ -1712,13 +1760,14 @@ int genpd_dev_pm_attach(struct device *dev) dev_dbg(dev, "adding to PM domain %s\n", pd->name); for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { - ret = pm_genpd_add_device(pd, dev); + ret = genpd_add_device(pd, dev, NULL); if (ret != -EAGAIN) break; mdelay(i); cond_resched(); } + mutex_unlock(&gpd_list_lock); if (ret < 0) { dev_err(dev, "failed to add to PM domain %s: %d",