USB: usbtest fix endless loop in unlink tests.
authorMartin Fuzzey <mfuzzey@gmail.com>
Thu, 4 Jun 2009 21:20:38 +0000 (23:20 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 16 Jun 2009 04:44:48 +0000 (21:44 -0700)
In tests 11 and 12 if the URB completes with an error status (eg babble)
the asynchrous unlink entered an endless loop trying to unlink
a non resubmitted URB.

Signed-off-by: Martin Fuzzey <mfuzzey@gmail.com>
Acked-by: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/misc/usbtest.c

index 5f1a19d..a9f06d7 100644 (file)
@@ -1072,23 +1072,34 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
         */
        msleep (jiffies % (2 * INTERRUPT_RATE));
        if (async) {
-retry:
-               retval = usb_unlink_urb (urb);
-               if (retval == -EBUSY || retval == -EIDRM) {
-                       /* we can't unlink urbs while they're completing.
-                        * or if they've completed, and we haven't resubmitted.
-                        * "normal" drivers would prevent resubmission, but
-                        * since we're testing unlink paths, we can't.
-                        */
-                       ERROR(dev,  "unlink retry\n");
-                       goto retry;
+               while (!completion_done(&completion)) {
+                       retval = usb_unlink_urb(urb);
+
+                       switch (retval) {
+                       case -EBUSY:
+                       case -EIDRM:
+                               /* we can't unlink urbs while they're completing
+                                * or if they've completed, and we haven't
+                                * resubmitted. "normal" drivers would prevent
+                                * resubmission, but since we're testing unlink
+                                * paths, we can't.
+                                */
+                               ERROR(dev, "unlink retry\n");
+                               continue;
+                       case 0:
+                       case -EINPROGRESS:
+                               break;
+
+                       default:
+                               dev_err(&dev->intf->dev,
+                                       "unlink fail %d\n", retval);
+                               return retval;
+                       }
+
+                       break;
                }
        } else
                usb_kill_urb (urb);
-       if (!(retval == 0 || retval == -EINPROGRESS)) {
-               dev_err(&dev->intf->dev, "unlink fail %d\n", retval);
-               return retval;
-       }
 
        wait_for_completion (&completion);
        retval = urb->status;