Commit b69810f3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 397d1d88 76467a94
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -1295,6 +1295,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
	struct cxl_region_params *p = &cxlr->params;
	struct cxl_decoder *cxld = cxl_rr->decoder;
	struct cxl_switch_decoder *cxlsd;
	struct cxl_port *iter = port;
	u16 eig, peig;
	u8 eiw, peiw;

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

	cxlsd = to_cxl_switch_decoder(&cxld->dev);
	if (cxl_rr->nr_targets_set) {
		int i, distance;
		int i, distance = 1;
		struct cxl_region_ref *cxl_rr_iter;

		/*
		 * Passthrough decoders impose no distance requirements between
		 * peers
		 * The "distance" between peer downstream ports represents which
		 * endpoint positions in the region interleave a given port can
		 * host.
		 *
		 * For example, at the root of a hierarchy the distance is
		 * always 1 as every index targets a different host-bridge. At
		 * each subsequent switch level those ports map every Nth region
		 * position where N is the width of the switch == distance.
		 */
		if (cxl_rr->nr_targets == 1)
			distance = 0;
		else
			distance = p->nr_targets / cxl_rr->nr_targets;
		do {
			cxl_rr_iter = cxl_rr_load(iter, cxlr);
			distance *= cxl_rr_iter->nr_targets;
			iter = to_cxl_port(iter->dev.parent);
		} while (!is_cxl_root(iter));
		distance *= cxlrd->cxlsd.cxld.interleave_ways;

		for (i = 0; i < cxl_rr->nr_targets_set; i++)
			if (ep->dport == cxlsd->target[i]) {
				rc = check_last_peer(cxled, ep, cxl_rr,
+4 −2
Original line number Diff line number Diff line
@@ -836,6 +836,9 @@ static ssize_t rcd_pcie_cap_emit(struct device *dev, u16 offset, char *buf, size
	if (!root_dev)
		return -ENXIO;

	if (!dport->regs.rcd_pcie_cap)
		return -ENXIO;

	guard(device)(root_dev);
	if (!root_dev->driver)
		return -ENXIO;
@@ -1032,8 +1035,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	if (rc)
		return rc;

	rc = cxl_pci_ras_unmask(pdev);
	if (rc)
	if (cxl_pci_ras_unmask(pdev))
		dev_dbg(&pdev->dev, "No RAS reporting unmasked\n");

	pci_save_state(pdev);