[PATCH v9 3/4] cxl/region: Start unmapped poison scan at the committed decoder boundary
From: Richard Cheng
Date: Tue Oct 20 2026 - 01:15:52 EST
poison_by_decoder() stops at the last committed decoder and records the
handoff in ctx->offset, but cxl_get_poison_unmapped() ignores it and
starts after the highest DPA allocation instead. Allocations exist for
uncommitted decoders too, so their DPA is skipped by both phases and
poison there is never reported. Resume the scan at ctx->offset, and scan
later partitions in full, restoring the pre-rewrite behavior.
Also reset ctx.offset when falling back to partition 0 in
cxl_get_poison_by_endpoint(). Resetting the partition and address
together makes the starting position for the full-partition scan
explicit.
Fixes: be5cbd084027 ("cxl: Kill enum cxl_decoder_mode")
Reviewed-by: Dave Jiang <dave.jiang@xxxxxxxxx>
Reviewed-by: Alison Schofield <alison.schofield@xxxxxxxxx>
Reviewed-by: Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx>
Reviewed-by: Davidlohr Bueso <dave@xxxxxxxxxxxx>
Signed-off-by: Richard Cheng <icheng@xxxxxxxxxx>
---
Changelog:
v8 -> v9:
- Rebase onto v7.3 of Linus tag
- Include the partition-0 fallback in cxl_get_poison_by_endpoint().
- Reset ctx.offset alongside ctx.part in that fallback, suggested by
Alison Schofield
---
drivers/cxl/core/region.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index ddf12075b95c..18114d25662b 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -2907,7 +2907,6 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
{
struct cxl_dev_state *cxlds = cxlmd->cxlds;
const struct resource *res;
- struct resource *p, *last;
u64 offset, length;
int rc = 0;
@@ -2920,10 +2919,8 @@ static int cxl_get_poison_unmapped(struct cxl_memdev *cxlmd,
*/
for (int i = ctx->part; i < cxlds->nr_partitions; i++) {
res = &cxlds->part[i].res;
- for (p = res->child, last = NULL; p; p = p->sibling)
- last = p;
- if (last)
- offset = last->end + 1;
+ if (i == ctx->part)
+ offset = ctx->offset;
else
offset = res->start;
length = res->end - offset + 1;
@@ -3001,9 +2998,14 @@ int cxl_get_poison_by_endpoint(struct cxl_port *port)
};
rc = device_for_each_child(&port->dev, &ctx, poison_by_decoder);
- if (rc == 1)
+ if (rc == 1) {
+ if (ctx.part < 0) {
+ ctx.part = 0;
+ ctx.offset = 0;
+ }
rc = cxl_get_poison_unmapped(to_cxl_memdev(port->uport_dev),
&ctx);
+ }
return rc;
}
--
2.43.0