Re: [PATCH v4 4/4] cxl/hdm: Restore commit_end when decoder enumeration fails
Alison Schofield <[email protected]>
| Newsgroups | org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Jul 21, 2026 at 08:12:39AM -0700, Dave Jiang wrote:
>
>
> On 7/20/26 6:59 PM, Alison Schofield wrote:
> > commit_end tracks the highest committed decoder on a port. It gets
> > advanced before decoder enumeration is complete, so a later failure
> > leaves it pointing at a decoder that was never added. The next probe
> > then rejects decoder0 as out of order and enumeration fails.
> >
> > Reset commit_end to the none committed baseline once the decoders are
>
> s/none committed/uncommitted/ ?
Done, thanks!
>
> > torn down, so a subsequent probe rebuilds it from scratch. Register
> > the reset before the decoders are added so that on unwind it runs
> > after every decoder has been unregistered. This prevents commit_end
> > from dropping below the highest committed decoder still registered and
> > exposing an inconsistent value to a concurrent reader.
> >
> > Protect the commit_end advance in the DVSEC emulation path against
> > concurrent readers, matching the register-programmed path.
> >
> > Fixes: 176baefb2eb5 ("cxl/hdm: Commit decoder state to hardware")
> > Fixes: b777e9bec960 ("cxl/hdm: Emulate HDM decoder from DVSEC range registers")
> > Signed-off-by: Alison Schofield <[email protected]>
>
> Reviewed-by: Dave Jiang <[email protected]>
>
>
> > ---
> > drivers/cxl/core/hdm.c | 23 ++++++++++++++++++++---
> > 1 file changed, 20 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
> > index 077aface1a2a..7d4ba7fa30fa 100644
> > --- a/drivers/cxl/core/hdm.c
> > +++ b/drivers/cxl/core/hdm.c
> > @@ -955,7 +955,8 @@ static int cxl_setup_hdm_decoder_from_dvsec(
> > * change the range registers at run time.
> > */
> > cxld->flags |= CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK;
> > - port->commit_end = cxld->id;
> > + scoped_guard(rwsem_write, &cxl_rwsem.region)
> > + port->commit_end = cxld->id;
> >
> > rc = devm_cxl_dpa_reserve(cxled, *dpa_base, len, 0);
> > if (rc) {
> > @@ -1181,6 +1182,14 @@ static void cxl_settle_decoders(struct cxl_hdm *cxlhdm)
> > msleep(20);
> > }
> >
> > +static void cxl_reset_commit_end(void *data)
> > +{
> > + struct cxl_port *port = data;
> > +
> > + guard(rwsem_write)(&cxl_rwsem.region);
> > + port->commit_end = -1;
> > +}
> > +
> > /**
> > * devm_cxl_enumerate_decoders - add decoder objects per HDM register set
> > * @cxlhdm: Structure to populate with HDM capabilities
> > @@ -1191,13 +1200,21 @@ static int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
> > {
> > void __iomem *hdm = cxlhdm->regs.hdm_decoder;
> > struct cxl_port *port = cxlhdm->port;
> > - int i;
> > u64 dpa_base = 0;
> > + int i, rc;
> >
> > cxl_settle_decoders(cxlhdm);
> >
> > + /*
> > + * Reset commit_end after all decoders have been torn down so a
> > + * subsequent probe rebuilds it from scratch.
> > + */
> > + rc = devm_add_action(&port->dev, cxl_reset_commit_end, port);
> > + if (rc)
> > + return rc;
> > +
> > for (i = 0; i < cxlhdm->decoder_count; i++) {
> > - int rc, target_count = cxlhdm->target_count;
> > + int target_count = cxlhdm->target_count;
> > struct cxl_decoder *cxld;
> >
> > if (is_cxl_endpoint(port)) {
>