openwrtv3/target/linux/brcm2708/patches-3.10/0078-dwc_otg-mask-correct-interrupts-after-transaction-er.patch

70 lines
2.5 KiB
Diff
Raw Normal View History

From 5608eaff0f301e9bf73998da020644f1673b66e4 Mon Sep 17 00:00:00 2001
From: P33M <P33M@github.com>
Date: Sat, 13 Jul 2013 20:41:26 +0100
Subject: [PATCH 078/196] dwc_otg: mask correct interrupts after transaction
error recovery
The dwc_otg driver will unmask certain interrupts on a transaction
that previously halted in the error state in order to reset the
QTD error count. The various fine-grained interrupt handlers do not
consider that other interrupts besides themselves were unmasked.
By disabling the two other interrupts only ever enabled in DMA mode
for this purpose, we can avoid unnecessary function calls in the
IRQ handler. This will also prevent an unneccesary FIQ interrupt
from being generated if the FIQ is enabled.
---
drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
index e8b4d35..27b673f 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
@@ -1851,7 +1851,11 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
* transfers in DMA mode for the sole purpose of
* resetting the error count after a transaction error
* occurs. The core will continue transferring data.
+ * Disable other interrupts unmasked for the same
+ * reason.
*/
+ disable_hc_int(hc_regs, datatglerr);
+ disable_hc_int(hc_regs, ack);
qtd->error_count = 0;
goto handle_nak_done;
}
@@ -1963,6 +1967,15 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
}
} else {
+ /*
+ * An unmasked ACK on a non-split DMA transaction is
+ * for the sole purpose of resetting error counts. Disable other
+ * interrupts unmasked for the same reason.
+ */
+ if(hcd->core_if->dma_enable) {
+ disable_hc_int(hc_regs, datatglerr);
+ disable_hc_int(hc_regs, nak);
+ }
qtd->error_count = 0;
if (hc->qh->ping_state) {
@@ -2328,6 +2341,14 @@ static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
} else if (hc->ep_is_in) {
+ /* An unmasked data toggle error on a non-split DMA transaction is
+ * for the sole purpose of resetting error counts. Disable other
+ * interrupts unmasked for the same reason.
+ */
+ if(hcd->core_if->dma_enable) {
+ disable_hc_int(hc_regs, ack);
+ disable_hc_int(hc_regs, nak);
+ }
qtd->error_count = 0;
}
--
1.9.1