1 From a05cd269cbf2623efe2499459efdd123ee04ab81 Mon Sep 17 00:00:00 2001
2 From: P33M <P33M@github.com>
3 Date: Wed, 4 Feb 2015 12:16:50 +0000
4 Subject: [PATCH 105/114] dwc_otg: fixup read-modify-write in critical paths
6 Be more careful about read-modify-write on registers that the FIQ
9 drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 13 +++++++++---
10 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 30 +++++++++++++++++++++++++---
11 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 22 ++++++++++++++++----
12 3 files changed, 55 insertions(+), 10 deletions(-)
14 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
15 index ac70f1d..1782d65 100644
16 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
17 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
18 @@ -2447,9 +2447,16 @@ void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd,
20 gintmsk_data_t gintmsk = {.d32 = 0 };
21 gintmsk.b.nptxfempty = 1;
22 - DWC_MODIFY_REG32(&hcd->core_if->
23 - core_global_regs->gintmsk, gintmsk.d32,
27 + local_fiq_disable();
28 + fiq_fsm_spin_lock(&hcd->fiq_state->lock);
29 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
30 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
33 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0);
38 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
39 index ee35196..6266661 100644
40 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
41 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
42 @@ -165,7 +165,15 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
44 gintmsk_data_t gintmsk = { .b.portintr = 1};
45 retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
46 - DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
48 + local_fiq_disable();
49 + fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
50 + DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
51 + fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
54 + DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
57 if (gintsts.b.hcintr) {
58 retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
59 @@ -1069,7 +1077,15 @@ static void halt_channel(dwc_otg_hcd_t * hcd,
62 gintmsk.b.nptxfempty = 1;
63 - DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
65 + local_fiq_disable();
66 + fiq_fsm_spin_lock(&hcd->fiq_state->lock);
67 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
68 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
71 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
75 * Move the QH from the periodic queued schedule to
76 @@ -1086,7 +1102,15 @@ static void halt_channel(dwc_otg_hcd_t * hcd,
79 gintmsk.b.ptxfempty = 1;
80 - DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
82 + local_fiq_disable();
83 + fiq_fsm_spin_lock(&hcd->fiq_state->lock);
84 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
85 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
88 + DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
93 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
94 index 17d3030..acd0dd7 100644
95 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
96 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
97 @@ -683,8 +683,15 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
98 status = schedule_periodic(hcd, qh);
99 if ( !hcd->periodic_qh_count ) {
100 intr_mask.b.sofintr = 1;
101 - DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
102 - intr_mask.d32, intr_mask.d32);
104 + local_fiq_disable();
105 + fiq_fsm_spin_lock(&hcd->fiq_state->lock);
106 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
107 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
108 + local_fiq_enable();
110 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
113 hcd->periodic_qh_count++;
115 @@ -745,8 +752,15 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh)
116 hcd->periodic_qh_count--;
117 if( !hcd->periodic_qh_count && !fiq_fsm_enable ) {
118 intr_mask.b.sofintr = 1;
119 - DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
122 + local_fiq_disable();
123 + fiq_fsm_spin_lock(&hcd->fiq_state->lock);
124 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, 0);
125 + fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
126 + local_fiq_enable();
128 + DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, 0);