diff options
author | Harini Katakam <harini.katakam@xilinx.com> | 2019-03-01 16:20:32 +0530 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-03-03 13:51:37 -0800 |
commit | 8beb79b7ae937632db1d2721d33b46526d41f153 (patch) | |
tree | a940e3543aed8ead37ac363865e0764a361c6c5a /drivers/net | |
parent | 41bc0ddb80e0380ab88b3902e638c89b3453b421 (diff) | |
download | linux-8beb79b7ae937632db1d2721d33b46526d41f153.tar.bz2 |
net: macb: Check MDIO state before read/write and use timeouts
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/cadence/macb.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 33 |
2 files changed, 29 insertions, 6 deletions
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 9bbaad9f3d63..f51040fedcf5 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -715,6 +715,8 @@ __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 diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index f2915f2fe21a..a19ed2b62181 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_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; } |