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);