Linux Serial subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Tapio Reijonen" <tapio.reijonen@vaisala.com>
Cc: linux-serial@vger.kernel.org
Subject: Re: [PATCH v7 9/9] serial: max310x: don't transmit while an RS485 reconfigure is pending
Date: Mon, 05 Oct 2026 13:41:09 +0000	[thread overview]
Message-ID: <20261005134109.EE6A11F00893@smtp.kernel.org> (raw)
In-Reply-To: <20261005-max310x-rs485-sw-delay-v7-9-6ae392eca08c@vaisala.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] tty: max310x: tx_work bypasses rs485_pending gate allowing transmission during reconfigure
- [High] tty: max310x: TOCTOU race on chip_tx_empty causes incorrect state rewind
--

commit 7203e556ec43dfcd637262655ece112903f9eb73
Author: Tapio Reijonen <tapio.reijonen@vaisala.com>

serial: max310x: don't transmit while an RS485 reconfigure is pending

This commit defers transmissions while an RS485 configuration is pending,
leaving data in the kfifo until rs_work finishes reprogramming the registers.
It drops the direct tx_work kick in the disable path in favor of restarting
the transmission once the configuration is fully applied.

> diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
> index 5fdb9dfca6027..833ab4d461235 100644
> --- a/drivers/tty/serial/max310x.c
> +++ b/drivers/tty/serial/max310x.c

[ ... ]

> @@ -979,6 +980,16 @@ static void max310x_start_tx(struct uart_port *port)
>  	if (one->tx_teardown)
>  		return;
>  
> +	/*
> +	 * An RS485 reconfigure is scheduled but not applied yet: transmitting
> +	 * now would use the old path against half-programmed registers - a
> +	 * TIOCSRS485 switching paths followed immediately by a write puts the
> +	 * data on the wire with the transceiver released. Leave the data in
> +	 * the kfifo; rs_work restarts TX once the configuration is applied.
> +	 */
> +	if (one->rs485_pending)
> +		return;

[Severity: High]
Does this check sufficiently gate the transmission?

While this defers synchronous writes, a TXEMPTY interrupt can asynchronously
queue tx_work during the pending RS485 reconfiguration:

max310x_port_irq()
  if (ists & MAX310X_IRQ_TXEMPTY_BIT)
      schedule_work(&s->p[portno].tx_work);

If tx_work executes concurrently with max310x_rs_proc(), it calls
max310x_handle_tx() which pumps data from xmit_fifo to the hardware FIFO:

max310x_handle_tx()
  while (!kfifo_is_empty(&tport->xmit_fifo)) {
      /* Limit to space available in TX FIFO */
      txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG);
      ...
  }

Since max310x_handle_tx() runs without holding a synchronizing lock or
checking the rs485_pending flag, can this regression allow background workers
to bypass the deferral mechanism and transmit data with a half-programmed
transceiver?

[ ... ]

> @@ -1465,6 +1479,31 @@ static void max310x_rs_proc(struct work_struct *ws)
>  
>  	max310x_port_update(&one->port, MAX310X_MODE2_REG,
>  			    MAX310X_MODE2_ECHOSUPR_BIT, mode2);
> +
> +	/*
> +	 * The configuration is applied: release any TX that start_tx()
> +	 * deferred while the reconfigure was pending, now on the right
> +	 * path. start_tx() can drop and retake the lock through the
> +	 * uart_port API - a raw spinlock guard here would unbalance it.
> +	 */
> +	chip_tx_empty = !max310x_port_read(&one->port,
> +					   MAX310X_TXFIFOLVL_REG);
> +
> +	uart_port_lock_irqsave(&one->port, &flags);
> +	one->rs485_pending = false;
> +	if (one->port.x_char ||
> +	    !kfifo_is_empty(&one->port.state->port.xmit_fifo)) {
> +		/*
> +		 * A send state adopted without chip data is the deferred
> +		 * write itself: restart it as a fresh envelope so the
> +		 * before-send delay is honoured.
> +		 */
> +		if (chip_tx_empty &&
> +		    READ_ONCE(one->tx_state) == MAX310X_TX_SEND)
> +			WRITE_ONCE(one->tx_state, MAX310X_TX_OFF);

[Severity: High]
Is it possible for chip_tx_empty to be stale here due to a race with tx_work?

The TX FIFO level is read outside the lock. Concurrently, tx_work can execute
max310x_handle_tx() and write new data to the chip FIFO without acquiring
port->lock.

When max310x_rs_proc() then acquires port->lock, it uses the stale
chip_tx_empty value to rewind the transmission state to MAX310X_TX_OFF, even
though data is already being transmitted.

Can this incorrect rewind introduce a regression by breaking the timing
envelope, causing data to hit the RS485 bus without the configured
before-send delay?

> +		max310x_start_tx(&one->port);
> +	}
> +	uart_port_unlock_irqrestore(&one->port, flags);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261005-max310x-rs485-sw-delay-v7-0-6ae392eca08c@vaisala.com?part=9

  reply	other threads:[~2026-10-05 13:41 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05 13:19 [PATCH v7 0/9] (no cover subject) Tapio Reijonen
2026-10-05 13:19 ` [PATCH v7 1/9] serial: max310x: don't clobber the TX break bit in set_termios Tapio Reijonen
2026-10-05 13:27   ` sashiko-bot
2026-10-05 15:57   ` Hugo Villeneuve
2026-10-06  4:06     ` Tapio Reijonen
2026-10-06 13:42       ` Hugo Villeneuve
2026-10-08  9:06         ` Tapio Reijonen
2026-10-05 13:19 ` [PATCH v7 2/9] serial: max310x: assert the transceiver during a break Tapio Reijonen
2026-10-05 13:39   ` sashiko-bot
2026-10-05 13:19 ` [PATCH v7 3/9] serial: max310x: centralize the RS485 transceiver programming Tapio Reijonen
2026-10-05 13:19 ` [PATCH v7 4/9] serial: max310x: convert RS485 delays from milliseconds to bit-times Tapio Reijonen
2026-10-05 13:33   ` sashiko-bot
2026-10-05 13:19 ` [PATCH v7 5/9] serial: max310x: stop the transmitter before powering down in shutdown Tapio Reijonen
2026-10-05 13:34   ` sashiko-bot
2026-10-05 13:19 ` [PATCH v7 6/9] serial: max310x: support active-low RTS on the hardware path Tapio Reijonen
2026-10-05 13:34   ` sashiko-bot
2026-10-05 13:19 ` [PATCH v7 7/9] serial: max310x: schedule tx_work directly from the IRQ handler Tapio Reijonen
2026-10-05 13:30   ` sashiko-bot
2026-10-05 13:19 ` [PATCH v7 8/9] serial: max310x: drive RTS in software when hardware delays are too short Tapio Reijonen
2026-10-05 13:40   ` sashiko-bot
2026-10-05 13:19 ` [PATCH v7 9/9] serial: max310x: don't transmit while an RS485 reconfigure is pending Tapio Reijonen
2026-10-05 13:41   ` sashiko-bot [this message]
2026-10-05 13:37 ` [PATCH v7 0/9] (no cover subject) Tapio Reijonen
2026-10-05 15:51 ` Hugo Villeneuve
2026-10-06  4:03   ` Tapio Reijonen

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=20261005134109.EE6A11F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tapio.reijonen@vaisala.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