[PATCH 3.16 062/132] USB: serial: fix initial-termios handling

From: Ben Hutchings
Date: Fri Sep 20 2019 - 10:35:26 EST


3.16.74-rc1 review patch. If anyone has any objections, please let me know.

------------------

From: Johan Hovold <johan@xxxxxxxxxx>

commit 579bebe5dd522580019e7b10b07daaf500f9fb1e upstream.

The USB-serial driver init_termios callback is used to override the
default initial terminal settings provided by USB-serial core.

After a bug was fixed in the original implementation introduced by
commit fe1ae7fdd2ee ("tty: USB serial termios bits"), the init_termios
callback was no longer called just once on first use as intended but
rather on every (first) open.

This specifically meant that the terminal settings saved on (final)
close were ignored when reopening a port for drivers overriding the
initial settings.

Also update the outdated function header referring to the creation of
termios objects.

Fixes: 7e29bb4b779f ("usb-serial: fix termios initialization logic")
Signed-off-by: Johan Hovold <johan@xxxxxxxxxx>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx>
---
drivers/usb/serial/usb-serial.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -167,9 +167,9 @@ void usb_serial_put(struct usb_serial *s
* @driver: the driver (USB in our case)
* @tty: the tty being created
*
- * Create the termios objects for this tty. We use the default
+ * Initialise the termios structure for this tty. We use the default
* USB serial settings but permit them to be overridden by
- * serial->type->init_termios.
+ * serial->type->init_termios on first open.
*
* This is the first place a new tty gets used. Hence this is where we
* acquire references to the usb_serial structure and the driver module,
@@ -181,6 +181,7 @@ static int serial_install(struct tty_dri
int idx = tty->index;
struct usb_serial *serial;
struct usb_serial_port *port;
+ bool init_termios;
int retval = -ENODEV;

port = usb_serial_port_get_by_minor(idx);
@@ -195,14 +196,16 @@ static int serial_install(struct tty_dri
if (retval)
goto error_get_interface;

+ init_termios = (driver->termios[idx] == NULL);
+
retval = tty_port_install(&port->port, driver, tty);
if (retval)
goto error_init_termios;

mutex_unlock(&serial->disc_mutex);

- /* allow the driver to update the settings */
- if (serial->type->init_termios)
+ /* allow the driver to update the initial settings */
+ if (init_termios && serial->type->init_termios)
serial->type->init_termios(tty);

tty->driver_data = port;