diff --git a/drivers/net/ice/base/ice_bitops.h b/drivers/net/ice/base/ice_bitops.h
index a3a67eb4b..f0aa8ce88 100644
--- a/drivers/net/ice/base/ice_bitops.h
+++ b/drivers/net/ice/base/ice_bitops.h
@@ -229,6 +229,37 @@ ice_or_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
 }
 
 /**
+ * ice_xor_bitmap - bitwise XOR 2 bitmaps and store result in dst bitmap
+ * @dst: Destination bitmap that receive the result of the operation
+ * @bmp1: The first bitmap of XOR operation
+ * @bmp2: The second bitmap to XOR with the first
+ * @size: Size of the bitmaps in bits
+ *
+ * This function performs a bitwise XOR on two "source" bitmaps of the same size
+ * and stores the result to "dst" bitmap. The "dst" bitmap must be of the same
+ * size as the "source" bitmaps to avoid buffer overflows.
+ */
+static inline void
+ice_xor_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,
+	       const ice_bitmap_t *bmp2, u16 size)
+{
+	ice_bitmap_t mask;
+	u16 i;
+
+	/* Handle all but last chunk*/
+	for (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)
+		dst[i] = bmp1[i] ^ bmp2[i];
+
+	/* We want to only XOR bits within the size. Furthermore, we also do
+	 * not want to modify destination bits which are beyond the specified
+	 * size. Use a bitmask to ensure that we only modify the bits that are
+	 * within the specified size.
+	 */
+	mask = LAST_CHUNK_MASK(size);
+	dst[i] = (dst[i] & ~mask) | ((bmp1[i] ^ bmp2[i]) & mask);
+}
+
+/**
  * ice_find_next_bit - Find the index of the next set bit of a bitmap
  * @bitmap: the bitmap to scan
  * @size: the size in bits of the bitmap
diff --git a/drivers/net/ice/base/ice_switch.c b/drivers/net/ice/base/ice_switch.c
index f88addec6..2b0c7c7a3 100644
--- a/drivers/net/ice/base/ice_switch.c
+++ b/drivers/net/ice/base/ice_switch.c
@@ -440,11 +440,47 @@ dummy_pppoe_packet[] = {
 /* this is a recipe to profile association bitmap */
 static ice_declare_bitmap(recipe_to_profile[ICE_MAX_NUM_RECIPES],
 			  ICE_MAX_NUM_PROFILES);
-static ice_declare_bitmap(available_result_ids, ICE_CHAIN_FV_INDEX_START + 1);
+
+/* this is a profile to recipe association bitmap */
+static ice_declare_bitmap(profile_to_recipe[ICE_MAX_NUM_PROFILES],
+			  ICE_MAX_NUM_RECIPES);
 
 static void ice_get_recp_to_prof_map(struct ice_hw *hw);
 
 /**
+ * ice_collect_result_idx - copy result index values
+ * @buf: buffer that contains the result index
+ * @recp: the recipe struct to copy data into
+ */
+static void ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,
+				   struct ice_sw_recipe *recp)
+{
+	if (buf->content.result_indx & ICE_AQ_RECIPE_ID_IS_ROOT)
+		ice_set_bit(buf->content.result_indx &
+			    ~ICE_AQ_RECIPE_ID_IS_ROOT, recp->res_idxs);
+}
+
+/**
+ * ice_collect_result_idx_from_bitmap - copy result index values using bitmap
+ * @hw: pointer to hardware structure
+ * @recp: the recipe struct to copy data into
+ */
+static void
+ice_collect_result_idx_from_bitmap(struct ice_hw *hw,
+				   struct ice_sw_recipe *recp)
+{
+	u16 bit = 0;
+
+	while (ICE_MAX_NUM_RECIPES >
+	       (bit = ice_find_next_bit(recp->r_bitmap, ICE_MAX_NUM_RECIPES,
+					bit))) {
+		ice_collect_result_idx(hw->switch_info->recp_list[bit].root_buf,
+				       recp);
+		bit++;
+	}
+}
+
+/**
  * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
  * @hw: pointer to hardware structure
  * @recps: struct that we need to populate
@@ -466,6 +502,7 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
 	u16 num_recps = ICE_MAX_NUM_RECIPES;
 	struct ice_prot_lkup_ext *lkup_exts;
 	enum ice_status status;
+	u8 is_root;
 
 	/* we need a buffer big enough to accommodate all the recipes */
 	tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,
