This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit d8deca6c52bc77df8dd408b14bb82a1391b272b7
Author: Jukka Laitinen <[email protected]>
AuthorDate: Fri Sep 11 10:35:08 2026 +0300

    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 <[email protected]>
---
 arch/arm/src/imx9/imx9_edma.c   | 4 ++--
 arch/arm64/src/imx9/imx9_edma.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/src/imx9/imx9_edma.c b/arch/arm/src/imx9/imx9_edma.c
index c045c120a92..c6efff7b3a2 100644
--- a/arch/arm/src/imx9/imx9_edma.c
+++ b/arch/arm/src/imx9/imx9_edma.c
@@ -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);
 }
 
 /****************************************************************************
diff --git a/arch/arm64/src/imx9/imx9_edma.c b/arch/arm64/src/imx9/imx9_edma.c
index af85d41dafa..08327f5d092 100644
--- a/arch/arm64/src/imx9/imx9_edma.c
+++ b/arch/arm64/src/imx9/imx9_edma.c
@@ -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);
 }
 
 /****************************************************************************

Reply via email to