diff options
-rw-r--r-- | drivers/net/phy/marvell.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 623292948fa7..0ea366c1217e 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1902,6 +1902,43 @@ error: return err; } +/* m88e1510_resume + * + * The 88e1510 PHY has an erratum where the phy downshift counter is not cleared + * after phy being suspended(BMCR_PDOWN set) and then later resumed(BMCR_PDOWN + * cleared). This can cause the link to intermittently downshift to a lower speed. + * + * Disabling and re-enabling the downshift feature clears the counter, allowing + * the PHY to retry gigabit link negotiation up to the programmed retry count + * before downshifting. This behavior has been observed on copper links. + */ +static int m88e1510_resume(struct phy_device *phydev) +{ + int err; + u8 cnt = 0; + + err = marvell_resume(phydev); + if (err < 0) + return err; + + /* read downshift counter value */ + err = m88e1011_get_downshift(phydev, &cnt); + if (err < 0) + return err; + + if (cnt) { + /* downshift disabled */ + err = m88e1011_set_downshift(phydev, 0); + if (err < 0) + return err; + + /* downshift enabled, with previous counter value */ + err = m88e1011_set_downshift(phydev, cnt); + } + + return err; +} + static int marvell_aneg_done(struct phy_device *phydev) { int retval = phy_read(phydev, MII_M1011_PHY_STATUS); @@ -3923,7 +3960,7 @@ static struct phy_driver marvell_drivers[] = { .handle_interrupt = marvell_handle_interrupt, .get_wol = m88e1318_get_wol, .set_wol = m88e1318_set_wol, - .resume = marvell_resume, + .resume = m88e1510_resume, .suspend = marvell_suspend, .read_page = marvell_read_page, .write_page = marvell_write_page, |