Skip to content

Commit

Permalink
netdev: bfin_mac: handle timeouts with the MDIO registers gracefully
Browse files Browse the repository at this point in the history
Have the low level MDIO functions pass back up timeout information so we
don't waste time polling them multiple times when there is a problem, and
so we don't let higher layers think the device is available when it isn't.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Mike Frysinger authored and David S. Miller committed May 18, 2010
1 parent c0da776 commit 2bfa0f0
Showing 1 changed file with 34 additions and 19 deletions.
53 changes: 34 additions & 19 deletions drivers/net/bfin_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ static u16 pin_req[] = P_RMII0;
static u16 pin_req[] = P_MII0;
#endif

static void bfin_mac_disable(void);
static void bfin_mac_enable(void);

static void desc_list_free(void)
{
struct net_dma_desc_rx *r;
Expand Down Expand Up @@ -260,7 +257,7 @@ static int desc_list_init(void)
* MII operations
*/
/* Wait until the previous MDC/MDIO transaction has completed */
static void bfin_mdio_poll(void)
static int bfin_mdio_poll(void)
{
int timeout_cnt = MAX_TIMEOUT_CNT;

Expand All @@ -270,22 +267,30 @@ static void bfin_mdio_poll(void)
if (timeout_cnt-- < 0) {
printk(KERN_ERR DRV_NAME
": wait MDC/MDIO transaction to complete timeout\n");
break;
return -ETIMEDOUT;
}
}

return 0;
}

/* Read an off-chip register in a PHY through the MDC/MDIO port */
static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
{
bfin_mdio_poll();
int ret;

ret = bfin_mdio_poll();
if (ret)
return ret;

/* read mode */
bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
SET_REGAD((u16) regnum) |
STABUSY);

bfin_mdio_poll();
ret = bfin_mdio_poll();
if (ret)
return ret;

return (int) bfin_read_EMAC_STADAT();
}
Expand All @@ -294,7 +299,11 @@ static int bfin_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
u16 value)
{
bfin_mdio_poll();
int ret;

ret = bfin_mdio_poll();
if (ret)
return ret;

bfin_write_EMAC_STADAT((u32) value);

Expand All @@ -304,9 +313,7 @@ static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
STAOP |
STABUSY);

bfin_mdio_poll();

return 0;
return bfin_mdio_poll();
}

static int bfin_mdiobus_reset(struct mii_bus *bus)
Expand Down Expand Up @@ -1180,8 +1187,9 @@ static void bfin_mac_disable(void)
/*
* Enable Interrupts, Receive, and Transmit
*/
static void bfin_mac_enable(void)
static int bfin_mac_enable(void)
{
int ret;
u32 opmode;

pr_debug("%s: %s\n", DRV_NAME, __func__);
Expand All @@ -1191,7 +1199,9 @@ static void bfin_mac_enable(void)
bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);

/* Wait MII done */
bfin_mdio_poll();
ret = bfin_mdio_poll();
if (ret)
return ret;

/* We enable only RX here */
/* ASTP : Enable Automatic Pad Stripping
Expand All @@ -1215,6 +1225,8 @@ static void bfin_mac_enable(void)
#endif
/* Turn on the EMAC rx */
bfin_write_EMAC_OPMODE(opmode);

return 0;
}

/* Our watchdog timed out. Called by the networking layer */
Expand Down Expand Up @@ -1327,7 +1339,7 @@ static void bfin_mac_shutdown(struct net_device *dev)
static int bfin_mac_open(struct net_device *dev)
{
struct bfin_mac_local *lp = netdev_priv(dev);
int retval;
int ret;
pr_debug("%s: %s\n", dev->name, __func__);

/*
Expand All @@ -1341,18 +1353,21 @@ static int bfin_mac_open(struct net_device *dev)
}

/* initial rx and tx list */
retval = desc_list_init();

if (retval)
return retval;
ret = desc_list_init();
if (ret)
return ret;

phy_start(lp->phydev);
phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
setup_system_regs(dev);
setup_mac_addr(dev->dev_addr);

bfin_mac_disable();
bfin_mac_enable();
ret = bfin_mac_enable();
if (ret)
return ret;
pr_debug("hardware init finished\n");

netif_start_queue(dev);
netif_carrier_on(dev);

Expand Down

0 comments on commit 2bfa0f0

Please sign in to comment.