On Tue, Apr 03, 2012 at 03:24:18PM -0400, Alan Stern wrote: > This patch (as1533) fixes a race between root-hub suspend and remote > wakeup. If a wakeup event occurs while a root hub is suspending, it > might not cause the suspend to fail. Although the host controller > drivers check for pending wakeup events at the start of their > bus_suspend routines, they generally do not check for wakeup events > while the routines are running. > > In addition, if a wakeup event occurs any time after khubd is frozen > and before the root hub is fully suspended, it might not cause a > system sleep transition to fail. For example, the host controller > drivers do not fail root-hub suspends when a connect-change event is > pending. > > To fix both these issues, this patch causes hcd_bus_suspend() to query > the controller driver's hub_status_data method after a root hub is > suspended, if the root hub is enabled for wakeup. Any pending status > changes will count as wakeup events, causing the root hub to be > resumed and the overall suspend to fail with -EBUSY. > > A significant point is that not all events are reflected immediately > in the status bits. Both EHCI and UHCI controllers notify the CPU > when remote wakeup begins on a port, but the port's suspend-change > status bit doesn't get set until after the port has completed the > transition out of the suspend state, some 25 milliseconds later. > Consequently, the patch will interpret any nonzero return value from > hub_status_data as indicating a pending event, even if none of the > status bits are set in the data buffer. Follow-up patches make the > necessary changes to ehci-hcd and uhci-hcd. > > Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> > CC: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> > CC: Chen Peter-B29397 <B29397@xxxxxxxxxxxxx> > CC: <stable@xxxxxxxxxxxxxxx> > > --- > > drivers/usb/core/hcd.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > Index: usb-3.3/drivers/usb/core/hcd.c > =================================================================== > --- usb-3.3.orig/drivers/usb/core/hcd.c > +++ usb-3.3/drivers/usb/core/hcd.c > @@ -1978,6 +1978,18 @@ int hcd_bus_suspend(struct usb_device *r > if (status == 0) { > usb_set_device_state(rhdev, USB_STATE_SUSPENDED); > hcd->state = HC_STATE_SUSPENDED; > + > + /* Did we race with a root-hub wakeup event? */ > + if (rhdev->do_remote_wakeup) { > + char buffer[6]; > + > + status = hcd->driver->hub_status_data(hcd, buffer); I have run this patch at FSL board, and found the kernel is hang at reading portsc of above code, the reason is controller is off after bus suspend. I have checked the ehci-tegra.c, it also powers off its controller at bus suspend, maybe there are other controllers also do that. > + if (status != 0) { > + dev_dbg(&rhdev->dev, "suspend raced with wakeup event\n"); > + hcd_bus_resume(rhdev, PMSG_AUTO_RESUME); > + status = -EBUSY; > + } > + } > } else { > spin_lock_irq(&hcd_root_hub_lock); > if (!HCD_DEAD(hcd)) { > > -- Best Regards, Peter Chen -- 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