Re: [PATCH v3 3/3] cxl/hdm: Restore commit_end when decoder enumeration fails
Alison Schofield <[email protected]>
| Newsgroups | org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
On Mon, Jul 20, 2026 at 02:14:30PM +0800, Li Ming wrote:
>
> 在 2026/7/18 05:42, Alison Schofield 写道:
> > 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
> > 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]>
> > ---
> > 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 4aaadb842d90..6dc6e53c28c6 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) {
> > @@ -1183,18 +1184,34 @@ static void cxl_settle_decoders(struct cxl_hdm *cxlhdm)
> > * @cxlhdm: Structure to populate with HDM capabilities
> > * @info: cached DVSEC range register info
> > */
> > +static void cxl_reset_commit_end(void *data)
> > +{
> > + struct cxl_port *port = data;
> > +
> > + guard(rwsem_write)(&cxl_rwsem.region);
> > + port->commit_end = -1;
> > +}
> > +
> > static int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
> > struct cxl_endpoint_dvsec_info *info)
> > {
> > 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_or_reset(&port->dev, cxl_reset_commit_end, port);
> > + if (rc)
> > + return rc;
>
> Seems like devm_add_action() is enough here. port->commit_end is -1 already.
Agree. The reset on fail would only write -1 over -1.
Changed in v4. Please take a look.
-- Alison