USB: address FIXME in usbnet w.r.t drivers claiming multiple interfaces
authorOliver Neukum <oneukum@suse.de>
Mon, 30 Apr 2007 08:37:44 +0000 (01:37 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 23 May 2007 06:45:48 +0000 (23:45 -0700)
This fixes the issue of drivers claiming multiple interfaces. Operations
are stopped as soon as an interface is suspend and resumed only as
all interfaces have been resumed.

Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/net/usb/usbnet.c
drivers/net/usb/usbnet.h

index f9cd42d058b042c7d68949fa1cfe985444189f1f..5b16d9a1269a2851e3f8982b23f835c256044ba7 100644 (file)
@@ -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);
index 82db5a8e528e57b95ad40c369afb31b7298c2aa6..a3f8b9e7bc00551d12690555d412ed28a9c9d55c 100644 (file)
@@ -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;