2013-07-15 10:22:27

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 00/11] ARM: DT: update cpu device of_node

From: Sudeep KarkadaNagesha <[email protected]>

As more and more information is getting added into the cpu node, the number
of drivers needing to parse the device tree for CPU nodes are increasing.
Most of the time, the information needed from the cpu node is preferred
in the logical CPU order. Hence many drivers first parse and search the
CPU node, match them to logical index if needed and then search for the
required property inside a particular cpu node. Some of them assume the
logical and physical CPU ordering to be same which is incorrect.

This patch series initialises the of_node in all the cpu devices when
registering the CPU device.
1. This avoids different drivers having to parse the cpu nodes to obtain
different attributes like operating points, latency,...etc.
2. This handles different physical and logical cpu ordering which is not
the case in current code.
3. Also all the cpu nodes will have their of_node initialised correctly.
Currently different drivers assign them partially and incorrectly.
4. Removes all the reduntant parsing in various drivers.

Regards,
Sudeep

Sudeep KarkadaNagesha (11):
driver/core: cpu: initialize of_node in cpu's device struture
ARM: DT/kernel: define ARM specific arch_of_get_cpu_node
ARM: topology: remove hwid(MPIDR dependency) from cpu_capacity
ARM: mvebu: remove device tree parsing for cpu nodes
drivers/bus: arm-cci: avoid parsing DT for cpu device nodes
cpufreq: imx6q-cpufreq: remove device tree parsing for cpu nodes
cpufreq: cpufreq-cpu0: remove device tree parsing for cpu nodes
cpufreq: highbank-cpufreq: remove device tree parsing for cpu nodes
cpufreq: spear-cpufreq: remove device tree parsing for cpu nodes
cpufreq: kirkwood-cpufreq: remove device tree parsing for cpu nodes
cpufreq: arm_big_little: remove device tree parsing for cpu nodes

arch/arm/include/asm/prom.h | 1 +
arch/arm/kernel/devtree.c | 29 ++++++++++++++++++
arch/arm/kernel/topology.c | 61 ++++++++++++-------------------------
arch/arm/mach-imx/mach-imx6q.c | 3 +-
arch/arm/mach-mvebu/platsmp.c | 52 +++++++++++++++----------------
drivers/base/cpu.c | 19 ++++++++++++
drivers/bus/arm-cci.c | 28 +++++------------
drivers/cpufreq/arm_big_little_dt.c | 39 +++++++++++-------------
drivers/cpufreq/cpufreq-cpu0.c | 23 +++-----------
drivers/cpufreq/highbank-cpufreq.c | 18 ++++-------
drivers/cpufreq/imx6q-cpufreq.c | 4 +--
drivers/cpufreq/kirkwood-cpufreq.c | 14 +++++++--
drivers/cpufreq/spear-cpufreq.c | 10 +++++-
13 files changed, 149 insertions(+), 152 deletions(-)

--
1.8.1.2


2013-07-15 10:22:32

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 10/11] cpufreq: kirkwood-cpufreq: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Now that the cpu device registration initialises the of_node(if available)
appropriately for all the cpus, parsing here is redundant.

This patch removes all DT parsing and uses cpu->of_node instead.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/cpufreq/kirkwood-cpufreq.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index c233ea6..18aa3eb 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -165,6 +166,7 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = {
static int kirkwood_cpufreq_probe(struct platform_device *pdev)
{
struct device_node *np;
+ struct device *cpu_dev;
struct resource *res;
int err;

@@ -175,9 +177,17 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
if (IS_ERR(priv.base))
return PTR_ERR(priv.base);

- np = of_find_node_by_path("/cpus/cpu@0");
- if (!np)
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ dev_err(&pdev->dev, "failed to get cpu device\n");
return -ENODEV;
+ }
+
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ dev_err(&pdev->dev, "failed to get cpu device node\n");
+ return -ENODEV;
+ }

priv.cpu_clk = of_clk_get_by_name(np, "cpu_clk");
if (IS_ERR(priv.cpu_clk)) {
--
1.8.1.2

2013-07-15 10:22:37

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 11/11] cpufreq: arm_big_little: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Now that the cpu device registration initialises the of_node(if available)
appropriately for all the cpus, parsing here is redundant.

This patch removes all DT parsing and uses cpu->of_node instead.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/cpufreq/arm_big_little_dt.c | 39 ++++++++++++++++---------------------
1 file changed, 17 insertions(+), 22 deletions(-)

diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index fd9e3ea..d2648d1 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -34,27 +34,19 @@
/* get cpu node with valid operating-points */
static struct device_node *get_cpu_node_with_valid_op(int cpu)
{
- struct device_node *np = NULL, *parent;
- int count = 0;
+ struct device *cpu_dev = get_cpu_device(cpu);
+ struct device_node *np;

- parent = of_find_node_by_path("/cpus");
- if (!parent) {
- pr_err("failed to find OF /cpus\n");
+ if (!cpu_dev) {
+ pr_err("failed to get cpu device\n");
return NULL;
}
-
- for_each_child_of_node(parent, np) {
- if (count++ != cpu)
- continue;
- if (!of_get_property(np, "operating-points", NULL)) {
- of_node_put(np);
- np = NULL;
- }
-
- break;
+ np = of_node_get(cpu_dev->of_node);
+ if (!of_get_property(np, "operating-points", NULL)) {
+ of_node_put(np);
+ np = NULL;
}

- of_node_put(parent);
return np;
}

@@ -63,11 +55,12 @@ static int dt_init_opp_table(struct device *cpu_dev)
struct device_node *np;
int ret;

- np = get_cpu_node_with_valid_op(cpu_dev->id);
- if (!np)
- return -ENODATA;
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ pr_err("failed to find cpu%d node\n", cpu_dev->id);
+ return -ENOENT;
+ }

- cpu_dev->of_node = np;
ret = of_init_opp_table(cpu_dev);
of_node_put(np);

@@ -79,9 +72,11 @@ static int dt_get_transition_latency(struct device *cpu_dev)
struct device_node *np;
u32 transition_latency = CPUFREQ_ETERNAL;

- np = get_cpu_node_with_valid_op(cpu_dev->id);
- if (!np)
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ pr_info("Failed to find cpu node. Use CPUFREQ_ETERNAL transition latency\n");
return CPUFREQ_ETERNAL;
+ }

of_property_read_u32(np, "clock-latency", &transition_latency);
of_node_put(np);
--
1.8.1.2

2013-07-15 10:22:31

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 07/11] cpufreq: cpufreq-cpu0: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Now that the cpu device registration initialises the of_node(if available)
appropriately for all the cpus, parsing here is redundant.

This patch removes all DT parsing and uses cpu->of_node instead.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/cpufreq/cpufreq-cpu0.c | 23 ++++-------------------
1 file changed, 4 insertions(+), 19 deletions(-)

diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index ad1fde2..5b05c26 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -174,29 +174,17 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {

static int cpu0_cpufreq_probe(struct platform_device *pdev)
{
- struct device_node *np, *parent;
+ struct device_node *np;
int ret;

- parent = of_find_node_by_path("/cpus");
- if (!parent) {
- pr_err("failed to find OF /cpus\n");
- return -ENOENT;
- }
-
- for_each_child_of_node(parent, np) {
- if (of_get_property(np, "operating-points", NULL))
- break;
- }
+ cpu_dev = &pdev->dev;

+ np = of_node_get(cpu_dev->of_node);
if (!np) {
pr_err("failed to find cpu0 node\n");
- ret = -ENOENT;
- goto out_put_parent;
+ return -ENOENT;
}

- cpu_dev = &pdev->dev;
- cpu_dev->of_node = np;
-
cpu_reg = devm_regulator_get(cpu_dev, "cpu0");
if (IS_ERR(cpu_reg)) {
/*
@@ -269,15 +257,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
}

of_node_put(np);
- of_node_put(parent);
return 0;

out_free_table:
opp_free_cpufreq_table(cpu_dev, &freq_table);
out_put_node:
of_node_put(np);
-out_put_parent:
- of_node_put(parent);
return ret;
}

--
1.8.1.2

2013-07-15 10:23:15

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 09/11] cpufreq: spear-cpufreq: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Now that the cpu device registration initialises the of_node(if available)
appropriately for all the cpus, parsing here is redundant.

This patch removes all DT parsing and uses cpu->of_node instead.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/cpufreq/spear-cpufreq.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index c3efa7f..eb73c47 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -14,6 +14,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/clk.h>
+#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/init.h>
@@ -218,12 +219,19 @@ static struct cpufreq_driver spear_cpufreq_driver = {
static int spear_cpufreq_driver_init(void)
{
struct device_node *np;
+ struct device *cpu_dev;
const struct property *prop;
struct cpufreq_frequency_table *freq_tbl;
const __be32 *val;
int cnt, i, ret;

- np = of_find_node_by_path("/cpus/cpu@0");
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ pr_err("failed to get cpu device\n");
+ return -ENODEV;
+ }
+
+ np = of_node_get(cpu_dev->of_node);
if (!np) {
pr_err("No cpu node found");
return -ENODEV;
--
1.8.1.2

2013-07-15 10:22:28

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 01/11] driver/core: cpu: initialize of_node in cpu's device struture

From: Sudeep KarkadaNagesha <[email protected]>

CPUs are also registered as devices but the of_node in these cpu
devices are not initialized. Currently different drivers requiring
to access cpu device node are parsing the nodes themselves and
initialising the of_node in cpu device.

The of_node in all the cpu devices properly needs to be initialized
properly and at one place. The best place to update this is CPU
subsystem driver when registering the cpu devices.

This patch introduces a new function arch_of_get_cpu_node and uses it
to assign of_node. The definition of this function can be overridden
by architecture specific implementation.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/base/cpu.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index a16d20e..4b3047a 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -28,6 +28,24 @@ static int cpu_subsys_match(struct device *dev, struct device_driver *drv)
return 0;
}

+/**
+ * arch_of_get_cpu_node - Get device node associated with the given logical CPU
+ * @cpu: CPU number(logical index) for which device node is required
+ *
+ * The only purpose of this function is to retrieve the device node for the
+ * given logical CPU index. It should be used to intialise the of_node in
+ * cpu device. Once of_node in cpu device is populated, all the further
+ * references can use that instead.
+ *
+ * CPU logical to physical index mapping is architecure specific and is built
+ * before booting secondary cores. Hence this function is marked __weak and
+ * can be overridden by architecture specific implementation.
+ */
+struct device_node * __weak arch_of_get_cpu_node(int cpu)
+{
+ return NULL;
+}
+
#ifdef CONFIG_HOTPLUG_CPU
static void change_cpu_under_node(struct cpu *cpu,
unsigned int from_nid, unsigned int to_nid)
@@ -289,6 +307,7 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
cpu->dev.release = cpu_device_release;
cpu->dev.offline_disabled = !cpu->hotpluggable;
cpu->dev.offline = !cpu_online(num);
+ cpu->dev.of_node = arch_of_get_cpu_node(num);
#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
cpu->dev.bus->uevent = arch_cpu_uevent;
#endif
--
1.8.1.2

2013-07-15 10:23:43

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 08/11] cpufreq: highbank-cpufreq: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Now that the cpu device registration initialises the of_node(if available)
appropriately for all the cpus, parsing here is redundant.

This patch removes all DT parsing and uses cpu->of_node instead.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/cpufreq/highbank-cpufreq.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c
index b61b5a3..794123f 100644
--- a/drivers/cpufreq/highbank-cpufreq.c
+++ b/drivers/cpufreq/highbank-cpufreq.c
@@ -69,23 +69,17 @@ static int hb_cpufreq_driver_init(void)
if (!of_machine_is_compatible("calxeda,highbank"))
return -ENODEV;

- for_each_child_of_node(of_find_node_by_path("/cpus"), np)
- if (of_get_property(np, "operating-points", NULL))
- break;
-
- if (!np) {
- pr_err("failed to find highbank cpufreq node\n");
- return -ENOENT;
- }
-
cpu_dev = get_cpu_device(0);
if (!cpu_dev) {
pr_err("failed to get highbank cpufreq device\n");
- ret = -ENODEV;
- goto out_put_node;
+ return -ENODEV;
}

- cpu_dev->of_node = np;
+ np = of_node_get(cpu_dev->of_node);
+ if (!np) {
+ pr_err("failed to find highbank cpufreq node\n");
+ return -ENOENT;
+ }

cpu_clk = clk_get(cpu_dev, NULL);
if (IS_ERR(cpu_clk)) {
--
1.8.1.2

2013-07-15 10:24:03

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 06/11] cpufreq: imx6q-cpufreq: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Now that the cpu device registration initialises the of_node(if available)
appropriately for all the cpus, parsing here is redundant.

This patch removes all DT parsing and uses cpu->of_node instead.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
arch/arm/mach-imx/mach-imx6q.c | 3 +--
drivers/cpufreq/imx6q-cpufreq.c | 4 +---
2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 7be13f8..a02f275 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -254,13 +254,12 @@ static void __init imx6q_opp_init(struct device *cpu_dev)
{
struct device_node *np;

- np = of_find_node_by_path("/cpus/cpu@0");
+ np = of_node_get(cpu_dev->of_node);
if (!np) {
pr_warn("failed to find cpu0 node\n");
return;
}

- cpu_dev->of_node = np;
if (of_init_opp_table(cpu_dev)) {
pr_warn("failed to init OPP table\n");
goto put_node;
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index e37cdae..b16632b 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -221,14 +221,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)

cpu_dev = &pdev->dev;

- np = of_find_node_by_path("/cpus/cpu@0");
+ np = of_node_get(cpu_dev->of_node);
if (!np) {
dev_err(cpu_dev, "failed to find cpu0 node\n");
return -ENOENT;
}

- cpu_dev->of_node = np;
-
arm_clk = devm_clk_get(cpu_dev, "arm");
pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys");
pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw");
--
1.8.1.2

2013-07-15 10:24:29

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 04/11] ARM: mvebu: remove device tree parsing for cpu nodes

From: Sudeep KarkadaNagesha <[email protected]>

Currently set_secondary_cpus_clock assume the CPU logical ordering
and the MPDIR in DT are same, which is incorrect.

Since the CPU device nodes can be retrieved in the logical ordering
using the helper, we can remove the devices tree parsing.

This patch removes DT parsing by making use of arch_of_get_cpu_node.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
arch/arm/mach-mvebu/platsmp.c | 52 ++++++++++++++++++++-----------------------
1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c
index 93f2f3a..b57af6c 100644
--- a/arch/arm/mach-mvebu/platsmp.c
+++ b/arch/arm/mach-mvebu/platsmp.c
@@ -23,51 +23,47 @@
#include <linux/of.h>
#include <linux/mbus.h>
#include <asm/cacheflush.h>
+#include <asm/prom.h>
#include <asm/smp_plat.h>
#include "common.h"
#include "armada-370-xp.h"
#include "pmsu.h"
#include "coherency.h"

+static struct clk *__init get_cpu_clk(int cpu)
+{
+ struct clk *cpu_clk;
+ struct device_node *np = arch_of_get_cpu_node(cpu);
+
+ if (WARN(!np, "missing cpu node\n"))
+ return NULL;
+ cpu_clk = of_clk_get(np, 0);
+ if (WARN_ON(IS_ERR(cpu_clk)))
+ return NULL;
+ return cpu_clk;
+}
+
void __init set_secondary_cpus_clock(void)
{
- int thiscpu;
+ int thiscpu, cpu;
unsigned long rate;
- struct clk *cpu_clk = NULL;
- struct device_node *np = NULL;
+ struct clk *cpu_clk;

thiscpu = smp_processor_id();
- for_each_node_by_type(np, "cpu") {
- int err;
- int cpu;
-
- err = of_property_read_u32(np, "reg", &cpu);
- if (WARN_ON(err))
- return;
-
- if (cpu == thiscpu) {
- cpu_clk = of_clk_get(np, 0);
- break;
- }
- }
- if (WARN_ON(IS_ERR(cpu_clk)))
+ cpu_clk = get_cpu_clk(thiscpu);
+ if (!cpu_clk)
return;
clk_prepare_enable(cpu_clk);
rate = clk_get_rate(cpu_clk);

/* set all the other CPU clk to the same rate than the boot CPU */
- for_each_node_by_type(np, "cpu") {
- int err;
- int cpu;
-
- err = of_property_read_u32(np, "reg", &cpu);
- if (WARN_ON(err))
+ for_each_possible_cpu(cpu) {
+ if (cpu == thiscpu)
+ continue;
+ cpu_clk = get_cpu_clk(cpu);
+ if (!cpu_clk)
return;
-
- if (cpu != thiscpu) {
- cpu_clk = of_clk_get(np, 0);
- clk_set_rate(cpu_clk, rate);
- }
+ clk_set_rate(cpu_clk, rate);
}
}

--
1.8.1.2

2013-07-15 10:24:27

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 02/11] ARM: DT/kernel: define ARM specific arch_of_get_cpu_node

From: Sudeep KarkadaNagesha <[email protected]>

CPU subsystem now provides architecture specific hook to retrieve the
of_node. Most of the cpu DT node parsing and initialisation is contained
in devtree.c. It's better to contain all CPU device node parsing there.

arch_of_get_cpu_node is mainly used to assign cpu->of_node when CPUs get
registered. This patch overrides the defination of the same. It can also
act as the helper function in pre-SMP/early initialisation stages to
retrieve CPU device node pointers in logical ordering.

This mainly helps to avoid replication of the code doing CPU node parsing
and physical(MPIDR) to logical mapping.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
arch/arm/include/asm/prom.h | 1 +
arch/arm/kernel/devtree.c | 29 +++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)

diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index a219227..96f1682 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -18,6 +18,7 @@
extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
extern void arm_dt_memblock_reserve(void);
extern void __init arm_dt_init_cpu_maps(void);
+extern struct device_node *arch_of_get_cpu_node(int cpu);

#else /* CONFIG_OF */

diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 5859c8b..3431aa9 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -169,6 +169,35 @@ void __init arm_dt_init_cpu_maps(void)
}
}

