On Wed, 10 Dec 2003, David Brownell wrote: > So your real issue is that the URB model doesn't have a notion of > "idle" that suits you.
Yes. That and the fact that synchonous usb_unlink_urb has semantics that are practically useless for drivers and it is widely misused. > How about the usb_sg_request model? That's closer to the three > state model you'd suggested, in terms of goals. Those requests > may be submitted exactly once, then they need re-initialization. > That re-init requirement is not part of the URB model at all. More importantly, usb_sg_request doesn't have completion handlers. It's not really asynchronous, in the sense that drivers eventually have to wait for a request to complete. > > Part of the problem is that I don't remember what precise definition you > > were using for what it means for an URB to be linked. Here's my > > definition, an operational one: > > > > An URB is linked when the low-level HC driver thinks it is. > > Whereas I've been using "URB is linked when it's on the list maintained > by usbcore". This is an important difference and it's worth spending some time on it. Consider what happens when the two definitions disagree. Suppose an URB is on the submit path on CPU-1 and has reached a point where it's on the usbcore list but the HC driver hasn't yet accepted it. What happens now if CPU-2 calls usb_unlink_urb for that URB? Answer: usbcore removes it from the list and tells the HC driver to dequeue it. The HC driver refuses to do so (because it hasn't been queued yet). Regardless, the core returns from the unlink call with the URB removed from its list. Meanwhile, on CPU-1 the HC driver continues its submit path and does send the URB to the hardware. The end result is that usbcore thinks the URB has been unlinked and is gone, but the hardware is processing it! > > This can be made a little clearer through the following considerations. > > In any HC driver there must be two points in the code, one on the submit > > path, the other on the dequeue path, presumably protected by the same > > spinlock. Let's call them point A and point B. In a race between > > submit_urb and unlink_urb, the result is decided by which point is reached > > first. If the submit thread reaches A before the unlink thread reaches B, > > then the URB will get linked and then unlinked. If the unlink thread > > reaches B before the submit thread reaches A, then the unlink will fail > > (because the URB wasn't linked to begin with) and the link will succeed -- > > so the URB will end up being linked. > > Those points are supposed to be in hcd_submit_urb() and hcd_unlink_urb(). They can't be, for the reason I outlined above. > Some cleanup is needed (splice and more), but that's basically true using > your definitions. > > Note the usb_sg_request() handles that a bit differently. If the thread > doing the cancel ("unlink") wins, it succeeds and prevents the other > thread from starting to process the request. There's no question that usb_sg_request is cleaner in this respect. Alan Stern ------------------------------------------------------- This SF.net email is sponsored by: IBM Linux Tutorials. Become an expert in LINUX or just sharpen your skills. Sign up for IBM's Free Linux Tutorials. Learn everything from the bash shell to sys admin. Click now! http://ads.osdn.com/?ad_id=1278&alloc_id=3371&op=click _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel