Commit f89e4e15 authored by Aleksandr Loktionov's avatar Aleksandr Loktionov Committed by Tony Nguyen
Browse files

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: default avatarDan Nowlin <dan.nowlin@intel.com>
Signed-off-by: default avatarDan Nowlin <dan.nowlin@intel.com>
Signed-off-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 3a6d87e2
Loading
Loading
Loading
Loading
+77 −14
Original line number Diff line number Diff line
@@ -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) {
+1 −0
Original line number Diff line number Diff line
@@ -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;