phylib: Fix auto-negotiation restart avoidance
A previous patch, 51e2a3846e
, made
genphy_config_aneg() not restart aneg by calling genphy_restart_aneg() if
the advertisement hadn't changed.
But, genphy_restart_aneg() doesn't just restart aneg, it may also *enable*
aneg or un-isolate the PHY from the MII (those functions are controlled by
the same register). The code to avoid calling genphy_restart_aneg() didn't
consider this.
So, modify genphy_config_aneg() to also check if the PHY needs to have aneg
enabled or be un-isolated before deciding not to restart aneg.
This caused a problem with certain Davicom PHYs, as that driver isolates
the PHY (why?) before calling genphy_config_aneg() and expects the PHY to
be un-isolated by that function.
Signed-off-by: Trent Piepho <tpiepho@freescale.com>
Reported-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
31c221c49f
commit
de339c2aa7
1 changed files with 23 additions and 11 deletions
|
@ -564,20 +564,32 @@ EXPORT_SYMBOL(genphy_restart_aneg);
|
|||
*/
|
||||
int genphy_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int result = 0;
|
||||
int result;
|
||||
|
||||
if (AUTONEG_ENABLE == phydev->autoneg) {
|
||||
int result = genphy_config_advert(phydev);
|
||||
if (AUTONEG_ENABLE != phydev->autoneg)
|
||||
return genphy_setup_forced(phydev);
|
||||
|
||||
if (result < 0) /* error */
|
||||
return result;
|
||||
result = genphy_config_advert(phydev);
|
||||
|
||||
/* Only restart aneg if we are advertising something different
|
||||
* than we were before. */
|
||||
if (result > 0)
|
||||
result = genphy_restart_aneg(phydev);
|
||||
} else
|
||||
result = genphy_setup_forced(phydev);
|
||||
if (result < 0) /* error */
|
||||
return result;
|
||||
|
||||
if (result == 0) {
|
||||
/* Advertisment hasn't changed, but maybe aneg was never on to
|
||||
* begin with? Or maybe phy was isolated? */
|
||||
int ctl = phy_read(phydev, MII_BMCR);
|
||||
|
||||
if (ctl < 0)
|
||||
return ctl;
|
||||
|
||||
if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
|
||||
result = 1; /* do restart aneg */
|
||||
}
|
||||
|
||||
/* Only restart aneg if we are advertising something different
|
||||
* than we were before. */
|
||||
if (result > 0)
|
||||
result = genphy_restart_aneg(phydev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Reference in a new issue