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

Commit 67bf926f authored by Thinh Nguyen's avatar Thinh Nguyen Committed by Greg Kroah-Hartman
Browse files

usb: dwc3: gadget: Refactor pullup()



[ Upstream commit 861c010a2ee1bc4a66d23f0da4aa22e75d8eaa24 ]

Move soft-disconnect sequence out of dwc3_gadget_pullup(). No
functional change here.

Signed-off-by: default avatarThinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/4c0f259b17d95acaaa931f90276683a48a32fe22.1650593829.git.Thinh.Nguyen@synopsys.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 040f2dbd2010 ("usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 24e4f630
Loading
Loading
Loading
Loading
+36 −29
Original line number Diff line number Diff line
@@ -2008,6 +2008,40 @@ static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
static void __dwc3_gadget_stop(struct dwc3 *dwc);
static int __dwc3_gadget_start(struct dwc3 *dwc);

static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc)
{
	u32 count;

	dwc->connected = false;

	/*
	 * In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a
	 * Section 4.1.8 Table 4-7, it states that for a device-initiated
	 * disconnect, the SW needs to ensure that it sends "a DEPENDXFER
	 * command for any active transfers" before clearing the RunStop
	 * bit.
	 */
	dwc3_stop_active_transfers(dwc);
	__dwc3_gadget_stop(dwc);

	/*
	 * In the Synopsys DesignWare Cores USB3 Databook Rev. 3.30a
	 * Section 1.3.4, it mentions that for the DEVCTRLHLT bit, the
	 * "software needs to acknowledge the events that are generated
	 * (by writing to GEVNTCOUNTn) while it is waiting for this bit
	 * to be set to '1'."
	 */
	count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
	count &= DWC3_GEVNTCOUNT_MASK;
	if (count > 0) {
		dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
		dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
			dwc->ev_buf->length;
	}

	return dwc3_gadget_run_stop(dwc, false, false);
}

static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
{
	struct dwc3		*dwc = gadget_to_dwc(g);
@@ -2064,33 +2098,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
	spin_lock_irqsave(&dwc->lock, flags);

	if (!is_on) {
		u32 count;

		dwc->connected = false;
		/*
		 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
		 * Section 4.1.8 Table 4-7, it states that for a device-initiated
		 * disconnect, the SW needs to ensure that it sends "a DEPENDXFER
		 * command for any active transfers" before clearing the RunStop
		 * bit.
		 */
		dwc3_stop_active_transfers(dwc);
		__dwc3_gadget_stop(dwc);

		/*
		 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
		 * Section 1.3.4, it mentions that for the DEVCTRLHLT bit, the
		 * "software needs to acknowledge the events that are generated
		 * (by writing to GEVNTCOUNTn) while it is waiting for this bit
		 * to be set to '1'."
		 */
		count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
		count &= DWC3_GEVNTCOUNT_MASK;
		if (count > 0) {
			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
			dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
						dwc->ev_buf->length;
		}
		ret = dwc3_gadget_soft_disconnect(dwc);
	} else {
		/*
		 * In the Synopsys DWC_usb31 1.90a programming guide section
@@ -2104,9 +2112,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)

		dwc3_event_buffers_setup(dwc);
		__dwc3_gadget_start(dwc);
		ret = dwc3_gadget_run_stop(dwc, true, false);
	}

	ret = dwc3_gadget_run_stop(dwc, is_on, false);
	spin_unlock_irqrestore(&dwc->lock, flags);
	enable_irq(dwc->irq_gadget);