[U-Boot] [PATCH 3/7] usb: dwc2: Throttle the setup packet resending

Marek Vasut marex at denx.de
Tue May 3 22:51:16 CEST 2016


Abort the request in case any of the tokens in the packet failed to
complete transfer 10 times. This is a precaution needed so that we
don't end in endless loop when scanning the bus with some braindead
devices.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Chin Liang See <clsee at altera.com>
Cc: Dinh Nguyen <dinguyen at opensource.altera.com>
Cc: Hans de Goede <hdegoede at redhat.com>
Cc: Stefan Roese <sr at denx.de>
Cc: Stephen Warren <swarren at nvidia.com>
---
 drivers/usb/host/dwc2.c | 44 ++++++++++++++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 8d3949e..27fcf7c 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -993,6 +993,8 @@ static int _submit_control_msg(struct dwc2_priv *priv, struct usb_device *dev,
 	u8 pid;
 	/* For CONTROL endpoint pid should start with DATA1 */
 	int status_direction;
+	int againctr = 0;
+	const int againmax = 10;
 
 	if (devnum == priv->root_hub_devnum) {
 		dev->status = 0;
@@ -1003,25 +1005,37 @@ static int _submit_control_msg(struct dwc2_priv *priv, struct usb_device *dev,
 
 	/* SETUP stage */
 	pid = DWC2_HC_PID_SETUP;
-	do {
+	againctr = 0;
+	while (true) {
 		ret = chunk_msg(priv, dev, pipe, &pid, 0, setup, 8);
-	} while (ret == -EAGAIN);
-	if (ret)
-		return ret;
+		if (!ret)
+			break;
+		if (ret != -EAGAIN)
+			return ret;
+		if (againctr == againmax)
+			return -EINVAL;
+		againctr++;
+	};
 
 	/* DATA stage */
 	act_len = 0;
 	if (buffer) {
 		pid = DWC2_HC_PID_DATA1;
-		do {
+		againctr = 0;
+		while (true) {
 			ret = chunk_msg(priv, dev, pipe, &pid, usb_pipein(pipe),
 					buffer, len);
 			act_len += dev->act_len;
 			buffer += dev->act_len;
 			len -= dev->act_len;
-		} while (ret == -EAGAIN);
-		if (ret)
-			return ret;
+			if (!ret)
+				break;
+			if (ret != -EAGAIN)
+				return ret;
+			if (againctr == againmax)
+				return -EINVAL;
+			againctr++;
+		};
 		status_direction = usb_pipeout(pipe);
 	} else {
 		/* No-data CONTROL always ends with an IN transaction */
@@ -1030,12 +1044,18 @@ static int _submit_control_msg(struct dwc2_priv *priv, struct usb_device *dev,
 
 	/* STATUS stage */
 	pid = DWC2_HC_PID_DATA1;
-	do {
+	againctr = 0;
+	while (true) {
 		ret = chunk_msg(priv, dev, pipe, &pid, status_direction,
 				priv->status_buffer, 0);
-	} while (ret == -EAGAIN);
-	if (ret)
-		return ret;
+		if (!ret)
+			break;
+		if (ret != -EAGAIN)
+			return ret;
+		if (againctr == againmax)
+			return -EINVAL;
+		againctr++;
+	};
 
 	dev->act_len = act_len;
 
-- 
2.7.0



More information about the U-Boot mailing list