Commit 7367539a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'cxl-fixes-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl

Pull cxl fix from Dave Jiang:
 "Add missing RCH support for endpoint access_coordinate calculation.

  A late bug was reported by Robert Richter that the Restricted CXL Host
  (RCH) support was missing in the CXL endpoint access_coordinate
  calculation.

  The missing support causes the topology iterator to stumble over a
  NULL pointer and triggers a kernel OOPS on a platform with CXL 1.1
  support.

  The fix bypasses RCH topology as the access_coordinate calculation is
  not necessary since RCH does not support hotplug and the memory region
  exported should be covered by the HMAT table already.

  A unit test is also added to cxl_test to check against future
  regressions on the topology iterator"

* tag 'cxl-fixes-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl:
  cxl: Fix cxl_endpoint_get_perf_coordinate() support for RCH
parents ddb4c3f2 5d211c70
...@@ -2184,6 +2184,7 @@ static bool parent_port_is_cxl_root(struct cxl_port *port) ...@@ -2184,6 +2184,7 @@ static bool parent_port_is_cxl_root(struct cxl_port *port)
int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
struct access_coordinate *coord) struct access_coordinate *coord)
{ {
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
struct access_coordinate c[] = { struct access_coordinate c[] = {
{ {
.read_bandwidth = UINT_MAX, .read_bandwidth = UINT_MAX,
...@@ -2197,12 +2198,20 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, ...@@ -2197,12 +2198,20 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
struct cxl_port *iter = port; struct cxl_port *iter = port;
struct cxl_dport *dport; struct cxl_dport *dport;
struct pci_dev *pdev; struct pci_dev *pdev;
struct device *dev;
unsigned int bw; unsigned int bw;
bool is_cxl_root; bool is_cxl_root;
if (!is_cxl_endpoint(port)) if (!is_cxl_endpoint(port))
return -EINVAL; return -EINVAL;
/*
* Skip calculation for RCD. Expectation is HMAT already covers RCD case
* since RCH does not support hotplug.
*/
if (cxlmd->cxlds->rcd)
return 0;
/* /*
* Exit the loop when the parent port of the current iter port is cxl * Exit the loop when the parent port of the current iter port is cxl
* root. The iterative loop starts at the endpoint and gathers the * 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, ...@@ -2232,8 +2241,12 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
return -EINVAL; return -EINVAL;
cxl_coordinates_combine(c, c, dport->coord); cxl_coordinates_combine(c, c, dport->coord);
dev = port->uport_dev->parent;
if (!dev_is_pci(dev))
return -ENODEV;
/* Get the calculated PCI paths bandwidth */ /* Get the calculated PCI paths bandwidth */
pdev = to_pci_dev(port->uport_dev->parent); pdev = to_pci_dev(dev);
bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL); bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL);
if (bw == 0) if (bw == 0)
return -ENXIO; return -ENXIO;
......
...@@ -1001,6 +1001,7 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port) ...@@ -1001,6 +1001,7 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev); struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
struct access_coordinate ep_c[ACCESS_COORDINATE_MAX];
struct range pmem_range = { struct range pmem_range = {
.start = cxlds->pmem_res.start, .start = cxlds->pmem_res.start,
.end = cxlds->pmem_res.end, .end = cxlds->pmem_res.end,
...@@ -1020,6 +1021,12 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port) ...@@ -1020,6 +1021,12 @@ static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port)
dpa_perf_setup(port, &pmem_range, &mds->pmem_perf); dpa_perf_setup(port, &pmem_range, &mds->pmem_perf);
cxl_memdev_update_perf(cxlmd); cxl_memdev_update_perf(cxlmd);
/*
* This function is here to only test the topology iterator. It serves
* no other purpose.
*/
cxl_endpoint_get_perf_coordinates(port, ep_c);
} }
static struct cxl_mock_ops cxl_mock_ops = { static struct cxl_mock_ops cxl_mock_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment