From 95da310e66ee8090119596c70ca8432e57f9a97f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 22 Jul 2008 11:09:07 +0100 Subject: usb_serial: API all change USB serial likes to use port->tty back pointers for the real work it does and to do so without any actual locking. Unfortunately when you consider hangup events, hangup/parallel reopen or even worse hangup followed by parallel close events the tty->port and port->tty pointers are not guaranteed to be the same as port->tty is the active tty while tty->port is the port the tty may or may not still be attached to. So rework the entire API to pass the tty struct. For console cases we need to pass both for now. This shows up multiple drivers that immediately crash with USB console some of which have been fixed in the process. Longer term we need a proper tty as console abstraction Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/serial/console.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/usb/serial/console.c') diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 201184c3fb8..940f5de6898 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -145,12 +145,12 @@ static int usb_console_setup(struct console *co, char *options) } port = serial->port[0]; - port->tty = NULL; + port->port.tty = NULL; info->port = port; - ++port->open_count; - if (port->open_count == 1) { + ++port->port.count; + if (port->port.count == 1) { if (serial->type->set_termios) { /* * allocate a fake tty so the driver can initialize @@ -171,15 +171,15 @@ static int usb_console_setup(struct console *co, char *options) } memset(&dummy, 0, sizeof(struct ktermios)); tty->termios = termios; - port->tty = tty; + port->port.tty = tty; } /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) - retval = serial->type->open(port, NULL); + retval = serial->type->open(NULL, port, NULL); else - retval = usb_serial_generic_open(port, NULL); + retval = usb_serial_generic_open(NULL, port, NULL); if (retval) { err("could not open USB console port"); @@ -188,9 +188,9 @@ static int usb_console_setup(struct console *co, char *options) if (serial->type->set_termios) { termios->c_cflag = cflag; - serial->type->set_termios(port, &dummy); + serial->type->set_termios(NULL, port, &dummy); - port->tty = NULL; + port->port.tty = NULL; kfree(termios); kfree(tty); } @@ -203,11 +203,11 @@ out: return retval; free_termios: kfree(termios); - port->tty = NULL; + port->port.tty = NULL; free_tty: kfree(tty); reset_open_count: - port->open_count = 0; + port->port.count = 0; goto out; } @@ -227,7 +227,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun dbg("%s - port %d, %d byte(s)", __func__, port->number, count); - if (!port->open_count) { + if (!port->port.count) { dbg ("%s - port not opened", __func__); return; } @@ -245,17 +245,17 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun } /* pass on to the driver specific version of this function if it is available */ if (serial->type->write) - retval = serial->type->write(port, buf, i); + retval = serial->type->write(NULL, port, buf, i); else - retval = usb_serial_generic_write(port, buf, i); + retval = usb_serial_generic_write(NULL, port, buf, i); dbg("%s - return value : %d", __func__, retval); if (lf) { /* append CR after LF */ unsigned char cr = 13; if (serial->type->write) - retval = serial->type->write(port, &cr, 1); + retval = serial->type->write(NULL, port, &cr, 1); else - retval = usb_serial_generic_write(port, &cr, 1); + retval = usb_serial_generic_write(NULL, port, &cr, 1); dbg("%s - return value : %d", __func__, retval); } buf += i; @@ -306,8 +306,8 @@ void usb_serial_console_exit (void) { if (usbcons_info.port) { unregister_console(&usbcons); - if (usbcons_info.port->open_count) - usbcons_info.port->open_count--; + if (usbcons_info.port->port.count) + usbcons_info.port->port.count--; usbcons_info.port = NULL; } } -- cgit v1.2.3-70-g09d2 From 4dbd5a0961ff55cb8a7bce309dd5ef9b04090570 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 22 Jul 2008 11:09:57 +0100 Subject: tty-usb-console: tidy the USB console code Code tidy Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/serial/console.c | 127 ++++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 61 deletions(-) (limited to 'drivers/usb/serial/console.c') diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 940f5de6898..9a4cd0a932b 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -6,7 +6,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. - * + * * Thanks to Randy Dunlap for the original version of this code. * */ @@ -67,7 +67,7 @@ static int usb_console_setup(struct console *co, char *options) struct tty_struct *tty = NULL; struct ktermios *termios = NULL, dummy; - dbg ("%s", __func__); + dbg("%s", __func__); if (options) { baud = simple_strtoul(options, NULL, 10); @@ -84,52 +84,52 @@ static int usb_console_setup(struct console *co, char *options) /* build a cflag setting */ switch (baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - /* - * Set this to a sane value to prevent a divide error - */ - baud = 9600; - break; + case 1200: + cflag |= B1200; + break; + case 2400: + cflag |= B2400; + break; + case 4800: + cflag |= B4800; + break; + case 19200: + cflag |= B19200; + break; + case 38400: + cflag |= B38400; + break; + case 57600: + cflag |= B57600; + break; + case 115200: + cflag |= B115200; + break; + case 9600: + default: + cflag |= B9600; + /* + * Set this to a sane value to prevent a divide error + */ + baud = 9600; + break; } switch (bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; + case 7: + cflag |= CS7; + break; + default: + case 8: + cflag |= CS8; + break; } switch (parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; + case 'o': case 'O': + cflag |= PARODD; + break; + case 'e': case 'E': + cflag |= PARENB; + break; } co->cflag = cflag; @@ -140,7 +140,7 @@ static int usb_console_setup(struct console *co, char *options) serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ - err ("No USB device connected to ttyUSB%i", co->index); + err("No USB device connected to ttyUSB%i", co->index); return -ENODEV; } @@ -148,7 +148,7 @@ static int usb_console_setup(struct console *co, char *options) port->port.tty = NULL; info->port = port; - + ++port->port.count; if (port->port.count == 1) { if (serial->type->set_termios) { @@ -174,7 +174,7 @@ static int usb_console_setup(struct console *co, char *options) port->port.tty = tty; } - /* only call the device specific open if this + /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) retval = serial->type->open(NULL, port, NULL); @@ -211,7 +211,8 @@ reset_open_count: goto out; } -static void usb_console_write(struct console *co, const char *buf, unsigned count) +static void usb_console_write(struct console *co, + const char *buf, unsigned count) { static struct usbcons_info *info = &usbcons_info; struct usb_serial_port *port = info->port; @@ -228,7 +229,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun dbg("%s - port %d, %d byte(s)", __func__, port->number, count); if (!port->port.count) { - dbg ("%s - port not opened", __func__); + dbg("%s - port not opened", __func__); return; } @@ -236,14 +237,15 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun unsigned int i; unsigned int lf; /* search for LF so we can insert CR if necessary */ - for (i=0, lf=0 ; i < count ; i++) { + for (i = 0, lf = 0 ; i < count ; i++) { if (*(buf + i) == 10) { lf = 1; i++; break; } } - /* pass on to the driver specific version of this function if it is available */ + /* pass on to the driver specific version of this function if + it is available */ if (serial->type->write) retval = serial->type->write(NULL, port, buf, i); else @@ -253,9 +255,11 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun /* append CR after LF */ unsigned char cr = 13; if (serial->type->write) - retval = serial->type->write(NULL, port, &cr, 1); + retval = serial->type->write(NULL, + port, &cr, 1); else - retval = usb_serial_generic_write(NULL, port, &cr, 1); + retval = usb_serial_generic_write(NULL, + port, &cr, 1); dbg("%s - return value : %d", __func__, retval); } buf += i; @@ -273,18 +277,19 @@ static struct console usbcons = { void usb_serial_console_disconnect(struct usb_serial *serial) { - if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { + if (serial && serial->port && serial->port[0] + && serial->port[0] == usbcons_info.port) { usb_serial_console_exit(); usb_serial_put(serial); } } -void usb_serial_console_init (int serial_debug, int minor) +void usb_serial_console_init(int serial_debug, int minor) { debug = serial_debug; if (minor == 0) { - /* + /* * Call register_console() if this is the first device plugged * in. If we call it earlier, then the callback to * console_setup() will fail, as there is not a device seen by @@ -293,16 +298,16 @@ void usb_serial_console_init (int serial_debug, int minor) /* * Register console. * NOTES: - * console_setup() is called (back) immediately (from register_console). - * console_write() is called immediately from register_console iff - * CON_PRINTBUFFER is set in flags. + * console_setup() is called (back) immediately (from + * register_console). console_write() is called immediately + * from register_console iff CON_PRINTBUFFER is set in flags. */ - dbg ("registering the USB serial console."); + dbg("registering the USB serial console."); register_console(&usbcons); } } -void usb_serial_console_exit (void) +void usb_serial_console_exit(void) { if (usbcons_info.port) { unregister_console(&usbcons); -- cgit v1.2.3-70-g09d2 From c17ee886976b64d29ea89ee5d87751438e26025b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 22 Jul 2008 11:10:08 +0100 Subject: tty-usb-console: Fix termios Setting CFLAG bits is all well and good but you must sort out ispeed and ospeed properly. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/serial/console.c | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) (limited to 'drivers/usb/serial/console.c') diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 9a4cd0a932b..7b74238ad1c 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -81,39 +81,11 @@ static int usb_console_setup(struct console *co, char *options) if (*s) doflow = (*s++ == 'r'); } + + /* Sane default */ + if (baud == 0) + baud = 9600; - /* build a cflag setting */ - switch (baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - /* - * Set this to a sane value to prevent a divide error - */ - baud = 9600; - break; - } switch (bits) { case 7: cflag |= CS7; @@ -188,6 +160,7 @@ static int usb_console_setup(struct console *co, char *options) if (serial->type->set_termios) { termios->c_cflag = cflag; + tty_termios_encode_baud_rate(termios, baud, baud); serial->type->set_termios(NULL, port, &dummy); port->port.tty = NULL; -- cgit v1.2.3-70-g09d2