get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/57930/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 57930,
    "url": "http://patches.dpdk.org/api/patches/57930/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190826105105.19121-28-qi.z.zhang@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20190826105105.19121-28-qi.z.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190826105105.19121-28-qi.z.zhang@intel.com",
    "date": "2019-08-26T10:50:29",
    "name": "[27/63] net/ice/base: improve switch advanced rule",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "eb1a9dd3168ccf9d57fb90898064d76d0432c076",
    "submitter": {
        "id": 504,
        "url": "http://patches.dpdk.org/api/people/504/?format=api",
        "name": "Qi Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "http://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190826105105.19121-28-qi.z.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 6119,
            "url": "http://patches.dpdk.org/api/series/6119/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=6119",
            "date": "2019-08-26T10:50:02",
            "name": "net/ice/base: update base code",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/6119/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/57930/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/57930/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 57C351C02D;\n\tMon, 26 Aug 2019 12:50:09 +0200 (CEST)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id A66621BF82\n\tfor <dev@dpdk.org>; Mon, 26 Aug 2019 12:49:15 +0200 (CEST)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t26 Aug 2019 03:49:15 -0700",
            "from dpdk51.sh.intel.com ([10.67.110.245])\n\tby orsmga003.jf.intel.com with ESMTP; 26 Aug 2019 03:49:13 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.64,431,1559545200\"; d=\"scan'208\";a=\"182402280\"",
        "From": "Qi Zhang <qi.z.zhang@intel.com>",
        "To": "wenzhuo.lu@intel.com,\n\tqiming.yang@intel.com",
        "Cc": "dev@dpdk.org, xiaolong.ye@intel.com, Qi Zhang <qi.z.zhang@intel.com>,\n\tDan Nowlin <dan.nowlin@intel.com>,\n\tPaul M Stillwell Jr <paul.m.stillwell.jr@intel.com>",
        "Date": "Mon, 26 Aug 2019 18:50:29 +0800",
        "Message-Id": "<20190826105105.19121-28-qi.z.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.13.6",
        "In-Reply-To": "<20190826105105.19121-1-qi.z.zhang@intel.com>",
        "References": "<20190826105105.19121-1-qi.z.zhang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 27/63] net/ice/base: improve switch advanced rule",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Correct algorithm to detect free field vector indexes to be\nused for recipe line result values. The code now scans all\nrecipes that are associated with all the field vector being\ntarged for a new recipe to detect which result indexes are\nunused.\n\nChange recipe chaining code to place recipe on a single line\nif it will fit, rather than looking to break things apart\naccording to preferred combinations.\n\nThese improvements fix a condition where recipes were getting\nadded with conflicting result index values.\n\nSigned-off-by: Dan Nowlin <dan.nowlin@intel.com>\nSigned-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>\nSigned-off-by: Qi Zhang <qi.z.zhang@intel.com>\n---\n drivers/net/ice/base/ice_bitops.h |  31 ++++\n drivers/net/ice/base/ice_switch.c | 354 +++++++++++++++++++++++++++++---------\n drivers/net/ice/base/ice_switch.h |   5 +\n 3 files changed, 309 insertions(+), 81 deletions(-)",
    "diff": "diff --git a/drivers/net/ice/base/ice_bitops.h b/drivers/net/ice/base/ice_bitops.h\nindex a3a67eb4b..f0aa8ce88 100644\n--- a/drivers/net/ice/base/ice_bitops.h\n+++ b/drivers/net/ice/base/ice_bitops.h\n@@ -229,6 +229,37 @@ ice_or_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,\n }\n \n /**\n+ * ice_xor_bitmap - bitwise XOR 2 bitmaps and store result in dst bitmap\n+ * @dst: Destination bitmap that receive the result of the operation\n+ * @bmp1: The first bitmap of XOR operation\n+ * @bmp2: The second bitmap to XOR with the first\n+ * @size: Size of the bitmaps in bits\n+ *\n+ * This function performs a bitwise XOR on two \"source\" bitmaps of the same size\n+ * and stores the result to \"dst\" bitmap. The \"dst\" bitmap must be of the same\n+ * size as the \"source\" bitmaps to avoid buffer overflows.\n+ */\n+static inline void\n+ice_xor_bitmap(ice_bitmap_t *dst, const ice_bitmap_t *bmp1,\n+\t       const ice_bitmap_t *bmp2, u16 size)\n+{\n+\tice_bitmap_t mask;\n+\tu16 i;\n+\n+\t/* Handle all but last chunk*/\n+\tfor (i = 0; i < BITS_TO_CHUNKS(size) - 1; i++)\n+\t\tdst[i] = bmp1[i] ^ bmp2[i];\n+\n+\t/* We want to only XOR bits within the size. Furthermore, we also do\n+\t * not want to modify destination bits which are beyond the specified\n+\t * size. Use a bitmask to ensure that we only modify the bits that are\n+\t * within the specified size.\n+\t */\n+\tmask = LAST_CHUNK_MASK(size);\n+\tdst[i] = (dst[i] & ~mask) | ((bmp1[i] ^ bmp2[i]) & mask);\n+}\n+\n+/**\n  * ice_find_next_bit - Find the index of the next set bit of a bitmap\n  * @bitmap: the bitmap to scan\n  * @size: the size in bits of the bitmap\ndiff --git a/drivers/net/ice/base/ice_switch.c b/drivers/net/ice/base/ice_switch.c\nindex f88addec6..2b0c7c7a3 100644\n--- a/drivers/net/ice/base/ice_switch.c\n+++ b/drivers/net/ice/base/ice_switch.c\n@@ -440,11 +440,47 @@ dummy_pppoe_packet[] = {\n /* this is a recipe to profile association bitmap */\n static ice_declare_bitmap(recipe_to_profile[ICE_MAX_NUM_RECIPES],\n \t\t\t  ICE_MAX_NUM_PROFILES);\n-static ice_declare_bitmap(available_result_ids, ICE_CHAIN_FV_INDEX_START + 1);\n+\n+/* this is a profile to recipe association bitmap */\n+static ice_declare_bitmap(profile_to_recipe[ICE_MAX_NUM_PROFILES],\n+\t\t\t  ICE_MAX_NUM_RECIPES);\n \n static void ice_get_recp_to_prof_map(struct ice_hw *hw);\n \n /**\n+ * ice_collect_result_idx - copy result index values\n+ * @buf: buffer that contains the result index\n+ * @recp: the recipe struct to copy data into\n+ */\n+static void ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,\n+\t\t\t\t   struct ice_sw_recipe *recp)\n+{\n+\tif (buf->content.result_indx & ICE_AQ_RECIPE_ID_IS_ROOT)\n+\t\tice_set_bit(buf->content.result_indx &\n+\t\t\t    ~ICE_AQ_RECIPE_ID_IS_ROOT, recp->res_idxs);\n+}\n+\n+/**\n+ * ice_collect_result_idx_from_bitmap - copy result index values using bitmap\n+ * @hw: pointer to hardware structure\n+ * @recp: the recipe struct to copy data into\n+ */\n+static void\n+ice_collect_result_idx_from_bitmap(struct ice_hw *hw,\n+\t\t\t\t   struct ice_sw_recipe *recp)\n+{\n+\tu16 bit = 0;\n+\n+\twhile (ICE_MAX_NUM_RECIPES >\n+\t       (bit = ice_find_next_bit(recp->r_bitmap, ICE_MAX_NUM_RECIPES,\n+\t\t\t\t\tbit))) {\n+\t\tice_collect_result_idx(hw->switch_info->recp_list[bit].root_buf,\n+\t\t\t\t       recp);\n+\t\tbit++;\n+\t}\n+}\n+\n+/**\n  * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries\n  * @hw: pointer to hardware structure\n  * @recps: struct that we need to populate\n@@ -466,6 +502,7 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,\n \tu16 num_recps = ICE_MAX_NUM_RECIPES;\n \tstruct ice_prot_lkup_ext *lkup_exts;\n \tenum ice_status status;\n+\tu8 is_root;\n \n \t/* we need a buffer big enough to accommodate all the recipes */\n \ttmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,\n@@ -507,14 +544,10 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,\n \t\t\tstatus = ICE_ERR_NO_MEMORY;\n \t\t\tgoto err_unroll;\n \t\t}\n-\t\t/* Avoid 8th bit since its result enable bit */\n+\t\t/* When copying, clear the result index enable bit */\n \t\tresult_idxs[result_idx] = root_bufs.content.result_indx &\n \t\t\t~ICE_AQ_RECIPE_RESULT_EN;\n-\t\t/* Check if result enable bit is set */\n-\t\tif (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)\n-\t\t\tice_clear_bit(ICE_CHAIN_FV_INDEX_START -\n-\t\t\t\t      result_idxs[result_idx++],\n-\t\t\t\t      available_result_ids);\n+\n \t\tice_memcpy(r_bitmap,\n \t\t\t   recipe_to_profile[tmp[sub_recps].recipe_indx],\n \t\t\t   sizeof(r_bitmap), ICE_NONDMA_TO_NONDMA);\n@@ -566,9 +599,29 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,\n \n \tice_memcpy(recps[rid].root_buf, tmp, recps[rid].n_grp_count *\n \t\t   sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA);\n+\n+\tice_memcpy(recps[rid].r_bitmap, tmp->recipe_bitmap,\n+\t\t   sizeof(recps[rid].r_bitmap), ICE_NONDMA_TO_NONDMA);\n+\n+\tif (tmp->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)\n+\t\trecps[rid].chain_idx = tmp->content.result_indx &\n+\t\t\t~ICE_AQ_RECIPE_RESULT_EN;\n+\telse\n+\t\trecps[rid].chain_idx = ICE_INVAL_CHAIN_IND;\n+\n+\trecps[rid].root_rid = tmp->content.rid & ~ICE_AQ_RECIPE_ID_IS_ROOT;\n+\tis_root = (tmp->content.rid & ICE_AQ_RECIPE_ID_IS_ROOT) != 0;\n+\trecps[rid].is_root = is_root;\n+\trecps[rid].big_recp = (is_root && recps[rid].n_grp_count > 1);\n+\n+\t/* Copy non-result fv index values to recipe. This call will also update\n+\t * the result index bitmap appropriately.\n+\t */\n+\tice_collect_result_idx_from_bitmap(hw, &recps[rid]);\n+\n+\trecps[rid].priority = tmp->content.act_ctrl_fwd_priority;\n \trecps[rid].recp_created = true;\n-\tif (tmp[sub_recps].content.rid & ICE_AQ_RECIPE_ID_IS_ROOT)\n-\t\trecps[rid].root_rid = rid;\n+\n err_unroll:\n \tice_free(hw, tmp);\n \treturn status;\n@@ -591,10 +644,12 @@ ice_get_recp_to_prof_map(struct ice_hw *hw)\n \tfor (i = 0; i < ICE_MAX_NUM_PROFILES; i++) {\n \t\tu16 j;\n \n+\t\tice_zero_bitmap(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);\n \t\tice_zero_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);\n \t\tif (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))\n \t\t\tcontinue;\n-\n+\t\tice_memcpy(profile_to_recipe[i], r_bitmap,\n+\t\t\t   sizeof(profile_to_recipe[i]), ICE_NONDMA_TO_NONDMA);\n \t\tfor (j = 0; j < ICE_MAX_NUM_RECIPES; j++)\n \t\t\tif (ice_is_bit_set(r_bitmap, j))\n \t\t\t\tice_set_bit(i, recipe_to_profile[j]);\n@@ -1443,7 +1498,7 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,\n {\n \tstruct ice_aq_desc desc;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_aq_sw_rules\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \n \tif (opc != ice_aqc_opc_add_sw_rules &&\n \t    opc != ice_aqc_opc_update_sw_rules &&\n@@ -1476,7 +1531,7 @@ ice_aq_add_recipe(struct ice_hw *hw,\n \tstruct ice_aq_desc desc;\n \tu16 buf_size;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_aq_add_recipe\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \tcmd = &desc.params.add_get_recipe;\n \tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);\n \n@@ -1518,7 +1573,7 @@ ice_aq_get_recipe(struct ice_hw *hw,\n \tif (*num_recipes != ICE_MAX_NUM_RECIPES)\n \t\treturn ICE_ERR_PARAM;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_aq_get_recipe\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \tcmd = &desc.params.add_get_recipe;\n \tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);\n \n@@ -1549,7 +1604,7 @@ ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,\n \tstruct ice_aqc_recipe_to_profile *cmd;\n \tstruct ice_aq_desc desc;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_aq_assoc_recipe_to_prof\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \tcmd = &desc.params.recipe_to_profile;\n \tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);\n \tcmd->profile_id = CPU_TO_LE16(profile_id);\n@@ -1578,7 +1633,7 @@ ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,\n \tstruct ice_aq_desc desc;\n \tenum ice_status status;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_aq_get_recipe_to_prof\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \tcmd = &desc.params.recipe_to_profile;\n \tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);\n \tcmd->profile_id = CPU_TO_LE16(profile_id);\n@@ -2917,7 +2972,7 @@ ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,\n \tstruct ice_aq_desc desc;\n \tenum ice_status status;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_aq_get_res_descs\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \n \tcmd = &desc.params.get_res_desc;\n \n@@ -4001,7 +4056,7 @@ ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)\n \tint pkt_type;\n \tu8 recipe_id;\n \n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_set_vsi_promisc\\n\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \n \tif (!ice_is_vsi_valid(hw, vsi_handle))\n \t\treturn ICE_ERR_PARAM;\n@@ -4219,7 +4274,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,\n  */\n void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)\n {\n-\tice_debug(hw, ICE_DBG_TRACE, \"ice_remove_vsi_fltr\\n\");\n+\tice_debug(hw, ICE_DBG_TRACE, \"%s\\n\", __func__);\n \n \tice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);\n \tice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);\n@@ -4654,11 +4709,6 @@ static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts)\n \tstruct ice_sw_recipe *recp;\n \tu16 i;\n \n-\t/* Initialize available_result_ids which tracks available result idx */\n-\tfor (i = 0; i <= ICE_CHAIN_FV_INDEX_START; i++)\n-\t\tice_set_bit(ICE_CHAIN_FV_INDEX_START - i,\n-\t\t\t    available_result_ids);\n-\n \t/* Walk through existing recipes to find a match */\n \trecp = hw->switch_info->recp_list;\n \tfor (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {\n@@ -4942,19 +4992,102 @@ ice_fill_fv_word_index(struct ice_hw *hw, struct LIST_HEAD_TYPE *fv_list,\n }\n \n /**\n+ * ice_find_free_recp_res_idx - find free result indexes for recipe\n+ * @hw: pointer to hardware structure\n+ * @profiles: bitmap of profiles that will be associated with the new recipe\n+ * @free_idx: pointer to variable to receive the free index bitmap\n+ *\n+ * The algorithm used here is:\n+ *\t1. When creating a new recipe, create a set P which contains all\n+ *\t   Profiles that will be associated with our new recipe\n+ *\n+ *\t2. For each Profile p in set P:\n+ *\t    a. Add all recipes associated with Profile p into set R\n+ *\t    b. Optional : PossibleIndexes &= profile[p].possibleIndexes\n+ *\t\t[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]\n+ *\t\ti. Or just assume they all have the same possible indexes:\n+ *\t\t\t44, 45, 46, 47\n+ *\t\t\ti.e., PossibleIndexes = 0x0000F00000000000\n+ *\n+ *\t3. For each Recipe r in set R:\n+ *\t    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes\n+ *\t    b. FreeIndexes = UsedIndexes ^ PossibleIndexes\n+ *\n+ *\tFreeIndexes will contain the bits indicating the indexes free for use,\n+ *      then the code needs to update the recipe[r].used_result_idx_bits to\n+ *      indicate which indexes were selected for use by this recipe.\n+ */\n+static u16\n+ice_find_free_recp_res_idx(struct ice_hw *hw, const ice_bitmap_t *profiles,\n+\t\t\t   ice_bitmap_t *free_idx)\n+{\n+\tice_declare_bitmap(possible_idx, ICE_MAX_FV_WORDS);\n+\tice_declare_bitmap(used_idx, ICE_MAX_FV_WORDS);\n+\tice_declare_bitmap(recipes, ICE_MAX_NUM_RECIPES);\n+\tu16 count = 0;\n+\tu16 bit;\n+\n+\tice_zero_bitmap(possible_idx, ICE_MAX_FV_WORDS);\n+\tice_zero_bitmap(free_idx, ICE_MAX_FV_WORDS);\n+\tice_zero_bitmap(used_idx, ICE_MAX_FV_WORDS);\n+\tice_zero_bitmap(recipes, ICE_MAX_NUM_RECIPES);\n+\n+\tfor (bit = 0; bit < ICE_MAX_FV_WORDS; bit++)\n+\t\tif (ICE_POSSIBLE_RES_IDX & BIT_ULL(bit))\n+\t\t\tice_set_bit(bit, possible_idx);\n+\n+\t/* For each profile we are going to associate the recipe with, add the\n+\t * recipes that are associated with that profile. This will give us\n+\t * the set of recipes that our recipe may collide with.\n+\t */\n+\tbit = 0;\n+\twhile (ICE_MAX_NUM_PROFILES >\n+\t       (bit = ice_find_next_bit(profiles, ICE_MAX_NUM_PROFILES, bit))) {\n+\t\tice_or_bitmap(recipes, recipes, profile_to_recipe[bit],\n+\t\t\t      ICE_MAX_NUM_RECIPES);\n+\n+\t\tbit++;\n+\t}\n+\n+\t/* For each recipe that our new recipe may collide with, determine\n+\t * which indexes have been used.\n+\t */\n+\tfor (bit = 0; bit < ICE_MAX_NUM_RECIPES; bit++)\n+\t\tif (ice_is_bit_set(recipes, bit))\n+\t\t\tice_or_bitmap(used_idx, used_idx,\n+\t\t\t\t      hw->switch_info->recp_list[bit].res_idxs,\n+\t\t\t\t      ICE_MAX_FV_WORDS);\n+\n+\tice_xor_bitmap(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);\n+\n+\t/* return number of free indexes */\n+\tbit = 0;\n+\twhile (ICE_MAX_FV_WORDS >\n+\t       (bit = ice_find_next_bit(free_idx, ICE_MAX_FV_WORDS, bit))) {\n+\t\tcount++;\n+\t\tbit++;\n+\t}\n+\n+\treturn count;\n+}\n+\n+/**\n  * ice_add_sw_recipe - function to call AQ calls to create switch recipe\n  * @hw: pointer to hardware structure\n  * @rm: recipe management list entry\n  * @match_tun: if field vector index for tunnel needs to be programmed\n+ * @profiles: bitmap of profiles that will be assocated.\n  */\n static enum ice_status\n ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,\n-\t\t  bool match_tun)\n+\t\t  bool match_tun, ice_bitmap_t *profiles)\n {\n+\tice_declare_bitmap(result_idx_bm, ICE_MAX_FV_WORDS);\n \tstruct ice_aqc_recipe_data_elem *tmp;\n \tstruct ice_aqc_recipe_data_elem *buf;\n \tstruct ice_recp_grp_entry *entry;\n \tenum ice_status status;\n+\tu16 free_res_idx;\n \tu16 recipe_count;\n \tu8 chain_idx;\n \tu8 recps = 0;\n@@ -4964,11 +5097,16 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,\n \t * the match fields in the chaining recipe reducing the number of\n \t * chained recipes by one.\n \t */\n-\tif (rm->n_grp_count > 1)\n+\t /* check number of free result indices */\n+\tice_zero_bitmap(result_idx_bm, ICE_MAX_FV_WORDS);\n+\tfree_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);\n+\n+\tif (rm->n_grp_count > 1) {\n+\t\tif (rm->n_grp_count > free_res_idx)\n+\t\t\treturn ICE_ERR_MAX_LIMIT;\n+\n \t\trm->n_grp_count++;\n-\tif (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE ||\n-\t    (match_tun && rm->n_grp_count > (ICE_MAX_CHAIN_RECIPE - 1)))\n-\t\treturn ICE_ERR_MAX_LIMIT;\n+\t}\n \n \ttmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,\n \t\t\t\t\t\t\t    ICE_MAX_NUM_RECIPES,\n@@ -4993,9 +5131,7 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,\n \t/* Allocate the recipe resources, and configure them according to the\n \t * match fields from protocol headers and extracted field vectors.\n \t */\n-\tchain_idx = ICE_CHAIN_FV_INDEX_START -\n-\t\tice_find_first_bit(available_result_ids,\n-\t\t\t\t   ICE_CHAIN_FV_INDEX_START + 1);\n+\tchain_idx = ice_find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);\n \tLIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {\n \t\tu8 i;\n \n@@ -5037,17 +5173,24 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,\n \t\t}\n \n \t\tif (rm->n_grp_count > 1) {\n+\t\t\t/* Checks to see if there really is a valid result index\n+\t\t\t * that can be used.\n+\t\t\t */\n+\t\t\tif (chain_idx >= ICE_MAX_FV_WORDS) {\n+\t\t\t\tice_debug(hw, ICE_DBG_SW,\n+\t\t\t\t\t  \"No chain index available\\n\");\n+\t\t\t\tstatus = ICE_ERR_MAX_LIMIT;\n+\t\t\t\tgoto err_unroll;\n+\t\t\t}\n+\n \t\t\tentry->chain_idx = chain_idx;\n \t\t\tbuf[recps].content.result_indx =\n \t\t\t\tICE_AQ_RECIPE_RESULT_EN |\n \t\t\t\t((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &\n \t\t\t\t ICE_AQ_RECIPE_RESULT_DATA_M);\n-\t\t\tice_clear_bit(ICE_CHAIN_FV_INDEX_START - chain_idx,\n-\t\t\t\t      available_result_ids);\n-\t\t\tchain_idx = ICE_CHAIN_FV_INDEX_START -\n-\t\t\t\tice_find_first_bit(available_result_ids,\n-\t\t\t\t\t\t   ICE_CHAIN_FV_INDEX_START +\n-\t\t\t\t\t\t   1);\n+\t\t\tice_clear_bit(chain_idx, result_idx_bm);\n+\t\t\tchain_idx = ice_find_first_bit(result_idx_bm,\n+\t\t\t\t\t\t       ICE_MAX_FV_WORDS);\n \t\t}\n \n \t\t/* fill recipe dependencies */\n@@ -5172,19 +5315,55 @@ ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,\n \t */\n \tLIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {\n \t\tstruct ice_switch_info *sw = hw->switch_info;\n+\t\tbool is_root, idx_found = false;\n \t\tstruct ice_sw_recipe *recp;\n+\t\tu16 idx, buf_idx = 0;\n+\n+\t\t/* find buffer index for copying some data */\n+\t\tfor (idx = 0; idx < rm->n_grp_count; idx++)\n+\t\t\tif (buf[idx].recipe_indx == entry->rid) {\n+\t\t\t\tbuf_idx = idx;\n+\t\t\t\tidx_found = true;\n+\t\t\t}\n+\n+\t\tif (!idx_found) {\n+\t\t\tstatus = ICE_ERR_OUT_OF_RANGE;\n+\t\t\tgoto err_unroll;\n+\t\t}\n \n \t\trecp = &sw->recp_list[entry->rid];\n+\t\tis_root = (rm->root_rid == entry->rid);\n+\t\trecp->is_root = is_root;\n+\n \t\trecp->root_rid = entry->rid;\n+\t\trecp->big_recp = (is_root && rm->n_grp_count > 1);\n+\n \t\tice_memcpy(&recp->ext_words, entry->r_group.pairs,\n \t\t\t   entry->r_group.n_val_pairs *\n \t\t\t   sizeof(struct ice_fv_word),\n \t\t\t   ICE_NONDMA_TO_NONDMA);\n \n+\t\tice_memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,\n+\t\t\t   sizeof(recp->r_bitmap), ICE_NONDMA_TO_NONDMA);\n+\n+\t\t/* Copy non-result fv index values and masks to recipe. This\n+\t\t * call will also update the result recipe bitmask.\n+\t\t */\n+\t\tice_collect_result_idx(&buf[buf_idx], recp);\n+\n+\t\t/* for non-root recipes, also copy to the root, this allows\n+\t\t * easier matching of a complete chained recipe\n+\t\t */\n+\t\tif (!is_root)\n+\t\t\tice_collect_result_idx(&buf[buf_idx],\n+\t\t\t\t\t       &sw->recp_list[rm->root_rid]);\n+\n \t\trecp->n_ext_words = entry->r_group.n_val_pairs;\n \t\trecp->chain_idx = entry->chain_idx;\n+\t\trecp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;\n+\t\trecp->tun_type = rm->tun_type;\n \t\trecp->recp_created = true;\n-\t\trecp->big_recp = false;\n+\t\trecp->adv_rule = 1;\n \t}\n \trm->root_buf = buf;\n \tice_free(hw, tmp);\n@@ -5215,36 +5394,42 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,\n \n \trm->n_grp_count = 0;\n \n-\t/* Each switch recipe can match up to 5 words or metadata. One word in\n-\t * each recipe is used to match the switch ID. Four words are left for\n-\t * matching other values. If the new advanced recipe requires more than\n-\t * 4 words, it needs to be split into multiple recipes which are chained\n-\t * together using the intermediate result that each produces as input to\n-\t * the other recipes in the sequence.\n-\t */\n-\tgroups = ARRAY_SIZE(ice_recipe_pack);\n \n-\t/* Check if any of the preferred recipes from the grouping policy\n-\t * matches.\n-\t */\n-\tfor (i = 0; i < groups; i++)\n-\t\t/* Check if the recipe from the preferred grouping matches\n-\t\t * or is a subset of the fields that needs to be looked up.\n+\tif (lkup_exts->n_val_words > ICE_NUM_WORDS_RECIPE) {\n+\t\t/* Each switch recipe can match up to 5 words or metadata. One\n+\t\t * word in each recipe is used to match the switch ID. Four\n+\t\t * words are left for matching other values. If the new advanced\n+\t\t * recipe requires more than 4 words, it needs to be split into\n+\t\t * multiple recipes which are chained together using the\n+\t\t * intermediate result that each produces as input to the other\n+\t\t * recipes in the sequence.\n \t\t */\n-\t\tif (ice_is_recipe_subset(lkup_exts, &ice_recipe_pack[i])) {\n-\t\t\t/* This recipe can be used by itself or grouped with\n-\t\t\t * other recipes.\n+\t\tgroups = ARRAY_SIZE(ice_recipe_pack);\n+\n+\t\t/* Check if any of the preferred recipes from the grouping\n+\t\t * policy matches.\n+\t\t */\n+\t\tfor (i = 0; i < groups; i++)\n+\t\t\t/* Check if the recipe from the preferred grouping\n+\t\t\t * matches or is a subset of the fields that needs to be\n+\t\t\t * looked up.\n \t\t\t */\n-\t\t\tentry = (struct ice_recp_grp_entry *)\n-\t\t\t\tice_malloc(hw, sizeof(*entry));\n-\t\t\tif (!entry) {\n-\t\t\t\tstatus = ICE_ERR_NO_MEMORY;\n-\t\t\t\tgoto err_unroll;\n+\t\t\tif (ice_is_recipe_subset(lkup_exts,\n+\t\t\t\t\t\t &ice_recipe_pack[i])) {\n+\t\t\t\t/* This recipe can be used by itself or grouped\n+\t\t\t\t * with other recipes.\n+\t\t\t\t */\n+\t\t\t\tentry = (struct ice_recp_grp_entry *)\n+\t\t\t\t\tice_malloc(hw, sizeof(*entry));\n+\t\t\t\tif (!entry) {\n+\t\t\t\t\tstatus = ICE_ERR_NO_MEMORY;\n+\t\t\t\t\tgoto err_unroll;\n+\t\t\t\t}\n+\t\t\t\tentry->r_group = ice_recipe_pack[i];\n+\t\t\t\tLIST_ADD(&entry->l_entry, &rm->rg_list);\n+\t\t\t\trm->n_grp_count++;\n \t\t\t}\n-\t\t\tentry->r_group = ice_recipe_pack[i];\n-\t\t\tLIST_ADD(&entry->l_entry, &rm->rg_list);\n-\t\t\trm->n_grp_count++;\n-\t\t}\n+\t}\n \n \t/* Create recipes for words that are marked not done by packing them\n \t * as best fit.\n@@ -5319,6 +5504,7 @@ static enum ice_status\n ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,\n \t\t   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)\n {\n+\tice_declare_bitmap(profiles, ICE_MAX_NUM_PROFILES);\n \tstruct ice_prot_lkup_ext *lkup_exts;\n \tstruct ice_recp_grp_entry *r_entry;\n \tstruct ice_sw_fv_list_entry *fvit;\n@@ -5355,13 +5541,6 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,\n \t\t}\n \t}\n \n-\t*rid = ice_find_recp(hw, lkup_exts);\n-\tif (*rid < ICE_MAX_NUM_RECIPES)\n-\t\t/* Success if found a recipe that match the existing criteria */\n-\t\tgoto err_free_lkup_exts;\n-\n-\t/* Recipe we need does not exist, add a recipe */\n-\n \trm = (struct ice_sw_recipe *)ice_malloc(hw, sizeof(*rm));\n \tif (!rm) {\n \t\tstatus = ICE_ERR_NO_MEMORY;\n@@ -5401,7 +5580,23 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,\n \t * recipes.\n \t */\n \tice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);\n-\tstatus = ice_add_sw_recipe(hw, rm, match_tun);\n+\n+\t/* get bitmap of all profiles the recipe will be associated with */\n+\tice_zero_bitmap(profiles, ICE_MAX_NUM_PROFILES);\n+\tLIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry,\n+\t\t\t    list_entry) {\n+\t\tice_debug(hw, ICE_DBG_SW, \"profile: %d\\n\", fvit->profile_id);\n+\t\tice_set_bit((u16)fvit->profile_id, profiles);\n+\t}\n+\n+\t/* Look for a recipe which matches our requested fv / mask list */\n+\t*rid = ice_find_recp(hw, lkup_exts);\n+\tif (*rid < ICE_MAX_NUM_RECIPES)\n+\t\t/* Success if found a recipe that match the existing criteria */\n+\t\tgoto err_unroll;\n+\n+\t/* Recipe we need does not exist, add a recipe */\n+\tstatus = ice_add_sw_recipe(hw, rm, match_tun, profiles);\n \tif (status)\n \t\tgoto err_unroll;\n \n@@ -5851,27 +6046,24 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,\n \tstruct ice_switch_info *sw;\n \tenum ice_status status;\n \tconst u8 *pkt = NULL;\n-\tbool found = false;\n+\tu16 word_cnt;\n \tu32 act = 0;\n \tu8 q_rgn;\n \n \tif (!lkups_cnt)\n \t\treturn ICE_ERR_PARAM;\n \n+\t/* get # of words we need to match */\n+\tword_cnt = 0;\n \tfor (i = 0; i < lkups_cnt; i++) {\n \t\tu16 j, *ptr;\n \n-\t\t/* Validate match masks to make sure that there is something\n-\t\t * to match.\n-\t\t */\n \t\tptr = (u16 *)&lkups[i].m_u;\n \t\tfor (j = 0; j < sizeof(lkups->m_u) / sizeof(u16); j++)\n-\t\t\tif (ptr[j] != 0) {\n-\t\t\t\tfound = true;\n-\t\t\t\tbreak;\n-\t\t\t}\n+\t\t\tif (ptr[j] != 0)\n+\t\t\t\tword_cnt++;\n \t}\n-\tif (!found)\n+\tif (!word_cnt || word_cnt > ICE_MAX_CHAIN_WORDS)\n \t\treturn ICE_ERR_PARAM;\n \n \t/* make sure that we can locate a dummy packet */\ndiff --git a/drivers/net/ice/base/ice_switch.h b/drivers/net/ice/base/ice_switch.h\nindex 4c34bc2ea..515ad3bb6 100644\n--- a/drivers/net/ice/base/ice_switch.h\n+++ b/drivers/net/ice/base/ice_switch.h\n@@ -183,6 +183,7 @@ struct ice_sw_recipe {\n \t/* For a chained recipe the root recipe is what should be used for\n \t * programming rules\n \t */\n+\tu8 is_root;\n \tu8 root_rid;\n \tu8 recp_created;\n \n@@ -226,6 +227,10 @@ struct ice_sw_recipe {\n \t/* Profiles this recipe is associated with */\n \tu8 num_profs, *prof_ids;\n \n+\t/* Possible result indexes are 44, 45, 46 and 47 */\n+#define ICE_POSSIBLE_RES_IDX 0x0000F00000000000ULL\n+\tice_declare_bitmap(res_idxs, ICE_MAX_FV_WORDS);\n+\n \t/* This allows user to specify the recipe priority.\n \t * For now, this becomes 'fwd_priority' when recipe\n \t * is created, usually recipes can have 'fwd' and 'join'\n",
    "prefixes": [
        "27/63"
    ]
}