These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / acpi / numa.c
index 1333cbd..72b6e9e 100644 (file)
  *  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, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  */
@@ -29,6 +25,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 +68,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 +86,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 +370,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);
 }