speedtouch: wait for receive urb completion handlers to finish after calling
  usb_unlink_urb.


 speedtouch.c |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+)


diff -Nru a/drivers/usb/misc/speedtouch.c b/drivers/usb/misc/speedtouch.c
--- a/drivers/usb/misc/speedtouch.c     Fri Jan 24 15:11:45 2003
+++ b/drivers/usb/misc/speedtouch.c     Fri Jan 24 15:11:45 2003
@@ -906,6 +906,9 @@
 static void udsl_usb_disconnect (struct usb_interface *intf)
 {
        struct udsl_instance_data *instance = usb_get_intfdata (intf);
+       struct list_head *pos;
+       unsigned long flags;
+       unsigned int count = 0;
        int i;
 
        PDEBUG ("disconnecting\n");
@@ -921,12 +924,39 @@
 
        down (&instance->serialize);
        /* no need to take the spinlock - recvqueue_tasklet is not running */
+       list_for_each (pos, &instance->spare_receivers)
+               if (++count > UDSL_NUMBER_RCV_URBS)
+                       panic (__FILE__ ": memory corruption detected at line %d!\n", 
+__LINE__);
        INIT_LIST_HEAD (&instance->spare_receivers);
        up (&instance->serialize);
 
+       PDEBUG ("udsl_usb_disconnect: flushed %u spare receivers\n", count);
+
+       count = UDSL_NUMBER_RCV_URBS - count;
+
        for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++)
                usb_unlink_urb (instance->rcvbufs[i].urb);
 
+       /* wait for completion handlers to finish */
+       do {
+               unsigned int completed = 0;
+
+               spin_lock_irqsave (&instance->completed_receivers_lock, flags);
+               list_for_each (pos, &instance->completed_receivers)
+                       if (++completed > count)
+                               panic (__FILE__ ": memory corruption detected at line 
+%d!\n", __LINE__);
+               spin_unlock_irqrestore (&instance->completed_receivers_lock, flags);
+
+               PDEBUG ("udsl_usb_disconnect: found %u completed receivers\n", 
+completed);
+
+               if (completed == count)
+                       break;
+
+               /* not all urbs accounted for */
+               yield ();
+       } while (1);
+
+       PDEBUG ("udsl_usb_disconnect: flushing %u completed receivers\n", count);
        /* no need to take the spinlock - no completion handlers running */
        INIT_LIST_HEAD (&instance->completed_receivers);
 



-------------------------------------------------------
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

Reply via email to