
From: Johan Hovold <johan@kernel.org> stable inclusion from stable-v5.10.145 commit 107c6b60582c99820916b19183b5c855e2d60434 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6D0VF Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit d02b006b29de14968ba4afa998bede0d55469e29 upstream. This reverts commit 32262e2e429cdb31f9e957e997d53458762931b7. The commit in question claims to determine the inverse of serial8250_get_divisor() but failed to notice that some drivers override the default implementation using a get_divisor() callback. This means that the computed line-speed values can be completely wrong and results in regular TCSETS requests failing (the incorrect values would also be passed to any overridden set_divisor() callback). Similarly, it also failed to honour the old (deprecated) ASYNC_SPD_FLAGS and would break applications relying on those when re-encoding the actual line speed. There are also at least two quirks, UART_BUG_QUOT and an OMAP1510 workaround, which were happily ignored and that are now broken. Finally, even if the offending commit were to be implemented correctly, this is a new feature and not something which should be backported to stable. Cc: Pali Rohár <pali@kernel.org> Fixes: 32262e2e429c ("serial: 8250: Fix reporting real baudrate value in c_ospeed field") Cc: stable <stable@vger.kernel.org> Signed-off-by: Johan Hovold <johan@kernel.org> Link: https://lore.kernel.org/r/20211007133146.28949-1-johan@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com> Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> --- drivers/tty/serial/8250/8250_port.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index eaf4eb33a78d..9d60418e4adb 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2547,19 +2547,6 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, return serial8250_do_get_divisor(port, baud, frac); } -static unsigned int serial8250_compute_baud_rate(struct uart_port *port, - unsigned int quot) -{ - if ((port->flags & UPF_MAGIC_MULTIPLIER) && quot == 0x8001) - return port->uartclk / 4; - else if ((port->flags & UPF_MAGIC_MULTIPLIER) && quot == 0x8002) - return port->uartclk / 8; - else if (port->type == PORT_NPCM) - return DIV_ROUND_CLOSEST(port->uartclk - 2 * (quot + 2), 16 * (quot + 2)); - else - return DIV_ROUND_CLOSEST(port->uartclk, 16 * quot); -} - static unsigned char serial8250_compute_lcr(struct uart_8250_port *up, tcflag_t c_cflag) { @@ -2701,14 +2688,11 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) baud = serial8250_get_baud_rate(port, termios, NULL); quot = serial8250_get_divisor(port, baud, &frac); - baud = serial8250_compute_baud_rate(port, quot); serial8250_rpm_get(up); spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); - if (tty_termios_baud_rate(termios)) - tty_termios_encode_baud_rate(termios, baud, baud); serial8250_set_divisor(port, baud, quot, frac); serial_port_out(port, UART_LCR, up->lcr); @@ -2742,7 +2726,6 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, baud = serial8250_get_baud_rate(port, termios, old); quot = serial8250_get_divisor(port, baud, &frac); - baud = serial8250_compute_baud_rate(port, quot); /* * Ok, we're now changing the port state. Do it with -- 2.25.1