Skip to content

Commit 9d2ee8d

Browse files
Jeff GuoNipaLocal
Jeff Guo
authored and
NipaLocal
committed
ice: enable symmetric-xor RSS for Toeplitz hash function
Allow the user to set the symmetric Toeplitz hash function via: # ethtool -X eth0 hfunc toeplitz symmetric-xor All existing RSS configurations will be converted to symmetric unless they have a non-symmetric field (other than IP src/dst and L4 src/dst ports) used for hashing. The driver will reject a new RSS configuration if such a field is requested. The hash function in the E800 NICs is set per-VSI and a specific AQ command is needed to modify the hash function. Use the AQ command to enable setting the symmetric Toeplitz RSS hash function for any VSI in the new ice_set_rss_hfunc(). When the Symmetric Toeplitz hash function is used, the hardware sets the input set of the RSS (Toeplitz) algorithm to be the XOR of the fields index by HSYMM and the fields index by the INSET registers. We use this to create a symmetric hash by setting the HSYMM registers to point to their counterparts in the INSET registers: HSYMM [src_fv] = dst_fv; HSYMM [dst_fv] = src_fv; where src_fv and dst_fv are the indexes of the protocol's src and dst fields. Reviewed-by: Wojciech Drewek <[email protected]> Signed-off-by: Jeff Guo <[email protected]> Signed-off-by: Jesse Brandeburg <[email protected]> Co-developed-by: Ahmed Zaki <[email protected]> Signed-off-by: Ahmed Zaki <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent ce09f91 commit 9d2ee8d

14 files changed

+402
-82
lines changed

drivers/net/ethernet/intel/ice/ice.h

+2
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ struct ice_vsi {
360360
/* RSS config */
361361
u16 rss_table_size; /* HW RSS table size */
362362
u16 rss_size; /* Allocated RSS queues */
363+
u8 rss_hfunc; /* User configured hash type */
363364
u8 *rss_hkey_user; /* User configured hash keys */
364365
u8 *rss_lut_user; /* User configured lookup table entries */
365366
u8 rss_lut_type; /* used to configure Get/Set RSS LUT AQ call */
@@ -920,6 +921,7 @@ int ice_set_rss_lut(struct ice_vsi *vsi, u8 *lut, u16 lut_size);
920921
int ice_get_rss_lut(struct ice_vsi *vsi, u8 *lut, u16 lut_size);
921922
int ice_set_rss_key(struct ice_vsi *vsi, u8 *seed);
922923
int ice_get_rss_key(struct ice_vsi *vsi, u8 *seed);
924+
int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc);
923925
void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);
924926
int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset);
925927
void ice_print_link_msg(struct ice_vsi *vsi, bool isup);

drivers/net/ethernet/intel/ice/ice_common.h

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <linux/bitfield.h>
88

9+
#include "ice.h"
910
#include "ice_type.h"
1011
#include "ice_nvm.h"
1112
#include "ice_flex_pipe.h"

drivers/net/ethernet/intel/ice/ice_ethtool.c

+22-17
Original file line numberDiff line numberDiff line change
@@ -2502,27 +2502,15 @@ static u32 ice_parse_hdrs(struct ethtool_rxnfc *nfc)
25022502
return hdrs;
25032503
}
25042504

2505-
#define ICE_FLOW_HASH_FLD_IPV4_SA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)
2506-
#define ICE_FLOW_HASH_FLD_IPV6_SA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)
2507-
#define ICE_FLOW_HASH_FLD_IPV4_DA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)
2508-
#define ICE_FLOW_HASH_FLD_IPV6_DA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)
2509-
#define ICE_FLOW_HASH_FLD_TCP_SRC_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)
2510-
#define ICE_FLOW_HASH_FLD_TCP_DST_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)
2511-
#define ICE_FLOW_HASH_FLD_UDP_SRC_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)
2512-
#define ICE_FLOW_HASH_FLD_UDP_DST_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)
2513-
#define ICE_FLOW_HASH_FLD_SCTP_SRC_PORT \
2514-
BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)
2515-
#define ICE_FLOW_HASH_FLD_SCTP_DST_PORT \
2516-
BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)
2517-
25182505
/**
25192506
* ice_parse_hash_flds - parses hash fields from RSS hash input
25202507
* @nfc: ethtool rxnfc command
2508+
* @symm: true if Symmetric Topelitz is set
25212509
*
25222510
* This function parses the rxnfc command and returns intended
25232511
* hash fields for RSS configuration
25242512
*/
2525-
static u64 ice_parse_hash_flds(struct ethtool_rxnfc *nfc)
2513+
static u64 ice_parse_hash_flds(struct ethtool_rxnfc *nfc, bool symm)
25262514
{
25272515
u64 hfld = ICE_HASH_INVALID;
25282516

@@ -2595,6 +2583,7 @@ ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc)
25952583
struct device *dev;
25962584
u64 hashed_flds;
25972585
int status;
2586+
bool symm;
25982587
u32 hdrs;
25992588

