mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Davidlohr Bueso <dave@stgolabs.net>
To: dave.jiang@intel.com
Cc: jic23@kernel.org, alison.schofield@intel.com, icheng@nvidia.com,
	benjamin.cheatham@amd.com, alucerop@amd.com,
	dongjoo.seo1@samsung.com, dave@stgolabs.net,
	linux-kernel@vger.kernel.org
Subject: [PATCH v6 9/9] cxl: Allow auto-committed BI hdm decoders
Date: Mon, 27 Jul 2026 12:36:01 -0700	[thread overview]
Message-ID: <20260727193601.651871-10-dave@stgolabs.net> (raw)
In-Reply-To: <20260727193601.651871-1-dave@stgolabs.net>

Allow auto-committed BI hdm decoders on sane platforms, rejecting
only broken paths (ie: one that cannot route BISnp, or BI paired
with a host-only target range type).

The respective region creation is done like any other committed
decoder - with cxlds->bi set by the time an decoder attaches.

A committed BI decoder under a window without the BI restriction is
refused (undefined behavior per the CFMWS Window Restrictions), as
is a committed decoder attaching to a region of a different
coherency model.

Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
 drivers/cxl/core/hdm.c    | 24 +++++++++++++++++-------
 drivers/cxl/core/pci.c    | 36 +++++++++++++++++++++++++++++-------
 drivers/cxl/core/region.c | 33 +++++++++++++++++++++++++++++++++
 drivers/cxl/port.c        |  4 ++++
 4 files changed, 83 insertions(+), 14 deletions(-)

diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index f437fe15c6df..c5be6fe4c77a 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -1061,13 +1061,23 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 		else
 			cxld->target_type = CXL_DECODER_DEVMEM;
 
-		/*
-		 * Autocommit BI-enabled decoders is not supported.
-		 * At this point cxlds->bi is not yet setup, so there
-		 * are no guarantees that the platform supports BI.
-		 */
-		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_BI, ctrl))
-			return -ENXIO;
+		if (FIELD_GET(CXL_HDM_DECODER0_CTRL_BI, ctrl)) {
+			struct cxl_dev_state *cxlds = cxled ?
+				cxled_to_memdev(cxled)->cxlds : NULL;
+
+			if (cxld->target_type == CXL_DECODER_HOSTONLYMEM) {
+				dev_warn(&port->dev,
+					 "decoder%d.%d: BI with host-only\n",
+					 port->id, cxld->id);
+				return -ENXIO;
+			}
+			if (cxlds && !cxlds->bi_capable) {
+				dev_warn(&port->dev,
+					 "decoder%d.%d: path not BI capable\n",
+					 port->id, cxld->id);
+				return -ENXIO;
+			}
+		}
 
 		guard(rwsem_write)(&cxl_rwsem.region);
 		if (cxld->id != cxl_num_decoders_committed(port)) {
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 554058ccb1e9..8d2651e06a79 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -1083,6 +1083,18 @@ static int __cxl_bi_commit_decoder(struct device *dev, void __iomem *bi)
 				    scale, base);
 }
 
