Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f616a7fc authored by Mayank Rana's avatar Mayank Rana
Browse files

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: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 7ecdb05f
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -1173,8 +1173,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);
@@ -1314,6 +1314,14 @@ static int dwc3_probe(struct platform_device *pdev)

	spin_lock_init(&dwc->lock);

	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);
@@ -1385,6 +1393,7 @@ static int dwc3_probe(struct platform_device *pdev)
	 * memory region the next time probe is called.
	 */
	res->start -= DWC3_GLOBALS_REGS_START;
	destroy_workqueue(dwc->dwc_wq);

	return ret;
}
@@ -1408,6 +1417,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_allow(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
+3 −0
Original line number Diff line number Diff line
@@ -1121,6 +1121,9 @@ struct dwc3 {

	u16			imod_interval;

	struct workqueue_struct	*dwc_wq;
	struct work_struct	bh_work;

	/* IRQ timing statistics */
	int			irq;
	unsigned long		ep_cmd_timeout_cnt;
+3 −0
Original line number Diff line number Diff line
@@ -2045,6 +2045,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);

+10 −1
Original line number Diff line number Diff line
@@ -3504,6 +3504,15 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc)
	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;
@@ -3588,7 +3597,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;
}
+1 −0
Original line number Diff line number Diff line
@@ -97,6 +97,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)
Loading