26002589
dev = ice_pf_to_dev(pf);
@@ -2604,7 +2593,8 @@ ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc)
26042593
return -EINVAL;
26052594
}
26062595

2607-
hashed_flds = ice_parse_hash_flds(nfc);
2596+
symm = !!(vsi->rss_hfunc == ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ);
2597+
hashed_flds = ice_parse_hash_flds(nfc, symm);
26082598
if (hashed_flds == ICE_HASH_INVALID) {
26092599
dev_dbg(dev, "Invalid hash fields, vsi num = %d\n",
26102600
vsi->vsi_num);
@@ -2621,7 +2611,9 @@ ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc)
26212611
cfg.hash_flds = hashed_flds;
26222612
cfg.addl_hdrs = hdrs;
26232613
cfg.hdr_type = ICE_RSS_ANY_HEADERS;
2624-
status = ice_add_rss_cfg(&pf->hw, vsi->idx, &cfg);
2614+
cfg.symm = symm;
2615+
2616+
status = ice_add_rss_cfg(&pf->hw, vsi, &cfg);
26252617
if (status) {
26262618
dev_dbg(dev, "ice_add_rss_cfg failed, vsi num = %d, error = %d\n",
26272619
vsi->vsi_num, status);
@@ -2642,6 +2634,7 @@ ice_get_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc)
26422634
struct ice_pf *pf = vsi->back;
26432635
struct device *dev;
26442636
u64 hash_flds;
2637+
bool symm;
26452638
u32 hdrs;
26462639

26472640
dev = ice_pf_to_dev(pf);
@@ -2660,7 +2653,7 @@ ice_get_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc)
26602653
return;
26612654
}
26622655

2663-
hash_flds = ice_get_rss_cfg(&pf->hw, vsi->idx, hdrs);
2656+
hash_flds = ice_get_rss_cfg(&pf->hw, vsi->idx, hdrs, &symm);
26642657
if (hash_flds == ICE_HASH_INVALID) {
26652658
dev_dbg(dev, "No hash fields found for the given header type, vsi num = %d\n",
26662659
vsi->vsi_num);
@@ -3242,6 +3235,8 @@ ice_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
32423235
}
32433236

32443237
rxfh->hfunc = ETH_RSS_HASH_TOP;
3238+
if (vsi->rss_hfunc == ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ)
3239+
rxfh->input_xfrm |= RXH_XFRM_SYM_XOR;
32453240

32463241
if (!rxfh->indir)
32473242
return 0;
@@ -3286,6 +3281,7 @@ ice_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh,
32863281
struct netlink_ext_ack *extack)
32873282
{
32883283
struct ice_netdev_priv *np = netdev_priv(netdev);
3284+
u8 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
32893285
struct ice_vsi *vsi = np->vsi;
32903286
struct ice_pf *pf = vsi->back;
32913287
struct device *dev;
@@ -3310,6 +3306,14 @@ ice_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh,
33103306
return -EOPNOTSUPP;
33113307
}
33123308