+struct device_node * __init arch_of_get_cpu_node(int cpu)
+{
+ struct device_node *cpun, *cpus;
+ const u32 *cell;
+ u64 hwid;
+ int ac;
+
+ cpus = of_find_node_by_path("/cpus");
+ if (WARN(!cpus, "Missing cpus node, bailing out\n"))
+ return NULL;
+
+ if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac)))
+ ac = of_n_addr_cells(cpus);
+
+ for_each_child_of_node(cpus, cpun) {
+ if (of_node_cmp(cpun->type, "cpu"))
+ continue;
+ cell = of_get_property(cpun, "reg", NULL);
+ if (WARN(!cell, "%s: missing reg property\n", cpun->full_name))
+ continue;
+
+ hwid = of_read_number(cell, ac);
+ if ((hwid & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu))
+ return cpun;
+ }
+
+ return NULL;
+}
+
/**
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
* @dt_phys: physical address of dt blob
--
1.8.1.2

2013-07-15 10:24:26

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 05/11] drivers/bus: arm-cci: avoid parsing DT for cpu device nodes

From: Sudeep KarkadaNagesha <[email protected]>

Since the CPU device nodes can be retrieved using arch_of_get_cpu_node,
we can use it to avoid parsing the cpus node searching the cpu nodes and
mapping to logical index.

This patch removes parsing DT for cpu nodes by using arch_of_get_cpu_node.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
drivers/bus/arm-cci.c | 28 +++++++---------------------
1 file changed, 7 insertions(+), 21 deletions(-)

diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 7332889..8de67c2 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -122,17 +122,8 @@ EXPORT_SYMBOL_GPL(cci_ace_get_port);

static void __init cci_ace_init_ports(void)
{
- int port, ac, cpu;
- u64 hwid;
- const u32 *cell;
- struct device_node *cpun, *cpus;
-
- cpus = of_find_node_by_path("/cpus");
- if (WARN(!cpus, "Missing cpus node, bailing out\n"))
- return;
-
- if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac)))
- ac = of_n_addr_cells(cpus);
+ int port, cpu;
+ struct device_node *cpun;

/*
* Port index look-up speeds up the function disabling ports by CPU,
@@ -141,18 +132,13 @@ static void __init cci_ace_init_ports(void)
* The stashed index array is initialized for all possible CPUs
* at probe time.
*/
- for_each_child_of_node(cpus, cpun) {
- if (of_node_cmp(cpun->type, "cpu"))
- continue;
- cell = of_get_property(cpun, "reg", NULL);
- if (WARN(!cell, "%s: missing reg property\n", cpun->full_name))
- continue;
-
- hwid = of_read_number(cell, ac);
- cpu = get_logical_index(hwid & MPIDR_HWID_BITMASK);
+ for_each_possible_cpu(cpu) {
+ /* too early to use cpu->of_node */
+ cpun = arch_of_get_cpu_node(cpu);

- if (cpu < 0 || !cpu_possible(cpu))
+ if (WARN(!cpun, "Missing cpu device node\n"))
continue;
+
port = __cci_ace_get_port(cpun, ACE_PORT);
if (port < 0)
continue;
--
1.8.1.2

2013-07-15 10:25:34

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: [RFC PATCH 03/11] ARM: topology: remove hwid/MPIDR dependency from cpu_capacity

From: Sudeep KarkadaNagesha <[email protected]>

Currently the topology code computes cpu capacity and stores it in
the list along with hwid(which is MPIDR) as it parses the CPU nodes
in the device tree. This is required as it needs to be mapped to the
logical CPU later.

Since the CPU device nodes can be retrieved in the logical ordering
using helpers, its possible to store cpu_capacity also in logical
ordering and avoid storing hwid for each entry.

This patch removes hwid by making use of arch_of_get_cpu_node.

Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
---
arch/arm/kernel/topology.c | 61 +++++++++++++++-------------------------------
1 file changed, 19 insertions(+), 42 deletions(-)

diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c
index c5a5954..c1a8f05 100644
--- a/arch/arm/kernel/topology.c
+++ b/arch/arm/kernel/topology.c
@@ -74,12 +74,8 @@ struct cpu_efficiency table_efficiency[] = {
{NULL, },
};

-struct cpu_capacity {
- unsigned long hwid;
- unsigned long capacity;
-};
-
-struct cpu_capacity *cpu_capacity;
+unsigned long *__cpu_capacity;
+#define cpu_capacity(cpu) __cpu_capacity[cpu]

unsigned long middle_capacity = 1;

@@ -100,15 +96,19 @@ static void __init parse_dt_topology(void)
unsigned long capacity = 0;
int alloc_size, cpu = 0;

- alloc_size = nr_cpu_ids * sizeof(struct cpu_capacity);
- cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT);
+ alloc_size = nr_cpu_ids * sizeof(*__cpu_capacity);
+ __cpu_capacity = kzalloc(alloc_size, GFP_NOWAIT);

- while ((cn = of_find_node_by_type(cn, "cpu"))) {
- const u32 *rate, *reg;
+ for_each_possible_cpu(cpu) {
+ const u32 *rate;
int len;

- if (cpu >= num_possible_cpus())
- break;
+ /* too early to use cpu->of_node */
+ cn = arch_of_get_cpu_node(cpu);
+ if (!cn) {
+ pr_err("missing device node for CPU %d\n", cpu);
+ continue;
+ }

for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
if (of_device_is_compatible(cn, cpu_eff->compatible))
@@ -124,12 +124,6 @@ static void __init parse_dt_topology(void)
continue;
}

- reg = of_get_property(cn, "reg", &len);
- if (!reg || len != 4) {
- pr_err("%s missing reg property\n", cn->full_name);
- continue;
- }
-
capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;

/* Save min capacity of the system */
@@ -140,13 +134,9 @@ static void __init parse_dt_topology(void)
if (capacity > max_capacity)
max_capacity = capacity;

- cpu_capacity[cpu].capacity = capacity;
- cpu_capacity[cpu++].hwid = be32_to_cpup(reg);
+ cpu_capacity(cpu) = capacity;
}

- if (cpu < num_possible_cpus())
- cpu_capacity[cpu].hwid = (unsigned long)(-1);
-
/* If min and max capacities are equals, we bypass the update of the
* cpu_scale because all CPUs have the same capacity. Otherwise, we
* compute a middle_capacity factor that will ensure that the capacity
@@ -154,9 +144,7 @@ static void __init parse_dt_topology(void)
* SCHED_POWER_SCALE, which is the default value, but with the
* constraint explained near table_efficiency[].
*/
- if (min_capacity == max_capacity)
- cpu_capacity[0].hwid = (unsigned long)(-1);
- else if (4*max_capacity < (3*(max_capacity + min_capacity)))
+ if (4*max_capacity < (3*(max_capacity + min_capacity)))
middle_capacity = (min_capacity + max_capacity)
>> (SCHED_POWER_SHIFT+1);
else
@@ -170,23 +158,12 @@ static void __init parse_dt_topology(void)
* boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
* function returns directly for SMP system.
*/
-void update_cpu_power(unsigned int cpu, unsigned long hwid)
+void update_cpu_power(unsigned int cpu)
{
- unsigned int idx = 0;
-
- /* look for the cpu's hwid in the cpu capacity table */
- for (idx = 0; idx < num_possible_cpus(); idx++) {
- if (cpu_capacity[idx].hwid == hwid)
- break;
-
- if (cpu_capacity[idx].hwid == -1)
- return;
- }
-
- if (idx == num_possible_cpus())
+ if (!cpu_capacity(cpu))
return;

- set_power_scale(cpu, cpu_capacity[idx].capacity / middle_capacity);
+ set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity);

printk(KERN_INFO "CPU%u: update cpu_power %lu\n",
cpu, arch_scale_freq_power(NULL, cpu));
@@ -194,7 +171,7 @@ void update_cpu_power(unsigned int cpu, unsigned long hwid)

#else
static inline void parse_dt_topology(void) {}
-static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {}
+static inline void update_cpu_power(unsigned int cpuid) {}
#endif

/*
@@ -281,7 +258,7 @@ void store_cpu_topology(unsigned int cpuid)

update_siblings_masks(cpuid);

- update_cpu_power(cpuid, mpidr & MPIDR_HWID_BITMASK);
+ update_cpu_power(cpuid);

printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
cpuid, cpu_topology[cpuid].thread_id,
--
1.8.1.2

2013-07-15 19:11:08

by Rob Herring

[permalink] [raw]
Subject: Re: [RFC PATCH 02/11] ARM: DT/kernel: define ARM specific arch_of_get_cpu_node

On 07/15/2013 05:22 AM, [email protected] wrote:
> From: Sudeep KarkadaNagesha <[email protected]>
>
> CPU subsystem now provides architecture specific hook to retrieve the
> of_node. Most of the cpu DT node parsing and initialisation is contained
> in devtree.c. It's better to contain all CPU device node parsing there.
>
> arch_of_get_cpu_node is mainly used to assign cpu->of_node when CPUs get
> registered. This patch overrides the defination of the same. It can also
> act as the helper function in pre-SMP/early initialisation stages to
> retrieve CPU device node pointers in logical ordering.
>
> This mainly helps to avoid replication of the code doing CPU node parsing
> and physical(MPIDR) to logical mapping.
>
> Signed-off-by: Sudeep KarkadaNagesha <[email protected]>

[snip]

> +struct device_node * __init arch_of_get_cpu_node(int cpu)
> +{
> + struct device_node *cpun, *cpus;
> + const u32 *cell;
> + u64 hwid;
> + int ac;
> +
> + cpus = of_find_node_by_path("/cpus");
> + if (WARN(!cpus, "Missing cpus node, bailing out\n"))
> + return NULL;
> +
> + if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac)))
> + ac = of_n_addr_cells(cpus);
> +
> + for_each_child_of_node(cpus, cpun) {
> + if (of_node_cmp(cpun->type, "cpu"))
> + continue;
> + cell = of_get_property(cpun, "reg", NULL);
> + if (WARN(!cell, "%s: missing reg property\n", cpun->full_name))
> + continue;
> +
> + hwid = of_read_number(cell, ac);
> + if ((hwid & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu))

Most of this function is not ARM specific, so it would be nice if we
could shrink the arch specific part down to just this match. A default
match of reg == logical cpu number might be useful.

The powermac cpufreq driver could probably also be converted
(arch/powerpc/platforms/powermac/cpufreq_64.c).

Other than that, this series looks good to me.

Rob

2013-07-16 01:27:21

by Shawn Guo

[permalink] [raw]
Subject: Re: [RFC PATCH 07/11] cpufreq: cpufreq-cpu0: remove device tree parsing for cpu nodes

On Mon, Jul 15, 2013 at 11:22:08AM +0100, [email protected] wrote:
> From: Sudeep KarkadaNagesha <[email protected]>
>
> Now that the cpu device registration initialises the of_node(if available)
> appropriately for all the cpus, parsing here is redundant.
>
> This patch removes all DT parsing and uses cpu->of_node instead.
>
> Signed-off-by: Sudeep KarkadaNagesha <[email protected]>

Acked-by: Shawn Guo <[email protected]>

2013-07-16 01:37:34

by Shawn Guo

[permalink] [raw]
Subject: Re: [RFC PATCH 06/11] cpufreq: imx6q-cpufreq: remove device tree parsing for cpu nodes

On Mon, Jul 15, 2013 at 11:22:07AM +0100, [email protected] wrote:
> From: Sudeep KarkadaNagesha <[email protected]>
>
> Now that the cpu device registration initialises the of_node(if available)
> appropriately for all the cpus, parsing here is redundant.
>
> This patch removes all DT parsing and uses cpu->of_node instead.
>
> Signed-off-by: Sudeep KarkadaNagesha <[email protected]>

Acked-by: Shawn Guo <[email protected]>

> ---
> arch/arm/mach-imx/mach-imx6q.c | 3 +--
> drivers/cpufreq/imx6q-cpufreq.c | 4 +---
> 2 files changed, 2 insertions(+), 5 deletions(-)

2013-07-16 06:27:07

by Viresh Kumar

[permalink] [raw]
Subject: Re: [RFC PATCH 01/11] driver/core: cpu: initialize of_node in cpu's device struture

On 15 July 2013 15:52, <[email protected]> wrote:
> From: Sudeep KarkadaNagesha <[email protected]>
>
> CPUs are also registered as devices but the of_node in these cpu
> devices are not initialized. Currently different drivers requiring
> to access cpu device node are parsing the nodes themselves and
> initialising the of_node in cpu device.
>
> The of_node in all the cpu devices properly needs to be initialized

s/properly /

> properly and at one place. The best place to update this is CPU
> subsystem driver when registering the cpu devices.
>
> This patch introduces a new function arch_of_get_cpu_node and uses it
> to assign of_node. The definition of this function can be overridden
> by architecture specific implementation.
>
> Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
> ---
> drivers/base/cpu.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index a16d20e..4b3047a 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -28,6 +28,24 @@ static int cpu_subsys_match(struct device *dev, struct device_driver *drv)
> return 0;
> }
>
> +/**
> + * arch_of_get_cpu_node - Get device node associated with the given logical CPU
> + * @cpu: CPU number(logical index) for which device node is required
> + *
> + * The only purpose of this function is to retrieve the device node for the
> + * given logical CPU index. It should be used to intialise the of_node in
> + * cpu device. Once of_node in cpu device is populated, all the further
> + * references can use that instead.
> + *
> + * CPU logical to physical index mapping is architecure specific and is built
> + * before booting secondary cores. Hence this function is marked __weak and
> + * can be overridden by architecture specific implementation.
> + */
> +struct device_node * __weak arch_of_get_cpu_node(int cpu)
> +{
> + return NULL;
> +}
> +
> #ifdef CONFIG_HOTPLUG_CPU
> static void change_cpu_under_node(struct cpu *cpu,
> unsigned int from_nid, unsigned int to_nid)
> @@ -289,6 +307,7 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
> cpu->dev.release = cpu_device_release;
> cpu->dev.offline_disabled = !cpu->hotpluggable;
> cpu->dev.offline = !cpu_online(num);
> + cpu->dev.of_node = arch_of_get_cpu_node(num);
> #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> cpu->dev.bus->uevent = arch_cpu_uevent;
> #endif
> --
> 1.8.1.2
>
>

2013-07-16 06:29:14

by Viresh Kumar

[permalink] [raw]
Subject: Re: [RFC PATCH 02/11] ARM: DT/kernel: define ARM specific arch_of_get_cpu_node

On 16 July 2013 00:40, Rob Herring <[email protected]> wrote:
> The powermac cpufreq driver could probably also be converted
> (arch/powerpc/platforms/powermac/cpufreq_64.c).

Its called: drivers/cpufreq/pmac64-cpufreq.c now.

2013-07-16 06:31:40

by Viresh Kumar

[permalink] [raw]
Subject: Re: [RFC PATCH 00/11] ARM: DT: update cpu device of_node

On 15 July 2013 15:52, <[email protected]> wrote:
> Sudeep KarkadaNagesha (11):
> cpufreq: imx6q-cpufreq: remove device tree parsing for cpu nodes
> cpufreq: cpufreq-cpu0: remove device tree parsing for cpu nodes
> cpufreq: highbank-cpufreq: remove device tree parsing for cpu nodes
> cpufreq: spear-cpufreq: remove device tree parsing for cpu nodes
> cpufreq: kirkwood-cpufreq: remove device tree parsing for cpu nodes
> cpufreq: arm_big_little: remove device tree parsing for cpu nodes

For cpufreq part:

Acked-by: Viresh Kumar <[email protected]>

2013-07-16 09:03:16

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: Re: [RFC PATCH 02/11] ARM: DT/kernel: define ARM specific arch_of_get_cpu_node

On 15/07/13 20:10, Rob Herring wrote:
> On 07/15/2013 05:22 AM, [email protected] wrote:
>> From: Sudeep KarkadaNagesha <[email protected]>
>>
>> CPU subsystem now provides architecture specific hook to retrieve the
>> of_node. Most of the cpu DT node parsing and initialisation is contained
>> in devtree.c. It's better to contain all CPU device node parsing there.
>>
>> arch_of_get_cpu_node is mainly used to assign cpu->of_node when CPUs get
>> registered. This patch overrides the defination of the same. It can also
>> act as the helper function in pre-SMP/early initialisation stages to
>> retrieve CPU device node pointers in logical ordering.
>>
>> This mainly helps to avoid replication of the code doing CPU node parsing
>> and physical(MPIDR) to logical mapping.
>>
>> Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
>
> [snip]
>
>> +struct device_node * __init arch_of_get_cpu_node(int cpu)
>> +{
>> + struct device_node *cpun, *cpus;
>> + const u32 *cell;
>> + u64 hwid;
>> + int ac;
>> +
>> + cpus = of_find_node_by_path("/cpus");
>> + if (WARN(!cpus, "Missing cpus node, bailing out\n"))
>> + return NULL;
>> +
>> + if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac)))
>> + ac = of_n_addr_cells(cpus);
>> +
>> + for_each_child_of_node(cpus, cpun) {
>> + if (of_node_cmp(cpun->type, "cpu"))
>> + continue;
>> + cell = of_get_property(cpun, "reg", NULL);
>> + if (WARN(!cell, "%s: missing reg property\n", cpun->full_name))
>> + continue;
>> +
>> + hwid = of_read_number(cell, ac);
>> + if ((hwid & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu))
>
> Most of this function is not ARM specific, so it would be nice if we
> could shrink the arch specific part down to just this match. A default
> match of reg == logical cpu number might be useful.
>
I completely agree, in fact that was my initial idea too.

But when I had a look at powerpc implementation of "of_get_cpu_node" in
arch/powerpc/kernel/prom.c, it looked like PPC is using some
compatibles(e.g. ibm,ppc-interrupt-server#s) which are not specified in
ePAPR. I am not sure is that's allowed or not, if allowed then we can't
have generic of_get_cpu_node with just arch specific hwid matching function.

Let me know how would you prefer me to proceed on this.

Regards,
Sudeep

2013-07-17 14:16:58

by Sudeep KarkadaNagesha

[permalink] [raw]
Subject: Re: [RFC PATCH 02/11] ARM: DT/kernel: define ARM specific arch_of_get_cpu_node

On 16/07/13 10:03, Sudeep KarkadaNagesha wrote:
> On 15/07/13 20:10, Rob Herring wrote:
>> On 07/15/2013 05:22 AM, [email protected] wrote:
>>> From: Sudeep KarkadaNagesha <[email protected]>
>>>
>>> CPU subsystem now provides architecture specific hook to retrieve the
>>> of_node. Most of the cpu DT node parsing and initialisation is contained
>>> in devtree.c. It's better to contain all CPU device node parsing there.
>>>
>>> arch_of_get_cpu_node is mainly used to assign cpu->of_node when CPUs get
>>> registered. This patch overrides the defination of the same. It can also
>>> act as the helper function in pre-SMP/early initialisation stages to
>>> retrieve CPU device node pointers in logical ordering.
>>>
>>> This mainly helps to avoid replication of the code doing CPU node parsing
>>> and physical(MPIDR) to logical mapping.
>>>
>>> Signed-off-by: Sudeep KarkadaNagesha <[email protected]>
>>
>> [snip]
>>
>>> +struct device_node * __init arch_of_get_cpu_node(int cpu)
>>> +{
>>> + struct device_node *cpun, *cpus;
>>> + const u32 *cell;
>>> + u64 hwid;
>>> + int ac;
>>> +
>>> + cpus = of_find_node_by_path("/cpus");
>>> + if (WARN(!cpus, "Missing cpus node, bailing out\n"))
>>> + return NULL;
>>> +
>>> + if (WARN_ON(of_property_read_u32(cpus, "#address-cells", &ac)))
>>> + ac = of_n_addr_cells(cpus);
>>> +
>>> + for_each_child_of_node(cpus, cpun) {
>>> + if (of_node_cmp(cpun->type, "cpu"))
>>> + continue;
>>> + cell = of_get_property(cpun, "reg", NULL);
>>> + if (WARN(!cell, "%s: missing reg property\n", cpun->full_name))
>>> + continue;
>>> +
>>> + hwid = of_read_number(cell, ac);
>>> + if ((hwid & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu))
>>
>> Most of this function is not ARM specific, so it would be nice if we
>> could shrink the arch specific part down to just this match. A default
>> match of reg == logical cpu number might be useful.
>>
> I completely agree, in fact that was my initial idea too.
>
> But when I had a look at powerpc implementation of "of_get_cpu_node" in
> arch/powerpc/kernel/prom.c, it looked like PPC is using some
> compatibles(e.g. ibm,ppc-interrupt-server#s) which are not specified in
> ePAPR. I am not sure is that's allowed or not, if allowed then we can't
> have generic of_get_cpu_node with just arch specific hwid matching function.

I meant property names not compatibles. Looks like PPC and SPARC seem to
use non-standard property names like "cpuid",
"ibm,ppc-interrupt-server#s" instead of single "reg" property for all
cpus/threads

Since the cpufreq driver doesn't depend on those properties, I moved
arch_of_get_cpu_node to OF/DT core in v2.

Regards,
Sudeep