Commit 14fff3d3 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[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.
parent b680dcc3
...@@ -354,6 +354,7 @@ static ssize_t ...@@ -354,6 +354,7 @@ static ssize_t
ep_io (struct ep_data *epdata, void *buf, unsigned len) ep_io (struct ep_data *epdata, void *buf, unsigned len)
{ {
DECLARE_COMPLETION (done); DECLARE_COMPLETION (done);
int value;
spin_lock_irq (&epdata->dev->lock); spin_lock_irq (&epdata->dev->lock);
if (likely (epdata->ep != NULL)) { if (likely (epdata->ep != NULL)) {
...@@ -363,14 +364,12 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len) ...@@ -363,14 +364,12 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
req->complete = epio_complete; req->complete = epio_complete;
req->buf = buf; req->buf = buf;
req->length = len; req->length = len;
epdata->status = usb_ep_queue (epdata->ep, req, GFP_ATOMIC); value = usb_ep_queue (epdata->ep, req, GFP_ATOMIC);
} else } else
epdata->status = -ENODEV; value = -ENODEV;
spin_unlock_irq (&epdata->dev->lock); spin_unlock_irq (&epdata->dev->lock);
if (epdata->status == 0) { if (likely (value == 0)) {
int value;
value = wait_event_interruptible (done.wait, done.done); value = wait_event_interruptible (done.wait, done.done);
if (value != 0) { if (value != 0) {
spin_lock_irq (&epdata->dev->lock); spin_lock_irq (&epdata->dev->lock);
...@@ -378,17 +377,21 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len) ...@@ -378,17 +377,21 @@ ep_io (struct ep_data *epdata, void *buf, unsigned len)
DBG (epdata->dev, "%s i/o interrupted\n", DBG (epdata->dev, "%s i/o interrupted\n",
epdata->name); epdata->name);
usb_ep_dequeue (epdata->ep, epdata->req); usb_ep_dequeue (epdata->ep, epdata->req);
spin_unlock_irq (&epdata->dev->lock);
wait_event (done.wait, done.done); wait_event (done.wait, done.done);
if (epdata->status == 0) if (epdata->status == -ECONNRESET)
epdata->status = value; epdata->status = -EINTR;
} else { } else {
spin_unlock_irq (&epdata->dev->lock);
DBG (epdata->dev, "endpoint gone\n"); DBG (epdata->dev, "endpoint gone\n");
epdata->status = -ENODEV; epdata->status = -ENODEV;
} }
spin_unlock_irq (&epdata->dev->lock);
}
} }
return epdata->status; return epdata->status;
}
return value;
} }
...@@ -424,10 +427,12 @@ ep_read (struct file *fd, char *buf, size_t len, loff_t *ptr) ...@@ -424,10 +427,12 @@ ep_read (struct file *fd, char *buf, size_t len, loff_t *ptr)
if (unlikely (!kbuf)) if (unlikely (!kbuf))
goto free1; goto free1;
VDEBUG (data->dev, "%s read %d OUT\n", data->name, len);
value = ep_io (data, kbuf, 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)) if (value >= 0 && copy_to_user (buf, kbuf, value))
value = -EFAULT; value = -EFAULT;
free1: free1:
up (&data->lock); up (&data->lock);
kfree (kbuf); kfree (kbuf);
...@@ -470,8 +475,9 @@ ep_write (struct file *fd, const char *buf, size_t len, loff_t *ptr) ...@@ -470,8 +475,9 @@ ep_write (struct file *fd, const char *buf, size_t len, loff_t *ptr)
goto free1; goto free1;
} }
VDEBUG (data->dev, "%s write %d IN\n", data->name, len);
value = ep_io (data, kbuf, len); value = ep_io (data, kbuf, len);
VDEBUG (data->dev, "%s write %d IN, status %d\n",
data->name, len, value);
free1: free1:
up (&data->lock); up (&data->lock);
kfree (kbuf); kfree (kbuf);
...@@ -1200,9 +1206,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1200,9 +1206,11 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (value >= 0) if (value >= 0)
value = min (ctrl->wLength, (u16) value); value = min (ctrl->wLength, (u16) value);
break; break;
case USB_DT_STRING:
default:
goto unrecognized; goto unrecognized;
default: // all others are errors
break;
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment