[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200319110344.21348-3-vigneshr@ti.com>
Date: Thu, 19 Mar 2020 16:33:40 +0530
From: Vignesh Raghavendra <vigneshr@...com>
To: Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Jiri Slaby <jslaby@...e.com>
CC: Vignesh Raghavendra <vigneshr@...com>,
<linux-serial@...r.kernel.org>, <linux-omap@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH 2/6] 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 <vigneshr@...com>
---
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 65b6d165df67..be2b7d374e60 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.25.2
Powered by blists - more mailing lists