Hi Sergei, > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c > index 84c1897..83f1f50 100644 > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -1511,12 +1511,14 @@ static void choose_address(struct usb_device *udev) > * bus->devnum_next. */ > devnum = find_next_zero_bit(bus->devmap.devicemap, 128, > bus->devnum_next); > - if (devnum >= 128) > + /* Due to Hardware bugs we need to reserve a device address > + * for flushing of endpoints. */ > + if (devnum >= 127) > devnum = find_next_zero_bit(bus->devmap.devicemap, > 128, 1); > - bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); > + bus->devnum_next = devnum >= 126 ? 1 : devnum + 1; > } > - if (devnum < 128) { > + if (devnum < 127) { Oh, horror... Should be technically Ok. > diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c > index 877d20b..b14a5ff 100644 > --- a/drivers/usb/musb/musb_host.c > +++ b/drivers/usb/musb/musb_host.c > @@ -106,24 +106,41 @@ static void musb_ep_program(struct musb *musb, u8 epnum, > static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) > { > void __iomem *epio = ep->regs; > + void __iomem *regs = ep->musb->mregs; > u16 csr; > - u16 lastcsr = 0; > - int retries = 1000; > + u8 addr; > + int retries = 3000; /* 3ms */ > > + /* > + * NOTE: We are using a hack here because the FIFO-FLUSH > + * bit is broken in hardware! The hack consists of changing Broken on which version of MUSB core? All, I guess. > + * the TXFUNCADDR to an unused device address and waiting > + * for any pending USB packets to hit the 3-strikes and your s/your/you're/ Ok. > + * gone rule. > + */ > + addr = musb_readb(regs, MUSB_BUSCTL_OFFSET(ep->epnum, MUSB_TXFUNCADDR)); > csr = musb_readw(epio, MUSB_TXCSR); > while (csr & MUSB_TXCSR_FIFONOTEMPTY) { Besides, flushing is only documented to work when there's a full packet in FIFO, so this condition should probably change... If you read on, you will see that on errors the TX FIFO will get flushed too. > - if (csr != lastcsr) > - DBG(3, "Host TX FIFONOTEMPTY csr: %02x\n", csr); > - lastcsr = csr; > - csr |= MUSB_TXCSR_FLUSHFIFO; > - musb_writew(epio, MUSB_TXCSR, csr); > + musb_writeb(regs, MUSB_BUSCTL_OFFSET(ep->epnum, > + MUSB_TXFUNCADDR), 127); There's special macro for that write, musb_write_txfunaddr(). Ok. > csr = musb_readw(epio, MUSB_TXCSR); > - if (WARN(retries-- < 1, > - "Could not flush host TX%d fifo: csr: %04x\n", > - ep->epnum, csr)) > - return; > - mdelay(1); > + retries--; > + if (retries == 0) { > + /* can happen if the USB clocks are OFF */ So what? Why you changed WARN() to DBG()? We can get a timeout in this loop during USB cable unplug, because then then the chip's clock is no longer running, and there is no response to any FIFO commands. This is not a serious problem so the WARN() was changed into DBG(). > + DBG(3, "Could not flush host TX%d " > + "fifo: csr=0x%04x\n", ep->epnum, csr); > + break; > + } > + udelay(1); > } > + /* clear any errors */ > + csr &= ~(MUSB_TXCSR_H_ERROR > + | MUSB_TXCSR_H_RXSTALL > + | MUSB_TXCSR_H_NAKTIMEOUT); > + musb_writew(epio, MUSB_TXCSR, csr); Why? Because when the 3-strikes and you're gone activates it will cause some error bits to be set which we should not report in the next TX transfer on the given FIFO. > @@ -1141,7 +1158,9 @@ void musb_host_tx(struct musb *musb, u8 epnum) > DBG(3, "TX 3strikes on ep=%d\n", epnum); > > status = -ETIMEDOUT; > - > + } else if (tx_csr & MUSB_TXCSR_TXPKTRDY) { > + /* BUSY - can happen during USB transfer cancel */ > + return; Is this change somehow releated to yor proposed workaround? No. This is a different issue, which actually causes data loss during stress tests. --HPS @ STE -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html