linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] Register an Energy Model for Arm reference platforms
@ 2019-02-01  9:30 Quentin Perret
  2019-02-01  9:30 ` [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Quentin Perret @ 2019-02-01  9:30 UTC (permalink / raw)
  To: viresh.kumar, sudeep.holla, rjw, nm, sboyd, mka
  Cc: linux-pm, linux-kernel, linux-arm-kernel, dietmar.eggemann,
	quentin.perret

The Energy Model (EM) framework feeds interested subsystems (the
scheduler/EAS as of now) with power costs provided by drivers. Yet, no
driver is actually doing that upstream yet. This series updates a set of
CPUFreq drivers in order to register power costs in the EM framework for
some of the Arm reference platforms for EAS: Hikey960, Juno and TC2.

The series is split as follows:
 - Patch 01 introduces in PM_OPP a helper function which estimates the
   CPU power using the P=CV²f equation also used by IPA. It should be
   noted that this introduces duplicate code with IPA, which will
   eventually be fixed by migrating IPA to using PM_EM. The ideal plan
   would be to do so later, in a separate patch series. I would indeed
   prefer to keep the thermal and CPUFreq discussion separate at this
   stage, if deemed acceptable.
 - Patches 02-04 make use of that PM_OPP helper function from the
   following CPUFreq drivers: cpufreq-dt, scpi-cpufreq and
   arm_big_little.
 - Patch 05 modifies the SCMI cpufreq driver to pass the power costs
   obtained from firmware to PM_EM. This patch is independent from the
   rest of the series.

Changes since v2 (20190130170506.20450-1-quentin.perret@arm.com)
 - Added comment to explain why we check only the dynamic-power-coeff
   property and not voltages in dev_pm_opp_of_register_em() (Viresh)
 - Fixed comments/docstrings of new functions in opp/of.c (Matthias)
 - Added Matthias' Tested-by to patch 01

Changes since v1 (20190128165522.31749-1-quentin.perret@arm.com):
 - Dropped the DT patches that have been queued by Sudeep
 - Introduced dev_pm_opp_of_register_em() helper to check the presence
   of the DT coeff before calling PM_EM (Viresh, Matthias)
 - Coding-style improvements (Viresh, Matthias)

Thanks,
Quentin

Dietmar Eggemann (1):
  cpufreq: arm_big_little: Register an Energy Model

Quentin Perret (4):
  PM / OPP: Introduce a power estimation helper
  cpufreq: dt: Register an Energy Model
  cpufreq: scpi: Register an Energy Model
  cpufreq: scmi: Register an Energy Model

 drivers/cpufreq/arm_big_little.c |  8 +++
 drivers/cpufreq/cpufreq-dt.c     |  8 ++-
 drivers/cpufreq/scmi-cpufreq.c   | 39 ++++++++++++-
 drivers/cpufreq/scpi-cpufreq.c   |  9 ++-
 drivers/opp/of.c                 | 96 ++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h           |  6 ++
 6 files changed, 157 insertions(+), 9 deletions(-)

-- 
2.20.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-01  9:30 [PATCH v3 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
@ 2019-02-01  9:30 ` Quentin Perret
  2019-02-01 12:04   ` Sudeep Holla
  2019-02-01  9:30 ` [PATCH v3 2/5] cpufreq: dt: Register an Energy Model Quentin Perret
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Quentin Perret @ 2019-02-01  9:30 UTC (permalink / raw)
  To: viresh.kumar, sudeep.holla, rjw, nm, sboyd, mka
  Cc: linux-pm, linux-kernel, linux-arm-kernel, dietmar.eggemann,
	quentin.perret

The Energy Model (EM) framework provides an API to let drivers register
the active power of CPUs. The drivers are expected to provide a callback
method which estimates the power consumed by a CPU at each available
performance levels. How exactly this should be implemented, however,
depends on the platform.

On some systems, PM_OPP knows the voltage and frequency at which CPUs
can run. When coupled with the CPU 'capacitance' (as provided by the
'dynamic-power-coefficient' devicetree binding), it is possible to
estimate the dynamic power consumption of a CPU as P = C * V^2 * f, with
C its capacitance and V and f respectively the voltage and frequency of
the OPP. The Intelligent Power Allocator (IPA) thermal governor already
implements that estimation method, in the thermal framework.

However, this power estimation method can be applied to any platform
where all the parameters are known (C, V and f), and not only those
suffering thermal issues. As such, the code implementing this feature
can be re-used to also populate the EM framework now used by EAS.

As a first step, introduce in PM_OPP a helper function which CPUFreq
drivers can use to register into the EM framework. This duplicates the
power estimation done in IPA until it can be migrated to using the EM
framework. This will be done later, once the EM framework has support
for at least all platforms currently supported by IPA.

Signed-off-by: Quentin Perret <quentin.perret@arm.com>
Tested-by: Matthias Kaehlcke <mka@chromium.org>
---
 drivers/opp/of.c       | 96 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h |  6 +++
 2 files changed, 102 insertions(+)

diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 06f0f632ec47..4bde13d94dc2 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -20,6 +20,7 @@
 #include <linux/pm_domain.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/energy_model.h>
 
 #include "opp.h"
 
@@ -1047,3 +1048,98 @@ struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp)
 	return of_node_get(opp->np);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node);
+
+/*
+ * Callback function provided to the Energy Model framework upon registration.
+ * This computes the power estimated by @CPU at @kHz if it is the frequency
+ * of an existing OPP, or at the frequency of the first OPP above @kHz otherwise
+ * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled
+ * frequency and @mW to the associated power. The power is estimated as
+ * P = C * V^2 * f with C being the CPU's capacitance and V and f respectively
+ * the voltage and frequency of the OPP.
+ *
+ * Returns -ENODEV if the CPU device cannot be found, -EINVAL if the power
+ * calculation failed because of missing parameters, 0 otherwise.
+ */
+static int __maybe_unused _get_cpu_power(unsigned long *mW, unsigned long *kHz,
+					 int cpu)
+{
+	struct device *cpu_dev;
+	struct dev_pm_opp *opp;
+	struct device_node *np;
+	unsigned long mV, Hz;
+	u32 cap;
+	u64 tmp;
+	int ret;
+
+	cpu_dev = get_cpu_device(cpu);
+	if (!cpu_dev)
+		return -ENODEV;
+
+	np = of_node_get(cpu_dev->of_node);
+	if (!np)
+		return -EINVAL;
+
+	ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap);
+	of_node_put(np);
+	if (ret)
+		return -EINVAL;
+
+	Hz = *kHz * 1000;
+	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &Hz);
+	if (IS_ERR(opp))
+		return -EINVAL;
+
+	mV = dev_pm_opp_get_voltage(opp) / 1000;
+	dev_pm_opp_put(opp);
+	if (!mV)
+		return -EINVAL;
+
+	tmp = (u64)cap * mV * mV * (Hz / 1000000);
+	do_div(tmp, 1000000000);
+
+	*mW = (unsigned long)tmp;
+	*kHz = Hz / 1000;
+
+	return 0;
+}
+
+/**
+ * dev_pm_opp_of_register_em() - Attempt to register an Energy Model
+ * @cpus	: CPUs for which an Energy Model has to be registered
+ * @nr_opp	: Number of OPPs to register in the Energy Model
+ *
+ * This checks whether the "dynamic-power-coefficient" devicetree property has
+ * been specified, and tries to register an Energy Model with it if it has.
+ */
+void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
+{
+	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
+	int ret, cpu = cpumask_first(cpus);
+	struct device *cpu_dev;
+	struct device_node *np;
+	u32 cap;
+
+	cpu_dev = get_cpu_device(cpu);
+	if (!cpu_dev)
+		return;
+
+	np = of_node_get(cpu_dev->of_node);
+	if (!np)
+		return;
+
+	/*
+	 * Register an EM _only_ if the 'dynamic-power-coefficient' property is
+	 * set in devicetree. It is assumed the voltage values are known if that
+	 * property is set since it is useless otherwise. If voltages are not
+	 * known, just let the EM registration fail with an error to alert the
+	 * user about the inconsistent configuration.
+	 */
+	ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap);
+	of_node_put(np);
+	if (ret || !cap)
+		return;
+
+	em_register_perf_domain(cpus, nr_opp, &em_cb);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_register_em);
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index b895f4e79868..58ae08b024bd 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -327,6 +327,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpuma
 struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev);
 struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp);
 int of_get_required_opp_performance_state(struct device_node *np, int index);
+void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp);
 #else
 static inline int dev_pm_opp_of_add_table(struct device *dev)
 {
@@ -365,6 +366,11 @@ static inline struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp)
 {
 	return NULL;
 }
+
+static inline void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
+{
+}
+
 static inline int of_get_required_opp_performance_state(struct device_node *np, int index)
 {
 	return -ENOTSUPP;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 2/5] cpufreq: dt: Register an Energy Model
  2019-02-01  9:30 [PATCH v3 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
  2019-02-01  9:30 ` [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
@ 2019-02-01  9:30 ` Quentin Perret
  2019-02-01  9:30 ` [PATCH v3 3/5] cpufreq: scpi: " Quentin Perret
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Quentin Perret @ 2019-02-01  9:30 UTC (permalink / raw)
  To: viresh.kumar, sudeep.holla, rjw, nm, sboyd, mka
  Cc: linux-pm, linux-kernel, linux-arm-kernel, dietmar.eggemann,
	quentin.perret

Now that PM_OPP provides a helper function to estimate the power
consumed by CPUs, make sure to try and register an Energy Model (EM)
from cpufreq-dt, hence ensuring interested subsystems (the task
scheduler, for example) can make use of that information when available.

Signed-off-by: Quentin Perret <quentin.perret@arm.com>
---
 drivers/cpufreq/cpufreq-dt.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index e58bfcb1169e..1d4ad6f67408 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -160,7 +160,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	unsigned int transition_latency;
 	bool fallback = false;
 	const char *name;
-	int ret;
+	int ret, nr_opp;
 
 	cpu_dev = get_cpu_device(policy->cpu);
 	if (!cpu_dev) {
@@ -231,8 +231,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	 * But we need OPP table to function so if it is not there let's
 	 * give platform code chance to provide it for us.
 	 */
-	ret = dev_pm_opp_get_opp_count(cpu_dev);
-	if (ret <= 0) {
+	nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+	if (nr_opp <= 0) {
 		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
 		ret = -EPROBE_DEFER;
 		goto out_free_opp;
@@ -280,6 +280,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.transition_latency = transition_latency;
 	policy->dvfs_possible_from_any_cpu = true;
 
+	dev_pm_opp_of_register_em(policy->cpus, nr_opp);
+
 	return 0;
 
 out_free_cpufreq_table:
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 3/5] cpufreq: scpi: Register an Energy Model
  2019-02-01  9:30 [PATCH v3 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
  2019-02-01  9:30 ` [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
  2019-02-01  9:30 ` [PATCH v3 2/5] cpufreq: dt: Register an Energy Model Quentin Perret
@ 2019-02-01  9:30 ` Quentin Perret
  2019-02-01  9:31 ` [PATCH v3 4/5] cpufreq: arm_big_little: " Quentin Perret
  2019-02-01  9:31 ` [PATCH v3 5/5] cpufreq: scmi: " Quentin Perret
  4 siblings, 0 replies; 13+ messages in thread
From: Quentin Perret @ 2019-02-01  9:30 UTC (permalink / raw)
  To: viresh.kumar, sudeep.holla, rjw, nm, sboyd, mka
  Cc: linux-pm, linux-kernel, linux-arm-kernel, dietmar.eggemann,
	quentin.perret

Now that PM_OPP provides a helper function to estimate the power
consumed by CPUs, make sure to try and register an Energy Model (EM)
from scpi-cpufreq, hence ensuring interested subsystems (the task
scheduler, for example) can make use of that information when available.

Signed-off-by: Quentin Perret <quentin.perret@arm.com>
---
 drivers/cpufreq/scpi-cpufreq.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 99449738faa4..8e77a67a8d8c 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -98,7 +98,7 @@ scpi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 
 static int scpi_cpufreq_init(struct cpufreq_policy *policy)
 {
-	int ret;
+	int ret, nr_opp;
 	unsigned int latency;
 	struct device *cpu_dev;
 	struct scpi_data *priv;
@@ -129,8 +129,8 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
 		return ret;
 	}
 
-	ret = dev_pm_opp_get_opp_count(cpu_dev);
-	if (ret <= 0) {
+	nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+	if (nr_opp <= 0) {
 		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
 		ret = -EPROBE_DEFER;
 		goto out_free_opp;
@@ -170,6 +170,9 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.transition_latency = latency;
 
 	policy->fast_switch_possible = false;
+
+	dev_pm_opp_of_register_em(policy->cpus, nr_opp);
+
 	return 0;
 
 out_free_cpufreq_table:
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 4/5] cpufreq: arm_big_little: Register an Energy Model
  2019-02-01  9:30 [PATCH v3 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
                   ` (2 preceding siblings ...)
  2019-02-01  9:30 ` [PATCH v3 3/5] cpufreq: scpi: " Quentin Perret
@ 2019-02-01  9:31 ` Quentin Perret
  2019-02-01 11:53   ` Sudeep Holla
  2019-02-01  9:31 ` [PATCH v3 5/5] cpufreq: scmi: " Quentin Perret
  4 siblings, 1 reply; 13+ messages in thread
From: Quentin Perret @ 2019-02-01  9:31 UTC (permalink / raw)
  To: viresh.kumar, sudeep.holla, rjw, nm, sboyd, mka
  Cc: linux-pm, linux-kernel, linux-arm-kernel, dietmar.eggemann,
	quentin.perret

From: Dietmar Eggemann <dietmar.eggemann@arm.com>

Now that PM_OPP provides a helper function to estimate the power
consumed by CPUs, make sure to try and register an Energy Model (EM)
from the arm_big_little CPUFreq driver, hence ensuring interested
subsystems (the task scheduler, for example) can make use of that
information when available.

Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
---
 drivers/cpufreq/arm_big_little.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index cf62a1f64dd7..18b05bcb2614 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -487,6 +487,14 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.transition_latency =
 				arm_bL_ops->get_transition_latency(cpu_dev);
 
+	ret = dev_pm_opp_get_opp_count(cpu_dev);
+	if (ret <= 0) {
+		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
+		return -EPROBE_DEFER;
+	}
+
+	dev_pm_opp_of_register_em(policy->cpus, ret);
+
 	if (is_bL_switching_enabled())
 		per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 5/5] cpufreq: scmi: Register an Energy Model
  2019-02-01  9:30 [PATCH v3 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
                   ` (3 preceding siblings ...)
  2019-02-01  9:31 ` [PATCH v3 4/5] cpufreq: arm_big_little: " Quentin Perret
@ 2019-02-01  9:31 ` Quentin Perret
  4 siblings, 0 replies; 13+ messages in thread
From: Quentin Perret @ 2019-02-01  9:31 UTC (permalink / raw)
  To: viresh.kumar, sudeep.holla, rjw, nm, sboyd, mka
  Cc: linux-pm, linux-kernel, linux-arm-kernel, dietmar.eggemann,
	quentin.perret

The Energy Model (EM) framework provides an API to register the active
power of CPUs. Call this API from the scmi-cpufreq driver by using the
power costs obtained from firmware. This is done to ensure interested
subsystems (the task scheduler, for example) can make use of the EM
when available.

Signed-off-by: Quentin Perret <quentin.perret@arm.com>
---
 drivers/cpufreq/scmi-cpufreq.c | 39 +++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index 242c3370544e..0d87e1433296 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -12,6 +12,7 @@
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/cpu_cooling.h>
+#include <linux/energy_model.h>
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/pm_opp.h>
@@ -103,13 +104,42 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 	return 0;
 }
 
+static int __maybe_unused
+scmi_get_cpu_power(unsigned long *power, unsigned long *KHz, int cpu)
+{
+	struct device *cpu_dev = get_cpu_device(cpu);
+	unsigned long Hz;
+	int ret, domain;
+
+	if (!cpu_dev) {
+		pr_err("failed to get cpu%d device\n", cpu);
+		return -ENODEV;
+	}
+
+	domain = handle->perf_ops->device_domain_id(cpu_dev);
+	if (domain < 0)
+		return domain;
+
+	/* Get the power cost of the performance domain. */
+	Hz = *KHz * 1000;
+	ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power);
+	if (ret)
+		return ret;
+
+	/* The EM framework specifies the frequency in KHz. */
+	*KHz = Hz / 1000;
+
+	return 0;
+}
+
 static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 {
-	int ret;
+	int ret, nr_opp;
 	unsigned int latency;
 	struct device *cpu_dev;
 	struct scmi_data *priv;
 	struct cpufreq_frequency_table *freq_table;
+	struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power);
 
 	cpu_dev = get_cpu_device(policy->cpu);
 	if (!cpu_dev) {
@@ -136,8 +166,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 		return ret;
 	}
 
-	ret = dev_pm_opp_get_opp_count(cpu_dev);
-	if (ret <= 0) {
+	nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+	if (nr_opp <= 0) {
 		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
 		ret = -EPROBE_DEFER;
 		goto out_free_opp;
@@ -171,6 +201,9 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.transition_latency = latency;
 
 	policy->fast_switch_possible = true;
+
+	em_register_perf_domain(policy->cpus, nr_opp, &em_cb);
+
 	return 0;
 
 out_free_priv:
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 4/5] cpufreq: arm_big_little: Register an Energy Model
  2019-02-01  9:31 ` [PATCH v3 4/5] cpufreq: arm_big_little: " Quentin Perret
@ 2019-02-01 11:53   ` Sudeep Holla
  2019-02-01 12:11     ` Quentin Perret
  0 siblings, 1 reply; 13+ messages in thread
From: Sudeep Holla @ 2019-02-01 11:53 UTC (permalink / raw)
  To: Quentin Perret
  Cc: viresh.kumar, rjw, nm, sboyd, mka, linux-pm, Sudeep Holla,
	linux-kernel, linux-arm-kernel, dietmar.eggemann

On Fri, Feb 01, 2019 at 09:31:00AM +0000, Quentin Perret wrote:
> From: Dietmar Eggemann <dietmar.eggemann@arm.com>
>
> Now that PM_OPP provides a helper function to estimate the power
> consumed by CPUs, make sure to try and register an Energy Model (EM)
> from the arm_big_little CPUFreq driver, hence ensuring interested
> subsystems (the task scheduler, for example) can make use of that
> information when available.
>
> Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
> Signed-off-by: Quentin Perret <quentin.perret@arm.com>
> ---
>  drivers/cpufreq/arm_big_little.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
> index cf62a1f64dd7..18b05bcb2614 100644
> --- a/drivers/cpufreq/arm_big_little.c
> +++ b/drivers/cpufreq/arm_big_little.c
> @@ -487,6 +487,14 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
>  	policy->cpuinfo.transition_latency =
>  				arm_bL_ops->get_transition_latency(cpu_dev);
>
> +	ret = dev_pm_opp_get_opp_count(cpu_dev);
> +	if (ret <= 0) {
> +		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
> +		return -EPROBE_DEFER;
> +	}

The only user of this has the check in init_opp_table that gets called from
get_cluster_clk_and_freq_table. So the above is not necessary, you can drop
it.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-01  9:30 ` [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
@ 2019-02-01 12:04   ` Sudeep Holla
  2019-02-01 12:09     ` Quentin Perret
  0 siblings, 1 reply; 13+ messages in thread
From: Sudeep Holla @ 2019-02-01 12:04 UTC (permalink / raw)
  To: Quentin Perret
  Cc: viresh.kumar, rjw, nm, sboyd, mka, linux-pm, linux-kernel,
	linux-arm-kernel, dietmar.eggemann

On Fri, Feb 01, 2019 at 09:30:57AM +0000, Quentin Perret wrote:
> The Energy Model (EM) framework provides an API to let drivers register
> the active power of CPUs. The drivers are expected to provide a callback
> method which estimates the power consumed by a CPU at each available
> performance levels. How exactly this should be implemented, however,
> depends on the platform.
> 
> On some systems, PM_OPP knows the voltage and frequency at which CPUs
> can run. When coupled with the CPU 'capacitance' (as provided by the
> 'dynamic-power-coefficient' devicetree binding), it is possible to
> estimate the dynamic power consumption of a CPU as P = C * V^2 * f, with
> C its capacitance and V and f respectively the voltage and frequency of
> the OPP. The Intelligent Power Allocator (IPA) thermal governor already
> implements that estimation method, in the thermal framework.
> 
> However, this power estimation method can be applied to any platform
> where all the parameters are known (C, V and f), and not only those
> suffering thermal issues. As such, the code implementing this feature
> can be re-used to also populate the EM framework now used by EAS.
> 
> As a first step, introduce in PM_OPP a helper function which CPUFreq
> drivers can use to register into the EM framework. This duplicates the
> power estimation done in IPA until it can be migrated to using the EM
> framework. This will be done later, once the EM framework has support
> for at least all platforms currently supported by IPA.
> 
> Signed-off-by: Quentin Perret <quentin.perret@arm.com>
> Tested-by: Matthias Kaehlcke <mka@chromium.org>
> ---
>  drivers/opp/of.c       | 96 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  6 +++
>  2 files changed, 102 insertions(+)
> 
> diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> index 06f0f632ec47..4bde13d94dc2 100644
> --- a/drivers/opp/of.c
> +++ b/drivers/opp/of.c
> @@ -20,6 +20,7 @@
>  #include <linux/pm_domain.h>
>  #include <linux/slab.h>
>  #include <linux/export.h>
> +#include <linux/energy_model.h>
>  
>  #include "opp.h"
>  
> @@ -1047,3 +1048,98 @@ struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp)
>  	return of_node_get(opp->np);
>  }
>  EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node);
> +
> +/*
> + * Callback function provided to the Energy Model framework upon registration.
> + * This computes the power estimated by @CPU at @kHz if it is the frequency
> + * of an existing OPP, or at the frequency of the first OPP above @kHz otherwise
> + * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled
> + * frequency and @mW to the associated power. The power is estimated as
> + * P = C * V^2 * f with C being the CPU's capacitance and V and f respectively
> + * the voltage and frequency of the OPP.
> + *
> + * Returns -ENODEV if the CPU device cannot be found, -EINVAL if the power
> + * calculation failed because of missing parameters, 0 otherwise.
> + */
> +static int __maybe_unused _get_cpu_power(unsigned long *mW, unsigned long *kHz,
> +					 int cpu)
> +{
> +	struct device *cpu_dev;
> +	struct dev_pm_opp *opp;
> +	struct device_node *np;
> +	unsigned long mV, Hz;
> +	u32 cap;
> +	u64 tmp;
> +	int ret;
> +
> +	cpu_dev = get_cpu_device(cpu);
> +	if (!cpu_dev)
> +		return -ENODEV;
> +
> +	np = of_node_get(cpu_dev->of_node);
> +	if (!np)
> +		return -EINVAL;
> +
> +	ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap);
> +	of_node_put(np);
> +	if (ret)
> +		return -EINVAL;
> +
> +	Hz = *kHz * 1000;
> +	opp = dev_pm_opp_find_freq_ceil(cpu_dev, &Hz);
> +	if (IS_ERR(opp))
> +		return -EINVAL;
> +
> +	mV = dev_pm_opp_get_voltage(opp) / 1000;
> +	dev_pm_opp_put(opp);
> +	if (!mV)
> +		return -EINVAL;
> +
> +	tmp = (u64)cap * mV * mV * (Hz / 1000000);
> +	do_div(tmp, 1000000000);
> +
> +	*mW = (unsigned long)tmp;
> +	*kHz = Hz / 1000;
> +
> +	return 0;
> +}
> +
> +/**
> + * dev_pm_opp_of_register_em() - Attempt to register an Energy Model
> + * @cpus	: CPUs for which an Energy Model has to be registered
> + * @nr_opp	: Number of OPPs to register in the Energy Model
> + *
> + * This checks whether the "dynamic-power-coefficient" devicetree property has
> + * been specified, and tries to register an Energy Model with it if it has.
> + */
> +void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
> +{
> +	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
> +	int ret, cpu = cpumask_first(cpus);
> +	struct device *cpu_dev;
> +	struct device_node *np;
> +	u32 cap;
> +
> +	cpu_dev = get_cpu_device(cpu);
> +	if (!cpu_dev)
> +		return;
> +
> +	np = of_node_get(cpu_dev->of_node);
> +	if (!np)
> +		return;
> +

Does it make sense to add the check for OPP count here. You need not pass
that as parameter. Just makes one less thing to check in new drivers adding
this support. Thoughts ?

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-01 12:04   ` Sudeep Holla
@ 2019-02-01 12:09     ` Quentin Perret
  2019-02-01 12:27       ` Sudeep Holla
  2019-02-01 18:16       ` Matthias Kaehlcke
  0 siblings, 2 replies; 13+ messages in thread
From: Quentin Perret @ 2019-02-01 12:09 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: viresh.kumar, rjw, nm, sboyd, mka, linux-pm, linux-kernel,
	linux-arm-kernel, dietmar.eggemann

Hi Sudeep,

On Friday 01 Feb 2019 at 12:04:53 (+0000), Sudeep Holla wrote:
> On Fri, Feb 01, 2019 at 09:30:57AM +0000, Quentin Perret wrote:
> > +void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
> > +{
> > +	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
> > +	int ret, cpu = cpumask_first(cpus);
> > +	struct device *cpu_dev;
> > +	struct device_node *np;
> > +	u32 cap;
> > +
> > +	cpu_dev = get_cpu_device(cpu);
> > +	if (!cpu_dev)
> > +		return;
> > +
> > +	np = of_node_get(cpu_dev->of_node);
> > +	if (!np)
> > +		return;
> > +
> 
> Does it make sense to add the check for OPP count here. You need not pass
> that as parameter. Just makes one less thing to check in new drivers adding
> this support. Thoughts ?

Yeah Matthias had the same suggestion. I don't mind moving it here TBH.
It's just that some users already do the opp count before calling this
function, so I figured I could as well use that data instead of counting
again.

But yeah, that's one less thing to worry about on the driver side so
I'll move the OPP count in there for v4 and we'll see if people ask me
to move it out to optimize things ;-)

Thanks,
Quentin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 4/5] cpufreq: arm_big_little: Register an Energy Model
  2019-02-01 11:53   ` Sudeep Holla
@ 2019-02-01 12:11     ` Quentin Perret
  0 siblings, 0 replies; 13+ messages in thread
