On Thu, Mar 13, 2025 at 06:55:12PM +0100, Thomas Gleixner wrote: > On Thu, Mar 13 2025 at 15:50, Jonathan Cameron wrote: > >> + guard(msi_descs_lock)(&dev->dev); > >> + int ret = __msix_setup_interrupts(dev, entries, nvec, masks); > >> + if (ret) > >> + pci_free_msi_irqs(dev); > > > > It's not immediately obvious what this is undoing (i.e. where the alloc > > is). I think it is at least mostly the pci_msi_setup_msi_irqs in > > __msix_setup_interrupts > > It's a universal cleanup for all possible error cases. > > > Why not handle the error in __msix_setup_interrupts and make that function > > side effect free. Does require gotos but in a function that isn't > > doing any cleanup magic so should be fine. > > I had the gotos first and then hated them. But you are right, it's better > to have them than having the magic clean up at the call site. > > I'll fold the delta patch below. > > Thanks, > > tglx > --- > --- a/drivers/pci/msi/msi.c > +++ b/drivers/pci/msi/msi.c > @@ -671,19 +671,23 @@ static int __msix_setup_interrupts(struc > int ret = msix_setup_msi_descs(dev, entries, nvec, masks); > > if (ret) > - return ret; > + goto fail; > > ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); > if (ret) > - return ret; > + goto fail; > > /* Check if all MSI entries honor device restrictions */ > ret = msi_verify_entries(dev); > if (ret) > - return ret; > + goto fail; > > msix_update_entries(dev, entries); > return 0; > + > +fail: > + pci_free_msi_irqs(dev); > + return ret; > } How about something like: int __msix_setup_interrupts(struct device *_dev,... ) { struct device *dev __free(msi_irqs) = _dev; int ret = msix_setup_msi_descs(dev, entries, nvec, masks); if (ret) return ret; ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); if (ret) return ret; /* Check if all MSI entries honor device restrictions */ ret = msi_verify_entries(dev); if (ret) return ret; retain_ptr(dev); msix_update_entries(dev, entries); return 0; } ?