Skip to content

Commit 5d211c7

Browse files
committed
cxl: Fix cxl_endpoint_get_perf_coordinate() support for RCH
Robert reported the following when booting a CXL host with Restricted CXL Host (RCH) topology: [ 39.815379] cxl_acpi ACPI0017:00: not a cxl_port device [ 39.827123] WARNING: CPU: 46 PID: 1754 at drivers/cxl/core/port.c:592 to_cxl_port+0x56/0x70 [cxl_core] ... plus some related subsequent NULL pointer dereference: [ 40.718708] BUG: kernel NULL pointer dereference, address: 00000000000002d8 The iterator to walk the PCIe path did not account for RCH topology. However RCH does not support hotplug and the memory exported by the Restricted CXL Device (RCD) should be covered by HMAT and therefore no access_coordinate is needed. Add check to see if the endpoint device is RCD and skip calculation. Also add a call to cxl_endpoint_get_perf_coordinates() in cxl_test in order to exercise the topology iterator. The dev_is_pci() check added is to help with this test and should be harmless for normal operation. Reported-by: Robert Richter <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Fixes: 592780b ("cxl: Fix retrieving of access_coordinates in PCIe path") Reviewed-by: Dan Williams <[email protected]> Tested-by: Robert Richter <[email protected]> Reviewed-by: Robert Richter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dave Jiang <[email protected]>
1 parent e67572c commit 5d211c7

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

drivers/cxl/core/port.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,7 @@ static bool parent_port_is_cxl_root(struct cxl_port *port)
21842184
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
21852185
struct access_coordinate *coord)
21862186
{
2187+
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
21872188
struct access_coordinate c[] = {
21882189
{
21892190
.read_bandwidth = UINT_MAX,
@@ -2197,12 +2198,20 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
21972198
struct cxl_port *iter = port;
21982199
struct cxl_dport *dport;
21992200
struct pci_dev *pdev;
2201+
struct device *dev;
22002202
unsigned int bw;
22012203
bool is_cxl_root;
22022204

22032205
if (!is_cxl_endpoint(port))
22042206
return -EINVAL;
22052207

2208+
/*
2209+
* Skip calculation for RCD. Expectation is HMAT already covers RCD case
2210+
* since RCH does not support hotplug.
2211+
*/
2212+
if (cxlmd->cxlds->rcd)
2213+
return 0;
2214+
22062215
/*
22072216
* Exit the loop when the parent port of the current iter port is cxl
22082217
* root. The iterative loop starts at the endpoint and gathers the
@@ -2232,8 +2241,12 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
22322241
return -EINVAL;
22332242
cxl_coordinates_combine(c, c, dport->coord);
22342243

2244+
dev = port->uport_dev->parent;
2245+
if (!dev_is_pci(dev))
2246+
return -ENODEV;
2247+
22352248
/* Get the calculated PCI paths bandwidth */
2236-
pdev = to_pci_dev(port->uport_dev->parent);
2249+
pdev = to_pci_dev(dev);
22372250
bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL);
22382251
if (bw == 0)
22392252
return -ENXIO;

tools/testing/cxl/test/cxl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
10011001
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
10021002
struct cxl_dev_state *cxlds = cxlmd->cxlds;
10031003
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
1004+
struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
10041005
struct range pmem_range = {
10051006
.start = cxlds->pmem_res.start,
10061007
.end = cxlds->pmem_res.end,
@@ -1020,6 +1021,12 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
10201021
dpa_perf_setup(port, &pmem_range, &mds->pmem_perf);
10211022

10221023
cxl_memdev_update_perf(cxlmd);
1024+
1025+
/*
1026+
* This function is here to only test the topology iterator. It serves
1027+
* no other purpose.
1028+
*/
1029+
cxl_endpoint_get_perf_coordinates(port, ep_c);
10231030
}
10241031

10251032
static struct cxl_mock_ops cxl_mock_ops = {

0 commit comments

Comments
 (0)