+/* Committed, or no explicit commit required */
+static bool cxl_bi_decoder_committed(void __iomem *bi)
+{
+	u32 caps = readl(bi + CXL_BI_DECODER_CAPS_OFFSET);
+	u32 sts = readl(bi + CXL_BI_DECODER_STATUS_OFFSET);
+
+	if (!FIELD_GET(CXL_BI_DECODER_CAPS_EXPLICIT_COMMIT_REQ, caps))
+		return true;
+
+	return FIELD_GET(CXL_BI_DECODER_STATUS_BI_COMMITTED, sts);
+}
+
 /* Enable or dealloc BI-ID changes in the given level of the topology. */
 static int __cxl_bi_ctrl_dport(struct cxl_dport *dport, bool enable)
 {
@@ -1127,6 +1139,16 @@ static int __cxl_bi_ctrl_dport(struct cxl_dport *dport, bool enable)
 		return 0;
 	case PCI_EXP_TYPE_DOWNSTREAM:
 		if (enable) {
+			/*
+			 * Adopt a dport that was already programmed and
+			 * committed by firmware: nothing new is enabled
+			 * below it, so no commit is due.
+			 */
+			if (FIELD_GET(CXL_BI_DECODER_CTRL_BI_ENABLE, ctrl) &&
+			    !FIELD_GET(CXL_BI_DECODER_CTRL_BI_FW, ctrl) &&
+			    cxl_bi_decoder_committed(bi))
+				return 0;
+
 			value = ctrl & ~CXL_BI_DECODER_CTRL_BI_FW;
 			value |= CXL_BI_DECODER_CTRL_BI_ENABLE;
 		} else {
@@ -1173,11 +1195,11 @@ static int __cxl_bi_ctrl_endpoint(struct cxl_dev_state *cxlds, bool enable)
 
 	if (enable) {
 		if (FIELD_GET(CXL_BI_DECODER_CTRL_BI_ENABLE, ctrl)) {
-			if (cxlds->bi)
-				return 0;
-			dev_err(cxlds->dev,
-				"BI already enabled in hardware\n");
-			return -EBUSY;
+			/* adopt firmware enabled */
+			if (!cxlds->bi)
+				dev_dbg(cxlds->dev,
+					"adopting firmware-enabled BI\n");
+			goto done;
 		}
 		val = ctrl | CXL_BI_DECODER_CTRL_BI_ENABLE;
 	} else {
@@ -1192,11 +1214,11 @@ static int __cxl_bi_ctrl_endpoint(struct cxl_dev_state *cxlds, bool enable)
 	}
 
 	writel(val, bi + CXL_BI_DECODER_CTRL_OFFSET);
-	cxlds->bi = enable;
 
 	dev_dbg(cxlds->dev, "BI requests %s\n",
 		str_enabled_disabled(enable));
-
+done:
+	cxlds->bi = enable;
 	return 0;
 }
 
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 7c11d5788d99..5f72f5e1afc4 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -1832,6 +1832,21 @@ static int cxl_region_attach_position(struct cxl_region *cxlr,
 	return rc;
 }
 
+/* Read back the committed BI bit of an auto-discovered decoder */
+static bool cxled_committed_bi(struct cxl_endpoint_decoder *cxled)
+{
+	struct cxl_port *port = cxled_to_port(cxled);
+	struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
+	u32 ctrl;
+
+	if (!cxlhdm || !cxlhdm->regs.hdm_decoder)
+		return false;
+
+	ctrl = readl(cxlhdm->regs.hdm_decoder +
+		     CXL_HDM_DECODER0_CTRL_OFFSET(cxled->cxld.id));
+	return FIELD_GET(CXL_HDM_DECODER0_CTRL_BI, ctrl);
+}
+
 static int cxl_region_attach_auto(struct cxl_region *cxlr,
 				  struct cxl_endpoint_decoder *cxled, int pos)
 {
@@ -1844,6 +1859,16 @@ static int cxl_region_attach_auto(struct cxl_region *cxlr,
 		return -EINVAL;
 	}
 
+	/* A committed decoder may only join a region of its own flavor */
+	if (cxled_committed_bi(cxled) !=
+	    (cxlr->type == CXL_DECODER_DEVMEM &&
+	     cxl_root_decoder_is_bi(cxlr->cxlrd))) {
+		dev_err(&cxlr->dev, "%s:%s coherency model mismatch\n",
+			dev_name(&cxled_to_memdev(cxled)->dev),
+			dev_name(&cxled->cxld.dev));
+		return -ENXIO;
+	}
+
 	if (pos >= 0) {
 		dev_dbg(&cxlr->dev, "%s: expected auto position, not %d\n",
 			dev_name(&cxled->cxld.dev), pos);
@@ -3811,6 +3836,14 @@ static struct cxl_region *construct_region(struct cxl_root_decoder *cxlrd,
 	if (part < 0)
 		return ERR_PTR(-EBUSY);
 
+	/* avoid UB */
+	if (cxled_committed_bi(cxled) && !cxl_root_decoder_is_bi(cxlrd)) {
+		dev_err(cxlmd->dev.parent,
+			"%s:%s BI decoder in a non-BI window\n",
+			dev_name(&cxlmd->dev), dev_name(&cxled->cxld.dev));
+		return ERR_PTR(-ENXIO);
+	}
+
 	do {
 		cxlr = __create_region(cxlrd, cxlds->part[part].mode,
 				       atomic_read(&cxlrd->region_id),
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index ab3317fc1388..0c666ce00aa2 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -181,6 +181,10 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
 	if (rc)
 		return rc;
 
+	/*
+	 * Must precede region discovery so that any firmware-committed BI
+	 * decoder is adopted before its region is assembled.
+	 */
 	rc = cxl_bi_setup(port);
 	if (rc)
 		dev_dbg(&port->dev, "BI setup failed rc=%d\n", rc);
-- 
2.39.5


  parent reply	other threads:[~2026-07-27 19:36 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-27 19:35 [PATCH v6 0/9] cxl: Support Back-Invalidate Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 1/9] cxl: Add BI register probing and port initialization Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 2/9] cxl/pci: Add BI topology enable/disable Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 3/9] cxl/hdm: Add BI coherency support for endpoint decoders Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 4/9] cxl: Add HDM-DB region creation Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 5/9] cxl/hdm: Rename decoder coherency flags Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 6/9] cxl/region: Log the coherency model at region creation Davidlohr Bueso
2026-07-27 19:35 ` [PATCH v6 7/9] cxl: Move BI setup to endpoint port probe Davidlohr Bueso
2026-07-27 19:36 ` [PATCH v6 8/9] cxl/pci: Split BI capability probe from setup Davidlohr Bueso
2026-07-27 19:36 ` Davidlohr Bueso [this message]
2026-07-27 20:59 ` [PATCH v6 0/9] cxl: Support Back-Invalidate Jonathan Cameron
2026-07-27 21:26   ` Davidlohr Bueso
2026-07-27 23:02     ` Dave Jiang
2026-07-28  4:32       ` Davidlohr Bueso

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=20260727193601.651871-10-dave@stgolabs.net \
    --to=dave@stgolabs.net \
    --cc=alison.schofield@intel.com \
    --cc=alucerop@amd.com \
    --cc=benjamin.cheatham@amd.com \
    --cc=dave.jiang@intel.com \
    --cc=dongjoo.seo1@samsung.com \
    --cc=icheng@nvidia.com \
    --cc=jic23@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /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

all inboxes | Powered by JetHome®