@@ -704,6 +704,10 @@ static void msgdma_tasklet(unsigned long data)
msgdma_chan_desc_cleanup(mdev);
}
+ /* Start next transfer if the DMA controller is idle */
+ if (mdev->idle)
+ msgdma_start_transfer(mdev);
+
spin_unlock(&mdev->lock);
}
@@ -720,13 +724,8 @@ static irqreturn_t msgdma_irq_handler(int irq, void *data)
u32 status;
status = ioread32(mdev->csr + MSGDMA_CSR_STATUS);
- if ((status & MSGDMA_CSR_STAT_BUSY) == 0) {
- /* Start next transfer if the DMA controller is idle */
- spin_lock(&mdev->lock);
+ if ((status & MSGDMA_CSR_STAT_BUSY) == 0)
mdev->idle = true;
- msgdma_start_transfer(mdev);
- spin_unlock(&mdev->lock);
- }
tasklet_schedule(&mdev->irq_tasklet);
Submitting new descriptors in the IRQ handler requires the lock to be held, which in turn should require interrupts to be disabled each time this lock is acquired in process context, which is not currently done. To reduce lock complexity and avoid deadlocks, move the new descriptor submission in the tasklet. Signed-off-by: Sylvain Lesne <lesne@alse-fr.com> --- Hi Stefan, here is a patch to do that. I tested it on my setup, and can confirm that I cannot reproduce the deadlock anymore! Since it's just reverting to code from your v2, I think I should add your signed-off-by as well, right? --- drivers/dma/altera-msgdma.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)