Skip to content

Commit 7b0c5f2

Browse files
dcbwdavem330
authored andcommitted
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>
1 parent 6eecdc5 commit 7b0c5f2

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

drivers/net/usb/sierra_net.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,13 @@ static void sierra_net_dosync(struct usbnet *dev)
426426

427427
dev_dbg(&dev->udev->dev, "%s", __func__);
428428

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+
429436
/* tell modem we are ready */
430437
status = sierra_net_send_sync(dev);
431438
if (status < 0)
@@ -704,6 +711,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
704711
/* set context index initially to 0 - prepares tx hdr template */
705712
sierra_net_set_ctx_index(priv, 0);
706713

714+
/* prepare sync message template */
715+
memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
716+
707717
/* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */
708718
dev->rx_urb_size = SIERRA_NET_RX_URB_SIZE;
709719
if (dev->udev->speed != USB_SPEED_HIGH)
@@ -739,11 +749,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
739749
kfree(priv);
740750
return -ENODEV;
741751
}
742-
/* prepare sync message from template */
743-
memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
744-
745-
/* initiate the sync sequence */
746-
sierra_net_dosync(dev);
747752

748753
return 0;
749754
}
@@ -766,8 +771,9 @@ static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf)
766771
netdev_err(dev->net,
767772
"usb_control_msg failed, status %d\n", status);
768773

769-
sierra_net_set_private(dev, NULL);
774+
usbnet_status_stop(dev);
770775

776+
sierra_net_set_private(dev, NULL);
771777
kfree(priv);
772778
}
773779

@@ -908,6 +914,24 @@ static const struct driver_info sierra_net_info_direct_ip = {
908914
.tx_fixup = sierra_net_tx_fixup,
909915
};
910916

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+
911935
#define DIRECT_IP_DEVICE(vend, prod) \
912936
{USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \
913937
.driver_info = (unsigned long)&sierra_net_info_direct_ip}, \
@@ -930,7 +954,7 @@ MODULE_DEVICE_TABLE(usb, products);
930954
static struct usb_driver sierra_net_driver = {
931955
.name = "sierra_net",
932956
.id_table = products,
933-
.probe = usbnet_probe,
957+
.probe = sierra_net_probe,
934958
.disconnect = usbnet_disconnect,
935959
.suspend = usbnet_suspend,
936960
.resume = usbnet_resume,

0 commit comments

Comments
 (0)