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