aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Marginean <[email protected]>2020-01-16 20:09:59 +0200
committerDavid S. Miller <[email protected]>2020-01-17 13:17:49 +0100
commit8c6123e150f26eda011bc284e7aff221ea4d306b (patch)
tree0c41b672759b0a35c259d6a2a6ff7d30a0a041b7
parent062a33b1ad7c8df9f8f03f7b01c18e31a794a01d (diff)
net: dsa: felix: Don't restart PCS SGMII AN if not needed
Some PHYs like VSC8234 don't like it when AN restarts on their system side and they restart line side AN too, going into an endless link up/down loop. Don't restart PCS AN if link is up already. Although in theory this feedback loop should be possible with the other in-band AN modes too, for some reason it was not seen with the VSC8514 QSGMII and AQR412 USXGMII PHYs. So keep this logic only for SGMII where the problem was found. Fixes: bdeced75b13f ("net: dsa: felix: Add PCS operations for PHYLINK") Suggested-by: Vladimir Oltean <[email protected]> Signed-off-by: Alex Marginean <[email protected]> Signed-off-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
-rw-r--r--drivers/net/dsa/ocelot/felix_vsc9959.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 1e82b0d72058..2c812b481778 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -645,6 +645,27 @@ static void vsc9959_pcs_init_sgmii(struct phy_device *pcs,
const struct phylink_link_state *state)
{
if (link_an_mode == MLO_AN_INBAND) {
+ int bmsr, bmcr;
+
+ /* Some PHYs like VSC8234 don't like it when AN restarts on
+ * their system side and they restart line side AN too, going
+ * into an endless link up/down loop. Don't restart PCS AN if
+ * link is up already.
+ * We do check that AN is enabled just in case this is the 1st
+ * call, PCS detects a carrier but AN is disabled from power on
+ * or by boot loader.
+ */
+ bmcr = phy_read(pcs, MII_BMCR);
+ if (bmcr < 0)
+ return;
+
+ bmsr = phy_read(pcs, MII_BMSR);
+ if (bmsr < 0)
+ return;
+
+ if ((bmcr & BMCR_ANENABLE) && (bmsr & BMSR_LSTATUS))
+ return;
+
/* SGMII spec requires tx_config_Reg[15:0] to be exactly 0x4001
* for the MAC PCS in order to acknowledge the AN.
*/