diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h index ed088f34f210e9..081ee6a63cf72f 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h @@ -393,4 +393,18 @@ extern void dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels); extern void dwc_otg_fiq_nop(struct fiq_state *state); +#define fiq_fsm_spin_lock_irqsave(lock, flags) \ + do { \ + local_fiq_disable(); \ + local_irq_save_nort(flags); \ + fiq_fsm_spin_lock(lock); \ + } while (0) + +#define fiq_fsm_spin_unlock_irqrestore(lock, flags) \ + do { \ + fiq_fsm_spin_unlock(lock); \ + local_irq_restore_nort(flags); \ + local_fiq_enable(); \ + } while (0) + #endif /* DWC_OTG_FIQ_FSM_H_ */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c index e59747cee7ab9f..67931a8c649a60 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c @@ -1414,12 +1414,10 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) dwc_otg_hc_init(hcd->core_if, hc); - local_irq_save(flags); - - if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); - } + if (fiq_enable) + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); + else + local_irq_save(flags); /* Enable the top level host channel interrupt. */ intr_enable = (1 << hc->hc_num); @@ -1429,12 +1427,10 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) gintmsk.b.hcintr = 1; DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32); - if (fiq_enable) { - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); - } - - local_irq_restore(flags); + if (fiq_enable) + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); + else + local_irq_restore(flags); hc->qh = qh; } @@ -1646,6 +1642,7 @@ int fiq_fsm_queue_isoc_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) int xfer_len, nrpackets; hcdma_data_t hcdma; hfnum_data_t hfnum; + unsigned long flags; if (st->fsm != FIQ_PASSTHROUGH) return 0; @@ -1721,8 +1718,7 @@ int fiq_fsm_queue_isoc_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32); fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32); hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32); DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32); DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32); @@ -1742,8 +1738,7 @@ int fiq_fsm_queue_isoc_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) } mb(); st->hcchar_copy.b.chen = 0; - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); return 0; } @@ -1769,6 +1764,7 @@ int fiq_fsm_queue_split_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) /* Program HC registers, setup FIQ_state, examine FIQ if periodic, start transfer (not if uframe 5) */ int hub_addr, port_addr, frame, uframe; struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num]; + unsigned long flags; /* * Non-periodic channel assignments stay in the non_periodic_active queue. @@ -1889,8 +1885,7 @@ int fiq_fsm_queue_split_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32); DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32); - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); if (hc->ep_type & 0x1) { hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); @@ -1999,8 +1994,7 @@ int fiq_fsm_queue_split_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh) DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32); } mb(); - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); return 0; } @@ -2481,6 +2475,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, dwc_otg_transaction_type_e tr_type) { + unsigned long flags; #ifdef DEBUG_SOF DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); #endif @@ -2506,11 +2501,9 @@ void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, gintmsk.b.nptxfempty = 1; if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0); - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); } else { DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, gintmsk.d32, 0); } 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 6947e98b87adb6..88f3e265ca0a5e 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c @@ -83,6 +83,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) gintmsk_data_t gintmsk; hfnum_data_t hfnum; haintmsk_data_t haintmsk; + unsigned long flags; #ifdef DEBUG dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; @@ -100,8 +101,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) /* Check if HOST Mode */ if (dwc_otg_is_host_mode(core_if)) { if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&dwc_otg_hcd->fiq_state->lock, flags); /* Pull in from the FIQ's disabled mask */ gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32); dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0; @@ -118,8 +118,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) gintsts.d32 &= gintmsk.d32; if (fiq_enable) { - fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&dwc_otg_hcd->fiq_state->lock, flags); } if (!gintsts.d32) { @@ -166,11 +165,9 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) gintmsk_data_t gintmsk = { .b.portintr = 1}; retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&dwc_otg_hcd->fiq_state->lock, flags); DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32); - fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&dwc_otg_hcd->fiq_state->lock, flags); } else { DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32); } @@ -210,8 +207,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) if (fiq_enable) { gintmsk_data_t gintmsk_new; haintmsk_data_t haintmsk_new; - local_fiq_disable(); - fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&dwc_otg_hcd->fiq_state->lock, flags); gintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->gintmsk_saved.d32; if(fiq_fsm_enable) haintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->haintmsk_saved.d32; @@ -234,8 +230,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); /* Re-enable interrupts that the FIQ masked (first time round) */ FIQ_WRITE(dwc_otg_hcd->fiq_state->dwc_regs_base + GINTMSK, gintmsk.d32); - fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&dwc_otg_hcd->fiq_state->lock, flags); if ((jiffies / HZ) > last_time) { //dwc_otg_qh_t *qh; @@ -637,6 +632,7 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) { int i; int retval = 0; + unsigned long flags; haint_data_t haint = { .d32 = 0 } ; /* Clear appropriate bits in HCINTn to clear the interrupt bit in @@ -649,12 +645,10 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) if(fiq_fsm_enable) { /* check the mask? */ - local_fiq_disable(); - fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&dwc_otg_hcd->fiq_state->lock, flags); haint.b2.chint |= ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint); dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint = ~0; - fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&dwc_otg_hcd->fiq_state->lock, flags); } for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { @@ -1061,6 +1055,8 @@ static void halt_channel(dwc_otg_hcd_t * hcd, dwc_hc_t * hc, dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) { + unsigned long flags; + if (hcd->core_if->dma_enable) { release_channel(hcd, hc, qtd, halt_status); return; @@ -1083,11 +1079,9 @@ static void halt_channel(dwc_otg_hcd_t * hcd, */ gintmsk.b.nptxfempty = 1; if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); } else { DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); } @@ -1108,11 +1102,9 @@ static void halt_channel(dwc_otg_hcd_t * hcd, */ gintmsk.b.ptxfempty = 1; if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); } else { DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); } diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c index fe8e8f841f0366..37f1c50d29dfd6 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c @@ -676,6 +676,7 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) { int status = 0; + unsigned long flags; gintmsk_data_t intr_mask = {.d32 = 0 }; if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { @@ -694,11 +695,9 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) if ( !hcd->periodic_qh_count ) { intr_mask.b.sofintr = 1; if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, intr_mask.d32); - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); } else { DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, intr_mask.d32); } @@ -742,6 +741,8 @@ static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) * @param qh QH to remove from schedule. */ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) { + unsigned long flags; + gintmsk_data_t intr_mask = {.d32 = 0 }; if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { @@ -763,11 +764,9 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) if( !hcd->periodic_qh_count && !fiq_fsm_enable ) { intr_mask.b.sofintr = 1; if (fiq_enable) { - local_fiq_disable(); - fiq_fsm_spin_lock(&hcd->fiq_state->lock); + fiq_fsm_spin_lock_irqsave(&hcd->fiq_state->lock, flags); DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, 0); - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); } else { DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, intr_mask.d32, 0); }