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

Commit c8ba6a8b authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3: Disable ep0 and interrupts when clearing run/stop



In dwc3_gadget_run_stop() when clearing the run/stop bit, ensure
that IRQs are masked and the ep0 in and out endpoints are disabled.
In case pullups are removed while a control transfer is in progress,
this makes sure that the control endpoints are properly cleaned up.
If and when run/stop is set again, the function already re-enables
the IRQ and ep0 when calling dwc3_gadget_restart(). While at it,
memset() the event buffers to clear stale contents when
reinitializing them in dwc3_event_buffers_setup().

Also, since calling dwc3_gadget_disable_irq() only masks the
interrupts at the controller layer, it might not catch instances
where an IRQ itself may have already been asserted but does not
arrive at the handler until after the pullups are removed. Add a
check to dwc3_interrupt() to catch this case as well.

Change-Id: Ie58979fe4b229240231760652189338ec5343a2d
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 8ca03863
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -335,6 +335,8 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)
				evt->buf, (unsigned long long) evt->dma,
				evt->length);

		memset(evt->buf, 0, evt->length);

		evt->lpos = 0;

		dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n),
+10 −0
Original line number Diff line number Diff line
@@ -1875,6 +1875,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)

		dwc->pullups_connected = true;
	} else {
		dwc3_gadget_disable_irq(dwc);
		__dwc3_gadget_ep_disable(dwc->eps[0]);
		__dwc3_gadget_ep_disable(dwc->eps[1]);

		reg &= ~DWC3_DCTL_RUN_STOP;

		if (dwc->has_hibernation && !suspend)
@@ -3509,6 +3513,12 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
		temp_cnt += dwc->ev_buffs[i]->count;
	}

	/* If run/stop is cleared don't process any more events */
	if (!dwc->pullups_connected) {
		dev_warn(dwc->dev, "IRQ received but run/stop is cleared\n");
		ret = IRQ_HANDLED;
	}

	spin_unlock(&dwc->lock);

	dwc->irq_start_time[dwc->irq_dbg_index] = start_time;