lkml.org 
[lkml]   [2018]   [Apr]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 048/190] serial: sh-sci: Fix race condition causing garbage during shutdown
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Geert Uytterhoeven <geert+renesas@glider.be>


    [ Upstream commit 1cf4a7efdc71cab84c42cfea7200608711ea954f ]

    If DMA is enabled and used, a burst of old data may be seen on the
    serial console during "poweroff" or "reboot". uart_flush_buffer()
    clears the circular buffer, but sci_port.tx_dma_len is not reset.
    This leads to a circular buffer overflow, dumping (UART_XMIT_SIZE -
    sci_port.tx_dma_len) bytes.

    To fix this, add a .flush_buffer() callback that resets
    sci_port.tx_dma_len.

    Inspired by commit 31ca2c63fdc0aee7 ("tty/serial: atmel: fix race
    condition (TX+DMA)").

    Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/tty/serial/sh-sci.c | 16 ++++++++++++++--
    1 file changed, 14 insertions(+), 2 deletions(-)

    --- a/drivers/tty/serial/sh-sci.c
    +++ b/drivers/tty/serial/sh-sci.c
    @@ -1457,7 +1457,16 @@ static void sci_free_dma(struct uart_por
    if (s->chan_rx)
    sci_rx_dma_release(s, false);
    }
    -#else
    +
    +static void sci_flush_buffer(struct uart_port *port)
    +{
    + /*
    + * In uart_flush_buffer(), the xmit circular buffer has just been
    + * cleared, so we have to reset tx_dma_len accordingly.
    + */
    + to_sci_port(port)->tx_dma_len = 0;
    +}
    +#else /* !CONFIG_SERIAL_SH_SCI_DMA */
    static inline void sci_request_dma(struct uart_port *port)
    {
    }
    @@ -1465,7 +1474,9 @@ static inline void sci_request_dma(struc
    static inline void sci_free_dma(struct uart_port *port)
    {
    }
    -#endif
    +
    +#define sci_flush_buffer NULL
    +#endif /* !CONFIG_SERIAL_SH_SCI_DMA */

    static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
    {
    @@ -2205,6 +2216,7 @@ static struct uart_ops sci_uart_ops = {
    .break_ctl = sci_break_ctl,
    .startup = sci_startup,
    .shutdown = sci_shutdown,
    + .flush_buffer = sci_flush_buffer,
    .set_termios = sci_set_termios,
    .pm = sci_pm,
    .type = sci_type,

    \
     
     \ /
      Last update: 2018-04-11 22:53    [W:2.565 / U:0.144 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site