Support for UPF_SPD_* flags is currently broken in more drivers for two reasons. First one is that uart_update_timeout() function does not calculate timeout for UPF_SPD_CUST flag correctly. Second reason is that userspace termios structre is modified by most drivers after each TIOCSSERIAL or TCSETS call to discard activation of UPF_SPD_* flags. Reproducer for these issues: #include <termios.h> #include <sys/ioctl.h> #include <asm/ioctls.h> #include <linux/serial.h> static unsigned cdiv(unsigned a, unsigned b) { if (!b) return b; return (a + (b/2)) / b; } void set_active_spd_cust_baud(int fd, unsigned baudrate) { struct serial_struct serial; struct termios termios; tcgetattr(fd, &termios); ioctl(fd, TIOCGSERIAL, &serial); serial.flags &= ~ASYNC_SPD_MASK; serial.flags |= ASYNC_SPD_CUST; serial.custom_divisor = cdiv(serial.baud_base, baudrate); ioctl(fd, TIOCSSERIAL, &serial); cfsetspeed(&termios, B38400); tcsetattr(fd, TCSANOW, &termios); } int is_spd_cust_active(int fd) { struct serial_struct serial; struct termios termios; tcgetattr(fd, &termios); ioctl(fd, TIOCGSERIAL, &serial); return (serial.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && cfgetospeed(&termios) == B38400; } (error handling was ommited for simplification) After calling set_active_spd_cust_baud() function SPD custom divisor should be active and therefore is_spd_cust_active() should return true. But it is not active (cfgetospeed does not return B38400) and this patch series should fix it. I have tested it with 8250 driver. Originally Johan Hovold reported that there may be issue with these ASYNC_SPD_FLAGS in email: https://lore.kernel.org/linux-serial/20211007133146.28949-1-johan@xxxxxxxxxx/ Johan, Greg, could you please test these patches if there is not any regression? Pali Rohár (3): serial: core: Document why UPF_SPD_CUST is not handled in uart_get_baud_rate() serial: core: Fix function uart_update_timeout() to handle UPF_SPD_CUST flag serial: Fix support for UPF_SPD_* flags in serial drivers drivers/tty/serial/21285.c | 2 +- drivers/tty/serial/8250/8250_mtk.c | 2 +- drivers/tty/serial/8250/8250_omap.c | 2 +- drivers/tty/serial/8250/8250_port.c | 2 +- drivers/tty/serial/altera_uart.c | 2 +- drivers/tty/serial/ar933x_uart.c | 2 +- drivers/tty/serial/arc_uart.c | 2 +- drivers/tty/serial/dz.c | 2 +- drivers/tty/serial/imx.c | 3 +- drivers/tty/serial/lantiq.c | 2 +- drivers/tty/serial/lpc32xx_hs.c | 2 +- drivers/tty/serial/men_z135_uart.c | 2 +- drivers/tty/serial/mps2-uart.c | 2 +- drivers/tty/serial/msm_serial.c | 2 +- drivers/tty/serial/mvebu-uart.c | 2 +- drivers/tty/serial/owl-uart.c | 2 +- drivers/tty/serial/pch_uart.c | 2 +- drivers/tty/serial/pic32_uart.c | 2 +- drivers/tty/serial/rda-uart.c | 2 +- drivers/tty/serial/rp2.c | 2 +- drivers/tty/serial/sccnxp.c | 2 +- drivers/tty/serial/serial-tegra.c | 2 +- drivers/tty/serial/serial_core.c | 76 ++++++++++++++++++++++++++++- drivers/tty/serial/sprd_serial.c | 2 +- drivers/tty/serial/timbuart.c | 2 +- drivers/tty/serial/vt8500_serial.c | 2 +- drivers/tty/serial/xilinx_uartps.c | 2 +- include/linux/serial_core.h | 2 + 28 files changed, 103 insertions(+), 28 deletions(-) -- 2.20.1