ChangeSet 1.1123.18.21, 2003/08/15 10:01:55-07:00, [EMAIL PROTECTED]
[PATCH] USB: usb_start_wait_urb() rewrite
The code that manges the synchronous control/bulk calls has
been a mess for ages. This patch rewrites it using:
- "struct completion" instead of a usb-internal clone therof,
- prepare_to_wait()/finish_wait() instead of the tangled
mess it now uses (or a new wait_event_timeout call, as in
previous versions of this patch).
It's a net code shrink and simplification.
drivers/usb/core/message.c | 93 +++++++++++++++++++--------------------------
1 files changed, 41 insertions(+), 52 deletions(-)
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c Fri Aug 15 10:44:14 2003
+++ b/drivers/usb/core/message.c Fri Aug 15 10:44:14 2003
@@ -16,77 +16,66 @@
#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;
-};
-
static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
{
- struct usb_api_data *awd = (struct usb_api_data *)urb->context;
+ complete((struct completion *)urb->context);
+}
- awd->done = 1;
- wmb();
- wake_up(&awd->wqh);
+
+static void timeout_kill(unsigned long data)
+{
+ struct urb *urb = (struct urb *) data;
+
+ dev_warn(&urb->dev->dev, "%s timeout on ep%d%s\n",
+ usb_pipecontrol(urb->pipe) ? "control" : "bulk",
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out");
+ 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)
{
- DECLARE_WAITQUEUE(wait, current);
- struct usb_api_data awd;
- int status;
-
- init_waitqueue_head(&awd.wqh);
- awd.done = 0;
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&awd.wqh, &wait);
-
- 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;
- }
-
- while (timeout && !awd.done)
- {
- timeout = schedule_timeout(timeout);
- set_current_state(TASK_UNINTERRUPTIBLE);
- rmb();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&awd.wqh, &wait);
-
- 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;
+ struct completion done;
+ struct timer_list timer;
+ int status;
+
+ init_completion(&done);
+ urb->context = &done;
+ urb->transfer_flags |= URB_ASYNC_UNLINK;
+ urb->actual_length = 0;
+ status = usb_submit_urb(urb, GFP_NOIO);
+
+ if (status == 0) {
+ if (timeout > 0) {
+ init_timer(&timer);
+ timer.expires = jiffies + timeout;
+ timer.data = (unsigned long)urb;
+ timer.function = timeout_kill;
+ /* grr. timeout _should_ include submit delays. */
+ add_timer(&timer);
}
- } else
+ wait_for_completion(&done);
status = urb->status;
+ /* note: HCDs return ETIMEDOUT for other reasons too */
+ if (status == -ECONNRESET)
+ status = -ETIMEDOUT;
+ if (timeout > 0)
+ del_timer_sync(&timer);
+ }
if (actual_length)
*actual_length = urb->actual_length;
-
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