Skip to content

Commit deb105f

Browse files
rohangt07kuba-moo
authored andcommitted
net: phy: marvell: Fix 88e1510 downshift counter errata
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 gigabit 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 times before downshifting. This behavior has been observed on copper links. Signed-off-by: Rohan G Thomas <[email protected]> Reviewed-by: Matthew Gerlach <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 214da63 commit deb105f

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

drivers/net/phy/marvell.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,43 @@ static int marvell_resume(struct phy_device *phydev)
19021902
return err;
19031903
}
19041904

1905+
/* m88e1510_resume
1906+
*
1907+
* The 88e1510 PHY has an erratum where the phy downshift counter is not cleared
1908+
* after phy being suspended(BMCR_PDOWN set) and then later resumed(BMCR_PDOWN
1909+
* cleared). This can cause the link to intermittently downshift to a lower speed.
1910+
*
1911+
* Disabling and re-enabling the downshift feature clears the counter, allowing
1912+
* the PHY to retry gigabit link negotiation up to the programmed retry count
1913+
* before downshifting. This behavior has been observed on copper links.
1914+
*/
1915+
static int m88e1510_resume(struct phy_device *phydev)
1916+
{
1917+
int err;
1918+
u8 cnt = 0;
1919+
1920+
err = marvell_resume(phydev);
1921+
if (err < 0)
1922+
return err;
1923+
1924+
/* read downshift counter value */
1925+
err = m88e1011_get_downshift(phydev, &cnt);
1926+
if (err < 0)
1927+
return err;
1928+
1929+
if (cnt) {
1930+
/* downshift disabled */
1931+
err = m88e1011_set_downshift(phydev, 0);
1932+
if (err < 0)
1933+
return err;
1934+
1935+
/* downshift enabled, with previous counter value */
1936+
err = m88e1011_set_downshift(phydev, cnt);
1937+
}
1938+
1939+
return err;
1940+
}
1941+
19051942
static int marvell_aneg_done(struct phy_device *phydev)
19061943
{
19071944
int retval = phy_read(phydev, MII_M1011_PHY_STATUS);
@@ -3923,7 +3960,7 @@ static struct phy_driver marvell_drivers[] = {
39233960
.handle_interrupt = marvell_handle_interrupt,
39243961
.get_wol = m88e1318_get_wol,
39253962
.set_wol = m88e1318_set_wol,
3926-
.resume = marvell_resume,
3963+
.resume = m88e1510_resume,
39273964
.suspend = marvell_suspend,
39283965
.read_page = marvell_read_page,
39293966
.write_page = marvell_write_page,

0 commit comments

Comments
 (0)