For those devices which support 64 pools, they also support PF and VF (i.e. different pools) to configure different RSS key and hash table. Enable multiple RSS, use up to 64 RSS configurations and each pool has a specific configuration. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/libwx/wx_hw.c | 111 ++++++++++++++----- drivers/net/ethernet/wangxun/libwx/wx_hw.h | 5 + drivers/net/ethernet/wangxun/libwx/wx_lib.c | 10 +- drivers/net/ethernet/wangxun/libwx/wx_type.h | 5 + 4 files changed, 100 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 5cb353a97d6d..0bb4cddf7809 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -1998,8 +1998,17 @@ static void wx_restore_vlan(struct wx *wx) wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid); } -static void wx_store_reta(struct wx *wx) +u32 wx_rss_indir_tbl_entries(struct wx *wx) { + if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) + return 64; + else + return 128; +} + +void wx_store_reta(struct wx *wx) +{ + u32 reta_entries = wx_rss_indir_tbl_entries(wx); u8 *indir_tbl = wx->rss_indir_tbl; u32 reta = 0; u32 i; @@ -2007,36 +2016,55 @@ static void wx_store_reta(struct wx *wx) /* Fill out the redirection table as follows: * - 8 bit wide entries containing 4 bit RSS index */ - for (i = 0; i < WX_MAX_RETA_ENTRIES; i++) { + for (i = 0; i < reta_entries; i++) { reta |= indir_tbl[i] << (i & 0x3) * 8; if ((i & 3) == 3) { - wr32(wx, WX_RDB_RSSTBL(i >> 2), reta); + if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) && + test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) + wr32(wx, WX_RDB_VMRSSTBL(i >> 2, wx->num_vfs), reta); + else + wr32(wx, WX_RDB_RSSTBL(i >> 2), reta); reta = 0; } } } +void wx_store_rsskey(struct wx *wx) +{ + u32 key_size = WX_RSS_KEY_SIZE / 4; + u32 i; + + if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) && + test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) { + for (i = 0; i < key_size; i++) + wr32(wx, WX_RDB_VMRSSRK(i, wx->num_vfs), + wx->rss_key[i]); + } else { + for (i = 0; i < key_size; i++) + wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]); + } +} + static void wx_setup_reta(struct wx *wx) { u16 rss_i = wx->ring_feature[RING_F_RSS].indices; - u32 random_key_size = WX_RSS_KEY_SIZE / 4; + u32 reta_entries = wx_rss_indir_tbl_entries(wx); u32 i, j; if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) { - if (wx->mac.type == wx_mac_em) - rss_i = 1; + if (test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) + rss_i = rss_i < 2 ? 2 : rss_i; else - rss_i = rss_i < 4 ? 4 : rss_i; + rss_i = 1; } /* Fill out hash function seeds */ - for (i = 0; i < random_key_size; i++) - wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]); + wx_store_rsskey(wx); /* Fill out redirection table */ memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl)); - for (i = 0, j = 0; i < WX_MAX_RETA_ENTRIES; i++, j++) { + for (i = 0, j = 0; i < reta_entries; i++, j++) { if (j == rss_i) j = 0; @@ -2046,6 +2074,52 @@ static void wx_setup_reta(struct wx *wx) wx_store_reta(wx); } +void wx_config_rss_field(struct wx *wx) +{ + u32 rss_field; + + /* Global RSS and multiple RSS have the same type field */ + rss_field = WX_RDB_RA_CTL_RSS_IPV4 | + WX_RDB_RA_CTL_RSS_IPV4_TCP | + WX_RDB_RA_CTL_RSS_IPV4_UDP | + WX_RDB_RA_CTL_RSS_IPV6 | + WX_RDB_RA_CTL_RSS_IPV6_TCP | + WX_RDB_RA_CTL_RSS_IPV6_UDP; + + if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) && + test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) { + wr32(wx, WX_RDB_PL_CFG(wx->num_vfs), rss_field); + + /* Enable global RSS and multiple RSS to make the RSS + * field of each pool take effect. + */ + wr32m(wx, WX_RDB_RA_CTL, + WX_RDB_RA_CTL_MULTI_RSS | WX_RDB_RA_CTL_RSS_EN, + WX_RDB_RA_CTL_MULTI_RSS | WX_RDB_RA_CTL_RSS_EN); + } else { + wr32(wx, WX_RDB_RA_CTL, rss_field); + } +} + +void wx_enable_rss(struct wx *wx, bool enable) +{ + if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) && + test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) { + if (enable) + wr32m(wx, WX_RDB_PL_CFG(wx->num_vfs), + WX_RDB_PL_CFG_RSS_EN, WX_RDB_PL_CFG_RSS_EN); + else + wr32m(wx, WX_RDB_PL_CFG(wx->num_vfs), + WX_RDB_PL_CFG_RSS_EN, 0); + } else { + if (enable) + wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, + WX_RDB_RA_CTL_RSS_EN); + else + wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0); + } +} + #define WX_RDB_RSS_PL_2 FIELD_PREP(GENMASK(31, 29), 1) #define WX_RDB_RSS_PL_4 FIELD_PREP(GENMASK(31, 29), 2) static void wx_setup_psrtype(struct wx *wx) @@ -2076,27 +2150,14 @@ static void wx_setup_psrtype(struct wx *wx) static void wx_setup_mrqc(struct wx *wx) { - u32 rss_field = 0; - /* Disable indicating checksum in descriptor, enables RSS hash */ wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD); - /* Perform hash on these packet types */ - rss_field = WX_RDB_RA_CTL_RSS_IPV4 | - WX_RDB_RA_CTL_RSS_IPV4_TCP | - WX_RDB_RA_CTL_RSS_IPV4_UDP | - WX_RDB_RA_CTL_RSS_IPV6 | - WX_RDB_RA_CTL_RSS_IPV6_TCP | - WX_RDB_RA_CTL_RSS_IPV6_UDP; - netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key)); + wx_config_rss_field(wx); + wx_enable_rss(wx, wx->rss_enabled); wx_setup_reta(wx); - - if (wx->rss_enabled) - rss_field |= WX_RDB_RA_CTL_RSS_EN; - - wr32(wx, WX_RDB_RA_CTL, rss_field); } /** diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h index 2393a743b564..13857376bbad 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h @@ -39,6 +39,11 @@ void wx_set_rx_mode(struct net_device *netdev); int wx_change_mtu(struct net_device *netdev, int new_mtu); void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring); void wx_enable_rx_queue(struct wx *wx, struct wx_ring *ring); +u32 wx_rss_indir_tbl_entries(struct wx *wx); +void wx_store_reta(struct wx *wx); +void wx_store_rsskey(struct wx *wx); +void wx_config_rss_field(struct wx *wx); +void wx_enable_rss(struct wx *wx, bool enable); void wx_configure_rx(struct wx *wx); void wx_configure(struct wx *wx); void wx_start_hw(struct wx *wx); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 5086db060c61..5ec26349c91b 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -3016,14 +3016,12 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features) struct wx *wx = netdev_priv(netdev); bool need_reset = false; - if (features & NETIF_F_RXHASH) { - wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, - WX_RDB_RA_CTL_RSS_EN); + if (features & NETIF_F_RXHASH) wx->rss_enabled = true; - } else { - wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0); + else wx->rss_enabled = false; - } + + wx_enable_rss(wx, wx->rss_enabled); netdev->features = features; diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index ec63e7ec8b24..0450e276ae28 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -168,9 +168,11 @@ #define WX_RDB_PL_CFG_L2HDR BIT(3) #define WX_RDB_PL_CFG_TUN_TUNHDR BIT(4) #define WX_RDB_PL_CFG_TUN_OUTL2HDR BIT(5) +#define WX_RDB_PL_CFG_RSS_EN BIT(24) #define WX_RDB_RSSTBL(_i) (0x19400 + ((_i) * 4)) #define WX_RDB_RSSRK(_i) (0x19480 + ((_i) * 4)) #define WX_RDB_RA_CTL 0x194F4 +#define WX_RDB_RA_CTL_MULTI_RSS BIT(0) #define WX_RDB_RA_CTL_RSS_EN BIT(2) /* RSS Enable */ #define WX_RDB_RA_CTL_RSS_IPV4_TCP BIT(16) #define WX_RDB_RA_CTL_RSS_IPV4 BIT(17) @@ -180,6 +182,9 @@ #define WX_RDB_RA_CTL_RSS_IPV6_UDP BIT(23) #define WX_RDB_FDIR_MATCH 0x19558 #define WX_RDB_FDIR_MISS 0x1955C +/* VM RSS */ +#define WX_RDB_VMRSSRK(_i, _p) (0x1A000 + ((_i) * 4) + ((_p) * 0x40)) +#define WX_RDB_VMRSSTBL(_i, _p) (0x1B000 + ((_i) * 4) + ((_p) * 0x40)) /******************************* PSR Registers *******************************/ /* psr control */ -- 2.48.1 For global RSS and multiple RSS scheme, the RSS type fields are defined identically in the registers. So they can be defined as the macros WX_RSS_FIELD_* to cleanup the codes. And to prepare for the RXFH support in the next patch, move the rss_field to struct wx. Signed-off-by: Jiawen Wu --- drivers/net/ethernet/wangxun/libwx/wx_hw.c | 17 +++++++++-------- drivers/net/ethernet/wangxun/libwx/wx_type.h | 12 ++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 0bb4cddf7809..9bffa8984cbe 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -2078,16 +2078,11 @@ void wx_config_rss_field(struct wx *wx) { u32 rss_field; - /* Global RSS and multiple RSS have the same type field */ - rss_field = WX_RDB_RA_CTL_RSS_IPV4 | - WX_RDB_RA_CTL_RSS_IPV4_TCP | - WX_RDB_RA_CTL_RSS_IPV4_UDP | - WX_RDB_RA_CTL_RSS_IPV6 | - WX_RDB_RA_CTL_RSS_IPV6_TCP | - WX_RDB_RA_CTL_RSS_IPV6_UDP; - if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) && test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) { + rss_field = rd32(wx, WX_RDB_PL_CFG(wx->num_vfs)); + rss_field &= ~WX_RDB_PL_CFG_RSS_MASK; + rss_field |= FIELD_PREP(WX_RDB_PL_CFG_RSS_MASK, wx->rss_flags); wr32(wx, WX_RDB_PL_CFG(wx->num_vfs), rss_field); /* Enable global RSS and multiple RSS to make the RSS @@ -2097,6 +2092,9 @@ void wx_config_rss_field(struct wx *wx) WX_RDB_RA_CTL_MULTI_RSS | WX_RDB_RA_CTL_RSS_EN, WX_RDB_RA_CTL_MULTI_RSS | WX_RDB_RA_CTL_RSS_EN); } else { + rss_field = rd32(wx, WX_RDB_RA_CTL); + rss_field &= ~WX_RDB_RA_CTL_RSS_MASK; + rss_field |= FIELD_PREP(WX_RDB_RA_CTL_RSS_MASK, wx->rss_flags); wr32(wx, WX_RDB_RA_CTL, rss_field); } } @@ -2450,6 +2448,9 @@ int wx_sw_init(struct wx *wx) wx_err(wx, "rss key allocation failed\n"); 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->mac_table = kcalloc(wx->mac.num_rar_entries, sizeof(struct wx_mac_addr), diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 0450e276ae28..bb03a9fdc711 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -169,6 +169,7 @@ #define WX_RDB_PL_CFG_TUN_TUNHDR BIT(4) #define WX_RDB_PL_CFG_TUN_OUTL2HDR BIT(5) #define WX_RDB_PL_CFG_RSS_EN BIT(24) +#define WX_RDB_PL_CFG_RSS_MASK GENMASK(23, 16) #define WX_RDB_RSSTBL(_i) (0x19400 + ((_i) * 4)) #define WX_RDB_RSSRK(_i) (0x19480 + ((_i) * 4)) #define WX_RDB_RA_CTL 0x194F4 @@ -180,6 +181,7 @@ #define WX_RDB_RA_CTL_RSS_IPV6_TCP BIT(21) #define WX_RDB_RA_CTL_RSS_IPV4_UDP BIT(22) #define WX_RDB_RA_CTL_RSS_IPV6_UDP BIT(23) +#define WX_RDB_RA_CTL_RSS_MASK GENMASK(23, 16) #define WX_RDB_FDIR_MATCH 0x19558 #define WX_RDB_FDIR_MISS 0x1955C /* VM RSS */ @@ -1197,6 +1199,15 @@ struct vf_macvlans { u8 vf_macvlan[ETH_ALEN]; }; +#define WX_RSS_FIELD_IPV4_TCP BIT(0) +#define WX_RSS_FIELD_IPV4 BIT(1) +#define WX_RSS_FIELD_IPV4_SCTP BIT(2) +#define WX_RSS_FIELD_IPV6_SCTP BIT(3) +#define WX_RSS_FIELD_IPV6_TCP BIT(4) +#define WX_RSS_FIELD_IPV6 BIT(5) +#define WX_RSS_FIELD_IPV4_UDP BIT(6) +#define WX_RSS_FIELD_IPV6_UDP BIT(7) + enum wx_pf_flags { WX_FLAG_MULTI_64_FUNC, WX_FLAG_SWFW_RING, @@ -1307,6 +1318,7 @@ struct wx { #define WX_MAX_RETA_ENTRIES 128 #define WX_RSS_INDIR_TBL_MAX 64 u8 rss_indir_tbl[WX_MAX_RETA_ENTRIES]; + u8 rss_flags; bool rss_enabled; #define WX_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ u32 *rss_key; -- 2.48.1 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 --- .../net/ethernet/wangxun/libwx/wx_ethtool.c | 136 ++++++++++++++++++ .../net/ethernet/wangxun/libwx/wx_ethtool.h | 12 ++ drivers/net/ethernet/wangxun/libwx/wx_hw.c | 3 +- drivers/net/ethernet/wangxun/libwx/wx_type.h | 6 + .../net/ethernet/wangxun/ngbe/ngbe_ethtool.c | 6 + .../ethernet/wangxun/txgbe/txgbe_ethtool.c | 6 + 6 files changed, 167 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c index 9572b9f28e59..fd826857af4a 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c @@ -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); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h index 9e002e699eca..2ddd4039d5d2 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.h @@ -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, diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 9bffa8984cbe..73d5a2a7c4f6 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -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), diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index bb03a9fdc711..d89b9b8a0a2c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -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, diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c index 4363bab33496..662f28bdde8a 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c @@ -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, diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c index b496ec502fed..e285b088c7b2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c @@ -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, -- 2.48.1 Enable/disable SR-IOV and use ethtool to set channels will change the number of rings, thereby changing the RSS configuration that the user has set. So reject these attempts if netif_is_rxfh_configured() returns true. And remind the user to reset the RSS configuration. Signed-off-by: Jiawen Wu --- .../net/ethernet/wangxun/libwx/wx_ethtool.c | 6 ++++ drivers/net/ethernet/wangxun/libwx/wx_hw.c | 36 +++++++++---------- drivers/net/ethernet/wangxun/libwx/wx_sriov.c | 22 +++++++++--- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c index fd826857af4a..d11245231d24 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c @@ -472,6 +472,12 @@ int wx_set_channels(struct net_device *dev, if (count > wx_max_channels(wx)) return -EINVAL; + if (netif_is_rxfh_configured(wx->netdev)) { + wx_err(wx, "Cannot change channels while RXFH is configured\n"); + wx_err(wx, "Run 'ethtool -X default' to reset RSS table\n"); + return -EBUSY; + } + if (test_bit(WX_FLAG_FDIR_CAPABLE, wx->flags)) wx->ring_feature[RING_F_FDIR].limit = count; diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index 73d5a2a7c4f6..1e2713f0c921 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -2047,28 +2047,30 @@ void wx_store_rsskey(struct wx *wx) static void wx_setup_reta(struct wx *wx) { - u16 rss_i = wx->ring_feature[RING_F_RSS].indices; - u32 reta_entries = wx_rss_indir_tbl_entries(wx); - u32 i, j; - - if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) { - if (test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) - rss_i = rss_i < 2 ? 2 : rss_i; - else - rss_i = 1; - } - /* Fill out hash function seeds */ wx_store_rsskey(wx); /* Fill out redirection table */ - memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl)); + if (!netif_is_rxfh_configured(wx->netdev)) { + u16 rss_i = wx->ring_feature[RING_F_RSS].indices; + u32 reta_entries = wx_rss_indir_tbl_entries(wx); + u32 i, j; - for (i = 0, j = 0; i < reta_entries; i++, j++) { - if (j == rss_i) - j = 0; + memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl)); - wx->rss_indir_tbl[i] = j; + if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) { + if (test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) + rss_i = rss_i < 2 ? 2 : rss_i; + else + rss_i = 1; + } + + for (i = 0, j = 0; i < reta_entries; i++, j++) { + if (j == rss_i) + j = 0; + + wx->rss_indir_tbl[i] = j; + } } wx_store_reta(wx); @@ -2151,8 +2153,6 @@ static void wx_setup_mrqc(struct wx *wx) /* Disable indicating checksum in descriptor, enables RSS hash */ wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD); - netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key)); - wx_config_rss_field(wx); wx_enable_rss(wx, wx->rss_enabled); wx_setup_reta(wx); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c index c82ae137756c..c6d158cd70da 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c @@ -150,6 +150,12 @@ static int wx_pci_sriov_enable(struct pci_dev *dev, struct wx *wx = pci_get_drvdata(dev); int err = 0, i; + if (netif_is_rxfh_configured(wx->netdev)) { + wx_err(wx, "Cannot enable SR-IOV while RXFH is configured\n"); + wx_err(wx, "Run 'ethtool -X default' to reset RSS table\n"); + return -EBUSY; + } + err = __wx_enable_sriov(wx, num_vfs); if (err) return err; @@ -173,12 +179,20 @@ static int wx_pci_sriov_enable(struct pci_dev *dev, return err; } -static void wx_pci_sriov_disable(struct pci_dev *dev) +static int wx_pci_sriov_disable(struct pci_dev *dev) { struct wx *wx = pci_get_drvdata(dev); + if (netif_is_rxfh_configured(wx->netdev)) { + wx_err(wx, "Cannot disable SR-IOV while RXFH is configured\n"); + wx_err(wx, "Run 'ethtool -X default' to reset RSS table\n"); + return -EBUSY; + } + wx_disable_sriov(wx); wx_sriov_reinit(wx); + + return 0; } int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) @@ -187,10 +201,8 @@ int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) int err; if (!num_vfs) { - if (!pci_vfs_assigned(pdev)) { - wx_pci_sriov_disable(pdev); - return 0; - } + if (!pci_vfs_assigned(pdev)) + return wx_pci_sriov_disable(pdev); wx_err(wx, "can't free VFs because some are assigned to VMs.\n"); return -EBUSY; -- 2.48.1