From: Samarth Narang <samarth.colleges@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jirislaby@kernel.org>
Cc: Samarth Narang <samarth.colleges@gmail.com>,
Krzysztof Kozlowski <krzk@kernel.org>,
Peter Griffin <peter.griffin@linaro.org>,
Alim Akhtar <alim.akhtar@samsung.com>,
Marek Szyprowski <m.szyprowski@samsung.com>,
Orson Zhai <orsonzhai@gmail.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Chunyan Zhang <zhang.lyra@gmail.com>,
Laxman Dewangan <ldewangan@nvidia.com>,
Thierry Reding <thierry.reding@kernel.org>,
Jonathan Hunter <jonathanh@nvidia.com>,
linux-serial@vger.kernel.org, linux-samsung-soc@vger.kernel.org,
linux-arm-msm@vger.kernel.org, linux-tegra@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: [BUG] serial: TX kfifo underflow when TCOFLUSH races with TX DMA (samsung, sprd, msm, pch_uart, tegra)
Date: Sat, 31 Oct 2026 00:47:33 +0000 [thread overview]
Message-ID: <20261031004733.3345841-1-samarth.colleges@gmail.com> (raw)
Hi,
The TX FIFO underflow previously fixed in 8250 by 9e512eaaf8f4 ("serial:
8250: Fix fifo underflow on flush") and in qcom-geni by 452d6fa37ae9,
7ea38c49e717, and e3c04834ae1a appears to affect five other serial
drivers. The line numbers below refer to mainline at 83f32c773255.
uart_flush_buffer() resets the transmit kfifo under the port lock before
calling the driver's flush_buffer() callback. If a TX DMA transfer is
still active and the driver does not account for it during the flush,
its completion callback may subsequently call uart_xmit_advance() using
the byte count from the old transfer. This can advance kfifo->out past
kfifo->in, causing kfifo_len() to wrap and the driver to transmit stale
buffer contents. As shown in the 8250 fix, a subsequent close can then
wait in tty_wait_until_sent() until it times out. The issue may arise
when a large write is followed by TCFLSH(TCOFLUSH), or when the port is
closed while TX DMA is active.
Four drivers have no flush_buffer() callback and therefore do not stop
or account for outstanding TX DMA when the kfifo is reset:
1. samsung_tty: Neither s3c64xx_serial_ops (line 1679) nor
apple_s5l_serial_ops (line 1700) implements flush_buffer(), while
s3c24xx_serial_tx_dma_complete() advances the kfifo by
tx_bytes_requested - residue (line 342) without checking whether a
flush occurred.
2. sprd_serial: serial_sprd_ops (line 944) has no flush_buffer()
callback, and sprd_complete_tx_dma() advances the kfifo by
tx_dma.trans_len (line 276).
3. msm_serial: msm_uart_pops (line 1547) does not implement
flush_buffer(), while msm_complete_tx_dma() advances by
sg_dma_len(&dma->tx_sg) - residue (line 482). Its check for an
already stopped transfer relies on tx_sg, which is not cleared by a
flush.
4. pch_uart: pch_uart_ops (line 1518) has no flush_buffer() callback,
and pch_dma_tx_complete() advances the kfifo using each scatterlist
entry's sg_dma_len() (line 756) without holding the port lock.
The fifth driver, serial-tegra, implements tegra_uart_flush_buffer()
(lines 1272-1279), but only clears tx_bytes and calls
dmaengine_terminate_all(). Its completion callback calculates the
transferred byte count from tx_bytes_requested - residue (line 537)
before acquiring the port lock and advances the kfifo afterward (line
540), while tx_bytes_requested is left unchanged by the flush. Although
terminated descriptors do not invoke their callbacks, a completion
already running when the flush occurs, particularly one waiting to
acquire the port lock held by uart_flush_buffer(), may still advance the
reset kfifo. This is the same race addressed by 452d6fa37ae9.
The existing 8250 and qcom-geni fixes provide possible approaches, with
the former clearing the outstanding DMA byte count under the port lock
and the latter marking completions as stale during a flush. As discussed
in 7ea38c49e717, comparing the completion count against kfifo_len()
alone is insufficient.
These findings came from a research static analyzer that checks whether
uart_ops implementations using TX DMA provide flush handling that
accounts for outstanding transfers, followed by manual inspection of the
reported paths. None has been reproduced on hardware. The same analysis
found flush handling in the 8250 core, atmel, fsl_lpuart, imx, sh-sci,
and qcom-geni, while amba-pl011 is not affected because it advances the
kfifo when preparing a transfer rather than on completion.
I would be happy to prepare separate patches for the affected drivers if
the maintainers agree with the analysis.
Thanks,
Samarth
next reply other threads:[~2026-10-31 0:47 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 0:47 Samarth Narang [this message]
2026-10-31 8:54 ` [BUG] serial: TX kfifo underflow when TCOFLUSH races with TX DMA (samsung, sprd, msm, pch_uart, tegra) Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261031004733.3345841-1-samarth.colleges@gmail.com \
--to=samarth.colleges@gmail.com \
--cc=alim.akhtar@samsung.com \
--cc=baolin.wang@linux.alibaba.com \
--cc=gregkh@linuxfoundation.org \
--cc=jirislaby@kernel.org \
--cc=jonathanh@nvidia.com \
--cc=krzk@kernel.org \
--cc=ldewangan@nvidia.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=orsonzhai@gmail.com \
--cc=peter.griffin@linaro.org \
--cc=thierry.reding@kernel.org \
--cc=zhang.lyra@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox