powerpc/hvsi: Fix endianness issues in the HVSI driver
[firefly-linux-kernel-4.4.55.git] / drivers / acpi / numa.c
index 1333cbdc3ea2fa673b744c2b81b6c311071be704..acaa3b4ea504cbefe9ede86d9ec27b62cd7add57 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/errno.h>
 #include <linux/acpi.h>
 #include <linux/numa.h>
+#include <linux/nodemask.h>
+#include <linux/topology.h>
 
 #define PREFIX "ACPI: "
 
@@ -70,7 +72,12 @@ static void __acpi_map_pxm_to_node(int pxm, int node)
 
 int acpi_map_pxm_to_node(int pxm)
 {
-       int node = pxm_to_node_map[pxm];
+       int node;
+
+       if (pxm < 0 || pxm >= MAX_PXM_DOMAINS)
+               return NUMA_NO_NODE;
+
+       node = pxm_to_node_map[pxm];
 
        if (node == NUMA_NO_NODE) {
                if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
@@ -83,6 +90,45 @@ int acpi_map_pxm_to_node(int pxm)
        return node;
 }
 
+/**
+ * acpi_map_pxm_to_online_node - Map proximity ID to online node
+ * @pxm: ACPI proximity ID
+ *
+ * This is similar to acpi_map_pxm_to_node(), but always returns an online
+ * node.  When the mapped node from a given proximity ID is offline, it
+ * looks up the node distance table and returns the nearest online node.
+ *
+ * ACPI device drivers, which are called after the NUMA initialization has
+ * completed in the kernel, can call this interface to obtain their device
+ * NUMA topology from ACPI tables.  Such drivers do not have to deal with
+ * offline nodes.  A node may be offline when a device proximity ID is
+ * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
+ * "numa=off" on x86.
+ */
+int acpi_map_pxm_to_online_node(int pxm)
+{
+       int node, n, dist, min_dist;
+
+       node = acpi_map_pxm_to_node(pxm);
+
+       if (node == NUMA_NO_NODE)
+               node = 0;
+
+       if (!node_online(node)) {
+               min_dist = INT_MAX;
+               for_each_online_node(n) {
+                       dist = node_distance(node, n);
+                       if (dist < min_dist) {
+                               min_dist = dist;
+                               node = n;
+                       }
+               }
+       }
+
+       return node;
+}
+EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
+
 static void __init
 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 {
@@ -328,8 +374,6 @@ int acpi_get_node(acpi_handle handle)
        int pxm;
 
        pxm = acpi_get_pxm(handle);
-       if (pxm < 0 || pxm >= MAX_PXM_DOMAINS)
-               return NUMA_NO_NODE;
 
        return acpi_map_pxm_to_node(pxm);
 }