Merge branch 'acpi-numa'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 25 Jul 2016 11:40:39 +0000 (13:40 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 25 Jul 2016 11:40:39 +0000 (13:40 +0200)
* acpi-numa:
  ACPI / NUMA: Enable ACPI based NUMA on ARM64
  arm64, ACPI, NUMA: NUMA support based on SRAT and SLIT
  ACPI / processor: Add acpi_map_madt_entry()
  ACPI / NUMA: Improve SRAT error detection and add messages
  ACPI / NUMA: Move acpi_numa_memory_affinity_init() to drivers/acpi/numa.c
  ACPI / NUMA: remove unneeded acpi_numa=1
  ACPI / NUMA: move bad_srat() and srat_disabled() to drivers/acpi/numa.c
  x86 / ACPI / NUMA: cleanup acpi_numa_processor_affinity_init()
  arm64, NUMA: Cleanup NUMA disabled messages
  arm64, NUMA: rework numa_add_memblk()
  ACPI / NUMA: move acpi_numa_slit_init() to drivers/acpi/numa.c
  ACPI / NUMA: Move acpi_numa_arch_fixup() to ia64 only
  ACPI / NUMA: remove duplicate NULL check
  ACPI / NUMA: Replace ACPI_DEBUG_PRINT() with pr_debug()
  ACPI / NUMA: Use pr_fmt() instead of printk

19 files changed:
arch/arm64/include/asm/acpi.h
arch/arm64/include/asm/numa.h
arch/arm64/kernel/Makefile
arch/arm64/kernel/acpi_numa.c [new file with mode: 0644]
arch/arm64/kernel/smp.c
arch/arm64/mm/numa.c
arch/ia64/include/asm/acpi.h
arch/ia64/kernel/acpi.c
arch/ia64/kernel/setup.c
arch/x86/include/asm/acpi.h
arch/x86/mm/numa.c
arch/x86/mm/srat.c
drivers/acpi/Kconfig
drivers/acpi/numa.c
drivers/acpi/processor_core.c
drivers/of/of_numa.c
include/acpi/acpi_numa.h
include/acpi/processor.h
include/linux/acpi.h

index aee323b..4b13ecd 100644 (file)
@@ -113,4 +113,12 @@ static inline const char *acpi_get_enable_method(int cpu)
 pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
 #endif
 
+#ifdef CONFIG_ACPI_NUMA
+int arm64_acpi_numa_init(void);
+int acpi_numa_get_nid(unsigned int cpu, u64 hwid);
+#else
+static inline int arm64_acpi_numa_init(void) { return -ENOSYS; }
+static inline int acpi_numa_get_nid(unsigned int cpu, u64 hwid) { return NUMA_NO_NODE; }
+#endif /* CONFIG_ACPI_NUMA */
+
 #endif /*_ASM_ACPI_H*/
index e9b4f29..600887e 100644 (file)
@@ -5,6 +5,8 @@
 
 #ifdef CONFIG_NUMA
 
+#define NR_NODE_MEMBLKS                (MAX_NUMNODES * 2)
+
 /* currently, arm64 implements flat NUMA topology */
 #define parent_node(node)      (node)
 
index 2173149..a5125c6 100644 (file)
@@ -42,6 +42,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_ACPI_NUMA)          += acpi_numa.o
 arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL)        += acpi_parking_protocol.o
 arm64-obj-$(CONFIG_PARAVIRT)           += paravirt.o
 arm64-obj-$(CONFIG_RANDOMIZE_BASE)     += kaslr.o
diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c
new file mode 100644 (file)
index 0000000..f85149c
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * ACPI 5.1 based NUMA setup for ARM64
+ * Lots of code was borrowed from arch/x86/mm/srat.c
+ *
+ * Copyright 2004 Andi Kleen, SuSE Labs.
+ * Copyright (C) 2013-2016, Linaro Ltd.
+ *             Author: Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
+ *
+ * Called from acpi_numa_init while reading the SRAT and SLIT tables.
+ * Assumes all memory regions belonging to a single proximity domain
+ * are in one chunk. Holes between them will be included in the node.
+ */
+
+#define pr_fmt(fmt) "ACPI: NUMA: " fmt
+
+#include <linux/acpi.h>
+#include <linux/bitmap.h>
+#include <linux/bootmem.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/memblock.h>
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+
+#include <acpi/processor.h>
+#include <asm/numa.h>
+
+static int cpus_in_srat;
+
+struct __node_cpu_hwid {
+       u32 node_id;    /* logical node containing this CPU */
+       u64 cpu_hwid;   /* MPIDR for this CPU */
+};
+
+static struct __node_cpu_hwid early_node_cpu_hwid[NR_CPUS] = {
+[0 ... NR_CPUS - 1] = {NUMA_NO_NODE, PHYS_CPUID_INVALID} };
+
+int acpi_numa_get_nid(unsigned int cpu, u64 hwid)
+{
+       int i;
+
+       for (i = 0; i < cpus_in_srat; i++) {
+               if (hwid == early_node_cpu_hwid[i].cpu_hwid)
+                       return early_node_cpu_hwid[i].node_id;
+       }
+
+       return NUMA_NO_NODE;
+}
+
+/* Callback for Proximity Domain -> ACPI processor UID mapping */
+void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
+{
+       int pxm, node;
+       phys_cpuid_t mpidr;
+
+       if (srat_disabled())
+               return;
+
+       if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
+               pr_err("SRAT: Invalid SRAT header length: %d\n",
+                       pa->header.length);
+               bad_srat();
+               return;
+       }
+
+       if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
+               return;
+
+       if (cpus_in_srat >= NR_CPUS) {
+               pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
+                            NR_CPUS);
+               return;
+       }
+
+       pxm = pa->proximity_domain;
+       node = acpi_map_pxm_to_node(pxm);
+
+       if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
+               pr_err("SRAT: Too many proximity domains %d\n", pxm);
+               bad_srat();
+               return;
+       }
+
+       mpidr = acpi_map_madt_entry(pa->acpi_processor_uid);
+       if (mpidr == PHYS_CPUID_INVALID) {
+               pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n",
+                       pxm, pa->acpi_processor_uid);
+               bad_srat();
+               return;
+       }
+
+       early_node_cpu_hwid[cpus_in_srat].node_id = node;
+       early_node_cpu_hwid[cpus_in_srat].cpu_hwid =  mpidr;
+       node_set(node, numa_nodes_parsed);
+       cpus_in_srat++;
+       pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d\n",
+               pxm, mpidr, node);
+}
+
+int __init arm64_acpi_numa_init(void)
+{
+       int ret;
+
+       ret = acpi_numa_init();
+       if (ret)
+               return ret;
+
+       return srat_disabled() ? -EINVAL : 0;
+}
index 62ff3c0..a68e0cc 100644 (file)
@@ -560,6 +560,8 @@ acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
         */
        acpi_set_mailbox_entry(cpu_count, processor);
 
+       early_map_cpu_to_node(cpu_count, acpi_numa_get_nid(cpu_count, hwid));
+
        cpu_count++;
 }
 
index 98dc104..c7fe3ec 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/module.h>
@@ -29,7 +30,7 @@ static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
 
 static int numa_distance_cnt;
 static u8 *numa_distance;
-static int numa_off;
+static bool numa_off;
 
 static __init int numa_parse_early_param(char *opt)
 {
@@ -37,7 +38,7 @@ static __init int numa_parse_early_param(char *opt)
                return -EINVAL;
        if (!strncmp(opt, "off", 3)) {
                pr_info("%s\n", "NUMA turned off");
-               numa_off = 1;
+               numa_off = true;
        }
        return 0;
 }
@@ -131,25 +132,25 @@ void __init early_map_cpu_to_node(unsigned int cpu, int nid)
  * numa_add_memblk - Set node id to memblk
  * @nid: NUMA node ID of the new memblk
  * @start: Start address of the new memblk
- * @size:  Size of the new memblk
+ * @end:  End address of the new memblk
  *
  * RETURNS:
  * 0 on success, -errno on failure.
  */
-int __init numa_add_memblk(int nid, u64 start, u64 size)
+int __init numa_add_memblk(int nid, u64 start, u64 end)
 {
        int ret;
 
-       ret = memblock_set_node(start, size, &memblock.memory, nid);
+       ret = memblock_set_node(start, (end - start), &memblock.memory, nid);
        if (ret < 0) {
                pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n",
-                       start, (start + size - 1), nid);
+                       start, (end - 1), nid);
                return ret;
        }
 
        node_set(nid, numa_nodes_parsed);
        pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n",
