diff options
Diffstat (limited to 'drivers/net/ethernet/wangxun/libwx/wx_hw.c')
-rw-r--r-- | drivers/net/ethernet/wangxun/libwx/wx_hw.c | 137 |
1 files changed, 97 insertions, 40 deletions
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index bcd07a715752..1e2713f0c921 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,45 +2016,110 @@ 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; } } } -static void wx_setup_reta(struct wx *wx) +void wx_store_rsskey(struct wx *wx) { - u16 rss_i = wx->ring_feature[RING_F_RSS].indices; - u32 random_key_size = WX_RSS_KEY_SIZE / 4; - u32 i, j; + u32 key_size = WX_RSS_KEY_SIZE / 4; + u32 i; - if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags)) { - if (wx->mac.type == wx_mac_em) - rss_i = 1; - else - rss_i = rss_i < 4 ? 4 : rss_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) +{ /* 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)); + 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; + + memset(wx->rss_indir_tbl, 0, sizeof(wx->rss_indir_tbl)); + + 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 < WX_MAX_RETA_ENTRIES; i++, j++) { - if (j == rss_i) - j = 0; + for (i = 0, j = 0; i < reta_entries; i++, j++) { + if (j == rss_i) + j = 0; - wx->rss_indir_tbl[i] = j; + wx->rss_indir_tbl[i] = j; + } } wx_store_reta(wx); } +void wx_config_rss_field(struct wx *wx) +{ + u32 rss_field; + + 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 + * 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 { + 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); + } +} + +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,31 +2150,12 @@ static void wx_setup_psrtype(struct wx *wx) static void wx_setup_mrqc(struct wx *wx) { - u32 rss_field = 0; - - /* VT, and RSS do not coexist at the same time */ - if (test_bit(WX_FLAG_VMDQ_ENABLED, wx->flags)) - return; - /* 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); } /** @@ -2393,6 +2448,8 @@ 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->mac_table = kcalloc(wx->mac.num_rar_entries, sizeof(struct wx_mac_addr), |