diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 08:41:41 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 13:07:53 -0400 |
| commit | 816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch) | |
| tree | 421fa29aedff988e392f92780637553e275d37a0 /drivers/usb/serial | |
| parent | 70ac4385a13f78bc478f26d317511893741b05bd (diff) | |
| parent | d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
fs/nfs/inode.c
fs/super.c
Fix conflicts between patch 'NFS: Split fs/nfs/inode.c' and patch
'VFS: Permit filesystem to override root dentry on mount'
Diffstat (limited to 'drivers/usb/serial')
| -rw-r--r-- | drivers/usb/serial/Kconfig | 18 | ||||
| -rw-r--r-- | drivers/usb/serial/airprime.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/console.c | 56 | ||||
| -rw-r--r-- | drivers/usb/serial/cp2101.c | 1 | ||||
| -rw-r--r-- | drivers/usb/serial/cyberjack.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/cypress_m8.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/empeg.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 13 | ||||
| -rw-r--r-- | drivers/usb/serial/ftdi_sio.h | 6 | ||||
| -rw-r--r-- | drivers/usb/serial/garmin_gps.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/generic.c | 4 | ||||
| -rw-r--r-- | drivers/usb/serial/io_edgeport.c | 48 | ||||
| -rw-r--r-- | drivers/usb/serial/ipaq.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/ipw.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/ir-usb.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/keyspan.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/kl5kusb105.c | 3 | ||||
| -rw-r--r-- | drivers/usb/serial/omninet.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/option.c | 139 | ||||
| -rw-r--r-- | drivers/usb/serial/pl2303.c | 4 | ||||
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 58 | ||||
| -rw-r--r-- | drivers/usb/serial/usb-serial.h | 5 | ||||
| -rw-r--r-- | drivers/usb/serial/visor.c | 2 | ||||
| -rw-r--r-- | drivers/usb/serial/whiteheat.c | 8 |
24 files changed, 271 insertions, 114 deletions
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 5c60be521561..8bd44fda5eaf 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
| @@ -417,7 +417,7 @@ config USB_SERIAL_MCT_U232 | |||
| 417 | Magic Control Technology Corp. (U232 is one of the model numbers). | 417 | Magic Control Technology Corp. (U232 is one of the model numbers). |
| 418 | 418 | ||
| 419 | This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB | 419 | This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB |
| 420 | BAY devices. | 420 | BAY, Belkin F5U109, and Belkin F5U409 devices. |
| 421 | 421 | ||
| 422 | To compile this driver as a module, choose M here: the | 422 | To compile this driver as a module, choose M here: the |
| 423 | module will be called mct_u232. | 423 | module will be called mct_u232. |
| @@ -491,16 +491,22 @@ config USB_SERIAL_XIRCOM | |||
| 491 | module will be called keyspan_pda. | 491 | module will be called keyspan_pda. |
| 492 | 492 | ||
| 493 | config USB_SERIAL_OPTION | 493 | config USB_SERIAL_OPTION |
| 494 | tristate "USB Option PCMCIA serial driver" | 494 | tristate "USB driver for GSM modems" |
| 495 | depends on USB_SERIAL && USB_OHCI_HCD && PCCARD | 495 | depends on USB_SERIAL |
| 496 | help | 496 | help |
| 497 | Say Y here if you want to use an Option card. This is a | 497 | Say Y here if you have an "Option" GSM PCMCIA card |
| 498 | GSM card, controlled by three serial ports which are connected | 498 | (or an OEM version: branded Huawei, Audiovox, or Novatel). |
| 499 | via an OHCI adapter located on a PC card. | 499 | |
| 500 | These cards feature a built-in OHCI-USB adapter and an | ||
| 501 | internally-connected GSM modem. The USB bus is not | ||
| 502 | accessible externally. | ||
| 500 | 503 | ||
| 501 | To compile this driver as a module, choose M here: the | 504 | To compile this driver as a module, choose M here: the |
| 502 | module will be called option. | 505 | module will be called option. |
| 503 | 506 | ||
| 507 | If this driver doesn't recognize your device, | ||
| 508 | it might be accessible via the FTDI_SIO driver. | ||
| 509 | |||
| 504 | config USB_SERIAL_OMNINET | 510 | config USB_SERIAL_OMNINET |
| 505 | tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" | 511 | tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)" |
| 506 | depends on USB_SERIAL && EXPERIMENTAL | 512 | depends on USB_SERIAL && EXPERIMENTAL |
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 694b205f9b73..94b9ba0ff875 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
| @@ -16,9 +16,11 @@ | |||
| 16 | #include "usb-serial.h" | 16 | #include "usb-serial.h" |
| 17 | 17 | ||
| 18 | static struct usb_device_id id_table [] = { | 18 | static struct usb_device_id id_table [] = { |
| 19 | { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ | ||
| 19 | { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ | 20 | { USB_DEVICE(0xf3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ |
| 20 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ | 21 | { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ |
| 21 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ | 22 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ |
| 23 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | ||
| 22 | { }, | 24 | { }, |
| 23 | }; | 25 | }; |
| 24 | MODULE_DEVICE_TABLE(usb, id_table); | 26 | MODULE_DEVICE_TABLE(usb, id_table); |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 8023bb7279b1..f3404e10afb4 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
| @@ -202,7 +202,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun | |||
| 202 | struct usb_serial *serial; | 202 | struct usb_serial *serial; |
| 203 | int retval = -ENODEV; | 203 | int retval = -ENODEV; |
| 204 | 204 | ||
| 205 | if (!port) | 205 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) |
| 206 | return; | 206 | return; |
| 207 | serial = port->serial; | 207 | serial = port->serial; |
| 208 | 208 | ||
| @@ -213,17 +213,38 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun | |||
| 213 | 213 | ||
| 214 | if (!port->open_count) { | 214 | if (!port->open_count) { |
| 215 | dbg ("%s - port not opened", __FUNCTION__); | 215 | dbg ("%s - port not opened", __FUNCTION__); |
| 216 | goto exit; | 216 | return; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | /* pass on to the driver specific version of this function if it is available */ | 219 | while (count) { |
| 220 | if (serial->type->write) | 220 | unsigned int i; |
| 221 | retval = serial->type->write(port, buf, count); | 221 | unsigned int lf; |
| 222 | else | 222 | /* search for LF so we can insert CR if necessary */ |
| 223 | retval = usb_serial_generic_write(port, buf, count); | 223 | for (i=0, lf=0 ; i < count ; i++) { |
| 224 | 224 | if (*(buf + i) == 10) { | |
| 225 | exit: | 225 | lf = 1; |
| 226 | dbg("%s - return value (if we had one): %d", __FUNCTION__, retval); | 226 | i++; |
| 227 | break; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | /* pass on to the driver specific version of this function if it is available */ | ||
| 231 | if (serial->type->write) | ||
| 232 | retval = serial->type->write(port, buf, i); | ||
| 233 | else | ||
| 234 | retval = usb_serial_generic_write(port, buf, i); | ||
| 235 | dbg("%s - return value : %d", __FUNCTION__, retval); | ||
| 236 | if (lf) { | ||
| 237 | /* append CR after LF */ | ||
| 238 | unsigned char cr = 13; | ||
| 239 | if (serial->type->write) | ||
| 240 | retval = serial->type->write(port, &cr, 1); | ||
| 241 | else | ||
| 242 | retval = usb_serial_generic_write(port, &cr, 1); | ||
| 243 | dbg("%s - return value : %d", __FUNCTION__, retval); | ||
| 244 | } | ||
| 245 | buf += i; | ||
| 246 | count -= i; | ||
| 247 | } | ||
| 227 | } | 248 | } |
| 228 | 249 | ||
| 229 | static struct console usbcons = { | 250 | static struct console usbcons = { |
| @@ -234,6 +255,14 @@ static struct console usbcons = { | |||
| 234 | .index = -1, | 255 | .index = -1, |
| 235 | }; | 256 | }; |
| 236 | 257 | ||
| 258 | void usb_serial_console_disconnect(struct usb_serial *serial) | ||
| 259 | { | ||
| 260 | if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { | ||
| 261 | usb_serial_console_exit(); | ||
| 262 | usb_serial_put(serial); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 237 | void usb_serial_console_init (int serial_debug, int minor) | 266 | void usb_serial_console_init (int serial_debug, int minor) |
| 238 | { | 267 | { |
| 239 | debug = serial_debug; | 268 | debug = serial_debug; |
| @@ -259,6 +288,11 @@ void usb_serial_console_init (int serial_debug, int minor) | |||
| 259 | 288 | ||
| 260 | void usb_serial_console_exit (void) | 289 | void usb_serial_console_exit (void) |
| 261 | { | 290 | { |
| 262 | unregister_console(&usbcons); | 291 | if (usbcons_info.port) { |
| 292 | unregister_console(&usbcons); | ||
| 293 | if (usbcons_info.port->open_count) | ||
| 294 | usbcons_info.port->open_count--; | ||
| 295 | usbcons_info.port = NULL; | ||
| 296 | } | ||
| 263 | } | 297 | } |
| 264 | 298 | ||
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index e0c2acdb3f06..f8c0cb287736 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
| @@ -59,6 +59,7 @@ static struct usb_device_id id_table [] = { | |||
| 59 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 59 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
| 60 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ | 60 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ |
| 61 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ | 61 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ |
| 62 | { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ | ||
| 62 | { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ | 63 | { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ |
| 63 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ | 64 | { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ |
| 64 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ | 65 | { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2357b1d102d7..1fd5c5a9f2ef 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
| @@ -469,7 +469,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs | |||
| 469 | 469 | ||
| 470 | exit: | 470 | exit: |
| 471 | spin_unlock(&priv->lock); | 471 | spin_unlock(&priv->lock); |
| 472 | schedule_work(&port->work); | 472 | usb_serial_port_softint(port); |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | static int __init cyberjack_init (void) | 475 | static int __init cyberjack_init (void) |
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 7212fbe3b6f2..5de76efe1b37 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
| @@ -824,7 +824,7 @@ send: | |||
| 824 | priv->bytes_out += count; /* do not count the line control and size bytes */ | 824 | priv->bytes_out += count; /* do not count the line control and size bytes */ |
| 825 | spin_unlock_irqrestore(&priv->lock, flags); | 825 | spin_unlock_irqrestore(&priv->lock, flags); |
| 826 | 826 | ||
| 827 | schedule_work(&port->work); | 827 | usb_serial_port_softint(port); |
| 828 | } /* cypress_send */ | 828 | } /* cypress_send */ |
| 829 | 829 | ||
| 830 | 830 | ||
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 63f7c78a1152..afca1eae5fb5 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c | |||
| @@ -335,7 +335,7 @@ static void empeg_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
| 335 | return; | 335 | return; |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | schedule_work(&port->work); | 338 | usb_serial_port_softint(port); |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | 341 | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 986d7622273d..b2bfea7c815a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -500,6 +500,7 @@ static struct usb_device_id id_table_combined [] = { | |||
| 500 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, | 500 | { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, |
| 501 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, | 501 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) }, |
| 502 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, | 502 | { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, |
| 503 | { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, | ||
| 503 | { }, /* Optional parameter entry */ | 504 | { }, /* Optional parameter entry */ |
| 504 | { } /* Terminating entry */ | 505 | { } /* Terminating entry */ |
| 505 | }; | 506 | }; |
| @@ -1261,7 +1262,6 @@ static void ftdi_shutdown (struct usb_serial *serial) | |||
| 1261 | 1262 | ||
| 1262 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) | 1263 | static int ftdi_open (struct usb_serial_port *port, struct file *filp) |
| 1263 | { /* ftdi_open */ | 1264 | { /* ftdi_open */ |
| 1264 | struct termios tmp_termios; | ||
| 1265 | struct usb_device *dev = port->serial->dev; | 1265 | struct usb_device *dev = port->serial->dev; |
| 1266 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1266 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1267 | unsigned long flags; | 1267 | unsigned long flags; |
| @@ -1271,8 +1271,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) | |||
| 1271 | 1271 | ||
| 1272 | dbg("%s", __FUNCTION__); | 1272 | dbg("%s", __FUNCTION__); |
| 1273 | 1273 | ||
| 1274 | 1274 | if (port->tty) | |
| 1275 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1275 | port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
| 1276 | 1276 | ||
| 1277 | /* No error checking for this (will get errors later anyway) */ | 1277 | /* No error checking for this (will get errors later anyway) */ |
| 1278 | /* See ftdi_sio.h for description of what is reset */ | 1278 | /* See ftdi_sio.h for description of what is reset */ |
| @@ -1286,7 +1286,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) | |||
| 1286 | This is same behaviour as serial.c/rs_open() - Kuba */ | 1286 | This is same behaviour as serial.c/rs_open() - Kuba */ |
| 1287 | 1287 | ||
| 1288 | /* ftdi_set_termios will send usb control messages */ | 1288 | /* ftdi_set_termios will send usb control messages */ |
| 1289 | ftdi_set_termios(port, &tmp_termios); | 1289 | if (port->tty) |
| 1290 | ftdi_set_termios(port, NULL); | ||
| 1290 | 1291 | ||
| 1291 | /* FIXME: Flow control might be enabled, so it should be checked - | 1292 | /* FIXME: Flow control might be enabled, so it should be checked - |
| 1292 | we have no control of defaults! */ | 1293 | we have no control of defaults! */ |
| @@ -1472,7 +1473,7 @@ static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
| 1472 | return; | 1473 | return; |
| 1473 | } | 1474 | } |
| 1474 | 1475 | ||
| 1475 | schedule_work(&port->work); | 1476 | usb_serial_port_softint(port); |
| 1476 | } /* ftdi_write_bulk_callback */ | 1477 | } /* ftdi_write_bulk_callback */ |
| 1477 | 1478 | ||
| 1478 | 1479 | ||
| @@ -1867,7 +1868,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ | |||
| 1867 | err("%s urb failed to set baudrate", __FUNCTION__); | 1868 | err("%s urb failed to set baudrate", __FUNCTION__); |
| 1868 | } | 1869 | } |
| 1869 | /* Ensure RTS and DTR are raised when baudrate changed from 0 */ | 1870 | /* Ensure RTS and DTR are raised when baudrate changed from 0 */ |
| 1870 | if ((old_termios->c_cflag & CBAUD) == B0) { | 1871 | if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) { |
| 1871 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | 1872 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); |
| 1872 | } | 1873 | } |
| 1873 | } | 1874 | } |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index d69a917e768f..6ab2ac845bd7 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
| @@ -436,6 +436,12 @@ | |||
| 436 | */ | 436 | */ |
| 437 | #define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ | 437 | #define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ |
| 438 | 438 | ||
| 439 | /* | ||
| 440 | * Yost Engineering, Inc. products (www.yostengineering.com). | ||
| 441 | * PID 0xE050 submitted by Aaron Prose. | ||
| 442 | */ | ||
| 443 | #define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ | ||
| 444 | |||
| 439 | /* Commands */ | 445 | /* Commands */ |
| 440 | #define FTDI_SIO_RESET 0 /* Reset the port */ | 446 | #define FTDI_SIO_RESET 0 /* Reset the port */ |
| 441 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ | 447 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 5ec9bf5bac8d..04767759cf8a 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
| @@ -1012,7 +1012,7 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
| 1012 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | 1012 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; |
| 1013 | } | 1013 | } |
| 1014 | 1014 | ||
| 1015 | schedule_work(&port->work); | 1015 | usb_serial_port_softint(port); |
| 1016 | } | 1016 | } |
| 1017 | 1017 | ||
| 1018 | 1018 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c62cc2876519..07a478c59fb2 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
| @@ -299,9 +299,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re | |||
| 299 | return; | 299 | return; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | usb_serial_port_softint((void *)port); | 302 | usb_serial_port_softint(port); |
| 303 | |||
| 304 | schedule_work(&port->work); | ||
| 305 | } | 303 | } |
| 306 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 304 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
| 307 | 305 | ||
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b606c5968102..b85d2156dfdc 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
| @@ -142,7 +142,7 @@ struct edgeport_port { | |||
| 142 | 142 | ||
| 143 | /* This structure holds all of the individual device information */ | 143 | /* This structure holds all of the individual device information */ |
| 144 | struct edgeport_serial { | 144 | struct edgeport_serial { |
| 145 | char name[MAX_NAME_LEN+1]; /* string name of this device */ | 145 | char name[MAX_NAME_LEN+2]; /* string name of this device */ |
| 146 | 146 | ||
| 147 | struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ | 147 | struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ |
| 148 | struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ | 148 | struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ |
| @@ -270,7 +270,7 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial); | |||
| 270 | static void get_boot_desc (struct edgeport_serial *edge_serial); | 270 | static void get_boot_desc (struct edgeport_serial *edge_serial); |
| 271 | static void load_application_firmware (struct edgeport_serial *edge_serial); | 271 | static void load_application_firmware (struct edgeport_serial *edge_serial); |
| 272 | 272 | ||
| 273 | static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size); | 273 | static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size); |
| 274 | 274 | ||
| 275 | 275 | ||
| 276 | // ************************************************************************ | 276 | // ************************************************************************ |
| @@ -373,7 +373,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial) | |||
| 373 | * Get string descriptor from device * | 373 | * Get string descriptor from device * |
| 374 | * * | 374 | * * |
| 375 | ************************************************************************/ | 375 | ************************************************************************/ |
| 376 | static int get_string (struct usb_device *dev, int Id, char *string) | 376 | static int get_string (struct usb_device *dev, int Id, char *string, int buflen) |
| 377 | { | 377 | { |
| 378 | struct usb_string_descriptor StringDesc; | 378 | struct usb_string_descriptor StringDesc; |
| 379 | struct usb_string_descriptor *pStringDesc; | 379 | struct usb_string_descriptor *pStringDesc; |
| @@ -395,7 +395,7 @@ static int get_string (struct usb_device *dev, int Id, char *string) | |||
| 395 | return 0; | 395 | return 0; |
| 396 | } | 396 | } |
| 397 | 397 | ||
| 398 | unicode_to_ascii(string, pStringDesc->wData, pStringDesc->bLength/2-1); | 398 | unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2); |
| 399 | 399 | ||
| 400 | kfree(pStringDesc); | 400 | kfree(pStringDesc); |
| 401 | return strlen(string); | 401 | return strlen(string); |
| @@ -2564,16 +2564,20 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio | |||
| 2564 | * ASCII range, but it's only for debugging... | 2564 | * ASCII range, but it's only for debugging... |
| 2565 | * NOTE: expects the unicode in LE format | 2565 | * NOTE: expects the unicode in LE format |
| 2566 | ****************************************************************************/ | 2566 | ****************************************************************************/ |
| 2567 | static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size) | 2567 | static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size) |
| 2568 | { | 2568 | { |
| 2569 | int i; | 2569 | int i; |
| 2570 | 2570 | ||
| 2571 | if (unicode_size <= 0) | 2571 | if (buflen <= 0) /* never happens, but... */ |
| 2572 | return; | 2572 | return; |
| 2573 | --buflen; /* space for nul */ | ||
| 2573 | 2574 | ||
| 2574 | for (i = 0; i < unicode_size; ++i) | 2575 | for (i = 0; i < unicode_size; i++) { |
| 2576 | if (i >= buflen) | ||
| 2577 | break; | ||
| 2575 | string[i] = (char)(le16_to_cpu(unicode[i])); | 2578 | string[i] = (char)(le16_to_cpu(unicode[i])); |
| 2576 | string[unicode_size] = 0x00; | 2579 | } |
| 2580 | string[i] = 0x00; | ||
| 2577 | } | 2581 | } |
| 2578 | 2582 | ||
| 2579 | 2583 | ||
| @@ -2603,11 +2607,17 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial) | |||
| 2603 | dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); | 2607 | dbg(" BoardRev: %d", edge_serial->manuf_descriptor.BoardRev); |
| 2604 | dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); | 2608 | dbg(" NumPorts: %d", edge_serial->manuf_descriptor.NumPorts); |
| 2605 | dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); | 2609 | dbg(" DescDate: %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); |
| 2606 | unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1); | 2610 | unicode_to_ascii(string, sizeof(string), |
| 2611 | edge_serial->manuf_descriptor.SerialNumber, | ||
| 2612 | edge_serial->manuf_descriptor.SerNumLength/2); | ||
| 2607 | dbg(" SerialNumber: %s", string); | 2613 | dbg(" SerialNumber: %s", string); |
| 2608 | unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1); | 2614 | unicode_to_ascii(string, sizeof(string), |
| 2615 | edge_serial->manuf_descriptor.AssemblyNumber, | ||
| 2616 | edge_serial->manuf_descriptor.AssemblyNumLength/2); | ||
| 2609 | dbg(" AssemblyNumber: %s", string); | 2617 | dbg(" AssemblyNumber: %s", string); |
| 2610 | unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1); | 2618 | unicode_to_ascii(string, sizeof(string), |
| 2619 | edge_serial->manuf_descriptor.OemAssyNumber, | ||
| 2620 | edge_serial->manuf_descriptor.OemAssyNumLength/2); | ||
| 2611 | dbg(" OemAssyNumber: %s", string); | 2621 | dbg(" OemAssyNumber: %s", string); |
| 2612 | dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); | 2622 | dbg(" UartType: %d", edge_serial->manuf_descriptor.UartType); |
| 2613 | dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); | 2623 | dbg(" IonPid: %d", edge_serial->manuf_descriptor.IonPid); |
| @@ -2720,7 +2730,7 @@ static int edge_startup (struct usb_serial *serial) | |||
| 2720 | struct edgeport_serial *edge_serial; | 2730 | struct edgeport_serial *edge_serial; |
| 2721 | struct edgeport_port *edge_port; | 2731 | struct edgeport_port *edge_port; |
| 2722 | struct usb_device *dev; | 2732 | struct usb_device *dev; |
| 2723 | int i; | 2733 | int i, j; |
| 2724 | 2734 | ||
| 2725 | dev = serial->dev; | 2735 | dev = serial->dev; |
| 2726 | 2736 | ||
| @@ -2735,11 +2745,11 @@ static int edge_startup (struct usb_serial *serial) | |||
| 2735 | usb_set_serial_data(serial, edge_serial); | 2745 | usb_set_serial_data(serial, edge_serial); |
| 2736 | 2746 | ||
| 2737 | /* get the name for the device from the device */ | 2747 | /* get the name for the device from the device */ |
| 2738 | if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) { | 2748 | i = get_string(dev, dev->descriptor.iManufacturer, |
| 2739 | edge_serial->name[i-1] = ' '; | 2749 | &edge_serial->name[0], MAX_NAME_LEN+1); |
| 2740 | } | 2750 | edge_serial->name[i++] = ' '; |
| 2741 | 2751 | get_string(dev, dev->descriptor.iProduct, | |
| 2742 | get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]); | 2752 | &edge_serial->name[i], MAX_NAME_LEN+2 - i); |
| 2743 | 2753 | ||
| 2744 | dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); | 2754 | dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); |
| 2745 | 2755 | ||
| @@ -2784,6 +2794,10 @@ static int edge_startup (struct usb_serial *serial) | |||
| 2784 | edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); | 2794 | edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL); |
| 2785 | if (edge_port == NULL) { | 2795 | if (edge_port == NULL) { |
| 2786 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); | 2796 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__); |
| 2797 | for (j = 0; j < i; ++j) { | ||
| 2798 | kfree (usb_get_serial_port_data(serial->port[j])); | ||
| 2799 | usb_set_serial_port_data(serial->port[j], NULL); | ||
| 2800 | } | ||
| 2787 | usb_set_serial_data(serial, NULL); | 2801 | usb_set_serial_data(serial, NULL); |
| 2788 | kfree(edge_serial); | 2802 | kfree(edge_serial); |
| 2789 | return -ENOMEM; | 2803 | return -ENOMEM; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 9a5c97989562..9da6d2a8f2b0 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
| @@ -870,7 +870,7 @@ static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
| 870 | spin_unlock_irqrestore(&write_list_lock, flags); | 870 | spin_unlock_irqrestore(&write_list_lock, flags); |
| 871 | } | 871 | } |
| 872 | 872 | ||
| 873 | schedule_work(&port->work); | 873 | usb_serial_port_softint(port); |
| 874 | } | 874 | } |
| 875 | 875 | ||
| 876 | static int ipaq_write_room(struct usb_serial_port *port) | 876 | static int ipaq_write_room(struct usb_serial_port *port) |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index e760a70242c1..a4a0bfeaab00 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
| @@ -376,7 +376,7 @@ static void ipw_write_bulk_callback(struct urb *urb, struct pt_regs *regs) | |||
| 376 | if (urb->status) | 376 | if (urb->status) |
| 377 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 377 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); |
| 378 | 378 | ||
| 379 | schedule_work(&port->work); | 379 | usb_serial_port_softint(port); |
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) | 382 | static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count) |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 426182ddc42a..9432c7302275 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
| @@ -408,7 +408,7 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
| 408 | urb->actual_length, | 408 | urb->actual_length, |
| 409 | urb->transfer_buffer); | 409 | urb->transfer_buffer); |
| 410 | 410 | ||
| 411 | schedule_work(&port->work); | 411 | usb_serial_port_softint(port); |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) | 414 | static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs) |
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 052b735c4fbd..2cf6ade704e4 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
| @@ -481,7 +481,7 @@ static void usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs) | |||
| 481 | dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); | 481 | dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); |
| 482 | 482 | ||
| 483 | if (port->open_count) | 483 | if (port->open_count) |
| 484 | schedule_work(&port->work); | 484 | usb_serial_port_softint(port); |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) | 487 | static void usa26_inack_callback(struct urb *urb, struct pt_regs *regs) |
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 78335a5f7743..65d79f630fa4 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
| @@ -569,8 +569,7 @@ static void klsi_105_write_bulk_callback ( struct urb *urb, struct pt_regs *regs | |||
| 569 | return; | 569 | return; |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | /* from generic_write_bulk_callback */ | 572 | usb_serial_port_softint(port); |
| 573 | schedule_work(&port->work); | ||
| 574 | } /* klsi_105_write_bulk_completion_callback */ | 573 | } /* klsi_105_write_bulk_completion_callback */ |
| 575 | 574 | ||
| 576 | 575 | ||
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 238033a87092..6dcdb5f598b8 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
| @@ -320,7 +320,7 @@ static void omninet_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
| 320 | return; | 320 | return; |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | schedule_work(&port->work); | 323 | usb_serial_port_softint(port); |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | 326 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cf2b80add7a..b0861b61bba7 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | Option Card (PCMCIA to) USB to Serial Driver | 2 | USB Driver for GSM modems |
| 3 | 3 | ||
| 4 | Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de> | 4 | Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de> |
| 5 | 5 | ||
| @@ -28,15 +28,34 @@ | |||
| 28 | 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard | 28 | 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard |
| 29 | 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes | 29 | 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes |
| 30 | wants to send >2000 bytes. | 30 | wants to send >2000 bytes. |
| 31 | 2006-04-10 v0.4.2 fixed two array overrun errors :-/ | 31 | 2006-04-10 v0.5 fixed two array overrun errors :-/ |
| 32 | 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 | ||
| 33 | 2006-05-15 v0.6 re-enable multi-port support | ||
| 34 | 2006-06-01 v0.6.1 add COBRA | ||
| 35 | 2006-06-01 v0.6.2 add backwards-compatibility stuff | ||
| 36 | 2006-06-01 v0.6.3 add Novatel Wireless | ||
| 37 | 2006-06-01 v0.7 Option => GSM | ||
| 32 | 38 | ||
| 33 | Work sponsored by: Sigos GmbH, Germany <info@sigos.de> | 39 | Work sponsored by: Sigos GmbH, Germany <info@sigos.de> |
| 34 | 40 | ||
| 41 | This driver exists because the "normal" serial driver doesn't work too well | ||
| 42 | with GSM modems. Issues: | ||
| 43 | - data loss -- one single Receive URB is not nearly enough | ||
| 44 | - nonstandard flow (Option devices) and multiplex (Sierra) control | ||
| 45 | - controlling the baud rate doesn't make sense | ||
| 46 | |||
| 47 | This driver is named "option" because the most common device it's | ||
| 48 | used for is a PC-Card (with an internal OHCI-USB interface, behind | ||
| 49 | which the GSM interface sits), made by Option Inc. | ||
| 50 | |||
| 51 | Some of the "one port" devices actually exhibit multiple USB instances | ||
| 52 | on the USB bus. This is not a bug, these ports are used for different | ||
| 53 | device features. | ||
| 35 | */ | 54 | */ |
| 36 | 55 | ||
| 37 | #define DRIVER_VERSION "v0.4" | 56 | #define DRIVER_VERSION "v0.7.0" |
| 38 | #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" | 57 | #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>" |
| 39 | #define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver" | 58 | #define DRIVER_DESC "USB Driver for GSM modems" |
| 40 | 59 | ||
| 41 | #include <linux/config.h> | 60 | #include <linux/config.h> |
| 42 | #include <linux/kernel.h> | 61 | #include <linux/kernel.h> |
| @@ -74,22 +93,45 @@ static int option_tiocmset(struct usb_serial_port *port, struct file *file, | |||
| 74 | static int option_send_setup(struct usb_serial_port *port); | 93 | static int option_send_setup(struct usb_serial_port *port); |
| 75 | 94 | ||
| 76 | /* Vendor and product IDs */ | 95 | /* Vendor and product IDs */ |
| 77 | #define OPTION_VENDOR_ID 0x0AF0 | 96 | #define OPTION_VENDOR_ID 0x0AF0 |
| 78 | #define HUAWEI_VENDOR_ID 0x12D1 | 97 | #define HUAWEI_VENDOR_ID 0x12D1 |
| 79 | #define AUDIOVOX_VENDOR_ID 0x0F3D | 98 | #define AUDIOVOX_VENDOR_ID 0x0F3D |
| 80 | 99 | #define SIERRAWIRELESS_VENDOR_ID 0x1199 | |
| 81 | #define OPTION_PRODUCT_OLD 0x5000 | 100 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 |
| 82 | #define OPTION_PRODUCT_FUSION 0x6000 | 101 | |
| 83 | #define OPTION_PRODUCT_FUSION2 0x6300 | 102 | #define OPTION_PRODUCT_OLD 0x5000 |
| 84 | #define HUAWEI_PRODUCT_E600 0x1001 | 103 | #define OPTION_PRODUCT_FUSION 0x6000 |
| 85 | #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 | 104 | #define OPTION_PRODUCT_FUSION2 0x6300 |
| 105 | #define OPTION_PRODUCT_COBRA 0x6500 | ||
| 106 | #define HUAWEI_PRODUCT_E600 0x1001 | ||
| 107 | #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 | ||
| 108 | #define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 | ||
| 109 | #define NOVATELWIRELESS_PRODUCT_U740 0x1400 | ||
| 86 | 110 | ||
| 87 | static struct usb_device_id option_ids[] = { | 111 | static struct usb_device_id option_ids[] = { |
| 88 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, | 112 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, |
| 89 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, | 113 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, |
| 90 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, | 114 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, |
| 115 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, | ||
| 91 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | 116 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, |
| 92 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, | 117 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, |
| 118 | { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, | ||
| 119 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | ||
| 120 | { } /* Terminating entry */ | ||
| 121 | }; | ||
| 122 | |||
| 123 | static struct usb_device_id option_ids1[] = { | ||
| 124 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, | ||
| 125 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) }, | ||
| 126 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) }, | ||
| 127 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) }, | ||
| 128 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, | ||
| 129 | { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, | ||
| 130 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, | ||
| 131 | { } /* Terminating entry */ | ||
| 132 | }; | ||
| 133 | static struct usb_device_id option_ids3[] = { | ||
| 134 | { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, | ||
| 93 | { } /* Terminating entry */ | 135 | { } /* Terminating entry */ |
| 94 | }; | 136 | }; |
| 95 | 137 | ||
| @@ -111,12 +153,39 @@ static struct usb_serial_driver option_3port_device = { | |||
| 111 | .owner = THIS_MODULE, | 153 | .owner = THIS_MODULE, |
| 112 | .name = "option", | 154 | .name = "option", |
| 113 | }, | 155 | }, |
| 114 | .description = "Option 3G data card", | 156 | .description = "GSM modem (3-port)", |
| 115 | .id_table = option_ids, | 157 | .id_table = option_ids3, |
| 116 | .num_interrupt_in = NUM_DONT_CARE, | 158 | .num_interrupt_in = NUM_DONT_CARE, |
| 117 | .num_bulk_in = NUM_DONT_CARE, | 159 | .num_bulk_in = NUM_DONT_CARE, |
| 118 | .num_bulk_out = NUM_DONT_CARE, | 160 | .num_bulk_out = NUM_DONT_CARE, |
| 119 | .num_ports = 1, /* 3, but the card reports its ports separately */ | 161 | .num_ports = 3, |
| 162 | .open = option_open, | ||
| 163 | .close = option_close, | ||
| 164 | .write = option_write, | ||
| 165 | .write_room = option_write_room, | ||
| 166 | .chars_in_buffer = option_chars_in_buffer, | ||
| 167 | .throttle = option_rx_throttle, | ||
| 168 | .unthrottle = option_rx_unthrottle, | ||
| 169 | .set_termios = option_set_termios, | ||
| 170 | .break_ctl = option_break_ctl, | ||
| 171 | .tiocmget = option_tiocmget, | ||
| 172 | .tiocmset = option_tiocmset, | ||
| 173 | .attach = option_startup, | ||
| 174 | .shutdown = option_shutdown, | ||
| 175 | .read_int_callback = option_instat_callback, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static struct usb_serial_driver option_1port_device = { | ||
| 179 | .driver = { | ||
| 180 | .owner = THIS_MODULE, | ||
| 181 | .name = "option", | ||
| 182 | }, | ||
| 183 | .description = "GSM modem (1-port)", | ||
| 184 | .id_table = option_ids1, | ||
| 185 | .num_interrupt_in = NUM_DONT_CARE, | ||
| 186 | .num_bulk_in = NUM_DONT_CARE, | ||
| 187 | .num_bulk_out = NUM_DONT_CARE, | ||
| 188 | .num_ports = 1, | ||
| 120 | .open = option_open, | 189 | .open = option_open, |
| 121 | .close = option_close, | 190 | .close = option_close, |
| 122 | .write = option_write, | 191 | .write = option_write, |
| @@ -170,6 +239,9 @@ struct option_port_private { | |||
| 170 | static int __init option_init(void) | 239 | static int __init option_init(void) |
| 171 | { | 240 | { |
| 172 | int retval; | 241 | int retval; |
| 242 | retval = usb_serial_register(&option_1port_device); | ||
| 243 | if (retval) | ||
| 244 | goto failed_1port_device_register; | ||
| 173 | retval = usb_serial_register(&option_3port_device); | 245 | retval = usb_serial_register(&option_3port_device); |
| 174 | if (retval) | 246 | if (retval) |
| 175 | goto failed_3port_device_register; | 247 | goto failed_3port_device_register; |
| @@ -184,6 +256,8 @@ static int __init option_init(void) | |||
| 184 | failed_driver_register: | 256 | failed_driver_register: |
| 185 | usb_serial_deregister (&option_3port_device); | 257 | usb_serial_deregister (&option_3port_device); |
| 186 | failed_3port_device_register: | 258 | failed_3port_device_register: |
| 259 | usb_serial_deregister (&option_1port_device); | ||
| 260 | failed_1port_device_register: | ||
| 187 | return retval; | 261 | return retval; |
| 188 | } | 262 | } |
| 189 | 263 | ||
| @@ -191,6 +265,7 @@ static void __exit option_exit(void) | |||
| 191 | { | 265 | { |
| 192 | usb_deregister (&option_driver); | 266 | usb_deregister (&option_driver); |
| 193 | usb_serial_deregister (&option_3port_device); | 267 | usb_serial_deregister (&option_3port_device); |
| 268 | usb_serial_deregister (&option_1port_device); | ||
| 194 | } | 269 | } |
| 195 | 270 | ||
| 196 | module_init(option_init); | 271 | module_init(option_init); |
| @@ -365,8 +440,7 @@ static void option_outdat_callback(struct urb *urb, struct pt_regs *regs) | |||
| 365 | 440 | ||
| 366 | port = (struct usb_serial_port *) urb->context; | 441 | port = (struct usb_serial_port *) urb->context; |
| 367 | 442 | ||
| 368 | if (port->open_count) | 443 | usb_serial_port_softint(port); |
| 369 | schedule_work(&port->work); | ||
| 370 | } | 444 | } |
| 371 | 445 | ||
| 372 | static void option_instat_callback(struct urb *urb, struct pt_regs *regs) | 446 | static void option_instat_callback(struct urb *urb, struct pt_regs *regs) |
| @@ -573,27 +647,30 @@ static struct urb *option_setup_urb(struct usb_serial *serial, int endpoint, | |||
| 573 | /* Setup urbs */ | 647 | /* Setup urbs */ |
| 574 | static void option_setup_urbs(struct usb_serial *serial) | 648 | static void option_setup_urbs(struct usb_serial *serial) |
| 575 | { | 649 | { |
| 576 | int j; | 650 | int i,j; |
| 577 | struct usb_serial_port *port; | 651 | struct usb_serial_port *port; |
| 578 | struct option_port_private *portdata; | 652 | struct option_port_private *portdata; |
| 579 | 653 | ||
| 580 | dbg("%s", __FUNCTION__); | 654 | dbg("%s", __FUNCTION__); |
| 581 | 655 | ||
| 582 | port = serial->port[0]; | 656 | |
| 583 | portdata = usb_get_serial_port_data(port); | 657 | for (i = 0; i < serial->num_ports; i++) { |
| 658 | port = serial->port[i]; | ||
| 659 | portdata = usb_get_serial_port_data(port); | ||
| 584 | 660 | ||
| 585 | /* Do indat endpoints first */ | 661 | /* Do indat endpoints first */ |
| 586 | for (j = 0; j < N_IN_URB; ++j) { | 662 | for (j = 0; j < N_IN_URB; ++j) { |
| 587 | portdata->in_urbs[j] = option_setup_urb (serial, | 663 | portdata->in_urbs[j] = option_setup_urb (serial, |
| 588 | port->bulk_in_endpointAddress, USB_DIR_IN, port, | 664 | port->bulk_in_endpointAddress, USB_DIR_IN, port, |
| 589 | portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); | 665 | portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); |
| 590 | } | 666 | } |
| 591 | 667 | ||
| 592 | /* outdat endpoints */ | 668 | /* outdat endpoints */ |
| 593 | for (j = 0; j < N_OUT_URB; ++j) { | 669 | for (j = 0; j < N_OUT_URB; ++j) { |
| 594 | portdata->out_urbs[j] = option_setup_urb (serial, | 670 | portdata->out_urbs[j] = option_setup_urb (serial, |
| 595 | port->bulk_out_endpointAddress, USB_DIR_OUT, port, | 671 | port->bulk_out_endpointAddress, USB_DIR_OUT, port, |
| 596 | portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); | 672 | portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); |
| 673 | } | ||
| 597 | } | 674 | } |
| 598 | } | 675 | } |
| 599 | 676 | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c96714bb1cb8..d88704387202 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
| @@ -314,7 +314,7 @@ static void pl2303_send(struct usb_serial_port *port) | |||
| 314 | // TODO: reschedule pl2303_send | 314 | // TODO: reschedule pl2303_send |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | schedule_work(&port->work); | 317 | usb_serial_port_softint(port); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static int pl2303_write_room(struct usb_serial_port *port) | 320 | static int pl2303_write_room(struct usb_serial_port *port) |
| @@ -600,7 +600,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) | |||
| 600 | unsigned int c_cflag; | 600 | unsigned int c_cflag; |
| 601 | int bps; | 601 | int bps; |
| 602 | long timeout; | 602 | long timeout; |
| 603 | wait_queue_t wait; \ | 603 | wait_queue_t wait; |
| 604 | 604 | ||
| 605 | dbg("%s - port %d", __FUNCTION__, port->number); | 605 | dbg("%s - port %d", __FUNCTION__, port->number); |
| 606 | 606 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9c36f0ece20f..a30135c7cfe6 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -162,12 +162,19 @@ static void destroy_serial(struct kref *kref) | |||
| 162 | } | 162 | } |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | flush_scheduled_work(); /* port->work */ | ||
| 166 | |||
| 165 | usb_put_dev(serial->dev); | 167 | usb_put_dev(serial->dev); |
| 166 | 168 | ||
| 167 | /* free up any memory that we allocated */ | 169 | /* free up any memory that we allocated */ |
| 168 | kfree (serial); | 170 | kfree (serial); |
| 169 | } | 171 | } |
| 170 | 172 | ||
| 173 | void usb_serial_put(struct usb_serial *serial) | ||
| 174 | { | ||
| 175 | kref_put(&serial->kref, destroy_serial); | ||
| 176 | } | ||
| 177 | |||
| 171 | /***************************************************************************** | 178 | /***************************************************************************** |
| 172 | * Driver tty interface functions | 179 | * Driver tty interface functions |
| 173 | *****************************************************************************/ | 180 | *****************************************************************************/ |
| @@ -201,12 +208,12 @@ static int serial_open (struct tty_struct *tty, struct file * filp) | |||
| 201 | 208 | ||
| 202 | ++port->open_count; | 209 | ++port->open_count; |
| 203 | 210 | ||
| 204 | if (port->open_count == 1) { | 211 | /* set up our port structure making the tty driver |
| 212 | * remember our port object, and us it */ | ||
| 213 | tty->driver_data = port; | ||
| 214 | port->tty = tty; | ||
| 205 | 215 | ||
| 206 | /* set up our port structure making the tty driver | 216 | if (port->open_count == 1) { |
| 207 | * remember our port object, and us it */ | ||
| 208 | tty->driver_data = port; | ||
| 209 | port->tty = tty; | ||
| 210 | 217 | ||
| 211 | /* lock this module before we call it | 218 | /* lock this module before we call it |
| 212 | * this may fail, which means we must bail out, | 219 | * this may fail, which means we must bail out, |
| @@ -230,9 +237,11 @@ bailout_module_put: | |||
| 230 | module_put(serial->type->driver.owner); | 237 | module_put(serial->type->driver.owner); |
| 231 | bailout_mutex_unlock: | 238 | bailout_mutex_unlock: |
| 232 | port->open_count = 0; | 239 | port->open_count = 0; |
| 240 | tty->driver_data = NULL; | ||
| 241 | port->tty = NULL; | ||
| 233 | mutex_unlock(&port->mutex); | 242 | mutex_unlock(&port->mutex); |
| 234 | bailout_kref_put: | 243 | bailout_kref_put: |
| 235 | kref_put(&serial->kref, destroy_serial); | 244 | usb_serial_put(serial); |
| 236 | return retval; | 245 | return retval; |
| 237 | } | 246 | } |
| 238 | 247 | ||
| @@ -268,7 +277,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) | |||
| 268 | } | 277 | } |
| 269 | 278 | ||
| 270 | mutex_unlock(&port->mutex); | 279 | mutex_unlock(&port->mutex); |
| 271 | kref_put(&port->serial->kref, destroy_serial); | 280 | usb_serial_put(port->serial); |
| 272 | } | 281 | } |
| 273 | 282 | ||
| 274 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) | 283 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) |
| @@ -276,7 +285,7 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int | |||
| 276 | struct usb_serial_port *port = tty->driver_data; | 285 | struct usb_serial_port *port = tty->driver_data; |
| 277 | int retval = -EINVAL; | 286 | int retval = -EINVAL; |
| 278 | 287 | ||
| 279 | if (!port) | 288 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) |
| 280 | goto exit; | 289 | goto exit; |
| 281 | 290 | ||
| 282 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); | 291 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); |
| @@ -296,7 +305,7 @@ exit: | |||
| 296 | static int serial_write_room (struct tty_struct *tty) | 305 | static int serial_write_room (struct tty_struct *tty) |
| 297 | { | 306 | { |
| 298 | struct usb_serial_port *port = tty->driver_data; | 307 | struct usb_serial_port *port = tty->driver_data; |
| 299 | int retval = -EINVAL; | 308 | int retval = -ENODEV; |
| 300 | 309 | ||
| 301 | if (!port) | 310 | if (!port) |
| 302 | goto exit; | 311 | goto exit; |
| @@ -318,7 +327,7 @@ exit: | |||
| 318 | static int serial_chars_in_buffer (struct tty_struct *tty) | 327 | static int serial_chars_in_buffer (struct tty_struct *tty) |
| 319 | { | 328 | { |
| 320 | struct usb_serial_port *port = tty->driver_data; | 329 | struct usb_serial_port *port = tty->driver_data; |
| 321 | int retval = -EINVAL; | 330 | int retval = -ENODEV; |
| 322 | 331 | ||
| 323 | if (!port) | 332 | if (!port) |
| 324 | goto exit; | 333 | goto exit; |
| @@ -473,7 +482,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int | |||
| 473 | begin += length; | 482 | begin += length; |
| 474 | length = 0; | 483 | length = 0; |
| 475 | } | 484 | } |
| 476 | kref_put(&serial->kref, destroy_serial); | 485 | usb_serial_put(serial); |
| 477 | } | 486 | } |
| 478 | *eof = 1; | 487 | *eof = 1; |
| 479 | done: | 488 | done: |
| @@ -488,19 +497,18 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file) | |||
| 488 | struct usb_serial_port *port = tty->driver_data; | 497 | struct usb_serial_port *port = tty->driver_data; |
| 489 | 498 | ||
| 490 | if (!port) | 499 | if (!port) |
| 491 | goto exit; | 500 | return -ENODEV; |
| 492 | 501 | ||
| 493 | dbg("%s - port %d", __FUNCTION__, port->number); | 502 | dbg("%s - port %d", __FUNCTION__, port->number); |
| 494 | 503 | ||
| 495 | if (!port->open_count) { | 504 | if (!port->open_count) { |
| 496 | dbg("%s - port not open", __FUNCTION__); | 505 | dbg("%s - port not open", __FUNCTION__); |
| 497 | goto exit; | 506 | return -ENODEV; |
| 498 | } | 507 | } |
| 499 | 508 | ||
| 500 | if (port->serial->type->tiocmget) | 509 | if (port->serial->type->tiocmget) |
| 501 | return port->serial->type->tiocmget(port, file); | 510 | return port->serial->type->tiocmget(port, file); |
| 502 | 511 | ||
| 503 | exit: | ||
| 504 | return -EINVAL; | 512 | return -EINVAL; |
| 505 | } | 513 | } |
| 506 | 514 | ||
| @@ -510,23 +518,32 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file, | |||
| 510 | struct usb_serial_port *port = tty->driver_data; | 518 | struct usb_serial_port *port = tty->driver_data; |
| 511 | 519 | ||
| 512 | if (!port) | 520 | if (!port) |
| 513 | goto exit; | 521 | return -ENODEV; |
| 514 | 522 | ||
| 515 | dbg("%s - port %d", __FUNCTION__, port->number); | 523 | dbg("%s - port %d", __FUNCTION__, port->number); |
| 516 | 524 | ||
| 517 | if (!port->open_count) { | 525 | if (!port->open_count) { |
| 518 | dbg("%s - port not open", __FUNCTION__); | 526 | dbg("%s - port not open", __FUNCTION__); |
| 519 | goto exit; | 527 | return -ENODEV; |
| 520 | } | 528 | } |
| 521 | 529 | ||
| 522 | if (port->serial->type->tiocmset) | 530 | if (port->serial->type->tiocmset) |
| 523 | return port->serial->type->tiocmset(port, file, set, clear); | 531 | return port->serial->type->tiocmset(port, file, set, clear); |
| 524 | 532 | ||
| 525 | exit: | ||
| 526 | return -EINVAL; | 533 | return -EINVAL; |
| 527 | } | 534 | } |
| 528 | 535 | ||
| 529 | void usb_serial_port_softint(void *private) | 536 | /* |
| 537 | * We would be calling tty_wakeup here, but unfortunately some line | ||
| 538 | * disciplines have an annoying habit of calling tty->write from | ||
| 539 | * the write wakeup callback (e.g. n_hdlc.c). | ||
| 540 | */ | ||
| 541 | void usb_serial_port_softint(struct usb_serial_port *port) | ||
| 542 | { | ||
| 543 | schedule_work(&port->work); | ||
| 544 | } | ||
| 545 | |||
| 546 | static void usb_serial_port_work(void *private) | ||
| 530 | { | 547 | { |
| 531 | struct usb_serial_port *port = private; | 548 | struct usb_serial_port *port = private; |
| 532 | struct tty_struct *tty; | 549 | struct tty_struct *tty; |
| @@ -789,7 +806,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 789 | port->serial = serial; | 806 | port->serial = serial; |
| 790 | spin_lock_init(&port->lock); | 807 | spin_lock_init(&port->lock); |
| 791 | mutex_init(&port->mutex); | 808 | mutex_init(&port->mutex); |
| 792 | INIT_WORK(&port->work, usb_serial_port_softint, port); | 809 | INIT_WORK(&port->work, usb_serial_port_work, port); |
| 793 | serial->port[i] = port; | 810 | serial->port[i] = port; |
| 794 | } | 811 | } |
| 795 | 812 | ||
| @@ -985,6 +1002,7 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
| 985 | struct device *dev = &interface->dev; | 1002 | struct device *dev = &interface->dev; |
| 986 | struct usb_serial_port *port; | 1003 | struct usb_serial_port *port; |
| 987 | 1004 | ||
| 1005 | usb_serial_console_disconnect(serial); | ||
| 988 | dbg ("%s", __FUNCTION__); | 1006 | dbg ("%s", __FUNCTION__); |
| 989 | 1007 | ||
| 990 | usb_set_intfdata (interface, NULL); | 1008 | usb_set_intfdata (interface, NULL); |
| @@ -996,7 +1014,7 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
| 996 | } | 1014 | } |
| 997 | /* let the last holder of this object | 1015 | /* let the last holder of this object |
| 998 | * cause it to be cleaned up */ | 1016 | * cause it to be cleaned up */ |
| 999 | kref_put(&serial->kref, destroy_serial); | 1017 | usb_serial_put(serial); |
| 1000 | } | 1018 | } |
| 1001 | dev_info(dev, "device disconnected\n"); | 1019 | dev_info(dev, "device disconnected\n"); |
| 1002 | } | 1020 | } |
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index dc89d8710460..d53ea9b11e81 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h | |||
| @@ -236,7 +236,7 @@ struct usb_serial_driver { | |||
| 236 | 236 | ||
| 237 | extern int usb_serial_register(struct usb_serial_driver *driver); | 237 | extern int usb_serial_register(struct usb_serial_driver *driver); |
| 238 | extern void usb_serial_deregister(struct usb_serial_driver *driver); | 238 | extern void usb_serial_deregister(struct usb_serial_driver *driver); |
| 239 | extern void usb_serial_port_softint(void *private); | 239 | extern void usb_serial_port_softint(struct usb_serial_port *port); |
| 240 | 240 | ||
| 241 | extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); | 241 | extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); |
| 242 | extern void usb_serial_disconnect(struct usb_interface *iface); | 242 | extern void usb_serial_disconnect(struct usb_interface *iface); |
| @@ -248,13 +248,16 @@ extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); | |||
| 248 | #ifdef CONFIG_USB_SERIAL_CONSOLE | 248 | #ifdef CONFIG_USB_SERIAL_CONSOLE |
| 249 | extern void usb_serial_console_init (int debug, int minor); | 249 | extern void usb_serial_console_init (int debug, int minor); |
| 250 | extern void usb_serial_console_exit (void); | 250 | extern void usb_serial_console_exit (void); |
| 251 | extern void usb_serial_console_disconnect(struct usb_serial *serial); | ||
| 251 | #else | 252 | #else |
| 252 | static inline void usb_serial_console_init (int debug, int minor) { } | 253 | static inline void usb_serial_console_init (int debug, int minor) { } |
| 253 | static inline void usb_serial_console_exit (void) { } | 254 | static inline void usb_serial_console_exit (void) { } |
| 255 | static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} | ||
| 254 | #endif | 256 | #endif |
| 255 | 257 | ||
| 256 | /* Functions needed by other parts of the usbserial core */ | 258 | /* Functions needed by other parts of the usbserial core */ |
| 257 | extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); | 259 | extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); |
| 260 | extern void usb_serial_put(struct usb_serial *serial); | ||
| 258 | extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); | 261 | extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); |
| 259 | extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); | 262 | extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); |
| 260 | extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); | 263 | extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f5c3841d4843..9e89b8d54f72 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
| @@ -480,7 +480,7 @@ static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs) | |||
| 480 | --priv->outstanding_urbs; | 480 | --priv->outstanding_urbs; |
| 481 | spin_unlock_irqrestore(&priv->lock, flags); | 481 | spin_unlock_irqrestore(&priv->lock, flags); |
| 482 | 482 | ||
| 483 | schedule_work(&port->work); | 483 | usb_serial_port_softint(port); |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | 486 | ||
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index f806553cd9a4..5b06fa366098 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
| @@ -388,7 +388,7 @@ static int whiteheat_attach (struct usb_serial *serial) | |||
| 388 | if (ret) { | 388 | if (ret) { |
| 389 | err("%s: Couldn't send command [%d]", serial->type->description, ret); | 389 | err("%s: Couldn't send command [%d]", serial->type->description, ret); |
| 390 | goto no_firmware; | 390 | goto no_firmware; |
| 391 | } else if (alen != sizeof(command)) { | 391 | } else if (alen != 2) { |
| 392 | err("%s: Send command incomplete [%d]", serial->type->description, alen); | 392 | err("%s: Send command incomplete [%d]", serial->type->description, alen); |
| 393 | goto no_firmware; | 393 | goto no_firmware; |
| 394 | } | 394 | } |
| @@ -400,7 +400,7 @@ static int whiteheat_attach (struct usb_serial *serial) | |||
| 400 | if (ret) { | 400 | if (ret) { |
| 401 | err("%s: Couldn't get results [%d]", serial->type->description, ret); | 401 | err("%s: Couldn't get results [%d]", serial->type->description, ret); |
| 402 | goto no_firmware; | 402 | goto no_firmware; |
| 403 | } else if (alen != sizeof(result)) { | 403 | } else if (alen != sizeof(*hw_info) + 1) { |
| 404 | err("%s: Get results incomplete [%d]", serial->type->description, alen); | 404 | err("%s: Get results incomplete [%d]", serial->type->description, alen); |
| 405 | goto no_firmware; | 405 | goto no_firmware; |
| 406 | } else if (result[0] != command[0]) { | 406 | } else if (result[0] != command[0]) { |
| @@ -1089,9 +1089,7 @@ static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs) | |||
| 1089 | return; | 1089 | return; |
| 1090 | } | 1090 | } |
| 1091 | 1091 | ||
| 1092 | usb_serial_port_softint((void *)port); | 1092 | usb_serial_port_softint(port); |
| 1093 | |||
| 1094 | schedule_work(&port->work); | ||
| 1095 | } | 1093 | } |
| 1096 | 1094 | ||
| 1097 | 1095 | ||
