Skip to content

Commit e8c4840

Browse files
committed
Merge branch 'net-wangxun-support-to-configure-rss'
Jiawen Wu says: ==================== net: wangxun: support to configure RSS Implement ethtool ops for RSS configuration, and support multiple RSS for multiple pools. ==================== Link: https://patch.msgid.link/20250926023843.34340-1-jiawenwu@trustnetic.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 1fb0e47 + 2a251b8 commit e8c4840

9 files changed

Lines changed: 304 additions & 49 deletions

File tree

drivers/net/ethernet/wangxun/libwx/wx_ethtool.c

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,142 @@ int wx_set_channels(struct net_device *dev,
481481
}
482482
EXPORT_SYMBOL(wx_set_channels);
483483

484+
u32 wx_rss_indir_size(struct net_device *netdev)
485+
{
486+
struct wx *wx = netdev_priv(netdev);
487+
488+
return wx_rss_indir_tbl_entries(wx);
489+
}
490+
EXPORT_SYMBOL(wx_rss_indir_size);
491+
492+
u32 wx_get_rxfh_key_size(struct net_device *netdev)
493+
{
494+
return WX_RSS_KEY_SIZE;
495+
}
496+
EXPORT_SYMBOL(wx_get_rxfh_key_size);
497+
498+
static void wx_get_reta(struct wx *wx, u32 *indir)
499+
{
500+
u32 reta_size = wx_rss_indir_tbl_entries(wx);
501+
u16 rss_m = wx->ring_feature[RING_F_RSS].mask;
502+
503+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags))
504+
rss_m = wx->ring_feature[RING_F_RSS].indices - 1;
505+
506+
for (u32 i = 0; i < reta_size; i++)
507+
indir[i] = wx->rss_indir_tbl[i] & rss_m;
508+
}
509+
510+
int wx_get_rxfh(struct net_device *netdev,
511+
struct ethtool_rxfh_param *rxfh)
512+
{
513+
struct wx *wx = netdev_priv(netdev);
514+
515+
rxfh->hfunc = ETH_RSS_HASH_TOP;
516+
517+
if (rxfh->indir)
518+
wx_get_reta(wx, rxfh->indir);
519+
520+
if (rxfh->key)
521+
memcpy(rxfh->key, wx->rss_key, WX_RSS_KEY_SIZE);
522+
523+
return 0;
524+
}
525+
EXPORT_SYMBOL(wx_get_rxfh);
526+
527+
int wx_set_rxfh(struct net_device *netdev,
528+
struct ethtool_rxfh_param *rxfh,
529+
struct netlink_ext_ack *extack)
530+
{
531+
struct wx *wx = netdev_priv(netdev);
532+
u32 reta_entries, i;
533+
534+
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
535+
rxfh->hfunc != ETH_RSS_HASH_TOP)
536+
return -EOPNOTSUPP;
537+
538+
reta_entries = wx_rss_indir_tbl_entries(wx);
539+
/* Fill out the redirection table */
540+
if (rxfh->indir) {
541+
for (i = 0; i < reta_entries; i++)
542+
wx->rss_indir_tbl[i] = rxfh->indir[i];
543+
544+
wx_store_reta(wx);
545+
}
546+
547+
/* Fill out the rss hash key */
548+
if (rxfh->key) {
549+
memcpy(wx->rss_key, rxfh->key, WX_RSS_KEY_SIZE);
550+
wx_store_rsskey(wx);
551+
}
552+
553+
return 0;
554+
}
555+
EXPORT_SYMBOL(wx_set_rxfh);
556+
557+
static const struct wx_rss_flow_map rss_flow_table[] = {
558+
{ TCP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_TCP },
559+
{ TCP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_TCP },
560+
{ UDP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_UDP },
561+
{ UDP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_UDP },
562+
{ SCTP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_SCTP },
563+
{ SCTP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_SCTP },
564+
};
565+
566+
int wx_get_rxfh_fields(struct net_device *dev,
567+
struct ethtool_rxfh_fields *nfc)
568+
{
569+
struct wx *wx = netdev_priv(dev);
570+
571+
nfc->data = RXH_IP_SRC | RXH_IP_DST;
572+
573+
for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
574+
const struct wx_rss_flow_map *entry = &rss_flow_table[i];
575+
576+
if (entry->flow_type == nfc->flow_type) {
577+
if (wx->rss_flags & entry->flag)
578+
nfc->data |= entry->data;
579+
break;
580+
}
581+
}
582+
583+
return 0;
584+
}
585+
EXPORT_SYMBOL(wx_get_rxfh_fields);
586+
587+
int wx_set_rxfh_fields(struct net_device *dev,
588+
const struct ethtool_rxfh_fields *nfc,
589+
struct netlink_ext_ack *extack)
590+
{
591+
struct wx *wx = netdev_priv(dev);
592+
u8 flags = wx->rss_flags;
593+
594+
if (!(nfc->data & RXH_IP_SRC) ||
595+
!(nfc->data & RXH_IP_DST))
596+
return -EINVAL;
597+
598+
for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
599+
const struct wx_rss_flow_map *entry = &rss_flow_table[i];
600+
601+
if (entry->flow_type == nfc->flow_type) {
602+
if (nfc->data & entry->data)
603+
flags |= entry->flag;
604+
else
605+
flags &= ~entry->flag;
606+
607+
if (flags != wx->rss_flags) {
608+
wx->rss_flags = flags;
609+
wx_config_rss_field(wx);
610+
}
611+
612+
return 0;
613+
}
614+
}
615+
616+
return -EINVAL;
617+
}
618+
EXPORT_SYMBOL(wx_set_rxfh_fields);
619+
484620
u32 wx_get_msglevel(struct net_device *netdev)
485621
{
486622
struct wx *wx = netdev_priv(netdev);

drivers/net/ethernet/wangxun/libwx/wx_ethtool.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@ void wx_get_channels(struct net_device *dev,
3838
struct ethtool_channels *ch);
3939
int wx_set_channels(struct net_device *dev,
4040
struct ethtool_channels *ch);
41+
u32 wx_rss_indir_size(struct net_device *netdev);
42+
u32 wx_get_rxfh_key_size(struct net_device *netdev);
43+
int wx_get_rxfh(struct net_device *netdev,
44+
struct ethtool_rxfh_param *rxfh);
45+
int wx_set_rxfh(struct net_device *netdev,
46+
struct ethtool_rxfh_param *rxfh,
47+
struct netlink_ext_ack *extack);
48+
int wx_get_rxfh_fields(struct net_device *dev,
49+
struct ethtool_rxfh_fields *cmd);
50+
int wx_set_rxfh_fields(struct net_device *dev,
51+
const struct ethtool_rxfh_fields *nfc,
52+
struct netlink_ext_ack *extack);
4153
u32 wx_get_msglevel(struct net_device *netdev);
4254
void wx_set_msglevel(struct net_device *netdev, u32 data);
4355
int wx_get_ts_info(struct net_device *dev,

drivers/net/ethernet/wangxun/libwx/wx_hw.c

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,54 +1998,128 @@ static void wx_restore_vlan(struct wx *wx)
19981998
wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid);
19991999
}
20002000

