On Mon, Aug 03, 2026 at 05:34:45PM -0700, Alison Schofield wrote:
> On Fri, Jul 31, 2026 at 01:48:11AM -0700, Anisa Su wrote:
> > From: Ira Weiny <[email protected]>
> > 
> > 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.
> > 
> > Configure DCD event log interrupts on devices supporting dynamic
> > capacity.  Disable DCD if interrupts are not supported.
> > 
> > Care is taken to preserve the interrupt policy set by the FW if FW first
> > has been selected by the BIOS.
> 
> Hi Anisa,
> 
> I gave one comment in response to a Sashiko comment, wrt 'drain'.
> Another below-
> 
> 
> > +
> > +   /*
> > +    * A CXL 3.0+ device can carry dcd_settings field without DCD command
> > +    * support, so size the request by the device's policy_size and only
> > +    * enable the DCD interrupt when DCD commands are supported.
> > +    */
> > +   if (cxl_dcd_supported(mds))
> > +           policy->dcd_settings = CXL_INT_MSI_MSIX;
> >  
> >     mbox_cmd = (struct cxl_mbox_cmd) {
> >             .opcode = CXL_MBOX_OP_SET_EVT_INT_POLICY,
> >             .payload_in = policy,
> > -           .size_in = sizeof(*policy),
> > +           .size_in = policy_size,
> >     };
> 
> Can you help me understand what happens if policy_size is only 4 bytes.
> dcd_settings is never sent in the Set command. How do we know cxl_irqsetup()
> isn't using a value the device never accepted?
> 
Hmmm... good catch. If a non spec-compliant device reports support for all four 
48h commands in the
CEL but simultaneously reports a 4 byte policy_size, the device will never see
policy->dcd_settings. Then the re-read at the end of cxl_event_config_msgnums()
doesn't erase the value that was never really set on the device:

        /* Retrieve final interrupt settings */
        return cxl_event_get_int_policy(mds, policy, NULL);


^ reads into the same struct, the device returns 4 bytes again, and byte 5
keeps the value the driver just wrote. So "final interrupt settings" is
the driver's own value round-tripping back for that field, and
cxl_irqsetup() arms the DCD interrupt from it.

A spec-compliant device can't trigger this, since cxl_dcd_supported() requires 
all
four 48h commands in the CEL, DCD is CXL 3.x, and a 3.x Get Event
Interrupt Policy returns the 5 byte policy including dcd_settings. But to
enforce it explicitly in the driver, added the check below in 
cxl_event_config(),
before cxl_event_config_msgnums():

        /*
         * dcd_settings cannot be sent to a device whose policy is too short
         * to hold it, so the device would never accept the setting
         * cxl_irqsetup() arms the DCD interrupt with.
         */
        if (cxl_dcd_supported(mds) && policy_size < sizeof(policy)) {
                dev_warn(mds->cxlds.dev,
                         "DCD supported but interrupt policy is only %zu 
bytes\n",
                         policy_size);
                cxl_disable_dcd(mds);
        }

Disabling DCD makes cxl_dcd_supported() false, so the Set stops setting
dcd_settings and cxl_irqsetup() skips the DCD interrupt.

Thanks,
Anisa

> 
> >     rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
> > @@ -596,7 +635,7 @@ static int cxl_event_config_msgnums(struct 
> > cxl_memdev_state *mds,
> >     }
> >  
> >     /* Retrieve final interrupt settings */
> > -   return cxl_event_get_int_policy(mds, policy);
> > +   return cxl_event_get_int_policy(mds, policy, NULL);
> >  }
> 
> snip
> 

Reply via email to