- 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;