2001-
static void wx_store_reta(struct wx *wx)
2001+
u32 wx_rss_indir_tbl_entries(struct wx *wx)
20022002
{
2003+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags))
2004+
return 64;
2005+
else
2006+
return 128;
2007+
}
2008+
2009+
void wx_store_reta(struct wx *wx)
2010+
{
2011+
u32 reta_entries = wx_rss_indir_tbl_entries(wx);
20032012
u8 *indir_tbl = wx->rss_indir_tbl;
20042013
u32 reta = 0;
20052014
u32 i;
20062015

20072016
/* Fill out the redirection table as follows:
20082017
* - 8 bit wide entries containing 4 bit RSS index
20092018
*/
2010-
for (i = 0; i < WX_MAX_RETA_ENTRIES; i++) {
2019+
for (i = 0; i < reta_entries; i++) {
20112020
reta |= indir_tbl[i] << (i & 0x3) * 8;
20122021
if ((i & 3) == 3) {
2013-
wr32(wx, WX_RDB_RSSTBL(i >> 2), reta);
2022+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) &&
2023+
test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags))
2024+
wr32(wx, WX_RDB_VMRSSTBL(i >> 2, wx->num_vfs), reta);
2025+
else
2026+
wr32(wx, WX_RDB_RSSTBL(i >> 2), reta);
20142027
reta = 0;
20152028
}
20162029
}
20172030
}
20182031

