On Sun, 6 Dec 2009, Arjan van de Ven wrote: > btw I instrumented both the suspend and resume, and made graphs out of > it for my laptop (modern laptop with Intel cpu/wifi/graphics of course). > > http://www.fenrus.org/graphs/suspend.svg > http://www.fenrus.org/graphs/resume.svg > > (also attached for convenience) > > the resume clearly shows that all this talking about PCI stuff is > completely without practical merit.. it's the USB stuff where the time > is spent. Arjan, can you try testing the USB timings again with the patch below (for vanilla 2.6.32)? Fair warning: I just composed this and haven't tried it out myself. Thanks, Alan Stern Index: 2.6.32/drivers/usb/core/driver.c =================================================================== --- 2.6.32.orig/drivers/usb/core/driver.c +++ 2.6.32/drivers/usb/core/driver.c @@ -1313,8 +1313,9 @@ static int usb_resume_both(struct usb_de * then we're stuck. */ status = usb_resume_device(udev, msg); } - } else if (udev->reset_resume) + } else { status = usb_resume_device(udev, msg); + } if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { Index: 2.6.32/drivers/usb/core/hub.c =================================================================== --- 2.6.32.orig/drivers/usb/core/hub.c +++ 2.6.32/drivers/usb/core/hub.c @@ -1674,7 +1674,7 @@ static int usb_configure_device_otg(stru * (Includes HNP test device.) */ if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { - err = usb_port_suspend(udev, PMSG_SUSPEND); + err = usb_port_suspend(udev, PMSG_AUTO_SUSPEND); if (err < 0) dev_dbg(&udev->dev, "HNP fail, %d\n", err); } @@ -2060,6 +2060,7 @@ static int check_port_resume_type(struct /* * usb_port_suspend - suspend a usb device's upstream port * @udev: device that's no longer in active use, not a root hub + * @msg: Power Management message describing this state transition * Context: must be able to sleep; device not locked; pm locks held * * Suspends a USB device that isn't in active use, conserving power. @@ -2107,7 +2108,7 @@ int usb_port_suspend(struct usb_device * { struct usb_hub *hub = hdev_to_hub(udev->parent); int port1 = udev->portnum; - int status; + int status = 0; // dev_dbg(hub->intfdev, "suspend port %d\n", port1); @@ -2128,6 +2129,13 @@ int usb_port_suspend(struct usb_device * status); } + /* For system sleep transitions we don't actually need to suspend + * the port. The device will suspend itself when the entire bus + * is suspended. + */ + if (!(msg.event & (PM_EVENT_USER | PM_EVENT_REMOTE | PM_EVENT_AUTO))) + return status; + /* see 7.1.7.6 */ status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND); if (status) { @@ -2231,6 +2239,7 @@ static int finish_port_resume(struct usb /* * usb_port_resume - re-activate a suspended usb device's upstream port * @udev: device to re-activate, not a root hub + * @msg: Power Management message describing this state transition * Context: must be able to sleep; device not locked; pm locks held * * This will re-activate the suspended device, increasing power usage -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html