[PATCH v4 2/4] cxl/hdm: Only interpret interleave settings on committed decoders

Alison Schofield <[email protected]>
Newsgroups org.kernel.vger.linux-cxl
Message-ID <48e04e2688a636d90b6e49f3e0c2dca78f773c4f.1784595445.git.alison.schofield@intel.com>
Decoder enumeration reads the interleave ways and granularity fields
from the CTRL register unconditionally, then decodes and validates
them for every decoder. On an uncommitted decoder these fields are
stale. They hold whatever was last latched and are reprogrammed when
the decoder is committed. Interpreting them serves no purpose, and
rejecting enumeration on a reserved encoding in those stale bits can
fail an otherwise usable decoder.

Decode and validate interleave ways and granularity only when the
decoder is committed. On an uncommitted decoder the stale register
values are not interpreted. The interleave fields are set when the
decoder is programmed at commit time.


Reported-by: Li Ming <[email protected]>
Closes: https://lore.kernel.org/all/[email protected]/
Signed-off-by: Alison Schofield <[email protected]>
---
 drivers/cxl/core/hdm.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index d81df45d8005..1f995191baf5 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -1064,21 +1064,24 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
 			writel(ctrl, hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
 		}
 	}
-	rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
-			  &cxld->interleave_ways);
-	if (rc) {
-		dev_warn(&port->dev,
-			 "decoder%d.%d: Invalid interleave ways (ctrl: %#x)\n",
-			 port->id, cxld->id, ctrl);
-		return rc;
-	}
-	rc = eig_to_granularity(FIELD_GET(CXL_HDM_DECODER0_CTRL_IG_MASK, ctrl),
-				 &cxld->interleave_granularity);
-	if (rc) {
-		dev_warn(&port->dev,
-			 "decoder%d.%d: Invalid interleave granularity (ctrl: %#x)\n",
-			 port->id, cxld->id, ctrl);
-		return rc;
+	/* Interleave settings are only valid on a committed decoder */
+	if (committed) {
+		rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
+				 &cxld->interleave_ways);
+		if (rc) {
+			dev_warn(&port->dev,
+				 "decoder%d.%d: Invalid interleave ways (ctrl: %#x)\n",
+				 port->id, cxld->id, ctrl);
+			return rc;
+		}
+		rc = eig_to_granularity(FIELD_GET(CXL_HDM_DECODER0_CTRL_IG_MASK, ctrl),
+					&cxld->interleave_granularity);
+		if (rc) {
+			dev_warn(&port->dev,
+				 "decoder%d.%d: Invalid interleave granularity (ctrl: %#x)\n",
+				 port->id, cxld->id, ctrl);
+			return rc;
+		}
 	}
 
 	dev_dbg(&port->dev, "decoder%d.%d: range: %#llx-%#llx iw: %d ig: %d\n",
-- 
2.37.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.