Merge tag 'dt-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / acpi / numa / srat.c
index 15bbaab..b8795fc 100644 (file)
@@ -27,11 +27,16 @@ static int node_to_pxm_map[MAX_NUMNODES]
                        = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
 unsigned char acpi_srat_revision __initdata;
-int acpi_numa __initdata;
+static int acpi_numa __initdata;
+
+void __init disable_srat(void)
+{
+       acpi_numa = -1;
+}
 
 int pxm_to_node(int pxm)
 {
-       if (pxm < 0)
+       if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
                return NUMA_NO_NODE;
        return pxm_to_node_map[pxm];
 }
@@ -130,6 +135,36 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
                }
                break;
 
+       case ACPI_SRAT_TYPE_GENERIC_AFFINITY:
+       {
+               struct acpi_srat_generic_affinity *p =
+                       (struct acpi_srat_generic_affinity *)header;
+
+               if (p->device_handle_type == 0) {
+                       /*
+                        * For pci devices this may be the only place they
+                        * are assigned a proximity domain
+                        */
+                       pr_debug("SRAT Generic Initiator(Seg:%u BDF:%u) in proximity domain %d %s\n",
+                                *(u16 *)(&p->device_handle[0]),
+                                *(u16 *)(&p->device_handle[2]),
+                                p->proximity_domain,
+                                (p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED) ?
+                               "enabled" : "disabled");
+               } else {
+                       /*
+                        * In this case we can rely on the device having a
+                        * proximity domain reference
+                        */
+                       pr_debug("SRAT Generic Initiator(HID=%.8s UID=%.4s) in proximity domain %d %s\n",
+                               (char *)(&p->device_handle[0]),
+                               (char *)(&p->device_handle[8]),
+                               p->proximity_domain,
+                               (p->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED) ?
+                               "enabled" : "disabled");
+               }
+       }
+       break;
        default:
                pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
                        header->type);
@@ -163,7 +198,7 @@ static int __init slit_valid(struct acpi_table_slit *slit)
 void __init bad_srat(void)
 {
        pr_err("SRAT: SRAT not used.\n");
-       acpi_numa = -1;
+       disable_srat();
 }
 
 int __init srat_disabled(void)
@@ -171,7 +206,7 @@ int __init srat_disabled(void)
        return acpi_numa < 0;
 }
 
-#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
+#if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
 /*
  * 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
@@ -332,6 +367,41 @@ acpi_parse_gicc_affinity(union acpi_subtable_headers *header,
        return 0;
 }
 
+#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
+static int __init
+acpi_parse_gi_affinity(union acpi_subtable_headers *header,
+                      const unsigned long end)
+{
+       struct acpi_srat_generic_affinity *gi_affinity;
+       int node;
+
+       gi_affinity = (struct acpi_srat_generic_affinity *)header;
+       if (!gi_affinity)
+               return -EINVAL;
+       acpi_table_print_srat_entry(&header->common);
+
+       if (!(gi_affinity->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED))
+               return -EINVAL;
+
+       node = acpi_map_pxm_to_node(gi_affinity->proximity_domain);
+       if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
+               pr_err("SRAT: Too many proximity domains.\n");
+               return -EINVAL;
+       }
+       node_set(node, numa_nodes_parsed);
+       node_set_state(node, N_GENERIC_INITIATOR);
+
+       return 0;
+}
+#else
+static int __init
+acpi_parse_gi_affinity(union acpi_subtable_headers *header,
+                      const unsigned long end)
+{
+       return 0;
+}
+#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
+
 static int __initdata parsed_numa_memblks;
 
 static int __init
@@ -385,7 +455,7 @@ int __init acpi_numa_init(void)
 
        /* SRAT: System Resource Affinity Table */
        if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
-               struct acpi_subtable_proc srat_proc[3];
+               struct acpi_subtable_proc srat_proc[4];
 
                memset(srat_proc, 0, sizeof(srat_proc));
                srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
@@ -394,6 +464,8 @@ int __init acpi_numa_init(void)
                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;
+               srat_proc[3].id = ACPI_SRAT_TYPE_GENERIC_AFFINITY;
+               srat_proc[3].handler = acpi_parse_gi_affinity;
 
                acpi_table_parse_entries_array(ACPI_SIG_SRAT,
                                        sizeof(struct acpi_table_srat),
@@ -436,6 +508,6 @@ int acpi_get_node(acpi_handle handle)
 
        pxm = acpi_get_pxm(handle);
 
-       return acpi_map_pxm_to_node(pxm);
+       return pxm_to_node(pxm);
 }
 EXPORT_SYMBOL(acpi_get_node);