[PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure

From: Logan Gunthorpe

Date: Mon Jul 27 2026 - 14:19:09 EST


When switchtec_dma_create() fails after channels have been added to
dma_dev->channels (either from switchtec_dma_chans_enumerate()'s own
error path, or from dma_async_device_register() failing), the channels
are released and freed but never removed from dma_dev->channels.

Add switchtec_dma_chans_disable() which disables interrupts and
removes the channels from the list.. Call it before releasing and
freeing channels in both error paths.

Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@xxxxxxxxxxxxxxx
Link: https://lore.kernel.org/dmaengine/20260721162822.05CDD1F000E9@xxxxxxxxxxxxxxx
Signed-off-by: Logan Gunthorpe <logang@xxxxxxxxxxxx>
---
drivers/dma/switchtec_dma.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 31feb2816e79..800d8ecd0717 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1184,6 +1184,20 @@ static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
kfree(swdma_dev->swdma_chans);
}

+static void switchtec_dma_chans_disable(struct pci_dev *pdev,
+ struct switchtec_dma_dev *swdma_dev)
+{
+ int i;
+
+ if (swdma_dev->chan_status_irq >= 0) {
+ pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
+ swdma_dev->chan_status_irq = -1;
+ }
+
+ for (i = 0; i < swdma_dev->chan_cnt; i++)
+ list_del(&swdma_dev->swdma_chans[i]->dma_chan.device_node);
+}
+
static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
struct pci_dev *pdev, int chan_cnt)
{
@@ -1217,6 +1231,7 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
return chan_cnt;

err_exit:
+ switchtec_dma_chans_disable(pdev, swdma_dev);
switchtec_dma_chans_release(pdev, swdma_dev);
switchtec_dma_chans_free(swdma_dev);

@@ -1320,6 +1335,7 @@ static int switchtec_dma_create(struct pci_dev *pdev)
return 0;

err_chans_release_exit:
+ switchtec_dma_chans_disable(pdev, swdma_dev);
switchtec_dma_chans_release(pdev, swdma_dev);
switchtec_dma_chans_free(swdma_dev);

--
2.47.3