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

Configure Feed

Select the types of activity you want to include in your feed.

cxl/core/regs: Add rcd_pcie_cap initialization

Add rcd_pcie_cap and its initialization to cache the offset of cxl1.1
device link status information. By caching it, avoid the walking
memory map area to find the offset when output the register value.

Given that this solution involves port lookups via cxl_pci_find_port()
and multiple exit paths where that reference needs to be dropped,
introduce a new put_cxl_root() scope-based-free handler.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Kobayashi,Daisuke <kobayashi.da-06@fujitsu.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Link: https://patch.msgid.link/20241002011549.408412-2-kobayashi.da-06@fujitsu.com
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>

authored by

Kobayashi,Daisuke and committed by
Dave Jiang
7a01213d 66418687

+88 -5
+5
drivers/cxl/core/core.h
··· 89 89 enum cxl_rcrb which); 90 90 u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb); 91 91 92 + #define PCI_RCRB_CAP_LIST_ID_MASK GENMASK(7, 0) 93 + #define PCI_RCRB_CAP_HDR_ID_MASK GENMASK(7, 0) 94 + #define PCI_RCRB_CAP_HDR_NEXT_MASK GENMASK(15, 8) 95 + #define PCI_CAP_EXP_SIZEOF 0x3c 96 + 92 97 extern struct rw_semaphore cxl_dpa_rwsem; 93 98 extern struct rw_semaphore cxl_region_rwsem; 94 99
+56
drivers/cxl/core/regs.c
··· 506 506 return offset; 507 507 } 508 508 509 + static resource_size_t cxl_rcrb_to_linkcap(struct device *dev, struct cxl_dport *dport) 510 + { 511 + resource_size_t rcrb = dport->rcrb.base; 512 + void __iomem *addr; 513 + u32 cap_hdr; 514 + u16 offset; 515 + 516 + if (!request_mem_region(rcrb, SZ_4K, "CXL RCRB")) 517 + return CXL_RESOURCE_NONE; 518 + 519 + addr = ioremap(rcrb, SZ_4K); 520 + if (!addr) { 521 + dev_err(dev, "Failed to map region %pr\n", addr); 522 + release_mem_region(rcrb, SZ_4K); 523 + return CXL_RESOURCE_NONE; 524 + } 525 + 526 + offset = FIELD_GET(PCI_RCRB_CAP_LIST_ID_MASK, readw(addr + PCI_CAPABILITY_LIST)); 527 + cap_hdr = readl(addr + offset); 528 + while ((FIELD_GET(PCI_RCRB_CAP_HDR_ID_MASK, cap_hdr)) != PCI_CAP_ID_EXP) { 529 + offset = FIELD_GET(PCI_RCRB_CAP_HDR_NEXT_MASK, cap_hdr); 530 + if (offset == 0 || offset > SZ_4K) { 531 + offset = 0; 532 + break; 533 + } 534 + cap_hdr = readl(addr + offset); 535 + } 536 + 537 + iounmap(addr); 538 + release_mem_region(rcrb, SZ_4K); 539 + if (!offset) 540 + return CXL_RESOURCE_NONE; 541 + 542 + return offset; 543 + } 544 + 545 + int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport) 546 + { 547 + void __iomem *dport_pcie_cap = NULL; 548 + resource_size_t pos; 549 + struct cxl_rcrb_info *ri; 550 + 551 + ri = &dport->rcrb; 552 + pos = cxl_rcrb_to_linkcap(&pdev->dev, dport); 553 + if (pos == CXL_RESOURCE_NONE) 554 + return -ENXIO; 555 + 556 + dport_pcie_cap = devm_cxl_iomap_block(&pdev->dev, 557 + ri->base + pos, 558 + PCI_CAP_EXP_SIZEOF); 559 + dport->regs.rcd_pcie_cap = dport_pcie_cap; 560 + 561 + return 0; 562 + } 563 + EXPORT_SYMBOL_NS_GPL(cxl_dport_map_rcd_linkcap, CXL); 564 + 509 565 resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri, 510 566 enum cxl_rcrb which) 511 567 {
+9
drivers/cxl/cxl.h
··· 235 235 struct_group_tagged(cxl_rch_regs, rch_regs, 236 236 void __iomem *dport_aer; 237 237 ); 238 + 239 + /* 240 + * RCD upstream port specific PCIe cap register 241 + * @pcie_cap: CXL 3.0 8.2.1.2 RCD Upstream Port RCRB 242 + */ 243 + struct_group_tagged(cxl_rcd_regs, rcd_regs, 244 + void __iomem *rcd_pcie_cap; 245 + ); 238 246 }; 239 247 240 248 struct cxl_reg_map { ··· 312 304 struct cxl_dport; 313 305 resource_size_t cxl_rcd_component_reg_phys(struct device *dev, 314 306 struct cxl_dport *dport); 307 + int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport); 315 308 316 309 #define CXL_RESOURCE_NONE ((resource_size_t) -1) 317 310 #define CXL_TARGET_STRLEN 20
+18 -5
drivers/cxl/pci.c
··· 475 475 } 476 476 477 477 static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev, 478 - struct cxl_register_map *map) 478 + struct cxl_register_map *map, 479 + struct cxl_dport *dport) 479 480 { 480 - struct cxl_dport *dport; 481 481 resource_size_t component_reg_phys; 482 482 483 483 *map = (struct cxl_register_map) { ··· 513 513 * is an RCH and try to extract the Component Registers from 514 514 * an RCRB. 515 515 */ 516 - if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) 517 - rc = cxl_rcrb_get_comp_regs(pdev, map); 516 + if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev)) { 517 + struct cxl_dport *dport; 518 + struct cxl_port *port __free(put_cxl_port) = 519 + cxl_pci_find_port(pdev, &dport); 520 + if (!port) 521 + return -EPROBE_DEFER; 518 522 519 - if (rc) 523 + rc = cxl_rcrb_get_comp_regs(pdev, map, dport); 524 + if (rc) 525 + return rc; 526 + 527 + rc = cxl_dport_map_rcd_linkcap(pdev, dport); 528 + if (rc) 529 + return rc; 530 + 531 + } else if (rc) { 520 532 return rc; 533 + } 521 534 522 535 return cxl_setup_regs(map); 523 536 }