summaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/phy_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r--drivers/net/phy/phy_device.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 16a0e7d..1716274 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);
OpenPOWER on IntegriCloud