--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -177,7 +177,7 @@ struct port { struct desc *desc_tab; /* coherent */ u32 desc_tab_phys; int id; /* logical port ID */ - int speed, duplex; + int link, speed, duplex; u8 firmware[4]; int hwts_tx_en; int hwts_rx_en; @@ -558,37 +558,52 @@ static void ixp4xx_mdio_remove(void) mdiobus_free(mdio_bus); } - -static void ixp4xx_adjust_link(struct net_device *dev) +static void ixp4xx_update_link(struct net_device *dev) { struct port *port = netdev_priv(dev); - struct phy_device *phydev = port->phydev; - if (!phydev->link) { - if (port->speed) { - port->speed = 0; - printk(KERN_INFO "%s: link down\n", dev->name); - } + if (!port->link) { + netif_carrier_off(dev); + printk(KERN_INFO "%s: link down\n", dev->name); return; } - if (port->speed == phydev->speed && port->duplex == phydev->duplex) - return; - - port->speed = phydev->speed; - port->duplex = phydev->duplex; - - if (port->duplex) + if (port->duplex == DUPLEX_FULL) __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, &port->regs->tx_control[0]); else __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX, &port->regs->tx_control[0]); + netif_carrier_on(dev); printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n", dev->name, port->speed, port->duplex ? "full" : "half"); } +static void ixp4xx_adjust_link(struct net_device *dev) +{ + struct port *port = netdev_priv(dev); + struct phy_device *phydev = port->phydev; + int status_change = 0; + + if (phydev->link) { + if (port->duplex != phydev->duplex + || port->speed != phydev->speed) { + status_change = 1; + } + } + + if (phydev->link != port->link) + status_change = 1; + + port->link = phydev->link; + port->speed = phydev->speed; + port->duplex = phydev->duplex; + + if (status_change) + ixp4xx_update_link(dev); +} + static int ixp4xx_phy_connect(struct net_device *dev) { struct port *port = netdev_priv(dev); @@ -624,7 +639,6 @@ static void ixp4xx_phy_start(struct net_ { struct port *port = netdev_priv(dev); - port->speed = 0; /* force "link up" message */ phy_start(port->phydev); } @@ -1515,6 +1529,10 @@ static int eth_init_one(struct platform_ if ((err = register_netdev(dev))) goto err_phy_dis; + port->link = 0; + port->speed = 0; + port->duplex = -1; + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, npe_name(port->npe));