]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: phy: microchip: enable downshift by default on LAN88xx
authorNicolai Buchwitz <nb@tipi-net.de>
Wed, 1 Apr 2026 12:38:45 +0000 (14:38 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 3 Apr 2026 01:03:03 +0000 (18:03 -0700)
Enable auto-downshift from 1000BASE-T to 100BASE-TX after 2 failed
auto-negotiation attempts by default. This ensures that links with
faulty or missing cable pairs (C and D) fall back to 100Mbps without
requiring userspace configuration.

The downshift count is stored in the driver's private data and applied
in config_init, so user changes via ethtool are preserved across
suspend/resume cycles.

Users can override or disable downshift at runtime:

  ethtool --set-phy-tunable eth0 downshift off

Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Link: https://patch.msgid.link/20260401123848.696766-3-nb@tipi-net.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/microchip.c

index bc293d2dd130d6775704ce66ef8d8238e6118aeb..33bc633bdba05e5b3a39e604826ced1ecddf21c5 100644 (file)
@@ -26,6 +26,7 @@ struct lan88xx_priv {
        int     chip_id;
        int     chip_rev;
        __u32   wolopts;
+       u8      downshift_cnt;
 };
 
 static int lan88xx_read_page(struct phy_device *phydev)
@@ -247,9 +248,15 @@ static int lan88xx_get_tunable(struct phy_device *phydev,
 static int lan88xx_set_tunable(struct phy_device *phydev,
                               struct ethtool_tunable *tuna, const void *data)
 {
+       struct lan88xx_priv *priv = phydev->priv;
+       int ret;
+
        switch (tuna->id) {
        case ETHTOOL_PHY_DOWNSHIFT:
-               return lan88xx_set_downshift(phydev, *(const u8 *)data);
+               ret = lan88xx_set_downshift(phydev, *(const u8 *)data);
+               if (!ret)
+                       priv->downshift_cnt = *(const u8 *)data;
+               return ret;
        default:
                return -EOPNOTSUPP;
        }
@@ -267,6 +274,7 @@ static int lan88xx_probe(struct phy_device *phydev)
                return -ENOMEM;
 
        priv->wolopts = 0;
+       priv->downshift_cnt = 2;
 
        len = of_property_read_variable_u32_array(dev->of_node,
                                                  "microchip,led-modes",
@@ -346,7 +354,8 @@ static void lan88xx_set_mdix(struct phy_device *phydev)
 
 static int lan88xx_config_init(struct phy_device *phydev)
 {
-       int val;
+       struct lan88xx_priv *priv = phydev->priv;
+       int val, err;
 
        /*Zerodetect delay enable */
        val = phy_read_mmd(phydev, MDIO_MMD_PCS,
@@ -359,6 +368,10 @@ static int lan88xx_config_init(struct phy_device *phydev)
        /* Config DSP registers */
        lan88xx_config_TR_regs(phydev);
 
+       err = lan88xx_set_downshift(phydev, priv->downshift_cnt);
+       if (err < 0)
+               return err;
+
        return 0;
 }