-                       start, (start + size - 1), nid);
+                       start, (end - 1), nid);
        return ret;
 }
 
@@ -362,12 +363,15 @@ static int __init dummy_numa_init(void)
        int ret;
        struct memblock_region *mblk;
 
-       pr_info("%s\n", "No NUMA configuration found");
+       if (numa_off)
+               pr_info("NUMA disabled\n"); /* Forced off on command line. */
+       else
+               pr_info("No NUMA configuration found\n");
        pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
               0LLU, PFN_PHYS(max_pfn) - 1);
 
        for_each_memblock(memory, mblk) {
-               ret = numa_add_memblk(0, mblk->base, mblk->size);
+               ret = numa_add_memblk(0, mblk->base, mblk->base + mblk->size);
                if (!ret)
                        continue;
 
@@ -375,7 +379,7 @@ static int __init dummy_numa_init(void)
                return ret;
        }
 
-       numa_off = 1;
+       numa_off = true;
        return 0;
 }
 
@@ -388,7 +392,9 @@ static int __init dummy_numa_init(void)
 void __init arm64_numa_init(void)
 {
        if (!numa_off) {
-               if (!numa_init(of_numa_init))
+               if (!acpi_disabled && !numa_init(arm64_acpi_numa_init))
+                       return;
+               if (acpi_disabled && !numa_init(of_numa_init))
                        return;
        }
 
index aa0fdf1..a3d0211 100644 (file)
@@ -140,6 +140,9 @@ static inline void per_cpu_scan_finalize(int min_cpus, int reserve_cpus)
                }
        }
 }
+
+extern void acpi_numa_fixup(void);
+
 #endif /* CONFIG_ACPI_NUMA */
 
 #endif /*__KERNEL__*/
index b1698bc..92b7bc9 100644 (file)
@@ -524,7 +524,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
        return 0;
 }
 
-void __init acpi_numa_arch_fixup(void)
+void __init acpi_numa_fixup(void)
 {
        int i, j, node_from, node_to;
 
index 2029a38..afddb3e 100644 (file)
@@ -552,6 +552,7 @@ setup_arch (char **cmdline_p)
        early_acpi_boot_init();
 # ifdef CONFIG_ACPI_NUMA
        acpi_numa_init();
+       acpi_numa_fixup();
 #  ifdef CONFIG_ACPI_HOTPLUG_CPU
        prefill_possible_map();
 #  endif
index 94c18eb..65f1e95 100644 (file)
@@ -145,7 +145,6 @@ static inline void disable_acpi(void) { }
 #define ARCH_HAS_POWER_INIT    1
 
 #ifdef CONFIG_ACPI_NUMA
-extern int acpi_numa;
 extern int x86_acpi_numa_init(void);
 #endif /* CONFIG_ACPI_NUMA */
 
index 9c086c5..968ac02 100644 (file)
@@ -1,4 +1,5 @@
 /* Common code for 32 and 64-bit NUMA */
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/string.h>
@@ -15,7 +16,6 @@
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/dma.h>
-#include <asm/acpi.h>
 #include <asm/amd_nb.h>
 
 #include "numa_internal.h"
index b5f8218..b1ecff4 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/bitmap.h>
 #include <linux/module.h>
 #include <linux/topology.h>
-#include <linux/bootmem.h>
-#include <linux/memblock.h>
 #include <linux/mm.h>
 #include <asm/proto.h>
 #include <asm/numa.h>
 #include <asm/apic.h>
 #include <asm/uv/uv.h>
 
-int acpi_numa __initdata;
-
-static __init int setup_node(int pxm)
-{
-       return acpi_map_pxm_to_node(pxm);
-}
-
-static __init void bad_srat(void)
-{
-       printk(KERN_ERR "SRAT: SRAT not used.\n");
-       acpi_numa = -1;
-}
-
-static __init inline int srat_disabled(void)
-{
-       return acpi_numa < 0;
-}
-
-/*
- * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
- * I/O localities since SRAT does not list them.  I/O localities are
- * not supported at this point.
- */
-void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
-{
-       int i, j;
-
-       for (i = 0; i < slit->locality_count; i++) {
-               const int from_node = pxm_to_node(i);
-
-               if (from_node == NUMA_NO_NODE)
-                       continue;
-
-               for (j = 0; j < slit->locality_count; j++) {
-                       const int to_node = pxm_to_node(j);
-
-                       if (to_node == NUMA_NO_NODE)
-                               continue;
-
-                       numa_set_distance(from_node, to_node,
-                               slit->entry[slit->locality_count * i + j]);
-               }
-       }
-}
-
 /* Callback for Proximity Domain -> x2APIC mapping */
 void __init
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
@@ -91,7 +44,7 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
                         pxm, apic_id);
                return;
        }