3309+
/* Update the VSI's hash function */
3310+
if (rxfh->input_xfrm & RXH_XFRM_SYM_XOR)
3311+
hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ;
3312+
3313+
err = ice_set_rss_hfunc(vsi, hfunc);
3314+
if (err)
3315+
return err;
3316+
33133317
if (rxfh->key) {
33143318
if (!vsi->rss_hkey_user) {
33153319
vsi->rss_hkey_user =
@@ -4220,6 +4224,7 @@ static const struct ethtool_ops ice_ethtool_ops = {
42204224
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
42214225
ETHTOOL_COALESCE_USE_ADAPTIVE |
42224226
ETHTOOL_COALESCE_RX_USECS_HIGH,
4227+
.cap_rss_sym_xor_supported = true,
42234228
.get_link_ksettings = ice_get_link_ksettings,
42244229
.set_link_ksettings = ice_set_link_ksettings,
42254230
.get_drvinfo = ice_get_drvinfo,

drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw)
441441
prof = hw->fdir_prof[flow];
442442
ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX,
443443
prof->fdir_seg[tun], TNL_SEG_CNT(tun),
444-
&hw_prof);
444+
false, &hw_prof);
445445
for (j = 0; j < prof->cnt; j++) {
446446
enum ice_flow_priority prio;
447447
u64 entry_h = 0;
@@ -682,7 +682,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,
682682
* actions (NULL) and zero actions 0.
683683
*/
684684
err = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg,
685-
TNL_SEG_CNT(tun), &prof);
685+
TNL_SEG_CNT(tun), false, &prof);
686686
if (err)
687687
return err;
688688
err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx,

drivers/net/ethernet/intel/ice/ice_flex_pipe.c

+25-8
Original file line numberDiff line numberDiff line change
@@ -1218,11 +1218,13 @@ ice_prof_has_mask(struct ice_hw *hw, enum ice_block blk, u8 prof, u16 *masks)
12181218
* @blk: HW block
12191219
* @fv: field vector to search for
12201220
* @masks: masks for FV
1221+
* @symm: symmetric setting for RSS flows
12211222
* @prof_id: receives the profile ID
12221223
*/
12231224
static int
12241225
ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk,
1225-
struct ice_fv_word *fv, u16 *masks, u8 *prof_id)
1226+
struct ice_fv_word *fv, u16 *masks, bool symm,
1227+
u8 *prof_id)
12261228
{
12271229
struct ice_es *es = &hw->blk[blk].es;
12281230
u8 i;
@@ -1236,6 +1238,9 @@ ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk,
12361238
for (i = 0; i < (u8)es->count; i++) {
12371239
u16 off = i * es->fvw;
12381240

1241+
if (blk == ICE_BLK_RSS && es->symm[i] != symm)
1242+
continue;
1243+
12391244
if (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv)))
12401245
continue;
12411246

@@ -1716,15 +1721,16 @@ ice_update_prof_masking(struct ice_hw *hw, enum ice_block blk, u16 prof_id,
17161721
}
17171722

17181723
/**
1719-
* ice_write_es - write an extraction sequence to hardware
1724+
* ice_write_es - write an extraction sequence and symmetric setting to hardware
17201725
* @hw: pointer to the HW struct
17211726
* @blk: the block in which to write the extraction sequence
17221727
* @prof_id: the profile ID to write
17231728
* @fv: pointer to the extraction sequence to write - NULL to clear extraction
1729+
* @symm: symmetric setting for RSS profiles
17241730
*/
17251731
static void
17261732
ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id,
1727-
struct ice_fv_word *fv)
1733+
struct ice_fv_word *fv, bool symm)
17281734
{
17291735
u16 off;
17301736

@@ -1737,6 +1743,9 @@ ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id,
17371743
memcpy(&hw->blk[blk].es.t[off], fv,
17381744
hw->blk[blk].es.fvw * sizeof(*fv));
17391745
}
1746+
1747+
if (blk == ICE_BLK_RSS)
1748+
hw->blk[blk].es.symm[prof_id] = symm;
17401749
}
17411750

