LKML Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v4 0/5] Register an Energy Model for Arm reference platforms
@ 2019-02-04 11:09 Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 11:09 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 v3 (20190201093101.31869-1-quentin.perret@arm.com)
 - Moved the OPP count inside dev_pm_opp_of_register_em() (Matthias,
   Sudeep)

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 |  2 +
 drivers/cpufreq/cpufreq-dt.c     |  2 +
 drivers/cpufreq/scmi-cpufreq.c   | 39 ++++++++++++-
 drivers/cpufreq/scpi-cpufreq.c   |  3 +
 drivers/opp/of.c                 | 99 ++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h           |  6 ++
 6 files changed, 148 insertions(+), 3 deletions(-)

-- 
2.20.1


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

* [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
@ 2019-02-04 11:09 ` Quentin Perret
  2019-02-04 18:03   ` Matthias Kaehlcke
  2019-02-04 11:09 ` [PATCH v4 2/5] cpufreq: dt: Register an Energy Model Quentin Perret
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 11:09 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       | 99 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_opp.h |  6 +++
 2 files changed, 105 insertions(+)

diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 06f0f632ec47..cd58959e5158 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,101 @@ 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
+ *
+ * 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)
+{
+	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
+	int ret, nr_opp, cpu = cpumask_first(cpus);
+	struct device *cpu_dev;
+	struct device_node *np;
+	u32 cap;
+
+	cpu_dev = get_cpu_device(cpu);
+	if (!cpu_dev)
+		return;
+
+	nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
+	if (nr_opp <= 0)
+		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..c9c76310865a 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);
 #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)
+{
+}
+
 static inline int of_get_required_opp_performance_state(struct device_node *np, int index)
 {
 	return -ENOTSUPP;
-- 
2.20.1


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

* [PATCH v4 2/5] cpufreq: dt: Register an Energy Model
  2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
@ 2019-02-04 11:09 ` Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 3/5] cpufreq: scpi: " Quentin Perret
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 11:09 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 | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index e58bfcb1169e..d74e0402512a 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -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);
+
 	return 0;
 
 out_free_cpufreq_table:
-- 
2.20.1


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

* [PATCH v4 3/5] cpufreq: scpi: Register an Energy Model
  2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 2/5] cpufreq: dt: Register an Energy Model Quentin Perret
