]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
r8152: Add support for 10Gbit Link Speeds and EEE
authorBirger Koblitz <mail@birger-koblitz.de>
Tue, 5 May 2026 15:56:33 +0000 (17:56 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 7 May 2026 01:54:14 +0000 (18:54 -0700)
The RTL8159 supports 10GBit Link speeds. Add support for this speed
in the setup and setting/getting through ethtool. Also add 10GBit EEE.
Add functionality for setup and ethtool get/set methods.

Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Aleksander Jan Bajkowski <olek2@wp.pl>
Link: https://patch.msgid.link/20260505-rtl8159_net_next-v4-1-1a648a9c4d8d@birger-koblitz.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/usb/r8152.c

index ae834876aa1acc7a9af08a4c01b7a984c4ab8433..05abfab1df94a571347196bfce7c232865e1058e 100644 (file)
@@ -621,6 +621,7 @@ enum spd_duplex {
        FORCE_1000M_FULL,
        NWAY_2500M_FULL,
        NWAY_5000M_FULL,
+       NWAY_10000M_FULL,
 };
 
 /* OCP_ALDPS_CONFIG */
@@ -742,6 +743,7 @@ enum spd_duplex {
 #define BP4_SUPER_ONLY         0x1578  /* RTL_VER_04 only */
 
 enum rtl_register_content {
+       _10000bps       = BIT(14),
        _5000bps        = BIT(12),
        _2500bps        = BIT(10),
        _1250bps        = BIT(9),
@@ -757,6 +759,8 @@ enum rtl_register_content {
 
 #define is_speed_2500(_speed)  (((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS))
 #define is_speed_5000(_speed)  (((_speed) & (_5000bps | LINK_STATUS)) == (_5000bps | LINK_STATUS))
+#define is_speed_10000(_speed) (((_speed) & (_10000bps | LINK_STATUS)) \
+                                == (_10000bps | LINK_STATUS))
 #define is_flow_control(_speed)        (((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow))
 
 #define RTL8152_MAX_TX         4
@@ -1008,6 +1012,7 @@ struct r8152 {
 
        u32 support_2500full:1;
        u32 support_5000full:1;
+       u32 support_10000full:1;
        u32 lenovo_macpassthru:1;
        u32 dell_tb_rx_agg_bug:1;
        u16 ocp_base;
@@ -1260,6 +1265,7 @@ enum tx_csum_stat {
 #define RTL_ADVERTISED_1000_FULL               BIT(5)
 #define RTL_ADVERTISED_2500_FULL               BIT(6)
 #define RTL_ADVERTISED_5000_FULL               BIT(7)
+#define RTL_ADVERTISED_10000_FULL              BIT(8)
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
  * The RTL chips use a 64 element hash table based on the Ethernet CRC.
@@ -6513,6 +6519,9 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
 
                        if (tp->support_5000full)
                                support |= RTL_ADVERTISED_5000_FULL;
+
+                       if (tp->support_10000full)
+                               support |= RTL_ADVERTISED_10000_FULL;
                }
 
                advertising &= support;
@@ -6559,9 +6568,10 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
                                r8152_mdio_write(tp, MII_CTRL1000, new1);
                }
 
-               if (tp->support_2500full || tp->support_5000full) {
+               if (tp->support_2500full || tp->support_5000full || tp->support_10000full) {
                        orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
-                       new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G);
+                       new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G
+                                       | MDIO_AN_10GBT_CTRL_ADV10G);
 
                        if (advertising & RTL_ADVERTISED_2500_FULL) {
                                new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G;
@@ -6573,6 +6583,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
                                tp->ups_info.speed_duplex = NWAY_5000M_FULL;
                        }
 
+                       if (advertising & RTL_ADVERTISED_10000_FULL) {
+                               new1 |= MDIO_AN_10GBT_CTRL_ADV10G;
+                               tp->ups_info.speed_duplex = NWAY_10000M_FULL;
+                       }
+
                        if (orig != new1)
                                ocp_reg_write(tp, OCP_10GBT_CTRL, new1);
                }
@@ -8708,7 +8723,10 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
        linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
                         cmd->link_modes.supported, tp->support_5000full);
 
-       if (tp->support_2500full || tp->support_5000full) {
+       linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+                        cmd->link_modes.supported, tp->support_10000full);
+
+       if (tp->support_2500full || tp->support_5000full || tp->support_10000full) {
                u16 ocp_10gbt_ctrl = ocp_reg_read(tp, OCP_10GBT_CTRL);
                u16 ocp_10gbt_stat = ocp_reg_read(tp, OCP_10GBT_STAT);
 
@@ -8737,6 +8755,19 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
                        if (is_speed_5000(rtl8152_get_speed(tp)))
                                cmd->base.speed = SPEED_5000;
                }
+
+               if (tp->support_10000full) {
+                       linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+                                        cmd->link_modes.advertising,
+                                        ocp_10gbt_ctrl & MDIO_AN_10GBT_CTRL_ADV10G);
+
+                       linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+                                        cmd->link_modes.lp_advertising,
+                                        ocp_10gbt_stat & MDIO_AN_10GBT_STAT_LP10G);
+
+                       if (is_speed_10000(rtl8152_get_speed(tp)))
+                               cmd->base.speed = SPEED_10000;
+               }
        }
 
        mutex_unlock(&tp->control);
@@ -8790,6 +8821,10 @@ static int rtl8152_set_link_ksettings(struct net_device *dev,
                     cmd->link_modes.advertising))
                advertising |= RTL_ADVERTISED_5000_FULL;
 
+       if (test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+                    cmd->link_modes.advertising))
+               advertising |= RTL_ADVERTISED_10000_FULL;
+
        mutex_lock(&tp->control);
 
        ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed,
@@ -8953,6 +8988,13 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
                        linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, common);
        }
 
+       if (tp->support_10000full) {
+               linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, eee->supported);
+
+               if (speed & _10000bps)
+                       linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, common);
+       }
+
        eee->eee_enabled = tp->eee_en;
 
        if (speed & _1000bps)
@@ -9967,6 +10009,11 @@ static int rtl8152_probe_once(struct usb_interface *intf,
                        tp->speed = SPEED_5000;
                        tp->advertising |= RTL_ADVERTISED_5000_FULL;
                }
+               if (tp->support_10000full &&
+                   tp->udev->speed >= USB_SPEED_SUPER) {
+                       tp->speed = SPEED_10000;
+                       tp->advertising |= RTL_ADVERTISED_10000_FULL;
+               }
                tp->advertising |= RTL_ADVERTISED_1000_FULL;
        }
        tp->duplex = DUPLEX_FULL;