blob: 47b4969d9b93dad31dcd55c2f02db82764d8c0dc [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * acpi_numa.c - ACPI NUMA support
4 *
5 * Copyright (C) 2002 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
Hanjun Guoac906a62016-05-24 15:35:31 -07007
8#define pr_fmt(fmt) "ACPI: " fmt
9
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/errno.h>
15#include <linux/acpi.h>
Hanjun Guo37704422016-05-24 15:35:41 -070016#include <linux/memblock.h>
David Rientjesb552a8c2009-11-17 14:27:32 -080017#include <linux/numa.h>
Toshi Kani99759862015-06-19 17:14:15 -060018#include <linux/nodemask.h>
19#include <linux/topology.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Yasunori Goto762834e2006-06-23 02:03:19 -070021static nodemask_t nodes_found_map = NODE_MASK_NONE;
Yasunori Goto762834e2006-06-23 02:03:19 -070022
23/* maps to convert between proximity domain and logical node ID */
Jan Beulichffada892007-12-13 08:32:26 +000024static int pxm_to_node_map[MAX_PXM_DOMAINS]
David Rientjesb552a8c2009-11-17 14:27:32 -080025 = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE };
Jan Beulichffada892007-12-13 08:32:26 +000026static int node_to_pxm_map[MAX_NUMNODES]
David Rientjesb552a8c2009-11-17 14:27:32 -080027 = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
Yasunori Goto762834e2006-06-23 02:03:19 -070028
Kurt Garloff8df0eb7c2012-01-17 04:18:02 -050029unsigned char acpi_srat_revision __initdata;
David Daneye84025e2016-05-24 15:35:39 -070030int acpi_numa __initdata;
Kurt Garloff8df0eb7c2012-01-17 04:18:02 -050031
Aaron Durbinf363d162007-05-16 22:11:06 -070032int pxm_to_node(int pxm)
Yasunori Goto762834e2006-06-23 02:03:19 -070033{
34 if (pxm < 0)
David Rientjesb552a8c2009-11-17 14:27:32 -080035 return NUMA_NO_NODE;
Yasunori Goto762834e2006-06-23 02:03:19 -070036 return pxm_to_node_map[pxm];
37}
38
Aaron Durbinf363d162007-05-16 22:11:06 -070039int node_to_pxm(int node)
Yasunori Goto762834e2006-06-23 02:03:19 -070040{
41 if (node < 0)
42 return PXM_INVAL;
43 return node_to_pxm_map[node];
44}
45
Bjorn Helgaasd79ed242014-01-24 15:48:01 -070046static void __acpi_map_pxm_to_node(int pxm, int node)
David Rientjes3484d792007-07-21 17:10:32 +020047{
David Rientjes0f9b75e2010-03-25 16:33:04 -070048 if (pxm_to_node_map[pxm] == NUMA_NO_NODE || node < pxm_to_node_map[pxm])
49 pxm_to_node_map[pxm] = node;
50 if (node_to_pxm_map[node] == PXM_INVAL || pxm < node_to_pxm_map[node])
51 node_to_pxm_map[node] = pxm;
David Rientjes3484d792007-07-21 17:10:32 +020052}
53
Luck, Tony8ff6f482007-05-24 13:57:40 -070054int acpi_map_pxm_to_node(int pxm)
Yasunori Goto762834e2006-06-23 02:03:19 -070055{
Toshi Kani99759862015-06-19 17:14:15 -060056 int node;
57
Boris Ostrovskyaec03f82016-12-12 23:18:29 -050058 if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
Toshi Kani99759862015-06-19 17:14:15 -060059 return NUMA_NO_NODE;
60
61 node = pxm_to_node_map[pxm];
Yasunori Goto762834e2006-06-23 02:03:19 -070062
Jianguo Wu1bb25df2013-08-30 09:25:40 +080063 if (node == NUMA_NO_NODE) {
Yasunori Goto762834e2006-06-23 02:03:19 -070064 if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
David Rientjesb552a8c2009-11-17 14:27:32 -080065 return NUMA_NO_NODE;
Yasunori Goto762834e2006-06-23 02:03:19 -070066 node = first_unset_node(nodes_found_map);
David Rientjes3484d792007-07-21 17:10:32 +020067 __acpi_map_pxm_to_node(pxm, node);
Yasunori Goto762834e2006-06-23 02:03:19 -070068 node_set(node, nodes_found_map);
69 }
70
71 return node;
72}
Dan Williams8fc5c732018-11-09 12:43:07 -080073EXPORT_SYMBOL(acpi_map_pxm_to_node);
Yasunori Goto762834e2006-06-23 02:03:19 -070074
David Rientjesae2c6dc2007-07-21 17:09:56 +020075static void __init
76acpi_table_print_srat_entry(struct acpi_subtable_header *header)
Linus Torvalds1da177e2005-04-16 15:20:36 -070077{
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 switch (header->type) {
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +030079 case ACPI_SRAT_TYPE_CPU_AFFINITY:
Len Brown4be44fc2005-08-05 00:44:28 -040080 {
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +030081 struct acpi_srat_cpu_affinity *p =
82 (struct acpi_srat_cpu_affinity *)header;
Hanjun Guo3dda4482016-05-24 15:35:32 -070083 pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n",
84 p->apic_id, p->local_sapic_eid,
85 p->proximity_domain_lo,
86 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
87 "enabled" : "disabled");
Len Brown4be44fc2005-08-05 00:44:28 -040088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 break;
90
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +030091 case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
Len Brown4be44fc2005-08-05 00:44:28 -040092 {
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +030093 struct acpi_srat_mem_affinity *p =
94 (struct acpi_srat_mem_affinity *)header;
Chao Fanb9ced182018-12-26 11:34:50 +080095 pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
96 (unsigned long long)p->base_address,
97 (unsigned long long)p->length,
Hanjun Guo3dda4482016-05-24 15:35:32 -070098 p->proximity_domain,
99 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
100 "enabled" : "disabled",
101 (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ?
102 " hot-pluggable" : "",
103 (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ?
104 " non-volatile" : "");
Len Brown4be44fc2005-08-05 00:44:28 -0400105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 break;
107
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800108 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800109 {
110 struct acpi_srat_x2apic_cpu_affinity *p =
111 (struct acpi_srat_x2apic_cpu_affinity *)header;
Hanjun Guo3dda4482016-05-24 15:35:32 -0700112 pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n",
113 p->apic_id,
114 p->proximity_domain,
115 (p->flags & ACPI_SRAT_CPU_ENABLED) ?
116 "enabled" : "disabled");
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800117 }
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800118 break;
Hanjun Guo3dda4482016-05-24 15:35:32 -0700119
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800120 case ACPI_SRAT_TYPE_GICC_AFFINITY:
121 {
122 struct acpi_srat_gicc_affinity *p =
123 (struct acpi_srat_gicc_affinity *)header;
124 pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n",
125 p->acpi_processor_uid,
126 p->proximity_domain,
127 (p->flags & ACPI_SRAT_GICC_ENABLED) ?
128 "enabled" : "disabled");
129 }
130 break;
131
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 default:
Hanjun Guoac906a62016-05-24 15:35:31 -0700133 pr_warn("Found unsupported SRAT entry (type = 0x%x)\n",
134 header->type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 break;
136 }
137}
138
Fenghua Yu39b89312008-06-09 16:48:18 -0700139/*
140 * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
141 * up the NUMA heuristics which wants the local node to have a smaller
142 * distance than the others.
143 * Do some quick checks here and only use the SLIT if it passes.
144 */
Hanjun Guo40e31852013-08-13 18:31:14 +0800145static int __init slit_valid(struct acpi_table_slit *slit)
Fenghua Yu39b89312008-06-09 16:48:18 -0700146{
147 int i, j;
148 int d = slit->locality_count;
149 for (i = 0; i < d; i++) {
150 for (j = 0; j < d; j++) {
151 u8 val = slit->entry[d*i + j];
152 if (i == j) {
153 if (val != LOCAL_DISTANCE)
154 return 0;
155 } else if (val <= LOCAL_DISTANCE)
156 return 0;
157 }
158 }
159 return 1;
160}
161
David Daneye84025e2016-05-24 15:35:39 -0700162void __init bad_srat(void)
163{
164 pr_err("SRAT: SRAT not used.\n");
165 acpi_numa = -1;
166}
167
168int __init srat_disabled(void)
169{
170 return acpi_numa < 0;
171}
172
Hanjun Guo6525afd2016-05-24 15:35:35 -0700173#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
174/*
175 * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for
176 * I/O localities since SRAT does not list them. I/O localities are
177 * not supported at this point.
178 */
179void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
180{
181 int i, j;
182
183 for (i = 0; i < slit->locality_count; i++) {
184 const int from_node = pxm_to_node(i);
185
186 if (from_node == NUMA_NO_NODE)
187 continue;
188
189 for (j = 0; j < slit->locality_count; j++) {
190 const int to_node = pxm_to_node(j);
191
192 if (to_node == NUMA_NO_NODE)
193 continue;
194
195 numa_set_distance(from_node, to_node,
196 slit->entry[slit->locality_count * i + j]);
197 }
198 }
199}
Hanjun Guo37704422016-05-24 15:35:41 -0700200
201/*
202 * Default callback for parsing of the Proximity Domain <-> Memory
203 * Area mappings
204 */
205int __init
206acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
207{
208 u64 start, end;
209 u32 hotpluggable;
210 int node, pxm;
211
212 if (srat_disabled())
213 goto out_err;
David Daneye0af2612016-05-24 15:35:42 -0700214 if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) {
215 pr_err("SRAT: Unexpected header length: %d\n",
216 ma->header.length);
Hanjun Guo37704422016-05-24 15:35:41 -0700217 goto out_err_bad_srat;
David Daneye0af2612016-05-24 15:35:42 -0700218 }
Hanjun Guo37704422016-05-24 15:35:41 -0700219 if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0)
220 goto out_err;
221 hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE;
222 if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG))
223 goto out_err;
224
225 start = ma->base_address;
226 end = start + ma->length;
227 pxm = ma->proximity_domain;
228 if (acpi_srat_revision <= 1)
229 pxm &= 0xff;
230
231 node = acpi_map_pxm_to_node(pxm);
David Daneye0af2612016-05-24 15:35:42 -0700232 if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
233 pr_err("SRAT: Too many proximity domains.\n");
Hanjun Guo37704422016-05-24 15:35:41 -0700234 goto out_err_bad_srat;
235 }
236
David Daneye0af2612016-05-24 15:35:42 -0700237 if (numa_add_memblk(node, start, end) < 0) {
238 pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n",
239 node, (unsigned long long) start,
240 (unsigned long long) end - 1);
Hanjun Guo37704422016-05-24 15:35:41 -0700241 goto out_err_bad_srat;
David Daneye0af2612016-05-24 15:35:42 -0700242 }
Hanjun Guo37704422016-05-24 15:35:41 -0700243
244 node_set(node, numa_nodes_parsed);
245
246 pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
247 node, pxm,
248 (unsigned long long) start, (unsigned long long) end - 1,
249 hotpluggable ? " hotplug" : "",
250 ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
251
252 /* Mark hotplug range in memblock. */
253 if (hotpluggable && memblock_mark_hotplug(start, ma->length))
254 pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n",
255 (unsigned long long)start, (unsigned long long)end - 1);
256
257 max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1));
258
259 return 0;
260out_err_bad_srat:
261 bad_srat();
262out_err:
263 return -EINVAL;
264}
Hanjun Guo6525afd2016-05-24 15:35:35 -0700265#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
266
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300267static int __init acpi_parse_slit(struct acpi_table_header *table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
Hanjun Guo2fad9302015-02-05 17:33:14 +0800269 struct acpi_table_slit *slit = (struct acpi_table_slit *)table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Fenghua Yu39b89312008-06-09 16:48:18 -0700271 if (!slit_valid(slit)) {
Hanjun Guoac906a62016-05-24 15:35:31 -0700272 pr_info("SLIT table looks invalid. Not used.\n");
Fenghua Yu39b89312008-06-09 16:48:18 -0700273 return -EINVAL;
274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 acpi_numa_slit_init(slit);
276
277 return 0;
278}
279
Bjorn Helgaasbeffbe52014-01-27 17:19:15 -0700280void __init __weak
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800281acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
282{
Hanjun Guoac906a62016-05-24 15:35:31 -0700283 pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800284}
285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286static int __init
Keith Busch60574d12019-03-11 14:55:57 -0600287acpi_parse_x2apic_affinity(union acpi_subtable_headers *header,
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800288 const unsigned long end)
289{
290 struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
291
292 processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
293 if (!processor_affinity)
294 return -EINVAL;
295
Keith Busch60574d12019-03-11 14:55:57 -0600296 acpi_table_print_srat_entry(&header->common);
Suresh Siddha7237d3d2009-03-30 13:55:30 -0800297
298 /* let architecture-dependent part to do it */
299 acpi_numa_x2apic_affinity_init(processor_affinity);
300
301 return 0;
302}
303
304static int __init
Keith Busch60574d12019-03-11 14:55:57 -0600305acpi_parse_processor_affinity(union acpi_subtable_headers *header,
Len Brown4be44fc2005-08-05 00:44:28 -0400306 const unsigned long end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307{
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300308 struct acpi_srat_cpu_affinity *processor_affinity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300310 processor_affinity = (struct acpi_srat_cpu_affinity *)header;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 if (!processor_affinity)
312 return -EINVAL;
313
Keith Busch60574d12019-03-11 14:55:57 -0600314 acpi_table_print_srat_entry(&header->common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
316 /* let architecture-dependent part to do it */
317 acpi_numa_processor_affinity_init(processor_affinity);
318
319 return 0;
320}
321
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800322static int __init
Keith Busch60574d12019-03-11 14:55:57 -0600323acpi_parse_gicc_affinity(union acpi_subtable_headers *header,
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800324 const unsigned long end)
325{
326 struct acpi_srat_gicc_affinity *processor_affinity;
327
328 processor_affinity = (struct acpi_srat_gicc_affinity *)header;
329 if (!processor_affinity)
330 return -EINVAL;
331
Keith Busch60574d12019-03-11 14:55:57 -0600332 acpi_table_print_srat_entry(&header->common);
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800333
334 /* let architecture-dependent part to do it */
335 acpi_numa_gicc_affinity_init(processor_affinity);
336
337 return 0;
338}
339
Thomas Renninger095adbb2012-07-31 17:41:09 +0200340static int __initdata parsed_numa_memblks;
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342static int __init
Keith Busch60574d12019-03-11 14:55:57 -0600343acpi_parse_memory_affinity(union acpi_subtable_headers * header,
Len Brown4be44fc2005-08-05 00:44:28 -0400344 const unsigned long end)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300346 struct acpi_srat_mem_affinity *memory_affinity;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300348 memory_affinity = (struct acpi_srat_mem_affinity *)header;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 if (!memory_affinity)
350 return -EINVAL;
351
Keith Busch60574d12019-03-11 14:55:57 -0600352 acpi_table_print_srat_entry(&header->common);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 /* let architecture-dependent part to do it */
Thomas Renninger095adbb2012-07-31 17:41:09 +0200355 if (!acpi_numa_memory_affinity_init(memory_affinity))
356 parsed_numa_memblks++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 return 0;
358}
359
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300360static int __init acpi_parse_srat(struct acpi_table_header *table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
Hanjun Guo2fad9302015-02-05 17:33:14 +0800362 struct acpi_table_srat *srat = (struct acpi_table_srat *)table;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Kurt Garloff8df0eb7c2012-01-17 04:18:02 -0500364 acpi_srat_revision = srat->header.revision;
365
Andi Kleencfa806f2010-07-20 15:18:36 -0700366 /* Real work done in acpi_table_parse_srat below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367
368 return 0;
369}
370
David Rientjesae2c6dc2007-07-21 17:09:56 +0200371static int __init
Alexey Starikovskiy15a58ed2007-02-02 19:48:22 +0300372acpi_table_parse_srat(enum acpi_srat_type id,
Lv Zhengb43e1062013-01-12 15:29:38 +0000373 acpi_tbl_entry_handler handler, unsigned int max_entries)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
Len Brown6eb87fe2007-02-10 22:17:07 -0500375 return acpi_table_parse_entries(ACPI_SIG_SRAT,
Len Brown4be44fc2005-08-05 00:44:28 -0400376 sizeof(struct acpi_table_srat), id,
377 handler, max_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378}
379
Yinghai Lu20e69262013-03-01 14:51:27 -0800380int __init acpi_numa_init(void)
Tang Chene8d19552013-02-22 16:33:44 -0800381{
Yinghai Lu20e69262013-03-01 14:51:27 -0800382 int cnt = 0;
383
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800384 if (acpi_disabled)
385 return -EINVAL;
386
Yinghai Lud3bd0582010-12-16 19:09:58 -0800387 /*
388 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
389 * SRAT cpu entries could have different order with that in MADT.
390 * So go over all cpu entries in SRAT to get apicid to node mapping.
391 */
David Rientjes87162732009-09-25 15:20:04 -0700392
Ross Zwisler02cb4892017-07-21 16:51:24 -0600393 /* SRAT: System Resource Affinity Table */
Len Brown7f8f97c2007-02-10 21:28:03 -0500394 if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800395 struct acpi_subtable_proc srat_proc[3];
Lukasz Anaczkowski702b07f2016-04-21 11:29:00 +0200396
397 memset(srat_proc, 0, sizeof(srat_proc));
398 srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
399 srat_proc[0].handler = acpi_parse_processor_affinity;
400 srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
401 srat_proc[1].handler = acpi_parse_x2apic_affinity;
Hanjun Guo4bac6fa2016-06-17 11:53:02 +0800402 srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY;
403 srat_proc[2].handler = acpi_parse_gicc_affinity;
Lukasz Anaczkowski702b07f2016-04-21 11:29:00 +0200404
405 acpi_table_parse_entries_array(ACPI_SIG_SRAT,
406 sizeof(struct acpi_table_srat),
407 srat_proc, ARRAY_SIZE(srat_proc), 0);
408
Yinghai Lu20e69262013-03-01 14:51:27 -0800409 cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
Ganapatrao Kulkarnifd3e4542017-11-15 22:59:02 +0530410 acpi_parse_memory_affinity, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 }
412
413 /* SLIT: System Locality Information Table */
Len Brown7f8f97c2007-02-10 21:28:03 -0500414 acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Yinghai Lu20e69262013-03-01 14:51:27 -0800416 if (cnt < 0)
417 return cnt;
Thomas Renninger095adbb2012-07-31 17:41:09 +0200418 else if (!parsed_numa_memblks)
Thomas Renningerf3946fb2012-07-31 17:41:08 +0200419 return -ENOENT;
Tejun Heo940fed22011-02-16 12:13:06 +0100420 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421}
422
Bjorn Helgaasd79ed242014-01-24 15:48:01 -0700423static int acpi_get_pxm(acpi_handle h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
Matthew Wilcox27663c52008-10-10 02:22:59 -0400425 unsigned long long pxm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 acpi_status status;
427 acpi_handle handle;
428 acpi_handle phandle = h;
429
430 do {
431 handle = phandle;
432 status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm);
433 if (ACPI_SUCCESS(status))
Jan Engelhardt50dd0962006-10-01 00:28:50 +0200434 return pxm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 status = acpi_get_parent(handle, &phandle);
Len Brown4be44fc2005-08-05 00:44:28 -0400436 } while (ACPI_SUCCESS(status));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 return -1;
438}
Yasunori Goto1e3590e2006-06-27 02:53:31 -0700439
Bjorn Helgaas486c79b2014-01-24 15:25:10 -0700440int acpi_get_node(acpi_handle handle)
Yasunori Goto1e3590e2006-06-27 02:53:31 -0700441{
Bjorn Helgaas962fe9c2014-01-24 15:42:17 -0700442 int pxm;
Yasunori Goto1e3590e2006-06-27 02:53:31 -0700443
Yasunori Goto1e3590e2006-06-27 02:53:31 -0700444 pxm = acpi_get_pxm(handle);
Yasunori Goto1e3590e2006-06-27 02:53:31 -0700445
Bjorn Helgaas962fe9c2014-01-24 15:42:17 -0700446 return acpi_map_pxm_to_node(pxm);
Yasunori Goto1e3590e2006-06-27 02:53:31 -0700447}
448EXPORT_SYMBOL(acpi_get_node);