tty: serial: qcom_geni_serial: Fix UART hang
authorRyan Case <ryandcase@chromium.org>
Wed, 19 Dec 2018 20:33:53 +0000 (12:33 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Feb 2020 15:38:52 +0000 (16:38 +0100)
[ Upstream commit 663abb1a7a7ff8fea9ab0145463de7fcff823755 ]

If a serial console write occured while a UART transmit command was
waiting for a done signal then no further data would be sent until
something new kicked the system into gear. If there is already data
waiting in the circular buffer we must re-enable the tx watermark so we
receive the expected interrupts.

Signed-off-by: Ryan Case <ryandcase@chromium.org>
Reviewed-by: Evan Green <evgreen@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

index b3f7d1a..2003dfc 100644 (file)
@@ -438,6 +438,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
        bool locked = true;
        unsigned long flags;
        u32 geni_status;
+       u32 irq_en;
 
        WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS);
 
@@ -472,6 +473,13 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
                 * has been sent, in which case we need to look for done first.
                 */
                qcom_geni_serial_poll_tx_done(uport);
+
+               if (uart_circ_chars_pending(&uport->state->xmit)) {
+                       irq_en = readl_relaxed(uport->membase +
+                                       SE_GENI_M_IRQ_EN);
+                       writel_relaxed(irq_en | M_TX_FIFO_WATERMARK_EN,
+                                       uport->membase + SE_GENI_M_IRQ_EN);
+               }
        }
 
        __qcom_geni_serial_console_write(uport, s, count);