diff options
Diffstat (limited to 'drivers/net/usb/sierra_net.c')
| -rw-r--r-- | drivers/net/usb/sierra_net.c | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index c27d27701ae..a251588762e 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -21,8 +21,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #define DRIVER_VERSION "v.2.0" @@ -311,10 +310,9 @@ static int sierra_net_send_cmd(struct usbnet *dev, struct sierra_net_data *priv = sierra_net_get_private(dev); int status; - status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - USB_CDC_SEND_ENCAPSULATED_COMMAND, - USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, 0, - priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT); + status = usbnet_write_cmd(dev, USB_CDC_SEND_ENCAPSULATED_COMMAND, + USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, + 0, priv->ifnum, cmd, cmdlen); if (status != cmdlen && status != -ENODEV) netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status); @@ -340,7 +338,7 @@ static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix) dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix); priv->tx_hdr_template[0] = 0x3F; priv->tx_hdr_template[1] = ctx_ix; - *((u16 *)&priv->tx_hdr_template[2]) = + *((__be16 *)&priv->tx_hdr_template[2]) = cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID); } @@ -414,11 +412,10 @@ static void sierra_net_handle_lsi(struct usbnet *dev, char *data, if (link_up) { sierra_net_set_ctx_index(priv, hh->msgspecific.byte); priv->link_up = 1; - netif_carrier_on(dev->net); } else { priv->link_up = 0; - netif_carrier_off(dev->net); } + usbnet_link_change(dev, link_up, 0); } static void sierra_net_dosync(struct usbnet *dev) @@ -428,6 +425,13 @@ static void sierra_net_dosync(struct usbnet *dev) dev_dbg(&dev->udev->dev, "%s", __func__); + /* The SIERRA_NET_HIP_MSYNC_ID command appears to request that the + * firmware restart itself. After restarting, the modem will respond + * with the SIERRA_NET_HIP_RESTART_ID indication. The driver continues + * sending MSYNC commands every few seconds until it receives the + * RESTART event from the firmware + */ + /* tell modem we are ready */ status = sierra_net_send_sync(dev); if (status < 0) @@ -460,11 +464,9 @@ static void sierra_net_kevent(struct work_struct *work) /* Query the modem for the LSI message */ buf = kzalloc(SIERRA_NET_USBCTL_BUF_LEN, GFP_KERNEL); - if (!buf) { - netdev_err(dev->net, - "failed to allocate buf for LS msg\n"); + if (!buf) return; - } + ifnum = priv->ifnum; len = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), USB_CDC_GET_ENCAPSULATED_RESPONSE, @@ -599,8 +601,8 @@ static void sierra_net_get_drvinfo(struct net_device *net, { /* Inherit standard device info */ usbnet_get_drvinfo(net, info); - strncpy(info->driver, driver_name, sizeof info->driver); - strncpy(info->version, DRIVER_VERSION, sizeof info->version); + strlcpy(info->driver, driver_name, sizeof(info->driver)); + strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); } static u32 sierra_net_get_link(struct net_device *net) @@ -632,32 +634,22 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu) static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) { int result = 0; - u16 *attrdata; - - attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL); - if (!attrdata) - return -ENOMEM; - - result = usb_control_msg( - dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - /* _u8 vendor specific request */ - SWI_USB_REQUEST_GET_FW_ATTR, - USB_DIR_IN | USB_TYPE_VENDOR, /* __u8 request type */ - 0x0000, /* __u16 value not used */ - 0x0000, /* __u16 index not used */ - attrdata, /* char *data */ - sizeof(*attrdata), /* __u16 size */ - USB_CTRL_SET_TIMEOUT); /* int timeout */ - - if (result < 0) { - kfree(attrdata); + __le16 attrdata; + + result = usbnet_read_cmd(dev, + /* _u8 vendor specific request */ + SWI_USB_REQUEST_GET_FW_ATTR, + USB_DIR_IN | USB_TYPE_VENDOR, /* __u8 request type */ + 0x0000, /* __u16 value not used */ + 0x0000, /* __u16 index not used */ + &attrdata, /* char *data */ + sizeof(attrdata) /* __u16 size */ + ); + + if (result < 0) return -EIO; - } - *datap = le16_to_cpu(*attrdata); - - kfree(attrdata); + *datap = le16_to_cpu(attrdata); return result; } @@ -697,10 +689,8 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) } /* Initialize sierra private data */ priv = kzalloc(sizeof *priv, GFP_KERNEL); - if (!priv) { - dev_err(&dev->udev->dev, "No memory"); + if (!priv) return -ENOMEM; - } priv->usbnet = dev; priv->ifnum = ifacenum; @@ -720,6 +710,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) /* set context index initially to 0 - prepares tx hdr template */ sierra_net_set_ctx_index(priv, 0); + /* prepare sync message template */ + memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); + /* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */ dev->rx_urb_size = SIERRA_NET_RX_URB_SIZE; if (dev->udev->speed != USB_SPEED_HIGH) @@ -755,11 +748,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) kfree(priv); return -ENODEV; } - /* prepare sync message from template */ - memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); - - /* initiate the sync sequence */ - sierra_net_dosync(dev); return 0; } @@ -782,8 +770,9 @@ static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf) netdev_err(dev->net, "usb_control_msg failed, status %d\n", status); - sierra_net_set_private(dev, NULL); + usbnet_status_stop(dev); + sierra_net_set_private(dev, NULL); kfree(priv); } @@ -924,6 +913,24 @@ static const struct driver_info sierra_net_info_direct_ip = { .tx_fixup = sierra_net_tx_fixup, }; +static int +sierra_net_probe(struct usb_interface *udev, const struct usb_device_id *prod) +{ + int ret; + + ret = usbnet_probe(udev, prod); + if (ret == 0) { + struct usbnet *dev = usb_get_intfdata(udev); + + ret = usbnet_status_start(dev, GFP_KERNEL); + if (ret == 0) { + /* Interrupt URB now set up; initiate sync sequence */ + sierra_net_dosync(dev); + } + } + return ret; +} + #define DIRECT_IP_DEVICE(vend, prod) \ {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \ .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ @@ -946,7 +953,7 @@ MODULE_DEVICE_TABLE(usb, products); static struct usb_driver sierra_net_driver = { .name = "sierra_net", .id_table = products, - .probe = usbnet_probe, + .probe = sierra_net_probe, .disconnect = usbnet_disconnect, .suspend = usbnet_suspend, .resume = usbnet_resume, |
