realtek: fix SFP ports on RTL83xx main
authorLorenz Brun <[email protected]>
Fri, 10 Oct 2025 21:11:38 +0000 (23:11 +0200)
committerHauke Mehrtens <[email protected]>
Sun, 12 Oct 2025 14:12:54 +0000 (16:12 +0200)
Right now the phylink capability function enables 2.5G and 10G modes on
Maple and Cypress, which they mostly (other than two SERDES on Cypress)
don't support. This causes these modes to be selected and break the link
as they are not supported by hardware.

I looked into doing this properly, but it cannot just be done based on
SoC, but needs to take the whole topology into account as a given MAC
might have very different capabilities depending on what SERDES are
assigned to it. So for now just use 1G and QSGMII for RTL83xx and 10G
for RTL93xx. This mostly works, except it will downgrade some 10G links
on RTL839x, but since there are also 1G SFPs on these this cannot be
solved without fully accounting for the global MAC and SERDES
configuration.

So this makes all of the 1G SFP slots work again, while keeping most of
the 10G SFP+ slots working at 10G with minimal changes.

Signed-off-by: Lorenz Brun <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20374
Signed-off-by: Hauke Mehrtens <[email protected]>
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c

index a84d1be6d6d57643261def827794d417257e394d..38608734f3ca73c8dc0b9c685b6595255b283022 100644 (file)
@@ -613,25 +613,44 @@ static void rtl83xx_config_interface(int port, phy_interface_t interface)
        pr_debug("configured port %d for interface %s\n", port, phy_modes(interface));
 }
 
-static void rtldsa_phylink_get_caps(struct dsa_switch *ds, int port,
+static void rtldsa_83xx_phylink_get_caps(struct dsa_switch *ds, int port,
                                    struct phylink_config *config)
 {
        /*
-        * TODO: This capability check will need some love. Depending on the model and the
-        * port different MAC features and link modes are supported. For now just enable all
-        * required MAC and PHY capabilites so that we can make use of the ports.
+        * TODO: This needs to take into account the MAC to SERDES mapping and the
+        * specific SoC capabilities. Right now we just assume all RTL83xx ports
+        * support up to 1G standalone and QSGMII as that covers most real-world
+        * use cases.
         */
+       config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 |
+                                  MAC_1000FD;
 
+       __set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_GMII, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_INTERNAL, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_QSGMII, config->supported_interfaces);
+}
+
+static void rtldsa_93xx_phylink_get_caps(struct dsa_switch *ds, int port,
+                                   struct phylink_config *config)
+{
+       /*
+        * TODO: This needs to take into account the MAC to SERDES mapping and the
+        * specific SoC capabilities. Right now we just assume all RTL93xx ports
+        * support up to 10G standalone and up to USXGMII as that covers most
+        * real-world use cases.
+        */
        config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 |
                                   MAC_1000FD | MAC_2500FD | MAC_5000FD | MAC_10000FD;
 
        __set_bit(PHY_INTERFACE_MODE_1000BASEX, config->supported_interfaces);
-       __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
-       __set_bit(PHY_INTERFACE_MODE_2500BASEX, config->supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_GMII, config->supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_INTERNAL, config->supported_interfaces);
-       __set_bit(PHY_INTERFACE_MODE_QSGMII, config->supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_QSGMII, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_2500BASEX, config->supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_USXGMII, config->supported_interfaces);
 }
 
@@ -2562,7 +2581,7 @@ const struct dsa_switch_ops rtl83xx_switch_ops = {
        .phy_read               = rtldsa_phy_read,
        .phy_write              = rtldsa_phy_write,
 
-       .phylink_get_caps       = rtldsa_phylink_get_caps,
+       .phylink_get_caps       = rtldsa_83xx_phylink_get_caps,
        .phylink_mac_config     = rtl83xx_phylink_mac_config,
        .phylink_mac_link_down  = rtl83xx_phylink_mac_link_down,
        .phylink_mac_link_up    = rtl83xx_phylink_mac_link_up,
@@ -2619,7 +2638,7 @@ const struct dsa_switch_ops rtl93xx_switch_ops = {
        .phy_read               = rtldsa_phy_read,
        .phy_write              = rtldsa_phy_write,
 
-       .phylink_get_caps       = rtldsa_phylink_get_caps,
+       .phylink_get_caps       = rtldsa_93xx_phylink_get_caps,
        .phylink_mac_config     = rtl93xx_phylink_mac_config,
        .phylink_mac_link_down  = rtl93xx_phylink_mac_link_down,
        .phylink_mac_link_up    = rtl93xx_phylink_mac_link_up,