Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-6.3/cxl-rr-emu' into cxl/next

Pick up the CXL DVSEC range register emulation for v6.3, and resolve
conflicts with the cxl_port_probe() split (from for-6.3/cxl-ram-region)
and event handling (from for-6.3/cxl-events).

+300 -182
+108 -11
drivers/cxl/core/hdm.c
··· 101 101 BIT(CXL_CM_CAP_CAP_ID_HDM)); 102 102 } 103 103 104 + static struct cxl_hdm *devm_cxl_setup_emulated_hdm(struct cxl_port *port, 105 + struct cxl_endpoint_dvsec_info *info) 106 + { 107 + struct device *dev = &port->dev; 108 + struct cxl_hdm *cxlhdm; 109 + 110 + if (!info->mem_enabled) 111 + return ERR_PTR(-ENODEV); 112 + 113 + cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL); 114 + if (!cxlhdm) 115 + return ERR_PTR(-ENOMEM); 116 + 117 + cxlhdm->port = port; 118 + cxlhdm->decoder_count = info->ranges; 119 + cxlhdm->target_count = info->ranges; 120 + dev_set_drvdata(&port->dev, cxlhdm); 121 + 122 + return cxlhdm; 123 + } 124 + 104 125 /** 105 126 * devm_cxl_setup_hdm - map HDM decoder component registers 106 127 * @port: cxl_port to map 128 + * @info: cached DVSEC range register info 107 129 */ 108 - struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port) 130 + struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, 131 + struct cxl_endpoint_dvsec_info *info) 109 132 { 110 133 struct device *dev = &port->dev; 111 134 struct cxl_hdm *cxlhdm; ··· 142 119 cxlhdm->port = port; 143 120 crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE); 144 121 if (!crb) { 122 + if (info && info->mem_enabled) 123 + return devm_cxl_setup_emulated_hdm(port, info); 124 + 145 125 dev_err(dev, "No component registers mapped\n"); 146 126 return ERR_PTR(-ENXIO); 147 127 } ··· 714 688 return 0; 715 689 } 716 690 691 + static int cxl_setup_hdm_decoder_from_dvsec(struct cxl_port *port, 692 + struct cxl_decoder *cxld, int which, 693 + struct cxl_endpoint_dvsec_info *info) 694 + { 695 + if (!is_cxl_endpoint(port)) 696 + return -EOPNOTSUPP; 697 + 698 + if (!range_len(&info->dvsec_range[which])) 699 + return -ENOENT; 700 + 701 + cxld->target_type = CXL_DECODER_EXPANDER; 702 + cxld->commit = NULL; 703 + cxld->reset = NULL; 704 + cxld->hpa_range = info->dvsec_range[which]; 705 + 706 + /* 707 + * Set the emulated decoder as locked pending additional support to 708 + * change the range registers at run time. 709 + */ 710 + cxld->flags |= CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK; 711 + port->commit_end = cxld->id; 712 + 713 + return 0; 714 + } 715 + 716 + static bool should_emulate_decoders(struct cxl_port *port) 717 + { 718 + struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev); 719 + void __iomem *hdm = cxlhdm->regs.hdm_decoder; 720 + u32 ctrl; 721 + int i; 722 + 723 + if (!is_cxl_endpoint(cxlhdm->port)) 724 + return false; 725 + 726 + if (!hdm) 727 + return true; 728 + 729 + /* 730 + * If any decoders are committed already, there should not be any 731 + * emulated DVSEC decoders. 732 + */ 733 + for (i = 0; i < cxlhdm->decoder_count; i++) { 734 + ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i)); 735 + if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl)) 736 + return false; 737 + } 738 + 739 + return true; 740 + } 741 + 717 742 static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld, 718 743 int *target_map, void __iomem *hdm, int which, 719 - u64 *dpa_base) 744 + u64 *dpa_base, struct cxl_endpoint_dvsec_info *info) 720 745 { 721 746 struct cxl_endpoint_decoder *cxled = NULL; 722 747 u64 size, base, skip, dpa_size; ··· 779 702 u64 value; 780 703 unsigned char target_id[8]; 781 704 } target_list; 705 + 706 + if (should_emulate_decoders(port)) 707 + return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info); 782 708 783 709 if (is_endpoint_decoder(&cxld->dev)) 784 710 cxled = to_cxl_endpoint_decoder(&cxld->dev); ··· 805 725 .start = base, 806 726 .end = base + size - 1, 807 727 }; 728 + 729 + if (cxled && !committed && range_len(&info->dvsec_range[which])) 730 + return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info); 808 731 809 732 /* decoders are enabled if committed */ 810 733 if (committed) { ··· 881 798 return 0; 882 799 } 883 800 884 - /** 885 - * devm_cxl_enumerate_decoders - add decoder objects per HDM register set 886 - * @cxlhdm: Structure to populate with HDM capabilities 887 - */ 888 - int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) 801 + static void cxl_settle_decoders(struct cxl_hdm *cxlhdm) 889 802 { 890 803 void __iomem *hdm = cxlhdm->regs.hdm_decoder; 891 - struct cxl_port *port = cxlhdm->port; 892 - int i, committed; 893 - u64 dpa_base = 0; 804 + int committed, i; 894 805 u32 ctrl; 806 + 807 + if (!hdm) 808 + return; 895 809 896 810 /* 897 811 * Since the register resource was recently claimed via request_region() ··· 906 826 /* ensure that future checks of committed can be trusted */ 907 827 if (committed != cxlhdm->decoder_count) 908 828 msleep(20); 829 + } 830 + 831 + /** 832 + * devm_cxl_enumerate_decoders - add decoder objects per HDM register set 833 + * @cxlhdm: Structure to populate with HDM capabilities 834 + * @info: cached DVSEC range register info 835 + */ 836 + int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, 837 + struct cxl_endpoint_dvsec_info *info) 838 + { 839 + void __iomem *hdm = cxlhdm->regs.hdm_decoder; 840 + struct cxl_port *port = cxlhdm->port; 841 + int i; 842 + u64 dpa_base = 0; 843 + 844 + cxl_settle_decoders(cxlhdm); 909 845 910 846 for (i = 0; i < cxlhdm->decoder_count; i++) { 911 847 int target_map[CXL_DECODER_MAX_INTERLEAVE] = { 0 }; ··· 952 856 cxld = &cxlsd->cxld; 953 857 } 954 858 955 - rc = init_hdm_decoder(port, cxld, target_map, hdm, i, &dpa_base); 859 + rc = init_hdm_decoder(port, cxld, target_map, hdm, i, 860 + &dpa_base, info); 956 861 if (rc) { 957 862 dev_warn(&port->dev, 958 863 "Failed to initialize decoder%d.%d\n",
+125 -139
drivers/cxl/core/pci.c
··· 142 142 } 143 143 EXPORT_SYMBOL_NS_GPL(cxl_await_media_ready, CXL); 144 144 145 - static int wait_for_valid(struct cxl_dev_state *cxlds) 145 + static int wait_for_valid(struct pci_dev *pdev, int d) 146 146 { 147 - struct pci_dev *pdev = to_pci_dev(cxlds->dev); 148 - int d = cxlds->cxl_dvsec, rc; 149 147 u32 val; 148 + int rc; 150 149 151 150 /* 152 151 * Memory_Info_Valid: When set, indicates that the CXL Range 1 Size high ··· 224 225 225 226 cxld = to_cxl_decoder(dev); 226 227 227 - if (!(cxld->flags & CXL_DECODER_F_LOCK)) 228 - return 0; 229 228 if (!(cxld->flags & CXL_DECODER_F_RAM)) 230 229 return 0; 231 230 ··· 253 256 return devm_add_action_or_reset(host, disable_hdm, cxlhdm); 254 257 } 255 258 256 - static bool __cxl_hdm_decode_init(struct cxl_dev_state *cxlds, 257 - struct cxl_hdm *cxlhdm, 258 - struct cxl_endpoint_dvsec_info *info) 259 + int cxl_dvsec_rr_decode(struct device *dev, int d, 260 + struct cxl_endpoint_dvsec_info *info) 261 + { 262 + struct pci_dev *pdev = to_pci_dev(dev); 263 + int hdm_count, rc, i, ranges = 0; 264 + u16 cap, ctrl; 265 + 266 + if (!d) { 267 + dev_dbg(dev, "No DVSEC Capability\n"); 268 + return -ENXIO; 269 + } 270 + 271 + rc = pci_read_config_word(pdev, d + CXL_DVSEC_CAP_OFFSET, &cap); 272 + if (rc) 273 + return rc; 274 + 275 + rc = pci_read_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, &ctrl); 276 + if (rc) 277 + return rc; 278 + 279 + if (!(cap & CXL_DVSEC_MEM_CAPABLE)) { 280 + dev_dbg(dev, "Not MEM Capable\n"); 281 + return -ENXIO; 282 + } 283 + 284 + /* 285 + * It is not allowed by spec for MEM.capable to be set and have 0 legacy 286 + * HDM decoders (values > 2 are also undefined as of CXL 2.0). As this 287 + * driver is for a spec defined class code which must be CXL.mem 288 + * capable, there is no point in continuing to enable CXL.mem. 289 + */ 290 + hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap); 291 + if (!hdm_count || hdm_count > 2) 292 + return -EINVAL; 293 + 294 + rc = wait_for_valid(pdev, d); 295 + if (rc) { 296 + dev_dbg(dev, "Failure awaiting MEM_INFO_VALID (%d)\n", rc); 297 + return rc; 298 + } 299 + 300 + /* 301 + * The current DVSEC values are moot if the memory capability is 302 + * disabled, and they will remain moot after the HDM Decoder 303 + * capability is enabled. 304 + */ 305 + info->mem_enabled = FIELD_GET(CXL_DVSEC_MEM_ENABLE, ctrl); 306 + if (!info->mem_enabled) 307 + return 0; 308 + 309 + for (i = 0; i < hdm_count; i++) { 310 + u64 base, size; 311 + u32 temp; 312 + 313 + rc = pci_read_config_dword( 314 + pdev, d + CXL_DVSEC_RANGE_SIZE_HIGH(i), &temp); 315 + if (rc) 316 + return rc; 317 + 318 + size = (u64)temp << 32; 319 + 320 + rc = pci_read_config_dword( 321 + pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(i), &temp); 322 + if (rc) 323 + return rc; 324 + 325 + size |= temp & CXL_DVSEC_MEM_SIZE_LOW_MASK; 326 + if (!size) { 327 + info->dvsec_range[i] = (struct range) { 328 + .start = 0, 329 + .end = CXL_RESOURCE_NONE, 330 + }; 331 + continue; 332 + } 333 + 334 + rc = pci_read_config_dword( 335 + pdev, d + CXL_DVSEC_RANGE_BASE_HIGH(i), &temp); 336 + if (rc) 337 + return rc; 338 + 339 + base = (u64)temp << 32; 340 + 341 + rc = pci_read_config_dword( 342 + pdev, d + CXL_DVSEC_RANGE_BASE_LOW(i), &temp); 343 + if (rc) 344 + return rc; 345 + 346 + base |= temp & CXL_DVSEC_MEM_BASE_LOW_MASK; 347 + 348 + info->dvsec_range[i] = (struct range) { 349 + .start = base, 350 + .end = base + size - 1 351 + }; 352 + 353 + ranges++; 354 + } 355 + 356 + info->ranges = ranges; 357 + 358 + return 0; 359 + } 360 + EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, CXL); 361 + 362 + /** 363 + * cxl_hdm_decode_init() - Setup HDM decoding for the endpoint 364 + * @cxlds: Device state 365 + * @cxlhdm: Mapped HDM decoder Capability 366 + * @info: Cached DVSEC range registers info 367 + * 368 + * Try to enable the endpoint's HDM Decoder Capability 369 + */ 370 + int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, 371 + struct cxl_endpoint_dvsec_info *info) 259 372 { 260 373 void __iomem *hdm = cxlhdm->regs.hdm_decoder; 261 374 struct cxl_port *port = cxlhdm->port; 262 375 struct device *dev = cxlds->dev; 263 376 struct cxl_port *root; 264 377 int i, rc, allowed; 265 - u32 global_ctrl; 378 + u32 global_ctrl = 0; 266 379 267 - global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); 380 + if (hdm) 381 + global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); 268 382 269 383 /* 270 384 * If the HDM Decoder Capability is already enabled then assume 271 385 * that some other agent like platform firmware set it up. 272 386 */ 273 - if (global_ctrl & CXL_HDM_DECODER_ENABLE) { 274 - rc = devm_cxl_enable_mem(&port->dev, cxlds); 275 - if (rc) 276 - return false; 277 - return true; 278 - } 387 + if (global_ctrl & CXL_HDM_DECODER_ENABLE || (!hdm && info->mem_enabled)) 388 + return devm_cxl_enable_mem(&port->dev, cxlds); 389 + else if (!hdm) 390 + return -ENODEV; 279 391 280 392 root = to_cxl_port(port->dev.parent); 281 393 while (!is_cxl_root(root) && is_cxl_port(root->dev.parent)) 282 394 root = to_cxl_port(root->dev.parent); 283 395 if (!is_cxl_root(root)) { 284 396 dev_err(dev, "Failed to acquire root port for HDM enable\n"); 285 - return false; 397 + return -ENODEV; 286 398 } 287 399 288 400 for (i = 0, allowed = 0; info->mem_enabled && i < info->ranges; i++) { ··· 423 317 * Decoder Capability Enable. 424 318 */ 425 319 if (info->mem_enabled) 426 - return false; 320 + return 0; 427 321 428 322 rc = devm_cxl_enable_hdm(&port->dev, cxlhdm); 429 323 if (rc) 430 - return false; 431 - 432 - rc = devm_cxl_enable_mem(&port->dev, cxlds); 433 - if (rc) 434 - return false; 435 - 436 - return true; 437 - } 438 - 439 - /** 440 - * cxl_hdm_decode_init() - Setup HDM decoding for the endpoint 441 - * @cxlds: Device state 442 - * @cxlhdm: Mapped HDM decoder Capability 443 - * 444 - * Try to enable the endpoint's HDM Decoder Capability 445 - */ 446 - int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm) 447 - { 448 - struct pci_dev *pdev = to_pci_dev(cxlds->dev); 449 - struct cxl_endpoint_dvsec_info info = { 0 }; 450 - int hdm_count, rc, i, ranges = 0; 451 - struct device *dev = &pdev->dev; 452 - int d = cxlds->cxl_dvsec; 453 - u16 cap, ctrl; 454 - 455 - if (!d) { 456 - dev_dbg(dev, "No DVSEC Capability\n"); 457 - return -ENXIO; 458 - } 459 - 460 - rc = pci_read_config_word(pdev, d + CXL_DVSEC_CAP_OFFSET, &cap); 461 - if (rc) 462 324 return rc; 463 325 464 - rc = pci_read_config_word(pdev, d + CXL_DVSEC_CTRL_OFFSET, &ctrl); 465 - if (rc) 466 - return rc; 467 - 468 - if (!(cap & CXL_DVSEC_MEM_CAPABLE)) { 469 - dev_dbg(dev, "Not MEM Capable\n"); 470 - return -ENXIO; 471 - } 472 - 473 - /* 474 - * It is not allowed by spec for MEM.capable to be set and have 0 legacy 475 - * HDM decoders (values > 2 are also undefined as of CXL 2.0). As this 476 - * driver is for a spec defined class code which must be CXL.mem 477 - * capable, there is no point in continuing to enable CXL.mem. 478 - */ 479 - hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap); 480 - if (!hdm_count || hdm_count > 2) 481 - return -EINVAL; 482 - 483 - rc = wait_for_valid(cxlds); 484 - if (rc) { 485 - dev_dbg(dev, "Failure awaiting MEM_INFO_VALID (%d)\n", rc); 486 - return rc; 487 - } 488 - 489 - /* 490 - * The current DVSEC values are moot if the memory capability is 491 - * disabled, and they will remain moot after the HDM Decoder 492 - * capability is enabled. 493 - */ 494 - info.mem_enabled = FIELD_GET(CXL_DVSEC_MEM_ENABLE, ctrl); 495 - if (!info.mem_enabled) 496 - goto hdm_init; 497 - 498 - for (i = 0; i < hdm_count; i++) { 499 - u64 base, size; 500 - u32 temp; 501 - 502 - rc = pci_read_config_dword( 503 - pdev, d + CXL_DVSEC_RANGE_SIZE_HIGH(i), &temp); 504 - if (rc) 505 - return rc; 506 - 507 - size = (u64)temp << 32; 508 - 509 - rc = pci_read_config_dword( 510 - pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(i), &temp); 511 - if (rc) 512 - return rc; 513 - 514 - size |= temp & CXL_DVSEC_MEM_SIZE_LOW_MASK; 515 - 516 - rc = pci_read_config_dword( 517 - pdev, d + CXL_DVSEC_RANGE_BASE_HIGH(i), &temp); 518 - if (rc) 519 - return rc; 520 - 521 - base = (u64)temp << 32; 522 - 523 - rc = pci_read_config_dword( 524 - pdev, d + CXL_DVSEC_RANGE_BASE_LOW(i), &temp); 525 - if (rc) 526 - return rc; 527 - 528 - base |= temp & CXL_DVSEC_MEM_BASE_LOW_MASK; 529 - 530 - info.dvsec_range[i] = (struct range) { 531 - .start = base, 532 - .end = base + size - 1 533 - }; 534 - 535 - if (size) 536 - ranges++; 537 - } 538 - 539 - info.ranges = ranges; 540 - 541 - /* 542 - * If DVSEC ranges are being used instead of HDM decoder registers there 543 - * is no use in trying to manage those. 544 - */ 545 - hdm_init: 546 - if (!__cxl_hdm_decode_init(cxlds, cxlhdm, &info)) { 547 - dev_err(dev, 548 - "Legacy range registers configuration prevents HDM operation.\n"); 549 - return -EBUSY; 550 - } 551 - 552 - return 0; 326 + return devm_cxl_enable_mem(&port->dev, cxlds); 553 327 } 554 328 EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL); 555 329
+18 -2
drivers/cxl/cxl.h
··· 693 693 int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld); 694 694 int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint); 695 695 696 + /** 697 + * struct cxl_endpoint_dvsec_info - Cached DVSEC info 698 + * @mem_enabled: cached value of mem_enabled in the DVSEC, PCIE_DEVICE 699 + * @ranges: Number of active HDM ranges this device uses. 700 + * @dvsec_range: cached attributes of the ranges in the DVSEC, PCIE_DEVICE 701 + */ 702 + struct cxl_endpoint_dvsec_info { 703 + bool mem_enabled; 704 + int ranges; 705 + struct range dvsec_range[2]; 706 + }; 707 + 696 708 struct cxl_hdm; 697 - struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port); 698 - int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm); 709 + struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, 710 + struct cxl_endpoint_dvsec_info *info); 711 + int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, 712 + struct cxl_endpoint_dvsec_info *info); 699 713 int devm_cxl_add_passthrough_decoder(struct cxl_port *port); 714 + int cxl_dvsec_rr_decode(struct device *dev, int dvsec, 715 + struct cxl_endpoint_dvsec_info *info); 700 716 701 717 bool is_cxl_region(struct device *dev); 702 718
-12
drivers/cxl/cxlmem.h
··· 188 188 #define CXL_CAPACITY_MULTIPLIER SZ_256M 189 189 190 190 /** 191 - * struct cxl_endpoint_dvsec_info - Cached DVSEC info 192 - * @mem_enabled: cached value of mem_enabled in the DVSEC, PCIE_DEVICE 193 - * @ranges: Number of active HDM ranges this device uses. 194 - * @dvsec_range: cached attributes of the ranges in the DVSEC, PCIE_DEVICE 195 - */ 196 - struct cxl_endpoint_dvsec_info { 197 - bool mem_enabled; 198 - int ranges; 199 - struct range dvsec_range[2]; 200 - }; 201 - 202 - /** 203 191 * Event Interrupt Policy 204 192 * 205 193 * CXL rev 3.0 section 8.2.9.2.4; Table 8-52
+2 -1
drivers/cxl/cxlpci.h
··· 70 70 71 71 int devm_cxl_port_enumerate_dports(struct cxl_port *port); 72 72 struct cxl_dev_state; 73 - int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm); 73 + int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, 74 + struct cxl_endpoint_dvsec_info *info); 74 75 void read_cdat_data(struct cxl_port *port); 75 76 void cxl_cor_error_detected(struct pci_dev *pdev); 76 77 pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
+10 -5
drivers/cxl/port.c
··· 69 69 if (rc == 1) 70 70 return devm_cxl_add_passthrough_decoder(port); 71 71 72 - cxlhdm = devm_cxl_setup_hdm(port); 72 + cxlhdm = devm_cxl_setup_hdm(port, NULL); 73 73 if (IS_ERR(cxlhdm)) 74 74 return PTR_ERR(cxlhdm); 75 75 76 - return devm_cxl_enumerate_decoders(cxlhdm); 76 + return devm_cxl_enumerate_decoders(cxlhdm, NULL); 77 77 } 78 78 79 79 static int cxl_endpoint_port_probe(struct cxl_port *port) 80 80 { 81 81 struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport); 82 + struct cxl_endpoint_dvsec_info info = { 0 }; 82 83 struct cxl_dev_state *cxlds = cxlmd->cxlds; 83 84 struct cxl_hdm *cxlhdm; 84 85 struct cxl_port *root; 85 86 int rc; 86 87 87 - cxlhdm = devm_cxl_setup_hdm(port); 88 + rc = cxl_dvsec_rr_decode(cxlds->dev, cxlds->cxl_dvsec, &info); 89 + if (rc < 0) 90 + return rc; 91 + 92 + cxlhdm = devm_cxl_setup_hdm(port, &info); 88 93 if (IS_ERR(cxlhdm)) 89 94 return PTR_ERR(cxlhdm); 90 95 ··· 101 96 if (rc) 102 97 return rc; 103 98 104 - rc = cxl_hdm_decode_init(cxlds, cxlhdm); 99 + rc = cxl_hdm_decode_init(cxlds, cxlhdm, &info); 105 100 if (rc) 106 101 return rc; 107 102 ··· 111 106 return rc; 112 107 } 113 108 114 - rc = devm_cxl_enumerate_decoders(cxlhdm); 109 + rc = devm_cxl_enumerate_decoders(cxlhdm, &info); 115 110 if (rc) 116 111 return rc; 117 112
+1
tools/testing/cxl/Kbuild
··· 10 10 ldflags-y += --wrap=devm_cxl_enumerate_decoders 11 11 ldflags-y += --wrap=cxl_await_media_ready 12 12 ldflags-y += --wrap=cxl_hdm_decode_init 13 + ldflags-y += --wrap=cxl_dvsec_rr_decode 13 14 ldflags-y += --wrap=cxl_rcrb_to_component 14 15 15 16 DRIVERS := ../../../drivers
+4 -2
tools/testing/cxl/test/cxl.c
··· 620 620 return &mock_pci_root[host_bridge_index(adev)]; 621 621 } 622 622 623 - static struct cxl_hdm *mock_cxl_setup_hdm(struct cxl_port *port) 623 + static struct cxl_hdm *mock_cxl_setup_hdm(struct cxl_port *port, 624 + struct cxl_endpoint_dvsec_info *info) 624 625 { 625 626 struct cxl_hdm *cxlhdm = devm_kzalloc(&port->dev, sizeof(*cxlhdm), GFP_KERNEL); 626 627 ··· 840 839 } 841 840 } 842 841 843 - static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) 842 + static int mock_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, 843 + struct cxl_endpoint_dvsec_info *info) 844 844 { 845 845 struct cxl_port *port = cxlhdm->port; 846 846 struct cxl_port *parent_port = to_cxl_port(port->dev.parent);
+28 -8
tools/testing/cxl/test/mock.c
··· 131 131 } 132 132 EXPORT_SYMBOL_GPL(__wrap_nvdimm_bus_register); 133 133 134 - struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port) 134 + struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port, 135 + struct cxl_endpoint_dvsec_info *info) 136 + 135 137 { 136 138 int index; 137 139 struct cxl_hdm *cxlhdm; 138 140 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 139 141 140 142 if (ops && ops->is_mock_port(port->uport)) 141 - cxlhdm = ops->devm_cxl_setup_hdm(port); 143 + cxlhdm = ops->devm_cxl_setup_hdm(port, info); 142 144 else 143 - cxlhdm = devm_cxl_setup_hdm(port); 145 + cxlhdm = devm_cxl_setup_hdm(port, info); 144 146 put_cxl_mock_ops(index); 145 147 146 148 return cxlhdm; ··· 164 162 } 165 163 EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL); 166 164 167 - int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm) 165 + int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, 166 + struct cxl_endpoint_dvsec_info *info) 168 167 { 169 168 int rc, index; 170 169 struct cxl_port *port = cxlhdm->port; 171 170 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 172 171 173 172 if (ops && ops->is_mock_port(port->uport)) 174 - rc = ops->devm_cxl_enumerate_decoders(cxlhdm); 173 + rc = ops->devm_cxl_enumerate_decoders(cxlhdm, info); 175 174 else 176 - rc = devm_cxl_enumerate_decoders(cxlhdm); 175 + rc = devm_cxl_enumerate_decoders(cxlhdm, info); 177 176 put_cxl_mock_ops(index); 178 177 179 178 return rc; ··· 212 209 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL); 213 210 214 211 int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds, 215 - struct cxl_hdm *cxlhdm) 212 + struct cxl_hdm *cxlhdm, 213 + struct cxl_endpoint_dvsec_info *info) 216 214 { 217 215 int rc = 0, index; 218 216 struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); ··· 221 217 if (ops && ops->is_mock_dev(cxlds->dev)) 222 218 rc = 0; 223 219 else 224 - rc = cxl_hdm_decode_init(cxlds, cxlhdm); 220 + rc = cxl_hdm_decode_init(cxlds, cxlhdm, info); 225 221 put_cxl_mock_ops(index); 226 222 227 223 return rc; 228 224 } 229 225 EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL); 226 + 227 + int __wrap_cxl_dvsec_rr_decode(struct device *dev, int dvsec, 228 + struct cxl_endpoint_dvsec_info *info) 229 + { 230 + int rc = 0, index; 231 + struct cxl_mock_ops *ops = get_cxl_mock_ops(&index); 232 + 233 + if (ops && ops->is_mock_dev(dev)) 234 + rc = 0; 235 + else 236 + rc = cxl_dvsec_rr_decode(dev, dvsec, info); 237 + put_cxl_mock_ops(index); 238 + 239 + return rc; 240 + } 241 + EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL); 230 242 231 243 resource_size_t __wrap_cxl_rcrb_to_component(struct device *dev, 232 244 resource_size_t rcrb,
+4 -2
tools/testing/cxl/test/mock.h
··· 23 23 bool (*is_mock_port)(struct device *dev); 24 24 bool (*is_mock_dev)(struct device *dev); 25 25 int (*devm_cxl_port_enumerate_dports)(struct cxl_port *port); 26 - struct cxl_hdm *(*devm_cxl_setup_hdm)(struct cxl_port *port); 26 + struct cxl_hdm *(*devm_cxl_setup_hdm)( 27 + struct cxl_port *port, struct cxl_endpoint_dvsec_info *info); 27 28 int (*devm_cxl_add_passthrough_decoder)(struct cxl_port *port); 28 - int (*devm_cxl_enumerate_decoders)(struct cxl_hdm *hdm); 29 + int (*devm_cxl_enumerate_decoders)( 30 + struct cxl_hdm *hdm, struct cxl_endpoint_dvsec_info *info); 29 31 }; 30 32 31 33 void register_cxl_mock_ops(struct cxl_mock_ops *ops);