From 4bcf59a5dea0f4e768e2b84fc78ce13a7fb27863 Mon Sep 17 00:00:00 2001 From: Vignesh Raghavendra Date: Thu, 19 Mar 2020 16:33:40 +0530 Subject: [PATCH] serial: 8250: 8250_omap: Account for data in flight during DMA teardown Take into account data stuck in DMA internal buffers before pushing data to higher layer. dma_tx_state has "in_flight_bytes" member that provides this information. Signed-off-by: Vignesh Raghavendra Link: https://lore.kernel.org/r/20200319110344.21348-3-vigneshr@ti.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index c13b48ad7cdb..bf1f2bba1d41 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -741,6 +741,8 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) struct omap8250_priv *priv = p->port.private_data; struct uart_8250_dma *dma = p->dma; struct tty_port *tty_port = &p->port.state->port; + struct dma_chan *rxchan = dma->rxchan; + dma_cookie_t cookie; struct dma_tx_state state; int count; unsigned long flags; @@ -751,12 +753,29 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) if (!dma->rx_running) goto unlock; + cookie = dma->rx_cookie; dma->rx_running = 0; - dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + dmaengine_tx_status(rxchan, cookie, &state); - count = dma->rx_size - state.residue; - if (count < dma->rx_size) - dmaengine_terminate_async(dma->rxchan); + count = dma->rx_size - state.residue + state.in_flight_bytes; + if (count < dma->rx_size) { + dmaengine_terminate_async(rxchan); + + /* + * Poll for teardown to complete which guarantees in + * flight data is drained. + */ + if (state.in_flight_bytes) { + int poll_count = 25; + + while (dmaengine_tx_status(rxchan, cookie, NULL) && + poll_count--) + cpu_relax(); + + if (!poll_count) + dev_err(p->port.dev, "teardown incomplete\n"); + } + } if (!count) goto unlock; ret = tty_insert_flip_string(tty_port, dma->rx_buf, count); -- 2.20.1