From patchwork Fri Mar 3 20:41:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 94865 Delivered-To: patch@linaro.org Received: by 10.140.82.71 with SMTP id g65csp418925qgd; Fri, 3 Mar 2017 12:49:44 -0800 (PST) X-Received: by 10.99.116.10 with SMTP id p10mr5664570pgc.74.1488574184660; Fri, 03 Mar 2017 12:49:44 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h9si3038974pli.285.2017.03.03.12.49.44; Fri, 03 Mar 2017 12:49:44 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S1752037AbdCCUtm (ORCPT + 13 others); Fri, 3 Mar 2017 15:49:42 -0500 Received: from mail-pg0-f42.google.com ([74.125.83.42]:34253 "EHLO mail-pg0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752164AbdCCUtl (ORCPT ); Fri, 3 Mar 2017 15:49:41 -0500 Received: by mail-pg0-f42.google.com with SMTP id 77so3255564pgc.1 for ; Fri, 03 Mar 2017 12:49:27 -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; bh=wa/AkZodlw/5x5kUfVBybMrR9/1CH75Z7UE6wJkpsgY=; b=B6b5bt3VedG3d92Ivz7mgvljALBKQZP9tvXkQg0CE/kxLeSmdFVYzbnmDOioT4bAYM mkcwVKSsgzstoSVEZ5/zvSCe9EZhJDF6JQbh9EP3IGvqQ+nFuwF/VTaWMvkOM0AKHgbm SJgKDkUvuVQ5UxPhzKxuNctB4wFuj5yk+N+9A= 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=wa/AkZodlw/5x5kUfVBybMrR9/1CH75Z7UE6wJkpsgY=; b=UYRegkH/fvpSCsfJOs2zIgc2SVovPQhVdMxQ5dvm3oCEJjteAowuhUHFW9fujyeum/ i9Esu4ic7oZnyTXanVVCoHng5BxmzMWP2stP2JQ8seJi0d5/CndGVv+Vz/8Bh+xIrTj+ vPjHBJVl846gTsxah0OnKss3OFOotYVX4fLpXHIB9ha8PwfovOmf3ti0wk3vXnpXyZT5 CCeyIZ+nXBuJNf7CEQcz8WnXdibuElzt4KbdBuy8jNA/z840JA6AIoL19vm+UU81z3pd TAwe0Xv5k6OegRgst5rV6cLX/6rdRvfK2rTFT/K6KiIA/rbw6oTFsHl2YAROBfqfG0I4 vsnQ== X-Gm-Message-State: AMke39m6UsRX8sfRfQU0lZ64CXiUJtuYPUrSLPAGhoyJCxvxmZar0jUt8wujHR9WXShWJd7y X-Received: by 10.84.202.194 with SMTP id q2mr7048921plh.108.1488573707532; Fri, 03 Mar 2017 12:41:47 -0800 (PST) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id o189sm25207003pga.12.2017.03.03.12.41.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 03 Mar 2017 12:41:46 -0800 (PST) From: Lina Iyer To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, brendan.jackman@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, Juri.Lelli@arm.com, Lina Iyer Subject: [PATCH V5 3/9] kernel/cpu_pm: Add runtime PM support for CPUs Date: Fri, 3 Mar 2017 12:41:29 -0800 Message-Id: <1488573695-106680-4-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> References: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Notify runtime PM when the CPU is going to be powered off in the idle state. This allows for runtime PM suspend/resume of the CPU as well as its PM domain. Cc: Kevin Hilman Cc: Rafael J. Wysocki Signed-off-by: Lina Iyer --- include/linux/cpuhotplug.h | 1 + kernel/cpu_pm.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) -- 2.7.4 diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 921acaa..448226a 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -79,6 +79,7 @@ enum cpuhp_state { CPUHP_AP_OFFLINE, CPUHP_AP_SCHED_STARTING, CPUHP_AP_RCUTREE_DYING, + CPUHP_AP_CPU_PM_STARTING, CPUHP_AP_IRQ_GIC_STARTING, CPUHP_AP_IRQ_HIP04_STARTING, CPUHP_AP_IRQ_ARMADA_XP_STARTING, diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c index 009cc9a..db95ef3 100644 --- a/kernel/cpu_pm.c +++ b/kernel/cpu_pm.c @@ -16,9 +16,12 @@ */ #include +#include +#include #include #include #include +#include #include #include @@ -99,6 +102,7 @@ int cpu_pm_enter(void) { int nr_calls; int ret = 0; + struct device *dev = get_cpu_device(smp_processor_id()); read_lock(&cpu_pm_notifier_lock); ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls); @@ -110,6 +114,10 @@ int cpu_pm_enter(void) cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL); read_unlock(&cpu_pm_notifier_lock); + /* Notify Runtime PM that we are suspending the CPU */ + if (!ret && dev) + RCU_NONIDLE(pm_runtime_put_sync_suspend(dev)); + return ret; } EXPORT_SYMBOL_GPL(cpu_pm_enter); @@ -129,6 +137,11 @@ EXPORT_SYMBOL_GPL(cpu_pm_enter); int cpu_pm_exit(void) { int ret; + struct device *dev = get_cpu_device(smp_processor_id()); + + /* Notify Runtime PM that we are resuming the CPU */ + if (dev) + RCU_NONIDLE(pm_runtime_get_sync(dev)); read_lock(&cpu_pm_notifier_lock); ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL); @@ -200,6 +213,40 @@ int cpu_cluster_pm_exit(void) } EXPORT_SYMBOL_GPL(cpu_cluster_pm_exit); +#ifdef CONFIG_HOTPLUG_CPU +static int cpu_pm_cpu_dying(unsigned int cpu) +{ + struct device *dev = get_cpu_device(cpu); + + if (dev) + pm_runtime_put_sync_suspend(dev); + + return 0; +} + +static int cpu_pm_cpu_starting(unsigned int cpu) +{ + struct device *dev = get_cpu_device(cpu); + + if (dev) + pm_runtime_get_sync(dev); + + return 0; +} + +static int __init cpu_pm_hotplug_init(void) +{ + int ret; + + ret = cpuhp_setup_state(CPUHP_AP_CPU_PM_STARTING, + "AP_CPU_PM_STARTING", + cpu_pm_cpu_starting, cpu_pm_cpu_dying); + + return ret; +} +device_initcall(cpu_pm_hotplug_init); +#endif + #ifdef CONFIG_PM static int cpu_pm_suspend(void) { From patchwork Fri Mar 3 20:41:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 94866 Delivered-To: patch@linaro.org Received: by 10.140.82.71 with SMTP id g65csp418931qgd; Fri, 3 Mar 2017 12:49:45 -0800 (PST) X-Received: by 10.84.224.133 with SMTP id s5mr6807333plj.93.1488574185309; Fri, 03 Mar 2017 12:49:45 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h9si3038974pli.285.2017.03.03.12.49.45; Fri, 03 Mar 2017 12:49:45 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S1752027AbdCCUtn (ORCPT + 13 others); Fri, 3 Mar 2017 15:49:43 -0500 Received: from mail-pf0-f176.google.com ([209.85.192.176]:35026 "EHLO mail-pf0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752178AbdCCUtl (ORCPT ); Fri, 3 Mar 2017 15:49:41 -0500 Received: by mail-pf0-f176.google.com with SMTP id j5so36721522pfb.2 for ; Fri, 03 Mar 2017 12:49:35 -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; bh=2lAJHhHbBud0/8z3g7/p/jQ0kIxeqjIfVAKhfkMvpTo=; b=dO0gxOJjz3LG8uxTV3kcHQoFmL2YiI2+5OEKCRb1JsHkTXpBqGvinqlMxqN4zSJKZx ZqOB9mH/IkJFTdO4pP2hG3PefGgnwqvvQFvVJCi3qfs6iT8zJy6Ez30/rQHwAquj/kk6 3qPL7doH4HtyWNysC0ibyTCrjcX3Tx9claZZc= 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=2lAJHhHbBud0/8z3g7/p/jQ0kIxeqjIfVAKhfkMvpTo=; b=ot1fJsemWXW0ZbcjEzE9I0CuPBWe1D0xLT4WHFj3wHOfMyyCOfGMccZp+d/JEjrTwc dHXX2oeKEMf9GvHG4v+E+ad+SWqHwMZ4VWgtPyafuSoQnTT1zr8TUiaVs8vUugyVgE/m cO1E8l2p59D0xu5LEuW/oGgPEkKzFHZKOGGg0A1a6WjdZa+LJK1uaEaT6WDz6dRlUlCw /StmDm/ZPlwzPOrA46LDLKosQoCldvp2paThWbdXpE3/fvISbHHStwQnO21/w9oyQUCL L66Nf/XfYz8QDuUWH98M//3ZSlmfqUQaD3AFbUFMsyZF7Am6XsJgOTqh4ajKxZ9jMrtG IjdQ== X-Gm-Message-State: AMke39mdMW/Bc8mL+62bJK6nsdJelVoMcqn5xdUpvm1SGaAr3lLSyHW5PN5xwB3G+LF82WUc X-Received: by 10.84.238.199 with SMTP id l7mr6977602pln.90.1488573710048; Fri, 03 Mar 2017 12:41:50 -0800 (PST) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id o189sm25207003pga.12.2017.03.03.12.41.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 03 Mar 2017 12:41:49 -0800 (PST) From: Lina Iyer To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, brendan.jackman@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, Juri.Lelli@arm.com, Lina Iyer Subject: [PATCH V5 4/9] PM / cpu_domains: Setup PM domains for CPUs/clusters Date: Fri, 3 Mar 2017 12:41:30 -0800 Message-Id: <1488573695-106680-5-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> References: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Define and add Generic PM domains (genpd) for CPU clusters. Many new SoCs group CPUs as clusters. Clusters share common resources like power rails, caches, VFP, Coresight etc. When all CPUs in the cluster are idle, these shared resources may also be put in their idle state. CPUs may be associated with their domain providers. The domains in turn may be associated with their providers. This is clean way to model the cluster hierarchy like that of ARM's big.little architecture. Platform drivers may initialize generic PM domains and setup the CPU PM domains for the genpd and attach CPUs to the domain. In the following patches, the CPUs are hooked up to runtime PM framework which helps power down the domain, when all the CPUs in the domain are idle. Cc: Ulf Hansson Suggested-by: Kevin Hilman Signed-off-by: Lina Iyer --- drivers/base/power/Makefile | 2 +- drivers/base/power/cpu_domains.c | 192 +++++++++++++++++++++++++++++++++++++++ include/linux/cpu_domains.h | 48 ++++++++++ 3 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 drivers/base/power/cpu_domains.c create mode 100644 include/linux/cpu_domains.h -- 2.7.4 diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 5998c53..ee383f1 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o runtime.o wakeirq.o obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_OPP) += opp/ -obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o +obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o domain_governor.o cpu_domains.o obj-$(CONFIG_HAVE_CLK) += clock_ops.o ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG diff --git a/drivers/base/power/cpu_domains.c b/drivers/base/power/cpu_domains.c new file mode 100644 index 0000000..04891dc --- /dev/null +++ b/drivers/base/power/cpu_domains.c @@ -0,0 +1,192 @@ +/* + * drivers/base/power/cpu_domains.c - Helper functions to create CPU PM domains. + * + * Copyright (C) 2016 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPU_PD_NAME_MAX 36 + +struct cpu_pm_domain { + struct list_head link; + struct cpu_pd_ops ops; + struct generic_pm_domain *genpd; + struct cpu_pm_domain *parent; + cpumask_var_t cpus; +}; + +/* List of CPU PM domains we care about */ +static LIST_HEAD(of_cpu_pd_list); +static DEFINE_MUTEX(cpu_pd_list_lock); + +static inline struct cpu_pm_domain *to_cpu_pd(struct generic_pm_domain *d) +{ + struct cpu_pm_domain *pd; + struct cpu_pm_domain *res = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(pd, &of_cpu_pd_list, link) + if (pd->genpd == d) { + res = pd; + break; + } + rcu_read_unlock(); + + return res; +} + +static int cpu_pd_power_on(struct generic_pm_domain *genpd) +{ + struct cpu_pm_domain *pd = to_cpu_pd(genpd); + + return pd->ops.power_on ? pd->ops.power_on() : 0; +} + +static int cpu_pd_power_off(struct generic_pm_domain *genpd) +{ + struct cpu_pm_domain *pd = to_cpu_pd(genpd); + + return pd->ops.power_off ? pd->ops.power_off(genpd->state_idx, + genpd->states[genpd->state_idx].param, + pd->cpus) : 0; +} + +/** + * cpu_pd_attach_domain: Attach a child CPU PM to its parent + * + * @parent: The parent generic PM domain + * @child: The child generic PM domain + * + * Generally, the child PM domain is the one to which CPUs are attached. + */ +int cpu_pd_attach_domain(struct generic_pm_domain *parent, + struct generic_pm_domain *child) +{ + struct cpu_pm_domain *cpu_pd, *parent_cpu_pd; + int ret; + + ret = pm_genpd_add_subdomain(parent, child); + if (ret) { + pr_err("%s: Unable to add sub-domain (%s) to %s.\n err=%d", + __func__, child->name, parent->name, ret); + return ret; + } + + cpu_pd = to_cpu_pd(child); + parent_cpu_pd = to_cpu_pd(parent); + + if (cpu_pd && parent_cpu_pd) + cpu_pd->parent = parent_cpu_pd; + + return ret; +} +EXPORT_SYMBOL(cpu_pd_attach_domain); + +/** + * cpu_pd_attach_cpu: Attach a CPU to its CPU PM domain. + * + * @genpd: The parent generic PM domain + * @cpu: The CPU number + */ +int cpu_pd_attach_cpu(struct generic_pm_domain *genpd, int cpu) +{ + int ret; + struct device *cpu_dev; + struct cpu_pm_domain *cpu_pd = to_cpu_pd(genpd); + + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) { + pr_warn("%s: Unable to get device for CPU%d\n", + __func__, cpu); + return -ENODEV; + } + + ret = genpd_dev_pm_attach(cpu_dev); + if (ret) + dev_warn(cpu_dev, + "%s: Unable to attach to power-domain: %d\n", + __func__, ret); + else + dev_dbg(cpu_dev, "Attached to domain\n"); + + while (!ret && cpu_pd) { + cpumask_set_cpu(cpu, cpu_pd->cpus); + cpu_pd = cpu_pd->parent; + }; + + return ret; +} +EXPORT_SYMBOL(cpu_pd_attach_cpu); + +/** + * cpu_pd_init: Initialize a CPU PM domain for a genpd + * + * @genpd: The initialized generic PM domain object. + * @ops: The power_on/power_off ops for the domain controller. + * + * Initialize a CPU PM domain based on a generic PM domain. The platform driver + * is expected to setup the genpd object and the states associated with the + * generic PM domain, before calling this function. + */ +int cpu_pd_init(struct generic_pm_domain *genpd, const struct cpu_pd_ops *ops) +{ + int ret = -ENOMEM; + struct cpu_pm_domain *pd; + + if (IS_ERR_OR_NULL(genpd)) + return -EINVAL; + + pd = kzalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) + goto fail; + + if (!zalloc_cpumask_var(&pd->cpus, GFP_KERNEL)) + goto fail; + + genpd->power_off = cpu_pd_power_off; + genpd->power_on = cpu_pd_power_on; + genpd->flags |= GENPD_FLAG_IRQ_SAFE; + pd->genpd = genpd; + if (ops) { + pd->ops.power_on = ops->power_on; + pd->ops.power_off = ops->power_off; + } + + INIT_LIST_HEAD_RCU(&pd->link); + mutex_lock(&cpu_pd_list_lock); + list_add_rcu(&pd->link, &of_cpu_pd_list); + mutex_unlock(&cpu_pd_list_lock); + + ret = pm_genpd_init(genpd, &simple_qos_governor, false); + if (ret) { + pr_err("Unable to initialize domain %s\n", genpd->name); + goto fail; + } + + pr_debug("adding %s as CPU PM domain\n", pd->genpd->name); + + return 0; +fail: + kfree(genpd->name); + kfree(genpd); + if (pd) + kfree(pd->cpus); + kfree(pd); + return ret; +} +EXPORT_SYMBOL(cpu_pd_init); diff --git a/include/linux/cpu_domains.h b/include/linux/cpu_domains.h new file mode 100644 index 0000000..7e71291 --- /dev/null +++ b/include/linux/cpu_domains.h @@ -0,0 +1,48 @@ +/* + * include/linux/cpu_domains.h + * + * Copyright (C) 2016 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __CPU_DOMAINS_H__ +#define __CPU_DOMAINS_H__ + +#include + +struct generic_pm_domain; +struct cpumask; + +struct cpu_pd_ops { + int (*power_off)(u32 state_idx, u32 param, const struct cpumask *mask); + int (*power_on)(void); +}; + +#ifdef CONFIG_PM_GENERIC_DOMAINS + +int cpu_pd_init(struct generic_pm_domain *genpd, const struct cpu_pd_ops *ops); + +int cpu_pd_attach_domain(struct generic_pm_domain *parent, + struct generic_pm_domain *child); + +int cpu_pd_attach_cpu(struct generic_pm_domain *genpd, int cpu); + +#else + +static inline int cpu_pd_init(struct generic_pm_domain *genpd, + const struct cpu_pd_ops *ops) +{ return ERR_PTR(-ENODEV); } + +static inline int cpu_pd_attach_domain(struct generic_pm_domain *parent, + struct generic_pm_domain *child) +{ return -ENODEV; } + +static inline int cpu_pd_attach_cpu(struct generic_pm_domain *genpd, int cpu) +{ return -ENODEV; } + +#endif /* CONFIG_PM_GENERIC_DOMAINS */ + +#endif /* __CPU_DOMAINS_H__ */ From patchwork Fri Mar 3 20:41:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 94860 Delivered-To: patch@linaro.org Received: by 10.140.82.71 with SMTP id g65csp416525qgd; Fri, 3 Mar 2017 12:43:00 -0800 (PST) X-Received: by 10.99.96.9 with SMTP id u9mr304969pgb.159.1488573780724; Fri, 03 Mar 2017 12:43:00 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m63si11582781pld.36.2017.03.03.12.43.00; Fri, 03 Mar 2017 12:43:00 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S1752037AbdCCUm5 (ORCPT + 13 others); Fri, 3 Mar 2017 15:42:57 -0500 Received: from mail-pf0-f169.google.com ([209.85.192.169]:36622 "EHLO mail-pf0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751970AbdCCUmy (ORCPT ); Fri, 3 Mar 2017 15:42:54 -0500 Received: by mail-pf0-f169.google.com with SMTP id x66so36636758pfb.3 for ; Fri, 03 Mar 2017 12:41:55 -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; bh=jKzRI7p0gKRTrygEsSKqQzrAjclxQir+aIOxjyGIgaQ=; b=WsfFeV6YrIHLC5IUaW56JFNWqR1zdMl+qay+JaHY8l6cxqm7LcAl2en6FqKIJkZnn7 cGJbuMlYTkPmLtxeOqWu+bcsIqo+MQWMVIszHl12jSt8MqLi1l4YqS8B3bOAdKwk2Ybi DP+7G9rVJ2jcAvNmk0viGKoo7UbgMDQi4v+zA= 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=jKzRI7p0gKRTrygEsSKqQzrAjclxQir+aIOxjyGIgaQ=; b=TjCYJWQxCKFWnunE746gmp3vqNJDhs+JmDCOTomA9FwM1XH+OVb0JISnY0DgEMO4tG oMFNiFwJWs9bzhfZEzCo0dVF/KQfiOeLzjHjilQsV4dU1BXDAkIDTHfUeFANYdSIN54k SLrhdpfW6AE/nC4DV4hrcB0FtvYqyALIGIcGhRDdrFYvmZwKLIka9SUPzLufoEC+kOhX s4+vxc86wd96sZAv+YcpwZ9+QxS1kUiMpM/TLc85YoSrkPEBOVcS24ZmX76vLdeqEkJ6 COmlFfD4rHfqdC9QcLnSq30CxDU8HpHkKMNDm+IUv8i0gc+79gKFs/LBF8/Di6ew+N/X cV0A== X-Gm-Message-State: AMke39n8x60VPUBUGEPuDJaEBncU/eKc7MkIkPd/Lu/eB5QmRW90XegeKXV+/F5knuh9Ky75 X-Received: by 10.98.204.25 with SMTP id a25mr5736203pfg.6.1488573714565; Fri, 03 Mar 2017 12:41:54 -0800 (PST) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id o189sm25207003pga.12.2017.03.03.12.41.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 03 Mar 2017 12:41:53 -0800 (PST) From: Lina Iyer To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, brendan.jackman@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, Juri.Lelli@arm.com, Lina Iyer Subject: [PATCH V5 6/9] PM / cpu_domains: Add PM Domain governor for CPUs Date: Fri, 3 Mar 2017 12:41:32 -0800 Message-Id: <1488573695-106680-7-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> References: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org A PM domain comprising of CPUs may be powered off when all the CPUs in the domain are powered down. Powering down a CPU domain is generally a expensive operation and therefore the power performance trade offs should be considered. The time between the last CPU powering down and the first CPU powering up in a domain, is the time available for the domain to sleep. Ideally, the sleep time of the domain should fulfill the residency requirement of the domains' idle state. To do this effectively, read the time before the wakeup of the cluster's CPUs and ensure that the domain's idle state sleep time guarantees the QoS requirements of each of the CPU, the PM QoS CPU_DMA_LATENCY and the state's residency. Signed-off-by: Lina Iyer --- drivers/base/power/cpu_domains.c | 80 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) -- 2.7.4 diff --git a/drivers/base/power/cpu_domains.c b/drivers/base/power/cpu_domains.c index 04891dc..4f2a40e 100644 --- a/drivers/base/power/cpu_domains.c +++ b/drivers/base/power/cpu_domains.c @@ -16,9 +16,12 @@ #include #include #include +#include +#include #include #include #include +#include #define CPU_PD_NAME_MAX 36 @@ -50,6 +53,81 @@ static inline struct cpu_pm_domain *to_cpu_pd(struct generic_pm_domain *d) return res; } +static bool cpu_pd_down_ok(struct dev_pm_domain *pd) +{ + struct generic_pm_domain *genpd = pd_to_genpd(pd); + struct cpu_pm_domain *cpu_pd = to_cpu_pd(genpd); + int qos_ns = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); + u64 sleep_ns; + ktime_t earliest, next_wakeup; + int cpu; + int i; + + /* Reset the last set genpd state, default to index 0 */ + genpd->state_idx = 0; + + /* We don't want to power down, if QoS is 0 */ + if (!qos_ns) + return false; + + /* + * Find the sleep time for the cluster. + * The time between now and the first wake up of any CPU that + * are in this domain hierarchy is the time available for the + * domain to be idle. + * + * We only care about the next wakeup for any online CPU in that + * cluster. Hotplug off any of the CPUs that we care about will + * wait on the genpd lock, until we are done. Any other CPU hotplug + * is not of consequence to our sleep time. + */ + earliest = ktime_set(KTIME_SEC_MAX, 0); + for_each_cpu_and(cpu, cpu_pd->cpus, cpu_online_mask) { + next_wakeup = tick_nohz_get_next_wakeup(cpu); + if (earliest > next_wakeup) + earliest = next_wakeup; + } + + sleep_ns = ktime_to_ns(ktime_sub(earliest, ktime_get())); + if (sleep_ns <= 0) + return false; + + /* + * Find the deepest sleep state that satisfies the residency + * requirement and the QoS constraint + */ + for (i = genpd->state_count - 1; i >= 0; i--) { + u64 state_sleep_ns; + + state_sleep_ns = genpd->states[i].power_off_latency_ns + + genpd->states[i].power_on_latency_ns + + genpd->states[i].residency_ns; + + /* + * If we can't sleep to save power in the state, move on + * to the next lower idle state. + */ + if (state_sleep_ns > sleep_ns) + continue; + + /* + * We also don't want to sleep more than we should to + * gaurantee QoS. + */ + if (state_sleep_ns < (qos_ns * NSEC_PER_USEC)) + break; + } + + if (i >= 0) + genpd->state_idx = i; + + return (i >= 0); +} + +static struct dev_power_governor cpu_pd_gov = { + .power_down_ok = cpu_pd_down_ok, +}; + static int cpu_pd_power_on(struct generic_pm_domain *genpd) { struct cpu_pm_domain *pd = to_cpu_pd(genpd); @@ -172,7 +250,7 @@ int cpu_pd_init(struct generic_pm_domain *genpd, const struct cpu_pd_ops *ops) list_add_rcu(&pd->link, &of_cpu_pd_list); mutex_unlock(&cpu_pd_list_lock); - ret = pm_genpd_init(genpd, &simple_qos_governor, false); + ret = pm_genpd_init(genpd, &cpu_pd_gov, false); if (ret) { pr_err("Unable to initialize domain %s\n", genpd->name); goto fail; From patchwork Fri Mar 3 20:41:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 94858 Delivered-To: patch@linaro.org Received: by 10.140.82.71 with SMTP id g65csp416500qgd; Fri, 3 Mar 2017 12:42:56 -0800 (PST) X-Received: by 10.98.201.212 with SMTP id l81mr5810978pfk.13.1488573776757; Fri, 03 Mar 2017 12:42:56 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u26si11559272pge.31.2017.03.03.12.42.56; Fri, 03 Mar 2017 12:42:56 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S1752093AbdCCUmz (ORCPT + 13 others); Fri, 3 Mar 2017 15:42:55 -0500 Received: from mail-pf0-f182.google.com ([209.85.192.182]:33272 "EHLO mail-pf0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752036AbdCCUmy (ORCPT ); Fri, 3 Mar 2017 15:42:54 -0500 Received: by mail-pf0-f182.google.com with SMTP id w189so36484523pfb.0 for ; Fri, 03 Mar 2017 12:41:57 -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; bh=qiJmaHQzS0bE0Z3khLT+haTTC5Ogp7L2zhL7C/GnKhc=; b=OhnQazm1GYnIYU0VCcxwNSH2KYd5hW/S78tu8r4B8dteS2TD7vBpRbiedCyxZnGSo9 jXhfacL+94ortwPKH94UgxZ+JojPmY/TkOClpOEnlI0wMGp6ARdJ3kX2X3y4pdGAfQ69 RxnDtvFW1Gz2Qt8GKLwAyMaQzRm1NiBbd6iKw= 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=qiJmaHQzS0bE0Z3khLT+haTTC5Ogp7L2zhL7C/GnKhc=; b=FmQqq2xOdMUr+eUfW4nO19iQzUPJvuL0627hdaoTn/zLUQWo2cdOIOet/h6d+87SDf sf4qS5iTK6Ve8kAytXh2NPfWD93fNWJSM67u+PBDqqPnqcyHjT9OqBYOQZzogXOBqip9 +NbLHrMAJE9qyAnmzr0JHP/VK9dQzYSVIgWm9YiG2wZVt3vH60P+x7xD7s4LA1blph1d bvUhqsWnJ0SbKlep+w/Cn/OzJooULVSNjdCQZGqaA4L18fO4aOEnVBQm+bRpL6iZj6ze XpuLLNqbz6OGYZf765XX9ZMHUmjzF4FxVCznz0Hj5XK3C/BdNOPV9Q4yM8oY2w4Isd7f TdrQ== X-Gm-Message-State: AMke39lVSK0bBm1ufdnUvLXe8hbAxeqAn6v9I48SLOMj1SNrfYt+8310rjfoEILJRbGGgB0S X-Received: by 10.98.138.132 with SMTP id o4mr5703000pfk.70.1488573717135; Fri, 03 Mar 2017 12:41:57 -0800 (PST) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id o189sm25207003pga.12.2017.03.03.12.41.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 03 Mar 2017 12:41:55 -0800 (PST) From: Lina Iyer To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, brendan.jackman@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, Juri.Lelli@arm.com, Lina Iyer Subject: [PATCH V5 7/9] PM / Domains: allow platform specific data for genpd states Date: Fri, 3 Mar 2017 12:41:33 -0800 Message-Id: <1488573695-106680-8-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> References: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Allow platforms to save a state specific parameter for the genpd state. The parameter would be used to identify the state when the platform is called to power off the domain. Signed-off-by: Lina Iyer --- include/linux/pm_domain.h | 1 + 1 file changed, 1 insertion(+) -- 2.7.4 diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 5339ed5..183995a 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -42,6 +42,7 @@ struct genpd_power_state { s64 power_on_latency_ns; s64 residency_ns; struct fwnode_handle *fwnode; + u32 param; }; struct genpd_lock_ops; From patchwork Fri Mar 3 20:41:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 94859 Delivered-To: patch@linaro.org Received: by 10.140.82.71 with SMTP id g65csp416509qgd; Fri, 3 Mar 2017 12:42:57 -0800 (PST) X-Received: by 10.99.238.69 with SMTP id n5mr5677798pgk.38.1488573777838; Fri, 03 Mar 2017 12:42:57 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v26si11581290pfa.151.2017.03.03.12.42.57; Fri, 03 Mar 2017 12:42:57 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S1752036AbdCCUm4 (ORCPT + 13 others); Fri, 3 Mar 2017 15:42:56 -0500 Received: from mail-pg0-f53.google.com ([74.125.83.53]:33443 "EHLO mail-pg0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752057AbdCCUmy (ORCPT ); Fri, 3 Mar 2017 15:42:54 -0500 Received: by mail-pg0-f53.google.com with SMTP id 25so47490909pgy.0 for ; Fri, 03 Mar 2017 12:42:00 -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; bh=AFy3Sr7gOSKdvfXzs08Y5f4f0cDRwhRTDKbEUGb/nrs=; b=gSmEQFAze5FzQ3te3bocuYE6AGXYSnre9x37TgHCbEuI8wYpFFkgxrSaE0mVScj1q1 Yu/7DnY0Ax7exbz1ecRapLHDTfdTiliHFOWUOF1CPEM3wgOMTYw8SlBRRFY0luBv2nyz LOJjwC4dRj9g0IPM8eMuoShiBv9S5HyLJqfys= 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=AFy3Sr7gOSKdvfXzs08Y5f4f0cDRwhRTDKbEUGb/nrs=; b=N4qZ0aDDiSYguj7JC3IVpWEWnlaUF35aZj+fg49A+LAZQpYRe+TSBwZYUWksGcobHF J+P8+IgKbt143j4ROY4fFSzaIil66VuzQy6nv1KQ2l+HLkQf4ioaEjKZQWwCpeqEFaur mua7X6miyLshrUMBLfzuJSG7D6VgP64vMpUHr8J/f38eJvY4UgyQJDL28ll6h7/uXqp/ DoVRci6mSmG5RwbPLzQr8jC3JV6tBkMW9EDb/QwqMnWjk0UZ6ed9o1l2opY8yURnI3J7 qKe4tdcZQYaVRWQ+l0wsAm/3CcQgQFr95BLdf/jwFbQK35K/6OQJZ8Wby00yipVAeT6F 5HKg== X-Gm-Message-State: AMke39mq4fbcdxm9Y/PrNqIegvfsogwnMQArv4hhUMZ30uBvFyj7MjthHaLpAU0AV2ywW3pc X-Received: by 10.98.62.82 with SMTP id l79mr5812217pfa.164.1488573719725; Fri, 03 Mar 2017 12:41:59 -0800 (PST) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id o189sm25207003pga.12.2017.03.03.12.41.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 03 Mar 2017 12:41:58 -0800 (PST) From: Lina Iyer To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, brendan.jackman@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, Juri.Lelli@arm.com, Lina Iyer Subject: [PATCH V5 8/9] PM / cpu_domains: Initialize CPU PM domains from DT Date: Fri, 3 Mar 2017 12:41:34 -0800 Message-Id: <1488573695-106680-9-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> References: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org Add helper functions to parse DT and initialize the CPU PM domains and attach CPU to their respective domains using information provided in the DT. For each CPU in the DT, we identify the domain provider; initialize and register the PM domain if isn't already registered and attach all the CPU devices to the domain. Usually, when there are multiple clusters of CPUs, there is a top level coherency domain that is dependent on these individual domains. All domains thus created are marked IRQ safe automatically and therefore may be powered down when the CPUs in the domain are powered down by cpuidle. Cc: Kevin Hilman Suggested-by: Ulf Hansson Signed-off-by: Lina Iyer --- drivers/base/power/cpu_domains.c | 210 +++++++++++++++++++++++++++++++++++++++ include/linux/cpu_domains.h | 20 ++++ 2 files changed, 230 insertions(+) -- 2.7.4 diff --git a/drivers/base/power/cpu_domains.c b/drivers/base/power/cpu_domains.c index 4f2a40e..a566d84 100644 --- a/drivers/base/power/cpu_domains.c +++ b/drivers/base/power/cpu_domains.c @@ -13,8 +13,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -268,3 +270,211 @@ int cpu_pd_init(struct generic_pm_domain *genpd, const struct cpu_pd_ops *ops) return ret; } EXPORT_SYMBOL(cpu_pd_init); + +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF + +static struct generic_pm_domain *of_get_genpd(struct device_node *dn) +{ + struct cpu_pm_domain *pd; + struct generic_pm_domain *genpd = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(pd, &of_cpu_pd_list, link) + if (pd->genpd->provider == &dn->fwnode) { + genpd = pd->genpd; + break; + } + rcu_read_unlock(); + + return genpd; +} + +static struct generic_pm_domain *alloc_genpd(struct device_node *dn) +{ + struct generic_pm_domain *genpd; + + genpd = kzalloc(sizeof(*genpd), GFP_KERNEL); + if (!genpd) + return ERR_PTR(-ENOMEM); + + genpd->name = kstrndup(dn->full_name, CPU_PD_NAME_MAX, GFP_KERNEL); + if (!genpd->name) { + kfree(genpd); + return ERR_PTR(-ENOMEM); + } + + return genpd; +} + +/** + * of_init_cpu_pm_domain() - Initialize a CPU PM domain from a device node + * + * @dn: The domain provider's device node + * @ops: The power_on/_off callbacks for the domain + * + * Returns the generic_pm_domain (genpd) pointer to the domain on success + */ +static struct generic_pm_domain *of_init_cpu_pm_domain(struct device_node *dn, + const struct cpu_pd_ops *plat_ops) +{ + struct cpu_pm_domain *pd = NULL; + struct generic_pm_domain *genpd = NULL; + int ret = -ENOMEM; + struct genpd_power_state *states = NULL; + const struct cpu_pd_ops *ops = plat_ops; + int count; + int i; + + if (!of_device_is_available(dn)) + return ERR_PTR(-ENODEV); + + /* If we already have the PM domain return that */ + genpd = of_get_genpd(dn); + if (genpd) + return genpd; + + /* Initialize a new PM Domains */ + genpd = alloc_genpd(dn); + if (IS_ERR(genpd)) + return genpd; + + ret = of_genpd_parse_idle_states(dn, &states, &count); + if (ret) + goto fail; + if (!count) { + ops = NULL; + goto skip_states; + } + + /* Populate platform specific states from DT */ + for (i = 0; ops->populate_state_data && i < count; i++) { + ret = ops->populate_state_data(to_of_node(states[i].fwnode), + &states[i].param); + if (ret) + goto fail; + } + + genpd->states = states; + genpd->state_count = count; + +skip_states: + ret = cpu_pd_init(genpd, ops); + if (ret) + goto fail; + + ret = of_genpd_add_provider_simple(dn, genpd); + if (ret) + pr_warn("Unable to add genpd %s as provider\n", + pd->genpd->name); + + return genpd; +fail: + kfree(genpd->name); + kfree(genpd); + if (pd) + kfree(pd->cpus); + kfree(pd); + return ERR_PTR(ret); +} + +static struct generic_pm_domain *of_get_cpu_domain(struct device_node *dn, + const struct cpu_pd_ops *ops, int cpu) +{ + struct of_phandle_args args; + struct generic_pm_domain *genpd, *parent; + int ret; + + genpd = of_init_cpu_pm_domain(dn, ops); + if (IS_ERR(genpd)) + return genpd; + + /* Is there a domain provider for this domain? */ + ret = of_parse_phandle_with_args(dn, "power-domains", + "#power-domain-cells", 0, &args); + if (ret < 0) + goto skip_parent; + + /* Find its parent and attach this domain to it, recursively */ + parent = of_get_cpu_domain(args.np, ops, cpu); + if (IS_ERR(parent)) + goto skip_parent; + + ret = cpu_pd_attach_domain(parent, genpd); + if (ret) + pr_err("Unable to attach domain %s to parent %s\n", + genpd->name, parent->name); + +skip_parent: + of_node_put(dn); + return genpd; +} + +/** + * of_setup_cpu_pd_single() - Setup the PM domains for a CPU + * + * @cpu: The CPU for which the PM domain is to be set up. + * @ops: The PM domain suspend/resume ops for the CPU's domain + * + * If the CPU PM domain exists already, then the CPU is attached to + * that CPU PD. If it doesn't, the domain is created, the @ops are + * set for power_on/power_off callbacks and then the CPU is attached + * to that domain. If the domain was created outside this framework, + * then we do not attach the CPU to the domain. + */ +int of_setup_cpu_pd_single(int cpu, const struct cpu_pd_ops *ops) +{ + + struct device_node *dn, *np; + struct generic_pm_domain *genpd; + struct cpu_pm_domain *cpu_pd; + + np = of_get_cpu_node(cpu, NULL); + if (!np) + return -ENODEV; + + dn = of_parse_phandle(np, "power-domains", 0); + of_node_put(np); + if (!dn) + return -ENODEV; + + /* Find the genpd for this CPU, create if not found */ + genpd = of_get_cpu_domain(dn, ops, cpu); + of_node_put(dn); + if (IS_ERR(genpd)) + return PTR_ERR(genpd); + + cpu_pd = to_cpu_pd(genpd); + if (!cpu_pd) { + pr_err("%s: Genpd was created outside CPU PM domains\n", + __func__); + return -ENOENT; + } + + return cpu_pd_attach_cpu(genpd, cpu); +} +EXPORT_SYMBOL(of_setup_cpu_pd_single); + +/** + * of_setup_cpu_pd() - Setup the PM domains for all CPUs + * + * @ops: The PM domain suspend/resume ops for all the domains + * + * Setup the CPU PM domain and attach all possible CPUs to their respective + * domains. The domains are created if not already and then attached. + */ +int of_setup_cpu_pd(const struct cpu_pd_ops *ops) +{ + int cpu; + int ret; + + for_each_possible_cpu(cpu) { + ret = of_setup_cpu_pd_single(cpu, ops); + if (ret) + break; + } + + return ret; +} +EXPORT_SYMBOL(of_setup_cpu_pd); + +#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ diff --git a/include/linux/cpu_domains.h b/include/linux/cpu_domains.h index 7e71291..251fbc2 100644 --- a/include/linux/cpu_domains.h +++ b/include/linux/cpu_domains.h @@ -15,8 +15,12 @@ struct generic_pm_domain; struct cpumask; +struct device_node; struct cpu_pd_ops { +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF + int (*populate_state_data)(struct device_node *n, u32 *param); +#endif int (*power_off)(u32 state_idx, u32 param, const struct cpumask *mask); int (*power_on)(void); }; @@ -45,4 +49,20 @@ static inline int cpu_pd_attach_cpu(struct generic_pm_domain *genpd, int cpu) #endif /* CONFIG_PM_GENERIC_DOMAINS */ +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF + +int of_setup_cpu_pd_single(int cpu, const struct cpu_pd_ops *ops); + +int of_setup_cpu_pd(const struct cpu_pd_ops *ops); + +#else + +static inline int of_setup_cpu_pd_single(int cpu, const struct cpu_pd_ops *ops) +{ return -ENODEV; } + +static inline int of_setup_cpu_pd(const struct cpu_pd_ops *ops) +{ return -ENODEV; } + +#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */ + #endif /* __CPU_DOMAINS_H__ */ From patchwork Fri Mar 3 20:41:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lina Iyer X-Patchwork-Id: 94861 Delivered-To: patch@linaro.org Received: by 10.140.82.71 with SMTP id g65csp416548qgd; Fri, 3 Mar 2017 12:43:04 -0800 (PST) X-Received: by 10.99.241.83 with SMTP id o19mr2466019pgk.81.1488573784568; Fri, 03 Mar 2017 12:43:04 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r17si11522976pgg.388.2017.03.03.12.43.04; Fri, 03 Mar 2017 12:43:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-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-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-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 S1751989AbdCCUnC (ORCPT + 13 others); Fri, 3 Mar 2017 15:43:02 -0500 Received: from mail-pf0-f172.google.com ([209.85.192.172]:34177 "EHLO mail-pf0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752082AbdCCUmy (ORCPT ); Fri, 3 Mar 2017 15:42:54 -0500 Received: by mail-pf0-f172.google.com with SMTP id e66so18039687pfe.1 for ; Fri, 03 Mar 2017 12:42:02 -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; bh=91y2xiSaIH8mHCdkE7TEB06kh1lqQlJpGwOOZGDufR0=; b=KbTVS7SZSlETYT/VTgmAS9JVI5ruHfXW+zw0Tr04XyqEdR7+cAM6zR54Eveg54EA6C 1ICjq7AWAfvw77ZsCR58y54ZRfv6Ai3aWRVbBKo/30ocmTAGF9Xx4J8Bv2oTcGcVugYY fw5EWcPVVE4EnBKsupJSw1Avbl17LQfotfOAs= 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=91y2xiSaIH8mHCdkE7TEB06kh1lqQlJpGwOOZGDufR0=; b=l1oYkxn26LT1yV7URMb354FEolhpf3UAYf/BxIpU3MlY5Jvv30WOZ+o33vgB/RCUB+ 7JlBzxlYHcUgpID9uMUzy3AcNTpY8WBlogXShHahixXDP+U+OH67FqkydqnsndZiwjig 46vbALoWSnhCHGTZc+4B3H6ZiAjRTc/MhqpIO3l/0e/fwafmV/gGUdhscee/dcSD9I4C j7sINLY/pkw1vWtpNizeKUDu7Xa8lSndTM9E/y4GwFqU2D2+F548+z5eFoVXqTBUpREz cAjIqYQiOqUf08TY/tVknyN9FBnOiZqrZKtPU8GzWhD1PAVNz2i2unbTPzt2eCtv0iWB 0YZA== X-Gm-Message-State: AMke39l0DzFjzHBxDOCGv4+j4CmF56JH+BAfcmbvsLw2uIjX3EyvdrwddTwfoREBhqL71mdJ X-Received: by 10.98.27.204 with SMTP id b195mr5670149pfb.154.1488573722197; Fri, 03 Mar 2017 12:42:02 -0800 (PST) Received: from ubuntu.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id o189sm25207003pga.12.2017.03.03.12.41.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 03 Mar 2017 12:42:01 -0800 (PST) From: Lina Iyer To: ulf.hansson@linaro.org, khilman@kernel.org, rjw@rjwysocki.net, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: andy.gross@linaro.org, sboyd@codeaurora.org, linux-arm-msm@vger.kernel.org, brendan.jackman@arm.com, lorenzo.pieralisi@arm.com, sudeep.holla@arm.com, Juri.Lelli@arm.com, Lina Iyer Subject: [PATCH V5 9/9] doc / cpu_domains: Describe CPU PM domains setup and governor Date: Fri, 3 Mar 2017 12:41:35 -0800 Message-Id: <1488573695-106680-10-git-send-email-lina.iyer@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> References: <1488573695-106680-1-git-send-email-lina.iyer@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org A generic CPU PM domain functionality is provided by drivers/base/power/cpu_domains.c. This document describes the generic usecase of CPU's PM domains, the setup of such domains and a CPU specific genpd governor. Signed-off-by: Lina Iyer --- Documentation/power/cpu_domains.txt | 109 ++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 Documentation/power/cpu_domains.txt -- 2.7.4 diff --git a/Documentation/power/cpu_domains.txt b/Documentation/power/cpu_domains.txt new file mode 100644 index 0000000..6a39a64 --- /dev/null +++ b/Documentation/power/cpu_domains.txt @@ -0,0 +1,109 @@ +CPU PM domains +============== + +Newer CPUs are grouped in SoCs as clusters. A cluster in addition to the CPUs +may have caches, floating point units and other architecture specific power +controller that share resources when any of the CPUs are active. When the CPUs +are in idle, some of these cluster components may also idle. A cluster may +also be nested inside another cluster that provides common coherency +interfaces to share data between the clusters. The organization of such +clusters and CPU may be descibed in DT, since they are SoC specific. + +CPUIdle framework enables the CPUs to determine the sleep time and enter low +power state to save power during periods of idle. CPUs in a cluster may enter +and exit idle state independently of each other. During the time when all the +CPUs are in idle state, the cluster may safely put some of the shared +resources in their idle state. The time between the last CPU to enter idle and +the first CPU to wake up is the time available for the cluster to enter its +idle state. + +When SoCs power down the CPU during cpuidle, they generally have supplemental +hardware that can handshake with the CPU with a signal that indicates that the +CPU has stopped execution. The hardware is also responsible for warm booting +the CPU on receiving an interrupt. In a cluster architecture, common resources +that are shared by a cluster may also be powered down by an external +microcontroller or a processor. The microcontroller may be programmed in +advance to put the hardware blocks in a low power state, when the last active +CPU sends the idle signal. When the signal is received, the microcontroller +may trigger the hardware blocks to enter their low power state. When an +interrupt to wakeup the processor is received, the microcontroller is +responsible for bringing up the hardware blocks to its active state, before +waking up the CPU. The timelines for such operations should be in the +acceptable range for for CPU idle to get power benefits. + +CPU PM Domain Setup +------------------- + +PM domains are represented in the DT as domain consumers and providers. A +device may have a domain provider and a domain provider may support multiple +domain consumers. Domains like clusters, may also be nested inside one +another. A domain that has no active consumer, may be powered off and any +resuming consumer would trigger the domain back to active. Parent domains may +be powered off when the child domains are powered off. The CPU cluster can be +fashioned as a PM domain. When the CPU devices are powered off, the PM domain +may be powered off. + +Device idle is reference counted by runtime PM. When there is no active need +for the device, runtime PM invokes callbacks to suspend the parent domain. +Generic PM domain (genpd) handles the hierarchy of devices, domains and the +reference counting of objects leading to last man down and first man up in the +domain. The CPU domains helper functions defines PM domains for each CPU +cluster and attaches the CPU devices to the respective PM domains. + +Platform drivers may use the following API to register their CPU PM domains. + +of_setup_cpu_pd() - +Provides a single step registration of the CPU PM domain and attach CPUs to +the genpd. Platform drivers may additionally register callbacks for power_on +and power_off operations for the PM domain. + +of_setup_cpu_pd_single() - +Define PM domain for a single CPU and attach the CPU to its domain. + + +CPU PM Domain governor +---------------------- + +CPUs have a unique ability to determine their next wakeup. CPUs may wake up +for known timer interrupts and unknown interrupts from idle. Prediction +algorithms and heuristic based algorithms like the Menu governor for cpuidle +can determine the next wakeup of the CPU. However, determining the wakeup +across a group of CPUs is a tough problem to solve. + +A simplistic approach would be to resort to known wakeups of the CPUs in +determining the next wakeup of any CPU in the cluster. The CPU PM domain +governor does just that. By looking into the tick device of the CPUs, the +governor can determine the sleep time between the last CPU and the first +scheduled wakeup of any CPU in that domain. This combined with the PM QoS +requirement for CPU_DMA_LATENCY can be used to determine the deepest possible +idle state of the CPU domain. + + +PSCI based CPU PM Domains +------------------------- + +ARM PSCI v1.0 supports PM domains for CPU clusters like in big.Little +architecture. It is supported as part of the OS-Initiated (OSI) mode of the +PSCI firmware. Since the control of domains is abstracted in the firmware, +Linux does not need even a driver to control these domains. The complexity of +determining the idle state of the PM domain is handled by the CPU PM domains. + +Every PSCI CPU PM domain idle state has a unique PSCI state id. The state id +is read from the DT and specified using the arm,psci-suspend-param property. +This makes it easy for big.Little SoCs to just specify the PM domain idle +states for the CPU along with the psci-suspend-param and everything else is +handled by the PSCI fimrware drivers and the firmware. + + +DT definitions for PSCI CPU PM Domains +-------------------------------------- + +A PM domain's idle state can be defined in DT, the description of which is +available in [1]. PSCI based CPU PM domains may define their idle states as +part of the psci node. The additional parameter arm,psci-suspend-param is used +to indicate to the firmwware the addition cluster state that would be achieved +after the last CPU makes the PSCI call to suspend the CPU. The description of +PSCI domain states is available in [2]. + +[1]. Documentation/devicetree/bindings/arm/idle-states.txt +[2]. Documentation/devicetree/bindings/arm/psci.txt