From: Bjorn Helgaas <helgaas@kernel.org>
To: Ganapatrao Kulkarni <gkulkarni@caviumnetworks.com>
Cc: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
linux-ia64@vger.kernel.org, linux-metag@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org,
linux-sh@vger.kernel.org, linux-arch@vger.kernel.org,
Will.Deacon@arm.com, catalin.marinas@arm.com,
grant.likely@linaro.org, leif.lindholm@linaro.org,
rfranz@cavium.com, ard.biesheuvel@linaro.org, msalter@redhat.com,
robh+dt@kernel.org, steve.capper@linaro.org,
hanjun.guo@linaro.org, al.stone@linaro.org, arnd@arndb.de,
pawel.moll@arm.com, mark.rutland@arm.com,
ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
rjw@rjwysocki.net, lenb@kernel.org, marc.zyngier@arm.com,
lorenzo.pieralisi@arm.com, bhelgaas@google.com,
tony.luck@intel.com, fenghua.yu@intel.com,
james.hogan@imgtec.com, benh@kernel.crashing.org,
tglx@linutronix.de, mingo@redhat.com, hpa@zytor.com,
x86@kernel.org, jonathan@jonmasters.org, rrichter@cavium.com,
Prasun.Kapoor@caviumnetworks.com, gpkulkarni@gmail.com
Subject: Re: [PATCH v9 3/6] arm64/arm, numa, dt: adding numa dt binding implementation for arm64 platforms.
Date: Tue, 26 Jan 2016 14:36:04 -0600 [thread overview]
Message-ID: <20160126203603.GC17600@localhost> (raw)
In-Reply-To: <1453134965-6125-4-git-send-email-gkulkarni@caviumnetworks.com>
Subject is "arm64/arm, numa, dt: adding ..." What is the significance
of the "arm" part? The other patches only mention "arm64".
General comment: the code below has little, if anything, that is
actually arm64-specific. Maybe this is the first DT-based NUMA
platform? I don't see other similar code for other arches, so maybe
it's too early to try to generalize it, but we should try to avoid
adding duplicates of this code if/when other arches do show up.
On Mon, Jan 18, 2016 at 10:06:02PM +0530, Ganapatrao Kulkarni wrote:
> Adding numa dt binding support for arm64 based platforms.
> dt node parsing for numa topology is done using device property
> numa-node-id and device node distance-map.
>
> Reviewed-by: Robert Richter <rrichter@cavium.com>
> Signed-off-by: Ganapatrao Kulkarni <gkulkarni@caviumnetworks.com>
> ---
> arch/arm64/Kconfig | 10 ++
> arch/arm64/include/asm/numa.h | 10 ++
> arch/arm64/kernel/Makefile | 1 +
> arch/arm64/kernel/of_numa.c | 257 ++++++++++++++++++++++++++++++++++++++++++
> arch/arm64/kernel/smp.c | 2 +
> arch/arm64/mm/numa.c | 10 +-
> 6 files changed, 289 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm64/kernel/of_numa.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 74f5d73..775cf4a 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -515,6 +515,16 @@ config NUMA
> local memory of the CPU and add some more
> NUMA awareness to the kernel.
>
> +config OF_NUMA
> + bool "Device Tree NUMA support"
> + depends on NUMA
> + depends on OF
> + default y
> + help
> + Enable Device Tree NUMA support.
> + This enables the numa mapping of cpu, memory, io and
> + inter node distances using dt bindings.
> +
> config NODES_SHIFT
> int "Maximum NUMA Nodes (as a power of 2)"
> range 1 10
> diff --git a/arch/arm64/include/asm/numa.h b/arch/arm64/include/asm/numa.h
> index f28f15b0..54deb38 100644
> --- a/arch/arm64/include/asm/numa.h
> +++ b/arch/arm64/include/asm/numa.h
> @@ -37,4 +37,14 @@ void numa_store_cpu_info(unsigned int cpu);
> static inline void numa_store_cpu_info(unsigned int cpu) { }
> static inline void arm64_numa_init(void) { }
> #endif /* CONFIG_NUMA */
> +
> +struct device_node;
> +#ifdef CONFIG_OF_NUMA
> +int __init arm64_of_numa_init(void);
> +void __init of_numa_set_node_info(unsigned int cpu, struct device_node *dn);
> +#else
> +static inline void of_numa_set_node_info(unsigned int cpu,
> + struct device_node *dn) { }
> +#endif
> +
> #endif /* __ASM_NUMA_H */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 474691f..7987763 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -41,6 +41,7 @@ arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o
> arm64-obj-$(CONFIG_PCI) += pci.o
> arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
> arm64-obj-$(CONFIG_ACPI) += acpi.o
> +arm64-obj-$(CONFIG_OF_NUMA) += of_numa.o
>
> obj-y += $(arm64-obj-y) vdso/
> obj-m += $(arm64-obj-m)
> diff --git a/arch/arm64/kernel/of_numa.c b/arch/arm64/kernel/of_numa.c
> new file mode 100644
> index 0000000..2f9e34b
> --- /dev/null
> +++ b/arch/arm64/kernel/of_numa.c
> @@ -0,0 +1,257 @@
> +/*
> + * OF NUMA Parsing support.
> + *
> + * Copyright (C) 2015 Cavium Inc.
> + * Author: Ganapatrao Kulkarni <gkulkarni@cavium.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/ctype.h>
> +#include <linux/memblock.h>
> +#include <linux/module.h>
> +#include <linux/nodemask.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +
> +#include <asm/smp_plat.h>
> +
> +/* define default numa node to 0 */
> +#define DEFAULT_NODE 0
> +#define OF_NUMA_PROP "numa-node-id"
> +
> +/* Returns nid in the range [0..MAX_NUMNODES-1],
> + * or NUMA_NO_NODE if no valid numa-node-id entry found
> + * or DEFAULT_NODE if no numa-node-id entry exists
> + */
> +static int of_numa_prop_to_nid(const __be32 *of_numa_prop, int length)
> +{
> + int nid;
> +
> + if (!of_numa_prop)
> + return DEFAULT_NODE;
> +
> + if (length != sizeof(*of_numa_prop)) {
> + pr_warn("NUMA: Invalid of_numa_prop length %d found.\n",
> + length);
> + return NUMA_NO_NODE;
> + }
> +
> + nid = of_read_number(of_numa_prop, 1);
> + if (nid >= MAX_NUMNODES) {
> + pr_warn("NUMA: Invalid numa node %d found.\n", nid);
> + return NUMA_NO_NODE;
> + }
> +
> + return nid;
> +}
> +
> +/* Must hold reference to node during call */
> +static int of_get_numa_nid(struct device_node *device)
> +{
> + int length;
> + const __be32 *of_numa_prop;
> +
> + of_numa_prop = of_get_property(device, OF_NUMA_PROP, &length);
> +
> + return of_numa_prop_to_nid(of_numa_prop, length);
> +}
> +
> +static int __init early_init_of_get_numa_nid(unsigned long node)
> +{
> + int length;
> + const __be32 *of_numa_prop;
> +
> + of_numa_prop = of_get_flat_dt_prop(node, OF_NUMA_PROP, &length);
> +
> + return of_numa_prop_to_nid(of_numa_prop, length);
> +}
> +
> +/* Walk the device tree upwards, looking for a numa-node-id property */
> +int of_node_to_nid(struct device_node *device)
> +{
> + struct device_node *parent;
> + int nid = NUMA_NO_NODE;
> +
> + of_node_get(device);
> + while (device) {
> + const __be32 *of_numa_prop;
> + int length;
> +
> + of_numa_prop = of_get_property(device, OF_NUMA_PROP, &length);
> + if (of_numa_prop) {
> + nid = of_numa_prop_to_nid(of_numa_prop, length);
> + break;
> + }
> +
> + parent = device;
> + device = of_get_parent(parent);
> + of_node_put(parent);
> + }
> + of_node_put(device);
> +
> + return nid;
> +}
> +
> +void __init of_numa_set_node_info(unsigned int cpu, struct device_node *device)
> +{
> + int nid = DEFAULT_NODE;
> +
> + if (device)
> + nid = of_get_numa_nid(device);
> +
> + cpu_to_node_map[cpu] = nid;
> +}
> +
> +/*
> + * Even though we connect cpus to numa domains later in SMP
> + * init, we need to know the node ids now for all cpus.
> +*/
> +static int __init early_init_parse_cpu_node(unsigned long node)
> +{
> + int nid;
> +
> + const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
> +
> + /* We are scanning "cpu" nodes only */
> + if (type == NULL)
> + return 0;
> + else if (strcmp(type, "cpu") != 0)
> + return 0;
> +
> + nid = early_init_of_get_numa_nid(node);
> +
> + if (nid == NUMA_NO_NODE)
> + return -EINVAL;
> +
> + node_set(nid, numa_nodes_parsed);
> + return 0;
> +}
> +
> +static int __init early_init_parse_memory_node(unsigned long node)
> +{
> + const __be32 *reg, *endp;
> + int length;
> + int nid;
> +
> + const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
> +
> + /* We are scanning "memory" nodes only */
> + if (type == NULL)
> + return 0;
> + else if (strcmp(type, "memory") != 0)
> + return 0;
> +
> + nid = early_init_of_get_numa_nid(node);
> +
> + if (nid == NUMA_NO_NODE)
> + return -EINVAL;
> +
> + reg = of_get_flat_dt_prop(node, "reg", &length);
> + endp = reg + (length / sizeof(__be32));
> +
> + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
> + u64 base, size;
> +
> + base = dt_mem_next_cell(dt_root_addr_cells, ®);
> + size = dt_mem_next_cell(dt_root_size_cells, ®);
> + pr_debug("NUMA-DT: base = %llx , node = %u\n",
> + base, nid);
> +
> + if (numa_add_memblk(nid, base, size) < 0)
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int __init early_init_parse_distance_map_v1(unsigned long node,
> + const char *uname)
> +{
> +
> + const __be32 *prop_dist_matrix;
> + int length = 0, i, matrix_count;
> + int nr_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
> +
> + pr_info("NUMA: parsing numa-distance-map-v1\n");
> +
> + prop_dist_matrix =
> + of_get_flat_dt_prop(node, "distance-matrix", &length);
> +
> + if (!length) {
> + pr_err("NUMA: failed to parse distance-matrix\n");
> + return -ENODEV;
> + }
> +
> + matrix_count = ((length / sizeof(__be32)) / (3 * nr_size_cells));
> +
> + if ((matrix_count * sizeof(__be32) * 3 * nr_size_cells) != length) {
> + pr_warn("NUMA: invalid distance-matrix length %d\n", length);
> + return -EINVAL;
> + }
> +
> + for (i = 0; i < matrix_count; i++) {
> + u32 nodea, nodeb, distance;
> +
> + nodea = dt_mem_next_cell(nr_size_cells, &prop_dist_matrix);
> + nodeb = dt_mem_next_cell(nr_size_cells, &prop_dist_matrix);
> + distance = dt_mem_next_cell(nr_size_cells, &prop_dist_matrix);
> + numa_set_distance(nodea, nodeb, distance);
> + pr_debug("NUMA-DT: distance[node%d -> node%d] = %d\n",
> + nodea, nodeb, distance);
> +
> + /* Set default distance of node B->A same as A->B */
> + if (nodeb > nodea)
> + numa_set_distance(nodeb, nodea, distance);
> + }
> +
> + return 0;
> +}
> +
> +static int __init early_init_parse_distance_map(unsigned long node,
> + const char *uname)
> +{
> +
> + if (strcmp(uname, "distance-map") != 0)
> + return 0;
> +
> + if (of_flat_dt_is_compatible(node, "numa-distance-map-v1"))
> + return early_init_parse_distance_map_v1(node, uname);
> +
> + return -EINVAL;
> +}
> +
> +/**
> + * early_init_of_scan_numa_map - parse memory node and map nid to memory range.
> + */
> +int __init early_init_of_scan_numa_map(unsigned long node, const char *uname,
> + int depth, void *data)
> +{
> + int ret;
> +
> + ret = early_init_parse_cpu_node(node);
> +
> + if (!ret)
> + ret = early_init_parse_memory_node(node);
> +
> + if (!ret)
> + ret = early_init_parse_distance_map(node, uname);
> +
> + return ret;
> +}
> +
> +/* DT node mapping is done already early_init_of_scan_memory */
> +int __init arm64_of_numa_init(void)
> +{
> + return of_scan_flat_dt(early_init_of_scan_numa_map, NULL);
> +}
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index d6e7d6a..a2a8c2d 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -520,6 +520,8 @@ static void __init of_parse_and_init_cpus(void)
>
> pr_debug("cpu logical map 0x%llx\n", hwid);
> cpu_logical_map(cpu_count) = hwid;
> + /* map logical cpu to node */
> + of_numa_set_node_info(cpu_count, dn);
> next:
> cpu_count++;
> }
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 050b083..9e8704b 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -383,5 +383,13 @@ static int __init dummy_numa_init(void)
> */
> void __init arm64_numa_init(void)
> {
> - numa_init(dummy_numa_init);
> + int ret = -ENODEV;
> +
> +#ifdef CONFIG_OF_NUMA
> + if (!numa_off)
> + ret = numa_init(arm64_of_numa_init);
> +#endif
> +
> + if (ret)
> + numa_init(dummy_numa_init);
> }
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2016-01-26 20:36 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-18 16:35 [PATCH v9 0/6] arm64, numa: Add numa support for arm64 platforms Ganapatrao Kulkarni
2016-01-18 16:36 ` [PATCH v9 1/6] arm64, numa: adding " Ganapatrao Kulkarni
2016-01-26 18:52 ` Bjorn Helgaas
2016-01-18 16:36 ` [PATCH v9 2/6] Documentation, dt, arm64/arm: dt bindings for numa Ganapatrao Kulkarni
2016-01-20 14:18 ` Rob Herring
2016-01-26 17:16 ` Ganapatrao Kulkarni
2016-01-18 16:36 ` [PATCH v9 3/6] arm64/arm, numa, dt: adding numa dt binding implementation for arm64 platforms Ganapatrao Kulkarni
2016-01-26 20:36 ` Bjorn Helgaas [this message]
2016-01-28 14:39 ` Will Deacon
2016-01-28 17:12 ` Ganapatrao Kulkarni
2016-01-28 18:08 ` Will Deacon
2016-01-28 18:48 ` Ganapatrao Kulkarni
2016-01-18 16:36 ` [PATCH v9 4/6] arm64, dt, thunderx: Add initial dts for Cavium Thunderx in 2 node topology Ganapatrao Kulkarni
2016-01-18 17:49 ` David Daney
2016-01-18 16:36 ` [PATCH v9 5/6] PCI: generic: Make pci-host-generic driver numa aware Ganapatrao Kulkarni
2016-01-18 17:41 ` David Daney
2016-01-19 5:58 ` Ganapatrao Kulkarni
2016-01-19 9:41 ` Lorenzo Pieralisi
2016-01-19 12:32 ` Ganapatrao Kulkarni
2016-01-26 20:50 ` Bjorn Helgaas
2016-01-26 20:52 ` Bjorn Helgaas
2016-01-18 16:36 ` [RFC PATCH v9 6/6] topology, cleanup: Avoid redefinition of cpumask_of_pcibus in asm header files Ganapatrao Kulkarni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160126203603.GC17600@localhost \
--to=helgaas@kernel.org \
--cc=Prasun.Kapoor@caviumnetworks.com \
--cc=Will.Deacon@arm.com \
--cc=al.stone@linaro.org \
--cc=ard.biesheuvel@linaro.org \
--cc=arnd@arndb.de \
--cc=benh@kernel.crashing.org \
--cc=bhelgaas@google.com \
--cc=catalin.marinas@arm.com \
--cc=devicetree@vger.kernel.org \
--cc=fenghua.yu@intel.com \
--cc=galak@codeaurora.org \
--cc=gkulkarni@caviumnetworks.com \
--cc=gpkulkarni@gmail.com \
--cc=grant.likely@linaro.org \
--cc=hanjun.guo@linaro.org \
--cc=hpa@zytor.com \
--cc=ijc+devicetree@hellion.org.uk \
--cc=james.hogan@imgtec.com \
--cc=jonathan@jonmasters.org \
--cc=leif.lindholm@linaro.org \
--cc=lenb@kernel.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-ia64@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-metag@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=linux-sh@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=lorenzo.pieralisi@arm.com \
--cc=marc.zyngier@arm.com \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=msalter@redhat.com \
--cc=pawel.moll@arm.com \
--cc=rfranz@cavium.com \
--cc=rjw@rjwysocki.net \
--cc=robh+dt@kernel.org \
--cc=rrichter@cavium.com \
--cc=steve.capper@linaro.org \
--cc=tglx@linutronix.de \
--cc=tony.luck@intel.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).