On Sunday 24 July 2022 14:28:43 Johan Hovold wrote: > On Tue, Jul 12, 2022 at 01:53:05PM +0200, Marek Behún wrote: > > From: Pali Rohár <pali@xxxxxxxxxx> > > > > When ASYNC_SPD_CUST is used, update custom_divisor and c_*speed fields > > so that they correspond to the newly set baud rate value, so that > > userspace GET ioctls will see the true baud rate that is being used. > > No, this is wrong. > > In fact, there's a long-standing bug in this driver which started > reporting back the actual baud rate when using SPD_CUST. Hello! And this commit is fixing also this bug as a side change. > The rate should be left unchanged at 38400 in that case. With this change, rate in c_cflag is unchanged and stays at B38400. What is updated is the real baudrate in c_ispeed and c_ospeed extensions. It is really wrong? I thought that c_cflag should stay unchanged at B38400 when ASYNC_SPD_CUST is used. > > Signed-off-by: Pali Rohár <pali@xxxxxxxxxx> > > Tested-by: Marek Behún <kabel@xxxxxxxxxx> > > Signed-off-by: Marek Behún <kabel@xxxxxxxxxx> > > --- > > drivers/usb/serial/ftdi_sio.c | 16 ++++++++++++++++ > > 1 file changed, 16 insertions(+) > > > > diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c > > index 5db1293bb7a2..39e8c5d06157 100644 > > --- a/drivers/usb/serial/ftdi_sio.c > > +++ b/drivers/usb/serial/ftdi_sio.c > > @@ -1303,6 +1303,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, > > { > > struct ftdi_private *priv = usb_get_serial_port_data(port); > > struct device *dev = &port->dev; > > + int fix_custom_divisor = 0; > > int div_value = 0; > > int div_okay = 1; > > int baud; > > @@ -1317,6 +1318,7 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, > > if (baud == 38400 && > > ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && > > (priv->custom_divisor)) { > > + fix_custom_divisor = 1; > > baud = DIV_ROUND_CLOSEST(priv->baud_base, priv->custom_divisor); > > dev_dbg(dev, "%s - custom divisor %d sets baud rate to %d\n", > > __func__, priv->custom_divisor, baud); > > @@ -1401,7 +1403,19 @@ static u32 get_ftdi_divisor(struct tty_struct *tty, > > ftdi_chip_name[priv->chip_type]); > > } > > > > + /* Fix deprecated async-compatible custom_divisor hack and update tty baud rate */ > > + if (fix_custom_divisor) { > > + priv->custom_divisor = DIV_ROUND_CLOSEST(priv->baud_base, baud); > > + old_baud = baud; > > + baud = 38400; > > + } > > + > > tty_encode_baud_rate(tty, baud, baud); > > + > > + /* For async-compatible custom_divisor store into TCGETS2 c_*speed fields real baud rate */ > > + if (fix_custom_divisor) > > + tty->termios.c_ispeed = tty->termios.c_ospeed = old_baud; > > + > > return div_value; > > } > > > > @@ -2674,6 +2688,8 @@ static void ftdi_set_termios(struct tty_struct *tty, > > dev_dbg(ddev, "%s: forcing baud rate for this device\n", __func__); > > tty_encode_baud_rate(tty, priv->force_baud, > > priv->force_baud); > > + termios->c_ispeed = termios->c_ospeed = > > + DIV_ROUND_CLOSEST(priv->baud_base, priv->custom_divisor); > > } > > > > /* Force RTS-CTS if this device requires it. */ > > Johan