ACPI: thermal: Install Notify() handler directly
[linux-block.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 #ifndef SZ_512G
1003 #define SZ_512G (SZ_64G * 8)
1004 #endif
1005
1006 static __init int cxl_rch_init(void)
1007 {
1008         int rc, i;
1009
1010         for (i = 0; i < ARRAY_SIZE(cxl_rch); i++) {
1011                 int idx = NR_CXL_HOST_BRIDGES + NR_CXL_SINGLE_HOST + i;
1012                 struct acpi_device *adev = &host_bridge[idx];
1013                 struct platform_device *pdev;
1014
1015                 pdev = platform_device_alloc("cxl_host_bridge", idx);
1016                 if (!pdev)
1017                         goto err_bridge;
1018
1019                 mock_companion(adev, &pdev->dev);
1020                 rc = platform_device_add(pdev);
1021                 if (rc) {
1022                         platform_device_put(pdev);
1023                         goto err_bridge;
1024                 }
1025
1026                 cxl_rch[i] = pdev;
1027                 mock_pci_bus[idx].bridge = &pdev->dev;
1028                 rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1029                                        "firmware_node");
1030                 if (rc)
1031                         goto err_bridge;
1032         }
1033
1034         for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
1035                 int idx = NR_MEM_MULTI + NR_MEM_SINGLE + i;
1036                 struct platform_device *rch = cxl_rch[i];
1037                 struct platform_device *pdev;
1038
1039                 pdev = platform_device_alloc("cxl_rcd", idx);
1040                 if (!pdev)
1041                         goto err_mem;
1042                 pdev->dev.parent = &rch->dev;
1043                 set_dev_node(&pdev->dev, i % 2);
1044
1045                 rc = platform_device_add(pdev);
1046                 if (rc) {
1047                         platform_device_put(pdev);
1048                         goto err_mem;
1049                 }
1050                 cxl_rcd[i] = pdev;
1051         }
1052
1053         return 0;
1054
1055 err_mem:
1056         for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
1057                 platform_device_unregister(cxl_rcd[i]);
1058 err_bridge:
1059         for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
1060                 struct platform_device *pdev = cxl_rch[i];
1061
1062                 if (!pdev)
1063                         continue;
1064                 sysfs_remove_link(&pdev->dev.kobj, "firmware_node");
1065                 platform_device_unregister(cxl_rch[i]);
1066         }
1067
1068         return rc;
1069 }
1070
1071 static void cxl_rch_exit(void)
1072 {
1073         int i;
1074
1075         for (i = ARRAY_SIZE(cxl_rcd) - 1; i >= 0; i--)
1076                 platform_device_unregister(cxl_rcd[i]);
1077         for (i = ARRAY_SIZE(cxl_rch) - 1; i >= 0; i--) {
1078                 struct platform_device *pdev = cxl_rch[i];
1079
1080                 if (!pdev)
1081                         continue;
1082                 sysfs_remove_link(&pdev->dev.kobj, "firmware_node");
1083                 platform_device_unregister(cxl_rch[i]);
1084         }
1085 }
1086
1087 static __init int cxl_single_init(void)
1088 {
1089         int i, rc;
1090
1091         for (i = 0; i < ARRAY_SIZE(cxl_hb_single); i++) {
1092                 struct acpi_device *adev =
1093                         &host_bridge[NR_CXL_HOST_BRIDGES + i];
1094                 struct platform_device *pdev;
1095
1096                 pdev = platform_device_alloc("cxl_host_bridge",
1097                                              NR_CXL_HOST_BRIDGES + i);
1098                 if (!pdev)
1099                         goto err_bridge;
1100
1101                 mock_companion(adev, &pdev->dev);
1102                 rc = platform_device_add(pdev);
1103                 if (rc) {
1104                         platform_device_put(pdev);
1105                         goto err_bridge;
1106                 }
1107
1108                 cxl_hb_single[i] = pdev;
1109                 mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
1110                 rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1111                                        "physical_node");
1112                 if (rc)
1113                         goto err_bridge;
1114         }
1115
1116         for (i = 0; i < ARRAY_SIZE(cxl_root_single); i++) {
1117                 struct platform_device *bridge =
1118                         cxl_hb_single[i % ARRAY_SIZE(cxl_hb_single)];
1119                 struct platform_device *pdev;
1120
1121                 pdev = platform_device_alloc("cxl_root_port",
1122                                              NR_MULTI_ROOT + i);
1123                 if (!pdev)
1124                         goto err_port;
1125                 pdev->dev.parent = &bridge->dev;
1126
1127                 rc = platform_device_add(pdev);
1128                 if (rc) {
1129                         platform_device_put(pdev);
1130                         goto err_port;
1131                 }
1132                 cxl_root_single[i] = pdev;
1133         }
1134
1135         for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
1136                 struct platform_device *root_port = cxl_root_single[i];
1137                 struct platform_device *pdev;
1138
1139                 pdev = platform_device_alloc("cxl_switch_uport",
1140                                              NR_MULTI_ROOT + i);
1141                 if (!pdev)
1142                         goto err_uport;
1143                 pdev->dev.parent = &root_port->dev;
1144
1145                 rc = platform_device_add(pdev);
1146                 if (rc) {
1147                         platform_device_put(pdev);
1148                         goto err_uport;
1149                 }
1150                 cxl_swu_single[i] = pdev;
1151         }
1152
1153         for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
1154                 struct platform_device *uport =
1155                         cxl_swu_single[i % ARRAY_SIZE(cxl_swu_single)];
1156                 struct platform_device *pdev;
1157
1158                 pdev = platform_device_alloc("cxl_switch_dport",
1159                                              i + NR_MEM_MULTI);
1160                 if (!pdev)
1161                         goto err_dport;
1162                 pdev->dev.parent = &uport->dev;
1163
1164                 rc = platform_device_add(pdev);
1165                 if (rc) {
1166                         platform_device_put(pdev);
1167                         goto err_dport;
1168                 }
1169                 cxl_swd_single[i] = pdev;
1170         }
1171
1172         for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
1173                 struct platform_device *dport = cxl_swd_single[i];
1174                 struct platform_device *pdev;
1175
1176                 pdev = platform_device_alloc("cxl_mem", NR_MEM_MULTI + i);
1177                 if (!pdev)
1178                         goto err_mem;
1179                 pdev->dev.parent = &dport->dev;
1180                 set_dev_node(&pdev->dev, i % 2);
1181
1182                 rc = platform_device_add(pdev);
1183                 if (rc) {
1184                         platform_device_put(pdev);
1185                         goto err_mem;
1186                 }
1187                 cxl_mem_single[i] = pdev;
1188         }
1189
1190         return 0;
1191
1192 err_mem:
1193         for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
1194                 platform_device_unregister(cxl_mem_single[i]);
1195 err_dport:
1196         for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
1197                 platform_device_unregister(cxl_swd_single[i]);
1198 err_uport:
1199         for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
1200                 platform_device_unregister(cxl_swu_single[i]);
1201 err_port:
1202         for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
1203                 platform_device_unregister(cxl_root_single[i]);
1204 err_bridge:
1205         for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) {
1206                 struct platform_device *pdev = cxl_hb_single[i];
1207
1208                 if (!pdev)
1209                         continue;
1210                 sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1211                 platform_device_unregister(cxl_hb_single[i]);
1212         }
1213
1214         return rc;
1215 }
1216
1217 static void cxl_single_exit(void)
1218 {
1219         int i;
1220
1221         for (i = ARRAY_SIZE(cxl_mem_single) - 1; i >= 0; i--)
1222                 platform_device_unregister(cxl_mem_single[i]);
1223         for (i = ARRAY_SIZE(cxl_swd_single) - 1; i >= 0; i--)
1224                 platform_device_unregister(cxl_swd_single[i]);
1225         for (i = ARRAY_SIZE(cxl_swu_single) - 1; i >= 0; i--)
1226                 platform_device_unregister(cxl_swu_single[i]);
1227         for (i = ARRAY_SIZE(cxl_root_single) - 1; i >= 0; i--)
1228                 platform_device_unregister(cxl_root_single[i]);
1229         for (i = ARRAY_SIZE(cxl_hb_single) - 1; i >= 0; i--) {
1230                 struct platform_device *pdev = cxl_hb_single[i];
1231
1232                 if (!pdev)
1233                         continue;
1234                 sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1235                 platform_device_unregister(cxl_hb_single[i]);
1236         }
1237 }
1238
1239 static __init int cxl_test_init(void)
1240 {
1241         int rc, i;
1242
1243         cxl_acpi_test();
1244         cxl_core_test();
1245         cxl_mem_test();
1246         cxl_pmem_test();
1247         cxl_port_test();
1248
1249         register_cxl_mock_ops(&cxl_mock_ops);
1250
1251         cxl_mock_pool = gen_pool_create(ilog2(SZ_2M), NUMA_NO_NODE);
1252         if (!cxl_mock_pool) {
1253                 rc = -ENOMEM;
1254                 goto err_gen_pool_create;
1255         }
1256
1257         rc = gen_pool_add(cxl_mock_pool, iomem_resource.end + 1 - SZ_64G,
1258                           SZ_64G, NUMA_NO_NODE);
1259         if (rc)
1260                 goto err_gen_pool_add;
1261
1262         if (interleave_arithmetic == 1) {
1263                 cfmws_start = CFMWS_XOR_ARRAY_START;
1264                 cfmws_end = CFMWS_XOR_ARRAY_END;
1265         } else {
1266                 cfmws_start = CFMWS_MOD_ARRAY_START;
1267                 cfmws_end = CFMWS_MOD_ARRAY_END;
1268         }
1269
1270         rc = populate_cedt();
1271         if (rc)
1272                 goto err_populate;
1273
1274         for (i = 0; i < ARRAY_SIZE(cxl_host_bridge); i++) {
1275                 struct acpi_device *adev = &host_bridge[i];
1276                 struct platform_device *pdev;
1277
1278                 pdev = platform_device_alloc("cxl_host_bridge", i);
1279                 if (!pdev)
1280                         goto err_bridge;
1281
1282                 mock_companion(adev, &pdev->dev);
1283                 rc = platform_device_add(pdev);
1284                 if (rc) {
1285                         platform_device_put(pdev);
1286                         goto err_bridge;
1287                 }
1288
1289                 cxl_host_bridge[i] = pdev;
1290                 mock_pci_bus[i].bridge = &pdev->dev;
1291                 rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
1292                                        "physical_node");
1293                 if (rc)
1294                         goto err_bridge;
1295         }
1296
1297         for (i = 0; i < ARRAY_SIZE(cxl_root_port); i++) {
1298                 struct platform_device *bridge =
1299                         cxl_host_bridge[i % ARRAY_SIZE(cxl_host_bridge)];
1300                 struct platform_device *pdev;
1301
1302                 pdev = platform_device_alloc("cxl_root_port", i);
1303                 if (!pdev)
1304                         goto err_port;
1305                 pdev->dev.parent = &bridge->dev;
1306
1307                 rc = platform_device_add(pdev);
1308                 if (rc) {
1309                         platform_device_put(pdev);
1310                         goto err_port;
1311                 }
1312                 cxl_root_port[i] = pdev;
1313         }
1314
1315         BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
1316         for (i = 0; i < ARRAY_SIZE(cxl_switch_uport); i++) {
1317                 struct platform_device *root_port = cxl_root_port[i];
1318                 struct platform_device *pdev;
1319
1320                 pdev = platform_device_alloc("cxl_switch_uport", i);
1321                 if (!pdev)
1322                         goto err_uport;
1323                 pdev->dev.parent = &root_port->dev;
1324
1325                 rc = platform_device_add(pdev);
1326                 if (rc) {
1327                         platform_device_put(pdev);
1328                         goto err_uport;
1329                 }
1330                 cxl_switch_uport[i] = pdev;
1331         }
1332
1333         for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
1334                 struct platform_device *uport =
1335                         cxl_switch_uport[i % ARRAY_SIZE(cxl_switch_uport)];
1336                 struct platform_device *pdev;
1337
1338                 pdev = platform_device_alloc("cxl_switch_dport", i);
1339                 if (!pdev)
1340                         goto err_dport;
1341                 pdev->dev.parent = &uport->dev;
1342
1343                 rc = platform_device_add(pdev);
1344                 if (rc) {
1345                         platform_device_put(pdev);
1346                         goto err_dport;
1347                 }
1348                 cxl_switch_dport[i] = pdev;
1349         }
1350
1351         for (i = 0; i < ARRAY_SIZE(cxl_mem); i++) {
1352                 struct platform_device *dport = cxl_switch_dport[i];
1353                 struct platform_device *pdev;
1354
1355                 pdev = platform_device_alloc("cxl_mem", i);
1356                 if (!pdev)
1357                         goto err_mem;
1358                 pdev->dev.parent = &dport->dev;
1359                 set_dev_node(&pdev->dev, i % 2);
1360
1361                 rc = platform_device_add(pdev);
1362                 if (rc) {
1363                         platform_device_put(pdev);
1364                         goto err_mem;
1365                 }
1366                 cxl_mem[i] = pdev;
1367         }
1368
1369         rc = cxl_single_init();
1370         if (rc)
1371                 goto err_mem;
1372
1373         rc = cxl_rch_init();
1374         if (rc)
1375                 goto err_single;
1376
1377         cxl_acpi = platform_device_alloc("cxl_acpi", 0);
1378         if (!cxl_acpi)
1379                 goto err_rch;
1380
1381         mock_companion(&acpi0017_mock, &cxl_acpi->dev);
1382         acpi0017_mock.dev.bus = &platform_bus_type;
1383
1384         rc = platform_device_add(cxl_acpi);
1385         if (rc)
1386                 goto err_add;
1387
1388         return 0;
1389
1390 err_add:
1391         platform_device_put(cxl_acpi);
1392 err_rch:
1393         cxl_rch_exit();
1394 err_single:
1395         cxl_single_exit();
1396 err_mem:
1397         for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
1398                 platform_device_unregister(cxl_mem[i]);
1399 err_dport:
1400         for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
1401                 platform_device_unregister(cxl_switch_dport[i]);
1402 err_uport:
1403         for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
1404                 platform_device_unregister(cxl_switch_uport[i]);
1405 err_port:
1406         for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
1407                 platform_device_unregister(cxl_root_port[i]);
1408 err_bridge:
1409         for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
1410                 struct platform_device *pdev = cxl_host_bridge[i];
1411
1412                 if (!pdev)
1413                         continue;
1414                 sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1415                 platform_device_unregister(cxl_host_bridge[i]);
1416         }
1417 err_populate:
1418         depopulate_all_mock_resources();
1419 err_gen_pool_add:
1420         gen_pool_destroy(cxl_mock_pool);
1421 err_gen_pool_create:
1422         unregister_cxl_mock_ops(&cxl_mock_ops);
1423         return rc;
1424 }
1425
1426 static __exit void cxl_test_exit(void)
1427 {
1428         int i;
1429
1430         platform_device_unregister(cxl_acpi);
1431         cxl_rch_exit();
1432         cxl_single_exit();
1433         for (i = ARRAY_SIZE(cxl_mem) - 1; i >= 0; i--)
1434                 platform_device_unregister(cxl_mem[i]);
1435         for (i = ARRAY_SIZE(cxl_switch_dport) - 1; i >= 0; i--)
1436                 platform_device_unregister(cxl_switch_dport[i]);
1437         for (i = ARRAY_SIZE(cxl_switch_uport) - 1; i >= 0; i--)
1438                 platform_device_unregister(cxl_switch_uport[i]);
1439         for (i = ARRAY_SIZE(cxl_root_port) - 1; i >= 0; i--)
1440                 platform_device_unregister(cxl_root_port[i]);
1441         for (i = ARRAY_SIZE(cxl_host_bridge) - 1; i >= 0; i--) {
1442                 struct platform_device *pdev = cxl_host_bridge[i];
1443
1444                 if (!pdev)
1445                         continue;
1446                 sysfs_remove_link(&pdev->dev.kobj, "physical_node");
1447                 platform_device_unregister(cxl_host_bridge[i]);
1448         }
1449         depopulate_all_mock_resources();
1450         gen_pool_destroy(cxl_mock_pool);
1451         unregister_cxl_mock_ops(&cxl_mock_ops);
1452 }
1453
1454 module_param(interleave_arithmetic, int, 0444);
1455 MODULE_PARM_DESC(interleave_arithmetic, "Modulo:0, XOR:1");
1456 module_init(cxl_test_init);
1457 module_exit(cxl_test_exit);
1458 MODULE_LICENSE("GPL v2");
1459 MODULE_IMPORT_NS(ACPI);
1460 MODULE_IMPORT_NS(CXL);