Skip to content

Commit 733b57f

Browse files
Robert Richterdjbw
authored andcommitted
cxl/pci: Early setup RCH dport component registers from RCRB
CXL RAS capabilities must be enabled and accessible as soon as the CXL endpoint is detected in the PCI hierarchy and bound to the cxl_pci driver. This needs to be independent of other modules such as cxl_port or cxl_mem. CXL RAS capabilities reside in the Component Registers. For an RCH this is determined by probing RCRB which is implemented very late once the CXL Memory Device is created. Change this by moving the RCRB probe to the cxl_pci driver. Do this by using a new introduced function cxl_pci_find_port() similar to cxl_mem_find_port() to determine the involved dport by the endpoint's PCI handle. Plug this into the existing cxl_pci_setup_regs() function to setup Component Registers. Probe the RCRB in case the Component Registers cannot be located through the CXL Register Locator capability. This unifies code and early sets up the Component Registers at the same time for both, VH and RCH mode. Only the cxl_pci driver is involved for this. This allows an early mapping of the CXL RAS capability registers. Signed-off-by: Robert Richter <[email protected]> Signed-off-by: Terry Bowman <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dan Williams <[email protected]>
1 parent 86917c5 commit 733b57f

File tree

4 files changed

+57
-18
lines changed

4 files changed

+57
-18
lines changed

drivers/cxl/core/port.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,13 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
14801480
}
14811481
EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL);
14821482

1483+
struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
1484+
struct cxl_dport **dport)
1485+
{
1486+
return find_cxl_port(pdev->dev.parent, dport);
1487+
}
1488+
EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL);
1489+
14831490
struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
14841491
struct cxl_dport **dport)
14851492
{

drivers/cxl/cxl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,8 @@ struct cxl_port *find_cxl_root(struct cxl_port *port);
664664
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
665665
void cxl_bus_rescan(void);
666666
void cxl_bus_drain(void);
667+
struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
668+
struct cxl_dport **dport);
667669
struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
668670
struct cxl_dport **dport);
669671
bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd);

drivers/cxl/mem.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,6 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
6565
ep->next = down;
6666
}
6767

68-
/*
69-
* The component registers for an RCD might come from the
70-
* host-bridge RCRB if they are not already mapped via the
71-
* typical register locator mechanism.
72-
*/
73-
if (parent_dport->rch && cxlds->component_reg_phys == CXL_RESOURCE_NONE)
74-
cxlds->component_reg_phys =
75-
cxl_rcd_component_reg_phys(&cxlmd->dev, parent_dport);
76-
7768
endpoint = devm_cxl_add_port(host, &cxlmd->dev,
7869
cxlds->component_reg_phys,
7970
parent_dport);

drivers/cxl/pci.c

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -274,27 +274,66 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
274274
return 0;
275275
}
276276

277+
/*
278+
* Assume that any RCIEP that emits the CXL memory expander class code
279+
* is an RCD
280+
*/
281+
static bool is_cxl_restricted(struct pci_dev *pdev)
282+
{
283+
return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
284+
}
285+
286+
static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
287+
struct cxl_register_map *map)
288+
{
289+
struct cxl_port *port;
290+
struct cxl_dport *dport;
291+
resource_size_t component_reg_phys;
292+
293+
*map = (struct cxl_register_map) {
294+
.dev = &pdev->dev,
295+
.resource = CXL_RESOURCE_NONE,
296+
};
297+
298+
port = cxl_pci_find_port(pdev, &dport);
299+
if (!port)
300+
return -EPROBE_DEFER;
301+
302+
component_reg_phys = cxl_rcd_component_reg_phys(&pdev->dev, dport);
303+
304+
put_device(&port->dev);
305+
306+
if (component_reg_phys == CXL_RESOURCE_NONE)
307+
return -ENXIO;
308+
309+
map->resource = component_reg_phys;
310+
map->reg_type = CXL_REGLOC_RBI_COMPONENT;
311+
map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;
312+
313+
return 0;
314+
}
315+
277316
static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
278317
struct cxl_register_map *map)
279318
{
280319
int rc;
281320

282321
rc = cxl_find_regblock(pdev, type, map);
322+
323+
/*
324+
* If the Register Locator DVSEC does not exist, check if it
325+
* is an RCH and try to extract the Component Registers from
326+
* an RCRB.
327+
*/
328+
if (rc && type == CXL_REGLOC_RBI_COMPONENT && is_cxl_restricted(pdev))
329+
rc = cxl_rcrb_get_comp_regs(pdev, map);
330+
283331
if (rc)
284332
return rc;
285333

286334
return cxl_setup_regs(map);
287335
}
288336

289-
/*
290-
* Assume that any RCIEP that emits the CXL memory expander class code
291-
* is an RCD
292-
*/
293-
static bool is_cxl_restricted(struct pci_dev *pdev)
294-
{
295-
return pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END;
296-
}
297-
298337
/*
299338
* CXL v3.0 6.2.3 Table 6-4
300339
* The table indicates that if PCIe Flit Mode is set, then CXL is in 256B flits

0 commit comments

Comments
 (0)