Linux kernel -stable discussions
 help / color / mirror / Atom feed
* [PATCH] usb: dwc3: Fix latency of DSTS while receiving wakeup event
@ 2024-07-30 12:47 Prashanth K
  2024-08-06 23:51 ` Thinh Nguyen
  0 siblings, 1 reply; 7+ messages in thread
From: Prashanth K @ 2024-07-30 12:47 UTC (permalink / raw)
  To: Thinh Nguyen, Greg Kroah-Hartman
  Cc: linux-kernel, linux-usb, Prashanth K, stable

When operating in High-Speed, it is observed that DSTS[USBLNKST] doesn't
update link state immediately after receiving the wakeup interrupt. Since
wakeup event handler calls the resume callbacks, there is a chance that
function drivers can perform an ep queue. Which in turn tries to perform
remote wakeup from send_gadget_ep_cmd(), this happens because DSTS[[21:18]
wasn't updated to U0 yet. It is observed that the latency of DSTS can be
in order of milli-seconds. Hence update the dwc->link_state from evtinfo,
and use this variable to prevent calling remote wakup unnecessarily.

Fixes: ecba9bc9946b ("usb: dwc3: gadget: Check for L1/L2/U3 for Start Transfer")
Cc: <stable@vger.kernel.org>
Signed-off-by: Prashanth K <quic_prashk@quicinc.com>
---
 drivers/usb/dwc3/gadget.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 89fc690fdf34..3b55285118b0 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -328,7 +328,8 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
 	}
 
 	if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
-		int link_state;
+		int	link_state;
+		bool	remote_wakeup = false;
 
 		/*
 		 * Initiate remote wakeup if the link state is in U3 when
@@ -339,15 +340,26 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
 		link_state = dwc3_gadget_get_link_state(dwc);
 		switch (link_state) {
 		case DWC3_LINK_STATE_U2:
-			if (dwc->gadget->speed >= USB_SPEED_SUPER)
+			if (dwc->gadget->speed < USB_SPEED_SUPER)
+				remote_wakeup = true;
+			break;
+		case DWC3_LINK_STATE_U3:
+			/*
+			 * In HS, DSTS can take few milliseconds to update linkstate bits,
+			 * so rely on dwc->link_state to identify whether gadget woke up.
+			 * Don't issue remote wakuep again if link is already in U0.
+			 */
+			if (dwc->link_state == DWC3_LINK_STATE_U0)
 				break;
 
-			fallthrough;
-		case DWC3_LINK_STATE_U3:
+			remote_wakeup = true;
+			break;
+		}
+
+		if (remote_wakeup) {
 			ret = __dwc3_gadget_wakeup(dwc, false);
 			dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
 					ret);
-			break;
 		}
 	}
 
@@ -4214,6 +4226,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, unsigned int evtinfo)
 {
 	dwc->suspended = false;
+	dwc->link_state = evtinfo & DWC3_LINK_STATE_MASK;
 
 	/*
 	 * TODO take core out of low power mode when that's
@@ -4225,8 +4238,6 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, unsigned int evtinfo)
 		dwc->gadget_driver->resume(dwc->gadget);
 		spin_lock(&dwc->lock);
 	}
-
-	dwc->link_state = evtinfo & DWC3_LINK_STATE_MASK;
 }
 
 static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-08-14  4:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-30 12:47 [PATCH] usb: dwc3: Fix latency of DSTS while receiving wakeup event Prashanth K
2024-08-06 23:51 ` Thinh Nguyen
2024-08-07  9:41   ` Prashanth K
2024-08-08  0:06     ` Thinh Nguyen
2024-08-13  9:53       ` Prashanth K
2024-08-13 23:30         ` Thinh Nguyen
2024-08-14  4:22           ` Prashanth K

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox