From patchwork Thu Oct 12 07:09:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 115593 Delivered-To: patch@linaro.org Received: by 10.140.22.163 with SMTP id 32csp1613945qgn; Thu, 12 Oct 2017 00:10:12 -0700 (PDT) X-Received: by 10.84.202.12 with SMTP id w12mr1386293pld.358.1507792212452; Thu, 12 Oct 2017 00:10:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1507792212; cv=none; d=google.com; s=arc-20160816; b=TC9ruBSZVbNRzONUwWCwflQCR6WAxiII341iZ7WtmZK6UN0kbY7qzOPz2EvUFcMD+z qNk5y8Qs+HjeLTQRpQ6iL9kFqwX92zDVgtWvjEhjR8/Ojtirdj09V7WM2q7q3wSLVruR Yt6SLJhTZxB0iaAYjnYzyTRfrq+HvSHImRvheHD73O4NOiaXhfF06fn0PUpX5t53ECxd KIVBhfA504zjJrO3xmPcwHQTnNfFgbV1yD/48nU/QMfxqW+tLsz3OT68+OmVfprgjoF3 I3ZilyLEoSBMCgSSV3uvA4NZMqH2qs3V7Fzu3cQPe+ejANgtjnnkmJ3/zDGVtmUBN+tD Cebw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=rqjSdLqPyTQ90ICnpcRtml8yxafC/Eo1Ob8yehIOVHY=; b=ACA0FVcmAN0LXPA4ZkFo8xGo6Br+xtWyHKlIKRTD5aJ5AdHJenasVlAEqqzTaf9Dgt /N1Ux5IrlKEvP1FcAyAymClN75O6mOt/AzIluRJE8s/HqHHsfoTDQfg5ut7kN253OQIo 3lu+WyKPy/xVtCoGIl/+vt5j8xmIhDVdCKxNFQdonYoK+oxTO/+5JoEAG1PqXmUt6Z+5 PNBdCEDOtKwlYH0Z0ARaT+Ep+IAbpU/XR9cVhWODcvh+YmQV8YubzIl/GQgW0yTE9aqt vDZFSEGP75TyVUYyDws0BpunWwF86ev+nvne6s/mBPmHAxAZ5s6rjb0vCDgsaPKjJror m9Yw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=LgAH8EVv; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z186si1046507pgd.390.2017.10.12.00.10.11; Thu, 12 Oct 2017 00:10:12 -0700 (PDT) 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 header.s=google header.b=LgAH8EVv; 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 S1752353AbdJLHKJ (ORCPT + 27 others); Thu, 12 Oct 2017 03:10:09 -0400 Received: from mail-pf0-f175.google.com ([209.85.192.175]:53688 "EHLO mail-pf0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751100AbdJLHKH (ORCPT ); Thu, 12 Oct 2017 03:10:07 -0400 Received: by mail-pf0-f175.google.com with SMTP id t188so1177658pfd.10 for ; Thu, 12 Oct 2017 00:10:07 -0700 (PDT) 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; bh=rqjSdLqPyTQ90ICnpcRtml8yxafC/Eo1Ob8yehIOVHY=; b=LgAH8EVvPQ1z7fl827xKcI1lmqM9cmiWXG68OoJWWPfEbudRsYrg1uH3aq77qWSs9S QUR7aKV7KJ2BygmgSRp/fL7rJoCOEqcpXeId0uhJZRhNsWmHZNH6TcVNfeiBcMpJOoP+ NIAoBgfKPzVLDLRKm0fnghV4THZwm0twJGxWI= 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; bh=rqjSdLqPyTQ90ICnpcRtml8yxafC/Eo1Ob8yehIOVHY=; b=NGThrcMlH98lPk1ZLMSDlUU8vnPYnwgvAmEQewPV3Zvj3UWJTmT/FIAOpILzhmJ6bg Vnr6+okMUbz6TZkEfZHeOcwu4hC4/Jtk45WoCU6nSHXrMj+GFHdnF3PCBSQxBFlsJvaB kk6U9Qsq2+nteL/hN8Kg5dhxhv+wgqwEjRAOCIuW1BWM/3y/O7gWpXqsNqMl+uyiytyY EjnaLWA52XScz8zc7rDweZgAxXcvwOLi/B/onzOHjLc7RSXx2UAkBAUrlllyhqSgXEtX duOESoGra7qoL1uVQyo2Mb/w1lzQ8gwAX5ti/PQo65M2FmvZaD3PeGqQJ8pEm5lwMP4S IVqQ== X-Gm-Message-State: AMCzsaWBCsc3381kKeWJZwFhBqa2/Q5OkrMwz2z9NPyS5h32gQsTvIBX aqGY3gBKrhJng668vBfvsn+RQQ== X-Google-Smtp-Source: AOwi7QBwRjmzHp7DHvn7BgdrGzvQ6t50F6ieKIG/sFu0cAMdDBHNWG7VsB2L0uUyzrEc85caCSCv/w== X-Received: by 10.98.181.1 with SMTP id y1mr1353305pfe.240.1507792207056; Thu, 12 Oct 2017 00:10:07 -0700 (PDT) Received: from localhost ([122.172.169.205]) by smtp.gmail.com with ESMTPSA id l1sm706790pff.77.2017.10.12.00.10.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Oct 2017 00:10:06 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V12 1/7] PM / Domains: Add support to select performance-state of domains Date: Thu, 12 Oct 2017 12:39:59 +0530 Message-Id: <0ffec4c9d7679be049cab74eebacb5ca248e903e.1507786342.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.15.0.rc1.236.g92ea95045093 In-Reply-To: <431a7a5803b4a552dfe2a71700e19b904c6d16dc.1507703370.git.viresh.kumar@linaro.org> References: <431a7a5803b4a552dfe2a71700e19b904c6d16dc.1507703370.git.viresh.kumar@linaro.org> 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 PM domains. This patch enhances the genpd core to support such platforms. The performance levels (within the genpd core) are identified by positive integer values, a lower value represents lower performance state. This patch adds a new genpd API, which is called by user drivers (like OPP framework): - int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state); This updates the performance state constraint of the device on its PM domain. On success, the genpd will have its performance state set to a value which is >= "state" passed to this routine. The genpd core calls the genpd->set_performance_state() callback, if implemented, else -ENODEV is returned to the caller. The PM domain drivers need to implement the following callback if they want to support performance states. - int (*set_performance_state)(struct generic_pm_domain *genpd, unsigned int state); This is called internally by the genpd core on several occasions. The genpd core passes the genpd pointer and the aggregate of the performance states of the devices supported by that genpd to this callback. This callback must update the performance state of the genpd (in a platform dependent way). The power domains can avoid supplying above callback, if they don't support setting performance-states. Currently we aren't propagating performance state changes of a subdomain to its masters as we don't have hardware that needs it right now. Over that, the performance states of subdomain and its masters may not have one-to-one mapping and would require additional information. We can get back to this once we have hardware that needs it. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- Only the first patch has got updates (out of the first 3 patches, which are going to get applied for now) and so I am resending only the first one here. V12: - Always allow setting performance state, even if genpd is off. Don't call the callback in that case. - Set performance state only when powering ON the genpd and not during power OFF. The driver can take care of it. - Merge several routines and remove unnecessary locking. - Update comments and log a bit. drivers/base/power/domain.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 12 ++++++ 2 files changed, 101 insertions(+) -- 2.15.0.rc1.236.g92ea95045093 diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index a6e4c8d7d837..735850893882 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -237,6 +237,86 @@ static void genpd_update_accounting(struct generic_pm_domain *genpd) static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {} #endif +/** + * dev_pm_genpd_set_performance_state- Set performance state of device's power + * domain. + * + * @dev: Device for which the performance-state needs to be set. + * @state: Target performance state of the device. This can be set as 0 when the + * device doesn't have any performance state constraints left (And so + * the device wouldn't participate anymore to find the target + * performance state of the genpd). + * + * It is assumed that the users guarantee that the genpd wouldn't be detached + * while this routine is getting called. + * + * Returns 0 on success and negative error values on failures. + */ +int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) +{ + struct generic_pm_domain *genpd; + struct generic_pm_domain_data *pd_data; + struct pm_domain_data *pdd; + int ret = 0; + + genpd = dev_to_genpd(dev); + if (IS_ERR(genpd)) + return -ENODEV; + + if (!genpd->set_performance_state) + return -EINVAL; + + if (!dev->power.subsys_data || !dev->power.subsys_data->domain_data) { + WARN_ON(1); + return -EINVAL; + } + + genpd_lock(genpd); + + /* New requested state is same as Max requested state */ + if (state == genpd->performance_state) + return 0; + + /* New requested state is higher than Max requested state */ + if (state > genpd->performance_state) + goto update_state; + + /* 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; + } + + /* + * We aren't propagating performance state changes of a subdomain to its + * masters as we don't have hardware that needs it. Over that, the + * performance states of subdomain and its masters may not have + * one-to-one mapping and would require additional information. We can + * get back to this once we have hardware that needs it. For that + * reason, we don't have to consider performance state of the subdomains + * of genpd here. + */ + +update_state: + if (genpd_status_on(genpd)) { + ret = genpd->set_performance_state(genpd, state); + if (ret) + goto unlock; + } + + genpd->performance_state = state; + pd_data = to_gpd_data(dev->power.subsys_data->domain_data); + pd_data->performance_state = state; + +unlock: + genpd_unlock(genpd); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_genpd_set_performance_state); + static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) { unsigned int state_idx = genpd->state_idx; @@ -256,6 +336,15 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) return ret; elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); + + if (unlikely(genpd->performance_state)) { + ret = genpd->set_performance_state(genpd, genpd->performance_state); + if (ret) { + pr_warn("%s: Failed to set performance state %d (%d)\n", + genpd->name, genpd->performance_state, ret); + } + } + if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns) return ret; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 84f423d5633e..3f8de25418a8 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -64,8 +64,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 *genpd, + unsigned int state); struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; @@ -121,6 +124,7 @@ struct generic_pm_domain_data { struct pm_domain_data base; struct gpd_timing_data td; struct notifier_block nb; + unsigned int performance_state; void *data; }; @@ -148,6 +152,8 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, extern int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); extern int pm_genpd_remove(struct generic_pm_domain *genpd); +extern int dev_pm_genpd_set_performance_state(struct device *dev, + unsigned int state); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; @@ -188,6 +194,12 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd) return -ENOTSUPP; } +static inline int dev_pm_genpd_set_performance_state(struct device *dev, + unsigned int state) +{ + return -ENOTSUPP; +} + #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) #endif