From patchwork Fri Feb 24 09:06:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 94425 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp601542qgi; Fri, 24 Feb 2017 01:14:44 -0800 (PST) X-Received: by 10.99.43.74 with SMTP id r71mr2171950pgr.83.1487927684643; Fri, 24 Feb 2017 01:14:44 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s5si6813245pgg.177.2017.02.24.01.14.44; Fri, 24 Feb 2017 01:14:44 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751542AbdBXJOl (ORCPT + 25 others); Fri, 24 Feb 2017 04:14:41 -0500 Received: from mail-pg0-f42.google.com ([74.125.83.42]:35832 "EHLO mail-pg0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751334AbdBXJO0 (ORCPT ); Fri, 24 Feb 2017 04:14:26 -0500 Received: by mail-pg0-f42.google.com with SMTP id b129so9352337pgc.2 for ; Fri, 24 Feb 2017 01:14:25 -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:in-reply-to:references :in-reply-to:references; bh=TAT89OO4uHxMyC3t7s8a0b5jBfH6XCxZ6sJZGfpOOEI=; b=JrzcPQb6Y/+twD58d4xhPpqlhsmmdhyBh9WjX+8gwaKYInmGjXf5RHnCC3ZPrAXgAN X340hQ7SbDsijf4GVima9To7jFkgr62SJ9tgQywgcdBepJzLb5ZVY0N073JDiwr1AY74 kvYvCQ8fX+l274Xuax1/Hs2iSzOfll0Pce3uA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=TAT89OO4uHxMyC3t7s8a0b5jBfH6XCxZ6sJZGfpOOEI=; b=qt8uknYeyJgA0sQ8LNzW3teEwXHgDp8KvvhcT0Ww7x/Z1t8w9q4SLYuwlyPdkOiqO5 eWUvGhldS/n1UREMAb97GgsJdnfTim57TSDBU9+urOMGyjvg4FfvJywPt1IM0woAzUBJ H7cySdCLjW7/HXZYVj1ePMmM4MtNdEfodXDzPOK4NnxgIdUTy82AbrcYAHoGvXLYjaB6 o1TVEZ5cwaSsPlAQ9sJPZQhoEBgJ1MIu9I16YltPtLHsBbFSouyO/1IHLsTUFSJc3h09 MAx71dRw4LICXQ9x/s/5bCSl2vs5Jc0XrRAjQ+DxYro69r19+3tqg9qPghzRnPdyyPQ4 P4iw== X-Gm-Message-State: AMke39mCD8YeMDk5JuD6cFwsORhuDd95yS3TlSmmA9u5jvGm02jIOrcgiEfAzu4ieUXrX6Fy X-Received: by 10.84.136.75 with SMTP id 69mr2425379plk.172.1487927221513; Fri, 24 Feb 2017 01:07:01 -0800 (PST) Received: from localhost ([122.172.165.189]) by smtp.gmail.com with ESMTPSA id y187sm13873589pfy.123.2017.02.24.01.07.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 24 Feb 2017 01:07:01 -0800 (PST) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman , Kevin Hilman , Len Brown , Pavel Machek Cc: linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Stephen Boyd , Nishanth Menon , Vincent Guittot , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, Viresh Kumar Subject: [PATCH V3 5/7] PM / domain: Register for PM QOS performance notifier Date: Fri, 24 Feb 2017 14:36:37 +0530 Message-Id: <4c694a1dbef6184b5ad3cfdc038fe826f6a0c972.1487926924.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.7.1.410.g6faf27b In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some platforms have the capability to configure the performance state of their Power Domains. The performance levels are identified by positive integer values, a lower value represents lower performance state. The power domain driver should be able to retrieve all information required to configure the performance state of the power domain, with the help of the performance constraint's target value. This patch implements performance state management in PM domain core. The performance QOS uses the common QOS notifier list and we call __performance_notifier() if the notifier is issued for performance constraint. This also allows the power domain drivers to implement a ->set_performance_state() callback, which will be called by the power domain core from within the notifier routine. If a domain doesn't implement ->set_performance_state() callback, then it is assumed that its parents are responsible for performance state configuration. Both devices and sub-domains are accounted for while finding the highest performance state requested. Signed-off-by: Viresh Kumar Tested-by: Rajendra Nayak --- drivers/base/power/domain.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 4 +++ 2 files changed, 81 insertions(+) -- 2.7.1.410.g6faf27b diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 303490ab5ffd..202effbebfd1 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -452,6 +452,79 @@ static int __resume_latency_notifier(struct generic_pm_domain_data *gpd_data, return NOTIFY_DONE; } +static void __update_domain_performance_state(struct generic_pm_domain *genpd, + int depth) +{ + struct generic_pm_domain_data *pd_data; + struct generic_pm_domain *subdomain; + struct pm_domain_data *pdd; + unsigned int state = 0; + struct gpd_link *link; + + /* Traverse all devices within the domain */ + list_for_each_entry(pdd, &genpd->dev_list, list_node) { + pd_data = to_gpd_data(pdd); + + if (pd_data->performance_state > state) + state = pd_data->performance_state; + } + + /* Traverse all subdomains within the domain */ + list_for_each_entry(link, &genpd->master_links, master_node) { + subdomain = link->slave; + + if (subdomain->performance_state > state) + state = subdomain->performance_state; + } + + if (genpd->performance_state == state) + return; + + genpd->performance_state = state; + + if (genpd->set_performance_state) { + genpd->set_performance_state(genpd, state); + return; + } + + /* Propagate to parent power domains */ + list_for_each_entry(link, &genpd->slave_links, slave_node) { + struct generic_pm_domain *master = link->master; + + genpd_lock_nested(master, depth + 1); + __update_domain_performance_state(master, depth + 1); + genpd_unlock(master); + } +} + +static int __performance_notifier(struct generic_pm_domain_data *gpd_data, + unsigned long val) +{ + struct generic_pm_domain *genpd = ERR_PTR(-ENODATA); + struct device *dev = gpd_data->base.dev; + struct pm_domain_data *pdd; + + spin_lock_irq(&dev->power.lock); + + pdd = dev->power.subsys_data ? + dev->power.subsys_data->domain_data : NULL; + + if (pdd && pdd->dev) + genpd = dev_to_genpd(dev); + + spin_unlock_irq(&dev->power.lock); + + if (IS_ERR(genpd)) + return NOTIFY_DONE; + + genpd_lock(genpd); + gpd_data->performance_state = val; + __update_domain_performance_state(genpd, 0); + genpd_unlock(genpd); + + return NOTIFY_DONE; +} + static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, unsigned long val, void *ptr) { @@ -464,6 +537,9 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, if (dev_pm_qos_notifier_is_resume_latency(dev, ptr)) return __resume_latency_notifier(gpd_data, val); + if (dev_pm_qos_notifier_is_performance(dev, ptr)) + return __performance_notifier(gpd_data, val); + dev_err(dev, "%s: Unexpected notifier call\n", __func__); return NOTIFY_BAD; } @@ -1157,6 +1233,7 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev, gpd_data->td.constraint_changed = true; gpd_data->td.effective_constraint_ns = -1; gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier; + gpd_data->performance_state = 0; spin_lock_irq(&dev->power.lock); diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 5339ed5bd6f9..83795935709e 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -62,8 +62,11 @@ struct generic_pm_domain { unsigned int device_count; /* Number of devices */ unsigned int suspended_count; /* System suspend device counter */ unsigned int prepared_count; /* Suspend counter of prepared devices */ + unsigned int performance_state; /* Max requested performance state */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); + int (*set_performance_state)(struct generic_pm_domain *domain, + unsigned int state); struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; @@ -117,6 +120,7 @@ struct generic_pm_domain_data { struct pm_domain_data base; struct gpd_timing_data td; struct notifier_block nb; + unsigned int performance_state; }; #ifdef CONFIG_PM_GENERIC_DOMAINS