diff options
author | Mayank Rana <mrana@codeaurora.org> | 2017-03-20 16:10:39 -0700 |
---|---|---|
committer | Mayank Rana <mrana@codeaurora.org> | 2017-03-31 15:22:57 -0700 |
commit | 7af71579f5fb6f5904ca65e5c49ed4779ddbe849 (patch) | |
tree | e73c10b42f9542314a99473e67d4dfe25cdd3f95 | |
parent | c451e3744b35669e8dfb5f6c98c4a91a3e604504 (diff) |
usb: dwc3: Use high priority worker as bottom half handler
Latency involved in handling dwc3 interrupt in real time threaded
interrupt is sometimes resulting into RT throttling. Hence queue
bottom half work from dwc3 hard irq handler to a high priority
workqueue. Also, update the corresponding irq flag in host
controller platform driver.
Change-Id: If65a522efb6d792eea7fa7afc4c5e4dcd1cb6fb8
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
-rw-r--r-- | drivers/usb/dwc3/core.c | 15 | ||||
-rw-r--r-- | drivers/usb/dwc3/core.h | 3 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-msm.c | 3 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 11 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci-plat.c | 4 |
6 files changed, 32 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ccc1aa8172c1..c2eba06f2ace 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1059,8 +1059,8 @@ static int dwc3_probe(struct platform_device *pdev) /* will be enabled in dwc3_msm_resume() */ irq_set_status_flags(irq, IRQ_NOAUTOEN); - ret = devm_request_threaded_irq(dev, irq, NULL, dwc3_interrupt, - IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc); + ret = devm_request_irq(dev, irq, dwc3_interrupt, IRQF_SHARED, "dwc3", + dwc); if (ret) { dev_err(dwc->dev, "failed to request irq #%d --> %d\n", irq, ret); @@ -1238,6 +1238,14 @@ static int dwc3_probe(struct platform_device *pdev) dev->dma_parms = dev->parent->dma_parms; dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); + dwc->dwc_wq = alloc_ordered_workqueue("dwc_wq", WQ_HIGHPRI); + if (!dwc->dwc_wq) { + pr_err("%s: Unable to create workqueue dwc_wq\n", __func__); + return -ENOMEM; + } + + INIT_WORK(&dwc->bh_work, dwc3_bh_work); + pm_runtime_no_callbacks(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); @@ -1303,6 +1311,7 @@ err0: * memory region the next time probe is called. */ res->start -= DWC3_GLOBALS_REGS_START; + destroy_workqueue(dwc->dwc_wq); return ret; } @@ -1332,6 +1341,8 @@ static int dwc3_remove(struct platform_device *pdev) dwc3_core_exit(dwc); dwc3_ulpi_exit(dwc); + destroy_workqueue(dwc->dwc_wq); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 7682f516c670..453eee734b23 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1022,6 +1022,9 @@ struct dwc3 { u16 imod_interval; + struct workqueue_struct *dwc_wq; + struct work_struct bh_work; + /* IRQ timing statistics */ int irq; unsigned long irq_cnt; diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 623f3ce211aa..a80fb34cdce8 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2053,6 +2053,9 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) if (dwc->irq) disable_irq(dwc->irq); + if (work_busy(&dwc->bh_work)) + dbg_event(0xFF, "pend evt", 0); + /* disable power event irq, hs and ss phy irq is used as wake up src */ disable_irq(mdwc->pwr_event_irq); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 0d6bc746c368..9608a79cbe40 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3393,6 +3393,15 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) return ret; } +void dwc3_bh_work(struct work_struct *w) +{ + struct dwc3 *dwc = container_of(w, struct dwc3, bh_work); + + pm_runtime_get_sync(dwc->dev); + dwc3_thread_interrupt(dwc->irq, dwc); + pm_runtime_put(dwc->dev); +} + static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) { struct dwc3 *dwc = _dwc; @@ -3484,7 +3493,7 @@ irqreturn_t dwc3_interrupt(int irq, void *_dwc) dwc->irq_dbg_index = (dwc->irq_dbg_index + 1) % MAX_INTR_STATS; if (ret == IRQ_WAKE_THREAD) - dwc3_thread_interrupt(dwc->irq, dwc); + queue_work(dwc->dwc_wq, &dwc->bh_work); return IRQ_HANDLED; } diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 99ff6df063a7..baa83cf9638b 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -105,6 +105,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force); irqreturn_t dwc3_interrupt(int irq, void *_dwc); +void dwc3_bh_work(struct work_struct *w); static inline dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, struct dwc3_trb *trb) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 7423645c204c..1ddf882fb607 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -245,7 +245,7 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_usb3_hcd; } - ret = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_ONESHOT); + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_usb_phy; @@ -254,7 +254,7 @@ static int xhci_plat_probe(struct platform_device *pdev) if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED | IRQF_ONESHOT); + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; |