1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
From 8eb79690a70cce34e9a1c35cf165716f78301d2e Mon Sep 17 00:00:00 2001
From: P33M <P33M@github.com>
Date: Fri, 20 Jun 2014 16:03:12 +0100
Subject: [PATCH 045/114] dwc_otg: Fix various issues with root port and
transaction errors
Process the host port interrupts correctly (and don't trample them).
Root port hotplug now functional again.
Fix a few thinkos with the transaction error passthrough for fiq_fsm.
---
drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 7 +++----
drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 6 +++++-
drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 +-
3 files changed, 9 insertions(+), 6 deletions(-)
--- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
@@ -1348,10 +1348,9 @@ static inline uint32_t dwc_otg_read_comm
local_fiq_disable();
/* Pull in the interrupts that the FIQ has masked */
gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
+ gintmsk.d32 |= gintmsk_common.d32;
/* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
- reenable_gintmsk->d32 |= gintmsk.d32;
- reenable_gintmsk->d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
- reenable_gintmsk->d32 &= gintmsk_common.d32;
+ reenable_gintmsk->d32 = gintmsk.d32;
local_fiq_enable();
}
@@ -1535,7 +1534,7 @@ int32_t dwc_otg_handle_common_intr(void
// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "CILOUT %1d", retval);
// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "%08x", gintsts.d32);
// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "%08x", gintmsk_reenable.d32);
- if (retval) {
+ if (retval && fiq_enable) {
DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_reenable.d32);
}
--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
@@ -696,7 +696,11 @@ static int notrace noinline fiq_fsm_do_h
fiq_print(FIQDBG_ERR, state, "ERRST %02d", n);
if (hcint_probe.b.nak || hcint_probe.b.ack || hcint_probe.b.datatglerr) {
fiq_print(FIQDBG_ERR, state, "RESET %02d", n);
- st->nr_errors = 0;
+ /* In some random cases we can get a NAK interrupt coincident with a Xacterr
+ * interrupt, after the device has disappeared.
+ */
+ if (!hcint.b.xacterr)
+ st->nr_errors = 0;
hcintmsk.b.nak = 0;
hcintmsk.b.ack = 0;
hcintmsk.b.datatglerr = 0;
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
@@ -2619,7 +2619,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc
case FIQ_PASSTHROUGH_ERRORSTATE:
/* Hook into the error count */
fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "HCDERR%02d", num);
- if (dwc_otg_hcd->fiq_state->channel[num].nr_errors) {
+ if (!dwc_otg_hcd->fiq_state->channel[num].nr_errors) {
qtd->error_count = 0;
fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "RESET ");
}
|