summaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@orcam.me.uk>2021-06-10 20:38:34 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-14 17:07:41 +0200
commit1e8c052902861cadcc3ac39e4800f0ca8f335622 (patch)
treefb6e9f262608ba4370b4cde74ca0832eb5cbf094 /drivers/tty
parent63432a8b2af244ea9a82652ce5a4a2d3e95883e9 (diff)
downloadlinux-stable-1e8c052902861cadcc3ac39e4800f0ca8f335622.tar.gz
linux-stable-1e8c052902861cadcc3ac39e4800f0ca8f335622.tar.bz2
linux-stable-1e8c052902861cadcc3ac39e4800f0ca8f335622.zip
serial: 8250: Actually allow UPF_MAGIC_MULTIPLIER baud rates
[ Upstream commit 78bcae8616ac277d6cb7f38e211493948ed73e30 ] Support for magic baud rate divisors of 32770 and 32769 used with SMSC Super I/O chips for extra baud rates of 230400 and 460800 respectively where base rate is 115200[1] has been added around Linux 2.5.64, which predates our repo history, but the origin could be identified as commit 2a717aad772f ("Merge with Linux 2.5.64.") with the old MIPS/Linux repo also at: <git://git.kernel.org/pub/scm/linux/kernel/git/ralf/linux.git>. Code that is now in `serial8250_do_get_divisor' was added back then to `serial8250_get_divisor', but that code would only ever trigger if one of the higher baud rates was actually requested, and that cannot ever happen, because the earlier call to `serial8250_get_baud_rate' never returns them. This is because it calls `uart_get_baud_rate' with the maximum requested being the base rate, that is clk/16 or 115200 for SMSC chips at their nominal clock rate. Fix it then and allow UPF_MAGIC_MULTIPLIER baud rates to be selected, by requesting the maximum baud rate of clk/4 rather than clk/16 if the flag has been set. Also correct the minimum baud rate, observing that these ports only support actual (non-magic) divisors of up to 32767 only. References: [1] "FDC37M81x, PC98/99 Compliant Enhanced Super I/O Controller with Keyboard/Mouse Wake-Up", Standard Microsystems Corporation, Rev. 03/27/2000, Table 31 - "Baud Rates", p. 77 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk> Link: https://lore.kernel.org/r/alpine.DEB.2.21.2105190412280.29169@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/8250/8250_port.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index fc5ab2032282..ff3f13693def 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -2629,6 +2629,21 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
struct ktermios *old)
{
unsigned int tolerance = port->uartclk / 100;
+ unsigned int min;
+ unsigned int max;
+
+ /*
+ * Handle magic divisors for baud rates above baud_base on SMSC
+ * Super I/O chips. Enable custom rates of clk/4 and clk/8, but
+ * disable divisor values beyond 32767, which are unavailable.
+ */
+ if (port->flags & UPF_MAGIC_MULTIPLIER) {
+ min = port->uartclk / 16 / UART_DIV_MAX >> 1;
+ max = (port->uartclk + tolerance) / 4;
+ } else {
+ min = port->uartclk / 16 / UART_DIV_MAX;
+ max = (port->uartclk + tolerance) / 16;
+ }
/*
* Ask the core to calculate the divisor for us.
@@ -2636,9 +2651,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port,
* slower than nominal still match standard baud rates without
* causing transmission errors.
*/
- return uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / UART_DIV_MAX,
- (port->uartclk + tolerance) / 16);
+ return uart_get_baud_rate(port, termios, old, min, max);
}
/*