> For the urb to complete.  The schedule_timeout() returned without
> that completion.  We only forced the completion path to start, with
> the unlink; if it wasn't already starting (maybe on another CPU).

So you are doing the conventional wait stuff only to implement
the timeout, aren't you?
This seems kind of convoluted to me. May I suggest doing the
timeout explicitely like this:

diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c        Sat Aug  9 10:15:31 2003
+++ b/drivers/usb/core/message.c        Sat Aug  9 10:15:31 2003
@@ -16,77 +16,71 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/timer.h>
 #include <asm/byteorder.h>
 
 #include "hcd.h"       /* for usbcore internals */
 #include "usb.h"
 
 struct usb_api_data {
-       wait_queue_head_t wqh;
-       int done;
+       struct completion cpl;
+       int timeout;
 };
 
 static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
 {
-       struct usb_api_data *awd = (struct usb_api_data *)urb->context;
+       struct usb_api_data *ct = (struct usb_api_data *)urb->context;
+       
+       ct->timeout = (urb->status == -ECONNRESET);
+       complete(&ct->cpl);
+}
+
 
-       awd->done = 1;
-       wmb();
-       wake_up(&awd->wqh);
+static void timeout_kill (unsigned long d)
+{
+       struct urb *u = (struct urb *)d;
+       
+       usb_unlink_urb(u);
 }
 
 // Starts urb and waits for completion or timeout
 static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
 { 
-       DECLARE_WAITQUEUE(wait, current);
        struct usb_api_data awd;
+       struct timer_list timeout_killer;
        int status;
 
-       init_waitqueue_head(&awd.wqh);  
-       awd.done = 0;
-
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(&awd.wqh, &wait);
+       init_completion(&awd.cpl);      
 
        urb->context = &awd;
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status) {
-               // something went wrong
-               usb_free_urb(urb);
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&awd.wqh, &wait);
-               return status;
-       }
+       urb->transfer_flags |= URB_ASYNC_UNLINK;
+       status = usb_submit_urb(urb, GFP_NOIO);
+       if (status)
+               goto out_err;
+       
+       init_timer(&timeout_killer);
+       timeout_killer.expires = jiffies + (timeout ? timeout : MAX_SCHEDULE_TIMEOUT);
+       timeout_killer.data = (unsigned long)urb;
+       timeout_killer.function = timeout_kill;
+       add_timer(&timeout_killer);
 
-       while (timeout && !awd.done)
-       {
-               timeout = schedule_timeout(timeout);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               rmb();
-       }
+       wait_for_completion(&awd.cpl);
 
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&awd.wqh, &wait);
+       del_timer_sync(&timeout_killer);
 
-       if (!timeout && !awd.done) {
-               if (urb->status != -EINPROGRESS) {      /* No callback?!! */
-                       printk(KERN_ERR "usb: raced timeout, "
-                           "pipe 0x%x status %d time left %d\n",
-                           urb->pipe, urb->status, timeout);
-                       status = urb->status;
-               } else {
-                       warn("usb_control/bulk_msg: timeout");
-                       usb_unlink_urb(urb);  // remove urb safely
-                       status = -ETIMEDOUT;
-               }
-       } else
+       if (!awd.timeout) {
                status = urb->status;
+       } else {
+               warn("usb_control/bulk_msg: timeout");
+               status = -ETIMEDOUT;
+       }
 
        if (actual_length)
                *actual_length = urb->actual_length;
 
+out_err:
        usb_free_urb(urb);
-       return status;
+       return status;
 }
 
 /*-------------------------------------------------------------------*/




-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to