From patchwork Fri Mar 4 11:23:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Hunter X-Patchwork-Id: 8502861 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 446F2C0553 for ; Fri, 4 Mar 2016 11:24:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3B21820218 for ; Fri, 4 Mar 2016 11:24:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 14598201F2 for ; Fri, 4 Mar 2016 11:24:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751882AbcCDLYQ (ORCPT ); Fri, 4 Mar 2016 06:24:16 -0500 Received: from hqemgate15.nvidia.com ([216.228.121.64]:5870 "EHLO hqemgate15.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751247AbcCDLYP (ORCPT ); Fri, 4 Mar 2016 06:24:15 -0500 Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate15.nvidia.com id ; Fri, 04 Mar 2016 03:23:54 -0800 Received: from hqemhub02.nvidia.com ([172.20.12.94]) by hqnvupgp07.nvidia.com (PGP Universal service); Fri, 04 Mar 2016 03:23:00 -0800 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Fri, 04 Mar 2016 03:23:00 -0800 Received: from jonathanh-lm.nvidia.com (172.20.144.16) by hqemhub02.nvidia.com (172.20.150.31) with Microsoft SMTP Server (TLS) id 8.3.406.0; Fri, 4 Mar 2016 03:24:13 -0800 From: Jon Hunter To: "Rafael J. Wysocki" , Kevin Hilman , Ulf Hansson CC: Thierry Reding , Kukjin Kim , Krzysztof Kozlowski , Alexander Aring , Eric Anholt , linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-tegra@vger.kernel.org, Jon Hunter Subject: [RFC PATCH 5/8] PM / Domains: Verify the PM domain is present when adding a provider Date: Fri, 4 Mar 2016 11:23:51 +0000 Message-ID: <1457090634-14785-6-git-send-email-jonathanh@nvidia.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1457090634-14785-1-git-send-email-jonathanh@nvidia.com> References: <1457090634-14785-1-git-send-email-jonathanh@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When a PM domain provider is added, there is currently no way to tell if the PM domain is actually present in the system. Naturally, the PM domain provider should not be registered if the PM domain has not been added. Nonetheless, to verify that the PM domain associated with a provider is present, store the 'provider_data' in the PM domain structure when adding the provider and make sure that the PM domain is found the list of PM domains registered. The of_genpd_add_provider_simple() and of_genpd_add_provider_onecell() functions have been updated to store the 'provider_data' by default to avoid having to modify all the current PM domain provider implementations. By doing this, we can also verify that the provider has been removed from the list of providers before removing a PM domain. Signed-off-by: Jon Hunter --- drivers/base/power/domain.c | 74 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/pm_domain.h | 13 +++++--- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index c2ba1d6dbad3..72055fef6256 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1570,6 +1570,24 @@ static LIST_HEAD(of_genpd_providers); static DEFINE_MUTEX(of_genpd_mutex); /** + * pm_genpd_provider_present - Check if the provider's PM domain is present. + * @data: Provider data associated with the PM domain. + */ +static bool pm_genpd_provider_present(void *data) +{ + struct generic_pm_domain *gpd; + + if (!data) + return false; + + list_for_each_entry(gpd, &gpd_list, gpd_list_node) + if (gpd->provider_data == data) + return true; + + return false; +} + +/** * __of_genpd_xlate_simple() - Xlate function for direct node-domain mapping * @genpdspec: OF phandle args to map into a PM domain * @data: xlate function private data - pointer to struct generic_pm_domain @@ -1625,9 +1643,15 @@ EXPORT_SYMBOL_GPL(__of_genpd_xlate_onecell); * @np: Device node pointer associated with the PM domain provider. * @xlate: Callback for decoding PM domain from phandle arguments. * @data: Context pointer for @xlate callback. + * + * The PM domain assocaited with the provider must have the + * 'provider_data' member of the PM domain structure populated with the + * same data pointer passed to this function. This is used to verify + * that the PM domain associated with the provider is present in the + * list of registered PM domains. */ -int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, - void *data) +static int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, + void *data) { struct of_genpd_provider *cp; @@ -1635,6 +1659,13 @@ int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, if (!cp) return -ENOMEM; + mutex_lock(&gpd_list_lock); + + if (!pm_genpd_provider_present(data)) { + mutex_unlock(&gpd_list_lock); + return -EINVAL; + } + cp->node = of_node_get(np); cp->data = data; cp->xlate = xlate; @@ -1642,11 +1673,48 @@ int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, mutex_lock(&of_genpd_mutex); list_add(&cp->link, &of_genpd_providers); mutex_unlock(&of_genpd_mutex); + mutex_unlock(&gpd_list_lock); pr_debug("Added domain provider from %s\n", np->full_name); return 0; } -EXPORT_SYMBOL_GPL(__of_genpd_add_provider); + +/** + * of_genpd_add_provider_simple() - Register a simple PM domain provider + * @np: Device node pointer associated with the PM domain provider. + * @genpd: Pointer to PM domain associated with the PM domain provider. + */ +int of_genpd_add_provider_simple(struct device_node *np, + struct generic_pm_domain *genpd) +{ + if (!np || !genpd) + return -EINVAL; + + genpd->provider_data = genpd; + + return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd); +} +EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple); + +/** + * of_genpd_add_provider_onecell() - Register a onecell PM domain provider + * @np: Device node pointer associated with the PM domain provider. + * @data: Pointer to the data associated with the PM domain provider. + */ +int of_genpd_add_provider_onecell(struct device_node *np, + struct genpd_onecell_data *data) +{ + unsigned int i; + + if (!np || !data) + return -EINVAL; + + for (i = 0; i < data->num_domains; i++) + data->domains[i]->provider_data = data; + + return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data); +} +EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell); /** * of_genpd_del_provider() - Remove a previously registered PM domain provider diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 510512d5390e..bed84413546f 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -53,6 +53,7 @@ struct generic_pm_domain { struct mutex lock; struct dev_power_governor *gov; struct work_struct power_off_work; + void *provider_data; const char *name; atomic_t sd_count; /* Number of subdomains with power "on" */ enum gpd_status status; /* Current state of the domain */ @@ -193,8 +194,10 @@ typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args, void *data); #ifdef CONFIG_PM_GENERIC_DOMAINS_OF -int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, - void *data); +int of_genpd_add_provider_simple(struct device_node *np, + struct generic_pm_domain *genpd); +int of_genpd_add_provider_onecell(struct device_node *np, + struct genpd_onecell_data *data); void of_genpd_del_provider(struct device_node *np); struct generic_pm_domain *__of_genpd_xlate_simple( struct of_phandle_args *genpdspec, @@ -235,18 +238,18 @@ static inline int genpd_dev_pm_attach(struct device *dev) { return -ENODEV; } -#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ static inline int of_genpd_add_provider_simple(struct device_node *np, struct generic_pm_domain *genpd) { - return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd); + return -ENOTSUPP; } static inline int of_genpd_add_provider_onecell(struct device_node *np, struct genpd_onecell_data *data) { - return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data); + return -ENOTSUPP; } +#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ #ifdef CONFIG_PM extern int dev_pm_domain_attach(struct device *dev, bool power_on);