-       node = setup_node(pxm);
+       node = acpi_map_pxm_to_node(pxm);
        if (node < 0) {
                printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
                bad_srat();
@@ -104,7 +57,6 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
        }
        set_apicid_to_node(apic_id, node);
        node_set(node, numa_nodes_parsed);
-       acpi_numa = 1;
        printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
               pxm, apic_id, node);
 }
@@ -127,7 +79,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
        pxm = pa->proximity_domain_lo;
        if (acpi_srat_revision >= 2)
                pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8;
-       node = setup_node(pxm);
+       node = acpi_map_pxm_to_node(pxm);
        if (node < 0) {
                printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
                bad_srat();
@@ -146,74 +98,10 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 
        set_apicid_to_node(apic_id, node);
        node_set(node, numa_nodes_parsed);
-       acpi_numa = 1;
        printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
               pxm, apic_id, node);
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-static inline int save_add_info(void) {return 1;}
-#else
-static inline int save_add_info(void) {return 0;}
-#endif
-
-/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
-int __init
-acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
-{
-       u64 start, end;
-       u32 hotpluggable;
-       int node, pxm;
-
-       if (srat_disabled())
-               goto out_err;
-       if (ma->header.length != sizeof(struct acpi_srat_mem_affinity))
-               goto out_err_bad_srat;
-       if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
-               goto out_err;
-       hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
-       if (hotpluggable && !save_add_info())
-               goto out_err;
-
-       start = ma->base_address;
-       end = start + ma->length;
-       pxm = ma->proximity_domain;
-       if (acpi_srat_revision <= 1)
-               pxm &= 0xff;
-
-       node = setup_node(pxm);
-       if (node < 0) {
-               printk(KERN_ERR "SRAT: Too many proximity domains.\n");
-               goto out_err_bad_srat;
-       }
-
-       if (numa_add_memblk(node, start, end) < 0)
-               goto out_err_bad_srat;
-
-       node_set(node, numa_nodes_parsed);
-
-       pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
-               node, pxm,
-               (unsigned long long) start, (unsigned long long) end - 1,
-               hotpluggable ? " hotplug" : "",
-               ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
-
-       /* Mark hotplug range in memblock. */
-       if (hotpluggable && memblock_mark_hotplug(start, ma->length))
-               pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
-                       (unsigned long long)start, (unsigned long long)end - 1);
-
-       max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
-
-       return 0;
-out_err_bad_srat:
-       bad_srat();
-out_err:
-       return -1;
-}
-
-void __init acpi_numa_arch_fixup(void) {}
-
 int __init x86_acpi_numa_init(void)
 {
        int ret;
index b7e2e77..dd76b36 100644 (file)
@@ -291,8 +291,8 @@ config ACPI_THERMAL
 config ACPI_NUMA
        bool "NUMA support"
        depends on NUMA
-       depends on (X86 || IA64)
-       default y if IA64_GENERIC || IA64_SGI_SN2
+       depends on (X86 || IA64 || ARM64)
+       default y if IA64_GENERIC || IA64_SGI_SN2 || ARM64
 
 config ACPI_CUSTOM_DSDT_FILE
        string "Custom DSDT Table file to include"
index d176e0e..ce3a7a1 100644 (file)
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  */
+
+#define pr_fmt(fmt) "ACPI: " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/acpi.h>
+#include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/numa.h>
 #include <linux/nodemask.h>
 #include <linux/topology.h>
 
-#define PREFIX "ACPI: "
-
-#define ACPI_NUMA      0x80000000
-#define _COMPONENT     ACPI_NUMA
-ACPI_MODULE_NAME("numa");
-
 static nodemask_t nodes_found_map = NODE_MASK_NONE;
 
 /* maps to convert between proximity domain and logical node ID */
@@ -43,6 +42,7 @@ static int node_to_pxm_map[MAX_NUMNODES]
                        = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
 unsigned char acpi_srat_revision __initdata;
+int acpi_numa __initdata;
 
 int pxm_to_node(int pxm)
 {
@@ -128,68 +128,63 @@ EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
 static void __init
 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 {
-
-       ACPI_FUNCTION_NAME("acpi_table_print_srat_entry");
-
-       if (!header)
-               return;
-
        switch (header->type) {
-
        case ACPI_SRAT_TYPE_CPU_AFFINITY:
-#ifdef ACPI_DEBUG_OUTPUT
                {
                        struct acpi_srat_cpu_affinity *p =
                            (struct acpi_srat_cpu_affinity *)header;
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
-                                         p->apic_id, p->local_sapic_eid,
-                                         p->proximity_domain_lo,
-                                         (p->flags & ACPI_SRAT_CPU_ENABLED)?
-                                         "enabled" : "disabled"));
+                       pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
+                                p->apic_id, p->local_sapic_eid,
+                                p->proximity_domain_lo,
+                                (p->flags & ACPI_SRAT_CPU_ENABLED) ?
+                                "enabled" : "disabled");
                }
-#endif                         /* ACPI_DEBUG_OUTPUT */
                break;
 
        case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
-#ifdef ACPI_DEBUG_OUTPUT
                {
                        struct acpi_srat_mem_affinity *p =
                            (struct acpi_srat_mem_affinity *)header;
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
-                                         (unsigned long)p->base_address,
-                                         (unsigned long)p->length,
-                                         p->proximity_domain,
-                                         (p->flags & ACPI_SRAT_MEM_ENABLED)?
-                                         "enabled" : "disabled",
-                                         (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?
-                                         " hot-pluggable" : "",
-                                         (p->flags & ACPI_SRAT_MEM_NON_VOLATILE)?
-                                         " non-volatile" : ""));
+                       pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
+                                (unsigned long)p->base_address,
+                                (unsigned long)p->length,
+                                p->proximity_domain,
+                                (p->flags & ACPI_SRAT_MEM_ENABLED) ?
+                                "enabled" : "disabled",
+                                (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
+                                " hot-pluggable" : "",
+                                (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ?
+                                " non-volatile" : "");
                }
-#endif                         /* ACPI_DEBUG_OUTPUT */
                break;
 
        case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
-#ifdef ACPI_DEBUG_OUTPUT
                {
                        struct acpi_srat_x2apic_cpu_affinity *p =
                            (struct acpi_srat_x2apic_cpu_affinity *)header;
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "SRAT Processor (x2apicid[0x%08x]) in"
-                                         " proximity domain %d %s\n",
-                                         p->apic_id,
-                                         p->proximity_domain,
-                                         (p->flags & ACPI_SRAT_CPU_ENABLED) ?
-                                         "enabled" : "disabled"));
+                       pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n",
+                                p->apic_id,
+                                p->proximity_domain,
+                                (p->flags & ACPI_SRAT_CPU_ENABLED) ?
+                                "enabled" : "disabled");
                }
