dmaengine: switchtec-dma: disable channels before freeing on registration failure

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 channel
status IRQ is still live while the channels are released and freed,
so it can fire mid-teardown against channels that are only partially
torn down.

Add switchtec_dma_chans_disable(), which frees the channel status IRQ
before releasing and freeing channels in both error paths.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
Link: https://lore.kernel.org/dmaengine/20260721162822.05CDD1F000E9@smtp.kernel.org
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Link: https://patch.msgid.link/20260902062153.31048-7-logang@deltatee.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Logan Gunthorpe 2026-09-02 00:21:48 -06:00 committed by Vinod Koul
parent 268f9159eb
commit 5b4c561554

View File

@ -1185,6 +1185,15 @@ 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)
{
if (swdma_dev->chan_status_irq >= 0) {
pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
swdma_dev->chan_status_irq = -1;
}
}
static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
struct pci_dev *pdev, int chan_cnt)
{
@ -1218,6 +1227,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);
@ -1321,6 +1331,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);