]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: wangxun: add RSS reta and rxfh fields support
authorJiawen Wu <jiawenwu@trustnetic.com>
Fri, 26 Sep 2025 02:38:42 +0000 (10:38 +0800)
committerJakub Kicinski <kuba@kernel.org>
Tue, 30 Sep 2025 01:11:16 +0000 (18:11 -0700)
Add ethtool ops for Rx flow hashing, query and set RSS indirection table
and hash key. Disable UDP RSS by default, and support to configure L4
header fields with TCP/UDP/SCTP for flow hasing.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20250926023843.34340-4-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
drivers/net/ethernet/wangxun/libwx/wx_ethtool.h
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ethernet/wangxun/libwx/wx_type.h
drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c

index 1a9b7bfbd1d2499ebed01c52ee80921d1106570d..06f401bd975c7d2338f60a9d3ddb065d1d23fdf3 100644 (file)
@@ -481,6 +481,142 @@ int wx_set_channels(struct net_device *dev,
 }
 EXPORT_SYMBOL(wx_set_channels);
 
+u32 wx_rss_indir_size(struct net_device *netdev)
+{
+       struct wx *wx = netdev_priv(netdev);
+
+       return wx_rss_indir_tbl_entries(wx);
+}
+EXPORT_SYMBOL(wx_rss_indir_size);
+
+u32 wx_get_rxfh_key_size(struct net_device *netdev)
+{
+       return WX_RSS_KEY_SIZE;
+}
+EXPORT_SYMBOL(wx_get_rxfh_key_size);
+
+static void wx_get_reta(struct wx *wx, u32 *indir)
+{
+       u32 reta_size = wx_rss_indir_tbl_entries(wx);
+       u16 rss_m = wx->ring_feature[RING_F_RSS].mask;
+
+       if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags))
+               rss_m = wx->ring_feature[RING_F_RSS].indices - 1;
+
+       for (u32 i = 0; i < reta_size; i++)
+               indir[i] = wx->rss_indir_tbl[i] & rss_m;
+}
+
+int wx_get_rxfh(struct net_device *netdev,
+               struct ethtool_rxfh_param *rxfh)
+{
+       struct wx *wx = netdev_priv(netdev);
+
+       rxfh->hfunc = ETH_RSS_HASH_TOP;
+
+       if (rxfh->indir)
+               wx_get_reta(wx, rxfh->indir);
+
+       if (rxfh->key)
+               memcpy(rxfh->key, wx->rss_key, WX_RSS_KEY_SIZE);
+
+       return 0;
+}
+EXPORT_SYMBOL(wx_get_rxfh);
+
+int wx_set_rxfh(struct net_device *netdev,
+               struct ethtool_rxfh_param *rxfh,
+               struct netlink_ext_ack *extack)
+{
+       struct wx *wx = netdev_priv(netdev);
+       u32 reta_entries, i;
+
+       if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+           rxfh->hfunc != ETH_RSS_HASH_TOP)
+               return -EOPNOTSUPP;
+
+       reta_entries = wx_rss_indir_tbl_entries(wx);
+       /* Fill out the redirection table */
+       if (rxfh->indir) {
+               for (i = 0; i < reta_entries; i++)
+                       wx->rss_indir_tbl[i] = rxfh->indir[i];
+
+               wx_store_reta(wx);
+       }
+
+       /* Fill out the rss hash key */
+       if (rxfh->key) {
+               memcpy(wx->rss_key, rxfh->key, WX_RSS_KEY_SIZE);
+               wx_store_rsskey(wx);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(wx_set_rxfh);
+
+static const struct wx_rss_flow_map rss_flow_table[] = {
+       { TCP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_TCP },
+       { TCP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_TCP },
+       { UDP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_UDP },
+       { UDP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_UDP },
+       { SCTP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_SCTP },
+       { SCTP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_SCTP },
+};
+
+int wx_get_rxfh_fields(struct net_device *dev,
+                      struct ethtool_rxfh_fields *nfc)
+{
+       struct wx *wx = netdev_priv(dev);
+
+       nfc->data = RXH_IP_SRC | RXH_IP_DST;
+
+       for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
+               const struct wx_rss_flow_map *entry = &rss_flow_table[i];
+
+               if (entry->flow_type == nfc->flow_type) {
+                       if (wx->rss_flags & entry->flag)
+                               nfc->data |= entry->data;
+                       break;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(wx_get_rxfh_fields);
+
+int wx_set_rxfh_fields(struct net_device *dev,
+                      const struct ethtool_rxfh_fields *nfc,
+                      struct netlink_ext_ack *extack)
+{
+       struct wx *wx = netdev_priv(dev);
+       u8 flags = wx->rss_flags;
+
+       if (!(nfc->data & RXH_IP_SRC) ||
+           !(nfc->data & RXH_IP_DST))
+               return -EINVAL;
+
+       for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
+               const struct wx_rss_flow_map *entry = &rss_flow_table[i];
+
+               if (entry->flow_type == nfc->flow_type) {
+                       if (nfc->data & entry->data)
+                               flags |= entry->flag;
+                       else
+                               flags &= ~entry->flag;
+
+                       if (flags != wx->rss_flags) {
+                               wx->rss_flags = flags;
+                               wx_config_rss_field(wx);
+                       }
+
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL(wx_set_rxfh_fields);
+
 u32 wx_get_msglevel(struct net_device *netdev)
 {
        struct wx *wx = netdev_priv(netdev);
index 073f1149a578f0d442f621f0bf5e038663d861a6..72709397046254636bbe21542bc846d65bc930b2 100644 (file)
@@ -38,6 +38,18 @@ void wx_get_channels(struct net_device *dev,
                     struct ethtool_channels *ch);
 int wx_set_channels(struct net_device *dev,
                    struct ethtool_channels *ch);
+u32 wx_rss_indir_size(struct net_device *netdev);
+u32 wx_get_rxfh_key_size(struct net_device *netdev);
+int wx_get_rxfh(struct net_device *netdev,
+               struct ethtool_rxfh_param *rxfh);
+int wx_set_rxfh(struct net_device *netdev,
+               struct ethtool_rxfh_param *rxfh,
+               struct netlink_ext_ack *extack);
+int wx_get_rxfh_fields(struct net_device *dev,
+                      struct ethtool_rxfh_fields *cmd);
+int wx_set_rxfh_fields(struct net_device *dev,
+                      const struct ethtool_rxfh_fields *nfc,
+                      struct netlink_ext_ack *extack);
 u32 wx_get_msglevel(struct net_device *netdev);
 void wx_set_msglevel(struct net_device *netdev, u32 data);
 int wx_get_ts_info(struct net_device *dev,
index 9bffa8984cbeb0f5829d9cc252f1b202b3299085..73d5a2a7c4f66cbcd0ef043c6a76f773dca2e254 100644 (file)
@@ -2449,8 +2449,7 @@ int wx_sw_init(struct wx *wx)
                return err;
        }
        wx->rss_flags = WX_RSS_FIELD_IPV4 | WX_RSS_FIELD_IPV4_TCP |
-                       WX_RSS_FIELD_IPV6 | WX_RSS_FIELD_IPV6_TCP |
-                       WX_RSS_FIELD_IPV4_UDP | WX_RSS_FIELD_IPV6_UDP;
+                       WX_RSS_FIELD_IPV6 | WX_RSS_FIELD_IPV6_TCP;
 
        wx->mac_table = kcalloc(wx->mac.num_rar_entries,
                                sizeof(struct wx_mac_addr),
index bb03a9fdc711b0f2877dfe85866b4cc312bd649e..d89b9b8a0a2ce06a6762d6c597ba3808fe29b43a 100644 (file)
@@ -1208,6 +1208,12 @@ struct vf_macvlans {
 #define WX_RSS_FIELD_IPV4_UDP      BIT(6)
 #define WX_RSS_FIELD_IPV6_UDP      BIT(7)
 
+struct wx_rss_flow_map {
+       u8 flow_type;
+       u32 data;
+       u8 flag;
+};
+
 enum wx_pf_flags {
        WX_FLAG_MULTI_64_FUNC,
        WX_FLAG_SWFW_RING,
index 4363bab3349687e83675b9ffdabab85c27083f86..662f28bdde8a4340bf1cbed0841ef72d9b75b8b6 100644 (file)
@@ -137,6 +137,12 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
        .set_coalesce           = wx_set_coalesce,
        .get_channels           = wx_get_channels,
        .set_channels           = ngbe_set_channels,
+       .get_rxfh_fields        = wx_get_rxfh_fields,
+       .set_rxfh_fields        = wx_set_rxfh_fields,
+       .get_rxfh_indir_size    = wx_rss_indir_size,
+       .get_rxfh_key_size      = wx_get_rxfh_key_size,
+       .get_rxfh               = wx_get_rxfh,
+       .set_rxfh               = wx_set_rxfh,
        .get_msglevel           = wx_get_msglevel,
        .set_msglevel           = wx_set_msglevel,
        .get_ts_info            = wx_get_ts_info,
index b496ec502feda7f8f07328de7bbe1fc593531d58..e285b088c7b267cab0b0582ffcde15f058ccf00d 100644 (file)
@@ -560,6 +560,12 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
        .set_channels           = txgbe_set_channels,
        .get_rxnfc              = txgbe_get_rxnfc,
        .set_rxnfc              = txgbe_set_rxnfc,
+       .get_rxfh_fields        = wx_get_rxfh_fields,
+       .set_rxfh_fields        = wx_set_rxfh_fields,
+       .get_rxfh_indir_size    = wx_rss_indir_size,
+       .get_rxfh_key_size      = wx_get_rxfh_key_size,
+       .get_rxfh               = wx_get_rxfh,
+       .set_rxfh               = wx_set_rxfh,
        .get_msglevel           = wx_get_msglevel,
        .set_msglevel           = wx_set_msglevel,
        .get_ts_info            = wx_get_ts_info,