Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1225075/?format=api
{ "id": 1225075, "url": "http://patchwork.ozlabs.org/api/patches/1225075/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200117153919.50321-5-anthony.l.nguyen@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20200117153919.50321-5-anthony.l.nguyen@intel.com>", "list_archive_url": null, "date": "2020-01-17T15:39:16", "name": "[S36,5/8] ice: Optimize table usage", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "ec2fb710d4cb5ec39d60b0881e03a287c4428681", "submitter": { "id": 68875, "url": "http://patchwork.ozlabs.org/api/people/68875/?format=api", "name": "Tony Nguyen", "email": "anthony.l.nguyen@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200117153919.50321-5-anthony.l.nguyen@intel.com/mbox/", "series": [ { "id": 153932, "url": "http://patchwork.ozlabs.org/api/series/153932/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=153932", "date": "2020-01-17T15:39:19", "name": "[S36,1/8] ice: Enable writing hardware filtering tables", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/153932/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1225075/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1225075/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org; spf=pass (sender SPF authorized)\n\tsmtp.mailfrom=osuosl.org (client-ip=140.211.166.133;\n\thelo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 47zyzc26MSz9sR4\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 18 Jan 2020 11:12:12 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id A818088163;\n\tSat, 18 Jan 2020 00:12:10 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id FH9q6RUeNGH2; Sat, 18 Jan 2020 00:12:05 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 412D088168;\n\tSat, 18 Jan 2020 00:12:04 +0000 (UTC)", "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\tby ash.osuosl.org (Postfix) with ESMTP id 3A2AC1BF846\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:12:02 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 364A922115\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:12:02 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id dRYQt24LKiaY for <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:11:57 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby silver.osuosl.org (Postfix) with ESMTPS id 2812C2226B\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tSat, 18 Jan 2020 00:11:57 +0000 (UTC)", "from orsmga005.jf.intel.com ([10.7.209.41])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t17 Jan 2020 16:11:56 -0800", "from unknown (HELO localhost.jf.intel.com) ([10.166.244.174])\n\tby orsmga005.jf.intel.com with ESMTP; 17 Jan 2020 16:11:55 -0800" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.70,332,1574150400\"; d=\"scan'208\";a=\"398818587\"", "From": "Tony Nguyen <anthony.l.nguyen@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Fri, 17 Jan 2020 07:39:16 -0800", "Message-Id": "<20200117153919.50321-5-anthony.l.nguyen@intel.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20200117153919.50321-1-anthony.l.nguyen@intel.com>", "References": "<20200117153919.50321-1-anthony.l.nguyen@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [PATCH S36 5/8] ice: Optimize table usage", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "Attempt to optimize TCAM entries and reduce table resource usage by\nsearching for profiles that can be reused. Provide resource cleanup\nof both hardware and software structures.\n\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\nSigned-off-by: Henry Tieman <henry.w.tieman@intel.com>\n---\n .../net/ethernet/intel/ice/ice_flex_pipe.c | 394 ++++++++++++++++++\n .../net/ethernet/intel/ice/ice_flex_pipe.h | 4 +\n drivers/net/ethernet/intel/ice/ice_flow.c | 338 +++++++++++++++\n drivers/net/ethernet/intel/ice/ice_flow.h | 10 +\n drivers/net/ethernet/intel/ice/ice_lib.c | 28 +-\n 5 files changed, 773 insertions(+), 1 deletion(-)", "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\nindex 6dca611b408a..99208946224c 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n@@ -1921,6 +1921,26 @@ ice_alloc_prof_id(struct ice_hw *hw, enum ice_block blk, u8 *prof_id)\n \treturn status;\n }\n \n+/**\n+ * ice_free_prof_id - free profile ID\n+ * @hw: pointer to the HW struct\n+ * @blk: the block from which to free the profile ID\n+ * @prof_id: the profile ID to free\n+ *\n+ * This function frees a profile ID, which also corresponds to a Field Vector.\n+ */\n+static enum ice_status\n+ice_free_prof_id(struct ice_hw *hw, enum ice_block blk, u8 prof_id)\n+{\n+\tu16 tmp_prof_id = (u16)prof_id;\n+\tu16 res_type;\n+\n+\tif (!ice_prof_id_rsrc_type(blk, &res_type))\n+\t\treturn ICE_ERR_PARAM;\n+\n+\treturn ice_free_hw_res(hw, res_type, 1, &tmp_prof_id);\n+}\n+\n /**\n * ice_prof_inc_ref - increment reference count for profile\n * @hw: pointer to the HW struct\n@@ -1962,6 +1982,28 @@ ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id,\n \t}\n }\n \n+/**\n+ * ice_prof_dec_ref - decrement reference count for profile\n+ * @hw: pointer to the HW struct\n+ * @blk: the block from which to free the profile ID\n+ * @prof_id: the profile ID for which to decrement the reference count\n+ */\n+static enum ice_status\n+ice_prof_dec_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id)\n+{\n+\tif (prof_id > hw->blk[blk].es.count)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (hw->blk[blk].es.ref_count[prof_id] > 0) {\n+\t\tif (!--hw->blk[blk].es.ref_count[prof_id]) {\n+\t\t\tice_write_es(hw, blk, prof_id, NULL);\n+\t\t\treturn ice_free_prof_id(hw, blk, prof_id);\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n /* Block / table section IDs */\n static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = {\n \t/* SWITCH */\n@@ -2218,6 +2260,64 @@ void ice_fill_blk_tbls(struct ice_hw *hw)\n \tice_init_sw_db(hw);\n }\n \n+/**\n+ * ice_free_prof_map - free profile map\n+ * @hw: pointer to the hardware structure\n+ * @blk_idx: HW block index\n+ */\n+static void ice_free_prof_map(struct ice_hw *hw, u8 blk_idx)\n+{\n+\tstruct ice_es *es = &hw->blk[blk_idx].es;\n+\tstruct ice_prof_map *del, *tmp;\n+\n+\tmutex_lock(&es->prof_map_lock);\n+\tlist_for_each_entry_safe(del, tmp, &es->prof_map, list) {\n+\t\tlist_del(&del->list);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), del);\n+\t}\n+\tINIT_LIST_HEAD(&es->prof_map);\n+\tmutex_unlock(&es->prof_map_lock);\n+}\n+\n+/**\n+ * ice_free_flow_profs - free flow profile entries\n+ * @hw: pointer to the hardware structure\n+ * @blk_idx: HW block index\n+ */\n+static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx)\n+{\n+\tstruct ice_flow_prof *p, *tmp;\n+\n+\tmutex_lock(&hw->fl_profs_locks[blk_idx]);\n+\tlist_for_each_entry_safe(p, tmp, &hw->fl_profs[blk_idx], l_entry) {\n+\t\tlist_del(&p->l_entry);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), p);\n+\t}\n+\tmutex_unlock(&hw->fl_profs_locks[blk_idx]);\n+\n+\t/* if driver is in reset and tables are being cleared\n+\t * re-initialize the flow profile list heads\n+\t */\n+\tINIT_LIST_HEAD(&hw->fl_profs[blk_idx]);\n+}\n+\n+/**\n+ * ice_free_vsig_tbl - free complete VSIG table entries\n+ * @hw: pointer to the hardware structure\n+ * @blk: the HW block on which to free the VSIG table entries\n+ */\n+static void ice_free_vsig_tbl(struct ice_hw *hw, enum ice_block blk)\n+{\n+\tu16 i;\n+\n+\tif (!hw->blk[blk].xlt2.vsig_tbl)\n+\t\treturn;\n+\n+\tfor (i = 1; i < ICE_MAX_VSIGS; i++)\n+\t\tif (hw->blk[blk].xlt2.vsig_tbl[i].in_use)\n+\t\t\tice_vsig_free(hw, blk, i);\n+}\n+\n /**\n * ice_free_hw_tbls - free hardware table memory\n * @hw: pointer to the hardware structure\n@@ -2231,11 +2331,15 @@ void ice_free_hw_tbls(struct ice_hw *hw)\n \t\tif (hw->blk[i].is_list_init) {\n \t\t\tstruct ice_es *es = &hw->blk[i].es;\n \n+\t\t\tice_free_prof_map(hw, i);\n \t\t\tmutex_destroy(&es->prof_map_lock);\n+\n+\t\t\tice_free_flow_profs(hw, i);\n \t\t\tmutex_destroy(&hw->fl_profs_locks[i]);\n \n \t\t\thw->blk[i].is_list_init = false;\n \t\t}\n+\t\tice_free_vsig_tbl(hw, (enum ice_block)i);\n \t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt1.ptypes);\n \t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt1.ptg_tbl);\n \t\tdevm_kfree(ice_hw_to_dev(hw), hw->blk[i].xlt1.t);\n@@ -2283,6 +2387,13 @@ void ice_clear_hw_tbls(struct ice_hw *hw)\n \t\tstruct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;\n \t\tstruct ice_es *es = &hw->blk[i].es;\n \n+\t\tif (hw->blk[i].is_list_init) {\n+\t\t\tice_free_prof_map(hw, i);\n+\t\t\tice_free_flow_profs(hw, i);\n+\t\t}\n+\n+\t\tice_free_vsig_tbl(hw, (enum ice_block)i);\n+\n \t\tmemset(xlt1->ptypes, 0, xlt1->count * sizeof(*xlt1->ptypes));\n \t\tmemset(xlt1->ptg_tbl, 0,\n \t\t ICE_MAX_PTGS * sizeof(*xlt1->ptg_tbl));\n@@ -2956,6 +3067,25 @@ ice_search_prof_id(struct ice_hw *hw, enum ice_block blk, u64 id)\n \treturn entry;\n }\n \n+/**\n+ * ice_vsig_prof_id_count - count profiles in a VSIG\n+ * @hw: pointer to the HW struct\n+ * @blk: hardware block\n+ * @vsig: VSIG to remove the profile from\n+ */\n+static u16\n+ice_vsig_prof_id_count(struct ice_hw *hw, enum ice_block blk, u16 vsig)\n+{\n+\tu16 idx = vsig & ICE_VSIG_IDX_M, count = 0;\n+\tstruct ice_vsig_prof *p;\n+\n+\tlist_for_each_entry(p, &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,\n+\t\t\t list)\n+\t\tcount++;\n+\n+\treturn count;\n+}\n+\n /**\n * ice_rel_tcam_idx - release a TCAM index\n * @hw: pointer to the HW struct\n@@ -3064,6 +3194,117 @@ ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig,\n \treturn ice_vsig_free(hw, blk, vsig);\n }\n \n+/**\n+ * ice_rem_prof_id_vsig - remove a specific profile from a VSIG\n+ * @hw: pointer to the HW struct\n+ * @blk: hardware block\n+ * @vsig: VSIG to remove the profile from\n+ * @hdl: profile handle indicating which profile to remove\n+ * @chg: list to receive a record of changes\n+ */\n+static enum ice_status\n+ice_rem_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,\n+\t\t struct list_head *chg)\n+{\n+\tu16 idx = vsig & ICE_VSIG_IDX_M;\n+\tstruct ice_vsig_prof *p, *t;\n+\tenum ice_status status;\n+\n+\tlist_for_each_entry_safe(p, t,\n+\t\t\t\t &hw->blk[blk].xlt2.vsig_tbl[idx].prop_lst,\n+\t\t\t\t list)\n+\t\tif (p->profile_cookie == hdl) {\n+\t\t\tif (ice_vsig_prof_id_count(hw, blk, vsig) == 1)\n+\t\t\t\t/* this is the last profile, remove the VSIG */\n+\t\t\t\treturn ice_rem_vsig(hw, blk, vsig, chg);\n+\n+\t\t\tstatus = ice_rem_prof_id(hw, blk, p);\n+\t\t\tif (!status) {\n+\t\t\t\tlist_del(&p->list);\n+\t\t\t\tdevm_kfree(ice_hw_to_dev(hw), p);\n+\t\t\t}\n+\t\t\treturn status;\n+\t\t}\n+\n+\treturn ICE_ERR_DOES_NOT_EXIST;\n+}\n+\n+/**\n+ * ice_rem_flow_all - remove all flows with a particular profile\n+ * @hw: pointer to the HW struct\n+ * @blk: hardware block\n+ * @id: profile tracking ID\n+ */\n+static enum ice_status\n+ice_rem_flow_all(struct ice_hw *hw, enum ice_block blk, u64 id)\n+{\n+\tstruct ice_chs_chg *del, *tmp;\n+\tenum ice_status status;\n+\tstruct list_head chg;\n+\tu16 i;\n+\n+\tINIT_LIST_HEAD(&chg);\n+\n+\tfor (i = 1; i < ICE_MAX_VSIGS; i++)\n+\t\tif (hw->blk[blk].xlt2.vsig_tbl[i].in_use) {\n+\t\t\tif (ice_has_prof_vsig(hw, blk, i, id)) {\n+\t\t\t\tstatus = ice_rem_prof_id_vsig(hw, blk, i, id,\n+\t\t\t\t\t\t\t &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_flow_all;\n+\t\t\t}\n+\t\t}\n+\n+\tstatus = ice_upd_prof_hw(hw, blk, &chg);\n+\n+err_ice_rem_flow_all:\n+\tlist_for_each_entry_safe(del, tmp, &chg, list_entry) {\n+\t\tlist_del(&del->list_entry);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), del);\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_rem_prof - remove profile\n+ * @hw: pointer to the HW struct\n+ * @blk: hardware block\n+ * @id: profile tracking ID\n+ *\n+ * This will remove the profile specified by the ID parameter, which was\n+ * previously created through ice_add_prof. If any existing entries\n+ * are associated with this profile, they will be removed as well.\n+ */\n+enum ice_status ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id)\n+{\n+\tstruct ice_prof_map *pmap;\n+\tenum ice_status status;\n+\n+\tmutex_lock(&hw->blk[blk].es.prof_map_lock);\n+\n+\tpmap = ice_search_prof_id_low(hw, blk, id);\n+\tif (!pmap) {\n+\t\tstatus = ICE_ERR_DOES_NOT_EXIST;\n+\t\tgoto err_ice_rem_prof;\n+\t}\n+\n+\t/* remove all flows with this profile */\n+\tstatus = ice_rem_flow_all(hw, blk, pmap->profile_cookie);\n+\tif (status)\n+\t\tgoto err_ice_rem_prof;\n+\n+\t/* dereference profile, and possibly remove */\n+\tice_prof_dec_ref(hw, blk, pmap->prof_id);\n+\n+\tlist_del(&pmap->list);\n+\tdevm_kfree(ice_hw_to_dev(hw), pmap);\n+\n+err_ice_rem_prof:\n+\tmutex_unlock(&hw->blk[blk].es.prof_map_lock);\n+\treturn status;\n+}\n+\n /**\n * ice_get_prof - get profile\n * @hw: pointer to the HW struct\n@@ -3714,3 +3955,156 @@ ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)\n \n \treturn status;\n }\n+\n+/**\n+ * ice_rem_prof_from_list - remove a profile from list\n+ * @hw: pointer to the HW struct\n+ * @lst: list to remove the profile from\n+ * @hdl: the profile handle indicating the profile to remove\n+ */\n+static enum ice_status\n+ice_rem_prof_from_list(struct ice_hw *hw, struct list_head *lst, u64 hdl)\n+{\n+\tstruct ice_vsig_prof *ent, *tmp;\n+\n+\tlist_for_each_entry_safe(ent, tmp, lst, list)\n+\t\tif (ent->profile_cookie == hdl) {\n+\t\t\tlist_del(&ent->list);\n+\t\t\tdevm_kfree(ice_hw_to_dev(hw), ent);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\treturn ICE_ERR_DOES_NOT_EXIST;\n+}\n+\n+/**\n+ * ice_rem_prof_id_flow - remove flow\n+ * @hw: pointer to the HW struct\n+ * @blk: hardware block\n+ * @vsi: the VSI from which to remove the profile specified by ID\n+ * @hdl: profile tracking handle\n+ *\n+ * Calling this function will update the hardware tables to remove the\n+ * profile indicated by the ID parameter for the VSIs specified in the VSI\n+ * array. Once successfully called, the flow will be disabled.\n+ */\n+enum ice_status\n+ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)\n+{\n+\tstruct ice_vsig_prof *tmp1, *del1;\n+\tstruct ice_chs_chg *tmp, *del;\n+\tstruct list_head chg, copy;\n+\tenum ice_status status;\n+\tu16 vsig;\n+\n+\tINIT_LIST_HEAD(©);\n+\tINIT_LIST_HEAD(&chg);\n+\n+\t/* determine if VSI is already part of a VSIG */\n+\tstatus = ice_vsig_find_vsi(hw, blk, vsi, &vsig);\n+\tif (!status && vsig) {\n+\t\tbool last_profile;\n+\t\tbool only_vsi;\n+\t\tu16 ref;\n+\n+\t\t/* found in VSIG */\n+\t\tlast_profile = ice_vsig_prof_id_count(hw, blk, vsig) == 1;\n+\t\tstatus = ice_vsig_get_ref(hw, blk, vsig, &ref);\n+\t\tif (status)\n+\t\t\tgoto err_ice_rem_prof_id_flow;\n+\t\tonly_vsi = (ref == 1);\n+\n+\t\tif (only_vsi) {\n+\t\t\t/* If the original VSIG only contains one reference,\n+\t\t\t * which will be the requesting VSI, then the VSI is not\n+\t\t\t * sharing entries and we can simply remove the specific\n+\t\t\t * characteristics from the VSIG.\n+\t\t\t */\n+\n+\t\t\tif (last_profile) {\n+\t\t\t\t/* If there are no profiles left for this VSIG,\n+\t\t\t\t * then simply remove the the VSIG.\n+\t\t\t\t */\n+\t\t\t\tstatus = ice_rem_vsig(hw, blk, vsig, &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\t\t\t} else {\n+\t\t\t\tstatus = ice_rem_prof_id_vsig(hw, blk, vsig,\n+\t\t\t\t\t\t\t hdl, &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\n+\t\t\t\t/* Adjust priorities */\n+\t\t\t\tstatus = ice_adj_prof_priorities(hw, blk, vsig,\n+\t\t\t\t\t\t\t\t &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\t\t\t}\n+\n+\t\t} else {\n+\t\t\t/* Make a copy of the VSIG's list of Profiles */\n+\t\t\tstatus = ice_get_profs_vsig(hw, blk, vsig, ©);\n+\t\t\tif (status)\n+\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\n+\t\t\t/* Remove specified profile entry from the list */\n+\t\t\tstatus = ice_rem_prof_from_list(hw, ©, hdl);\n+\t\t\tif (status)\n+\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\n+\t\t\tif (list_empty(©)) {\n+\t\t\t\tstatus = ice_move_vsi(hw, blk, vsi,\n+\t\t\t\t\t\t ICE_DEFAULT_VSIG, &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\n+\t\t\t} else if (!ice_find_dup_props_vsig(hw, blk, ©,\n+\t\t\t\t\t\t\t &vsig)) {\n+\t\t\t\t/* found an exact match */\n+\t\t\t\t/* add or move VSI to the VSIG that matches */\n+\t\t\t\t/* Search for a VSIG with a matching profile\n+\t\t\t\t * list\n+\t\t\t\t */\n+\n+\t\t\t\t/* Found match, move VSI to the matching VSIG */\n+\t\t\t\tstatus = ice_move_vsi(hw, blk, vsi, vsig, &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\t\t\t} else {\n+\t\t\t\t/* since no existing VSIG supports this\n+\t\t\t\t * characteristic pattern, we need to create a\n+\t\t\t\t * new VSIG and TCAM entries\n+\t\t\t\t */\n+\t\t\t\tstatus = ice_create_vsig_from_lst(hw, blk, vsi,\n+\t\t\t\t\t\t\t\t ©, &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\n+\t\t\t\t/* Adjust priorities */\n+\t\t\t\tstatus = ice_adj_prof_priorities(hw, blk, vsig,\n+\t\t\t\t\t\t\t\t &chg);\n+\t\t\t\tif (status)\n+\t\t\t\t\tgoto err_ice_rem_prof_id_flow;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tstatus = ICE_ERR_DOES_NOT_EXIST;\n+\t}\n+\n+\t/* update hardware tables */\n+\tif (!status)\n+\t\tstatus = ice_upd_prof_hw(hw, blk, &chg);\n+\n+err_ice_rem_prof_id_flow:\n+\tlist_for_each_entry_safe(del, tmp, &chg, list_entry) {\n+\t\tlist_del(&del->list_entry);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), del);\n+\t}\n+\n+\tlist_for_each_entry_safe(del1, tmp1, ©, list) {\n+\t\tlist_del(&del1->list);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), del1);\n+\t}\n+\n+\treturn status;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\nindex 33e4510da24c..c7b5e1a6ea2b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n@@ -23,6 +23,8 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],\n \t struct ice_fv_word *es);\n enum ice_status\n ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl);\n+enum ice_status\n+ice_rem_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl);\n enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buff, u32 len);\n enum ice_status\n ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len);\n@@ -31,4 +33,6 @@ void ice_free_seg(struct ice_hw *hw);\n void ice_fill_blk_tbls(struct ice_hw *hw);\n void ice_clear_hw_tbls(struct ice_hw *hw);\n void ice_free_hw_tbls(struct ice_hw *hw);\n+enum ice_status\n+ice_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 id);\n #endif /* _ICE_FLEX_PIPE_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c\nindex 1bbf4b6ed7d2..3cd270d96fb8 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.c\n@@ -377,6 +377,77 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)\n \treturn status;\n }\n \n+#define ICE_FLOW_FIND_PROF_CHK_FLDS\t0x00000001\n+#define ICE_FLOW_FIND_PROF_CHK_VSI\t0x00000002\n+#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR\t0x00000004\n+\n+/**\n+ * ice_flow_find_prof_conds - Find a profile matching headers and conditions\n+ * @hw: pointer to the HW struct\n+ * @blk: classification stage\n+ * @dir: flow direction\n+ * @segs: array of one or more packet segments that describe the flow\n+ * @segs_cnt: number of packet segments provided\n+ * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)\n+ * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)\n+ */\n+static struct ice_flow_prof *\n+ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,\n+\t\t\t enum ice_flow_dir dir, struct ice_flow_seg_info *segs,\n+\t\t\t u8 segs_cnt, u16 vsi_handle, u32 conds)\n+{\n+\tstruct ice_flow_prof *p, *prof = NULL;\n+\n+\tmutex_lock(&hw->fl_profs_locks[blk]);\n+\tlist_for_each_entry(p, &hw->fl_profs[blk], l_entry)\n+\t\tif ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&\n+\t\t segs_cnt && segs_cnt == p->segs_cnt) {\n+\t\t\tu8 i;\n+\n+\t\t\t/* Check for profile-VSI association if specified */\n+\t\t\tif ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&\n+\t\t\t ice_is_vsi_valid(hw, vsi_handle) &&\n+\t\t\t !test_bit(vsi_handle, p->vsis))\n+\t\t\t\tcontinue;\n+\n+\t\t\t/* Protocol headers must be checked. Matched fields are\n+\t\t\t * checked if specified.\n+\t\t\t */\n+\t\t\tfor (i = 0; i < segs_cnt; i++)\n+\t\t\t\tif (segs[i].hdrs != p->segs[i].hdrs ||\n+\t\t\t\t ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&\n+\t\t\t\t segs[i].match != p->segs[i].match))\n+\t\t\t\t\tbreak;\n+\n+\t\t\t/* A match is found if all segments are matched */\n+\t\t\tif (i == segs_cnt) {\n+\t\t\t\tprof = p;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\tmutex_unlock(&hw->fl_profs_locks[blk]);\n+\n+\treturn prof;\n+}\n+\n+/**\n+ * ice_flow_find_prof_id - Look up a profile with given profile ID\n+ * @hw: pointer to the HW struct\n+ * @blk: classification stage\n+ * @prof_id: unique ID to identify this flow profile\n+ */\n+static struct ice_flow_prof *\n+ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)\n+{\n+\tstruct ice_flow_prof *p;\n+\n+\tlist_for_each_entry(p, &hw->fl_profs[blk], l_entry)\n+\t\tif (p->id == prof_id)\n+\t\t\treturn p;\n+\n+\treturn NULL;\n+}\n+\n /**\n * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields\n * @hw: pointer to the HW struct\n@@ -450,6 +521,31 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,\n \treturn status;\n }\n \n+/**\n+ * ice_flow_rem_prof_sync - remove a flow profile\n+ * @hw: pointer to the hardware structure\n+ * @blk: classification stage\n+ * @prof: pointer to flow profile to remove\n+ *\n+ * Assumption: the caller has acquired the lock to the profile list\n+ */\n+static enum ice_status\n+ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,\n+\t\t struct ice_flow_prof *prof)\n+{\n+\tenum ice_status status;\n+\n+\t/* Remove all hardware profiles associated with this flow profile */\n+\tstatus = ice_rem_prof(hw, blk, prof->id);\n+\tif (!status) {\n+\t\tlist_del(&prof->l_entry);\n+\t\tmutex_destroy(&prof->entries_lock);\n+\t\tdevm_kfree(ice_hw_to_dev(hw), prof);\n+\t}\n+\n+\treturn status;\n+}\n+\n /**\n * ice_flow_assoc_prof - associate a VSI with a flow profile\n * @hw: pointer to the hardware structure\n@@ -482,6 +578,38 @@ ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,\n \treturn status;\n }\n \n+/**\n+ * ice_flow_disassoc_prof - disassociate a VSI from a flow profile\n+ * @hw: pointer to the hardware structure\n+ * @blk: classification stage\n+ * @prof: pointer to flow profile\n+ * @vsi_handle: software VSI handle\n+ *\n+ * Assumption: the caller has acquired the lock to the profile list\n+ * and the software VSI handle has been validated\n+ */\n+static enum ice_status\n+ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,\n+\t\t struct ice_flow_prof *prof, u16 vsi_handle)\n+{\n+\tenum ice_status status = 0;\n+\n+\tif (test_bit(vsi_handle, prof->vsis)) {\n+\t\tstatus = ice_rem_prof_id_flow(hw, blk,\n+\t\t\t\t\t ice_get_hw_vsi_num(hw,\n+\t\t\t\t\t\t\t\t vsi_handle),\n+\t\t\t\t\t prof->id);\n+\t\tif (!status)\n+\t\t\tclear_bit(vsi_handle, prof->vsis);\n+\t\telse\n+\t\t\tice_debug(hw, ICE_DBG_FLOW,\n+\t\t\t\t \"HW profile remove failed, %d\\n\",\n+\t\t\t\t status);\n+\t}\n+\n+\treturn status;\n+}\n+\n /**\n * ice_flow_add_prof - Add a flow profile for packet segments and matched fields\n * @hw: pointer to the HW struct\n@@ -524,6 +652,35 @@ ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,\n \treturn status;\n }\n \n+/**\n+ * ice_flow_rem_prof - Remove a flow profile and all entries associated with it\n+ * @hw: pointer to the HW struct\n+ * @blk: the block for which the flow profile is to be removed\n+ * @prof_id: unique ID of the flow profile to be removed\n+ */\n+static enum ice_status\n+ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)\n+{\n+\tstruct ice_flow_prof *prof;\n+\tenum ice_status status;\n+\n+\tmutex_lock(&hw->fl_profs_locks[blk]);\n+\n+\tprof = ice_flow_find_prof_id(hw, blk, prof_id);\n+\tif (!prof) {\n+\t\tstatus = ICE_ERR_DOES_NOT_EXIST;\n+\t\tgoto out;\n+\t}\n+\n+\t/* prof becomes invalid after the call */\n+\tstatus = ice_flow_rem_prof_sync(hw, blk, prof);\n+\n+out:\n+\tmutex_unlock(&hw->fl_profs_locks[blk]);\n+\n+\treturn status;\n+}\n+\n /**\n * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer\n * @seg: packet segment the field being set belongs to\n@@ -645,6 +802,132 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,\n \treturn 0;\n }\n \n+/**\n+ * ice_rem_vsi_rss_list - remove VSI from RSS list\n+ * @hw: pointer to the hardware structure\n+ * @vsi_handle: software VSI handle\n+ *\n+ * Remove the VSI from all RSS configurations in the list.\n+ */\n+void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)\n+{\n+\tstruct ice_rss_cfg *r, *tmp;\n+\n+\tif (list_empty(&hw->rss_list_head))\n+\t\treturn;\n+\n+\tmutex_lock(&hw->rss_locks);\n+\tlist_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)\n+\t\tif (test_and_clear_bit(vsi_handle, r->vsis))\n+\t\t\tif (bitmap_empty(r->vsis, ICE_MAX_VSI)) {\n+\t\t\t\tlist_del(&r->l_entry);\n+\t\t\t\tdevm_kfree(ice_hw_to_dev(hw), r);\n+\t\t\t}\n+\tmutex_unlock(&hw->rss_locks);\n+}\n+\n+/**\n+ * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI\n+ * @hw: pointer to the hardware structure\n+ * @vsi_handle: software VSI handle\n+ *\n+ * This function will iterate through all flow profiles and disassociate\n+ * the VSI from that profile. If the flow profile has no VSIs it will\n+ * be removed.\n+ */\n+enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)\n+{\n+\tconst enum ice_block blk = ICE_BLK_RSS;\n+\tstruct ice_flow_prof *p, *t;\n+\tenum ice_status status = 0;\n+\n+\tif (!ice_is_vsi_valid(hw, vsi_handle))\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (list_empty(&hw->fl_profs[blk]))\n+\t\treturn 0;\n+\n+\tmutex_lock(&hw->fl_profs_locks[blk]);\n+\tlist_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)\n+\t\tif (test_bit(vsi_handle, p->vsis)) {\n+\t\t\tstatus = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);\n+\t\t\tif (status)\n+\t\t\t\tbreak;\n+\n+\t\t\tif (bitmap_empty(p->vsis, ICE_MAX_VSI)) {\n+\t\t\t\tstatus = ice_flow_rem_prof_sync(hw, blk, p);\n+\t\t\t\tif (status)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\tmutex_unlock(&hw->fl_profs_locks[blk]);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_rem_rss_list - remove RSS configuration from list\n+ * @hw: pointer to the hardware structure\n+ * @vsi_handle: software VSI handle\n+ * @prof: pointer to flow profile\n+ *\n+ * Assumption: lock has already been acquired for RSS list\n+ */\n+static void\n+ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)\n+{\n+\tstruct ice_rss_cfg *r, *tmp;\n+\n+\t/* Search for RSS hash fields associated to the VSI that match the\n+\t * hash configurations associated to the flow profile. If found\n+\t * remove from the RSS entry list of the VSI context and delete entry.\n+\t */\n+\tlist_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)\n+\t\tif (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&\n+\t\t r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {\n+\t\t\tclear_bit(vsi_handle, r->vsis);\n+\t\t\tif (bitmap_empty(r->vsis, ICE_MAX_VSI)) {\n+\t\t\t\tlist_del(&r->l_entry);\n+\t\t\t\tdevm_kfree(ice_hw_to_dev(hw), r);\n+\t\t\t}\n+\t\t\treturn;\n+\t\t}\n+}\n+\n+/**\n+ * ice_add_rss_list - add RSS configuration to list\n+ * @hw: pointer to the hardware structure\n+ * @vsi_handle: software VSI handle\n+ * @prof: pointer to flow profile\n+ *\n+ * Assumption: lock has already been acquired for RSS list\n+ */\n+static enum ice_status\n+ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)\n+{\n+\tstruct ice_rss_cfg *r, *rss_cfg;\n+\n+\tlist_for_each_entry(r, &hw->rss_list_head, l_entry)\n+\t\tif (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&\n+\t\t r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {\n+\t\t\tset_bit(vsi_handle, r->vsis);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\trss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),\n+\t\t\t GFP_KERNEL);\n+\tif (!rss_cfg)\n+\t\treturn ICE_ERR_NO_MEMORY;\n+\n+\trss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;\n+\trss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;\n+\tset_bit(vsi_handle, rss_cfg->vsis);\n+\n+\tlist_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);\n+\n+\treturn 0;\n+}\n+\n #define ICE_FLOW_PROF_HASH_S\t0\n #define ICE_FLOW_PROF_HASH_M\t(0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)\n #define ICE_FLOW_PROF_HDR_S\t32\n@@ -696,6 +979,52 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,\n \tif (status)\n \t\tgoto exit;\n \n+\t/* Search for a flow profile that has matching headers, hash fields\n+\t * and has the input VSI associated to it. If found, no further\n+\t * operations required and exit.\n+\t */\n+\tprof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,\n+\t\t\t\t\tvsi_handle,\n+\t\t\t\t\tICE_FLOW_FIND_PROF_CHK_FLDS |\n+\t\t\t\t\tICE_FLOW_FIND_PROF_CHK_VSI);\n+\tif (prof)\n+\t\tgoto exit;\n+\n+\t/* Check if a flow profile exists with the same protocol headers and\n+\t * associated with the input VSI. If so disasscociate the VSI from\n+\t * this profile. The VSI will be added to a new profile created with\n+\t * the protocol header and new hash field configuration.\n+\t */\n+\tprof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,\n+\t\t\t\t\tvsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);\n+\tif (prof) {\n+\t\tstatus = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);\n+\t\tif (!status)\n+\t\t\tice_rem_rss_list(hw, vsi_handle, prof);\n+\t\telse\n+\t\t\tgoto exit;\n+\n+\t\t/* Remove profile if it has no VSIs associated */\n+\t\tif (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {\n+\t\t\tstatus = ice_flow_rem_prof(hw, blk, prof->id);\n+\t\t\tif (status)\n+\t\t\t\tgoto exit;\n+\t\t}\n+\t}\n+\n+\t/* Search for a profile that has same match fields only. If this\n+\t * exists then associate the VSI to this profile.\n+\t */\n+\tprof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,\n+\t\t\t\t\tvsi_handle,\n+\t\t\t\t\tICE_FLOW_FIND_PROF_CHK_FLDS);\n+\tif (prof) {\n+\t\tstatus = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);\n+\t\tif (!status)\n+\t\t\tstatus = ice_add_rss_list(hw, vsi_handle, prof);\n+\t\tgoto exit;\n+\t}\n+\n \t/* Create a new flow profile with generated profile and packet\n \t * segment information.\n \t */\n@@ -708,6 +1037,15 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,\n \t\tgoto exit;\n \n \tstatus = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);\n+\t/* If association to a new flow profile failed then this profile can\n+\t * be removed.\n+\t */\n+\tif (status) {\n+\t\tice_flow_rem_prof(hw, blk, prof->id);\n+\t\tgoto exit;\n+\t}\n+\n+\tstatus = ice_add_rss_list(hw, vsi_handle, prof);\n \n exit:\n \tkfree(segs);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h\nindex 05b0dab4793c..38669b077209 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.h\n@@ -4,6 +4,7 @@\n #ifndef _ICE_FLOW_H_\n #define _ICE_FLOW_H_\n \n+#define ICE_FLOW_ENTRY_HANDLE_INVAL\t0\n #define ICE_FLOW_FLD_OFF_INVAL\t\t0xffff\n \n /* Generate flow hash field from flow field type(s) */\n@@ -60,6 +61,12 @@ enum ice_flow_dir {\n \tICE_FLOW_RX\t\t= 0x02,\n };\n \n+enum ice_flow_priority {\n+\tICE_FLOW_PRIO_LOW,\n+\tICE_FLOW_PRIO_NORMAL,\n+\tICE_FLOW_PRIO_HIGH\n+};\n+\n #define ICE_FLOW_SEG_MAX\t\t2\n #define ICE_FLOW_FV_EXTRACT_SZ\t\t2\n \n@@ -130,7 +137,10 @@ struct ice_rss_cfg {\n \tu32 packet_hdr;\n };\n \n+enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h);\n+void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle);\n enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle);\n+enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle);\n enum ice_status\n ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,\n \t\tu32 addl_hdrs);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c\nindex 3b4e6462b8ab..b65019978335 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_lib.c\n@@ -505,7 +505,28 @@ bool ice_is_peer_ena(struct ice_pf *pf)\n }\n \n /**\n- * ice_rss_clean - Delete RSS related VSI structures that hold user inputs\n+ * ice_vsi_clean_rss_flow_fld - Delete RSS configuration\n+ * @vsi: the VSI being cleaned up\n+ *\n+ * This function deletes RSS input set for all flows that were configured\n+ * for this VSI\n+ */\n+static void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi)\n+{\n+\tstruct ice_pf *pf = vsi->back;\n+\tenum ice_status status;\n+\n+\tif (ice_is_safe_mode(pf))\n+\t\treturn;\n+\n+\tstatus = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);\n+\tif (status)\n+\t\tdev_dbg(ice_pf_to_dev(pf), \"ice_rem_vsi_rss_cfg failed for vsi = %d, error = %d\\n\",\n+\t\t\tvsi->vsi_num, status);\n+}\n+\n+/**\n+ * ice_rss_clean - Delete RSS related VSI structures and configuration\n * @vsi: the VSI being removed\n */\n static void ice_rss_clean(struct ice_vsi *vsi)\n@@ -519,6 +540,11 @@ static void ice_rss_clean(struct ice_vsi *vsi)\n \t\tdevm_kfree(dev, vsi->rss_hkey_user);\n \tif (vsi->rss_lut_user)\n \t\tdevm_kfree(dev, vsi->rss_lut_user);\n+\n+\tice_vsi_clean_rss_flow_fld(vsi);\n+\t/* remove RSS replay list */\n+\tif (!ice_is_safe_mode(pf))\n+\t\tice_rem_vsi_rss_list(&pf->hw, vsi->idx);\n }\n \n /**\n", "prefixes": [ "S36", "5/8" ] }