Skip to content

Commit b69810f

Browse files
committed
Merge tag 'cxl-fixes-6.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl
Pull cxl fixes from Ira Weiny: - prevent probe failure when non-critical RAS unmasking fails - fix CXL 1.1 link status sysfs attribute - fix 4 way (and greater) switch interleave region creation * tag 'cxl-fixes-6.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cxl/cxl: cxl/region: Fix region creation for greater than x2 switches cxl/pci: Check dport->regs.rcd_pcie_cap availability before accessing cxl/pci: Fix potential bogus return value upon successful probing
2 parents 397d1d8 + 76467a9 commit b69810f

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

drivers/cxl/core/region.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
12951295
struct cxl_region_params *p = &cxlr->params;
12961296
struct cxl_decoder *cxld = cxl_rr->decoder;
12971297
struct cxl_switch_decoder *cxlsd;
1298+
struct cxl_port *iter = port;
12981299
u16 eig, peig;
12991300
u8 eiw, peiw;
13001301

@@ -1311,16 +1312,26 @@ static int cxl_port_setup_targets(struct cxl_port *port,
13111312

13121313
cxlsd = to_cxl_switch_decoder(&cxld->dev);
13131314
if (cxl_rr->nr_targets_set) {
1314-
int i, distance;
1315+
int i, distance = 1;
1316+
struct cxl_region_ref *cxl_rr_iter;
13151317

13161318
/*
1317-
* Passthrough decoders impose no distance requirements between
1318-
* peers
1319+
* The "distance" between peer downstream ports represents which
1320+
* endpoint positions in the region interleave a given port can
1321+
* host.
1322+
*
1323+
* For example, at the root of a hierarchy the distance is
1324+
* always 1 as every index targets a different host-bridge. At
1325+
* each subsequent switch level those ports map every Nth region
1326+
* position where N is the width of the switch == distance.
13191327
*/
1320-
if (cxl_rr->nr_targets == 1)
1321-
distance = 0;
1322-
else
1323-
distance = p->nr_targets / cxl_rr->nr_targets;
1328+
do {
1329+
cxl_rr_iter = cxl_rr_load(iter, cxlr);
1330+
distance *= cxl_rr_iter->nr_targets;
1331+
iter = to_cxl_port(iter->dev.parent);
1332+
} while (!is_cxl_root(iter));
1333+
distance *= cxlrd->cxlsd.cxld.interleave_ways;
1334+
13241335
for (i = 0; i < cxl_rr->nr_targets_set; i++)
13251336
if (ep->dport == cxlsd->target[i]) {
13261337
rc = check_last_peer(cxled, ep, cxl_rr,

drivers/cxl/pci.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,9 @@ static ssize_t rcd_pcie_cap_emit(struct device *dev, u16 offset, char *buf, size
836836
if (!root_dev)
837837
return -ENXIO;
838838

839+
if (!dport->regs.rcd_pcie_cap)
840+
return -ENXIO;
841+
839842
guard(device)(root_dev);
840843
if (!root_dev->driver)
841844
return -ENXIO;
@@ -1032,8 +1035,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
10321035
if (rc)
10331036
return rc;
10341037

1035-
rc = cxl_pci_ras_unmask(pdev);
1036-
if (rc)
1038+
if (cxl_pci_ras_unmask(pdev))
10371039
dev_dbg(&pdev->dev, "No RAS reporting unmasked\n");
10381040

10391041
pci_save_state(pdev);

0 commit comments

Comments
 (0)