This patch uses completion timeout instead of a timer to implement a timeout when submitting an URB in usb_start_wait_urb()
It also put the task in interruptible state instead of an uninterruptible one while waiting for the completion. I'm not sure about this part though and the comment is not clear. If someone can confirm that the task can be put in an interruptible state here that would be great. thanks -- >8 -- drivers/usb/core/message.c | 74 +++++++++++++++++--------------------------- 1 files changed, 29 insertions(+), 45 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 08fb20f..9d52263 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -23,60 +23,44 @@ static void usb_api_blocking_completion( complete((struct completion *)urb->context); } - -static void timeout_kill(unsigned long data) -{ - struct urb *urb = (struct urb *) data; - - usb_unlink_urb(urb); -} - -// Starts urb and waits for completion or timeout -// note that this call is NOT interruptible, while -// many device driver i/o requests should be interruptible -static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) +/* + * Starts urb and waits for completion or timeout note that this call + * is NOT interruptible, while many device driver i/o requests should + * be interruptible + */ +static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) { - struct completion done; - struct timer_list timer; - int status; + struct completion done; + int status; init_completion(&done); urb->context = &done; urb->actual_length = 0; status = usb_submit_urb(urb, GFP_NOIO); - - if (status == 0) { - if (timeout > 0) { - init_timer(&timer); - timer.expires = jiffies + msecs_to_jiffies(timeout); - timer.data = (unsigned long)urb; - timer.function = timeout_kill; - /* grr. timeout _should_ include submit delays. */ - add_timer(&timer); - } - wait_for_completion(&done); - status = urb->status; - /* note: HCDs return ETIMEDOUT for other reasons too */ - if (status == -ECONNRESET) { - dev_dbg(&urb->dev->dev, - "%s timed out on ep%d%s len=%d/%d\n", - current->comm, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - urb->actual_length, - urb->transfer_buffer_length - ); - if (urb->actual_length > 0) - status = 0; - else - status = -ETIMEDOUT; - } - if (timeout > 0) - del_timer_sync(&timer); + if (unlikely(status)) + goto out; + + if (wait_for_completion_interruptible_timeout( + &done, timeout ? : MAX_SCHEDULE_TIMEOUT) <= 0) { + usb_unlink_urb(urb); } - + status = urb->status; + /* note: HCDs return ETIMEDOUT for other reasons too */ + if (status == -ECONNRESET) { + status = urb->actual_length > 0 ? 0 : -ETIMEDOUT; + + dev_dbg(&urb->dev->dev, + "%s timed out on ep%d%s len=%d/%d\n", + current->comm, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->actual_length, + urb->transfer_buffer_length); + } +out: if (actual_length) *actual_length = urb->actual_length; + usb_free_urb(urb); return status; } Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel