xref: /openbmc/linux/drivers/acpi/numa/hmat.c (revision 0e17c50f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019, Intel Corporation.
4  *
5  * Heterogeneous Memory Attributes Table (HMAT) representation
6  *
7  * This program parses and reports the platform's HMAT tables, and registers
8  * the applicable attributes with the node's interfaces.
9  */
10 
11 #define pr_fmt(fmt) "acpi/hmat: " fmt
12 #define dev_fmt(fmt) "acpi/hmat: " fmt
13 
14 #include <linux/acpi.h>
15 #include <linux/bitops.h>
16 #include <linux/device.h>
17 #include <linux/init.h>
18 #include <linux/list.h>
19 #include <linux/mm.h>
20 #include <linux/platform_device.h>
21 #include <linux/list_sort.h>
22 #include <linux/memregion.h>
23 #include <linux/memory.h>
24 #include <linux/mutex.h>
25 #include <linux/node.h>
26 #include <linux/sysfs.h>
27 
28 static u8 hmat_revision;
29 
30 static LIST_HEAD(targets);
31 static LIST_HEAD(initiators);
32 static LIST_HEAD(localities);
33 
34 static DEFINE_MUTEX(target_lock);
35 
36 /*
37  * The defined enum order is used to prioritize attributes to break ties when
38  * selecting the best performing node.
39  */
40 enum locality_types {
41 	WRITE_LATENCY,
42 	READ_LATENCY,
43 	WRITE_BANDWIDTH,
44 	READ_BANDWIDTH,
45 };
46 
47 static struct memory_locality *localities_types[4];
48 
49 struct target_cache {
50 	struct list_head node;
51 	struct node_cache_attrs cache_attrs;
52 };
53 
54 struct memory_target {
55 	struct list_head node;
56 	unsigned int memory_pxm;
57 	unsigned int processor_pxm;
58 	struct resource memregions;
59 	struct node_hmem_attrs hmem_attrs;
60 	struct list_head caches;
61 	struct node_cache_attrs cache_attrs;
62 	bool registered;
63 };
64 
65 struct memory_initiator {
66 	struct list_head node;
67 	unsigned int processor_pxm;
68 };
69 
70 struct memory_locality {
71 	struct list_head node;
72 	struct acpi_hmat_locality *hmat_loc;
73 };
74 
75 static struct memory_initiator *find_mem_initiator(unsigned int cpu_pxm)
76 {
77 	struct memory_initiator *initiator;
78 
79 	list_for_each_entry(initiator, &initiators, node)
80 		if (initiator->processor_pxm == cpu_pxm)
81 			return initiator;
82 	return NULL;
83 }
84 
85 static struct memory_target *find_mem_target(unsigned int mem_pxm)
86 {
87 	struct memory_target *target;
88 
89 	list_for_each_entry(target, &targets, node)
90 		if (target->memory_pxm == mem_pxm)
91 			return target;
92 	return NULL;
93 }
94 
95 static __init void alloc_memory_initiator(unsigned int cpu_pxm)
96 {
97 	struct memory_initiator *initiator;
98 
99 	if (pxm_to_node(cpu_pxm) == NUMA_NO_NODE)
100 		return;
101 
102 	initiator = find_mem_initiator(cpu_pxm);
103 	if (initiator)
104 		return;
105 
106 	initiator = kzalloc(sizeof(*initiator), GFP_KERNEL);
107 	if (!initiator)
108 		return;
109 
110 	initiator->processor_pxm = cpu_pxm;
111 	list_add_tail(&initiator->node, &initiators);
112 }
113 
114 static __init void alloc_memory_target(unsigned int mem_pxm,
115 		resource_size_t start, resource_size_t len)
116 {
117 	struct memory_target *target;
118 
119 	target = find_mem_target(mem_pxm);
120 	if (!target) {
121 		target = kzalloc(sizeof(*target), GFP_KERNEL);
122 		if (!target)
123 			return;
124 		target->memory_pxm = mem_pxm;
125 		target->processor_pxm = PXM_INVAL;
126 		target->memregions = (struct resource) {
127 			.name	= "ACPI mem",
128 			.start	= 0,
129 			.end	= -1,
130 			.flags	= IORESOURCE_MEM,
131 		};
132 		list_add_tail(&target->node, &targets);
133 		INIT_LIST_HEAD(&target->caches);
134 	}
135 
136 	/*
137 	 * There are potentially multiple ranges per PXM, so record each
138 	 * in the per-target memregions resource tree.
139 	 */
140 	if (!__request_region(&target->memregions, start, len, "memory target",
141 				IORESOURCE_MEM))
142 		pr_warn("failed to reserve %#llx - %#llx in pxm: %d\n",
143 				start, start + len, mem_pxm);
144 }
145 
146 static __init const char *hmat_data_type(u8 type)
147 {
148 	switch (type) {
149 	case ACPI_HMAT_ACCESS_LATENCY:
150 		return "Access Latency";
151 	case ACPI_HMAT_READ_LATENCY:
152 		return "Read Latency";
153 	case ACPI_HMAT_WRITE_LATENCY:
154 		return "Write Latency";
155 	case ACPI_HMAT_ACCESS_BANDWIDTH:
156 		return "Access Bandwidth";
157 	case ACPI_HMAT_READ_BANDWIDTH:
158 		return "Read Bandwidth";
159 	case ACPI_HMAT_WRITE_BANDWIDTH:
160 		return "Write Bandwidth";
161 	default:
162 		return "Reserved";
163 	}
164 }
165 
166 static __init const char *hmat_data_type_suffix(u8 type)
167 {
168 	switch (type) {
169 	case ACPI_HMAT_ACCESS_LATENCY:
170 	case ACPI_HMAT_READ_LATENCY:
171 	case ACPI_HMAT_WRITE_LATENCY:
172 		return " nsec";
173 	case ACPI_HMAT_ACCESS_BANDWIDTH:
174 	case ACPI_HMAT_READ_BANDWIDTH:
175 	case ACPI_HMAT_WRITE_BANDWIDTH:
176 		return " MB/s";
177 	default:
178 		return "";
179 	}
180 }
181 
182 static u32 hmat_normalize(u16 entry, u64 base, u8 type)
183 {
184 	u32 value;
185 
186 	/*
187 	 * Check for invalid and overflow values
188 	 */
189 	if (entry == 0xffff || !entry)
190 		return 0;
191 	else if (base > (UINT_MAX / (entry)))
192 		return 0;
193 
194 	/*
195 	 * Divide by the base unit for version 1, convert latency from
196 	 * picosenonds to nanoseconds if revision 2.
197 	 */
198 	value = entry * base;
199 	if (hmat_revision == 1) {
200 		if (value < 10)
201 			return 0;
202 		value = DIV_ROUND_UP(value, 10);
203 	} else if (hmat_revision == 2) {
204 		switch (type) {
205 		case ACPI_HMAT_ACCESS_LATENCY:
206 		case ACPI_HMAT_READ_LATENCY:
207 		case ACPI_HMAT_WRITE_LATENCY:
208 			value = DIV_ROUND_UP(value, 1000);
209 			break;
210 		default:
211 			break;
212 		}
213 	}
214 	return value;
215 }
216 
217 static void hmat_update_target_access(struct memory_target *target,
218 					     u8 type, u32 value)
219 {
220 	switch (type) {
221 	case ACPI_HMAT_ACCESS_LATENCY:
222 		target->hmem_attrs.read_latency = value;
223 		target->hmem_attrs.write_latency = value;
224 		break;
225 	case ACPI_HMAT_READ_LATENCY:
226 		target->hmem_attrs.read_latency = value;
227 		break;
228 	case ACPI_HMAT_WRITE_LATENCY:
229 		target->hmem_attrs.write_latency = value;
230 		break;
231 	case ACPI_HMAT_ACCESS_BANDWIDTH:
232 		target->hmem_attrs.read_bandwidth = value;
233 		target->hmem_attrs.write_bandwidth = value;
234 		break;
235 	case ACPI_HMAT_READ_BANDWIDTH:
236 		target->hmem_attrs.read_bandwidth = value;
237 		break;
238 	case ACPI_HMAT_WRITE_BANDWIDTH:
239 		target->hmem_attrs.write_bandwidth = value;
240 		break;
241 	default:
242 		break;
243 	}
244 }
245 
246 static __init void hmat_add_locality(struct acpi_hmat_locality *hmat_loc)
247 {
248 	struct memory_locality *loc;
249 
250 	loc = kzalloc(sizeof(*loc), GFP_KERNEL);
251 	if (!loc) {
252 		pr_notice_once("Failed to allocate HMAT locality\n");
253 		return;
254 	}
255 
256 	loc->hmat_loc = hmat_loc;
257 	list_add_tail(&loc->node, &localities);
258 
259 	switch (hmat_loc->data_type) {
260 	case ACPI_HMAT_ACCESS_LATENCY:
261 		localities_types[READ_LATENCY] = loc;
262 		localities_types[WRITE_LATENCY] = loc;
263 		break;
264 	case ACPI_HMAT_READ_LATENCY:
265 		localities_types[READ_LATENCY] = loc;
266 		break;
267 	case ACPI_HMAT_WRITE_LATENCY:
268 		localities_types[WRITE_LATENCY] = loc;
269 		break;
270 	case ACPI_HMAT_ACCESS_BANDWIDTH:
271 		localities_types[READ_BANDWIDTH] = loc;
272 		localities_types[WRITE_BANDWIDTH] = loc;
273 		break;
274 	case ACPI_HMAT_READ_BANDWIDTH:
275 		localities_types[READ_BANDWIDTH] = loc;
276 		break;
277 	case ACPI_HMAT_WRITE_BANDWIDTH:
278 		localities_types[WRITE_BANDWIDTH] = loc;
279 		break;
280 	default:
281 		break;
282 	}
283 }
284 
285 static __init int hmat_parse_locality(union acpi_subtable_headers *header,
286 				      const unsigned long end)
287 {
288 	struct acpi_hmat_locality *hmat_loc = (void *)header;
289 	struct memory_target *target;
290 	unsigned int init, targ, total_size, ipds, tpds;
291 	u32 *inits, *targs, value;
292 	u16 *entries;
293 	u8 type, mem_hier;
294 
295 	if (hmat_loc->header.length < sizeof(*hmat_loc)) {
296 		pr_notice("HMAT: Unexpected locality header length: %u\n",
297 			 hmat_loc->header.length);
298 		return -EINVAL;
299 	}
300 
301 	type = hmat_loc->data_type;
302 	mem_hier = hmat_loc->flags & ACPI_HMAT_MEMORY_HIERARCHY;
303 	ipds = hmat_loc->number_of_initiator_Pds;
304 	tpds = hmat_loc->number_of_target_Pds;
305 	total_size = sizeof(*hmat_loc) + sizeof(*entries) * ipds * tpds +
306 		     sizeof(*inits) * ipds + sizeof(*targs) * tpds;
307 	if (hmat_loc->header.length < total_size) {
308 		pr_notice("HMAT: Unexpected locality header length:%u, minimum required:%u\n",
309 			 hmat_loc->header.length, total_size);
310 		return -EINVAL;
311 	}
312 
313 	pr_info("HMAT: Locality: Flags:%02x Type:%s Initiator Domains:%u Target Domains:%u Base:%lld\n",
314 		hmat_loc->flags, hmat_data_type(type), ipds, tpds,
315 		hmat_loc->entry_base_unit);
316 
317 	inits = (u32 *)(hmat_loc + 1);
318 	targs = inits + ipds;
319 	entries = (u16 *)(targs + tpds);
320 	for (init = 0; init < ipds; init++) {
321 		alloc_memory_initiator(inits[init]);
322 		for (targ = 0; targ < tpds; targ++) {
323 			value = hmat_normalize(entries[init * tpds + targ],
324 					       hmat_loc->entry_base_unit,
325 					       type);
326 			pr_info("  Initiator-Target[%u-%u]:%u%s\n",
327 				inits[init], targs[targ], value,
328 				hmat_data_type_suffix(type));
329 
330 			if (mem_hier == ACPI_HMAT_MEMORY) {
331 				target = find_mem_target(targs[targ]);
332 				if (target && target->processor_pxm == inits[init])
333 					hmat_update_target_access(target, type, value);
334 			}
335 		}
336 	}
337 
338 	if (mem_hier == ACPI_HMAT_MEMORY)
339 		hmat_add_locality(hmat_loc);
340 
341 	return 0;
342 }
343 
344 static __init int hmat_parse_cache(union acpi_subtable_headers *header,
345 				   const unsigned long end)
346 {
347 	struct acpi_hmat_cache *cache = (void *)header;
348 	struct memory_target *target;
349 	struct target_cache *tcache;
350 	u32 attrs;
351 
352 	if (cache->header.length < sizeof(*cache)) {
353 		pr_notice("HMAT: Unexpected cache header length: %u\n",
354 			 cache->header.length);
355 		return -EINVAL;
356 	}
357 
358 	attrs = cache->cache_attributes;
359 	pr_info("HMAT: Cache: Domain:%u Size:%llu Attrs:%08x SMBIOS Handles:%d\n",
360 		cache->memory_PD, cache->cache_size, attrs,
361 		cache->number_of_SMBIOShandles);
362 
363 	target = find_mem_target(cache->memory_PD);
364 	if (!target)
365 		return 0;
366 
367 	tcache = kzalloc(sizeof(*tcache), GFP_KERNEL);
368 	if (!tcache) {
369 		pr_notice_once("Failed to allocate HMAT cache info\n");
370 		return 0;
371 	}
372 
373 	tcache->cache_attrs.size = cache->cache_size;
374 	tcache->cache_attrs.level = (attrs & ACPI_HMAT_CACHE_LEVEL) >> 4;
375 	tcache->cache_attrs.line_size = (attrs & ACPI_HMAT_CACHE_LINE_SIZE) >> 16;
376 
377 	switch ((attrs & ACPI_HMAT_CACHE_ASSOCIATIVITY) >> 8) {
378 	case ACPI_HMAT_CA_DIRECT_MAPPED:
379 		tcache->cache_attrs.indexing = NODE_CACHE_DIRECT_MAP;
380 		break;
381 	case ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING:
382 		tcache->cache_attrs.indexing = NODE_CACHE_INDEXED;
383 		break;
384 	case ACPI_HMAT_CA_NONE:
385 	default:
386 		tcache->cache_attrs.indexing = NODE_CACHE_OTHER;
387 		break;
388 	}
389 
390 	switch ((attrs & ACPI_HMAT_WRITE_POLICY) >> 12) {
391 	case ACPI_HMAT_CP_WB:
392 		tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_BACK;
393 		break;
394 	case ACPI_HMAT_CP_WT:
395 		tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_THROUGH;
396 		break;
397 	case ACPI_HMAT_CP_NONE:
398 	default:
399 		tcache->cache_attrs.write_policy = NODE_CACHE_WRITE_OTHER;
400 		break;
401 	}
402 	list_add_tail(&tcache->node, &target->caches);
403 
404 	return 0;
405 }
406 
407 static int __init hmat_parse_proximity_domain(union acpi_subtable_headers *header,
408 					      const unsigned long end)
409 {
410 	struct acpi_hmat_proximity_domain *p = (void *)header;
411 	struct memory_target *target = NULL;
412 
413 	if (p->header.length != sizeof(*p)) {
414 		pr_notice("HMAT: Unexpected address range header length: %u\n",
415 			 p->header.length);
416 		return -EINVAL;
417 	}
418 
419 	if (hmat_revision == 1)
420 		pr_info("HMAT: Memory (%#llx length %#llx) Flags:%04x Processor Domain:%u Memory Domain:%u\n",
421 			p->reserved3, p->reserved4, p->flags, p->processor_PD,
422 			p->memory_PD);
423 	else
424 		pr_info("HMAT: Memory Flags:%04x Processor Domain:%u Memory Domain:%u\n",
425 			p->flags, p->processor_PD, p->memory_PD);
426 
427 	if (p->flags & ACPI_HMAT_MEMORY_PD_VALID && hmat_revision == 1) {
428 		target = find_mem_target(p->memory_PD);
429 		if (!target) {
430 			pr_debug("HMAT: Memory Domain missing from SRAT\n");
431 			return -EINVAL;
432 		}
433 	}
434 	if (target && p->flags & ACPI_HMAT_PROCESSOR_PD_VALID) {
435 		int p_node = pxm_to_node(p->processor_PD);
436 
437 		if (p_node == NUMA_NO_NODE) {
438 			pr_debug("HMAT: Invalid Processor Domain\n");
439 			return -EINVAL;
440 		}
441 		target->processor_pxm = p->processor_PD;
442 	}
443 
444 	return 0;
445 }
446 
447 static int __init hmat_parse_subtable(union acpi_subtable_headers *header,
448 				      const unsigned long end)
449 {
450 	struct acpi_hmat_structure *hdr = (void *)header;
451 
452 	if (!hdr)
453 		return -EINVAL;
454 
455 	switch (hdr->type) {
456 	case ACPI_HMAT_TYPE_PROXIMITY:
457 		return hmat_parse_proximity_domain(header, end);
458 	case ACPI_HMAT_TYPE_LOCALITY:
459 		return hmat_parse_locality(header, end);
460 	case ACPI_HMAT_TYPE_CACHE:
461 		return hmat_parse_cache(header, end);
462 	default:
463 		return -EINVAL;
464 	}
465 }
466 
467 static __init int srat_parse_mem_affinity(union acpi_subtable_headers *header,
468 					  const unsigned long end)
469 {
470 	struct acpi_srat_mem_affinity *ma = (void *)header;
471 
472 	if (!ma)
473 		return -EINVAL;
474 	if (!(ma->flags & ACPI_SRAT_MEM_ENABLED))
475 		return 0;
476 	alloc_memory_target(ma->proximity_domain, ma->base_address, ma->length);
477 	return 0;
478 }
479 
480 static u32 hmat_initiator_perf(struct memory_target *target,
481 			       struct memory_initiator *initiator,
482 			       struct acpi_hmat_locality *hmat_loc)
483 {
484 	unsigned int ipds, tpds, i, idx = 0, tdx = 0;
485 	u32 *inits, *targs;
486 	u16 *entries;
487 
488 	ipds = hmat_loc->number_of_initiator_Pds;
489 	tpds = hmat_loc->number_of_target_Pds;
490 	inits = (u32 *)(hmat_loc + 1);
491 	targs = inits + ipds;
492 	entries = (u16 *)(targs + tpds);
493 
494 	for (i = 0; i < ipds; i++) {
495 		if (inits[i] == initiator->processor_pxm) {
496 			idx = i;
497 			break;
498 		}
499 	}
500 
501 	if (i == ipds)
502 		return 0;
503 
504 	for (i = 0; i < tpds; i++) {
505 		if (targs[i] == target->memory_pxm) {
506 			tdx = i;
507 			break;
508 		}
509 	}
510 	if (i == tpds)
511 		return 0;
512 
513 	return hmat_normalize(entries[idx * tpds + tdx],
514 			      hmat_loc->entry_base_unit,
515 			      hmat_loc->data_type);
516 }
517 
518 static bool hmat_update_best(u8 type, u32 value, u32 *best)
519 {
520 	bool updated = false;
521 
522 	if (!value)
523 		return false;
524 
525 	switch (type) {
526 	case ACPI_HMAT_ACCESS_LATENCY:
527 	case ACPI_HMAT_READ_LATENCY:
528 	case ACPI_HMAT_WRITE_LATENCY:
529 		if (!*best || *best > value) {
530 			*best = value;
531 			updated = true;
532 		}
533 		break;
534 	case ACPI_HMAT_ACCESS_BANDWIDTH:
535 	case ACPI_HMAT_READ_BANDWIDTH:
536 	case ACPI_HMAT_WRITE_BANDWIDTH:
537 		if (!*best || *best < value) {
538 			*best = value;
539 			updated = true;
540 		}
541 		break;
542 	}
543 
544 	return updated;
545 }
546 
547 static int initiator_cmp(void *priv, struct list_head *a, struct list_head *b)
548 {
549 	struct memory_initiator *ia;
550 	struct memory_initiator *ib;
551 	unsigned long *p_nodes = priv;
552 
553 	ia = list_entry(a, struct memory_initiator, node);
554 	ib = list_entry(b, struct memory_initiator, node);
555 
556 	set_bit(ia->processor_pxm, p_nodes);
557 	set_bit(ib->processor_pxm, p_nodes);
558 
559 	return ia->processor_pxm - ib->processor_pxm;
560 }
561 
562 static void hmat_register_target_initiators(struct memory_target *target)
563 {
564 	static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
565 	struct memory_initiator *initiator;
566 	unsigned int mem_nid, cpu_nid;
567 	struct memory_locality *loc = NULL;
568 	u32 best = 0;
569 	int i;
570 
571 	mem_nid = pxm_to_node(target->memory_pxm);
572 	/*
573 	 * If the Address Range Structure provides a local processor pxm, link
574 	 * only that one. Otherwise, find the best performance attributes and
575 	 * register all initiators that match.
576 	 */
577 	if (target->processor_pxm != PXM_INVAL) {
578 		cpu_nid = pxm_to_node(target->processor_pxm);
579 		register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
580 		return;
581 	}
582 
583 	if (list_empty(&localities))
584 		return;
585 
586 	/*
587 	 * We need the initiator list sorted so we can use bitmap_clear for
588 	 * previously set initiators when we find a better memory accessor.
589 	 * We'll also use the sorting to prime the candidate nodes with known
590 	 * initiators.
591 	 */
592 	bitmap_zero(p_nodes, MAX_NUMNODES);
593 	list_sort(p_nodes, &initiators, initiator_cmp);
594 	for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
595 		loc = localities_types[i];
596 		if (!loc)
597 			continue;
598 
599 		best = 0;
600 		list_for_each_entry(initiator, &initiators, node) {
601 			u32 value;
602 
603 			if (!test_bit(initiator->processor_pxm, p_nodes))
604 				continue;
605 
606 			value = hmat_initiator_perf(target, initiator, loc->hmat_loc);
607 			if (hmat_update_best(loc->hmat_loc->data_type, value, &best))
608 				bitmap_clear(p_nodes, 0, initiator->processor_pxm);
609 			if (value != best)
610 				clear_bit(initiator->processor_pxm, p_nodes);
611 		}
612 		if (best)
613 			hmat_update_target_access(target, loc->hmat_loc->data_type, best);
614 	}
615 
616 	for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
617 		cpu_nid = pxm_to_node(i);
618 		register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
619 	}
620 }
621 
622 static void hmat_register_target_cache(struct memory_target *target)
623 {
624 	unsigned mem_nid = pxm_to_node(target->memory_pxm);
625 	struct target_cache *tcache;
626 
627 	list_for_each_entry(tcache, &target->caches, node)
628 		node_add_cache(mem_nid, &tcache->cache_attrs);
629 }
630 
631 static void hmat_register_target_perf(struct memory_target *target)
632 {
633 	unsigned mem_nid = pxm_to_node(target->memory_pxm);
634 	node_set_perf_attrs(mem_nid, &target->hmem_attrs, 0);
635 }
636 
637 static void hmat_register_target_device(struct memory_target *target,
638 		struct resource *r)
639 {
640 	/* define a clean / non-busy resource for the platform device */
641 	struct resource res = {
642 		.start = r->start,
643 		.end = r->end,
644 		.flags = IORESOURCE_MEM,
645 	};
646 	struct platform_device *pdev;
647 	struct memregion_info info;
648 	int rc, id;
649 
650 	rc = region_intersects(res.start, resource_size(&res), IORESOURCE_MEM,
651 			IORES_DESC_SOFT_RESERVED);
652 	if (rc != REGION_INTERSECTS)
653 		return;
654 
655 	id = memregion_alloc(GFP_KERNEL);
656 	if (id < 0) {
657 		pr_err("memregion allocation failure for %pr\n", &res);
658 		return;
659 	}
660 
661 	pdev = platform_device_alloc("hmem", id);
662 	if (!pdev) {
663 		pr_err("hmem device allocation failure for %pr\n", &res);
664 		goto out_pdev;
665 	}
666 
667 	pdev->dev.numa_node = acpi_map_pxm_to_online_node(target->memory_pxm);
668 	info = (struct memregion_info) {
669 		.target_node = acpi_map_pxm_to_node(target->memory_pxm),
670 	};
671 	rc = platform_device_add_data(pdev, &info, sizeof(info));
672 	if (rc < 0) {
673 		pr_err("hmem memregion_info allocation failure for %pr\n", &res);
674 		goto out_pdev;
675 	}
676 
677 	rc = platform_device_add_resources(pdev, &res, 1);
678 	if (rc < 0) {
679 		pr_err("hmem resource allocation failure for %pr\n", &res);
680 		goto out_resource;
681 	}
682 
683 	rc = platform_device_add(pdev);
684 	if (rc < 0) {
685 		dev_err(&pdev->dev, "device add failed for %pr\n", &res);
686 		goto out_resource;
687 	}
688 
689 	return;
690 
691 out_resource:
692 	put_device(&pdev->dev);
693 out_pdev:
694 	memregion_free(id);
695 }
696 
697 static void hmat_register_target_devices(struct memory_target *target)
698 {
699 	struct resource *res;
700 
701 	/*
702 	 * Do not bother creating devices if no driver is available to
703 	 * consume them.
704 	 */
705 	if (!IS_ENABLED(CONFIG_DEV_DAX_HMEM))
706 		return;
707 
708 	for (res = target->memregions.child; res; res = res->sibling)
709 		hmat_register_target_device(target, res);
710 }
711 
712 static void hmat_register_target(struct memory_target *target)
713 {
714 	int nid = pxm_to_node(target->memory_pxm);
715 
716 	/*
717 	 * Devices may belong to either an offline or online
718 	 * node, so unconditionally add them.
719 	 */
720 	hmat_register_target_devices(target);
721 
722 	/*
723 	 * Skip offline nodes. This can happen when memory
724 	 * marked EFI_MEMORY_SP, "specific purpose", is applied
725 	 * to all the memory in a promixity domain leading to
726 	 * the node being marked offline / unplugged, or if
727 	 * memory-only "hotplug" node is offline.
728 	 */
729 	if (nid == NUMA_NO_NODE || !node_online(nid))
730 		return;
731 
732 	mutex_lock(&target_lock);
733 	if (!target->registered) {
734 		hmat_register_target_initiators(target);
735 		hmat_register_target_cache(target);
736 		hmat_register_target_perf(target);
737 		target->registered = true;
738 	}
739 	mutex_unlock(&target_lock);
740 }
741 
742 static void hmat_register_targets(void)
743 {
744 	struct memory_target *target;
745 
746 	list_for_each_entry(target, &targets, node)
747 		hmat_register_target(target);
748 }
749 
750 static int hmat_callback(struct notifier_block *self,
751 			 unsigned long action, void *arg)
752 {
753 	struct memory_target *target;
754 	struct memory_notify *mnb = arg;
755 	int pxm, nid = mnb->status_change_nid;
756 
757 	if (nid == NUMA_NO_NODE || action != MEM_ONLINE)
758 		return NOTIFY_OK;
759 
760 	pxm = node_to_pxm(nid);
761 	target = find_mem_target(pxm);
762 	if (!target)
763 		return NOTIFY_OK;
764 
765 	hmat_register_target(target);
766 	return NOTIFY_OK;
767 }
768 
769 static struct notifier_block hmat_callback_nb = {
770 	.notifier_call = hmat_callback,
771 	.priority = 2,
772 };
773 
774 static __init void hmat_free_structures(void)
775 {
776 	struct memory_target *target, *tnext;
777 	struct memory_locality *loc, *lnext;
778 	struct memory_initiator *initiator, *inext;
779 	struct target_cache *tcache, *cnext;
780 
781 	list_for_each_entry_safe(target, tnext, &targets, node) {
782 		struct resource *res, *res_next;
783 
784 		list_for_each_entry_safe(tcache, cnext, &target->caches, node) {
785 			list_del(&tcache->node);
786 			kfree(tcache);
787 		}
788 
789 		list_del(&target->node);
790 		res = target->memregions.child;
791 		while (res) {
792 			res_next = res->sibling;
793 			__release_region(&target->memregions, res->start,
794 					resource_size(res));
795 			res = res_next;
796 		}
797 		kfree(target);
798 	}
799 
800 	list_for_each_entry_safe(initiator, inext, &initiators, node) {
801 		list_del(&initiator->node);
802 		kfree(initiator);
803 	}
804 
805 	list_for_each_entry_safe(loc, lnext, &localities, node) {
806 		list_del(&loc->node);
807 		kfree(loc);
808 	}
809 }
810 
811 static __init int hmat_init(void)
812 {
813 	struct acpi_table_header *tbl;
814 	enum acpi_hmat_type i;
815 	acpi_status status;
816 
817 	if (srat_disabled())
818 		return 0;
819 
820 	status = acpi_get_table(ACPI_SIG_SRAT, 0, &tbl);
821 	if (ACPI_FAILURE(status))
822 		return 0;
823 
824 	if (acpi_table_parse_entries(ACPI_SIG_SRAT,
825 				sizeof(struct acpi_table_srat),
826 				ACPI_SRAT_TYPE_MEMORY_AFFINITY,
827 				srat_parse_mem_affinity, 0) < 0)
828 		goto out_put;
829 	acpi_put_table(tbl);
830 
831 	status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
832 	if (ACPI_FAILURE(status))
833 		goto out_put;
834 
835 	hmat_revision = tbl->revision;
836 	switch (hmat_revision) {
837 	case 1:
838 	case 2:
839 		break;
840 	default:
841 		pr_notice("Ignoring HMAT: Unknown revision:%d\n", hmat_revision);
842 		goto out_put;
843 	}
844 
845 	for (i = ACPI_HMAT_TYPE_PROXIMITY; i < ACPI_HMAT_TYPE_RESERVED; i++) {
846 		if (acpi_table_parse_entries(ACPI_SIG_HMAT,
847 					     sizeof(struct acpi_table_hmat), i,
848 					     hmat_parse_subtable, 0) < 0) {
849 			pr_notice("Ignoring HMAT: Invalid table");
850 			goto out_put;
851 		}
852 	}
853 	hmat_register_targets();
854 
855 	/* Keep the table and structures if the notifier may use them */
856 	if (!register_hotmemory_notifier(&hmat_callback_nb))
857 		return 0;
858 out_put:
859 	hmat_free_structures();
860 	acpi_put_table(tbl);
861 	return 0;
862 }
863 device_initcall(hmat_init);
864