Here is my patch to implement proper timing of synchronous unlinks. Basically it just uses a spinlock to cause unlink requests during a completion handler to wait until the handler has returned before carrying out the unlink. This seems like a pretty small and uninvasive sort of change.
Alan Stern ===== drivers/usb/core/hcd.c 1.89 vs edited ===== --- 1.89/drivers/usb/core/hcd.c Thu Jan 16 04:29:28 2003 +++ edited/drivers/usb/core/hcd.c Wed Jan 22 16:25:26 2003 @@ -1116,8 +1116,13 @@ * lock sequence needed for the usb_hcd_giveback_urb() code paths * (urb lock, then hcd_data_lock) in case some other CPU is now * unlinking it. + * + * In case the completion handler is already running, we first + * acquire urb->handler_lock; this will cause us to wait until + * the handler has returned. */ - spin_lock_irqsave (&urb->lock, flags); + spin_lock_irqsave (&urb->handler_lock, flags); + spin_lock (&urb->lock); spin_lock (&hcd_data_lock); if (!urb->dev || !urb->dev->bus) { @@ -1170,7 +1175,8 @@ urb->status = -ECONNRESET; } spin_unlock (&hcd_data_lock); - spin_unlock_irqrestore (&urb->lock, flags); + spin_unlock (&urb->lock); + spin_unlock_irqrestore (&urb->handler_lock, flags); if (urb == (struct urb *) hcd->rh_timer.data) { usb_rh_status_dequeue (hcd, urb); @@ -1200,7 +1206,8 @@ done: spin_unlock (&hcd_data_lock); - spin_unlock_irqrestore (&urb->lock, flags); + spin_unlock (&urb->lock); + spin_unlock_irqrestore (&urb->handler_lock, flags); bye: if (retval && sys) dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); @@ -1307,7 +1314,9 @@ } /* pass ownership to the completion handler */ + spin_lock (&urb->handler_lock); urb->complete (urb, regs); + spin_unlock (&urb->handler_lock); usb_put_urb (urb); } EXPORT_SYMBOL (usb_hcd_giveback_urb); ===== drivers/usb/core/urb.c 1.19 vs edited ===== --- 1.19/drivers/usb/core/urb.c Wed Oct 30 22:55:08 2002 +++ edited/drivers/usb/core/urb.c Wed Jan 22 16:13:58 2003 @@ -44,6 +44,7 @@ memset(urb, 0, sizeof(*urb)); urb->count = (atomic_t)ATOMIC_INIT(1); spin_lock_init(&urb->lock); + spin_lock_init(&urb->handler_lock); return urb; } ===== include/linux/usb.h 1.123 vs edited ===== --- 1.123/include/linux/usb.h Fri Jan 17 13:21:23 2003 +++ edited/include/linux/usb.h Wed Jan 22 16:04:12 2003 @@ -728,6 +728,7 @@ { spinlock_t lock; /* lock for the URB */ atomic_t count; /* reference count of the URB */ + spinlock_t handler_lock; /* lock during completion routine */ void *hcpriv; /* private data for host controller */ struct list_head urb_list; /* list pointer to all active urbs */ struct usb_device *dev; /* (in) pointer to associated device */ ------------------------------------------------------- This SF.net email is sponsored by: Scholarships for Techies! Can't afford IT training? All 2003 ictp students receive scholarships. Get hands-on training in Microsoft, Cisco, Sun, Linux/UNIX, and more. www.ictp.com/training/sourceforge.asp _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel