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: 159289 Delivered-To: patches@linaro.org Received: by 2002:a02:5cc1:0:0:0:0:0 with SMTP id w62csp4833404jad; Wed, 27 Feb 2019 11:58:43 -0800 (PST) X-Received: by 2002:a19:8094:: with SMTP id b142mr1875130lfd.117.1551297523140; Wed, 27 Feb 2019 11:58:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551297523; cv=none; d=google.com; s=arc-20160816; b=rpRJft/KTn34QT49/fXVNJSJXtn1aNLxwrR1fOO/vCfa8ZTDPYYl4gXpHeMH1cYMEu JsENnzcBz0EYjmvgoXrkC/BELjTfqLAkwueycjlJxG6D3Toi4abmPhCgWSWCBBMivAhs fsFG8URC3VwlYlAjhd/QzuwOP7RglHgio3T/r1s++S8pvQV7OX3Ibclq5acd5veZlnKO Gk7jjnsAlLwjxW3C11dK7OdrW+tY8AKQJSdngrDxYQ2aablsCO439n9BGu4Pzm1C0Rog zmPMIb31orQePhXz//ZYpJqCOcmVyhThOg237WnxqpX2AnTakgjEFnxJMbn1svcQDs7p JSgw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=XKFXfVA/MFOFOm3N3DxhXtUoRuHmZYEZxmpq4iLOsS0=; b=tIlexEhijS0eDMdrflhHE1yIxS6bXRfHFTiLoxGSKq/2FNG1ozzmlkpkqwM8ae7eET 0gsYbBj09G0jlM+k6JnJo1cFzzyq/My4Pr7ovxZhHQXzUSGuCNaS8a1oHcoCjViEQDpQ rAtCVVorazEN5CrxwX8dZHoOD+/Qr+MlGXYRCF4wiP0/cYw4VMbP9hjn+A2DB8QP68Ci iFeXMbAHB4wTOL7G7OjgoFwl0D9o8vy9ZoCl9MAf45+WSyvUJ0swUPVBpOEz5rcrac4P +4WJXgnAI6LXa/tt1bCBg7lUrjqEA3EPsWmv01RxWDek+m/+Xt/5Bv5FD7rB7Um3gOB3 8GQA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BCNOViW0; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id d3sor10169901ljj.39.2019.02.27.11.58.42 for (Google Transport Security); Wed, 27 Feb 2019 11:58:43 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BCNOViW0; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=W0yawMxSki6xCPY9navIl7FWRaOTFHPBlZLt7wdMTbQBRRVkTGaVu7/iZiA1QF2GLG cJtcfBXcNR4uMiPU090JjgkKZte2Ev/zO+tZ0PqdVwqEgFOcpJVzA7Y24DI3gZQDA0EY wMpIKAAVMTd3tfWpj5Ge6FP5ujLK0s1FW7QpEVTF2W5b8LxfCl7+4YPf6pCwc168lGJE DuuMbvWQyL75ltdGTpDAeNx9iFxXT4dWbHKJgXpuVl7WAoDlPcY4iUJJODals9PfpK2M OWUSoMRNlpEPW7WiuFgjdfi4z/RpM1hK+ak3U/M1ez8vZv8xffZkWfWxk+LzqGVcs2km Gehw== X-Gm-Message-State: AHQUAuY94Uahmncp7Hkg5RoVt/Zca3VJRA5mDPLfRJ0ghnpjgzO2HJJ2 T5dULgfU+o9NH1oDi5R+UG8BvM/C 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) Return-Path: 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> 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 --- Changes in v12: - None. --- drivers/base/power/domain.c | 12 ++++++++++-- include/linux/pm_domain.h | 4 +++- 2 files changed, 13 insertions(+), 3 deletions(-) -- 2.17.1 Acked-by: Daniel Lezcano 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: 159290 Delivered-To: patches@linaro.org Received: by 2002:a02:5cc1:0:0:0:0:0 with SMTP id w62csp4833443jad; Wed, 27 Feb 2019 11:58:45 -0800 (PST) X-Received: by 2002:a2e:a0cb:: with SMTP id f11mr2635094ljm.55.1551297525394; Wed, 27 Feb 2019 11:58:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551297525; cv=none; d=google.com; s=arc-20160816; b=ssPeUJNVZN5Hzb6d+wv8x5NV+iDMcBggbUxH241ofOjgWqqzYxbJUGN3QaJEyzZv3s Gc+xgkKFzg4mRSqSxJwEwUhiiNPfhr6Sjj0FgDLA3bkblouFTAJluPaMREDu3AmFAF7K yUtAJQj1g5on7DHjaTVYo2KrVNS1DJCx6vEpJ/0TW0eeWyjMzswnEtxl5qRPkJaDlyA5 ZiZNNpnryd2ITdBVmk7eVPEjklWtBREPqoTUGSFw9N/prUvekn4pDyQUitcEthFIGkF6 OQxsaPT6ouxR77OXGs1qDNipsqDHPIcPlshTs3FDMmE+WdR1LKpl12RdcEqWjEt+Dw6w E2IQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=TSS7UyhFKusvN1QpHYAVmHi7+a3wd/308ysavr6LVN8=; b=KIM9gDICRuPY9i0UYG5qiOl/LjjVrMYAeZditZdeGBovWAa5XaJ7JWT0uptUihoDml TmAhhMx9dTfhCBoeXd9/uCBywBT9CIDV2FWwyIXEVCSbvwKU8rO0zpcYgBvx6U6kv/92 0fcIbujp9dS7Yqmg6epM7HiFXjRKBdxAfZY46g5IcmJarE5lkPDRB1FXJ0OJGyZMshgV y5iolH4fGU5Rx5PJoDfhmHnyjXY3YGfRUHv5vnzQarCuFwSX0+AVJYwH14X+5ulT5U7j qkwnwfHEea2k958jwEGXy2ycCPyQoflkqa+ZvHngreyDA93kFAj+1ANHMtMXPCM5X+bw GMHA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ptMtJ10i; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id b16sor4059502lji.16.2019.02.27.11.58.45 for (Google Transport Security); Wed, 27 Feb 2019 11:58:45 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ptMtJ10i; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=GS7AFfNVHxjam0QP1cns9LUVvUy2c6Pydffr0G6d6w6svGh4QbrG5AIqmS614ZTyhZ p1yOulS//QG4ZqYDW7aAn+Ig9aGEUUSJgaqbLCrlrllrh+gksNgoWcPaLRQ6PpVxrdVf bYEysLeCoCSW5tYc3nU3CHpxVkT8jw/2l0BczB8ubJeI44RWyEgR+HKxdrQz6/3nVNdM oC5do+YE4ZeKibOsn/cDG/8qpEEt9M2xmzv9hBJl2D9aCUr0twLCrqJNXaFh2lz5vJ7T PYefC8CL/eznP4hDNYbHSJJulMbsBQ+szrUYN0fo2Sj80ZxkL5s7kEgpo0OPJbPF30tv fnVA== X-Gm-Message-State: APjAAAUm8FfNgdvCLZuS4IRZ7rtGC7I9Sn5Hba6/hnSo2oH8545q3/SN M8331bPobOCNGPk4QDxVdNp8nRUe 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) Return-Path: 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> 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 --- Changes in v12: - None. --- drivers/base/power/domain.c | 66 ++++++++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 13 ++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) -- 2.17.1 Acked-by: Daniel Lezcano 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: 159291 Delivered-To: patches@linaro.org Received: by 2002:a02:5cc1:0:0:0:0:0 with SMTP id w62csp4833471jad; Wed, 27 Feb 2019 11:58:47 -0800 (PST) X-Received: by 2002:a19:384a:: with SMTP id d10mr1857908lfj.111.1551297527018; Wed, 27 Feb 2019 11:58:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551297527; cv=none; d=google.com; s=arc-20160816; b=hgMKq3OhlaIk2aG/AkTLXpIIkYp+3WQeHYE6wuhIRRNXBp5IQGplW5V1cXtIN6bk6w MC4/u1TW9DnShbum6eIlDWeEYtaXR66EtJ52AbY5p9MWerdln4b6XPnn+xiHVB8Ro0Ch yP6ujww7tVSgtwssn2UVRjz86PtlJSb6RTH2ojXETJigGmXseseTd5F8es8B/CL+SLIY V5irsibZNHsvnLNJ9hW/aVv7vxpn0oYcMaiGbWyr7MsA3H5X15oCOUad39KStho0SjFw PywPMpn6eRihC6UcrwMe/N2F8yfPrVJvNsrVedCOCQ7BQgzQ50xKO7xv/RkBkMpQ/yiN WBvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=I9FC+10KjcWm9oxkGkEiLX6p0r263JrQVxFR/hZ1DCo=; b=W31mZrVUDmJ+kL6tJD78suyGvH7LcJYJF3fWXyvXrG78ZTC4ao+EDYUVVqrgRk/sOk nWKYWnXcI6gexPo/hKthJi9+J06gM+DO1dA3jFPezjal1CskW5PgA3WRRh+PHbpSE/oz 90pjhShO9k66AcDChYDsiQI6c43oE4XlUrm4fXluyeTZEUu4uMIptkLeK+NsBEpTEcg0 3rOTZhJTUo/2wi73718RFTPqDNLG+iS2B8SXLqiw4ADkECpUnQmxdOmP2SBJhqgw3M7A rQypQLxlMia+jddJsgy56A0ODrU02C7CdtfTxHwAqaOhws8kLRzlT6HZuRQaQ1lNi4EQ DYNw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="W/O0gxne"; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id r13sor4680904lfm.8.2019.02.27.11.58.46 for (Google Transport Security); Wed, 27 Feb 2019 11:58:47 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="W/O0gxne"; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=BhQHus2e262x6/RMc0ebq6KVi1aPGAsbx3WcOe0U0flUFOO489Vql3tOOni9ax6A3V zwjmHFZSdc7f19bVhtJGPm3PYM+2+8jivelal4mw7fx47oJe87EGXyzAVQXjuVI+uDeI MBpNFeTdUPZKvPkuOtBhzBy6bumD4J+uolGc09m3GL0T2k01nsNbmurM56lj+rQyPz1x LTbwRrsHHlEPmoCNJtzn/s6uXAdTgTaqRCDUBRY0UuZ/g5Y/dUylkW9EhLKbspwtYhcu rX9Mi8P5JvSlUSSla1LSRX4fgU+pGdZiOjc0HQffNE22uJGkn1eNERD0SproPuTXABdK 4WTA== X-Gm-Message-State: AHQUAuYilT7HtO0Cmp97Z3FS0IPokO1Z6JieDJYsDd9/n/ZLeXYMMiAR MC5RJpIqC4V7EK9X32BcmTZT18zF 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) Return-Path: 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> 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 --- 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(-) -- 2.17.1 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: 159292 Delivered-To: patches@linaro.org Received: by 2002:a02:5cc1:0:0:0:0:0 with SMTP id w62csp4833505jad; Wed, 27 Feb 2019 11:58:48 -0800 (PST) X-Received: by 2002:a2e:96c9:: with SMTP id d9mr2390387ljj.133.1551297528893; Wed, 27 Feb 2019 11:58:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551297528; cv=none; d=google.com; s=arc-20160816; b=GLuTM8M66yOjB7WIQ1Tzu4aRhXfMVHVc+a/oINdjylCW6mBsqyhVfEQk7t4xtKSDTt G88inEq190NTpNpRarBV02xwhCWDL1NQCVINXBThN4JsVJv/Fl/Lh/4rE/6qKIS0R9I7 r7JCSdAmeBj+Lcrvf42F65pDz2cWh9o979IBnMEwF/1JuSkqThA8Vr5jeDhY9zjex2QA DaQrsQH/5sbyG0E63gomrpq2BKjALFcefJRj3/j+0y4bvMAmixUoGl9I1GNukKJ2JAHd vxxjC8wAamrh9FWIrsczvUz26edlspsZnU4QJvrybaIG2SBFtidCe8JmnH9zJm4z35U9 gKsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=0UE75rMIQ1/9Jb6g/TX5/C4pyxCKvxuMKoZQJmTsETs=; b=0U7vgAD3yUBsIi+a0liMHhabzo4irEsj4K7JSgXfyeEuF0SyyoMyknlctM1N535kMJ pA7OkvEd1LbpYqtTtTxkjjF7ZoV4JJiQBWbazaqFLfcs/swlKPZLHcsc8aihEeJnOCp+ 3dcipCtAIqInlQkSAHe2fKIPFigBhWE3tRVqeni3KXQR1CSI0RL/DGM6Bvrfb8FIs0Yc MnnakKk8ddios+ThWLO7f+JhEMZ8ZKbiV1Uzi8XrUBpcF0pEZ1bXJNzTcJji7xjLHAOh roORqhpBJkxCtJJa3tPmS3cV9Gmb/myt5Bp6JeKCQMvlkmKwqby8ZEDVqwvKMb0U/PGP HW/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fs9VQPmQ; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id e23sor9975653ljg.25.2019.02.27.11.58.48 for (Google Transport Security); Wed, 27 Feb 2019 11:58:48 -0800 (PST) Received-SPF: pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fs9VQPmQ; spf=pass (google.com: domain of ulf.hansson@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=ulf.hansson@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=iSB/V75JtDc+7ECKibh9uiPXvIMy1G33mqnbdjRTJOWgr6Pu77HKECrHjzA7zr9ZoX TaxGjJ/wSc7nu3jd1bGH+581IQJTntAB3WIB4JQWnnv2dm1tbygFg9YSwfnf6Gx1U13Y CBniCz7A2OXhaC8STXt+AlL7tAiE8rfEJ2aQMsN3rQp04+lljc1RTZcjmJQBzifR/8f+ d5oG5qXp0MHx7TAkXY/wEy+9tU+G19mZ2AnOPhpg55/MXdiu8zAwoPEJOKW7wb4pndZ7 UzUTJOBd+20u9axFrzZIo5frIbq8S++Z3xpsYlhOVriMF9tf0NaK2GyZQwtvAoGPQHTD EyHg== X-Gm-Message-State: APjAAAWfJ/tRqrrtSdehbLfJFCZ6f758n2kkJj8wrEc2obGh2bH0TqRO 86Ow/g9huPHABeodxQs2+UA75h2e 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) Return-Path: 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> 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 --- Changes in v12: - Rebased. --- drivers/base/power/domain_governor.c | 62 +++++++++++++++++++++++++++- include/linux/pm_domain.h | 3 ++ 2 files changed, 64 insertions(+), 1 deletion(-) -- 2.17.1 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