Linux CXL
 help / color / mirror / Atom feed
From: Robert Richter <rrichter@amd.com>
To: Alison Schofield <alison.schofield@intel.com>,
	Vishal Verma <vishal.l.verma@intel.com>,
	Ira Weiny <ira.weiny@intel.com>,
	Dan Williams <dan.j.williams@intel.com>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	Dave Jiang <dave.jiang@intel.com>,
	Davidlohr Bueso <dave@stgolabs.net>
Cc: <linux-cxl@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	Gregory Price <gourry@gourry.net>,
	Terry Bowman <terry.bowman@amd.com>,
	Robert Richter <rrichter@amd.com>
Subject: [PATCH 2/2] cxl/pci: Check link status and only enable active dports
Date: Wed, 5 Mar 2025 11:01:23 +0100	[thread overview]
Message-ID: <20250305100123.3077031-3-rrichter@amd.com> (raw)
In-Reply-To: <20250305100123.3077031-1-rrichter@amd.com>

When downstream ports are enumerated, some of them may not be
connected to a corresponding endpoint or upstream switch port. The
dport is inactive and its link status is down then. For permanently
disabled ports a HwInit configuration mechanism (set by hardware or
firmware) may assign a (further unused) default port number. The port
number may be set to the same value accross other inactive links.
Those duplicate port numbers cause the downstream port enumeration to
fail including the root or switch port initialization
(cxl_switch_port_probe()) and all its active downstream ports.

Prevent a port initialization failure by checking the link status and
only enabling active dports. If a dport is inactive, there is no
matching component (endpoint or switch) connected to and thus, it must
not be enumerated and added to the kernel's CXL device hierarchy.
There is no device that will connect to an inactive dport.

Signed-off-by: Robert Richter <rrichter@amd.com>
---
 drivers/cxl/core/pci.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 524b8749cc0b..72683e1b41e3 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -32,6 +32,26 @@ struct cxl_walk_context {
 	int count;
 };
 
+static int get_port_num(struct pci_dev *pdev)
+{
+	u32 lnkcap, port_num;
+	u16 lnksta;
+
+	if (pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &lnkcap))
+		return -ENXIO;
+
+	/* Skip inactive links */
+	if (lnkcap & PCI_EXP_LNKCAP_DLLLARC) {
+		pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
+		if (!(lnksta & PCI_EXP_LNKSTA_DLLLA))
+			return -ENOENT;
+	}
+
+	port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap);
+
+	return port_num;
+}
+
 static int match_add_dports(struct pci_dev *pdev, void *data)
 {
 	struct cxl_walk_context *ctx = data;
@@ -39,7 +59,7 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
 	int type = pci_pcie_type(pdev);
 	struct cxl_register_map map;
 	struct cxl_dport *dport;
-	u32 lnkcap, port_num;
+	int port_num;
 	int rc;
 
 	if (pdev->bus != ctx->bus)
@@ -48,15 +68,17 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
 		return 0;
 	if (type != ctx->type)
 		return 0;
-	if (pci_read_config_dword(pdev, pci_pcie_cap(pdev) + PCI_EXP_LNKCAP,
-				  &lnkcap))
+
+	port_num = get_port_num(pdev);
+	if (port_num == -ENOENT)
+		pci_dbg(pdev, "Skipping dport, link is down\n");
+	if (port_num < 0)
 		return 0;
 
 	rc = cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
 	if (rc)
 		dev_dbg(&port->dev, "failed to find component registers\n");
 
-	port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap);
 	dport = devm_cxl_add_dport(port, &pdev->dev, port_num, map.resource);
 	if (IS_ERR(dport)) {
 		rc = PTR_ERR(dport);
-- 
2.39.5


  parent reply	other threads:[~2025-03-05 10:10 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-05 10:01 [PATCH 0/2] cxl/pci: Inactive downstream port handling Robert Richter
2025-03-05 10:01 ` [PATCH 1/2] cxl/pci: Ignore downstream ports with duplicate port IDs Robert Richter
2025-03-05 15:09   ` Ira Weiny
2025-03-07 15:28     ` Robert Richter
2025-03-14 12:11   ` Jonathan Cameron
2025-03-05 10:01 ` Robert Richter [this message]
2025-03-05 15:19   ` [PATCH 2/2] cxl/pci: Check link status and only enable active dports Ira Weiny
2025-03-07 15:43     ` Robert Richter
2025-03-07 20:51       ` Ira Weiny
2025-03-14 12:14   ` Jonathan Cameron
2025-03-05 19:06 ` [PATCH 0/2] cxl/pci: Inactive downstream port handling Dan Williams
2025-03-07 14:06   ` Robert Richter
2025-03-07 20:58     ` Dan Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250305100123.3077031-3-rrichter@amd.com \
    --to=rrichter@amd.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=alison.schofield@intel.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=dave@stgolabs.net \
    --cc=gourry@gourry.net \
    --cc=ira.weiny@intel.com \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=terry.bowman@amd.com \
    --cc=vishal.l.verma@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox