[PATCH 02/23] net: davinci-emac: Add timeout to polling loop

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Do not poll forever when the hardware does not behave like we want to.

Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
---
 drivers/net/davinci_emac.c | 47 ++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 2f6091d155..bda62214ef 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -105,13 +105,40 @@ static void davinci_eth_mdio_enable(struct davinci_emac_priv *priv)
 	while (readl(priv->adap_mdio + EMAC_MDIO_CONTROL) & MDIO_CONTROL_IDLE);
 }
 
+/* wait until hardware is ready for another user access */
+static int wait_for_user_access(struct davinci_emac_priv *priv, uint32_t *val)
+{
+	u32 tmp;
+	uint64_t start = get_time_ns();
+
+	do {
+		tmp = readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0);
+
+		if (!(tmp & MDIO_USERACCESS0_GO))
+			break;
+
+		if (is_timeout(start, 100 * MSECOND)) {
+			dev_err(priv->dev, "timeout waiting for user access\n");
+			return -ETIMEDOUT;
+		}
+	} while (1);
+
+	if (val)
+		*val = tmp;
+
+	return 0;
+}
+
+
 static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg)
 {
 	struct davinci_emac_priv *priv = bus->priv;
 	uint16_t value;
-	int tmp;
+	int tmp, ret;
 
-	while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO);
+	ret = wait_for_user_access(priv, NULL);
+	if (ret)
+		return ret;
 
 	writel(MDIO_USERACCESS0_GO |
 		MDIO_USERACCESS0_WRITE_READ |
@@ -119,8 +146,9 @@ static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg)
 		((addr & 0x1f) << 16),
 		priv->adap_mdio + EMAC_MDIO_USERACCESS0);
 
-	/* Wait for command to complete */
-	while ((tmp = readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0)) & MDIO_USERACCESS0_GO);
+	ret = wait_for_user_access(priv, &tmp);
+	if (ret)
+		return ret;
 
 	if (tmp & MDIO_USERACCESS0_ACK) {
 		value = tmp & 0xffff;
@@ -135,7 +163,11 @@ static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg)
 static int davinci_miibus_write(struct mii_bus *bus, int addr, int reg, u16 value)
 {
 	struct davinci_emac_priv *priv = bus->priv;
-	while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO);
+	int ret;
+
+	ret = wait_for_user_access(priv, NULL);
+	if (ret)
+		return ret;
 
 	dev_dbg(priv->dev, "davinci_miibus_write: addr=0x%02x reg=0x%02x value=0x%04x\n",
 		   addr, reg, value);
@@ -146,10 +178,7 @@ static int davinci_miibus_write(struct mii_bus *bus, int addr, int reg, u16 valu
 				(value & 0xffff),
 		priv->adap_mdio + EMAC_MDIO_USERACCESS0);
 
-	/* Wait for command to complete */
-	while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO);
-
-	return 0;
+	return wait_for_user_access(priv, NULL);
 }
 
 static int davinci_emac_get_ethaddr(struct eth_device *edev, unsigned char *adr)
-- 
2.19.1


_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox



[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux