Commit 0864c7a9 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

USB: gadgetfs simplifications

This simplifies event reading by eliminating arithmetic and being
more direct/obvious, and tweaks some debug messages slightly.
The math elimination will change timings, sometimes enough to
allow a race to appear.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 7489d149
...@@ -1062,39 +1062,36 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) ...@@ -1062,39 +1062,36 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
/* return queued events right away */ /* return queued events right away */
if (dev->ev_next != 0) { if (dev->ev_next != 0) {
unsigned i, n; unsigned i, n;
int tmp = dev->ev_next;
len = min (len, tmp * sizeof (struct usb_gadgetfs_event));
n = len / sizeof (struct usb_gadgetfs_event); n = len / sizeof (struct usb_gadgetfs_event);
if (dev->ev_next < n)
n = dev->ev_next;
/* ep0 can't deliver events when STATE_DEV_SETUP */ /* ep0 i/o has special semantics during STATE_DEV_SETUP */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (dev->event [i].type == GADGETFS_SETUP) { if (dev->event [i].type == GADGETFS_SETUP) {
len = i + 1; dev->state = STATE_DEV_SETUP;
len *= sizeof (struct usb_gadgetfs_event); n = i + 1;
n = 0;
break; break;
} }
} }
spin_unlock_irq (&dev->lock); spin_unlock_irq (&dev->lock);
len = n * sizeof (struct usb_gadgetfs_event);
if (copy_to_user (buf, &dev->event, len)) if (copy_to_user (buf, &dev->event, len))
retval = -EFAULT; retval = -EFAULT;
else else
retval = len; retval = len;
if (len > 0) { if (len > 0) {
len /= sizeof (struct usb_gadgetfs_event);
/* NOTE this doesn't guard against broken drivers; /* NOTE this doesn't guard against broken drivers;
* concurrent ep0 readers may lose events. * concurrent ep0 readers may lose events.
*/ */
spin_lock_irq (&dev->lock); spin_lock_irq (&dev->lock);
dev->ev_next -= len; if (dev->ev_next > n) {
if (dev->ev_next != 0) memmove(&dev->event[0], &dev->event[n],
memmove (&dev->event, &dev->event [len],
sizeof (struct usb_gadgetfs_event) sizeof (struct usb_gadgetfs_event)
* (tmp - len)); * (dev->ev_next - n));
if (n == 0) }
dev->state = STATE_DEV_SETUP; dev->ev_next -= n;
spin_unlock_irq (&dev->lock); spin_unlock_irq (&dev->lock);
} }
return retval; return retval;
...@@ -1149,7 +1146,7 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) ...@@ -1149,7 +1146,7 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type)
for (i = 0; i != dev->ev_next; i++) { for (i = 0; i != dev->ev_next; i++) {
if (dev->event [i].type != type) if (dev->event [i].type != type)
continue; continue;
DBG (dev, "discard old event %d\n", type); DBG(dev, "discard old event[%d] %d\n", i, type);
dev->ev_next--; dev->ev_next--;
if (i == dev->ev_next) if (i == dev->ev_next)
break; break;
...@@ -1162,9 +1159,9 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type) ...@@ -1162,9 +1159,9 @@ next_event (struct dev_data *dev, enum usb_gadgetfs_event_type type)
default: default:
BUG (); BUG ();
} }
VDEBUG(dev, "event[%d] = %d\n", dev->ev_next, type);
event = &dev->event [dev->ev_next++]; event = &dev->event [dev->ev_next++];
BUG_ON (dev->ev_next > N_EVENT); BUG_ON (dev->ev_next > N_EVENT);
VDEBUG (dev, "ev %d, next %d\n", type, dev->ev_next);
memset (event, 0, sizeof *event); memset (event, 0, sizeof *event);
event->type = type; event->type = type;
return event; return event;
......
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