From: Quentin Perret @ 2019-02-01 12:11 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: viresh.kumar, rjw, nm, sboyd, mka, linux-pm, linux-kernel,
	linux-arm-kernel, dietmar.eggemann

On Friday 01 Feb 2019 at 11:53:57 (+0000), Sudeep Holla wrote:
> On Fri, Feb 01, 2019 at 09:31:00AM +0000, Quentin Perret wrote:
> > From: Dietmar Eggemann <dietmar.eggemann@arm.com>
> >
> > Now that PM_OPP provides a helper function to estimate the power
> > consumed by CPUs, make sure to try and register an Energy Model (EM)
> > from the arm_big_little CPUFreq driver, hence ensuring interested
> > subsystems (the task scheduler, for example) can make use of that
> > information when available.
> >
> > Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
> > Signed-off-by: Quentin Perret <quentin.perret@arm.com>
> > ---
> >  drivers/cpufreq/arm_big_little.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
> > index cf62a1f64dd7..18b05bcb2614 100644
> > --- a/drivers/cpufreq/arm_big_little.c
> > +++ b/drivers/cpufreq/arm_big_little.c
> > @@ -487,6 +487,14 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
> >  	policy->cpuinfo.transition_latency =
> >  				arm_bL_ops->get_transition_latency(cpu_dev);
> >
> > +	ret = dev_pm_opp_get_opp_count(cpu_dev);
> > +	if (ret <= 0) {
> > +		dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
> > +		return -EPROBE_DEFER;
> > +	}
> 
> The only user of this has the check in init_opp_table that gets called from
> get_cluster_clk_and_freq_table. So the above is not necessary, you can drop
> it.

