]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: simplify RTL8214FC patches for ethtool copper/fiber switching 18816/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Fri, 16 May 2025 07:31:07 +0000 (03:31 -0400)
committerRobert Marko <robimarko@gmail.com>
Mon, 26 May 2025 08:37:54 +0000 (10:37 +0200)
There is a patch/bug cascade in the realtek target phy code that must be resolved.

1. The phy_driver structure is patched to add features ONLY needed for RTL8214FC

2. The kernel is patched to allow switching fiber/copper port of phys through ethtool
   by calling these new features.

3. With those patches applied the bootup always switches RTL8214FC ports to copper.
   Even if a SFP module was found before and the phy driver switched to fibre before.

3. So another patch is needed that reprobes the SFP module to activate fiber again.

4. Because of the reprobing we need a fourth patch that avoid duplicate devices.

Simplify this by removing all patches and reusing the existing ethtool phy tunable
interface. The command line usage might be counterintuitive but it avoids tons of
problems in the code. In addition, this scenario is not used frequently.

Before:ethtool -s lan25 port fibre/tp
After: ethtool --set-phy-tunable lan25 downshift on/off

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/18816
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.6/drivers/net/phy/rtl83xx-phy.c
target/linux/realtek/patches-6.6/706-include-linux-add-phy-ops-for-rtl838x.patch
target/linux/realtek/patches-6.6/708-drivers-net-phy-eee-support-for-rtl838x.patch
target/linux/realtek/patches-6.6/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch [deleted file]
target/linux/realtek/patches-6.6/714-net-phy-sfp-add-support-for-SMBus.patch

index 8ca8c2a3db36e7628688b208a40228eb3662af0c..cf79b9bbe44809548d6a14280c40d12ebea82612 100644 (file)
@@ -1084,27 +1084,32 @@ static void rtl8214fc_media_set(struct phy_device *phydev, bool set_fibre)
        }
 }
 
-static int rtl8214fc_set_port(struct phy_device *phydev, int port)
+static int rtl8214fc_set_tunable(struct phy_device *phydev,
+                                struct ethtool_tunable *tuna, const void *data)
 {
-       bool is_fibre = (port == PORT_FIBRE ? true : false);
-       int addr = phydev->mdio.addr;
-
-       pr_debug("%s port %d to %d\n", __func__, addr, port);
-
-       rtl8214fc_media_set(phydev, is_fibre);
-
-       return 0;
+       /*
+        * The RTL8214FC driver usually detects insertion of SFP modules and automatically toggles
+        * between copper and fiber. There may be cases where the user wants to switch the port on
+        * demand. Usually ethtool offers to change the port of a multiport network card with
+        * "ethtool -s lan25 port fibre/tp" if the driver supports it. This does not work for
+        * attached phys. For more details see phy_ethtool_ksettings_set(). To avoid patching the
+        * kernel misuse the phy downshift tunable to offer that feature. For this use
+        * "ethtool --set-phy-tunable lan25 downshift on/off".
+        */
+       switch (tuna->id) {
+       case ETHTOOL_PHY_DOWNSHIFT:
+               rtl8214fc_media_set(phydev, !rtl8214fc_media_is_fibre(phydev));
+               return 0;
+       default:
+               return -EOPNOTSUPP;
+       }
 }
 
-static int rtl8214fc_get_port(struct phy_device *phydev)
+static int rtl8214fc_get_tunable(struct phy_device *phydev,
+                                struct ethtool_tunable *tuna, void *data)
 {
-       int addr = phydev->mdio.addr;
-
-       pr_debug("%s: port %d\n", __func__, addr);
-       if (rtl8214fc_media_is_fibre(phydev))
-               return PORT_FIBRE;
-
-       return PORT_MII;
+       /* Needed to make rtl8214fc_set_tunable() work */
+       return 0;
 }
 
 static int rtl8214fc_get_features(struct phy_device *phydev)
@@ -3954,13 +3959,13 @@ static struct phy_driver rtl83xx_phy_driver[] = {
                .config_aneg    = rtl8214fc_config_aneg,
                .get_eee        = rtl8214fc_get_eee,
                .get_features   = rtl8214fc_get_features,
-               .get_port       = rtl8214fc_get_port,
+               .get_tunable    = rtl8214fc_get_tunable,
                .probe          = rtl8214fc_phy_probe,
                .read_page      = rtl821x_read_page,
                .read_status    = rtl8214fc_read_status,
                .resume         = rtl8214fc_resume,
                .set_eee        = rtl8214fc_set_eee,
-               .set_port       = rtl8214fc_set_port,
+               .set_tunable    = rtl8214fc_set_tunable,
                .suspend        = rtl8214fc_suspend,
                .write_page     = rtl821x_write_page,
        },
index 09255c572147efe510f5fca46d824d694b1b27ed..3404d55ed3cd5621fd44891f411dfb404d5ddd0a 100644 (file)
@@ -21,12 +21,10 @@ Submitted-by: John Crispin <john@phrozen.org>
 
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
-@@ -1181,6 +1181,10 @@ struct phy_driver {
+@@ -1181,6 +1181,8 @@ struct phy_driver {
         */
        int (*led_polarity_set)(struct phy_device *dev, int index,
                                unsigned long modes);
-+      int (*get_port)(struct phy_device *dev);
-+      int (*set_port)(struct phy_device *dev, int port);
 +      int (*get_eee)(struct phy_device *dev, struct ethtool_eee *e);
 +      int (*set_eee)(struct phy_device *dev, struct ethtool_eee *e);
  };
index a92045ba8a7b0b24bd450ad50dc4869ebef24c7e..44461992b17cf9483d7ad242ba62ce72d5a4f5d9 100644 (file)
@@ -21,19 +21,7 @@ Submitted-by: John Crispin <john@phrozen.org>
 
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
-@@ -2503,6 +2503,11 @@ int phylink_ethtool_ksettings_set(struct
-                *   the presence of a PHY, this should not be changed as that
-                *   should be determined from the media side advertisement.
-                */
-+              if (pl->phydev->drv->get_port && pl->phydev->drv->set_port) {
-+                      if(pl->phydev->drv->get_port(pl->phydev) != kset->base.port) {
-+                              pl->phydev->drv->set_port(pl->phydev, kset->base.port);
-+                      }
-+              }
-               return phy_ethtool_ksettings_set(pl->phydev, &phy_kset);
-       }
-@@ -2805,8 +2810,11 @@ int phylink_ethtool_get_eee(struct phyli
+@@ -2805,8 +2805,11 @@ int phylink_ethtool_get_eee(struct phyli
  
        ASSERT_RTNL();
  
@@ -46,7 +34,7 @@ Submitted-by: John Crispin <john@phrozen.org>
  
        return ret;
  }
-@@ -2823,8 +2831,11 @@ int phylink_ethtool_set_eee(struct phyli
+@@ -2823,8 +2826,11 @@ int phylink_ethtool_set_eee(struct phyli
  
        ASSERT_RTNL();
  
diff --git a/target/linux/realtek/patches-6.6/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch b/target/linux/realtek/patches-6.6/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch
deleted file mode 100644 (file)
index 9f90510..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From a381ac0aa281fdb0b41a39d8a2bc08fd88f6db92 Mon Sep 17 00:00:00 2001
-From: Antoine Tenart <antoine.tenart@bootlin.com>
-Date: Tue, 25 Feb 2020 16:32:37 +0100
-Subject: [PATCH 1/3] net: phy: sfp: re-probe modules on DEV_UP event
-
-Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
----
- drivers/net/phy/sfp.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/phy/sfp.c
-+++ b/drivers/net/phy/sfp.c
-@@ -1570,6 +1570,10 @@ static void sfp_hwmon_probe(struct work_
-       struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work);
-       int err;
-+      /* Avoid duplicate hwmon devices when re-probing */
-+      if (sfp->hwmon_dev)
-+              return;
-+
-       /* hwmon interface needs to access 16bit registers in atomic way to
-        * guarantee coherency of the diagnostic monitoring data. If it is not
-        * possible to guarantee coherency because EEPROM is broken in such way
-@@ -2432,6 +2436,13 @@ static void sfp_sm_module(struct sfp *sf
-               return;
-       }
-+      /* Re-probe the SFP modules when an interface is brought up, as the MAC
-+       * do not report its link status (This means Phylink wouldn't be
-+       * triggered if the PHY had a link before a MAC is brought up).
-+       */
-+      if (event == SFP_E_DEV_UP && sfp->sm_mod_state == SFP_MOD_PRESENT)
-+              sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
-+
-       switch (sfp->sm_mod_state) {
-       default:
-               if (event == SFP_E_INSERT) {
index ea6149281d1cbfc649efc1c7da761543e7b71379..4fb1e7f293a5c74f49506f774773689d325f4769 100644 (file)
@@ -107,7 +107,7 @@ Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
  static void sfp_i2c_mdiobus_destroy(struct sfp *sfp)
  {
        mdiobus_unregister(sfp->i2c_mii);
-@@ -1888,9 +1965,15 @@ static void sfp_sm_fault(struct sfp *sfp
+@@ -1884,9 +1961,15 @@ static void sfp_sm_fault(struct sfp *sfp
  
  static int sfp_sm_add_mdio_bus(struct sfp *sfp)
  {