Re: [PATCH v11 10/31] cxl/mem: Configure dynamic capacity interrupts
Anisa Su <[email protected]> Wed, 15 Jul 2026 16:09:12 -0700
| Newsgroups | dev.linux.lists.nvdimm,dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Jun 25, 2026 at 06:14:41PM +0000, [email protected] wrote: > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: > - [High] An unhandled DCD event status bit will cause an infinite loop in the `cxl_event_thread` IRQ handler if DCD processing is disabled dynamically. Fixed > - [High] The driver fails to perform an initial drain of the DCD event log when the BIOS has control of standard CXL errors (`!native_cxl`), stranding pre-existing events. Fixed > -- > > commit 4e2d7455b6a9875d8ee530fc91ae3a8b65741caa > Author: Ira Weiny <[email protected]> > > cxl/mem: Configure dynamic capacity interrupts > > Dynamic Capacity Devices (DCD) support extent change notifications > through the event log mechanism. The interrupt mailbox commands were > extended in CXL 3.1 to support these notifications. Firmware can't > configure DCD events to be FW controlled but can retain control of > memory events. > > > diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c > > index 8d12c684d6700..95a4bf7c1e466 100644 > > --- a/drivers/cxl/pci.c > > +++ b/drivers/cxl/pci.c > [ ... ] > > @@ -632,6 +657,30 @@ static int cxl_event_irqsetup(struct cxl_memdev_state *mds, > > return 0; > > } > > > > +static int cxl_irqsetup(struct cxl_memdev_state *mds, > > + struct cxl_event_interrupt_policy *policy, > > + bool native_cxl) > > +{ > > + struct cxl_dev_state *cxlds = &mds->cxlds; > > + int rc; > > + > > + if (native_cxl) { > > + rc = cxl_event_irqsetup(mds, policy); > > + if (rc) > > + return rc; > > + } > > + > > + if (cxl_dcd_supported(mds)) { > > + rc = cxl_event_req_irq(cxlds, policy->dcd_settings); > > + if (rc) { > > + dev_err(cxlds->dev, "Failed to get interrupt for DCD event log\n"); > > + cxl_disable_dcd(mds); > > [Severity: High] > If cxl_event_req_irq() fails here, cxl_disable_dcd() is called, but the > device is already programmed to generate DCD interrupts. > > When a DCD event interrupt fires, cxl_event_thread() will read the status > and retain the CXLDEV_EVENT_STATUS_DCD bit because the mask includes it. > However, cxl_mem_get_event_records() skips draining the log when > cxl_dcd_supported() is false: > > drivers/cxl/core/mbox.c:cxl_mem_get_event_records() { > ... > if (cxl_dcd_supported(mds) && (status & CXLDEV_EVENT_STATUS_DCD)) > cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_DCD); > ... > } > > Will this cause cxl_event_thread() to spin in an infinite loop since the > status bit is never cleared by draining the log? > The fix is in cxl_event_thread(). Instead of setting the event drain mask based only on the value of native_cxl: mask = host_bridge->native_cxl_error ? CXLDEV_EVENT_STATUS_ALL : CXLDEV_EVENT_STATUS_DCD; we additionally check cxl_dcd_supported(), because the native_cxl value only determines if the standard logs are owned by firmware. DCD event logs are always OS owned. So the mask becomes: u32 mask = 0; if (host_bridge->native_cxl_error) mask |= CXLDEV_EVENT_STATUS_ALL & ~CXLDEV_EVENT_STATUS_DCD; if (cxl_dcd_supported(mds)) mask |= CXLDEV_EVENT_STATUS_DCD; This gets put in a new helper function cxl_event_drain_mask() because the second bug below uses it too. The helper is called from cxl_event_thread(): static irqreturn_t cxl_event_thread(int irq, void *id) { struct cxl_dev_id *dev_id = id; struct cxl_dev_state *cxlds = dev_id->cxlds; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); struct pci_host_bridge *host_bridge = pci_find_host_bridge(to_pci_dev(cxlds->dev)->bus); u32 mask = cxl_event_drain_mask(host_bridge, mds); ... So if dcd has been disabled afterwards, DCD events are still cleared. > > + } > > + } > > + > > + return 0; > > +} > [ ... ] > > @@ -687,11 +744,16 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, > > if (rc) > > return rc; > > > > - rc = cxl_event_irqsetup(mds, &policy); > > + rc = cxl_irqsetup(mds, &policy, native_cxl); > > if (rc) > > return rc; > > > > - cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); > > + if (native_cxl) > > + cxl_mem_get_event_records(mds, CXLDEV_EVENT_STATUS_ALL); > > [Severity: High] > If the BIOS has control of standard CXL errors (!native_cxl), does this skip > the initial drain of the DCD event log? > > Since the driver owns the DCD log regardless of native_cxl, it appears that > pre-existing DCD events might be left in the log, potentially preventing > subsequent edge-triggered interrupts from firing. > Fixed by calling previous defined helper cxl_event_drain_mask() which also checks if dcd is enabled. So if (native_cxl) cxl_mem_get_event_records() is replaced by status = cxl_event_drain_mask(host_bridge, mds); if (status) cxl_mem_get_event_records(mds, status); > > + > > + dev_dbg(mds->cxlds.dev, "Event config : %s DCD %s\n", > > + native_cxl ? "OS" : "BIOS", > > + cxl_dcd_supported(mds) ? "supported" : "not supported"); > > > > return 0; > > } > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=10