[U-Boot] [PATCH 1/3] FEC: Remove endless loop in the FEC driver

Marek Vasut marex at denx.de
Wed Aug 29 15:49:49 CEST 2012


The FEC hardware sometimes errors out on data transfer and hangs in
the tightloop adjusted by this patch. So add timeout into the tightloop
to make such a hang recoverable.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Joe Hershberger <joe.hershberger at ni.com>
Cc: Fabio Estevam <festevam at gmail.com>
Cc: Otavio Salvador <otavio at ossystems.com.br>
Cc: Stefano Babic <sbabic at denx.de>
---
 drivers/net/fec_mxc.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index bc44d38..6f071e9 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -35,6 +35,12 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/*
+ * Timeout the transfer after 5 mS. This is usually a bit more, since
+ * the code in the tightloops this timeout is used in adds some overhead.
+ */
+#define FEC_XFER_TIMEOUT	5000
+
 #ifndef CONFIG_MII
 #error "CONFIG_MII has to be defined!"
 #endif
@@ -697,6 +703,8 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
 	unsigned int status;
 	uint32_t size, end;
 	uint32_t addr;
+	int timeout = FEC_XFER_TIMEOUT;
+	int ret = 0;
 
 	/*
 	 * This routine transmits one frame.  This routine only accepts
@@ -764,6 +772,10 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
 	while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
 		udelay(1);
 		invalidate_dcache_range(addr, addr + size);
+		if (!timeout--) {
+			ret = -EINVAL;
+			break;
+		}
 	}
 
 	debug("fec_send: status 0x%x index %d\n",
@@ -775,7 +787,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
 	else
 		fec->tbd_index = 1;
 
-	return 0;
+	return ret;
 }
 
 /**
-- 
1.7.10.4



More information about the U-Boot mailing list