Re: [PATCH 1/4] dmaengine: dw-edma-pcie: Free IRQ vectors on probe failures

From: Koichiro Den

Date: Thu May 21 2026 - 13:01:20 EST


On Thu, May 21, 2026 at 10:39:09AM -0400, Frank Li wrote:
> On Thu, May 21, 2026 at 11:21:50PM +0900, Koichiro Den wrote:
> > dw_edma_pcie_probe() leaks IRQ vectors by returning without calling
> > pci_free_irq_vectors() in error paths after pci_alloc_irq_vectors()
> > succeeds.
>
> I remember pcim_enable_device() already auto manage irqs.

You are right, pcim_enable_device() already manages the IRQ vectors.

Thanks for pointing it out. I'll drop patch 1 if I need to respin, or ask the
maintainers to disregard it when applying.

Best regards,
Koichiro

>
> Frank
>
> >
> > Route the post-allocation failures through a common cleanup path so the
> > vectors are released before probe returns.
> >
> > Fixes: 41aaff2a2ac0 ("dmaengine: Add Synopsys eDMA IP PCIe glue-logic")
> > Cc: stable@xxxxxxxxxxxxxxx
> > Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
> > ---
> > drivers/dma/dw-edma/dw-edma-pcie.c | 39 +++++++++++++++++++++---------
> > 1 file changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > index 0b30ce138503..87c31d01fb10 100644
> > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > @@ -410,8 +410,10 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > chip->ll_rd_cnt = vsec_data->rd_ch_cnt;
> >
> > chip->reg_base = pcim_iomap_table(pdev)[vsec_data->rg.bar];
> > - if (!chip->reg_base)
> > - return -ENOMEM;
> > + if (!chip->reg_base) {
> > + err = -ENOMEM;
> > + goto err_free_irq_vectors;
> > + }
> >
> > for (i = 0; i < chip->ll_wr_cnt && !non_ll; i++) {
> > struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
> > @@ -420,8 +422,10 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > struct dw_edma_block *dt_block = &vsec_data->dt_wr[i];
> >
> > ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
> > - if (!ll_region->vaddr.io)
> > - return -ENOMEM;
> > + if (!ll_region->vaddr.io) {
> > + err = -ENOMEM;
> > + goto err_free_irq_vectors;
> > + }
> >
> > ll_region->vaddr.io += ll_block->off;
> > ll_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
> > @@ -430,8 +434,10 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > ll_region->sz = ll_block->sz;
> >
> > dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
> > - if (!dt_region->vaddr.io)
> > - return -ENOMEM;
> > + if (!dt_region->vaddr.io) {
> > + err = -ENOMEM;
> > + goto err_free_irq_vectors;
> > + }
> >
> > dt_region->vaddr.io += dt_block->off;
> > dt_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
> > @@ -447,8 +453,10 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > struct dw_edma_block *dt_block = &vsec_data->dt_rd[i];
> >
> > ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
> > - if (!ll_region->vaddr.io)
> > - return -ENOMEM;
> > + if (!ll_region->vaddr.io) {
> > + err = -ENOMEM;
> > + goto err_free_irq_vectors;
> > + }
> >
> > ll_region->vaddr.io += ll_block->off;
> > ll_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
> > @@ -457,8 +465,10 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > ll_region->sz = ll_block->sz;
> >
> > dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
> > - if (!dt_region->vaddr.io)
> > - return -ENOMEM;
> > + if (!dt_region->vaddr.io) {
> > + err = -ENOMEM;
> > + goto err_free_irq_vectors;
> > + }
> >
> > dt_region->vaddr.io += dt_block->off;
> > dt_region->paddr = dw_edma_get_phys_addr(pdev, vsec_data,
> > @@ -513,20 +523,25 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > /* Validating if PCI interrupts were enabled */
> > if (!pci_dev_msi_enabled(pdev)) {
> > pci_err(pdev, "enable interrupt failed\n");
> > - return -EPERM;
> > + err = -EPERM;
> > + goto err_free_irq_vectors;
> > }
> >
> > /* Starting eDMA driver */
> > err = dw_edma_probe(chip);
> > if (err) {
> > pci_err(pdev, "eDMA probe failed\n");
> > - return err;
> > + goto err_free_irq_vectors;
> > }
> >
> > /* Saving data structure reference */
> > pci_set_drvdata(pdev, chip);
> >
> > return 0;
> > +
> > +err_free_irq_vectors:
> > + pci_free_irq_vectors(pdev);
> > + return err;
> > }
> >
> > static void dw_edma_pcie_remove(struct pci_dev *pdev)
> > --
> > 2.51.0
> >