From: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> To: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>, Kevin Hilman <khilman-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, Ulf Hansson <ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> Cc: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Kukjin Kim <kgene-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>, Krzysztof Kozlowski <k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>, Alexander Aring <alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>, Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>, linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> Subject: [RFC PATCH 7/8] PM / Domains: Prepare for adding support to remove PM domains Date: Fri, 4 Mar 2016 11:23:53 +0000 [thread overview] Message-ID: <1457090634-14785-8-git-send-email-jonathanh@nvidia.com> (raw) In-Reply-To: <1457090634-14785-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 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 <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> --- 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 438885f2455f..9b33377bf01b 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1214,14 +1214,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; @@ -1261,6 +1255,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); /** @@ -1314,13 +1326,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; @@ -1363,6 +1370,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); /** @@ -1807,12 +1831,22 @@ static struct generic_pm_domain *of_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 = of_genpd_get_from_provider(genpdspec); - if (IS_ERR(genpd)) - return PTR_ERR(genpd); + if (IS_ERR(genpd)) { + ret = PTR_ERR(genpd); + goto out; + } - return pm_genpd_add_device(genpd, dev); + ret = genpd_add_device(genpd, dev, NULL); + +out: + mutex_unlock(&gpd_list_lock); + + return ret; } /** @@ -1828,16 +1862,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 = of_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 = of_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); + +out: + mutex_unlock(&gpd_list_lock); - return pm_genpd_add_subdomain(parent, subdomain); + return ret; } /** @@ -1935,9 +1981,11 @@ int genpd_dev_pm_attach(struct device *dev) return -ENOENT; } + mutex_lock(&gpd_list_lock); pd = of_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; @@ -1946,13 +1994,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", -- 2.1.4
WARNING: multiple messages have this Message-ID (diff)
From: jonathanh@nvidia.com (Jon Hunter) To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 7/8] PM / Domains: Prepare for adding support to remove PM domains Date: Fri, 4 Mar 2016 11:23:53 +0000 [thread overview] Message-ID: <1457090634-14785-8-git-send-email-jonathanh@nvidia.com> (raw) In-Reply-To: <1457090634-14785-1-git-send-email-jonathanh@nvidia.com> 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 <jonathanh@nvidia.com> --- 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 438885f2455f..9b33377bf01b 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1214,14 +1214,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; @@ -1261,6 +1255,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); /** @@ -1314,13 +1326,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; @@ -1363,6 +1370,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); /** @@ -1807,12 +1831,22 @@ static struct generic_pm_domain *of_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 = of_genpd_get_from_provider(genpdspec); - if (IS_ERR(genpd)) - return PTR_ERR(genpd); + if (IS_ERR(genpd)) { + ret = PTR_ERR(genpd); + goto out; + } - return pm_genpd_add_device(genpd, dev); + ret = genpd_add_device(genpd, dev, NULL); + +out: + mutex_unlock(&gpd_list_lock); + + return ret; } /** @@ -1828,16 +1862,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 = of_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 = of_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); + +out: + mutex_unlock(&gpd_list_lock); - return pm_genpd_add_subdomain(parent, subdomain); + return ret; } /** @@ -1935,9 +1981,11 @@ int genpd_dev_pm_attach(struct device *dev) return -ENOENT; } + mutex_lock(&gpd_list_lock); pd = of_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; @@ -1946,13 +1994,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", -- 2.1.4
next prev parent reply other threads:[~2016-03-04 11:23 UTC|newest] Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-03-04 11:23 [RFC PATCH 0/8] PM / Domains: Add support for removing PM domains Jon Hunter 2016-03-04 11:23 ` Jon Hunter 2016-03-04 11:23 ` [RFC PATCH 3/8] staging: board: Remove calls to of_genpd_get_from_provider() Jon Hunter 2016-03-04 11:23 ` Jon Hunter 2016-03-04 11:23 ` [RFC PATCH 4/8] PM / Domains: Don't expose generic_pm_domain structure Jon Hunter 2016-03-04 11:23 ` Jon Hunter 2016-08-05 11:55 ` Ulf Hansson 2016-08-05 11:55 ` Ulf Hansson [not found] ` <1457090634-14785-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 2016-03-04 11:23 ` [RFC PATCH 1/8] PM / Domains: Add new helper functions for device-tree Jon Hunter 2016-03-04 11:23 ` Jon Hunter 2016-06-22 11:00 ` Jon Hunter 2016-06-22 11:00 ` Jon Hunter 2016-06-22 14:58 ` Jon Hunter 2016-06-22 14:58 ` Jon Hunter 2016-06-22 15:08 ` Ulf Hansson 2016-06-22 15:08 ` Ulf Hansson 2016-06-22 15:22 ` Jon Hunter 2016-06-22 15:22 ` Jon Hunter 2016-06-22 15:36 ` Ulf Hansson 2016-06-22 15:36 ` Ulf Hansson 2016-03-04 11:23 ` [RFC PATCH 2/8] ARM: EXYNOS: Remove calls to of_genpd_get_from_provider() Jon Hunter 2016-03-04 11:23 ` Jon Hunter 2016-03-04 11:23 ` [RFC PATCH 5/8] PM / Domains: Verify the PM domain is present when adding a provider Jon Hunter 2016-03-04 11:23 ` Jon Hunter 2016-08-05 11:57 ` Ulf Hansson 2016-08-05 11:57 ` Ulf Hansson 2016-03-04 11:23 ` Jon Hunter [this message] 2016-03-04 11:23 ` [RFC PATCH 7/8] PM / Domains: Prepare for adding support to remove PM domains Jon Hunter 2016-03-04 12:33 ` [RFC PATCH 0/8] PM / Domains: Add support for removing " Ulf Hansson 2016-03-04 12:33 ` Ulf Hansson [not found] ` <CAPDyKFq3hNARzjSOoP+-NmcgfSWzG6GDmh7qVX6yx6QPgN9Arw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2016-03-28 12:38 ` Jon Hunter 2016-03-28 12:38 ` Jon Hunter [not found] ` <56F925D9.3080703-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 2016-06-06 13:19 ` Jon Hunter 2016-06-06 13:19 ` Jon Hunter 2016-06-15 14:46 ` Ulf Hansson 2016-06-15 14:46 ` Ulf Hansson 2016-03-04 11:23 ` [RFC PATCH 6/8] PM / Domains: Remove a provider by referencing the data pointer Jon Hunter 2016-03-04 11:23 ` Jon Hunter [not found] ` <1457090634-14785-7-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 2016-06-15 14:38 ` Ulf Hansson 2016-06-15 14:38 ` Ulf Hansson 2016-06-21 13:47 ` Jon Hunter 2016-06-21 13:47 ` Jon Hunter [not found] ` <5769455C.9010809-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 2016-07-11 13:14 ` Jon Hunter 2016-07-11 13:14 ` Jon Hunter 2016-08-05 11:55 ` Ulf Hansson 2016-08-05 11:55 ` Ulf Hansson [not found] ` <CAPDyKFovC07Z9y-4RQ4MKGtjJx5w1D8er3Fv-8HF2qyTKgVViQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2016-08-11 16:39 ` Jon Hunter 2016-08-11 16:39 ` Jon Hunter [not found] ` <18ad702c-83fe-fd6d-89ae-57e6f2715860-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 2016-08-12 0:24 ` Rafael J. Wysocki 2016-08-12 0:24 ` Rafael J. Wysocki 2016-06-21 14:45 ` Jon Hunter 2016-06-21 14:45 ` Jon Hunter 2016-03-04 11:23 ` [RFC PATCH 8/8] PM / Domains: Add support for removing PM domains Jon Hunter 2016-03-04 11:23 ` Jon Hunter [not found] ` <1457090634-14785-9-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> 2016-06-15 14:33 ` Ulf Hansson 2016-06-15 14:33 ` Ulf Hansson 2016-06-21 14:08 ` Jon Hunter 2016-06-21 14:08 ` Jon Hunter
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1457090634-14785-8-git-send-email-jonathanh@nvidia.com \ --to=jonathanh-ddmlm1+adcrqt0dzr+alfa@public.gmane.org \ --cc=alex.aring-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org \ --cc=k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org \ --cc=kgene-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \ --cc=khilman-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \ --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \ --cc=linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org \ --cc=thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \ --cc=ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.