I could imagine that "misc OHCI updates" patch of a few weeks back speeding up an OHCI implementation because it had less work to do (no periodic schedule dma), exposing such a race.
OK, see how this patch behaves for you. The "bad entry" stuff seems to have been caused by trying to have a fast-path (the same one 2.4 usb-ohci has) getting rid of a 1 msec unlink delay in some cases. It finally stopped working; I confess I've never quite trusted that shortcut!
Well, was this supposed to work with 2.6.3-bk9 or 2.6.4-rc1? At least it applied almost cleanly (probably harmless offset) and compiled.
However, things are getting really worse now, sorry.
How does this (from Ben's patch) do instead? Theory being:
HC: issue memory writes, they're in PCI buffers, raises IRQ.
HCD: receives IRQ, reads memory ... old ED and TD contents.
Sees no updates, recycles wrong TD, corrupts queue when
the writes finally arrive.Roman, I seem to recall you objecting strongly at some point to a similar change. Comments? In this case it's bad, because the HCD is about to unlink a TD.
- Dave
--- 1.56/drivers/usb/host/ohci-hcd.c Fri Feb 20 07:59:50 2004
+++ edited/drivers/usb/host/ohci-hcd.c Thu Mar 4 14:56:25 2004
@@ -571,13 +573,8 @@
struct ohci_regs *regs = ohci->regs;
int ints;
- /* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
- if ((ohci->hcca->done_head != 0)
- && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
- ints = OHCI_INTR_WDH;
-
/* cardbus/... hardware gone before remove() */
- } else if ((ints = readl (®s->intrstatus)) == ~(u32)0) {
+ if ((ints = readl (®s->intrstatus)) == ~(u32)0) {
disable (ohci);
ohci_dbg (ohci, "device removed!\n");
return IRQ_HANDLED;