From c3a012ce65818beb274195cd47f31ed80d0fbaa5 Mon Sep 17 00:00:00 2001
From: Bryan Wu <bryan.wu@analog.com>
Date: Tue, 16 Jun 2009 05:26:27 -0400
Subject: [PATCH] usb: musb: add timeout via CONFIG_MUSB_TIMEOUT

Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Remy Bohmer <linux@bohmer.net>
---
 drivers/usb/musb/musb_hcd.c | 31 +++++++++++++++++++++++++++++++
 drivers/usb/musb/musb_hcd.h |  4 ++++
 2 files changed, 35 insertions(+)

diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 352a0d4eb0..19d978b245 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -111,6 +111,7 @@ static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
 {
 	u16 csr;
 	int result = 1;
+	int timeout = CONFIG_MUSB_TIMEOUT;
 
 	while (result > 0) {
 		csr = readw(&musbr->txcsr);
@@ -152,7 +153,17 @@ static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
 			}
 			break;
 		}
+
+		/* Check the timeout */
+		if (--timeout)
+			udelay(1);
+		else {
+			dev->status = USB_ST_CRC_ERR;
+			result = -1;
+			break;
+		}
 	}
+
 	return result;
 }
 
@@ -162,6 +173,7 @@ static int wait_until_ep0_ready(struct usb_device *dev, u32 bit_mask)
 static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
 {
 	u16 csr;
+	int timeout = CONFIG_MUSB_TIMEOUT;
 
 	do {
 		if (check_stall(ep, 1)) {
@@ -174,6 +186,15 @@ static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
 			dev->status = USB_ST_CRC_ERR;
 			return 0;
 		}
+
+		/* Check the timeout */
+		if (--timeout)
+			udelay(1);
+		else {
+			dev->status = USB_ST_CRC_ERR;
+			return -1;
+		}
+
 	} while (csr & MUSB_TXCSR_TXPKTRDY);
 	return 1;
 }
@@ -184,6 +205,7 @@ static u8 wait_until_txep_ready(struct usb_device *dev, u8 ep)
 static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep)
 {
 	u16 csr;
+	int timeout = CONFIG_MUSB_TIMEOUT;
 
 	do {
 		if (check_stall(ep, 0)) {
@@ -196,6 +218,15 @@ static u8 wait_until_rxep_ready(struct usb_device *dev, u8 ep)
 			dev->status = USB_ST_CRC_ERR;
 			return 0;
 		}
+
+		/* Check the timeout */
+		if (--timeout)
+			udelay(1);
+		else {
+			dev->status = USB_ST_CRC_ERR;
+			return -1;
+		}
+
 	} while (!(csr & MUSB_RXCSR_RXPKTRDY));
 	return 1;
 }
diff --git a/drivers/usb/musb/musb_hcd.h b/drivers/usb/musb/musb_hcd.h
index bb83311b01..b7f571d037 100644
--- a/drivers/usb/musb/musb_hcd.h
+++ b/drivers/usb/musb/musb_hcd.h
@@ -30,6 +30,10 @@
 extern unsigned char new[];
 #endif
 
+#ifndef CONFIG_MUSB_TIMEOUT
+# define CONFIG_MUSB_TIMEOUT 100000
+#endif
+
 /* This defines the endpoint number used for control transfers */
 #define MUSB_CONTROL_EP 0
 
-- 
2.39.5