lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240730124742.561408-1-quic_prashk@quicinc.com>
Date: Tue, 30 Jul 2024 18:17:42 +0530
From: Prashanth K <quic_prashk@...cinc.com>
To: Thinh Nguyen <Thinh.Nguyen@...opsys.com>,
        Greg Kroah-Hartman
	<gregkh@...uxfoundation.org>
CC: <linux-kernel@...r.kernel.org>, <linux-usb@...r.kernel.org>,
        Prashanth K
	<quic_prashk@...cinc.com>, <stable@...r.kernel.org>
Subject: [PATCH] usb: dwc3: Fix latency of DSTS while receiving wakeup event

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@...r.kernel.org>
Signed-off-by: Prashanth K <quic_prashk@...cinc.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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