ChangeSet 1.1325.4.11, 2003/09/23 17:18:18-07:00, david-b@pacbell.net

[PATCH] USB: usb gadgetfs updates

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.


 drivers/usb/gadget/inode.c |   34 +++++++++++++++++++++-------------
 1 files changed, 21 insertions(+), 13 deletions(-)


diff -Nru a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
--- a/drivers/usb/gadget/inode.c	Thu Sep 25 14:31:44 2003
+++ b/drivers/usb/gadget/inode.c	Thu Sep 25 14:31:44 2003
@@ -354,6 +354,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 +364,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 +377,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 +427,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 +475,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 +1206,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;
 
