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


Reply via email to