lkml.org 
[lkml]   [2020]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.14 069/127] serial: 8250_port: Don't service RX FIFO if throttled
    Date
    From: Vignesh Raghavendra <vigneshr@ti.com>

    [ Upstream commit f19c3f6c8109b8bab000afd35580929958e087a9 ]

    When port's throttle callback is called, it should stop pushing any more
    data into TTY buffer to avoid buffer overflow. This means driver has to
    stop HW from receiving more data and assert the HW flow control. For
    UARTs with auto HW flow control (such as 8250_omap) manual assertion of
    flow control line is not possible and only way is to allow RX FIFO to
    fill up, thus trigger auto HW flow control logic.

    Therefore make sure that 8250 generic IRQ handler does not drain data
    when port is stopped (i.e UART_LSR_DR is unset in read_status_mask). Not
    servicing, RX FIFO would trigger auto HW flow control when FIFO
    occupancy reaches preset threshold, thus halting RX.
    Since, error conditions in UART_LSR register are cleared just by reading
    the register, data has to be drained in case there are FIFO errors, else
    error information will lost.

    Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
    Link: https://lore.kernel.org/r/20200319103230.16867-2-vigneshr@ti.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/tty/serial/8250/8250_port.c | 16 +++++++++++++++-
    1 file changed, 15 insertions(+), 1 deletion(-)

    diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
    index 07d5925791e1c..9880a50d664fc 100644
    --- a/drivers/tty/serial/8250/8250_port.c
    +++ b/drivers/tty/serial/8250/8250_port.c
    @@ -1865,6 +1865,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
    unsigned char status;
    unsigned long flags;
    struct uart_8250_port *up = up_to_u8250p(port);
    + bool skip_rx = false;

    if (iir & UART_IIR_NO_INT)
    return 0;
    @@ -1873,7 +1874,20 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)

    status = serial_port_in(port, UART_LSR);

    - if (status & (UART_LSR_DR | UART_LSR_BI)) {
    + /*
    + * If port is stopped and there are no error conditions in the
    + * FIFO, then don't drain the FIFO, as this may lead to TTY buffer
    + * overflow. Not servicing, RX FIFO would trigger auto HW flow
    + * control when FIFO occupancy reaches preset threshold, thus
    + * halting RX. This only works when auto HW flow control is
    + * available.
    + */
    + if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) &&
    + (port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) &&
    + !(port->read_status_mask & UART_LSR_DR))
    + skip_rx = true;
    +
    + if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {
    if (!up->dma || handle_rx_dma(up, iir))
    status = serial8250_rx_chars(up, status);
    }
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-09-18 04:33    [W:5.811 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site