[PATCH v3 7/9] cxl/region: Fail region creation on position check mismatch

Alison Schofield <[email protected]> Thu, 30 Jul 2026 15:20:27 -0700
Newsgroups org.kernel.vger.linux-cxl
Message-ID <73e263e243583a26d0ab302a4f39aabc4a47b105.1785444498.git.alison.schofield@intel.com>
The position check in cxl_region_attach() only logged a mismatch
between the attach-order position and the auto-discovery calculator.
A mismatch means the same configuration would decode wrong when
presented as CXL_REGION_F_AUTO, yet region creation still succeeded.

Fail region creation on a mismatch, before the region reaches
CXL_CONFIG_ACTIVE, so a configuration that cannot round-trip through
auto-discovery cannot be committed.

Since cxl_region_setup_targets() has already programmed the topology
at this point, tear it down before returning so a later detach can
cleanly replace the endpoint.

Signed-off-by: Alison Schofield <[email protected]>
---
 drivers/cxl/core/region.c | 46 +++++++++++++++++++--------------------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index b4e8ebe158f7..62179d987e4b 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2492,6 +2492,29 @@ static int cxl_region_attach(struct cxl_region *cxlr,
 		rc = cxl_region_setup_targets(cxlr);
 		if (rc)
 			return rc;
+
+		/*
+		 * Verify that auto-discovery reconstructs the endpoint
+		 * positions assigned while creating the region.
+		 */
+		root_pos_per_target = root_positions_per_target(cxlr);
+		for (int i = 0; i < p->nr_targets; i++) {
+			struct cxl_endpoint_decoder *target = p->targets[i];
+			int test_pos;
+
+			test_pos = cxl_calc_interleave_pos(target,
+							   &cxlr->hpa_range,
+							   root_pos_per_target,
+							   p->interleave_granularity);
+			if (test_pos != target->pos) {
+				dev_err(&target->cxld.dev,
+					"cxl_calc_interleave_pos() mismatch: test_pos:%d target->pos:%d\n",
+					test_pos, target->pos);
+				cxl_region_teardown_targets(cxlr);
+				return -ENXIO;
+			}
+		}
+
 		p->state = CXL_CONFIG_ACTIVE;
 		cxl_region_shared_upstream_bandwidth_update(cxlr);
 	}
@@ -2503,29 +2526,6 @@ static int cxl_region_attach(struct cxl_region *cxlr,
 		.end = p->res->end,
 	};
 
-	if (p->nr_targets != p->interleave_ways)
-		return 0;
-
-	/*
-	 * Test the auto-discovery position calculator function
-	 * against this successfully created user-defined region.
-	 * A fail message here means that this interleave config
-	 * will fail when presented as CXL_REGION_F_AUTO.
-	 */
-	root_pos_per_target = root_positions_per_target(cxlr);
-	for (int i = 0; i < p->nr_targets; i++) {
-		struct cxl_endpoint_decoder *target = p->targets[i];
-		int test_pos;
-
-		test_pos = cxl_calc_interleave_pos(target, &cxlr->hpa_range,
-						   root_pos_per_target,
-						   p->interleave_granularity);
-		dev_dbg(&target->cxld.dev,
-			"Test cxl_calc_interleave_pos(): %s test_pos:%d target->pos:%d\n",
-			(test_pos == target->pos) ? "success" : "fail",
-			test_pos, target->pos);
-	}
-
 	return 0;
 }
 
-- 
2.37.3