[PATCH] USB: EHCI qh update race fix
This makes the EHCI driver stop trying to update a live QH ... it's not like OHCI, that can't be done safely because of a hardware race. The fix: - Unlinks the QH before updating it; only the tail can safely be updated "live", not the queue head. The async schedule (all control/bulk QHs) and periodic schedule (interrupt QH) work a bit differently ... high bandwidth transfers will hiccup. - Moves "update QH" and "clear toggle" logic into one new qh_refresh() routine, used in several places. The race shows readily enough under load with the right hardware. The controller silicon might be relatively slow, or maybe it's the bus that's slow/busy: Host Controller --- ---------- reads two TD pointers update two TD pointers wmb() activate QH reads rest of QH Net result is that the HC treated old TD pointers as valid, and things started misbehaving. Busy controllers would misbehave worse; some systems wouldn't notice more than a slowdown, especially with light USB loads. This affects behavior in two cases. The uncommon one is when an endpoint gets an error and halts. The more common one happens when the controller runs off the end of its queue and overlays an inactive "dummy" TD into the QH ... something the spec says shouldn't happen, but which more silicon seems to be doing. (Presumably to reduce DMA chatter.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Showing
Please register or sign in to comment