On Tue, 6 Apr 2010, Dominik Brodowski wrote: > Hey, > > On Tue, Apr 06, 2010 at 08:07:52AM +0200, Oliver Neukum wrote: > > > > The only problem: "hciconfig hci0 up" fails to get the device to an useable > > > > state again, even if I disable autosuspend again... > > > > > > That's a new problem. Does the device get autoresumed correctly? If > > > yes, then where does the failure occur? > > Using my patch, the device gets autosuspended and autoresumed correctly > (it's bit strange that the intf are interated over the same way during > suspend and resume, not in opposite directions). Here's a patch for the core which should make your change to the btusb driver unnecessary. However I'm not yet convinced this is the right thing to do. The patch also reverses the order in which interfaces are suspended, so that the suspend and resume iterations will run in opposite orders. Alan Stern Index: usb-2.6/drivers/usb/core/driver.c =================================================================== --- usb-2.6.orig/drivers/usb/core/driver.c +++ usb-2.6/drivers/usb/core/driver.c @@ -300,7 +300,7 @@ static int usb_probe_interface(struct de intf->condition = USB_INTERFACE_BINDING; - /* Bound interfaces are initially active. They are + /* Probed interfaces are initially active. They are * runtime-PM-enabled only if the driver has autosuspend support. * They are sensitive to their children's power states. */ @@ -436,11 +436,11 @@ int usb_driver_claim_interface(struct us iface->condition = USB_INTERFACE_BOUND; - /* Bound interfaces are initially active. They are + /* Claimed interfaces are initially inactive (suspended). They are * runtime-PM-enabled only if the driver has autosuspend support. * They are sensitive to their children's power states. */ - pm_runtime_set_active(dev); + pm_runtime_set_suspended(dev); pm_suspend_ignore_children(dev, false); if (driver->supports_autosuspend) pm_runtime_enable(dev); @@ -1169,7 +1169,7 @@ done: static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) { int status = 0; - int i = 0; + int i = 0, n = 0; struct usb_interface *intf; if (udev->state == USB_STATE_NOTATTACHED || @@ -1178,7 +1178,8 @@ static int usb_suspend_both(struct usb_d /* Suspend all the interfaces and then udev itself */ if (udev->actconfig) { - for (; i < udev->actconfig->desc.bNumInterfaces; i++) { + n = udev->actconfig->desc.bNumInterfaces; + for (i = n - 1; i >= 0; --i) { intf = udev->actconfig->interface[i]; status = usb_suspend_interface(udev, intf, msg); if (status != 0) @@ -1191,7 +1192,7 @@ static int usb_suspend_both(struct usb_d /* If the suspend failed, resume interfaces that did get suspended */ if (status != 0) { msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); - while (--i >= 0) { + while (++i < n) { intf = udev->actconfig->interface[i]; usb_resume_interface(udev, intf, msg, 0); } -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html