diff options
Diffstat (limited to 'drivers/usb/serial')
30 files changed, 716 insertions, 424 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 35a2373cde6..9374bd2aba2 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -97,13 +97,19 @@ static int usb_serial_device_remove(struct device *dev) struct usb_serial_port *port; int retval = 0; int minor; + int autopm_err; port = to_usb_serial_port(dev); if (!port) return -ENODEV; - /* make sure suspend/resume doesn't race against port_remove */ - usb_autopm_get_interface(port->serial->interface); + /* + * Make sure suspend/resume doesn't race against port_remove. + * + * Note that no further runtime PM callbacks will be made if + * autopm_get fails. + */ + autopm_err = usb_autopm_get_interface(port->serial->interface); minor = port->minor; tty_unregister_device(usb_serial_tty_driver, minor); @@ -117,7 +123,9 @@ static int usb_serial_device_remove(struct device *dev) dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", driver->description, minor); - usb_autopm_put_interface(port->serial->interface); + if (!autopm_err) + usb_autopm_put_interface(port->serial->interface); + return retval; } diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 82371f61f23..2d72aa3564a 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -323,11 +323,11 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) if (r) goto out; - dev_dbg(&port->dev, "%s - submitting interrupt urb", __func__); + dev_dbg(&port->dev, "%s - submitting interrupt urb\n", __func__); r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (r) { - dev_err(&port->dev, "%s - failed submitting interrupt urb," - " error %d\n", __func__, r); + dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n", + __func__, r); ch341_close(port); goto out; } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 95fa1217afd..330df5ce435 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -104,6 +104,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ + { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ @@ -152,6 +153,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ + { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 0ac3b3b3236..2916dea3ede 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -220,7 +220,7 @@ static int cyberjack_write(struct tty_struct *tty, result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { dev_err(&port->dev, - "%s - failed submitting write urb, error %d", + "%s - failed submitting write urb, error %d\n", __func__, result); /* Throw away data. No better idea what to do with it. */ priv->wrfilled = 0; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index bccb1223143..01bf5339281 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -279,7 +279,7 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) * the generic firmware, but are not used with * NMEA and SiRF protocols */ dev_dbg(&port->dev, - "%s - failed setting baud rate, unsupported speed of %d on Earthmate GPS", + "%s - failed setting baud rate, unsupported speed of %d on Earthmate GPS\n", __func__, new_rate); return -1; } @@ -1224,7 +1224,6 @@ static void cypress_write_int_callback(struct urb *urb) struct usb_serial_port *port = urb->context; struct cypress_private *priv = usb_get_serial_port_data(port); struct device *dev = &urb->dev->dev; - int result; int status = urb->status; switch (status) { @@ -1239,21 +1238,9 @@ static void cypress_write_int_callback(struct urb *urb) __func__, status); priv->write_urb_in_use = 0; return; - case -EPIPE: /* no break needed; clear halt and resubmit */ - if (!priv->comm_is_ok) - break; - usb_clear_halt(port->serial->dev, 0x02); - /* error in the urb, so we have to resubmit it */ - dev_dbg(dev, "%s - nonzero write bulk status received: %d\n", - __func__, status); - port->interrupt_out_urb->transfer_buffer_length = 1; - result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); - if (!result) - return; - dev_err(dev, "%s - failed resubmitting write urb, error %d\n", - __func__, result); - cypress_set_dead(port); - break; + case -EPIPE: + /* Cannot call usb_clear_halt while in_interrupt */ + /* FALLTHROUGH */ default: dev_err(dev, "%s - unexpected nonzero write status received: %d\n", __func__, status); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ce0d7b0db01..8a3813be1b2 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -152,6 +152,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, @@ -191,6 +192,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, + { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_LP101_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TAGSYS_P200X_PID) }, { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, @@ -577,6 +580,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ @@ -715,7 +720,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, - { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, + { USB_DEVICE(TESTO_VID, TESTO_1_PID) }, + { USB_DEVICE(TESTO_VID, TESTO_3_PID) }, { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, @@ -904,6 +910,43 @@ static const struct usb_device_id id_table_combined[] = { /* Crucible Devices */ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, + /* Cressi Devices */ + { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) }, + /* Brainboxes Devices */ + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, + /* Infineon Devices */ + { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) }, { } /* Terminating entry */ }; @@ -1526,14 +1569,17 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port) struct usb_device *udev = serial->dev; struct usb_interface *interface = serial->interface; - struct usb_endpoint_descriptor *ep_desc = &interface->cur_altsetting->endpoint[1].desc; + struct usb_endpoint_descriptor *ep_desc; unsigned num_endpoints; - int i; + unsigned i; num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); + if (!num_endpoints) + return; + /* NOTE: some customers have programmed FT232R/FT245R devices * with an endpoint size of 0 - not good. In this case, we * want to override the endpoint descriptor setting and use a diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index a7019d1e305..c4777bc6aee 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -50,6 +50,7 @@ #define TI_XDS100V2_PID 0xa6d0 #define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */ +#define FTDI_EV3CON_PID 0xABB9 /* Mindstorms EV3 Console Adapter */ /* US Interface Navigator (http://www.usinterface.com/) */ #define FTDI_USINT_CAT_PID 0xb810 /* Navigator CAT and 2nd PTT lines */ @@ -363,6 +364,12 @@ /* Sprog II (Andrew Crosland's SprogII DCC interface) */ #define FTDI_SPROG_II 0xF0C8 +/* + * Two of the Tagsys RFID Readers + */ +#define FTDI_TAGSYS_LP101_PID 0xF0E9 /* Tagsys L-P101 RFID*/ +#define FTDI_TAGSYS_P200X_PID 0xF0EE /* Tagsys Medio P200x RFID*/ + /* an infrared receiver for user access control with IR tags */ #define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ @@ -531,6 +538,11 @@ */ #define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ +/* + * NovaTech product ids (FTDI_VID) + */ +#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */ + /********************************/ /** third-party VID/PID combos **/ @@ -572,6 +584,12 @@ #define RATOC_PRODUCT_ID_USB60F 0xb020 /* + * Infineon Technologies + */ +#define INFINEON_VID 0x058b +#define INFINEON_TRIBOARD_PID 0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */ + +/* * Acton Research Corp. */ #define ACTON_VID 0x0647 /* Vendor ID */ @@ -786,7 +804,8 @@ * Submitted by Colin Leroy */ #define TESTO_VID 0x128D -#define TESTO_USB_INTERFACE_PID 0x0001 +#define TESTO_1_PID 0x0001 +#define TESTO_3_PID 0x0003 /* * Mobility Electronics products. @@ -1313,3 +1332,46 @@ * Manufacturer: Smart GSM Team */ #define FTDI_Z3X_PID 0x0011 + +/* + * Product: Cressi PC Interface + * Manufacturer: Cressi + */ +#define FTDI_CRESSI_PID 0x87d0 + +/* + * Brainboxes devices + */ +#define BRAINBOXES_VID 0x05d1 +#define BRAINBOXES_VX_001_PID 0x1001 /* VX-001 ExpressCard 1 Port RS232 */ +#define BRAINBOXES_VX_012_PID 0x1002 /* VX-012 ExpressCard 2 Port RS232 */ +#define BRAINBOXES_VX_023_PID 0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */ +#define BRAINBOXES_VX_034_PID 0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */ +#define BRAINBOXES_US_101_PID 0x1011 /* US-101 1xRS232 */ +#define BRAINBOXES_US_324_PID 0x1013 /* US-324 1xRS422/485 1Mbaud */ +#define BRAINBOXES_US_606_1_PID 0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */ +#define BRAINBOXES_US_606_2_PID 0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */ +#define BRAINBOXES_US_606_3_PID 0x2003 /* US-606 6 Port RS232 Serial Port 4 and 6 */ +#define BRAINBOXES_US_701_1_PID 0x2011 /* US-701 4xRS232 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_701_2_PID 0x2012 /* US-701 4xRS422 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_279_1_PID 0x2021 /* US-279 8xRS422 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_279_2_PID 0x2022 /* US-279 8xRS422 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_279_3_PID 0x2023 /* US-279 8xRS422 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_279_4_PID 0x2024 /* US-279 8xRS422 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_346_1_PID 0x3011 /* US-346 4xRS422/485 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_346_2_PID 0x3012 /* US-346 4xRS422/485 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_257_PID 0x5001 /* US-257 2xRS232 1Mbaud */ +#define BRAINBOXES_US_313_PID 0x6001 /* US-313 2xRS422/485 1Mbaud */ +#define BRAINBOXES_US_357_PID 0x7001 /* US_357 1xRS232/422/485 */ +#define BRAINBOXES_US_842_1_PID 0x8001 /* US-842 8xRS422/485 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_842_2_PID 0x8002 /* US-842 8xRS422/485 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_842_3_PID 0x8003 /* US-842 8xRS422/485 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_842_4_PID 0x8004 /* US-842 8xRS422/485 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_160_1_PID 0x9001 /* US-160 16xRS232 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_160_2_PID 0x9002 /* US-160 16xRS232 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_160_3_PID 0x9003 /* US-160 16xRS232 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_160_4_PID 0x9004 /* US-160 16xRS232 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_160_5_PID 0x9005 /* US-160 16xRS232 1Mbaud Port 9 and 10 */ +#define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */ +#define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */ +#define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */ diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index b63ce023f96..1bd192290b0 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -332,9 +332,9 @@ void usb_serial_generic_process_read_urb(struct urb *urb) * stuff like 3G modems, so shortcircuit it in the 99.9999999% of * cases where the USB serial is not a console anyway. */ - if (!port->port.console || !port->sysrq) + if (!port->port.console || !port->sysrq) { tty_insert_flip_string(&port->port, ch, urb->actual_length); - else { + } else { for (i = 0; i < urb->actual_length; i++, ch++) { if (!usb_serial_handle_sysrq_char(port, *ch)) tty_insert_flip_char(&port->port, *ch, TTY_NORMAL); @@ -359,24 +359,38 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) 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", - __func__, urb->status); + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + dev_dbg(&port->dev, "%s - urb stopped: %d\n", + __func__, urb->status); return; + case -EPIPE: + dev_err(&port->dev, "%s - urb stopped: %d\n", + __func__, urb->status); + return; + default: + dev_err(&port->dev, "%s - nonzero urb status: %d\n", + __func__, urb->status); + goto resubmit; } usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); port->serial->type->process_read_urb(urb); +resubmit: /* Throttle the device if requested by tty */ spin_lock_irqsave(&port->lock, flags); port->throttled = port->throttle_req; if (!port->throttled) { spin_unlock_irqrestore(&port->lock, flags); usb_serial_generic_submit_read_urb(port, i, GFP_ATOMIC); - } else + } else { spin_unlock_irqrestore(&port->lock, flags); + } } EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); @@ -384,29 +398,38 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) { unsigned long flags; struct usb_serial_port *port = urb->context; - int status = urb->status; int i; - for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) + for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) { if (port->write_urbs[i] == urb) break; - + } spin_lock_irqsave(&port->lock, flags); port->tx_bytes -= urb->transfer_buffer_length; set_bit(i, &port->write_urbs_free); spin_unlock_irqrestore(&port->lock, flags); - if (status) { - dev_dbg(&port->dev, "%s - non-zero urb status: %d\n", - __func__, status); - - spin_lock_irqsave(&port->lock, flags); - kfifo_reset_out(&port->write_fifo); - spin_unlock_irqrestore(&port->lock, flags); - } else { - usb_serial_generic_write_start(port, GFP_ATOMIC); + switch (urb->status) { + case 0: + break; + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + dev_dbg(&port->dev, "%s - urb stopped: %d\n", + __func__, urb->status); + return; + case -EPIPE: + dev_err_console(port, "%s - urb stopped: %d\n", + __func__, urb->status); + return; + default: + dev_err_console(port, "%s - nonzero urb status: %d\n", + __func__, urb->status); + goto resubmit; } +resubmit: + usb_serial_generic_write_start(port, GFP_ATOMIC); usb_serial_port_softint(port); } EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a2db5be9c30..c0a42e9e677 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -28,6 +28,7 @@ #include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/serial.h> +#include <linux/swab.h> #include <linux/kfifo.h> #include <linux/ioctl.h> #include <linux/firmware.h> @@ -280,7 +281,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, { int status = 0; __u8 read_length; - __be16 be_start_address; + u16 be_start_address; dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length); @@ -296,10 +297,14 @@ static int read_download_mem(struct usb_device *dev, int start_address, if (read_length > 1) { dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length); } - be_start_address = cpu_to_be16(start_address); + /* + * NOTE: Must use swab as wIndex is sent in little-endian + * byte order regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vread_sync(dev, UMPC_MEMORY_READ, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, read_length); if (status) { @@ -394,7 +399,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, struct device *dev = &serial->serial->dev->dev; int status = 0; int write_length; - __be16 be_start_address; + u16 be_start_address; /* We can only send a maximum of 1 aligned byte page at a time */ @@ -409,11 +414,16 @@ static int write_i2c_mem(struct edgeport_serial *serial, __func__, start_address, write_length); usb_serial_debug_data(dev, __func__, write_length, buffer); - /* Write first page */ - be_start_address = cpu_to_be16(start_address); + /* + * Write first page. + * + * NOTE: Must use swab as wIndex is sent in little-endian byte order + * regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, write_length); if (status) { dev_dbg(dev, "%s - ERROR %d\n", __func__, status); @@ -436,11 +446,16 @@ static int write_i2c_mem(struct edgeport_serial *serial, __func__, start_address, write_length); usb_serial_debug_data(dev, __func__, write_length, buffer); - /* Write next page */ - be_start_address = cpu_to_be16(start_address); + /* + * Write next page. + * + * NOTE: Must use swab as wIndex is sent in little-endian byte + * order regardless of host byte order. + */ + be_start_address = swab16((u16)start_address); status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE, (__u16)address_type, - (__force __u16)be_start_address, + be_start_address, buffer, write_length); if (status) { dev_err(dev, "%s - ERROR %d\n", __func__, status); @@ -585,8 +600,8 @@ static int get_descriptor_addr(struct edgeport_serial *serial, if (rom_desc->Type == desc_type) return start_address; - start_address = start_address + sizeof(struct ti_i2c_desc) - + rom_desc->Size; + start_address = start_address + sizeof(struct ti_i2c_desc) + + le16_to_cpu(rom_desc->Size); } while ((start_address < TI_MAX_I2C_SIZE) && rom_desc->Type); @@ -599,7 +614,7 @@ static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer) __u16 i; __u8 cs = 0; - for (i = 0; i < rom_desc->Size; i++) + for (i = 0; i < le16_to_cpu(rom_desc->Size); i++) cs = (__u8)(cs + buffer[i]); if (cs != rom_desc->CheckSum) { @@ -650,7 +665,7 @@ static int check_i2c_image(struct edgeport_serial *serial) break; if ((start_address + sizeof(struct ti_i2c_desc) + - rom_desc->Size) > TI_MAX_I2C_SIZE) { + le16_to_cpu(rom_desc->Size)) > TI_MAX_I2C_SIZE) { status = -ENODEV; dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__); break; @@ -665,7 +680,8 @@ static int check_i2c_image(struct edgeport_serial *serial) /* Read the descriptor data */ status = read_rom(serial, start_address + sizeof(struct ti_i2c_desc), - rom_desc->Size, buffer); + le16_to_cpu(rom_desc->Size), + buffer); if (status) break; @@ -674,7 +690,7 @@ static int check_i2c_image(struct edgeport_serial *serial) break; } start_address = start_address + sizeof(struct ti_i2c_desc) + - rom_desc->Size; + le16_to_cpu(rom_desc->Size); } while ((rom_desc->Type != I2C_DESC_TYPE_ION) && (start_address < TI_MAX_I2C_SIZE)); @@ -712,7 +728,7 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) /* Read the descriptor data */ status = read_rom(serial, start_address+sizeof(struct ti_i2c_desc), - rom_desc->Size, buffer); + le16_to_cpu(rom_desc->Size), buffer); if (status) goto exit; @@ -805,7 +821,7 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data; i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK; - i2c_header->Size = (__u16)buffer_size; + i2c_header->Size = cpu_to_le16(buffer_size); i2c_header->CheckSum = cs; firmware_rec->Ver_Major = OperationalMajorVersion; firmware_rec->Ver_Minor = OperationalMinorVersion; diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h index 51f83fbb73b..6f6a856bc37 100644 --- a/drivers/usb/serial/io_usbvend.h +++ b/drivers/usb/serial/io_usbvend.h @@ -594,7 +594,7 @@ struct edge_boot_descriptor { struct ti_i2c_desc { __u8 Type; // Type of descriptor - __u16 Size; // Size of data only not including header + __le16 Size; // Size of data only not including header __u8 CheckSum; // Checksum (8 bit sum of data only) __u8 Data[0]; // Data starts here } __attribute__((packed)); diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index d00dae17d52..5ad4a0fb4b2 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1151,7 +1151,7 @@ static ssize_t vcc_mode_store(struct device *dev, goto fail_store_vcc_mode; } - dev_dbg(dev, "%s: setting vcc_mode = %ld", __func__, v); + dev_dbg(dev, "%s: setting vcc_mode = %ld\n", __func__, v); if ((v != 3) && (v != 5)) { dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 265c6776b08..93cb7cebda6 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -397,17 +397,6 @@ static void usa26_instat_callback(struct urb *urb) msg = (struct keyspan_usa26_portStatusMessage *)data; -#if 0 - dev_dbg(&urb->dev->dev, - "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d", - __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, - msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled, - msg->controlResponse); -#endif - - /* Now do something useful with the data */ - - /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port); @@ -523,9 +512,6 @@ static void usa28_instat_callback(struct urb *urb) goto exit; } - /*dev_dbg(&urb->dev->dev, "%s %12ph", __func__, data);*/ - - /* Now do something useful with the data */ msg = (struct keyspan_usa28_portStatusMessage *)data; /* Check port number from message and retrieve private data */ @@ -605,9 +591,6 @@ static void usa49_instat_callback(struct urb *urb) goto exit; } - /*dev_dbg(&urb->dev->dev, "%s: %11ph", __func__, data);*/ - - /* Now do something useful with the data */ msg = (struct keyspan_usa49_portStatusMessage *)data; /* Check port number from message and retrieve private data */ @@ -1552,14 +1535,14 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, this_urb = p_priv->outcont_urb; - dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe)); - /* Make sure we have an urb then send the message */ if (this_urb == NULL) { dev_dbg(&port->dev, "%s - oops no urb.\n", __func__); return -1; } + dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe)); + /* Save reset port val for resend. Don't overwrite resend for open/close condition. */ if ((reset_port + 1) > p_priv->resend_cont) @@ -1793,12 +1776,6 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__); -#if 0 - else { - dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__, - this_urb->transfer_buffer_length); - } -#endif return 0; } @@ -1976,13 +1953,6 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err); -#if 0 - else { - dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__, - outcont_urb, this_urb->transfer_buffer_length, - usb_pipeendpoint(this_urb->pipe)); - } -#endif return 0; } diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index e972412b614..742d827f876 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -189,7 +189,7 @@ exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) dev_err(&port->dev, - "%s - usb_submit_urb failed with result %d", + "%s - usb_submit_urb failed with result %d\n", __func__, retval); } diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index c88cc4966b2..d7440b7557a 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -201,7 +201,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, else { status = get_unaligned_le16(status_buf); - dev_info(&port->serial->dev->dev, "read status %x %x", + dev_info(&port->serial->dev->dev, "read status %x %x\n", status_buf[0], status_buf[1]); *line_state_p = klsi_105_status2linestate(status); @@ -464,7 +464,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, priv->cfg.baudrate = kl5kusb105a_sio_b115200; break; default: - dev_dbg(dev, "KLSI USB->Serial converter: unsupported baudrate request, using default of 9600"); + dev_dbg(dev, "unsupported baudrate, using 9600\n"); priv->cfg.baudrate = kl5kusb105a_sio_b9600; baud = 9600; break; diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 618c1c1f227..078f9ed419c 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -215,13 +215,13 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { /* Setting Baudrate, Parity and Stopbits */ result = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), + usb_sndctrlpipe(port->serial->dev, 0), SUSBCRequest_SetBaudRateParityAndStopBits, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, SUSBCR_SBR_9600 | SUSBCR_SPASB_EvenParity | SUSBCR_SPASB_1StopBit, 0, - transfer_buffer, + NULL, 0, KOBIL_TIMEOUT ); @@ -229,12 +229,12 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) /* reset all queues */ result = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), + usb_sndctrlpipe(port->serial->dev, 0), SUSBCRequest_Misc, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, SUSBCR_MSC_ResetAllQueues, 0, - transfer_buffer, + NULL, 0, KOBIL_TIMEOUT ); @@ -445,12 +445,12 @@ static int kobil_tiocmset(struct tty_struct *tty, else dev_dbg(dev, "%s - Clearing DTR\n", __func__); result = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), + usb_sndctrlpipe(port->serial->dev, 0), SUSBCRequest_SetStatusLinesOrQueues, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, ((dtr != 0) ? SUSBCR_SSL_SETDTR : SUSBCR_SSL_CLRDTR), 0, - transfer_buffer, + NULL, 0, KOBIL_TIMEOUT); } else { @@ -459,12 +459,12 @@ static int kobil_tiocmset(struct tty_struct *tty, else dev_dbg(dev, "%s - Clearing RTS\n", __func__); result = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), + usb_sndctrlpipe(port->serial->dev, 0), SUSBCRequest_SetStatusLinesOrQueues, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, ((rts != 0) ? SUSBCR_SSL_SETRTS : SUSBCR_SSL_CLRRTS), 0, - transfer_buffer, + NULL, 0, KOBIL_TIMEOUT); } @@ -514,7 +514,7 @@ static void kobil_set_termios(struct tty_struct *tty, tty_encode_baud_rate(tty, speed, speed); result = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), + usb_sndctrlpipe(port->serial->dev, 0), SUSBCRequest_SetBaudRateParityAndStopBits, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, urb_val, @@ -546,18 +546,19 @@ static int kobil_ioctl(struct tty_struct *tty, return -ENOBUFS; result = usb_control_msg(port->serial->dev, - usb_rcvctrlpipe(port->serial->dev, 0), + usb_sndctrlpipe(port->serial->dev, 0), SUSBCRequest_Misc, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, SUSBCR_MSC_ResetAllQueues, 0, - NULL, /* transfer_buffer, */ + NULL, 0, KOBIL_TIMEOUT ); dev_dbg(&port->dev, - "%s - Send reset_all_queues (FLUSH) URB returns: %i", __func__, result); + "%s - Send reset_all_queues (FLUSH) URB returns: %i\n", + __func__, result); kfree(transfer_buffer); return (result < 0) ? -EIO: 0; default: diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 4eb277225a7..dfd728a263d 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -209,7 +209,7 @@ static int write_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, index, NULL, 0, MOS_WDR_TIMEOUT); if (status < 0) dev_err(&usbdev->dev, - "mos7720: usb_control_msg() failed: %d", status); + "mos7720: usb_control_msg() failed: %d\n", status); return status; } @@ -240,7 +240,7 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, *data = *buf; else if (status < 0) dev_err(&usbdev->dev, - "mos7720: usb_control_msg() failed: %d", status); + "mos7720: usb_control_msg() failed: %d\n", status); kfree(buf); return status; @@ -399,7 +399,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, &mos_parport->deferred_urbs); spin_unlock_irqrestore(&mos_parport->listlock, flags); tasklet_schedule(&mos_parport->urb_tasklet); - dev_dbg(&usbdev->dev, "tasklet scheduled"); + dev_dbg(&usbdev->dev, "tasklet scheduled\n"); return 0; } @@ -418,7 +418,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, mutex_unlock(&serial->disc_mutex); if (ret_val) { dev_err(&usbdev->dev, - "%s: submit_urb() failed: %d", __func__, ret_val); + "%s: submit_urb() failed: %d\n", __func__, ret_val); spin_lock_irqsave(&mos_parport->listlock, flags); list_del(&urbtrack->urblist_entry); spin_unlock_irqrestore(&mos_parport->listlock, flags); @@ -656,7 +656,7 @@ static size_t parport_mos7715_write_compat(struct parport *pp, parport_epilogue(pp); if (retval) { dev_err(&mos_parport->serial->dev->dev, - "mos7720: usb_bulk_msg() failed: %d", retval); + "mos7720: usb_bulk_msg() failed: %d\n", retval); return 0; } return actual_len; @@ -875,7 +875,7 @@ static void mos7715_interrupt_callback(struct urb *urb) if (!(iir & 0x01)) { /* serial port interrupt pending */ switch (iir & 0x0f) { case SERIAL_IIR_RLS: - dev_dbg(dev, "Serial Port: Receiver status error or address bit detected in 9-bit mode\n\n"); + dev_dbg(dev, "Serial Port: Receiver status error or address bit detected in 9-bit mode\n"); break; case SERIAL_IIR_CTI: dev_dbg(dev, "Serial Port: Receiver time out\n"); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index e9d967ff521..393be562d87 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -522,11 +522,11 @@ static void mos7840_set_led_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d", + dev_dbg(&urb->dev->dev, "%s - urb shutting down: %d\n", __func__, urb->status); break; default: - dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d", + dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, urb->status); } } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5c86f57e4af..a9688940543 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -161,6 +161,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 #define NOVATELWIRELESS_PRODUCT_E362 0x9010 +#define NOVATELWIRELESS_PRODUCT_E371 0x9011 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 @@ -234,8 +235,31 @@ static void option_instat_callback(struct urb *urb); #define QUALCOMM_VENDOR_ID 0x05C6 #define CMOTECH_VENDOR_ID 0x16d8 -#define CMOTECH_PRODUCT_6008 0x6008 -#define CMOTECH_PRODUCT_6280 0x6280 +#define CMOTECH_PRODUCT_6001 0x6001 +#define CMOTECH_PRODUCT_CMU_300 0x6002 +#define CMOTECH_PRODUCT_6003 0x6003 +#define CMOTECH_PRODUCT_6004 0x6004 +#define CMOTECH_PRODUCT_6005 0x6005 +#define CMOTECH_PRODUCT_CGU_628A 0x6006 +#define CMOTECH_PRODUCT_CHE_628S 0x6007 +#define CMOTECH_PRODUCT_CMU_301 0x6008 +#define CMOTECH_PRODUCT_CHU_628 0x6280 +#define CMOTECH_PRODUCT_CHU_628S 0x6281 +#define CMOTECH_PRODUCT_CDU_680 0x6803 +#define CMOTECH_PRODUCT_CDU_685A 0x6804 +#define CMOTECH_PRODUCT_CHU_720S 0x7001 +#define CMOTECH_PRODUCT_7002 0x7002 +#define CMOTECH_PRODUCT_CHU_629K 0x7003 +#define CMOTECH_PRODUCT_7004 0x7004 +#define CMOTECH_PRODUCT_7005 0x7005 +#define CMOTECH_PRODUCT_CGU_629 0x7006 +#define CMOTECH_PRODUCT_CHU_629S 0x700a +#define CMOTECH_PRODUCT_CHU_720I 0x7211 +#define CMOTECH_PRODUCT_7212 0x7212 +#define CMOTECH_PRODUCT_7213 0x7213 +#define CMOTECH_PRODUCT_7251 0x7251 +#define CMOTECH_PRODUCT_7252 0x7252 +#define CMOTECH_PRODUCT_7253 0x7253 #define TELIT_VENDOR_ID 0x1bc7 #define TELIT_PRODUCT_UC864E 0x1003 @@ -243,6 +267,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 +#define TELIT_PRODUCT_UE910_V2 0x1012 #define TELIT_PRODUCT_LE920 0x1200 /* ZTE PRODUCTS */ @@ -286,6 +311,7 @@ static void option_instat_callback(struct urb *urb); #define ALCATEL_PRODUCT_X060S_X200 0x0000 #define ALCATEL_PRODUCT_X220_X500D 0x0017 #define ALCATEL_PRODUCT_L100V 0x011e +#define ALCATEL_PRODUCT_L800MA 0x0203 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -326,6 +352,9 @@ static void option_instat_callback(struct urb *urb); /* Zoom */ #define ZOOM_PRODUCT_4597 0x9607 +/* SpeedUp SU9800 usb 3g modem */ +#define SPEEDUP_PRODUCT_SU9800 0x9800 + /* Haier products */ #define HAIER_VENDOR_ID 0x201e #define HAIER_PRODUCT_CE100 0x2009 @@ -346,8 +375,13 @@ static void option_instat_callback(struct urb *urb); /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c #define OLIVETTI_PRODUCT_OLICARD100 0xc000 +#define OLIVETTI_PRODUCT_OLICARD120 0xc001 +#define OLIVETTI_PRODUCT_OLICARD140 0xc002 #define OLIVETTI_PRODUCT_OLICARD145 0xc003 +#define OLIVETTI_PRODUCT_OLICARD155 0xc004 #define OLIVETTI_PRODUCT_OLICARD200 0xc005 +#define OLIVETTI_PRODUCT_OLICARD160 0xc00a +#define OLIVETTI_PRODUCT_OLICARD500 0xc00b /* Celot products */ #define CELOT_VENDOR_ID 0x211f @@ -501,6 +535,10 @@ static const struct option_blacklist_info huawei_cdc12_blacklist = { .reserved = BIT(1) | BIT(2), }; +static const struct option_blacklist_info net_intf0_blacklist = { + .reserved = BIT(0), +}; + static const struct option_blacklist_info net_intf1_blacklist = { .reserved = BIT(1), }; @@ -982,6 +1020,7 @@ static const struct usb_device_id option_ids[] = { /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -1034,13 +1073,53 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ - { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ - { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6004) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6005) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_628A) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHE_628S), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_301), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_628S) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_680) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CDU_685A) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720S), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7002), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629K), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7004), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7005) }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CGU_629), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_629S), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CHU_720I), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7212), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7213), + .driver_info = (kernel_ulong_t)&net_intf0_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7251), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7252), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_7253), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ @@ -1362,7 +1441,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1267, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1268, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1269, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1270, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1271, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) }, @@ -1407,6 +1487,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G v2 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) }, @@ -1497,11 +1579,14 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L800MA), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist }, + { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, SPEEDUP_PRODUCT_SU9800, 0xff) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, @@ -1525,7 +1610,8 @@ static const struct usb_device_id option_ids[] = { /* Cinterion */ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, - { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, @@ -1535,12 +1621,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) }, { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, - - { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD140), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD155), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200), - .driver_info = (kernel_ulong_t)&net_intf6_blacklist - }, + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD160), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD500), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO 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.*/ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) }, @@ -1652,7 +1747,6 @@ static struct usb_serial_driver option_1port_device = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, - .set_termios = usb_wwan_set_termios, .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, @@ -1827,6 +1921,7 @@ static void option_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving IRQ data */ if (status != -ESHUTDOWN && status != -ENOENT) { + usb_mark_last_busy(port->serial->dev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err) dev_dbg(dev, "%s: resubmit intr urb failed. (%d)\n", @@ -1846,6 +1941,7 @@ static int option_send_setup(struct usb_serial_port *port) struct option_private *priv = intfdata->private; struct usb_wwan_port_private *portdata; int val = 0; + int res; portdata = usb_get_serial_port_data(port); @@ -1854,9 +1950,17 @@ static int option_send_setup(struct usb_serial_port *port) if (portdata->rts_state) val |= 0x02; - return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + res = usb_autopm_get_interface(serial->interface); + if (res) + return res; + + res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21, val, priv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); + + usb_autopm_put_interface(serial->interface); + + return res; } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2e22fc22c38..b3d5a35c0d4 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -83,6 +83,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index c38b8c00c06..42bc082896a 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -121,8 +121,11 @@ #define SUPERIAL_VENDOR_ID 0x5372 #define SUPERIAL_PRODUCT_ID 0x2303 -/* Hewlett-Packard LD220-HP POS Pole Display */ +/* Hewlett-Packard POS Pole Displays */ #define HP_VENDOR_ID 0x03f0 +#define HP_LD960_PRODUCT_ID 0x0b39 +#define HP_LCM220_PRODUCT_ID 0x3139 +#define HP_LCM960_PRODUCT_ID 0x3239 #define HP_LD220_PRODUCT_ID 0x3524 /* Cressi Edy (diving computer) PC interface */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c65437cfd4a..b2aa003bf41 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -22,8 +22,17 @@ #define DRIVER_AUTHOR "Qualcomm Inc" #define DRIVER_DESC "Qualcomm USB Serial driver" +/* standard device layouts supported by this driver */ +enum qcserial_layouts { + QCSERIAL_G2K = 0, /* Gobi 2000 */ + QCSERIAL_G1K = 1, /* Gobi 1000 */ + QCSERIAL_SWI = 2, /* Sierra Wireless */ +}; + #define DEVICE_G1K(v, p) \ - USB_DEVICE(v, p), .driver_info = 1 + USB_DEVICE(v, p), .driver_info = QCSERIAL_G1K +#define DEVICE_SWI(v, p) \ + USB_DEVICE(v, p), .driver_info = QCSERIAL_SWI static const struct usb_device_id id_table[] = { /* Gobi 1000 devices */ @@ -126,19 +135,27 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */ {USB_DEVICE(0x0AF0, 0x8120)}, /* Option GTM681W */ - /* non Gobi Qualcomm serial devices */ - {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 0)}, /* Sierra Wireless MC7700 Device Management */ - {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 2)}, /* Sierra Wireless MC7700 NMEA */ - {USB_DEVICE_INTERFACE_NUMBER(0x0f3d, 0x68a2, 3)}, /* Sierra Wireless MC7700 Modem */ - {USB_DEVICE_INTERFACE_NUMBER(0x114f, 0x68a2, 0)}, /* Sierra Wireless MC7750 Device Management */ - {USB_DEVICE_INTERFACE_NUMBER(0x114f, 0x68a2, 2)}, /* Sierra Wireless MC7750 NMEA */ - {USB_DEVICE_INTERFACE_NUMBER(0x114f, 0x68a2, 3)}, /* Sierra Wireless MC7750 Modem */ - {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 0)}, /* Sierra Wireless MC7710 Device Management */ - {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 2)}, /* Sierra Wireless MC7710 NMEA */ - {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x68a2, 3)}, /* Sierra Wireless MC7710 Modem */ - {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 0)}, /* Sierra Wireless EM7700 Device Management */ - {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 2)}, /* Sierra Wireless EM7700 NMEA */ - {USB_DEVICE_INTERFACE_NUMBER(0x1199, 0x901c, 3)}, /* Sierra Wireless EM7700 Modem */ + /* non-Gobi Sierra Wireless devices */ + {DEVICE_SWI(0x0f3d, 0x68a2)}, /* Sierra Wireless MC7700 */ + {DEVICE_SWI(0x114f, 0x68a2)}, /* Sierra Wireless MC7750 */ + {DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */ + {DEVICE_SWI(0x1199, 0x68c0)}, /* Sierra Wireless MC73xx */ + {DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */ + {DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */ + {DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */ + {DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */ + {DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9055)}, /* Netgear AirCard 341U */ + {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x413c, 0x81a2)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ + {DEVICE_SWI(0x413c, 0x81a3)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ + {DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ + {DEVICE_SWI(0x413c, 0x81a8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */ + {DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ { } /* Terminating entry */ }; @@ -151,11 +168,8 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) int retval = -ENODEV; __u8 nintf; __u8 ifnum; - bool is_gobi1k = id->driver_info ? true : false; int altsetting = -1; - dev_dbg(dev, "Is Gobi 1000 = %d\n", is_gobi1k); - nintf = serial->dev->actconfig->desc.bNumInterfaces; dev_dbg(dev, "Num Interfaces = %d\n", nintf); ifnum = intf->desc.bInterfaceNumber; @@ -183,32 +197,29 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) } - /* allow any number of interfaces when doing direct interface match */ - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) { - dev_dbg(dev, "Generic Qualcomm serial interface found\n"); - altsetting = 0; - goto done; - } - - if (nintf < 3 || nintf > 4) { - dev_err(dev, "unknown number of interfaces: %d\n", nintf); - goto done; - } - /* default to enabling interface */ altsetting = 0; - /* Composite mode; don't bind to the QMI/net interface as that + /* + * Composite mode; don't bind to the QMI/net interface as that * gets handled by other drivers. */ - if (is_gobi1k) { - /* Gobi 1K USB layout: + switch (id->driver_info) { + case QCSERIAL_G1K: + /* + * Gobi 1K USB layout: * 0: DM/DIAG (use libqcdm from ModemManager for communication) * 1: serial port (doesn't respond) * 2: AT-capable modem port * 3: QMI/net */ + if (nintf < 3 || nintf > 4) { + dev_err(dev, "unknown number of interfaces: %d\n", nintf); + altsetting = -1; + goto done; + } + if (ifnum == 0) { dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n"); altsetting = 1; @@ -216,13 +227,21 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) dev_dbg(dev, "Modem port found\n"); else altsetting = -1; - } else { - /* Gobi 2K+ USB layout: + break; + case QCSERIAL_G2K: + /* + * Gobi 2K+ USB layout: * 0: QMI/net * 1: DM/DIAG (use libqcdm from ModemManager for communication) * 2: AT-capable modem port * 3: NMEA */ + if (nintf < 3 || nintf > 4) { + dev_err(dev, "unknown number of interfaces: %d\n", nintf); + altsetting = -1; + goto done; + } + switch (ifnum) { case 0: /* Don't claim the QMI/net interface */ @@ -243,6 +262,35 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n"); break; } + break; + case QCSERIAL_SWI: + /* + * Sierra Wireless layout: + * 0: DM/DIAG (use libqcdm from ModemManager for communication) + * 2: NMEA + * 3: AT-capable modem port + * 8: QMI/net + */ + switch (ifnum) { + case 0: + dev_dbg(dev, "DM/DIAG interface found\n"); + break; + case 2: + dev_dbg(dev, "NMEA GPS interface found\n"); + break; + case 3: + dev_dbg(dev, "Modem port found\n"); + break; + default: + /* don't claim any unsupported interface */ + altsetting = -1; + break; + } + break; + default: + dev_err(dev, "unsupported device layout type: %lu\n", + id->driver_info); + break; } done: diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 7725ed261ed..504f5bff79c 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -372,7 +372,7 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) device_port, data, 2, QT2_USB_TIMEOUT); if (status < 0) { - dev_err(&port->dev, "%s - open port failed %i", __func__, + dev_err(&port->dev, "%s - open port failed %i\n", __func__, status); kfree(data); return status; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index a9eb6221a81..6f7f01eb556 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -58,6 +58,7 @@ struct sierra_intf_private { spinlock_t susp_lock; unsigned int suspended:1; int in_flight; + unsigned int open_ports; }; static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) @@ -291,7 +292,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, - { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */ { } }; @@ -316,7 +316,6 @@ struct sierra_port_private { int dsr_state; int dcd_state; int ri_state; - unsigned int opened:1; }; static int sierra_send_setup(struct usb_serial_port *port) @@ -365,20 +364,13 @@ static int sierra_send_setup(struct usb_serial_port *port) if (retval < 0) return retval; - retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT); usb_autopm_put_interface(serial->interface); return retval; } -static void sierra_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, struct ktermios *old_termios) -{ - tty_termios_copy_hw(&tty->termios, old_termios); - sierra_send_setup(port); -} - static int sierra_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -419,9 +411,7 @@ static int sierra_tiocmset(struct tty_struct *tty, static void sierra_release_urb(struct urb *urb) { - struct usb_serial_port *port; if (urb) { - port = urb->context; kfree(urb->transfer_buffer); usb_free_urb(urb); } @@ -434,7 +424,7 @@ static void sierra_outdat_callback(struct urb *urb) struct sierra_intf_private *intfdata; int status = urb->status; - intfdata = port->serial->private; + intfdata = usb_get_serial_data(port->serial); /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree(urb->transfer_buffer); @@ -471,7 +461,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, return 0; portdata = usb_get_serial_port_data(port); - intfdata = serial->private; + intfdata = usb_get_serial_data(serial); dev_dbg(&port->dev, "%s: write (%zd bytes)\n", __func__, writesize); spin_lock_irqsave(&portdata->lock, flags); @@ -675,6 +665,23 @@ static int sierra_write_room(struct tty_struct *tty) return 2048; } +static int sierra_chars_in_buffer(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + unsigned long flags; + int chars; + + /* NOTE: This overcounts somewhat. */ + spin_lock_irqsave(&portdata->lock, flags); + chars = portdata->outstanding_urbs * MAX_TRANSFER; + spin_unlock_irqrestore(&portdata->lock, flags); + + dev_dbg(&port->dev, "%s - %d\n", __func__, chars); + + return chars; +} + static void sierra_stop_rx_urbs(struct usb_serial_port *port) { int i; @@ -730,9 +737,6 @@ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, struct urb *urb; u8 *buf; - if (endpoint == -1) - return NULL; - urb = usb_alloc_urb(0, mem_flags); if (!urb) return NULL; @@ -759,40 +763,48 @@ static void sierra_close(struct usb_serial_port *port) int i; struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; - struct sierra_intf_private *intfdata = port->serial->private; + struct sierra_intf_private *intfdata = usb_get_serial_data(serial); + struct urb *urb; portdata = usb_get_serial_port_data(port); - portdata->rts_state = 0; - portdata->dtr_state = 0; - - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) { + /* + * Need to take susp_lock to make sure port is not already being + * resumed, but no need to hold it due to ASYNC_INITIALIZED. + */ + spin_lock_irq(&intfdata->susp_lock); + if (--intfdata->open_ports == 0) 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); + spin_unlock_irq(&intfdata->susp_lock); + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) + break; + kfree(urb->transfer_buffer); + usb_free_urb(urb); + usb_autopm_put_interface_async(serial->interface); + spin_lock(&portdata->lock); + portdata->outstanding_urbs--; + spin_unlock(&portdata->lock); } - mutex_unlock(&serial->disc_mutex); - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; - spin_unlock_irq(&intfdata->susp_lock); sierra_stop_rx_urbs(port); + usb_kill_anchored_urbs(&portdata->active); + for (i = 0; i < portdata->num_in_urbs; i++) { sierra_release_urb(portdata->in_urbs[i]); portdata->in_urbs[i] = NULL; } + + usb_autopm_get_interface_no_resume(serial->interface); } static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) { struct sierra_port_private *portdata; struct usb_serial *serial = port->serial; - struct sierra_intf_private *intfdata = serial->private; + struct sierra_intf_private *intfdata = usb_get_serial_data(serial); int i; int err; int endpoint; @@ -800,11 +812,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - /* Set some sane defaults */ - portdata->rts_state = 1; - portdata->dtr_state = 1; - - endpoint = port->bulk_in_endpointAddress; for (i = 0; i < portdata->num_in_urbs; i++) { urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port, @@ -817,23 +824,26 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN); err = sierra_submit_rx_urbs(port, GFP_KERNEL); - if (err) { - /* get rid of everything as in close */ - sierra_close(port); - /* restore balance for autopm */ - if (!serial->disconnected) - usb_autopm_put_interface(serial->interface); - return err; - } - sierra_send_setup(port); + if (err) + goto err_submit; - serial->interface->needs_remote_wakeup = 1; spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 1; + if (++intfdata->open_ports == 1) + serial->interface->needs_remote_wakeup = 1; spin_unlock_irq(&intfdata->susp_lock); usb_autopm_put_interface(serial->interface); return 0; + +err_submit: + 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; + } + + return err; } @@ -929,6 +939,7 @@ static int sierra_port_remove(struct usb_serial_port *port) struct sierra_port_private *portdata; portdata = usb_get_serial_port_data(port); + usb_set_serial_port_data(port, NULL); kfree(portdata); return 0; @@ -945,6 +956,8 @@ static void stop_read_write_urbs(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; sierra_stop_rx_urbs(port); usb_kill_anchored_urbs(&portdata->active); } @@ -952,58 +965,84 @@ static void stop_read_write_urbs(struct usb_serial *serial) static int sierra_suspend(struct usb_serial *serial, pm_message_t message) { - struct sierra_intf_private *intfdata; - int b; + struct sierra_intf_private *intfdata = usb_get_serial_data(serial); + spin_lock_irq(&intfdata->susp_lock); if (PMSG_IS_AUTO(message)) { - intfdata = serial->private; - spin_lock_irq(&intfdata->susp_lock); - b = intfdata->in_flight; - - if (b) { + if (intfdata->in_flight) { spin_unlock_irq(&intfdata->susp_lock); return -EBUSY; - } else { - intfdata->suspended = 1; - spin_unlock_irq(&intfdata->susp_lock); } } + intfdata->suspended = 1; + spin_unlock_irq(&intfdata->susp_lock); + stop_read_write_urbs(serial); return 0; } +/* Caller must hold susp_lock. */ +static int sierra_submit_delayed_urbs(struct usb_serial_port *port) +{ + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + struct sierra_intf_private *intfdata; + struct urb *urb; + int ec = 0; + int err; + + intfdata = usb_get_serial_data(port->serial); + + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) + break; + + usb_anchor_urb(urb, &portdata->active); + intfdata->in_flight++; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + dev_err(&port->dev, "%s - submit urb failed: %d", + __func__, err); + ec++; + intfdata->in_flight--; + usb_unanchor_urb(urb); + kfree(urb->transfer_buffer); + usb_free_urb(urb); + + spin_lock(&portdata->lock); + portdata->outstanding_urbs--; + spin_unlock(&portdata->lock); + } + } + + if (ec) + return -EIO; + + return 0; +} + static int sierra_resume(struct usb_serial *serial) { struct usb_serial_port *port; - struct sierra_intf_private *intfdata = serial->private; - struct sierra_port_private *portdata; - struct urb *urb; + struct sierra_intf_private *intfdata = usb_get_serial_data(serial); int ec = 0; int i, err; spin_lock_irq(&intfdata->susp_lock); for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - portdata = usb_get_serial_port_data(port); - while ((urb = usb_get_from_anchor(&portdata->delayed))) { - usb_anchor_urb(urb, &portdata->active); - intfdata->in_flight++; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - intfdata->in_flight--; - usb_unanchor_urb(urb); - usb_scuttle_anchored_urbs(&portdata->delayed); - break; - } - } + if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) + continue; - if (portdata->opened) { - err = sierra_submit_rx_urbs(port, GFP_ATOMIC); - if (err) - ec++; - } + err = sierra_submit_delayed_urbs(port); + if (err) + ec++; + + err = sierra_submit_rx_urbs(port, GFP_ATOMIC); + if (err) + ec++; } intfdata->suspended = 0; spin_unlock_irq(&intfdata->susp_lock); @@ -1030,7 +1069,7 @@ static struct usb_serial_driver sierra_device = { .dtr_rts = sierra_dtr_rts, .write = sierra_write, .write_room = sierra_write_room, - .set_termios = sierra_set_termios, + .chars_in_buffer = sierra_chars_in_buffer, .tiocmget = sierra_tiocmget, .tiocmset = sierra_tiocmset, .attach = sierra_startup, diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 4ec04f73c80..ef0dbf0703c 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -220,9 +220,9 @@ static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status) GET_UART_STATUS, GET_UART_STATUS_TYPE, 0, GET_UART_STATUS_MSR, buf, 1, 100); if (ret < 0) - dev_err(&port->dev, "failed to get modem status: %d", ret); + dev_err(&port->dev, "failed to get modem status: %d\n", ret); - dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x", ret, *buf); + dev_dbg(&port->dev, "0xc0:0x22:0:6 %d - 0x02%x\n", ret, *buf); *status = *buf; kfree(buf); @@ -342,8 +342,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty, case 1000000: buf[0] = 0x0b; break; default: - dev_err(&port->dev, "spcp825 driver does not support the " - "baudrate requested, using default of 9600.\n"); + dev_err(&port->dev, "unsupported baudrate, using 9600\n"); } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 9fa7dd413e8..8fceec7298e 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -74,9 +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(&port->dev, - "Improper amount of data received from the device, " - "%d bytes", urb->actual_length); + dev_dbg(&port->dev, "%s - short packet\n", __func__); } exit: diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index ec7cea58566..3dd3ff8c50d 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -293,7 +293,7 @@ static int ti_startup(struct usb_serial *serial) int status; dev_dbg(&dev->dev, - "%s - product 0x%4X, num configurations %d, configuration value %d", + "%s - product 0x%4X, num configurations %d, configuration value %d\n", __func__, le16_to_cpu(dev->descriptor.idProduct), dev->descriptor.bNumConfigurations, dev->actconfig->desc.bConfigurationValue); @@ -803,7 +803,7 @@ static void ti_set_termios(struct tty_struct *tty, tty_encode_baud_rate(tty, baud, baud); dev_dbg(&port->dev, - "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d", + "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n", __func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode); diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index f112b079ddf..fb79775447b 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -71,7 +71,8 @@ DEVICE(hp4x, HP4X_IDS); /* Suunto ANT+ USB Driver */ #define SUUNTO_IDS() \ - { USB_DEVICE(0x0fcf, 0x1008) } + { USB_DEVICE(0x0fcf, 0x1008) }, \ + { USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */ DEVICE(suunto, SUUNTO_IDS); /* Siemens USB/MPI adapter */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 7c9dc28640b..02de3110fe9 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -868,7 +868,7 @@ static int usb_serial_probe(struct usb_interface *interface, max_endpoints = max(max_endpoints, (int)serial->num_ports); serial->num_port_pointers = max_endpoints; - dev_dbg(ddev, "setting up %d port structures for this device", max_endpoints); + dev_dbg(ddev, "setting up %d port structure(s)\n", max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); if (!port) @@ -923,9 +923,8 @@ static int usb_serial_probe(struct usb_interface *interface, port = serial->port[i]; if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) goto probe_error; - buffer_size = serial->type->bulk_out_size; - if (!buffer_size) - buffer_size = usb_endpoint_maxp(endpoint); + buffer_size = max_t(int, serial->type->bulk_out_size, + usb_endpoint_maxp(endpoint)); port->bulk_out_size = buffer_size; port->bulk_out_endpointAddress = endpoint->bEndpointAddress; @@ -1034,7 +1033,7 @@ static int usb_serial_probe(struct usb_interface *interface, for (i = 0; i < num_ports; ++i) { port = serial->port[i]; dev_set_name(&port->dev, "ttyUSB%d", port->minor); - dev_dbg(ddev, "registering %s", dev_name(&port->dev)); + dev_dbg(ddev, "registering %s\n", dev_name(&port->dev)); device_enable_async_suspend(&port->dev); retval = device_add(&port->dev); @@ -1061,6 +1060,7 @@ static void usb_serial_disconnect(struct usb_interface *interface) struct usb_serial *serial = usb_get_intfdata(interface); struct device *dev = &interface->dev; struct usb_serial_port *port; + struct tty_struct *tty; usb_serial_console_disconnect(serial); @@ -1071,18 +1071,16 @@ static void usb_serial_disconnect(struct usb_interface *interface) for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; - if (port) { - struct tty_struct *tty = tty_port_tty_get(&port->port); - if (tty) { - tty_vhangup(tty); - 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); + tty = tty_port_tty_get(&port->port); + if (tty) { + tty_vhangup(tty); + 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); } if (serial->type->disconnect) serial->type->disconnect(serial); @@ -1095,7 +1093,6 @@ static void usb_serial_disconnect(struct usb_interface *interface) int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) { struct usb_serial *serial = usb_get_intfdata(intf); - struct usb_serial_port *port; int i, r = 0; serial->suspending = 1; @@ -1113,12 +1110,8 @@ 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) - usb_serial_port_poison_urbs(port); - } - + for (i = 0; i < serial->num_ports; ++i) + usb_serial_port_poison_urbs(serial->port[i]); err_out: return r; } @@ -1126,14 +1119,10 @@ 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); - } + for (i = 0; i < serial->num_ports; ++i) + usb_serial_port_unpoison_urbs(serial->port[i]); } int usb_serial_resume(struct usb_interface *intf) @@ -1161,9 +1150,9 @@ static int usb_serial_reset_resume(struct usb_interface *intf) usb_serial_unpoison_port_urbs(serial); serial->suspending = 0; - if (serial->type->reset_resume) + if (serial->type->reset_resume) { rv = serial->type->reset_resume(serial); - else { + } else { rv = -EOPNOTSUPP; intf->needs_binding = 1; } @@ -1338,9 +1327,9 @@ static int usb_serial_register(struct usb_serial_driver *driver) if (retval) { pr_err("problem %d when registering driver %s\n", retval, driver->description); list_del(&driver->driver_list); - } else + } else { pr_info("USB Serial support registered for %s\n", driver->description); - + } mutex_unlock(&table_lock); return retval; } @@ -1348,10 +1337,12 @@ static int usb_serial_register(struct usb_serial_driver *driver) static void usb_serial_deregister(struct usb_serial_driver *device) { pr_info("USB Serial deregistering driver %s\n", device->description); + mutex_lock(&table_lock); list_del(&device->driver_list); - usb_serial_bus_deregister(device); mutex_unlock(&table_lock); + + usb_serial_bus_deregister(device); } /** diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 684739b8efd..f22dff58b58 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -11,15 +11,11 @@ extern void usb_wwan_close(struct usb_serial_port *port); extern int usb_wwan_port_probe(struct usb_serial_port *port); extern int usb_wwan_port_remove(struct usb_serial_port *port); extern int usb_wwan_write_room(struct tty_struct *tty); -extern void usb_wwan_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, - struct ktermios *old); extern int usb_wwan_tiocmget(struct tty_struct *tty); extern int usb_wwan_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); extern int usb_wwan_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -extern int usb_wwan_send_setup(struct usb_serial_port *port); extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); extern int usb_wwan_chars_in_buffer(struct tty_struct *tty); @@ -39,6 +35,7 @@ struct usb_wwan_intf_private { spinlock_t susp_lock; unsigned int suspended:1; int in_flight; + unsigned int open_ports; int (*send_setup) (struct usb_serial_port *port); void *private; }; @@ -51,7 +48,6 @@ struct usb_wwan_port_private { struct urb *out_urbs[N_OUT_URB]; u8 *out_buffer[N_OUT_URB]; unsigned long out_busy; /* Bit vector of URBs in use */ - int opened; struct usb_anchor delayed; /* Settings for the port */ diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 640fe017323..2f805cb386a 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -41,7 +41,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata; - intfdata = port->serial->private; + intfdata = usb_get_serial_data(port->serial); if (!intfdata->send_setup) return; @@ -55,20 +55,6 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) } EXPORT_SYMBOL(usb_wwan_dtr_rts); -void usb_wwan_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, - struct ktermios *old_termios) -{ - struct usb_wwan_intf_private *intfdata = port->serial->private; - - /* Doesn't support option setting */ - tty_termios_copy_hw(&tty->termios, old_termios); - - if (intfdata->send_setup) - intfdata->send_setup(port); -} -EXPORT_SYMBOL(usb_wwan_set_termios); - int usb_wwan_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -96,7 +82,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty, struct usb_wwan_intf_private *intfdata; portdata = usb_get_serial_port_data(port); - intfdata = port->serial->private; + intfdata = usb_get_serial_data(port->serial); if (!intfdata->send_setup) return -EINVAL; @@ -192,7 +178,6 @@ int usb_wwan_ioctl(struct tty_struct *tty, } EXPORT_SYMBOL(usb_wwan_ioctl); -/* Write */ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { @@ -205,7 +190,7 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, unsigned long flags; portdata = usb_get_serial_port_data(port); - intfdata = port->serial->private; + intfdata = usb_get_serial_data(port->serial); dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); @@ -228,8 +213,10 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, usb_pipeendpoint(this_urb->pipe), i); err = usb_autopm_get_interface_async(port->serial->interface); - if (err < 0) + if (err < 0) { + clear_bit(i, &portdata->out_busy); break; + } /* send the data */ memcpy(this_urb->transfer_buffer, buf, todo); @@ -244,9 +231,9 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, spin_unlock_irqrestore(&intfdata->susp_lock, flags); err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err) { - dev_dbg(&port->dev, - "usb_submit_urb %p (write bulk) failed (%d)\n", - this_urb, err); + dev_err(&port->dev, + "%s: submit urb %d failed: %d\n", + __func__, i, err); clear_bit(i, &portdata->out_busy); spin_lock_irqsave(&intfdata->susp_lock, flags); intfdata->in_flight--; @@ -314,7 +301,7 @@ static void usb_wwan_outdat_callback(struct urb *urb) int i; port = urb->context; - intfdata = port->serial->private; + intfdata = usb_get_serial_data(port->serial); usb_serial_port_softint(port); usb_autopm_put_interface_async(port->serial->interface); @@ -325,7 +312,7 @@ static void usb_wwan_outdat_callback(struct urb *urb) for (i = 0; i < N_OUT_URB; ++i) { if (portdata->out_urbs[i] == urb) { - smp_mb__before_clear_bit(); + smp_mb__before_atomic(); clear_bit(i, &portdata->out_busy); break; } @@ -384,7 +371,15 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) struct urb *urb; portdata = usb_get_serial_port_data(port); - intfdata = serial->private; + intfdata = usb_get_serial_data(serial); + + if (port->interrupt_in_urb) { + err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (err) { + dev_err(&port->dev, "%s: submit int urb failed: %d\n", + __func__, err); + } + } /* Start reading from the IN endpoint */ for (i = 0; i < N_IN_URB; i++) { @@ -393,17 +388,15 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) continue; err = usb_submit_urb(urb, GFP_KERNEL); if (err) { - dev_dbg(&port->dev, "%s: submit urb %d failed (%d) %d\n", - __func__, i, err, urb->transfer_buffer_length); + dev_err(&port->dev, + "%s: submit read urb %d failed: %d\n", + __func__, i, err); } } - if (intfdata->send_setup) - intfdata->send_setup(port); - - serial->interface->needs_remote_wakeup = 1; spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 1; + if (++intfdata->open_ports == 1) + serial->interface->needs_remote_wakeup = 1; spin_unlock_irq(&intfdata->susp_lock); /* this balances a get in the generic USB serial code */ usb_autopm_put_interface(serial->interface); @@ -412,32 +405,56 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) } EXPORT_SYMBOL(usb_wwan_open); +static void unbusy_queued_urb(struct urb *urb, + struct usb_wwan_port_private *portdata) +{ + int i; + + for (i = 0; i < N_OUT_URB; i++) { + if (urb == portdata->out_urbs[i]) { + clear_bit(i, &portdata->out_busy); + break; + } + } +} + void usb_wwan_close(struct usb_serial_port *port) { int i; struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; - struct usb_wwan_intf_private *intfdata = port->serial->private; + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); + struct urb *urb; portdata = usb_get_serial_port_data(port); - /* Stop reading/writing urbs */ + /* + * Need to take susp_lock to make sure port is not already being + * resumed, but no need to hold it due to ASYNC_INITIALIZED. + */ spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; + if (--intfdata->open_ports == 0) + serial->interface->needs_remote_wakeup = 0; spin_unlock_irq(&intfdata->susp_lock); + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) + break; + unbusy_queued_urb(urb, portdata); + usb_autopm_put_interface_async(serial->interface); + } + 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]); + usb_kill_urb(port->interrupt_in_urb); - /* 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); -/* Helper functions used by usb_wwan_setup_urbs */ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, int endpoint, int dir, void *ctx, char *buf, int len, @@ -450,7 +467,6 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, if (!urb) return NULL; - /* Fill URB using supplied data. */ usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); @@ -463,9 +479,11 @@ int usb_wwan_port_probe(struct usb_serial_port *port) struct usb_wwan_port_private *portdata; struct urb *urb; u8 *buffer; - int err; int i; + if (!port->bulk_in_size || !port->bulk_out_size) + return -ENODEV; + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) return -ENOMEM; @@ -473,9 +491,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) init_usb_anchor(&portdata->delayed); for (i = 0; i < N_IN_URB; i++) { - if (!port->bulk_in_size) - break; - buffer = (u8 *)__get_free_page(GFP_KERNEL); if (!buffer) goto bail_out_error; @@ -489,9 +504,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) } for (i = 0; i < N_OUT_URB; i++) { - if (!port->bulk_out_size) - break; - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); if (!buffer) goto bail_out_error2; @@ -506,13 +518,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, portdata); - if (port->interrupt_in_urb) { - err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (err) - dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", - __func__, err); - } - return 0; bail_out_error2: @@ -539,32 +544,28 @@ int usb_wwan_port_remove(struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); usb_set_serial_port_data(port, NULL); - /* Stop reading/writing urbs and free them */ for (i = 0; i < N_IN_URB; i++) { - usb_kill_urb(portdata->in_urbs[i]); usb_free_urb(portdata->in_urbs[i]); free_page((unsigned long)portdata->in_buffer[i]); } for (i = 0; i < N_OUT_URB; i++) { - usb_kill_urb(portdata->out_urbs[i]); usb_free_urb(portdata->out_urbs[i]); kfree(portdata->out_buffer[i]); } - /* Now free port private data */ kfree(portdata); + return 0; } EXPORT_SYMBOL(usb_wwan_port_remove); #ifdef CONFIG_PM -static void stop_read_write_urbs(struct usb_serial *serial) +static void stop_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct usb_wwan_port_private *portdata; - /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); @@ -574,123 +575,117 @@ static void stop_read_write_urbs(struct usb_serial *serial) usb_kill_urb(portdata->in_urbs[j]); for (j = 0; j < N_OUT_URB; j++) usb_kill_urb(portdata->out_urbs[j]); + usb_kill_urb(port->interrupt_in_urb); } } int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) { - struct usb_wwan_intf_private *intfdata = serial->private; - int b; + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); + spin_lock_irq(&intfdata->susp_lock); if (PMSG_IS_AUTO(message)) { - spin_lock_irq(&intfdata->susp_lock); - b = intfdata->in_flight; - spin_unlock_irq(&intfdata->susp_lock); - - if (b) + if (intfdata->in_flight) { + spin_unlock_irq(&intfdata->susp_lock); return -EBUSY; + } } - - spin_lock_irq(&intfdata->susp_lock); intfdata->suspended = 1; spin_unlock_irq(&intfdata->susp_lock); - stop_read_write_urbs(serial); + + stop_urbs(serial); return 0; } EXPORT_SYMBOL(usb_wwan_suspend); -static void unbusy_queued_urb(struct urb *urb, struct usb_wwan_port_private *portdata) -{ - int i; - - for (i = 0; i < N_OUT_URB; i++) { - if (urb == portdata->out_urbs[i]) { - clear_bit(i, &portdata->out_busy); - break; - } - } -} - -static void play_delayed(struct usb_serial_port *port) +/* Caller must hold susp_lock. */ +static int usb_wwan_submit_delayed_urbs(struct usb_serial_port *port) { - struct usb_wwan_intf_private *data; + struct usb_serial *serial = port->serial; + struct usb_wwan_intf_private *data = usb_get_serial_data(serial); struct usb_wwan_port_private *portdata; struct urb *urb; + int err_count = 0; int err; portdata = usb_get_serial_port_data(port); - data = port->serial->private; - while ((urb = usb_get_from_anchor(&portdata->delayed))) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (!err) { - data->in_flight++; - } else { - /* we have to throw away the rest */ - do { - unbusy_queued_urb(urb, portdata); - usb_autopm_put_interface_no_suspend(port->serial->interface); - } while ((urb = usb_get_from_anchor(&portdata->delayed))); + + for (;;) { + urb = usb_get_from_anchor(&portdata->delayed); + if (!urb) break; + + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) { + dev_err(&port->dev, "%s: submit urb failed: %d\n", + __func__, err); + err_count++; + unbusy_queued_urb(urb, portdata); + usb_autopm_put_interface_async(serial->interface); + continue; } + data->in_flight++; } + + if (err_count) + return -EIO; + + return 0; } int usb_wwan_resume(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; - struct usb_wwan_intf_private *intfdata = serial->private; + struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial); struct usb_wwan_port_private *portdata; struct urb *urb; - int err = 0; + int err; + int err_count = 0; - /* get the interrupt URBs resubmitted unconditionally */ + spin_lock_irq(&intfdata->susp_lock); for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; - if (!port->interrupt_in_urb) { - dev_dbg(&port->dev, "%s: No interrupt URB for port\n", __func__); + + if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) continue; - } - err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); - dev_dbg(&port->dev, "Submitted interrupt URB for port (result %d)\n", err); - if (err < 0) { - dev_err(&port->dev, "%s: Error %d for interrupt URB\n", - __func__, err); - goto err_out; - } - } - for (i = 0; i < serial->num_ports; i++) { - /* walk all ports */ - port = serial->port[i]; portdata = usb_get_serial_port_data(port); - /* skip closed ports */ - spin_lock_irq(&intfdata->susp_lock); - if (!portdata || !portdata->opened) { - spin_unlock_irq(&intfdata->susp_lock); - continue; + if (port->interrupt_in_urb) { + err = usb_submit_urb(port->interrupt_in_urb, + GFP_ATOMIC); + if (err) { + dev_err(&port->dev, + "%s: submit int urb failed: %d\n", + __func__, err); + err_count++; + } } + err = usb_wwan_submit_delayed_urbs(port); + if (err) + err_count++; + for (j = 0; j < N_IN_URB; j++) { urb = portdata->in_urbs[j]; err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { - dev_err(&port->dev, "%s: Error %d for bulk URB %d\n", - __func__, err, i); - spin_unlock_irq(&intfdata->susp_lock); - goto err_out; + dev_err(&port->dev, + "%s: submit read urb %d failed: %d\n", + __func__, i, err); + err_count++; } } - play_delayed(port); - spin_unlock_irq(&intfdata->susp_lock); } - spin_lock_irq(&intfdata->susp_lock); intfdata->suspended = 0; spin_unlock_irq(&intfdata->susp_lock); -err_out: - return err; + + if (err_count) + return -EIO; + + return 0; } EXPORT_SYMBOL(usb_wwan_resume); #endif |
