OpenWrt – Rev 1

Subversion Repositories:
Rev:
--- 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));