On Sat, 10 Jun 2017, Benjamin Herrenschmidt wrote: > Hi ! > > The USB spec is twisting my brain sideways trying to figure out how to > properly handle suspend/resume in the case of the aspeed vHub. > > Reminder: This is a combo-gadget HW that has 5 UDC "ports" (gadgets) > and a virtual hub above them, so it looks to the host as a hub with 5 > ports, the hub functionality is partially done in HW, partially in SW > in my driver. > > So first what I think is the easy case of explicit port suspend/resume > by SetPortFeature/ClearPortFeature. > > In that case, I can just call the gadget suspend() callback for that > port, keep track that the port is suspended, and *maybe* also disable > the HW so it doesn't respond on any pipe. > > Same goes with the obvious resume case above I assume. A port reset > would probably also "resume" though I would forward a reset to the > gadget rather than a resume, right ? (but clear my "suspended" state > flag). IIRC, according to the USB spec a host is never supposed to issue a reset request to a suspended port. It has to resume the port first. But yes, if you did get a reset then you would clear the suspend status and forward the reset to the gadget. > Now where things become interesting: > > - A wakeup() from the gadget. If the port is suspended but nothing > else above it, what do I do ? Mark the port resumed and move on ? Do I > need to call the gadget resume() callback ? Assuming the vhub itself is not suspended, mark the port as resumed and invoke the callback, but also set the port-suspend-change bit in the port's status register so that the port's bit will be set in the next reply on the vhub's interrupt endpoint. > - If I get a suspend from the host. IE. the top level port of the vhub > detects a suspend state on the bus (the HW signals that to me). I > assume here I should call "suspend" on all my downstream gadgets, at > least those who weren't already suspended. But do I also change the > internal state to "suspended" for all the ports ? Yes, invoke the suspend callbacks, but do not change the downstream port statuses. > - Then I get a resume from the host, ie, the upstream bus resumes, > should I resume *all* my downstream ports ? Only the ones where the port status says that the port is not suspended. > What if a downstream port > had been explicitly suspended with SetPortFeature before the host > suspended the whole bus, will the bus resume also clear that suspend > state or should that port remain suspended until a ClearPortFeature or > reset occurs ? It remains suspended. But there's one other interesting case you have forgotten about. That's where the vhub is suspended when one of the gadgets sends a wakeup request. You have to clear the suspend status on all the downstream ports (and set the port-suspend-change status bits) and send a wakeup request on your upstream port. > - I assume a bus reset (after set address) will result in broadcasting > a reset to all the downstream ports. What if they were suspended, > should I call resume first then reset or just reset on the gadgets ? No, a reset sent to the vhub does not broadcast anything to the downstream ports. It merely disables all of them and clears all their status bits (the connect and connect-change bits will then get set if a gadget is bound to the port -- the exact timing depends on whether you want to emulate port power switching since a reset will turn off the port's power feature). To the gadgets, this should appear to be the same as a suspend -- in fact, you should invoke their suspend callbacks. Likewise if the host clears a port's enable feature. > - Should my virtual hub "emulate" the various timings/delays of a hub > switching between those different states ? Esp. from resume or reset to > enabled, is it ok if it's more/less immediate ? Immediate is okay. The only time anyone would care would be if they are doing some bizarre test for conformance to the spec, and probably not even the USB CV would test for state changes occurring too quickly. > - When a downstream port is suspended, I assume I need to actively > block activity on its pipes ? ie, not forward setup packets and NAK > everything to it, or is this unnecessary ? I don't know the details of how your hardware works. In theory, you should disable those endpoints completely -- don't send ACKs, don't send NAKs, don't send or receive anything. And of course this implies that you never receive any setup packets, so naturally you never forward any of them. 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