Re: [PATCH v6 1/9] serial: max310x: don't clobber the TX break bit in set_termios
From: Hugo Villeneuve
Date: Mon Oct 05 2026 - 11:52:46 EST
Hi Tapio,
On Sun, 04 Oct 2026 12:16:21 +0000
Tapio Reijonen <tapio.reijonen@xxxxxxxxxxx> wrote:
> max310x_set_termios() overwrites the whole LCR register, but LCR
> also carries the TX break bit that max310x_break_ctl() drives. A break
> is a state, not an event: TIOCSBRK sets the bit and it must stay set
> until TIOCCBRK. Any termios change in between - no concurrency
> required - rewrites LCR from the termios bits alone and silently ends
> the break early.
A little bit confusing, because termios bits alone would not clear Tx
break. Maybe:
"rewrites LCR from the termios bits with Tx break cleared, thus
silently ending the break early" ?
>
> Update only the LCR bits that are derived from termios and leave the
> TX break and RTS pin control bits untouched. Since nothing clears a
> break when a port is closed with the break still asserted - the tty
> core sends no break-off on release, and the unconditional write here
> was the accidental recovery - clear TXBREAK in startup(), the same way
> 8250 does.
You say that Tx break bit must stay set until TIOCCBRK, but you clear
it in startup, so does the comment should indicate that it must stay
set until TIOCCBRK or port closing or startup?
>
> Fixes: f65444187a66 ("serial: New serial driver MAX310X")
> Assisted-by: Claude:claude-fable-5
> Signed-off-by: Tapio Reijonen <tapio.reijonen@xxxxxxxxxxx>
> ---
> drivers/tty/serial/max310x.c | 17 +++++++++++++++--
> 1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
> index 022502986c5fcf1ff4de9328746ddc71677be730..fead9c51163d8372d1b609ee9cd5b87faa917fc1 100644
> --- a/drivers/tty/serial/max310x.c
> +++ b/drivers/tty/serial/max310x.c
> @@ -158,6 +158,8 @@
> #define MAX310X_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
> #define MAX310X_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
> #define MAX310X_LCR_RTS_BIT (1 << 7) /* RTS pin control */
> +/* LCR bits owned by termios; TX break and RTS are driven elsewhere */
> +#define MAX310X_LCR_TERMIOS_MASK GENMASK(5, 0)
owned -> modified ?
driven -> configured or modified?
>
> /* IRDA register bits */
> #define MAX310X_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */
> @@ -969,8 +971,12 @@ static void max310x_set_termios(struct uart_port *port,
> if (termios->c_cflag & CSTOPB)
> lcr |= MAX310X_LCR_STOPLEN_BIT; /* 2 stops */
>
> - /* Update LCR register */
> - max310x_port_write(port, MAX310X_LCR_REG, lcr);
> + /*
> + * Update LCR register. Leave the TX break bit alone: it is driven by
> + * break_ctl(), and a whole-register write here would end a break in
> + * progress.
Maybe simpler:
"Update LCR register except TX break and RTS. Clearing TX break would
end..." ?
> + */
> + max310x_port_update(port, MAX310X_LCR_REG, MAX310X_LCR_TERMIOS_MASK, lcr);
>
> /* Set read status mask */
> port->read_status_mask = MAX310X_LSR_RXOVR_BIT;
> @@ -1088,6 +1094,13 @@ static int max310x_startup(struct uart_port *port)
>
> max310x_power(port, 1);
>
> + /*
> + * Clear a latched break: nothing clears TXBREAK when a port is
> + * closed with a break still asserted, and set_termios() no longer
> + * rewrites it.
TXBREAK -> "TX break" (consistent with your previous comments)
rewrites -> clears
> + */
> + max310x_port_update(port, MAX310X_LCR_REG, MAX310X_LCR_TXBREAK_BIT, 0);
> +
> /* Configure MODE1 register */
> max310x_port_update(port, MAX310X_MODE1_REG,
> MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
>
> --
> 2.47.3
>
--
Hugo Villeneuve