From patchwork Mon Nov 3 03:53:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Kachhap X-Patchwork-Id: 5213641 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 864539F380 for ; Mon, 3 Nov 2014 04:01:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7618820204 for ; Mon, 3 Nov 2014 04:01:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2C70B201BB for ; Mon, 3 Nov 2014 04:01:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752357AbaKCEBS (ORCPT ); Sun, 2 Nov 2014 23:01:18 -0500 Received: from mailout3.samsung.com ([203.254.224.33]:22640 "EHLO mailout3.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752304AbaKCEBR (ORCPT ); Sun, 2 Nov 2014 23:01:17 -0500 Received: from epcpsbgr4.samsung.com (u144.gpu120.samsung.co.kr [203.254.230.144]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NEG00FYC364OMC0@mailout3.samsung.com>; Mon, 03 Nov 2014 13:01:16 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [172.20.52.126]) by epcpsbgr4.samsung.com (EPCPMTA) with SMTP id 5C.94.18167.B0EF6545; Mon, 03 Nov 2014 13:01:15 +0900 (KST) X-AuditID: cbfee690-f79ab6d0000046f7-2e-5456fe0b7f12 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id CC.59.09430.B0EF6545; Mon, 03 Nov 2014 13:01:15 +0900 (KST) Received: from chromebld-server.sisodomain.com ([107.108.73.106]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0NEG00BUJ320LR40@mmp2.samsung.com>; Mon, 03 Nov 2014 13:01:15 +0900 (KST) From: Amit Daniel Kachhap To: linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-pm@vger.kernel.org Cc: kgene.kim@samsung.com, pankaj.dubey@samsung.com, Amit Daniel Kachhap , "Rafael J. Wysocki" Subject: [PATCH 03/12] PM / Domains: Add notifier support for power domain transitions Date: Mon, 03 Nov 2014 09:23:01 +0530 Message-id: <1414986790-11940-4-git-send-email-amit.daniel@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1414986790-11940-1-git-send-email-amit.daniel@samsung.com> References: <1414986790-11940-1-git-send-email-amit.daniel@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrCLMWRmVeSWpSXmKPExsWyRsSkTpf7X1iIwZEN1hYNV0MsehdcZbPY 9Pgaq8Xn3iOMFjPO72OyWLT1C7vF4xVv2R3YPRbvecnksXlJvUffllWMHp83yQWwRHHZpKTm ZJalFunbJXBlnD0WXzDXtmLj4/vMDYxbjbsYOTkkBEwkfj/rY4SwxSQu3FvP1sXIxSEksJRR 4lDTFEaYoqmLZ7NDJKYzSsz4/ZwZwpnAJLG26RwzSBWbgLHEz5372UFsEYF0iTWLdoONYhaY wShx4u9bsFHCAhESK//8ZgKxWQRUJaY2/WUDsXkF3CXaH61g7WLkAFqnIDFnkg1ImFPAQ+Jk 33VWEFsIqGTSu+dMIDMlBPrZJf5Oa2GHmCMg8W3yIRaIXlmJTQeYIa6WlDi44gbLBEbhBYwM qxhFUwuSC4qT0otM9IoTc4tL89L1kvNzNzECA/v0v2cTdjDeO2B9iFGAg1GJh7dge1iIEGti WXFl7iFGU6ANE5mlRJPzgfGTVxJvaGxmZGFqYmpsZG5ppiTO+1rqZ7CQQHpiSWp2ampBalF8 UWlOavEhRiYOTqkGxqSvz5XmTVlp89Dzpayh3qRzB/rTb4uoaatalps84Thkv/78XrYVGV4B XNsZUv7dXW461fjtm4O35mrzrwnQP7vPde21e9/Ni0+2WXscCd858d7MCb0Lmk8GJC7ImL/4 oI/Aqzf25anXzPwZl9+0P9KzPNZLbPoyTc3okoRLE6MUe4U+vtM790mJpTgj0VCLuag4EQB4 lKQSZwIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprHIsWRmVeSWpSXmKPExsVy+t9jQV3uf2EhBi+PGFo0XA2x6F1wlc1i 0+NrrBafe48wWsw4v4/JYtHWL+wWj1e8ZXdg91i85yWTx+Yl9R59W1YxenzeJBfAEtXAaJOR mpiSWqSQmpecn5KZl26r5B0c7xxvamZgqGtoaWGupJCXmJtqq+TiE6DrlpkDdICSQlliTilQ KCCxuFhJ3w7ThNAQN10LmMYIXd+QILgeIwM0kLCGMePssfiCubYVGx/fZ25g3GrcxcjJISFg IjF18Wx2CFtM4sK99WxdjFwcQgLTGSVm/H7ODOFMYJJY23SOGaSKTcBY4ufO/WAdIgLpEmsW 7QbrYBaYwShx4u9bRpCEsECExMo/v5lAbBYBVYmpTX/ZQGxeAXeJ9kcrWLsYOYDWKUjMmWQD EuYU8JA42XedFcQWAiqZ9O450wRG3gWMDKsYRVMLkguKk9JzjfSKE3OLS/PS9ZLzczcxguPm mfQOxlUNFocYBTgYlXh4C7aHhQixJpYVV+YeYpTgYFYS4a1cCxTiTUmsrEotyo8vKs1JLT7E aAp01ERmKdHkfGBM55XEGxqbmJsam1qaWJiYWSqJ8x5stQ4UEkhPLEnNTk0tSC2C6WPi4JRq YGy5vPrezyXvmFe6Jbofbp79N7LReIYdR/O12onrmKPrfWv92X5MuCIVLOZivWhqzNSAtCfM OSURnou1dO78bZ8184rwKyW5w1ZXkifbiH/e+7pK4ssxr8L3NtK2Apza2ro35URuLi3vDDcN /pN+nrnV7tKZqp2KliuDzM5K+3+d/33TFb/pZ5VYijMSDbWYi4oTAaC3OL2xAgAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-7.5 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 These power domain transition notifiers will assist in carrying out some activity associated with domain power on/off such as some registers which may lose its contents and need save/restore across domain power off/on. 4 type of notifications are added, GPD_OFF_PRE - GPD state before power off GPD_OFF_POST - GPD state after power off GPD_ON_PRE - GPD state before power off GPD_ON_POST - GPD state after power off 3 notfication API's are exported. 1) int genpd_register_notifier(struct notifier_block *nb, char *pd_name); 2) int genpd_unregister_notifier(struct notifier_block *nb, char *pd_name); 3) void genpd_invoke_transition_notifier(struct generic_pm_domain *genpd, enum gpd_on_off_state state); In this approach the notifiers are registered/unregistered with pd name. The actual invoking of the notfiers will be done by the platform implementing power domain enable/disable low level handlers according to the above defined notification types. This approach will considerably reduce the number of call to notifiers as compared to calling always from core powerdomain subsystem. Also the registered domain's will be managed inside a cache list and not part of the genpd structure. This will help in registration of notifiers from subsystems (such as clock) even when the PD subsystem is still not initialised. This list also filters out the unregistered pd's requesting notification. Cc: Rafael J. Wysocki Reviewed-by: Pankaj Dubey Signed-off-by: Amit Daniel Kachhap --- drivers/base/power/domain.c | 112 ++++++++++++++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 31 ++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 40bc2f4..e05045e 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -46,10 +46,19 @@ __retval; \ }) +struct cache_notify_domains { + char *name; + /* Node in the cache pm domain name list */ + struct list_head cache_list_node; +}; + static LIST_HEAD(gpd_list); static DEFINE_MUTEX(gpd_list_lock); +static LIST_HEAD(domain_notify_list); +static DEFINE_MUTEX(domain_notify_list_lock); +static BLOCKING_NOTIFIER_HEAD(genpd_transition_notifier_list); -static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) +struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) { struct generic_pm_domain *genpd = NULL, *gpd; @@ -66,6 +75,7 @@ static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) mutex_unlock(&gpd_list_lock); return genpd; } +EXPORT_SYMBOL_GPL(pm_genpd_lookup_name); struct generic_pm_domain *dev_to_genpd(struct device *dev) { @@ -1908,6 +1918,106 @@ void pm_genpd_init(struct generic_pm_domain *genpd, mutex_unlock(&gpd_list_lock); } +/** + * genpd_register_notifier - Register a PM domain for future notification. + * @nb: notification block containing notification handle. + * @pd_name: PM domain name. + */ +int genpd_register_notifier(struct notifier_block *nb, char *pd_name) +{ + int ret; + struct cache_notify_domains *entry; + + if (!pd_name) + return -EINVAL; + + /* Search if the pd is already registered */ + mutex_lock(&domain_notify_list_lock); + list_for_each_entry(entry, &domain_notify_list, cache_list_node) { + if (!strcmp(entry->name, pd_name)) + break; + } + mutex_unlock(&domain_notify_list_lock); + + if (entry) { + pr_err("%s: pd already exists\n", __func__); + return -EINVAL; + } + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + entry->name = pd_name; + + mutex_lock(&domain_notify_list_lock); + list_add(&entry->cache_list_node, &domain_notify_list); + mutex_unlock(&domain_notify_list_lock); + ret = blocking_notifier_chain_register( + &genpd_transition_notifier_list, nb); + return ret; +} + +/** + * genpd_unregister_notifier - Un-register a PM domain for future notification. + * @nb: notification block containing notification handle. + * @pd_name: PM domain name. + */ +int genpd_unregister_notifier(struct notifier_block *nb, char *pd_name) +{ + int ret; + struct cache_notify_domains *entry; + + mutex_lock(&domain_notify_list_lock); + list_for_each_entry(entry, &domain_notify_list, cache_list_node) { + if (!strcmp(entry->name, pd_name)) + break; + } + if (!entry) { + mutex_unlock(&domain_notify_list_lock); + pr_err("%s: Invalid pd name\n", __func__); + return -EINVAL; + } + list_del(&entry->cache_list_node); + mutex_unlock(&domain_notify_list_lock); + ret = blocking_notifier_chain_unregister( + &genpd_transition_notifier_list, nb); + return ret; +} + +/** + * genpd_invoke_transition_notifier - Calls the matching notification handler. + * @genpd: generic power domain structure. + * @state: can be of type - GPD_OFF_PRE/GPD_OFF_POST/GPD_ON_PRE/GPD_ON_POST. + */ +void genpd_invoke_transition_notifier(struct generic_pm_domain *genpd, + enum gpd_on_off_state state) +{ + struct cache_notify_domains *entry; + + if (!genpd) { + pr_err("Invalid genpd parameter\n"); + return; + } + + if (state != GPD_OFF_PRE || state != GPD_OFF_POST + || state != GPD_ON_PRE || state != GPD_ON_POST) { + pr_err("Invalid state parameter\n"); + return; + } + + mutex_lock(&domain_notify_list_lock); + list_for_each_entry(entry, &domain_notify_list, cache_list_node) { + if (!strcmp(entry->name, genpd->name)) + break; + } + mutex_unlock(&domain_notify_list_lock); + if (!entry) /* Simply ignore */ + return; + + blocking_notifier_call_chain(&genpd_transition_notifier_list, state, + genpd); +} #ifdef CONFIG_PM_GENERIC_DOMAINS_OF /* * Device Tree based PM domain providers. diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 73e938b..659997f 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -25,6 +25,13 @@ enum gpd_status { GPD_STATE_POWER_OFF, /* PM domain is off */ }; +enum gpd_on_off_state { + GPD_OFF_PRE = 0, /* GPD state before power off */ + GPD_OFF_POST, /* GPD state after power off */ + GPD_ON_PRE, /* GPD state before power on */ + GPD_ON_POST, /* GPD state after power on */ +}; + struct dev_power_governor { bool (*power_down_ok)(struct dev_pm_domain *domain); bool (*stop_ok)(struct device *dev); @@ -148,6 +155,12 @@ extern int pm_genpd_name_poweron(const char *domain_name); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; + +struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name); +int genpd_register_notifier(struct notifier_block *nb, char *pd_name); +int genpd_unregister_notifier(struct notifier_block *nb, char *pd_name); +void genpd_invoke_transition_notifier(struct generic_pm_domain *genpd, + enum gpd_on_off_state state); #else static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) @@ -219,6 +232,24 @@ static inline int pm_genpd_name_poweron(const char *domain_name) { return -ENOSYS; } +static inline struct +generic_pm_domain *pm_genpd_lookup_name(const char *domain_name) +{ + return NULL; +} +static inline int +genpd_register_notifier(struct notifier_block *nb, char *pd_name) +{ + return 0; +} +static inline int +genpd_unregister_notifier(struct notifier_block *nb, char *pd_name) +{ + return 0; +} +static inline void +genpd_invoke_transition_notifier(struct generic_pm_domain *genpd, + enum gpd_on_off_state state) { } #define simple_qos_governor NULL #define pm_domain_always_on_gov NULL #endif