-#endif                         /* ACPI_DEBUG_OUTPUT */
                break;
+
+       case ACPI_SRAT_TYPE_GICC_AFFINITY:
+               {
+                       struct acpi_srat_gicc_affinity *p =
+                           (struct acpi_srat_gicc_affinity *)header;
+                       pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n",
+                                p->acpi_processor_uid,
+                                p->proximity_domain,
+                                (p->flags & ACPI_SRAT_GICC_ENABLED) ?
+                                "enabled" : "disabled");
+               }
+               break;
+
        default:
-               printk(KERN_WARNING PREFIX
-                      "Found unsupported SRAT entry (type = 0x%x)\n",
-                      header->type);
+               pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
+                       header->type);
                break;
        }
 }
@@ -217,12 +212,117 @@ static int __init slit_valid(struct acpi_table_slit *slit)
        return 1;
 }
 
+void __init bad_srat(void)
+{
+       pr_err("SRAT: SRAT not used.\n");
+       acpi_numa = -1;
+}
+
+int __init srat_disabled(void)
+{
+       return acpi_numa < 0;
+}
+
+#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
+/*
+ * Callback for SLIT parsing.  pxm_to_node() returns NUMA_NO_NODE for
+ * I/O localities since SRAT does not list them.  I/O localities are
+ * not supported at this point.
+ */
+void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
+{
+       int i, j;
+
+       for (i = 0; i < slit->locality_count; i++) {
+               const int from_node = pxm_to_node(i);
+
+               if (from_node == NUMA_NO_NODE)
+                       continue;
+
+               for (j = 0; j < slit->locality_count; j++) {
+                       const int to_node = pxm_to_node(j);
+
+                       if (to_node == NUMA_NO_NODE)
+                               continue;
+
+                       numa_set_distance(from_node, to_node,
+                               slit->entry[slit->locality_count * i + j]);
+               }
+       }
+}
+
+/*
+ * Default callback for parsing of the Proximity Domain <-> Memory
+ * Area mappings
+ */
+int __init
+acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
+{
+       u64 start, end;
+       u32 hotpluggable;
+       int node, pxm;
+
+       if (srat_disabled())
+               goto out_err;
+       if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) {
+               pr_err("SRAT: Unexpected header length: %d\n",
+                      ma->header.length);
+               goto out_err_bad_srat;
+       }
+       if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
+               goto out_err;
+       hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
+       if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
+               goto out_err;
+
+       start = ma->base_address;
+       end = start + ma->length;
+       pxm = ma->proximity_domain;
+       if (acpi_srat_revision <= 1)
+               pxm &= 0xff;
+
+       node = acpi_map_pxm_to_node(pxm);
+       if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
+               pr_err("SRAT: Too many proximity domains.\n");
+               goto out_err_bad_srat;
+       }
+
+       if (numa_add_memblk(node, start, end) < 0) {
+               pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n",
+                      node, (unsigned long long) start,
+                      (unsigned long long) end - 1);
+               goto out_err_bad_srat;
+       }
+
+       node_set(node, numa_nodes_parsed);
+
+       pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
+               node, pxm,
+               (unsigned long long) start, (unsigned long long) end - 1,
+               hotpluggable ? " hotplug" : "",
+               ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
+
+       /* Mark hotplug range in memblock. */
+       if (hotpluggable && memblock_mark_hotplug(start, ma->length))
+               pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
+                       (unsigned long long)start, (unsigned long long)end - 1);
+
+       max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
+
+       return 0;
+out_err_bad_srat:
+       bad_srat();
+out_err:
+       return -EINVAL;
+}
+#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
+
 static int __init acpi_parse_slit(struct acpi_table_header *table)
 {
        struct acpi_table_slit *slit = (struct acpi_table_slit *)table;
 
        if (!slit_valid(slit)) {
-               printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
+               pr_info("SLIT table looks invalid. Not used.\n");
                return -EINVAL;
        }
        acpi_numa_slit_init(slit);
@@ -233,12 +333,9 @@ static int __init acpi_parse_slit(struct acpi_table_header *table)
 void __init __weak
 acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 {
-       printk(KERN_WARNING PREFIX
-              "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
-       return;
+       pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
 }
 
-
 static int __init
 acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
                           const unsigned long end)
@@ -275,6 +372,24 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header,
        return 0;
 }
 