@ 2019-02-04 11:09 ` " Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 4/5] cpufreq: arm_big_little: " Quentin Perret
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 11:09 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 | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 99449738faa4..b279f94d82f7 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -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);
+
 	return 0;
 
 out_free_cpufreq_table:
-- 
2.20.1


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

* [PATCH v4 4/5] cpufreq: arm_big_little: Register an Energy Model
  2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
                   ` (2 preceding siblings ...)
  2019-02-04 11:09 ` [PATCH v4 3/5] cpufreq: scpi: " Quentin Perret
@ 2019-02-04 11:09 ` " Quentin Perret
  2019-02-04 11:09 ` [PATCH v4 5/5] cpufreq: scmi: " Quentin Perret
  2019-02-05  4:55 ` [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Viresh Kumar
  5 siblings, 0 replies; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 11:09 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 | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index cf62a1f64dd7..7fe52fcddcf1 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -487,6 +487,8 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.transition_latency =
 				arm_bL_ops->get_transition_latency(cpu_dev);
 
+	dev_pm_opp_of_register_em(policy->cpus);
+
 	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	[flat|nested] 9+ messages in thread

* [PATCH v4 5/5] cpufreq: scmi: Register an Energy Model
  2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
                   ` (3 preceding siblings ...)
  2019-02-04 11:09 ` [PATCH v4 4/5] cpufreq: arm_big_little: " Quentin Perret
@ 2019-02-04 11:09 ` " Quentin Perret
  2019-02-05  4:55 ` [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Viresh Kumar
  5 siblings, 0 replies; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 11:09 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	[flat|nested] 9+ messages in thread

* Re: [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-04 11:09 ` [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
@ 2019-02-04 18:03   ` Matthias Kaehlcke
  2019-02-04 18:21     ` Quentin Perret
  0 siblings, 1 reply; 9+ messages in thread
From: Matthias Kaehlcke @ 2019-02-04 18:03 UTC (permalink / raw)
  To: Quentin Perret
  Cc: viresh.kumar, sudeep.holla, rjw, nm, sboyd, linux-pm,
	linux-kernel, linux-arm-kernel, dietmar.eggemann

On Mon, Feb 04, 2019 at 11:09:48AM +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       | 99 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_opp.h |  6 +++
>  2 files changed, 105 insertions(+)
> 
> diff --git a/drivers/opp/of.c b/drivers/opp/of.c
> index 06f0f632ec47..cd58959e5158 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,101 @@ 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
> + *
> + * 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)
> +{
> +	struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power);
> +	int ret, nr_opp, cpu = cpumask_first(cpus);
> +	struct device *cpu_dev;
> +	struct device_node *np;
> +	u32 cap;
> +
> +	cpu_dev = get_cpu_device(cpu);
> +	if (!cpu_dev)
> +		return;
> +
> +	nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
> +	if (nr_opp <= 0)
> +		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..c9c76310865a 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);
>  #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)
> +{
> +}
> +
>  static inline int of_get_required_opp_performance_state(struct device_node *np, int index)
>  {
>  	return -ENOTSUPP;

There is the option to remove the OPP check from the cpufreq drivers
and instead return an error from dev_pm_opp_of_register_em(), but with
the more complex error handling it might be more hassle than it's
worth.

Reviewed-by: Matthias Kaehlcke <mka@chromium.org>

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

* Re: [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper
  2019-02-04 18:03   ` Matthias Kaehlcke
@ 2019-02-04 18:21     ` Quentin Perret
  0 siblings, 0 replies; 9+ messages in thread
From: Quentin Perret @ 2019-02-04 18:21 UTC (permalink / raw)
  To: Matthias Kaehlcke
  Cc: viresh.kumar, sudeep.holla, rjw, nm, sboyd, linux-pm,
	linux-kernel, linux-arm-kernel, dietmar.eggemann

On Monday 04 Feb 2019 at 10:03:03 (-0800), Matthias Kaehlcke wrote:
> There is the option to remove the OPP check from the cpufreq drivers
> and instead return an error from dev_pm_opp_of_register_em(), but with
> the more complex error handling it might be more hassle than it's
> worth.

Agreed. And that would make the API a bit weird I guess, so I preferred
the simple solution.

> Reviewed-by: Matthias Kaehlcke <mka@chromium.org>

Thanks !
Quentin

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

* Re: [PATCH v4 0/5] Register an Energy Model for Arm reference platforms
  2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
                   ` (4 preceding siblings ...)
  2019-02-04 11:09 ` [PATCH v4 5/5] cpufreq: scmi: " Quentin Perret
@ 2019-02-05  4:55 ` Viresh Kumar
  5 siblings, 0 replies; 9+ messages in thread
From: Viresh Kumar @ 2019-02-05  4:55 UTC (permalink / raw)
  To: Quentin Perret
  Cc: sudeep.holla, rjw, nm, sboyd, mka, linux-pm, linux-kernel,
	linux-arm-kernel, dietmar.eggemann

On 04-02-19, 11:09, Quentin Perret wrote:
> 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 v3 (20190201093101.31869-1-quentin.perret@arm.com)
>  - Moved the OPP count inside dev_pm_opp_of_register_em() (Matthias,
>    Sudeep)

Applied. Thanks.

-- 
viresh

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

end of thread, back to index

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-04 11:09 [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Quentin Perret
2019-02-04 11:09 ` [PATCH v4 1/5] PM / OPP: Introduce a power estimation helper Quentin Perret
2019-02-04 18:03   ` Matthias Kaehlcke
2019-02-04 18:21     ` Quentin Perret
2019-02-04 11:09 ` [PATCH v4 2/5] cpufreq: dt: Register an Energy Model Quentin Perret
2019-02-04 11:09 ` [PATCH v4 3/5] cpufreq: scpi: " Quentin Perret
2019-02-04 11:09 ` [PATCH v4 4/5] cpufreq: arm_big_little: " Quentin Perret
2019-02-04 11:09 ` [PATCH v4 5/5] cpufreq: scmi: " Quentin Perret
2019-02-05  4:55 ` [PATCH v4 0/5] Register an Energy Model for Arm reference platforms Viresh Kumar

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git