Merge tag 'regmap-fix-v4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / acpi / numa.c
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)