--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -171,12 +171,13 @@ struct port { struct npe *npe; struct net_device *netdev; struct napi_struct napi; + struct phy_device *phydev; struct eth_plat_info *plat; buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; 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,36 +559,46 @@ static void ixp4xx_mdio_remove(void) } -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 = dev->phydev; - - if (!phydev->link) { - if (port->speed) { - port->speed = 0; - 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); @@ -623,7 +634,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); } @@ -1499,6 +1509,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));