@@ -507,14 +544,10 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
 			status = ICE_ERR_NO_MEMORY;
 			goto err_unroll;
 		}
-		/* Avoid 8th bit since its result enable bit */
+		/* When copying, clear the result index enable bit */
 		result_idxs[result_idx] = root_bufs.content.result_indx &
 			~ICE_AQ_RECIPE_RESULT_EN;
-		/* Check if result enable bit is set */
-		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
-			ice_clear_bit(ICE_CHAIN_FV_INDEX_START -
-				      result_idxs[result_idx++],
-				      available_result_ids);
+
 		ice_memcpy(r_bitmap,
 			   recipe_to_profile[tmp[sub_recps].recipe_indx],
 			   sizeof(r_bitmap), ICE_NONDMA_TO_NONDMA);
@@ -566,9 +599,29 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
 
 	ice_memcpy(recps[rid].root_buf, tmp, recps[rid].n_grp_count *
 		   sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA);
+
+	ice_memcpy(recps[rid].r_bitmap, tmp->recipe_bitmap,
+		   sizeof(recps[rid].r_bitmap), ICE_NONDMA_TO_NONDMA);
+
+	if (tmp->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
+		recps[rid].chain_idx = tmp->content.result_indx &
+			~ICE_AQ_RECIPE_RESULT_EN;
+	else
+		recps[rid].chain_idx = ICE_INVAL_CHAIN_IND;
+
+	recps[rid].root_rid = tmp->content.rid & ~ICE_AQ_RECIPE_ID_IS_ROOT;
+	is_root = (tmp->content.rid & ICE_AQ_RECIPE_ID_IS_ROOT) != 0;
+	recps[rid].is_root = is_root;
+	recps[rid].big_recp = (is_root && recps[rid].n_grp_count > 1);
+
+	/* Copy non-result fv index values to recipe. This call will also update
+	 * the result index bitmap appropriately.
+	 */
+	ice_collect_result_idx_from_bitmap(hw, &recps[rid]);
+
+	recps[rid].priority = tmp->content.act_ctrl_fwd_priority;
 	recps[rid].recp_created = true;
-	if (tmp[sub_recps].content.rid & ICE_AQ_RECIPE_ID_IS_ROOT)
-		recps[rid].root_rid = rid;
+
 err_unroll:
 	ice_free(hw, tmp);
 	return status;
@@ -591,10 +644,12 @@ ice_get_recp_to_prof_map(struct ice_hw *hw)
 	for (i = 0; i < ICE_MAX_NUM_PROFILES; i++) {
 		u16 j;
 
+		ice_zero_bitmap(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
 		ice_zero_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
 		if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
 			continue;
-
+		ice_memcpy(profile_to_recipe[i], r_bitmap,
+			   sizeof(profile_to_recipe[i]), ICE_NONDMA_TO_NONDMA);
 		for (j = 0; j < ICE_MAX_NUM_RECIPES; j++)
 			if (ice_is_bit_set(r_bitmap, j))
 				ice_set_bit(i, recipe_to_profile[j]);
@@ -1443,7 +1498,7 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
 {
 	struct ice_aq_desc desc;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_sw_rules");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 
 	if (opc != ice_aqc_opc_add_sw_rules &&
 	    opc != ice_aqc_opc_update_sw_rules &&
@@ -1476,7 +1531,7 @@ ice_aq_add_recipe(struct ice_hw *hw,
 	struct ice_aq_desc desc;
 	u16 buf_size;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_add_recipe");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 	cmd = &desc.params.add_get_recipe;
 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
 
@@ -1518,7 +1573,7 @@ ice_aq_get_recipe(struct ice_hw *hw,
 	if (*num_recipes != ICE_MAX_NUM_RECIPES)
 		return ICE_ERR_PARAM;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_recipe");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 	cmd = &desc.params.add_get_recipe;
 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
 
@@ -1549,7 +1604,7 @@ ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
 	struct ice_aqc_recipe_to_profile *cmd;
 	struct ice_aq_desc desc;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_assoc_recipe_to_prof");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 	cmd = &desc.params.recipe_to_profile;
 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
 	cmd->profile_id = CPU_TO_LE16(profile_id);
@@ -1578,7 +1633,7 @@ ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
 	struct ice_aq_desc desc;
 	enum ice_status status;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_recipe_to_prof");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 	cmd = &desc.params.recipe_to_profile;
 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
 	cmd->profile_id = CPU_TO_LE16(profile_id);
@@ -2917,7 +2972,7 @@ ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,
 	struct ice_aq_desc desc;
 	enum ice_status status;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_res_descs");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 
 	cmd = &desc.params.get_res_desc;
 
@@ -4001,7 +4056,7 @@ ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
 	int pkt_type;
 	u8 recipe_id;
 
-	ice_debug(hw, ICE_DBG_TRACE, "ice_set_vsi_promisc\n");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 
 	if (!ice_is_vsi_valid(hw, vsi_handle))
 		return ICE_ERR_PARAM;
@@ -4219,7 +4274,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
  */
 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
 {
-	ice_debug(hw, ICE_DBG_TRACE, "ice_remove_vsi_fltr\n");
+	ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
 
 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
@@ -4654,11 +4709,6 @@ static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts)
 	struct ice_sw_recipe *recp;
 	u16 i;
 
-	/* Initialize available_result_ids which tracks available result idx */
-	for (i = 0; i <= ICE_CHAIN_FV_INDEX_START; i++)
-		ice_set_bit(ICE_CHAIN_FV_INDEX_START - i,
-			    available_result_ids);
-
 	/* Walk through existing recipes to find a match */
 	recp = hw->switch_info->recp_list;
 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
@@ -4942,19 +4992,102 @@ ice_fill_fv_word_index(struct ice_hw *hw, struct LIST_HEAD_TYPE *fv_list,
 }
 
 /**
+ * ice_find_free_recp_res_idx - find free result indexes for recipe
+ * @hw: pointer to hardware structure
+ * @profiles: bitmap of profiles that will be associated with the new recipe
+ * @free_idx: pointer to variable to receive the free index bitmap
+ *
+ * The algorithm used here is:
+ *	1. When creating a new recipe, create a set P which contains all
+ *	   Profiles that will be associated with our new recipe
+ *
+ *	2. For each Profile p in set P:
+ *	    a. Add all recipes associated with Profile p into set R
+ *	    b. Optional : PossibleIndexes &= profile[p].possibleIndexes
+ *		[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
+ *		i. Or just assume they all have the same possible indexes:
+ *			44, 45, 46, 47
+ *			i.e., PossibleIndexes = 0x0000F00000000000
+ *
+ *	3. For each Recipe r in set R:
+ *	    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
+ *	    b. FreeIndexes = UsedIndexes ^ PossibleIndexes
+ *
+ *	FreeIndexes will contain the bits indicating the indexes free for use,
+ *      then the code needs to update the recipe[r].used_result_idx_bits to
+ *      indicate which indexes were selected for use by this recipe.
+ */
+static u16
+ice_find_free_recp_res_idx(struct ice_hw *hw, const ice_bitmap_t *profiles,
+			   ice_bitmap_t *free_idx)
+{
+	ice_declare_bitmap(possible_idx, ICE_MAX_FV_WORDS);
+	ice_declare_bitmap(used_idx, ICE_MAX_FV_WORDS);
+	ice_declare_bitmap(recipes, ICE_MAX_NUM_RECIPES);
+	u16 count = 0;
+	u16 bit;
+
+	ice_zero_bitmap(possible_idx, ICE_MAX_FV_WORDS);
+	ice_zero_bitmap(free_idx, ICE_MAX_FV_WORDS);
+	ice_zero_bitmap(used_idx, ICE_MAX_FV_WORDS);
+	ice_zero_bitmap(recipes, ICE_MAX_NUM_RECIPES);
+
+	for (bit = 0; bit < ICE_MAX_FV_WORDS; bit++)
+		if (ICE_POSSIBLE_RES_IDX & BIT_ULL(bit))
+			ice_set_bit(bit, possible_idx);
+
+	/* For each profile we are going to associate the recipe with, add the
+	 * recipes that are associated with that profile. This will give us
+	 * the set of recipes that our recipe may collide with.
+	 */
+	bit = 0;
+	while (ICE_MAX_NUM_PROFILES >
+	       (bit = ice_find_next_bit(profiles, ICE_MAX_NUM_PROFILES, bit))) {
+		ice_or_bitmap(recipes, recipes, profile_to_recipe[bit],
+			      ICE_MAX_NUM_RECIPES);
+
+		bit++;
+	}
+
+	/* For each recipe that our new recipe may collide with, determine
+	 * which indexes have been used.
+	 */
+	for (bit = 0; bit < ICE_MAX_NUM_RECIPES; bit++)
+		if (ice_is_bit_set(recipes, bit))
+			ice_or_bitmap(used_idx, used_idx,
+				      hw->switch_info->recp_list[bit].res_idxs,
+				      ICE_MAX_FV_WORDS);
+
+	ice_xor_bitmap(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
+
+	/* return number of free indexes */
+	bit = 0;
+	while (ICE_MAX_FV_WORDS >
+	       (bit = ice_find_next_bit(free_idx, ICE_MAX_FV_WORDS, bit))) {
+		count++;
+		bit++;
+	}
+
+	return count;
+}
+
+/**
  * ice_add_sw_recipe - function to call AQ calls to create switch recipe
  * @hw: pointer to hardware structure
  * @rm: recipe management list entry
  * @match_tun: if field vector index for tunnel needs to be programmed
+ * @profiles: bitmap of profiles that will be assocated.
  */
 static enum ice_status
 ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
-		  bool match_tun)
+		  bool match_tun, ice_bitmap_t *profiles)
 {
+	ice_declare_bitmap(result_idx_bm, ICE_MAX_FV_WORDS);
 	struct ice_aqc_recipe_data_elem *tmp;
 	struct ice_aqc_recipe_data_elem *buf;
 	struct ice_recp_grp_entry *entry;
 	enum ice_status status;
+	u16 free_res_idx;
 	u16 recipe_count;
 	u8 chain_idx;
 	u8 recps = 0;
@@ -4964,11 +5097,16 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
 	 * the match fields in the chaining recipe reducing the number of
 	 * chained recipes by one.
 	 */
-	if (rm->n_grp_count > 1)
+	 /* check number of free result indices */
+	ice_zero_bitmap(result_idx_bm, ICE_MAX_FV_WORDS);
+	free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
+
+	if (rm->n_grp_count > 1) {
+		if (rm->n_grp_count > free_res_idx)
+			return ICE_ERR_MAX_LIMIT;
+
 		rm->n_grp_count++;
-	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE ||
-	    (match_tun && rm->n_grp_count > (ICE_MAX_CHAIN_RECIPE - 1)))
-		return ICE_ERR_MAX_LIMIT;
+	}
 
 	tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,
 							    ICE_MAX_NUM_RECIPES,
@@ -4993,9 +5131,7 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
 	/* Allocate the recipe resources, and configure them according to the
 	 * match fields from protocol headers and extracted field vectors.
 	 */
-	chain_idx = ICE_CHAIN_FV_INDEX_START -
-		ice_find_first_bit(available_result_ids,
-				   ICE_CHAIN_FV_INDEX_START + 1);
+	chain_idx = ice_find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
 	LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {
 		u8 i;
 
@@ -5037,17 +5173,24 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
 		}
 
 		if (rm->n_grp_count > 1) {
+			/* Checks to see if there really is a valid result index
+			 * that can be used.
+			 */
+			if (chain_idx >= ICE_MAX_FV_WORDS) {
+				ice_debug(hw, ICE_DBG_SW,
+					  "No chain index available\n");
+				status = ICE_ERR_MAX_LIMIT;
+				goto err_unroll;
+			}
+
 			entry->chain_idx = chain_idx;
 			buf[recps].content.result_indx =
 				ICE_AQ_RECIPE_RESULT_EN |
 				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
 				 ICE_AQ_RECIPE_RESULT_DATA_M);
-			ice_clear_bit(ICE_CHAIN_FV_INDEX_START - chain_idx,
-				      available_result_ids);
-			chain_idx = ICE_CHAIN_FV_INDEX_START -
-				ice_find_first_bit(available_result_ids,
-						   ICE_CHAIN_FV_INDEX_START +
-						   1);
+			ice_clear_bit(chain_idx, result_idx_bm);
+			chain_idx = ice_find_first_bit(result_idx_bm,
+						       ICE_MAX_FV_WORDS);
 		}
 
 		/* fill recipe dependencies */
@@ -5172,19 +5315,55 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
 	 */
 	LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {
 		struct ice_switch_info *sw = hw->switch_info;
+		bool is_root, idx_found = false;
 		struct ice_sw_recipe *recp;
+		u16 idx, buf_idx = 0;
+
+		/* find buffer index for copying some data */
+		for (idx = 0; idx < rm->n_grp_count; idx++)
+			if (buf[idx].recipe_indx == entry->rid) {
+				buf_idx = idx;
+				idx_found = true;
+			}
+
+		if (!idx_found) {
+			status = ICE_ERR_OUT_OF_RANGE;
+			goto err_unroll;
+		}
 
 		recp = &sw->recp_list[entry->rid];
+		is_root = (rm->root_rid == entry->rid);
+		recp->is_root = is_root;
+
 		recp->root_rid = entry->rid;
+		recp->big_recp = (is_root && rm->n_grp_count > 1);
+
 		ice_memcpy(&recp->ext_words, entry->r_group.pairs,
 			   entry->r_group.n_val_pairs *
 			   sizeof(struct ice_fv_word),
 			   ICE_NONDMA_TO_NONDMA);
 
+		ice_memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
+			   sizeof(recp->r_bitmap), ICE_NONDMA_TO_NONDMA);
+
+		/* Copy non-result fv index values and masks to recipe. This
+		 * call will also update the result recipe bitmask.
+		 */
+		ice_collect_result_idx(&buf[buf_idx], recp);
+
+		/* for non-root recipes, also copy to the root, this allows
+		 * easier matching of a complete chained recipe
+		 */
+		if (!is_root)
+			ice_collect_result_idx(&buf[buf_idx],
+					       &sw->recp_list[rm->root_rid]);
+
 		recp->n_ext_words = entry->r_group.n_val_pairs;
 		recp->chain_idx = entry->chain_idx;
+		recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
+		recp->tun_type = rm->tun_type;
 		recp->recp_created = true;
-		recp->big_recp = false;
+		recp->adv_rule = 1;
 	}
 	rm->root_buf = buf;
 	ice_free(hw, tmp);
@@ -5215,36 +5394,42 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
 
 	rm->n_grp_count = 0;
 
-	/* Each switch recipe can match up to 5 words or metadata. One word in
-	 * each recipe is used to match the switch ID. Four words are left for
-	 * matching other values. If the new advanced recipe requires more than
-	 * 4 words, it needs to be split into multiple recipes which are chained
-	 * together using the intermediate result that each produces as input to
-	 * the other recipes in the sequence.
-	 */
-	groups = ARRAY_SIZE(ice_recipe_pack);
 
-	/* Check if any of the preferred recipes from the grouping policy
-	 * matches.
-	 */
-	for (i = 0; i < groups; i++)
-		/* Check if the recipe from the preferred grouping matches
-		 * or is a subset of the fields that needs to be looked up.
+	if (lkup_exts->n_val_words > ICE_NUM_WORDS_RECIPE) {
+		/* Each switch recipe can match up to 5 words or metadata. One
+		 * word in each recipe is used to match the switch ID. Four
+		 * words are left for matching other values. If the new advanced
+		 * recipe requires more than 4 words, it needs to be split into
+		 * multiple recipes which are chained together using the
+		 * intermediate result that each produces as input to the other
+		 * recipes in the sequence.
 		 */
-		if (ice_is_recipe_subset(lkup_exts, &ice_recipe_pack[i])) {
-			/* This recipe can be used by itself or grouped with
-			 * other recipes.
+		groups = ARRAY_SIZE(ice_recipe_pack);
+
+		/* Check if any of the preferred recipes from the grouping
+		 * policy matches.
+		 */
+		for (i = 0; i < groups; i++)
+			/* Check if the recipe from the preferred grouping
+			 * matches or is a subset of the fields that needs to be
+			 * looked up.
 			 */
-			entry = (struct ice_recp_grp_entry *)
-				ice_malloc(hw, sizeof(*entry));
-			if (!entry) {
-				status = ICE_ERR_NO_MEMORY;
-				goto err_unroll;
+			if (ice_is_recipe_subset(lkup_exts,
+						 &ice_recipe_pack[i])) {
+				/* This recipe can be used by itself or grouped
+				 * with other recipes.
+				 */
+				entry = (struct ice_recp_grp_entry *)
+					ice_malloc(hw, sizeof(*entry));
+				if (!entry) {
+					status = ICE_ERR_NO_MEMORY;
+					goto err_unroll;
+				}
+				entry->r_group = ice_recipe_pack[i];
+				LIST_ADD(&entry->l_entry, &rm->rg_list);
+				rm->n_grp_count++;
 			}
-			entry->r_group = ice_recipe_pack[i];
-			LIST_ADD(&entry->l_entry, &rm->rg_list);
-			rm->n_grp_count++;
-		}
+	}
 
 	/* Create recipes for words that are marked not done by packing them
 	 * as best fit.
@@ -5319,6 +5504,7 @@ static enum ice_status
 ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
 {
+	ice_declare_bitmap(profiles, ICE_MAX_NUM_PROFILES);
 	struct ice_prot_lkup_ext *lkup_exts;
 	struct ice_recp_grp_entry *r_entry;
 	struct ice_sw_fv_list_entry *fvit;
@@ -5355,13 +5541,6 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 		}
 	}
 
-	*rid = ice_find_recp(hw, lkup_exts);
-	if (*rid < ICE_MAX_NUM_RECIPES)
-		/* Success if found a recipe that match the existing criteria */
-		goto err_free_lkup_exts;
-
-	/* Recipe we need does not exist, add a recipe */
-
 	rm = (struct ice_sw_recipe *)ice_malloc(hw, sizeof(*rm));
 	if (!rm) {
 		status = ICE_ERR_NO_MEMORY;
@@ -5401,7 +5580,23 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 	 * recipes.
 	 */
 	ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
-	status = ice_add_sw_recipe(hw, rm, match_tun);
+
+	/* get bitmap of all profiles the recipe will be associated with */
+	ice_zero_bitmap(profiles, ICE_MAX_NUM_PROFILES);
+	LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry,
+			    list_entry) {
+		ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
+		ice_set_bit((u16)fvit->profile_id, profiles);
+	}
+
+	/* Look for a recipe which matches our requested fv / mask list */
+	*rid = ice_find_recp(hw, lkup_exts);
+	if (*rid < ICE_MAX_NUM_RECIPES)
+		/* Success if found a recipe that match the existing criteria */
+		goto err_unroll;
+
+	/* Recipe we need does not exist, add a recipe */
+	status = ice_add_sw_recipe(hw, rm, match_tun, profiles);
 	if (status)
 		goto err_unroll;
 
@@ -5851,27 +6046,24 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 	struct ice_switch_info *sw;
 	enum ice_status status;
 	const u8 *pkt = NULL;
-	bool found = false;
+	u16 word_cnt;
 	u32 act = 0;
 	u8 q_rgn;
 
 	if (!lkups_cnt)
 		return ICE_ERR_PARAM;
 
+	/* get # of words we need to match */
+	word_cnt = 0;
 	for (i = 0; i < lkups_cnt; i++) {
 		u16 j, *ptr;
 
-		/* Validate match masks to make sure that there is something
-		 * to match.
-		 */
 		ptr = (u16 *)&lkups[i].m_u;
 		for (j = 0; j < sizeof(lkups->m_u) / sizeof(u16); j++)
-			if (ptr[j] != 0) {
-				found = true;
-				break;
-			}
+			if (ptr[j] != 0)
+				word_cnt++;
 	}
-	if (!found)
+	if (!word_cnt || word_cnt > ICE_MAX_CHAIN_WORDS)
 		return ICE_ERR_PARAM;
 
 	/* make sure that we can locate a dummy packet */
diff --git a/drivers/net/ice/base/ice_switch.h b/drivers/net/ice/base/ice_switch.h
index 4c34bc2ea..515ad3bb6 100644
--- a/drivers/net/ice/base/ice_switch.h
+++ b/drivers/net/ice/base/ice_switch.h
@@ -183,6 +183,7 @@ struct ice_sw_recipe {
 	/* For a chained recipe the root recipe is what should be used for
 	 * programming rules
 	 */
+	u8 is_root;
 	u8 root_rid;
 	u8 recp_created;
 
@@ -226,6 +227,10 @@ struct ice_sw_recipe {
 	/* Profiles this recipe is associated with */
 	u8 num_profs, *prof_ids;
 
+	/* Possible result indexes are 44, 45, 46 and 47 */
+#define ICE_POSSIBLE_RES_IDX 0x0000F00000000000ULL
+	ice_declare_bitmap(res_idxs, ICE_MAX_FV_WORDS);
+
 	/* This allows user to specify the recipe priority.
 	 * For now, this becomes 'fwd_priority' when recipe
 	 * is created, usually recipes can have 'fwd' and 'join'