Will do.

Thanks,
Quentin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-01 12:09     ` Quentin Perret
@ 2019-02-01 12:27       ` Sudeep Holla
  2019-02-01 12:44         ` Sudeep Holla
  2019-02-01 18:16       ` Matthias Kaehlcke
  1 sibling, 1 reply; 13+ messages in thread
From: Sudeep Holla @ 2019-02-01 12:27 UTC (permalink / raw)
  To: Quentin Perret
  Cc: viresh.kumar, rjw, nm, sboyd, mka, linux-pm, linux-kernel,
	linux-arm-kernel, dietmar.eggemann

On Fri, Feb 01, 2019 at 12:09:53PM +0000, Quentin Perret wrote:
> Hi Sudeep,
>
> On Friday 01 Feb 2019 at 12:04:53 (+0000), Sudeep Holla wrote:
> > On Fri, Feb 01, 2019 at 09:30:57AM +0000, Quentin Perret wrote:
> > > +void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
> > > +{
> > > +	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
> > > +	int ret, cpu = cpumask_first(cpus);
> > > +	struct device *cpu_dev;
> > > +	struct device_node *np;
> > > +	u32 cap;
> > > +
> > > +	cpu_dev = get_cpu_device(cpu);
> > > +	if (!cpu_dev)
> > > +		return;
> > > +
> > > +	np = of_node_get(cpu_dev->of_node);
> > > +	if (!np)
> > > +		return;
> > > +

Forgot earlier, you can use of_cpu_device_node_get to combine the above 2.

> >
> > Does it make sense to add the check for OPP count here. You need not pass
> > that as parameter. Just makes one less thing to check in new drivers adding
> > this support. Thoughts ?
>
> Yeah Matthias had the same suggestion. I don't mind moving it here TBH.
> It's just that some users already do the opp count before calling this
> function, so I figured I could as well use that data instead of counting
> again.
>

Indeed, I was under same opinion after seeing in 2 patches and then 3rd
made me think why not. Also since you fetch cpu_dev already there, it
should be fine.

> But yeah, that's one less thing to worry about on the driver side so
> I'll move the OPP count in there for v4 and we'll see if people ask me
> to move it out to optimize things ;-)
>

