diff options
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/cdc_ether.c | 16 | ||||
-rw-r--r-- | drivers/net/usb/rndis_host.c | 1 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.c | 25 | ||||
-rw-r--r-- | drivers/net/usb/usbnet.h | 1 |
4 files changed, 33 insertions, 10 deletions
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 5a21f06bf8a..675ac99a79c 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -91,6 +91,22 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) "CDC descriptors on config\n"); } + /* Maybe CDC descriptors are after the endpoint? This bug has + * been seen on some 2Wire Inc RNDIS-ish products. + */ + if (len == 0) { + struct usb_host_endpoint *hep; + + hep = intf->cur_altsetting->endpoint; + if (hep) { + buf = hep->extra; + len = hep->extralen; + } + if (len) + dev_dbg(&intf->dev, + "CDC descriptors on endpoint\n"); + } + /* this assumes that if there's a non-RNDIS vendor variant * of cdc-acm, it'll fail RNDIS requests cleanly. */ diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 980e4aaa97a..cd991a0f75b 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -515,6 +515,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) dev_err(&intf->dev, "dev can't take %u byte packets (max %u)\n", dev->hard_mtu, tmp); + retval = -EINVAL; goto fail_and_release; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f9cd42d058b..5b16d9a1269 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1252,20 +1252,23 @@ EXPORT_SYMBOL_GPL(usbnet_probe); /*-------------------------------------------------------------------------*/ -/* FIXME these suspend/resume methods assume non-CDC style - * devices, with only one interface. +/* + * suspend the whole driver as soon as the first interface is suspended + * resume only when the last interface is resumed */ int usbnet_suspend (struct usb_interface *intf, pm_message_t message) { struct usbnet *dev = usb_get_intfdata(intf); - /* accelerate emptying of the rx and queues, to avoid - * having everything error out. - */ - netif_device_detach (dev->net); - (void) unlink_urbs (dev, &dev->rxq); - (void) unlink_urbs (dev, &dev->txq); + if (!dev->suspend_count++) { + /* accelerate emptying of the rx and queues, to avoid + * having everything error out. + */ + netif_device_detach (dev->net); + (void) unlink_urbs (dev, &dev->rxq); + (void) unlink_urbs (dev, &dev->txq); + } return 0; } EXPORT_SYMBOL_GPL(usbnet_suspend); @@ -1274,8 +1277,10 @@ int usbnet_resume (struct usb_interface *intf) { struct usbnet *dev = usb_get_intfdata(intf); - netif_device_attach (dev->net); - tasklet_schedule (&dev->bh); + if (!--dev->suspend_count) { + netif_device_attach (dev->net); + tasklet_schedule (&dev->bh); + } return 0; } EXPORT_SYMBOL_GPL(usbnet_resume); diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h index 82db5a8e528..a3f8b9e7bc0 100644 --- a/drivers/net/usb/usbnet.h +++ b/drivers/net/usb/usbnet.h @@ -32,6 +32,7 @@ struct usbnet { const char *driver_name; wait_queue_head_t *wait; struct mutex phy_mutex; + unsigned char suspend_count; /* i/o info: pipes etc */ unsigned in, out; |