Skip to content

Commit f85e045

Browse files
l1kgregkh
authored andcommitted
serial: 8250: Fix RTS modem control while in rs485 mode
Commit f45709d ("serial: 8250: Don't touch RTS modem control while in rs485 mode") sought to prevent user space from interfering with rs485 communication by ignoring a TIOCMSET ioctl() which changes RTS polarity. It did so in serial8250_do_set_mctrl(), which turns out to be too deep in the call stack: When a uart_port is opened, RTS polarity is set by the rs485-aware function uart_port_dtr_rts(). It calls down to serial8250_do_set_mctrl() and that particular RTS polarity change should *not* be ignored. The user-visible result is that on 8250_omap ports which use rs485 with inverse polarity (RTS bit in MCR register is 1 to receive, 0 to send), a newly opened port initially sets up RTS for sending instead of receiving. That's because omap_8250_startup() sets the cached value up->mcr to 0 and omap_8250_restore_regs() subsequently writes it to the MCR register. Due to the commit, serial8250_do_set_mctrl() preserves that incorrect register value: do_sys_openat2 do_filp_open path_openat vfs_open do_dentry_open chrdev_open tty_open uart_open tty_port_open uart_port_activate uart_startup uart_port_startup serial8250_startup omap_8250_startup # up->mcr = 0 uart_change_speed serial8250_set_termios omap_8250_set_termios omap_8250_restore_regs serial8250_out_MCR # up->mcr written tty_port_block_til_ready uart_dtr_rts uart_port_dtr_rts serial8250_set_mctrl omap8250_set_mctrl serial8250_do_set_mctrl # mcr[1] = 1 ignored Fix by intercepting RTS changes from user space in uart_tiocmset() instead. Link: https://lore.kernel.org/linux-serial/[email protected]/ Fixes: f45709d ("serial: 8250: Don't touch RTS modem control while in rs485 mode") Cc: Chao Zeng <[email protected]> Cc: [email protected] # v5.7+ Reported-by: Su Bao Cheng <[email protected]> Reported-by: Jan Kiszka <[email protected]> Tested-by: Su Bao Cheng <[email protected]> Signed-off-by: Lukas Wunner <[email protected]> Link: https://lore.kernel.org/r/21170e622a1aaf842a50b32146008b5374b3dd1d.1637596432.git.lukas@wunner.de Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4e96797 commit f85e045

File tree

2 files changed

+5
-7
lines changed

2 files changed

+5
-7
lines changed

drivers/tty/serial/8250/8250_port.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2024,13 +2024,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
20242024
struct uart_8250_port *up = up_to_u8250p(port);
20252025
unsigned char mcr;
20262026

2027-
if (port->rs485.flags & SER_RS485_ENABLED) {
2028-
if (serial8250_in_MCR(up) & UART_MCR_RTS)
2029-
mctrl |= TIOCM_RTS;
2030-
else
2031-
mctrl &= ~TIOCM_RTS;
2032-
}
2033-
20342027
mcr = serial8250_TIOCM_to_MCR(mctrl);
20352028

20362029
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;

drivers/tty/serial/serial_core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
10751075
goto out;
10761076

10771077
if (!tty_io_error(tty)) {
1078+
if (uport->rs485.flags & SER_RS485_ENABLED) {
1079+
set &= ~TIOCM_RTS;
1080+
clear &= ~TIOCM_RTS;
1081+
}
1082+
10781083
uart_update_mctrl(uport, set, clear);
10791084
ret = 0;
10801085
}

0 commit comments

Comments
 (0)