xref: /linux/tools/testing/cxl/test/cxl.c (revision d104e3d17f7bfc505281f57f8c1a5589fca6ffe4)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright(c) 2021 Intel Corporation. All rights reserved.
3 
4 #include <linux/platform_device.h>
5 #include <linux/memory_hotplug.h>
6 #include <linux/genalloc.h>
7 #include <linux/module.h>
8 #include <linux/mutex.h>
9 #include <linux/acpi.h>
10 #include <linux/pci.h>
11 #include <linux/mm.h>
12 #include <cxlmem.h>
13 
14 #include "../watermark.h"
15 #include "mock.h"
16 
17 static int interleave_arithmetic;
18 
19 #define FAKE_QTG_ID	42
20 
21 #define NR_CXL_HOST_BRIDGES 2
22 #define NR_CXL_SINGLE_HOST 1
23 #define NR_CXL_RCH 1
24 #define NR_CXL_ROOT_PORTS 2
25 #define NR_CXL_SWITCH_PORTS 2
26 #define NR_CXL_PORT_DECODERS 8
27 #define NR_BRIDGES (NR_CXL_HOST_BRIDGES + NR_CXL_SINGLE_HOST + NR_CXL_RCH)
28 
29 static struct platform_device *cxl_acpi;
30 static struct platform_device *cxl_host_bridge[NR_CXL_HOST_BRIDGES];
31 #define NR_MULTI_ROOT (NR_CXL_HOST_BRIDGES * NR_CXL_ROOT_PORTS)
32 static struct platform_device *cxl_root_port[NR_MULTI_ROOT];
33 static struct platform_device *cxl_switch_uport[NR_MULTI_ROOT];
34 #define NR_MEM_MULTI \
35 	(NR_CXL_HOST_BRIDGES * NR_CXL_ROOT_PORTS * NR_CXL_SWITCH_PORTS)
36 static struct platform_device *cxl_switch_dport[NR_MEM_MULTI];
37 
38 static struct platform_device *cxl_hb_single[NR_CXL_SINGLE_HOST];
39 static struct platform_device *cxl_root_single[NR_CXL_SINGLE_HOST];
40 static struct platform_device *cxl_swu_single[NR_CXL_SINGLE_HOST];
41 #define NR_MEM_SINGLE (NR_CXL_SINGLE_HOST * NR_CXL_SWITCH_PORTS)
42 static struct platform_device *cxl_swd_single[NR_MEM_SINGLE];
43 
44 struct platform_device *cxl_mem[NR_MEM_MULTI];
45 struct platform_device *cxl_mem_single[NR_MEM_SINGLE];
46 
47 static struct platform_device *cxl_rch[NR_CXL_RCH];
48 static struct platform_device *cxl_rcd[NR_CXL_RCH];
49 
50 static inline bool is_multi_bridge(struct device *dev)
51 {
52 	int i;
53 
54 	for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++)
55 		if (&cxl_host_bridge[i]->dev == dev)
56 			return true;
57 	return false;
58 }
59 
60 static inline bool is_single_bridge(struct device *dev)
61 {
62 	int i;
63 
64 	for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++)
65 		if (&cxl_hb_single[i]->dev == dev)
66 			return true;
67 	return false;
68 }
69 
70 static struct acpi_device acpi0017_mock;
71 static struct acpi_device host_bridge[NR_BRIDGES] = {
72 	[0] = {
73 		.handle = &host_bridge[0],
74 		.pnp.unique_id = "0",
75 	},
76 	[1] = {
77 		.handle = &host_bridge[1],
78 		.pnp.unique_id = "1",
79 	},
80 	[2] = {
81 		.handle = &host_bridge[2],
82 		.pnp.unique_id = "2",
83 	},
84 	[3] = {
85 		.handle = &host_bridge[3],
86 		.pnp.unique_id = "3",
87 	},
88 };
89 
90 static bool is_mock_dev(struct device *dev)
91 {
92 	int i;
93 
94 	for (i = 0; i < ARRAY_SIZE(cxl_mem); i++)
95 		if (dev == &cxl_mem[i]->dev)
96 			return true;
97 	for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++)
98 		if (dev == &cxl_mem_single[i]->dev)
99 			return true;
100 	for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++)
101 		if (dev == &cxl_rcd[i]->dev)
102 			return true;
103 	if (dev == &cxl_acpi->dev)
104 		return true;
105 	return false;
106 }
107 
108 static bool is_mock_adev(struct acpi_device *adev)
109 {
110 	int i;
111 
112 	if (adev == &acpi0017_mock)
113 		return true;
114 
115 	for (i = 0; i < ARRAY_SIZE(host_bridge); i++)
116 		if (adev == &host_bridge[i])
117 			return true;
118 
119 	return false;
120 }
121 
122 static struct {
123 	struct acpi_table_cedt cedt;
124 	struct acpi_cedt_chbs chbs[NR_BRIDGES];
125 	struct {
126 		struct acpi_cedt_cfmws cfmws;
127 		u32 target[1];
128 	} cfmws0;
129 	struct {
130 		struct acpi_cedt_cfmws cfmws;
131 		u32 target[2];
132 	} cfmws1;
133 	struct {
134 		struct acpi_cedt_cfmws cfmws;
135 		u32 target[1];
136 	} cfmws2;
137 	struct {
138 		struct acpi_cedt_cfmws cfmws;
139 		u32 target[2];
140 	} cfmws3;
141 	struct {
142 		struct acpi_cedt_cfmws cfmws;
143 		u32 target[1];
144 	} cfmws4;
145 	struct {
146 		struct acpi_cedt_cfmws cfmws;
147 		u32 target[1];
148 	} cfmws5;
149 	struct {
150 		struct acpi_cedt_cfmws cfmws;
151 		u32 target[1];
152 	} cfmws6;
153 	struct {
154 		struct acpi_cedt_cfmws cfmws;
155 		u32 target[2];
156 	} cfmws7;
157 	struct {
158 		struct acpi_cedt_cfmws cfmws;
159 		u32 target[3];
160 	} cfmws8;
161 	struct {
162 		struct acpi_cedt_cxims cxims;
163 		u64 xormap_list[2];
164 	} cxims0;
165 } __packed mock_cedt = {
166 	.cedt = {
167 		.header = {
168 			.signature = "CEDT",
169 			.length = sizeof(mock_cedt),
170 			.revision = 1,
171 		},
172 	},
173 	.chbs[0] = {
174 		.header = {
175 			.type = ACPI_CEDT_TYPE_CHBS,
176 			.length = sizeof(mock_cedt.chbs[0]),
177 		},
178 		.uid = 0,
179 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20,
180 	},
181 	.chbs[1] = {
182 		.header = {
183 			.type = ACPI_CEDT_TYPE_CHBS,
184 			.length = sizeof(mock_cedt.chbs[0]),
185 		},
186 		.uid = 1,
187 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20,
188 	},
189 	.chbs[2] = {
190 		.header = {
191 			.type = ACPI_CEDT_TYPE_CHBS,
192 			.length = sizeof(mock_cedt.chbs[0]),
193 		},
194 		.uid = 2,
195 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20,
196 	},
197 	.chbs[3] = {
198 		.header = {
199 			.type = ACPI_CEDT_TYPE_CHBS,
200 			.length = sizeof(mock_cedt.chbs[0]),
201 		},
202 		.uid = 3,
203 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL11,
204 	},
205 	.cfmws0 = {
206 		.cfmws = {
207 			.header = {
208 				.type = ACPI_CEDT_TYPE_CFMWS,
209 				.length = sizeof(mock_cedt.cfmws0),
210 			},
211 			.interleave_ways = 0,
212 			.granularity = 4,
213 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
214 					ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
215 			.qtg_id = FAKE_QTG_ID,
216 			.window_size = SZ_256M * 4UL,
217 		},
218 		.target = { 0 },
219 	},
220 	.cfmws1 = {
221 		.cfmws = {
222 			.header = {
223 				.type = ACPI_CEDT_TYPE_CFMWS,
224 				.length = sizeof(mock_cedt.cfmws1),
225 			},
226 			.interleave_ways = 1,
227 			.granularity = 4,
228 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
229 					ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
230 			.qtg_id = FAKE_QTG_ID,
231 			.window_size = SZ_256M * 8UL,
232 		},
233 		.target = { 0, 1, },
234 	},
235 	.cfmws2 = {
236 		.cfmws = {
237 			.header = {
238 				.type = ACPI_CEDT_TYPE_CFMWS,
239 				.length = sizeof(mock_cedt.cfmws2),
240 			},
241 			.interleave_ways = 0,
242 			.granularity = 4,
243 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
244 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
245 			.qtg_id = FAKE_QTG_ID,
246 			.window_size = SZ_256M * 4UL,
247 		},
248 		.target = { 0 },
249 	},
250 	.cfmws3 = {
251 		.cfmws = {
252 			.header = {
253 				.type = ACPI_CEDT_TYPE_CFMWS,
254 				.length = sizeof(mock_cedt.cfmws3),
255 			},
256 			.interleave_ways = 1,
257 			.granularity = 4,
258 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
259 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
260 			.qtg_id = FAKE_QTG_ID,
261 			.window_size = SZ_256M * 8UL,
262 		},
263 		.target = { 0, 1, },
264 	},
265 	.cfmws4 = {
266 		.cfmws = {
267 			.header = {
268 				.type = ACPI_CEDT_TYPE_CFMWS,
269 				.length = sizeof(mock_cedt.cfmws4),
270 			},
271 			.interleave_ways = 0,
272 			.granularity = 4,
273 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
274 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
275 			.qtg_id = FAKE_QTG_ID,
276 			.window_size = SZ_256M * 4UL,
277 		},
278 		.target = { 2 },
279 	},
280 	.cfmws5 = {
281 		.cfmws = {
282 			.header = {
283 				.type = ACPI_CEDT_TYPE_CFMWS,
284 				.length = sizeof(mock_cedt.cfmws5),
285 			},
286 			.interleave_ways = 0,
287 			.granularity = 4,
288 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
289 					ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
290 			.qtg_id = FAKE_QTG_ID,
291 			.window_size = SZ_256M,
292 		},
293 		.target = { 3 },
294 	},
295 	/* .cfmws6,7,8 use ACPI_CEDT_CFMWS_ARITHMETIC_XOR */
296 	.cfmws6 = {
297 		.cfmws = {
298 			.header = {
299 				.type = ACPI_CEDT_TYPE_CFMWS,
300 				.length = sizeof(mock_cedt.cfmws6),
301 			},
302 			.interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
303 			.interleave_ways = 0,
304 			.granularity = 4,
305 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
306 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
307 			.qtg_id = FAKE_QTG_ID,
308 			.window_size = SZ_256M * 8UL,
309 		},
310 		.target = { 0, },
311 	},
312 	.cfmws7 = {
313 		.cfmws = {
314 			.header = {
315 				.type = ACPI_CEDT_TYPE_CFMWS,
316 				.length = sizeof(mock_cedt.cfmws7),
317 			},
318 			.interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
319 			.interleave_ways = 1,
320 			.granularity = 0,
321 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
322 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
323 			.qtg_id = FAKE_QTG_ID,
324 			.window_size = SZ_256M * 8UL,
325 		},
326 		.target = { 0, 1, },
327 	},
328 	.cfmws8 = {
329 		.cfmws = {
330 			.header = {
331 				.type = ACPI_CEDT_TYPE_CFMWS,
332 				.length = sizeof(mock_cedt.cfmws8),
333 			},
334 			.interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
335 			.interleave_ways = 8,
336 			.granularity = 1,
337 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
338 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
339 			.qtg_id = FAKE_QTG_ID,
340 			.window_size = SZ_512M * 6UL,
341 		},
342 		.target = { 0, 1, 2, },
343 	},
344 	.cxims0 = {
345 		.cxims = {
346 			.header = {
347 				.type = ACPI_CEDT_TYPE_CXIMS,
348 				.length = sizeof(mock_cedt.cxims0),
349 			},
350 			.hbig = 0,
351 			.nr_xormaps = 2,
352 		},
353 		.xormap_list = { 0x404100, 0x808200, },
354 	},
355 };
356 
357 struct acpi_cedt_cfmws *mock_cfmws[] = {
358 	[0] = &mock_cedt.cfmws0.cfmws,
359 	[1] = &mock_cedt.cfmws1.cfmws,
360 	[2] = &mock_cedt.cfmws2.cfmws,
361 	[3] = &mock_cedt.cfmws3.cfmws,
362 	[4] = &mock_cedt.cfmws4.cfmws,
363 	[5] = &mock_cedt.cfmws5.cfmws,
364 	/* Modulo Math above, XOR Math below */
365 	[6] = &mock_cedt.cfmws6.cfmws,
366 	[7] = &mock_cedt.cfmws7.cfmws,
367 	[8] = &mock_cedt.cfmws8.cfmws,
368 };
369 
370 static int cfmws_start;
371 static int cfmws_end;
372 #define CFMWS_MOD_ARRAY_START 0
373 #define CFMWS_MOD_ARRAY_END   5
374 #define CFMWS_XOR_ARRAY_START 6
375 #define CFMWS_XOR_ARRAY_END   8
376 
377 struct acpi_cedt_cxims *mock_cxims[1] = {
378 	[0] = &mock_cedt.cxims0.cxims,
379 };
380 
381 struct cxl_mock_res {
382 	struct list_head list;
383 	struct range range;
384 };
385 
386 static LIST_HEAD(mock_res);
387 static DEFINE_MUTEX(mock_res_lock);
388 static struct gen_pool *cxl_mock_pool;
389 
390 static void depopulate_all_mock_resources(void)
391 {
392 	struct cxl_mock_res *res, *_res;
393 
394 	mutex_lock(&mock_res_lock);
395 	list_for_each_entry_safe(res, _res, &mock_res, list) {
396 		gen_pool_free(cxl_mock_pool, res->range.start,
397 			      range_len(&res->range));
398 		list_del(&res->list);
399 		kfree(res);
400 	}
401 	mutex_unlock(&mock_res_lock);
402 }
403 
404 static struct cxl_mock_res *alloc_mock_res(resource_size_t size, int align)
405 {
406 	struct cxl_mock_res *res = kzalloc(sizeof(*res), GFP_KERNEL);
407 	struct genpool_data_align data = {
408 		.align = align,
409 	};
410 	unsigned long phys;
411 
412 	INIT_LIST_HEAD(&res->list);
413 	phys = gen_pool_alloc_algo(cxl_mock_pool, size,
414 				   gen_pool_first_fit_align, &data);
415 	if (!phys)
416 		return NULL;
417 
418 	res->range = (struct range) {
419 		.start = phys,
420 		.end = phys + size - 1,
421 	};
422 	mutex_lock(&mock_res_lock);
423 	list_add(&res->list, &mock_res);
424 	mutex_unlock(&mock_res_lock);
425 
426 	return res;
427 }
428 
429 static int populate_cedt(void)
430 {
431 	struct cxl_mock_res *res;
432 	int i;
433 
434 	for (i = 0; i < ARRAY_SIZE(mock_cedt.chbs); i++) {
435 		struct acpi_cedt_chbs *chbs = &mock_cedt.chbs[i];
436 		resource_size_t size;
437 
438 		if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL20)
439 			size = ACPI_CEDT_CHBS_LENGTH_CXL20;
440 		else
441 			size = ACPI_CEDT_CHBS_LENGTH_CXL11;
442 
443 		res = alloc_mock_res(size, size);
444 		if (!res)
445 			return -ENOMEM;
446 		chbs->base = res->range.start;
447 		chbs->length = size;
448 	}
449 
450 	for (i = cfmws_start; i <= cfmws_end; i++) {
451 		struct acpi_cedt_cfmws *window = mock_cfmws[i];
452 
453 		res = alloc_mock_res(window->window_size, SZ_256M);
454 		if (!res)
455 			return -ENOMEM;
456 		window->base_hpa = res->range.start;
457 	}
458 
459 	return 0;
460 }
461 
462 static bool is_mock_port(struct device *dev);
463 
464 /*
465  * WARNING, this hack assumes the format of 'struct cxl_cfmws_context'
466  * and 'struct cxl_chbs_context' share the property that the first
467  * struct member is a cxl_test device being probed by the cxl_acpi
468  * driver.
469  */
470 struct cxl_cedt_context {
471 	struct device *dev;
472 };
473 
474 static int mock_acpi_table_parse_cedt(enum acpi_cedt_type id,
475 				      acpi_tbl_entry_handler_arg handler_arg,
476 				      void *arg)
477 {
478 	struct cxl_cedt_context *ctx = arg;
479 	struct device *dev = ctx->dev;
480 	union acpi_subtable_headers *h;
481 	unsigned long end;
482 	int i;
483 
484 	if (!is_mock_port(dev) && !is_mock_dev(dev))
485 		return acpi_table_parse_cedt(id, handler_arg, arg);
486 
487 	if (id == ACPI_CEDT_TYPE_CHBS)
488 		for (i = 0; i < ARRAY_SIZE(mock_cedt.chbs); i++) {
489 			h = (union acpi_subtable_headers *)&mock_cedt.chbs[i];
490 			end = (unsigned long)&mock_cedt.chbs[i + 1];
491 			handler_arg(h, arg, end);
492 		}
493 
494 	if (id == ACPI_CEDT_TYPE_CFMWS)
495 		for (i = cfmws_start; i <= cfmws_end; i++) {
496 			h = (union acpi_subtable_headers *) mock_cfmws[i];
497 			end = (unsigned long) h + mock_cfmws[i]->header.length;
498 			handler_arg(h, arg, end);
499 		}
500 
501 	if (id == ACPI_CEDT_TYPE_CXIMS)
502 		for (i = 0; i < ARRAY_SIZE(mock_cxims); i++) {
503 			h = (union acpi_subtable_headers *)mock_cxims[i];
504 			end = (unsigned long)h + mock_cxims[i]->header.length;
505 			handler_arg(h, arg, end);
506 		}
507 
508 	return 0;
509 }
510 
511 static bool is_mock_bridge(struct device *dev)
512 {
513 	int i;
514 
515 	for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++)
516 		if (dev == &cxl_host_bridge[i]->dev)
517 			return true;
518 	for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++)
519 		if (dev == &cxl_hb_single[i]->dev)
520 			return true;
521 	for (i = 0; i < ARRAY_SIZE(cxl_rch); i++)
522 		if (dev == &cxl_rch[i]->dev)
523 			return true;
524 
525 	return false;
526 }
527 
528 static bool is_mock_port(struct device *dev)
529 {
530 	int i;
531 
532 	if (is_mock_bridge(dev))
533 		return true;
534 
535 	for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++)
536 		if (dev == &cxl_root_port[i]->dev)
537 			return true;
538 
539 	for (i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++)
540 		if (dev == &cxl_switch_uport[i]->dev)
541 			return true;
542 
543 	for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++)
544 		if (dev == &cxl_switch_dport[i]->dev)
545 			return true;
546 
547 	for (i = 0; i < ARRAY_SIZE(cxl_root_single); i++)
548 		if (dev == &cxl_root_single[i]->dev)
549 			return true;
550 
551 	for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++)
552 		if (dev == &cxl_swu_single[i]->dev)
553 			return true;
554 
555 	for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++)
556 		if (dev == &cxl_swd_single[i]->dev)
557 			return true;
558 
559 	if (is_cxl_memdev(dev))
560 		return is_mock_dev(dev->parent);
561 
562 	return false;
563 }
564 
565 static int host_bridge_index(struct acpi_device *adev)
566 {
567 	return adev - host_bridge;
568 }
569 
570 static struct acpi_device *find_host_bridge(acpi_handle handle)
571 {
572 	int i;
573 
574 	for (i = 0; i < ARRAY_SIZE(host_bridge); i++)
575 		if (handle == host_bridge[i].handle)
576 			return &host_bridge[i];
577 	return NULL;
578 }
579 
580 static acpi_status
581 mock_acpi_evaluate_integer(acpi_handle handle, acpi_string pathname,
582 			   struct acpi_object_list *arguments,
583 			   unsigned long long *data)
584 {
585 	struct acpi_device *adev = find_host_bridge(handle);
586 
587 	if (!adev || strcmp(pathname, METHOD_NAME__UID) != 0)
588 		return acpi_evaluate_integer(handle, pathname, arguments, data);
589 
590 	*data = host_bridge_index(adev);
591 	return AE_OK;
592 }
593 
594 static struct pci_bus mock_pci_bus[NR_BRIDGES];
595 static struct acpi_pci_root mock_pci_root[ARRAY_SIZE(mock_pci_bus)] = {
596 	[0] = {
597 		.bus = &mock_pci_bus[0],
598 	},
599 	[1] = {
600 		.bus = &mock_pci_bus[1],
601 	},
602 	[2] = {
603 		.bus = &mock_pci_bus[2],
604 	},
605 	[3] = {
606 		.bus = &mock_pci_bus[3],
607 	},
608 
609 };
610 
611 static bool is_mock_bus(struct pci_bus *bus)
612 {
613 	int i;
614 
615 	for (i = 0; i < ARRAY_SIZE(mock_pci_bus); i++)
616 		if (bus == &mock_pci_bus[i])
617 			return true;
618 	return false;
619 }
620 
621 static struct acpi_pci_root *mock_acpi_pci_find_root(acpi_handle handle)
622 {
623 	struct acpi_device *adev = find_host_bridge(handle);
624 
625 	if (!adev)
626 		return acpi_pci_find_root(handle);
627 	return &mock_pci_root[host_bridge_index(adev)];
628 }
629 
630 static struct cxl_hdm *mock_cxl_setup_hdm(struct cxl_port *port,
631 					  struct cxl_endpoint_dvsec_info *info)
632 {
633 	struct cxl_hdm *cxlhdm = devm_kzalloc(&port->dev, sizeof(*cxlhdm), GFP_KERNEL);
634 	struct device *dev = &port->dev;
635 
636 	if (!cxlhdm)
637 		return ERR_PTR(-ENOMEM);
638 
639 	cxlhdm->port = port;
640 	cxlhdm->interleave_mask = ~0U;
641 	cxlhdm->iw_cap_mask = ~0UL;
642 	dev_set_drvdata(dev, cxlhdm);
643 	return cxlhdm;
644 }
645 
646 struct target_map_ctx {
647 	u32 *target_map;
648 	int index;
649 	int target_count;
650 };
651 
652 static int map_targets(struct device *dev, void *data)
653 {
654 	struct platform_device *pdev = to_platform_device(dev);
655 	struct target_map_ctx *ctx = data;
656 
657 	ctx->target_map[ctx->index++] = pdev->id;
658 
659 	if (ctx->index > ctx->target_count) {
660 		dev_WARN_ONCE(dev, 1, "too many targets found?\n");
661 		return -ENXIO;
662 	}
663 
664 	return 0;
665 }
666 
667 static int mock_decoder_commit(struct cxl_decoder *cxld)
668 {
669 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
670 	int id = cxld->id;
671 
672 	if (cxld->flags & CXL_DECODER_F_ENABLE)
673 		return 0;
674 
675 	dev_dbg(&port->dev, "%s commit\n", dev_name(&cxld->dev));
676 	if (cxl_num_decoders_committed(port) != id) {
677 		dev_dbg(&port->dev,
678 			"%s: out of order commit, expected decoder%d.%d\n",
679 			dev_name(&cxld->dev), port->id,
680 			cxl_num_decoders_committed(port));
681 		return -EBUSY;
682 	}
683 
684 	port->commit_end++;
685 	cxld->flags |= CXL_DECODER_F_ENABLE;
686 
687 	return 0;
688 }
689 
690 static void mock_decoder_reset(struct cxl_decoder *cxld)
691 {
692 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
693 	int id = cxld->id;
694 
695 	if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
696 		return;
697 
698 	dev_dbg(&port->dev, "%s reset\n", dev_name(&cxld->dev));
699 	if (port->commit_end == id)
700 		cxl_port_commit_reap(cxld);
701 	else
702 		dev_dbg(&port->dev,
703 			"%s: out of order reset, expected decoder%d.%d\n",
704 			dev_name(&cxld->dev), port->id, port->commit_end);
705 	cxld->flags &= ~CXL_DECODER_F_ENABLE;
706 }
707 
708 static void default_mock_decoder(struct cxl_decoder *cxld)
709 {
710 	cxld->hpa_range = (struct range){
711 		.start = 0,
712 		.end = -1,
713 	};
714 
715 	cxld->interleave_ways = 1;
716 	cxld->interleave_granularity = 256;
717 	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
718 	cxld->commit = mock_decoder_commit;
719 	cxld->reset = mock_decoder_reset;
720 }
721 
722 static int first_decoder(struct device *dev, const void *data)
723 {
724 	struct cxl_decoder *cxld;
725 
726 	if (!is_switch_decoder(dev))
727 		return 0;
728 	cxld = to_cxl_decoder(dev);
729 	if (cxld->id == 0)
730 		return 1;
731 	return 0;
732 }
733 
734 static void mock_init_hdm_decoder(struct cxl_decoder *cxld)
735 {
736 	struct acpi_cedt_cfmws *window = mock_cfmws[0];
737 	struct platform_device *pdev = NULL;
738 	struct cxl_endpoint_decoder *cxled;
739 	struct cxl_switch_decoder *cxlsd;
740 	struct cxl_port *port, *iter;
741 	const int size = SZ_512M;
742 	struct cxl_memdev *cxlmd;
743 	struct cxl_dport *dport;
744 	struct device *dev;
745 	bool hb0 = false;
746 	u64 base;
747 	int i;
748 
749 	if (is_endpoint_decoder(&cxld->dev)) {
750 		cxled = to_cxl_endpoint_decoder(&cxld->dev);
751 		cxlmd = cxled_to_memdev(cxled);
752 		WARN_ON(!dev_is_platform(cxlmd->dev.parent));
753 		pdev = to_platform_device(cxlmd->dev.parent);
754 
755 		/* check is endpoint is attach to host-bridge0 */
756 		port = cxled_to_port(cxled);
757 		do {
758 			if (port->uport_dev == &cxl_host_bridge[0]->dev) {
759 				hb0 = true;
760 				break;
761 			}
762 			if (is_cxl_port(port->dev.parent))
763 				port = to_cxl_port(port->dev.parent);
764 			else
765 				port = NULL;
766 		} while (port);
767 		port = cxled_to_port(cxled);
768 	}
769 
770 	/*
771 	 * The first decoder on the first 2 devices on the first switch
772 	 * attached to host-bridge0 mock a fake / static RAM region. All
773 	 * other decoders are default disabled. Given the round robin
774 	 * assignment those devices are named cxl_mem.0, and cxl_mem.4.
775 	 *
776 	 * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
777 	 */
778 	if (!hb0 || pdev->id % 4 || pdev->id > 4 || cxld->id > 0) {
779 		default_mock_decoder(cxld);
780 		return;
781 	}
782 
783 	base = window->base_hpa;
784 	cxld->hpa_range = (struct range) {
785 		.start = base,
786 		.end = base + size - 1,
787 	};
788 
789 	cxld->interleave_ways = 2;
790 	eig_to_granularity(window->granularity, &cxld->interleave_granularity);
791 	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
792 	cxld->flags = CXL_DECODER_F_ENABLE;
793 	cxled->state = CXL_DECODER_STATE_AUTO;
794 	port->commit_end = cxld->id;
795 	devm_cxl_dpa_reserve(cxled, 0, size / cxld->interleave_ways, 0);
796 	cxld->commit = mock_decoder_commit;
797 	cxld->reset = mock_decoder_reset;
798 
799 	/*
800 	 * Now that endpoint decoder is set up, walk up the hierarchy
801 	 * and setup the switch and root port decoders targeting @cxlmd.
802 	 */
803 	iter = port;
804 	for (i = 0; i < 2; i++) {
805 		dport = iter->parent_dport;
806 		iter = dport->port;
807 		dev = device_find_child(&iter->dev, NULL, first_decoder);
808 		/*
809 		 * Ancestor ports are guaranteed to be enumerated before
810 		 * @port, and all ports have at least one decoder.
811 		 */
812 		if (WARN_ON(!dev))
813 			continue;
814 
815 		cxlsd = to_cxl_switch_decoder(dev);
816 		if (i == 0) {
817 			/* put cxl_mem.4 second in the decode order */
818 			if (pdev->id == 4) {
819 				cxlsd->target[1] = dport;
820 				cxld->target_map[1] = dport->port_id;
821 			} else {
822 				cxlsd->target[0] = dport;
823 				cxld->target_map[0] = dport->port_id;
824 			}
825 		} else {
826 			cxlsd->target[0] = dport;
827 			cxld->target_map[0] = dport->port_id;
828 		}
829 		cxld = &cxlsd->cxld;
830 		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
831 		cxld->flags = CXL_DECODER_F_ENABLE;
832 		iter->commit_end = 0;
833 		/*
834 		 * Switch targets 2 endpoints, while host bridge targets
835 		 * one root port
836 		 */
837 		if (i == 0)
838 			cxld->interleave_ways = 2;
839 		else
840 			cxld->interleave_ways = 1;
841 		cxld->interleave_granularity = 4096;
842 		cxld->hpa_range = (struct range) {
843 			.start = base,
844 			.end = base + size - 1,
845 		};
846 		put_device(dev);
847 	}
848 }
849 
850 static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
851 				       struct cxl_endpoint_dvsec_info *info)
852 {
853 	struct cxl_port *port = cxlhdm->port;
854 	struct cxl_port *parent_port = to_cxl_port(port->dev.parent);
855 	int target_count, i;
856 
857 	if (is_cxl_endpoint(port))
858 		target_count = 0;
859 	else if (is_cxl_root(parent_port))
860 		target_count = NR_CXL_ROOT_PORTS;
861 	else
862 		target_count = NR_CXL_SWITCH_PORTS;
863 
864 	for (i = 0; i < NR_CXL_PORT_DECODERS; i++) {
865 		struct target_map_ctx ctx = {
866 			.target_count = target_count,
867 		};
868 		struct cxl_decoder *cxld;
869 		int rc;
870 
871 		if (target_count) {
872 			struct cxl_switch_decoder *cxlsd;
873 
874 			cxlsd = cxl_switch_decoder_alloc(port, target_count);
875 			if (IS_ERR(cxlsd)) {
876 				dev_warn(&port->dev,
877 					 "Failed to allocate the decoder\n");
878 				return PTR_ERR(cxlsd);
879 			}
880 			cxld = &cxlsd->cxld;
881 		} else {
882 			struct cxl_endpoint_decoder *cxled;
883 
884 			cxled = cxl_endpoint_decoder_alloc(port);
885 
886 			if (IS_ERR(cxled)) {
887 				dev_warn(&port->dev,
888 					 "Failed to allocate the decoder\n");
889 				return PTR_ERR(cxled);
890 			}
891 			cxld = &cxled->cxld;
892 		}
893 
894 		ctx.target_map = cxld->target_map;
895 
896 		mock_init_hdm_decoder(cxld);
897 
898 		if (target_count) {
899 			rc = device_for_each_child(port->uport_dev, &ctx,
900 						   map_targets);
901 			if (rc) {
902 				put_device(&cxld->dev);
903 				return rc;
904 			}
905 		}
906 
907 		rc = cxl_decoder_add_locked(cxld);
908 		if (rc) {
909 			put_device(&cxld->dev);
910 			dev_err(&port->dev, "Failed to add decoder\n");
911 			return rc;
912 		}
913 
914 		rc = cxl_decoder_autoremove(&port->dev, cxld);
915 		if (rc)
916 			return rc;
917 		dev_dbg(&cxld->dev, "Added to port %s\n", dev_name(&port->dev));
918 	}
919 
920 	return 0;
921 }
922 
923 static int __mock_cxl_decoders_setup(struct cxl_port *port)
924 {
925 	struct cxl_hdm *cxlhdm;
926 
927 	cxlhdm = mock_cxl_setup_hdm(port, NULL);
928 	if (IS_ERR(cxlhdm)) {
929 		if (PTR_ERR(cxlhdm) != -ENODEV)
930 			dev_err(&port->dev, "Failed to map HDM decoder capability\n");
931 		return PTR_ERR(cxlhdm);
932 	}
933 
934 	return mock_cxl_enumerate_decoders(cxlhdm, NULL);
935 }
936 
937 static int mock_cxl_switch_port_decoders_setup(struct cxl_port *port)
938 {
939 	if (is_cxl_root(port) || is_cxl_endpoint(port))
940 		return -EOPNOTSUPP;
941 
942 	return __mock_cxl_decoders_setup(port);
943 }
944 
945 static int mock_cxl_endpoint_decoders_setup(struct cxl_port *port)
946 {
947 	if (!is_cxl_endpoint(port))
948 		return -EOPNOTSUPP;
949 
950 	return __mock_cxl_decoders_setup(port);
951 }
952 
953 static int get_port_array(struct cxl_port *port,
954 			  struct platform_device ***port_array,
955 			  int *port_array_size)
956 {
957 	struct platform_device **array;
958 	int array_size;
959 
960 	if (port->depth == 1) {
961 		if (is_multi_bridge(port->uport_dev)) {
962 			array_size = ARRAY_SIZE(cxl_root_port);
963 			array = cxl_root_port;
964 		} else if (is_single_bridge(port->uport_dev)) {
965 			array_size = ARRAY_SIZE(cxl_root_single);
966 			array = cxl_root_single;
967 		} else {
968 			dev_dbg(&port->dev, "%s: unknown bridge type\n",
969 				dev_name(port->uport_dev));
970 			return -ENXIO;
971 		}
972 	} else if (port->depth == 2) {
973 		struct cxl_port *parent = to_cxl_port(port->dev.parent);
974 
975 		if (is_multi_bridge(parent->uport_dev)) {
976 			array_size = ARRAY_SIZE(cxl_switch_dport);
977 			array = cxl_switch_dport;
978 		} else if (is_single_bridge(parent->uport_dev)) {
979 			array_size = ARRAY_SIZE(cxl_swd_single);
980 			array = cxl_swd_single;
981 		} else {
982 			dev_dbg(&port->dev, "%s: unknown bridge type\n",
983 				dev_name(port->uport_dev));
984 			return -ENXIO;
985 		}
986 	} else {
987 		dev_WARN_ONCE(&port->dev, 1, "unexpected depth %d\n",
988 			      port->depth);
989 		return -ENXIO;
990 	}
991 
992 	*port_array = array;
993 	*port_array_size = array_size;
994 
995 	return 0;
996 }
997 
998 static int mock_cxl_port_enumerate_dports(struct cxl_port *port)
999 {
1000 	struct platform_device **array;
1001 	int i, array_size;
1002 	int rc;
1003 
1004 	rc = get_port_array(port, &array, &array_size);
1005 	if (rc)
1006 		return rc;
1007 
1008 	for (i = 0; i < array_size; i++) {
1009 		struct platform_device *pdev = array[i];
1010 		struct cxl_dport *dport;
1011 
1012 		if (pdev->dev.parent != port->uport_dev) {
1013 			dev_dbg(&port->dev, "%s: mismatch parent %s\n",
1014 				dev_name(port->uport_dev),
1015 				dev_name(pdev->dev.parent));
1016 			continue;
1017 		}
1018 
1019 		dport = devm_cxl_add_dport(port, &pdev->dev, pdev->id,
1020 					   CXL_RESOURCE_NONE);
1021 
1022 		if (IS_ERR(dport))
1023 			return PTR_ERR(dport);
1024 	}
1025 
1026 	return 0;
1027 }
1028 
1029 static struct cxl_dport *mock_cxl_add_dport_by_dev(struct cxl_port *port,
1030 						   struct device *dport_dev)
1031 {
1032 	struct platform_device **array;
1033 	int rc, i, array_size;
1034 
1035 	rc = get_port_array(port, &array, &array_size);
1036 	if (rc)
1037 		return ERR_PTR(rc);
1038 
1039 	for (i = 0; i < array_size; i++) {
1040 		struct platform_device *pdev = array[i];
1041 
1042 		if (pdev->dev.parent != port->uport_dev) {
1043 			dev_dbg(&port->dev, "%s: mismatch parent %s\n",
1044 				dev_name(port->uport_dev),
1045 				dev_name(pdev->dev.parent));
1046 			continue;
1047 		}
1048 
1049 		if (&pdev->dev != dport_dev)
1050 			continue;
1051 
1052 		return devm_cxl_add_dport(port, &pdev->dev, pdev->id,
1053 					  CXL_RESOURCE_NONE);
1054 	}
1055 
1056 	return ERR_PTR(-ENODEV);
1057 }
1058 
1059 /*
1060  * Faking the cxl_dpa_perf for the memdev when appropriate.
1061  */
1062 static void dpa_perf_setup(struct cxl_port *endpoint, struct range *range,
1063 			   struct cxl_dpa_perf *dpa_perf)
1064 {
1065 	dpa_perf->qos_class = FAKE_QTG_ID;
1066 	dpa_perf->dpa_range = *range;
1067 	for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
1068 		dpa_perf->coord[i].read_latency = 500;
1069 		dpa_perf->coord[i].write_latency = 500;
1070 		dpa_perf->coord[i].read_bandwidth = 1000;
1071 		dpa_perf->coord[i].write_bandwidth = 1000;
1072 	}
1073 }
1074 
1075 static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
1076 {
1077 	struct cxl_root *cxl_root __free(put_cxl_root) =
1078 		find_cxl_root(port);
1079 	struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
1080 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
1081 	struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
1082 
1083 	if (!cxl_root)
1084 		return;
1085 
1086 	for (int i = 0; i < cxlds->nr_partitions; i++) {
1087 		struct resource *res = &cxlds->part[i].res;
1088 		struct cxl_dpa_perf *perf = &cxlds->part[i].perf;
1089 		struct range range = {
1090 			.start = res->start,
1091 			.end = res->end,
1092 		};
1093 
1094 		dpa_perf_setup(port, &range, perf);
1095 	}
1096 
1097 	cxl_memdev_update_perf(cxlmd);
1098 
1099 	/*
1100 	 * This function is here to only test the topology iterator. It serves
1101 	 * no other purpose.
1102 	 */
1103 	cxl_endpoint_get_perf_coordinates(port, ep_c);
1104 }
1105 
1106 static struct cxl_mock_ops cxl_mock_ops = {
1107 	.is_mock_adev = is_mock_adev,
1108 	.is_mock_bridge = is_mock_bridge,
1109 	.is_mock_bus = is_mock_bus,
1110 	.is_mock_port = is_mock_port,
1111 	.is_mock_dev = is_mock_dev,
1112 	.acpi_table_parse_cedt = mock_acpi_table_parse_cedt,
1113 	.acpi_evaluate_integer = mock_acpi_evaluate_integer,
1114 	.acpi_pci_find_root = mock_acpi_pci_find_root,
1115 	.devm_cxl_switch_port_decoders_setup = mock_cxl_switch_port_decoders_setup,
1116 	.devm_cxl_endpoint_decoders_setup = mock_cxl_endpoint_decoders_setup,
1117 	.devm_cxl_port_enumerate_dports = mock_cxl_port_enumerate_dports,
1118 	.cxl_endpoint_parse_cdat = mock_cxl_endpoint_parse_cdat,
1119 	.devm_cxl_add_dport_by_dev = mock_cxl_add_dport_by_dev,
1120 	.list = LIST_HEAD_INIT(cxl_mock_ops.list),
1121 };
1122 
1123 static void mock_companion(struct acpi_device *adev, struct device *dev)
1124 {
1125 	device_initialize(&adev->dev);
1126 	fwnode_init(&adev->fwnode, NULL);
1127 	dev->fwnode = &adev->fwnode;
1128 	adev->fwnode.dev = dev;
1129 }
1130 
1131 #ifndef SZ_64G
1132 #define SZ_64G (SZ_32G * 2)
1133 #endif
1134 
1135 static __init int cxl_rch_topo_init(void)
1136 {
1137 	int rc, i;
1138 
1139 	for (i = 0; i < ARRAY_SIZE(cxl_rch); i++) {
1140 		int idx = NR_CXL_HOST_BRIDGES + NR_CXL_SINGLE_HOST + i;
1141 		struct acpi_device *adev = &host_bridge[idx];
1142 		struct platform_device *pdev;
1143 
1144 		pdev = platform_device_alloc("cxl_host_bridge", idx);
1145 		if (!pdev)
1146 			goto err_bridge;
1147 
1148 		mock_companion(adev, &pdev->dev);
1149 		rc = platform_device_add(pdev);
1150 		if (rc) {
1151 			platform_device_put(pdev);
1152 			goto err_bridge;
1153 		}
1154 
1155 		cxl_rch[i] = pdev;
1156 		mock_pci_bus[idx].bridge = &pdev->dev;
1157 		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1158 				       "firmware_node");
1159 		if (rc)
1160 			goto err_bridge;
1161 	}
1162 
1163 	return 0;
1164 
1165 err_bridge:
1166 	for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
1167 		struct platform_device *pdev = cxl_rch[i];
1168 
1169 		if (!pdev)
1170 			continue;
1171 		sysfs_remove_link(&pdev->dev.kobj, "firmware_node");
1172 		platform_device_unregister(cxl_rch[i]);
1173 	}
1174 
1175 	return rc;
1176 }
1177 
1178 static void cxl_rch_topo_exit(void)
1179 {
1180 	int i;
1181 
1182 	for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
1183 		struct platform_device *pdev = cxl_rch[i];
1184 
1185 		if (!pdev)
1186 			continue;
1187 		sysfs_remove_link(&pdev->dev.kobj, "firmware_node");
1188 		platform_device_unregister(cxl_rch[i]);
1189 	}
1190 }
1191 
1192 static __init int cxl_single_topo_init(void)
1193 {
1194 	int i, rc;
1195 
1196 	for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++) {
1197 		struct acpi_device *adev =
1198 			&host_bridge[NR_CXL_HOST_BRIDGES + i];
1199 		struct platform_device *pdev;
1200 
1201 		pdev = platform_device_alloc("cxl_host_bridge",
1202 					     NR_CXL_HOST_BRIDGES + i);
1203 		if (!pdev)
1204 			goto err_bridge;
1205 
1206 		mock_companion(adev, &pdev->dev);
1207 		rc = platform_device_add(pdev);
1208 		if (rc) {
1209 			platform_device_put(pdev);
1210 			goto err_bridge;
1211 		}
1212 
1213 		cxl_hb_single[i] = pdev;
1214 		mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
1215 		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1216 				       "physical_node");
1217 		if (rc)
1218 			goto err_bridge;
1219 	}
1220 
1221 	for (i = 0; i < ARRAY_SIZE(cxl_root_single); i++) {
1222 		struct platform_device *bridge =
1223 			cxl_hb_single[i % ARRAY_SIZE(cxl_hb_single)];
1224 		struct platform_device *pdev;
1225 
1226 		pdev = platform_device_alloc("cxl_root_port",
1227 					     NR_MULTI_ROOT + i);
1228 		if (!pdev)
1229 			goto err_port;
1230 		pdev->dev.parent = &bridge->dev;
1231 
1232 		rc = platform_device_add(pdev);
1233 		if (rc) {
1234 			platform_device_put(pdev);
1235 			goto err_port;
1236 		}
1237 		cxl_root_single[i] = pdev;
1238 	}
1239 
1240 	for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
1241 		struct platform_device *root_port = cxl_root_single[i];
1242 		struct platform_device *pdev;
1243 
1244 		pdev = platform_device_alloc("cxl_switch_uport",
1245 					     NR_MULTI_ROOT + i);
1246 		if (!pdev)
1247 			goto err_uport;
1248 		pdev->dev.parent = &root_port->dev;
1249 
1250 		rc = platform_device_add(pdev);
1251 		if (rc) {
1252 			platform_device_put(pdev);
1253 			goto err_uport;
1254 		}
1255 		cxl_swu_single[i] = pdev;
1256 	}
1257 
1258 	for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
1259 		struct platform_device *uport =
1260 			cxl_swu_single[i % ARRAY_SIZE(cxl_swu_single)];
1261 		struct platform_device *pdev;
1262 
1263 		pdev = platform_device_alloc("cxl_switch_dport",
1264 					     i + NR_MEM_MULTI);
1265 		if (!pdev)
1266 			goto err_dport;
1267 		pdev->dev.parent = &uport->dev;
1268 
1269 		rc = platform_device_add(pdev);
1270 		if (rc) {
1271 			platform_device_put(pdev);
1272 			goto err_dport;
1273 		}
1274 		cxl_swd_single[i] = pdev;
1275 	}
1276 
1277 	return 0;
1278 
1279 err_dport:
1280 	for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
1281 		platform_device_unregister(cxl_swd_single[i]);
1282 err_uport:
1283 	for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
1284 		platform_device_unregister(cxl_swu_single[i]);
1285 err_port:
1286 	for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
1287 		platform_device_unregister(cxl_root_single[i]);
1288 err_bridge:
1289 	for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) {
1290 		struct platform_device *pdev = cxl_hb_single[i];
1291 
1292 		if (!pdev)
1293 			continue;
1294 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1295 		platform_device_unregister(cxl_hb_single[i]);
1296 	}
1297 
1298 	return rc;
1299 }
1300 
1301 static void cxl_single_topo_exit(void)
1302 {
1303 	int i;
1304 
1305 	for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
1306 		platform_device_unregister(cxl_swd_single[i]);
1307 	for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
1308 		platform_device_unregister(cxl_swu_single[i]);
1309 	for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
1310 		platform_device_unregister(cxl_root_single[i]);
1311 	for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) {
1312 		struct platform_device *pdev = cxl_hb_single[i];
1313 
1314 		if (!pdev)
1315 			continue;
1316 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1317 		platform_device_unregister(cxl_hb_single[i]);
1318 	}
1319 }
1320 
1321 static void cxl_mem_exit(void)
1322 {
1323 	int i;
1324 
1325 	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
1326 		platform_device_unregister(cxl_rcd[i]);
1327 	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
1328 		platform_device_unregister(cxl_mem_single[i]);
1329 	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
1330 		platform_device_unregister(cxl_mem[i]);
1331 }
1332 
1333 static int cxl_mem_init(void)
1334 {
1335 	int i, rc;
1336 
1337 	for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) {
1338 		struct platform_device *dport = cxl_switch_dport[i];
1339 		struct platform_device *pdev;
1340 
1341 		pdev = platform_device_alloc("cxl_mem", i);
1342 		if (!pdev)
1343 			goto err_mem;
1344 		pdev->dev.parent = &dport->dev;
1345 		set_dev_node(&pdev->dev, i % 2);
1346 
1347 		rc = platform_device_add(pdev);
1348 		if (rc) {
1349 			platform_device_put(pdev);
1350 			goto err_mem;
1351 		}
1352 		cxl_mem[i] = pdev;
1353 	}
1354 
1355 	for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
1356 		struct platform_device *dport = cxl_swd_single[i];
1357 		struct platform_device *pdev;
1358 
1359 		pdev = platform_device_alloc("cxl_mem", NR_MEM_MULTI + i);
1360 		if (!pdev)
1361 			goto err_single;
1362 		pdev->dev.parent = &dport->dev;
1363 		set_dev_node(&pdev->dev, i % 2);
1364 
1365 		rc = platform_device_add(pdev);
1366 		if (rc) {
1367 			platform_device_put(pdev);
1368 			goto err_single;
1369 		}
1370 		cxl_mem_single[i] = pdev;
1371 	}
1372 
1373 	for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
1374 		int idx = NR_MEM_MULTI + NR_MEM_SINGLE + i;
1375 		struct platform_device *rch = cxl_rch[i];
1376 		struct platform_device *pdev;
1377 
1378 		pdev = platform_device_alloc("cxl_rcd", idx);
1379 		if (!pdev)
1380 			goto err_rcd;
1381 		pdev->dev.parent = &rch->dev;
1382 		set_dev_node(&pdev->dev, i % 2);
1383 
1384 		rc = platform_device_add(pdev);
1385 		if (rc) {
1386 			platform_device_put(pdev);
1387 			goto err_rcd;
1388 		}
1389 		cxl_rcd[i] = pdev;
1390 	}
1391 
1392 	return 0;
1393 
1394 err_rcd:
1395 	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
1396 		platform_device_unregister(cxl_rcd[i]);
1397 err_single:
1398 	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
1399 		platform_device_unregister(cxl_mem_single[i]);
1400 err_mem:
1401 	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
1402 		platform_device_unregister(cxl_mem[i]);
1403 	return rc;
1404 }
1405 
1406 static __init int cxl_test_init(void)
1407 {
1408 	int rc, i;
1409 	struct range mappable;
1410 
1411 	cxl_acpi_test();
1412 	cxl_core_test();
1413 	cxl_mem_test();
1414 	cxl_pmem_test();
1415 	cxl_port_test();
1416 
1417 	register_cxl_mock_ops(&cxl_mock_ops);
1418 
1419 	cxl_mock_pool = gen_pool_create(ilog2(SZ_2M), NUMA_NO_NODE);
1420 	if (!cxl_mock_pool) {
1421 		rc = -ENOMEM;
1422 		goto err_gen_pool_create;
1423 	}
1424 	mappable = mhp_get_pluggable_range(true);
1425 
1426 	rc = gen_pool_add(cxl_mock_pool,
1427 			  min(iomem_resource.end + 1 - SZ_64G,
1428 			      mappable.end + 1 - SZ_64G),
1429 			  SZ_64G, NUMA_NO_NODE);
1430 	if (rc)
1431 		goto err_gen_pool_add;
1432 
1433 	if (interleave_arithmetic == 1) {
1434 		cfmws_start = CFMWS_XOR_ARRAY_START;
1435 		cfmws_end = CFMWS_XOR_ARRAY_END;
1436 	} else {
1437 		cfmws_start = CFMWS_MOD_ARRAY_START;
1438 		cfmws_end = CFMWS_MOD_ARRAY_END;
1439 	}
1440 
1441 	rc = populate_cedt();
1442 	if (rc)
1443 		goto err_populate;
1444 
1445 	for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) {
1446 		struct acpi_device *adev = &host_bridge[i];
1447 		struct platform_device *pdev;
1448 
1449 		pdev = platform_device_alloc("cxl_host_bridge", i);
1450 		if (!pdev)
1451 			goto err_bridge;
1452 
1453 		mock_companion(adev, &pdev->dev);
1454 		rc = platform_device_add(pdev);
1455 		if (rc) {
1456 			platform_device_put(pdev);
1457 			goto err_bridge;
1458 		}
1459 
1460 		cxl_host_bridge[i] = pdev;
1461 		mock_pci_bus[i].bridge = &pdev->dev;
1462 		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1463 				       "physical_node");
1464 		if (rc)
1465 			goto err_bridge;
1466 	}
1467 
1468 	for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) {
1469 		struct platform_device *bridge =
1470 			cxl_host_bridge[i % ARRAY_SIZE(cxl_host_bridge)];
1471 		struct platform_device *pdev;
1472 
1473 		pdev = platform_device_alloc("cxl_root_port", i);
1474 		if (!pdev)
1475 			goto err_port;
1476 		pdev->dev.parent = &bridge->dev;
1477 
1478 		rc = platform_device_add(pdev);
1479 		if (rc) {
1480 			platform_device_put(pdev);
1481 			goto err_port;
1482 		}
1483 		cxl_root_port[i] = pdev;
1484 	}
1485 
1486 	BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
1487 	for (i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++) {
1488 		struct platform_device *root_port = cxl_root_port[i];
1489 		struct platform_device *pdev;
1490 
1491 		pdev = platform_device_alloc("cxl_switch_uport", i);
1492 		if (!pdev)
1493 			goto err_uport;
1494 		pdev->dev.parent = &root_port->dev;
1495 
1496 		rc = platform_device_add(pdev);
1497 		if (rc) {
1498 			platform_device_put(pdev);
1499 			goto err_uport;
1500 		}
1501 		cxl_switch_uport[i] = pdev;
1502 	}
1503 
1504 	for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
1505 		struct platform_device *uport =
1506 			cxl_switch_uport[i % ARRAY_SIZE(cxl_switch_uport)];
1507 		struct platform_device *pdev;
1508 
1509 		pdev = platform_device_alloc("cxl_switch_dport", i);
1510 		if (!pdev)
1511 			goto err_dport;
1512 		pdev->dev.parent = &uport->dev;
1513 
1514 		rc = platform_device_add(pdev);
1515 		if (rc) {
1516 			platform_device_put(pdev);
1517 			goto err_dport;
1518 		}
1519 		cxl_switch_dport[i] = pdev;
1520 	}
1521 
1522 	rc = cxl_single_topo_init();
1523 	if (rc)
1524 		goto err_dport;
1525 
1526 	rc = cxl_rch_topo_init();
1527 	if (rc)
1528 		goto err_single;
1529 
1530 	cxl_acpi = platform_device_alloc("cxl_acpi", 0);
1531 	if (!cxl_acpi)
1532 		goto err_rch;
1533 
1534 	mock_companion(&acpi0017_mock, &cxl_acpi->dev);
1535 	acpi0017_mock.dev.bus = &platform_bus_type;
1536 
1537 	rc = platform_device_add(cxl_acpi);
1538 	if (rc)
1539 		goto err_root;
1540 
1541 	rc = cxl_mem_init();
1542 	if (rc)
1543 		goto err_root;
1544 
1545 	return 0;
1546 
1547 err_root:
1548 	platform_device_put(cxl_acpi);
1549 err_rch:
1550 	cxl_rch_topo_exit();
1551 err_single:
1552 	cxl_single_topo_exit();
1553 err_dport:
1554 	for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
1555 		platform_device_unregister(cxl_switch_dport[i]);
1556 err_uport:
1557 	for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
1558 		platform_device_unregister(cxl_switch_uport[i]);
1559 err_port:
1560 	for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
1561 		platform_device_unregister(cxl_root_port[i]);
1562 err_bridge:
1563 	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
1564 		struct platform_device *pdev = cxl_host_bridge[i];
1565 
1566 		if (!pdev)
1567 			continue;
1568 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1569 		platform_device_unregister(cxl_host_bridge[i]);
1570 	}
1571 err_populate:
1572 	depopulate_all_mock_resources();
1573 err_gen_pool_add:
1574 	gen_pool_destroy(cxl_mock_pool);
1575 err_gen_pool_create:
1576 	unregister_cxl_mock_ops(&cxl_mock_ops);
1577 	return rc;
1578 }
1579 
1580 static __exit void cxl_test_exit(void)
1581 {
1582 	int i;
1583 
1584 	cxl_mem_exit();
1585 	platform_device_unregister(cxl_acpi);
1586 	cxl_rch_topo_exit();
1587 	cxl_single_topo_exit();
1588 	for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
1589 		platform_device_unregister(cxl_switch_dport[i]);
1590 	for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
1591 		platform_device_unregister(cxl_switch_uport[i]);
1592 	for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
1593 		platform_device_unregister(cxl_root_port[i]);
1594 	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
1595 		struct platform_device *pdev = cxl_host_bridge[i];
1596 
1597 		if (!pdev)
1598 			continue;
1599 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1600 		platform_device_unregister(cxl_host_bridge[i]);
1601 	}
1602 	depopulate_all_mock_resources();
1603 	gen_pool_destroy(cxl_mock_pool);
1604 	unregister_cxl_mock_ops(&cxl_mock_ops);
1605 }
1606 
1607 module_param(interleave_arithmetic, int, 0444);
1608 MODULE_PARM_DESC(interleave_arithmetic, "Modulo:0, XOR:1");
1609 module_init(cxl_test_init);
1610 module_exit(cxl_test_exit);
1611 MODULE_LICENSE("GPL v2");
1612 MODULE_DESCRIPTION("cxl_test: setup module");
1613 MODULE_IMPORT_NS("ACPI");
1614 MODULE_IMPORT_NS("CXL");
1615