From 8a7298d361827a1f244415dde62b1b07688d6a3a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 23 Feb 2013 10:11:35 -0500 Subject: usb/serial: Remove unnecessary check for console The tty port ops shutdown() routine is not called for console ports; remove extra check. Signed-off-by: Peter Hurley Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index a19ed74d770d..8424478e0b76 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -256,22 +256,18 @@ static int serial_open(struct tty_struct *tty, struct file *filp) * serial_down - shut down hardware * @tport: tty port to shut down * - * Shut down a USB serial port unless it is the console. We never - * shut down the console hardware as it will always be in use. Serialized - * against activate by the tport mutex and kept to matching open/close pairs + * Shut down a USB serial port. Serialized against activate by the + * tport mutex and kept to matching open/close pairs * of calls by the ASYNCB_INITIALIZED flag. + * + * Not called if tty is console. */ static void serial_down(struct tty_port *tport) { struct usb_serial_port *port = container_of(tport, struct usb_serial_port, port); struct usb_serial_driver *drv = port->serial->type; - /* - * The console is magical. Do not hang up the console hardware - * or there will be tears. - */ - if (port->port.console) - return; + if (drv->close) drv->close(port); } -- cgit v1.2.3 From ae8d4879667949fb49f0862b11ba680f671b2185 Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Thu, 7 Mar 2013 01:51:12 +0530 Subject: usb: serial: Remove redundant NULL check before kfree kfree on NULL pointer is a no-op. Signed-off-by: Syam Sidhardhan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 809fb329eca5..107ff9e3ddad 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1252,8 +1252,7 @@ static void mos7840_close(struct usb_serial_port *port) if (mos7840_port->write_urb) { /* if this urb had a transfer buffer already (old tx) free it */ - if (mos7840_port->write_urb->transfer_buffer != NULL) - kfree(mos7840_port->write_urb->transfer_buffer); + kfree(mos7840_port->write_urb->transfer_buffer); usb_free_urb(mos7840_port->write_urb); } -- cgit v1.2.3 From 29727f3bc2e691d59c521ff09b4d59a743b5d9a3 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Wed, 20 Mar 2013 11:46:10 -0400 Subject: Revert "USB: quatech2: only write to the tty if the port is open." This reverts commit 27b351c5546008c640b3e65152f60ca74b3706f1. Calling tty_flip_buffer_push on an unopened tty is legal, so the driver doesn't need track if port has been opened. Reverting this allows the entire is_open logic to be removed. Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index d643a4d4d770..00e6c9bac8a3 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -661,9 +661,7 @@ void qt2_process_read_urb(struct urb *urb) __func__); break; } - - if (port_priv->is_open) - tty_flip_buffer_push(&port->port); + tty_flip_buffer_push(&port->port); newport = *(ch + 3); @@ -706,8 +704,7 @@ void qt2_process_read_urb(struct urb *urb) tty_insert_flip_string(&port->port, ch, 1); } - if (port_priv->is_open) - tty_flip_buffer_push(&port->port); + tty_flip_buffer_push(&port->port); } static void qt2_write_bulk_callback(struct urb *urb) -- cgit v1.2.3 From 93e4f47f4d1a3483f009202e8a66a3a08de5c4b6 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 15 Mar 2013 12:08:54 +0800 Subject: USB: serial: comments on suspend failure If suspend callback fails in system sleep context, usb core will ignore the failure and let system sleep go ahead further, so this patch comments on the case and requires that serial->type->suspend() MUST return 0 in system sleep context. Acked-by: Johan Hovold Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bbe7f2eb8160..2fc05004c1b6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1137,6 +1137,11 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) serial->suspending = 1; + /* + * serial->type->suspend() MUST return 0 in system sleep context, + * otherwise, the resume callback has to recover device from + * previous suspend failure. + */ if (serial->type->suspend) { r = serial->type->suspend(serial, message); if (r < 0) { -- cgit v1.2.3 From 4cba98ff877043aeb92e86102b0250b312ddf017 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:18 +0100 Subject: USB: ftdi_sio: remove obsolete port data refcounting Remove the port data refcounting and release the private data explicitly at port remove. The port data refcounting was used to make sure the port data was not freed until the last tty reference was closed. Since moving over to tty ports, the underlying assumptions are no longer valid as close is now called as part of tty port shutdown, which can occur before the final tty reference is dropped on device disconnect. This means that the private port data refcounting is now completely useless, as the last reference will always be dropped on port_remove. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d4809d551473..c5757385790e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID; static __u16 product; struct ftdi_private { - struct kref kref; enum ftdi_chip_type chip_type; /* type of device, either SIO or FT8U232AM */ int baud_base; /* baud base clock for divisor setting */ @@ -910,7 +909,6 @@ static int ftdi_sio_probe(struct usb_serial *serial, static int ftdi_sio_port_probe(struct usb_serial_port *port); static int ftdi_sio_port_remove(struct usb_serial_port *port); static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port); -static void ftdi_close(struct usb_serial_port *port); static void ftdi_dtr_rts(struct usb_serial_port *port, int on); static void ftdi_process_read_urb(struct urb *urb); static int ftdi_prepare_write_buffer(struct usb_serial_port *port, @@ -950,7 +948,6 @@ static struct usb_serial_driver ftdi_sio_device = { .port_probe = ftdi_sio_port_probe, .port_remove = ftdi_sio_port_remove, .open = ftdi_open, - .close = ftdi_close, .dtr_rts = ftdi_dtr_rts, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, @@ -1687,7 +1684,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) return -ENOMEM; } - kref_init(&priv->kref); mutex_init(&priv->cfg_lock); priv->flags = ASYNC_LOW_LATENCY; @@ -1825,13 +1821,6 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial) return 0; } -static void ftdi_sio_priv_release(struct kref *k) -{ - struct ftdi_private *priv = container_of(k, struct ftdi_private, kref); - - kfree(priv); -} - static int ftdi_sio_port_remove(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1840,7 +1829,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) remove_sysfs_attrs(port); - kref_put(&priv->kref, ftdi_sio_priv_release); + kfree(priv); return 0; } @@ -1850,7 +1839,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) struct ktermios dummy; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); - int result; /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ @@ -1869,12 +1857,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) ftdi_set_termios(tty, port, &dummy); } - /* Start reading from the device */ - result = usb_serial_generic_open(tty, port); - if (!result) - kref_get(&priv->kref); - - return result; + return usb_serial_generic_open(tty, port); } static void ftdi_dtr_rts(struct usb_serial_port *port, int on) @@ -1899,19 +1882,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on) clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } -/* - * usbserial:__serial_close only calls ftdi_close if the point is open - * - * This only gets called when it is the last close - */ -static void ftdi_close(struct usb_serial_port *port) -{ - struct ftdi_private *priv = usb_get_serial_port_data(port); - - usb_serial_generic_close(port); - kref_put(&priv->kref, ftdi_sio_priv_release); -} - /* The SIO requires the first byte to have: * B0 1 * B1 0 -- cgit v1.2.3 From 6f60b34c4db4e5c5004d5d80ae2e1f80ba3fbd77 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:19 +0100 Subject: USB: kl5kusb105: remove unnecessary urb kill on close Remove kill of interrupt-in urb on close as it has never been submitted. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kl5kusb105.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 769d910ae0a5..57fd00194f7f 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -360,9 +360,6 @@ static void klsi_105_close(struct usb_serial_port *port) /* shutdown our bulk reads and writes */ usb_serial_generic_close(port); - - /* wgg - do I need this? I think so. */ - usb_kill_urb(port->interrupt_in_urb); } /* We need to write a complete 64-byte data block and encode the -- cgit v1.2.3 From 83e86c79a61d4098aa3e53bb919adfe0c4c34461 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:20 +0100 Subject: USB: iuu_phoenix: remove unnecessary urb kill on close Remove kill of interrupt-in urb on close as it has never been submitted. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index ff77027160aa..a3bfcb37f733 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -957,7 +957,6 @@ static void iuu_close(struct usb_serial_port *port) dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__); usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); iuu_led(port, 0, 0, 0xF000, 0xFF); } } -- cgit v1.2.3 From 7b5789a86890423e1460362798140c26822798b1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:21 +0100 Subject: USB: pl2303: use interface device for debug Use interface rather than usb-serial device for debugging interface related operations. This gives more descriptive messages, such as [ 905.669436] pl2303 1-4.1:1.0: 0x40:0x1:0x8:0x0 0 rather than [ 341.943535] usb 1-4.1: 0x40:0x1:0x8:0x0 0 Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 3b10018d89a3..5b2e62f6dc50 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -149,7 +149,7 @@ static int pl2303_vendor_read(__u16 value, __u16 index, int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE, value, index, buf, 1, 100); - dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", + dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index, res, buf[0]); return res; @@ -161,7 +161,7 @@ static int pl2303_vendor_write(__u16 value, __u16 index, int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, 100); - dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x %d\n", + dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x %d\n", VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index, res); return res; -- cgit v1.2.3 From f45d0a5aa593cdf48a37489fc61c145e16964288 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:22 +0100 Subject: USB: pl2303: make set_control_lines a port operation Pass usb-serial port rather than usb device to set_control_lines, and make sure port device is used for all port related debugging. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 5b2e62f6dc50..e7e407b67994 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -248,14 +248,15 @@ static int pl2303_port_remove(struct usb_serial_port *port) return 0; } -static int set_control_lines(struct usb_device *dev, u8 value) +static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value) { + struct usb_device *dev = port->serial->dev; int retval; retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE, value, 0, NULL, 0, 100); - dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__, + dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__, value, retval); return retval; } @@ -437,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty, if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - set_control_lines(serial->dev, control); + pl2303_set_control_lines(port, control); } else { spin_unlock_irqrestore(&priv->lock, flags); } @@ -480,7 +481,7 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - set_control_lines(port->serial->dev, control); + pl2303_set_control_lines(port, control); } static void pl2303_close(struct usb_serial_port *port) @@ -550,7 +551,7 @@ static int pl2303_tiocmset(struct tty_struct *tty, mutex_lock(&serial->disc_mutex); if (!serial->disconnected) - ret = set_control_lines(serial->dev, control); + ret = pl2303_set_control_lines(port, control); else ret = -ENODEV; mutex_unlock(&serial->disc_mutex); -- cgit v1.2.3 From 395e08da8adfe873c5f79e549bb6b7fa5d9f3832 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:23 +0100 Subject: USB: serial: rename tty-port callbacks Rename the tty-port callbacks using a common prefix to more clearly separate them from the tty and usb driver callbacks. Rename serial_down to serial_port_shutdown to match the callback name. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 2fc05004c1b6..3e290fc2adc4 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -225,7 +225,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) return retval; } -static int serial_activate(struct tty_port *tport, struct tty_struct *tty) +static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty) { struct usb_serial_port *port = container_of(tport, struct usb_serial_port, port); @@ -254,7 +254,7 @@ static int serial_open(struct tty_struct *tty, struct file *filp) } /** - * serial_down - shut down hardware + * serial_port_shutdown - shut down hardware * @tport: tty port to shut down * * Shut down a USB serial port. Serialized against activate by the @@ -263,7 +263,7 @@ static int serial_open(struct tty_struct *tty, struct file *filp) * * Not called if tty is console. */ -static void serial_down(struct tty_port *tport) +static void serial_port_shutdown(struct tty_port *tport) { struct usb_serial_port *port = container_of(tport, struct usb_serial_port, port); @@ -677,7 +677,7 @@ static struct usb_serial_driver *search_serial_device( return NULL; } -static int serial_carrier_raised(struct tty_port *port) +static int serial_port_carrier_raised(struct tty_port *port) { struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); struct usb_serial_driver *drv = p->serial->type; @@ -688,7 +688,7 @@ static int serial_carrier_raised(struct tty_port *port) return 1; } -static void serial_dtr_rts(struct tty_port *port, int on) +static void serial_port_dtr_rts(struct tty_port *port, int on) { struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); struct usb_serial *serial = p->serial; @@ -708,10 +708,10 @@ static void serial_dtr_rts(struct tty_port *port, int on) } static const struct tty_port_operations serial_port_ops = { - .carrier_raised = serial_carrier_raised, - .dtr_rts = serial_dtr_rts, - .activate = serial_activate, - .shutdown = serial_down, + .carrier_raised = serial_port_carrier_raised, + .dtr_rts = serial_port_dtr_rts, + .activate = serial_port_activate, + .shutdown = serial_port_shutdown, }; static int usb_serial_probe(struct usb_interface *interface, -- cgit v1.2.3 From 9993b42b638ec031a55bfe1bc16317cbb5c69722 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:24 +0100 Subject: USB: serial: remove redundant comments Remove redundant comments and fix some minor coding style issues. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 3e290fc2adc4..262beefca71e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -14,7 +14,6 @@ * * See Documentation/usb/usb-serial.txt for more information on using this * driver - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -49,7 +48,6 @@ drivers depend on it. */ -/* initially all NULL */ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; static DEFINE_MUTEX(table_lock); static LIST_HEAD(usb_serial_driver_list); @@ -338,7 +336,6 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf, dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__, port->number, count); - /* pass on to the driver specific version of this function */ retval = port->serial->type->write(tty, port, buf, count); if (retval < 0) retval = usb_translate_errors(retval); @@ -351,7 +348,7 @@ static int serial_write_room(struct tty_struct *tty) struct usb_serial_port *port = tty->driver_data; dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - /* pass on to the driver specific version of this function */ + return port->serial->type->write_room(tty); } @@ -381,7 +378,6 @@ static void serial_throttle(struct tty_struct *tty) dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - /* pass on to the driver specific version of this function */ if (port->serial->type->throttle) port->serial->type->throttle(tty); } @@ -392,7 +388,6 @@ static void serial_unthrottle(struct tty_struct *tty) dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - /* pass on to the driver specific version of this function */ if (port->serial->type->unthrottle) port->serial->type->unthrottle(tty); } @@ -406,12 +401,11 @@ static int serial_ioctl(struct tty_struct *tty, dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd); - /* pass on to the driver specific version of this function - if it is available */ - if (port->serial->type->ioctl) { + if (port->serial->type->ioctl) retval = port->serial->type->ioctl(tty, cmd, arg); - } else + else retval = -ENOIOCTLCMD; + return retval; } @@ -421,8 +415,6 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - /* pass on to the driver specific version of this function - if it is available */ if (port->serial->type->set_termios) port->serial->type->set_termios(tty, port, old); else @@ -435,10 +427,9 @@ static int serial_break(struct tty_struct *tty, int break_state) dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - /* pass on to the driver specific version of this function - if it is available */ if (port->serial->type->break_ctl) port->serial->type->break_ctl(tty, break_state); + return 0; } @@ -1471,7 +1462,6 @@ void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_driver } EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); -/* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From d12e211d44844930b7460ffab43ff9b078a45369 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:25 +0100 Subject: USB: serial: clean up debug info Remove redundant port number from debug output (already printed as part of device name). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 262beefca71e..fee8d8a04f7b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -247,7 +247,8 @@ static int serial_open(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); + return tty_port_open(&port->port, tty, filp); } @@ -275,7 +276,8 @@ static void serial_hangup(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); + tty_port_hangup(&port->port); } @@ -283,7 +285,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); + tty_port_close(&port->port, tty, filp); } @@ -302,14 +305,14 @@ static void serial_cleanup(struct tty_struct *tty) struct usb_serial *serial; struct module *owner; + dev_dbg(tty->dev, "%s\n", __func__); + /* The console is magical. Do not hang up the console hardware * or there will be tears. */ if (port->port.console) return; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); - tty->driver_data = NULL; serial = port->serial; @@ -333,8 +336,7 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf, if (port->serial->dev->state == USB_STATE_NOTATTACHED) goto exit; - dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__, - port->number, count); + dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count); retval = port->serial->type->write(tty, port, buf, count); if (retval < 0) @@ -347,7 +349,7 @@ static int serial_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); return port->serial->type->write_room(tty); } @@ -358,7 +360,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty) struct usb_serial *serial = port->serial; int count = 0; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); mutex_lock(&serial->disc_mutex); /* if the device was unplugged then any remaining characters @@ -376,7 +378,7 @@ static void serial_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->throttle) port->serial->type->throttle(tty); @@ -386,7 +388,7 @@ static void serial_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->unthrottle) port->serial->type->unthrottle(tty); @@ -398,8 +400,7 @@ static int serial_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; int retval = -ENODEV; - dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__, - port->number, cmd); + dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd); if (port->serial->type->ioctl) retval = port->serial->type->ioctl(tty, cmd, arg); @@ -413,7 +414,7 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->set_termios) port->serial->type->set_termios(tty, port, old); @@ -425,7 +426,7 @@ static int serial_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->break_ctl) port->serial->type->break_ctl(tty, break_state); @@ -483,7 +484,7 @@ static int serial_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->tiocmget) return port->serial->type->tiocmget(tty); @@ -495,7 +496,7 @@ static int serial_tiocmset(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->tiocmset) return port->serial->type->tiocmset(tty, set, clear); @@ -507,7 +508,7 @@ static int serial_get_icount(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); if (port->serial->type->get_icount) return port->serial->type->get_icount(tty, icount); @@ -535,7 +536,7 @@ static void usb_serial_port_work(struct work_struct *work) if (!tty) return; - dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + dev_dbg(tty->dev, "%s\n", __func__); tty_wakeup(tty); tty_kref_put(tty); -- cgit v1.2.3 From 6b03f7f79f5610ad119dc99643be20b44095c265 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:26 +0100 Subject: USB: serial: remove redundant allocation error messages Failed allocations already get an OOM message and a stack dump. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index fee8d8a04f7b..e7f97b58e914 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -603,10 +603,8 @@ static struct usb_serial *create_serial(struct usb_device *dev, struct usb_serial *serial; serial = kzalloc(sizeof(*serial), GFP_KERNEL); - if (!serial) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); + if (!serial) return NULL; - } serial->dev = usb_get_dev(dev); serial->type = driver; serial->interface = usb_get_intf(interface); @@ -750,7 +748,6 @@ static int usb_serial_probe(struct usb_interface *interface, serial = create_serial(dev, interface, type); if (!serial) { module_put(type->driver.owner); - dev_err(ddev, "%s - out of memory\n", __func__); return -ENOMEM; } @@ -914,16 +911,12 @@ static int usb_serial_probe(struct usb_interface *interface, for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) { set_bit(j, &port->read_urbs_free); port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); - if (!port->read_urbs[j]) { - dev_err(ddev, "No free urbs available\n"); + if (!port->read_urbs[j]) goto probe_error; - } port->bulk_in_buffers[j] = kmalloc(buffer_size, GFP_KERNEL); - if (!port->bulk_in_buffers[j]) { - dev_err(ddev, "Couldn't allocate bulk_in_buffer\n"); + if (!port->bulk_in_buffers[j]) goto probe_error; - } usb_fill_bulk_urb(port->read_urbs[j], dev, usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), @@ -950,16 +943,12 @@ static int usb_serial_probe(struct usb_interface *interface, for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) { set_bit(j, &port->write_urbs_free); port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); - if (!port->write_urbs[j]) { - dev_err(ddev, "No free urbs available\n"); + if (!port->write_urbs[j]) goto probe_error; - } port->bulk_out_buffers[j] = kmalloc(buffer_size, GFP_KERNEL); - if (!port->bulk_out_buffers[j]) { - dev_err(ddev, "Couldn't allocate bulk_out_buffer\n"); + if (!port->bulk_out_buffers[j]) goto probe_error; - } usb_fill_bulk_urb(port->write_urbs[j], dev, usb_sndbulkpipe(dev, endpoint->bEndpointAddress), @@ -977,19 +966,15 @@ static int usb_serial_probe(struct usb_interface *interface, endpoint = interrupt_in_endpoint[i]; port = serial->port[i]; port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port->interrupt_in_urb) { - dev_err(ddev, "No free urbs available\n"); + if (!port->interrupt_in_urb) goto probe_error; - } buffer_size = usb_endpoint_maxp(endpoint); port->interrupt_in_endpointAddress = endpoint->bEndpointAddress; port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!port->interrupt_in_buffer) { - dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n"); + if (!port->interrupt_in_buffer) goto probe_error; - } usb_fill_int_urb(port->interrupt_in_urb, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), @@ -1006,20 +991,16 @@ static int usb_serial_probe(struct usb_interface *interface, endpoint = interrupt_out_endpoint[i]; port = serial->port[i]; port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port->interrupt_out_urb) { - dev_err(ddev, "No free urbs available\n"); + if (!port->interrupt_out_urb) goto probe_error; - } buffer_size = usb_endpoint_maxp(endpoint); port->interrupt_out_size = buffer_size; port->interrupt_out_endpointAddress = endpoint->bEndpointAddress; port->interrupt_out_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!port->interrupt_out_buffer) { - dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n"); + if (!port->interrupt_out_buffer) goto probe_error; - } usb_fill_int_urb(port->interrupt_out_urb, dev, usb_sndintpipe(dev, endpoint->bEndpointAddress), -- cgit v1.2.3 From 49bd196dc651606e2f97f42957f9fcde3186f615 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:27 +0100 Subject: USB: serial: remove port number from generic-driver debug Remove redundant port number from debug output (already printed as part of device name). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4c5c23f1cae5..927c5d6a255e 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -272,8 +272,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port, if (!test_and_clear_bit(index, &port->read_urbs_free)) return 0; - dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__, - port->number, index); + dev_dbg(&port->dev, "%s - urb %d\n", __func__, index); res = usb_submit_urb(port->read_urbs[index], mem_flags); if (res) { @@ -347,8 +346,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) } set_bit(i, &port->read_urbs_free); - dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n", - __func__, port->number, i, urb->actual_length); + dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i, + urb->actual_length); if (urb->status) { dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", @@ -473,8 +472,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, { struct tty_port *port = &usb_port->port; - dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__, - usb_port->number, status); + dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status); if (status) wake_up_interruptible(&port->open_wait); -- cgit v1.2.3 From 5c3275282422dcb895e2e9902c7fba4fd9d2512b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:28 +0100 Subject: USB: ark3116: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 4775f8209e55..3b811feb35fd 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -341,18 +341,15 @@ static void ark3116_close(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - if (serial->dev) { - /* disable DMA */ - ark3116_write_reg(serial, UART_FCR, 0); - - /* deactivate interrupts */ - ark3116_write_reg(serial, UART_IER, 0); + /* disable DMA */ + ark3116_write_reg(serial, UART_FCR, 0); - usb_serial_generic_close(port); - if (serial->num_interrupt_in) - usb_kill_urb(port->interrupt_in_urb); - } + /* deactivate interrupts */ + ark3116_write_reg(serial, UART_IER, 0); + usb_serial_generic_close(port); + if (serial->num_interrupt_in) + usb_kill_urb(port->interrupt_in_urb); } static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port) -- cgit v1.2.3 From 1bc77f4df6b11948893cb1427fb6211c94f51364 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:29 +0100 Subject: USB: cyberjack: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cyberjack.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 629bd2894506..de9253d63a48 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -166,11 +166,8 @@ static int cyberjack_open(struct tty_struct *tty, static void cyberjack_close(struct usb_serial_port *port) { - if (port->serial->dev) { - /* shutdown any bulk reads that might be going on */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - } + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); } static int cyberjack_write(struct tty_struct *tty, -- cgit v1.2.3 From 28e679ae6fd67023d5e8e61a0092791c5082c21c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:30 +0100 Subject: USB: digi_acceleport: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 92 ++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 47 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index ebe45fa0ed50..76a8c202a8e2 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -1149,53 +1149,51 @@ static void digi_close(struct usb_serial_port *port) if (port->serial->disconnected) goto exit; - if (port->serial->dev) { - /* FIXME: Transmit idle belongs in the wait_unti_sent path */ - digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); - - /* disable input flow control */ - buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; - buf[1] = priv->dp_port_num; - buf[2] = DIGI_DISABLE; - buf[3] = 0; - - /* disable output flow control */ - buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; - buf[5] = priv->dp_port_num; - buf[6] = DIGI_DISABLE; - buf[7] = 0; - - /* disable reading modem signals automatically */ - buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; - buf[9] = priv->dp_port_num; - buf[10] = DIGI_DISABLE; - buf[11] = 0; - - /* disable receive */ - buf[12] = DIGI_CMD_RECEIVE_ENABLE; - buf[13] = priv->dp_port_num; - buf[14] = DIGI_DISABLE; - buf[15] = 0; - - /* flush fifos */ - buf[16] = DIGI_CMD_IFLUSH_FIFO; - buf[17] = priv->dp_port_num; - buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; - buf[19] = 0; - - ret = digi_write_oob_command(port, buf, 20, 0); - if (ret != 0) - dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret); - - /* wait for final commands on oob port to complete */ - prepare_to_wait(&priv->dp_flush_wait, &wait, - TASK_INTERRUPTIBLE); - schedule_timeout(DIGI_CLOSE_TIMEOUT); - finish_wait(&priv->dp_flush_wait, &wait); - - /* shutdown any outstanding bulk writes */ - usb_kill_urb(port->write_urb); - } + /* FIXME: Transmit idle belongs in the wait_unti_sent path */ + digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); + + /* disable input flow control */ + buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; + buf[1] = priv->dp_port_num; + buf[2] = DIGI_DISABLE; + buf[3] = 0; + + /* disable output flow control */ + buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; + buf[5] = priv->dp_port_num; + buf[6] = DIGI_DISABLE; + buf[7] = 0; + + /* disable reading modem signals automatically */ + buf[8] = DIGI_CMD_READ_INPUT_SIGNALS; + buf[9] = priv->dp_port_num; + buf[10] = DIGI_DISABLE; + buf[11] = 0; + + /* disable receive */ + buf[12] = DIGI_CMD_RECEIVE_ENABLE; + buf[13] = priv->dp_port_num; + buf[14] = DIGI_DISABLE; + buf[15] = 0; + + /* flush fifos */ + buf[16] = DIGI_CMD_IFLUSH_FIFO; + buf[17] = priv->dp_port_num; + buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; + buf[19] = 0; + + ret = digi_write_oob_command(port, buf, 20, 0); + if (ret != 0) + dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", + ret); + /* wait for final commands on oob port to complete */ + prepare_to_wait(&priv->dp_flush_wait, &wait, + TASK_INTERRUPTIBLE); + schedule_timeout(DIGI_CLOSE_TIMEOUT); + finish_wait(&priv->dp_flush_wait, &wait); + + /* shutdown any outstanding bulk writes */ + usb_kill_urb(port->write_urb); exit: spin_lock_irq(&priv->dp_port_lock); priv->dp_write_urb_in_use = 0; -- cgit v1.2.3 From 853127faa43f4971c4e9fc506bb86622208ca935 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:31 +0100 Subject: USB: iuu_phoenix: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index a3bfcb37f733..8eeefe3af0b6 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -951,14 +951,11 @@ static void iuu_close(struct usb_serial_port *port) return; iuu_uart_off(port); - if (serial->dev) { - /* free writebuf */ - /* shutdown our urbs */ - dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__); - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - iuu_led(port, 0, 0, 0xF000, 0xFF); - } + + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + + iuu_led(port, 0, 0, 0xF000, 0xFF); } static void iuu_init_termios(struct tty_struct *tty) -- cgit v1.2.3 From 80dfe0ceb31d92aca835d94f0255d93288e5ed12 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:32 +0100 Subject: USB: keyspan: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Remove some out-commented bogus code while at it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 1fd1935c8316..6abe8a4fee0e 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1115,7 +1115,6 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on) static void keyspan_close(struct usb_serial_port *port) { int i; - struct usb_serial *serial = port->serial; struct keyspan_port_private *p_priv; p_priv = usb_get_serial_port_data(port); @@ -1123,28 +1122,17 @@ static void keyspan_close(struct usb_serial_port *port) p_priv->rts_state = 0; p_priv->dtr_state = 0; - if (serial->dev) { - keyspan_send_setup(port, 2); - /* pilot-xfer seems to work best with this delay */ - mdelay(100); - /* keyspan_set_termios(port, NULL); */ - } - - /*while (p_priv->outcont_urb->status == -EINPROGRESS) { - dev_dbg(&port->dev, "%s - urb in progress\n", __func__); - }*/ + keyspan_send_setup(port, 2); + /* pilot-xfer seems to work best with this delay */ + mdelay(100); p_priv->out_flip = 0; p_priv->in_flip = 0; - if (serial->dev) { - /* Stop reading/writing urbs */ - stop_urb(p_priv->inack_urb); - /* stop_urb(p_priv->outcont_urb); */ - for (i = 0; i < 2; i++) { - stop_urb(p_priv->in_urbs[i]); - stop_urb(p_priv->out_urbs[i]); - } + stop_urb(p_priv->inack_urb); + for (i = 0; i < 2; i++) { + stop_urb(p_priv->in_urbs[i]); + stop_urb(p_priv->out_urbs[i]); } } -- cgit v1.2.3 From d7f08452ffd3abbc2dbbf763cdec05496923f3b7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:33 +0100 Subject: USB: keyspan_pda: remove bogus disconnect test from dtr_rts Remove bogus (and unnecessary) test for serial->dev being NULL in dtr_rts. The device is never cleared, and disconnect is handled for dtr_rts in usb-serial core anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 3b17d5d13dc8..0d992ba7bd05 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -595,12 +595,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) { struct usb_serial *serial = port->serial; - if (serial->dev) { - if (on) - keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2)); - else - keyspan_pda_set_modem_info(serial, 0); - } + if (on) + keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2)); + else + keyspan_pda_set_modem_info(serial, 0); } -- cgit v1.2.3 From 75d22b323fad49715068f74af9e65dbaba06614e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:34 +0100 Subject: USB: keyspan_pda: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan_pda.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 0d992ba7bd05..da3b29eb605c 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -649,13 +649,8 @@ error: } static void keyspan_pda_close(struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; - - if (serial->dev) { - /* shutdown our bulk reads and writes */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->interrupt_in_urb); - } + usb_kill_urb(port->write_urb); + usb_kill_urb(port->interrupt_in_urb); } -- cgit v1.2.3 From bb3529c6a01fce3e23c968982f46fa46a0095345 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:35 +0100 Subject: USB: mos7840: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Simplify urb killing, and remove some related debug and dead code while at it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 316ad5f0d1a2..979ef1999581 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1223,25 +1223,10 @@ static void mos7840_close(struct usb_serial_port *port) } } - /* While closing port, shutdown all bulk read, write * - * and interrupt read if they exists */ - if (serial->dev) { - if (mos7840_port->write_urb) { - dev_dbg(&port->dev, "%s", "Shutdown bulk write\n"); - usb_kill_urb(mos7840_port->write_urb); - } - if (mos7840_port->read_urb) { - dev_dbg(&port->dev, "%s", "Shutdown bulk read\n"); - usb_kill_urb(mos7840_port->read_urb); - mos7840_port->read_urb_busy = false; - } - if ((&mos7840_port->control_urb)) { - dev_dbg(&port->dev, "%s", "Shutdown control read\n"); - /*/ usb_kill_urb (mos7840_port->control_urb); */ - } - } -/* if(mos7840_port->ctrl_buf != NULL) */ -/* kfree(mos7840_port->ctrl_buf); */ + usb_kill_urb(mos7840_port->write_urb); + usb_kill_urb(mos7840_port->read_urb); + mos7840_port->read_urb_busy = false; + port0->open_ports--; dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number); if (port0->open_ports == 0) { @@ -1330,9 +1315,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state) if (mos7840_port == NULL) return; - if (serial->dev) - /* flush and block until tx is empty */ - mos7840_block_until_chase_response(tty, mos7840_port); + /* flush and block until tx is empty */ + mos7840_block_until_chase_response(tty, mos7840_port); if (break_state == -1) data = mos7840_port->shadowLCR | LCR_SET_BREAK; -- cgit v1.2.3 From 9c210bfa29dc3845ae61b544f673d9753ffa3618 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:36 +0100 Subject: USB: sierra: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index c13f6e747748..2b06481dc85c 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -778,30 +778,25 @@ static void sierra_close(struct usb_serial_port *port) portdata->rts_state = 0; portdata->dtr_state = 0; - if (serial->dev) { - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) { - serial->interface->needs_remote_wakeup = 0; - /* odd error handling due to pm counters */ - if (!usb_autopm_get_interface(serial->interface)) - sierra_send_setup(port); - else - usb_autopm_get_interface_no_resume(serial->interface); - - } - mutex_unlock(&serial->disc_mutex); - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; - spin_unlock_irq(&intfdata->susp_lock); + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) { + serial->interface->needs_remote_wakeup = 0; + /* odd error handling due to pm counters */ + if (!usb_autopm_get_interface(serial->interface)) + sierra_send_setup(port); + else + usb_autopm_get_interface_no_resume(serial->interface); + } + mutex_unlock(&serial->disc_mutex); + spin_lock_irq(&intfdata->susp_lock); + portdata->opened = 0; + spin_unlock_irq(&intfdata->susp_lock); - /* Stop reading urbs */ - sierra_stop_rx_urbs(port); - /* .. and release them */ - for (i = 0; i < portdata->num_in_urbs; i++) { - sierra_release_urb(portdata->in_urbs[i]); - portdata->in_urbs[i] = NULL; - } + sierra_stop_rx_urbs(port); + for (i = 0; i < portdata->num_in_urbs; i++) { + sierra_release_urb(portdata->in_urbs[i]); + portdata->in_urbs[i] = NULL; } } -- cgit v1.2.3 From e6d144bc27da921b81d46eb7cac461be59ae301b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:37 +0100 Subject: USB: usb_wwan: remove bogus disconnect test in close Remove bogus (and unnecessary) test for serial->dev being NULL in close. The device is never cleared, and close is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb_wwan.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 571965aa1cc0..ece326ef63a0 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -421,20 +421,19 @@ void usb_wwan_close(struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - if (serial->dev) { - /* Stop reading/writing urbs */ - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; - spin_unlock_irq(&intfdata->susp_lock); + /* Stop reading/writing urbs */ + spin_lock_irq(&intfdata->susp_lock); + portdata->opened = 0; + spin_unlock_irq(&intfdata->susp_lock); - for (i = 0; i < N_IN_URB; i++) - usb_kill_urb(portdata->in_urbs[i]); - for (i = 0; i < N_OUT_URB; i++) - usb_kill_urb(portdata->out_urbs[i]); - /* balancing - important as an error cannot be handled*/ - usb_autopm_get_interface_no_resume(serial->interface); - serial->interface->needs_remote_wakeup = 0; - } + for (i = 0; i < N_IN_URB; i++) + usb_kill_urb(portdata->in_urbs[i]); + for (i = 0; i < N_OUT_URB; i++) + usb_kill_urb(portdata->out_urbs[i]); + + /* balancing - important as an error cannot be handled*/ + usb_autopm_get_interface_no_resume(serial->interface); + serial->interface->needs_remote_wakeup = 0; } EXPORT_SYMBOL(usb_wwan_close); -- cgit v1.2.3 From 19c61853831f4f957885665ce36a573cbabf9ba1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:38 +0100 Subject: USB: serial: remove bogus disconnect test in cleanup Remove bogus (and unnecessary) test for serial->dev being NULL in cleanup. The device is never cleared, and cleanup is never called after a completed disconnect anyway. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 927c5d6a255e..131d6cbeefee 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -104,24 +104,20 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_open); static void generic_cleanup(struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; unsigned long flags; int i; - if (serial->dev) { - /* shutdown any bulk transfers that might be going on */ - if (port->bulk_out_size) { - for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) - usb_kill_urb(port->write_urbs[i]); + if (port->bulk_out_size) { + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) + usb_kill_urb(port->write_urbs[i]); - spin_lock_irqsave(&port->lock, flags); - kfifo_reset_out(&port->write_fifo); - spin_unlock_irqrestore(&port->lock, flags); - } - if (port->bulk_in_size) { - for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) - usb_kill_urb(port->read_urbs[i]); - } + spin_lock_irqsave(&port->lock, flags); + kfifo_reset_out(&port->write_fifo); + spin_unlock_irqrestore(&port->lock, flags); + } + if (port->bulk_in_size) { + for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) + usb_kill_urb(port->read_urbs[i]); } } -- cgit v1.2.3 From bf8773c6eacc9c3241455fdb7e82050ad2323a0a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:39 +0100 Subject: USB: ssu100: remove explicit initialisation of disconnect The disconnect callback is set to the generic implementation by usb-serial core if NULL. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 4b2a19757b4d..97aca3fce883 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -641,7 +641,6 @@ static struct usb_serial_driver ssu100_device = { .get_icount = ssu100_get_icount, .ioctl = ssu100_ioctl, .set_termios = ssu100_set_termios, - .disconnect = usb_serial_generic_disconnect, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3 From 618e183d03a95da200bed48e5277efe428feef26 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:40 +0100 Subject: USB: ssu100: remove custom close operation The generic close operation will be used if the close field is left uninitialised. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 97aca3fce883..45b8c29060d1 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -315,11 +315,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) return usb_serial_generic_open(tty, port); } -static void ssu100_close(struct usb_serial_port *port) -{ - usb_serial_generic_close(port); -} - static int get_serial_info(struct usb_serial_port *port, struct serial_struct __user *retinfo) { @@ -630,7 +625,6 @@ static struct usb_serial_driver ssu100_device = { .id_table = id_table, .num_ports = 1, .open = ssu100_open, - .close = ssu100_close, .attach = ssu100_attach, .port_probe = ssu100_port_probe, .port_remove = ssu100_port_remove, -- cgit v1.2.3 From f8f0ad8621cf01e1e3f8264863b270c2308a9c1a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:41 +0100 Subject: USB: serial: fix generic disconnect implementation There is no need for the generic disconnect callback to stop the read and write urbs a second time as this has already been taken care of by close (which is called from hangup as part of disconnect). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 131d6cbeefee..a6d0ac638e0a 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -102,7 +102,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port } EXPORT_SYMBOL_GPL(usb_serial_generic_open); -static void generic_cleanup(struct usb_serial_port *port) +void usb_serial_generic_close(struct usb_serial_port *port) { unsigned long flags; int i; @@ -120,11 +120,6 @@ static void generic_cleanup(struct usb_serial_port *port) usb_kill_urb(port->read_urbs[i]); } } - -void usb_serial_generic_close(struct usb_serial_port *port) -{ - generic_cleanup(port); -} EXPORT_SYMBOL_GPL(usb_serial_generic_close); int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, @@ -507,11 +502,6 @@ EXPORT_SYMBOL_GPL(usb_serial_generic_resume); void usb_serial_generic_disconnect(struct usb_serial *serial) { - int i; - - /* stop reads and writes on all ports */ - for (i = 0; i < serial->num_ports; ++i) - generic_cleanup(serial->port[i]); } EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect); -- cgit v1.2.3 From 0f16cfe39eeef47c91aa3c3bf2b49954d5313a58 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:42 +0100 Subject: USB: serial: remove generic disconnect callback Remove the now empty generic disconnect callback and make the disconnect callback non-mandatory. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 6 ------ drivers/usb/serial/usb-serial.c | 4 ++-- include/linux/usb/serial.h | 1 - 3 files changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index a6d0ac638e0a..4d421f3f8a7c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -45,7 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = { }, .id_table = generic_device_ids, .num_ports = 1, - .disconnect = usb_serial_generic_disconnect, .release = usb_serial_generic_release, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, @@ -500,11 +499,6 @@ int usb_serial_generic_resume(struct usb_serial *serial) } EXPORT_SYMBOL_GPL(usb_serial_generic_resume); -void usb_serial_generic_disconnect(struct usb_serial *serial) -{ -} -EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect); - void usb_serial_generic_release(struct usb_serial *serial) { } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index e7f97b58e914..569b6792c218 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1095,7 +1095,8 @@ static void usb_serial_disconnect(struct usb_interface *interface) device_del(&port->dev); } } - serial->type->disconnect(serial); + if (serial->type->disconnect) + serial->type->disconnect(serial); /* let the last holder of this object cause it to be cleaned up */ usb_serial_put(serial); @@ -1304,7 +1305,6 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, chars_in_buffer); set_to_generic_if_null(device, read_bulk_callback); set_to_generic_if_null(device, write_bulk_callback); - set_to_generic_if_null(device, disconnect); set_to_generic_if_null(device, release); set_to_generic_if_null(device, process_read_urb); set_to_generic_if_null(device, prepare_write_buffer); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 1819b59aab2a..437dfd6787f9 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -329,7 +329,6 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb); extern void usb_serial_generic_write_bulk_callback(struct urb *urb); extern void usb_serial_generic_throttle(struct tty_struct *tty); extern void usb_serial_generic_unthrottle(struct tty_struct *tty); -extern void usb_serial_generic_disconnect(struct usb_serial *serial); extern void usb_serial_generic_release(struct usb_serial *serial); extern int usb_serial_generic_register(void); extern void usb_serial_generic_deregister(void); -- cgit v1.2.3 From 79b80b8a1141ba0605e917a6fc12d44383ab29b8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:43 +0100 Subject: USB: serial: remove generic release callback Remove empty generic release implementation and make the release callback non-mandatory (like attach, probe and disconnect). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 5 ----- drivers/usb/serial/usb-serial.c | 3 +-- include/linux/usb/serial.h | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4d421f3f8a7c..aa71f6e72f61 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -45,7 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = { }, .id_table = generic_device_ids, .num_ports = 1, - .release = usb_serial_generic_release, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, .resume = usb_serial_generic_resume, @@ -498,7 +497,3 @@ int usb_serial_generic_resume(struct usb_serial *serial) return c ? -EIO : 0; } EXPORT_SYMBOL_GPL(usb_serial_generic_resume); - -void usb_serial_generic_release(struct usb_serial *serial) -{ -} diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 569b6792c218..4819fd9a639a 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -137,7 +137,7 @@ static void destroy_serial(struct kref *kref) if (serial->minor != SERIAL_TTY_NO_MINOR) return_serial(serial); - if (serial->attached) + if (serial->attached && serial->type->release) serial->type->release(serial); /* Now that nothing is using the ports, they can be freed */ @@ -1305,7 +1305,6 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, chars_in_buffer); set_to_generic_if_null(device, read_bulk_callback); set_to_generic_if_null(device, write_bulk_callback); - set_to_generic_if_null(device, release); set_to_generic_if_null(device, process_read_urb); set_to_generic_if_null(device, prepare_write_buffer); } diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 437dfd6787f9..3f8f5e3c76d5 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -329,7 +329,6 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb); extern void usb_serial_generic_write_bulk_callback(struct urb *urb); extern void usb_serial_generic_throttle(struct tty_struct *tty); extern void usb_serial_generic_unthrottle(struct tty_struct *tty); -extern void usb_serial_generic_release(struct usb_serial *serial); extern int usb_serial_generic_register(void); extern void usb_serial_generic_deregister(void); extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, -- cgit v1.2.3 From c3452f5e444446fad9bb1957d22a25334798f94c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:44 +0100 Subject: USB: serial: clean up generic-operation handling Most USB serial drivers are, and should be, using as much of the generic implementation as possible. Rename the fixup_generic function to a more descriptive name. Reword the related debug message in a more neutral tone (and remember to add the missing newline). Finally, move the operations initialisation to after the initial sanity checks. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4819fd9a639a..3eb4d06e49be 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1291,12 +1291,12 @@ module_exit(usb_serial_exit); do { \ if (!type->function) { \ type->function = usb_serial_generic_##function; \ - pr_debug("Had to override the " #function \ - " usb serial operation with the generic one.");\ - } \ + pr_debug("%s: using generic " #function "\n", \ + type->driver.name); \ + } \ } while (0) -static void fixup_generic(struct usb_serial_driver *device) +static void usb_serial_operations_init(struct usb_serial_driver *device) { set_to_generic_if_null(device, open); set_to_generic_if_null(device, write); @@ -1316,8 +1316,6 @@ static int usb_serial_register(struct usb_serial_driver *driver) if (usb_disabled()) return -ENODEV; - fixup_generic(driver); - if (!driver->description) driver->description = driver->driver.name; if (!driver->usb_driver) { @@ -1326,6 +1324,8 @@ static int usb_serial_register(struct usb_serial_driver *driver) return -EINVAL; } + usb_serial_operations_init(driver); + /* Add this device to our list of devices */ mutex_lock(&table_lock); list_add(&driver->driver_list, &usb_serial_driver_list); -- cgit v1.2.3 From 30d9d42e9a7c205cc139dce743463b8070684df5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:45 +0100 Subject: USB: cyberjack: fix disconnect handling Make sure the interrupt urb submitted in port_probe is killed in port_remove. The interrupt-urb completion handler references the port and may get called after port_remove has returned and the port has been unregistered (although this is currently prevented by usb-serial core as we are using a non-private urb). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cyberjack.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index de9253d63a48..781426230d69 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -51,7 +51,6 @@ #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static void cyberjack_disconnect(struct usb_serial *serial); static int cyberjack_port_probe(struct usb_serial_port *port); static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_open(struct tty_struct *tty, @@ -79,7 +78,6 @@ static struct usb_serial_driver cyberjack_device = { .description = "Reiner SCT Cyberjack USB card reader", .id_table = id_table, .num_ports = 1, - .disconnect = cyberjack_disconnect, .port_probe = cyberjack_port_probe, .port_remove = cyberjack_port_remove, .open = cyberjack_open, @@ -130,20 +128,14 @@ static int cyberjack_port_remove(struct usb_serial_port *port) { struct cyberjack_private *priv; + usb_kill_urb(port->interrupt_in_urb); + priv = usb_get_serial_port_data(port); kfree(priv); return 0; } -static void cyberjack_disconnect(struct usb_serial *serial) -{ - int i; - - for (i = 0; i < serial->num_ports; ++i) - usb_kill_urb(serial->port[i]->interrupt_in_urb); -} - static int cyberjack_open(struct tty_struct *tty, struct usb_serial_port *port) { -- cgit v1.2.3 From a4a83100a1653a389a5efaa68ad32c9b89010910 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:46 +0100 Subject: USB: serial: fix port release We should not call kill_traffic (and usb_kill_urb) once disconnect returns. Any pending urbs are killed at disconnect and new submissions are prevented by usb_unbind_interface (and usb_disable_interface). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 3eb4d06e49be..456792952db6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -572,13 +572,6 @@ static void port_release(struct device *dev) dev_dbg(dev, "%s\n", __func__); - /* - * Stop all the traffic before cancelling the work, so that - * nobody will restart it by calling usb_serial_port_softint. - */ - kill_traffic(port); - cancel_work_sync(&port->work); - usb_free_urb(port->interrupt_in_urb); usb_free_urb(port->interrupt_out_urb); for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) { -- cgit v1.2.3 From 69a3d2125796b3452da1b9fce851af96ac24b3a9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:47 +0100 Subject: USB: serial: rename port release Rename port_release so that all usb_serial_port functions have a common prefix. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 456792952db6..db0b646d5dc9 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -565,7 +565,7 @@ static void kill_traffic(struct usb_serial_port *port) usb_kill_urb(port->interrupt_out_urb); } -static void port_release(struct device *dev) +static void usb_serial_port_release(struct device *dev) { struct usb_serial_port *port = to_usb_serial_port(dev); int i; @@ -888,7 +888,7 @@ static int usb_serial_probe(struct usb_interface *interface, port->dev.parent = &interface->dev; port->dev.driver = NULL; port->dev.bus = &usb_serial_bus_type; - port->dev.release = &port_release; + port->dev.release = &usb_serial_port_release; device_initialize(&port->dev); } -- cgit v1.2.3 From 6a5c821cad1459ec2b5fd5778f46d13c4255a7bf Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:49 +0100 Subject: USB: serial: use urb poison to reliably kill traffic Use usb_poison_urb to reliably kill all urbs on disconnect and suspend. This way there will be no question that the urbs cannot be resubmitted by buggy subdrivers. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 55 +++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index db0b646d5dc9..0b39d013c505 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -542,27 +542,30 @@ static void usb_serial_port_work(struct work_struct *work) tty_kref_put(tty); } -static void kill_traffic(struct usb_serial_port *port) +static void usb_serial_port_poison_urbs(struct usb_serial_port *port) { int i; for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) - usb_kill_urb(port->read_urbs[i]); + usb_poison_urb(port->read_urbs[i]); for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) - usb_kill_urb(port->write_urbs[i]); - /* - * This is tricky. - * Some drivers submit the read_urb in the - * handler for the write_urb or vice versa - * this order determines the order in which - * usb_kill_urb() must be used to reliably - * kill the URBs. As it is unknown here, - * both orders must be used in turn. - * The call below is not redundant. - */ - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_out_urb); + usb_poison_urb(port->write_urbs[i]); + + usb_poison_urb(port->interrupt_in_urb); + usb_poison_urb(port->interrupt_out_urb); +} + +static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) + usb_unpoison_urb(port->read_urbs[i]); + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) + usb_unpoison_urb(port->write_urbs[i]); + + usb_unpoison_urb(port->interrupt_in_urb); + usb_unpoison_urb(port->interrupt_out_urb); } static void usb_serial_port_release(struct device *dev) @@ -1082,7 +1085,7 @@ static void usb_serial_disconnect(struct usb_interface *interface) tty_vhangup(tty); tty_kref_put(tty); } - kill_traffic(port); + usb_serial_port_poison_urbs(port); cancel_work_sync(&port->work); if (device_is_registered(&port->dev)) device_del(&port->dev); @@ -1120,7 +1123,7 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) - kill_traffic(port); + usb_serial_port_poison_urbs(port); } err_out: @@ -1128,11 +1131,25 @@ err_out: } EXPORT_SYMBOL(usb_serial_suspend); +static void usb_serial_unpoison_port_urbs(struct usb_serial *serial) +{ + struct usb_serial_port *port; + int i; + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (port) + usb_serial_port_unpoison_urbs(port); + } +} + int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); int rv; + usb_serial_unpoison_port_urbs(serial); + serial->suspending = 0; if (serial->type->resume) rv = serial->type->resume(serial); @@ -1148,6 +1165,8 @@ static int usb_serial_reset_resume(struct usb_interface *intf) struct usb_serial *serial = usb_get_intfdata(intf); int rv; + usb_serial_unpoison_port_urbs(serial); + serial->suspending = 0; if (serial->type->reset_resume) rv = serial->type->reset_resume(serial); -- cgit v1.2.3 From 5cb27dde2e8b7bcbdce6de270c73c021a65caff8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:50 +0100 Subject: USB: serial: clean up usb-serial bus device removal Make sure to unregister the tty-device before calling subdriver port_remove. This way remove will reverse probe, and specifically any port data released in port_remove will be available throughout tty unregister. Note that the order currently does not matter as the tty-layer can make callbacks also after the device has been unregistered. This is handled in usb-serial core using the disconnected flag, which is already set when usb-serial bus device remove is called. Cc: Peter Hurley Reported-by: Peter Hurley Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/bus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 37decb13d7eb..3c4db6d196c6 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -106,14 +106,15 @@ static int usb_serial_device_remove(struct device *dev) /* make sure suspend/resume doesn't race against port_remove */ usb_autopm_get_interface(port->serial->interface); + minor = port->number; + tty_unregister_device(usb_serial_tty_driver, minor); + device_remove_file(&port->dev, &dev_attr_port_number); driver = port->serial->type; if (driver->port_remove) retval = driver->port_remove(port); - minor = port->number; - tty_unregister_device(usb_serial_tty_driver, minor); dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", driver->description, minor); -- cgit v1.2.3 From 143d9d961608b737d90a813deaaf91affb41c83c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:51 +0100 Subject: USB: serial: add tiocmiwait subdriver operation Add tiocmiwait operation to struct usb_serial_driver. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 15 +++++++++++---- include/linux/usb/serial.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 0b39d013c505..ada400d6594b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -402,10 +402,17 @@ static int serial_ioctl(struct tty_struct *tty, dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd); - if (port->serial->type->ioctl) - retval = port->serial->type->ioctl(tty, cmd, arg); - else - retval = -ENOIOCTLCMD; + switch (cmd) { + case TIOCMIWAIT: + if (port->serial->type->tiocmiwait) + retval = port->serial->type->tiocmiwait(tty, arg); + break; + default: + if (port->serial->type->ioctl) + retval = port->serial->type->ioctl(tty, cmd, arg); + else + retval = -ENOIOCTLCMD; + } return retval; } diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 3f8f5e3c76d5..9c8b53f80f48 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -272,6 +272,7 @@ struct usb_serial_driver { int (*tiocmget)(struct tty_struct *tty); int (*tiocmset)(struct tty_struct *tty, unsigned int set, unsigned int clear); + int (*tiocmiwait)(struct tty_struct *tty, unsigned long arg); int (*get_icount)(struct tty_struct *tty, struct serial_icounter_struct *icount); /* Called by the tty layer for port level work. There may or may not -- cgit v1.2.3 From 980373b7918b8023be6b7df03857f494ae124d0b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:52 +0100 Subject: USB: serial: add generic TIOCMIWAIT implementation Add generic TIOCMIWAIT implementation which correctly handles hangup, USB-device disconnect, does not rely on the deprecated sleep_on functions and hence does not suffer from the races currently affecting several usb-serial drivers. This makes it much easier to add TIOCMIWAIT support to subdrivers as the tricky details related to hangup and disconnect (e.g. atomicity, that the private port data may have been freed when woken up, and waking up processes at disconnect) have been handled once and for all. To add support to a subdriver, simply set the tiocmiwait-port-operation field, update the port icount fields and wake up any process sleeping on the tty-port modem-status-change wait queue on changes. Note that the tty-port initialised flag can be used to detect disconnected as the port will be hung up as part of disconnect (and cannot be reactivated due to the disconnected flag). However, as the tty-port implementation currently wakes up processes before calling port shutdown, the tty-hupping flag must also be checked to detect hangup for now. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/usb/serial.h | 5 ++++ 2 files changed, 63 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index aa71f6e72f61..18bc74e20fe1 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -418,6 +418,64 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) } EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); +static bool usb_serial_generic_msr_changed(struct tty_struct *tty, + unsigned long arg, struct async_icount *cprev) +{ + struct usb_serial_port *port = tty->driver_data; + struct async_icount cnow; + unsigned long flags; + bool ret; + + /* + * Use tty-port initialised flag to detect all hangups including the + * one generated at USB-device disconnect. + * + * FIXME: Remove hupping check once tty_port_hangup calls shutdown + * (which clears the initialised flag) before wake up. + */ + if (test_bit(TTY_HUPPING, &tty->flags)) + return true; + if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) + return true; + + spin_lock_irqsave(&port->lock, flags); + cnow = port->icount; /* atomic copy*/ + spin_unlock_irqrestore(&port->lock, flags); + + ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); + + *cprev = cnow; + + return ret; +} + +int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct async_icount cnow; + unsigned long flags; + int ret; + + spin_lock_irqsave(&port->lock, flags); + cnow = port->icount; /* atomic copy */ + spin_unlock_irqrestore(&port->lock, flags); + + ret = wait_event_interruptible(port->port.delta_msr_wait, + usb_serial_generic_msr_changed(tty, arg, &cnow)); + if (!ret) { + if (test_bit(TTY_HUPPING, &tty->flags)) + ret = -EIO; + if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) + ret = -EIO; + } + + return ret; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait); + #ifdef CONFIG_MAGIC_SYSRQ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) { diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 9c8b53f80f48..47c8d2c506c8 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -61,6 +62,7 @@ * @bulk_out_buffers: pointers to the bulk out buffers for this port * @write_urbs: pointers to the bulk out urbs for this port * @write_urbs_free: status bitmap the for bulk out urbs + * @icount: interrupt counters * @tx_bytes: number of bytes currently in host stack queues * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this * port. @@ -109,6 +111,7 @@ struct usb_serial_port { unsigned long write_urbs_free; __u8 bulk_out_endpointAddress; + struct async_icount icount; int tx_bytes; unsigned long flags; @@ -330,6 +333,8 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb); extern void usb_serial_generic_write_bulk_callback(struct urb *urb); extern void usb_serial_generic_throttle(struct tty_struct *tty); extern void usb_serial_generic_unthrottle(struct tty_struct *tty); +extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty, + unsigned long arg); extern int usb_serial_generic_register(void); extern void usb_serial_generic_deregister(void); extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, -- cgit v1.2.3 From c371de14b9a23aadb57accab0ca2e5dd28de7f16 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:53 +0100 Subject: USB: serial: wake up MSR-wait queue on disconnect Make sure processes waiting for modem-status changes are woken up at disconnect. This is needed for custom subdriver TIOCMIWAIT-implementations which do not yet handle hangup. Even though processes on the tty-port wait queue are woken up at hangup the wake-up call in usb-serial disconnect is still needed if a woken-up process may go back to sleep (e.g. due to an incomplete TIOCMIWAIT-implementation). If a disconnect occurs after a hangup, any process waiting for changes will not be woken up a second time by the tty-layer as the port will then have been disassociated from the tty. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index ada400d6594b..456881620727 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1093,6 +1093,7 @@ static void usb_serial_disconnect(struct usb_interface *interface) tty_kref_put(tty); } usb_serial_port_poison_urbs(port); + wake_up_interruptible(&port->port.delta_msr_wait); cancel_work_sync(&port->work); if (device_is_registered(&port->dev)) device_del(&port->dev); -- cgit v1.2.3 From befefcda4bddc52d29248931801961a72aeef28b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:54 +0100 Subject: USB: serial: add generic get_icount implementation Add generic get_icount implementation that subdrivers relying on the port interrupt counters can use. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 27 +++++++++++++++++++++++++++ include/linux/usb/serial.h | 2 ++ 2 files changed, 29 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 18bc74e20fe1..5e55761b2cb8 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -476,6 +476,33 @@ int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg) } EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait); +int usb_serial_generic_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) +{ + struct usb_serial_port *port = tty->driver_data; + struct async_icount cnow; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + cnow = port->icount; /* atomic copy */ + spin_unlock_irqrestore(&port->lock, flags); + + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + icount->tx = cnow.tx; + icount->rx = cnow.rx; + icount->frame = cnow.frame; + icount->parity = cnow.parity; + icount->overrun = cnow.overrun; + icount->brk = cnow.brk; + icount->buf_overrun = cnow.buf_overrun; + + return 0; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount); + #ifdef CONFIG_MAGIC_SYSRQ int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) { diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 47c8d2c506c8..c786ee7fca8f 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -335,6 +335,8 @@ extern void usb_serial_generic_throttle(struct tty_struct *tty); extern void usb_serial_generic_unthrottle(struct tty_struct *tty); extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg); +extern int usb_serial_generic_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount); extern int usb_serial_generic_register(void); extern void usb_serial_generic_deregister(void); extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, -- cgit v1.2.3 From cb1676a61a83f9a01517abd496f080bf7d56168e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:55 +0100 Subject: USB: ftdi_sio: use port icount Use the port-data icount for interrupt counters. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c5757385790e..ea7433e708bb 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -67,7 +67,6 @@ struct ftdi_private { */ int flags; /* some ASYNC_xxxx flags are supported */ unsigned long last_dtr_rts; /* saved modem control outputs */ - struct async_icount icount; char prev_status; /* Used for TIOCMIWAIT */ char transmit_empty; /* If transmitter is empty or not */ __u16 interface; /* FT2232C, FT2232H or FT4232H port interface @@ -1909,7 +1908,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, c = kfifo_out(&port->write_fifo, &buffer[i + 1], len); if (!c) break; - priv->icount.tx += c; + port->icount.tx += c; buffer[i] = (c << 2) + 1; count += c + 1; } @@ -1917,7 +1916,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, } else { count = kfifo_out_locked(&port->write_fifo, dest, size, &port->lock); - priv->icount.tx += count; + port->icount.tx += count; } return count; @@ -1946,13 +1945,13 @@ static int ftdi_process_packet(struct usb_serial_port *port, char diff_status = status ^ priv->prev_status; if (diff_status & FTDI_RS0_CTS) - priv->icount.cts++; + port->icount.cts++; if (diff_status & FTDI_RS0_DSR) - priv->icount.dsr++; + port->icount.dsr++; if (diff_status & FTDI_RS0_RI) - priv->icount.rng++; + port->icount.rng++; if (diff_status & FTDI_RS0_RLSD) - priv->icount.dcd++; + port->icount.dcd++; wake_up_interruptible(&port->delta_msr_wait); priv->prev_status = status; @@ -1964,18 +1963,18 @@ static int ftdi_process_packet(struct usb_serial_port *port, * over framing errors */ if (packet[1] & FTDI_RS_BI) { flag = TTY_BREAK; - priv->icount.brk++; + port->icount.brk++; usb_serial_handle_break(port); } else if (packet[1] & FTDI_RS_PE) { flag = TTY_PARITY; - priv->icount.parity++; + port->icount.parity++; } else if (packet[1] & FTDI_RS_FE) { flag = TTY_FRAME; - priv->icount.frame++; + port->icount.frame++; } /* Overrun is special, not associated with a char */ if (packet[1] & FTDI_RS_OE) { - priv->icount.overrun++; + port->icount.overrun++; tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); } } @@ -1989,7 +1988,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, len -= 2; if (!len) return 0; /* status only */ - priv->icount.rx += len; + port->icount.rx += len; ch = packet + 2; if (port->port.console && port->sysrq) { @@ -2357,8 +2356,7 @@ static int ftdi_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount) { struct usb_serial_port *port = tty->driver_data; - struct ftdi_private *priv = usb_get_serial_port_data(port); - struct async_icount *ic = &priv->icount; + struct async_icount *ic = &port->icount; icount->cts = ic->cts; icount->dsr = ic->dsr; @@ -2378,7 +2376,6 @@ static int ftdi_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; - struct ftdi_private *priv = usb_get_serial_port_data(port); struct async_icount cnow; struct async_icount cprev; @@ -2404,7 +2401,7 @@ static int ftdi_ioctl(struct tty_struct *tty, * This code is borrowed from linux/drivers/char/serial.c */ case TIOCMIWAIT: - cprev = priv->icount; + cprev = port->icount; for (;;) { interruptible_sleep_on(&port->delta_msr_wait); /* see if a signal did it */ @@ -2414,7 +2411,7 @@ static int ftdi_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; - cnow = priv->icount; + cnow = port->icount; if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || -- cgit v1.2.3 From f307e5cd3f3d2243ec69abc9df890052b88349f5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:56 +0100 Subject: USB: ftdi_sio: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation which does not suffer from the races involved when using the deprecated sleep_on functions. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ea7433e708bb..fa3077fa7f65 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -954,6 +954,7 @@ static struct usb_serial_driver ftdi_sio_device = { .prepare_write_buffer = ftdi_prepare_write_buffer, .tiocmget = ftdi_tiocmget, .tiocmset = ftdi_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = ftdi_get_icount, .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, @@ -1824,8 +1825,6 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); - wake_up_interruptible(&port->delta_msr_wait); - remove_sysfs_attrs(port); kfree(priv); @@ -1953,7 +1952,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, if (diff_status & FTDI_RS0_RLSD) port->icount.dcd++; - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); priv->prev_status = status; } @@ -2376,8 +2375,6 @@ static int ftdi_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; - struct async_icount cnow; - struct async_icount cprev; dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); @@ -2391,35 +2388,6 @@ static int ftdi_ioctl(struct tty_struct *tty, case TIOCSSERIAL: /* sets serial port data */ return set_serial_info(tty, port, (struct serial_struct __user *) arg); - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was. - * - * This code is borrowed from linux/drivers/char/serial.c - */ - case TIOCMIWAIT: - cprev = port->icount; - for (;;) { - interruptible_sleep_on(&port->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - cnow = port->icount; - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } case TIOCSERGETLSR: return get_lsr_info(port, (struct serial_struct __user *)arg); break; -- cgit v1.2.3 From 6f86fec9fa38b8f69902f973e0cff612b2a0f0b0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:57 +0100 Subject: USB: ftdi_sio: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index fa3077fa7f65..1199dc52e388 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -917,8 +917,6 @@ static void ftdi_set_termios(struct tty_struct *tty, static int ftdi_tiocmget(struct tty_struct *tty); static int ftdi_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int ftdi_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); static int ftdi_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static void ftdi_break_ctl(struct tty_struct *tty, int break_state); @@ -955,7 +953,7 @@ static struct usb_serial_driver ftdi_sio_device = { .tiocmget = ftdi_tiocmget, .tiocmset = ftdi_tiocmset, .tiocmiwait = usb_serial_generic_tiocmiwait, - .get_icount = ftdi_get_icount, + .get_icount = usb_serial_generic_get_icount, .ioctl = ftdi_ioctl, .set_termios = ftdi_set_termios, .break_ctl = ftdi_break_ctl, @@ -2351,26 +2349,6 @@ static int ftdi_tiocmset(struct tty_struct *tty, return update_mctrl(port, set, clear); } -static int ftdi_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct async_icount *ic = &port->icount; - - icount->cts = ic->cts; - icount->dsr = ic->dsr; - icount->rng = ic->rng; - icount->dcd = ic->dcd; - icount->tx = ic->tx; - icount->rx = ic->rx; - icount->frame = ic->frame; - icount->parity = ic->parity; - icount->overrun = ic->overrun; - icount->brk = ic->brk; - icount->buf_overrun = ic->buf_overrun; - return 0; -} - static int ftdi_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { -- cgit v1.2.3 From b4cb7536cc4883fe133de8733430ccdb23e23fa9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:58 +0100 Subject: USB: ark3116: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 58 ++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 40 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 3b811feb35fd..ed3f6b884073 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial) } struct ark3116_private { - struct async_icount icount; int irda; /* 1 for irda device */ /* protects hw register updates */ @@ -402,31 +401,10 @@ err_out: return result; } -static int ark3116_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct ark3116_private *priv = usb_get_serial_port_data(port); - struct async_icount cnow = priv->icount; - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - return 0; -} - static int ark3116_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; - struct ark3116_private *priv = usb_get_serial_port_data(port); struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; @@ -450,7 +428,7 @@ static int ark3116_ioctl(struct tty_struct *tty, return 0; case TIOCMIWAIT: for (;;) { - struct async_icount prev = priv->icount; + struct async_icount prev = port->icount; interruptible_sleep_on(&port->delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) @@ -459,19 +437,19 @@ static int ark3116_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; - if ((prev.rng == priv->icount.rng) && - (prev.dsr == priv->icount.dsr) && - (prev.dcd == priv->icount.dcd) && - (prev.cts == priv->icount.cts)) + if ((prev.rng == port->icount.rng) && + (prev.dsr == port->icount.dsr) && + (prev.dcd == port->icount.dcd) && + (prev.cts == port->icount.cts)) return -EIO; if ((arg & TIOCM_RNG && - (prev.rng != priv->icount.rng)) || + (prev.rng != port->icount.rng)) || (arg & TIOCM_DSR && - (prev.dsr != priv->icount.dsr)) || + (prev.dsr != port->icount.dsr)) || (arg & TIOCM_CD && - (prev.dcd != priv->icount.dcd)) || + (prev.dcd != port->icount.dcd)) || (arg & TIOCM_CTS && - (prev.cts != priv->icount.cts))) + (prev.cts != port->icount.cts))) return 0; } break; @@ -572,13 +550,13 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) if (msr & UART_MSR_ANY_DELTA) { /* update input line counters */ if (msr & UART_MSR_DCTS) - priv->icount.cts++; + port->icount.cts++; if (msr & UART_MSR_DDSR) - priv->icount.dsr++; + port->icount.dsr++; if (msr & UART_MSR_DDCD) - priv->icount.dcd++; + port->icount.dcd++; if (msr & UART_MSR_TERI) - priv->icount.rng++; + port->icount.rng++; wake_up_interruptible(&port->delta_msr_wait); } } @@ -595,13 +573,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr) if (lsr&UART_LSR_BRK_ERROR_BITS) { if (lsr & UART_LSR_BI) - priv->icount.brk++; + port->icount.brk++; if (lsr & UART_LSR_FE) - priv->icount.frame++; + port->icount.frame++; if (lsr & UART_LSR_PE) - priv->icount.parity++; + port->icount.parity++; if (lsr & UART_LSR_OE) - priv->icount.overrun++; + port->icount.overrun++; } } @@ -719,7 +697,7 @@ static struct usb_serial_driver ark3116_device = { .ioctl = ark3116_ioctl, .tiocmget = ark3116_tiocmget, .tiocmset = ark3116_tiocmset, - .get_icount = ark3116_get_icount, + .get_icount = usb_serial_generic_get_icount, .open = ark3116_open, .close = ark3116_close, .break_ctl = ark3116_break_ctl, -- cgit v1.2.3 From 7caed7e78c14e53479fea75c132d297257a2423c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:36:59 +0100 Subject: USB: ark3116: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation which does not suffer from the races involved when using the deprecated sleep_on functions. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index ed3f6b884073..3b16118cbf62 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -426,33 +426,6 @@ static int ark3116_ioctl(struct tty_struct *tty, if (copy_from_user(&serstruct, user_arg, sizeof(serstruct))) return -EFAULT; return 0; - case TIOCMIWAIT: - for (;;) { - struct async_icount prev = port->icount; - interruptible_sleep_on(&port->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - if ((prev.rng == port->icount.rng) && - (prev.dsr == port->icount.dsr) && - (prev.dcd == port->icount.dcd) && - (prev.cts == port->icount.cts)) - return -EIO; - if ((arg & TIOCM_RNG && - (prev.rng != port->icount.rng)) || - (arg & TIOCM_DSR && - (prev.dsr != port->icount.dsr)) || - (arg & TIOCM_CD && - (prev.dcd != port->icount.dcd)) || - (arg & TIOCM_CTS && - (prev.cts != port->icount.cts))) - return 0; - } - break; } return -ENOIOCTLCMD; @@ -557,7 +530,7 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) port->icount.dcd++; if (msr & UART_MSR_TERI) port->icount.rng++; - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); } } @@ -697,6 +670,7 @@ static struct usb_serial_driver ark3116_device = { .ioctl = ark3116_ioctl, .tiocmget = ark3116_tiocmget, .tiocmset = ark3116_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .open = ark3116_open, .close = ark3116_close, -- cgit v1.2.3 From 7bb98f0edd1df8687ca9c8ce9492f8ac6b8ec448 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:00 +0100 Subject: USB: ch341: replace custom ioctl operation with tiocmiwait Replace custom ioctl operation with tiocmiwait. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 07d4650a32ab..1a97985df782 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -500,8 +500,9 @@ exit: __func__, status); } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 prevstatus; @@ -542,26 +543,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return 0; } -static int ch341_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = tty->driver_data; - - dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd); - - switch (cmd) { - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); - return wait_modem_info(port, arg); - - default: - dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); - break; - } - - return -ENOIOCTLCMD; -} - static int ch341_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -611,11 +592,11 @@ static struct usb_serial_driver ch341_device = { .dtr_rts = ch341_dtr_rts, .carrier_raised = ch341_carrier_raised, .close = ch341_close, - .ioctl = ch341_ioctl, .set_termios = ch341_set_termios, .break_ctl = ch341_break_ctl, .tiocmget = ch341_tiocmget, .tiocmset = ch341_tiocmset, + .tiocmiwait = ch341_tiocmiwait, .read_int_callback = ch341_read_int_callback, .port_probe = ch341_port_probe, .port_remove = ch341_port_remove, -- cgit v1.2.3 From 3f550431925891d2ea4338d298aceeceb1c6cbf1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:01 +0100 Subject: USB: ch341: fix TIOCMIWAIT and disconnect Use tty-port modem-status-change wait queue on which processes are woken up at hangup and disconnect. Currently a process waiting on modem-status changes will not be woken on device disconnect as wake up was only done in dtr_rts which isn't guaranteed to be called (e.g. if HUPCL is not set). Also remove the redundant wake-up call from dtr_rts. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 1a97985df782..c2a4171ab9cb 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -296,7 +296,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on) priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR); spin_unlock_irqrestore(&priv->lock, flags); ch341_set_handshake(port->serial->dev, priv->line_control); - wake_up_interruptible(&port->delta_msr_wait); } static void ch341_close(struct usb_serial_port *port) @@ -489,7 +488,7 @@ static void ch341_read_int_callback(struct urb *urb) tty_kref_put(tty); } - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); } exit: @@ -516,7 +515,7 @@ static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg) spin_unlock_irqrestore(&priv->lock, flags); while (!multi_change) { - interruptible_sleep_on(&port->delta_msr_wait); + interruptible_sleep_on(&port->port.delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; -- cgit v1.2.3 From 493516e34455cdfcd0a2875bb62ed5d910782958 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:02 +0100 Subject: USB: cypress_m8: replace custom ioctl operation with tiocmiwait Replace custom ioctl operation with tiocmiwait. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 85 +++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 49 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index ba7352e4187e..cdbb09691aee 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -129,13 +129,12 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static void cypress_send(struct usb_serial_port *port); static int cypress_write_room(struct tty_struct *tty); -static int cypress_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg); static void cypress_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static int cypress_tiocmget(struct tty_struct *tty); static int cypress_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); +static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg); static int cypress_chars_in_buffer(struct tty_struct *tty); static void cypress_throttle(struct tty_struct *tty); static void cypress_unthrottle(struct tty_struct *tty); @@ -158,10 +157,10 @@ static struct usb_serial_driver cypress_earthmate_device = { .dtr_rts = cypress_dtr_rts, .write = cypress_write, .write_room = cypress_write_room, - .ioctl = cypress_ioctl, .set_termios = cypress_set_termios, .tiocmget = cypress_tiocmget, .tiocmset = cypress_tiocmset, + .tiocmiwait = cypress_tiocmiwait, .chars_in_buffer = cypress_chars_in_buffer, .throttle = cypress_throttle, .unthrottle = cypress_unthrottle, @@ -184,10 +183,10 @@ static struct usb_serial_driver cypress_hidcom_device = { .dtr_rts = cypress_dtr_rts, .write = cypress_write, .write_room = cypress_write_room, - .ioctl = cypress_ioctl, .set_termios = cypress_set_termios, .tiocmget = cypress_tiocmget, .tiocmset = cypress_tiocmset, + .tiocmiwait = cypress_tiocmiwait, .chars_in_buffer = cypress_chars_in_buffer, .throttle = cypress_throttle, .unthrottle = cypress_unthrottle, @@ -210,10 +209,10 @@ static struct usb_serial_driver cypress_ca42v2_device = { .dtr_rts = cypress_dtr_rts, .write = cypress_write, .write_room = cypress_write_room, - .ioctl = cypress_ioctl, .set_termios = cypress_set_termios, .tiocmget = cypress_tiocmget, .tiocmset = cypress_tiocmset, + .tiocmiwait = cypress_tiocmiwait, .chars_in_buffer = cypress_chars_in_buffer, .throttle = cypress_throttle, .unthrottle = cypress_unthrottle, @@ -855,55 +854,43 @@ static int cypress_tiocmset(struct tty_struct *tty, } -static int cypress_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) +static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); - - dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd); - - switch (cmd) { - /* This code comes from drivers/char/serial.c and ftdi_sio.c */ - case TIOCMIWAIT: - for (;;) { - interruptible_sleep_on(&port->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - { - char diff = priv->diff_status; - if (diff == 0) - return -EIO; /* no change => error */ - - /* consume all events */ - priv->diff_status = 0; - - /* return 0 if caller wanted to know about - these bits */ - if (((arg & TIOCM_RNG) && (diff & UART_RI)) || - ((arg & TIOCM_DSR) && (diff & UART_DSR)) || - ((arg & TIOCM_CD) && (diff & UART_CD)) || - ((arg & TIOCM_CTS) && (diff & UART_CTS))) - return 0; - /* otherwise caller can't care less about what - * happened, and so we continue to wait for - * more events. - */ - } - } - return 0; - default: - break; + char diff; + + for (;;) { + interruptible_sleep_on(&port->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + if (port->serial->disconnected) + return -EIO; + + diff = priv->diff_status; + if (diff == 0) + return -EIO; /* no change => error */ + + /* consume all events */ + priv->diff_status = 0; + + /* return 0 if caller wanted to know about + these bits */ + if (((arg & TIOCM_RNG) && (diff & UART_RI)) || + ((arg & TIOCM_DSR) && (diff & UART_DSR)) || + ((arg & TIOCM_CD) && (diff & UART_CD)) || + ((arg & TIOCM_CTS) && (diff & UART_CTS))) + return 0; + /* otherwise caller can't care less about what + * happened, and so we continue to wait for + * more events. + */ } - dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd); - return -ENOIOCTLCMD; -} /* cypress_ioctl */ + return 0; +} static void cypress_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) -- cgit v1.2.3 From c648e94ebfc7701f4d0c79dce959134f02f24ce7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:03 +0100 Subject: USB: cypress_m8: fix TIOCMIWAIT and disconnect Use tty-port modem-status-change wait queue on which processes are woken up at hangup and disconnect. Currently a process waiting on modem-status changes will not be woken on device disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index cdbb09691aee..e4a62cfc4081 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -861,7 +861,7 @@ static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg) char diff; for (;;) { - interruptible_sleep_on(&port->delta_msr_wait); + interruptible_sleep_on(&port->port.delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; @@ -1176,7 +1176,7 @@ static void cypress_read_int_callback(struct urb *urb) if (priv->current_status != priv->prev_status) { priv->diff_status |= priv->current_status ^ priv->prev_status; - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); priv->prev_status = priv->current_status; } spin_unlock_irqrestore(&priv->lock, flags); -- cgit v1.2.3 From a7fa57742ea692631a4076254408366a01eb3582 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:04 +0100 Subject: USB: digi_acceleport: remove unused MSR-wait queue Remove unused, private modem-status wait queue from driver. If TIOCMIWAIT is ever implemented it must not rely on a private wait queue which may have been released when woken up. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/digi_acceleport.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 76a8c202a8e2..32873b406402 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -196,7 +196,6 @@ struct digi_port { unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE]; int dp_write_urb_in_use; unsigned int dp_modem_signals; - wait_queue_head_t dp_modem_change_wait; int dp_transmit_idle; wait_queue_head_t dp_transmit_idle_wait; int dp_throttled; @@ -1250,7 +1249,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) spin_lock_init(&priv->dp_port_lock); priv->dp_port_num = port_num; - init_waitqueue_head(&priv->dp_modem_change_wait); init_waitqueue_head(&priv->dp_transmit_idle_wait); init_waitqueue_head(&priv->dp_flush_wait); init_waitqueue_head(&priv->dp_close_wait); @@ -1541,7 +1539,6 @@ static int digi_read_oob_callback(struct urb *urb) else priv->dp_modem_signals &= ~TIOCM_CD; - wake_up_interruptible(&priv->dp_modem_change_wait); spin_unlock(&priv->dp_port_lock); } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) { spin_lock(&priv->dp_port_lock); -- cgit v1.2.3 From 4bb4e6384ad633448b3bbd49df63188330bbf740 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:05 +0100 Subject: USB: f81232: add custom tiocmiwait operation Break out TIOCMIWAIT handling from custom ioctl operation and use tiocmiwait operation field instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/f81232.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index a172ad5c5ce8..d1fdd8d1e3ba 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -242,8 +242,9 @@ static int f81232_carrier_raised(struct usb_serial_port *port) return 0; } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct f81232_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int prevstatus; @@ -302,11 +303,6 @@ static int f81232_ioctl(struct tty_struct *tty, return -EFAULT; return 0; - - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, - port->number); - return wait_modem_info(port, arg); default: dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); @@ -358,6 +354,7 @@ static struct usb_serial_driver f81232_device = { .set_termios = f81232_set_termios, .tiocmget = f81232_tiocmget, .tiocmset = f81232_tiocmset, + .tiocmiwait = f81232_tiocmiwait, .process_read_urb = f81232_process_read_urb, .read_int_callback = f81232_read_int_callback, .port_probe = f81232_port_probe, -- cgit v1.2.3 From 3018bb51583e8b9f9e76574c71d45e43d8299ebc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:06 +0100 Subject: USB: f81232: fix TIOCMIWAIT and disconnect Use tty-port modem-status-change wait queue on which processes are woken up at hangup and disconnect. Currently a process waiting on modem-status changes will not be woken on device disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/f81232.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index d1fdd8d1e3ba..090b411d893f 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -110,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb) line_status = priv->line_status; priv->line_status &= ~UART_STATE_TRANSIENT_MASK; spin_unlock_irqrestore(&priv->lock, flags); - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); if (!urb->actual_length) return; @@ -256,7 +256,7 @@ static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg) spin_unlock_irqrestore(&priv->lock, flags); while (1) { - interruptible_sleep_on(&port->delta_msr_wait); + interruptible_sleep_on(&port->port.delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; -- cgit v1.2.3 From d36a7712497b547a21bf46c3be517cb06ccb93ee Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:07 +0100 Subject: USB: io_edgeport: switch to generic get_icount implementation Switch to the generic get_icount implementation. Note that the interrupt counters will no longer be reset at open which is in accordance with which how the other drivers work. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 45 +++++++--------------------------------- drivers/usb/serial/io_tables.h | 8 +++---- 2 files changed, 11 insertions(+), 42 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index efd8b978128c..16ef8f3714d9 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -111,7 +111,6 @@ struct edgeport_port { wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */ wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ - struct async_icount icount; struct usb_serial_port *port; /* loop back to the owner of this object */ }; @@ -215,8 +214,6 @@ static void edge_break(struct tty_struct *tty, int break_state); static int edge_tiocmget(struct tty_struct *tty); static int edge_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int edge_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); static int edge_startup(struct usb_serial *serial); static void edge_disconnect(struct usb_serial *serial); static void edge_release(struct usb_serial *serial); @@ -885,9 +882,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) init_waitqueue_head(&edge_port->wait_chase); init_waitqueue_head(&edge_port->wait_command); - /* initialize our icount structure */ - memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); - /* initialize our port settings */ edge_port->txCredits = 0; /* Can't send any data yet */ /* Must always set this bit to enable ints! */ @@ -1314,7 +1308,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, /* decrement the number of credits we have by the number we just sent */ edge_port->txCredits -= count; - edge_port->icount.tx += count; + edge_port->port->icount.tx += count; status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { @@ -1326,7 +1320,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, /* revert the credits as something bad happened. */ edge_port->txCredits += count; - edge_port->icount.tx -= count; + edge_port->port->icount.tx -= count; } dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n", __func__, count, edge_port->txCredits, fifo->count); @@ -1588,31 +1582,6 @@ static int edge_tiocmget(struct tty_struct *tty) return result; } -static int edge_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct async_icount cnow; - cnow = edge_port->icount; - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__, - port->number, icount->rx, icount->tx); - return 0; -} - static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { @@ -1665,7 +1634,7 @@ static int edge_ioctl(struct tty_struct *tty, case TIOCMIWAIT: dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); - cprev = edge_port->icount; + cprev = port->icount; while (1) { prepare_to_wait(&port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE); @@ -1678,7 +1647,7 @@ static int edge_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; - cnow = edge_port->icount; + cnow = port->icount; if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ @@ -1866,7 +1835,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, edge_serial->rxPort); edge_tty_recv(edge_port->port, buffer, rxLen); - edge_port->icount.rx += rxLen; + edge_port->port->icount.rx += rxLen; } buffer += rxLen; } @@ -2042,7 +2011,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { - icount = &edge_port->icount; + icount = &edge_port->port->icount; /* update input line counters */ if (newMsr & EDGEPORT_MSR_DELTA_CTS) @@ -2088,7 +2057,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, edge_tty_recv(edge_port->port, &data, 1); /* update input line counters */ - icount = &edge_port->icount; + icount = &edge_port->port->icount; if (newLsr & LSR_BREAK) icount->brk++; if (newLsr & LSR_OVER_ERR) diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 1511dd0ad324..35fe9ad7d3da 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -116,7 +116,7 @@ static struct usb_serial_driver edgeport_2port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, - .get_icount = edge_get_icount, + .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, @@ -147,7 +147,7 @@ static struct usb_serial_driver edgeport_4port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, - .get_icount = edge_get_icount, + .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, @@ -178,7 +178,7 @@ static struct usb_serial_driver edgeport_8port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, - .get_icount = edge_get_icount, + .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, @@ -209,7 +209,7 @@ static struct usb_serial_driver epic_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, - .get_icount = edge_get_icount, + .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, -- cgit v1.2.3 From 8b8070d8580c38e15979b2a88f3a4d7b02bd3bde Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:08 +0100 Subject: USB: io_edgeport: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 35 +---------------------------------- drivers/usb/serial/io_tables.h | 4 ++++ 2 files changed, 5 insertions(+), 34 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 16ef8f3714d9..ff9a6ef8477f 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1618,8 +1618,6 @@ static int edge_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; DEFINE_WAIT(wait); struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct async_icount cnow; - struct async_icount cprev; dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); @@ -1631,37 +1629,6 @@ static int edge_ioctl(struct tty_struct *tty, case TIOCGSERIAL: dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__, port->number); return get_serial_info(edge_port, (struct serial_struct __user *) arg); - - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); - cprev = port->icount; - while (1) { - prepare_to_wait(&port->delta_msr_wait, - &wait, TASK_INTERRUPTIBLE); - schedule(); - finish_wait(&port->delta_msr_wait, &wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - cnow = port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - break; - } return -ENOIOCTLCMD; } @@ -2022,7 +1989,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) icount->dcd++; if (newMsr & EDGEPORT_MSR_DELTA_RI) icount->rng++; - wake_up_interruptible(&edge_port->port->delta_msr_wait); + wake_up_interruptible(&edge_port->port->port.delta_msr_wait); } /* Save the new modem status */ diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 35fe9ad7d3da..ae5fac5656c9 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -116,6 +116,7 @@ static struct usb_serial_driver edgeport_2port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, @@ -147,6 +148,7 @@ static struct usb_serial_driver edgeport_4port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, @@ -178,6 +180,7 @@ static struct usb_serial_driver edgeport_8port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, @@ -209,6 +212,7 @@ static struct usb_serial_driver epic_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, -- cgit v1.2.3 From cf9a9d66bd29f32011d271695ffaa289489b3a7d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:09 +0100 Subject: USB: io_ti: switch to generic get_icount implementation Switch to the generic get_icount implementation. Note that the interrupt counters will no longer be reset at open which is in accordance with which how the other drivers work. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 40 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 7777172206de..fb9e66480f17 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -86,7 +86,6 @@ struct edgeport_port { int baud_rate; int close_pending; int lsr_event; - struct async_icount icount; struct edgeport_serial *edge_serial; struct usb_serial_port *port; __u8 bUartMode; /* Port type, 0: RS232, etc. */ @@ -1445,7 +1444,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { - icount = &edge_port->icount; + icount = &edge_port->port->icount; /* update input line counters */ if (msr & EDGEPORT_MSR_DELTA_CTS) @@ -1498,7 +1497,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, edge_tty_recv(edge_port->port, &data, 1); /* update input line counters */ - icount = &edge_port->icount; + icount = &edge_port->port->icount; if (new_lsr & LSR_BREAK) icount->brk++; if (new_lsr & LSR_OVER_ERR) @@ -1657,7 +1656,7 @@ static void edge_bulk_in_callback(struct urb *urb) else edge_tty_recv(edge_port->port, data, urb->actual_length); - edge_port->icount.rx += urb->actual_length; + edge_port->port->icount.rx += urb->actual_length; } exit: @@ -1750,8 +1749,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) dev = port->serial->dev; - memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); - /* turn off loopback */ status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0); if (status) { @@ -1999,7 +1996,7 @@ static void edge_send(struct tty_struct *tty) edge_port->ep_write_urb_in_use = 0; /* TODO: reschedule edge_send */ } else - edge_port->icount.tx += count; + edge_port->port->icount.tx += count; /* wakeup any process waiting for writes to complete */ /* there is now more room in the buffer for new writes */ @@ -2360,27 +2357,6 @@ static int edge_tiocmget(struct tty_struct *tty) return result; } -static int edge_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct async_icount *ic = &edge_port->icount; - - icount->cts = ic->cts; - icount->dsr = ic->dsr; - icount->rng = ic->rng; - icount->dcd = ic->dcd; - icount->tx = ic->tx; - icount->rx = ic->rx; - icount->frame = ic->frame; - icount->parity = ic->parity; - icount->overrun = ic->overrun; - icount->brk = ic->brk; - icount->buf_overrun = ic->buf_overrun; - return 0; -} - static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { @@ -2428,7 +2404,7 @@ static int edge_ioctl(struct tty_struct *tty, (struct serial_struct __user *) arg); case TIOCMIWAIT: dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); - cprev = edge_port->icount; + cprev = edge_port->port->icount; while (1) { interruptible_sleep_on(&port->delta_msr_wait); /* see if a signal did it */ @@ -2438,7 +2414,7 @@ static int edge_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; - cnow = edge_port->icount; + cnow = port->icount; if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ @@ -2618,7 +2594,7 @@ static struct usb_serial_driver edgeport_1port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, - .get_icount = edge_get_icount, + .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, @@ -2649,7 +2625,7 @@ static struct usb_serial_driver edgeport_2port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, - .get_icount = edge_get_icount, + .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, -- cgit v1.2.3 From 48ee5801381dba2e80187c08f15713e859ab5c0f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:10 +0100 Subject: USB: io_ti: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation which does not suffer from the races involved when using the deprecated sleep_on functions. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index fb9e66480f17..8914002a0f65 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -86,6 +86,7 @@ struct edgeport_port { int baud_rate; int close_pending; int lsr_event; + struct edgeport_serial *edge_serial; struct usb_serial_port *port; __u8 bUartMode; /* Port type, 0: RS232, etc. */ @@ -1455,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) icount->dcd++; if (msr & EDGEPORT_MSR_DELTA_RI) icount->rng++; - wake_up_interruptible(&edge_port->port->delta_msr_wait); + wake_up_interruptible(&edge_port->port->port.delta_msr_wait); } /* Save the new modem status */ @@ -2392,8 +2393,6 @@ static int edge_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; struct edgeport_port *edge_port = usb_get_serial_port_data(port); - struct async_icount cnow; - struct async_icount cprev; dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); @@ -2402,32 +2401,6 @@ static int edge_ioctl(struct tty_struct *tty, dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__); return get_serial_info(edge_port, (struct serial_struct __user *) arg); - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); - cprev = edge_port->port->icount; - while (1) { - interruptible_sleep_on(&port->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - cnow = port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* not reached */ - break; } return -ENOIOCTLCMD; } @@ -2522,7 +2495,6 @@ static int edge_port_remove(struct usb_serial_port *port) struct edgeport_port *edge_port; edge_port = usb_get_serial_port_data(port); - edge_remove_sysfs_attrs(port); kfifo_free(&edge_port->write_fifo); kfree(edge_port); @@ -2594,6 +2566,7 @@ static struct usb_serial_driver edgeport_1port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, @@ -2625,6 +2598,7 @@ static struct usb_serial_driver edgeport_2port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .write = edge_write, .write_room = edge_write_room, -- cgit v1.2.3 From 09b0e3957549e7036a66e4597a7167e43861cfd6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:11 +0100 Subject: USB: iuu_phoenix: remove unused MSR-wait queue Remove unused, private modem-status wait queue from driver. If TIOCMIWAIT is ever implemented it must not rely on a private wait queue which may have been released when woken up. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 8eeefe3af0b6..1ccf9e4e82c2 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -55,7 +55,6 @@ static void read_rxcmd_callback(struct urb *urb); struct iuu_private { spinlock_t lock; /* store irq state */ - wait_queue_head_t delta_msr_wait; u8 line_status; int tiostatus; /* store IUART SIGNAL for tiocmget call */ u8 reset; /* if 1 reset is needed */ @@ -94,7 +93,6 @@ static int iuu_port_probe(struct usb_serial_port *port) priv->vcc = vcc_default; spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); usb_set_serial_port_data(port, priv); -- cgit v1.2.3 From 468c740ee5372b74e9d9bd4d7ec2d81d44e67f2d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:12 +0100 Subject: USB: mct_u232: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 06d5a60be2c4..6f4303cef0d8 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -59,8 +59,6 @@ static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int mct_u232_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int mct_u232_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); static void mct_u232_throttle(struct tty_struct *tty); static void mct_u232_unthrottle(struct tty_struct *tty); @@ -99,7 +97,7 @@ static struct usb_serial_driver mct_u232_device = { .port_probe = mct_u232_port_probe, .port_remove = mct_u232_port_remove, .ioctl = mct_u232_ioctl, - .get_icount = mct_u232_get_icount, + .get_icount = usb_serial_generic_get_icount, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -113,7 +111,6 @@ struct mct_u232_private { unsigned char last_lsr; /* Line Status Register */ unsigned char last_msr; /* Modem Status Register */ unsigned int rx_flags; /* Throttling flags */ - struct async_icount icount; }; #define THROTTLED 0x01 @@ -570,7 +567,7 @@ static void mct_u232_read_int_callback(struct urb *urb) /* Record Control Line states */ mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr); - mct_u232_msr_to_icount(&priv->icount, priv->last_msr); + mct_u232_msr_to_icount(&port->icount, priv->last_msr); #if 0 /* Not yet handled. See belkin_sa.c for further information */ @@ -804,7 +801,7 @@ static int mct_u232_ioctl(struct tty_struct *tty, dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__); spin_lock_irqsave(&mct_u232_port->lock, flags); - cprev = mct_u232_port->icount; + cprev = port->icount; spin_unlock_irqrestore(&mct_u232_port->lock, flags); for ( ; ; ) { prepare_to_wait(&port->delta_msr_wait, @@ -819,7 +816,7 @@ static int mct_u232_ioctl(struct tty_struct *tty, return -EIO; spin_lock_irqsave(&mct_u232_port->lock, flags); - cnow = mct_u232_port->icount; + cnow = port->icount; spin_unlock_irqrestore(&mct_u232_port->lock, flags); if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) @@ -837,35 +834,6 @@ static int mct_u232_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } -static int mct_u232_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); - struct async_icount *ic = &mct_u232_port->icount; - unsigned long flags; - - spin_lock_irqsave(&mct_u232_port->lock, flags); - - icount->cts = ic->cts; - icount->dsr = ic->dsr; - icount->rng = ic->rng; - icount->dcd = ic->dcd; - icount->rx = ic->rx; - icount->tx = ic->tx; - icount->frame = ic->frame; - icount->overrun = ic->overrun; - icount->parity = ic->parity; - icount->brk = ic->brk; - icount->buf_overrun = ic->buf_overrun; - - spin_unlock_irqrestore(&mct_u232_port->lock, flags); - - dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", - __func__, icount->rx, icount->tx); - return 0; -} - module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); -- cgit v1.2.3 From 128434ab5607c6bccf385765e94382cedd3d06fa Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:13 +0100 Subject: USB: mct_u232: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 58 ++----------------------------------------- 1 file changed, 2 insertions(+), 56 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 6f4303cef0d8..3353c9ed7721 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -35,7 +35,6 @@ #include #include #include -#include #include "mct_u232.h" #define DRIVER_AUTHOR "Wolfgang Grandegger " @@ -57,8 +56,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); static int mct_u232_tiocmget(struct tty_struct *tty); static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int mct_u232_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg); static void mct_u232_throttle(struct tty_struct *tty); static void mct_u232_unthrottle(struct tty_struct *tty); @@ -93,10 +90,10 @@ static struct usb_serial_driver mct_u232_device = { .break_ctl = mct_u232_break_ctl, .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .attach = mct_u232_startup, .port_probe = mct_u232_port_probe, .port_remove = mct_u232_port_remove, - .ioctl = mct_u232_ioctl, .get_icount = usb_serial_generic_get_icount, }; @@ -595,7 +592,7 @@ static void mct_u232_read_int_callback(struct urb *urb) tty_kref_put(tty); } #endif - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); spin_unlock_irqrestore(&priv->lock, flags); exit: retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -783,57 +780,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty) } } -static int mct_u232_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - DEFINE_WAIT(wait); - struct usb_serial_port *port = tty->driver_data; - struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); - struct async_icount cnow, cprev; - unsigned long flags; - - dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); - - switch (cmd) { - - case TIOCMIWAIT: - - dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__); - - spin_lock_irqsave(&mct_u232_port->lock, flags); - cprev = port->icount; - spin_unlock_irqrestore(&mct_u232_port->lock, flags); - for ( ; ; ) { - prepare_to_wait(&port->delta_msr_wait, - &wait, TASK_INTERRUPTIBLE); - schedule(); - finish_wait(&port->delta_msr_wait, &wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - spin_lock_irqsave(&mct_u232_port->lock, flags); - cnow = port->icount; - spin_unlock_irqrestore(&mct_u232_port->lock, flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - - } - return -ENOIOCTLCMD; -} - module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); -- cgit v1.2.3 From 35711578044076d00d396cb6787d3cc593a4c35a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:14 +0100 Subject: USB: mos7720: remove broken get_icount and TIOCMIWAIT Remove broken get_icount and TIOCMIWAIT support. The driver has an icount structure but it is never been updated which makes get_icount rather pointless and causes TIOCMIWAIT to always return -EIO. Note that the TIOCMIWAIT implementation has always been broken and would not work even if icount support was added as it does not wait for the modem status to change (does not use a work queue at all). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 55 -------------------------------------------- 1 file changed, 55 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index e0ebec3b5d6a..d1e2bf30bff8 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -62,7 +62,6 @@ struct moschip_port { __u8 shadowMCR; /* last MCR value received */ __u8 shadowMSR; /* last MSR value received */ char open; - struct async_icount icount; struct usb_serial_port *port; /* loop back to the owner */ struct urb *write_urb_pool[NUM_URBS]; }; @@ -1075,9 +1074,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) dev_err(&port->dev, "%s - Error %d submitting read urb\n", __func__, response); - /* initialize our icount structure */ - memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); - /* initialize our port settings */ mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */ @@ -1803,33 +1799,6 @@ static int mos7720_tiocmset(struct tty_struct *tty, return 0; } -static int mos7720_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct moschip_port *mos7720_port; - struct async_icount cnow; - - mos7720_port = usb_get_serial_port_data(port); - cnow = mos7720_port->icount; - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, - icount->rx, icount->tx); - return 0; -} - static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, unsigned int __user *value) { @@ -1905,8 +1874,6 @@ static int mos7720_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port; - struct async_icount cnow; - struct async_icount cprev; mos7720_port = usb_get_serial_port_data(port); if (mos7720_port == NULL) @@ -1931,27 +1898,6 @@ static int mos7720_ioctl(struct tty_struct *tty, dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__); return get_serial_info(mos7720_port, (struct serial_struct __user *)arg); - - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); - cprev = mos7720_port->icount; - while (1) { - if (signal_pending(current)) - return -ERESTARTSYS; - cnow = mos7720_port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - break; } return -ENOIOCTLCMD; @@ -2107,7 +2053,6 @@ static struct usb_serial_driver moschip7720_2port_driver = { .ioctl = mos7720_ioctl, .tiocmget = mos7720_tiocmget, .tiocmset = mos7720_tiocmset, - .get_icount = mos7720_get_icount, .set_termios = mos7720_set_termios, .write = mos7720_write, .write_room = mos7720_write_room, -- cgit v1.2.3 From c9fac85345ca8fd7f6519232a4c0024f648647b5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:15 +0100 Subject: USB: mos7840: remove smp barriers from icount handling Remove SMP memory barriers from icount handling and rely on the barriers implied by wait_event, sleep and locks, while using the port lock to guarantee atomicity. This is a step in moving over to the generic icount implementations. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 48 ++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 979ef1999581..7af3d4206523 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -406,22 +406,14 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) icount = &mos7840_port->icount; /* update input line counters */ - if (new_msr & MOS_MSR_DELTA_CTS) { + if (new_msr & MOS_MSR_DELTA_CTS) icount->cts++; - smp_wmb(); - } - if (new_msr & MOS_MSR_DELTA_DSR) { + if (new_msr & MOS_MSR_DELTA_DSR) icount->dsr++; - smp_wmb(); - } - if (new_msr & MOS_MSR_DELTA_CD) { + if (new_msr & MOS_MSR_DELTA_CD) icount->dcd++; - smp_wmb(); - } - if (new_msr & MOS_MSR_DELTA_RI) { + if (new_msr & MOS_MSR_DELTA_RI) icount->rng++; - smp_wmb(); - } mos7840_port->delta_msr_cond = 1; wake_up_interruptible(&port->port->delta_msr_wait); @@ -443,22 +435,14 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) /* update input line counters */ icount = &port->icount; - if (new_lsr & SERIAL_LSR_BI) { + if (new_lsr & SERIAL_LSR_BI) icount->brk++; - smp_wmb(); - } - if (new_lsr & SERIAL_LSR_OE) { + if (new_lsr & SERIAL_LSR_OE) icount->overrun++; - smp_wmb(); - } - if (new_lsr & SERIAL_LSR_PE) { + if (new_lsr & SERIAL_LSR_PE) icount->parity++; - smp_wmb(); - } - if (new_lsr & SERIAL_LSR_FE) { + if (new_lsr & SERIAL_LSR_FE) icount->frame++; - smp_wmb(); - } } /************************************************************************/ @@ -778,7 +762,6 @@ static void mos7840_bulk_in_callback(struct urb *urb) tty_insert_flip_string(tport, data, urb->actual_length); tty_flip_buffer_push(tport); mos7840_port->icount.rx += urb->actual_length; - smp_wmb(); dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); } @@ -1507,7 +1490,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, } bytes_sent = transfer_size; mos7840_port->icount.tx += transfer_size; - smp_wmb(); dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); exit: return bytes_sent; @@ -2133,11 +2115,14 @@ static int mos7840_get_icount(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7840_port; struct async_icount cnow; + unsigned long flags; mos7840_port = mos7840_get_port_private(port); + + spin_lock_irqsave(&port->lock, flags); cnow = mos7840_port->icount; + spin_unlock_irqrestore(&port->lock, flags); - smp_rmb(); icount->cts = cnow.cts; icount->dsr = cnow.dsr; icount->rng = cnow.rng; @@ -2166,7 +2151,7 @@ static int mos7840_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; void __user *argp = (void __user *)arg; struct moschip_port *mos7840_port; - + unsigned long flags; struct async_icount cnow; struct async_icount cprev; @@ -2197,7 +2182,9 @@ static int mos7840_ioctl(struct tty_struct *tty, case TIOCMIWAIT: dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); + spin_lock_irqsave(&port->lock, flags); cprev = mos7840_port->icount; + spin_unlock_irqrestore(&port->lock, flags); while (1) { /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ mos7840_port->delta_msr_cond = 0; @@ -2213,11 +2200,14 @@ static int mos7840_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; + spin_lock_irqsave(&port->lock, flags); cnow = mos7840_port->icount; - smp_rmb(); + spin_unlock_irqrestore(&port->lock, flags); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || -- cgit v1.2.3 From 8c1a07ff7f28549881db0885074feb3e02b07ddb Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:16 +0100 Subject: USB: mos7840: switch to generic get_icount implementation Switch to the generic get_icount implementation. Note that the interrupt counters will no longer be reset at open which is in accordance with which how the other drivers work. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 56 +++++++------------------------------------- 1 file changed, 9 insertions(+), 47 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 7af3d4206523..92feae6e8851 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -220,7 +220,6 @@ struct moschip_port { char open_ports; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ int delta_msr_cond; - struct async_icount icount; struct usb_serial_port *port; /* loop back to the owner of this object */ /* Offsets */ @@ -399,11 +398,10 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) struct moschip_port *mos7840_port; struct async_icount *icount; mos7840_port = port; - icount = &mos7840_port->icount; if (new_msr & (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI | MOS_MSR_DELTA_CD)) { - icount = &mos7840_port->icount; + icount = &mos7840_port->port->icount; /* update input line counters */ if (new_msr & MOS_MSR_DELTA_CTS) @@ -434,7 +432,7 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) } /* update input line counters */ - icount = &port->icount; + icount = &port->port->icount; if (new_lsr & SERIAL_LSR_BI) icount->brk++; if (new_lsr & SERIAL_LSR_OE) @@ -761,8 +759,8 @@ static void mos7840_bulk_in_callback(struct urb *urb) struct tty_port *tport = &mos7840_port->port->port; tty_insert_flip_string(tport, data, urb->actual_length); tty_flip_buffer_push(tport); - mos7840_port->icount.rx += urb->actual_length; - dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); + port->icount.rx += urb->actual_length; + dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx); } if (!mos7840_port->read_urb) { @@ -1113,17 +1111,12 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) /* initialize our wait queues */ init_waitqueue_head(&mos7840_port->wait_chase); - /* initialize our icount structure */ - memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); - /* initialize our port settings */ /* Must set to enable ints! */ mos7840_port->shadowMCR = MCR_MASTER_IE; /* send a open port command */ mos7840_port->open = 1; /* mos7840_change_port_settings(mos7840_port,old_termios); */ - mos7840_port->icount.tx = 0; - mos7840_port->icount.rx = 0; return 0; } @@ -1489,8 +1482,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, goto exit; } bytes_sent = transfer_size; - mos7840_port->icount.tx += transfer_size; - dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); + port->icount.tx += transfer_size; + dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx); exit: return bytes_sent; @@ -2109,37 +2102,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port, return 0; } -static int mos7840_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct moschip_port *mos7840_port; - struct async_icount cnow; - unsigned long flags; - - mos7840_port = mos7840_get_port_private(port); - - spin_lock_irqsave(&port->lock, flags); - cnow = mos7840_port->icount; - spin_unlock_irqrestore(&port->lock, flags); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, - icount->rx, icount->tx); - return 0; -} - /***************************************************************************** * SerialIoctl * this function handles any ioctl calls to the driver @@ -2183,7 +2145,7 @@ static int mos7840_ioctl(struct tty_struct *tty, case TIOCMIWAIT: dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); spin_lock_irqsave(&port->lock, flags); - cprev = mos7840_port->icount; + cprev = port->icount; spin_unlock_irqrestore(&port->lock, flags); while (1) { /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ @@ -2201,7 +2163,7 @@ static int mos7840_ioctl(struct tty_struct *tty, return -EIO; spin_lock_irqsave(&port->lock, flags); - cnow = mos7840_port->icount; + cnow = port->icount; spin_unlock_irqrestore(&port->lock, flags); if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && @@ -2565,7 +2527,7 @@ static struct usb_serial_driver moschip7840_4port_device = { .break_ctl = mos7840_break, .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, - .get_icount = mos7840_get_icount, + .get_icount = usb_serial_generic_get_icount, .port_probe = mos7840_port_probe, .port_remove = mos7840_port_remove, .read_bulk_callback = mos7840_bulk_in_callback, -- cgit v1.2.3 From 0c61337138763cb24901f394306715019f3272a6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:17 +0100 Subject: USB: mos7840: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 48 ++------------------------------------------ 1 file changed, 2 insertions(+), 46 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 92feae6e8851..f0b4e5c01e13 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -219,7 +219,6 @@ struct moschip_port { char open; char open_ports; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ - int delta_msr_cond; struct usb_serial_port *port; /* loop back to the owner of this object */ /* Offsets */ @@ -413,8 +412,7 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) if (new_msr & MOS_MSR_DELTA_RI) icount->rng++; - mos7840_port->delta_msr_cond = 1; - wake_up_interruptible(&port->port->delta_msr_wait); + wake_up_interruptible(&port->port->port.delta_msr_wait); } } @@ -2113,9 +2111,6 @@ static int mos7840_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; void __user *argp = (void __user *)arg; struct moschip_port *mos7840_port; - unsigned long flags; - struct async_icount cnow; - struct async_icount cprev; if (mos7840_port_paranoia_check(port, __func__)) return -1; @@ -2141,46 +2136,6 @@ static int mos7840_ioctl(struct tty_struct *tty, case TIOCSSERIAL: dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__); break; - - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); - spin_lock_irqsave(&port->lock, flags); - cprev = port->icount; - spin_unlock_irqrestore(&port->lock, flags); - while (1) { - /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ - mos7840_port->delta_msr_cond = 0; - wait_event_interruptible(port->delta_msr_wait, - (port->serial->disconnected || - mos7840_port-> - delta_msr_cond == 1)); - - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - spin_lock_irqsave(&port->lock, flags); - cnow = port->icount; - spin_unlock_irqrestore(&port->lock, flags); - - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - break; - default: break; } @@ -2527,6 +2482,7 @@ static struct usb_serial_driver moschip7840_4port_device = { .break_ctl = mos7840_break, .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .port_probe = mos7840_port_probe, .port_remove = mos7840_port_remove, -- cgit v1.2.3 From 1c9f995363d4a80de72da15af3d66a3dc2f56952 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:18 +0100 Subject: USB: oti6858: replace custom ioctl operation with tiocmiwait Replace custom ioctl operation with tiocmiwait. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/oti6858.c | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 87c71ccfee87..fd5dcb878fa5 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -124,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port); static void oti6858_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static void oti6858_init_termios(struct tty_struct *tty); -static int oti6858_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg); static void oti6858_read_int_callback(struct urb *urb); static void oti6858_read_bulk_callback(struct urb *urb); static void oti6858_write_bulk_callback(struct urb *urb); @@ -136,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); +static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg); static int oti6858_port_probe(struct usb_serial_port *port); static int oti6858_port_remove(struct usb_serial_port *port); @@ -150,11 +149,11 @@ static struct usb_serial_driver oti6858_device = { .open = oti6858_open, .close = oti6858_close, .write = oti6858_write, - .ioctl = oti6858_ioctl, .set_termios = oti6858_set_termios, .init_termios = oti6858_init_termios, .tiocmget = oti6858_tiocmget, .tiocmset = oti6858_tiocmset, + .tiocmiwait = oti6858_tiocmiwait, .read_bulk_callback = oti6858_read_bulk_callback, .read_int_callback = oti6858_read_int_callback, .write_bulk_callback = oti6858_write_bulk_callback, @@ -650,8 +649,9 @@ static int oti6858_tiocmget(struct tty_struct *tty) return result; } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct oti6858_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int prev, status; @@ -689,24 +689,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return 0; } -static int oti6858_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = tty->driver_data; - - dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg); - - switch (cmd) { - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__); - return wait_modem_info(port, arg); - default: - dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd); - break; - } - return -ENOIOCTLCMD; -} - static void oti6858_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; -- cgit v1.2.3 From 215f6f04668e80543995300c9528ac0143fcda7f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:19 +0100 Subject: USB: oti6858: fix TIOCMIWAIT and disconnect Use tty-port modem-status-change wait queue on which processes are woken up at hangup and disconnect. Currently a process waiting on modem-status changes will not be woken on device disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/oti6858.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index fd5dcb878fa5..7e3e0782e51f 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -662,7 +662,7 @@ static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg) spin_unlock_irqrestore(&priv->lock, flags); while (1) { - wait_event_interruptible(port->delta_msr_wait, + wait_event_interruptible(port->port.delta_msr_wait, port->serial->disconnected || priv->status.pin_state != prev); if (signal_pending(current)) @@ -747,7 +747,7 @@ static void oti6858_read_int_callback(struct urb *urb) if (!priv->transient) { if (xs->pin_state != priv->status.pin_state) - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE); } -- cgit v1.2.3 From 824d11bef5540062d17380c65ee52d4b2948ca84 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:20 +0100 Subject: USB: pl2303: add custom tiocmiwait operation Break out TIOCMIWAIT handling from custom ioctl operation and use tiocmiwait operation field instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index e7e407b67994..1f7fd1aaa2f5 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -593,8 +593,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port) return 0; } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg) { + struct usb_serial_port *port = tty->driver_data; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int prevstatus; @@ -652,10 +653,6 @@ static int pl2303_ioctl(struct tty_struct *tty, return -EFAULT; return 0; - - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); - return wait_modem_info(port, arg); default: dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); break; @@ -836,6 +833,7 @@ static struct usb_serial_driver pl2303_device = { .set_termios = pl2303_set_termios, .tiocmget = pl2303_tiocmget, .tiocmset = pl2303_tiocmset, + .tiocmiwait = pl2303_tiocmiwait, .process_read_urb = pl2303_process_read_urb, .read_int_callback = pl2303_read_int_callback, .attach = pl2303_startup, -- cgit v1.2.3 From 6d0cad657a133818038683120fff9c5c5f8dc751 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:21 +0100 Subject: USB: pl2303: fix TIOCMIWAIT and disconnect Use tty-port modem-status-change wait queue on which processes are woken up at hangup and disconnect. Currently a process waiting on modem-status changes will not be woken on device disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1f7fd1aaa2f5..997eba4dcbeb 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -607,7 +607,7 @@ static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg) spin_unlock_irqrestore(&priv->lock, flags); while (1) { - interruptible_sleep_on(&port->delta_msr_wait); + interruptible_sleep_on(&port->port.delta_msr_wait); /* see if a signal did it */ if (signal_pending(current)) return -ERESTARTSYS; @@ -718,7 +718,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port, spin_unlock_irqrestore(&priv->lock, flags); if (priv->line_status & UART_BREAK_ERROR) usb_serial_handle_break(port); - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); tty = tty_port_tty_get(&port->port); if (!tty) @@ -782,7 +782,7 @@ static void pl2303_process_read_urb(struct urb *urb) line_status = priv->line_status; priv->line_status &= ~UART_STATE_TRANSIENT_MASK; spin_unlock_irqrestore(&priv->lock, flags); - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); if (!urb->actual_length) return; -- cgit v1.2.3 From 0a4142fb9ceddb7e8c48570431038a91bbee7c7c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:22 +0100 Subject: USB: quatech2: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 51 ++++++++++--------------------------------- 1 file changed, 12 insertions(+), 39 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 80a8bc30a871..3506a2c5e4e9 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -128,8 +128,6 @@ struct qt2_port_private { u8 shadowLSR; u8 shadowMSR; - struct async_icount icount; - struct usb_serial_port *port; }; @@ -501,16 +499,16 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - prev = priv->icount; + prev = port->icount; spin_unlock_irqrestore(&priv->lock, flags); while (1) { wait_event_interruptible(port->delta_msr_wait, (port->serial->disconnected || - (priv->icount.rng != prev.rng) || - (priv->icount.dsr != prev.dsr) || - (priv->icount.dcd != prev.dcd) || - (priv->icount.cts != prev.cts))); + (port->icount.rng != prev.rng) || + (port->icount.dsr != prev.dsr) || + (port->icount.dcd != prev.dcd) || + (port->icount.cts != prev.cts))); if (signal_pending(current)) return -ERESTARTSYS; @@ -519,7 +517,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return -EIO; spin_lock_irqsave(&priv->lock, flags); - cur = priv->icount; + cur = port->icount; spin_unlock_irqrestore(&priv->lock, flags); if ((prev.rng == cur.rng) && @@ -537,28 +535,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return 0; } -static int qt2_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct qt2_port_private *priv = usb_get_serial_port_data(port); - struct async_icount cnow = priv->icount; - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - static int qt2_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -958,16 +934,13 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch) if (newMSR & UART_MSR_ANY_DELTA) { /* update input line counters */ if (newMSR & UART_MSR_DCTS) - port_priv->icount.cts++; - + port->icount.cts++; if (newMSR & UART_MSR_DDSR) - port_priv->icount.dsr++; - + port->icount.dsr++; if (newMSR & UART_MSR_DDCD) - port_priv->icount.dcd++; - + port->icount.dcd++; if (newMSR & UART_MSR_TERI) - port_priv->icount.rng++; + port->icount.rng++; wake_up_interruptible(&port->delta_msr_wait); } @@ -989,7 +962,7 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch) port_priv->shadowLSR = newLSR; spin_unlock_irqrestore(&port_priv->lock, flags); - icount = &port_priv->icount; + icount = &port->icount; if (newLSR & UART_LSR_BRK_ERROR_BITS) { @@ -1099,7 +1072,7 @@ static struct usb_serial_driver qt2_device = { .break_ctl = qt2_break_ctl, .tiocmget = qt2_tiocmget, .tiocmset = qt2_tiocmset, - .get_icount = qt2_get_icount, + .get_icount = usb_serial_generic_get_icount, .ioctl = qt2_ioctl, .set_termios = qt2_set_termios, }; -- cgit v1.2.3 From b59597047ace8531ce9d469e1de0d85792e8cef1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:23 +0100 Subject: USB: quatech2: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 50 ++----------------------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 3506a2c5e4e9..085cad471c41 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -492,49 +492,6 @@ static int get_serial_info(struct usb_serial_port *port, return 0; } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) -{ - struct qt2_port_private *priv = usb_get_serial_port_data(port); - struct async_icount prev, cur; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - prev = port->icount; - spin_unlock_irqrestore(&priv->lock, flags); - - while (1) { - wait_event_interruptible(port->delta_msr_wait, - (port->serial->disconnected || - (port->icount.rng != prev.rng) || - (port->icount.dsr != prev.dsr) || - (port->icount.dcd != prev.dcd) || - (port->icount.cts != prev.cts))); - - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - spin_lock_irqsave(&priv->lock, flags); - cur = port->icount; - spin_unlock_irqrestore(&priv->lock, flags); - - if ((prev.rng == cur.rng) && - (prev.dsr == cur.dsr) && - (prev.dcd == cur.dcd) && - (prev.cts == cur.cts)) - return -EIO; - - if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || - (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || - (arg & TIOCM_CD && (prev.dcd != cur.dcd)) || - (arg & TIOCM_CTS && (prev.cts != cur.cts))) - return 0; - } - return 0; -} - static int qt2_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -544,10 +501,6 @@ static int qt2_ioctl(struct tty_struct *tty, case TIOCGSERIAL: return get_serial_info(port, (struct serial_struct __user *)arg); - - case TIOCMIWAIT: - return wait_modem_info(port, arg); - default: break; } @@ -942,7 +895,7 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch) if (newMSR & UART_MSR_TERI) port->icount.rng++; - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); } } @@ -1072,6 +1025,7 @@ static struct usb_serial_driver qt2_device = { .break_ctl = qt2_break_ctl, .tiocmget = qt2_tiocmget, .tiocmset = qt2_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .ioctl = qt2_ioctl, .set_termios = qt2_set_termios, -- cgit v1.2.3 From f65f9a50ddc6db4deebd01541bea09fb1672ce40 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:24 +0100 Subject: USB: spcp8x5: remove broken TIOCMIWAIT support Remove broken TIOCMIWAIT support. This drivers appears to implement TIOCMIWAIT but has no means of receiving modem-status interrupts. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 68 -------------------------------------------- 1 file changed, 68 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 549ef68ff5fa..e24d23b524b1 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -472,8 +472,6 @@ static void spcp8x5_process_read_urb(struct urb *urb) status = priv->line_status; priv->line_status &= ~UART_STATE_TRANSIENT_MASK; spin_unlock_irqrestore(&priv->lock, flags); - /* wake up the wait for termios */ - wake_up_interruptible(&port->delta_msr_wait); if (!urb->actual_length) return; @@ -509,71 +507,6 @@ static void spcp8x5_process_read_urb(struct urb *urb) tty_flip_buffer_push(&port->port); } -static int spcp8x5_wait_modem_info(struct usb_serial_port *port, - unsigned int arg) -{ - struct spcp8x5_private *priv = usb_get_serial_port_data(port); - unsigned long flags; - unsigned int prevstatus; - unsigned int status; - unsigned int changed; - - spin_lock_irqsave(&priv->lock, flags); - prevstatus = priv->line_status; - spin_unlock_irqrestore(&priv->lock, flags); - - while (1) { - /* wake up in bulk read */ - interruptible_sleep_on(&port->delta_msr_wait); - - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - spin_lock_irqsave(&priv->lock, flags); - status = priv->line_status; - spin_unlock_irqrestore(&priv->lock, flags); - - changed = prevstatus^status; - - if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) || - ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) || - ((arg & TIOCM_CD) && (changed & MSR_STATUS_LINE_DCD)) || - ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS))) - return 0; - - prevstatus = status; - } - /* NOTREACHED */ - return 0; -} - -static int spcp8x5_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = tty->driver_data; - - dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, - port->number, cmd); - - switch (cmd) { - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, - port->number); - return spcp8x5_wait_modem_info(port, arg); - - default: - dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__, - cmd); - break; - } - - return -ENOIOCTLCMD; -} - static int spcp8x5_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { @@ -634,7 +567,6 @@ static struct usb_serial_driver spcp8x5_device = { .carrier_raised = spcp8x5_carrier_raised, .set_termios = spcp8x5_set_termios, .init_termios = spcp8x5_init_termios, - .ioctl = spcp8x5_ioctl, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, .port_probe = spcp8x5_port_probe, -- cgit v1.2.3 From 23bd364dcf90de36f470e5a29f1684e128b53f38 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:25 +0100 Subject: USB: spcp8x5: remove broken uart-error handling Remove broken uart-error handling. This driver appears to implement uart-error handling but does not receive status interrupts or status information with bulk in transfers. Instead status was retrieved at open and used to flag only the first bulk in transfer. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 52 -------------------------------------------- 1 file changed, 52 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index e24d23b524b1..f34930cda68d 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -456,57 +456,6 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) return usb_serial_generic_open(tty, port); } -static void spcp8x5_process_read_urb(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct spcp8x5_private *priv = usb_get_serial_port_data(port); - unsigned char *data = urb->transfer_buffer; - unsigned long flags; - u8 status; - char tty_flag; - - /* get tty_flag from status */ - tty_flag = TTY_NORMAL; - - spin_lock_irqsave(&priv->lock, flags); - status = priv->line_status; - priv->line_status &= ~UART_STATE_TRANSIENT_MASK; - spin_unlock_irqrestore(&priv->lock, flags); - - if (!urb->actual_length) - return; - - - if (status & UART_STATE_TRANSIENT_MASK) { - /* break takes precedence over parity, which takes precedence - * over framing errors */ - if (status & UART_BREAK_ERROR) - tty_flag = TTY_BREAK; - else if (status & UART_PARITY_ERROR) - tty_flag = TTY_PARITY; - else if (status & UART_FRAME_ERROR) - tty_flag = TTY_FRAME; - dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); - - /* overrun is special, not associated with a char */ - if (status & UART_OVERRUN_ERROR) - tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); - - if (status & UART_DCD) { - struct tty_struct *tty = tty_port_tty_get(&port->port); - if (tty) { - usb_serial_handle_dcd_change(port, tty, - priv->line_status & MSR_STATUS_LINE_DCD); - tty_kref_put(tty); - } - } - } - - tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag, - urb->actual_length); - tty_flip_buffer_push(&port->port); -} - static int spcp8x5_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { @@ -571,7 +520,6 @@ static struct usb_serial_driver spcp8x5_device = { .tiocmset = spcp8x5_tiocmset, .port_probe = spcp8x5_port_probe, .port_remove = spcp8x5_port_remove, - .process_read_urb = spcp8x5_process_read_urb, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3 From 2d816ac6f5e0a0dc03be752c1599ed9588b403d2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:26 +0100 Subject: USB: spcp8x5: clean up code Clean up this driver somewhat. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 72 +++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 35 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index f34930cda68d..a5c3a3684dc2 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -13,8 +13,6 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * - * */ #include #include @@ -28,7 +26,7 @@ #include #include -#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" +#define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" #define SPCP8x5_007_VID 0x04FC #define SPCP8x5_007_PID 0x0201 @@ -52,7 +50,7 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); struct spcp8x5_usb_ctrl_arg { - u8 type; + u8 type; u8 cmd; u8 cmd_type; u16 value; @@ -147,10 +145,10 @@ enum spcp8x5_type { }; struct spcp8x5_private { - spinlock_t lock; + spinlock_t lock; enum spcp8x5_type type; - u8 line_control; - u8 line_status; + u8 line_control; + u8 line_status; }; static int spcp8x5_port_probe(struct usb_serial_port *port) @@ -180,7 +178,7 @@ static int spcp8x5_port_probe(struct usb_serial_port *port) spin_lock_init(&priv->lock); priv->type = type; - usb_set_serial_port_data(port , priv); + usb_set_serial_port_data(port, priv); return 0; } @@ -195,13 +193,16 @@ static int spcp8x5_port_remove(struct usb_serial_port *port) return 0; } -/* set the modem control line of the device. - * NOTE spcp825-007 not supported this */ -static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value, +/* + * Set the modem control line of the device. + * + * NOTE: not supported by spcp825-007 + */ +static int spcp8x5_set_ctrl_line(struct usb_device *dev, u8 value, enum spcp8x5_type type) { int retval; - u8 mcr = 0 ; + u8 mcr = 0; if (type == SPCP825_007_TYPE) return -EPERM; @@ -215,8 +216,11 @@ static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value, return retval; } -/* get the modem status register of the device - * NOTE spcp825-007 not supported this */ +/* + * Get the modem status register of the device. + * + * NOTE: not supported by spcp825-007 + */ static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, enum spcp8x5_type type) { @@ -249,9 +253,12 @@ static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, return ret; } -/* select the work mode. - * NOTE this function not supported by spcp825-007 */ -static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, +/* + * Select the work mode. + * + * NOTE: not supported by spcp825-007 + */ +static void spcp8x5_set_work_mode(struct usb_device *dev, u16 value, u16 index, enum spcp8x5_type type) { int ret; @@ -273,8 +280,10 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, static int spcp8x5_carrier_raised(struct usb_serial_port *port) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); + if (priv->line_status & MSR_STATUS_LINE_DCD) return 1; + return 0; } @@ -293,20 +302,17 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) | MCR_CONTROL_LINE_RTS); control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); + spcp8x5_set_ctrl_line(port->serial->dev, control, priv->type); } static void spcp8x5_init_termios(struct tty_struct *tty) { - /* for the 1st time call this function */ tty->termios = tty_std_termios; tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; tty->termios.c_ispeed = 115200; tty->termios.c_ospeed = 115200; } -/* set the serial param for transfer. we should check if we really need to - * transfer. if we set flow control we should do this too. */ static void spcp8x5_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { @@ -321,7 +327,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty, int i; u8 control; - /* check that they really want us to change something */ if (!tty_termios_hw_change(&tty->termios, old_termios)) return; @@ -337,7 +342,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - spcp8x5_set_ctrlLine(serial->dev, control , priv->type); + spcp8x5_set_ctrl_line(serial->dev, control , priv->type); } else { spin_unlock_irqrestore(&priv->lock, flags); } @@ -397,9 +402,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty, if (cflag & PARENB) { buf[1] |= (cflag & PARODD) ? SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ; - } else + } else { buf[1] |= SET_UART_FORMAT_PAR_NONE; - + } uartdata = buf[0] | buf[1]<<8; i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -412,13 +417,11 @@ static void spcp8x5_set_termios(struct tty_struct *tty, if (cflag & CRTSCTS) { /* enable hardware flow control */ - spcp8x5_set_workMode(serial->dev, 0x000a, + spcp8x5_set_work_mode(serial->dev, 0x000a, SET_WORKING_MODE_U2C, priv->type); } } -/* open the serial port. do some usb system call. set termios and get the line - * status of the device. */ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; @@ -438,7 +441,7 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) if (ret) return ret; - spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); + spcp8x5_set_ctrl_line(serial->dev, priv->line_control, priv->type); /* Setup termios */ if (tty) @@ -476,7 +479,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty, control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); + return spcp8x5_set_ctrl_line(port->serial->dev, control, priv->type); } static int spcp8x5_tiocmget(struct tty_struct *tty) @@ -503,7 +506,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty) return result; } -/* All of the device info needed for the spcp8x5 SIO serial converter */ static struct usb_serial_driver spcp8x5_device = { .driver = { .owner = THIS_MODULE, @@ -511,13 +513,13 @@ static struct usb_serial_driver spcp8x5_device = { }, .id_table = id_table, .num_ports = 1, - .open = spcp8x5_open, + .open = spcp8x5_open, .dtr_rts = spcp8x5_dtr_rts, .carrier_raised = spcp8x5_carrier_raised, - .set_termios = spcp8x5_set_termios, + .set_termios = spcp8x5_set_termios, .init_termios = spcp8x5_init_termios, - .tiocmget = spcp8x5_tiocmget, - .tiocmset = spcp8x5_tiocmset, + .tiocmget = spcp8x5_tiocmget, + .tiocmset = spcp8x5_tiocmset, .port_probe = spcp8x5_port_probe, .port_remove = spcp8x5_port_remove, }; -- cgit v1.2.3 From 8413d2fd80a8e1f09a37c371610a89618980b08f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:27 +0100 Subject: USB: spcp8x5: pass usb-serial port to control functions Pass usb-serial port to the control functions for uart status and work mode. Use port device for debugging and use dev_err to report errors. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 54 +++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index a5c3a3684dc2..5779dd819d31 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -198,21 +198,22 @@ static int spcp8x5_port_remove(struct usb_serial_port *port) * * NOTE: not supported by spcp825-007 */ -static int spcp8x5_set_ctrl_line(struct usb_device *dev, u8 value, - enum spcp8x5_type type) +static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr) { + struct spcp8x5_private *priv = usb_get_serial_port_data(port); + struct usb_device *dev = port->serial->dev; int retval; - u8 mcr = 0; - if (type == SPCP825_007_TYPE) + if (priv->type == SPCP825_007_TYPE) return -EPERM; - mcr = (unsigned short)value; retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_UART_STATUS_TYPE, SET_UART_STATUS, mcr, 0x04, NULL, 0, 100); - if (retval != 0) - dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval); + if (retval != 0) { + dev_err(&port->dev, "failed to set control lines: %d\n", + retval); + } return retval; } @@ -221,15 +222,16 @@ static int spcp8x5_set_ctrl_line(struct usb_device *dev, u8 value, * * NOTE: not supported by spcp825-007 */ -static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, - enum spcp8x5_type type) +static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) { + struct spcp8x5_private *priv = usb_get_serial_port_data(port); + struct usb_device *dev = port->serial->dev; u8 *status_buffer; int ret; /* I return Permited not support here but seem inval device * is more fix */ - if (type == SPCP825_007_TYPE) + if (priv->type == SPCP825_007_TYPE) return -EPERM; if (status == NULL) return -EINVAL; @@ -243,10 +245,10 @@ static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, GET_UART_STATUS, GET_UART_STATUS_TYPE, 0, GET_UART_STATUS_MSR, status_buffer, 1, 100); if (ret < 0) - dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)", - status_buffer, ret); + dev_err(&port->dev, "failed to get modem status: %d", ret); + + dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x", ret, *status_buffer); - dev_dbg(&dev->dev, "0xc0:0x22:0:6 %d - 0x%p ", ret, status_buffer); status[0] = status_buffer[0]; kfree(status_buffer); @@ -258,23 +260,24 @@ static int spcp8x5_get_msr(struct usb_device *dev, u8 *status, * * NOTE: not supported by spcp825-007 */ -static void spcp8x5_set_work_mode(struct usb_device *dev, u16 value, - u16 index, enum spcp8x5_type type) +static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, + u16 index) { + struct spcp8x5_private *priv = usb_get_serial_port_data(port); + struct usb_device *dev = port->serial->dev; int ret; /* I return Permited not support here but seem inval device * is more fix */ - if (type == SPCP825_007_TYPE) + if (priv->type == SPCP825_007_TYPE) return; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_WORKING_MODE_TYPE, SET_WORKING_MODE, value, index, NULL, 0, 100); - dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index); + dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index); if (ret < 0) - dev_dbg(&dev->dev, - "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); + dev_err(&port->dev, "failed to set work mode: %d\n", ret); } static int spcp8x5_carrier_raised(struct usb_serial_port *port) @@ -302,7 +305,7 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) | MCR_CONTROL_LINE_RTS); control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - spcp8x5_set_ctrl_line(port->serial->dev, control, priv->type); + spcp8x5_set_ctrl_line(port, control); } static void spcp8x5_init_termios(struct tty_struct *tty) @@ -342,7 +345,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, if (control != priv->line_control) { control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - spcp8x5_set_ctrl_line(serial->dev, control , priv->type); + spcp8x5_set_ctrl_line(port, control); } else { spin_unlock_irqrestore(&priv->lock, flags); } @@ -417,8 +420,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, if (cflag & CRTSCTS) { /* enable hardware flow control */ - spcp8x5_set_work_mode(serial->dev, 0x000a, - SET_WORKING_MODE_U2C, priv->type); + spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C); } } @@ -441,13 +443,13 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) if (ret) return ret; - spcp8x5_set_ctrl_line(serial->dev, priv->line_control, priv->type); + spcp8x5_set_ctrl_line(port, priv->line_control); /* Setup termios */ if (tty) spcp8x5_set_termios(tty, port, &tmp_termios); - spcp8x5_get_msr(serial->dev, &status, priv->type); + spcp8x5_get_msr(port, &status); /* may be we should update uart status here but now we did not do */ spin_lock_irqsave(&priv->lock, flags); @@ -479,7 +481,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty, control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - return spcp8x5_set_ctrl_line(port->serial->dev, control, priv->type); + return spcp8x5_set_ctrl_line(port, control); } static int spcp8x5_tiocmget(struct tty_struct *tty) -- cgit v1.2.3 From 0a967f62e6623a2a7bb3a5707352b6667c0c649e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:28 +0100 Subject: USB: spcp8x5: clean up modem status retrieval Clean up modem status retrieval. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 5779dd819d31..e0093dd22238 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -226,31 +226,27 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); struct usb_device *dev = port->serial->dev; - u8 *status_buffer; + u8 *buf; int ret; /* I return Permited not support here but seem inval device * is more fix */ if (priv->type == SPCP825_007_TYPE) return -EPERM; - if (status == NULL) - return -EINVAL; - status_buffer = kmalloc(1, GFP_KERNEL); - if (!status_buffer) + buf = kzalloc(1, GFP_KERNEL); + if (!buf) return -ENOMEM; - status_buffer[0] = status[0]; ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_UART_STATUS, GET_UART_STATUS_TYPE, - 0, GET_UART_STATUS_MSR, status_buffer, 1, 100); + 0, GET_UART_STATUS_MSR, buf, 1, 100); if (ret < 0) dev_err(&port->dev, "failed to get modem status: %d", ret); - dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x", ret, *status_buffer); - - status[0] = status_buffer[0]; - kfree(status_buffer); + dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x", ret, *buf); + *status = *buf; + kfree(buf); return ret; } -- cgit v1.2.3 From 4d63143db1426342f186cfe258db73571bf57897 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:29 +0100 Subject: USB: spcp8x5: reimplement device type detection Reimplement device type detection using the device id table and quirks. Device type was used to detect one device type which did not support to control functions. Add quirks to the device table and store them in the private port data at probe instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 70 +++++++++++++------------------------------- 1 file changed, 21 insertions(+), 49 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index e0093dd22238..a454a3f1acb3 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -28,6 +28,9 @@ #define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" +#define SPCP825_QUIRK_NO_UART_STATUS 0x01 +#define SPCP825_QUIRK_NO_WORK_MODE 0x02 + #define SPCP8x5_007_VID 0x04FC #define SPCP8x5_007_PID 0x0201 #define SPCP8x5_008_VID 0x04fc @@ -44,7 +47,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)}, { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)}, { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)}, - { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)}, + { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID), + .driver_info = SPCP825_QUIRK_NO_UART_STATUS | + SPCP825_QUIRK_NO_WORK_MODE }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); @@ -136,47 +141,32 @@ struct spcp8x5_usb_ctrl_arg { #define UART_OVERRUN_ERROR 0x40 #define UART_CTS 0x80 -enum spcp8x5_type { - SPCP825_007_TYPE, - SPCP825_008_TYPE, - SPCP825_PHILIP_TYPE, - SPCP825_INTERMATIC_TYPE, - SPCP835_TYPE, -}; - struct spcp8x5_private { + unsigned quirks; spinlock_t lock; - enum spcp8x5_type type; u8 line_control; u8 line_status; }; +static int spcp8x5_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + usb_set_serial_data(serial, (void *)id); + + return 0; +} + static int spcp8x5_port_probe(struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; + const struct usb_device_id *id = usb_get_serial_data(port->serial); struct spcp8x5_private *priv; - enum spcp8x5_type type = SPCP825_007_TYPE; - u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); - - if (product == 0x0201) - type = SPCP825_007_TYPE; - else if (product == 0x0231) - type = SPCP835_TYPE; - else if (product == 0x0235) - type = SPCP825_008_TYPE; - else if (product == 0x0204) - type = SPCP825_INTERMATIC_TYPE; - else if (product == 0x0471 && - serial->dev->descriptor.idVendor == cpu_to_le16(0x081e)) - type = SPCP825_PHILIP_TYPE; - dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; spin_lock_init(&priv->lock); - priv->type = type; + priv->quirks = id->driver_info; usb_set_serial_port_data(port, priv); @@ -193,18 +183,13 @@ static int spcp8x5_port_remove(struct usb_serial_port *port) return 0; } -/* - * Set the modem control line of the device. - * - * NOTE: not supported by spcp825-007 - */ static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); struct usb_device *dev = port->serial->dev; int retval; - if (priv->type == SPCP825_007_TYPE) + if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS) return -EPERM; retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -217,11 +202,6 @@ static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr) return retval; } -/* - * Get the modem status register of the device. - * - * NOTE: not supported by spcp825-007 - */ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) { struct spcp8x5_private *priv = usb_get_serial_port_data(port); @@ -229,9 +209,7 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) u8 *buf; int ret; - /* I return Permited not support here but seem inval device - * is more fix */ - if (priv->type == SPCP825_007_TYPE) + if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS) return -EPERM; buf = kzalloc(1, GFP_KERNEL); @@ -251,11 +229,6 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) return ret; } -/* - * Select the work mode. - * - * NOTE: not supported by spcp825-007 - */ static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, u16 index) { @@ -263,9 +236,7 @@ static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, struct usb_device *dev = port->serial->dev; int ret; - /* I return Permited not support here but seem inval device - * is more fix */ - if (priv->type == SPCP825_007_TYPE) + if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE) return; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), @@ -518,6 +489,7 @@ static struct usb_serial_driver spcp8x5_device = { .init_termios = spcp8x5_init_termios, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, + .probe = spcp8x5_probe, .port_probe = spcp8x5_port_probe, .port_remove = spcp8x5_port_remove, }; -- cgit v1.2.3 From e1ed212d8593f8d5036709ae257e0e019dbecd4f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:30 +0100 Subject: USB: spcp8x5: add proper modem-status support Fetch modem status on carrier_raised and tiocmget. This driver appeared to support modem-status but only read the modem status registers once at open and then used that cached value for all further enquires. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/spcp8x5.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index a454a3f1acb3..cf3df793c2b7 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -1,7 +1,7 @@ /* * spcp8x5 USB to serial adaptor driver * - * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com) * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn) * Copyright (C) 2006 S1 Corp. * @@ -145,7 +145,6 @@ struct spcp8x5_private { unsigned quirks; spinlock_t lock; u8 line_control; - u8 line_status; }; static int spcp8x5_probe(struct usb_serial *serial, @@ -249,9 +248,11 @@ static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value, static int spcp8x5_carrier_raised(struct usb_serial_port *port) { - struct spcp8x5_private *priv = usb_get_serial_port_data(port); + u8 msr; + int ret; - if (priv->line_status & MSR_STATUS_LINE_DCD) + ret = spcp8x5_get_msr(port, &msr); + if (ret || msr & MSR_STATUS_LINE_DCD) return 1; return 0; @@ -397,9 +398,6 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct spcp8x5_private *priv = usb_get_serial_port_data(port); int ret; - unsigned long flags; - u8 status = 0x30; - /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */ usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -412,17 +410,9 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) spcp8x5_set_ctrl_line(port, priv->line_control); - /* Setup termios */ if (tty) spcp8x5_set_termios(tty, port, &tmp_termios); - spcp8x5_get_msr(port, &status); - - /* may be we should update uart status here but now we did not do */ - spin_lock_irqsave(&priv->lock, flags); - priv->line_status = status & 0xf0 ; - spin_unlock_irqrestore(&priv->lock, flags); - port->port.drain_delay = 256; return usb_serial_generic_open(tty, port); @@ -457,12 +447,15 @@ static int spcp8x5_tiocmget(struct tty_struct *tty) struct spcp8x5_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int mcr; - unsigned int status; + u8 status; unsigned int result; + result = spcp8x5_get_msr(port, &status); + if (result) + return result; + spin_lock_irqsave(&priv->lock, flags); mcr = priv->line_control; - status = priv->line_status; spin_unlock_irqrestore(&priv->lock, flags); result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) -- cgit v1.2.3 From 31ecdb6befeab20d93b49b8dd640c081b48912d0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:31 +0100 Subject: USB: ssu100: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 55 +++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 40 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 45b8c29060d1..8d94a5a7c4b6 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -61,7 +61,6 @@ struct ssu100_port_private { spinlock_t status_lock; u8 shadowLSR; u8 shadowMSR; - struct async_icount icount; }; static inline int ssu100_control_msg(struct usb_device *dev, @@ -345,16 +344,16 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) unsigned long flags; spin_lock_irqsave(&priv->status_lock, flags); - prev = priv->icount; + prev = port->icount; spin_unlock_irqrestore(&priv->status_lock, flags); while (1) { wait_event_interruptible(port->delta_msr_wait, (port->serial->disconnected || - (priv->icount.rng != prev.rng) || - (priv->icount.dsr != prev.dsr) || - (priv->icount.dcd != prev.dcd) || - (priv->icount.cts != prev.cts))); + (port->icount.rng != prev.rng) || + (port->icount.dsr != prev.dsr) || + (port->icount.dcd != prev.dcd) || + (port->icount.cts != prev.cts))); if (signal_pending(current)) return -ERESTARTSYS; @@ -363,7 +362,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return -EIO; spin_lock_irqsave(&priv->status_lock, flags); - cur = priv->icount; + cur = port->icount; spin_unlock_irqrestore(&priv->status_lock, flags); if ((prev.rng == cur.rng) && @@ -381,30 +380,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) return 0; } -static int ssu100_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct ssu100_port_private *priv = usb_get_serial_port_data(port); - struct async_icount cnow = priv->icount; - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - - - static int ssu100_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -527,13 +502,13 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) if (msr & UART_MSR_ANY_DELTA) { /* update input line counters */ if (msr & UART_MSR_DCTS) - priv->icount.cts++; + port->icount.cts++; if (msr & UART_MSR_DDSR) - priv->icount.dsr++; + port->icount.dsr++; if (msr & UART_MSR_DDCD) - priv->icount.dcd++; + port->icount.dcd++; if (msr & UART_MSR_TERI) - priv->icount.rng++; + port->icount.rng++; wake_up_interruptible(&port->delta_msr_wait); } } @@ -553,22 +528,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, /* we always want to update icount, but we only want to * update tty_flag for one case */ if (lsr & UART_LSR_BI) { - priv->icount.brk++; + port->icount.brk++; *tty_flag = TTY_BREAK; usb_serial_handle_break(port); } if (lsr & UART_LSR_PE) { - priv->icount.parity++; + port->icount.parity++; if (*tty_flag == TTY_NORMAL) *tty_flag = TTY_PARITY; } if (lsr & UART_LSR_FE) { - priv->icount.frame++; + port->icount.frame++; if (*tty_flag == TTY_NORMAL) *tty_flag = TTY_FRAME; } if (lsr & UART_LSR_OE){ - priv->icount.overrun++; + port->icount.overrun++; if (*tty_flag == TTY_NORMAL) *tty_flag = TTY_OVERRUN; } @@ -632,7 +607,7 @@ static struct usb_serial_driver ssu100_device = { .process_read_urb = ssu100_process_read_urb, .tiocmget = ssu100_tiocmget, .tiocmset = ssu100_tiocmset, - .get_icount = ssu100_get_icount, + .get_icount = usb_serial_generic_get_icount, .ioctl = ssu100_ioctl, .set_termios = ssu100_set_termios, }; -- cgit v1.2.3 From c24c838e8effd55ba330d1966d9846400af4bec8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:32 +0100 Subject: USB: ssu100: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ssu100.c | 50 ++------------------------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 8d94a5a7c4b6..5b62dbbdf996 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -337,49 +337,6 @@ static int get_serial_info(struct usb_serial_port *port, return 0; } -static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) -{ - struct ssu100_port_private *priv = usb_get_serial_port_data(port); - struct async_icount prev, cur; - unsigned long flags; - - spin_lock_irqsave(&priv->status_lock, flags); - prev = port->icount; - spin_unlock_irqrestore(&priv->status_lock, flags); - - while (1) { - wait_event_interruptible(port->delta_msr_wait, - (port->serial->disconnected || - (port->icount.rng != prev.rng) || - (port->icount.dsr != prev.dsr) || - (port->icount.dcd != prev.dcd) || - (port->icount.cts != prev.cts))); - - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - spin_lock_irqsave(&priv->status_lock, flags); - cur = port->icount; - spin_unlock_irqrestore(&priv->status_lock, flags); - - if ((prev.rng == cur.rng) && - (prev.dsr == cur.dsr) && - (prev.dcd == cur.dcd) && - (prev.cts == cur.cts)) - return -EIO; - - if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || - (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || - (arg & TIOCM_CD && (prev.dcd != cur.dcd)) || - (arg & TIOCM_CTS && (prev.cts != cur.cts))) - return 0; - } - return 0; -} - static int ssu100_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -391,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty, case TIOCGSERIAL: return get_serial_info(port, (struct serial_struct __user *) arg); - - case TIOCMIWAIT: - return wait_modem_info(port, arg); - default: break; } @@ -509,7 +462,7 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) port->icount.dcd++; if (msr & UART_MSR_TERI) port->icount.rng++; - wake_up_interruptible(&port->delta_msr_wait); + wake_up_interruptible(&port->port.delta_msr_wait); } } @@ -607,6 +560,7 @@ static struct usb_serial_driver ssu100_device = { .process_read_urb = ssu100_process_read_urb, .tiocmget = ssu100_tiocmget, .tiocmset = ssu100_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .ioctl = ssu100_ioctl, .set_termios = ssu100_set_termios, -- cgit v1.2.3 From 783ca3557b83b915d1b7a47240e7ab6acca0aac8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:33 +0100 Subject: USB: ti_usb_3410_5052: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 44 ++++++----------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 73deb029fc05..999772538374 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -73,7 +73,6 @@ struct ti_port { unsigned int tp_uart_base_addr; int tp_flags; int tp_closing_wait;/* in .01 secs */ - struct async_icount tp_icount; wait_queue_head_t tp_write_wait; struct ti_device *tp_tdev; struct usb_serial_port *tp_port; @@ -108,8 +107,6 @@ static void ti_throttle(struct tty_struct *tty); static void ti_unthrottle(struct tty_struct *tty); static int ti_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int ti_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); static void ti_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); static int ti_tiocmget(struct tty_struct *tty); @@ -235,7 +232,7 @@ static struct usb_serial_driver ti_1port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, - .get_icount = ti_get_icount, + .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, .read_bulk_callback = ti_bulk_in_callback, @@ -265,7 +262,7 @@ static struct usb_serial_driver ti_2port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, - .get_icount = ti_get_icount, + .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, .read_bulk_callback = ti_bulk_in_callback, @@ -480,8 +477,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) port_number = port->number - port->serial->minor; - memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount)); - tport->tp_msr = 0; tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); @@ -731,31 +726,6 @@ static void ti_unthrottle(struct tty_struct *tty) } } -static int ti_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct ti_port *tport = usb_get_serial_port_data(port); - struct async_icount cnow = tport->tp_icount; - - dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__, - cnow.rx, cnow.tx); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - static int ti_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -780,7 +750,7 @@ static int ti_ioctl(struct tty_struct *tty, (struct serial_struct __user *)arg); case TIOCMIWAIT: dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); - cprev = tport->tp_icount; + cprev = port->icount; while (1) { interruptible_sleep_on(&port->delta_msr_wait); if (signal_pending(current)) @@ -789,7 +759,7 @@ static int ti_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; - cnow = tport->tp_icount; + cnow = port->icount; if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ @@ -1156,7 +1126,7 @@ static void ti_bulk_in_callback(struct urb *urb) else ti_recv(port, urb->transfer_buffer, urb->actual_length); spin_lock(&tport->tp_lock); - tport->tp_icount.rx += urb->actual_length; + port->icount.rx += urb->actual_length; spin_unlock(&tport->tp_lock); } @@ -1265,7 +1235,7 @@ static void ti_send(struct ti_port *tport) /* TODO: reschedule ti_send */ } else { spin_lock_irqsave(&tport->tp_lock, flags); - tport->tp_icount.tx += count; + port->icount.tx += count; spin_unlock_irqrestore(&tport->tp_lock, flags); } @@ -1385,7 +1355,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) if (msr & TI_MSR_DELTA_MASK) { spin_lock_irqsave(&tport->tp_lock, flags); - icount = &tport->tp_icount; + icount = &tport->tp_port->icount; if (msr & TI_MSR_DELTA_CTS) icount->cts++; if (msr & TI_MSR_DELTA_DSR) -- cgit v1.2.3 From 6c75e26067c8b8a17aea1bb54b9a8dc9d229c5e8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:34 +0100 Subject: USB: ti_usb_3410_5052: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation which does not suffer from the races involved when using the deprecated sleep_on functions. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 999772538374..07268591b0d1 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -232,6 +232,7 @@ static struct usb_serial_driver ti_1port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, @@ -262,6 +263,7 @@ static struct usb_serial_driver ti_2port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, @@ -731,8 +733,6 @@ static int ti_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - struct async_icount cnow; - struct async_icount cprev; dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd); @@ -748,29 +748,6 @@ static int ti_ioctl(struct tty_struct *tty, dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__); return ti_set_serial_info(tty, tport, (struct serial_struct __user *)arg); - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); - cprev = port->icount; - while (1) { - interruptible_sleep_on(&port->delta_msr_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - cnow = port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) - return 0; - cprev = cnow; - } - break; } return -ENOIOCTLCMD; } @@ -1364,7 +1341,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) icount->dcd++; if (msr & TI_MSR_DELTA_RI) icount->rng++; - wake_up_interruptible(&tport->tp_port->delta_msr_wait); + wake_up_interruptible(&tport->tp_port->port.delta_msr_wait); spin_unlock_irqrestore(&tport->tp_lock, flags); } -- cgit v1.2.3 From ecb9eb8064ba705e9182772db28809a755c920e8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:36 +0100 Subject: USB: cp210x: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 4747d1c328ff..2c659553c07c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -462,11 +462,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) static void cp210x_close(struct usb_serial_port *port) { usb_serial_generic_close(port); - - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) - cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); - mutex_unlock(&port->serial->disc_mutex); + cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); } /* -- cgit v1.2.3 From 87ddf4dc16d93db92431d57c4b2fcd640f428228 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:37 +0100 Subject: USB: cypress_m8: remove bogus disconnect test from close Remove disconnected test from close which did not protect any device IO at all. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index e4a62cfc4081..d341555d37d8 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -632,12 +632,6 @@ static void cypress_close(struct usb_serial_port *port) struct cypress_private *priv = usb_get_serial_port_data(port); unsigned long flags; - /* writing is potentially harmful, lock must be taken */ - mutex_lock(&port->serial->disc_mutex); - if (port->serial->disconnected) { - mutex_unlock(&port->serial->disc_mutex); - return; - } spin_lock_irqsave(&priv->lock, flags); kfifo_reset_out(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); @@ -649,7 +643,6 @@ static void cypress_close(struct usb_serial_port *port) if (stats) dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", priv->bytes_in, priv->bytes_out, priv->cmd_count); - mutex_unlock(&port->serial->disc_mutex); } /* cypress_close */ -- cgit v1.2.3 From bca87e9efb5258749f016a63b2abed40229c68c9 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:38 +0100 Subject: USB: io_ti: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 8914002a0f65..0ccc4225d593 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1907,21 +1907,10 @@ static void edge_close(struct usb_serial_port *port) kfifo_reset_out(&edge_port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - /* assuming we can still talk to the device, - * send a close port command to it */ dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__); port_number = port->number - port->serial->minor; - - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) { - send_cmd(serial->dev, - UMPC_CLOSE_PORT, - (__u8)(UMPM_UART1_PORT + port_number), - 0, - NULL, - 0); - } - mutex_unlock(&serial->disc_mutex); + send_cmd(serial->dev, UMPC_CLOSE_PORT, + (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); mutex_lock(&edge_serial->es_lock); --edge_port->edge_serial->num_ports_open; -- cgit v1.2.3 From 9fcb2e6e7e34e3ca6a6f364a1d65279e44749e07 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:39 +0100 Subject: USB: kl5kusb105: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kl5kusb105.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 57fd00194f7f..1b4054fe52a5 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -341,22 +341,17 @@ static void klsi_105_close(struct usb_serial_port *port) { int rc; - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* send READ_OFF */ - rc = usb_control_msg(port->serial->dev, - usb_sndctrlpipe(port->serial->dev, 0), - KL5KUSB105A_SIO_CONFIGURE, - USB_TYPE_VENDOR | USB_DIR_OUT, - KL5KUSB105A_SIO_CONFIGURE_READ_OFF, - 0, /* index */ - NULL, 0, - KLSI_TIMEOUT); - if (rc < 0) - dev_err(&port->dev, - "Disabling read failed (error = %d)\n", rc); - } - mutex_unlock(&port->serial->disc_mutex); + /* send READ_OFF */ + rc = usb_control_msg(port->serial->dev, + usb_sndctrlpipe(port->serial->dev, 0), + KL5KUSB105A_SIO_CONFIGURE, + USB_TYPE_VENDOR | USB_DIR_OUT, + KL5KUSB105A_SIO_CONFIGURE_READ_OFF, + 0, /* index */ + NULL, 0, + KLSI_TIMEOUT); + if (rc < 0) + dev_err(&port->dev, "failed to disable read: %d\n", rc); /* shutdown our bulk reads and writes */ usb_serial_generic_close(port); -- cgit v1.2.3 From 5813f281bba6603bed52d6005a9d6a9f23f5c061 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:40 +0100 Subject: USB: metro-usb: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/metro-usb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index bf3c7a23553e..47e247759eb0 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -177,10 +177,7 @@ static void metrousb_cleanup(struct usb_serial_port *port) usb_unlink_urb(port->interrupt_in_urb); usb_kill_urb(port->interrupt_in_urb); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) - metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); - mutex_unlock(&port->serial->disc_mutex); + metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); } static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) -- cgit v1.2.3 From cf41aa9e19052d467b54786090e1d3ba9104e394 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:41 +0100 Subject: USB: mos7720: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7720.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index d1e2bf30bff8..fc506bb71315 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1140,16 +1140,9 @@ static void mos7720_close(struct usb_serial_port *port) usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb); - mutex_lock(&serial->disc_mutex); - /* these commands must not be issued if the device has - * been disconnected */ - if (!serial->disconnected) { - write_mos_reg(serial, port->number - port->serial->minor, - MCR, 0x00); - write_mos_reg(serial, port->number - port->serial->minor, - IER, 0x00); - } - mutex_unlock(&serial->disc_mutex); + write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00); + write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00); + mos7720_port->open = 0; } -- cgit v1.2.3 From 94c51dca2ce9a3dd0c52ec6f57df4fb3e81e3ec7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:42 +0100 Subject: USB: opticon: fix return value of tiocmset Make sure we return 0 or a negative error number appropriate for userspace on errors. Currently 1 rather than 0 is returned on successful operation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index e13e1a4d3e1e..6af5bb810062 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -120,7 +120,10 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, 0, 0, buffer, 1, 0); kfree(buffer); - return retval; + if (retval < 0) + return retval; + + return 0; } static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -329,10 +332,13 @@ static int opticon_tiocmset(struct tty_struct *tty, /* Send the new RTS state to the connected device */ mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) + if (!serial->disconnected) { ret = send_control_msg(port, CONTROL_RTS, !rts); - else + if (ret) + ret = usb_translate_errors(ret); + } else { ret = -ENODEV; + } mutex_unlock(&serial->disc_mutex); return ret; -- cgit v1.2.3 From 94bcef624548fd2bcf94cb7f9fcbaedbd96d5742 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:43 +0100 Subject: USB: opticon: remove disconnect test from tiocmset Remove unnecessary disconnect test in tiocmset. No ioctls will be made after disconnect returns. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 6af5bb810062..5f4b0cd0f6e9 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -309,7 +309,6 @@ static int opticon_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; struct opticon_private *priv = usb_get_serial_port_data(port); unsigned long flags; bool rts; @@ -330,18 +329,11 @@ static int opticon_tiocmset(struct tty_struct *tty, if (!changed) return 0; - /* Send the new RTS state to the connected device */ - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) { - ret = send_control_msg(port, CONTROL_RTS, !rts); - if (ret) - ret = usb_translate_errors(ret); - } else { - ret = -ENODEV; - } - mutex_unlock(&serial->disc_mutex); + ret = send_control_msg(port, CONTROL_RTS, !rts); + if (ret) + return usb_translate_errors(ret); - return ret; + return 0; } static int get_serial_info(struct usb_serial_port *port, -- cgit v1.2.3 From aff5b323b319758257a838cdc45f494c6674447c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:44 +0100 Subject: USB: pl2303: fix return value of tiocmset Make sure we return 0 or a negative error number appropriate for userspace on errors. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 997eba4dcbeb..4dff17902fa0 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -550,10 +550,13 @@ static int pl2303_tiocmset(struct tty_struct *tty, spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) + if (!serial->disconnected) { ret = pl2303_set_control_lines(port, control); - else + if (ret) + ret = usb_translate_errors(ret); + } else { ret = -ENODEV; + } mutex_unlock(&serial->disc_mutex); return ret; -- cgit v1.2.3 From 5ddbb26b8b571231cace9f013b2d0ae66229b316 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:45 +0100 Subject: USB: pl2303: remove disconnect test from tiocmset Remove unnecessary disconnect test in tiocmset. No ioctls will be made after disconnect returns. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 4dff17902fa0..7151659367a0 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -531,7 +531,6 @@ static int pl2303_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; u8 control; @@ -549,17 +548,11 @@ static int pl2303_tiocmset(struct tty_struct *tty, control = priv->line_control; spin_unlock_irqrestore(&priv->lock, flags); - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) { - ret = pl2303_set_control_lines(port, control); - if (ret) - ret = usb_translate_errors(ret); - } else { - ret = -ENODEV; - } - mutex_unlock(&serial->disc_mutex); + ret = pl2303_set_control_lines(port, control); + if (ret) + return usb_translate_errors(ret); - return ret; + return 0; } static int pl2303_tiocmget(struct tty_struct *tty) -- cgit v1.2.3 From 81ae1b3c31a91358950011fee16698226a1bda45 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:46 +0100 Subject: USB: quatech2: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/quatech2.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 085cad471c41..3c278521f7e2 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -422,12 +422,6 @@ static void qt2_close(struct usb_serial_port *port) port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); - mutex_lock(&port->serial->disc_mutex); - if (port->serial->disconnected) { - mutex_unlock(&port->serial->disc_mutex); - return; - } - /* flush the port transmit buffer */ i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -458,8 +452,6 @@ static void qt2_close(struct usb_serial_port *port) if (i < 0) dev_err(&port->dev, "%s - close port failed %i\n", __func__, i); - - mutex_unlock(&port->serial->disc_mutex); } static void qt2_disconnect(struct usb_serial *serial) -- cgit v1.2.3 From 7620c33afb643451e1cbdc7fa666842440f8af63 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:47 +0100 Subject: USB: visor: always disable uart on close Always try to disable the uart on close. Since the switch to tty ports, close will be called as part of shutdown before disconnect returns. Hence there is no need to check the disconnected flag, and we can put devices in disabled states also on driver unbind. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/visor.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 1129aa73c23e..7573ec8a084f 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -257,24 +257,18 @@ static void visor_close(struct usb_serial_port *port) { unsigned char *transfer_buffer; - /* shutdown our urbs */ usb_serial_generic_close(port); usb_kill_urb(port->interrupt_in_urb); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Try to send shutdown message, unless the device is gone */ - transfer_buffer = kmalloc(0x12, GFP_KERNEL); - if (transfer_buffer) { - usb_control_msg(port->serial->dev, + transfer_buffer = kmalloc(0x12, GFP_KERNEL); + if (!transfer_buffer) + return; + usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), VISOR_CLOSE_NOTIFICATION, 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300); - kfree(transfer_buffer); - } - } - mutex_unlock(&port->serial->disc_mutex); + kfree(transfer_buffer); } static void visor_read_int_callback(struct urb *urb) -- cgit v1.2.3 From 91972724525829a9399a2cb41e60cad853b09229 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:48 +0100 Subject: USB: garmin_gps: remove bogus disconnect test in close Remove bogus disconnect test for serial device being NULL in close. This can never happen as close is guaranteed to be called before the last tty reference is dropped (and port->serial is cleared). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/garmin_gps.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 81caf5623ee2..1ade6cf23f7e 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -946,16 +946,12 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port) static void garmin_close(struct usb_serial_port *port) { - struct usb_serial *serial = port->serial; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n", __func__, port->number, garmin_data_p->mode, garmin_data_p->state, garmin_data_p->flags); - if (!serial) - return; - garmin_clear(garmin_data_p); /* shutdown our urbs */ -- cgit v1.2.3 From 5dbabace4f8514500c729d3e4fe10b2811a35f15 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:49 +0100 Subject: USB: garmin_gps: remove bogus disconnect test in bulk callback Remove bogus disconnect test for serial device being NULL in read bulk callback. This can never happen as the port read urb is killed (and poisoned) at close, which in turn is guaranteed to be called before the last tty reference is dropped (and port->serial is cleared). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/garmin_gps.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 1ade6cf23f7e..b110c573ea85 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1181,17 +1181,11 @@ static void garmin_read_bulk_callback(struct urb *urb) { unsigned long flags; struct usb_serial_port *port = urb->context; - struct usb_serial *serial = port->serial; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; int status = urb->status; int retval; - if (!serial) { - dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__); - return; - } - if (status) { dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n", __func__, status); -- cgit v1.2.3 From 8976f1df91aa36e0cea312ed4e547831db57261a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:50 +0100 Subject: USB: iuu_phoenix: remove bogus disconnect test in close Remove bogus disconnect test for serial device being NULL in close. This can never happen as close is guaranteed to be called before the last tty reference is dropped (and port->serial is cleared). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/iuu_phoenix.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 1ccf9e4e82c2..9d74c278b7b5 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -942,11 +942,6 @@ static void iuu_set_termios(struct tty_struct *tty, static void iuu_close(struct usb_serial_port *port) { /* iuu_led (port,255,0,0,0); */ - struct usb_serial *serial; - - serial = port->serial; - if (!serial) - return; iuu_uart_off(port); -- cgit v1.2.3 From 659597b77493959c699b4e99841a2c778eaa70bc Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:51 +0100 Subject: USB: serial: update copyright information Update copyright information. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/generic.c | 2 +- drivers/usb/serial/usb-serial.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1199dc52e388..9a5295efc74d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1,7 +1,7 @@ /* * USB FTDI SIO driver * - * Copyright (C) 2009 - 2010 + * Copyright (C) 2009 - 2013 * Johan Hovold (jhovold@gmail.com) * Copyright (C) 1999 - 2001 * Greg Kroah-Hartman (greg@kroah.com) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 5e55761b2cb8..297665fdd16d 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -1,7 +1,7 @@ /* * USB Serial Converter Generic functions * - * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com) + * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com) * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) * * This program is free software; you can redistribute it and/or diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 456881620727..5eb96df8de05 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1,6 +1,7 @@ /* * USB Serial Converter driver * + * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com) * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2000 Peter Berger (pberger@brimson.com) * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com) -- cgit v1.2.3 From b13379758f17e66d60f1f288bf917762c54ebd2f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 28 Mar 2013 11:02:24 -0700 Subject: Revert "USB: serial: fix hang when opening port" This reverts commit eba0e3c3a0ba7b96f01cbe997680f6a4401a0bfc. When merged together (usb-linus and usb-next), this fix isn't needed and causes a build error. Revert the commit to solve the build issue. Reported-by: Stephen Rothwell Cc: Ming Lei Cc: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 57e6f53a3dac..5eb96df8de05 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -892,7 +892,6 @@ static int usb_serial_probe(struct usb_interface *interface, port->port.ops = &serial_port_ops; port->serial = serial; spin_lock_init(&port->lock); - init_waitqueue_head(&port->delta_msr_wait); /* Keep this for private driver use for the moment but should probably go away */ INIT_WORK(&port->work, usb_serial_port_work); -- cgit v1.2.3 From 6a3ae8412f9e9cee0e8647954f4f7f2c50664ca2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 5 Apr 2013 08:42:41 +0300 Subject: USB: keyspan: pull in one indent level We can remove the "if (urb->actual_length) {" check because checking for "while (i < urb->actual_length) {" is sufficient. This lets us pull the code in one indent level. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 69 ++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 6abe8a4fee0e..3d92394aba3a 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -726,45 +726,44 @@ static void usa49wg_indat_callback(struct urb *urb) i = 0; len = 0; - if (urb->actual_length) { - while (i < urb->actual_length) { + while (i < urb->actual_length) { - /* Check port number from message*/ - if (data[i] >= serial->num_ports) { - dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", - __func__, data[i]); - return; - } - port = serial->port[data[i++]]; - len = data[i++]; + /* Check port number from message */ + if (data[i] >= serial->num_ports) { + dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", + __func__, data[i]); + return; + } + port = serial->port[data[i++]]; + len = data[i++]; - /* 0x80 bit is error flag */ - if ((data[i] & 0x80) == 0) { - /* no error on any byte */ - i++; - for (x = 1; x < len ; ++x) - tty_insert_flip_char(&port->port, - data[i++], 0); - } else { - /* - * some bytes had errors, every byte has status - */ - for (x = 0; x + 1 < len; x += 2) { - int stat = data[i], flag = 0; - if (stat & RXERROR_OVERRUN) - flag |= TTY_OVERRUN; - if (stat & RXERROR_FRAMING) - flag |= TTY_FRAME; - if (stat & RXERROR_PARITY) - flag |= TTY_PARITY; - /* XXX should handle break (0x10) */ - tty_insert_flip_char(&port->port, - data[i+1], flag); - i += 2; - } + /* 0x80 bit is error flag */ + if ((data[i] & 0x80) == 0) { + /* no error on any byte */ + i++; + for (x = 1; x < len ; ++x) + tty_insert_flip_char(&port->port, + data[i++], 0); + } else { + /* + * some bytes had errors, every byte has status + */ + for (x = 0; x + 1 < len; x += 2) { + int stat = data[i], flag = 0; + + if (stat & RXERROR_OVERRUN) + flag |= TTY_OVERRUN; + if (stat & RXERROR_FRAMING) + flag |= TTY_FRAME; + if (stat & RXERROR_PARITY) + flag |= TTY_PARITY; + /* XXX should handle break (0x10) */ + tty_insert_flip_char(&port->port, data[i+1], + flag); + i += 2; } - tty_flip_buffer_push(&port->port); } + tty_flip_buffer_push(&port->port); } /* Resubmit urb so we continue receiving */ -- cgit v1.2.3 From 01a60e76b6392547ad3dca3ac05b9c886fa5da45 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 5 Apr 2013 08:43:20 +0300 Subject: USB: keyspan: add a sanity test on "len" "len" comes from the USB transfer and it's probably correct. The thing is that we already have similar checks like: if (data[i] >= serial->num_ports) { So adding a sanity test here matches the rest of the code and is a good idea. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 3d92394aba3a..025310bc358a 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -741,14 +741,15 @@ static void usa49wg_indat_callback(struct urb *urb) if ((data[i] & 0x80) == 0) { /* no error on any byte */ i++; - for (x = 1; x < len ; ++x) + for (x = 1; x < len && i < urb->actual_length; ++x) tty_insert_flip_char(&port->port, data[i++], 0); } else { /* * some bytes had errors, every byte has status */ - for (x = 0; x + 1 < len; x += 2) { + for (x = 0; x + 1 < len && + i + 1 < urb->actual_length; x += 2) { int stat = data[i], flag = 0; if (stat & RXERROR_OVERRUN) -- cgit v1.2.3 From ae3759c2573031f1306496c6f9f32f20e86f03aa Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 4 Apr 2013 22:41:01 +0200 Subject: USB: io_ti, stop dereferencing potential NULL tty_port_tty_get might return a tty which is NULL. But it is dereferenced unconditionally in edge_send. Stop dereferencing that by sending usb_serial_port pointer around. Signed-off-by: Jiri Slaby Cc: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 0ccc4225d593..f2a1601775b1 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -206,7 +206,7 @@ static int restart_read(struct edgeport_port *edge_port); static void edge_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); -static void edge_send(struct tty_struct *tty); +static void edge_send(struct usb_serial_port *port, struct tty_struct *tty); /* sysfs attributes */ static int edge_create_sysfs_attrs(struct usb_serial_port *port); @@ -1712,7 +1712,7 @@ static void edge_bulk_out_callback(struct urb *urb) /* send any buffered data */ tty = tty_port_tty_get(&port->port); - edge_send(tty); + edge_send(port, tty); tty_kref_put(tty); } @@ -1940,14 +1940,13 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, count = kfifo_in_locked(&edge_port->write_fifo, data, count, &edge_port->ep_lock); - edge_send(tty); + edge_send(port, tty); return count; } -static void edge_send(struct tty_struct *tty) +static void edge_send(struct usb_serial_port *port, struct tty_struct *tty) { - struct usb_serial_port *port = tty->driver_data; int count, result; struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned long flags; -- cgit v1.2.3 From 58f8b6c4fa5a13cb2ddb400e26e9e65766d71e38 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Sun, 7 Apr 2013 12:08:55 +0200 Subject: USB: add ftdi_sio USB ID for GDM Boost V1.x This patch add a missing usb device id for the GDMBoost V1.x device The patch is against 3.9-rc5 Signed-off-by: Stefani Seibold Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 778c54dd3dff..fc7bd147d3b1 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -187,6 +187,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) }, { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index e79861eeed4c..3c003512f60a 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -74,6 +74,7 @@ #define FTDI_OPENDCC_THROTTLE_PID 0xBFDA #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC +#define FTDI_OPENDCC_GBM_BOOST_PID 0xBFDD /* NZR SEM 16+ USB (http://www.nzr.de) */ #define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ -- cgit v1.2.3 From a2a2d6c7f93e160b52a4ad0164db1f43f743ae0f Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Tue, 9 Apr 2013 11:26:02 +0200 Subject: USB: option: add a D-Link DWM-156 variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding support for a Mediatek based device labelled as D-Link Model: DWM-156, H/W Ver: A7 Also adding two other device IDs found in the Debian(!) packages included on the embedded device driver CD. This is a composite MBIM + serial ports + card reader device: T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 14 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=2001 ProdID=7d01 Rev= 3.00 S: Manufacturer=D-Link,Inc S: Product=D-Link DWM-156 C:* #Ifs= 7 Cfg#= 1 Atr=a0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0e Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=88(I) Atr=03(Int.) MxPS= 64 Ivl=125us I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=02 Prot=01 Driver=option E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=500us E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 6 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms Cc: stable Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 558adfc05007..e1bff4b9af06 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1350,6 +1350,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) }, /* D-Link DWM-156 (variant) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) }, /* D-Link DWM-156 (variant) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3 From 25e11ec4fe5271c4895265ecbb69531e6b0c0dd5 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 9 Apr 2013 14:29:25 +0200 Subject: USB: regroup all depends on USB within an if USB block This patch removes the depends on USB from all config symbols in drivers/usb/host/Kconfig and replace that with an if USB / endif block as suggested by Alan Stern. Some source ... Kconfig lines have been shuffled around to permit a better regroupment of the Kconfig files depending on "config USB" item. No functionnal change is introduced. Acked-by: Alan Stern Signed-off-by: Florian Fainelli Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 23 +++++++++++++++-------- drivers/usb/atm/Kconfig | 2 +- drivers/usb/class/Kconfig | 6 +----- drivers/usb/core/Kconfig | 6 ------ drivers/usb/host/Kconfig | 30 +++++++++++------------------- drivers/usb/image/Kconfig | 4 +--- drivers/usb/misc/Kconfig | 21 --------------------- drivers/usb/misc/sisusbvga/Kconfig | 2 +- drivers/usb/mon/Kconfig | 1 - drivers/usb/musb/Kconfig | 2 +- drivers/usb/renesas_usbhs/Kconfig | 2 +- drivers/usb/serial/Kconfig | 2 +- drivers/usb/storage/Kconfig | 7 +++---- drivers/usb/wusbcore/Kconfig | 2 -- 14 files changed, 36 insertions(+), 74 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 2c481b808276..92e1dc94ecc8 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -122,9 +122,9 @@ config USB To compile this driver as a module, choose M here: the module will be called usbcore. -source "drivers/usb/core/Kconfig" +if USB -source "drivers/usb/dwc3/Kconfig" +source "drivers/usb/core/Kconfig" source "drivers/usb/mon/Kconfig" @@ -134,8 +134,6 @@ source "drivers/usb/host/Kconfig" source "drivers/usb/musb/Kconfig" -source "drivers/usb/chipidea/Kconfig" - source "drivers/usb/renesas_usbhs/Kconfig" source "drivers/usb/class/Kconfig" @@ -144,12 +142,19 @@ source "drivers/usb/storage/Kconfig" source "drivers/usb/image/Kconfig" +endif + +source "drivers/usb/dwc3/Kconfig" + +source "drivers/usb/chipidea/Kconfig" + comment "USB port drivers" - depends on USB + +if USB config USB_USS720 tristate "USS720 parport driver" - depends on USB && PARPORT + depends on PARPORT select PARPORT_NOT_PC ---help--- This driver is for USB parallel port adapters that use the Lucent @@ -180,10 +185,12 @@ source "drivers/usb/serial/Kconfig" source "drivers/usb/misc/Kconfig" -source "drivers/usb/phy/Kconfig" - source "drivers/usb/atm/Kconfig" +endif # USB + +source "drivers/usb/phy/Kconfig" + source "drivers/usb/gadget/Kconfig" endif # USB_SUPPORT diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig index be0b8daac9c7..0f922942a07a 100644 --- a/drivers/usb/atm/Kconfig +++ b/drivers/usb/atm/Kconfig @@ -4,7 +4,7 @@ menuconfig USB_ATM tristate "USB DSL modem support" - depends on USB && ATM + depends on ATM select CRC32 default n help diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig index 316aac8e4ca1..bb8b73682a70 100644 --- a/drivers/usb/class/Kconfig +++ b/drivers/usb/class/Kconfig @@ -2,11 +2,10 @@ # USB Class driver configuration # comment "USB Device Class drivers" - depends on USB config USB_ACM tristate "USB Modem (CDC ACM) support" - depends on USB && TTY + depends on TTY ---help--- This driver supports USB modems and ISDN adapters which support the Communication Device Class Abstract Control Model interface. @@ -21,7 +20,6 @@ config USB_ACM config USB_PRINTER tristate "USB Printer support" - depends on USB help Say Y here if you want to connect a USB printer to your computer's USB port. @@ -31,7 +29,6 @@ config USB_PRINTER config USB_WDM tristate "USB Wireless Device Management support" - depends on USB ---help--- This driver supports the WMC Device Management functionality of cell phones compliant to the CDC WMC specification. You can use @@ -42,7 +39,6 @@ config USB_WDM config USB_TMC tristate "USB Test and Measurement Class support" - depends on USB help Say Y here if you want to connect a USB device that follows the USB.org specification for USB Test and Measurement devices diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 7b7305e3abc8..8772b3659296 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -3,7 +3,6 @@ # config USB_DEBUG bool "USB verbose debug messages" - depends on USB help Say Y here if you want the USB core & hub drivers to produce a bunch of debug messages to the system log. Select this if you are having a @@ -11,7 +10,6 @@ config USB_DEBUG config USB_ANNOUNCE_NEW_DEVICES bool "USB announce new devices" - depends on USB default N help Say Y here if you want the USB core to always announce the @@ -25,11 +23,9 @@ config USB_ANNOUNCE_NEW_DEVICES log, or have any doubts about this, say N here. comment "Miscellaneous USB options" - depends on USB config USB_DEFAULT_PERSIST bool "Enable USB persist by default" - depends on USB default y help Say N here if you don't want USB power session persistance @@ -45,7 +41,6 @@ config USB_DEFAULT_PERSIST config USB_DYNAMIC_MINORS bool "Dynamic USB minor allocation" - depends on USB help If you say Y here, the USB subsystem will use dynamic minor allocation for any device that uses the USB major number. @@ -56,7 +51,6 @@ config USB_DYNAMIC_MINORS config USB_OTG bool "OTG support" - depends on USB depends on USB_SUSPEND default n help diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index dbeac41595de..1714c6defd23 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -2,11 +2,9 @@ # USB Host Controller Drivers # comment "USB Host Controller Drivers" - depends on USB config USB_C67X00_HCD tristate "Cypress C67x00 HCD support" - depends on USB help The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role host/peripheral/OTG USB controllers. @@ -19,7 +17,7 @@ config USB_C67X00_HCD config USB_XHCI_HCD tristate "xHCI HCD (USB 3.0) support" - depends on USB && USB_ARCH_HAS_XHCI + depends on USB_ARCH_HAS_XHCI ---help--- The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 "SuperSpeed" host controller hardware. @@ -43,7 +41,7 @@ config USB_XHCI_HCD_DEBUGGING config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" - depends on USB && USB_ARCH_HAS_EHCI + depends on USB_ARCH_HAS_EHCI ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. @@ -280,7 +278,7 @@ config USB_EHCI_ATH79 config USB_OXU210HP_HCD tristate "OXU210HP HCD support" - depends on USB && GENERIC_HARDIRQS + depends on GENERIC_HARDIRQS ---help--- The OXU210HP is an USB host/OTG/device controller. Enable this option if your board has this chip. If unsure, say N. @@ -293,7 +291,6 @@ config USB_OXU210HP_HCD config USB_ISP116X_HCD tristate "ISP116X HCD support" - depends on USB ---help--- The ISP1160 and ISP1161 chips are USB host controllers. Enable this option if your board has this chip. If unsure, say N. @@ -305,7 +302,6 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB ---help--- The ISP1760 chip is a USB 2.0 host controller. @@ -320,7 +316,6 @@ config USB_ISP1760_HCD config USB_ISP1362_HCD tristate "ISP1362 HCD support" - depends on USB default N ---help--- Supports the Philips ISP1362 chip as a host controller @@ -332,7 +327,7 @@ config USB_ISP1362_HCD config USB_OHCI_HCD tristate "OHCI HCD support" - depends on USB && USB_ARCH_HAS_OHCI + depends on USB_ARCH_HAS_OHCI select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 depends on USB_ISP1301 || !ARCH_LPC32XX ---help--- @@ -490,7 +485,7 @@ config USB_OHCI_LITTLE_ENDIAN config USB_UHCI_HCD tristate "UHCI HCD (most Intel and VIA) support" - depends on USB && (PCI || SPARC_LEON || ARCH_VT8500) + depends on PCI || SPARC_LEON || ARCH_VT8500 ---help--- The Universal Host Controller Interface is a standard by Intel for accessing the USB hardware in the PC (which is also called the USB @@ -530,7 +525,7 @@ config USB_UHCI_BIG_ENDIAN_DESC config USB_FHCI_HCD tristate "Freescale QE USB Host Controller support" - depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE + depends on OF_GPIO && QE_GPIO && QUICC_ENGINE select FSL_GTM select QE_USB help @@ -547,7 +542,7 @@ config FHCI_DEBUG config USB_U132_HCD tristate "Elan U132 Adapter Host Controller" - depends on USB && USB_FTDI_ELAN + depends on USB_FTDI_ELAN default M help The U132 adapter is a USB to CardBus adapter specifically designed @@ -575,7 +570,6 @@ config USB_U132_HCD config USB_SL811_HCD tristate "SL811HS HCD support" - depends on USB help The SL811HS is a single-port USB controller that supports either host side or peripheral side roles. Enable this option if your @@ -607,7 +601,6 @@ config USB_SL811_CS config USB_R8A66597_HCD tristate "R8A66597 HCD support" - depends on USB help The R8A66597 is a USB 2.0 host and peripheral controller. @@ -619,7 +612,6 @@ config USB_R8A66597_HCD config USB_RENESAS_USBHS_HCD tristate "Renesas USBHS HCD support" - depends on USB depends on USB_RENESAS_USBHS help The Renesas USBHS is a USB 2.0 host and peripheral controller. @@ -644,7 +636,7 @@ config USB_WHCI_HCD config USB_HWA_HCD tristate "Host Wire Adapter (HWA) driver" - depends on USB && UWB + depends on UWB select USB_WUSB select UWB_HWA help @@ -658,7 +650,7 @@ config USB_HWA_HCD config USB_IMX21_HCD tristate "i.MX21 HCD support" - depends on USB && ARM && ARCH_MXC + depends on ARM && ARCH_MXC help This driver enables support for the on-chip USB host in the i.MX21 processor. @@ -668,7 +660,7 @@ config USB_IMX21_HCD config USB_OCTEON_EHCI bool "Octeon on-chip EHCI support" - depends on USB && USB_EHCI_HCD && CPU_CAVIUM_OCTEON + depends on USB_EHCI_HCD && CPU_CAVIUM_OCTEON default n select USB_EHCI_BIG_ENDIAN_MMIO help @@ -679,7 +671,7 @@ config USB_OCTEON_EHCI config USB_OCTEON_OHCI bool "Octeon on-chip OHCI support" - depends on USB && USB_OHCI_HCD && CPU_CAVIUM_OCTEON + depends on USB_OHCI_HCD && CPU_CAVIUM_OCTEON default USB_OCTEON_EHCI select USB_OHCI_BIG_ENDIAN_MMIO select USB_OHCI_LITTLE_ENDIAN diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig index 33350f9dd34f..320d368c8dac 100644 --- a/drivers/usb/image/Kconfig +++ b/drivers/usb/image/Kconfig @@ -2,11 +2,9 @@ # USB Imaging devices configuration # comment "USB Imaging devices" - depends on USB config USB_MDC800 tristate "USB Mustek MDC800 Digital Camera support" - depends on USB ---help--- Say Y here if you want to connect this type of still camera to your computer's USB port. This driver can be used with gphoto 0.4.3 @@ -19,7 +17,7 @@ config USB_MDC800 config USB_MICROTEK tristate "Microtek X6USB scanner support" - depends on USB && SCSI + depends on SCSI help Say Y here if you want support for the Microtek X6USB and possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L. diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 3b1a3f4ec5e9..a51e7d6afda9 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -2,11 +2,9 @@ # USB Miscellaneous driver configuration # comment "USB Miscellaneous drivers" - depends on USB config USB_EMI62 tristate "EMI 6|2m USB Audio interface support" - depends on USB ---help--- This driver loads firmware to Emagic EMI 6|2m low latency USB Audio and Midi interface. @@ -21,7 +19,6 @@ config USB_EMI62 config USB_EMI26 tristate "EMI 2|6 USB Audio interface support" - depends on USB ---help--- This driver loads firmware to Emagic EMI 2|6 low latency USB Audio interface. @@ -34,7 +31,6 @@ config USB_EMI26 config USB_ADUTUX tristate "ADU devices from Ontrak Control Systems" - depends on USB help Say Y if you want to use an ADU device from Ontrak Control Systems. @@ -44,7 +40,6 @@ config USB_ADUTUX config USB_SEVSEG tristate "USB 7-Segment LED Display" - depends on USB help Say Y here if you have a USB 7-Segment Display by Delcom @@ -53,7 +48,6 @@ config USB_SEVSEG config USB_RIO500 tristate "USB Diamond Rio500 support" - depends on USB help Say Y here if you want to connect a USB Rio500 mp3 player to your computer's USB port. Please read @@ -64,7 +58,6 @@ config USB_RIO500 config USB_LEGOTOWER tristate "USB Lego Infrared Tower support" - depends on USB help Say Y here if you want to connect a USB Lego Infrared Tower to your computer's USB port. @@ -77,7 +70,6 @@ config USB_LEGOTOWER config USB_LCD tristate "USB LCD driver support" - depends on USB help Say Y here if you want to connect an USBLCD to your computer's USB port. The USBLCD is a small USB interface board for @@ -89,7 +81,6 @@ config USB_LCD config USB_LED tristate "USB LED driver support" - depends on USB help Say Y here if you want to connect an USBLED device to your computer's USB port. @@ -99,7 +90,6 @@ config USB_LED config USB_CYPRESS_CY7C63 tristate "Cypress CY7C63xxx USB driver support" - depends on USB help Say Y here if you want to connect a Cypress CY7C63xxx micro controller to your computer's USB port. Currently this @@ -113,7 +103,6 @@ config USB_CYPRESS_CY7C63 config USB_CYTHERM tristate "Cypress USB thermometer driver support" - depends on USB help Say Y here if you want to connect a Cypress USB thermometer device to your computer's USB port. This device is also known @@ -126,7 +115,6 @@ config USB_CYTHERM config USB_IDMOUSE tristate "Siemens ID USB Mouse Fingerprint sensor support" - depends on USB help Say Y here if you want to use the fingerprint sensor on the Siemens ID Mouse. There is also a Siemens ID Mouse @@ -140,7 +128,6 @@ config USB_IDMOUSE config USB_FTDI_ELAN tristate "Elan PCMCIA CardBus Adapter USB Client" - depends on USB default M help ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters. @@ -164,7 +151,6 @@ config USB_FTDI_ELAN config USB_APPLEDISPLAY tristate "Apple Cinema Display support" - depends on USB select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE help @@ -175,7 +161,6 @@ source "drivers/usb/misc/sisusbvga/Kconfig" config USB_LD tristate "USB LD driver" - depends on USB help This driver is for generic USB devices that use interrupt transfers, like LD Didactic's USB devices. @@ -185,7 +170,6 @@ config USB_LD config USB_TRANCEVIBRATOR tristate "PlayStation 2 Trance Vibrator driver support" - depends on USB help Say Y here if you want to connect a PlayStation 2 Trance Vibrator device to your computer's USB port. @@ -195,7 +179,6 @@ config USB_TRANCEVIBRATOR config USB_IOWARRIOR tristate "IO Warrior driver support" - depends on USB help Say Y here if you want to support the IO Warrior devices from Code Mercenaries. This includes support for the following devices: @@ -209,7 +192,6 @@ config USB_IOWARRIOR config USB_TEST tristate "USB testing driver" - depends on USB help This driver is for testing host controller software. It is used with specialized device firmware for regression and stress testing, @@ -220,7 +202,6 @@ config USB_TEST config USB_ISIGHTFW tristate "iSight firmware loading support" - depends on USB select FW_LOADER help This driver loads firmware for USB Apple iSight cameras, allowing @@ -233,7 +214,6 @@ config USB_ISIGHTFW config USB_YUREX tristate "USB YUREX driver support" - depends on USB help Say Y here if you want to connect a YUREX to your computer's USB port. The YUREX is a leg-shakes sensor. See @@ -246,7 +226,6 @@ config USB_YUREX config USB_EZUSB_FX2 tristate "Functions for loading firmware on EZUSB chips" - depends on USB help Say Y here if you need EZUSB device support. (Cypress FX/FX2/FX2LP microcontrollers) diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig index 30ea7ca6846e..0d03a5200482 100644 --- a/drivers/usb/misc/sisusbvga/Kconfig +++ b/drivers/usb/misc/sisusbvga/Kconfig @@ -1,7 +1,7 @@ config USB_SISUSBVGA tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)" - depends on USB && (USB_MUSB_HDRC || USB_EHCI_HCD) + depends on (USB_MUSB_HDRC || USB_EHCI_HCD) ---help--- Say Y here if you intend to attach a USB2VGA dongle based on a Net2280 and a SiS315 chip. diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index 635745f57fbd..5c6ffa2a612e 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig @@ -4,7 +4,6 @@ config USB_MON tristate "USB Monitor" - depends on USB help If you select this option, a component which captures the USB traffic between peripheral-specific drivers and HC drivers will be built. diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 47442d35b6fc..06f8d29af1ef 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -6,7 +6,7 @@ # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller config USB_MUSB_HDRC tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' - depends on USB && USB_GADGET + depends on USB_GADGET help Say Y here if your system has a dual role high speed USB controller based on the Mentor Graphics silicon IP. Then diff --git a/drivers/usb/renesas_usbhs/Kconfig b/drivers/usb/renesas_usbhs/Kconfig index 29feb00d7f39..019bf7e49ee6 100644 --- a/drivers/usb/renesas_usbhs/Kconfig +++ b/drivers/usb/renesas_usbhs/Kconfig @@ -4,7 +4,7 @@ config USB_RENESAS_USBHS tristate 'Renesas USBHS controller' - depends on USB && USB_GADGET && GENERIC_HARDIRQS + depends on USB_GADGET && GENERIC_HARDIRQS default n help Renesas USBHS is a discrete USB host and peripheral controller chip diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 17b7f9ae36ad..bf3733629b09 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -4,7 +4,7 @@ menuconfig USB_SERIAL tristate "USB Serial Converter support" - depends on USB && TTY + depends on TTY ---help--- Say Y here if you have a USB device that provides normal serial ports, or acts like a serial device, and you want to connect it to diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index eab04a6b5fbc..8470e1b114f2 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -4,11 +4,10 @@ comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may" comment "also be needed; see USB_STORAGE Help for more info" - depends on USB config USB_STORAGE tristate "USB Mass Storage support" - depends on USB && SCSI + depends on SCSI ---help--- Say Y here if you want to connect USB mass storage devices to your computer's USB port. This is the driver you need for USB @@ -188,7 +187,7 @@ config USB_STORAGE_CYPRESS_ATACB config USB_STORAGE_ENE_UB6250 tristate "USB ENE card reader support" - depends on USB && SCSI + depends on SCSI depends on USB_STORAGE ---help--- Say Y here if you wish to control a ENE SD/MS Card reader. @@ -203,7 +202,7 @@ config USB_STORAGE_ENE_UB6250 config USB_UAS tristate "USB Attached SCSI" - depends on USB && SCSI && BROKEN + depends on SCSI && BROKEN help The USB Attached SCSI protocol is supported by some USB storage devices. It permits higher performance by supporting diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index 8bf19760d447..0e17b966e1b4 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -3,7 +3,6 @@ # config USB_WUSB tristate "Enable Wireless USB extensions" - depends on USB depends on PCI depends on UWB select CRYPTO @@ -19,7 +18,6 @@ config USB_WUSB config USB_WUSB_CBAF tristate "Support WUSB Cable Based Association (CBA)" - depends on USB help Some WUSB devices support Cable Based Association. It's used to enable the secure communication between the host and the -- cgit v1.2.3 From 1157f69bee295987952bf0cbbcbc419d497eb51c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 11 Apr 2013 15:08:20 +0200 Subject: usb-serial: add support for USB Wishbone-serial adapters Wishbone is an open hardware SoC bus commonly used in FPGA designs. Bus access can be serialized using the Etherbone protocol . This driver is intended to be used with devices which attach their internal Wishbone bus to a USB serial interface using the Etherbone protocol. A userspace library is required to speak the protocol made available by this driver as ttyUSBx. Signed-off-by: Wesley W. Terpstra Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 17 +++++++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/wishbone-serial.c | 95 ++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 drivers/usb/serial/wishbone-serial.c (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index bf3733629b09..1d55762afbb1 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -667,6 +667,23 @@ config USB_SERIAL_ZIO To compile this driver as a module, choose M here: the module will be called zio. +config USB_SERIAL_WISHBONE + tristate "USB-Wishbone adapter interface driver" + help + Say Y here if you want to use a USB attached Wishbone bus. + + Wishbone is an open hardware SoC bus commonly used in FPGA + designs. Bus access can be serialized using the Etherbone + protocol . + + This driver is intended to be used with devices which attach + their internal Wishbone bus to a USB serial interface using + the Etherbone protocol. A userspace library is required to + speak the protocol made available by this driver as ttyUSBx. + + To compile this driver as a module, choose M here: the + module will be called wishbone-serial. + config USB_SERIAL_ZTE tristate "ZTE USB serial driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index eaf5ca14dfeb..cec63fa19104 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o +obj-$(CONFIG_USB_SERIAL_WISHBONE) += wishbone-serial.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c new file mode 100644 index 000000000000..481ec669bf7c --- /dev/null +++ b/drivers/usb/serial/wishbone-serial.c @@ -0,0 +1,95 @@ +/* + * USB Wishbone-Serial adapter driver + * + * Copyright (C) 2013 Wesley W. Terpstra + * Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define GSI_VENDOR_OPENCLOSE 0xB0 + +static const struct usb_device_id id_table[] = { + { USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* + * Etherbone must be told that a new stream has begun before data arrives. + * This is necessary to restart the negotiation of Wishbone bus parameters. + * Similarly, when the stream ends, Etherbone must be told so that the cycle + * line can be driven low in the case that userspace failed to do so. + */ +static int usb_gsi_openclose(struct usb_serial_port *port, int value) +{ + struct usb_device *dev = port->serial->dev; + + return usb_control_msg( + dev, + usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */ + GSI_VENDOR_OPENCLOSE, + USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, + value, /* wValue = device is open(1) or closed(0) */ + port->serial->interface->cur_altsetting->desc.bInterfaceNumber, + 0, 0, /* There is no data stage */ + 5000); /* Timeout till operation fails */ +} + +static int wishbone_serial_open(struct tty_struct *tty, + struct usb_serial_port *port) +{ + int retval; + + retval = usb_gsi_openclose(port, 1); + if (retval) { + dev_err(&port->serial->dev->dev, + "Could not mark device as open (%d)\n", + retval); + return retval; + } + + retval = usb_serial_generic_open(tty, port); + if (retval) + usb_gsi_openclose(port, 0); + + return retval; +} + +static void wishbone_serial_close(struct usb_serial_port *port) +{ + usb_serial_generic_close(port); + usb_gsi_openclose(port, 0); +} + +static struct usb_serial_driver wishbone_serial_device = { + .driver = { + .owner = THIS_MODULE, + .name = "wishbone_serial", + }, + .id_table = id_table, + .num_ports = 1, + .open = &wishbone_serial_open, + .close = &wishbone_serial_close, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &wishbone_serial_device, NULL +}; + +module_usb_serial_driver(serial_drivers, id_table); + +MODULE_AUTHOR("Wesley W. Terpstra "); +MODULE_DESCRIPTION("USB Wishbone-Serial adapter"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b8a261b59c8c6014d7dc984811ec81f14ef6f767 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Apr 2013 08:45:34 -0700 Subject: USB: serial: wishbone-serial: fix up minor sparse warning This fixes a sparse warning where we should be using NULL instead of 0 Cc: Wesley W. Terpstra Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/wishbone-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c index 481ec669bf7c..100573c6f19e 100644 --- a/drivers/usb/serial/wishbone-serial.c +++ b/drivers/usb/serial/wishbone-serial.c @@ -43,7 +43,7 @@ static int usb_gsi_openclose(struct usb_serial_port *port, int value) USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, value, /* wValue = device is open(1) or closed(0) */ port->serial->interface->cur_altsetting->desc.bInterfaceNumber, - 0, 0, /* There is no data stage */ + NULL, 0, /* There is no data stage */ 5000); /* Timeout till operation fails */ } -- cgit v1.2.3 From 81f58c67b1d71b3a1a6c2bb077844249790807c8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:19 +0200 Subject: USB: omninet: use kzalloc for private data Make sure the port private data, which contains the write sequence number, is cleared at allocation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 1e1cafe287e4..ea1105c84d50 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -112,7 +112,7 @@ static int omninet_port_probe(struct usb_serial_port *port) { struct omninet_data *od; - od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); + od = kzalloc(sizeof(*od), GFP_KERNEL); if (!od) return -ENOMEM; -- cgit v1.2.3 From b42abbcde44a0a58e7dbaa4e3f0adc4cf5b74684 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:20 +0200 Subject: USB: omninet: clean up protocol description Clean up and fix typos in protocol comment. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index ea1105c84d50..ec16b92d52b3 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -74,29 +74,28 @@ static struct usb_serial_driver * const serial_drivers[] = { }; -/* The protocol. +/* + * The protocol. * * The omni.net always exchange 64 bytes of data with the host. The first - * four bytes are the control header, you can see it in the above structure. + * four bytes are the control header. * * oh_seq is a sequence number. Don't know if/how it's used. * oh_len is the length of the data bytes in the packet. * oh_xxx Bit-mapped, related to handshaking and status info. - * I normally set it to 0x03 in trasmitted frames. + * I normally set it to 0x03 in transmitted frames. * 7: Active when the TA is in a CONNECTed state. * 6: unknown * 5: handshaking, unknown * 4: handshaking, unknown * 3: unknown, usually 0 * 2: unknown, usually 0 - * 1: handshaking, unknown, usually set to 1 in trasmitted frames - * 0: handshaking, unknown, usually set to 1 in trasmitted frames + * 1: handshaking, unknown, usually set to 1 in transmitted frames + * 0: handshaking, unknown, usually set to 1 in transmitted frames * oh_pad Probably a pad byte. * * After the header you will find data bytes if oh_len was greater than zero. - * */ - struct omninet_header { __u8 oh_seq; __u8 oh_len; -- cgit v1.2.3 From d91641b161594672242b3c5d8656ad3b2ef58f34 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:21 +0200 Subject: USB: omninet: clean up protocol defines Remove redundant data-offset define, which was really just the header length. Add payload-size define and use the bulk-out size define for the actual bulk-out size. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index ec16b92d52b3..9dcaa7727de5 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -154,9 +154,9 @@ static void omninet_close(struct usb_serial_port *port) } -#define OMNINET_DATAOFFSET 0x04 -#define OMNINET_HEADERLEN sizeof(struct omninet_header) -#define OMNINET_BULKOUTSIZE (64 - OMNINET_HEADERLEN) +#define OMNINET_HEADERLEN 4 +#define OMNINET_BULKOUTSIZE 64 +#define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) static void omninet_read_bulk_callback(struct urb *urb) { @@ -173,7 +173,7 @@ static void omninet_read_bulk_callback(struct urb *urb) } if (urb->actual_length && header->oh_len) { - tty_insert_flip_string(&port->port, data + OMNINET_DATAOFFSET, + tty_insert_flip_string(&port->port, data + OMNINET_HEADERLEN, header->oh_len); tty_flip_buffer_push(&port->port); } @@ -208,9 +208,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, return 0; } - count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; + count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count; - memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, + memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN, buf, count); usb_serial_debug_data(&port->dev, __func__, count, @@ -222,7 +222,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, header->oh_pad = 0x00; /* send the data out the bulk port, always 64 bytes */ - wport->write_urb->transfer_buffer_length = 64; + wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE; result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); if (result) { -- cgit v1.2.3 From a6c042f95031afbeb0b0fb77643bc9211a3f2e2e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:22 +0200 Subject: USB: omninet: refactor read-urb processing Refactor read-urb processing, and add sanity checks on header and data lengths. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 9dcaa7727de5..7aaf9692b334 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -158,11 +158,26 @@ static void omninet_close(struct usb_serial_port *port) #define OMNINET_BULKOUTSIZE 64 #define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) +static void omninet_process_read_urb(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + const struct omninet_header *hdr = urb->transfer_buffer; + const unsigned char *data; + size_t data_len; + + if (urb->actual_length <= OMNINET_HEADERLEN || !hdr->oh_len) + return; + + data = (char *)urb->transfer_buffer + OMNINET_HEADERLEN; + data_len = min_t(size_t, urb->actual_length - OMNINET_HEADERLEN, + hdr->oh_len); + tty_insert_flip_string(&port->port, data, data_len); + tty_flip_buffer_push(&port->port); +} + static void omninet_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; - unsigned char *data = urb->transfer_buffer; - struct omninet_header *header = (struct omninet_header *) &data[0]; int status = urb->status; int result; @@ -172,11 +187,7 @@ static void omninet_read_bulk_callback(struct urb *urb) return; } - if (urb->actual_length && header->oh_len) { - tty_insert_flip_string(&port->port, data + OMNINET_HEADERLEN, - header->oh_len); - tty_flip_buffer_push(&port->port); - } + omninet_process_read_urb(urb); /* Continue trying to always read */ result = usb_submit_urb(urb, GFP_ATOMIC); -- cgit v1.2.3 From fbf947736968cbb0e55ec4b5d861d31a4a106c99 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:23 +0200 Subject: USB: omninet: switch to generic read implementation Switch to the more efficient generic read implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/omninet.c | 43 +++---------------------------------------- 1 file changed, 3 insertions(+), 40 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 7aaf9692b334..5739bf6f7200 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -33,8 +33,7 @@ /* function prototypes */ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port); -static void omninet_close(struct usb_serial_port *port); -static void omninet_read_bulk_callback(struct urb *urb); +static void omninet_process_read_urb(struct urb *urb); static void omninet_write_bulk_callback(struct urb *urb); static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); @@ -61,11 +60,10 @@ static struct usb_serial_driver zyxel_omninet_device = { .port_probe = omninet_port_probe, .port_remove = omninet_port_remove, .open = omninet_open, - .close = omninet_close, .write = omninet_write, .write_room = omninet_write_room, - .read_bulk_callback = omninet_read_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback, + .process_read_urb = omninet_process_read_urb, .disconnect = omninet_disconnect, }; @@ -134,26 +132,13 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; struct usb_serial_port *wport; - int result = 0; wport = serial->port[1]; tty_port_tty_set(&wport->port, tty); - /* Start reading from the device */ - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) - dev_err(&port->dev, - "%s - failed submitting read urb, error %d\n", - __func__, result); - return result; -} - -static void omninet_close(struct usb_serial_port *port) -{ - usb_kill_urb(port->read_urb); + return usb_serial_generic_open(tty, port); } - #define OMNINET_HEADERLEN 4 #define OMNINET_BULKOUTSIZE 64 #define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) @@ -175,28 +160,6 @@ static void omninet_process_read_urb(struct urb *urb) tty_flip_buffer_push(&port->port); } -static void omninet_read_bulk_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - int status = urb->status; - int result; - - if (status) { - dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n", - __func__, status); - return; - } - - omninet_process_read_urb(urb); - - /* Continue trying to always read */ - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) - dev_err(&port->dev, - "%s - failed resubmitting read urb, error %d\n", - __func__, result); -} - static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { -- cgit v1.2.3 From 8e34c6c2ee9ed4cafe01e760e0c4bc1c8f7e9cb7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:24 +0200 Subject: USB: kobil_sct: fix broken debug code Replace broken and commented-out debug code with usb_serial_debug_data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 903d938e174b..da1a372fc46c 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -333,24 +333,8 @@ static void kobil_read_int_callback(struct urb *urb) } if (urb->actual_length) { - - /* BEGIN DEBUG */ - /* - char *dbg_data; - - dbg_data = kzalloc((3 * purb->actual_length + 10) - * sizeof(char), GFP_KERNEL); - if (! dbg_data) { - return; - } - for (i = 0; i < purb->actual_length; i++) { - sprintf(dbg_data +3*i, "%02X ", data[i]); - } - dev_dbg(&port->dev, " <-- %s\n", dbg_data); - kfree(dbg_data); - */ - /* END DEBUG */ - + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, + data); tty_insert_flip_string(&port->port, data, urb->actual_length); tty_flip_buffer_push(&port->port); } -- cgit v1.2.3 From 9c0343aa6cbbb62b8b829c87b15839f35bdebbf2 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:25 +0200 Subject: USB: kobil_sct: remove unused endpoint address Remove unused interrupt-in endpoint address from private data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index da1a372fc46c..5bcfd57267f7 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -107,7 +107,6 @@ static struct usb_serial_driver * const serial_drivers[] = { struct kobil_private { int write_int_endpoint_address; - int read_int_endpoint_address; unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */ int filled; /* index of the last char in buf */ int cur_pos; /* index of the next char to send in buf */ @@ -166,13 +165,6 @@ static int kobil_port_probe(struct usb_serial_port *port) priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress; } - if (usb_endpoint_is_int_in(&endpoint->desc)) { - dev_dbg(&serial->dev->dev, - "%s Found interrupt in endpoint. Address: %d\n", - __func__, endpoint->desc.bEndpointAddress); - priv->read_int_endpoint_address = - endpoint->desc.bEndpointAddress; - } } return 0; } -- cgit v1.2.3 From feb0a36a523b9fd07275b12f76b344901f884253 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:26 +0200 Subject: USB: kobil_sct: use port interrupt-out urb Use the port interrupt-out urb rather than abusing the port write_urb pointer and allocating a new urb at every open (but the first...). Note that the write_urb abuse would have led to a double free should there ever be interfaces with a bulk-out endpoint. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 75 +++++------------------------------------- 1 file changed, 8 insertions(+), 67 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5bcfd57267f7..78b48c31abf5 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -65,7 +65,7 @@ static int kobil_tiocmget(struct tty_struct *tty); static int kobil_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static void kobil_read_int_callback(struct urb *urb); -static void kobil_write_callback(struct urb *purb); +static void kobil_write_int_callback(struct urb *urb); static void kobil_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old); static void kobil_init_termios(struct tty_struct *tty); @@ -99,6 +99,7 @@ static struct usb_serial_driver kobil_device = { .write = kobil_write, .write_room = kobil_write_room, .read_int_callback = kobil_read_int_callback, + .write_int_callback = kobil_write_int_callback, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -106,7 +107,6 @@ static struct usb_serial_driver * const serial_drivers[] = { }; struct kobil_private { - int write_int_endpoint_address; unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */ int filled; /* index of the last char in buf */ int cur_pos; /* index of the next char to send in buf */ @@ -116,14 +116,8 @@ struct kobil_private { static int kobil_port_probe(struct usb_serial_port *port) { - int i; struct usb_serial *serial = port->serial; struct kobil_private *priv; - struct usb_device *pdev; - struct usb_host_config *actconfig; - struct usb_interface *interface; - struct usb_host_interface *altsetting; - struct usb_host_endpoint *endpoint; priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL); if (!priv) @@ -149,23 +143,6 @@ static int kobil_port_probe(struct usb_serial_port *port) } usb_set_serial_port_data(port, priv); - /* search for the necessary endpoints */ - pdev = serial->dev; - actconfig = pdev->actconfig; - interface = actconfig->interface[0]; - altsetting = interface->cur_altsetting; - endpoint = altsetting->endpoint; - - for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { - endpoint = &altsetting->endpoint[i]; - if (usb_endpoint_is_int_out(&endpoint->desc)) { - dev_dbg(&serial->dev->dev, - "%s Found interrupt out endpoint. Address: %d\n", - __func__, endpoint->desc.bEndpointAddress); - priv->write_int_endpoint_address = - endpoint->desc.bEndpointAddress; - } - } return 0; } @@ -197,7 +174,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) struct kobil_private *priv; unsigned char *transfer_buffer; int transfer_buffer_length = 8; - int write_urb_transfer_buffer_length = 8; priv = usb_get_serial_port_data(port); @@ -206,27 +182,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) if (!transfer_buffer) return -ENOMEM; - /* allocate write_urb */ - if (!port->write_urb) { - dev_dbg(dev, "%s - Allocating port->write_urb\n", __func__); - port->write_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port->write_urb) { - dev_dbg(dev, "%s - usb_alloc_urb failed\n", __func__); - kfree(transfer_buffer); - return -ENOMEM; - } - } - - /* allocate memory for write_urb transfer buffer */ - port->write_urb->transfer_buffer = - kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL); - if (!port->write_urb->transfer_buffer) { - kfree(transfer_buffer); - usb_free_urb(port->write_urb); - port->write_urb = NULL; - return -ENOMEM; - } - /* get hardware version */ result = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), @@ -302,12 +257,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) static void kobil_close(struct usb_serial_port *port) { /* FIXME: Add rts/dtr methods */ - if (port->write_urb) { - usb_poison_urb(port->write_urb); - kfree(port->write_urb->transfer_buffer); - usb_free_urb(port->write_urb); - port->write_urb = NULL; - } + usb_kill_urb(port->interrupt_out_urb); usb_kill_urb(port->interrupt_in_urb); } @@ -336,7 +286,7 @@ static void kobil_read_int_callback(struct urb *urb) } -static void kobil_write_callback(struct urb *purb) +static void kobil_write_int_callback(struct urb *urb) { } @@ -379,23 +329,14 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, while (todo > 0) { /* max 8 byte in one urb (endpoint size) */ - length = (todo < 8) ? todo : 8; + length = min(todo, port->interrupt_out_size); /* copy data to transfer buffer */ - memcpy(port->write_urb->transfer_buffer, + memcpy(port->interrupt_out_buffer, priv->buf + priv->cur_pos, length); - usb_fill_int_urb(port->write_urb, - port->serial->dev, - usb_sndintpipe(port->serial->dev, - priv->write_int_endpoint_address), - port->write_urb->transfer_buffer, - length, - kobil_write_callback, - port, - 8 - ); + port->interrupt_out_urb->transfer_buffer_length = length; priv->cur_pos = priv->cur_pos + length; - result = usb_submit_urb(port->write_urb, GFP_NOIO); + result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO); dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result); todo = priv->filled - priv->cur_pos; -- cgit v1.2.3 From 35807187e4b35200b12edad319a36ee7a0167ba7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:27 +0200 Subject: USB: mct_u232: clean up read implementation The device uses the second interrupt-in endpoint of the interface for reading. Stop abusing the port read urb and store a pointer to the second interrupt-in urb as port-private data instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 3353c9ed7721..6a15adf53360 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -43,7 +43,6 @@ /* * Function prototypes */ -static int mct_u232_startup(struct usb_serial *serial); static int mct_u232_port_probe(struct usb_serial_port *port); static int mct_u232_port_remove(struct usb_serial_port *remove); static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); @@ -91,7 +90,6 @@ static struct usb_serial_driver mct_u232_device = { .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, .tiocmiwait = usb_serial_generic_tiocmiwait, - .attach = mct_u232_startup, .port_probe = mct_u232_port_probe, .port_remove = mct_u232_port_remove, .get_icount = usb_serial_generic_get_icount, @@ -102,6 +100,7 @@ static struct usb_serial_driver * const serial_drivers[] = { }; struct mct_u232_private { + struct urb *read_urb; spinlock_t lock; unsigned int control_state; /* Modem Line Setting (TIOCM) */ unsigned char last_lcr; /* Line Control Register */ @@ -376,22 +375,6 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, * Driver's tty interface functions */ -static int mct_u232_startup(struct usb_serial *serial) -{ - struct usb_serial_port *port, *rport; - - /* Puh, that's dirty */ - port = serial->port[0]; - rport = serial->port[1]; - /* No unlinking, it wasn't submitted yet. */ - usb_free_urb(port->read_urb); - port->read_urb = rport->interrupt_in_urb; - rport->interrupt_in_urb = NULL; - port->read_urb->context = port; - - return 0; -} /* mct_u232_startup */ - static int mct_u232_port_probe(struct usb_serial_port *port) { struct mct_u232_private *priv; @@ -400,6 +383,10 @@ static int mct_u232_port_probe(struct usb_serial_port *port) if (!priv) return -ENOMEM; + /* Use second interrupt-in endpoint for reading. */ + priv->read_urb = port->serial->port[1]->interrupt_in_urb; + priv->read_urb->context = port; + spin_lock_init(&priv->lock); usb_set_serial_port_data(port, priv); @@ -463,17 +450,17 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr); spin_unlock_irqrestore(&priv->lock, flags); - retval = usb_submit_urb(port->read_urb, GFP_KERNEL); + retval = usb_submit_urb(priv->read_urb, GFP_KERNEL); if (retval) { dev_err(&port->dev, - "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n", + "usb_submit_urb(read) failed pipe 0x%x err %d\n", port->read_urb->pipe, retval); goto error; } retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (retval) { - usb_kill_urb(port->read_urb); + usb_kill_urb(priv->read_urb); dev_err(&port->dev, "usb_submit_urb(read int) failed pipe 0x%x err %d", port->interrupt_in_urb->pipe, retval); @@ -503,11 +490,9 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) static void mct_u232_close(struct usb_serial_port *port) { - /* - * Must kill the read urb as it is actually an interrupt urb, which - * generic close thus fails to kill. - */ - usb_kill_urb(port->read_urb); + struct mct_u232_private *priv = usb_get_serial_port_data(port); + + usb_kill_urb(priv->read_urb); usb_kill_urb(port->interrupt_in_urb); usb_serial_generic_close(port); -- cgit v1.2.3 From cced926f0e4fb02a08d2d14e443631fe8a28db98 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:28 +0200 Subject: USB: symbolserial: use port interrupt-in urb Use the port interrupt-in urb rather managing a private one. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/symbolserial.c | 102 +++++--------------------------------- 1 file changed, 12 insertions(+), 90 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index be05e6caf9a3..32ebddf7f010 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -29,13 +29,6 @@ MODULE_DEVICE_TABLE(usb, id_table); /* This structure holds all of the individual device information */ struct symbol_private { struct usb_device *udev; - struct usb_serial *serial; - struct usb_serial_port *port; - unsigned char *int_buffer; - struct urb *int_urb; - int buffer_size; - u8 bInterval; - u8 int_address; spinlock_t lock; /* protects the following flags */ bool throttled; bool actually_throttled; @@ -44,9 +37,9 @@ struct symbol_private { static void symbol_int_callback(struct urb *urb) { - struct symbol_private *priv = urb->context; + struct usb_serial_port *port = urb->context; + struct symbol_private *priv = usb_get_serial_data(port->serial); unsigned char *data = urb->transfer_buffer; - struct usb_serial_port *port = priv->port; int status = urb->status; int result; int data_length; @@ -94,12 +87,7 @@ exit: /* Continue trying to always read if we should */ if (!priv->throttled) { - usb_fill_int_urb(priv->int_urb, priv->udev, - usb_rcvintpipe(priv->udev, - priv->int_address), - priv->int_buffer, priv->buffer_size, - symbol_int_callback, priv, priv->bInterval); - result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", @@ -118,15 +106,10 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) spin_lock_irqsave(&priv->lock, flags); priv->throttled = false; priv->actually_throttled = false; - priv->port = port; spin_unlock_irqrestore(&priv->lock, flags); /* Start reading from the device */ - usb_fill_int_urb(priv->int_urb, priv->udev, - usb_rcvintpipe(priv->udev, priv->int_address), - priv->int_buffer, priv->buffer_size, - symbol_int_callback, priv, priv->bInterval); - result = usb_submit_urb(priv->int_urb, GFP_KERNEL); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", @@ -136,10 +119,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port) static void symbol_close(struct usb_serial_port *port) { - struct symbol_private *priv = usb_get_serial_data(port->serial); - - /* shutdown our urbs */ - usb_kill_urb(priv->int_urb); + usb_kill_urb(port->interrupt_in_urb); } static void symbol_throttle(struct tty_struct *tty) @@ -166,7 +146,7 @@ static void symbol_unthrottle(struct tty_struct *tty) spin_unlock_irq(&priv->lock); if (was_throttled) { - result = usb_submit_urb(priv->int_urb, GFP_KERNEL); + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result) dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", @@ -177,10 +157,11 @@ static void symbol_unthrottle(struct tty_struct *tty) static int symbol_startup(struct usb_serial *serial) { struct symbol_private *priv; - struct usb_host_interface *intf; - int i; - int retval = -ENOMEM; - bool int_in_found = false; + + if (!serial->num_interrupt_in) { + dev_err(&serial->dev->dev, "no interrupt-in endpoint\n"); + return -ENODEV; + } /* create our private serial structure */ priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -189,75 +170,16 @@ static int symbol_startup(struct usb_serial *serial) return -ENOMEM; } spin_lock_init(&priv->lock); - priv->serial = serial; - priv->port = serial->port[0]; priv->udev = serial->dev; - /* find our interrupt endpoint */ - intf = serial->interface->altsetting; - for (i = 0; i < intf->desc.bNumEndpoints; ++i) { - struct usb_endpoint_descriptor *endpoint; - - endpoint = &intf->endpoint[i].desc; - if (!usb_endpoint_is_int_in(endpoint)) - continue; - - priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!priv->int_urb) { - dev_err(&priv->udev->dev, "out of memory\n"); - goto error; - } - - priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; - priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); - if (!priv->int_buffer) { - dev_err(&priv->udev->dev, "out of memory\n"); - goto error; - } - - priv->int_address = endpoint->bEndpointAddress; - priv->bInterval = endpoint->bInterval; - - /* set up our int urb */ - usb_fill_int_urb(priv->int_urb, priv->udev, - usb_rcvintpipe(priv->udev, - endpoint->bEndpointAddress), - priv->int_buffer, priv->buffer_size, - symbol_int_callback, priv, priv->bInterval); - - int_in_found = true; - break; - } - - if (!int_in_found) { - dev_err(&priv->udev->dev, - "Error - the proper endpoints were not found!\n"); - goto error; - } - usb_set_serial_data(serial, priv); return 0; - -error: - usb_free_urb(priv->int_urb); - kfree(priv->int_buffer); - kfree(priv); - return retval; -} - -static void symbol_disconnect(struct usb_serial *serial) -{ - struct symbol_private *priv = usb_get_serial_data(serial); - - usb_kill_urb(priv->int_urb); - usb_free_urb(priv->int_urb); } static void symbol_release(struct usb_serial *serial) { struct symbol_private *priv = usb_get_serial_data(serial); - kfree(priv->int_buffer); kfree(priv); } @@ -271,10 +193,10 @@ static struct usb_serial_driver symbol_device = { .attach = symbol_startup, .open = symbol_open, .close = symbol_close, - .disconnect = symbol_disconnect, .release = symbol_release, .throttle = symbol_throttle, .unthrottle = symbol_unthrottle, + .read_int_callback = symbol_int_callback, }; static struct usb_serial_driver * const serial_drivers[] = { -- cgit v1.2.3 From ef31025d6811320ead36a8902b16090dea01b34c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:29 +0200 Subject: USB: symbolserial: remove unused private data Use port device for debug messages in interrupt-urb callback and remove unused private data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/symbolserial.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 32ebddf7f010..2c2bfa1994f8 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -26,13 +26,10 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); -/* This structure holds all of the individual device information */ struct symbol_private { - struct usb_device *udev; spinlock_t lock; /* protects the following flags */ bool throttled; bool actually_throttled; - bool rts; }; static void symbol_int_callback(struct urb *urb) @@ -77,7 +74,7 @@ static void symbol_int_callback(struct urb *urb) tty_insert_flip_string(&port->port, &data[1], data_length); tty_flip_buffer_push(&port->port); } else { - dev_dbg(&priv->udev->dev, + dev_dbg(&port->dev, "Improper amount of data received from the device, " "%d bytes", urb->actual_length); } @@ -170,7 +167,6 @@ static int symbol_startup(struct usb_serial *serial) return -ENOMEM; } spin_lock_init(&priv->lock); - priv->udev = serial->dev; usb_set_serial_data(serial, priv); return 0; -- cgit v1.2.3 From a85796ee514954b1ef5efe8928ef38777aab8c2d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2013 18:01:30 +0200 Subject: USB: symbolserial: move private-data allocation to port_probe Allocate port-private data in port-probe rather than in attach. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/symbolserial.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 2c2bfa1994f8..9b1648945e7a 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -1,6 +1,7 @@ /* * Symbol USB barcode to serial driver * + * Copyright (C) 2013 Johan Hovold * Copyright (C) 2009 Greg Kroah-Hartman * Copyright (C) 2009 Novell Inc. * @@ -35,7 +36,7 @@ struct symbol_private { static void symbol_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct symbol_private *priv = usb_get_serial_data(port->serial); + struct symbol_private *priv = usb_get_serial_port_data(port); unsigned char *data = urb->transfer_buffer; int status = urb->status; int result; @@ -153,30 +154,36 @@ static void symbol_unthrottle(struct tty_struct *tty) static int symbol_startup(struct usb_serial *serial) { - struct symbol_private *priv; - if (!serial->num_interrupt_in) { dev_err(&serial->dev->dev, "no interrupt-in endpoint\n"); return -ENODEV; } - /* create our private serial structure */ + return 0; +} + +static int symbol_port_probe(struct usb_serial_port *port) +{ + struct symbol_private *priv; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + if (!priv) return -ENOMEM; - } + spin_lock_init(&priv->lock); - usb_set_serial_data(serial, priv); + usb_set_serial_port_data(port, priv); + return 0; } -static void symbol_release(struct usb_serial *serial) +static int symbol_port_remove(struct usb_serial_port *port) { - struct symbol_private *priv = usb_get_serial_data(serial); + struct symbol_private *priv = usb_get_serial_port_data(port); kfree(priv); + + return 0; } static struct usb_serial_driver symbol_device = { @@ -187,9 +194,10 @@ static struct usb_serial_driver symbol_device = { .id_table = id_table, .num_ports = 1, .attach = symbol_startup, + .port_probe = symbol_port_probe, + .port_remove = symbol_port_remove, .open = symbol_open, .close = symbol_close, - .release = symbol_release, .throttle = symbol_throttle, .unthrottle = symbol_unthrottle, .read_int_callback = symbol_int_callback, -- cgit v1.2.3 From b6fd35ee5766143d6bc3c333edf374c336ebdca6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:17 +0200 Subject: USB: io_ti: fix TIOCGSERIAL Fix regression introduced by commit f40d78155 ("USB: io_ti: kill custom closing_wait implementation") which made TIOCGSERIAL return the wrong value for closing_wait. Signed-off-by: Johan Hovold Cc: stable # 3.9 Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index f2a1601775b1..ab979a2e6953 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2357,7 +2357,7 @@ static int get_serial_info(struct edgeport_port *edge_port, cwait = edge_port->port->port.closing_wait; if (cwait != ASYNC_CLOSING_WAIT_NONE) - cwait = jiffies_to_msecs(closing_wait) / 10; + cwait = jiffies_to_msecs(cwait) / 10; memset(&tmp, 0, sizeof(tmp)); -- cgit v1.2.3 From a8ec374f96da361e7a31113b1e471065adf33d7c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:18 +0200 Subject: USB: io_ti: remove redundant wait_until_sent Remove redundant wait_until_sent, which has already been handled by the tty-layer, from break_ctl. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index ab979a2e6953..158bf4bc29cc 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2400,8 +2400,6 @@ static void edge_break(struct tty_struct *tty, int break_state) int status; int bv = 0; /* Off */ - tty_wait_until_sent(tty, 0); - if (break_state == -1) bv = 1; /* On */ status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); -- cgit v1.2.3 From 113ec31e16afe197a668d4b63ce41e04dc706c64 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:19 +0200 Subject: USB: ti_usb_3410_5052: move write-fifo flushing to close Move write-fifo flushing from ti_drain to close where it belongs. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 07268591b0d1..a49d2a746ccf 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -128,7 +128,7 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg); static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush); +static void ti_drain(struct ti_port *tport, unsigned long timeout); static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty); static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty); @@ -601,6 +601,7 @@ static void ti_close(struct usb_serial_port *port) int port_number; int status; int do_unlock; + unsigned long flags; tdev = usb_get_serial_data(port->serial); tport = usb_get_serial_port_data(port); @@ -609,11 +610,14 @@ static void ti_close(struct usb_serial_port *port) tport->tp_is_open = 0; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1); + ti_drain(tport, (tport->tp_closing_wait*HZ)/100); usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); tport->tp_write_urb_in_use = 0; + spin_lock_irqsave(&tport->tp_lock, flags); + kfifo_reset_out(&tport->write_fifo); + spin_unlock_irqrestore(&tport->tp_lock, flags); port_number = port->number - port->serial->minor; @@ -965,7 +969,7 @@ static void ti_break(struct tty_struct *tty, int break_state) if (tport == NULL) return; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0); + ti_drain(tport, (tport->tp_closing_wait*HZ)/100); status = ti_write_byte(port, tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, @@ -1361,7 +1365,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) } -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) +static void ti_drain(struct ti_port *tport, unsigned long timeout) { struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; @@ -1386,11 +1390,6 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) } set_current_state(TASK_RUNNING); remove_wait_queue(&tport->tp_write_wait, &wait); - - /* flush any remaining data in the buffer */ - if (flush) - kfifo_reset_out(&tport->write_fifo); - spin_unlock_irq(&tport->tp_lock); mutex_lock(&port->serial->disc_mutex); -- cgit v1.2.3 From b5784f7d8528926d69c5868f1ddb2af99f85e799 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:20 +0200 Subject: USB: ti_usb_3410_5052: remove lsr from port data The line status register is only polled so let's not keep a possibly outdated value in the port data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index a49d2a746ccf..3ed8ecafe597 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -67,7 +67,6 @@ struct ti_port { int tp_is_open; __u8 tp_msr; - __u8 tp_lsr; __u8 tp_shadow_mcr; __u8 tp_uart_mode; /* 232 or 485 modes */ unsigned int tp_uart_base_addr; @@ -121,7 +120,7 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data, int length); static void ti_send(struct ti_port *tport); static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); -static int ti_get_lsr(struct ti_port *tport); +static int ti_get_lsr(struct ti_port *tport, u8 *lsr); static int ti_get_serial_info(struct ti_port *tport, struct serial_struct __user *ret_arg); static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, @@ -1251,7 +1250,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr) } -static int ti_get_lsr(struct ti_port *tport) +static int ti_get_lsr(struct ti_port *tport, u8 *lsr) { int size, status; struct ti_device *tdev = tport->tp_tdev; @@ -1277,7 +1276,7 @@ static int ti_get_lsr(struct ti_port *tport) dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR); - tport->tp_lsr = data->bLSR; + *lsr = data->bLSR; free_data: kfree(data); @@ -1370,6 +1369,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout) struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; wait_queue_t wait; + u8 lsr; spin_lock_irq(&tport->tp_lock); @@ -1396,11 +1396,11 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout) /* wait for data to drain from the device */ /* wait for empty tx register, plus 20 ms */ timeout += jiffies; - tport->tp_lsr &= ~TI_LSR_TX_EMPTY; + lsr = 0; while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error + && !(lsr & TI_LSR_TX_EMPTY) && !tdev->td_urb_error && !port->serial->disconnected) { - if (ti_get_lsr(tport)) + if (ti_get_lsr(tport, &lsr)) break; mutex_unlock(&port->serial->disc_mutex); msleep_interruptible(20); -- cgit v1.2.3 From 2c992cd73772bd0ef107536e8e3399d28493caa8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:21 +0200 Subject: USB: ti_usb_3410_5052: query hardware-buffer status in chars_in_buffer Query hardware-buffer status in chars_in_buffer should the write fifo be empty. This is needed to make the tty layer wait for hardware buffers to drain on close. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 3ed8ecafe597..062b6d872ea3 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -687,6 +687,8 @@ static int ti_chars_in_buffer(struct tty_struct *tty) struct ti_port *tport = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; + int ret; + u8 lsr; if (tport == NULL) return 0; @@ -695,6 +697,12 @@ static int ti_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&tport->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); + if (!chars) { + ret = ti_get_lsr(tport, &lsr); + if (!ret && !(lsr & TI_LSR_TX_EMPTY)) + chars = 1; + } + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } -- cgit v1.2.3 From c0419024332a73f299bdd7a6875a00cf3942a054 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:22 +0200 Subject: USB: ti_usb_3410_5052: remove redundant drain from break_ctl Remove redundant drain, which has already been handled by the tty-layer, from break_ctl. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 062b6d872ea3..6a40823e85c4 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -976,8 +976,6 @@ static void ti_break(struct tty_struct *tty, int break_state) if (tport == NULL) return; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100); - status = ti_write_byte(port, tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); -- cgit v1.2.3 From f1175daa5312dd1b3f5940413c7c41ed195066f7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:23 +0200 Subject: USB: ti_usb_3410_5052: kill custom closing_wait Kill custom closing_wait implementation and let the tty-layer handle it instead. Note that the port drain-delay is set to three characters to keep the 20ms delay after wait_until_sent at low baudrates (1200 baud) during close. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 69 ++++++++--------------------------- 1 file changed, 15 insertions(+), 54 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 6a40823e85c4..4b52132812c1 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -71,7 +71,6 @@ struct ti_port { __u8 tp_uart_mode; /* 232 or 485 modes */ unsigned int tp_uart_base_addr; int tp_flags; - int tp_closing_wait;/* in .01 secs */ wait_queue_head_t tp_write_wait; struct ti_device *tp_tdev; struct usb_serial_port *tp_port; @@ -127,8 +126,6 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg); static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); -static void ti_drain(struct ti_port *tport, unsigned long timeout); - static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty); static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty); @@ -428,7 +425,7 @@ static int ti_port_probe(struct usb_serial_port *port) tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; else tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; - tport->tp_closing_wait = closing_wait; + port->port.closing_wait = msecs_to_jiffies(10 * closing_wait); init_waitqueue_head(&tport->tp_write_wait); if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { kfree(tport); @@ -581,6 +578,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) tport->tp_is_open = 1; ++tdev->td_open_port_count; + port->port.drain_delay = 3; + goto release_lock; unlink_int_urb: @@ -609,8 +608,6 @@ static void ti_close(struct usb_serial_port *port) tport->tp_is_open = 0; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100); - usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); tport->tp_write_urb_in_use = 0; @@ -1295,10 +1292,15 @@ static int ti_get_serial_info(struct ti_port *tport, { struct usb_serial_port *port = tport->tp_port; struct serial_struct ret_serial; + unsigned cwait; if (!ret_arg) return -EFAULT; + cwait = port->port.closing_wait; + if (cwait != ASYNC_CLOSING_WAIT_NONE) + cwait = jiffies_to_msecs(cwait) / 10; + memset(&ret_serial, 0, sizeof(ret_serial)); ret_serial.type = PORT_16550A; @@ -1307,7 +1309,7 @@ static int ti_get_serial_info(struct ti_port *tport, ret_serial.flags = tport->tp_flags; ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; - ret_serial.closing_wait = tport->tp_closing_wait; + ret_serial.closing_wait = cwait; if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg))) return -EFAULT; @@ -1320,12 +1322,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg) { struct serial_struct new_serial; + unsigned cwait; if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) return -EFAULT; + cwait = new_serial.closing_wait; + if (cwait != ASYNC_CLOSING_WAIT_NONE) + cwait = msecs_to_jiffies(10 * new_serial.closing_wait); + tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; - tport->tp_closing_wait = new_serial.closing_wait; + tport->tp_port->port.closing_wait = cwait; return 0; } @@ -1370,52 +1377,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) } -static void ti_drain(struct ti_port *tport, unsigned long timeout) -{ - struct ti_device *tdev = tport->tp_tdev; - struct usb_serial_port *port = tport->tp_port; - wait_queue_t wait; - u8 lsr; - - spin_lock_irq(&tport->tp_lock); - - /* wait for data to drain from the buffer */ - tdev->td_urb_error = 0; - init_waitqueue_entry(&wait, current); - add_wait_queue(&tport->tp_write_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (kfifo_len(&tport->write_fifo) == 0 - || timeout == 0 || signal_pending(current) - || tdev->td_urb_error - || port->serial->disconnected) /* disconnect */ - break; - spin_unlock_irq(&tport->tp_lock); - timeout = schedule_timeout(timeout); - spin_lock_irq(&tport->tp_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&tport->tp_write_wait, &wait); - spin_unlock_irq(&tport->tp_lock); - - mutex_lock(&port->serial->disc_mutex); - /* wait for data to drain from the device */ - /* wait for empty tx register, plus 20 ms */ - timeout += jiffies; - lsr = 0; - while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && !(lsr & TI_LSR_TX_EMPTY) && !tdev->td_urb_error - && !port->serial->disconnected) { - if (ti_get_lsr(tport, &lsr)) - break; - mutex_unlock(&port->serial->disc_mutex); - msleep_interruptible(20); - mutex_lock(&port->serial->disc_mutex); - } - mutex_unlock(&port->serial->disc_mutex); -} - - static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty) { unsigned long flags; -- cgit v1.2.3 From 9f06d15f8db6946e41f73196a122b84a37938878 Mon Sep 17 00:00:00 2001 From: Adrian Thomasset Date: Tue, 23 Apr 2013 12:46:29 +0100 Subject: USB: ftdi_sio: correct ST Micro Connect Lite PIDs The current ST Micro Connect Lite uses the FT4232H hi-speed quad USB UART FTDI chip. It is also possible to drive STM reference targets populated with an on-board JTAG debugger based on the FT2232H chip with the same STMicroelectronics tools. For this reason, the ST Micro Connect Lite PIDs should be ST_STMCLT_2232_PID: 0x3746 ST_STMCLT_4232_PID: 0x3747 Signed-off-by: Adrian Thomasset Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 4 +++- drivers/usb/serial/ftdi_sio_ids.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index fc7bd147d3b1..e4d7fbd7e4e7 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -869,7 +869,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), + { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(ST_VID, ST_STMCLT_4232_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 3c003512f60a..98528270c43c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1151,7 +1151,8 @@ * STMicroelectonics */ #define ST_VID 0x0483 -#define ST_STMCLT1030_PID 0x3747 /* ST Micro Connect Lite STMCLT1030 */ +#define ST_STMCLT_2232_PID 0x3746 +#define ST_STMCLT_4232_PID 0x3747 /* * Papouch products (http://www.papouch.com/) -- cgit v1.2.3 From d19bf5cedfd7d53854a3bd699c98b467b139833b Mon Sep 17 00:00:00 2001 From: Filippo Turato Date: Sat, 20 Apr 2013 15:04:08 +0200 Subject: USB: serial: option: Added support Olivetti Olicard 145 This adds PID for Olivetti Olicard 145 in option.c Signed-off-by: Filippo Turato Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e1bff4b9af06..bff059a19e2f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -347,6 +347,7 @@ static void option_instat_callback(struct urb *urb); /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c #define OLIVETTI_PRODUCT_OLICARD100 0xc000 +#define OLIVETTI_PRODUCT_OLICARD145 0xc003 /* Celot products */ #define CELOT_VENDOR_ID 0x211f @@ -1273,6 +1274,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ -- cgit v1.2.3 From 71d9a2b95fc9c9474d46d764336efd7a5a805555 Mon Sep 17 00:00:00 2001 From: Adrian Thomasset Date: Wed, 24 Apr 2013 11:37:35 +0100 Subject: USB: ftdi_sio: enable two UART ports on ST Microconnect Lite The FT4232H used in the ST Micro Connect Lite has four hi-speed UART ports. The first two ports are reserved for the JTAG interface. We enable by default ports 2 and 3 as UARTs (where port 2 is a conventional RS-232 UART) Signed-off-by: Adrian Thomasset Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index e4d7fbd7e4e7..242b5776648a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1789,20 +1789,24 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) } /* - * First and second port on STMCLiteadaptors is reserved for JTAG interface - * and the forth port for pio + * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's + * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and + * can be accessed from userspace. + * The next two ports are enabled as UARTs by default, where port 2 is + * a conventional RS-232 UART. */ static int ftdi_stmclite_probe(struct usb_serial *serial) { struct usb_device *udev = serial->dev; struct usb_interface *interface = serial->interface; - if (interface == udev->actconfig->interface[2]) - return 0; - - dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); + if (interface == udev->actconfig->interface[0] || + interface == udev->actconfig->interface[1]) { + dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n"); + return -ENODEV; + } - return -ENODEV; + return 0; } /* -- cgit v1.2.3