The probe failure paths after IRQ setup free channel state while
hardware interrupts can still be enabled. A concurrent interrupt can
then walk lch_map[] and access channel memory that teardown is
releasing.
Disable IRQENABLE_L1 and clear irq_enable_mask under irq_lock before
teardown, then read IRQENABLE_L1 back to flush the posted write. Guard
the L1 accesses for legacy platforms where that register is not
mapped.
Fixes: 7bedaa553760 ("dmaengine: add OMAP DMA engine driver")
Cc: [email protected]
Assisted-by: Codex:GPT-5
Signed-off-by: Rosen Penev <[email protected]>
---
drivers/dma/ti/omap-dma.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index cef4e3a38b04..61a935660341 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -1811,6 +1811,13 @@ static int omap_dma_probe(struct platform_device *pdev)
if (rc) {
pr_warn("OMAP-DMA: failed to register slave DMA engine device:
%d\n",
rc);
+ if (!omap_dma_legacy(od)) {
+ spin_lock_irq(&od->irq_lock);
+ od->irq_enable_mask = 0;
+ omap_dma_glbl_write(od, IRQENABLE_L1, 0);
+ spin_unlock_irq(&od->irq_lock);
+ omap_dma_glbl_read(od, IRQENABLE_L1);
+ }
if (od->ll123_supported)
dma_pool_destroy(od->desc_pool);
omap_dma_free(od);
@@ -1828,6 +1835,13 @@ static int omap_dma_probe(struct platform_device *pdev)
if (rc) {
pr_warn("OMAP-DMA: failed to register DMA
controller\n");
dma_async_device_unregister(&od->ddev);
+ if (!omap_dma_legacy(od)) {
+ spin_lock_irq(&od->irq_lock);
+ od->irq_enable_mask = 0;
+ omap_dma_glbl_write(od, IRQENABLE_L1, 0);
+ spin_unlock_irq(&od->irq_lock);
+ omap_dma_glbl_read(od, IRQENABLE_L1);
+ }
if (od->ll123_supported)
dma_pool_destroy(od->desc_pool);
omap_dma_free(od);
--
2.54.0