netdev: bfin_mac: handle timeouts with the MDIO registers gracefully
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>
This commit is contained in:
parent
c0da776bde
commit
2bfa0f0c9a
@ -81,9 +81,6 @@ static u16 pin_req[] = P_RMII0;
|
|||||||
static u16 pin_req[] = P_MII0;
|
static u16 pin_req[] = P_MII0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void bfin_mac_disable(void);
|
|
||||||
static void bfin_mac_enable(void);
|
|
||||||
|
|
||||||
static void desc_list_free(void)
|
static void desc_list_free(void)
|
||||||
{
|
{
|
||||||
struct net_dma_desc_rx *r;
|
struct net_dma_desc_rx *r;
|
||||||
@ -260,7 +257,7 @@ init_error:
|
|||||||
* MII operations
|
* MII operations
|
||||||
*/
|
*/
|
||||||
/* Wait until the previous MDC/MDIO transaction has completed */
|
/* 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;
|
int timeout_cnt = MAX_TIMEOUT_CNT;
|
||||||
|
|
||||||
@ -270,22 +267,30 @@ static void bfin_mdio_poll(void)
|
|||||||
if (timeout_cnt-- < 0) {
|
if (timeout_cnt-- < 0) {
|
||||||
printk(KERN_ERR DRV_NAME
|
printk(KERN_ERR DRV_NAME
|
||||||
": wait MDC/MDIO transaction to complete timeout\n");
|
": 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 */
|
/* 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)
|
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 */
|
/* read mode */
|
||||||
bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
|
bfin_write_EMAC_STAADD(SET_PHYAD((u16) phy_addr) |
|
||||||
SET_REGAD((u16) regnum) |
|
SET_REGAD((u16) regnum) |
|
||||||
STABUSY);
|
STABUSY);
|
||||||
|
|
||||||
bfin_mdio_poll();
|
ret = bfin_mdio_poll();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return (int) bfin_read_EMAC_STADAT();
|
return (int) bfin_read_EMAC_STADAT();
|
||||||
}
|
}
|
||||||
@ -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,
|
static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
|
||||||
u16 value)
|
u16 value)
|
||||||
{
|
{
|
||||||
bfin_mdio_poll();
|
int ret;
|
||||||
|
|
||||||
|
ret = bfin_mdio_poll();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
bfin_write_EMAC_STADAT((u32) value);
|
bfin_write_EMAC_STADAT((u32) value);
|
||||||
|
|
||||||
@ -304,9 +313,7 @@ static int bfin_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
|
|||||||
STAOP |
|
STAOP |
|
||||||
STABUSY);
|
STABUSY);
|
||||||
|
|
||||||
bfin_mdio_poll();
|
return bfin_mdio_poll();
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bfin_mdiobus_reset(struct mii_bus *bus)
|
static int bfin_mdiobus_reset(struct mii_bus *bus)
|
||||||
@ -1180,8 +1187,9 @@ static void bfin_mac_disable(void)
|
|||||||
/*
|
/*
|
||||||
* Enable Interrupts, Receive, and Transmit
|
* Enable Interrupts, Receive, and Transmit
|
||||||
*/
|
*/
|
||||||
static void bfin_mac_enable(void)
|
static int bfin_mac_enable(void)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
u32 opmode;
|
u32 opmode;
|
||||||
|
|
||||||
pr_debug("%s: %s\n", DRV_NAME, __func__);
|
pr_debug("%s: %s\n", DRV_NAME, __func__);
|
||||||
@ -1191,7 +1199,9 @@ static void bfin_mac_enable(void)
|
|||||||
bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
|
bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config);
|
||||||
|
|
||||||
/* Wait MII done */
|
/* Wait MII done */
|
||||||
bfin_mdio_poll();
|
ret = bfin_mdio_poll();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* We enable only RX here */
|
/* We enable only RX here */
|
||||||
/* ASTP : Enable Automatic Pad Stripping
|
/* ASTP : Enable Automatic Pad Stripping
|
||||||
@ -1215,6 +1225,8 @@ static void bfin_mac_enable(void)
|
|||||||
#endif
|
#endif
|
||||||
/* Turn on the EMAC rx */
|
/* Turn on the EMAC rx */
|
||||||
bfin_write_EMAC_OPMODE(opmode);
|
bfin_write_EMAC_OPMODE(opmode);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Our watchdog timed out. Called by the networking layer */
|
/* Our watchdog timed out. Called by the networking layer */
|
||||||
@ -1327,7 +1339,7 @@ static void bfin_mac_shutdown(struct net_device *dev)
|
|||||||
static int bfin_mac_open(struct net_device *dev)
|
static int bfin_mac_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct bfin_mac_local *lp = netdev_priv(dev);
|
struct bfin_mac_local *lp = netdev_priv(dev);
|
||||||
int retval;
|
int ret;
|
||||||
pr_debug("%s: %s\n", dev->name, __func__);
|
pr_debug("%s: %s\n", dev->name, __func__);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1341,18 +1353,21 @@ static int bfin_mac_open(struct net_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* initial rx and tx list */
|
/* initial rx and tx list */
|
||||||
retval = desc_list_init();
|
ret = desc_list_init();
|
||||||
|
if (ret)
|
||||||
if (retval)
|
return ret;
|
||||||
return retval;
|
|
||||||
|
|
||||||
phy_start(lp->phydev);
|
phy_start(lp->phydev);
|
||||||
phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
|
phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
|
||||||
setup_system_regs(dev);
|
setup_system_regs(dev);
|
||||||
setup_mac_addr(dev->dev_addr);
|
setup_mac_addr(dev->dev_addr);
|
||||||
|
|
||||||
bfin_mac_disable();
|
bfin_mac_disable();
|
||||||
bfin_mac_enable();
|
ret = bfin_mac_enable();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
pr_debug("hardware init finished\n");
|
pr_debug("hardware init finished\n");
|
||||||
|
|
||||||
netif_start_queue(dev);
|
netif_start_queue(dev);
|
||||||
netif_carrier_on(dev);
|
netif_carrier_on(dev);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user