Hi Oliver, I decided to see how other drivers deal with this usb_unlink_urb
issue. The first thing I looked was devio.c. And guess what, it looks like
it assumes that the completion handler has completed by the time
usb_unlink_urb finishes:
static void destroy_async (struct dev_state *ps, struct list_head *list)
{
struct async *as;
unsigned long flags;
spin_lock_irqsave(&ps->lock, flags);
while (!list_empty(list)) {
as = list_entry(list->next, struct async, asynclist);
list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
/* usb_unlink_urb calls the completion handler with status == -ENOENT
*/
usb_unlink_urb(as->urb);
spin_lock_irqsave(&ps->lock, flags);
}
spin_unlock_irqrestore(&ps->lock, flags);
while ((as = async_getcompleted(ps))) <=== assumes completion handler
finished before this call
free_async(as);
Hmm, I wonder what the chances are that the next driver I look at
suffers from the same kind of problem.
All the best,
Duncan.
On Friday 10 January 2003 14:55, Oliver Neukum wrote:
> Am Freitag, 10. Januar 2003 13:21 schrieb Duncan Sands:
> > > I am afraid I do not agree. Your reasoning is correct only on UP.
> > > If the code in question runs on another CPU, you are in trouble.
> >
> > It all depends on the semantics of usb_unlink_urb. Consider the
> > patch below. Is this any better? Maybe not: if usb_unlink_urb
> > returns before the completion handler (running on another CPU)
> > reaches the tasklet_schedule statement, then what is to stop
> > the tasklet being scheduled by the completion handler after the
> > tasklet_kill? Nothing. So it all depends on whether or
> > not usb_unlink_urb guarantees that the completion handler has
> > finished running before it (usb_unlink_urb) returns.
>
> if (urb->status != -EINPROGRESS) {
> retval = -EBUSY;
> goto done;
> }
> from hcd.c
>
> So, usb_unlink_urb() will explicitely return if the completion handler
> is running. To be safe you need something like:
>
> (in disconnect() )
> spin_lock_irq(...);
> descriptor->disconnected = 1;
> tasklet_kill(...);
> spin_unlock_irq(...);
>
> (in the completion handler)
> spin_lock(...);
> if (!descriptor->disconnected)
> tasklet_schedule(...);
> spin_unlock(...);
>
> HTH
> Oliver
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel