Alan Stern wrote:
On Fri, 18 Jul 2003, Oliver Neukum wrote:


It seems to me that you are racing against HC hardware.


Yes, certainly.

But not at that level, and URBs aren't hardware data structures either.


You cannot unlink an URB that is being executed, can you?


With UHCI you can.  What will happen is that the HCD will finish executing
the current TD, but on its next loop through the hardware schedule the QH
will no longer be in the chain.  As a result, you end up with an invalid
USB transaction: the initial packets go out on the bus but the final ones
don't.

All HCs have a similar answer to this question: (a) take all the relevant data structures off the hardware schedule; then (b) make sure they're off (by waiting for the next frame, or in the case of EHCI for an explicit IAA handshake); (c) run through and handle the work, reporting both hardware and software/unlink completions; and finally (d) relink the data structures if necessary.


At the same time you must retain EINPROGRESS in the status
field until some time _after_ io is completed, because you
need to evaluate the result of the transfer.


See above. The status can be set to -ECONNRESET because the transfer doesn't finish. Or maybe the race goes the other way and the transfer does finish; nevertheless the URB is marked as having been unlinked. The driver does not check the hardware status field to see whether the transfer completed successfully before the unlink occurred.

As pointed out earlier on this thread, the HCD glue does check urb->status before proceeding.


Part of this problem is caused already in the hcd glue layer. hcd_unlink_urb() sets urb->status to -ECONNRESET or -ENOENT _before_ calling the HC driver to dequeue the URB.

One could easily argue that this behavior is a bug.

Sounds like you want to try ... ;)


It's just how unlinking is defined; not a bug.  At some point,
some software component chooses what urb->status will be.

Since the communication between layers is asynchronous, the
urb can't be (synchronously) unlinked before that status
is changed.  So the status is decided before the HCD gets
kicked to accelerate any unlinking.  That prevents all
kinds of nastiness.


IMHO the only way to learn whether an URB can be unlinked
is to try it.


Is there any point in the code that tries to determine whether an URB can be unlinked without actually trying it?

If you have to ask that, you haven't looked at the code that actually calls into the HCD to make it unlink. There's some code there that does exactly that -- and I've mentioned it before on this thread, come to think of it.



Alan Stern






-------------------------------------------------------
This SF.net email is sponsored by: VM Ware
With VMware you can run multiple operating systems on a single machine.
WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the
same time. Free trial click here: http://www.vmware.com/wl/offer/345/0
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to