lkml.org 
[lkml]   [2020]   [May]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 62/81] tty: serial: qcom_geni_serial: Fix wrap around of TX buffer
    Date
    From: Matthias Kaehlcke <mka@chromium.org>

    [ Upstream commit 3c66eb4ba18dd1cab0d1bde651cde6d8bdb47696 ]

    Before commit a1fee899e5bed ("tty: serial: qcom_geni_serial: Fix
    softlock") the size of TX transfers was limited to the TX FIFO size,
    and wrap arounds of the UART circular buffer were split into two
    transfers. With the commit wrap around are allowed within a transfer.
    The TX FIFO of the geni serial port uses a word size of 4 bytes. In
    case of a circular buffer wrap within a transfer the driver currently
    may write an incomplete word to the FIFO, with some bytes containing
    data from the circular buffer and others being zero. Since the
    transfer isn't completed yet the zero bytes are sent as if they were
    actual data.

    Handle wrap arounds of the TX buffer properly and ensure that words
    written to the TX FIFO always contain valid data (unless the transfer
    is completed).

    Fixes: a1fee899e5bed ("tty: serial: qcom_geni_serial: Fix softlock")
    Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
    Reviewed-by: Evan Green <evgreen@chromium.org>
    Tested-by: Ryan Case <ryandcase@chromium.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/tty/serial/qcom_geni_serial.c | 12 +++++++-----
    1 file changed, 7 insertions(+), 5 deletions(-)

    diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
    index 4458419f053b..0d405cc58e72 100644
    --- a/drivers/tty/serial/qcom_geni_serial.c
    +++ b/drivers/tty/serial/qcom_geni_serial.c
    @@ -705,7 +705,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
    avail *= port->tx_bytes_pw;

    tail = xmit->tail;
    - chunk = min3(avail, pending, (size_t)(UART_XMIT_SIZE - tail));
    + chunk = min(avail, pending);
    if (!chunk)
    goto out_write_wakeup;

    @@ -727,19 +727,21 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,

    memset(buf, 0, ARRAY_SIZE(buf));
    tx_bytes = min_t(size_t, remaining, port->tx_bytes_pw);
    - for (c = 0; c < tx_bytes ; c++)
    - buf[c] = xmit->buf[tail + c];
    +
    + for (c = 0; c < tx_bytes ; c++) {
    + buf[c] = xmit->buf[tail++];
    + tail &= UART_XMIT_SIZE - 1;
    + }

    iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);

    i += tx_bytes;
    - tail += tx_bytes;
    uport->icount.tx += tx_bytes;
    remaining -= tx_bytes;
    port->tx_remaining -= tx_bytes;
    }

    - xmit->tail = tail & (UART_XMIT_SIZE - 1);
    + xmit->tail = tail;

    /*
    * The tx fifo watermark is level triggered and latched. Though we had
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-05-26 21:06    [W:3.432 / U:0.452 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site