net: ethernet: mtk_eth_soc: only write values if needed
authorDaniel Golle <daniel@makrotopia.org>
Tue, 14 Mar 2023 00:34:45 +0000 (00:34 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Mar 2023 08:58:13 +0000 (08:58 +0000)
Only restart auto-negotiation and write link timer if actually
necessary. This prevents losing the link in case of minor
changes.

Fixes: 7e538372694b ("net: ethernet: mediatek: Re-add support SGMII")
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Tested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mediatek/mtk_sgmii.c

index 612f65b..83976dc 100644 (file)
@@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
                          const unsigned long *advertising,
                          bool permit_pause_to_mac)
 {
+       bool mode_changed = false, changed, use_an;
        struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
        unsigned int rgc3, sgm_mode, bmcr;
        int advertise, link_timer;
-       bool changed, use_an;
 
        advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
                                                             advertising);
        if (advertise < 0)
                return advertise;
 
-       link_timer = phylink_get_link_timer_ns(interface);
-       if (link_timer < 0)
-               return link_timer;
-
        /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
         * we assume that fixes it's speed at bitrate = line rate (in
         * other words, 1000Mbps or 2500Mbps).
@@ -77,13 +73,16 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
        }
 
        if (use_an) {
-               /* FIXME: Do we need to set AN_RESTART here? */
-               bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE;
+               bmcr = SGMII_AN_ENABLE;
        } else {
                bmcr = 0;
        }
 
        if (mpcs->interface != interface) {
+               link_timer = phylink_get_link_timer_ns(interface);
+               if (link_timer < 0)
+                       return link_timer;
+
                /* PHYA power down */
                regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
                                   SGMII_PHYA_PWD, SGMII_PHYA_PWD);
@@ -101,16 +100,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
                regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
                                   RG_PHY_SPEED_3_125G, rgc3);
 
+               /* Setup the link timer */
+               regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
+
                mpcs->interface = interface;
+               mode_changed = true;
        }
 
        /* Update the advertisement, noting whether it has changed */
        regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
                                 SGMII_ADVERTISE, advertise, &changed);
 
-       /* Setup the link timer and QPHY power up inside SGMIISYS */
-       regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
-
        /* Update the sgmsys mode register */
        regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
                           SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
@@ -118,7 +118,7 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
 
        /* Update the BMCR */
        regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
-                          SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
+                          SGMII_AN_ENABLE, bmcr);
 
        /* Release PHYA power down state
         * Only removing bit SGMII_PHYA_PWD isn't enough.
@@ -132,7 +132,7 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
        usleep_range(50, 100);
        regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
 
-       return changed;
+       return changed || mode_changed;
 }
 
 static void mtk_pcs_restart_an(struct phylink_pcs *pcs)