Okay guys, it turns out that doing what you want isn't so hard if you 
don't mind being a little bit unorthodox.

How do you like this patch?  It goes on top of the one Greg already has in 
his tree.

Those FIXMEs are okay, at least for now.  The device lock is currently 
needed only by the hub driver, which does have suspend/resume support.

If you want, this can be made to work without dropping and reacquiring 
dev->sem.  It would mean exporting a currently-private subroutine from the 
driver core.

Alan Stern



Index: usb-2.6/drivers/usb/core/usb.c
===================================================================
--- usb-2.6.orig/drivers/usb/core/usb.c
+++ usb-2.6/drivers/usb/core/usb.c
@@ -1030,9 +1030,16 @@ static int usb_generic_suspend(struct de
                else
                        mark_quiesced(intf);
        } else {
-               // FIXME else if there's no suspend method, disconnect...
-               dev_warn(dev, "no %s?\n", "suspend");
-               mark_quiesced(intf);
+               dev_warn(dev, "no suspend?  unbinding...\n");
+               up(&dev->sem);
+
+               /*
+                * FIXME: You're not supposed to do this without holding
+                * the USB device lock.  But we can't just grab the lock
+                * because our caller might already be holding it.
+                */
+               usb_driver_release_interface(driver, intf);
+               down(&dev->sem);
                status = 0;
        }
        return status;
@@ -1059,9 +1066,22 @@ static int usb_generic_resume(struct dev
                return usb_resume_device (to_usb_device(dev));
        }
 
-       if ((dev->driver == NULL) ||
-           (dev->driver_data == &usb_generic_driver_data))
+       /* try to bind interfaces that have no driver */
+       if (dev->driver == NULL) {
+               up(&dev->sem);
+
+               /*
+                * FIXME: You're not supposed to do this without holding
+                * the USB device lock.  But we can't just grab the lock
+                * because our caller might already be holding it.
+                */
+               device_attach(dev);
+               down(&dev->sem);
                return 0;
+       }
+
+       if (dev->driver_data == &usb_generic_driver_data)
+               return 0;               /* Shouldn't happen */
 
        intf = to_usb_interface(dev);
        driver = to_usb_driver(dev->driver);
@@ -1081,7 +1101,7 @@ static int usb_generic_resume(struct dev
                        mark_quiesced(intf);
                }
        } else
-               dev_warn(dev, "no %s?\n", "resume");
+               dev_warn(dev, "no resume?\n");
        return 0;
 }
 
Index: usb-2.6/drivers/usb/core/hub.c
===================================================================
--- usb-2.6.orig/drivers/usb/core/hub.c
+++ usb-2.6/drivers/usb/core/hub.c
@@ -1893,12 +1893,6 @@ int usb_resume_device(struct usb_device 
                dev_dbg(&udev->dev, "can't resume, status %d\n",
                        status);
 
-       /* rebind drivers that had no suspend() */
-       if (status == 0) {
-               usb_unlock_device(udev);
-               bus_rescan_devices(&usb_bus_type);
-               usb_lock_device(udev);
-       }
        return status;
 }
 



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to