| From: Johan Hovold <johan@kernel.org> |
| Date: Sun, 15 Jul 2018 15:39:34 +0200 |
| Subject: tty: fix termios input-speed encoding when using BOTHER |
| |
| commit 1cee38f0363a88db374e50b232ca17b9a4c12fa0 upstream. |
| |
| When the termios CIBAUD bits are left unset (i.e. B0), we use the same |
| output and input speed and should leave CIBAUD unchanged. |
| |
| When the user requests a rate using BOTHER and c_ospeed which the driver |
| cannot set exactly, the driver can report back the actual baud rate |
| using tty_termios_encode_baud_rate(). If this rate is close enough to a |
| standard rate however, we could end up setting CIBAUD to a Bfoo value |
| despite the user having left it unset. |
| |
| This in turn could lead to an unexpected input rate being set on |
| subsequent termios updates. |
| |
| Fix this by using a zero tolerance value also for the input rate when |
| CIBAUD is clear so that the matching logic works as expected. |
| |
| Fixes: 78137e3b34e1 ("[PATCH] tty: improve encode_baud_rate logic") |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| [bwh: Backported to 3.16: adjust filename] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/tty/tty_ioctl.c | 10 +++++++--- |
| 1 file changed, 7 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/tty/tty_ioctl.c |
| +++ b/drivers/tty/tty_ioctl.c |
| @@ -407,16 +407,20 @@ void tty_termios_encode_baud_rate(struct |
| termios->c_ospeed = obaud; |
| |
| #ifdef BOTHER |
| + if ((termios->c_cflag >> IBSHIFT) & CBAUD) |
| + ibinput = 1; /* An input speed was specified */ |
| + |
| /* If the user asked for a precise weird speed give a precise weird |
| answer. If they asked for a Bfoo speed they may have problems |
| digesting non-exact replies so fuzz a bit */ |
| |
| - if ((termios->c_cflag & CBAUD) == BOTHER) |
| + if ((termios->c_cflag & CBAUD) == BOTHER) { |
| oclose = 0; |
| + if (!ibinput) |
| + iclose = 0; |
| + } |
| if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) |
| iclose = 0; |
| - if ((termios->c_cflag >> IBSHIFT) & CBAUD) |
| - ibinput = 1; /* An input speed was specified */ |
| #endif |
| termios->c_cflag &= ~CBAUD; |
| #ifdef IBSHIFT |