diff options
Diffstat (limited to 'drivers/usb/serial/sierra.c')
| -rw-r--r-- | drivers/usb/serial/sierra.c | 503 |
1 files changed, 225 insertions, 278 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 7481ff8a49e..6f7f01eb556 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -18,7 +18,7 @@ */ /* Uncomment to log function calls */ /* #define DEBUG */ -#define DRIVER_VERSION "v.1.7.16" + #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" @@ -46,8 +46,7 @@ allocations > PAGE_SIZE and the number of packets in a page is an integer 512 is the largest possible packet on EHCI */ -static int debug; -static int nmea; +static bool nmea; /* Used in interface blacklisting */ struct sierra_iface_info { @@ -59,13 +58,12 @@ 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) { - int result; - dev_dbg(&udev->dev, "%s\n", __func__); - result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), SWIMS_USB_REQUEST_SetPower, /* __u8 request */ USB_TYPE_VENDOR, /* __u8 request type */ swiState, /* __u16 value */ @@ -73,14 +71,11 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) NULL, /* void *data */ 0, /* __u16 size */ USB_CTRL_SET_TIMEOUT); /* int timeout */ - return result; } static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) { - int result; - dev_dbg(&udev->dev, "%s\n", __func__); - result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), SWIMS_USB_REQUEST_SetNmea, /* __u8 request */ USB_TYPE_VENDOR, /* __u8 request type */ enable, /* __u16 value */ @@ -88,7 +83,6 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) NULL, /* void *data */ 0, /* __u16 size */ USB_CTRL_SET_TIMEOUT); /* int timeout */ - return result; } static int sierra_calc_num_ports(struct usb_serial *serial) @@ -96,8 +90,6 @@ static int sierra_calc_num_ports(struct usb_serial *serial) int num_ports = 0; u8 ifnum, numendpoints; - dev_dbg(&serial->dev->dev, "%s\n", __func__); - ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints; @@ -150,7 +142,6 @@ static int sierra_calc_interface(struct usb_serial *serial) int interface; struct usb_interface *p_interface; struct usb_host_interface *p_host_interface; - dev_dbg(&serial->dev->dev, "%s\n", __func__); /* Get the interface structure pointer from the serial struct */ p_interface = serial->interface; @@ -171,13 +162,11 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; - dev_dbg(&udev->dev, "%s\n", __func__); - ifnum = sierra_calc_interface(serial); + /* * If this interface supports more than 1 alternate * select the 2nd one @@ -199,11 +188,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -221,7 +205,7 @@ static const struct sierra_iface_info typeB_interface_list = { }; /* 'blacklist' of interfaces not served by this driver */ -static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; +static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 }; static const struct sierra_iface_info direct_ip_interface_blacklist = { .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), .ifaceinfo = direct_ip_non_serial_ifaces, @@ -301,7 +285,13 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1199, 0x68A3), /* 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 */ + /* AT&T Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, + { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, { } }; @@ -326,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) @@ -338,8 +327,6 @@ static int sierra_send_setup(struct usb_serial_port *port) int do_send = 0; int retval; - dev_dbg(&port->dev, "%s\n", __func__); - portdata = usb_get_serial_port_data(port); if (portdata->dtr_state) @@ -373,29 +360,23 @@ static int sierra_send_setup(struct usb_serial_port *port) if (!do_send) return 0; - usb_autopm_get_interface(serial->interface); - retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + retval = usb_autopm_get_interface(serial->interface); + if (retval < 0) + return retval; + + 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) -{ - dev_dbg(&port->dev, "%s\n", __func__); - tty_termios_copy_hw(tty->termios, old_termios); - sierra_send_setup(port); -} - -static int sierra_tiocmget(struct tty_struct *tty, struct file *file) +static int sierra_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; unsigned int value; struct sierra_port_private *portdata; - dev_dbg(&port->dev, "%s\n", __func__); portdata = usb_get_serial_port_data(port); value = ((portdata->rts_state) ? TIOCM_RTS : 0) | @@ -408,7 +389,7 @@ static int sierra_tiocmget(struct tty_struct *tty, struct file *file) return value; } -static int sierra_tiocmset(struct tty_struct *tty, struct file *file, +static int sierra_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; @@ -430,10 +411,7 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file, static void sierra_release_urb(struct urb *urb) { - struct usb_serial_port *port; if (urb) { - port = urb->context; - dev_dbg(&port->dev, "%s: %p\n", __func__, urb); kfree(urb->transfer_buffer); usb_free_urb(urb); } @@ -446,8 +424,7 @@ static void sierra_outdat_callback(struct urb *urb) struct sierra_intf_private *intfdata; int status = urb->status; - dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); - 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); @@ -484,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); @@ -510,21 +487,19 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, buffer = kmalloc(writesize, GFP_ATOMIC); if (!buffer) { - dev_err(&port->dev, "out of memory\n"); retval = -ENOMEM; goto error_no_buffer; } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - dev_err(&port->dev, "no more free urbs\n"); retval = -ENOMEM; goto error_no_urb; } memcpy(buffer, buf, writesize); - usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer); + usb_serial_debug_data(&port->dev, __func__, writesize, buffer); usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, @@ -582,30 +557,23 @@ static void sierra_indat_callback(struct urb *urb) int err; int endpoint; struct usb_serial_port *port; - struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; endpoint = usb_pipeendpoint(urb->pipe); port = urb->context; - dev_dbg(&port->dev, "%s: %p\n", __func__, urb); - if (status) { dev_dbg(&port->dev, "%s: nonzero status: %d on" " endpoint %02x\n", __func__, status, endpoint); } else { if (urb->actual_length) { - tty = tty_port_tty_get(&port->port); - if (tty) { - tty_insert_flip_string(tty, data, - urb->actual_length); - tty_flip_buffer_push(tty); - - tty_kref_put(tty); - usb_serial_debug_data(debug, &port->dev, - __func__, urb->actual_length, data); - } + tty_insert_flip_string(&port->port, data, + urb->actual_length); + tty_flip_buffer_push(&port->port); + + usb_serial_debug_data(&port->dev, __func__, + urb->actual_length, data); } else { dev_dbg(&port->dev, "%s: empty read urb" " received\n", __func__); @@ -648,7 +616,6 @@ static void sierra_instat_callback(struct urb *urb) unsigned char signals = *((unsigned char *) urb->transfer_buffer + sizeof(struct usb_ctrlrequest)); - struct tty_struct *tty; dev_dbg(&port->dev, "%s: signal x%x\n", __func__, signals); @@ -659,11 +626,8 @@ static void sierra_instat_callback(struct urb *urb) portdata->dsr_state = ((signals & 0x02) ? 1 : 0); portdata->ri_state = ((signals & 0x08) ? 1 : 0); - tty = tty_port_tty_get(&port->port); - if (tty && !C_CLOCAL(tty) && - old_dcd_state && !portdata->dcd_state) - tty_hangup(tty); - tty_kref_put(tty); + if (old_dcd_state && !portdata->dcd_state) + tty_port_tty_hangup(&port->port, true); } else { dev_dbg(&port->dev, "%s: type %x req %x\n", __func__, req_pkt->bRequestType, @@ -675,7 +639,6 @@ static void sierra_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving IRQ data */ if (status != -ESHUTDOWN && status != -ENOENT) { usb_mark_last_busy(serial->dev); - urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err && err != -EPERM) dev_err(&port->dev, "%s: resubmit intr urb " @@ -689,8 +652,6 @@ static int sierra_write_room(struct tty_struct *tty) struct sierra_port_private *portdata = usb_get_serial_port_data(port); unsigned long flags; - dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); - /* try to give a good number back based on if we have any free urbs at * this point in time */ spin_lock_irqsave(&portdata->lock, flags); @@ -704,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; @@ -759,15 +737,9 @@ 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 == NULL) { - dev_dbg(&serial->dev->dev, "%s: alloc for endpoint %d failed\n", - __func__, endpoint); + if (!urb) return NULL; - } buf = kmalloc(len, mem_flags); if (buf) { @@ -776,13 +748,9 @@ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); - /* debug */ dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__, dir == USB_DIR_IN ? 'i' : 'o', urb, buf); } else { - dev_dbg(&serial->dev->dev, "%s %c u:%p d:%p\n", __func__, - dir == USB_DIR_IN ? 'i' : 'o', urb, buf); - sierra_release_urb(urb); urb = NULL; } @@ -795,43 +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; - dev_dbg(&port->dev, "%s\n", __func__); portdata = usb_get_serial_port_data(port); - portdata->rts_state = 0; - portdata->dtr_state = 0; + /* + * 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; + spin_unlock_irq(&intfdata->susp_lock); - if (serial->dev) { - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) { - serial->interface->needs_remote_wakeup = 0; - usb_autopm_get_interface(serial->interface); - sierra_send_setup(port); - } - mutex_unlock(&serial->disc_mutex); - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; - 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); + } + sierra_stop_rx_urbs(port); + usb_kill_anchored_urbs(&portdata->active); - /* Stop reading urbs */ - sierra_stop_rx_urbs(port); - /* .. and release them */ - for (i = 0; i < portdata->num_in_urbs; i++) { - sierra_release_urb(portdata->in_urbs[i]); - portdata->in_urbs[i] = NULL; - } + 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; @@ -839,13 +812,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) portdata = usb_get_serial_port_data(port); - dev_dbg(&port->dev, "%s\n", __func__); - - /* 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, @@ -858,51 +824,51 @@ 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 */ - 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; } static void sierra_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; portdata = usb_get_serial_port_data(port); portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) { - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) - sierra_send_setup(port); - mutex_unlock(&serial->disc_mutex); - } + sierra_send_setup(port); } static int sierra_startup(struct usb_serial *serial) { - struct usb_serial_port *port; - struct sierra_port_private *portdata; - struct sierra_iface_info *himemoryp = NULL; - int i; - u8 ifnum; + struct sierra_intf_private *intfdata; - dev_dbg(&serial->dev->dev, "%s\n", __func__); + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -911,70 +877,72 @@ static int sierra_startup(struct usb_serial *serial) if (nmea) sierra_vsc_set_nmea(serial->dev, 1); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for " - "sierra_port_private (%d) failed!\n", - __func__, i); - return -ENOMEM; - } - spin_lock_init(&portdata->lock); - init_usb_anchor(&portdata->active); - init_usb_anchor(&portdata->delayed); - ifnum = i; - /* Assume low memory requirements */ - portdata->num_out_urbs = N_OUT_URB; - portdata->num_in_urbs = N_IN_URB; - - /* Determine actual memory requirements */ - if (serial->num_ports == 1) { - /* Get interface number for composite device */ - ifnum = sierra_calc_interface(serial); - himemoryp = - (struct sierra_iface_info *)&typeB_interface_list; - if (is_himemory(ifnum, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - else { - himemoryp = - (struct sierra_iface_info *)&typeA_interface_list; - if (is_himemory(i, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - dev_dbg(&serial->dev->dev, - "Memory usage (urbs) interface #%d, in=%d, out=%d\n", - ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); - /* Set the port private data pointer */ - usb_set_serial_port_data(port, portdata); - } - return 0; } static void sierra_release(struct usb_serial *serial) { - int i; - struct usb_serial_port *port; + struct sierra_intf_private *intfdata; + + intfdata = usb_get_serial_data(serial); + kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; + const struct sierra_iface_info *himemoryp; + u8 ifnum; - dev_dbg(&serial->dev->dev, "%s\n", __func__); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - kfree(portdata); + spin_lock_init(&portdata->lock); + init_usb_anchor(&portdata->active); + init_usb_anchor(&portdata->delayed); + + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = &typeB_interface_list; + } else { + /* This is really the usb-serial port number of the interface + * rather than the interface number. + */ + ifnum = port->port_number; + himemoryp = &typeA_interface_list; } + + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + + dev_dbg(&port->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + + usb_set_serial_port_data(port, portdata); + + return 0; +} + +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; } #ifdef CONFIG_PM @@ -988,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); } @@ -995,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; - - if (message.event & PM_EVENT_AUTO) { - intfdata = serial->private; - spin_lock_irq(&intfdata->susp_lock); - b = intfdata->in_flight; + struct sierra_intf_private *intfdata = usb_get_serial_data(serial); - if (b) { + spin_lock_irq(&intfdata->susp_lock); + if (PMSG_IS_AUTO(message)) { + 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); @@ -1054,30 +1050,11 @@ static int sierra_resume(struct usb_serial *serial) return ec ? -EIO : 0; } -static int sierra_reset_resume(struct usb_interface *intf) -{ - struct usb_serial *serial = usb_get_intfdata(intf); - dev_err(&serial->dev->dev, "%s\n", __func__); - return usb_serial_resume(intf); -} #else #define sierra_suspend NULL #define sierra_resume NULL -#define sierra_reset_resume NULL #endif -static struct usb_driver sierra_driver = { - .name = "sierra", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .suspend = usb_serial_suspend, - .resume = usb_serial_resume, - .reset_resume = sierra_reset_resume, - .id_table = id_table, - .no_dynamic_id = 1, - .supports_autosuspend = 1, -}; - static struct usb_serial_driver sierra_device = { .driver = { .owner = THIS_MODULE, @@ -1085,7 +1062,6 @@ static struct usb_serial_driver sierra_device = { }, .description = "Sierra USB modem", .id_table = id_table, - .usb_driver = &sierra_driver, .calc_num_ports = sierra_calc_num_ports, .probe = sierra_probe, .open = sierra_open, @@ -1093,56 +1069,27 @@ 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, .release = sierra_release, + .port_probe = sierra_port_probe, + .port_remove = sierra_port_remove, .suspend = sierra_suspend, .resume = sierra_resume, .read_int_callback = sierra_instat_callback, }; -/* Functions used by new usb-serial code. */ -static int __init sierra_init(void) -{ - int retval; - retval = usb_serial_register(&sierra_device); - if (retval) - goto failed_device_register; - - - retval = usb_register(&sierra_driver); - if (retval) - goto failed_driver_register; - - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - - return 0; - -failed_driver_register: - usb_serial_deregister(&sierra_device); -failed_device_register: - return retval; -} - -static void __exit sierra_exit(void) -{ - usb_deregister(&sierra_driver); - usb_serial_deregister(&sierra_device); -} +static struct usb_serial_driver * const serial_drivers[] = { + &sierra_device, NULL +}; -module_init(sierra_init); -module_exit(sierra_exit); +module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); module_param(nmea, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(nmea, "NMEA streaming"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug messages"); |