17421751
/**
@@ -1753,7 +1762,7 @@ ice_prof_dec_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id)
17531762

17541763
if (hw->blk[blk].es.ref_count[prof_id] > 0) {
17551764
if (!--hw->blk[blk].es.ref_count[prof_id]) {
1756-
ice_write_es(hw, blk, prof_id, NULL);
1765+
ice_write_es(hw, blk, prof_id, NULL, false);
17571766
ice_free_prof_masks(hw, blk, prof_id);
17581767
return ice_free_prof_id(hw, blk, prof_id);
17591768
}
@@ -2116,6 +2125,7 @@ void ice_free_hw_tbls(struct ice_hw *hw)
21162125
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].prof_redir.t);
21172126
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.t);
21182127
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.ref_count);
2128+
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.symm);
21192129
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.written);
21202130
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.mask_ena);
21212131
devm_kfree(ice_hw_to_dev(hw), hw->blk[i].prof_id.id);
@@ -2180,6 +2190,7 @@ void ice_clear_hw_tbls(struct ice_hw *hw)
21802190

21812191
memset(es->t, 0, es->count * sizeof(*es->t) * es->fvw);
21822192
memset(es->ref_count, 0, es->count * sizeof(*es->ref_count));
2193+
memset(es->symm, 0, es->count * sizeof(*es->symm));
21832194
memset(es->written, 0, es->count * sizeof(*es->written));
21842195
memset(es->mask_ena, 0, es->count * sizeof(*es->mask_ena));
21852196

@@ -2297,6 +2308,11 @@ int ice_init_hw_tbls(struct ice_hw *hw)
22972308
if (!es->ref_count)
22982309
goto err;
22992310

2311+
es->symm = devm_kcalloc(ice_hw_to_dev(hw), es->count,
2312+
sizeof(*es->symm), GFP_KERNEL);
2313+
if (!es->symm)
2314+
goto err;
2315+
23002316
es->written = devm_kcalloc(ice_hw_to_dev(hw), es->count,
23012317
sizeof(*es->written), GFP_KERNEL);
23022318
if (!es->written)
@@ -2974,6 +2990,7 @@ ice_add_prof_attrib(struct ice_prof_map *prof, u8 ptg, u16 ptype,
29742990
* @attr_cnt: number of elements in attr array
29752991
* @es: extraction sequence (length of array is determined by the block)
29762992
* @masks: mask for extraction sequence
2993+
* @symm: symmetric setting for RSS profiles
29772994
*
29782995
* This function registers a profile, which matches a set of PTYPES with a
29792996
* particular extraction sequence. While the hardware profile is allocated
@@ -2983,7 +3000,7 @@ ice_add_prof_attrib(struct ice_prof_map *prof, u8 ptg, u16 ptype,
29833000
int
29843001
ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
29853002
const struct ice_ptype_attributes *attr, u16 attr_cnt,
2986-
struct ice_fv_word *es, u16 *masks)
3003+
struct ice_fv_word *es, u16 *masks, bool symm)
29873004
{
29883005
u32 bytes = DIV_ROUND_UP(ICE_FLOW_PTYPE_MAX, BITS_PER_BYTE);
29893006
DECLARE_BITMAP(ptgs_used, ICE_XLT1_CNT);
@@ -2997,7 +3014,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
29973014
mutex_lock(&hw->blk[blk].es.prof_map_lock);
29983015

29993016
/* search for existing profile */
3000-
status = ice_find_prof_id_with_mask(hw, blk, es, masks, &prof_id);
3017+
status = ice_find_prof_id_with_mask(hw, blk, es, masks, symm, &prof_id);
30013018
if (status) {
30023019
/* allocate profile ID */
30033020
status = ice_alloc_prof_id(hw, blk, &prof_id);
@@ -3020,7 +3037,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
30203037
goto err_ice_add_prof;
30213038

30223039
/* and write new es */
3023-
ice_write_es(hw, blk, prof_id, es);
3040+
ice_write_es(hw, blk, prof_id, es, symm);
30243041
}
30253042

30263043
ice_prof_inc_ref(hw, blk, prof_id);
@@ -3108,7 +3125,7 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
31083125
* This will search for a profile tracking ID which was previously added.
31093126
* The profile map lock should be held before calling this function.
31103127
*/
3111-
static struct ice_prof_map *
3128+
struct ice_prof_map *
31123129
ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id)
31133130
{
31143131
struct ice_prof_map *entry = NULL;

drivers/net/ethernet/intel/ice/ice_flex_pipe.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ bool ice_hw_ptype_ena(struct ice_hw *hw, u16 ptype);
4242
int
4343
ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],
4444
const struct ice_ptype_attributes *attr, u16 attr_cnt,
45-
struct ice_fv_word *es, u16 *masks);
45+
struct ice_fv_word *es, u16 *masks, bool symm);
46+
struct ice_prof_map *
47+
ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id);
4648
int
4749
ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl);
4850
int

drivers/net/ethernet/intel/ice/ice_flex_type.h

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ struct ice_es {
146146
u32 *mask_ena;
147147
struct list_head prof_map;
148148
struct ice_fv_word *t;
149+
u8 *symm; /* symmetric setting per profile (RSS blk)*/
149150
struct mutex prof_map_lock; /* protect access to profiles list */
150151
u8 *written;
151152
u8 reverse; /* set to true to reverse FV order */

0 commit comments

Comments
 (0)