xref: /linux/tools/testing/cxl/test/cxl.c (revision 920f27122cbacfd3b540a3f2f67b0145203d5581)
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 static bool extended_linear_cache;
19 static bool fail_autoassemble;
20 static bool type2_test;
21 
22 #define FAKE_QTG_ID	42
23 
24 #define NR_CXL_HOST_BRIDGES 2
25 #define NR_CXL_SINGLE_HOST 1
26 #define NR_CXL_RCH 1
27 #define NR_CXL_ROOT_PORTS 2
28 #define NR_CXL_SWITCH_PORTS 2
29 #define NR_CXL_PORT_DECODERS 8
30 #define NR_BRIDGES (NR_CXL_HOST_BRIDGES + NR_CXL_SINGLE_HOST + NR_CXL_RCH)
31 #define NR_CXL_TYPE2_ACCEL 1
32 
33 #define MOCK_AUTO_REGION_SIZE_DEFAULT SZ_512M
34 static int mock_auto_region_size = MOCK_AUTO_REGION_SIZE_DEFAULT;
35 
36 static struct platform_device *cxl_acpi;
37 static struct platform_device *cxl_host_bridge[NR_CXL_HOST_BRIDGES];
38 #define NR_MULTI_ROOT (NR_CXL_HOST_BRIDGES * NR_CXL_ROOT_PORTS)
39 static struct platform_device *cxl_root_port[NR_MULTI_ROOT];
40 static struct platform_device *cxl_switch_uport[NR_MULTI_ROOT];
41 #define NR_MEM_MULTI \
42 	(NR_CXL_HOST_BRIDGES * NR_CXL_ROOT_PORTS * NR_CXL_SWITCH_PORTS)
43 static struct platform_device *cxl_switch_dport[NR_MEM_MULTI];
44 
45 static struct platform_device *cxl_hb_single[NR_CXL_SINGLE_HOST];
46 static struct platform_device *cxl_root_single[NR_CXL_SINGLE_HOST];
47 static struct platform_device *cxl_swu_single[NR_CXL_SINGLE_HOST];
48 #define NR_MEM_SINGLE (NR_CXL_SINGLE_HOST * NR_CXL_SWITCH_PORTS)
49 static struct platform_device *cxl_swd_single[NR_MEM_SINGLE];
50 
51 struct platform_device *cxl_mem[NR_MEM_MULTI];
52 struct platform_device *cxl_mem_single[NR_MEM_SINGLE];
53 
54 static struct platform_device *cxl_rch[NR_CXL_RCH];
55 static struct platform_device *cxl_rcd[NR_CXL_RCH];
56 
57 /*
58  * Decoder registry
59  *
60  * Record decoder programming so that the topology can be reconstructed
61  * after cxl_acpi unbind/bind. This allows a user-created region config
62  * to be replayed as if firmware had provided the region at enumeration
63  * time.
64  *
65  * Entries are keyed by a stable port identity (port->uport_dev) combined
66  * with the decoder id. Decoder state is saved at initialization and
67  * updated on commit and reset.
68  *
69  * On re-enumeration mock_init_hdm_decoder() consults this registry to
70  * restore enabled decoders. Disabled decoders are reinitialized to a
71  * clean default state rather than replaying stale programming.
72  */
73 static DEFINE_XARRAY(decoder_registry);
74 
75 /*
76  * When set, decoder reset will not update the registry. This allows
77  * region destroy operations to reset live decoders without erasing
78  * the saved programming needed for replay after re-enumeration.
79  */
80 static bool decoder_reset_preserve_registry;
81 
is_multi_bridge(struct device * dev)82 static inline bool is_multi_bridge(struct device *dev)
83 {
84 	int i;
85 
86 	for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++)
87 		if (&cxl_host_bridge[i]->dev == dev)
88 			return true;
89 	return false;
90 }
91 
is_single_bridge(struct device * dev)92 static inline bool is_single_bridge(struct device *dev)
93 {
94 	int i;
95 
96 	for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++)
97 		if (&cxl_hb_single[i]->dev == dev)
98 			return true;
99 	return false;
100 }
101 
102 static struct acpi_device acpi0017_mock;
103 static struct acpi_device host_bridge[NR_BRIDGES] = {
104 	[0] = {
105 		.handle = &host_bridge[0],
106 		.pnp.unique_id = "0",
107 	},
108 	[1] = {
109 		.handle = &host_bridge[1],
110 		.pnp.unique_id = "1",
111 	},
112 	[2] = {
113 		.handle = &host_bridge[2],
114 		.pnp.unique_id = "2",
115 	},
116 	[3] = {
117 		.handle = &host_bridge[3],
118 		.pnp.unique_id = "3",
119 	},
120 };
121 
is_mock_dev(struct device * dev)122 static bool is_mock_dev(struct device *dev)
123 {
124 	int i;
125 
126 	for (i = 0; i < ARRAY_SIZE(cxl_mem); i++)
127 		if (dev == &cxl_mem[i]->dev)
128 			return true;
129 	for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++)
130 		if (dev == &cxl_mem_single[i]->dev)
131 			return true;
132 	for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++)
133 		if (dev == &cxl_rcd[i]->dev)
134 			return true;
135 	if (dev == &cxl_acpi->dev)
136 		return true;
137 	return false;
138 }
139 
is_mock_adev(struct acpi_device * adev)140 static bool is_mock_adev(struct acpi_device *adev)
141 {
142 	int i;
143 
144 	if (adev == &acpi0017_mock)
145 		return true;
146 
147 	for (i = 0; i < ARRAY_SIZE(host_bridge); i++)
148 		if (adev == &host_bridge[i])
149 			return true;
150 
151 	return false;
152 }
153 
154 static struct {
155 	struct acpi_table_cedt cedt;
156 	struct acpi_cedt_chbs chbs[NR_BRIDGES];
157 	struct {
158 		struct acpi_cedt_cfmws cfmws;
159 		u32 target[1];
160 	} cfmws0;
161 	struct {
162 		struct acpi_cedt_cfmws cfmws;
163 		u32 target[2];
164 	} cfmws1;
165 	struct {
166 		struct acpi_cedt_cfmws cfmws;
167 		u32 target[1];
168 	} cfmws2;
169 	struct {
170 		struct acpi_cedt_cfmws cfmws;
171 		u32 target[2];
172 	} cfmws3;
173 	struct {
174 		struct acpi_cedt_cfmws cfmws;
175 		u32 target[1];
176 	} cfmws4;
177 	struct {
178 		struct acpi_cedt_cfmws cfmws;
179 		u32 target[1];
180 	} cfmws5;
181 	struct {
182 		struct acpi_cedt_cfmws cfmws;
183 		u32 target[1];
184 	} cfmws6;
185 	struct {
186 		struct acpi_cedt_cfmws cfmws;
187 		u32 target[2];
188 	} cfmws7;
189 	struct {
190 		struct acpi_cedt_cfmws cfmws;
191 		u32 target[3];
192 	} cfmws8;
193 	struct {
194 		struct acpi_cedt_cxims cxims;
195 		u64 xormap_list[2];
196 	} cxims0;
197 } __packed mock_cedt = {
198 	.cedt = {
199 		.header = {
200 			.signature = "CEDT",
201 			.length = sizeof(mock_cedt),
202 			.revision = 1,
203 		},
204 	},
205 	.chbs[0] = {
206 		.header = {
207 			.type = ACPI_CEDT_TYPE_CHBS,
208 			.length = sizeof(mock_cedt.chbs[0]),
209 		},
210 		.uid = 0,
211 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20,
212 	},
213 	.chbs[1] = {
214 		.header = {
215 			.type = ACPI_CEDT_TYPE_CHBS,
216 			.length = sizeof(mock_cedt.chbs[0]),
217 		},
218 		.uid = 1,
219 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20,
220 	},
221 	.chbs[2] = {
222 		.header = {
223 			.type = ACPI_CEDT_TYPE_CHBS,
224 			.length = sizeof(mock_cedt.chbs[0]),
225 		},
226 		.uid = 2,
227 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL20,
228 	},
229 	.chbs[3] = {
230 		.header = {
231 			.type = ACPI_CEDT_TYPE_CHBS,
232 			.length = sizeof(mock_cedt.chbs[0]),
233 		},
234 		.uid = 3,
235 		.cxl_version = ACPI_CEDT_CHBS_VERSION_CXL11,
236 	},
237 	.cfmws0 = {
238 		.cfmws = {
239 			.header = {
240 				.type = ACPI_CEDT_TYPE_CFMWS,
241 				.length = sizeof(mock_cedt.cfmws0),
242 			},
243 			.interleave_ways = 0,
244 			.granularity = 4,
245 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
246 					ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
247 			.qtg_id = FAKE_QTG_ID,
248 			.window_size = SZ_256M * 4UL,
249 		},
250 		.target = { 0 },
251 	},
252 	.cfmws1 = {
253 		.cfmws = {
254 			.header = {
255 				.type = ACPI_CEDT_TYPE_CFMWS,
256 				.length = sizeof(mock_cedt.cfmws1),
257 			},
258 			.interleave_ways = 1,
259 			.granularity = 4,
260 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
261 					ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
262 			.qtg_id = FAKE_QTG_ID,
263 			.window_size = SZ_256M * 8UL,
264 		},
265 		.target = { 0, 1, },
266 	},
267 	.cfmws2 = {
268 		.cfmws = {
269 			.header = {
270 				.type = ACPI_CEDT_TYPE_CFMWS,
271 				.length = sizeof(mock_cedt.cfmws2),
272 			},
273 			.interleave_ways = 0,
274 			.granularity = 4,
275 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
276 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
277 			.qtg_id = FAKE_QTG_ID,
278 			.window_size = SZ_256M * 4UL,
279 		},
280 		.target = { 0 },
281 	},
282 	.cfmws3 = {
283 		.cfmws = {
284 			.header = {
285 				.type = ACPI_CEDT_TYPE_CFMWS,
286 				.length = sizeof(mock_cedt.cfmws3),
287 			},
288 			.interleave_ways = 1,
289 			.granularity = 4,
290 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
291 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
292 			.qtg_id = FAKE_QTG_ID,
293 			.window_size = SZ_256M * 8UL,
294 		},
295 		.target = { 0, 1, },
296 	},
297 	.cfmws4 = {
298 		.cfmws = {
299 			.header = {
300 				.type = ACPI_CEDT_TYPE_CFMWS,
301 				.length = sizeof(mock_cedt.cfmws4),
302 			},
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 * 4UL,
309 		},
310 		.target = { 2 },
311 	},
312 	.cfmws5 = {
313 		.cfmws = {
314 			.header = {
315 				.type = ACPI_CEDT_TYPE_CFMWS,
316 				.length = sizeof(mock_cedt.cfmws5),
317 			},
318 			.interleave_ways = 0,
319 			.granularity = 4,
320 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
321 					ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
322 			.qtg_id = FAKE_QTG_ID,
323 			.window_size = SZ_256M > PMD_SIZE ? SZ_256M : PMD_SIZE,
324 		},
325 		.target = { 3 },
326 	},
327 	/* .cfmws6,7,8 use ACPI_CEDT_CFMWS_ARITHMETIC_XOR */
328 	.cfmws6 = {
329 		.cfmws = {
330 			.header = {
331 				.type = ACPI_CEDT_TYPE_CFMWS,
332 				.length = sizeof(mock_cedt.cfmws6),
333 			},
334 			.interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
335 			.interleave_ways = 0,
336 			.granularity = 4,
337 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
338 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
339 			.qtg_id = FAKE_QTG_ID,
340 			.window_size = SZ_256M * 8UL,
341 		},
342 		.target = { 0, },
343 	},
344 	.cfmws7 = {
345 		.cfmws = {
346 			.header = {
347 				.type = ACPI_CEDT_TYPE_CFMWS,
348 				.length = sizeof(mock_cedt.cfmws7),
349 			},
350 			.interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
351 			.interleave_ways = 1,
352 			.granularity = 0,
353 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
354 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
355 			.qtg_id = FAKE_QTG_ID,
356 			.window_size = SZ_256M * 8UL,
357 		},
358 		.target = { 0, 1, },
359 	},
360 	.cfmws8 = {
361 		.cfmws = {
362 			.header = {
363 				.type = ACPI_CEDT_TYPE_CFMWS,
364 				.length = sizeof(mock_cedt.cfmws8),
365 			},
366 			.interleave_arithmetic = ACPI_CEDT_CFMWS_ARITHMETIC_XOR,
367 			.interleave_ways = 8,
368 			.granularity = 1,
369 			.restrictions = ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM |
370 					ACPI_CEDT_CFMWS_RESTRICT_PMEM,
371 			.qtg_id = FAKE_QTG_ID,
372 			.window_size = SZ_512M * 6UL,
373 		},
374 		.target = { 0, 1, 2, },
375 	},
376 	.cxims0 = {
377 		.cxims = {
378 			.header = {
379 				.type = ACPI_CEDT_TYPE_CXIMS,
380 				.length = sizeof(mock_cedt.cxims0),
381 			},
382 			.hbig = 0,
383 			.nr_xormaps = 2,
384 		},
385 		.xormap_list = { 0x404100, 0x808200, },
386 	},
387 };
388 
389 static struct acpi_cedt_cfmws type2_cfmws0 = {
390 	.header = {
391 		.type = ACPI_CEDT_TYPE_CFMWS,
392 		.length = sizeof(mock_cedt.cfmws0),
393 	},
394 	.interleave_ways = 0,
395 	.granularity = 4,
396 	.restrictions = ACPI_CEDT_CFMWS_RESTRICT_DEVMEM |
397 			ACPI_CEDT_CFMWS_RESTRICT_VOLATILE,
398 	.qtg_id = FAKE_QTG_ID,
399 	.window_size = SZ_256M * 4,
400 };
401 
402 struct acpi_cedt_cfmws *mock_cfmws[] = {
403 	[0] = &mock_cedt.cfmws0.cfmws,
404 	[1] = &mock_cedt.cfmws1.cfmws,
405 	[2] = &mock_cedt.cfmws2.cfmws,
406 	[3] = &mock_cedt.cfmws3.cfmws,
407 	[4] = &mock_cedt.cfmws4.cfmws,
408 	[5] = &mock_cedt.cfmws5.cfmws,
409 	/* Modulo Math above, XOR Math below */
410 	[6] = &mock_cedt.cfmws6.cfmws,
411 	[7] = &mock_cedt.cfmws7.cfmws,
412 	[8] = &mock_cedt.cfmws8.cfmws,
413 };
414 
415 static int cfmws_start;
416 static int cfmws_end;
417 #define CFMWS_MOD_ARRAY_START 0
418 #define CFMWS_MOD_ARRAY_END   5
419 #define CFMWS_XOR_ARRAY_START 6
420 #define CFMWS_XOR_ARRAY_END   8
421 
422 struct acpi_cedt_cxims *mock_cxims[1] = {
423 	[0] = &mock_cedt.cxims0.cxims,
424 };
425 
426 struct cxl_mock_res {
427 	struct list_head list;
428 	struct range range;
429 };
430 
431 static LIST_HEAD(mock_res);
432 static DEFINE_MUTEX(mock_res_lock);
433 static struct gen_pool *cxl_mock_pool;
434 
depopulate_all_mock_resources(void)435 static void depopulate_all_mock_resources(void)
436 {
437 	struct cxl_mock_res *res, *_res;
438 
439 	mutex_lock(&mock_res_lock);
440 	list_for_each_entry_safe(res, _res, &mock_res, list) {
441 		gen_pool_free(cxl_mock_pool, res->range.start,
442 			      range_len(&res->range));
443 		list_del(&res->list);
444 		kfree(res);
445 	}
446 	mutex_unlock(&mock_res_lock);
447 }
448 
alloc_mock_res(resource_size_t size,int align)449 static struct cxl_mock_res *alloc_mock_res(resource_size_t size, int align)
450 {
451 	struct genpool_data_align data = {
452 		.align = align,
453 	};
454 	unsigned long phys;
455 
456 	struct cxl_mock_res *res __free(kfree) = kzalloc(sizeof(*res),
457 							 GFP_KERNEL);
458 	if (!res)
459 		return NULL;
460 
461 	INIT_LIST_HEAD(&res->list);
462 	phys = gen_pool_alloc_algo(cxl_mock_pool, size,
463 				   gen_pool_first_fit_align, &data);
464 	if (!phys)
465 		return NULL;
466 
467 	res->range = (struct range) {
468 		.start = phys,
469 		.end = phys + size - 1,
470 	};
471 	mutex_lock(&mock_res_lock);
472 	list_add(&res->list, &mock_res);
473 	mutex_unlock(&mock_res_lock);
474 
475 	return no_free_ptr(res);
476 }
477 
478 /* Only update CFMWS0 as this is used by the auto region. */
cfmws_elc_update(struct acpi_cedt_cfmws * window,int index)479 static void cfmws_elc_update(struct acpi_cedt_cfmws *window, int index)
480 {
481 	if (!extended_linear_cache)
482 		return;
483 
484 	if (index != 0)
485 		return;
486 
487 	/*
488 	 * The window size should be 2x of the CXL region size where half is
489 	 * DRAM and half is CXL
490 	 */
491 	window->window_size = mock_auto_region_size * 2;
492 }
493 
update_type2_cfmws(void)494 static void update_type2_cfmws(void)
495 {
496 	memcpy(&mock_cedt.cfmws0.cfmws, &type2_cfmws0, sizeof(type2_cfmws0));
497 }
498 
populate_cedt(void)499 static int populate_cedt(void)
500 {
501 	struct cxl_mock_res *res;
502 	int i;
503 
504 	for (i = 0; i < ARRAY_SIZE(mock_cedt.chbs); i++) {
505 		struct acpi_cedt_chbs *chbs = &mock_cedt.chbs[i];
506 		resource_size_t size;
507 
508 		if (chbs->cxl_version == ACPI_CEDT_CHBS_VERSION_CXL20)
509 			size = ACPI_CEDT_CHBS_LENGTH_CXL20;
510 		else
511 			size = ACPI_CEDT_CHBS_LENGTH_CXL11;
512 
513 		res = alloc_mock_res(size, size);
514 		if (!res)
515 			return -ENOMEM;
516 		chbs->base = res->range.start;
517 		chbs->length = size;
518 	}
519 
520 	if (type2_test)
521 		update_type2_cfmws();
522 
523 	for (i = cfmws_start; i <= cfmws_end; i++) {
524 		struct acpi_cedt_cfmws *window = mock_cfmws[i];
525 		int align = SZ_256M;
526 
527 		if (i == 0 && !type2_test)
528 			cfmws_elc_update(window, i);
529 		if (window->restrictions & ACPI_CEDT_CFMWS_RESTRICT_VOLATILE)
530 			align = max_t(int, SZ_256M, PMD_SIZE);
531 		res = alloc_mock_res(window->window_size, align);
532 		if (!res)
533 			return -ENOMEM;
534 		window->base_hpa = res->range.start;
535 	}
536 
537 	return 0;
538 }
539 
540 static bool is_mock_port(struct device *dev);
541 
542 /*
543  * WARNING, this hack assumes the format of 'struct cxl_cfmws_context'
544  * and 'struct cxl_chbs_context' share the property that the first
545  * struct member is a cxl_test device being probed by the cxl_acpi
546  * driver.
547  */
548 struct cxl_cedt_context {
549 	struct device *dev;
550 };
551 
mock_acpi_table_parse_cedt(enum acpi_cedt_type id,acpi_tbl_entry_handler_arg handler_arg,void * arg)552 static int mock_acpi_table_parse_cedt(enum acpi_cedt_type id,
553 				      acpi_tbl_entry_handler_arg handler_arg,
554 				      void *arg)
555 {
556 	struct cxl_cedt_context *ctx = arg;
557 	struct device *dev = ctx->dev;
558 	union acpi_subtable_headers *h;
559 	unsigned long end;
560 	int i;
561 
562 	if (!is_mock_port(dev) && !is_mock_dev(dev))
563 		return acpi_table_parse_cedt(id, handler_arg, arg);
564 
565 	if (id == ACPI_CEDT_TYPE_CHBS)
566 		for (i = 0; i < ARRAY_SIZE(mock_cedt.chbs); i++) {
567 			h = (union acpi_subtable_headers *)&mock_cedt.chbs[i];
568 			end = (unsigned long)&mock_cedt.chbs[i + 1];
569 			handler_arg(h, arg, end);
570 		}
571 
572 	if (id == ACPI_CEDT_TYPE_CFMWS)
573 		for (i = cfmws_start; i <= cfmws_end; i++) {
574 			h = (union acpi_subtable_headers *) mock_cfmws[i];
575 			end = (unsigned long) h + mock_cfmws[i]->header.length;
576 			handler_arg(h, arg, end);
577 		}
578 
579 	if (id == ACPI_CEDT_TYPE_CXIMS)
580 		for (i = 0; i < ARRAY_SIZE(mock_cxims); i++) {
581 			h = (union acpi_subtable_headers *)mock_cxims[i];
582 			end = (unsigned long)h + mock_cxims[i]->header.length;
583 			handler_arg(h, arg, end);
584 		}
585 
586 	return 0;
587 }
588 
is_mock_bridge(struct device * dev)589 static bool is_mock_bridge(struct device *dev)
590 {
591 	int i;
592 
593 	for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++)
594 		if (dev == &cxl_host_bridge[i]->dev)
595 			return true;
596 	for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++)
597 		if (dev == &cxl_hb_single[i]->dev)
598 			return true;
599 	for (i = 0; i < ARRAY_SIZE(cxl_rch); i++)
600 		if (dev == &cxl_rch[i]->dev)
601 			return true;
602 
603 	return false;
604 }
605 
is_mock_port(struct device * dev)606 static bool is_mock_port(struct device *dev)
607 {
608 	int i;
609 
610 	if (is_mock_bridge(dev))
611 		return true;
612 
613 	for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++)
614 		if (dev == &cxl_root_port[i]->dev)
615 			return true;
616 
617 	for (i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++)
618 		if (dev == &cxl_switch_uport[i]->dev)
619 			return true;
620 
621 	for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++)
622 		if (dev == &cxl_switch_dport[i]->dev)
623 			return true;
624 
625 	for (i = 0; i < ARRAY_SIZE(cxl_root_single); i++)
626 		if (dev == &cxl_root_single[i]->dev)
627 			return true;
628 
629 	for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++)
630 		if (dev == &cxl_swu_single[i]->dev)
631 			return true;
632 
633 	for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++)
634 		if (dev == &cxl_swd_single[i]->dev)
635 			return true;
636 
637 	if (is_cxl_memdev(dev))
638 		return is_mock_dev(dev->parent);
639 
640 	return false;
641 }
642 
host_bridge_index(struct acpi_device * adev)643 static int host_bridge_index(struct acpi_device *adev)
644 {
645 	return adev - host_bridge;
646 }
647 
find_host_bridge(acpi_handle handle)648 static struct acpi_device *find_host_bridge(acpi_handle handle)
649 {
650 	int i;
651 
652 	for (i = 0; i < ARRAY_SIZE(host_bridge); i++)
653 		if (handle == host_bridge[i].handle)
654 			return &host_bridge[i];
655 	return NULL;
656 }
657 
658 static acpi_status
mock_acpi_evaluate_integer(acpi_handle handle,acpi_string pathname,struct acpi_object_list * arguments,unsigned long long * data)659 mock_acpi_evaluate_integer(acpi_handle handle, acpi_string pathname,
660 			   struct acpi_object_list *arguments,
661 			   unsigned long long *data)
662 {
663 	struct acpi_device *adev = find_host_bridge(handle);
664 
665 	if (!adev || strcmp(pathname, METHOD_NAME__UID) != 0)
666 		return acpi_evaluate_integer(handle, pathname, arguments, data);
667 
668 	*data = host_bridge_index(adev);
669 	return AE_OK;
670 }
671 
672 static int
mock_hmat_get_extended_linear_cache_size(struct resource * backing_res,int nid,resource_size_t * cache_size)673 mock_hmat_get_extended_linear_cache_size(struct resource *backing_res,
674 					 int nid, resource_size_t *cache_size)
675 {
676 	struct acpi_cedt_cfmws *window = mock_cfmws[0];
677 	struct resource cfmws0_res =
678 		DEFINE_RES_MEM(window->base_hpa, window->window_size);
679 
680 	if (!extended_linear_cache ||
681 	    !resource_contains(&cfmws0_res, backing_res)) {
682 		return hmat_get_extended_linear_cache_size(backing_res,
683 							   nid, cache_size);
684 	}
685 
686 	*cache_size = mock_auto_region_size;
687 
688 	return 0;
689 }
690 
691 static struct pci_bus mock_pci_bus[NR_BRIDGES];
692 static struct acpi_pci_root mock_pci_root[ARRAY_SIZE(mock_pci_bus)] = {
693 	[0] = {
694 		.bus = &mock_pci_bus[0],
695 	},
696 	[1] = {
697 		.bus = &mock_pci_bus[1],
698 	},
699 	[2] = {
700 		.bus = &mock_pci_bus[2],
701 	},
702 	[3] = {
703 		.bus = &mock_pci_bus[3],
704 	},
705 
706 };
707 
is_mock_bus(struct pci_bus * bus)708 static bool is_mock_bus(struct pci_bus *bus)
709 {
710 	int i;
711 
712 	for (i = 0; i < ARRAY_SIZE(mock_pci_bus); i++)
713 		if (bus == &mock_pci_bus[i])
714 			return true;
715 	return false;
716 }
717 
mock_acpi_pci_find_root(acpi_handle handle)718 static struct acpi_pci_root *mock_acpi_pci_find_root(acpi_handle handle)
719 {
720 	struct acpi_device *adev = find_host_bridge(handle);
721 
722 	if (!adev)
723 		return acpi_pci_find_root(handle);
724 	return &mock_pci_root[host_bridge_index(adev)];
725 }
726 
mock_cxl_setup_hdm(struct cxl_port * port,struct cxl_endpoint_dvsec_info * info)727 static struct cxl_hdm *mock_cxl_setup_hdm(struct cxl_port *port,
728 					  struct cxl_endpoint_dvsec_info *info)
729 {
730 	struct cxl_hdm *cxlhdm = devm_kzalloc(&port->dev, sizeof(*cxlhdm), GFP_KERNEL);
731 	struct device *dev = &port->dev;
732 
733 	if (!cxlhdm)
734 		return ERR_PTR(-ENOMEM);
735 
736 	cxlhdm->port = port;
737 	cxlhdm->interleave_mask = ~0U;
738 	cxlhdm->iw_cap_mask = ~0UL;
739 	dev_set_drvdata(dev, cxlhdm);
740 	return cxlhdm;
741 }
742 
743 struct target_map_ctx {
744 	u32 *target_map;
745 	int index;
746 	int target_count;
747 };
748 
map_targets(struct device * dev,void * data)749 static int map_targets(struct device *dev, void *data)
750 {
751 	struct platform_device *pdev = to_platform_device(dev);
752 	struct target_map_ctx *ctx = data;
753 
754 	ctx->target_map[ctx->index++] = pdev->id;
755 
756 	if (ctx->index > ctx->target_count) {
757 		dev_WARN_ONCE(dev, 1, "too many targets found?\n");
758 		return -ENXIO;
759 	}
760 
761 	return 0;
762 }
763 
764 /*
765  * Build a stable registry key from the decoder's upstream port identity
766  * and decoder id.
767  *
768  * Decoder objects and cxl_port objects are reallocated on each enumeration,
769  * so their addresses cannot be used directly as replay keys. However,
770  * port->uport_dev is stable for a given topology across cxl_acpi unbind/bind
771  * in cxl_test, so use that as the port identity and pack the local decoder
772  * id into the low bits.
773  *
774  * The key is formed as:
775  *     ((unsigned long)port->uport_dev << 4) | cxld->id
776  *
777  * The low bits hold the decoder id (which must fit in 4 bits) while
778  * the remaining bits identify the upstream port. This key is only used
779  * within cxl_test to locate saved decoder state during replay.
780  */
cxld_registry_index(struct cxl_decoder * cxld)781 static unsigned long cxld_registry_index(struct cxl_decoder *cxld)
782 {
783 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
784 
785 	dev_WARN_ONCE(&port->dev, cxld->id >= 16,
786 		      "decoder id:%d out of range\n", cxld->id);
787 	return (((unsigned long)port->uport_dev) << 4) | cxld->id;
788 }
789 
790 struct cxl_test_decoder {
791 	union {
792 		struct cxl_switch_decoder cxlsd;
793 		struct cxl_endpoint_decoder cxled;
794 	};
795 	struct range dpa_range;
796 };
797 
cxld_registry_find(struct cxl_decoder * cxld)798 static struct cxl_test_decoder *cxld_registry_find(struct cxl_decoder *cxld)
799 {
800 	return xa_load(&decoder_registry, cxld_registry_index(cxld));
801 }
802 
803 #define dbg_cxld(port, msg, cxld)                                                       \
804 	do {                                                                            \
805 		struct cxl_decoder *___d = (cxld);                                      \
806 		dev_dbg((port)->uport_dev,                                              \
807 			"decoder%d: %s range: %#llx-%#llx iw: %d ig: %d flags: %#lx\n", \
808 			___d->id, msg, ___d->hpa_range.start,                           \
809 			___d->hpa_range.end + 1, ___d->interleave_ways,                 \
810 			___d->interleave_granularity, ___d->flags);                     \
811 	} while (0)
812 
813 static int mock_decoder_commit(struct cxl_decoder *cxld);
814 static void mock_decoder_reset(struct cxl_decoder *cxld);
815 static void init_disabled_mock_decoder(struct cxl_decoder *cxld);
816 
cxld_copy(struct cxl_decoder * a,struct cxl_decoder * b)817 static void cxld_copy(struct cxl_decoder *a, struct cxl_decoder *b)
818 {
819 	a->id = b->id;
820 	a->hpa_range = b->hpa_range;
821 	a->interleave_ways = b->interleave_ways;
822 	a->interleave_granularity = b->interleave_granularity;
823 	a->target_type = b->target_type;
824 	a->flags = b->flags;
825 	a->commit = mock_decoder_commit;
826 	a->reset = mock_decoder_reset;
827 }
828 
829 /*
830  * Restore decoder programming saved in the registry.
831  *
832  * Only decoders that were saved enabled are restored. Disabled decoders
833  * are left in their default inactive state so that stale programming is
834  * not resurrected after topology replay.
835  *
836  * For endpoint decoders this also restores the DPA reservation needed
837  * to reconstruct committed mappings.
838  */
cxld_registry_restore(struct cxl_decoder * cxld,struct cxl_test_decoder * td)839 static int cxld_registry_restore(struct cxl_decoder *cxld,
840 				 struct cxl_test_decoder *td)
841 {
842 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
843 	int rc;
844 
845 	if (is_switch_decoder(&cxld->dev)) {
846 		struct cxl_switch_decoder *cxlsd =
847 			to_cxl_switch_decoder(&cxld->dev);
848 
849 		if (!(td->cxlsd.cxld.flags & CXL_DECODER_F_ENABLE))
850 			return 0;
851 
852 		dbg_cxld(port, "restore", &td->cxlsd.cxld);
853 		cxld_copy(cxld, &td->cxlsd.cxld);
854 		WARN_ON(cxlsd->nr_targets != td->cxlsd.nr_targets);
855 
856 		/* Restore saved target intent; live dport binding happens later */
857 		for (int i = 0; i < cxlsd->nr_targets; i++) {
858 			cxlsd->target[i] = NULL;
859 			cxld->target_map[i] = td->cxlsd.cxld.target_map[i];
860 		}
861 
862 		port->commit_end = cxld->id;
863 
864 	} else {
865 		struct cxl_endpoint_decoder *cxled =
866 			to_cxl_endpoint_decoder(&cxld->dev);
867 
868 		if (!(td->cxled.cxld.flags & CXL_DECODER_F_ENABLE))
869 			return 0;
870 
871 		dbg_cxld(port, "restore", &td->cxled.cxld);
872 		cxld_copy(cxld, &td->cxled.cxld);
873 		cxled->state = td->cxled.state;
874 		cxled->skip = td->cxled.skip;
875 		if (range_len(&td->dpa_range)) {
876 			rc = devm_cxl_dpa_reserve(cxled, td->dpa_range.start,
877 						  range_len(&td->dpa_range),
878 						  td->cxled.skip);
879 			if (rc) {
880 				init_disabled_mock_decoder(cxld);
881 				return rc;
882 			}
883 		}
884 		port->commit_end = cxld->id;
885 	}
886 
887 	return 0;
888 }
889 
__cxld_registry_save(struct cxl_test_decoder * td,struct cxl_decoder * cxld)890 static void __cxld_registry_save(struct cxl_test_decoder *td,
891 				 struct cxl_decoder *cxld)
892 {
893 	if (is_switch_decoder(&cxld->dev)) {
894 		struct cxl_switch_decoder *cxlsd =
895 			to_cxl_switch_decoder(&cxld->dev);
896 
897 		cxld_copy(&td->cxlsd.cxld, cxld);
898 		td->cxlsd.nr_targets = cxlsd->nr_targets;
899 
900 		/* Save target port_id as a stable identify for the dport */
901 		for (int i = 0; i < cxlsd->nr_targets; i++) {
902 			struct cxl_dport *dport;
903 
904 			if (!cxlsd->target[i])
905 				continue;
906 
907 			dport = cxlsd->target[i];
908 			td->cxlsd.cxld.target_map[i] = dport->port_id;
909 		}
910 	} else {
911 		struct cxl_endpoint_decoder *cxled =
912 			to_cxl_endpoint_decoder(&cxld->dev);
913 
914 		cxld_copy(&td->cxled.cxld, cxld);
915 		td->cxled.state = cxled->state;
916 		td->cxled.skip = cxled->skip;
917 
918 		if (!(cxld->flags & CXL_DECODER_F_ENABLE)) {
919 			td->dpa_range.start = 0;
920 			td->dpa_range.end = -1;
921 		} else if (cxled->dpa_res) {
922 			td->dpa_range.start = cxled->dpa_res->start;
923 			td->dpa_range.end = cxled->dpa_res->end;
924 		} else {
925 			td->dpa_range.start = 0;
926 			td->dpa_range.end = -1;
927 		}
928 	}
929 }
930 
cxld_registry_save(struct cxl_test_decoder * td,struct cxl_decoder * cxld)931 static void cxld_registry_save(struct cxl_test_decoder *td,
932 			       struct cxl_decoder *cxld)
933 {
934 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
935 
936 	dbg_cxld(port, "save", cxld);
937 	__cxld_registry_save(td, cxld);
938 }
939 
cxld_registry_update(struct cxl_decoder * cxld)940 static void cxld_registry_update(struct cxl_decoder *cxld)
941 {
942 	struct cxl_test_decoder *td = cxld_registry_find(cxld);
943 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
944 
945 	if (WARN_ON_ONCE(!td))
946 		return;
947 
948 	dbg_cxld(port, "update", cxld);
949 	__cxld_registry_save(td, cxld);
950 }
951 
mock_decoder_commit(struct cxl_decoder * cxld)952 static int mock_decoder_commit(struct cxl_decoder *cxld)
953 {
954 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
955 	int id = cxld->id;
956 
957 	if (cxld->flags & CXL_DECODER_F_ENABLE)
958 		return 0;
959 
960 	dev_dbg(&port->dev, "%s commit\n", dev_name(&cxld->dev));
961 	if (cxl_num_decoders_committed(port) != id) {
962 		dev_dbg(&port->dev,
963 			"%s: out of order commit, expected decoder%d.%d\n",
964 			dev_name(&cxld->dev), port->id,
965 			cxl_num_decoders_committed(port));
966 		return -EBUSY;
967 	}
968 
969 	port->commit_end++;
970 	cxld->flags |= CXL_DECODER_F_ENABLE;
971 	if (is_endpoint_decoder(&cxld->dev)) {
972 		struct cxl_endpoint_decoder *cxled =
973 			to_cxl_endpoint_decoder(&cxld->dev);
974 
975 		cxled->state = CXL_DECODER_STATE_AUTO;
976 	}
977 	cxld_registry_update(cxld);
978 
979 	return 0;
980 }
981 
mock_decoder_reset(struct cxl_decoder * cxld)982 static void mock_decoder_reset(struct cxl_decoder *cxld)
983 {
984 	struct cxl_port *port = to_cxl_port(cxld->dev.parent);
985 	int id = cxld->id;
986 
987 	if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
988 		return;
989 
990 	dev_dbg(&port->dev, "%s reset\n", dev_name(&cxld->dev));
991 	if (port->commit_end == id)
992 		cxl_port_commit_reap(cxld);
993 	else
994 		dev_dbg(&port->dev,
995 			"%s: out of order reset, expected decoder%d.%d\n",
996 			dev_name(&cxld->dev), port->id, port->commit_end);
997 	cxld->flags &= ~CXL_DECODER_F_ENABLE;
998 
999 	if (is_endpoint_decoder(&cxld->dev)) {
1000 		struct cxl_endpoint_decoder *cxled =
1001 			to_cxl_endpoint_decoder(&cxld->dev);
1002 
1003 		cxled->state = CXL_DECODER_STATE_MANUAL;
1004 		cxled->skip = 0;
1005 	}
1006 	if (decoder_reset_preserve_registry)
1007 		dev_dbg(port->uport_dev, "decoder%d: skip registry update\n",
1008 			cxld->id);
1009 	else
1010 		cxld_registry_update(cxld);
1011 }
1012 
cxld_registry_new(struct cxl_decoder * cxld)1013 static struct cxl_test_decoder *cxld_registry_new(struct cxl_decoder *cxld)
1014 {
1015 	struct cxl_test_decoder *td __free(kfree) =
1016 		kzalloc(sizeof(*td), GFP_KERNEL);
1017 	unsigned long key = cxld_registry_index(cxld);
1018 
1019 	if (!td)
1020 		return NULL;
1021 
1022 	if (xa_insert(&decoder_registry, key, td, GFP_KERNEL)) {
1023 		WARN_ON(1);
1024 		return NULL;
1025 	}
1026 
1027 	cxld_registry_save(td, cxld);
1028 	return no_free_ptr(td);
1029 }
1030 
init_disabled_mock_decoder(struct cxl_decoder * cxld)1031 static void init_disabled_mock_decoder(struct cxl_decoder *cxld)
1032 {
1033 	cxld->hpa_range.start = 0;
1034 	cxld->hpa_range.end = -1;
1035 	cxld->interleave_ways = 1;
1036 	cxld->interleave_granularity = 0;
1037 	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
1038 	cxld->flags = 0;
1039 	cxld->commit = mock_decoder_commit;
1040 	cxld->reset = mock_decoder_reset;
1041 
1042 	if (is_switch_decoder(&cxld->dev)) {
1043 		struct cxl_switch_decoder *cxlsd =
1044 			to_cxl_switch_decoder(&cxld->dev);
1045 
1046 		for (int i = 0; i < cxlsd->nr_targets; i++) {
1047 			cxlsd->target[i] = NULL;
1048 			cxld->target_map[i] = 0;
1049 		}
1050 	} else {
1051 		struct cxl_endpoint_decoder *cxled =
1052 			to_cxl_endpoint_decoder(&cxld->dev);
1053 
1054 		cxled->state = CXL_DECODER_STATE_MANUAL;
1055 		cxled->skip = 0;
1056 	}
1057 }
1058 
default_mock_decoder(struct cxl_decoder * cxld)1059 static void default_mock_decoder(struct cxl_decoder *cxld)
1060 {
1061 	cxld->hpa_range = (struct range){
1062 		.start = 0,
1063 		.end = -1,
1064 	};
1065 
1066 	cxld->interleave_ways = 1;
1067 	cxld->interleave_granularity = 256;
1068 	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
1069 	cxld->commit = mock_decoder_commit;
1070 	cxld->reset = mock_decoder_reset;
1071 
1072 	WARN_ON_ONCE(!cxld_registry_new(cxld));
1073 }
1074 
first_decoder(struct device * dev,const void * data)1075 static int first_decoder(struct device *dev, const void *data)
1076 {
1077 	struct cxl_decoder *cxld;
1078 
1079 	if (!is_switch_decoder(dev))
1080 		return 0;
1081 	cxld = to_cxl_decoder(dev);
1082 	if (cxld->id == 0)
1083 		return 1;
1084 	return 0;
1085 }
1086 
1087 enum cxld_init_type {
1088 	MOCK_DECODER_INIT_DEFAULT,
1089 	MOCK_DECODER_INIT_SAVED,
1090 	MOCK_DECODER_INIT_TYPE3_AUTO,
1091 	MOCK_DECODER_INIT_TYPE2_AUTO,
1092 };
1093 
get_decoder_init_type(struct cxl_decoder * cxld,struct platform_device * pdev,bool hb0,struct cxl_test_decoder ** td)1094 static enum cxld_init_type get_decoder_init_type(struct cxl_decoder *cxld,
1095 						 struct platform_device *pdev,
1096 						 bool hb0,
1097 						 struct cxl_test_decoder **td)
1098 {
1099 	struct cxl_test_decoder *found_td = cxld_registry_find(cxld);
1100 
1101 	if (found_td) {
1102 		*td = found_td;
1103 		return MOCK_DECODER_INIT_SAVED;
1104 	}
1105 
1106 	*td = NULL;
1107 
1108 	/*
1109 	 * The first decoder on the first 2 devices on the first switch
1110 	 * attached to host-bridge0 mock a fake / static RAM region. All
1111 	 * other decoders are default disabled. Given the round robin
1112 	 * assignment those devices are named cxl_mem.0, and cxl_mem.4.
1113 	 *
1114 	 * See 'cxl list -BMPu -m cxl_mem.0,cxl_mem.4'
1115 	 */
1116 	if (!is_endpoint_decoder(&cxld->dev) || !hb0 || pdev->id % 4 ||
1117 	    pdev->id > 4 || cxld->id > 0)
1118 		return MOCK_DECODER_INIT_DEFAULT;
1119 
1120 	return type2_test ? MOCK_DECODER_INIT_TYPE2_AUTO :
1121 			    MOCK_DECODER_INIT_TYPE3_AUTO;
1122 }
1123 
mock_decoder_handle_saved(struct cxl_decoder * cxld,struct cxl_test_decoder * td)1124 static bool mock_decoder_handle_saved(struct cxl_decoder *cxld, struct cxl_test_decoder *td)
1125 {
1126 	bool enabled;
1127 
1128 	if (is_switch_decoder(&cxld->dev))
1129 		enabled = td->cxlsd.cxld.flags & CXL_DECODER_F_ENABLE;
1130 	else
1131 		enabled = td->cxled.cxld.flags & CXL_DECODER_F_ENABLE;
1132 
1133 	if (enabled)
1134 		return !cxld_registry_restore(cxld, td);
1135 
1136 	init_disabled_mock_decoder(cxld);
1137 	return false;
1138 }
1139 
mock_init_hdm_type2_cxled(struct cxl_endpoint_decoder * cxled,struct cxl_port * port)1140 static void mock_init_hdm_type2_cxled(struct cxl_endpoint_decoder *cxled,
1141 				      struct cxl_port *port)
1142 {
1143 	struct acpi_cedt_cfmws *window = mock_cfmws[0];
1144 	struct cxl_decoder *cxld = &cxled->cxld;
1145 	struct cxl_switch_decoder *cxlsd;
1146 	struct cxl_dport *dport;
1147 	struct cxl_port *root_port;
1148 	struct device *dev;
1149 	u64 base;
1150 
1151 	base = window->base_hpa;
1152 	cxld->hpa_range = (struct range) {
1153 		.start = base,
1154 		.end = base + mock_auto_region_size - 1,
1155 	};
1156 
1157 	cxld->interleave_ways = 1;
1158 	eig_to_granularity(window->granularity, &cxld->interleave_granularity);
1159 	cxld->target_type = CXL_DECODER_DEVMEM;
1160 	cxld->flags = CXL_DECODER_F_ENABLE;
1161 	cxled->state = CXL_DECODER_STATE_AUTO;
1162 	port->commit_end = cxld->id;
1163 	devm_cxl_dpa_reserve(cxled, 0,
1164 			     mock_auto_region_size / cxld->interleave_ways, 0);
1165 	cxld->commit = mock_decoder_commit;
1166 	cxld->reset = mock_decoder_reset;
1167 
1168 	WARN_ON_ONCE(!cxld_registry_new(cxld));
1169 	/*
1170 	 * Now that endpoint decoder is set up, walk up the hierarchy
1171 	 * and setup the root port decoder targeting @cxlmd.
1172 	 */
1173 	dport = port->parent_dport;
1174 	root_port = dport->port;
1175 	dev = device_find_child(&root_port->dev, NULL, first_decoder);
1176 	/*
1177 	 * Ancestor ports are guaranteed to be enumerated before
1178 	 * @port, and all ports have at least one decoder.
1179 	 */
1180 	if (WARN_ON(!dev))
1181 		return;
1182 
1183 	cxlsd = to_cxl_switch_decoder(dev);
1184 	cxld = &cxlsd->cxld;
1185 	cxld->target_type = CXL_DECODER_DEVMEM;
1186 	cxld->flags = CXL_DECODER_F_ENABLE;
1187 	root_port->commit_end = 0;
1188 	cxld->interleave_ways = 1;
1189 	cxld->interleave_granularity = 4096;
1190 	cxld->target_map[0] = dport->port_id;
1191 	cxld->hpa_range = (struct range) {
1192 		.start = base,
1193 		.end = base + mock_auto_region_size - 1,
1194 	};
1195 	cxld->commit = mock_decoder_commit;
1196 	cxld->reset = mock_decoder_reset;
1197 
1198 	/*
1199 	 * Only target_map[] is programmed above, mimicking
1200 	 * firmware. On real hardware target[] is populated as
1201 	 * dports enumerate, via update_decoder_targets(). The
1202 	 * mock's dports are already bound by now, so fire that
1203 	 * resolution explicitly here rather than stamping
1204 	 * target[] directly.
1205 	 */
1206 	cxl_port_update_decoder_targets(root_port, dport);
1207 
1208 	cxld_registry_update(cxld);
1209 	put_device(dev);
1210 }
1211 
mock_init_hdm_type3_cxled(struct cxl_endpoint_decoder * cxled,struct cxl_port * port,struct platform_device * pdev,bool hb0)1212 static void mock_init_hdm_type3_cxled(struct cxl_endpoint_decoder *cxled,
1213 				      struct cxl_port *port,
1214 				      struct platform_device *pdev,
1215 				      bool hb0)
1216 {
1217 	struct acpi_cedt_cfmws *window = mock_cfmws[0];
1218 	struct cxl_decoder *cxld = &cxled->cxld;
1219 	struct cxl_switch_decoder *cxlsd;
1220 	struct cxl_dport *dport;
1221 	struct cxl_port *iter;
1222 	struct device *dev;
1223 	u64 base;
1224 	int i;
1225 
1226 	/* Simulate missing cxl_mem.4 configuration */
1227 	if (hb0 && pdev->id == 4 && cxld->id == 0 && fail_autoassemble) {
1228 		default_mock_decoder(cxld);
1229 		return;
1230 	}
1231 
1232 	base = window->base_hpa;
1233 	if (extended_linear_cache)
1234 		base += mock_auto_region_size;
1235 	cxld->hpa_range = (struct range) {
1236 		.start = base,
1237 		.end = base + mock_auto_region_size - 1,
1238 	};
1239 
1240 	cxld->interleave_ways = 2;
1241 	eig_to_granularity(window->granularity, &cxld->interleave_granularity);
1242 	cxld->target_type = CXL_DECODER_HOSTONLYMEM;
1243 	cxld->flags = CXL_DECODER_F_ENABLE;
1244 	cxled->state = CXL_DECODER_STATE_AUTO;
1245 	port->commit_end = cxld->id;
1246 	devm_cxl_dpa_reserve(cxled, 0,
1247 			     mock_auto_region_size / cxld->interleave_ways, 0);
1248 	cxld->commit = mock_decoder_commit;
1249 	cxld->reset = mock_decoder_reset;
1250 
1251 	WARN_ON_ONCE(!cxld_registry_new(cxld));
1252 	/*
1253 	 * Now that endpoint decoder is set up, walk up the hierarchy
1254 	 * and setup the switch and root port decoders targeting @cxlmd.
1255 	 */
1256 	iter = port;
1257 	for (i = 0; i < 2; i++) {
1258 		dport = iter->parent_dport;
1259 		iter = dport->port;
1260 		dev = device_find_child(&iter->dev, NULL, first_decoder);
1261 		/*
1262 		 * Ancestor ports are guaranteed to be enumerated before
1263 		 * @port, and all ports have at least one decoder.
1264 		 */
1265 		if (WARN_ON(!dev))
1266 			continue;
1267 
1268 		cxlsd = to_cxl_switch_decoder(dev);
1269 		if (i == 0) {
1270 			/* put cxl_mem.4 second in the decode order */
1271 			if (pdev->id == 4)
1272 				cxlsd->cxld.target_map[1] = dport->port_id;
1273 			else
1274 				cxlsd->cxld.target_map[0] = dport->port_id;
1275 		} else {
1276 			cxlsd->cxld.target_map[0] = dport->port_id;
1277 		}
1278 		cxld = &cxlsd->cxld;
1279 		cxld->target_type = CXL_DECODER_HOSTONLYMEM;
1280 		cxld->flags = CXL_DECODER_F_ENABLE;
1281 		iter->commit_end = 0;
1282 		/*
1283 		 * Switch targets 2 endpoints, while host bridge targets
1284 		 * one root port
1285 		 */
1286 		if (i == 0)
1287 			cxld->interleave_ways = 2;
1288 		else
1289 			cxld->interleave_ways = 1;
1290 		cxld->interleave_granularity = 4096;
1291 		cxld->hpa_range = (struct range) {
1292 			.start = base,
1293 			.end = base + mock_auto_region_size - 1,
1294 		};
1295 		cxld->commit = mock_decoder_commit;
1296 		cxld->reset = mock_decoder_reset;
1297 
1298 		/*
1299 		 * Only target_map[] is programmed above, mimicking
1300 		 * firmware. On real hardware target[] is populated as
1301 		 * dports enumerate, via update_decoder_targets(). The
1302 		 * mock's dports are already bound by now, so fire that
1303 		 * resolution explicitly here rather than stamping
1304 		 * target[] directly.
1305 		 */
1306 		cxl_port_update_decoder_targets(iter, dport);
1307 
1308 		cxld_registry_update(cxld);
1309 		put_device(dev);
1310 	}
1311 }
1312 
1313 /*
1314  * Initialize a decoder during HDM enumeration.
1315  *
1316  * If a saved registry entry exists:
1317  *   - enabled decoders are restored from the saved programming
1318  *   - disabled decoders are initialized in a clean disabled state
1319  *
1320  * If no registry entry exists the decoder follows the normal mock
1321  * initialization path, including the special auto-region setup for
1322  * the first endpoints under host-bridge0.
1323  *
1324  * Returns true if decoder state was restored from the registry. In
1325  * that case the saved decode configuration (including target mapping)
1326  * has already been applied and the map_targets() is skipped.
1327  */
mock_init_hdm_decoder(struct cxl_decoder * cxld)1328 static bool mock_init_hdm_decoder(struct cxl_decoder *cxld)
1329 {
1330 	struct cxl_endpoint_decoder *cxled = NULL;
1331 	struct platform_device *pdev = NULL;
1332 	struct cxl_test_decoder *td;
1333 	struct cxl_memdev *cxlmd;
1334 	struct cxl_port *port;
1335 	bool hb0 = false;
1336 
1337 	if (is_endpoint_decoder(&cxld->dev)) {
1338 		cxled = to_cxl_endpoint_decoder(&cxld->dev);
1339 		cxlmd = cxled_to_memdev(cxled);
1340 		WARN_ON(!dev_is_platform(cxlmd->dev.parent));
1341 		pdev = to_platform_device(cxlmd->dev.parent);
1342 
1343 		/* check is endpoint is attach to host-bridge0 */
1344 		port = cxled_to_port(cxled);
1345 		do {
1346 			if (port->uport_dev == &cxl_host_bridge[0]->dev) {
1347 				hb0 = true;
1348 				break;
1349 			}
1350 			if (is_cxl_port(port->dev.parent))
1351 				port = to_cxl_port(port->dev.parent);
1352 			else
1353 				port = NULL;
1354 		} while (port);
1355 		port = cxled_to_port(cxled);
1356 	} else {
1357 		port = to_cxl_port(cxld->dev.parent);
1358 	}
1359 
1360 	switch (get_decoder_init_type(cxld, pdev, hb0, &td)) {
1361 	case MOCK_DECODER_INIT_SAVED:
1362 		if (WARN_ON(!td))
1363 			return false;
1364 		return mock_decoder_handle_saved(cxld, td);
1365 	case MOCK_DECODER_INIT_DEFAULT:
1366 		/*
1367 		 * The default path picks up all the decoders that are not
1368 		 * endpoint.
1369 		 */
1370 		default_mock_decoder(cxld);
1371 		return false;
1372 	case MOCK_DECODER_INIT_TYPE3_AUTO:
1373 		mock_init_hdm_type3_cxled(cxled, port, pdev, hb0);
1374 		return false;
1375 	case MOCK_DECODER_INIT_TYPE2_AUTO:
1376 		mock_init_hdm_type2_cxled(cxled, port);
1377 		return false;
1378 	default:
1379 		return false;
1380 	}
1381 	return false;
1382 }
1383 
mock_cxl_enumerate_decoders(struct cxl_hdm * cxlhdm,struct cxl_endpoint_dvsec_info * info)1384 static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
1385 				       struct cxl_endpoint_dvsec_info *info)
1386 {
1387 	struct cxl_port *port = cxlhdm->port;
1388 	struct cxl_port *parent_port = to_cxl_port(port->dev.parent);
1389 	int target_count, i;
1390 	bool restored;
1391 
1392 	if (is_cxl_endpoint(port))
1393 		target_count = 0;
1394 	else if (is_cxl_root(parent_port))
1395 		target_count = NR_CXL_ROOT_PORTS;
1396 	else
1397 		target_count = NR_CXL_SWITCH_PORTS;
1398 
1399 	for (i = 0; i < NR_CXL_PORT_DECODERS; i++) {
1400 		struct target_map_ctx ctx = {
1401 			.target_count = target_count,
1402 		};
1403 		struct cxl_decoder *cxld;
1404 		int rc;
1405 
1406 		if (target_count) {
1407 			struct cxl_switch_decoder *cxlsd;
1408 
1409 			cxlsd = cxl_switch_decoder_alloc(port, target_count);
1410 			if (IS_ERR(cxlsd)) {
1411 				dev_warn(&port->dev,
1412 					 "Failed to allocate the decoder\n");
1413 				return PTR_ERR(cxlsd);
1414 			}
1415 			cxld = &cxlsd->cxld;
1416 		} else {
1417 			struct cxl_endpoint_decoder *cxled;
1418 
1419 			cxled = cxl_endpoint_decoder_alloc(port);
1420 
1421 			if (IS_ERR(cxled)) {
1422 				dev_warn(&port->dev,
1423 					 "Failed to allocate the decoder\n");
1424 				return PTR_ERR(cxled);
1425 			}
1426 			cxld = &cxled->cxld;
1427 		}
1428 
1429 		ctx.target_map = cxld->target_map;
1430 		restored = mock_init_hdm_decoder(cxld);
1431 		if (target_count && !restored) {
1432 			rc = device_for_each_child(port->uport_dev, &ctx,
1433 						   map_targets);
1434 			if (rc) {
1435 				put_device(&cxld->dev);
1436 				return rc;
1437 			}
1438 		}
1439 
1440 		rc = cxl_decoder_add_locked(cxld);
1441 		if (rc) {
1442 			put_device(&cxld->dev);
1443 			dev_err(&port->dev, "Failed to add decoder\n");
1444 			return rc;
1445 		}
1446 
1447 		rc = cxl_decoder_autoremove(&port->dev, cxld);
1448 		if (rc)
1449 			return rc;
1450 		dev_dbg(&cxld->dev, "Added to port %s\n", dev_name(&port->dev));
1451 	}
1452 
1453 	return 0;
1454 }
1455 
__mock_cxl_decoders_setup(struct cxl_port * port)1456 static int __mock_cxl_decoders_setup(struct cxl_port *port)
1457 {
1458 	struct cxl_hdm *cxlhdm;
1459 
1460 	cxlhdm = mock_cxl_setup_hdm(port, NULL);
1461 	if (IS_ERR(cxlhdm)) {
1462 		if (PTR_ERR(cxlhdm) != -ENODEV)
1463 			dev_err(&port->dev, "Failed to map HDM decoder capability\n");
1464 		return PTR_ERR(cxlhdm);
1465 	}
1466 
1467 	return mock_cxl_enumerate_decoders(cxlhdm, NULL);
1468 }
1469 
mock_cxl_switch_port_decoders_setup(struct cxl_port * port)1470 static int mock_cxl_switch_port_decoders_setup(struct cxl_port *port)
1471 {
1472 	if (is_cxl_root(port) || is_cxl_endpoint(port))
1473 		return -EOPNOTSUPP;
1474 
1475 	return __mock_cxl_decoders_setup(port);
1476 }
1477 
mock_cxl_endpoint_decoders_setup(struct cxl_port * port)1478 static int mock_cxl_endpoint_decoders_setup(struct cxl_port *port)
1479 {
1480 	if (!is_cxl_endpoint(port))
1481 		return -EOPNOTSUPP;
1482 
1483 	return __mock_cxl_decoders_setup(port);
1484 }
1485 
get_port_array(struct cxl_port * port,struct platform_device *** port_array,int * port_array_size)1486 static int get_port_array(struct cxl_port *port,
1487 			  struct platform_device ***port_array,
1488 			  int *port_array_size)
1489 {
1490 	struct platform_device **array;
1491 	int array_size;
1492 
1493 	if (port->depth == 1) {
1494 		if (is_multi_bridge(port->uport_dev)) {
1495 			array_size = ARRAY_SIZE(cxl_root_port);
1496 			array = cxl_root_port;
1497 		} else if (is_single_bridge(port->uport_dev)) {
1498 			array_size = ARRAY_SIZE(cxl_root_single);
1499 			array = cxl_root_single;
1500 		} else {
1501 			dev_dbg(&port->dev, "%s: unknown bridge type\n",
1502 				dev_name(port->uport_dev));
1503 			return -ENXIO;
1504 		}
1505 	} else if (port->depth == 2) {
1506 		struct cxl_port *parent = to_cxl_port(port->dev.parent);
1507 
1508 		if (is_multi_bridge(parent->uport_dev)) {
1509 			array_size = ARRAY_SIZE(cxl_switch_dport);
1510 			array = cxl_switch_dport;
1511 		} else if (is_single_bridge(parent->uport_dev)) {
1512 			array_size = ARRAY_SIZE(cxl_swd_single);
1513 			array = cxl_swd_single;
1514 		} else {
1515 			dev_dbg(&port->dev, "%s: unknown bridge type\n",
1516 				dev_name(port->uport_dev));
1517 			return -ENXIO;
1518 		}
1519 	} else {
1520 		dev_WARN_ONCE(&port->dev, 1, "unexpected depth %d\n",
1521 			      port->depth);
1522 		return -ENXIO;
1523 	}
1524 
1525 	*port_array = array;
1526 	*port_array_size = array_size;
1527 
1528 	return 0;
1529 }
1530 
mock_cxl_add_dport_by_dev(struct cxl_port * port,struct device * dport_dev)1531 static struct cxl_dport *mock_cxl_add_dport_by_dev(struct cxl_port *port,
1532 						   struct device *dport_dev)
1533 {
1534 	struct platform_device **array;
1535 	int rc, i, array_size;
1536 
1537 	rc = get_port_array(port, &array, &array_size);
1538 	if (rc)
1539 		return ERR_PTR(rc);
1540 
1541 	for (i = 0; i < array_size; i++) {
1542 		struct platform_device *pdev = array[i];
1543 
1544 		if (pdev->dev.parent != port->uport_dev) {
1545 			dev_dbg(&port->dev, "%s: mismatch parent %s\n",
1546 				dev_name(port->uport_dev),
1547 				dev_name(pdev->dev.parent));
1548 			continue;
1549 		}
1550 
1551 		if (&pdev->dev != dport_dev)
1552 			continue;
1553 
1554 		return devm_cxl_add_dport(port, &pdev->dev, pdev->id,
1555 					  CXL_RESOURCE_NONE);
1556 	}
1557 
1558 	return ERR_PTR(-ENODEV);
1559 }
1560 
1561 /*
1562  * Faking the cxl_dpa_perf for the memdev when appropriate.
1563  */
dpa_perf_setup(struct cxl_port * endpoint,struct range * range,struct cxl_dpa_perf * dpa_perf)1564 static void dpa_perf_setup(struct cxl_port *endpoint, struct range *range,
1565 			   struct cxl_dpa_perf *dpa_perf)
1566 {
1567 	dpa_perf->qos_class = FAKE_QTG_ID;
1568 	dpa_perf->dpa_range = *range;
1569 	for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
1570 		dpa_perf->coord[i].read_latency = 500;
1571 		dpa_perf->coord[i].write_latency = 500;
1572 		dpa_perf->coord[i].read_bandwidth = 1000;
1573 		dpa_perf->coord[i].write_bandwidth = 1000;
1574 	}
1575 }
1576 
mock_cxl_endpoint_parse_cdat(struct cxl_port * port)1577 static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
1578 {
1579 	struct cxl_root *cxl_root __free(put_cxl_root) =
1580 		find_cxl_root(port);
1581 	struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
1582 	struct cxl_dev_state *cxlds = cxlmd->cxlds;
1583 	struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
1584 
1585 	if (!cxl_root)
1586 		return;
1587 
1588 	for (int i = 0; i < cxlds->nr_partitions; i++) {
1589 		struct resource *res = &cxlds->part[i].res;
1590 		struct cxl_dpa_perf *perf = &cxlds->part[i].perf;
1591 		struct range range = {
1592 			.start = res->start,
1593 			.end = res->end,
1594 		};
1595 
1596 		dpa_perf_setup(port, &range, perf);
1597 	}
1598 
1599 	cxl_memdev_update_perf(cxlmd);
1600 
1601 	/*
1602 	 * This function is here to only test the topology iterator. It serves
1603 	 * no other purpose.
1604 	 */
1605 	cxl_endpoint_get_perf_coordinates(port, ep_c);
1606 }
1607 
1608 /*
1609  * Simulate that the first half of mock CXL Window 0 is "Soft Reserve" capacity
1610  */
mock_walk_hmem_resources(struct device * host,walk_hmem_fn fn)1611 static int mock_walk_hmem_resources(struct device *host, walk_hmem_fn fn)
1612 {
1613 	struct acpi_cedt_cfmws *cfmws = mock_cfmws[0];
1614 	struct resource window =
1615 		DEFINE_RES_MEM(cfmws->base_hpa, cfmws->window_size / 2);
1616 
1617 	dev_dbg(host, "walk cxl_test resource: %pr\n", &window);
1618 	return fn(host, 0, &window);
1619 }
1620 
1621 /*
1622  * This should only be called by the dax_hmem case, treat mismatches (negative
1623  * result) as "fallback to base region_intersects()". Simulate that the first
1624  * half of mock CXL Window 0 is IORES_DESC_CXL capacity.
1625  */
mock_region_intersects(resource_size_t start,size_t size,unsigned long flags,unsigned long desc)1626 static int mock_region_intersects(resource_size_t start, size_t size,
1627 				  unsigned long flags, unsigned long desc)
1628 {
1629 	struct resource res = DEFINE_RES_MEM(start, size);
1630 	struct acpi_cedt_cfmws *cfmws = mock_cfmws[0];
1631 	struct resource window =
1632 		DEFINE_RES_MEM(cfmws->base_hpa, cfmws->window_size / 2);
1633 
1634 	if (resource_overlaps(&res, &window))
1635 		return REGION_INTERSECTS;
1636 	pr_debug("warning: no cxl_test CXL intersection for %pr\n", &res);
1637 	return -1;
1638 }
1639 
1640 
1641 static int
mock_region_intersects_soft_reserve(resource_size_t start,size_t size)1642 mock_region_intersects_soft_reserve(resource_size_t start, size_t size)
1643 {
1644 	struct resource res = DEFINE_RES_MEM(start, size);
1645 	struct acpi_cedt_cfmws *cfmws = mock_cfmws[0];
1646 	struct resource window =
1647 		DEFINE_RES_MEM(cfmws->base_hpa, cfmws->window_size / 2);
1648 
1649 	if (resource_overlaps(&res, &window))
1650 		return REGION_INTERSECTS;
1651 	pr_debug("warning: no cxl_test soft reserve intersection for %pr\n", &res);
1652 	return -1;
1653 }
1654 
1655 static struct cxl_mock_ops cxl_mock_ops = {
1656 	.is_mock_adev = is_mock_adev,
1657 	.is_mock_bridge = is_mock_bridge,
1658 	.is_mock_bus = is_mock_bus,
1659 	.is_mock_port = is_mock_port,
1660 	.is_mock_dev = is_mock_dev,
1661 	.acpi_table_parse_cedt = mock_acpi_table_parse_cedt,
1662 	.acpi_evaluate_integer = mock_acpi_evaluate_integer,
1663 	.acpi_pci_find_root = mock_acpi_pci_find_root,
1664 	.devm_cxl_switch_port_decoders_setup = mock_cxl_switch_port_decoders_setup,
1665 	.devm_cxl_endpoint_decoders_setup = mock_cxl_endpoint_decoders_setup,
1666 	.cxl_endpoint_parse_cdat = mock_cxl_endpoint_parse_cdat,
1667 	.devm_cxl_add_dport_by_dev = mock_cxl_add_dport_by_dev,
1668 	.hmat_get_extended_linear_cache_size =
1669 		mock_hmat_get_extended_linear_cache_size,
1670 	.walk_hmem_resources = mock_walk_hmem_resources,
1671 	.region_intersects = mock_region_intersects,
1672 	.region_intersects_soft_reserve = mock_region_intersects_soft_reserve,
1673 	.list = LIST_HEAD_INIT(cxl_mock_ops.list),
1674 };
1675 
mock_companion(struct acpi_device * adev,struct device * dev)1676 static void mock_companion(struct acpi_device *adev, struct device *dev)
1677 {
1678 	device_initialize(&adev->dev);
1679 	fwnode_init(&adev->fwnode, NULL);
1680 	dev->fwnode = &adev->fwnode;
1681 	adev->fwnode.dev = dev;
1682 }
1683 
1684 #ifndef SZ_64G
1685 #define SZ_64G (SZ_32G * 2)
1686 #endif
1687 
cxl_mock_platform_device_add(struct platform_device * pdev,struct platform_device ** ppdev)1688 static int cxl_mock_platform_device_add(struct platform_device *pdev,
1689 					struct platform_device **ppdev)
1690 {
1691 	int rc;
1692 
1693 	if (ppdev)
1694 		*ppdev = pdev;
1695 	rc = platform_device_add(pdev);
1696 	if (rc) {
1697 		platform_device_put(pdev);
1698 		if (ppdev)
1699 			*ppdev = NULL;
1700 	}
1701 
1702 	return rc;
1703 }
1704 
cxl_rch_topo_init(void)1705 static __init int cxl_rch_topo_init(void)
1706 {
1707 	int rc, i;
1708 
1709 	for (i = 0; i < ARRAY_SIZE(cxl_rch); i++) {
1710 		int idx = NR_CXL_HOST_BRIDGES + NR_CXL_SINGLE_HOST + i;
1711 		struct acpi_device *adev = &host_bridge[idx];
1712 		struct platform_device *pdev;
1713 
1714 		pdev = platform_device_alloc("cxl_host_bridge", idx);
1715 		if (!pdev) {
1716 			rc = -ENOMEM;
1717 			goto err_bridge;
1718 		}
1719 
1720 		mock_companion(adev, &pdev->dev);
1721 		rc = cxl_mock_platform_device_add(pdev, &cxl_rch[i]);
1722 		if (rc)
1723 			goto err_bridge;
1724 
1725 		mock_pci_bus[idx].bridge = &pdev->dev;
1726 		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1727 				       "firmware_node");
1728 		if (rc)
1729 			goto err_bridge;
1730 	}
1731 
1732 	return 0;
1733 
1734 err_bridge:
1735 	for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
1736 		struct platform_device *pdev = cxl_rch[i];
1737 
1738 		if (!pdev)
1739 			continue;
1740 		sysfs_remove_link(&pdev->dev.kobj, "firmware_node");
1741 		platform_device_unregister(cxl_rch[i]);
1742 	}
1743 
1744 	return rc;
1745 }
1746 
cxl_rch_topo_exit(void)1747 static void cxl_rch_topo_exit(void)
1748 {
1749 	int i;
1750 
1751 	for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
1752 		struct platform_device *pdev = cxl_rch[i];
1753 
1754 		if (!pdev)
1755 			continue;
1756 		sysfs_remove_link(&pdev->dev.kobj, "firmware_node");
1757 		platform_device_unregister(cxl_rch[i]);
1758 	}
1759 }
1760 
cxl_single_topo_init(void)1761 static __init int cxl_single_topo_init(void)
1762 {
1763 	int i, rc;
1764 
1765 	for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++) {
1766 		struct acpi_device *adev =
1767 			&host_bridge[NR_CXL_HOST_BRIDGES + i];
1768 		struct platform_device *pdev;
1769 
1770 		pdev = platform_device_alloc("cxl_host_bridge",
1771 					     NR_CXL_HOST_BRIDGES + i);
1772 		if (!pdev) {
1773 			rc = -ENOMEM;
1774 			goto err_bridge;
1775 		}
1776 
1777 		mock_companion(adev, &pdev->dev);
1778 		rc = cxl_mock_platform_device_add(pdev, &cxl_hb_single[i]);
1779 		if (rc)
1780 			goto err_bridge;
1781 
1782 		mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
1783 		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1784 				       "physical_node");
1785 		if (rc)
1786 			goto err_bridge;
1787 	}
1788 
1789 	for (i = 0; i < ARRAY_SIZE(cxl_root_single); i++) {
1790 		struct platform_device *bridge =
1791 			cxl_hb_single[i % ARRAY_SIZE(cxl_hb_single)];
1792 		struct platform_device *pdev;
1793 
1794 		pdev = platform_device_alloc("cxl_root_port",
1795 					     NR_MULTI_ROOT + i);
1796 		if (!pdev) {
1797 			rc = -ENOMEM;
1798 			goto err_port;
1799 		}
1800 		pdev->dev.parent = &bridge->dev;
1801 
1802 		rc = cxl_mock_platform_device_add(pdev, &cxl_root_single[i]);
1803 		if (rc)
1804 			goto err_port;
1805 	}
1806 
1807 	for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
1808 		struct platform_device *root_port = cxl_root_single[i];
1809 		struct platform_device *pdev;
1810 
1811 		pdev = platform_device_alloc("cxl_switch_uport",
1812 					     NR_MULTI_ROOT + i);
1813 		if (!pdev) {
1814 			rc = -ENOMEM;
1815 			goto err_uport;
1816 		}
1817 		pdev->dev.parent = &root_port->dev;
1818 
1819 		rc = cxl_mock_platform_device_add(pdev, &cxl_swu_single[i]);
1820 		if (rc)
1821 			goto err_uport;
1822 	}
1823 
1824 	for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
1825 		struct platform_device *uport =
1826 			cxl_swu_single[i % ARRAY_SIZE(cxl_swu_single)];
1827 		struct platform_device *pdev;
1828 
1829 		pdev = platform_device_alloc("cxl_switch_dport",
1830 					     i + NR_MEM_MULTI);
1831 		if (!pdev) {
1832 			rc = -ENOMEM;
1833 			goto err_dport;
1834 		}
1835 		pdev->dev.parent = &uport->dev;
1836 
1837 		rc = cxl_mock_platform_device_add(pdev, &cxl_swd_single[i]);
1838 		if (rc)
1839 			goto err_dport;
1840 	}
1841 
1842 	return 0;
1843 
1844 err_dport:
1845 	for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
1846 		platform_device_unregister(cxl_swd_single[i]);
1847 err_uport:
1848 	for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
1849 		platform_device_unregister(cxl_swu_single[i]);
1850 err_port:
1851 	for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
1852 		platform_device_unregister(cxl_root_single[i]);
1853 err_bridge:
1854 	for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) {
1855 		struct platform_device *pdev = cxl_hb_single[i];
1856 
1857 		if (!pdev)
1858 			continue;
1859 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1860 		platform_device_unregister(cxl_hb_single[i]);
1861 	}
1862 
1863 	return rc;
1864 }
1865 
cxl_single_topo_exit(void)1866 static void cxl_single_topo_exit(void)
1867 {
1868 	int i;
1869 
1870 	for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
1871 		platform_device_unregister(cxl_swd_single[i]);
1872 	for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
1873 		platform_device_unregister(cxl_swu_single[i]);
1874 	for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
1875 		platform_device_unregister(cxl_root_single[i]);
1876 	for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) {
1877 		struct platform_device *pdev = cxl_hb_single[i];
1878 
1879 		if (!pdev)
1880 			continue;
1881 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1882 		platform_device_unregister(cxl_hb_single[i]);
1883 	}
1884 }
1885 
cxl_type3_mem_exit(void)1886 static void cxl_type3_mem_exit(void)
1887 {
1888 	struct platform_device *pdev;
1889 	int i;
1890 
1891 	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--) {
1892 		pdev = cxl_rcd[i];
1893 		if (!pdev)
1894 			continue;
1895 		platform_device_unregister(cxl_rcd[i]);
1896 	}
1897 
1898 	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--) {
1899 		pdev = cxl_mem_single[i];
1900 		if (!pdev)
1901 			continue;
1902 		platform_device_unregister(cxl_mem_single[i]);
1903 	}
1904 
1905 	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--) {
1906 		pdev = cxl_mem[i];
1907 		if (!pdev)
1908 			continue;
1909 		platform_device_unregister(pdev);
1910 	}
1911 }
1912 
cxl_type2_mem_exit(void)1913 static void cxl_type2_mem_exit(void)
1914 {
1915 	for (int i = NR_CXL_TYPE2_ACCEL - 1; i >= 0; i--) {
1916 		struct platform_device *pdev = cxl_mem[i];
1917 
1918 		if (!pdev)
1919 			continue;
1920 		platform_device_unregister(pdev);
1921 	}
1922 }
1923 
cxl_mem_exit(void)1924 static void cxl_mem_exit(void)
1925 {
1926 	if (type2_test) {
1927 		cxl_type2_mem_exit();
1928 		return;
1929 	}
1930 
1931 	cxl_type3_mem_exit();
1932 }
1933 
cxl_type2_mem_init(void)1934 static int cxl_type2_mem_init(void)
1935 {
1936 	int i, rc;
1937 
1938 	for (i = 0; i < NR_CXL_TYPE2_ACCEL; i++) {
1939 		struct platform_device *dport = cxl_root_port[i];
1940 		struct platform_device *pdev;
1941 
1942 		pdev = platform_device_alloc("cxl_type2_accel", i);
1943 		if (!pdev) {
1944 			rc = -ENOMEM;
1945 			goto err_mem;
1946 		}
1947 		pdev->dev.parent = &dport->dev;
1948 		set_dev_node(&pdev->dev, i % 2);
1949 
1950 		rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]);
1951 		if (rc)
1952 			goto err_mem;
1953 	}
1954 
1955 	return 0;
1956 
1957 err_mem:
1958 	for (i = NR_CXL_TYPE2_ACCEL - 1; i >= 0; i--)
1959 		platform_device_unregister(cxl_mem[i]);
1960 	return rc;
1961 }
1962 
cxl_type3_mem_init(void)1963 static int cxl_type3_mem_init(void)
1964 {
1965 	int i, rc;
1966 
1967 	for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) {
1968 		struct platform_device *dport = cxl_switch_dport[i];
1969 		struct platform_device *pdev;
1970 
1971 		pdev = platform_device_alloc("cxl_mem", i);
1972 		if (!pdev) {
1973 			rc = -ENOMEM;
1974 			goto err_mem;
1975 		}
1976 		pdev->dev.parent = &dport->dev;
1977 		set_dev_node(&pdev->dev, i % 2);
1978 
1979 		rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]);
1980 		if (rc)
1981 			goto err_mem;
1982 	}
1983 
1984 	for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
1985 		struct platform_device *dport = cxl_swd_single[i];
1986 		struct platform_device *pdev;
1987 
1988 		pdev = platform_device_alloc("cxl_mem", NR_MEM_MULTI + i);
1989 		if (!pdev) {
1990 			rc = -ENOMEM;
1991 			goto err_single;
1992 		}
1993 		pdev->dev.parent = &dport->dev;
1994 		set_dev_node(&pdev->dev, i % 2);
1995 
1996 		rc = cxl_mock_platform_device_add(pdev, &cxl_mem_single[i]);
1997 		if (rc)
1998 			goto err_single;
1999 	}
2000 
2001 	for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
2002 		int idx = NR_MEM_MULTI + NR_MEM_SINGLE + i;
2003 		struct platform_device *rch = cxl_rch[i];
2004 		struct platform_device *pdev;
2005 
2006 		pdev = platform_device_alloc("cxl_rcd", idx);
2007 		if (!pdev) {
2008 			rc = -ENOMEM;
2009 			goto err_rcd;
2010 		}
2011 		pdev->dev.parent = &rch->dev;
2012 		set_dev_node(&pdev->dev, i % 2);
2013 
2014 		rc = cxl_mock_platform_device_add(pdev, &cxl_rcd[i]);
2015 		if (rc)
2016 			goto err_rcd;
2017 	}
2018 
2019 	return 0;
2020 
2021 err_rcd:
2022 	for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
2023 		platform_device_unregister(cxl_rcd[i]);
2024 err_single:
2025 	for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
2026 		platform_device_unregister(cxl_mem_single[i]);
2027 err_mem:
2028 	for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
2029 		platform_device_unregister(cxl_mem[i]);
2030 	return rc;
2031 }
2032 
cxl_mem_init(void)2033 static int cxl_mem_init(void)
2034 {
2035 	if (type2_test)
2036 		return cxl_type2_mem_init();
2037 	return cxl_type3_mem_init();
2038 }
2039 
2040 static ssize_t
decoder_reset_preserve_registry_show(struct device * dev,struct device_attribute * attr,char * buf)2041 decoder_reset_preserve_registry_show(struct device *dev,
2042 				     struct device_attribute *attr, char *buf)
2043 {
2044 	return sysfs_emit(buf, "%d\n", decoder_reset_preserve_registry);
2045 }
2046 
2047 static ssize_t
decoder_reset_preserve_registry_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2048 decoder_reset_preserve_registry_store(struct device *dev,
2049 				      struct device_attribute *attr,
2050 				      const char *buf, size_t count)
2051 {
2052 	int rc;
2053 
2054 	rc = kstrtobool(buf, &decoder_reset_preserve_registry);
2055 	if (rc)
2056 		return rc;
2057 	return count;
2058 }
2059 
2060 static DEVICE_ATTR_RW(decoder_reset_preserve_registry);
2061 
2062 static struct attribute *cxl_acpi_attrs[] = {
2063 	&dev_attr_decoder_reset_preserve_registry.attr, NULL
2064 };
2065 ATTRIBUTE_GROUPS(cxl_acpi);
2066 
have_multiple_modparms(void)2067 static bool __init have_multiple_modparms(void)
2068 {
2069 	int count = 0;
2070 
2071 	if (interleave_arithmetic)
2072 		count++;
2073 	if (extended_linear_cache)
2074 		count++;
2075 	if (hmem_test)
2076 		count++;
2077 	if (type2_test)
2078 		count++;
2079 
2080 	return count > 1;
2081 }
2082 
host_bridges_remove(void)2083 static void host_bridges_remove(void)
2084 {
2085 	int i;
2086 
2087 	for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
2088 		struct platform_device *pdev = cxl_host_bridge[i];
2089 
2090 		if (!pdev)
2091 			continue;
2092 
2093 		sysfs_remove_link(&pdev->dev.kobj, "physical_node");
2094 		platform_device_unregister(cxl_host_bridge[i]);
2095 	}
2096 }
2097 
host_bridges_populate(void)2098 static int host_bridges_populate(void)
2099 {
2100 	int rc = 0;
2101 
2102 	for (int i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) {
2103 		struct acpi_device *adev = &host_bridge[i];
2104 		struct platform_device *pdev;
2105 
2106 		pdev = platform_device_alloc("cxl_host_bridge", i);
2107 		if (!pdev) {
2108 			rc = -ENOMEM;
2109 			goto err_bridge;
2110 		}
2111 
2112 		mock_companion(adev, &pdev->dev);
2113 		rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
2114 		if (rc)
2115 			goto err_bridge;
2116 
2117 		mock_pci_bus[i].bridge = &pdev->dev;
2118 		rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
2119 				       "physical_node");
2120 		if (rc)
2121 			goto err_bridge;
2122 	}
2123 
2124 	return 0;
2125 
2126 err_bridge:
2127 	host_bridges_remove();
2128 	return rc;
2129 }
2130 
cxl_rootports_remove(void)2131 static void cxl_rootports_remove(void)
2132 {
2133 	for (int i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--) {
2134 		struct platform_device *pdev = cxl_root_port[i];
2135 
2136 		if (!pdev)
2137 			continue;
2138 
2139 		platform_device_unregister(pdev);
2140 	}
2141 }
2142 
cxl_rootports_populate(void)2143 static int cxl_rootports_populate(void)
2144 {
2145 	int rc = 0;
2146 
2147 	for (int i = 0; i < ARRAY_SIZE(cxl_root_port); i++) {
2148 		struct platform_device *bridge =
2149 			cxl_host_bridge[i % ARRAY_SIZE(cxl_host_bridge)];
2150 		struct platform_device *pdev;
2151 
2152 		pdev = platform_device_alloc("cxl_root_port", i);
2153 		if (!pdev) {
2154 			rc = -ENOMEM;
2155 			goto err_port;
2156 		}
2157 
2158 		pdev->dev.parent = &bridge->dev;
2159 
2160 		rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
2161 		if (rc)
2162 			goto err_port;
2163 	}
2164 
2165 	return 0;
2166 
2167 err_port:
2168 	cxl_rootports_remove();
2169 	return rc;
2170 }
2171 
cxl_usps_remove(void)2172 static void cxl_usps_remove(void)
2173 {
2174 	for (int i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--) {
2175 		struct platform_device *pdev = cxl_switch_uport[i];
2176 
2177 		if (!pdev)
2178 			continue;
2179 
2180 		platform_device_unregister(cxl_switch_uport[i]);
2181 	}
2182 }
2183 
cxl_usps_populate(void)2184 static int cxl_usps_populate(void)
2185 {
2186 	int rc = 0;
2187 
2188 	for (int i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++) {
2189 		struct platform_device *root_port = cxl_root_port[i];
2190 		struct platform_device *pdev;
2191 
2192 		pdev = platform_device_alloc("cxl_switch_uport", i);
2193 		if (!pdev) {
2194 			rc = -ENOMEM;
2195 			goto err_uport;
2196 		}
2197 
2198 		pdev->dev.parent = &root_port->dev;
2199 
2200 		rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
2201 		if (rc)
2202 			goto err_uport;
2203 	}
2204 
2205 	return 0;
2206 
2207 err_uport:
2208 	cxl_usps_remove();
2209 	return rc;
2210 }
2211 
cxl_dsps_remove(void)2212 static void cxl_dsps_remove(void)
2213 {
2214 	for (int i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--) {
2215 		struct platform_device *pdev = cxl_switch_dport[i];
2216 
2217 		if (!pdev)
2218 			continue;
2219 
2220 		platform_device_unregister(cxl_switch_dport[i]);
2221 	}
2222 }
2223 
2224 
cxl_dsps_populate(void)2225 static int cxl_dsps_populate(void)
2226 {
2227 	int rc = 0;
2228 
2229 	for (int i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
2230 		struct platform_device *uport =
2231 			cxl_switch_uport[i % ARRAY_SIZE(cxl_switch_uport)];
2232 		struct platform_device *pdev;
2233 
2234 		pdev = platform_device_alloc("cxl_switch_dport", i);
2235 		if (!pdev) {
2236 			rc = -ENOMEM;
2237 			goto err_dport;
2238 		}
2239 		pdev->dev.parent = &uport->dev;
2240 
2241 		rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
2242 		if (rc)
2243 			goto err_dport;
2244 	}
2245 
2246 	return 0;
2247 
2248 err_dport:
2249 	cxl_dsps_remove();
2250 	return rc;
2251 }
2252 
cxl_switches_remove(void)2253 static void cxl_switches_remove(void)
2254 {
2255 	cxl_dsps_remove();
2256 	cxl_usps_remove();
2257 }
2258 
cxl_switches_populate(void)2259 static int cxl_switches_populate(void)
2260 {
2261 	int rc;
2262 
2263 	BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
2264 	rc = cxl_usps_populate();
2265 	if (rc)
2266 		return rc;
2267 
2268 	rc = cxl_dsps_populate();
2269 	if (rc) {
2270 		cxl_usps_remove();
2271 		return rc;
2272 	}
2273 
2274 	return 0;
2275 }
2276 
cxl_type2_topo_exit(void)2277 static void cxl_type2_topo_exit(void)
2278 {
2279 	cxl_rootports_remove();
2280 	host_bridges_remove();
2281 }
2282 
cxl_type2_topo_init(void)2283 static int cxl_type2_topo_init(void)
2284 {
2285 	int rc;
2286 
2287 	rc = host_bridges_populate();
2288 	if (rc)
2289 		return rc;
2290 
2291 	rc = cxl_rootports_populate();
2292 	if (rc) {
2293 		host_bridges_remove();
2294 		return rc;
2295 	}
2296 
2297 	return 0;
2298 }
2299 
cxl_type3_topo_exit(void)2300 static void cxl_type3_topo_exit(void)
2301 {
2302 	cxl_rch_topo_exit();
2303 	cxl_single_topo_exit();
2304 	cxl_switches_remove();
2305 	cxl_rootports_remove();
2306 	host_bridges_remove();
2307 }
2308 
cxl_type3_topo_init(void)2309 static int cxl_type3_topo_init(void)
2310 {
2311 	int rc;
2312 
2313 	rc = host_bridges_populate();
2314 	if (rc)
2315 		return rc;
2316 
2317 	rc = cxl_rootports_populate();
2318 	if (rc)
2319 		goto err_host_bridges;
2320 
2321 	rc = cxl_switches_populate();
2322 	if (rc)
2323 		goto err_root_ports;
2324 
2325 	rc = cxl_single_topo_init();
2326 	if (rc)
2327 		goto err_switches;
2328 
2329 	rc = cxl_rch_topo_init();
2330 	if (rc)
2331 		goto err_single;
2332 
2333 	return 0;
2334 
2335 err_single:
2336 	cxl_single_topo_exit();
2337 err_switches:
2338 	cxl_switches_remove();
2339 err_root_ports:
2340 	cxl_rootports_remove();
2341 err_host_bridges:
2342 	host_bridges_remove();
2343 	return rc;
2344 }
2345 
cxl_topo_exit(void)2346 static void cxl_topo_exit(void)
2347 {
2348 	if (type2_test) {
2349 		cxl_type2_topo_exit();
2350 		return;
2351 	}
2352 
2353 	cxl_type3_topo_exit();
2354 }
2355 
cxl_topo_init(void)2356 static int cxl_topo_init(void)
2357 {
2358 	if (type2_test)
2359 		return cxl_type2_topo_init();
2360 	return cxl_type3_topo_init();
2361 }
2362 
cxl_test_init(void)2363 static __init int cxl_test_init(void)
2364 {
2365 	struct range mappable;
2366 	int rc;
2367 
2368 	/* Enforce a single module param active at a time */
2369 	if (have_multiple_modparms())
2370 		return -EINVAL;
2371 
2372 	if (!IS_ALIGNED(mock_auto_region_size, PMD_SIZE)) {
2373 		pr_err_once("mock_auto_region_size %d must be PMD-aligned\n",
2374 			    mock_auto_region_size);
2375 		return -EINVAL;
2376 	}
2377 
2378 	cxl_acpi_test();
2379 	cxl_core_test();
2380 	cxl_mem_test();
2381 	cxl_pmem_test();
2382 	cxl_port_test();
2383 
2384 	register_cxl_mock_ops(&cxl_mock_ops);
2385 
2386 	cxl_mock_pool = gen_pool_create(ilog2(SZ_2M), NUMA_NO_NODE);
2387 	if (!cxl_mock_pool) {
2388 		rc = -ENOMEM;
2389 		goto err_gen_pool_create;
2390 	}
2391 	mappable = mhp_get_pluggable_range(true);
2392 
2393 	rc = gen_pool_add(cxl_mock_pool,
2394 			  min(iomem_resource.end + 1 - SZ_64G,
2395 			      mappable.end + 1 - SZ_64G),
2396 			  SZ_64G, NUMA_NO_NODE);
2397 	if (rc)
2398 		goto err_gen_pool_add;
2399 
2400 	if (interleave_arithmetic == 1) {
2401 		cfmws_start = CFMWS_XOR_ARRAY_START;
2402 		cfmws_end = CFMWS_XOR_ARRAY_END;
2403 	} else {
2404 		cfmws_start = CFMWS_MOD_ARRAY_START;
2405 		cfmws_end = CFMWS_MOD_ARRAY_END;
2406 	}
2407 
2408 	rc = populate_cedt();
2409 	if (rc)
2410 		goto err_populate;
2411 
2412 	rc = cxl_topo_init();
2413 	if (rc)
2414 		goto err_populate;
2415 
2416 	cxl_acpi = platform_device_alloc("cxl_acpi", 0);
2417 	if (!cxl_acpi) {
2418 		rc = -ENOMEM;
2419 		goto err_topo;
2420 	}
2421 
2422 	mock_companion(&acpi0017_mock, &cxl_acpi->dev);
2423 	acpi0017_mock.dev.bus = &platform_bus_type;
2424 	cxl_acpi->dev.groups = cxl_acpi_groups;
2425 
2426 	rc = cxl_mock_platform_device_add(cxl_acpi, NULL);
2427 	if (rc)
2428 		goto err_topo;
2429 
2430 	rc = cxl_mem_init();
2431 	if (rc)
2432 		goto err_root;
2433 
2434 	rc = hmem_test_init();
2435 	if (rc)
2436 		goto err_mem;
2437 
2438 	return 0;
2439 
2440 err_mem:
2441 	cxl_mem_exit();
2442 err_root:
2443 	platform_device_unregister(cxl_acpi);
2444 err_topo:
2445 	cxl_topo_exit();
2446 err_populate:
2447 	depopulate_all_mock_resources();
2448 err_gen_pool_add:
2449 	gen_pool_destroy(cxl_mock_pool);
2450 err_gen_pool_create:
2451 	unregister_cxl_mock_ops(&cxl_mock_ops);
2452 	return rc;
2453 }
2454 
free_decoder_registry(void)2455 static void free_decoder_registry(void)
2456 {
2457 	unsigned long index;
2458 	void *entry;
2459 
2460 	xa_for_each(&decoder_registry, index, entry) {
2461 		xa_erase(&decoder_registry, index);
2462 		kfree(entry);
2463 	}
2464 }
2465 
cxl_test_exit(void)2466 static __exit void cxl_test_exit(void)
2467 {
2468 	hmem_test_exit();
2469 	cxl_mem_exit();
2470 	platform_device_unregister(cxl_acpi);
2471 	cxl_topo_exit();
2472 	depopulate_all_mock_resources();
2473 	gen_pool_destroy(cxl_mock_pool);
2474 	unregister_cxl_mock_ops(&cxl_mock_ops);
2475 	free_decoder_registry();
2476 	xa_destroy(&decoder_registry);
2477 }
2478 
2479 module_param(interleave_arithmetic, int, 0444);
2480 MODULE_PARM_DESC(interleave_arithmetic, "Modulo:0, XOR:1");
2481 module_param(extended_linear_cache, bool, 0444);
2482 MODULE_PARM_DESC(extended_linear_cache, "Enable extended linear cache support");
2483 module_param(fail_autoassemble, bool, 0444);
2484 MODULE_PARM_DESC(fail_autoassemble, "Simulate missing member of an auto-region");
2485 module_param(type2_test, bool, 0444);
2486 MODULE_PARM_DESC(type2_test, "Enable type 2 support testing");
2487 module_init(cxl_test_init);
2488 module_exit(cxl_test_exit);
2489 MODULE_LICENSE("GPL v2");
2490 MODULE_DESCRIPTION("cxl_test: setup module");
2491 MODULE_IMPORT_NS("ACPI");
2492 MODULE_IMPORT_NS("CXL");
2493