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