|
@@ -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);
|
|
|
|