Skip to content

Commit bb003a1

Browse files
P33Mpopcornmix
P33M
authored andcommitted
dwc_otg: fix locking around dequeueing and killing URBs
kill_urbs_in_qh_list() is practically only ever called with the fiq lock already held, so don't spinlock twice in the case where we need to cancel an isochronous transfer. Also fix up a case where the global interrupt register could be read with the fiq lock not held. Fixes the deadlock seen in #2907
1 parent 89dbc88 commit bb003a1

File tree

2 files changed

+7
-6
lines changed

2 files changed

+7
-6
lines changed

drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,16 +1344,21 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gin
13441344
*/
13451345
gintmsk_common.b.portintr = 1;
13461346
}
1347-
gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
1348-
gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
13491347
if(fiq_enable) {
13501348
local_fiq_disable();
1349+
fiq_fsm_spin_lock(&hcd->fiq_state->lock);
1350+
gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
1351+
gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
13511352
/* Pull in the interrupts that the FIQ has masked */
13521353
gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
13531354
gintmsk.d32 |= gintmsk_common.d32;
13541355
/* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
13551356
reenable_gintmsk->d32 = gintmsk.d32;
1357+
fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
13561358
local_fiq_enable();
1359+
} else {
1360+
gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
1361+
gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
13571362
}
13581363

13591364
gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);

drivers/usb/host/dwc_otg/dwc_otg_hcd.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,11 @@ static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
195195
* but not yet been through the IRQ handler.
196196
*/
197197
if (fiq_fsm_enable && (hcd->fiq_state->channel[qh->channel->hc_num].fsm != FIQ_PASSTHROUGH)) {
198-
local_fiq_disable();
199-
fiq_fsm_spin_lock(&hcd->fiq_state->lock);
200198
qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
201199
qh->channel->halt_pending = 1;
202200
if (hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_TURBO ||
203201
hcd->fiq_state->channel[n].fsm == FIQ_HS_ISOC_SLEEPING)
204202
hcd->fiq_state->channel[n].fsm = FIQ_HS_ISOC_ABORTED;
205-
fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
206-
local_fiq_enable();
207203
} else {
208204
dwc_otg_hc_halt(hcd->core_if, qh->channel,
209205
DWC_OTG_HC_XFER_URB_DEQUEUE);

0 commit comments

Comments
 (0)