From 6b0add375667640ad564308c3de9ed13c2ae29de Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Sat, 12 May 2018 23:15:11 +0800 Subject: [PATCH 1/3] don't thread the shared irqs We have not to thread the irqs shared between SPI and UART for the moment in the case of -rt. But ideally, we should refactor that as a hreaded handler. Signed-off-by: Tiejun Chen --- drivers/spi/spi-bcm2835aux.c | 4 ++++ drivers/tty/serial/8250/8250_bcm2835aux.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 3094d818cf06d4..4c18df321c828c 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -489,7 +489,11 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, bs->irq, bcm2835aux_spi_interrupt, +#ifdef CONFIG_PREEMPT_RT_FULL + IRQF_SHARED | IRQF_NO_THREAD, +#else IRQF_SHARED, +#endif dev_name(&pdev->dev), master); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index aa7e7eb3019bb0..3b41e079a9bca6 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -63,6 +63,10 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) } data->uart.port.irq = ret; +#ifdef CONFIG_PREEMPT_RT_FULL + data->uart.port.irqflags = IRQF_NO_THREAD; +#endif + /* map the main registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { From fea9fa90703058d8667bdf00e814b10012c31e49 Mon Sep 17 00:00:00 2001 From: paul-1 <6473457+paul-1@users.noreply.github.com> Date: Sun, 11 Feb 2018 15:24:11 -0500 Subject: [PATCH 2/3] usb: dwc_otg: fix system lockup when interrupts are threaded Fix lockup in dwc_otg driver that leads to a system freeze of the 4-core Raspberry Pi board when RT Preempt kernel is in use or when interrupts are threaded in general. The lockup occurs when the irq handler thread gets preempted while it holds the fiq spin lock. The patch makes sure to disable local irq while fiq spin lock is held irrespective of whether the interrupt is threaded or not. The patch also unifies the use of the fiq spin lock outside the fiq handler by introducing two function-like macros fiq_fsm_spin_lock_irqsave and fiq_fsm_spin_unlock_irqrestore. Under RT kernel, the bug can be reproduced in a few minutes by running hackbench and cyclictest in this way $ ( while true; do nice hackbench 30 >/dev/null; done )& $ echo "run 'kill $!' to stop hackbench" $ cyclictest -a -t -n -p 80 Signed-off-by: Oussama Ghorbel --- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 14 +++++++ drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 41 ++++++++------------ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 39 +++++++------------ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 14 +++---- 4 files changed, 52 insertions(+), 56 deletions(-) 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 f517371421884f..447e1ec470990e 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h +++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h @@ -394,4 +394,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(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(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 cdfb9a6b7c5972..a1af3d2bac7664 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c @@ -1,4 +1,3 @@ - /* ========================================================================== * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ * $Revision: #104 $ @@ -1413,12 +1412,11 @@ 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); @@ -1428,12 +1426,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; } @@ -1654,6 +1650,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; @@ -1729,8 +1726,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); @@ -1750,8 +1746,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; } @@ -1777,6 +1772,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. @@ -1897,8 +1893,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); @@ -2007,8 +2002,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; } @@ -2489,6 +2483,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 @@ -2514,11 +2509,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..3d4fdf960cec30 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,7 @@ 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 +1078,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 +1101,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 2823dc9af63f1f..d3c1d86a2ddc8e 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c @@ -675,6 +675,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)) { @@ -693,11 +694,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); } @@ -741,6 +740,7 @@ 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)) { @@ -762,11 +762,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); } From 02586ccd069c7f0e7be7be4610a1207295ca9bc5 Mon Sep 17 00:00:00 2001 From: paul-1 Date: Tue, 18 Jun 2019 23:20:21 -0400 Subject: [PATCH 3/3] dwc_otg: Addition lock for the rt kernels Signed-off-by: paul-1 --- drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c index 799ab14b9edadd..ee71a00f33195f 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c @@ -1322,6 +1322,7 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) */ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk, dwc_otg_hcd_t *hcd) { + unsigned long flags; gahbcfg_data_t gahbcfg = {.d32 = 0 }; gintsts_data_t gintsts; gintmsk_data_t gintmsk; @@ -1337,6 +1338,7 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gin gintmsk_common.b.lpmtranrcvd = 1; #endif gintmsk_common.b.restoredone = 1; + if(dwc_otg_is_device_mode(core_if)) { /** @todo: The port interrupt occurs while in device @@ -1345,8 +1347,7 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gin gintmsk_common.b.portintr = 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); gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); /* Pull in the interrupts that the FIQ has masked */ @@ -1354,8 +1355,7 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gin 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; - fiq_fsm_spin_unlock(&hcd->fiq_state->lock); - local_fiq_enable(); + fiq_fsm_spin_unlock_irqrestore(&hcd->fiq_state->lock, flags); } else { gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);