Message ID | E1ePsZ2-0007rr-F3@rmk-PC.armlinux.org.uk |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | net: phy: marvell: avoid pause mode on SGMII-to-Copper for 88e151x | expand |
From: Russell King <rmk+kernel@armlinux.org.uk> Date: Fri, 15 Dec 2017 16:10:20 +0000 > Observed on the 88e1512 in SGMII-to-Copper mode, negotiating pause > is unreliable. While the pause bits can be set in the advertisment > register, they clear shortly after negotiation with a link partner > commences irrespective of the cause of the negotiation. > > While these bits may be correctly conveyed to the link partner on the > first negotiation, a subsequent negotiation (eg, due to negotiation > restart by the link partner, or reconnection of the cable) will result > in the link partner seeing these bits as zero, while the kernel > believes that it has advertised pause modes. > > This leads to the local kernel evaluating (eg) symmetric pause mode, > while the remote end evaluates that we have no pause mode capability. > > Since we can't guarantee the advertisment, disable pause mode support > with this PHY when used in SGMII-to-Copper mode. > > The 88e1510 in RGMII-to-Copper mode appears to behave correctly. > > Reviewed-by: Andrew Lunn <andrew@lunn.ch> > Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Applied.
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index b5a8f750e433..2510acc0feb0 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -879,6 +879,8 @@ static int m88e1510_config_init(struct phy_device *phydev) /* SGMII-to-Copper mode initialization */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + u32 pause; + /* Select page 18 */ err = marvell_set_page(phydev, 18); if (err < 0) @@ -902,6 +904,16 @@ static int m88e1510_config_init(struct phy_device *phydev) err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE); if (err < 0) return err; + + /* There appears to be a bug in the 88e1512 when used in + * SGMII to copper mode, where the AN advertisment register + * clears the pause bits each time a negotiation occurs. + * This means we can never be truely sure what was advertised, + * so disable Pause support. + */ + pause = SUPPORTED_Pause | SUPPORTED_Asym_Pause; + phydev->supported &= ~pause; + phydev->advertising &= ~pause; } return m88e1121_config_init(phydev);