+static int __init
+acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
+                        const unsigned long end)
+{
+       struct acpi_srat_gicc_affinity *processor_affinity;
+
+       processor_affinity = (struct acpi_srat_gicc_affinity *)header;
+       if (!processor_affinity)
+               return -EINVAL;
+
+       acpi_table_print_srat_entry(header);
+
+       /* let architecture-dependent part to do it */
+       acpi_numa_gicc_affinity_init(processor_affinity);
+
+       return 0;
+}
+
 static int __initdata parsed_numa_memblks;
 
 static int __init
@@ -319,6 +434,9 @@ int __init acpi_numa_init(void)
 {
        int cnt = 0;
 
+       if (acpi_disabled)
+               return -EINVAL;
+
        /*
         * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
         * SRAT cpu entries could have different order with that in MADT.
@@ -327,13 +445,15 @@ int __init acpi_numa_init(void)
 
        /* SRAT: Static Resource Affinity Table */
        if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
-               struct acpi_subtable_proc srat_proc[2];
+               struct acpi_subtable_proc srat_proc[3];
 
                memset(srat_proc, 0, sizeof(srat_proc));
                srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
                srat_proc[0].handler = acpi_parse_processor_affinity;
                srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
                srat_proc[1].handler = acpi_parse_x2apic_affinity;
+               srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY;
+               srat_proc[2].handler = acpi_parse_gicc_affinity;
 
                acpi_table_parse_entries_array(ACPI_SIG_SRAT,
                                        sizeof(struct acpi_table_srat),
@@ -347,8 +467,6 @@ int __init acpi_numa_init(void)
        /* SLIT: System Locality Information Table */
        acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
-       acpi_numa_arch_fixup();
-
        if (cnt < 0)
                return cnt;
        else if (!parsed_numa_memblks)
index 33a38d6..9125d7d 100644 (file)
@@ -108,13 +108,12 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry,
        return -EINVAL;
 }
 
-static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
+static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt,
+                                  int type, u32 acpi_id)
 {
        unsigned long madt_end, entry;
        phys_cpuid_t phys_id = PHYS_CPUID_INVALID;      /* CPU hardware ID */
-       struct acpi_table_madt *madt;
 
-       madt = get_madt_table();
        if (!madt)
                return phys_id;
 
@@ -145,6 +144,25 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
        return phys_id;
 }
 
+phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
+{
+       struct acpi_table_madt *madt = NULL;
+       acpi_size tbl_size;
+       phys_cpuid_t rv;
+
+       acpi_get_table_with_size(ACPI_SIG_MADT, 0,
+                                (struct acpi_table_header **)&madt,
+                                &tbl_size);
+       if (!madt)
+               return PHYS_CPUID_INVALID;
+
+       rv = map_madt_entry(madt, 1, acpi_id);
+
+       early_acpi_os_unmap_memory(madt, tbl_size);
+
+       return rv;
+}
+
 static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -185,7 +203,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
 
        phys_id = map_mat_entry(handle, type, acpi_id);
        if (invalid_phys_cpuid(phys_id))
-               phys_id = map_madt_entry(type, acpi_id);
+               phys_id = map_madt_entry(get_madt_table(), type, acpi_id);
 
        return phys_id;
 }
index 0f2784b..ed5a097 100644 (file)
@@ -91,8 +91,8 @@ static int __init of_numa_parse_memory_nodes(void)
                pr_debug("NUMA:  base = %llx len = %llx, node = %u\n",
                         rsrc.start, rsrc.end - rsrc.start + 1, nid);
 
-               r = numa_add_memblk(nid, rsrc.start,
-                                   rsrc.end - rsrc.start + 1);
+
+               r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1);
                if (r)
                        break;
        }
index 94a37cd..d4b7294 100644 (file)
@@ -15,6 +15,10 @@ extern int pxm_to_node(int);
 extern int node_to_pxm(int);
 extern int acpi_map_pxm_to_node(int);
 extern unsigned char acpi_srat_revision;
+extern int acpi_numa __initdata;
+
+extern void bad_srat(void);
+extern int srat_disabled(void);
 
 #endif                         /* CONFIG_ACPI_NUMA */
 #endif                         /* __ACP_NUMA_H */
index 6f1805d..f473e66 100644 (file)
@@ -309,6 +309,7 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 /* in processor_core.c */
 phys_cpuid_t acpi_get_phys_id(acpi_handle, int type, u32 acpi_id);
+phys_cpuid_t acpi_map_madt_entry(u32 acpi_id);
 int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id);
 int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
 
index 288fac5..9515db6 100644 (file)
@@ -232,12 +232,26 @@ int acpi_table_parse_madt(enum acpi_madt_type id,
 int acpi_parse_mcfg (struct acpi_table_header *header);
 void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
 
-/* the following four functions are architecture-dependent */
+/* the following numa functions are architecture-dependent */
 void acpi_numa_slit_init (struct acpi_table_slit *slit);
+
+#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
+#else
+static inline void
+acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { }
+#endif
+
 void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
+
+#ifdef CONFIG_ARM64
+void acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa);
+#else
+static inline void
+acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa) { }
+#endif
+
 int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
-void acpi_numa_arch_fixup(void);
 
 #ifndef PHYS_CPUID_INVALID
 typedef u32 phys_cpuid_t;