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