| From cca89c154c2d9d37052401c8581ad0422ff38cf7 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 6 Jan 2021 17:21:56 +0100 |
| Subject: serial: stm32: fix DMA initialization error handling |
| |
| From: Erwan Le Ray <erwan.leray@foss.st.com> |
| |
| [ Upstream commit e7997f7ff7f8154d477f6f976698d868a2ac3934 ] |
| |
| DMA initialization error handling is not properly implemented in the |
| driver. |
| Fix DMA initialization error handling by: |
| - moving TX DMA descriptor request error handling in a new dedicated |
| fallback_err label |
| - adding error handling to TX DMA descriptor submission |
| - adding error handling to RX DMA descriptor submission |
| |
| This patch depends on '24832ca3ee85 ("tty: serial: stm32-usart: Remove set |
| but unused 'cookie' variables")' which unfortunately doesn't include a |
| "Fixes" tag. |
| |
| Fixes: 3489187204eb ("serial: stm32: adding dma support") |
| Signed-off-by: Erwan Le Ray <erwan.leray@foss.st.com> |
| Link: https://lore.kernel.org/r/20210106162203.28854-2-erwan.leray@foss.st.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/tty/serial/stm32-usart.c | 24 +++++++++++++++++------- |
| 1 file changed, 17 insertions(+), 7 deletions(-) |
| |
| diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c |
| index f4de32d3f2afe..6248304a001f4 100644 |
| --- a/drivers/tty/serial/stm32-usart.c |
| +++ b/drivers/tty/serial/stm32-usart.c |
| @@ -383,17 +383,18 @@ static void stm32_transmit_chars_dma(struct uart_port *port) |
| DMA_MEM_TO_DEV, |
| DMA_PREP_INTERRUPT); |
| |
| - if (!desc) { |
| - for (i = count; i > 0; i--) |
| - stm32_transmit_chars_pio(port); |
| - return; |
| - } |
| + if (!desc) |
| + goto fallback_err; |
| |
| desc->callback = stm32_tx_dma_complete; |
| desc->callback_param = port; |
| |
| /* Push current DMA TX transaction in the pending queue */ |
| - dmaengine_submit(desc); |
| + if (dma_submit_error(dmaengine_submit(desc))) { |
| + /* dma no yet started, safe to free resources */ |
| + dmaengine_terminate_async(stm32port->tx_ch); |
| + goto fallback_err; |
| + } |
| |
| /* Issue pending DMA TX requests */ |
| dma_async_issue_pending(stm32port->tx_ch); |
| @@ -402,6 +403,11 @@ static void stm32_transmit_chars_dma(struct uart_port *port) |
| |
| xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); |
| port->icount.tx += count; |
| + return; |
| + |
| +fallback_err: |
| + for (i = count; i > 0; i--) |
| + stm32_transmit_chars_pio(port); |
| } |
| |
| static void stm32_transmit_chars(struct uart_port *port) |
| @@ -1130,7 +1136,11 @@ static int stm32_of_dma_rx_probe(struct stm32_port *stm32port, |
| desc->callback_param = NULL; |
| |
| /* Push current DMA transaction in the pending queue */ |
| - dmaengine_submit(desc); |
| + ret = dma_submit_error(dmaengine_submit(desc)); |
| + if (ret) { |
| + dmaengine_terminate_sync(stm32port->rx_ch); |
| + goto config_err; |
| + } |
| |
| /* Issue pending DMA requests */ |
| dma_async_issue_pending(stm32port->rx_ch); |
| -- |
| 2.27.0 |
| |