On Thursday 27 July 2006 8:41 am, Alan Stern wrote:

> > > The problem came up when there was a control URB running while the HCD
> > > module was unloaded.  hcd_endpoint_disable() didn't wait for the URB to 
> > > complete, the driver was unloaded from memory, and boom!
> > 
> > Hmm, the if(1) should leave the urb in ep->urb_list so 
> > hcd_endpoint_disable()
> > would go through the loop again, retrying until the urb completed.  Or was
> > there something else going on?  (It's late, sigh.)
> 
> Yes, the URB remained in ep->urb_list and hcd_endpoint_disable() did see
> it when it went through the loop again.  But urb->status had been changed
> to -ESHUTDOWN, so hcd_endpoint_disable() simply skipped over it and did
> not keep retrying to unlink it.  (It would be a bug for usbcore to call a
> dequeue method more than once for the same URB.)

So that'd be a bug; it should busy-wait until list_empty(ep->urb_list)
somehow, maybe an msleep() would suffice.


> The real problem was this: hcd_endpoint_disable() relies on 
> hcd->driver->endpoint_disable() to wait until all URBs for an endpoint 
> have completed.  Normally that's fine, but it doesn't work with URBs for 
> endpoints on the root hub -- because these URBs never go through the 
> hcd->driver->enqueue() pathway to begin with.
> 
> So we needed another way to wait for them.  My solution was to wait in 
> usb_rh_urb_dequeue().  Maybe there's a better way.

I still don't follow.  If the root hub control URBs don't go through
that code path, how would endpoint_disable() be able to notice them
in the first place?


> > > Nowadays we can prevent the crash with appropriate refcounting.  But it
> > > could still leave us calling hcd->driver->stop() while the control URB was
> > > running.  Do you think it would be safe, given how non-standardized those 
> > > HCD methods are?
> > 
> > I'm missing something.  Refcounting wouldn't solve that; the issue is that
> > the URB wasn't yet given back, and thus is on ep->urb_list (with a refcount,
> > sure, but _because_ it's on the list and thus still busy).  So stop() 
> > wouldn't
> > be called ... if HCDs don't behave the same, that's clearly trouble.
> 
> No, you're confused.  (It must have been _very_ late.)
> 
> Note that hcd_endpoint_disable() doesn't wait for ep->urb_list to be 
> empty.  It merely waits for hcd->driver->endpoint_disable() to return.

But _should_ it wait for urb_list to be empty, before calling the
driver's endpoint_disable()?


> Refcounting would solve the problem of the HCD's module being unloaded 
> from memory while its code was still in use.  It would also solve the 
> related problem of the HCD's private data structure being freed while 
> still in use.
> 
> But if hcd_endpoint_disable() fails to wait for root-hub URBs to complete,
> then there is a possibility that stop() could be called while an URB was
> still in progress.  (Actually, improvements to the hub driver have made
> this much less likely.  Still, it's something to be aware of.)

To the extent that root hub urbs -- control or status -- get special
treatment, maybe there should just be a per-usb_device counter of
how many are in flight, and that should go to zero before stop().

- Dave


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to