diff options
Diffstat (limited to 'target/linux/brcm2708/patches-3.10/0079-dwc_otg-fiq-prevent-FIQ-thrash-and-incorrect-state-p.patch')
-rw-r--r-- | target/linux/brcm2708/patches-3.10/0079-dwc_otg-fiq-prevent-FIQ-thrash-and-incorrect-state-p.patch | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.10/0079-dwc_otg-fiq-prevent-FIQ-thrash-and-incorrect-state-p.patch b/target/linux/brcm2708/patches-3.10/0079-dwc_otg-fiq-prevent-FIQ-thrash-and-incorrect-state-p.patch new file mode 100644 index 0000000000..f8e7378b74 --- /dev/null +++ b/target/linux/brcm2708/patches-3.10/0079-dwc_otg-fiq-prevent-FIQ-thrash-and-incorrect-state-p.patch @@ -0,0 +1,54 @@ +From 4d44d8447b13ded9c6931583938183c76b1846ed Mon Sep 17 00:00:00 2001 +From: P33M <P33M@github.com> +Date: Sat, 13 Jul 2013 21:48:41 +0100 +Subject: [PATCH 079/174] dwc_otg: fiq: prevent FIQ thrash and incorrect state + passing to IRQ + +In the case of a transaction to a device that had previously aborted +due to an error, several interrupts are enabled to reset the error +count when a device responds. This has the side-effect of making the +FIQ thrash because the hardware will generate multiple instances of +a NAK on an IN bulk/interrupt endpoint and multiple instances of ACK +on an OUT bulk/interrupt endpoint. Make the FIQ mask and clear the +associated interrupts. + +Additionally, on non-split transactions make sure that only unmasked +interrupts are cleared. This caused a hard-to-trigger but serious +race condition when you had the combination of an endpoint awaiting +error recovery and a transaction completed on an endpoint - due to +the sequencing and timing of interrupts generated by the dwc_otg core, +it was possible to confuse the IRQ handler. +--- + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -324,6 +324,27 @@ int fiq_hcintr_handle(int channel, hfnum + } + } + } ++ else ++ { ++ /* ++ * If we have any of NAK, ACK, Datatlgerr active on a ++ * non-split channel, the sole reason is to reset error ++ * counts for a previously broken transaction. The FIQ ++ * will thrash on NAK IN and ACK OUT in particular so ++ * handle it "once" and allow the IRQ to do the rest. ++ */ ++ hcint.d32 &= hcintmsk.d32; ++ if(hcint.b.nak) ++ { ++ hcintmsk.b.nak = 0; ++ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32); ++ } ++ if (hcint.b.ack) ++ { ++ hcintmsk.b.ack = 0; ++ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32); ++ } ++ } + + // Clear the interrupt, this will also clear the HAINT bit + FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32); |