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: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
7489d14943
commit
0864c7a928
@@ -1062,39 +1062,36 @@ scan:
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user