Some small updates:

 - Sometimes read requests can be satisfied directly from
   the OUT fifo.  This fixes a bug where the return code
   from usb_ep_queue() overwrite the transfer status, which
   in that case was set _before_ that call returned.
   (Synchronous behavior; not the usual async completion.)

 - In the same vein,  usb_ep_dequeue() doesn't need to be
   synchronous -- though so far most controller drivers
   have implemented it that way.  So drop the spinlock
   before the wait_event() sleep.

 - Some debug messages are more useful AFTER the event
   than before.

 - The only descriptor fetches user mode drivers will
   need to handle are for string descriptors.  Stall all
   other requests, like ones for other-speed configs
   on single-speed devices.

Please merge.

- Dave

--- greg-2.5bk/drivers/usb/gadget/inode.c       2003-09-18 18:04:30.000000000 -0700
+++ gadget-2.6/drivers/usb/gadget/inode.c       2003-09-22 11:13:54.000000000 -0700
@@ -354,6 +358,7 @@
 ep_io (struct ep_data *epdata, void *buf, unsigned len)
 {
        DECLARE_COMPLETION (done);
+       int value;
 
        spin_lock_irq (&epdata->dev->lock);
        if (likely (epdata->ep != NULL)) {
@@ -363,14 +368,12 @@
                req->complete = epio_complete;
                req->buf = buf;
                req->length = len;
-               epdata->status = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
+               value = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
        } else
-               epdata->status = -ENODEV;
+               value = -ENODEV;
        spin_unlock_irq (&epdata->dev->lock);
 
-       if (epdata->status == 0) {
-               int     value;
-
+       if (likely (value == 0)) {
                value = wait_event_interruptible (done.wait, done.done);
                if (value != 0) {
                        spin_lock_irq (&epdata->dev->lock);
@@ -378,17 +381,21 @@
                                DBG (epdata->dev, "%s i/o interrupted\n",
                                                epdata->name);
                                usb_ep_dequeue (epdata->ep, epdata->req);
+                               spin_unlock_irq (&epdata->dev->lock);
+
                                wait_event (done.wait, done.done);
-                               if (epdata->status == 0)
-                                       epdata->status = value;
+                               if (epdata->status == -ECONNRESET)
+                                       epdata->status = -EINTR;
                        } else {
+                               spin_unlock_irq (&epdata->dev->lock);
+
                                DBG (epdata->dev, "endpoint gone\n");
                                epdata->status = -ENODEV;
                        }
-                       spin_unlock_irq (&epdata->dev->lock);
                }
+               return epdata->status;
        }
-       return epdata->status;
+       return value;
 }
 
 
@@ -424,10 +431,12 @@
        if (unlikely (!kbuf))
                goto free1;
 
-       VDEBUG (data->dev, "%s read %d OUT\n", data->name, len);
        value = ep_io (data, kbuf, len);
+       VDEBUG (data->dev, "%s read %d OUT, status %d\n",
+               data->name, len, value);
        if (value >= 0 && copy_to_user (buf, kbuf, value))
                value = -EFAULT;
+
 free1:
        up (&data->lock);
        kfree (kbuf);
@@ -470,8 +479,9 @@
                goto free1;
        }
 
-       VDEBUG (data->dev, "%s write %d IN\n", data->name, len);
        value = ep_io (data, kbuf, len);
+       VDEBUG (data->dev, "%s write %d IN, status %d\n",
+               data->name, len, value);
 free1:
        up (&data->lock);
        kfree (kbuf);
@@ -1200,9 +1210,11 @@
                        if (value >= 0)
                                value = min (ctrl->wLength, (u16) value);
                        break;
-
-               default:
+               case USB_DT_STRING:
                        goto unrecognized;
+
+               default:                // all others are errors
+                       break;
                }
                break;
 

Reply via email to