On Tue, 14 Jul 2009, Yang Fei-AFY095 wrote: > Time0: Suspend one port - selective suspend. By calling ehci_control > with typeReq=SetPortFeature and wValue=USB_PORT_FEAT_SUSPEND; > > Time1: Remote wakeup from device triggers an STS_PCD interrupt , handled > by ehci_irq; > > Time2: The ISR falls into if (status & STS_PCD), at this moment EHCI is > still running (global suspend is expected to come shortly after > selective suspend), so usb_hcd_resume_root_hub doesn't get called; > > Time3: In the while loop, since PORT_RESUME is set for the port being > waked up, rh_timer is set to fire 20ms later; > > Time4: At the end of ehci_irq, usb_hcd_poll_rh_status is called, nothing > happens here because ehci_hub_status_data returns 0, reason being > time_after_eq(jiffies, ehci->reset_done) is false as ehci->reset_done > has been set to 20ms later in Time3; > > Time5: EHCI is halted - global suspend scheduled by the host driver. > Time between Time0 and Time5 is about 20ms; > > Time6: rh_timer fires. Time between Time3 and Time6 is 20ms (set in > ehci_irq). rh_timer_func -> usb_hcd_poll_rh_status -> > ehci_hub_status_data. Still nothing happens this time because > ehci_hub_status_data returns 0 again as it falls into the first if > statement if (!HC_IS_RUNNING(hcd->state)) (EHCI has been halted in > Time5, so hcd->state is SUSPENDED now). > > The consequence is that the remote wakeup gets lost, the host doesn't > resume the bus as expected. What you're really saying is that we need to improve the way we handle the race between suspending a root hub and receiving a remote wakeup on one of its ports. The way we do it now, the remote wakeup event can get lost. You are right. I haven't had time to write a patch, but I think we need to do something like this at the start of ehci_bus_suspend: First, write 0 to the intr_enable register. This will prevent us from seeing any future wakeup events. Next, if any ports are in the middle of a resume sequence (reset_done[port] is nonzero), we have to wait for the resumes to finish and handle all the post-resume actions. Then go ahead with suspending the root hub and re-enabling interrupt requests. Finally at the end, if we did encounter any in-progress resumes, call usb_hcd_resume_root_hub. Probably all the host controller drivers will need similar changes. Does that sound like it will solve your problem? 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