ice: improve TCAM priority handling for RSS profiles

Enhance TCAM priority logic to avoid conflicts between RSS profiles
with overlapping PTGs and attributes.

Track used PTG and attribute combinations.
Ensure higher-priority profiles override lower ones.
Add helper for setting TCAM flags and masks.

Ensure RSS rule consistency and prevent unintended matches.

Co-developed-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Aleksandr Loktionov 2025-10-30 14:59:48 +01:00 committed by Tony Nguyen
parent 3a6d87e2ea
commit f89e4e1512
2 changed files with 78 additions and 14 deletions

View File

@ -3577,6 +3577,19 @@ ice_move_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig,
return 0;
}
/**
* ice_set_tcam_flags - set TCAM flag don't care mask
* @mask: mask for flags
* @dc_mask: pointer to the don't care mask
*/
static void ice_set_tcam_flags(u16 mask, u8 dc_mask[ICE_TCAM_KEY_VAL_SZ])
{
u16 inverted_mask = ~mask;
/* flags are lowest u16 */
put_unaligned_le16(inverted_mask, dc_mask);
}
/**
* ice_rem_chg_tcam_ent - remove a specific TCAM entry from change list
* @hw: pointer to the HW struct
@ -3647,6 +3660,9 @@ ice_prof_tcam_ena_dis(struct ice_hw *hw, enum ice_block blk, bool enable,
if (!p)
return -ENOMEM;
/* set don't care masks for TCAM flags */
ice_set_tcam_flags(tcam->attr.mask, dc_msk);
status = ice_tcam_write_entry(hw, blk, tcam->tcam_idx, tcam->prof_id,
tcam->ptg, vsig, 0, tcam->attr.flags,
vl_msk, dc_msk, nm_msk);
@ -3672,6 +3688,34 @@ ice_prof_tcam_ena_dis(struct ice_hw *hw, enum ice_block blk, bool enable,
return status;
}
/**
* ice_ptg_attr_in_use - determine if PTG and attribute pair is in use
* @ptg_attr: pointer to the PTG and attribute pair to check
* @ptgs_used: bitmap that denotes which PTGs are in use
* @attr_used: array of PTG and attributes pairs already used
* @attr_cnt: count of entries in the attr_used array
*
* Return: true if the PTG and attribute pair is in use, false otherwise.
*/
static bool
ice_ptg_attr_in_use(struct ice_tcam_inf *ptg_attr, unsigned long *ptgs_used,
struct ice_tcam_inf *attr_used[], u16 attr_cnt)
{
u16 i;
if (!test_bit(ptg_attr->ptg, ptgs_used))
return false;
/* the PTG is used, so now look for correct attributes */
for (i = 0; i < attr_cnt; i++)
if (attr_used[i]->ptg == ptg_attr->ptg &&
attr_used[i]->attr.flags == ptg_attr->attr.flags &&
attr_used[i]->attr.mask == ptg_attr->attr.mask)
return true;
return false;
}
/**
* ice_adj_prof_priorities - adjust profile based on priorities
* @hw: pointer to the HW struct
@ -3684,10 +3728,16 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
struct list_head *chg)
{
DECLARE_BITMAP(ptgs_used, ICE_XLT1_CNT);
struct ice_tcam_inf **attr_used;
struct ice_vsig_prof *t;
int status;
u16 attr_used_cnt = 0;
int status = 0;
u16 idx;
attr_used = kcalloc(ICE_MAX_PTG_ATTRS, sizeof(*attr_used), GFP_KERNEL);
if (!attr_used)
return -ENOMEM;
bitmap_zero(ptgs_used, ICE_XLT1_CNT);
idx = vsig & ICE_VSIG_IDX_M;
@ -3705,11 +3755,15 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
u16 i;
for (i = 0; i < t->tcam_count; i++) {
bool used;
/* Scan the priorities from newest to oldest.
* Make sure that the newest profiles take priority.
*/
if (test_bit(t->tcam[i].ptg, ptgs_used) &&
t->tcam[i].in_use) {
used = ice_ptg_attr_in_use(&t->tcam[i], ptgs_used,
attr_used, attr_used_cnt);
if (used && t->tcam[i].in_use) {
/* need to mark this PTG as never match, as it
* was already in use and therefore duplicate
* (and lower priority)
@ -3719,9 +3773,8 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
&t->tcam[i],
chg);
if (status)
return status;
} else if (!test_bit(t->tcam[i].ptg, ptgs_used) &&
!t->tcam[i].in_use) {
goto free_attr_used;
} else if (!used && !t->tcam[i].in_use) {
/* need to enable this PTG, as it in not in use
* and not enabled (highest priority)
*/
@ -3730,15 +3783,21 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
&t->tcam[i],
chg);
if (status)
return status;
goto free_attr_used;
}
/* keep track of used ptgs */
__set_bit(t->tcam[i].ptg, ptgs_used);
set_bit(t->tcam[i].ptg, ptgs_used);
if (attr_used_cnt < ICE_MAX_PTG_ATTRS)
attr_used[attr_used_cnt++] = &t->tcam[i];
else
ice_debug(hw, ICE_DBG_INIT, "Warn: ICE_MAX_PTG_ATTRS exceeded\n");
}
}
return 0;
free_attr_used:
kfree(attr_used);
return status;
}
/**
@ -3821,11 +3880,15 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,
p->vsig = vsig;
p->tcam_idx = t->tcam[i].tcam_idx;
/* set don't care masks for TCAM flags */
ice_set_tcam_flags(t->tcam[i].attr.mask, dc_msk);
/* write the TCAM entry */
status = ice_tcam_write_entry(hw, blk, t->tcam[i].tcam_idx,
t->tcam[i].prof_id,
t->tcam[i].ptg, vsig, 0, 0,
vl_msk, dc_msk, nm_msk);
t->tcam[i].ptg, vsig, 0,
t->tcam[i].attr.flags, vl_msk,
dc_msk, nm_msk);
if (status) {
devm_kfree(ice_hw_to_dev(hw), p);
goto err_ice_add_prof_id_vsig;
@ -4139,9 +4202,6 @@ ice_flow_assoc_fdir_prof(struct ice_hw *hw, enum ice_block blk,
u16 vsi_num;
int status;
if (blk != ICE_BLK_FD)
return -EINVAL;
vsi_num = ice_get_hw_vsi_num(hw, dest_vsi);
status = ice_add_prof_id_flow(hw, blk, vsi_num, hdl);
if (status) {
@ -4150,6 +4210,9 @@ ice_flow_assoc_fdir_prof(struct ice_hw *hw, enum ice_block blk,
return status;
}
if (blk != ICE_BLK_FD)
return 0;
vsi_num = ice_get_hw_vsi_num(hw, fdir_vsi);
status = ice_add_prof_id_flow(hw, blk, vsi_num, hdl);
if (status) {

View File

@ -187,6 +187,7 @@ struct ice_prof_map {
};
#define ICE_INVALID_TCAM 0xFFFF
#define ICE_MAX_PTG_ATTRS 1024
struct ice_tcam_inf {
u16 tcam_idx;