2019-
static void wx_setup_reta(struct wx *wx)
2032+
void wx_store_rsskey(struct wx *wx)
20202033
{
2021-
u16 rss_i = wx->ring_feature[RING_F_RSS].indices;
2022-
u32 random_key_size = WX_RSS_KEY_SIZE / 4;
2023-
u32 i, j;
2034+
u32 key_size = WX_RSS_KEY_SIZE / 4;
2035+
u32 i;
20242036

2025-
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) {
2026-
if (wx->mac.type == wx_mac_em)
2027-
rss_i = 1;
2028-
else
2029-
rss_i = rss_i < 4 ? 4 : rss_i;
2037+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) &&
2038+
test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) {
2039+
for (i = 0; i < key_size; i++)
2040+
wr32(wx, WX_RDB_VMRSSRK(i, wx->num_vfs),
2041+
wx->rss_key[i]);
2042+
} else {
2043+
for (i = 0; i < key_size; i++)
2044+
wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]);
20302045
}
2046+
}
20312047

2048+
static void wx_setup_reta(struct wx *wx)
2049+
{
20322050
/* Fill out hash function seeds */
2033-
for (i = 0; i < random_key_size; i++)
2034-
wr32(wx, WX_RDB_RSSRK(i), wx->rss_key[i]);
2051+
wx_store_rsskey(wx);
20352052

20362053
/* Fill out redirection table */
2037-
memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl));
2054+
if (!netif_is_rxfh_configured(wx->netdev)) {
2055+
u16 rss_i = wx->ring_feature[RING_F_RSS].indices;
2056+
u32 reta_entries = wx_rss_indir_tbl_entries(wx);
2057+
u32 i, j;
20382058

2039-
for (i = 0, j = 0; i < WX_MAX_RETA_ENTRIES; i++, j++) {
2040-
if (j == rss_i)
2041-
j = 0;
2059+
memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl));
20422060

2043-
wx->rss_indir_tbl[i] = j;
2061+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) {
2062+
if (test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags))
2063+
rss_i = rss_i < 2 ? 2 : rss_i;
2064+
else
2065+
rss_i = 1;
2066+
}
2067+
2068+
for (i = 0, j = 0; i < reta_entries; i++, j++) {
2069+
if (j == rss_i)
2070+
j = 0;
2071+
2072+
wx->rss_indir_tbl[i] = j;
2073+
}
20442074
}
20452075

20462076
wx_store_reta(wx);
20472077
}
20482078

2079+
void wx_config_rss_field(struct wx *wx)
2080+
{
2081+
u32 rss_field;
2082+
2083+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) &&
2084+
test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) {
2085+
rss_field = rd32(wx, WX_RDB_PL_CFG(wx->num_vfs));
2086+
rss_field &= ~WX_RDB_PL_CFG_RSS_MASK;
2087+
rss_field |= FIELD_PREP(WX_RDB_PL_CFG_RSS_MASK, wx->rss_flags);
2088+
wr32(wx, WX_RDB_PL_CFG(wx->num_vfs), rss_field);
2089+
2090+
/* Enable global RSS and multiple RSS to make the RSS
2091+
* field of each pool take effect.
2092+
*/
2093+
wr32m(wx, WX_RDB_RA_CTL,
2094+
WX_RDB_RA_CTL_MULTI_RSS | WX_RDB_RA_CTL_RSS_EN,
2095+
WX_RDB_RA_CTL_MULTI_RSS | WX_RDB_RA_CTL_RSS_EN);
2096+
} else {
2097+
rss_field = rd32(wx, WX_RDB_RA_CTL);
2098+
rss_field &= ~WX_RDB_RA_CTL_RSS_MASK;
2099+
rss_field |= FIELD_PREP(WX_RDB_RA_CTL_RSS_MASK, wx->rss_flags);
2100+
wr32(wx, WX_RDB_RA_CTL, rss_field);
2101+
}
2102+
}
2103+
2104+
void wx_enable_rss(struct wx *wx, bool enable)
2105+
{
2106+
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags) &&
2107+
test_bit(WX_FLAG_MULTI_64_FUNC, wx->flags)) {
2108+
if (enable)
2109+
wr32m(wx, WX_RDB_PL_CFG(wx->num_vfs),
2110+
WX_RDB_PL_CFG_RSS_EN, WX_RDB_PL_CFG_RSS_EN);
2111+
else
2112+
wr32m(wx, WX_RDB_PL_CFG(wx->num_vfs),
2113+
WX_RDB_PL_CFG_RSS_EN, 0);
2114+
} else {
2115+
if (enable)
2116+
wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN,
2117+
WX_RDB_RA_CTL_RSS_EN);
2118+
else
2119+
wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0);
2120+
}
2121+
}
2122+
20492123
#define WX_RDB_RSS_PL_2 FIELD_PREP(GENMASK(31, 29), 1)
20502124
#define WX_RDB_RSS_PL_4 FIELD_PREP(GENMASK(31, 29), 2)
20512125
static void wx_setup_psrtype(struct wx *wx)
@@ -2076,27 +2150,12 @@ static void wx_setup_psrtype(struct wx *wx)
20762150

