ChangeSet 1.1243.50.14, 2003/06/10 14:50:17-07:00, david-b@pacbell.net [PATCH] USB: net2280 patch: control-out fix, minor cleanups The main thing this fixes is making the control-OUT path work. Drivers like RNDIS and DFU need it; this should resolve one bug report. It also has some minor cleanups. drivers/usb/gadget/net2280.c | 30 +++++++++++++++++++++--------- 1 files changed, 21 insertions(+), 9 deletions(-) diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c Tue Jun 10 17:11:14 2003 +++ b/drivers/usb/gadget/net2280.c Tue Jun 10 17:11:14 2003 @@ -20,10 +20,12 @@ * short OUT transfers happen.) Drivers can use the req->no_interrupt * hint to completely eliminate some IRQs, if a later IRQ is guaranteed * and DMA chaining is enabled. + * + * Note that almost all the errata workarounds here are only needed for + * rev1 chips. Rev1a silicon (0110) fixes almost all of them. */ -// #define NET2280_DMA_OUT_WORKAROUND -// #define USE_DMA_CHAINING +#define USE_DMA_CHAINING /* @@ -180,6 +182,13 @@ * kicking in the "toggle-irrelevant" mode. */ tmp = USB_ENDPOINT_XFER_BULK; + } else if (tmp == USB_ENDPOINT_XFER_BULK) { + /* catch some particularly blatant driver bugs */ + if ((dev->gadget.speed == USB_SPEED_HIGH + && max != 512) + || (dev->gadget.speed == USB_SPEED_FULL + && max > 64)) + return -ERANGE; } ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC) ? 1 : 0; tmp <<= ENDPOINT_TYPE; @@ -252,9 +261,6 @@ udelay (1); usec--; } while (usec > 0); -#ifdef DEBUG - if (done == 0) dump_stack (); /* ignore out_flush timeout */ -#endif return -ETIMEDOUT; } @@ -917,6 +923,8 @@ */ if (read_fifo (ep, req)) { done (ep, req, 0); + if (ep->num == 0) + allow_status (ep); /* don't queue it */ req = 0; } else @@ -1194,9 +1202,12 @@ VDEBUG (ep->dev, "%s %s halt\n", _ep->name, value ? "set" : "clear"); /* set/clear, then synch memory views with the device */ - if (value) - set_halt (ep); - else + if (value) { + if (ep->num == 0) + ep->dev->protocol_stall = 1; + else + set_halt (ep); + } else clear_halt (ep); (void) readl (&ep->regs->ep_rsp); @@ -2042,7 +2053,8 @@ * can decide to stall ep0 after that done() returns, * from non-irq context */ - allow_status (ep); + if (!ep->stopped) + allow_status (ep); req = 0; } else { if (!list_empty (&ep->queue) && !ep->stopped)