All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "James Hilliard" <james.hilliard1@gmail.com>
Cc: linux-serial@vger.kernel.org, imx@lists.linux.dev, Frank.Li@kernel.org
Subject: Re: [PATCH v10 7/8] serial: 8250: retire canceled RX DMA before reusing the receive buffer
Date: Mon, 09 Nov 2026 04:22:32 +0000	[thread overview]
Message-ID: <sashiko-outbox-204402@kernel.org> (raw)
In-Reply-To: <20261108-submit-serial-8250-dma-cancel-v1-v10-7-e6227ddb95b1@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [High] serial: 8250: unbounded pause retry loop in
  serial8250_rx_dma_flush_work()
--

commit 818afe206e7bf388666735a110a648d91146a4e7
Author: James Hilliard <james.hilliard1@gmail.com>

serial: 8250: retire canceled RX DMA before reusing the receive buffer

This commit defers reuse of a canceled RX DMA buffer until a worker has
drained pending DMA callbacks, and retries failed pause attempts from
process context before copying or recovering the channel.

> diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c
> index 739a8238e4dec..1ea22954150ca 100644
> --- a/drivers/tty/serial/8250/8250_dma.c
> +++ b/drivers/tty/serial/8250/8250_dma.c
[ ... ]
> +/* Try to obtain a stable residue before retiring the current descriptor. */
> +static int serial8250_rx_dma_try_flush(struct uart_8250_port *p)
> +{
> +	struct uart_8250_dma *dma = p->dma;
> +	struct dma_tx_state state;
> +	enum dma_status status;
> +	int ret;
> +
> +	lockdep_assert_held_once(&p->port.lock);
> +
> +	ret = dmaengine_pause(dma->rxchan);
> +	status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
> +	if (status == DMA_ERROR) {
> +		ret = -EIO;
> +		goto recover;
> +	}
> +	if (ret && status != DMA_COMPLETE) {
> +		/*
> +		 * Hardware may be idle before the provider publishes completion.
> +		 * Leave the descriptor alive and retry outside interrupt context;
> +		 * neither copying its buffer nor canceling it is safe yet.
> +		 */
> +		dma->rx_pause_pending = true;
> +		serial8250_out_IER(p, p->ier);
> +		return ret;
> +	}
[ ... ]
> +static void serial8250_rx_dma_flush_work(struct work_struct *work)
> +{
> +	struct uart_8250_dma *dma = container_of(work, struct uart_8250_dma, rx_flush_work);
> +	struct uart_8250_port *p = dma->port;
> +	unsigned int delay_us = 1 * USEC_PER_MSEC;
> +	ktime_t start = ktime_get();
> +	bool recover, retry, restore_rx;
> +	bool warned = false;
> +	int ret;
> +
> +	guard(serial8250_rpm)(p);
> +
> +	for (;;) {
> +		scoped_guard(uart_port_lock_irqsave, &p->port) {
> +			/* Shutdown cancels this work and drains both DMA channels. */
> +			if (dma->shutting_down)
> +				return;
> +			/* Serialize reset with completion and shutdown notifications. */
> +			WRITE_ONCE(dma->rx_pause_wakeup, false);
> +			retry = dma->rx_pause_pending && !dma->rx_terminating;
> +			if (retry) {
> +				ret = serial8250_rx_dma_try_flush(p);
> +				retry = dma->rx_pause_pending && !dma->rx_terminating;
> +			}
> +			recover = dma->rx_err;
> +		}
> +		if (!retry)
> +			break;
> +		if (!warned && ktime_ms_delta(ktime_get(), start) >= 1 * MSEC_PER_SEC) {
> +			dev_warn(p->port.dev,
> +				 "RX DMA pause stalled: %d; retaining transfer and retrying\n",
> +				 ret);
> +			warned = true;
> +		}
> +		/* Notifications also cover completion or shutdown before sleeping. */
> +		wait_event_hrtimeout(dma->rx_pause_wait, READ_ONCE(dma->rx_pause_wakeup),
> +				     ns_to_ktime(delay_us * NSEC_PER_USEC));
> +		delay_us = min(delay_us * 2, 1 * USEC_PER_SEC);
> +	}

[Severity: High]
As reported by Raul E Rangel on v8 [1], can serial8250_rx_dma_flush_work()
spin in its retry loop until the port is closed when dmaengine_pause() fails
persistently on a partial transfer?

Once p->port.lock and local IRQs have been released across a few sleeps, any
pending completion hardirq for a finished transfer has already run. On a
partial transfer that has not reached dma->rx_size, an in-tree provider such
as dw-axi-dmac can time out waiting for DWAXIDMAC_IRQ_SUSPENDED in
dma_chan_pause(), clear that status bit while leaving the hardware channel
suspended, and return -EAGAIN on every subsequent retry:

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c:dma_chan_pause() {
	...
	do {
		if (axi_chan_irq_read(chan) & DWAXIDMAC_IRQ_SUSPENDED)
			break;

		udelay(2);
	} while (--timeout);

	axi_chan_irq_clear(chan, DWAXIDMAC_IRQ_SUSPENDED);

	chan->is_paused = true;

	return timeout ? 0 : -EAGAIN;
}

Because the channel is suspended in hardware, it never receives more bytes to
reach DMA_COMPLETE, and every retry in serial8250_rx_dma_try_flush() keeps
dma->rx_pause_pending set. That wedges RX on the port (with UART_IER_RDI,
UART_IER_RLSI, and UART_IER_RTOIE masked and skip_rx forced in
serial8250_handle_irq_locked()), holds the runtime PM reference in
serial8250_rx_dma_flush_work(), and causes dw8250_idle_enter() to fail with
-EAGAIN until shutdown(), which then discards dma->rx_buf without delivering
the partial data anyway.

Escalating to serial8250_rx_dma_recover(p) after a bounded retry budget (or
immediately on -ENOSYS / -EOPNOTSUPP) would let dmaengine_terminate_sync()
stop the channel and fall back to PIO.

[1] https://lore.kernel.org/r/20261029222734.3086943-1-rrangel@chromium.org

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-submit-serial-8250-dma-cancel-v1-v10-0-e6227ddb95b1@gmail.com?part=7

  reply	other threads:[~2026-11-09  4:22 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09  3:50 [PATCH v10 0/8] serial: 8250: serialize DMA cancellation with buffer reuse James Hilliard
2026-11-09  3:50 ` [PATCH v10 1/8] serial: 8250_omap: separate locked TX DMA completion processing James Hilliard
2026-11-09  3:56   ` sashiko-bot
2026-11-09  3:50 ` [PATCH v10 2/8] serial: serialize asynchronous write wakeups with the port lock James Hilliard
2026-11-09  4:04   ` sashiko-bot
2026-11-09 22:57   ` Andy Shevchenko
2026-11-09  3:50 ` [PATCH v10 3/8] serial: 8250_omap: serialize RX DMA completion and flushing James Hilliard
2026-11-09  4:08   ` sashiko-bot
2026-11-09  3:50 ` [PATCH v10 4/8] serial: 8250_omap: quiesce DMA IRQ handling before shutdown James Hilliard
2026-11-09  4:00   ` sashiko-bot
2026-11-09  3:50 ` [PATCH v10 5/8] serial: core: allow drivers to reserve flushed transmit storage James Hilliard
2026-11-09  4:07   ` sashiko-bot
2026-11-09  3:50 ` [PATCH v10 6/8] serial: 8250: drain canceled TX DMA before reusing its buffer James Hilliard
2026-11-09  4:03   ` sashiko-bot
2026-11-09  3:50 ` [PATCH v10 7/8] serial: 8250: retire canceled RX DMA before reusing the receive buffer James Hilliard
2026-11-09  4:22   ` sashiko-bot [this message]
2026-11-09 16:21   ` Raul E Rangel
2026-11-09  3:50 ` [PATCH v10 8/8] serial: 8250: retain DMA resources when termination fails James Hilliard
2026-11-09  4:05   ` sashiko-bot
2026-11-09 16:21   ` Raul E Rangel
  -- strict thread matches above, loose matches on Subject: below --
2026-11-02 23:14 [PATCH v9 0/8] serial: 8250: serialize DMA cancellation with buffer reuse James Hilliard
2026-11-02 23:14 ` [PATCH v9 1/8] serial: 8250_omap: separate locked TX DMA completion processing James Hilliard
2026-11-02 23:21   ` sashiko-bot
2026-11-03 16:10   ` Raul E Rangel
2026-11-02 23:14 ` [PATCH v9 2/8] serial: serialize asynchronous write wakeups with the port lock James Hilliard
2026-11-02 23:25   ` sashiko-bot
2026-11-03 16:10   ` Raul E Rangel
2026-11-03 17:06   ` Andy Shevchenko
2026-11-03 20:25     ` Maciej W. Rozycki
2026-11-02 23:14 ` [PATCH v9 3/8] serial: 8250_omap: serialize RX DMA completion and flushing James Hilliard
2026-11-02 23:32   ` sashiko-bot
2026-11-03 11:55   ` Ilpo Järvinen
2026-11-03 16:10   ` Raul E Rangel
2026-11-02 23:14 ` [PATCH v9 4/8] serial: 8250_omap: quiesce DMA IRQ handling before shutdown James Hilliard
2026-11-02 23:22   ` sashiko-bot
2026-11-03 16:11   ` Raul E Rangel
2026-11-02 23:14 ` [PATCH v9 5/8] serial: core: allow drivers to reserve flushed transmit storage James Hilliard
2026-11-02 23:32   ` sashiko-bot
2026-11-03 16:11   ` Raul E Rangel
2026-11-03 17:08   ` Andy Shevchenko
2026-11-02 23:14 ` [PATCH v9 6/8] serial: 8250: drain canceled TX DMA before reusing its buffer James Hilliard
2026-11-02 23:28   ` sashiko-bot
2026-11-03 16:11   ` Raul E Rangel
2026-11-03 17:21   ` Andy Shevchenko
2026-11-02 23:14 ` [PATCH v9 7/8] serial: 8250: retire canceled RX DMA before reusing the receive buffer James Hilliard
2026-11-02 23:49   ` sashiko-bot
2026-11-03  1:23     ` James Hilliard
2026-11-03 16:11   ` Raul E Rangel
2026-11-03 18:05     ` James Hilliard
2026-11-03 17:33   ` Andy Shevchenko
2026-11-03 17:54     ` James Hilliard
2026-11-03 18:06       ` Andy Shevchenko
2026-11-03 18:16         ` James Hilliard
2026-11-03 20:59           ` Andy Shevchenko
2026-11-02 23:14 ` [PATCH v9 8/8] serial: 8250: retain DMA resources when termination fails James Hilliard
2026-11-02 23:29   ` sashiko-bot
2026-11-03 16:11   ` Raul E Rangel
2026-11-03 17:35   ` Andy Shevchenko

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=sashiko-outbox-204402@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=james.hilliard1@gmail.com \
    --cc=linux-serial@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.