diff options
Diffstat (limited to 'drivers/acpi/numa.c')
-rw-r--r-- | drivers/acpi/numa.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 1333cbdc3ea2..acaa3b4ea504 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
31 | #include <linux/numa.h> | 31 | #include <linux/numa.h> |
32 | #include <linux/nodemask.h> | ||
33 | #include <linux/topology.h> | ||
32 | 34 | ||
33 | #define PREFIX "ACPI: " | 35 | #define PREFIX "ACPI: " |
34 | 36 | ||
@@ -70,7 +72,12 @@ static void __acpi_map_pxm_to_node(int pxm, int node) | |||
70 | 72 | ||
71 | int acpi_map_pxm_to_node(int pxm) | 73 | int acpi_map_pxm_to_node(int pxm) |
72 | { | 74 | { |
73 | int node = pxm_to_node_map[pxm]; | 75 | int node; |
76 | |||
77 | if (pxm < 0 || pxm >= MAX_PXM_DOMAINS) | ||
78 | return NUMA_NO_NODE; | ||
79 | |||
80 | node = pxm_to_node_map[pxm]; | ||
74 | 81 | ||
75 | if (node == NUMA_NO_NODE) { | 82 | if (node == NUMA_NO_NODE) { |
76 | if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) | 83 | if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) |
@@ -83,6 +90,45 @@ int acpi_map_pxm_to_node(int pxm) | |||
83 | return node; | 90 | return node; |
84 | } | 91 | } |
85 | 92 | ||
93 | /** | ||
94 | * acpi_map_pxm_to_online_node - Map proximity ID to online node | ||
95 | * @pxm: ACPI proximity ID | ||
96 | * | ||
97 | * This is similar to acpi_map_pxm_to_node(), but always returns an online | ||
98 | * node. When the mapped node from a given proximity ID is offline, it | ||
99 | * looks up the node distance table and returns the nearest online node. | ||
100 | * | ||
101 | * ACPI device drivers, which are called after the NUMA initialization has | ||
102 | * completed in the kernel, can call this interface to obtain their device | ||
103 | * NUMA topology from ACPI tables. Such drivers do not have to deal with | ||
104 | * offline nodes. A node may be offline when a device proximity ID is | ||
105 | * unique, SRAT memory entry does not exist, or NUMA is disabled, ex. | ||
106 | * "numa=off" on x86. | ||
107 | */ | ||
108 | int acpi_map_pxm_to_online_node(int pxm) | ||
109 | { | ||
110 | int node, n, dist, min_dist; | ||
111 | |||
112 | node = acpi_map_pxm_to_node(pxm); | ||
113 | |||
114 | if (node == NUMA_NO_NODE) | ||
115 | node = 0; | ||
116 | |||
117 | if (!node_online(node)) { | ||
118 | min_dist = INT_MAX; | ||
119 | for_each_online_node(n) { | ||
120 | dist = node_distance(node, n); | ||
121 | if (dist < min_dist) { | ||
122 | min_dist = dist; | ||
123 | node = n; | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | return node; | ||
129 | } | ||
130 | EXPORT_SYMBOL(acpi_map_pxm_to_online_node); | ||
131 | |||
86 | static void __init | 132 | static void __init |
87 | acpi_table_print_srat_entry(struct acpi_subtable_header *header) | 133 | acpi_table_print_srat_entry(struct acpi_subtable_header *header) |
88 | { | 134 | { |
@@ -328,8 +374,6 @@ int acpi_get_node(acpi_handle handle) | |||
328 | int pxm; | 374 | int pxm; |
329 | 375 | ||
330 | pxm = acpi_get_pxm(handle); | 376 | pxm = acpi_get_pxm(handle); |
331 | if (pxm < 0 || pxm >= MAX_PXM_DOMAINS) | ||
332 | return NUMA_NO_NODE; | ||
333 | 377 | ||
334 | return acpi_map_pxm_to_node(pxm); | 378 | return acpi_map_pxm_to_node(pxm); |
335 | } | 379 | } |