20772151
static void wx_setup_mrqc(struct wx *wx)
20782152
{
2079-
u32 rss_field = 0;
2080-
20812153
/* Disable indicating checksum in descriptor, enables RSS hash */
20822154
wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD);
20832155

2084-
/* Perform hash on these packet types */
2085-
rss_field = WX_RDB_RA_CTL_RSS_IPV4 |
2086-
WX_RDB_RA_CTL_RSS_IPV4_TCP |
2087-
WX_RDB_RA_CTL_RSS_IPV4_UDP |
2088-
WX_RDB_RA_CTL_RSS_IPV6 |
2089-
WX_RDB_RA_CTL_RSS_IPV6_TCP |
2090-
WX_RDB_RA_CTL_RSS_IPV6_UDP;
2091-
2092-
netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key));
2093-
2156+
wx_config_rss_field(wx);
2157+
wx_enable_rss(wx, wx->rss_enabled);
20942158
wx_setup_reta(wx);
2095-
2096-
if (wx->rss_enabled)
2097-
rss_field |= WX_RDB_RA_CTL_RSS_EN;
2098-
2099-
wr32(wx, WX_RDB_RA_CTL, rss_field);
21002159
}
21012160

21022161
/**
@@ -2389,6 +2448,8 @@ int wx_sw_init(struct wx *wx)
23892448
wx_err(wx, "rss key allocation failed\n");
23902449
return err;
23912450
}
2451+
wx->rss_flags = WX_RSS_FIELD_IPV4 | WX_RSS_FIELD_IPV4_TCP |
2452+
WX_RSS_FIELD_IPV6 | WX_RSS_FIELD_IPV6_TCP;
23922453

23932454
wx->mac_table = kcalloc(wx->mac.num_rar_entries,
23942455
sizeof(struct wx_mac_addr),

drivers/net/ethernet/wangxun/libwx/wx_hw.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ void wx_set_rx_mode(struct net_device *netdev);
3939
int wx_change_mtu(struct net_device *netdev, int new_mtu);
4040
void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring);
4141
void wx_enable_rx_queue(struct wx *wx, struct wx_ring *ring);
42+
u32 wx_rss_indir_tbl_entries(struct wx *wx);
43+
void wx_store_reta(struct wx *wx);
44+
void wx_store_rsskey(struct wx *wx);
45+
void wx_config_rss_field(struct wx *wx);
46+
void wx_enable_rss(struct wx *wx, bool enable);
4247
void wx_configure_rx(struct wx *wx);
4348
void wx_configure(struct wx *wx);
4449
void wx_start_hw(struct wx *wx);

drivers/net/ethernet/wangxun/libwx/wx_lib.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,14 +3016,8 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
30163016
struct wx *wx = netdev_priv(netdev);
30173017
bool need_reset = false;
30183018

3019-
if (features & NETIF_F_RXHASH) {
3020-
wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN,
3021-
WX_RDB_RA_CTL_RSS_EN);
3022-
wx->rss_enabled = true;
3023-
} else {
3024-
wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0);
3025-
wx->rss_enabled = false;
3026-
}
3019+
wx->rss_enabled = !!(features & NETIF_F_RXHASH);
3020+
wx_enable_rss(wx, wx->rss_enabled);
30273021

30283022
netdev->features = features;
30293023

0 commit comments

Comments
 (0)