Yes, but I will leave it to Viresh's taste :)

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-01 12:27       ` Sudeep Holla
@ 2019-02-01 12:44         ` Sudeep Holla
  0 siblings, 0 replies; 13+ messages in thread
From: Sudeep Holla @ 2019-02-01 12:44 UTC (permalink / raw)
  To: Quentin Perret
  Cc: viresh.kumar, rjw, nm, sboyd, mka, linux-pm, linux-kernel,
	linux-arm-kernel, dietmar.eggemann

On Fri, Feb 01, 2019 at 12:27:45PM +0000, Sudeep Holla wrote:
> On Fri, Feb 01, 2019 at 12:09:53PM +0000, Quentin Perret wrote:
> > Hi Sudeep,
> >
> > On Friday 01 Feb 2019 at 12:04:53 (+0000), Sudeep Holla wrote:
> > > On Fri, Feb 01, 2019 at 09:30:57AM +0000, Quentin Perret wrote:
> > > > +void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
> > > > +{
> > > > +	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
> > > > +	int ret, cpu = cpumask_first(cpus);
> > > > +	struct device *cpu_dev;
> > > > +	struct device_node *np;
> > > > +	u32 cap;
> > > > +
> > > > +	cpu_dev = get_cpu_device(cpu);
> > > > +	if (!cpu_dev)
> > > > +		return;
> > > > +
> > > > +	np = of_node_get(cpu_dev->of_node);
> > > > +	if (!np)
> > > > +		return;
> > > > +
>
> Forgot earlier, you can use of_cpu_device_node_get to combine the above 2.
>

Scratch it, you need cpu_dev anyways. So ignore that.

--
Regards,
Sudeep

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-01 12:09     ` Quentin Perret
  2019-02-01 12:27       ` Sudeep Holla
@ 2019-02-01 18:16       ` Matthias Kaehlcke
  1 sibling, 0 replies; 13+ messages in thread
From: Matthias Kaehlcke @ 2019-02-01 18:16 UTC (permalink / raw)
  To: Quentin Perret
  Cc: Sudeep Holla, viresh.kumar, rjw, nm, sboyd, linux-pm,
	linux-kernel, linux-arm-kernel, dietmar.eggemann

On Fri, Feb 01, 2019 at 12:09:53PM +0000, Quentin Perret wrote:
> Hi Sudeep,
> 
> On Friday 01 Feb 2019 at 12:04:53 (+0000), Sudeep Holla wrote:
> > On Fri, Feb 01, 2019 at 09:30:57AM +0000, Quentin Perret wrote:
> > > +void dev_pm_opp_of_register_em(struct cpumask *cpus, int nr_opp)
> > > +{
> > > +	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
> > > +	int ret, cpu = cpumask_first(cpus);
> > > +	struct device *cpu_dev;
> > > +	struct device_node *np;
> > > +	u32 cap;
> > > +
> > > +	cpu_dev = get_cpu_device(cpu);
> > > +	if (!cpu_dev)
> > > +		return;
> > > +
> > > +	np = of_node_get(cpu_dev->of_node);
> > > +	if (!np)
> > > +		return;
> > > +
> > 
> > Does it make sense to add the check for OPP count here. You need not pass
> > that as parameter. Just makes one less thing to check in new drivers adding
> > this support. Thoughts ?
> 
> Yeah Matthias had the same suggestion. I don't mind moving it here TBH.
> It's just that some users already do the opp count before calling this
> function, so I figured I could as well use that data instead of counting
> again.
> 
> But yeah, that's one less thing to worry about on the driver side so
> I'll move the OPP count in there for v4 and we'll see if people ask me
> to move it out to optimize things ;-)

From an API perspective it would be nice to get rid of the nr_opp
parameter, it seems somewhat arbitrary. Moving dev_pm_opp_get_opp_count()
from the drivers into dev_pm_opp_of_register_em() (instead of calling
it twice) also sounds good in general, as long as the error handling
doesn't become too messy. In the current version
dev_pm_opp_of_register_em() doesn't return a value, with the change it
would have to return one to catch an empty OPP table, and it needs
to be distinguished from other cases where the EM registration fails
but the cpufreq driver is still functional (e.g. no
'dynamic-power-coefficient'). Maybe return -ENOTSUPP in those cases?

Well, let's see how it looks like :)

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-02-01 18:16 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-01  9:30 [PATCH v3 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
2019-02-01  9:30 ` [PATCH v3 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
2019-02-01 12:04   ` Sudeep Holla
2019-02-01 12:09     ` Quentin Perret
2019-02-01 12:27       ` Sudeep Holla
2019-02-01 12:44         ` Sudeep Holla
2019-02-01 18:16       ` Matthias Kaehlcke
2019-02-01  9:30 ` [PATCH v3 2/5] cpufreq: dt: Register an Energy Model Quentin Perret
2019-02-01  9:30 ` [PATCH v3 3/5] cpufreq: scpi: " Quentin Perret
2019-02-01  9:31 ` [PATCH v3 4/5] cpufreq: arm_big_little: " Quentin Perret
2019-02-01 11:53   ` Sudeep Holla
2019-02-01 12:11     ` Quentin Perret
2019-02-01  9:31 ` [PATCH v3 5/5] cpufreq: scmi: " Quentin Perret

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).