net: macb: Check MDIO state before read/write and use timeouts
authorHarini Katakam <harini.katakam@xilinx.com>
Fri, 1 Mar 2019 10:50:32 +0000 (16:20 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sun, 3 Mar 2019 21:51:37 +0000 (13:51 -0800)
Replace the while loop in MDIO read/write functions with a timeout.
In addition, add a check for MDIO bus busy before initiating a new
operation as well to make sure there is no ongoing MDIO operation.

Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Signed-off-by: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Signed-off-by: Harini Katakam <harini.katakam@xilinx.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c

index 9bbaad9f3d6326cdd113e48faa0d0e091bcde04c..f51040fedcf5dc250b86a2c89988246d76c27399 100644 (file)
                __v; \
        })
 
+#define MACB_READ_NSR(bp)      macb_readl(bp, NSR)
+
 /* struct macb_dma_desc - Hardware DMA descriptor
  * @addr: DMA address of data buffer
  * @ctrl: Control and status bits
index f2915f2fe21ae27dfe36870725e04e9a548cab58..a19ed2b62181fbac07ad98cf104b020213e08d25 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/ip.h>
 #include <linux/udp.h>
 #include <linux/tcp.h>
+#include <linux/iopoll.h>
 #include "macb.h"
 
 #define MACB_RX_BUFFER_SIZE    128
@@ -79,6 +80,8 @@
  */
 #define MACB_HALT_TIMEOUT      1230
 
+#define MACB_MDIO_TIMEOUT      1000000 /* in usecs */
+
 /* DMA buffer descriptor might be different size
  * depends on hardware configuration:
  *
@@ -318,10 +321,23 @@ static void macb_get_hwaddr(struct macb *bp)
        eth_hw_addr_random(bp->dev);
 }
 
+static int macb_mdio_wait_for_idle(struct macb *bp)
+{
+       u32 val;
+
+       return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE),
+                                 1, MACB_MDIO_TIMEOUT);
+}
+
 static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
        struct macb *bp = bus->priv;
        int value;
+       int err;
+
+       err = macb_mdio_wait_for_idle(bp);
+       if (err < 0)
+               return err;
 
        macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
                              | MACB_BF(RW, MACB_MAN_READ)
@@ -329,9 +345,9 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
                              | MACB_BF(REGA, regnum)
                              | MACB_BF(CODE, MACB_MAN_CODE)));
 
-       /* wait for end of transfer */
-       while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
-               cpu_relax();
+       err = macb_mdio_wait_for_idle(bp);
+       if (err < 0)
+               return err;
 
        value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
 
@@ -342,6 +358,11 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
                           u16 value)
 {
        struct macb *bp = bus->priv;
+       int err;
+
+       err = macb_mdio_wait_for_idle(bp);
+       if (err < 0)
+               return err;
 
        macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
                              | MACB_BF(RW, MACB_MAN_WRITE)
@@ -350,9 +371,9 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
                              | MACB_BF(CODE, MACB_MAN_CODE)
                              | MACB_BF(DATA, value)));
 
-       /* wait for end of transfer */
-       while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
-               cpu_relax();
+       err = macb_mdio_wait_for_idle(bp);
+       if (err < 0)
+               return err;
 
        return 0;
 }