From: Harini Katakam <hari...@xilinx.com>

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.da...@xilinx.com>
Signed-off-by: Sai Pavan Boddu <sai.pavan.bo...@xilinx.com>
Signed-off-by: Harini Katakam <hari...@xilinx.com>
---
v2 changes:
Use readx_poll_timeout

Changes form RFC:
Cleaned up timeout implementation and moved it to a helper.

 drivers/net/ethernet/cadence/macb.h      |  3 +++
 drivers/net/ethernet/cadence/macb_main.c | 33 ++++++++++++++++++++++++++------
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/cadence/macb.h 
b/drivers/net/ethernet/cadence/macb.h
index 3d45f4c..df7bee1 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -714,6 +714,9 @@
                __v; \
        })
 
+#define MACB_IDLE_MASK         (1 << MACB_IDLE_OFFSET)
+#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
diff --git a/drivers/net/ethernet/cadence/macb_main.c 
b/drivers/net/ethernet/cadence/macb_main.c
index 1d86b4d..fd86ece 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -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_IDLE_MASK,
+                                 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;
 }
-- 
2.7.4

Reply via email to