On Fri, 12 Oct 2012, Peter Chen wrote: > Taking EHCI controller as an example, it just needs to change ehci_bus_resume, > if there is any enabled, unsuspended port, set hcd->unsuspended_device_on_port We don't need to do that. See below. > > usb_bus_resume() can poll the port statuses to see if there are any > > enabled, unsuspended ports. If there aren't any, the delay can be > > skipped. > Taking EHCI controller as an example, you mean: > > - Change hcd_bus_resume like below: > > status = hcd->driver->bus_resume(hcd); > clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); > if (status == 0) { > char buffer[6]; > > status = hcd->driver->hub_status_data(hcd, buffer); > if (status != 0) { > /* There are any enabled unsuspended ports */ > /* TRSMRCY = 10 msec */ > msleep(10); > spin_lock_irq(&hcd_root_hub_lock); > - Add get any enabled, unsuspended port as port change condition at > ehci_hub_status_data. No, like this: --- usb-3.6.orig/drivers/usb/core/hcd.c +++ usb-3.6/drivers/usb/core/hcd.c @@ -2023,6 +2023,7 @@ int hcd_bus_resume(struct usb_device *rh struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); int status; int old_state = hcd->state; + int port1; dev_dbg(&rhdev->dev, "usb %sresume\n", (PMSG_IS_AUTO(msg) ? "auto-" : "")); @@ -2039,8 +2040,6 @@ int hcd_bus_resume(struct usb_device *rh status = hcd->driver->bus_resume(hcd); clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); if (status == 0) { - /* TRSMRCY = 10 msec */ - msleep(10); spin_lock_irq(&hcd_root_hub_lock); if (!HCD_DEAD(hcd)) { usb_set_device_state(rhdev, rhdev->actconfig @@ -2050,6 +2049,22 @@ int hcd_bus_resume(struct usb_device *rh hcd->state = HC_STATE_RUNNING; } spin_unlock_irq(&hcd_root_hub_lock); + + /* Any enabled non-suspended port requires TRSMRCY delay */ + for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { + __le16 buf[2]; + unsigned pstatus; + + buf[0] = 0; + hcd->driver->hub_control(hcd, USB_DIR_IN | USB_RT_PORT, + 0, port1, (char *) buf, 4); + pstatus = le16_to_cpu(buf[0]); + if ((pstatus & USB_PORT_STAT_ENABLE) && + !(pstatus & USB_PORT_STAT_SUSPEND)) { + msleep(10); /* TRSMRCY */ + break; + } + } } else { hcd->state = old_state; dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", I haven't tested this, just compiled it. Alan Stern -- 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