Commit a4572e0c authored by Cristian Bercaru's avatar Cristian Bercaru Committed by David S. Miller

phy: unmask link partner capabilities

Masking the link partner's capabilities with local capabilities can be
misleading in autonegotiation scenarios such as PAUSE frame
autonegotiation.
This patch calculates the join between the local capabilities and the
link parner capabilities, when it determines the speed and duplex
settings, but does not mask any of the link partner capabilities when
it calculates PAUSE frame settings.
Signed-off-by: default avatarCristian Bercaru <cristian.bercaru@freescale.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 46833a86
...@@ -916,6 +916,8 @@ int genphy_read_status(struct phy_device *phydev) ...@@ -916,6 +916,8 @@ int genphy_read_status(struct phy_device *phydev)
int err; int err;
int lpa; int lpa;
int lpagb = 0; int lpagb = 0;
int common_adv;
int common_adv_gb = 0;
/* Update the link, but return if there was an error */ /* Update the link, but return if there was an error */
err = genphy_update_link(phydev); err = genphy_update_link(phydev);
...@@ -937,7 +939,7 @@ int genphy_read_status(struct phy_device *phydev) ...@@ -937,7 +939,7 @@ int genphy_read_status(struct phy_device *phydev)
phydev->lp_advertising = phydev->lp_advertising =
mii_stat1000_to_ethtool_lpa_t(lpagb); mii_stat1000_to_ethtool_lpa_t(lpagb);
lpagb &= adv << 2; common_adv_gb = lpagb & adv << 2;
} }
lpa = phy_read(phydev, MII_LPA); lpa = phy_read(phydev, MII_LPA);
...@@ -950,25 +952,25 @@ int genphy_read_status(struct phy_device *phydev) ...@@ -950,25 +952,25 @@ int genphy_read_status(struct phy_device *phydev)
if (adv < 0) if (adv < 0)
return adv; return adv;
lpa &= adv; common_adv = lpa & adv;
phydev->speed = SPEED_10; phydev->speed = SPEED_10;
phydev->duplex = DUPLEX_HALF; phydev->duplex = DUPLEX_HALF;
phydev->pause = 0; phydev->pause = 0;
phydev->asym_pause = 0; phydev->asym_pause = 0;
if (lpagb & (LPA_1000FULL | LPA_1000HALF)) { if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
phydev->speed = SPEED_1000; phydev->speed = SPEED_1000;
if (lpagb & LPA_1000FULL) if (common_adv_gb & LPA_1000FULL)
phydev->duplex = DUPLEX_FULL; phydev->duplex = DUPLEX_FULL;
} else if (lpa & (LPA_100FULL | LPA_100HALF)) { } else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
phydev->speed = SPEED_100; phydev->speed = SPEED_100;
if (lpa & LPA_100FULL) if (common_adv & LPA_100FULL)
phydev->duplex = DUPLEX_FULL; phydev->duplex = DUPLEX_FULL;
} else } else
if (lpa & LPA_10FULL) if (common_adv & LPA_10FULL)
phydev->duplex = DUPLEX_FULL; phydev->duplex = DUPLEX_FULL;
if (phydev->duplex == DUPLEX_FULL) { if (phydev->duplex == DUPLEX_FULL) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment