Commit 7b0c5f21f348a66de495868b8df0284e8dfd6bbf

Authored by Dan Williams
Committed by David S. Miller
1 parent 6eecdc5f95

sierra_net: keep status interrupt URB active

The driver and firmware sync up through SYNC messages, and the
firmware's affirmative reply to these SYNC messages appears to be the
"Reset" indication received via the status interrupt endpoint.  Thus the
driver needs the status interrupt endpoint always active so that the
Reset indication can be received even if the netdev is closed, which is
the case right after device insertion.

If the Reset indication is not received by the driver, it continues
sending SYNC messages to the firmware, which crashes about 10 seconds
later and the device stops responding.

Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 31 additions and 7 deletions Side-by-side Diff

drivers/net/usb/sierra_net.c
... ... @@ -426,6 +426,13 @@
426 426  
427 427 dev_dbg(&dev->udev->dev, "%s", __func__);
428 428  
  429 + /* The SIERRA_NET_HIP_MSYNC_ID command appears to request that the
  430 + * firmware restart itself. After restarting, the modem will respond
  431 + * with the SIERRA_NET_HIP_RESTART_ID indication. The driver continues
  432 + * sending MSYNC commands every few seconds until it receives the
  433 + * RESTART event from the firmware
  434 + */
  435 +
429 436 /* tell modem we are ready */
430 437 status = sierra_net_send_sync(dev);
431 438 if (status < 0)
... ... @@ -704,6 +711,9 @@
704 711 /* set context index initially to 0 - prepares tx hdr template */
705 712 sierra_net_set_ctx_index(priv, 0);
706 713  
  714 + /* prepare sync message template */
  715 + memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
  716 +
707 717 /* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */
708 718 dev->rx_urb_size = SIERRA_NET_RX_URB_SIZE;
709 719 if (dev->udev->speed != USB_SPEED_HIGH)
710 720  
... ... @@ -739,12 +749,7 @@
739 749 kfree(priv);
740 750 return -ENODEV;
741 751 }
742   - /* prepare sync message from template */
743   - memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
744 752  
745   - /* initiate the sync sequence */
746   - sierra_net_dosync(dev);
747   -
748 753 return 0;
749 754 }
750 755  
751 756  
... ... @@ -766,8 +771,9 @@
766 771 netdev_err(dev->net,
767 772 "usb_control_msg failed, status %d\n", status);
768 773  
769   - sierra_net_set_private(dev, NULL);
  774 + usbnet_status_stop(dev);
770 775  
  776 + sierra_net_set_private(dev, NULL);
771 777 kfree(priv);
772 778 }
773 779  
... ... @@ -908,6 +914,24 @@
908 914 .tx_fixup = sierra_net_tx_fixup,
909 915 };
910 916  
  917 +static int
  918 +sierra_net_probe(struct usb_interface *udev, const struct usb_device_id *prod)
  919 +{
  920 + int ret;
  921 +
  922 + ret = usbnet_probe(udev, prod);
  923 + if (ret == 0) {
  924 + struct usbnet *dev = usb_get_intfdata(udev);
  925 +
  926 + ret = usbnet_status_start(dev, GFP_KERNEL);
  927 + if (ret == 0) {
  928 + /* Interrupt URB now set up; initiate sync sequence */
  929 + sierra_net_dosync(dev);
  930 + }
  931 + }
  932 + return ret;
  933 +}
  934 +
911 935 #define DIRECT_IP_DEVICE(vend, prod) \
912 936 {USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \
913 937 .driver_info = (unsigned long)&sierra_net_info_direct_ip}, \
... ... @@ -930,7 +954,7 @@
930 954 static struct usb_driver sierra_net_driver = {
931 955 .name = "sierra_net",
932 956 .id_table = products,
933   - .probe = usbnet_probe,
  957 + .probe = sierra_net_probe,
934 958 .disconnect = usbnet_disconnect,
935 959 .suspend = usbnet_suspend,
936 960 .resume = usbnet_resume,