diff options
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r-- | drivers/net/phy/phy_device.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 16a0e7de5888..171627480058 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -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); |