From patchwork Wed Feb 27 19:58:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 10832261 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5982E13B5 for ; Wed, 27 Feb 2019 19:59:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A79D2C594 for ; Wed, 27 Feb 2019 19:59:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3C3CB2E5A9; Wed, 27 Feb 2019 19:59:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D40E12C594 for ; Wed, 27 Feb 2019 19:59:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730265AbfB0T6p (ORCPT ); Wed, 27 Feb 2019 14:58:45 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:39951 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730149AbfB0T6p (ORCPT ); Wed, 27 Feb 2019 14:58:45 -0500 Received: by mail-lj1-f193.google.com with SMTP id w6so14991317ljd.7 for ; Wed, 27 Feb 2019 11:58:43 -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=XKFXfVA/MFOFOm3N3DxhXtUoRuHmZYEZxmpq4iLOsS0=; b=BCNOViW05Viv/rVAqgh4Vsn2bB/S6rmx007nW5Zwfg3vOsf2oiUNr2cy+h1kftVC1O bu8OYpbnjns/sJO3ZVm2y2mMVvfyKc5T8ToLluuy4Ym+LbQsz5Bw8NYC596JvipOH2k9 4hUg069/roFn9YCZWfP6Ya/L0OOyZxOhQvrivrUoEomsZXKx4S3j/C7bhV/lcIWBHY/9 ZS+1Z69pFXGch6UfZOAc3Y2359plZH2U7Sx37NqdNH25je5jjhYblLPfuyWaY58vBevx uUqpLXxkYkaERvVNnnVdnmP1OxIeXVmuPuDi5S71RyTevI9kwdjMnD2n17nhk0uMunLa Fqtw== 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=XKFXfVA/MFOFOm3N3DxhXtUoRuHmZYEZxmpq4iLOsS0=; b=LpS/K3TZ6TsMb4Xy6IMM6KBsslGRxMgltH9eGs9VtHXNm5ruMb0FecevDj9Rumbes+ 1HWhXI/9FkOrdWPXcn9VIeqiyne9ogpAn0ig/XNP3toTwe/3csu8dES79PmH/pYc+OlJ hPc8pchGAjfsvA0nAK1EFB98MflJHbBmt8ll//LaF2vXOnhbkiv2cz2N30lG0jw94aFc 9FSsqoePyzJQJbJpyTkjqcc75HYUnxjl9MvIx2m7GnQZq5OMgZvyO5P6KGFrV/0d1DIm E87KP3XVabPUHAF6Q+tTrsZOqWNJElc8AIc0ocLZq8R9/lqJPHDSKWhz2zAQZTNAapNf Kgcg== X-Gm-Message-State: AHQUAubIGi2hp0t5vGcT91nsi2NoBgXEHeHXHLdP+ghO6+Lhu4Iw77Z8 wzTDG4/B6c5buz0dq05MfVwUiA== X-Google-Smtp-Source: APXvYqwoEEWsyKRDgF2ZqvMiwFnQqs7Nd2PwXFGAP3pHpMx7U5f+SRreNguy4ZpIWPZAhCu2g6hqmg== X-Received: by 2002:a2e:9916:: with SMTP id v22mr2435944lji.68.1551297522613; Wed, 27 Feb 2019 11:58:42 -0800 (PST) Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id z128sm723802lfa.60.2019.02.27.11.58.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Feb 2019 11:58:41 -0800 (PST) From: Ulf Hansson To: "Rafael J . Wysocki" , linux-pm@vger.kernel.org Cc: Frederic Weisbecker , Thomas Gleixner , Sudeep Holla , Lorenzo Pieralisi , Mark Rutland , Daniel Lezcano , "Raju P . L . S . S . S . N" , Stephen Boyd , Tony Lindgren , Kevin Hilman , Lina Iyer , Ulf Hansson , Viresh Kumar , Vincent Guittot , Geert Uytterhoeven , linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v12 1/4] PM / Domains: Add a generic data pointer to the genpd_power_state struct Date: Wed, 27 Feb 2019 20:58:33 +0100 Message-Id: <20190227195836.24739-2-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190227195836.24739-1-ulf.hansson@linaro.org> References: <20190227195836.24739-1-ulf.hansson@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Let's add a data pointer to the genpd_power_state struct, to allow a genpd backend driver to store per state specific data. To introduce the pointer, we need to change the way genpd deals with freeing of the corresponding allocated data. More precisely, let's clarify the responsibility of whom that shall free the data, by adding a ->free_states() callback to the struct generic_pm_domain. The one allocating the data shall assign the callback, to allow genpd to invoke it from genpd_remove(). Cc: Lina Iyer Co-developed-by: Lina Iyer Signed-off-by: Ulf Hansson Acked-by: Daniel Lezcano --- Changes in v12: - None. --- drivers/base/power/domain.c | 12 ++++++++++-- include/linux/pm_domain.h | 4 +++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 2c334c01fc43..03885c003c6a 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1685,6 +1685,12 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, } EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain); +static void genpd_free_default_power_state(struct genpd_power_state *states, + unsigned int state_count) +{ + kfree(states); +} + static int genpd_set_default_power_state(struct generic_pm_domain *genpd) { struct genpd_power_state *state; @@ -1695,7 +1701,7 @@ static int genpd_set_default_power_state(struct generic_pm_domain *genpd) genpd->states = state; genpd->state_count = 1; - genpd->free = state; + genpd->free_states = genpd_free_default_power_state; return 0; } @@ -1811,7 +1817,9 @@ static int genpd_remove(struct generic_pm_domain *genpd) list_del(&genpd->gpd_list_node); genpd_unlock(genpd); cancel_work_sync(&genpd->power_off_work); - kfree(genpd->free); + if (genpd->free_states) + genpd->free_states(genpd->states, genpd->state_count); + pr_debug("%s: removed %s\n", __func__, genpd->name); return 0; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 1ed5874bcee0..8e1399231753 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -69,6 +69,7 @@ struct genpd_power_state { s64 residency_ns; struct fwnode_handle *fwnode; ktime_t idle_time; + void *data; }; struct genpd_lock_ops; @@ -110,9 +111,10 @@ struct generic_pm_domain { struct device *dev); unsigned int flags; /* Bit field of configs for genpd */ struct genpd_power_state *states; + void (*free_states)(struct genpd_power_state *states, + unsigned int state_count); unsigned int state_count; /* number of states */ unsigned int state_idx; /* state that genpd will go to when off */ - void *free; /* Free the state that was allocated for default */ ktime_t on_time; ktime_t accounting_time; const struct genpd_lock_ops *lock_ops; From patchwork Wed Feb 27 19:58:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 10832243 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F192E139A for ; Wed, 27 Feb 2019 19:58:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E28272E4E4 for ; Wed, 27 Feb 2019 19:58:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D5EDF2E4E5; Wed, 27 Feb 2019 19:58:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B020A2E4E3 for ; Wed, 27 Feb 2019 19:58:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729825AbfB0T6s (ORCPT ); Wed, 27 Feb 2019 14:58:48 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:46051 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730263AbfB0T6r (ORCPT ); Wed, 27 Feb 2019 14:58:47 -0500 Received: by mail-lj1-f193.google.com with SMTP id d24so14728123ljc.12 for ; Wed, 27 Feb 2019 11:58:45 -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=TSS7UyhFKusvN1QpHYAVmHi7+a3wd/308ysavr6LVN8=; b=ptMtJ10idarPBBhSJWQpGuBKBGhqenLNPBTdRtzkXhpfmS6x+mMhr17ciOL+E70iCh f6hkNEk5ggSOdY3rNEPXcfvjVfP2RHUE8RmLBSjIHlW64LOP+leTar42vorMb15WS0KH Zbhbmxy1QShAHAEey5J9oWA9g2IF+hUFUFoJEaLSNnMTw66MkLlN9PpxZ5vPhCCTAaY0 FrpSm3gRN42MHHfSaVIkHXLU+c26rK/2VlbxR4jeH3HdJLamhlSrjcehBrjqw4QVAduP aJ0ZpL73O2xmHfSchmda2kpu7zs71c22TNcrR81SJHVIw4vlbSo6kDANGA5nJds5Zkrd pzMQ== 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=TSS7UyhFKusvN1QpHYAVmHi7+a3wd/308ysavr6LVN8=; b=j8adc3UWCMjD1GAAxnDmT2domCiY4hGUlhaKX4mnWs6+0wDIBUmXZPR12p4G/wBKkn b8gFcK4FHbTi5iuuTfu6jPvcxYeKuXbHUdIwYTCFlwAZHTWE3fq7T56NppGqolFriU+Z Wx7yP7AX4y6tatcnh22npqHoI7paBQ7YAc75phoLeXrusBV2hp6kowjTRTYKDurGbchF AtZ0z8DuuL4hMd+dhPVzvJpmvdM2GE5Brz4/X5ROWUQ6GJYrnAmiD36cTRCHtgwpd4lP gq7/BwI7FV5cHloL+1LYw0RG8f7VtyHe/juQTym2+m0I+vxRe10qEprLMla4edwUWtP0 FAIA== X-Gm-Message-State: APjAAAUIkIEWdR5wRy+I26cllATN2OzI+Z8d+8hATT7lDX0IPBflBiRe Ztvw3RUPZwqnRZ7X39Gc7Jn9yQ== X-Google-Smtp-Source: APXvYqwjqDWE4R2b9ofz0WGKpw59wybQYlw3ncmQN1cJUrxgGYZv7N3Z4XVAGwGVIXp+yGHvffbepw== X-Received: by 2002:a2e:12da:: with SMTP id 87mr2462983ljs.181.1551297524743; Wed, 27 Feb 2019 11:58:44 -0800 (PST) Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id z128sm723802lfa.60.2019.02.27.11.58.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Feb 2019 11:58:44 -0800 (PST) From: Ulf Hansson To: "Rafael J . Wysocki" , linux-pm@vger.kernel.org Cc: Frederic Weisbecker , Thomas Gleixner , Sudeep Holla , Lorenzo Pieralisi , Mark Rutland , Daniel Lezcano , "Raju P . L . S . S . S . N" , Stephen Boyd , Tony Lindgren , Kevin Hilman , Lina Iyer , Ulf Hansson , Viresh Kumar , Vincent Guittot , Geert Uytterhoeven , linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v12 2/4] PM / Domains: Add support for CPU devices to genpd Date: Wed, 27 Feb 2019 20:58:34 +0100 Message-Id: <20190227195836.24739-3-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190227195836.24739-1-ulf.hansson@linaro.org> References: <20190227195836.24739-1-ulf.hansson@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP To enable a device belonging to a CPU to be attached to a PM domain managed by genpd, let's do a few changes to it, as to make it convenient to manage the specifics around CPUs. To be able to quickly find out what CPUs that are attached to a genpd, which typically becomes useful from a genpd governor as following changes is about to show, let's add a cpumask to the struct generic_pm_domain. At the point when a CPU device gets attached to a genpd, let's update the genpd's cpumask. Moreover, let's also propagate changes to the cpumask upwards in the topology to the master PM domains. In this way, the cpumask for a genpd hierarchically reflects all CPUs attached to the topology below it. Finally, let's make this an opt-in feature, to avoid having to manage CPUs and the cpumask for a genpd that doesn't need it. For that reason, let's add a new genpd configuration bit, GENPD_FLAG_CPU_DOMAIN. Cc: Lina Iyer Co-developed-by: Lina Iyer Acked-by: Rafael J. Wysocki Signed-off-by: Ulf Hansson Acked-by: Daniel Lezcano --- Changes in v12: - None. --- drivers/base/power/domain.c | 66 ++++++++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 13 ++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 03885c003c6a..da10052e6427 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "power.h" @@ -126,6 +127,7 @@ static const struct genpd_lock_ops genpd_spin_ops = { #define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE) #define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON) #define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP) +#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN) static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev, const struct generic_pm_domain *genpd) @@ -1452,6 +1454,56 @@ static void genpd_free_dev_data(struct device *dev, dev_pm_put_subsys_data(dev); } +static void __genpd_update_cpumask(struct generic_pm_domain *genpd, + int cpu, bool set, unsigned int depth) +{ + struct gpd_link *link; + + if (!genpd_is_cpu_domain(genpd)) + return; + + list_for_each_entry(link, &genpd->slave_links, slave_node) { + struct generic_pm_domain *master = link->master; + + genpd_lock_nested(master, depth + 1); + __genpd_update_cpumask(master, cpu, set, depth + 1); + genpd_unlock(master); + } + + if (set) + cpumask_set_cpu(cpu, genpd->cpus); + else + cpumask_clear_cpu(cpu, genpd->cpus); +} + +static void genpd_update_cpumask(struct generic_pm_domain *genpd, + struct device *dev, bool set) +{ + int cpu; + + if (!genpd_is_cpu_domain(genpd)) + return; + + for_each_possible_cpu(cpu) { + if (get_cpu_device(cpu) == dev) { + __genpd_update_cpumask(genpd, cpu, set, 0); + return; + } + } +} + +static void genpd_set_cpumask(struct generic_pm_domain *genpd, + struct device *dev) +{ + genpd_update_cpumask(genpd, dev, true); +} + +static void genpd_clear_cpumask(struct generic_pm_domain *genpd, + struct device *dev) +{ + genpd_update_cpumask(genpd, dev, false); +} + static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, struct gpd_timing_data *td) { @@ -1473,6 +1525,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, if (ret) goto out; + genpd_set_cpumask(genpd, dev); + dev_pm_domain_set(dev, &genpd->domain); genpd->device_count++; @@ -1534,6 +1588,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, if (genpd->detach_dev) genpd->detach_dev(genpd, dev); + genpd_clear_cpumask(genpd, dev); dev_pm_domain_set(dev, NULL); list_del_init(&pdd->list_node); @@ -1767,11 +1822,18 @@ int pm_genpd_init(struct generic_pm_domain *genpd, if (genpd_is_always_on(genpd) && !genpd_status_on(genpd)) return -EINVAL; + if (genpd_is_cpu_domain(genpd) && + !zalloc_cpumask_var(&genpd->cpus, GFP_KERNEL)) + return -ENOMEM; + /* Use only one "off" state if there were no states declared */ if (genpd->state_count == 0) { ret = genpd_set_default_power_state(genpd); - if (ret) + if (ret) { + if (genpd_is_cpu_domain(genpd)) + free_cpumask_var(genpd->cpus); return ret; + } } else if (!gov) { pr_warn("%s : no governor for states\n", genpd->name); } @@ -1817,6 +1879,8 @@ static int genpd_remove(struct generic_pm_domain *genpd) list_del(&genpd->gpd_list_node); genpd_unlock(genpd); cancel_work_sync(&genpd->power_off_work); + if (genpd_is_cpu_domain(genpd)) + free_cpumask_var(genpd->cpus); if (genpd->free_states) genpd->free_states(genpd->states, genpd->state_count); diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 8e1399231753..a6e251fe9deb 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -16,6 +16,7 @@ #include #include #include +#include /* * Flags to control the behaviour of a genpd. @@ -42,11 +43,22 @@ * GENPD_FLAG_ACTIVE_WAKEUP: Instructs genpd to keep the PM domain powered * on, in case any of its attached devices is used * in the wakeup path to serve system wakeups. + * + * GENPD_FLAG_CPU_DOMAIN: Instructs genpd that it should expect to get + * devices attached, which may belong to CPUs or + * possibly have subdomains with CPUs attached. + * This flag enables the genpd backend driver to + * deploy idle power management support for CPUs + * and groups of CPUs. Note that, the backend + * driver must then comply with the so called, + * last-man-standing algorithm, for the CPUs in the + * PM domain. */ #define GENPD_FLAG_PM_CLK (1U << 0) #define GENPD_FLAG_IRQ_SAFE (1U << 1) #define GENPD_FLAG_ALWAYS_ON (1U << 2) #define GENPD_FLAG_ACTIVE_WAKEUP (1U << 3) +#define GENPD_FLAG_CPU_DOMAIN (1U << 4) enum gpd_status { GPD_STATE_ACTIVE = 0, /* PM domain is active */ @@ -94,6 +106,7 @@ struct generic_pm_domain { unsigned int suspended_count; /* System suspend device counter */ unsigned int prepared_count; /* Suspend counter of prepared devices */ unsigned int performance_state; /* Aggregated max performance state */ + cpumask_var_t cpus; /* A cpumask of the attached CPUs */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); struct opp_table *opp_table; /* OPP table of the genpd */ From patchwork Wed Feb 27 19:58:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 10832257 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9485713B5 for ; Wed, 27 Feb 2019 19:59:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 858932C594 for ; Wed, 27 Feb 2019 19:59:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 795392E5A9; Wed, 27 Feb 2019 19:59:07 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E2EDB2E56E for ; Wed, 27 Feb 2019 19:59:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730311AbfB0T6u (ORCPT ); Wed, 27 Feb 2019 14:58:50 -0500 Received: from mail-lf1-f68.google.com ([209.85.167.68]:42825 "EHLO mail-lf1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730305AbfB0T6t (ORCPT ); Wed, 27 Feb 2019 14:58:49 -0500 Received: by mail-lf1-f68.google.com with SMTP id p1so13364009lfk.9 for ; Wed, 27 Feb 2019 11:58:47 -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=I9FC+10KjcWm9oxkGkEiLX6p0r263JrQVxFR/hZ1DCo=; b=W/O0gxneC3anBlV0dLqPWOeg7o1IwJkTZydODUphl9PF+b+qxDTK5l7f4ZXn2b1DYR uym80thZ53ZvAjzliPpxqtrKxW03+wNoOrn6q94ZVyW/bOpCqfQL2MCHA35spNnx9o84 bTtsfBhxjP27sCt6aEktM69GsK7oUCAYi0LUtRm1ONJOEyAULFXWD4XE4f2ZW5EmaBZc GdBJCzQkKl6lefJAFvP/yA6X6B8CnNwXcNTyCvJNpDvV1ze9DnM9UO9rvhsU/r3kVPP5 cEwBwvQJea5QPmhkiteaHArtPl2m/PJ3+66rk5sLzdIRW0BmGOS9W2iIqn+yBfGHbkkb y4BA== 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=I9FC+10KjcWm9oxkGkEiLX6p0r263JrQVxFR/hZ1DCo=; b=Z+soloO16wtrbclFDum7/tDCAqOBHJ0nZsAPaxvH98CstIhORJyp0RZ+oN6qYRvPfA 8/4VxCBu9CDp5BTc6dcHdneQCin4q0XZCtn+zqt5FWpdseHY4kvSdAQfJtl4wwfQKXw5 DVGxDLGVdIc5P+3jFTLlQ9wCqxQ5uqqFbyNKl5ITtSh0C7pMoRtXhLhC7D6bg/PinBNh rVrhHHBHfmEp5gE5fqmmLQBmY737CtVKRzodXHCKEwbqyOhZ/2GYHChnIgXTBsvEDmTg fjSQ6zJ1ypbHN1flqh0Ozgezjwq9lMW4RL4iXpoi0qMmCenRdqq1ZShnvaognCSI5DrV uvyQ== X-Gm-Message-State: AHQUAubp6/RJYBqOExtokmJCUuZKp4GF3zUU+UUhEgdn+jnO13Kh/DFW GIF+mkq2LlMux65RJ5FqdZwzTA== X-Google-Smtp-Source: AHgI3IbJrKjGluCCVPBj7ymE9kz4ZuCKVo32//FJr6Rd/I84iYd75LAeHPxnpNXEh8mDiaTThX+Zgg== X-Received: by 2002:a19:ec0c:: with SMTP id b12mr1988765lfa.27.1551297526598; Wed, 27 Feb 2019 11:58:46 -0800 (PST) Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id z128sm723802lfa.60.2019.02.27.11.58.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Feb 2019 11:58:45 -0800 (PST) From: Ulf Hansson To: "Rafael J . Wysocki" , linux-pm@vger.kernel.org Cc: Frederic Weisbecker , Thomas Gleixner , Sudeep Holla , Lorenzo Pieralisi , Mark Rutland , Daniel Lezcano , "Raju P . L . S . S . S . N" , Stephen Boyd , Tony Lindgren , Kevin Hilman , Lina Iyer , Ulf Hansson , Viresh Kumar , Vincent Guittot , Geert Uytterhoeven , linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v12 3/4] cpuidle: Export the next timer/tick expiration for a CPU Date: Wed, 27 Feb 2019 20:58:35 +0100 Message-Id: <20190227195836.24739-4-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190227195836.24739-1-ulf.hansson@linaro.org> References: <20190227195836.24739-1-ulf.hansson@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP To be able to predict the sleep duration for a CPU that is entering idle, knowing when the next timer/tick is going to expire, is extremely useful. Both the teo and the menu cpuidle governors already makes use of this information, while selecting an idle state. Moving forward, the similar prediction needs to be done, but for a group of idle CPUs rather than for a single idle CPU. Following changes implements a new genpd governor, which needs this. Support this, by sharing a new function called tick_nohz_get_next_hrtimer(), which returns the next hrtimer or the next tick, whatever that expires first. Additionally, when cpuidle is about to invoke the ->enter() callback, then call tick_nohz_get_next_hrtimer() and store its return value in the per CPU struct cpuidle_device, as to make it available outside cpuidle. Do note, at the point when cpuidle calls tick_nohz_get_next_hrtimer(), the governor's ->select() callback has already made a decision whether to stop the tick or not. In this way, tick_nohz_get_next_hrtimer() actually returns the next timer expiration, whatever origin. Cc: Lina Iyer Co-developed-by: Lina Iyer Co-developed-by: Daniel Lezcano Signed-off-by: Ulf Hansson Acked-by: Daniel Lezcano --- Changes in v12: - New patch. --- drivers/cpuidle/cpuidle.c | 8 ++++++++ include/linux/cpuidle.h | 1 + include/linux/tick.h | 7 ++++++- kernel/time/tick-sched.c | 12 ++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 7f108309e871..255365b1a6ab 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -328,6 +328,14 @@ int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, int index) { + /* + * Store the next hrtimer, which becomes either next tick or the next + * timer event, whatever expires first. Additionally, to make this data + * useful for consumers outside cpuidle, we rely on that the governor's + * ->select() callback have decided, whether to stop the tick or not. + */ + dev->next_hrtimer = tick_nohz_get_next_hrtimer(); + if (cpuidle_state_is_coupled(drv, index)) return cpuidle_enter_state_coupled(dev, drv, index); return cpuidle_enter_state(dev, drv, index); diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 3b39472324a3..bb9a0db89f1a 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -83,6 +83,7 @@ struct cpuidle_device { unsigned int use_deepest_state:1; unsigned int poll_time_limit:1; unsigned int cpu; + ktime_t next_hrtimer; int last_residency; struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; diff --git a/include/linux/tick.h b/include/linux/tick.h index 55388ab45fd4..8891b5ac3e40 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -122,6 +122,7 @@ extern void tick_nohz_idle_enter(void); extern void tick_nohz_idle_exit(void); extern void tick_nohz_irq_exit(void); extern bool tick_nohz_idle_got_tick(void); +extern ktime_t tick_nohz_get_next_hrtimer(void); extern ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next); extern unsigned long tick_nohz_get_idle_calls(void); extern unsigned long tick_nohz_get_idle_calls_cpu(int cpu); @@ -145,7 +146,11 @@ static inline void tick_nohz_idle_restart_tick(void) { } static inline void tick_nohz_idle_enter(void) { } static inline void tick_nohz_idle_exit(void) { } static inline bool tick_nohz_idle_got_tick(void) { return false; } - +static inline ktime_t tick_nohz_get_next_hrtimer(void) +{ + /* Next wake up is the tick period, assume it starts now */ + return ktime_add(ktime_get(), TICK_NSEC); +} static inline ktime_t tick_nohz_get_sleep_length(ktime_t *delta_next) { *delta_next = TICK_NSEC; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 6fa52cd6df0b..8d18e03124ff 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -1022,6 +1022,18 @@ bool tick_nohz_idle_got_tick(void) return false; } +/** + * tick_nohz_get_next_hrtimer - return the next expiration time for the hrtimer + * or the tick, whatever that expires first. Note that, if the tick has been + * stopped, it returns the next hrtimer. + * + * Called from power state control code with interrupts disabled + */ +ktime_t tick_nohz_get_next_hrtimer(void) +{ + return __this_cpu_read(tick_cpu_device.evtdev)->next_event; +} + /** * tick_nohz_get_sleep_length - return the expected length of the current sleep * @delta_next: duration until the next event if the tick cannot be stopped From patchwork Wed Feb 27 19:58:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 10832249 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 63FE9139A for ; Wed, 27 Feb 2019 19:59:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3AF2E2A3EB for ; Wed, 27 Feb 2019 19:59:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 239342E596; Wed, 27 Feb 2019 19:59:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 47B7B29A57 for ; Wed, 27 Feb 2019 19:59:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730131AbfB0T67 (ORCPT ); Wed, 27 Feb 2019 14:58:59 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:39488 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730263AbfB0T6v (ORCPT ); Wed, 27 Feb 2019 14:58:51 -0500 Received: by mail-lj1-f193.google.com with SMTP id g80so14986567ljg.6 for ; Wed, 27 Feb 2019 11:58:49 -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=0UE75rMIQ1/9Jb6g/TX5/C4pyxCKvxuMKoZQJmTsETs=; b=fs9VQPmQRj1jiGfHFNe+tJQzJI/tPaF4zmdsl+FEfGNRZTQirJtSKBWKu0nP6x9p0P MX0Hbv/cwTvGR2e61LKylfYtHNgmn/DmeP8G+mBoDwMTa/1krseYVY1yHowfF6DtZZyG NvWrUlGUdS3p0z34XIAdAmqWDhOv9yUvmNyxAO1Js0VvKRfEOmphrUyuYAHMDesJrnZe HSSzhaYavELPrv+OHmP5NeS1Xmddt1qkqXM56BGOkN3vk6QbPckGwmHYf6VMkMwyh+td 0+KksbCPy+IGogdMyDlbvZHrwOfRgEJkDZx4VOYUZzPK8rxhrzuZfF+qgYO4vlF9+hSl aOIw== 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=0UE75rMIQ1/9Jb6g/TX5/C4pyxCKvxuMKoZQJmTsETs=; b=DldnFP/yuRFdYj/X+uRNsJzHbc0RtShRZhHJmD6nlvqek9va96/VTNd19qfFoWiMkI alsErDj1fsnNw3d9KVneC5TpMOb0dV4tnn7ycSNzKQy4Xl5krBMZIhj0PlfW28oefpDY tnAeLVwGoVMlgmPzyiXwC8l67JmXZIR5PvhkAdbWXr73W41gvKufu2hiQF06S/rNBhJ8 oVN8UznWSbipQ2g8rVBRXi8jZsRTPDAY4pqZpsM9JBFCzFW3+v2BTLl/tEArR2zEL5wE xROXtA0n2IAlL3gXlrTtPnNTqSkuGQs/6sllVBUR0flpC9yY1Wl0RsDEy+MjvVzkKJWX 2I7A== X-Gm-Message-State: APjAAAVrfbmr3NQW4ZRNI57eNsll9MJ2lNLX4SWE56ixFPZu9IFCfd4X 7441DWk0gYdEUxI2eYX4Lca+xg== X-Google-Smtp-Source: APXvYqzgcYN6BOjXkQsZhyiVuASKF6e74OjwL//SPfBfIgNC+i7ZJXtxi2TwaSAwvDwqowOVbiFCqA== X-Received: by 2002:a2e:680e:: with SMTP id c14mr2469128lja.51.1551297528417; Wed, 27 Feb 2019 11:58:48 -0800 (PST) Received: from localhost.localdomain (h-158-174-22-210.NA.cust.bahnhof.se. [158.174.22.210]) by smtp.gmail.com with ESMTPSA id z128sm723802lfa.60.2019.02.27.11.58.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Feb 2019 11:58:47 -0800 (PST) From: Ulf Hansson To: "Rafael J . Wysocki" , linux-pm@vger.kernel.org Cc: Frederic Weisbecker , Thomas Gleixner , Sudeep Holla , Lorenzo Pieralisi , Mark Rutland , Daniel Lezcano , "Raju P . L . S . S . S . N" , Stephen Boyd , Tony Lindgren , Kevin Hilman , Lina Iyer , Ulf Hansson , Viresh Kumar , Vincent Guittot , Geert Uytterhoeven , linux-arm-kernel@lists.infradead.org, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v12 4/4] PM / Domains: Add genpd governor for CPUs Date: Wed, 27 Feb 2019 20:58:36 +0100 Message-Id: <20190227195836.24739-5-ulf.hansson@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190227195836.24739-1-ulf.hansson@linaro.org> References: <20190227195836.24739-1-ulf.hansson@linaro.org> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP As it's now perfectly possible that a PM domain managed by genpd contains devices belonging to CPUs, we should start to take into account the residency values for the idle states during the state selection process. The residency value specifies the minimum duration of time, the CPU or a group of CPUs, needs to spend in an idle state to not waste energy entering it. To deal with this, let's add a new genpd governor, pm_domain_cpu_gov, that may be used for a PM domain that have CPU devices attached or if the CPUs are attached through subdomains. The new governor computes the minimum expected idle duration time for the online CPUs being attached to the PM domain and its subdomains. Then in the state selection process, trying the deepest state first, it verifies that the idle duration time satisfies the state's residency value. It should be noted that, when computing the minimum expected idle duration time, we use the information about the next timer/tick that is stored in the per CPU variable, cpuidle_devices, for the related CPUs. Future wise, this deserves to be improved, as there are obviously more reasons to why a CPU may be woken up from idle. Cc: Lina Iyer Co-developed-by: Lina Iyer Signed-off-by: Ulf Hansson Acked-by: Daniel Lezcano --- Changes in v12: - Rebased. --- drivers/base/power/domain_governor.c | 62 +++++++++++++++++++++++++++- include/linux/pm_domain.h | 3 ++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 99896fbf18e4..fb8fd21e69a7 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include static int dev_update_qos_constraint(struct device *dev, void *data) { @@ -211,8 +214,10 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) struct generic_pm_domain *genpd = pd_to_genpd(pd); struct gpd_link *link; - if (!genpd->max_off_time_changed) + if (!genpd->max_off_time_changed) { + genpd->state_idx = genpd->cached_power_down_state_idx; return genpd->cached_power_down_ok; + } /* * We have to invalidate the cached results for the masters, so @@ -237,6 +242,7 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) genpd->state_idx--; } + genpd->cached_power_down_state_idx = genpd->state_idx; return genpd->cached_power_down_ok; } @@ -245,6 +251,55 @@ static bool always_on_power_down_ok(struct dev_pm_domain *domain) return false; } +static bool cpu_power_down_ok(struct dev_pm_domain *pd) +{ + struct generic_pm_domain *genpd = pd_to_genpd(pd); + struct cpuidle_device *dev; + ktime_t domain_wakeup; + s64 idle_duration_ns; + int cpu, i; + + /* Validate dev PM QoS constraints. */ + if (!default_power_down_ok(pd)) + return false; + + if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN)) + return true; + + /* + * Find the next wakeup for any of the online CPUs within the PM domain + * and its subdomains. Note, we only need the genpd->cpus, as it already + * contains a mask of all CPUs from subdomains. + */ + domain_wakeup = ktime_set(KTIME_SEC_MAX, 0); + for_each_cpu_and(cpu, genpd->cpus, cpu_online_mask) { + dev = per_cpu(cpuidle_devices, cpu); + if (dev && ktime_before(dev->next_hrtimer, domain_wakeup)) + domain_wakeup = dev->next_hrtimer; + } + + /* The minimum idle duration is from now - until the next wakeup. */ + idle_duration_ns = ktime_to_ns(ktime_sub(domain_wakeup, ktime_get())); + if (idle_duration_ns <= 0) + return false; + + /* + * Find the deepest idle state that has its residency value satisfied + * and by also taking into account the power off latency for the state. + * Start at the state picked by the dev PM QoS constraint validation. + */ + i = genpd->state_idx; + do { + if (idle_duration_ns >= (genpd->states[i].residency_ns + + genpd->states[i].power_off_latency_ns)) { + genpd->state_idx = i; + return true; + } + } while (--i >= 0); + + return false; +} + struct dev_power_governor simple_qos_governor = { .suspend_ok = default_suspend_ok, .power_down_ok = default_power_down_ok, @@ -257,3 +312,8 @@ struct dev_power_governor pm_domain_always_on_gov = { .power_down_ok = always_on_power_down_ok, .suspend_ok = default_suspend_ok, }; + +struct dev_power_governor pm_domain_cpu_gov = { + .suspend_ok = default_suspend_ok, + .power_down_ok = cpu_power_down_ok, +}; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index a6e251fe9deb..ae7061556a26 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -118,6 +118,7 @@ struct generic_pm_domain { s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; bool cached_power_down_ok; + bool cached_power_down_state_idx; int (*attach_dev)(struct generic_pm_domain *domain, struct device *dev); void (*detach_dev)(struct generic_pm_domain *domain, @@ -202,6 +203,7 @@ 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; +extern struct dev_power_governor pm_domain_cpu_gov; #else static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) @@ -245,6 +247,7 @@ static inline int dev_pm_genpd_set_performance_state(struct device *dev, #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) +#define pm_domain_cpu_gov (*(struct dev_power_governor *)(NULL)) #endif #ifdef CONFIG_PM_GENERIC_DOMAINS_SLEEP