On Wed, 21 Aug 2013, Sarah Sharp wrote: > Background > ---------- > > The USB 2.0 specification, section 7.1.7.7, says that upon device remote > wakeup signaling, the first active hub (which is often the roothub) must > rebroadcast the resume signaling for at least 20 ms (TDRSMDN). After > that's done, the hub's suspend status change bit will be set, and system > software must not access the device for at least 10 ms (TRSMRCY). > > It turns out that TRSMRCY is a *minimum*, not a *maximum*, according to > Table 7-14. That means the port can actually take longer than TRSMRCY > to resume. Any attempt to communicate with the device, or reset the > device, will result in a USB device disconnect. By the way, I just noticed your Google+ posting about this. I think you (and perhaps the engineers you spoke with) may have misunderstood what Table 7-14 means when it lists 10 ms as the _minimum_ value for TRSMRCY. This delay value is a requirement on the OS. The host system must not access the device until at least 10 ms after the resume is complete. The system can wait longer than that if it wants -- that's why 10 ms is a minimum. It just has to avoid accessing the device sooner. A _minimum_ value on the host side translates into a _maximum_ value on the device side. The device can safely assume that it can spend up to 10 ms getting back into shape after a resume, but no more. After 10 ms, the host may try to communicate with it. > Then, when the USB core calls into get port status, it transitions the > port from the Resume state to the RExit state by changing the port link > state to U0. The xHCI driver will get a port status change event when > that transition is complete, but that port status change event is > currently ignored. The excess delay you observe with xHCI is the time spent in the RExit substate? That probably should not be counted as part of the TRSMRCY period. It's hard to say for certain, because TRSMRCY is described only in the USB-2 spec and not in the xHCI spec, and vice versa for RExit. Still, it's reasonable to assume that the TRSMRCY period should begin when the port changes back to U0, not when it leaves the RESUME state and enters RExit. So in the end this appears to be a simple bug in xhci-hcd. The Get-Port-Status request that terminates the resume signalling should wait until the port goes back into U0 (which agrees with what you have already decided, of course). ehci-hcd does something similar: /* stop resume signaling */ temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME); ehci_writel(ehci, temp, status_reg); clear_bit(wIndex, &ehci->resuming_ports); retval = ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 2000 /* 2msec */); The ehci_handshake call busy-waits until the controller turns off the PORT_RESUME bit, which happens when the port has switched to a high-speed idle. It's supposed to take no more than 2 ms but hopefully is a lot faster. (Hmmm, maybe the private lock should be dropped during this handshake...) 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