[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