On Fri, 17 Jul 2009, Yang Fei-AFY095 wrote: > > >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. > > Isn't spin_lock_irq sufficient to disable interrupts? No, for two reasons. First, it disables interrupts on the current CPU but not on other CPUs. Second, we will need the interrupts to remain disabled while we wait for in-progress resumes to complete, during which time we have to drop the spinlock. > > 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. > > There is a while loop trying to suspend all ports. Can we also check for > RESUME bit here, if any port is in the middle of resuming (or > reset_done[port] is nonzero), return -EBUSY and give up the current > global suspend? We could, provided remote wakeup was enabled for the root hub. I'm not sure it would be a good idea, though. It might be -- I'm undecided. But what would we do if remote wakeup was not enabled on the root hub? Also, you must keep in mind that when users tell their computers to go to sleep, they don't want the sleep to fail simply because some USB device has decided it wants to wake up now. > > Then go ahead with suspending the root hub and re-enabling > > interrupt requests. > > If there is any port resuming while we try to make a global suspend, > shouldn't we let the resume to continue and quit suspending? The driver > can always try suspending again at a later time. Root hubs should behave like normal external hubs, as much as possible. What does an external hub do if you suspend it just after one of its downstream ports receives a remote wakeup request? Does the suspend fail? No, it doesn't. The hub suspends and then forwards the wakeup request out its upstream port. > > Finally at the end, if we did encounter any in-progress > > resumes, call usb_hcd_resume_root_hub. (I forgot to mention earlier, we do this only if remote wakeup is enabled for the root hub.) > In the issue described in previous email, if we quit suspending, when > rh_timer fires the ehci_hub_status_data would be able to go through > (instead of returning at the beginning because of hcd->state is > suspended) and eventually wakeup the hub_thread to finish resuming the > port. I'm aware of that. The fact that it solves your problem doesn't mean it's the right thing to do. 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