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