* [PATCH v4 1/8] ARM: initialize cpu_scale to its default
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 14:24 ` [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings Juri Lelli
` (6 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
juri.lelli, broonie
Instead of looping through all cpus calling set_capacity_scale, we can
initialise cpu_scale per-cpu variables to SCHED_CAPACITY_SCALE with their
definition.
Cc: Russell King <linux@arm.linux.org.uk>
Acked-by: Vincent Guittot <vincent.guittot@linaro.org>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
Applied:
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=8497/1
---
arch/arm/kernel/topology.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 08b7847..ec279d1 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -40,7 +40,7 @@
* to run the rebalance_domains for all idle cores and the cpu_capacity can be
* updated during this sequence.
*/
-static DEFINE_PER_CPU(unsigned long, cpu_scale);
+static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
{
@@ -306,8 +306,6 @@ void __init init_cpu_topology(void)
cpu_topo->socket_id = -1;
cpumask_clear(&cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
-
- set_capacity_scale(cpu, SCHED_CAPACITY_SCALE);
}
smp_wmb();
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
2016-03-18 14:24 ` [PATCH v4 1/8] ARM: initialize cpu_scale to its default Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 17:49 ` Sai Gurrappadi
2016-03-20 1:15 ` Rob Herring
2016-03-18 14:24 ` [PATCH v4 3/8] arm: parse cpu capacity from DT Juri Lelli
` (5 subsequent siblings)
7 siblings, 2 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, peterz, catalin.marinas, Linus Walleij, will.deacon,
morten.rasmussen, lorenzo.pieralisi, vincent.guittot, juri.lelli,
Ian Campbell, Chen-Yu Tsai, devicetree, Pawel Moll, linux-pm,
Kumar Gala, broonie, Gregory CLEMENT, linux, dietmar.eggemann,
linux-arm-kernel, Thomas Petazzoni, Paul Walmsley, robh+dt,
sudeep.holla, Olof Johansson, Maxime Ripard
ARM systems may be configured to have cpus with different power/performance
characteristics within the same chip. In this case, additional information
has to be made available to the kernel (the scheduler in particular) for it
to be aware of such differences and take decisions accordingly.
Therefore, this patch aims at standardizing cpu capacities device tree
bindings for ARM platforms. Bindings define cpu capacity parameter, to
allow operating systems to retrieve such information from the device tree
and initialize related kernel structures, paving the way for common code in
the kernel to deal with heterogeneity.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: devicetree@vger.kernel.org
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
Changes from v1:
- removed section regarding capacity-scale
- added information regarding normalization
---
.../devicetree/bindings/arm/cpu-capacity.txt | 222 +++++++++++++++++++++
Documentation/devicetree/bindings/arm/cpus.txt | 9 +
2 files changed, 231 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/cpu-capacity.txt
diff --git a/Documentation/devicetree/bindings/arm/cpu-capacity.txt b/Documentation/devicetree/bindings/arm/cpu-capacity.txt
new file mode 100644
index 0000000..fdfc453
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/cpu-capacity.txt
@@ -0,0 +1,222 @@
+==========================================
+ARM CPUs capacity bindings
+==========================================
+
+==========================================
+1 - Introduction
+==========================================
+
+ARM systems may be configured to have cpus with different power/performance
+characteristics within the same chip. In this case, additional information
+has to be made available to the kernel (the scheduler in particular) for
+it to be aware of such differences and take decisions accordingly.
+
+==========================================
+2 - CPU capacity definition
+==========================================
+
+CPU capacity is a number that provides the scheduler information about CPUs
+heterogeneity. Such heterogeneity can come from micro-architectural differences
+(e.g., ARM big.LITTLE systems) or maximum frequency at which CPUs can run
+(e.g., SMP systems with multiple frequency domains). Heterogeneity in this
+context is about differing performance characteristics; this binding tries to
+capture a first-order approximation of the relative performance of CPUs.
+
+One simple way to estimate CPU capacities is to iteratively run a well-known
+CPU user space benchmark (e.g, sysbench) on each CPU at maximum frequency and
+then normalize values w.r.t. the best performing CPU. One can also do a
+statistically significant study of a wide collection of benchmarks, but pros
+of such an approach are not really evident at the time of writing.
+
+==========================================
+3 - capacity
+==========================================
+
+capacity is an optional cpu node [1] property: u32 value representing CPU
+capacity. Values are normalized w.r.t. the biggest capacity found while
+parsing the DT.
+
+If capacity property is all-or-nothing: if it is specified for a cpu node, it
+has to be specified for every other cpu nodes, or the system will fall back to
+the default capacity value for every CPU.
+
+===========================================
+4 - Examples
+===========================================
+
+Example 1 (ARM 64-bit, 6-cpu system, two clusters):
+capacities are scaled w.r.t. 1024 (cpu@0 and cpu@1)
+
+cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&A57_0>;
+ };
+ core1 {
+ cpu = <&A57_1>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&A53_0>;
+ };
+ core1 {
+ cpu = <&A53_1>;
+ };
+ core2 {
+ cpu = <&A53_2>;
+ };
+ core3 {
+ cpu = <&A53_3>;
+ };
+ };
+ };
+
+ idle-states {
+ entry-method = "arm,psci";
+
+ CPU_SLEEP_0: cpu-sleep-0 {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010000>;
+ local-timer-stop;
+ entry-latency-us = <100>;
+ exit-latency-us = <250>;
+ min-residency-us = <150>;
+ };
+
+ CLUSTER_SLEEP_0: cluster-sleep-0 {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x1010000>;
+ local-timer-stop;
+ entry-latency-us = <800>;
+ exit-latency-us = <700>;
+ min-residency-us = <2500>;
+ };
+ };
+
+ A57_0: cpu@0 {
+ compatible = "arm,cortex-a57","arm,armv8";
+ reg = <0x0 0x0>;
+ device_type = "cpu";
+ enable-method = "psci";
+ next-level-cache = <&A57_L2>;
+ clocks = <&scpi_dvfs 0>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <1024>;
+ };
+
+ A57_1: cpu@1 {
+ compatible = "arm,cortex-a57","arm,armv8";
+ reg = <0x0 0x1>;
+ device_type = "cpu";
+ enable-method = "psci";
+ next-level-cache = <&A57_L2>;
+ clocks = <&scpi_dvfs 0>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <1024>;
+ };
+
+ A53_0: cpu@100 {
+ compatible = "arm,cortex-a53","arm,armv8";
+ reg = <0x0 0x100>;
+ device_type = "cpu";
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ clocks = <&scpi_dvfs 1>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
+ };
+
+ A53_1: cpu@101 {
+ compatible = "arm,cortex-a53","arm,armv8";
+ reg = <0x0 0x101>;
+ device_type = "cpu";
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ clocks = <&scpi_dvfs 1>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
+ };
+
+ A53_2: cpu@102 {
+ compatible = "arm,cortex-a53","arm,armv8";
+ reg = <0x0 0x102>;
+ device_type = "cpu";
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ clocks = <&scpi_dvfs 1>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
+ };
+
+ A53_3: cpu@103 {
+ compatible = "arm,cortex-a53","arm,armv8";
+ reg = <0x0 0x103>;
+ device_type = "cpu";
+ enable-method = "psci";
+ next-level-cache = <&A53_L2>;
+ clocks = <&scpi_dvfs 1>;
+ cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
+ };
+
+ A57_L2: l2-cache0 {
+ compatible = "cache";
+ };
+
+ A53_L2: l2-cache1 {
+ compatible = "cache";
+ };
+};
+
+Example 2 (ARM 32-bit, 4-cpu system, two clusters,
+ cpus 0,1@1GHz, cpus 2,3@500MHz):
+capacities are scaled w.r.t. 2 (cpu@0 and cpu@1), this means that first
+cluster is twice fast than second cluster (i.e., cpu@0 and cpu@1 might be
+running at twice the clock-frequency of cpu@2 and cpu@3)
+
+cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0>;
+ capacity = <2>;
+ };
+
+ cpu1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <1>;
+ capacity = <2>;
+ };
+
+ cpu2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0x100>;
+ capacity = <1>;
+ };
+
+ cpu3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a15";
+ reg = <0x101>;
+ capacity = <1>;
+ };
+};
+
+===========================================
+5 - References
+===========================================
+
+[1] ARM Linux Kernel documentation - CPUs bindings
+ Documentation/devicetree/bindings/arm/cpus.txt
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index ae9be07..efd6151 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -237,6 +237,13 @@ nodes to be present and contain the properties described below.
# List of phandles to idle state nodes supported
by this cpu [3].
+ - capacity
+ Usage: Optional
+ Value type: <u32>
+ Definition:
+ # u32 value representing CPU capacity [3], relative to
+ highest capacity in the system.
+
- rockchip,pmu
Usage: optional for systems that have an "enable-method"
property value of "rockchip,rk3066-smp"
@@ -460,3 +467,5 @@ cpus {
[2] arm/msm/qcom,kpss-acc.txt
[3] ARM Linux kernel documentation - idle states bindings
Documentation/devicetree/bindings/arm/idle-states.txt
+[3] ARM Linux kernel documentation - cpu capacity bindings
+ Documentation/devicetree/bindings/arm/cpu-capacity.txt
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings
2016-03-18 14:24 ` [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings Juri Lelli
@ 2016-03-18 17:49 ` Sai Gurrappadi
[not found] ` <56EC3F9E.4050209-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-03-20 1:15 ` Rob Herring
1 sibling, 1 reply; 20+ messages in thread
From: Sai Gurrappadi @ 2016-03-18 17:49 UTC (permalink / raw)
To: Juri Lelli, linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
broonie, Pawel Moll, Ian Campbell, Kumar Gala, Maxime Ripard,
Olof Johansson, Gregory CLEMENT, Paul Walmsley, Linus Walleij,
Chen-Yu Tsai, Thomas Petazzoni, pboonstoppel
Hi Juri,
On 03/18/2016 07:24 AM, Juri Lelli wrote:
<snip>
> +
> +==========================================
> +2 - CPU capacity definition
> +==========================================
> +
> +CPU capacity is a number that provides the scheduler information about CPUs
> +heterogeneity. Such heterogeneity can come from micro-architectural differences
> +(e.g., ARM big.LITTLE systems) or maximum frequency at which CPUs can run
> +(e.g., SMP systems with multiple frequency domains). Heterogeneity in this
> +context is about differing performance characteristics; this binding tries to
> +capture a first-order approximation of the relative performance of CPUs.
Any reason why this capacity number is not dynamically generated based on the
max frequency for each CPU? The DT property would then instead specify just
the micro-architectural differences between the CPU types.
-Sai
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings
2016-03-18 14:24 ` [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings Juri Lelli
2016-03-18 17:49 ` Sai Gurrappadi
@ 2016-03-20 1:15 ` Rob Herring
2016-03-21 11:39 ` Juri Lelli
1 sibling, 1 reply; 20+ messages in thread
From: Rob Herring @ 2016-03-20 1:15 UTC (permalink / raw)
To: Juri Lelli
Cc: linux-kernel, linux-pm, linux-arm-kernel, devicetree, peterz,
vincent.guittot, mark.rutland, linux, sudeep.holla,
lorenzo.pieralisi, catalin.marinas, will.deacon, morten.rasmussen,
dietmar.eggemann, broonie, Pawel Moll, Ian Campbell, Kumar Gala,
Maxime Ripard, Olof Johansson, Gregory CLEMENT, Paul Walmsley,
Linus Walleij, Chen-Yu Tsai, Thomas Petazzoni
On Fri, Mar 18, 2016 at 02:24:08PM +0000, Juri Lelli wrote:
> ARM systems may be configured to have cpus with different power/performance
> characteristics within the same chip. In this case, additional information
> has to be made available to the kernel (the scheduler in particular) for it
> to be aware of such differences and take decisions accordingly.
>
> Therefore, this patch aims at standardizing cpu capacities device tree
> bindings for ARM platforms. Bindings define cpu capacity parameter, to
> allow operating systems to retrieve such information from the device tree
> and initialize related kernel structures, paving the way for common code in
> the kernel to deal with heterogeneity.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Pawel Moll <pawel.moll@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> Cc: Kumar Gala <galak@codeaurora.org>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Chen-Yu Tsai <wens@csie.org>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Juri Lelli <juri.lelli@arm.com>
> ---
>
> Changes from v1:
> - removed section regarding capacity-scale
> - added information regarding normalization
> ---
> .../devicetree/bindings/arm/cpu-capacity.txt | 222 +++++++++++++++++++++
> Documentation/devicetree/bindings/arm/cpus.txt | 9 +
> 2 files changed, 231 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/cpu-capacity.txt
>
> diff --git a/Documentation/devicetree/bindings/arm/cpu-capacity.txt b/Documentation/devicetree/bindings/arm/cpu-capacity.txt
> new file mode 100644
> index 0000000..fdfc453
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/cpu-capacity.txt
> @@ -0,0 +1,222 @@
> +==========================================
> +ARM CPUs capacity bindings
> +==========================================
> +
> +==========================================
> +1 - Introduction
> +==========================================
> +
> +ARM systems may be configured to have cpus with different power/performance
> +characteristics within the same chip. In this case, additional information
> +has to be made available to the kernel (the scheduler in particular) for
> +it to be aware of such differences and take decisions accordingly.
> +
> +==========================================
> +2 - CPU capacity definition
> +==========================================
> +
> +CPU capacity is a number that provides the scheduler information about CPUs
> +heterogeneity. Such heterogeneity can come from micro-architectural differences
> +(e.g., ARM big.LITTLE systems) or maximum frequency at which CPUs can run
> +(e.g., SMP systems with multiple frequency domains). Heterogeneity in this
> +context is about differing performance characteristics; this binding tries to
> +capture a first-order approximation of the relative performance of CPUs.
> +
> +One simple way to estimate CPU capacities is to iteratively run a well-known
> +CPU user space benchmark (e.g, sysbench) on each CPU at maximum frequency and
> +then normalize values w.r.t. the best performing CPU. One can also do a
> +statistically significant study of a wide collection of benchmarks, but pros
> +of such an approach are not really evident at the time of writing.
I'll say again what I did previously. I don't have a problem this being
in DT, but I want to see a defined method for determining the value. The
above is a pretty vague statement. That can be run X to generate the
value on the cpu. Or ARM providing the "golden" value for each core. As
you said, it is only a 1st order approximation, so vendor to vendor
implementation variations should not matter.
I also worry about what happens in more complex cases with lots of
possible OPPs such as Qualcomm chips. This single value may not be
sufficient.
Rob
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings
2016-03-20 1:15 ` Rob Herring
@ 2016-03-21 11:39 ` Juri Lelli
0 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-21 11:39 UTC (permalink / raw)
To: Rob Herring
Cc: linux-kernel, linux-pm, linux-arm-kernel, devicetree, peterz,
vincent.guittot, mark.rutland, linux, sudeep.holla,
lorenzo.pieralisi, catalin.marinas, will.deacon, morten.rasmussen,
dietmar.eggemann, broonie, Pawel Moll, Ian Campbell, Kumar Gala,
Maxime Ripard, Olof Johansson, Gregory CLEMENT, Paul Walmsley,
Linus Walleij, Chen-Yu Tsai, Thomas Petazzoni
On 19/03/16 20:15, Rob Herring wrote:
> On Fri, Mar 18, 2016 at 02:24:08PM +0000, Juri Lelli wrote:
> > ARM systems may be configured to have cpus with different power/performance
> > characteristics within the same chip. In this case, additional information
> > has to be made available to the kernel (the scheduler in particular) for it
> > to be aware of such differences and take decisions accordingly.
> >
> > Therefore, this patch aims at standardizing cpu capacities device tree
> > bindings for ARM platforms. Bindings define cpu capacity parameter, to
> > allow operating systems to retrieve such information from the device tree
> > and initialize related kernel structures, paving the way for common code in
> > the kernel to deal with heterogeneity.
> >
> > Cc: Rob Herring <robh+dt@kernel.org>
> > Cc: Pawel Moll <pawel.moll@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
> > Cc: Kumar Gala <galak@codeaurora.org>
> > Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> > Cc: Olof Johansson <olof@lixom.net>
> > Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
> > Cc: Paul Walmsley <paul@pwsan.com>
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Cc: Chen-Yu Tsai <wens@csie.org>
> > Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> > Cc: devicetree@vger.kernel.org
> > Signed-off-by: Juri Lelli <juri.lelli@arm.com>
> > ---
> >
> > Changes from v1:
> > - removed section regarding capacity-scale
> > - added information regarding normalization
> > ---
> > .../devicetree/bindings/arm/cpu-capacity.txt | 222 +++++++++++++++++++++
> > Documentation/devicetree/bindings/arm/cpus.txt | 9 +
> > 2 files changed, 231 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/arm/cpu-capacity.txt
> >
> > diff --git a/Documentation/devicetree/bindings/arm/cpu-capacity.txt b/Documentation/devicetree/bindings/arm/cpu-capacity.txt
> > new file mode 100644
> > index 0000000..fdfc453
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/cpu-capacity.txt
> > @@ -0,0 +1,222 @@
> > +==========================================
> > +ARM CPUs capacity bindings
> > +==========================================
> > +
> > +==========================================
> > +1 - Introduction
> > +==========================================
> > +
> > +ARM systems may be configured to have cpus with different power/performance
> > +characteristics within the same chip. In this case, additional information
> > +has to be made available to the kernel (the scheduler in particular) for
> > +it to be aware of such differences and take decisions accordingly.
> > +
> > +==========================================
> > +2 - CPU capacity definition
> > +==========================================
> > +
> > +CPU capacity is a number that provides the scheduler information about CPUs
> > +heterogeneity. Such heterogeneity can come from micro-architectural differences
> > +(e.g., ARM big.LITTLE systems) or maximum frequency at which CPUs can run
> > +(e.g., SMP systems with multiple frequency domains). Heterogeneity in this
> > +context is about differing performance characteristics; this binding tries to
> > +capture a first-order approximation of the relative performance of CPUs.
> > +
> > +One simple way to estimate CPU capacities is to iteratively run a well-known
> > +CPU user space benchmark (e.g, sysbench) on each CPU at maximum frequency and
> > +then normalize values w.r.t. the best performing CPU. One can also do a
> > +statistically significant study of a wide collection of benchmarks, but pros
> > +of such an approach are not really evident at the time of writing.
>
> I'll say again what I did previously. I don't have a problem this being
> in DT, but I want to see a defined method for determining the value. The
> above is a pretty vague statement. That can be run X to generate the
> value on the cpu. Or ARM providing the "golden" value for each core. As
> you said, it is only a 1st order approximation, so vendor to vendor
> implementation variations should not matter.
>
OK, sorry if I didn't get it. :-)
What we usually do to come up with these numbers for a new platform is
really something as simple as:
- set every CPUs to performance governor
- run the following on first CPU of each cluster
# taskset '<CPUmask>' sysbench --test=cpu --num-threads=1 --max-time=10 \
run | grep "events:" | awk '{print $5}'
- normalize numbers w.r.t. highest value obtained by running the former
I'm not sure we can put something like this in the definition above, but
I wont raise any objections if we actually can. :-)
The "golden" value solution I don't think is feasible. Different
implementations of the same CPU, and different configurations of caches
etc., will end up giving different numbers. This values has to be a per
platform thing, IMHO. Also, being it a per platform and relative number,
it will be "confined" to a certain platform only (comparing capacities
across different DTs has no meaning).
> I also worry about what happens in more complex cases with lots of
> possible OPPs such as Qualcomm chips. This single value may not be
> sufficient.
>
Having many OPPs are not a problem. This value only tells about
micro-arch differences and it is used to obtain CPU scale invariance
component. We then have a frequency invariant component to handle clock
frequency differences (there is also an on-going discussion about this
[1]). The capacity values are to be obtained running at max freq.
Thanks,
- Juri
[1] https://lkml.org/lkml/2016/3/14/64
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v4 3/8] arm: parse cpu capacity from DT
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
2016-03-18 14:24 ` [PATCH v4 1/8] ARM: initialize cpu_scale to its default Juri Lelli
2016-03-18 14:24 ` [PATCH v4 2/8] Documentation: arm: define DT cpu capacity bindings Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 14:24 ` [PATCH v4 4/8] arm, dts: add TC2 cpu capacity information Juri Lelli
` (4 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
juri.lelli, broonie
With the introduction of cpu capacity bindings, CPU capacities can now be
extracted from DT. Add parsing of such information at boot time. We keep
code that can produce same information, based on different DT properties
and hard-coded values, as fall-back for backward compatibility.
Caveat: the information provided by this patch will start to be used in
the future, by properly defining arch_scale_cpu_capacity().
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
Changes from v1:
- normalize w.r.t. highest capacity found in DT
- bailout conditions (all-or-nothing)
---
arch/arm/kernel/topology.c | 78 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index ec279d1..53c13c1 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -78,6 +78,67 @@ static unsigned long *__cpu_capacity;
#define cpu_capacity(cpu) __cpu_capacity[cpu]
static unsigned long middle_capacity = 1;
+static bool cap_from_dt = true;
+static u32 *raw_capacity;
+static bool cap_parsing_failed;
+static u32 capacity_scale;
+
+static int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu)
+{
+ int ret = 1;
+ u32 cpu_capacity;
+
+ if (cap_parsing_failed)
+ return !ret;
+
+ ret = of_property_read_u32(cpu_node,
+ "capacity",
+ &cpu_capacity);
+ if (!ret) {
+ if (!raw_capacity) {
+ raw_capacity = kzalloc(sizeof(*raw_capacity) *
+ num_possible_cpus(), GFP_KERNEL);
+ if (!raw_capacity) {
+ pr_err("cpu_capacity: failed to allocate memory"
+ " for raw capacities\n");
+ cap_parsing_failed = true;
+ return !ret;
+ }
+ }
+ capacity_scale = max(cpu_capacity, capacity_scale);
+ raw_capacity[cpu] = cpu_capacity;
+ pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n",
+ cpu_node->full_name, raw_capacity[cpu]);
+ } else {
+ pr_err("cpu_capacity: missing %s raw capacity "
+ "(fallback to 1024 for all CPUs)\n",
+ cpu_node->full_name);
+ cap_parsing_failed = true;
+ kfree(raw_capacity);
+ }
+
+ return !ret;
+}
+
+static void __init normalize_cpu_capacity(void)
+{
+ u64 capacity;
+ int cpu;
+
+ if (cap_parsing_failed)
+ return;
+
+ pr_info("cpu_capacity: capacity_scale=%u\n", capacity_scale);
+ for_each_possible_cpu(cpu) {
+ capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT)
+ / capacity_scale;
+ set_capacity_scale(cpu, capacity);
+ pr_info("cpu_capacity: CPU%d cpu_capacity=%lu\n",
+ cpu, arch_scale_cpu_capacity(NULL, cpu));
+ }
+
+ kfree(raw_capacity);
+}
/*
* Iterate all CPUs' descriptor in DT and compute the efficiency
@@ -99,6 +160,12 @@ static void __init parse_dt_topology(void)
__cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity),
GFP_NOWAIT);
+ cn = of_find_node_by_path("/cpus");
+ if (!cn) {
+ pr_err("No CPU information found in DT\n");
+ return;
+ }
+
for_each_possible_cpu(cpu) {
const u32 *rate;
int len;
@@ -110,6 +177,13 @@ static void __init parse_dt_topology(void)
continue;
}
+ if (parse_cpu_capacity(cn, cpu)) {
+ of_node_put(cn);
+ continue;
+ }
+
+ cap_from_dt = false;
+
for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
if (of_device_is_compatible(cn, cpu_eff->compatible))
break;
@@ -151,6 +225,8 @@ static void __init parse_dt_topology(void)
middle_capacity = ((max_capacity / 3)
>> (SCHED_CAPACITY_SHIFT-1)) + 1;
+ if (cap_from_dt && !cap_parsing_failed)
+ normalize_cpu_capacity();
}
/*
@@ -160,7 +236,7 @@ static void __init parse_dt_topology(void)
*/
static void update_cpu_capacity(unsigned int cpu)
{
- if (!cpu_capacity(cpu))
+ if (!cpu_capacity(cpu) || cap_from_dt)
return;
set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity);
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 4/8] arm, dts: add TC2 cpu capacity information
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
` (2 preceding siblings ...)
2016-03-18 14:24 ` [PATCH v4 3/8] arm: parse cpu capacity from DT Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 14:24 ` [PATCH v4 5/8] arm64: parse cpu capacity from DT Juri Lelli
` (3 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
juri.lelli, broonie, Liviu Dudau, Pawel Moll, Ian Campbell,
Kumar Gala
Add TC2 cpu capacity binding information.
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: devicetree@vger.kernel.org
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
Changes from v1:
- capacity-scale removed
---
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 17f63f7..0924844 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -39,6 +39,7 @@
reg = <0>;
cci-control-port = <&cci_control1>;
cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
+ capacity = <1024>;
};
cpu1: cpu@1 {
@@ -47,6 +48,7 @@
reg = <1>;
cci-control-port = <&cci_control1>;
cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
+ capacity = <1024>;
};
cpu2: cpu@2 {
@@ -55,6 +57,7 @@
reg = <0x100>;
cci-control-port = <&cci_control2>;
cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
+ capacity = <430>;
};
cpu3: cpu@3 {
@@ -63,6 +66,7 @@
reg = <0x101>;
cci-control-port = <&cci_control2>;
cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
+ capacity = <430>;
};
cpu4: cpu@4 {
@@ -71,6 +75,7 @@
reg = <0x102>;
cci-control-port = <&cci_control2>;
cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
+ capacity = <430>;
};
idle-states {
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 5/8] arm64: parse cpu capacity from DT
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
` (3 preceding siblings ...)
2016-03-18 14:24 ` [PATCH v4 4/8] arm, dts: add TC2 cpu capacity information Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 14:24 ` [PATCH v4 6/8] arm64, dts: add Juno cpu capacity information Juri Lelli
` (2 subsequent siblings)
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, devicetree, lorenzo.pieralisi, vincent.guittot,
juri.lelli, linux-pm, peterz, catalin.marinas, broonie,
Mark Brown, will.deacon, dietmar.eggemann, robh+dt, sudeep.holla,
linux, morten.rasmussen, linux-arm-kernel
With the introduction of cpu capacity bindings, CPU capacities can now be
extracted from DT. Add parsing of such information at boot time. Also,
store such information using per CPU variables, as we do for arm.
Caveat: the information provided by this patch will start to be used in
the future, by properly defining arch_scale_cpu_capacity().
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Brown <broonie@linaro.org>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
Changes from v1:
- normalize w.r.t. highest capacity found in DT
- bailout conditions (all-or-nothing)
---
arch/arm64/kernel/topology.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 694f6de..69229b3 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -19,10 +19,82 @@
#include <linux/nodemask.h>
#include <linux/of.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#include <asm/cputype.h>
#include <asm/topology.h>
+static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+
+unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
+{
+ return per_cpu(cpu_scale, cpu);
+}
+
+static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
+{
+ per_cpu(cpu_scale, cpu) = capacity;
+}
+
+static u32 capacity_scale;
+static u32 *raw_capacity;
+static bool cap_parsing_failed;
+
+static void __init parse_cpu_capacity(struct device_node *cpu_node, int cpu)
+{
+ int ret;
+ u32 cpu_capacity;
+
+ if (cap_parsing_failed)
+ return;
+
+ ret = of_property_read_u32(cpu_node,
+ "capacity",
+ &cpu_capacity);
+ if (!ret) {
+ if (!raw_capacity) {
+ raw_capacity = kzalloc(sizeof(*raw_capacity) *
+ num_possible_cpus(), GFP_KERNEL);
+ if (!raw_capacity) {
+ pr_err("cpu_capacity: failed to allocate memory"
+ " for raw capacities\n");
+ cap_parsing_failed = true;
+ return;
+ }
+ }
+ capacity_scale = max(cpu_capacity, capacity_scale);
+ raw_capacity[cpu] = cpu_capacity;
+ pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n",
+ cpu_node->full_name, raw_capacity[cpu]);
+ } else {
+ pr_err("cpu_capacity: missing %s raw capacity "
+ "(fallback to 1024 for all CPUs)\n",
+ cpu_node->full_name);
+ cap_parsing_failed = true;
+ kfree(raw_capacity);
+ }
+}
+
+static void __init normalize_cpu_capacity(void)
+{
+ u64 capacity;
+ int cpu;
+
+ if (cap_parsing_failed)
+ return;
+
+ pr_info("cpu_capacity: capacity_scale=%u\n", capacity_scale);
+ for_each_possible_cpu(cpu) {
+ capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT)
+ / capacity_scale;
+ set_capacity_scale(cpu, capacity);
+ pr_info("cpu_capacity: CPU%d cpu_capacity=%lu\n",
+ cpu, arch_scale_cpu_capacity(NULL, cpu));
+ }
+
+ kfree(raw_capacity);
+}
+
static int __init get_cpu_for_node(struct device_node *node)
{
struct device_node *cpu_node;
@@ -34,6 +106,7 @@ static int __init get_cpu_for_node(struct device_node *node)
for_each_possible_cpu(cpu) {
if (of_get_cpu_node(cpu, NULL) == cpu_node) {
+ parse_cpu_capacity(cpu_node, cpu);
of_node_put(cpu_node);
return cpu;
}
@@ -185,6 +258,8 @@ static int __init parse_dt_topology(void)
if (ret != 0)
goto out_map;
+ normalize_cpu_capacity();
+
/*
* Check that all cores are in the topology; the SMP code will
* only mark cores described in the DT as possible.
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 6/8] arm64, dts: add Juno cpu capacity information
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
` (4 preceding siblings ...)
2016-03-18 14:24 ` [PATCH v4 5/8] arm64: parse cpu capacity from DT Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 14:24 ` [PATCH v4 7/8] arm: add sysfs cpu_capacity attribute Juri Lelli
2016-03-18 14:24 ` [PATCH v4 8/8] arm64: " Juri Lelli
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
juri.lelli, broonie, Pawel Moll, Ian Campbell, Kumar Gala,
Liviu Dudau, Arnd Bergmann, Jon Medhurst, Olof Johansson,
Robin Murphy
Add Juno cpu capacity bindings information.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Liviu Dudau <Liviu.Dudau@arm.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Jon Medhurst <tixy@linaro.org>
Cc: Olof Johansson <olof@lixom.net>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: devicetree@vger.kernel.org
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
Changes from v1:
- capacity-scale removed
---
arch/arm64/boot/dts/arm/juno.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index dcfcf15..a15c781 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -90,6 +90,7 @@
next-level-cache = <&A57_L2>;
clocks = <&scpi_dvfs 0>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <1024>;
};
A57_1: cpu@1 {
@@ -100,6 +101,7 @@
next-level-cache = <&A57_L2>;
clocks = <&scpi_dvfs 0>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <1024>;
};
A53_0: cpu@100 {
@@ -110,6 +112,7 @@
next-level-cache = <&A53_L2>;
clocks = <&scpi_dvfs 1>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
};
A53_1: cpu@101 {
@@ -120,6 +123,7 @@
next-level-cache = <&A53_L2>;
clocks = <&scpi_dvfs 1>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
};
A53_2: cpu@102 {
@@ -130,6 +134,7 @@
next-level-cache = <&A53_L2>;
clocks = <&scpi_dvfs 1>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
};
A53_3: cpu@103 {
@@ -140,6 +145,7 @@
next-level-cache = <&A53_L2>;
clocks = <&scpi_dvfs 1>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+ capacity = <447>;
};
A57_L2: l2-cache0 {
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 7/8] arm: add sysfs cpu_capacity attribute
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
` (5 preceding siblings ...)
2016-03-18 14:24 ` [PATCH v4 6/8] arm64, dts: add Juno cpu capacity information Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
2016-03-18 14:24 ` [PATCH v4 8/8] arm64: " Juri Lelli
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
juri.lelli, broonie
Add a sysfs cpu_capacity attribute with which it is possible to read and
write (thus over-writing default values) CPUs capacity. This might be
useful in situations where values needs changing after boot.
The new attribute shows up as:
/sys/devices/system/cpu/cpu*/cpu_capacity
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
arch/arm/kernel/topology.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index 53c13c1..28a4029 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -52,6 +52,74 @@ static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
per_cpu(cpu_scale, cpu) = capacity;
}
+#ifdef CONFIG_PROC_SYSCTL
+#include <asm/cpu.h>
+#include <linux/string.h>
+static ssize_t show_cpu_capacity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, dev);
+ ssize_t rc;
+ int cpunum = cpu->dev.id;
+ unsigned long capacity = arch_scale_cpu_capacity(NULL, cpunum);
+
+ rc = sprintf(buf, "%lu\n", capacity);
+
+ return rc;
+}
+
+static ssize_t store_cpu_capacity(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, dev);
+ int this_cpu = cpu->dev.id, i;
+ unsigned long new_capacity;
+ ssize_t ret;
+
+ if (count) {
+ char *p = (char *) buf;
+
+ ret = kstrtoul(p, 0, &new_capacity);
+ if (ret)
+ return ret;
+ if (new_capacity > SCHED_CAPACITY_SCALE)
+ return -EINVAL;
+
+ for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
+ set_capacity_scale(i, new_capacity);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(cpu_capacity,
+ 0644,
+ show_cpu_capacity,
+ store_cpu_capacity);
+
+static int register_cpu_capacity_sysctl(void)
+{
+ int i;
+ struct device *cpu;
+
+ for_each_possible_cpu(i) {
+ cpu = get_cpu_device(i);
+ if (!cpu) {
+ pr_err("%s: too early to get CPU%d device!\n",
+ __func__, i);
+ continue;
+ }
+ device_create_file(cpu, &dev_attr_cpu_capacity);
+ }
+
+ return 0;
+}
+late_initcall(register_cpu_capacity_sysctl);
+#endif
+
#ifdef CONFIG_OF
struct cpu_efficiency {
const char *compatible;
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v4 8/8] arm64: add sysfs cpu_capacity attribute
2016-03-18 14:24 [PATCH v4 0/8] CPUs capacity information for heterogeneous systems Juri Lelli
` (6 preceding siblings ...)
2016-03-18 14:24 ` [PATCH v4 7/8] arm: add sysfs cpu_capacity attribute Juri Lelli
@ 2016-03-18 14:24 ` Juri Lelli
7 siblings, 0 replies; 20+ messages in thread
From: Juri Lelli @ 2016-03-18 14:24 UTC (permalink / raw)
To: linux-kernel
Cc: linux-pm, linux-arm-kernel, devicetree, peterz, vincent.guittot,
robh+dt, mark.rutland, linux, sudeep.holla, lorenzo.pieralisi,
catalin.marinas, will.deacon, morten.rasmussen, dietmar.eggemann,
juri.lelli, broonie, Mark Brown
Add a sysfs cpu_capacity attribute with which it is possible to read and
write (thus over-writing default values) CPUs capacity. This might be
useful in situations where values needs changing after boot.
The new attribute shows up as:
/sys/devices/system/cpu/cpu*/cpu_capacity
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Brown <broonie@linaro.org>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Juri Lelli <juri.lelli@arm.com>
---
arch/arm64/kernel/topology.c | 68 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 69229b3..4d1fddb 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -36,6 +36,74 @@ static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
per_cpu(cpu_scale, cpu) = capacity;
}
+#ifdef CONFIG_PROC_SYSCTL
+#include <asm/cpu.h>
+#include <linux/string.h>
+static ssize_t show_cpu_capacity(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, dev);
+ ssize_t rc;
+ int cpunum = cpu->dev.id;
+ unsigned long capacity = arch_scale_cpu_capacity(NULL, cpunum);
+
+ rc = sprintf(buf, "%lu\n", capacity);
+
+ return rc;
+}
+
+static ssize_t store_cpu_capacity(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, dev);
+ int this_cpu = cpu->dev.id, i;
+ unsigned long new_capacity;
+ ssize_t ret;
+
+ if (count) {
+ char *p = (char *) buf;
+
+ ret = kstrtoul(p, 0, &new_capacity);
+ if (ret)
+ return ret;
+ if (new_capacity > SCHED_CAPACITY_SCALE)
+ return -EINVAL;
+
+ for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
+ set_capacity_scale(i, new_capacity);
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(cpu_capacity,
+ 0644,
+ show_cpu_capacity,
+ store_cpu_capacity);
+
+static int register_cpu_capacity_sysctl(void)
+{
+ int i;
+ struct device *cpu;
+
+ for_each_possible_cpu(i) {
+ cpu = get_cpu_device(i);
+ if (!cpu) {
+ pr_err("%s: too early to get CPU%d device!\n",
+ __func__, i);
+ continue;
+ }
+ device_create_file(cpu, &dev_attr_cpu_capacity);
+ }
+
+ return 0;
+}
+late_initcall(register_cpu_capacity_sysctl);
+#endif
+
static u32 capacity_scale;
static u32 *raw_capacity;
static bool cap_parsing_failed;
--
2.7.0
^ permalink raw reply related [flat|nested] 20+ messages in thread