Re: [PATCH] cxl/hdm: Avoid DVSEC fallback after region teardown
From: Alison Schofield
Date: Thu Feb 12 2026 - 23:32:32 EST
On Thu, Feb 12, 2026 at 10:38:00PM +0000, Smita Koralahalli wrote:
> After destroy-region, cxl_region_decode_reset() clears the HDM decoder
> registers (base/size/commit). If the memdev is subsequently bounced
> (disable/enable), port probe re-evaluates decoder capability via
> should_emulate_decoders().
>
> The existing logic checks each decoder's COMMITTED bit. Since those bits
> are cleared by region teardown, should_emulate_decoders() incorrectly
> falls back to DVSEC range emulation, even though HDM capability is still
> present.
>
> DVSEC fallback marks the endpoint decoder as AUTO, which triggers
> cxl_add_to_region() -> construct_region(). That path copies the default
> interleave_granularity (4096) into the region parameters. The resulting
> spurious autodiscovered region consumes the CFMWS HPA space and causes a
> subsequent create-region to fail in hpa_alloc().
>
> Use the global CXL_HDM_DECODER_ENABLE bit instead of per-decoder COMMITTED
> bits to detect HDM capability. If the HDM decoder block is enabled, zeroed
> registers indicate teardown, not absence of HDM support. This prevents the
> unintended DVSEC fallback and subsequent region creation failure.
Nice find Smita!
I tried this out following your recipe w an auto region:
disable/destroy the region then disable/enable one memdev.
There was a problem before the patch that went away after the patch,
but the signature was different. In my case, the endpoint tried and
failed to begin construction on a new auto region yet still blocked
recreation of the original region because it consumed an endpoint
decoder, not the HPA space.
Memdev enable led to this:
[] cxl_pci 0000:da:00.0: mem3:decoder12.0 no CXL window for range 0x0:0x1fffffffff
which comes from cxl_add_to_region()->get_cxl_root_decoder()
And then the original region fails to recreate with:
cxl region: cxl_memdev_find_decoder: could not get a free decoder for mem3
Did you see any of that or totally different messaging?
It would be nice to confirm any varietals here and add useful signatures
to the commit log to help with searches.
-- Alison
>
> Based on cxl/fixes.
> base-commit: 8441c7d3bd6c5a52ab2ecf77e43a5bf262004f5c
>
> Fixes: 52cc48ad2a76 ("cxl/hdm: Limit emulation to the number of range registers")
> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@xxxxxxx>
> ---
> drivers/cxl/core/hdm.c | 25 +++++++++----------------
> 1 file changed, 9 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> index eb5a3a7640c6..a0718cbcc355 100644
> --- a/drivers/cxl/core/hdm.c
> +++ b/drivers/cxl/core/hdm.c
> @@ -94,7 +94,6 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
> struct cxl_hdm *cxlhdm;
> void __iomem *hdm;
> u32 ctrl;
> - int i;
>
> if (!info)
> return false;
> @@ -113,22 +112,16 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
> return false;
>
> /*
> - * If any decoders are committed already, there should not be any
> - * emulated DVSEC decoders.
> + * If HDM decoders are globally enabled, do not fall back to DVSEC
> + * range emulation. Zeroed decoder registers after region teardown
> + * do not imply absence of HDM capability.
> + *
> + * Falling back to DVSEC here would treat the decoder as AUTO and
> + * may incorrectly latch default interleave settings.
> */
> - for (i = 0; i < cxlhdm->decoder_count; i++) {
> - ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
> - dev_dbg(&info->port->dev,
> - "decoder%d.%d: committed: %ld base: %#x_%.8x size: %#x_%.8x\n",
> - info->port->id, i,
> - FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl),
> - readl(hdm + CXL_HDM_DECODER0_BASE_HIGH_OFFSET(i)),
> - readl(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(i)),
> - readl(hdm + CXL_HDM_DECODER0_SIZE_HIGH_OFFSET(i)),
> - readl(hdm + CXL_HDM_DECODER0_SIZE_LOW_OFFSET(i)));
> - if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
> - return false;
> - }
> + ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET);
> + if (ctrl & CXL_HDM_DECODER_ENABLE)
> + return false;
>
> return true;
> }
> --
> 2.17.1
>