]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/phy/phy_device.c
PHY: Avoid unnecessary aneg restarts
[linux-2.6-omap-h63xx.git] / drivers / net / phy / phy_device.c
index 16a0e7de588807540cc4722fb18301c6fd4d940e..17162748005893a86ca206faf95c5ec194be5eb5 100644 (file)
@@ -419,13 +419,14 @@ EXPORT_SYMBOL(phy_detach);
  *
  * Description: Writes MII_ADVERTISE with the appropriate values,
  *   after sanitizing the values to make sure we only advertise
- *   what is supported.
+ *   what is supported.  Returns < 0 on error, 0 if the PHY's advertisement
+ *   hasn't changed, and > 0 if it has changed.
  */
 int genphy_config_advert(struct phy_device *phydev)
 {
        u32 advertise;
-       int adv;
-       int err;
+       int oldadv, adv;
+       int err, changed = 0;
 
        /* Only allow advertising what
         * this PHY supports */
@@ -433,7 +434,7 @@ int genphy_config_advert(struct phy_device *phydev)
        advertise = phydev->advertising;
 
        /* Setup standard advertisement */
-       adv = phy_read(phydev, MII_ADVERTISE);
+       oldadv = adv = phy_read(phydev, MII_ADVERTISE);
 
        if (adv < 0)
                return adv;
@@ -453,15 +454,18 @@ int genphy_config_advert(struct phy_device *phydev)
        if (advertise & ADVERTISED_Asym_Pause)
                adv |= ADVERTISE_PAUSE_ASYM;
 
-       err = phy_write(phydev, MII_ADVERTISE, adv);
+       if (adv != oldadv) {
+               err = phy_write(phydev, MII_ADVERTISE, adv);
 
-       if (err < 0)
-               return err;
+               if (err < 0)
+                       return err;
+               changed = 1;
+       }
 
        /* Configure gigabit if it's supported */
        if (phydev->supported & (SUPPORTED_1000baseT_Half |
                                SUPPORTED_1000baseT_Full)) {
-               adv = phy_read(phydev, MII_CTRL1000);
+               oldadv = adv = phy_read(phydev, MII_CTRL1000);
 
                if (adv < 0)
                        return adv;
@@ -471,13 +475,17 @@ int genphy_config_advert(struct phy_device *phydev)
                        adv |= ADVERTISE_1000HALF;
                if (advertise & SUPPORTED_1000baseT_Full)
                        adv |= ADVERTISE_1000FULL;
-               err = phy_write(phydev, MII_CTRL1000, adv);
 
-               if (err < 0)
-                       return err;
+               if (adv != oldadv) {
+                       err = phy_write(phydev, MII_CTRL1000, adv);
+
+                       if (err < 0)
+                               return err;
+                       changed = 1;
+               }
        }
 
-       return adv;
+       return changed;
 }
 EXPORT_SYMBOL(genphy_config_advert);
 
@@ -561,19 +569,22 @@ int genphy_restart_aneg(struct phy_device *phydev)
  */
 int genphy_config_aneg(struct phy_device *phydev)
 {
-       int err = 0;
+       int result = 0;
 
        if (AUTONEG_ENABLE == phydev->autoneg) {
-               err = genphy_config_advert(phydev);
+               int result = genphy_config_advert(phydev);
 
-               if (err < 0)
-                       return err;
+               if (result < 0) /* error */
+                       return result;
 
-               err = genphy_restart_aneg(phydev);
+               /* Only restart aneg if we are advertising something different
+                * than we were before.  */
+               if (result > 0)
+                       result = genphy_restart_aneg(phydev);
        } else
-               err = genphy_setup_forced(phydev);
+               result = genphy_setup_forced(phydev);
 
-       return err;
+       return result;
 }
 EXPORT_SYMBOL(genphy_config_aneg);