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

Commit 25d24cdc authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Offload IRQ handling to softirq context"

parents 1d245aea 75c1d2a1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -819,6 +819,7 @@ struct dwc3_scratchpad_array {
 * @in_lpm: if 1, indicates that the controller is in low power mode (no clocks)
 * @tx_fifo_size: Available RAM size for TX fifo allocation
 * @irq: irq number
 * @bh: tasklet which handles the interrupt
 * @irq_cnt: total irq count
 * @bh_completion_time: time taken for taklet completion
 * @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt
@@ -964,6 +965,7 @@ struct dwc3 {

	/* IRQ timing statistics */
	int			irq;
	struct tasklet_struct	bh;
	unsigned long		irq_cnt;
	unsigned                bh_completion_time[MAX_INTR_STATS];
	unsigned                bh_handled_evt_cnt[MAX_INTR_STATS];
+23 −6
Original line number Diff line number Diff line
@@ -2161,8 +2161,8 @@ static int dwc3_gadget_start(struct usb_gadget *g,
	int			irq;

	irq = platform_get_irq(to_platform_device(dwc->dev), 0);
	ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
			IRQF_SHARED, "dwc3", dwc);
	dwc->irq = irq;
	ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, "dwc3", dwc);
	if (ret) {
		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
				irq, ret);
@@ -2207,9 +2207,12 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
	unsigned long		flags;
	int			irq;

	dwc3_gadget_disable_irq(dwc);

	tasklet_kill(&dwc->bh);

	spin_lock_irqsave(&dwc->lock, flags);

	dwc3_gadget_disable_irq(dwc);
	__dwc3_gadget_ep_disable(dwc->eps[0]);
	__dwc3_gadget_ep_disable(dwc->eps[1]);

@@ -3448,6 +3451,15 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
	return ret;
}

static void dwc3_interrupt_bh(unsigned long param)
{
	struct dwc3 *dwc = (struct dwc3 *) param;

	pm_runtime_get(dwc->dev);
	dwc3_thread_interrupt(dwc->irq, dwc);
	enable_irq(dwc->irq);
}

static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
{
	struct dwc3 *dwc = _dwc;
@@ -3541,10 +3553,12 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
	dwc->irq_event_count[dwc->irq_dbg_index] = temp_cnt / 4;
	dwc->irq_dbg_index = (dwc->irq_dbg_index + 1) % MAX_INTR_STATS;

	if (ret == IRQ_WAKE_THREAD)
		pm_runtime_get(dwc->dev);
	if (ret == IRQ_WAKE_THREAD) {
		disable_irq_nosync(irq);
		tasklet_schedule(&dwc->bh);
	}

	return ret;
	return IRQ_HANDLED;
}

/**
@@ -3590,6 +3604,9 @@ int dwc3_gadget_init(struct dwc3 *dwc)
		goto err3;
	}

	dwc->bh.func = dwc3_interrupt_bh;
	dwc->bh.data = (unsigned long)dwc;

	dwc->gadget.ops			= &dwc3_gadget_ops;
	dwc->gadget.max_speed		= USB_SPEED_SUPER;
	dwc->gadget.speed		= USB_SPEED_UNKNOWN;