Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <rohan.g.thomas@altera.com>
Reviewed-by: Matthew Gerlach <matthew.gerlach@altera.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250906-marvell_fix-v2-1-f6efb286937f@altera.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Rohan G Thomas and committed by
Jakub Kicinski
deb105f4 214da634

+38 -1
+38 -1
drivers/net/phy/marvell.c
··· 1902 1902 return err; 1903 1903 } 1904 1904 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 + 1905 1942 static int marvell_aneg_done(struct phy_device *phydev) 1906 1943 { 1907 1944 int retval = phy_read(phydev, MII_M1011_PHY_STATUS); ··· 3960 3923 .handle_interrupt = marvell_handle_interrupt, 3961 3924 .get_wol = m88e1318_get_wol, 3962 3925 .set_wol = m88e1318_set_wol, 3963 - .resume = marvell_resume, 3926 + .resume = m88e1510_resume, 3964 3927 .suspend = marvell_suspend, 3965 3928 .read_page = marvell_read_page, 3966 3929 .write_page = marvell_write_page,