Re: virtual hub and suspend/resume/reset questions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 11 Jun 2017, Benjamin Herrenschmidt wrote:

> > > 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.
> 
> Ok. So just to make sure I get you right, when the function calls
> wakeup(), the UDC driver, from within that wakeup, will call back into
> the function resume() ? Or do I need to somewhat break that call chain
> and call back resume() later ?

Under a non-emulated hub, the wakeup() function would start sending the
wakeup signal upstream and then return.  The gadget's resume callback
would not be invoked until later, probably at the end of the wakeup
sequence (the API isn't specific about this; it would most likely
depend on how the UDC hardware works).  So yes, you should break that
call chain.

> > 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.
> 
> Ok. So that's interesting and very weird in a way. That means that if
> the host has explicitly suspended let's say port A and B, and the vhub
> itself got suspended (thus suspending C, D and E but without affecting
> their port status), what happens differs whether the wakeup comes from
> the host (global bus wakeup) vs. a suspend request of one of the
> devices (let's say A).

Yes.  In the USB-2.0 spec, Figure 11-10, there are two different 
transitions out of the Suspended state, depending on whether the resume 
was initiated from upstream or downstream.

> In the first case, only C, D and E get woken up. But if A triggers a
> wakeup, it will also wakeup B. Or if C triggers a wakeup, it will
> wakeup A and B (while a wakeup from the host wouldn't have woken those
> up).

That's right.

> It's a bit weird... but I'm happy to implement what the spec says.

There's a nice description of all this in section 7.1.7.7 of the spec.

> > >  - 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.
> 
> Oh interesting. I was assuming a clearing of port enable to be a reset
> rather than a suspend.
> 
> So for example, from the perspective of an ordinary gadget today (ie
> not my driver), if I yank the cable, what they see is a suspend ?

> Ah, wait... the gadget driver has a ->disconnect() ... Maybe that's
> what I should call in that case no ?

Yes.  Yanking the cable would remove Vbus power, so the UDC would see a
disconnect rather than a suspend.  Or if the unplug was slow enough,
so that the data pins in the USB cable lost contact long before the
power pins, the UDC would see a suspend followed by a disconnect.

On the other hand, when the user on the host writes to the
/sys/bus/usb/devices/.../remove file, that causes the host to turn off
the port's enable feature.  To the device this looks the same as a
suspend.

Brief summary: Suspend is signalled by idle on the bus (the J state:
D+ high and D- low) for more than 3 ms; reset is signalled by the SE0
state (D+ and D- both low) on the bus -- if the connection is running 
at full speed.  High speed is similar but more complicated.

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



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux