On Wed, 15 Jan 2003, Oliver Neukum wrote:

> Am Mittwoch, 15. Januar 2003 17:04 schrieb Alan Stern:
> > resubmitted urbs.  Second (and more subtle), there are differences between
> > resubmitting an urb from the handler as opposed to submitting it again
> > after the handler is done.  For example, any bandwidth reserved for the
> > urb is kept when the handler resubmits, but it is deallocated otherwise.
> 
> Eh, how so? usb_hcd_giveback_urb() does call unlink_urb()
> unconditionally.

This is where my lack of knowledge of the details underlying the usb core
shows through.  Okay, looking at hcd.c I see where urb_unlink() is called
and how it releases the bandwidth.  I'm surprised; is it really supposed
to work this way?

I recall a long discussion a few months ago between you and David Brownell
concerning the question of how to reserve bandwidth.  The upshot was that
there was no need, because bandwidth was allocated on demand and would be
retained as long as an urb was resubmitted by its completion handler.  
Looking at the code, it appears that is not the case --
usb_release_bandwidth() is called whether the urb is resubmitted or not.

I don't know what ought to happen here.  Somebody will have to fill me in.

> The URB cannot finish regularly because that would be a hardware
> IRQ reentering itself. The generic IRQ code should prevent that.

Okay, there's no reason to worry about the possibility of a resubmitted 
urb being COMPLETING, and hence no reason to acquire the handler_lock 
before setting the state to COMPLETING.  (But what if the resubmitted urb 
goes to a different usb device, on a different bus attached to a different 
IRQ line?  Can't one hardware IRQ interrupt another?  What if it is 
fielded by a different processor?)

> So the only cause of a status change at that point can be usb_unlink_urb().
> In that case going to CANCELED seem to be correct and not causing
> a problem.
> 
> IMHO changing the status to CANCELED is no problem and neither
> is spinning on the handler_lock. Submitting and unlinking an URB
> from a completion handler is arcane anyway.

The situation I had in mind (rare, I admit -- but that's where the
gremlins live) is that the handler always resubmits, but one time through
the loop another processor decides to unlink the urb somewhere between
when it was resubmitted and when the handler returned.  When that
happens the state will be CANCELED upon the return from the handler, and
so usb_hcd_giveback_urb() will proceed to change the state to IDLE.  (It
has to assume this was a normally cancelled urb, not one that was
resubmitted and then cancelled.)  This would be wrong; the state should
remain CANCELED since the handler for the cancelled urb has not yet been
called.  Now the state is corrupted, something I would like to avoid.

Although corrupting the state in this way seems innocent enough here, it
has the potential to lead to problems later on.  Since it only requires a 
little more programming effort to get things right, I think we should do 
so.

> Could you explain why CANCELED and TERMINATING should be differentiated?
> It seems to me that both usb_unlink_urb() and usb_submit_urb() would fail
> with an error in both cases.

Well, the explanation above shows why something like TERMINATING needs to
exist.  Differentiating them occurs in two places.  Immediately after the
call to the completion handler, the state gets set to IDLE if it was
TERMINATING but not if it was CANCELED.  Although usb_submit_urb() will
fail with an error in both cases, the errors ought to be different: If the
state was CANCELED then the urb was resubmitted _before its handler was
called_; definitely a programming bug.  If the state was TERMINATING then
the handler is trying to resubmit a cancelled urb, which is not a bug; the
routine should fail but not BUG or oops.  Lastly, usb_unlink_urb() does
not need to differentiate these states.

> > In hcd_unlink_urb(): the CANCELED and TERMINATING cases are both BUGS (or
> > maybe they are both just oopses) -- someone has tried to unlink the same
> > urb twice.  In the COMPLETING case, the state should change to
> > TERMINATING.
> 
> A double unlink can happen in some network drivers if timeout and disconnect
> race. Can we simply return an error?

Yes.  The drivers could be rewritten to avoid a double unlink (I did just 
that for usb-storage), but an error here is probably okay.

> I'll do that as soon as we have a final version. I've followed your
> suggestions that seem obvious, but can we discuss the introduction
> of a TERMINATING state and double locking?

Now that I know that giveback_urb cannot be called reentrantly, I see
there's no need to worry about double locking.  That routine is 
the only place that needs to acquire handler_lock while there is a 
possibility of holding another spinlock, so the issue doesn't arise.

If you feel that my approach still isn't right and want to discuss it some 
more, I'll be happy to oblige.

Alan Stern



-------------------------------------------------------
This SF.NET email is sponsored by: A Thawte Code Signing Certificate 
is essential in establishing user confidence by providing assurance of 
authenticity and code integrity. Download our Free Code Signing guide:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0028en
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to