summaryrefslogtreecommitdiff
path: root/drivers/usb/serial/sierra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r--drivers/usb/serial/sierra.c366
1 files changed, 180 insertions, 186 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index de958c5b52e3..741e68e46139 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
USB Driver for Sierra Wireless
@@ -9,10 +10,6 @@
IMPORTANT DISCLAIMER: This driver is not commercially supported by
Sierra Wireless. Use at your own risk.
- This driver is free software; you can redistribute it and/or modify
- it under the terms of Version 2 of the GNU General Public License as
- published by the Free Software Foundation.
-
Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/
@@ -48,16 +45,16 @@
static bool nmea;
-/* Used in interface blacklisting */
-struct sierra_iface_info {
- const u32 infolen; /* number of interface numbers on blacklist */
- const u8 *ifaceinfo; /* pointer to the array holding the numbers */
+struct sierra_iface_list {
+ const u8 *nums; /* array of interface numbers */
+ size_t count; /* number of elements in array */
};
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)
@@ -84,7 +81,8 @@ static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable)
USB_CTRL_SET_TIMEOUT); /* int timeout */
}
-static int sierra_calc_num_ports(struct usb_serial *serial)
+static int sierra_calc_num_ports(struct usb_serial *serial,
+ struct usb_serial_endpoints *epds)
{
int num_ports = 0;
u8 ifnum, numendpoints;
@@ -102,69 +100,36 @@ static int sierra_calc_num_ports(struct usb_serial *serial)
return num_ports;
}
-static int is_blacklisted(const u8 ifnum,
- const struct sierra_iface_info *blacklist)
+static bool is_listed(const u8 ifnum, const struct sierra_iface_list *list)
{
- const u8 *info;
int i;
- if (blacklist) {
- info = blacklist->ifaceinfo;
+ if (!list)
+ return false;
- for (i = 0; i < blacklist->infolen; i++) {
- if (info[i] == ifnum)
- return 1;
- }
+ for (i = 0; i < list->count; i++) {
+ if (list->nums[i] == ifnum)
+ return true;
}
- return 0;
-}
-
-static int is_himemory(const u8 ifnum,
- const struct sierra_iface_info *himemorylist)
-{
- const u8 *info;
- int i;
- if (himemorylist) {
- info = himemorylist->ifaceinfo;
-
- for (i=0; i < himemorylist->infolen; i++) {
- if (info[i] == ifnum)
- return 1;
- }
- }
- return 0;
+ return false;
}
-static int sierra_calc_interface(struct usb_serial *serial)
+static u8 sierra_interface_num(struct usb_serial *serial)
{
- int interface;
- struct usb_interface *p_interface;
- struct usb_host_interface *p_host_interface;
-
- /* Get the interface structure pointer from the serial struct */
- p_interface = serial->interface;
-
- /* Get a pointer to the host interface structure */
- p_host_interface = p_interface->cur_altsetting;
-
- /* read the interface descriptor for this active altsetting
- * to find out the interface number we are on
- */
- interface = p_host_interface->desc.bInterfaceNumber;
-
- return interface;
+ return serial->interface->cur_altsetting->desc.bInterfaceNumber;
}
static int sierra_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
+ const struct sierra_iface_list *ignore_list;
int result = 0;
struct usb_device *udev;
u8 ifnum;
udev = serial->dev;
- ifnum = sierra_calc_interface(serial);
+ ifnum = sierra_interface_num(serial);
/*
* If this interface supports more than 1 alternate
@@ -177,13 +142,10 @@ static int sierra_probe(struct usb_serial *serial,
usb_set_interface(udev, ifnum, 1);
}
- /* ifnum could have changed - by calling usb_set_interface */
- ifnum = sierra_calc_interface(serial);
+ ignore_list = (const struct sierra_iface_list *)id->driver_info;
- if (is_blacklisted(ifnum,
- (struct sierra_iface_info *)id->driver_info)) {
- dev_dbg(&serial->dev->dev,
- "Ignoring blacklisted interface #%d\n", ifnum);
+ if (is_listed(ifnum, ignore_list)) {
+ dev_dbg(&serial->dev->dev, "Ignoring interface #%d\n", ifnum);
return -ENODEV;
}
@@ -192,22 +154,22 @@ static int sierra_probe(struct usb_serial *serial,
/* interfaces with higher memory requirements */
static const u8 hi_memory_typeA_ifaces[] = { 0, 2 };
-static const struct sierra_iface_info typeA_interface_list = {
- .infolen = ARRAY_SIZE(hi_memory_typeA_ifaces),
- .ifaceinfo = hi_memory_typeA_ifaces,
+static const struct sierra_iface_list typeA_interface_list = {
+ .nums = hi_memory_typeA_ifaces,
+ .count = ARRAY_SIZE(hi_memory_typeA_ifaces),
};
static const u8 hi_memory_typeB_ifaces[] = { 3, 4, 5, 6 };
-static const struct sierra_iface_info typeB_interface_list = {
- .infolen = ARRAY_SIZE(hi_memory_typeB_ifaces),
- .ifaceinfo = hi_memory_typeB_ifaces,
+static const struct sierra_iface_list typeB_interface_list = {
+ .nums = hi_memory_typeB_ifaces,
+ .count = ARRAY_SIZE(hi_memory_typeB_ifaces),
};
-/* 'blacklist' of interfaces not served by this driver */
+/* 'ignorelist' of interfaces not served by this driver */
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,
+static const struct sierra_iface_list direct_ip_interface_ignore = {
+ .nums = direct_ip_non_serial_ifaces,
+ .count = ARRAY_SIZE(direct_ip_non_serial_ifaces),
};
static const struct usb_device_id id_table[] = {
@@ -281,17 +243,22 @@ static const struct usb_device_id id_table[] = {
/* Sierra Wireless HSPA Non-Composite Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
{ USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
- { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
- .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ /* Sierra Wireless Direct IP modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_ignore
+ },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_ignore
},
+ { USB_DEVICE(0x1199, 0x68AB) }, /* Sierra Wireless AR8550 */
/* 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
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_ignore
},
- { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */
- .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ /* Airprime/Sierra Wireless Direct IP modems */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF),
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_ignore
},
- { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
{ }
};
@@ -316,7 +283,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)
@@ -337,7 +303,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
/* If composite device then properly report interface */
if (serial->num_ports == 1) {
- interface = sierra_calc_interface(serial);
+ interface = sierra_interface_num(serial);
/* Control message is sent only to interfaces with
* interrupt_in endpoints
*/
@@ -365,20 +331,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 +378,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);
}
@@ -433,8 +390,9 @@ static void sierra_outdat_callback(struct urb *urb)
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
struct sierra_intf_private *intfdata;
int status = urb->status;
+ unsigned long flags;
- 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);
@@ -443,12 +401,12 @@ static void sierra_outdat_callback(struct urb *urb)
dev_dbg(&port->dev, "%s - nonzero write bulk status "
"received: %d\n", __func__, status);
- spin_lock(&portdata->lock);
+ spin_lock_irqsave(&portdata->lock, flags);
--portdata->outstanding_urbs;
- spin_unlock(&portdata->lock);
- spin_lock(&intfdata->susp_lock);
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ spin_lock_irqsave(&intfdata->susp_lock, flags);
--intfdata->in_flight;
- spin_unlock(&intfdata->susp_lock);
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
usb_serial_port_softint(port);
}
@@ -463,7 +421,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
unsigned long flags;
unsigned char *buffer;
struct urb *urb;
- size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER);
+ size_t writesize = min_t(size_t, count, MAX_TRANSFER);
int retval = 0;
/* verify that we actually have some data to write */
@@ -471,7 +429,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);
@@ -495,22 +453,18 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
goto error_simple;
}
- buffer = kmalloc(writesize, GFP_ATOMIC);
+ buffer = kmemdup(buf, 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(&port->dev, __func__, writesize, buffer);
usb_fill_bulk_urb(urb, serial->dev,
@@ -614,8 +568,7 @@ static void sierra_instat_callback(struct urb *urb)
urb, port, portdata);
if (status == 0) {
- struct usb_ctrlrequest *req_pkt =
- (struct usb_ctrlrequest *)urb->transfer_buffer;
+ struct usb_ctrlrequest *req_pkt = urb->transfer_buffer;
if (!req_pkt) {
dev_dbg(&port->dev, "%s: NULL req_pkt\n",
@@ -658,7 +611,7 @@ static void sierra_instat_callback(struct urb *urb)
}
}
-static int sierra_write_room(struct tty_struct *tty)
+static unsigned int sierra_write_room(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
@@ -677,6 +630,23 @@ static int sierra_write_room(struct tty_struct *tty)
return 2048;
}
+static unsigned 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;
+ unsigned 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 - %u\n", __func__, chars);
+
+ return chars;
+}
+
static void sierra_stop_rx_urbs(struct usb_serial_port *port)
{
int i;
@@ -732,15 +702,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) {
@@ -752,9 +716,6 @@ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
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;
}
@@ -767,40 +728,49 @@ 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 the tty-port initialized
+ * flag.
+ */
+ 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_irq(&portdata->lock);
+ portdata->outstanding_urbs--;
+ spin_unlock_irq(&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;
@@ -808,11 +778,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,
@@ -825,23 +790,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;
}
@@ -890,7 +858,7 @@ 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;
+ const struct sierra_iface_list *himemory_list;
u8 ifnum;
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
@@ -908,17 +876,17 @@ static int sierra_port_probe(struct usb_serial_port *port)
/* Determine actual memory requirements */
if (serial->num_ports == 1) {
/* Get interface number for composite device */
- ifnum = sierra_calc_interface(serial);
- himemoryp = &typeB_interface_list;
+ ifnum = sierra_interface_num(serial);
+ himemory_list = &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;
+ himemory_list = &typeA_interface_list;
}
- if (is_himemory(ifnum, himemoryp)) {
+ if (is_listed(ifnum, himemory_list)) {
portdata->num_out_urbs = N_OUT_URB_HM;
portdata->num_in_urbs = N_IN_URB_HM;
}
@@ -932,14 +900,13 @@ static int sierra_port_probe(struct usb_serial_port *port)
return 0;
}
-static int sierra_port_remove(struct usb_serial_port *port)
+static void 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
@@ -953,6 +920,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);
}
@@ -960,58 +929,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 (!tty_port_initialized(&port->port))
+ 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);
@@ -1026,7 +1021,6 @@ static int sierra_resume(struct usb_serial *serial)
static struct usb_serial_driver sierra_device = {
.driver = {
- .owner = THIS_MODULE,
.name = "sierra",
},
.description = "Sierra USB modem",
@@ -1038,7 +1032,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,
@@ -1058,7 +1052,7 @@ module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
-module_param(nmea, bool, S_IRUGO | S_IWUSR);
+module_param(nmea, bool, 0644);
MODULE_PARM_DESC(nmea, "NMEA streaming");