summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViken Dadhaniya <viken.dadhaniya@oss.qualcomm.com>2026-05-28 22:48:07 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-27 11:07:41 +0100
commitead244f937d6ee50600f974b6a3a7374d74784a6 (patch)
treea3b495e6cec01eaabe59e20b61e7f631c8a963c2
parent74be188eb2dc1c99d63986167b9a67d415fe7326 (diff)
downloadlinux-ead244f937d6ee50600f974b6a3a7374d74784a6.tar.gz
linux-ead244f937d6ee50600f974b6a3a7374d74784a6.zip
serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero
commit b93062b6d8a1b2d9bad235cac25558a909819026 upstream. In qcom_geni_serial_handle_rx_dma(), geni_se_rx_dma_unprep() clears port->rx_dma_addr before SE_DMA_RX_LEN_IN is read. If the register is zero, for example when the RX stale counter fires on an idle line, the handler returns without calling geni_se_rx_dma_prep(). The next RX DMA interrupt then hits the !port->rx_dma_addr guard and returns immediately, so the RX DMA buffer is never rearmed and later input is lost. Keep the handler on the rearm path when rx_in is zero. Warn about the unexpected zero-length DMA completion, skip received-data handling, and always call geni_se_rx_dma_prep(). Fixes: 2aaa43c70778 ("tty: serial: qcom-geni-serial: add support for serial engine DMA") Cc: stable@vger.kernel.org Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> Signed-off-by: Viken Dadhaniya <viken.dadhaniya@oss.qualcomm.com> Link: https://patch.msgid.link/20260528-serial-rx-0-byte-fix-v2-1-b4195cfe342f@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 774c0b7f8508..9d372db5216f 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -904,12 +904,9 @@ static void qcom_geni_serial_handle_rx_dma(struct uart_port *uport, bool drop)
port->rx_dma_addr = 0;
rx_in = readl(uport->membase + SE_DMA_RX_LEN_IN);
- if (!rx_in) {
- dev_warn(uport->dev, "serial engine reports 0 RX bytes in!\n");
- return;
- }
-
- if (!drop)
+ if (!rx_in)
+ dev_warn_ratelimited(uport->dev, "serial engine reports 0 RX bytes in!\n");
+ else if (!drop)
handle_rx_uart(uport, rx_in);
ret = geni_se_rx_dma_prep(&port->se, port->rx_buf,