Commit e5dd661b authored by Michal Swiatkowski's avatar Michal Swiatkowski Committed by Tony Nguyen
Browse files

ice: Fix FV offset searching



Checking only protocol ids while searching for correct FVs can lead to a
situation, when incorrect FV will be added to the list. Incorrect means
that FV has correct protocol id but incorrect offset.

Call ice_get_sw_fv_list with ice_prot_lkup_ext struct which contains all
protocol ids with offsets.

With this modification allocating and collecting protocol ids list is
not longer needed.

Signed-off-by: default avatarMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: default avatarSandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 81dd9849
Loading
Loading
Loading
Loading
+9 −13
Original line number Diff line number Diff line
@@ -1871,20 +1871,19 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type req_profs,
/**
 * ice_get_sw_fv_list
 * @hw: pointer to the HW structure
 * @prot_ids: field vector to search for with a given protocol ID
 * @ids_cnt: lookup/protocol count
 * @lkups: list of protocol types
 * @bm: bitmap of field vectors to consider
 * @fv_list: Head of a list
 *
 * Finds all the field vector entries from switch block that contain
 * a given protocol ID and returns a list of structures of type
 * a given protocol ID and offset and returns a list of structures of type
 * "ice_sw_fv_list_entry". Every structure in the list has a field vector
 * definition and profile ID information
 * NOTE: The caller of the function is responsible for freeing the memory
 * allocated for every list entry.
 */
int
ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
ice_get_sw_fv_list(struct ice_hw *hw, struct ice_prot_lkup_ext *lkups,
		   unsigned long *bm, struct list_head *fv_list)
{
	struct ice_sw_fv_list_entry *fvl;
@@ -1896,7 +1895,7 @@ ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,

	memset(&state, 0, sizeof(state));

	if (!ids_cnt || !hw->seg)
	if (!lkups->n_val_words || !hw->seg)
		return -EINVAL;

	ice_seg = hw->seg;
@@ -1915,20 +1914,17 @@ ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
		if (!test_bit((u16)offset, bm))
			continue;

		for (i = 0; i < ids_cnt; i++) {
		for (i = 0; i < lkups->n_val_words; i++) {
			int j;

			/* This code assumes that if a switch field vector line
			 * has a matching protocol, then this line will contain
			 * the entries necessary to represent every field in
			 * that protocol header.
			 */
			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
				if (fv->ew[j].prot_id == prot_ids[i])
				if (fv->ew[j].prot_id ==
				    lkups->fv_words[i].prot_id &&
				    fv->ew[j].off == lkups->fv_words[i].off)
					break;
			if (j >= hw->blk[ICE_BLK_SW].es.fvw)
				break;
			if (i + 1 == ids_cnt) {
			if (i + 1 == lkups->n_val_words) {
				fvl = devm_kzalloc(ice_hw_to_dev(hw),
						   sizeof(*fvl), GFP_KERNEL);
				if (!fvl)
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type type,
void
ice_init_prof_result_bm(struct ice_hw *hw);
int
ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt,
ice_get_sw_fv_list(struct ice_hw *hw, struct ice_prot_lkup_ext *lkups,
		   unsigned long *bm, struct list_head *fv_list);
int
ice_pkg_buf_unreserve_section(struct ice_buf_build *bld, u16 count);
+2 −37
Original line number Diff line number Diff line
@@ -4734,41 +4734,6 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
	return status;
}

/**
 * ice_get_fv - get field vectors/extraction sequences for spec. lookup types
 * @hw: pointer to hardware structure
 * @lkups: lookup elements or match criteria for the advanced recipe, one
 *	   structure per protocol header
 * @lkups_cnt: number of protocols
 * @bm: bitmap of field vectors to consider
 * @fv_list: pointer to a list that holds the returned field vectors
 */
static int
ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
	   unsigned long *bm, struct list_head *fv_list)
{
	u8 *prot_ids;
	int status;
	u16 i;

	prot_ids = kcalloc(lkups_cnt, sizeof(*prot_ids), GFP_KERNEL);
	if (!prot_ids)
		return -ENOMEM;

	for (i = 0; i < lkups_cnt; i++)
		if (!ice_prot_type_to_id(lkups[i].type, &prot_ids[i])) {
			status = -EIO;
			goto free_mem;
		}

	/* Find field vectors that include all specified protocol types */
	status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, bm, fv_list);

free_mem:
	kfree(prot_ids);
	return status;
}

/**
 * ice_tun_type_match_word - determine if tun type needs a match mask
 * @tun_type: tunnel type
@@ -4917,11 +4882,11 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,

	/* Get bitmap of field vectors (profiles) that are compatible with the
	 * rule request; only these will be searched in the subsequent call to
	 * ice_get_fv.
	 * ice_get_sw_fv_list.
	 */
	ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);

	status = ice_get_fv(hw, lkups, lkups_cnt, fv_bitmap, &rm->fv_list);
	status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list);
	if (status)
		goto err_unroll;