From 10da822304832f5075aff8ab3159762e4f3e3208 Mon Sep 17 00:00:00 2001 From: hujun5 Date: Sun, 22 Dec 2024 16:54:20 +0800 Subject: [PATCH] use small lock in following file arch/arm/src/efm32/efm32_leserial.c arch/arm/src/efm32/efm32_serial.c arch/arm/src/gd32f4/gd32f4xx_serial.c arch/arm/src/imx9/imx9_edma.c arch/arm/src/imxrt/imxrt_edma.c arch/arm/src/imxrt/imxrt_hprtc.c arch/arm/src/kinetis/kinetis_lpserial.c arch/arm/src/lc823450/lc823450_gpio.c arch/arm/src/s32k1xx/s32k1xx_edma.c arch/arm/src/s32k3xx/s32k3xx_edma.c arch/arm64/src/imx9/imx9_edma.c Signed-off-by: hujun5 --- arch/arm/src/efm32/efm32_leserial.c | 35 ++++++++++++------ arch/arm/src/efm32/efm32_serial.c | 38 +++++++++++++------- arch/arm/src/gd32f4/gd32f4xx_serial.c | 17 ++++++--- arch/arm/src/imx9/imx9_edma.c | 47 +++++++++++++++++-------- arch/arm/src/imxrt/imxrt_edma.c | 40 ++++++++++++++------- arch/arm/src/imxrt/imxrt_hprtc.c | 7 ++-- arch/arm/src/kinetis/kinetis_lpserial.c | 30 ++++++++++++---- arch/arm/src/lc823450/lc823450_gpio.c | 14 ++++---- arch/arm/src/s32k1xx/s32k1xx_edma.c | 44 ++++++++++++++++------- arch/arm/src/s32k3xx/s32k3xx_edma.c | 46 +++++++++++++++++------- arch/arm64/src/imx9/imx9_edma.c | 47 +++++++++++++++++-------- 11 files changed, 254 insertions(+), 111 deletions(-) diff --git a/arch/arm/src/efm32/efm32_leserial.c b/arch/arm/src/efm32/efm32_leserial.c index 9e70547ba7750..560591923175b 100644 --- a/arch/arm/src/efm32/efm32_leserial.c +++ b/arch/arm/src/efm32/efm32_leserial.c @@ -134,6 +134,7 @@ struct efm32_leuart_s { const struct efm32_config_s *config; uint16_t ien; /* Interrupts enabled */ + spinlock_t lock; /* Spinlock */ }; /**************************************************************************** @@ -212,6 +213,7 @@ static const struct efm32_config_s g_leuart0config = static struct efm32_leuart_s g_leuart0priv = { .config = &g_leuart0config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_leuart0port = @@ -247,6 +249,7 @@ static struct efm32_config_s g_leuart1config = static struct efm32_leuart_s g_leuart1priv = { .config = &g_leuart1config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_leuart1port = @@ -303,6 +306,17 @@ static inline void efm32_setuartint(struct efm32_leuart_s *priv) * Name: efm32_restoreuartint ****************************************************************************/ +static void efm32_restoreuartint_nolock(struct efm32_leuart_s *priv, + uint32_t ien) +{ + /* Re-enable/re-disable interrupts corresponding to the state of + * bits in ien. + */ + + priv->ien = ien; + efm32_setuartint(priv); +} + static void efm32_restoreuartint(struct efm32_leuart_s *priv, uint32_t ien) { irqstate_t flags; @@ -311,10 +325,9 @@ static void efm32_restoreuartint(struct efm32_leuart_s *priv, uint32_t ien) * bits in ien. */ - flags = spin_lock_irqsave(NULL); - priv->ien = ien; - efm32_setuartint(priv); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&priv->lock); + efm32_restoreuartint_nolock(priv, len); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -325,14 +338,14 @@ static void efm32_disableuartint(struct efm32_leuart_s *priv, uint32_t *ien) { irqstate_t flags; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (ien) { *ien = priv->ien; } - efm32_restoreuartint(priv, 0); - spin_unlock_irqrestore(NULL, flags); + efm32_restoreuartint_nolock(priv, 0); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -607,7 +620,7 @@ static void efm32_rxint(struct uart_dev_s *dev, bool enable) struct efm32_leuart_s *priv = (struct efm32_leuart_s *)dev->priv; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->lock); if (enable) { /* Receive an interrupt when there is anything in the Rx data register @@ -625,7 +638,7 @@ static void efm32_rxint(struct uart_dev_s *dev, bool enable) efm32_setuartint(priv); } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -673,7 +686,7 @@ static void efm32_txint(struct uart_dev_s *dev, bool enable) struct efm32_leuart_s *priv = (struct efm32_leuart_s *)dev->priv; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->lock); if (enable) { /* Enable the TX interrupt */ @@ -697,7 +710,7 @@ static void efm32_txint(struct uart_dev_s *dev, bool enable) efm32_setuartint(priv); } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/efm32/efm32_serial.c b/arch/arm/src/efm32/efm32_serial.c index a2bfcbbe5fd9a..087465195d550 100644 --- a/arch/arm/src/efm32/efm32_serial.c +++ b/arch/arm/src/efm32/efm32_serial.c @@ -223,6 +223,7 @@ struct efm32_usart_s const struct efm32_config_s *config; #endif uint16_t ien; /* Interrupts enabled */ + spinlock_t lock; /* Spinlock */ }; /**************************************************************************** @@ -303,7 +304,7 @@ static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; /* This describes the state of the EFM32 USART0 port. */ #ifdef CONFIG_EFM32_USART0_ISUART -static const struct efm32_usart_s g_usart0config = +static const struct efm32_config_s g_usart0config = { .uartbase = EFM32_USART0_BASE, .baud = CONFIG_USART0_BAUD, @@ -317,6 +318,7 @@ static const struct efm32_usart_s g_usart0config = static struct efm32_usart_s g_usart0priv = { .config = &g_usart0config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_usart0port = @@ -353,6 +355,7 @@ static struct efm32_config_s g_usart1config = static struct efm32_usart_s g_usart1priv = { .config = &g_usart1config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_usart1port = @@ -389,6 +392,7 @@ static struct efm32_config_s g_usart2config = static struct efm32_usart_s g_usart2priv = { .config = &g_usart2config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_usart2port = @@ -425,6 +429,7 @@ static struct efm32_config_s g_uart0config = static struct efm32_usart_s g_uart0priv = { .config = &g_uart0config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_uart0port = @@ -447,7 +452,7 @@ static struct uart_dev_s g_uart0port = /* This describes the state of the EFM32 UART1 port. */ #ifdef CONFIG_EFM32_UART1 -static struct efm32_usart_s g_uart1config = +static struct efm32_config_s g_uart1config = { .uartbase = EFM32_UART1_BASE, .baud = CONFIG_UART1_BAUD, @@ -461,6 +466,7 @@ static struct efm32_usart_s g_uart1config = static struct efm32_usart_s g_uart1priv = { .config = &g_uart1config, + .lock = SP_UNLOCKED }; static struct uart_dev_s g_uart1port = @@ -516,6 +522,13 @@ static inline void efm32_setuartint(struct efm32_usart_s *priv) * Name: efm32_restoreuartint ****************************************************************************/ +static void efm32_restoreuartint_nolock(struct efm32_usart_s *priv, + uint32_t ien) +{ + priv->ien = ien; + efm32_setuartint(priv); +} + static void efm32_restoreuartint(struct efm32_usart_s *priv, uint32_t ien) { irqstate_t flags; @@ -524,10 +537,9 @@ static void efm32_restoreuartint(struct efm32_usart_s *priv, uint32_t ien) * ien */ - flags = spin_lock_irqsave(NULL); - priv->ien = ien; - efm32_setuartint(priv); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&priv->lock); + efm32_restoreuartint_nolock(priv, len); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -539,14 +551,14 @@ static void efm32_disableuartint(struct efm32_usart_s *priv, uint32_t *ien) { irqstate_t flags; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (ien) { *ien = priv->ien; } - efm32_restoreuartint(priv, 0); - spin_unlock_irqrestore(NULL, flags); + efm32_restoreuartint_nolock(priv, 0); + spin_unlock_irqrestore(&priv->lock, flags); } #endif @@ -966,7 +978,7 @@ static void efm32_rxint(struct uart_dev_s *dev, bool enable) struct efm32_usart_s *priv = (struct efm32_usart_s *)dev->priv; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->lock); if (enable) { /* Receive an interrupt when their is anything in the Rx data register @@ -984,7 +996,7 @@ static void efm32_rxint(struct uart_dev_s *dev, bool enable) efm32_setuartint(priv); } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -1032,7 +1044,7 @@ static void efm32_txint(struct uart_dev_s *dev, bool enable) struct efm32_usart_s *priv = (struct efm32_usart_s *)dev->priv; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->lock); if (enable) { /* Enable the TX interrupt */ @@ -1056,7 +1068,7 @@ static void efm32_txint(struct uart_dev_s *dev, bool enable) efm32_setuartint(priv); } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/gd32f4/gd32f4xx_serial.c b/arch/arm/src/gd32f4/gd32f4xx_serial.c index 49176c6b52fc3..ad903b6c7a59d 100644 --- a/arch/arm/src/gd32f4/gd32f4xx_serial.c +++ b/arch/arm/src/gd32f4/gd32f4xx_serial.c @@ -131,6 +131,7 @@ struct up_dev_s uint8_t stop_2bits; /* True: Configure with 2 stop bits instead of 1 */ uint32_t tx_gpio; /* USART TX GPIO pin configuration */ uint32_t rx_gpio; /* USART RX GPIO pin configuration */ + spinlock_t lock; /* Spinlock */ # ifdef CONFIG_SERIAL_IFLOWCONTROL uint32_t rts_gpio; /* UART RTS GPIO pin configuration */ @@ -437,6 +438,7 @@ static struct up_dev_s g_usart0priv = .tx_gpio = GPIO_USART0_TX, .rx_gpio = GPIO_USART0_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART0_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_USART0_RTS, @@ -509,6 +511,7 @@ static struct up_dev_s g_usart1priv = .tx_gpio = GPIO_USART1_TX, .rx_gpio = GPIO_USART1_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART1_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_USART1_RTS, @@ -581,6 +584,7 @@ static struct up_dev_s g_usart2priv = .tx_gpio = GPIO_USART2_TX, .rx_gpio = GPIO_USART2_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART2_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_USART2_RTS, @@ -653,6 +657,7 @@ static struct up_dev_s g_usart5priv = .tx_gpio = GPIO_USART5_TX, .rx_gpio = GPIO_USART5_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART5_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_USART5_RTS, @@ -725,6 +730,7 @@ static struct up_dev_s g_uart3priv = .tx_gpio = GPIO_UART3_TX, .rx_gpio = GPIO_UART3_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART3_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_UART3_RTS, @@ -797,6 +803,7 @@ static struct up_dev_s g_uart4priv = .tx_gpio = GPIO_UART4_TX, .rx_gpio = GPIO_UART4_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART4_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_UART4_RTS, @@ -869,6 +876,7 @@ static struct up_dev_s g_uart6priv = .tx_gpio = GPIO_UART6_TX, .rx_gpio = GPIO_UART6_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART6_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_UART6_RTS, @@ -941,6 +949,7 @@ static struct up_dev_s g_uart7priv = .tx_gpio = GPIO_UART7_TX, .rx_gpio = GPIO_UART7_RX, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_UART7_IFLOWCONTROL) .iflow = true, .rts_gpio = GPIO_UART7_RTS, @@ -1127,7 +1136,7 @@ static void up_disableusartint(struct up_dev_s *priv, uint32_t *ie) irqstate_t flags; uint32_t ctl_ie; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (ie) { @@ -1161,7 +1170,7 @@ static void up_disableusartint(struct up_dev_s *priv, uint32_t *ie) ctl_ie = (USART_CFG_CTL_MASK << USART_CFG_SHIFT); up_setusartint(priv, ctl_ie); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -1172,11 +1181,11 @@ static void up_restoreusartint(struct up_dev_s *priv, uint32_t ie) { irqstate_t flags; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); up_setusartint(priv, ie); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** diff --git a/arch/arm/src/imx9/imx9_edma.c b/arch/arm/src/imx9/imx9_edma.c index ddd61151c63db..dc3f619557e0b 100644 --- a/arch/arm/src/imx9/imx9_edma.c +++ b/arch/arm/src/imx9/imx9_edma.c @@ -145,6 +145,7 @@ struct imx9_edma_s /* This array describes each DMA channel */ struct imx9_dmach_s dmach[IMX9_EDMA_NCHANNELS]; + spinlock_t lock; }; /**************************************************************************** @@ -159,6 +160,7 @@ static struct imx9_edma_s g_edma = #if CONFIG_IMX9_EDMA_NTCD > 0 .dsem = SEM_INITIALIZER(CONFIG_IMX9_EDMA_NTCD), #endif + .lock = SP_UNLOCKED }; #if CONFIG_IMX9_EDMA_NTCD > 0 @@ -198,15 +200,15 @@ static struct imx9_edmatcd_s *imx9_tcd_alloc(void) * waiting. */ - flags = enter_critical_section(); nxsem_wait_uninterruptible(&g_edma.dsem); /* Now there should be a TCD in the free list reserved just for us */ + flags = spin_lock_irqsave(&g_edma.lock); tcd = (struct imx9_edmatcd_s *)sq_remfirst(&g_tcd_free); DEBUGASSERT(tcd != NULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return tcd; } #endif @@ -220,6 +222,17 @@ static struct imx9_edmatcd_s *imx9_tcd_alloc(void) ****************************************************************************/ #if CONFIG_IMX9_EDMA_NTCD > 0 +static void imx9_tcd_free_nolock(struct imx9_edmatcd_s *tcd) +{ + /* Add the the TCD to the end of the free list and post the 'dsem', + * possibly waking up another thread that might be waiting for + * a TCD. + */ + + sq_addlast((sq_entry_t *)tcd, &g_tcd_free); + nxsem_post(&g_edma.dsem); +} + static void imx9_tcd_free(struct imx9_edmatcd_s *tcd) { irqstate_t flags; @@ -229,10 +242,11 @@ static void imx9_tcd_free(struct imx9_edmatcd_s *tcd) * a TCD. */ - flags = spin_lock_irqsave(NULL); - sq_addlast((sq_entry_t *)tcd, &g_tcd_free); - nxsem_post(&g_edma.dsem); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + imx9_tcd_free_nolock(tcd); + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } #endif @@ -458,6 +472,11 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result) edma_callback_t callback; void *arg; + irqstate_t flags; + + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + /* Disable channel IRQ requests */ putreg32(EDMA_CH_INT, base + IMX9_EDMA_CH_INT_OFFSET); @@ -487,7 +506,7 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result) next = dmach->flags & EDMA_CONFIG_LOOPDEST ? NULL : (struct imx9_edmatcd_s *)((uintptr_t)tcd->dlastsga); - imx9_tcd_free(tcd); + imx9_tcd_free_nolock(tcd); } dmach->head = NULL; @@ -507,6 +526,9 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result) { callback((DMACH_HANDLE)dmach, arg, true, result); } + + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } /**************************************************************************** @@ -1344,7 +1366,7 @@ int imx9_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, /* Save the callback info. This will be invoked when the DMA completes */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); dmach->callback = callback; dmach->arg = arg; @@ -1363,7 +1385,7 @@ int imx9_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, putreg32(regval, base + IMX9_EDMA_CH_CSR_OFFSET); } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return OK; } @@ -1386,14 +1408,11 @@ int imx9_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void imx9_dmach_stop(DMACH_HANDLE handle) { struct imx9_dmach_s *dmach = (struct imx9_dmach_s *)handle; - irqstate_t flags; dmainfo("dmach: %p\n", dmach); DEBUGASSERT(dmach != NULL); - flags = spin_lock_irqsave(NULL); imx9_dmaterminate(dmach, -EINTR); - spin_unlock_irqrestore(NULL, flags); } /**************************************************************************** @@ -1508,7 +1527,7 @@ void imx9_dmasample(DMACH_HANDLE handle, struct imx9_dmaregs_s *regs) /* eDMA Global Registers */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); /* REVISIT: eDMA4 does not show INT_HIGH / HRS_HIGH values correctly */ @@ -1542,7 +1561,7 @@ void imx9_dmasample(DMACH_HANDLE handle, struct imx9_dmaregs_s *regs) regs->dmamux = 0; } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif /* CONFIG_DEBUG_DMA */ diff --git a/arch/arm/src/imxrt/imxrt_edma.c b/arch/arm/src/imxrt/imxrt_edma.c index 4fe790a4ac486..1a839ce196c83 100644 --- a/arch/arm/src/imxrt/imxrt_edma.c +++ b/arch/arm/src/imxrt/imxrt_edma.c @@ -158,6 +158,7 @@ static struct imxrt_edma_s g_edma = #if CONFIG_IMXRT_EDMA_NTCD > 0 .dsem = SEM_INITIALIZER(CONFIG_IMXRT_EDMA_NTCD), #endif + .lock = SP_UNLOCKED }; #if CONFIG_IMXRT_EDMA_NTCD > 0 @@ -197,15 +198,15 @@ static struct imxrt_edmatcd_s *imxrt_tcd_alloc(void) * waiting. */ - flags = enter_critical_section(); nxsem_wait_uninterruptible(&g_edma.dsem); /* Now there should be a TCD in the free list reserved just for us */ + flags = spin_lock_irqsave(&g_edma.lock); tcd = (struct imxrt_edmatcd_s *)sq_remfirst(&g_tcd_free); DEBUGASSERT(tcd != NULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return tcd; } #endif @@ -219,6 +220,17 @@ static struct imxrt_edmatcd_s *imxrt_tcd_alloc(void) ****************************************************************************/ #if CONFIG_IMXRT_EDMA_NTCD > 0 +static void imxrt_tcd_free_nolock(struct imxrt_edmatcd_s *tcd) +{ + /* Add the the TCD to the end of the free list and post the 'dsem', + * possibly waking up another thread that might be waiting for + * a TCD. + */ + + sq_addlast((sq_entry_t *)tcd, &g_tcd_free); + nxsem_post(&g_edma.dsem); +} + static void imxrt_tcd_free(struct imxrt_edmatcd_s *tcd) { irqstate_t flags; @@ -228,10 +240,9 @@ static void imxrt_tcd_free(struct imxrt_edmatcd_s *tcd) * a TCD. */ - flags = spin_lock_irqsave(NULL); - sq_addlast((sq_entry_t *)tcd, &g_tcd_free); - nxsem_post(&g_edma.dsem); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&g_edma.lock); + imxrt_tcd_free_nolock(tcd); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif @@ -436,8 +447,11 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result) uint8_t regval8; uint8_t chan; edma_callback_t callback; + irqstate_t flags; void *arg; + flags = spin_lock_irqsave(&g_edma.lock); + /* Disable channel ERROR interrupts */ chan = dmach->chan; @@ -469,7 +483,7 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result) next = dmach->flags & EDMA_CONFIG_LOOPDEST ? NULL : (struct imxrt_edmatcd_s *)tcd->dlastsga; - imxrt_tcd_free(tcd); + imxrt_tcd_free_nolock(tcd); } dmach->head = NULL; @@ -489,6 +503,8 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result) { callback((DMACH_HANDLE)dmach, arg, true, result); } + + spin_unlock_irqrestore(&g_edma.lock, flags); } /**************************************************************************** @@ -1143,7 +1159,7 @@ int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, /* Save the callback info. This will be invoked when the DMA completes */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); dmach->callback = callback; dmach->arg = arg; @@ -1168,7 +1184,7 @@ int imxrt_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, putreg8(regval8, IMXRT_EDMA_SERQ); } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return OK; } @@ -1196,9 +1212,7 @@ void imxrt_dmach_stop(DMACH_HANDLE handle) dmainfo("dmach: %p\n", dmach); DEBUGASSERT(dmach != NULL); - flags = spin_lock_irqsave(NULL); imxrt_dmaterminate(dmach, -EINTR); - spin_unlock_irqrestore(NULL, flags); } /**************************************************************************** @@ -1313,7 +1327,7 @@ void imxrt_dmasample(DMACH_HANDLE handle, struct imxrt_dmaregs_s *regs) /* eDMA Global Registers */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); regs->cr = getreg32(IMXRT_EDMA_CR); /* Control */ regs->es = getreg32(IMXRT_EDMA_ES); /* Error Status */ @@ -1348,7 +1362,7 @@ void imxrt_dmasample(DMACH_HANDLE handle, struct imxrt_dmaregs_s *regs) regaddr = IMXRT_DMAMUX_CHCFG(chan); regs->dmamux = getreg32(regaddr); /* Channel configuration */ - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif /* CONFIG_DEBUG_DMA */ diff --git a/arch/arm/src/imxrt/imxrt_hprtc.c b/arch/arm/src/imxrt/imxrt_hprtc.c index 3e9d166b12db7..94a78d5693f4e 100644 --- a/arch/arm/src/imxrt/imxrt_hprtc.c +++ b/arch/arm/src/imxrt/imxrt_hprtc.c @@ -56,6 +56,7 @@ /* Callback to use when the alarm expires */ #if defined(CONFIG_RTC_ALARM) && defined(CONFIG_RTC_DRIVER) +static spinlock_t g_imxrt_hprtc_lock = SP_UNLOCKED; static hprtc_alarm_callback_t g_hprtc_alarmcb; #endif @@ -526,7 +527,7 @@ int imxrt_hprtc_setalarm(struct timespec *ts, hprtc_alarm_callback_t cb) * interrupted or preempted. */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_imxrt_hprtc_lock); now = imxrt_hprtc_time(); @@ -539,7 +540,7 @@ int imxrt_hprtc_setalarm(struct timespec *ts, hprtc_alarm_callback_t cb) if ((uint32_t)ts->tv_sec <= now) { rtcwarn("WARNING: time is in the past\n"); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_imxrt_hprtc_lock, flags); return -EINVAL; } @@ -569,7 +570,7 @@ int imxrt_hprtc_setalarm(struct timespec *ts, hprtc_alarm_callback_t cb) /* Unconditionally enable the RTC alarm interrupt */ imxrt_hprtc_alarmenable(); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_imxrt_hprtc_lock, flags); return OK; } #endif diff --git a/arch/arm/src/kinetis/kinetis_lpserial.c b/arch/arm/src/kinetis/kinetis_lpserial.c index 13bc8de93a4a6..b8274b7f572f8 100644 --- a/arch/arm/src/kinetis/kinetis_lpserial.c +++ b/arch/arm/src/kinetis/kinetis_lpserial.c @@ -273,6 +273,7 @@ struct kinetis_dev_s uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (8 or 9) */ uint8_t stop2; /* Use 2 stop bits */ + spinlock_t lock; /* Spinlock */ #ifdef CONFIG_SERIAL_IFLOWCONTROL bool iflow; /* input flow control (RTS) enabled */ #endif @@ -428,6 +429,7 @@ static struct kinetis_dev_s g_lpuart0priv = .parity = CONFIG_LPUART0_PARITY, .bits = CONFIG_LPUART0_BITS, .stop2 = CONFIG_LPUART0_2STOP, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART0_OFLOWCONTROL) .oflow = true, .cts_gpio = PIN_LPUART0_CTS, @@ -475,6 +477,7 @@ static struct kinetis_dev_s g_lpuart1priv = .parity = CONFIG_LPUART1_PARITY, .bits = CONFIG_LPUART1_BITS, .stop2 = CONFIG_LPUART1_2STOP, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART1_OFLOWCONTROL) .oflow = true, .cts_gpio = PIN_LPUART1_CTS, @@ -522,6 +525,7 @@ static struct kinetis_dev_s g_lpuart2priv = .parity = CONFIG_LPUART2_PARITY, .bits = CONFIG_LPUART2_BITS, .stop2 = CONFIG_LPUART2_2STOP, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART2_OFLOWCONTROL) .oflow = true, .cts_gpio = PIN_LPUART2_CTS, @@ -569,6 +573,7 @@ static struct kinetis_dev_s g_lpuart3priv = .parity = CONFIG_LPUART3_PARITY, .bits = CONFIG_LPUART3_BITS, .stop2 = CONFIG_LPUART3_2STOP, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART3_OFLOWCONTROL) .oflow = true, .cts_gpio = PIN_LPUART3_CTS, @@ -616,6 +621,7 @@ static struct kinetis_dev_s g_lpuart4priv = .parity = CONFIG_LPUART4_PARITY, .bits = CONFIG_LPUART4_BITS, .stop2 = CONFIG_LPUART4_2STOP, + .lock = SP_UNLOCKED, #if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART4_OFLOWCONTROL) .oflow = true, .cts_gpio = PIN_LPUART4_CTS, @@ -700,6 +706,17 @@ static void kinetis_setuartint(struct kinetis_dev_s *priv) * Name: kinetis_restoreuartint ****************************************************************************/ +static void kinetis_restoreuartint_nolock(struct kinetis_dev_s *priv, + uint32_t ie) +{ + /* Re-enable/re-disable interrupts corresponding to the state of bits in + * ie + */ + + priv->ie = ie & LPUART_CTRL_ALL_INTS; + kinetis_setuartint(priv); +} + static void kinetis_restoreuartint(struct kinetis_dev_s *priv, uint32_t ie) { irqstate_t flags; @@ -708,10 +725,9 @@ static void kinetis_restoreuartint(struct kinetis_dev_s *priv, uint32_t ie) * ie */ - flags = spin_lock_irqsave(NULL); - priv->ie = ie & LPUART_CTRL_ALL_INTS; - kinetis_setuartint(priv); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&priv->lock); + kinetis_restoreuartint_nolock(priv, ie); + spin_unlock_irqrestore(&priv->lock, flags); } /**************************************************************************** @@ -723,14 +739,14 @@ static void kinetis_disableuartint(struct kinetis_dev_s *priv, uint32_t *ie) { irqstate_t flags; - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&priv->lock); if (ie) { *ie = priv->ie; } - kinetis_restoreuartint(priv, 0); - spin_unlock_irqrestore(NULL, flags); + kinetis_restoreuartint_nolock(priv, 0); + spin_unlock_irqrestore(&priv->lock, flags); } #endif diff --git a/arch/arm/src/lc823450/lc823450_gpio.c b/arch/arm/src/lc823450/lc823450_gpio.c index 5c39bbd9fd38d..a82c9d5fdffd2 100644 --- a/arch/arm/src/lc823450/lc823450_gpio.c +++ b/arch/arm/src/lc823450/lc823450_gpio.c @@ -54,6 +54,8 @@ * Private Data ****************************************************************************/ +static spinlock_t g_gpio_lock = SP_UNLOCKED; + #ifdef CONFIG_IOEX static struct ioex_dev_s *g_ioex_dev; #endif @@ -229,12 +231,12 @@ int lc823450_gpio_mux(uint16_t gpiocfg) if (port <= (GPIO_PORT5 >> GPIO_PORT_SHIFT)) { - irqstate_t flags = spin_lock_irqsave(NULL); + irqstate_t flags = spin_lock_irqsave(&g_gpio_lock); val = getreg32(PMDCNT0 + (port * 4)); val &= ~(3 << (2 * pin)); val |= (mux << (2 *pin)); putreg32(val, PMDCNT0 + (port * 4)); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); } else { @@ -277,7 +279,7 @@ int lc823450_gpio_config(uint16_t gpiocfg) /* Handle the GPIO configuration by the basic mode of the pin */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_gpio_lock); /* pull up/down specified */ @@ -302,7 +304,7 @@ int lc823450_gpio_config(uint16_t gpiocfg) break; } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); } #ifdef CONFIG_IOEX else if (port <= (GPIO_PORTEX >> GPIO_PORT_SHIFT)) @@ -390,7 +392,7 @@ void lc823450_gpio_write(uint16_t gpiocfg, bool value) regaddr = lc823450_get_gpio_data(port); - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_gpio_lock); /* Write the value (0 or 1). To the data register */ @@ -407,7 +409,7 @@ void lc823450_gpio_write(uint16_t gpiocfg, bool value) putreg32(regval, regaddr); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); } #ifdef CONFIG_IOEX else if (port <= (GPIO_PORTEX >> GPIO_PORT_SHIFT)) diff --git a/arch/arm/src/s32k1xx/s32k1xx_edma.c b/arch/arm/src/s32k1xx/s32k1xx_edma.c index dd7f3708b313f..95ac88ff566f6 100644 --- a/arch/arm/src/s32k1xx/s32k1xx_edma.c +++ b/arch/arm/src/s32k1xx/s32k1xx_edma.c @@ -142,6 +142,7 @@ struct s32k1xx_edma_s /* This array describes each DMA channel */ struct s32k1xx_dmach_s dmach[S32K1XX_EDMA_NCHANNELS]; + spinlock_t lock; }; /**************************************************************************** @@ -156,6 +157,7 @@ static struct s32k1xx_edma_s g_edma = #if CONFIG_S32K1XX_EDMA_NTCD > 0 .dsem = SEM_INITIALIZER(CONFIG_S32K1XX_EDMA_NTCD), #endif + .lock = SP_UNLOCKED }; #if CONFIG_S32K1XX_EDMA_NTCD > 0 @@ -195,15 +197,15 @@ static struct s32k1xx_edmatcd_s *s32k1xx_tcd_alloc(void) * waiting. */ - flags = enter_critical_section(); nxsem_wait_uninterruptible(&g_edma.dsem); /* Now there should be a TCD in the free list reserved just for us */ + flags = spin_lock_irqsave(&g_edma.lock); tcd = (struct s32k1xx_edmatcd_s *)sq_remfirst(&g_tcd_free); DEBUGASSERT(tcd != NULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return tcd; } #endif @@ -217,6 +219,17 @@ static struct s32k1xx_edmatcd_s *s32k1xx_tcd_alloc(void) ****************************************************************************/ #if CONFIG_S32K1XX_EDMA_NTCD > 0 +static void s32k1xx_tcd_free_nolock(struct s32k1xx_edmatcd_s *tcd) +{ + /* Add the the TCD to the end of the free list and post the 'dsem', + * possibly waking up another thread that might be waiting for + * a TCD. + */ + + sq_addlast((sq_entry_t *)tcd, &g_tcd_free); + nxsem_post(&g_edma.dsem); +} + static void s32k1xx_tcd_free(struct s32k1xx_edmatcd_s *tcd) { irqstate_t flags; @@ -226,10 +239,9 @@ static void s32k1xx_tcd_free(struct s32k1xx_edmatcd_s *tcd) * a TCD. */ - flags = spin_lock_irqsave(NULL); - sq_addlast((sq_entry_t *)tcd, &g_tcd_free); - nxsem_post(&g_edma.dsem); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&g_edma.lock); + s32k1xx_tcd_free_nolock(tcd); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif @@ -432,9 +444,13 @@ static void s32k1xx_dmaterminate(struct s32k1xx_dmach_s *dmach, int result) struct s32k1xx_edmatcd_s *next; #endif uintptr_t regaddr; + irqstate_t flags; uint8_t regval8; uint8_t chan; + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + /* Disable channel ERROR interrupts */ chan = dmach->chan; @@ -465,7 +481,7 @@ static void s32k1xx_dmaterminate(struct s32k1xx_dmach_s *dmach, int result) next = dmach->flags & EDMA_CONFIG_LOOPDEST ? NULL : (struct s32k1xx_edmatcd_s *)tcd->dlastsga; - s32k1xx_tcd_free(tcd); + s32k1xx_tcd_free_nolock(tcd); } dmach->head = NULL; @@ -482,6 +498,8 @@ static void s32k1xx_dmaterminate(struct s32k1xx_dmach_s *dmach, int result) dmach->callback = NULL; dmach->arg = NULL; dmach->state = S32K1XX_DMA_IDLE; + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } /**************************************************************************** @@ -1098,7 +1116,7 @@ int s32k1xx_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, /* Save the callback info. This will be invoked when the DMA completes */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); dmach->callback = callback; dmach->arg = arg; @@ -1123,7 +1141,7 @@ int s32k1xx_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, putreg8(regval8, S32K1XX_EDMA_SERQ); } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return OK; } @@ -1151,9 +1169,9 @@ void s32k1xx_dmach_stop(DMACH_HANDLE handle) dmainfo("dmach: %p\n", dmach); DEBUGASSERT(dmach != NULL); - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); s32k1xx_dmaterminate(dmach, -EINTR); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } /**************************************************************************** @@ -1251,7 +1269,7 @@ void s32k1xx_dmasample(DMACH_HANDLE handle, struct s32k1xx_dmaregs_s *regs) /* eDMA Global Registers */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); regs->cr = getreg32(S32K1XX_EDMA_CR); /* Control */ regs->es = getreg32(S32K1XX_EDMA_ES); /* Error Status */ @@ -1286,7 +1304,7 @@ void s32k1xx_dmasample(DMACH_HANDLE handle, struct s32k1xx_dmaregs_s *regs) regaddr = S32K1XX_DMAMUX_CHCFG(chan); regs->dmamux = getreg32(regaddr); /* Channel configuration */ - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif /* CONFIG_DEBUG_DMA */ diff --git a/arch/arm/src/s32k3xx/s32k3xx_edma.c b/arch/arm/src/s32k3xx/s32k3xx_edma.c index b0e193b9253bf..36c24219e3a9f 100644 --- a/arch/arm/src/s32k3xx/s32k3xx_edma.c +++ b/arch/arm/src/s32k3xx/s32k3xx_edma.c @@ -206,6 +206,7 @@ static struct s32k3xx_edma_s g_edma = #if CONFIG_S32K3XX_EDMA_NTCD > 0 .dsem = SEM_INITIALIZER(CONFIG_S32K3XX_EDMA_NTCD), #endif + .lock = SP_UNLOCKED }; #if CONFIG_S32K3XX_EDMA_NTCD > 0 @@ -450,15 +451,15 @@ static struct s32k3xx_edmatcd_s *s32k3xx_tcd_alloc(void) * waiting. */ - flags = enter_critical_section(); nxsem_wait_uninterruptible(&g_edma.dsem); /* Now there should be a TCD in the free list reserved just for us */ + flags = spin_lock_irqsave(&g_edma.lock); tcd = (struct s32k3xx_edmatcd_s *)sq_remfirst(&g_tcd_free); DEBUGASSERT(tcd != NULL); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return tcd; } #endif @@ -472,6 +473,17 @@ static struct s32k3xx_edmatcd_s *s32k3xx_tcd_alloc(void) ****************************************************************************/ #if CONFIG_S32K3XX_EDMA_NTCD > 0 +static void s32k3xx_tcd_free_nolock(struct s32k3xx_edmatcd_s *tcd) +{ + /* Add the the TCD to the end of the free list and post the 'dsem', + * possibly waking up another thread that might be waiting for + * a TCD. + */ + + sq_addlast((sq_entry_t *)tcd, &g_tcd_free); + nxsem_post(&g_edma.dsem); +} + static void s32k3xx_tcd_free(struct s32k3xx_edmatcd_s *tcd) { irqstate_t flags; @@ -481,10 +493,11 @@ static void s32k3xx_tcd_free(struct s32k3xx_edmatcd_s *tcd) * a TCD. */ - flags = spin_lock_irqsave(NULL); - sq_addlast((sq_entry_t *)tcd, &g_tcd_free); - nxsem_post(&g_edma.dsem); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + s32k3xx_tcd_free_nolock(tcd); + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } #endif @@ -709,8 +722,12 @@ static void s32k3xx_dmaterminate(struct s32k3xx_dmach_s *dmach, int result) #endif uint8_t chan; edma_callback_t callback; + irqstate_t flags; void *arg; + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + chan = dmach->chan; /* Disable channel IRQ requests */ @@ -742,7 +759,7 @@ static void s32k3xx_dmaterminate(struct s32k3xx_dmach_s *dmach, int result) next = dmach->flags & EDMA_CONFIG_LOOPDEST ? NULL : (struct s32k3xx_edmatcd_s *)tcd->dlastsga; - s32k3xx_tcd_free(tcd); + s32k3xx_tcd_free_nolock(tcd); } dmach->head = NULL; @@ -762,6 +779,9 @@ static void s32k3xx_dmaterminate(struct s32k3xx_dmach_s *dmach, int result) { callback((DMACH_HANDLE)dmach, arg, true, result); } + + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } /**************************************************************************** @@ -1377,7 +1397,7 @@ int s32k3xx_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, /* Save the callback info. This will be invoked when the DMA completes */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); dmach->callback = callback; dmach->arg = arg; @@ -1397,7 +1417,7 @@ int s32k3xx_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, putreg32(regval, S32K3XX_EDMA_TCD[chan] + S32K3XX_EDMA_CH_CSR_OFFSET); } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return OK; } @@ -1425,9 +1445,9 @@ void s32k3xx_dmach_stop(DMACH_HANDLE handle) dmainfo("dmach: %p\n", dmach); DEBUGASSERT(dmach != NULL); - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); s32k3xx_dmaterminate(dmach, -EINTR); - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } /**************************************************************************** @@ -1544,7 +1564,7 @@ void s32k3xx_dmasample(DMACH_HANDLE handle, struct s32k3xx_dmaregs_s *regs) /* eDMA Global Registers */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); regs->cr = getreg32(S32K3XX_EDMA_CSR); /* Control */ regs->es = getreg32(S32K3XX_EDMA_ES); /* Error Status */ @@ -1576,7 +1596,7 @@ void s32k3xx_dmasample(DMACH_HANDLE handle, struct s32k3xx_dmaregs_s *regs) regs->dmamux = getreg32(S32K3XX_DMAMUX1_CHCFG(chan - 16)); /* Channel configuration */ } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif /* CONFIG_DEBUG_DMA */ diff --git a/arch/arm64/src/imx9/imx9_edma.c b/arch/arm64/src/imx9/imx9_edma.c index 1d5f6085454f7..7669f6c35b684 100644 --- a/arch/arm64/src/imx9/imx9_edma.c +++ b/arch/arm64/src/imx9/imx9_edma.c @@ -141,6 +141,7 @@ struct imx9_edma_s /* This array describes each DMA channel */ struct imx9_dmach_s dmach[IMX9_EDMA_NCHANNELS]; + spinlock_t lock; }; /**************************************************************************** @@ -155,6 +156,7 @@ static struct imx9_edma_s g_edma = #if CONFIG_IMX9_EDMA_NTCD > 0 .dsem = SEM_INITIALIZER(CONFIG_IMX9_EDMA_NTCD), #endif + .lock = SP_UNLOCKED }; #if CONFIG_IMX9_EDMA_NTCD > 0 @@ -194,15 +196,15 @@ static struct imx9_edmatcd_s *imx9_tcd_alloc(void) * waiting. */ - flags = enter_critical_section(); nxsem_wait_uninterruptible(&g_edma.dsem); /* Now there should be a TCD in the free list reserved just for us */ + flags = spin_lock_irqsave(&g_edma.lock); tcd = (struct imx9_edmatcd_s *)sq_remfirst(&g_tcd_free); DEBUGASSERT(tcd != NULL); - leave_critical_section(flags); + spin_lock_irqsave(&g_edma.lock, flags); return tcd; } #endif @@ -216,6 +218,17 @@ static struct imx9_edmatcd_s *imx9_tcd_alloc(void) ****************************************************************************/ #if CONFIG_IMX9_EDMA_NTCD > 0 +static void imx9_tcd_free_nolock(struct imx9_edmatcd_s *tcd) +{ + /* Add the the TCD to the end of the free list and post the 'dsem', + * possibly waking up another thread that might be waiting for + * a TCD. + */ + + sq_addlast((sq_entry_t *)tcd, &g_tcd_free); + nxsem_post(&g_edma.dsem); +} + static void imx9_tcd_free(struct imx9_edmatcd_s *tcd) { irqstate_t flags; @@ -225,10 +238,11 @@ static void imx9_tcd_free(struct imx9_edmatcd_s *tcd) * a TCD. */ - flags = spin_lock_irqsave(NULL); - sq_addlast((sq_entry_t *)tcd, &g_tcd_free); - nxsem_post(&g_edma.dsem); - spin_unlock_irqrestore(NULL, flags); + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + imx9_tcd_free_nolock(tcd); + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } #endif @@ -438,6 +452,11 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result) edma_callback_t callback; void *arg; + irqstate_t flags; + + flags = spin_lock_irqsave(&g_edma.lock); + sched_lock(); + /* Disable channel IRQ requests */ putreg32(EDMA_CH_INT, base + IMX9_EDMA_CH_INT_OFFSET); @@ -467,7 +486,7 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result) next = dmach->flags & EDMA_CONFIG_LOOPDEST ? NULL : (struct imx9_edmatcd_s *)((uintptr_t)tcd->dlastsga); - imx9_tcd_free(tcd); + imx9_tcd_free_nolock(tcd); } dmach->head = NULL; @@ -487,6 +506,9 @@ static void imx9_dmaterminate(struct imx9_dmach_s *dmach, int result) { callback((DMACH_HANDLE)dmach, arg, true, result); } + + spin_unlock_irqrestore(&g_edma.lock, flags); + sched_unlock(); } /**************************************************************************** @@ -1252,7 +1274,7 @@ int imx9_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, /* Save the callback info. This will be invoked when the DMA completes */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); dmach->callback = callback; dmach->arg = arg; @@ -1271,7 +1293,7 @@ int imx9_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, putreg32(regval, base + IMX9_EDMA_CH_CSR_OFFSET); } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); return OK; } @@ -1294,14 +1316,11 @@ int imx9_dmach_start(DMACH_HANDLE handle, edma_callback_t callback, void imx9_dmach_stop(DMACH_HANDLE handle) { struct imx9_dmach_s *dmach = (struct imx9_dmach_s *)handle; - irqstate_t flags; dmainfo("dmach: %p\n", dmach); DEBUGASSERT(dmach != NULL); - flags = spin_lock_irqsave(NULL); imx9_dmaterminate(dmach, -EINTR); - spin_unlock_irqrestore(NULL, flags); } /**************************************************************************** @@ -1416,7 +1435,7 @@ void imx9_dmasample(DMACH_HANDLE handle, struct imx9_dmaregs_s *regs) /* eDMA Global Registers */ - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&g_edma.lock); /* REVISIT: eDMA4 does not show INT_HIGH / HRS_HIGH values correctly */ @@ -1450,7 +1469,7 @@ void imx9_dmasample(DMACH_HANDLE handle, struct imx9_dmaregs_s *regs) regs->dmamux = 0; } - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&g_edma.lock, flags); } #endif /* CONFIG_DEBUG_DMA */