arch/arm/imx9, arch/arm64/imx9: Release eDMA lock before callbacks

Fix a potential deadlock in the DMA driver. DMA completion callbacks
may immediately submit another transfer, for example:

imx9_dmaterminate()
  -> imx9_dma_txcallback()
    -> imx9_dma_txavailable()
      -> uart_xmitchars_dma()
        -> imx9_dma_send()
          -> imx9_dmach_stop()
	    -> imx9_dmaterminate()

Resulting dmaterminate to take the same spinlock again. Fix this by moving
the spin_unlock_irqrestore_nopreempt before calling the callback. It is not
necessary to keep dma channel locked during the callback; the channel is
already free at this point.

This doesn't directly affect arch/arm/imx9 (the cortex-m version) because
it is not SMP (the spinlock is reduced to blocking irqs), but it is worth
fixing at the same to keep drivers in sync.

Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
Jukka Laitinen 2026-09-11 10:35:08 +03:00 • committed by Alan C. Assis
parent d5d93f6207
commit d8deca6c52
2 changed files with 4 additions and 4 deletions

View file

@ -548,12 +548,12 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result)
dmach->arg = NULL;
dmach->state = IMX9_DMA_IDLE;
spin_unlock_irqrestore_nopreempt(&g_edma.lock, flags);
if (callback)
{
callback((DMACH_HANDLE)dmach, arg, true, result);
}
spin_unlock_irqrestore_nopreempt(&g_edma.lock, flags);
}
/****************************************************************************

View file

@ -499,12 +499,12 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result)
dmach->arg = NULL;
dmach->state = IMX9_DMA_IDLE;
spin_unlock_irqrestore_nopreempt(&g_edma.lock, flags);
if (callback)
{
callback((DMACH_HANDLE)dmach, arg, true, result);
}
spin_unlock_irqrestore_nopreempt(&g_edma.lock, flags);
}
/****************************************************************************