Message ID | 20190624123540.20629-3-geert+renesas@glider.be (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | serial: sh-sci: Fix .flush_buffer() issues | expand |
On Mon, Jun 24, 2019 at 02:35:40PM +0200, Geert Uytterhoeven wrote: [..] > diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c > index d4504daff99263f5..d18c680aa64b3427 100644 > --- a/drivers/tty/serial/sh-sci.c > +++ b/drivers/tty/serial/sh-sci.c > @@ -1656,11 +1656,18 @@ static void sci_free_dma(struct uart_port *port) > > static void sci_flush_buffer(struct uart_port *port) > { > + struct sci_port *s = to_sci_port(port); > + > /* > * In uart_flush_buffer(), the xmit circular buffer has just been > - * cleared, so we have to reset tx_dma_len accordingly. > + * cleared, so we have to reset tx_dma_len accordingly, and stop any > + * pending transfers > */ > - to_sci_port(port)->tx_dma_len = 0; > + s->tx_dma_len = 0; > + if (s->chan_tx) { > + dmaengine_terminate_async(s->chan_tx); > + s->cookie_tx = -EINVAL; > + } I am seeing a similar solution being employed by other tty/serial drivers [1]. One major difference is that those drivers make use of dmaengine_terminate_all(). Since the latter is deprecated starting with commit [2], the API choice looks reasonable to me. Reviewed-by: Eugeniu Rosca <erosca@de.adit-jv.com> Tested-by: Eugeniu Rosca <erosca@de.adit-jv.com> [1] git grep -W "static void.*flush_buffer" -- drivers/tty/serial/ | grep dmaengine_terminate drivers/tty/serial/fsl_lpuart.c- dmaengine_terminate_all(sport->dma_tx_chan); drivers/tty/serial/imx.c- dmaengine_terminate_all(sport->dma_chan_tx); drivers/tty/serial/serial-tegra.c- dmaengine_terminate_all(tup->tx_dma_chan); [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b36f09c3c441a6 ("dmaengine: Add transfer termination synchronization support")
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d4504daff99263f5..d18c680aa64b3427 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1656,11 +1656,18 @@ static void sci_free_dma(struct uart_port *port) static void sci_flush_buffer(struct uart_port *port) { + struct sci_port *s = to_sci_port(port); + /* * In uart_flush_buffer(), the xmit circular buffer has just been - * cleared, so we have to reset tx_dma_len accordingly. + * cleared, so we have to reset tx_dma_len accordingly, and stop any + * pending transfers */ - to_sci_port(port)->tx_dma_len = 0; + s->tx_dma_len = 0; + if (s->chan_tx) { + dmaengine_terminate_async(s->chan_tx); + s->cookie_tx = -EINVAL; + } } #else /* !CONFIG_SERIAL_SH_SCI_DMA */ static inline void sci_request_dma(struct uart_port *port)
While the .flush_buffer() callback clears sci_port.tx_dma_len since commit 1cf4a7efdc71cab8 ("serial: sh-sci: Fix race condition causing garbage during shutdown"), it does not terminate a transmit DMA operation that may be in progress. Fix this by terminating any pending DMA operations, and resetting the corresponding cookie. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> --- drivers/tty/serial/sh-sci.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)