Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1320197/?format=api
{ "id": 1320197, "url": "http://patchwork.ozlabs.org/api/patches/1320197/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200701012557.40234-6-haiyue.wang@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": "<20200701012557.40234-6-haiyue.wang@intel.com>", "list_archive_url": null, "date": "2020-07-01T01:25:57", "name": "[net-next,v7,5/5] ice: add switch rule management for DCF", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "971df104c3356e1228ff35a4d5b14e7f0aa696f3", "submitter": { "id": 79056, "url": "http://patchwork.ozlabs.org/api/people/79056/?format=api", "name": "Haiyue Wang", "email": "haiyue.wang@intel.com" }, "delegate": { "id": 109701, "url": "http://patchwork.ozlabs.org/api/users/109701/?format=api", "username": "anguy11", "first_name": "Anthony", "last_name": "Nguyen", "email": "anthony.l.nguyen@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200701012557.40234-6-haiyue.wang@intel.com/mbox/", "series": [ { "id": 186808, "url": "http://patchwork.ozlabs.org/api/series/186808/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=186808", "date": "2020-07-01T01:25:52", "name": "ice: add Intel DCF mode support", "version": 7, "mbox": "http://patchwork.ozlabs.org/series/186808/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1320197/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1320197/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;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=140.211.166.136; helo=silver.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org; receiver=<UNKNOWN>)", "ozlabs.org;\n dmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 49xP291wQ5z9sQt\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 1 Jul 2020 11:36:01 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id A85D024400;\n\tWed, 1 Jul 2020 01:35:59 +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 vZhLnbM-fR4N; Wed, 1 Jul 2020 01:35:52 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id B0C5924214;\n\tWed, 1 Jul 2020 01:35:51 +0000 (UTC)", "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n by ash.osuosl.org (Postfix) with ESMTP id 4DDAE1BF34E\n for <intel-wired-lan@lists.osuosl.org>; Wed, 1 Jul 2020 01:35:49 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by fraxinus.osuosl.org (Postfix) with ESMTP id 4A8F587808\n for <intel-wired-lan@lists.osuosl.org>; Wed, 1 Jul 2020 01:35:49 +0000 (UTC)", "from fraxinus.osuosl.org ([127.0.0.1])\n by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id wmnCuqdPocVg for <intel-wired-lan@lists.osuosl.org>;\n Wed, 1 Jul 2020 01:35:46 +0000 (UTC)", "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n by fraxinus.osuosl.org (Postfix) with ESMTPS id A6BA7877FB\n for <intel-wired-lan@lists.osuosl.org>; Wed, 1 Jul 2020 01:35:46 +0000 (UTC)", "from fmsmga005.fm.intel.com ([10.253.24.32])\n by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 30 Jun 2020 18:35:46 -0700", "from npg-dpdk-haiyue-1.sh.intel.com ([10.67.119.213])\n by fmsmga005.fm.intel.com with ESMTP; 30 Jun 2020 18:35:44 -0700" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "IronPort-SDR": [ "\n aek67ER/big02aCFaxUNAyFlSWyGUmbUtlIMII9+4WlQvva4jeZnDYftoC59WnmdY4Zf99pl9e\n uFZCgi2arw6w==", "\n 1xmDJxLhj9S3351JITkcD361xAykQRyMxq4mMFkb5OJPRIff3eZWWbAYJMDpLr7OYqSLdjmM3C\n Nt4W7a4KnOSg==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6000,8403,9668\"; a=\"144601267\"", "E=Sophos;i=\"5.75,298,1589266800\"; d=\"scan'208\";a=\"144601267\"", "E=Sophos;i=\"5.75,298,1589266800\"; d=\"scan'208\";a=\"481399992\"" ], "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "From": "Haiyue Wang <haiyue.wang@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Wed, 1 Jul 2020 09:25:57 +0800", "Message-Id": "<20200701012557.40234-6-haiyue.wang@intel.com>", "X-Mailer": "git-send-email 2.27.0", "In-Reply-To": "<20200701012557.40234-1-haiyue.wang@intel.com>", "References": "<20200619045711.16055-1-haiyue.wang@intel.com>\n <20200701012557.40234-1-haiyue.wang@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [net-next,\n v7 5/5] ice: add switch rule management for DCF", "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 <intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>,\n <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 <mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Cc": "Xiao Zhang <xiao.zhang@intel.com>, Beilei Xing <beilei.xing@intel.com>", "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": "The PF shall track all the outstanding switch filters (filter IDs to be\nprecise) added by the DCF.\n\nUpon a VF reset event, the PF shall clear all outstanding switch filters\nfor the given VF. Upon completion of either VF or PF reset, the PF shall\nskip replay of filters that were added by the DCF. The PF shall however\ncontinue to replay the filters that were not added by DCF for the VF(s).\n\nIf the trust mode of the DCF is taken away without the DCF gracefully\nrelinquishing the DCF functionality (by way appropriate virtchnl message\nexchanges), then the PF shall remove all switch filters that were added\nby the DCF. The PF shall transition back from DCF mode to regular mode,\nthe VF shall be treated as any other untrusted VF, and the PF will reset\nthe VF.\n\nIf a designated DCF requests AVF functionality from the same VF (VF-ID)\nwithout the DCF gracefully relinquishing the DCF functionality first (by\nway appropriate virtchnl message exchanges), the PF shall remove all the\nswitch filters that were added by the DCF.\n\nSigned-off-by: Xiao Zhang <xiao.zhang@intel.com>\nSigned-off-by: Beilei Xing <beilei.xing@intel.com>\nSigned-off-by: Haiyue Wang <haiyue.wang@intel.com>\n---\n drivers/net/ethernet/intel/ice/ice_dcf.c | 713 ++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_dcf.h | 41 +\n drivers/net/ethernet/intel/ice/ice_switch.c | 16 +-\n drivers/net/ethernet/intel/ice/ice_switch.h | 27 +-\n drivers/net/ethernet/intel/ice/ice_type.h | 9 +\n .../net/ethernet/intel/ice/ice_virtchnl_pf.c | 40 +\n 6 files changed, 821 insertions(+), 25 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice_dcf.c b/drivers/net/ethernet/intel/ice/ice_dcf.c\nindex e7d37735aaa5..154005f1b634 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dcf.c\n+++ b/drivers/net/ethernet/intel/ice/ice_dcf.c\n@@ -124,3 +124,716 @@ void ice_dcf_set_state(struct ice_pf *pf, enum ice_dcf_state state)\n \n \tpf->dcf.state = state;\n }\n+\n+/**\n+ * ice_dcf_rm_sw_rule_to_vsi - remove switch rule of \"forward to VSI\"\n+ * @pf: pointer to the PF struct\n+ * @s_entry: pointer to switch rule entry to remove\n+ */\n+static int\n+ice_dcf_rm_sw_rule_to_vsi(struct ice_pf *pf,\n+\t\t\t struct ice_dcf_sw_rule_entry *s_entry)\n+{\n+\tstruct ice_aqc_sw_rules_elem *s_rule;\n+\tenum ice_status status;\n+\n+\ts_rule = kzalloc(ICE_SW_RULE_RX_TX_NO_HDR_SIZE, GFP_KERNEL);\n+\tif (!s_rule)\n+\t\treturn -ENOMEM;\n+\n+\ts_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);\n+\ts_rule->pdata.lkup_tx_rx.act = 0;\n+\ts_rule->pdata.lkup_tx_rx.hdr_len = 0;\n+\ts_rule->pdata.lkup_tx_rx.index = cpu_to_le16(s_entry->rule_id);\n+\tstatus = ice_aq_sw_rules(&pf->hw, s_rule, ICE_SW_RULE_RX_TX_NO_HDR_SIZE,\n+\t\t\t\t 1, ice_aqc_opc_remove_sw_rules, NULL);\n+\tkfree(s_rule);\n+\tif (status)\n+\t\treturn -EIO;\n+\n+\tlist_del(&s_entry->list_entry);\n+\tkfree(s_entry);\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_dcf_rm_sw_rule_to_vsi_list - remove switch rule of \"forward to VSI list\"\n+ * @pf: pointer to the PF struct\n+ * @s_entry: pointer to switch rule entry to remove\n+ */\n+static int\n+ice_dcf_rm_sw_rule_to_vsi_list(struct ice_pf *pf,\n+\t\t\t struct ice_dcf_sw_rule_entry *s_entry)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info = s_entry->vsi_list_info;\n+\tstruct ice_aqc_alloc_free_res_elem *res_buf;\n+\tstruct ice_aqc_sw_rules_elem *s_rule;\n+\tenum ice_status status;\n+\tu16 rule_sz;\n+\tu16 vsi_id;\n+\tint i = 0;\n+\n+\tif (!vsi_list_info)\n+\t\treturn -EINVAL;\n+\n+\t/* The VSI list is empty, it can be freed immediately */\n+\tif (!vsi_list_info->vsi_count)\n+\t\tgoto free_vsi_list;\n+\n+\trule_sz = ICE_SW_RULE_VSI_LIST_SIZE(vsi_list_info->vsi_count);\n+\ts_rule = kzalloc(rule_sz, GFP_KERNEL);\n+\tif (!s_rule)\n+\t\treturn -ENOMEM;\n+\n+\ts_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);\n+\ts_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_info->list_id);\n+\ts_rule->pdata.vsi_list.number_vsi =\n+\t\t\t\t\tcpu_to_le16(vsi_list_info->vsi_count);\n+\tfor_each_set_bit(vsi_id, vsi_list_info->hw_vsi_map, ICE_HW_VSI_ID_MAX)\n+\t\ts_rule->pdata.vsi_list.vsi[i++] = cpu_to_le16(vsi_id);\n+\n+\tbitmap_zero(vsi_list_info->hw_vsi_map, ICE_HW_VSI_ID_MAX);\n+\tvsi_list_info->vsi_count = 0;\n+\n+\tstatus = ice_aq_sw_rules(&pf->hw, s_rule, rule_sz, 1,\n+\t\t\t\t ice_aqc_opc_update_sw_rules, NULL);\n+\tkfree(s_rule);\n+\tif (status)\n+\t\treturn -EIO;\n+\n+free_vsi_list:\n+\tres_buf = kzalloc(sizeof(*res_buf), GFP_KERNEL);\n+\tif (!res_buf)\n+\t\treturn -ENOMEM;\n+\n+\tres_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);\n+\tres_buf->num_elems = cpu_to_le16(1);\n+\tres_buf->elem[0].e.sw_resp = cpu_to_le16(vsi_list_info->list_id);\n+\tstatus = ice_aq_alloc_free_res(&pf->hw, 1, res_buf, sizeof(*res_buf),\n+\t\t\t\t ice_aqc_opc_free_res, NULL);\n+\tkfree(res_buf);\n+\tif (status)\n+\t\treturn -EIO;\n+\n+\tlist_del(&vsi_list_info->list_entry);\n+\tkfree(vsi_list_info);\n+\ts_entry->vsi_list_info = NULL;\n+\n+\treturn ice_dcf_rm_sw_rule_to_vsi(pf, s_entry);\n+}\n+\n+/**\n+ * ice_dcf_rm_vsi_from_list - remove VSI from switch rule forward VSI list\n+ * @pf: pointer to the PF struct\n+ * @vsi_list_info: pointer to the VSI list info\n+ * @hw_vsi_id: the Hardware VSI number\n+ */\n+static int\n+ice_dcf_rm_vsi_from_list(struct ice_pf *pf,\n+\t\t\t struct ice_dcf_vsi_list_info *vsi_list_info,\n+\t\t\t u16 hw_vsi_id)\n+{\n+\tstruct ice_aqc_sw_rules_elem *s_rule;\n+\tenum ice_status status;\n+\n+\tif (!vsi_list_info || !vsi_list_info->vsi_count ||\n+\t !test_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))\n+\t\treturn -ENOENT;\n+\n+\ts_rule = kzalloc(ICE_SW_RULE_VSI_LIST_SIZE(1), GFP_KERNEL);\n+\tif (!s_rule)\n+\t\treturn -ENOMEM;\n+\n+\ts_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);\n+\ts_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_info->list_id);\n+\ts_rule->pdata.vsi_list.number_vsi = cpu_to_le16(1);\n+\ts_rule->pdata.vsi_list.vsi[0] = cpu_to_le16(hw_vsi_id);\n+\tstatus = ice_aq_sw_rules(&pf->hw, s_rule,\n+\t\t\t\t ICE_SW_RULE_VSI_LIST_SIZE(1), 1,\n+\t\t\t\t ice_aqc_opc_update_sw_rules, NULL);\n+\tkfree(s_rule);\n+\tif (status)\n+\t\treturn -EIO;\n+\n+\t/* When the VF resets gracefully, it should keep the VSI list and its\n+\t * rule, just clears the VSI from list, so that the DCF can replay the\n+\t * rule by updating this VF to list successfully.\n+\t */\n+\tvsi_list_info->vsi_count--;\n+\tclear_bit(hw_vsi_id, vsi_list_info->hw_vsi_map);\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_rm_dcf_sw_vsi_rule - remove switch rules added by DCF to VSI\n+ * @pf: pointer to the PF struct\n+ * @hw_vsi_id: hardware VSI ID of the VF\n+ */\n+void ice_rm_dcf_sw_vsi_rule(struct ice_pf *pf, u16 hw_vsi_id)\n+{\n+\tstruct ice_dcf_sw_rule_entry *s_entry, *tmp;\n+\tint ret;\n+\n+\tlist_for_each_entry_safe(s_entry, tmp, &pf->dcf.sw_rule_head,\n+\t\t\t\t list_entry)\n+\t\tif (s_entry->fltr_act == ICE_FWD_TO_VSI_LIST) {\n+\t\t\tret = ice_dcf_rm_vsi_from_list(pf,\n+\t\t\t\t\t\t s_entry->vsi_list_info,\n+\t\t\t\t\t\t hw_vsi_id);\n+\t\t\tif (ret && ret != -ENOENT)\n+\t\t\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\t\t\"Failed to remove VSI %u from VSI list : %d\\n\",\n+\t\t\t\t\thw_vsi_id, ret);\n+\t\t} else if (s_entry->fwd_id.hw_vsi_id == hw_vsi_id) {\n+\t\t\tret = ice_dcf_rm_sw_rule_to_vsi(pf, s_entry);\n+\t\t\tif (ret)\n+\t\t\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\t\t\"Failed to remove VSI %u switch rule : %d\\n\",\n+\t\t\t\t\thw_vsi_id, ret);\n+\t\t}\n+}\n+\n+/**\n+ * ice_dcf_init_sw_rule_mgmt - initializes DCF rule filter mngt struct\n+ * @pf: pointer to the PF struct\n+ */\n+void ice_dcf_init_sw_rule_mgmt(struct ice_pf *pf)\n+{\n+\tINIT_LIST_HEAD(&pf->dcf.sw_rule_head);\n+\tINIT_LIST_HEAD(&pf->dcf.vsi_list_info_head);\n+}\n+\n+/**\n+ * ice_rm_all_dcf_sw_rules - remove switch rules configured by DCF\n+ * @pf: pointer to the PF struct\n+ */\n+void ice_rm_all_dcf_sw_rules(struct ice_pf *pf)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info, *list_info_tmp;\n+\tstruct ice_dcf_sw_rule_entry *sw_rule, *rule_tmp;\n+\tu16 rule_id, list_id;\n+\tint ret;\n+\n+\tlist_for_each_entry_safe(sw_rule, rule_tmp, &pf->dcf.sw_rule_head,\n+\t\t\t\t list_entry)\n+\t\tif (sw_rule->fltr_act == ICE_FWD_TO_VSI_LIST) {\n+\t\t\tlist_id = sw_rule->fwd_id.vsi_list_id;\n+\t\t\trule_id = sw_rule->rule_id;\n+\t\t\tret = ice_dcf_rm_sw_rule_to_vsi_list(pf, sw_rule);\n+\t\t\tif (ret)\n+\t\t\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\t\t\"Failed to remove switch rule 0x%04x with list id %u : %d\\n\",\n+\t\t\t\t\trule_id, list_id, ret);\n+\t\t} else {\n+\t\t\trule_id = sw_rule->rule_id;\n+\t\t\tret = ice_dcf_rm_sw_rule_to_vsi(pf, sw_rule);\n+\t\t\tif (ret)\n+\t\t\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\t\t\"Failed to remove switch rule 0x%04x : %d\\n\",\n+\t\t\t\t\trule_id, ret);\n+\t\t}\n+\n+\t/* clears rule filter management data if AdminQ command has error */\n+\tlist_for_each_entry_safe(vsi_list_info, list_info_tmp,\n+\t\t\t\t &pf->dcf.vsi_list_info_head,\n+\t\t\t\t list_entry) {\n+\t\tlist_del(&vsi_list_info->list_entry);\n+\t\tkfree(vsi_list_info);\n+\t}\n+\n+\tlist_for_each_entry_safe(sw_rule, rule_tmp, &pf->dcf.sw_rule_head,\n+\t\t\t\t list_entry) {\n+\t\tlist_del(&sw_rule->list_entry);\n+\t\tkfree(sw_rule);\n+\t}\n+}\n+\n+/**\n+ * ice_dcf_find_vsi_list_info - find the VSI list by ID.\n+ * @pf: pointer to the PF info\n+ * @vsi_list_id: VSI list ID\n+ */\n+static struct ice_dcf_vsi_list_info *\n+ice_dcf_find_vsi_list_info(struct ice_pf *pf, u16 vsi_list_id)\n+{\n+\tstruct ice_dcf_vsi_list_info *list_info;\n+\n+\tlist_for_each_entry(list_info, &pf->dcf.vsi_list_info_head, list_entry)\n+\t\tif (list_info->list_id == vsi_list_id)\n+\t\t\treturn list_info;\n+\n+\treturn NULL;\n+}\n+\n+/**\n+ * ice_dcf_add_vsi_id - add new VSI ID into list.\n+ * @vsi_list_info: pointer to the VSI list info\n+ * @hw_vsi_id: the VSI ID\n+ */\n+static void\n+ice_dcf_add_vsi_id(struct ice_dcf_vsi_list_info *vsi_list_info, u16 hw_vsi_id)\n+{\n+\tif (!test_and_set_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))\n+\t\tvsi_list_info->vsi_count++;\n+}\n+\n+/**\n+ * ice_dcf_del_vsi_id - delete the VSI ID from list.\n+ * @vsi_list_info: pointer to the VSI list info\n+ * @hw_vsi_id: the VSI ID\n+ */\n+static void\n+ice_dcf_del_vsi_id(struct ice_dcf_vsi_list_info *vsi_list_info, u16 hw_vsi_id)\n+{\n+\tif (test_and_clear_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))\n+\t\tvsi_list_info->vsi_count--;\n+}\n+\n+/**\n+ * ice_dcf_parse_alloc_vsi_list_res - parse the allocate VSI list resource\n+ * @pf: pointer to the PF info\n+ * @res: pointer to the VSI list resource\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_parse_alloc_vsi_list_res(struct ice_pf *pf,\n+\t\t\t\t struct ice_aqc_res_elem *res)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+\tu16 list_id = le16_to_cpu(res->e.sw_resp);\n+\n+\tvsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);\n+\tif (vsi_list_info)\n+\t\treturn VIRTCHNL_STATUS_SUCCESS;\n+\n+\tvsi_list_info = kzalloc(sizeof(*vsi_list_info), GFP_KERNEL);\n+\tif (!vsi_list_info)\n+\t\treturn VIRTCHNL_STATUS_ERR_NO_MEMORY;\n+\n+\tvsi_list_info->list_id = list_id;\n+\tlist_add(&vsi_list_info->list_entry, &pf->dcf.vsi_list_info_head);\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_parse_free_vsi_list_res - parse the free VSI list resource\n+ * @pf: pointer to the PF info\n+ * @res: pointer to the VSI list resource\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_parse_free_vsi_list_res(struct ice_pf *pf,\n+\t\t\t\tstruct ice_aqc_res_elem *res)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+\tu16 list_id = le16_to_cpu(res->e.sw_resp);\n+\n+\tvsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);\n+\tif (!vsi_list_info)\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\n+\tif (vsi_list_info->vsi_count)\n+\t\tdev_warn(ice_pf_to_dev(pf),\n+\t\t\t \"VSI list %u still has %u VSIs to be removed!\\n\",\n+\t\t\t list_id, vsi_list_info->vsi_count);\n+\n+\tif (vsi_list_info->sw_rule)\n+\t\tvsi_list_info->sw_rule->vsi_list_info = NULL;\n+\n+\tlist_del(&vsi_list_info->list_entry);\n+\tkfree(vsi_list_info);\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_set_vsi_list - set the VSI to VSI list\n+ * @pf: pointer to the PF info\n+ * @vsi_list: pointer to the VSI ID list to be set\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_set_vsi_list(struct ice_pf *pf, struct ice_sw_rule_vsi_list *vsi_list)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+\tint i;\n+\n+\tvsi_list_info =\n+\t\tice_dcf_find_vsi_list_info(pf, le16_to_cpu(vsi_list->index));\n+\tif (!vsi_list_info)\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\n+\tfor (i = 0; i < le16_to_cpu(vsi_list->number_vsi); i++)\n+\t\tice_dcf_add_vsi_id(vsi_list_info,\n+\t\t\t\t le16_to_cpu(vsi_list->vsi[i]));\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_clear_vsi_list - clear the VSI from VSI list\n+ * @pf: pointer to the PF info\n+ * @vsi_list: pointer to the VSI ID list to be cleared\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_clear_vsi_list(struct ice_pf *pf, struct ice_sw_rule_vsi_list *vsi_list)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+\tint i;\n+\n+\tvsi_list_info =\n+\t\tice_dcf_find_vsi_list_info(pf, le16_to_cpu(vsi_list->index));\n+\tif (!vsi_list_info)\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\n+\tfor (i = 0; i < le16_to_cpu(vsi_list->number_vsi); i++)\n+\t\tice_dcf_del_vsi_id(vsi_list_info,\n+\t\t\t\t le16_to_cpu(vsi_list->vsi[i]));\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_find_sw_rule - find the switch rule by ID.\n+ * @pf: pointer to the PF info\n+ * @rule_id: switch rule ID\n+ */\n+static struct ice_dcf_sw_rule_entry *\n+ice_dcf_find_sw_rule(struct ice_pf *pf, u16 rule_id)\n+{\n+\tstruct ice_dcf_sw_rule_entry *sw_rule;\n+\n+\tlist_for_each_entry(sw_rule, &pf->dcf.sw_rule_head, list_entry)\n+\t\tif (sw_rule->rule_id == rule_id)\n+\t\t\treturn sw_rule;\n+\n+\treturn NULL;\n+}\n+\n+/**\n+ * ice_dcf_parse_add_sw_rule_data - parse the add switch rule data\n+ * @pf: pointer to the PF info\n+ * @lkup: pointer to the add switch rule data\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_parse_add_sw_rule_data(struct ice_pf *pf,\n+\t\t\t struct ice_sw_rule_lkup_rx_tx *lkup)\n+{\n+\tstruct ice_dcf_sw_rule_entry *sw_rule;\n+\tu32 act;\n+\n+\tsw_rule = kzalloc(sizeof(*sw_rule), GFP_KERNEL);\n+\tif (!sw_rule)\n+\t\treturn VIRTCHNL_STATUS_ERR_NO_MEMORY;\n+\n+\tact = le32_to_cpu(lkup->act);\n+\tsw_rule->fltr_act = ICE_FWD_TO_VSI;\n+\tsw_rule->fwd_id.hw_vsi_id = (act & ICE_SINGLE_ACT_VSI_ID_M) >>\n+\t\t\t\t\tICE_SINGLE_ACT_VSI_ID_S;\n+\tsw_rule->rule_id = le16_to_cpu(lkup->index);\n+\n+\tlist_add(&sw_rule->list_entry, &pf->dcf.sw_rule_head);\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_parse_updt_sw_rule_data - parse the update switch rule data\n+ * @pf: pointer to the PF info\n+ * @lkup: pointer to the update switch rule data\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_parse_updt_sw_rule_data(struct ice_pf *pf,\n+\t\t\t\tstruct ice_sw_rule_lkup_rx_tx *lkup)\n+{\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+\tstruct ice_dcf_sw_rule_entry *sw_rule;\n+\tu16 vsi_list_id, rule_id;\n+\tu32 act;\n+\n+\trule_id = le16_to_cpu(lkup->index);\n+\tsw_rule = ice_dcf_find_sw_rule(pf, rule_id);\n+\tif (!sw_rule)\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\n+\tact = le32_to_cpu(lkup->act);\n+\tif (!(act & ICE_SINGLE_ACT_VSI_LIST)) {\n+\t\tu16 vsi_hw_id = (act & ICE_SINGLE_ACT_VSI_ID_M) >>\n+\t\t\t\tICE_SINGLE_ACT_VSI_ID_S;\n+\n+\t\tsw_rule->fltr_act = ICE_FWD_TO_VSI;\n+\t\tsw_rule->fwd_id.hw_vsi_id = vsi_hw_id;\n+\n+\t\treturn VIRTCHNL_STATUS_SUCCESS;\n+\t}\n+\n+\tvsi_list_id = (act & ICE_SINGLE_ACT_VSI_LIST_ID_M) >>\n+\t\t\t\tICE_SINGLE_ACT_VSI_LIST_ID_S;\n+\tif (sw_rule->vsi_list_info) {\n+\t\tif (sw_rule->vsi_list_info->list_id == vsi_list_id)\n+\t\t\treturn VIRTCHNL_STATUS_SUCCESS;\n+\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"The switch rule 0x%04x is running on VSI list %u\\n\",\n+\t\t\trule_id, sw_rule->vsi_list_info->list_id);\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\t}\n+\n+\tvsi_list_info = ice_dcf_find_vsi_list_info(pf, vsi_list_id);\n+\tif (!vsi_list_info) {\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"No VSI list %u found to bind the switch rule 0x%04x\\n\",\n+\t\t\tvsi_list_id, rule_id);\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\t}\n+\n+\tif (vsi_list_info->sw_rule) {\n+\t\tif (vsi_list_info->sw_rule->rule_id == rule_id)\n+\t\t\treturn VIRTCHNL_STATUS_SUCCESS;\n+\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"The VSI list %u is running on switch rule 0x%04x\\n\",\n+\t\t\tvsi_list_id, vsi_list_info->sw_rule->rule_id);\n+\t\treturn VIRTCHNL_STATUS_ERR_PARAM;\n+\t}\n+\n+\tvsi_list_info->sw_rule = sw_rule;\n+\n+\tsw_rule->fltr_act = ICE_FWD_TO_VSI_LIST;\n+\tsw_rule->fwd_id.vsi_list_id = vsi_list_id;\n+\tsw_rule->vsi_list_info = vsi_list_info;\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_parse_rm_sw_rule_data - parse the remove switch rule data\n+ * @pf: pointer to the PF info\n+ * @lkup: pointer to the remove switch rule data\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_parse_rm_sw_rule_data(struct ice_pf *pf,\n+\t\t\t struct ice_sw_rule_lkup_rx_tx *lkup)\n+{\n+\tstruct ice_dcf_sw_rule_entry *sw_rule, *tmp;\n+\tu16 rule_id = le16_to_cpu(lkup->index);\n+\n+\tlist_for_each_entry_safe(sw_rule, tmp, &pf->dcf.sw_rule_head,\n+\t\t\t\t list_entry)\n+\t\tif (sw_rule->rule_id == rule_id) {\n+\t\t\tlist_del(&sw_rule->list_entry);\n+\t\t\tkfree(sw_rule);\n+\t\t}\n+\n+\treturn VIRTCHNL_STATUS_SUCCESS;\n+}\n+\n+/**\n+ * ice_dcf_handle_add_sw_rule_rsp - handle the add switch rule response\n+ * @pf: pointer to the PF info\n+ * @aq_buf: pointer to the add switch rule command buffer\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_handle_add_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)\n+{\n+\tenum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;\n+\tstruct ice_aqc_sw_rules_elem *em =\n+\t\t\t(struct ice_aqc_sw_rules_elem *)aq_buf;\n+\tu16 type = le16_to_cpu(em->type);\n+\n+\tif (type == ICE_AQC_SW_RULES_T_VSI_LIST_SET)\n+\t\tstatus = ice_dcf_set_vsi_list(pf, &em->pdata.vsi_list);\n+\telse if (type == ICE_AQC_SW_RULES_T_LKUP_RX)\n+\t\tstatus = ice_dcf_parse_add_sw_rule_data(pf,\n+\t\t\t\t\t\t\t&em->pdata.lkup_tx_rx);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_dcf_handle_updt_sw_rule_rsp - handle the update switch rule response\n+ * @pf: pointer to the PF info\n+ * @aq_buf: pointer to the update switch rule command buffer\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_handle_updt_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)\n+{\n+\tenum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;\n+\tstruct ice_aqc_sw_rules_elem *em =\n+\t\t\t(struct ice_aqc_sw_rules_elem *)aq_buf;\n+\tu16 type = le16_to_cpu(em->type);\n+\n+\tif (type == ICE_AQC_SW_RULES_T_VSI_LIST_SET)\n+\t\tstatus = ice_dcf_set_vsi_list(pf, &em->pdata.vsi_list);\n+\telse if (type == ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR)\n+\t\tstatus = ice_dcf_clear_vsi_list(pf, &em->pdata.vsi_list);\n+\telse if (type == ICE_AQC_SW_RULES_T_LKUP_RX)\n+\t\tstatus = ice_dcf_parse_updt_sw_rule_data(pf,\n+\t\t\t\t\t\t\t &em->pdata.lkup_tx_rx);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_dcf_handle_rm_sw_rule_rsp - handle the remove switch rule response\n+ * @pf: pointer to the PF info\n+ * @aq_buf: pointer to the remove switch rule command buffer\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_handle_rm_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)\n+{\n+\tenum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;\n+\tstruct ice_aqc_sw_rules_elem *em =\n+\t\t\t(struct ice_aqc_sw_rules_elem *)aq_buf;\n+\tu16 type = le16_to_cpu(em->type);\n+\n+\tif (type == ICE_AQC_SW_RULES_T_LKUP_RX)\n+\t\tstatus = ice_dcf_parse_rm_sw_rule_data(pf,\n+\t\t\t\t\t\t &em->pdata.lkup_tx_rx);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_dcf_handle_alloc_res_rsp - handle the allocate resource response\n+ * @pf: pointer to the PF info\n+ * @aq_buf: pointer to the allocate resource command buffer\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_handle_alloc_res_rsp(struct ice_pf *pf, u8 *aq_buf)\n+{\n+\tenum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;\n+\tstruct ice_aqc_alloc_free_res_elem *res_buf =\n+\t\t (struct ice_aqc_alloc_free_res_elem *)aq_buf;\n+\tu16 type = (le16_to_cpu(res_buf->res_type) &\n+\t\t ICE_AQC_RES_TYPE_M) >> ICE_AQC_RES_TYPE_S;\n+\n+\tif (type == ICE_AQC_RES_TYPE_VSI_LIST_REP)\n+\t\tstatus = ice_dcf_parse_alloc_vsi_list_res(pf,\n+\t\t\t\t\t\t\t &res_buf->elem[0]);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_dcf_handle_free_res_rsp - handle the free resource response\n+ * @pf: pointer to the PF info\n+ * @aq_buf: pointer to the free resource command buffer\n+ */\n+static enum virtchnl_status_code\n+ice_dcf_handle_free_res_rsp(struct ice_pf *pf, u8 *aq_buf)\n+{\n+\tenum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;\n+\tstruct ice_aqc_alloc_free_res_elem *res_buf =\n+\t\t (struct ice_aqc_alloc_free_res_elem *)aq_buf;\n+\tu16 type = (le16_to_cpu(res_buf->res_type) &\n+\t\t ICE_AQC_RES_TYPE_M) >> ICE_AQC_RES_TYPE_S;\n+\n+\tif (type == ICE_AQC_RES_TYPE_VSI_LIST_REP)\n+\t\tstatus = ice_dcf_parse_free_vsi_list_res(pf,\n+\t\t\t\t\t\t\t &res_buf->elem[0]);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_dcf_post_aq_send_cmd - get the data from firmware successful response\n+ * @pf: pointer to the PF info\n+ * @aq_desc: descriptor describing the command\n+ * @aq_buf: the AdminQ command buffer\n+ */\n+enum virtchnl_status_code\n+ice_dcf_post_aq_send_cmd(struct ice_pf *pf, struct ice_aq_desc *aq_desc,\n+\t\t\t u8 *aq_buf)\n+{\n+\tenum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;\n+\tu16 opc = le16_to_cpu(aq_desc->opcode);\n+\n+\tif (!aq_buf)\n+\t\treturn VIRTCHNL_STATUS_SUCCESS;\n+\n+\tif (opc == ice_aqc_opc_add_sw_rules)\n+\t\tstatus = ice_dcf_handle_add_sw_rule_rsp(pf, aq_buf);\n+\telse if (opc == ice_aqc_opc_update_sw_rules)\n+\t\tstatus = ice_dcf_handle_updt_sw_rule_rsp(pf, aq_buf);\n+\telse if (opc == ice_aqc_opc_remove_sw_rules)\n+\t\tstatus = ice_dcf_handle_rm_sw_rule_rsp(pf, aq_buf);\n+\telse if (opc == ice_aqc_opc_alloc_res)\n+\t\tstatus = ice_dcf_handle_alloc_res_rsp(pf, aq_buf);\n+\telse if (opc == ice_aqc_opc_free_res)\n+\t\tstatus = ice_dcf_handle_free_res_rsp(pf, aq_buf);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_dcf_pre_aq_send_cmd - check if it needs to send the command to firmware\n+ * @vf: pointer to the VF info\n+ * @aq_desc: descriptor describing the command\n+ * @aq_buf: the AdminQ command buffer\n+ * @aq_buf_size: the AdminQ command buffer size\n+ */\n+bool\n+ice_dcf_pre_aq_send_cmd(struct ice_vf *vf, struct ice_aq_desc *aq_desc,\n+\t\t\tu8 *aq_buf, u16 aq_buf_size)\n+{\n+\tstruct ice_pf *pf = vf->pf;\n+\n+\tswitch (le16_to_cpu(aq_desc->opcode)) {\n+\tcase ice_aqc_opc_update_sw_rules:\n+\t{\n+\t\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+\t\tstruct ice_aqc_sw_rules_elem *s_rule;\n+\t\tu16 list_id, vsi_id;\n+\n+\t\tif (aq_buf_size < ICE_SW_RULE_VSI_LIST_SIZE(1))\n+\t\t\tbreak;\n+\n+\t\ts_rule = (struct ice_aqc_sw_rules_elem *)aq_buf;\n+\t\tif (le16_to_cpu(s_rule->type) !=\n+\t\t\t\t\tICE_AQC_SW_RULES_T_VSI_LIST_CLEAR ||\n+\t\t le16_to_cpu(s_rule->pdata.vsi_list.number_vsi) != 1)\n+\t\t\tbreak;\n+\n+\t\tlist_id = le16_to_cpu(s_rule->pdata.vsi_list.index);\n+\t\tvsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);\n+\t\tif (!vsi_list_info)\n+\t\t\tbreak;\n+\n+\t\tvsi_id = le16_to_cpu(s_rule->pdata.vsi_list.vsi[0]);\n+\t\tif (vsi_id >= ICE_HW_VSI_ID_MAX ||\n+\t\t test_bit(vsi_id, vsi_list_info->hw_vsi_map))\n+\t\t\tbreak;\n+\n+\t\t/* The VSI is removed from list already, no need to send the\n+\t\t * command to firmware.\n+\t\t */\n+\t\treturn true;\n+\t}\n+\tcase ice_aqc_opc_remove_sw_rules:\n+\t{\n+\t\tstruct ice_aqc_sw_rules_elem *s_rule;\n+\t\tu16 rule_id;\n+\n+\t\tif (aq_buf_size < ICE_SW_RULE_RX_TX_NO_HDR_SIZE)\n+\t\t\tbreak;\n+\n+\t\ts_rule = (struct ice_aqc_sw_rules_elem *)aq_buf;\n+\t\tif (le16_to_cpu(s_rule->type) != ICE_AQC_SW_RULES_T_LKUP_RX)\n+\t\t\tbreak;\n+\n+\t\trule_id = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);\n+\t\tif (ice_dcf_find_sw_rule(pf, rule_id))\n+\t\t\tbreak;\n+\n+\t\t/* The switch rule is removed already, no need to send the\n+\t\t * command to firmware.\n+\t\t */\n+\t\treturn true;\n+\t}\n+\n+\tdefault:\n+\t\tbreak;\n+\t}\n+\n+\treturn false;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dcf.h b/drivers/net/ethernet/intel/ice/ice_dcf.h\nindex 1ca228f89a19..23842db0a884 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dcf.h\n+++ b/drivers/net/ethernet/intel/ice/ice_dcf.h\n@@ -21,10 +21,42 @@ enum ice_dcf_state {\n \tICE_DCF_STATE_PAUSE,\n };\n \n+struct ice_dcf_sw_rule_entry;\n+\n+#define ICE_HW_VSI_ID_MAX\tBIT(10) /* The AQ VSI number uses 10 bits */\n+\n+struct ice_dcf_vsi_list_info {\n+\tstruct list_head list_entry;\n+\tstruct ice_dcf_sw_rule_entry *sw_rule;\n+\tu16 list_id;\n+\n+\tu16 vsi_count;\n+\tDECLARE_BITMAP(hw_vsi_map, ICE_HW_VSI_ID_MAX);\n+};\n+\n+struct ice_dcf_sw_rule_entry {\n+\tstruct list_head list_entry;\n+\tu16 rule_id;\n+\n+\t/* Only support ICE_FWD_TO_VSI and ICE_FWD_TO_VSI_LIST */\n+\tenum ice_sw_fwd_act_type fltr_act;\n+\t/* Depending on filter action */\n+\tunion {\n+\t\tu16 hw_vsi_id:10;\n+\t\tu16 vsi_list_id:10;\n+\t} fwd_id;\n+\n+\tstruct ice_dcf_vsi_list_info *vsi_list_info;\n+};\n+\n struct ice_dcf {\n \tstruct ice_vf *vf;\n \tenum ice_dcf_state state;\n \n+\t/* Trace the switch rules added/removed by DCF */\n+\tstruct list_head sw_rule_head;\n+\tstruct list_head vsi_list_info_head;\n+\n \t/* Handle the AdminQ command between the DCF (Device Config Function)\n \t * and the firmware.\n \t */\n@@ -46,5 +78,14 @@ bool ice_check_dcf_allowed(struct ice_vf *vf);\n bool ice_is_vf_dcf(struct ice_vf *vf);\n enum ice_dcf_state ice_dcf_get_state(struct ice_pf *pf);\n void ice_dcf_set_state(struct ice_pf *pf, enum ice_dcf_state state);\n+void ice_dcf_init_sw_rule_mgmt(struct ice_pf *pf);\n+void ice_rm_all_dcf_sw_rules(struct ice_pf *pf);\n+void ice_rm_dcf_sw_vsi_rule(struct ice_pf *pf, u16 hw_vsi_id);\n+bool\n+ice_dcf_pre_aq_send_cmd(struct ice_vf *vf, struct ice_aq_desc *aq_desc,\n+\t\t\tu8 *aq_buf, u16 aq_buf_size);\n+enum virtchnl_status_code\n+ice_dcf_post_aq_send_cmd(struct ice_pf *pf, struct ice_aq_desc *aq_desc,\n+\t\t\t u8 *aq_buf);\n #endif /* CONFIG_PCI_IOV */\n #endif /* _ICE_DCF_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c\nindex ccbe1cc64295..ee434b8d794d 100644\n--- a/drivers/net/ethernet/intel/ice/ice_switch.c\n+++ b/drivers/net/ethernet/intel/ice/ice_switch.c\n@@ -23,24 +23,10 @@\n *\tIn case of Ether type filter it is treated as header without VLAN tag\n *\tand byte 12 and 13 is used to program a given Ether type instead\n */\n-#define DUMMY_ETH_HDR_LEN\t\t16\n static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,\n \t\t\t\t\t\t\t0x2, 0, 0, 0, 0, 0,\n \t\t\t\t\t\t\t0x81, 0, 0, 0};\n \n-#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \\\n-\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \\\n-\t (DUMMY_ETH_HDR_LEN * \\\n-\t sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0])))\n-#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \\\n-\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))\n-#define ICE_SW_RULE_LG_ACT_SIZE(n) \\\n-\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \\\n-\t ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0])))\n-#define ICE_SW_RULE_VSI_LIST_SIZE(n) \\\n-\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \\\n-\t ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0])))\n-\n /**\n * ice_init_def_sw_recp - initialize the recipe book keeping tables\n * @hw: pointer to the HW struct\n@@ -490,7 +476,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,\n *\n * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware\n */\n-static enum ice_status\n+enum ice_status\n ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,\n \t\tu8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)\n {\ndiff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h\nindex 8b4f9d35c860..05cd6ea24d44 100644\n--- a/drivers/net/ethernet/intel/ice/ice_switch.h\n+++ b/drivers/net/ethernet/intel/ice/ice_switch.h\n@@ -14,6 +14,20 @@\n #define ICE_VSI_INVAL_ID 0xffff\n #define ICE_INVAL_Q_HANDLE 0xFFFF\n \n+#define DUMMY_ETH_HDR_LEN\t\t16\n+#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \\\n+\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \\\n+\t (DUMMY_ETH_HDR_LEN * \\\n+\t sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0])))\n+#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \\\n+\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))\n+#define ICE_SW_RULE_LG_ACT_SIZE(n) \\\n+\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \\\n+\t ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0])))\n+#define ICE_SW_RULE_VSI_LIST_SIZE(n) \\\n+\t(offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \\\n+\t ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0])))\n+\n /* VSI context structure for add/get/update/free operations */\n struct ice_vsi_ctx {\n \tu16 vsi_num;\n@@ -28,15 +42,6 @@ struct ice_vsi_ctx {\n \tstruct ice_q_ctx *lan_q_ctx[ICE_MAX_TRAFFIC_CLASS];\n };\n \n-enum ice_sw_fwd_act_type {\n-\tICE_FWD_TO_VSI = 0,\n-\tICE_FWD_TO_VSI_LIST, /* Do not use this when adding filter */\n-\tICE_FWD_TO_Q,\n-\tICE_FWD_TO_QGRP,\n-\tICE_DROP_PACKET,\n-\tICE_INVAL_ACT\n-};\n-\n /* Switch recipe ID enum values are specific to hardware */\n enum ice_sw_lkup_type {\n \tICE_SW_LKUP_ETHERTYPE = 0,\n@@ -247,5 +252,7 @@ bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle);\n \n enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle);\n void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw);\n-\n+enum ice_status\n+ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,\n+\t\tu8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd);\n #endif /* _ICE_SWITCH_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex c1ad8622e65c..c2eff68d5469 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -707,6 +707,15 @@ struct ice_hw_port_stats {\n \tu64 fd_sb_match;\n };\n \n+enum ice_sw_fwd_act_type {\n+\tICE_FWD_TO_VSI = 0,\n+\tICE_FWD_TO_VSI_LIST, /* Do not use this when adding filter */\n+\tICE_FWD_TO_Q,\n+\tICE_FWD_TO_QGRP,\n+\tICE_DROP_PACKET,\n+\tICE_INVAL_ACT\n+};\n+\n /* Checksum and Shadow RAM pointers */\n #define ICE_SR_BOOT_CFG_PTR\t\t0x132\n #define ICE_NVM_OROM_VER_OFF\t\t0x02\ndiff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\nindex 919f1cec784e..fa1f84118456 100644\n--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\n+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\n@@ -361,6 +361,7 @@ void ice_free_vfs(struct ice_pf *pf)\n \t\tdev_warn(dev, \"VFs are assigned - not disabling SR-IOV\\n\");\n \n \tif (ice_dcf_get_state(pf) != ICE_DCF_STATE_OFF) {\n+\t\tice_rm_all_dcf_sw_rules(pf);\n \t\tice_dcf_set_state(pf, ICE_DCF_STATE_OFF);\n \t\tpf->dcf.vf = NULL;\n \t}\n@@ -1055,6 +1056,9 @@ static void ice_vf_clear_counters(struct ice_vf *vf)\n */\n static void ice_vf_pre_vsi_rebuild(struct ice_vf *vf)\n {\n+\t/* Remove switch rules associated with the reset VF */\n+\tice_rm_dcf_sw_vsi_rule(vf->pf, vf->lan_vsi_num);\n+\n \tice_vf_clear_counters(vf);\n \tice_clear_vf_reset_trigger(vf);\n }\n@@ -1584,6 +1588,8 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs)\n \tif (ret)\n \t\tgoto err_pci_disable_sriov;\n \n+\tice_dcf_init_sw_rule_mgmt(pf);\n+\n \tif (ice_set_per_vf_res(pf)) {\n \t\tdev_err(dev, \"Not enough resources for %d VFs, try with fewer number of VFs\\n\",\n \t\t\tnum_vfs);\n@@ -2013,6 +2019,13 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)\n \t\t\t ICE_DCF_VFID);\n \t} else if (ice_is_vf_dcf(vf) &&\n \t\t ice_dcf_get_state(pf) != ICE_DCF_STATE_OFF) {\n+\t\t/* If a designated DCF requests AVF functionality from the\n+\t\t * same VF without the DCF gracefully relinquishing the DCF\n+\t\t * functionality first, remove ALL switch filters that were\n+\t\t * added by the DCF.\n+\t\t */\n+\t\tdev_info(ice_pf_to_dev(pf), \"DCF is not in the OFF state, removing all switch filters that were added by the DCF\\n\");\n+\t\tice_rm_all_dcf_sw_rules(pf);\n \t\tice_dcf_set_state(pf, ICE_DCF_STATE_OFF);\n \t\tpf->dcf.vf = NULL;\n \t\tice_reset_vf(vf, false);\n@@ -3723,6 +3736,18 @@ ice_dcf_handle_aq_cmd(struct ice_vf *vf, struct ice_aq_desc *aq_desc,\n \tif ((aq_buf && !aq_buf_size) || (!aq_buf && aq_buf_size))\n \t\treturn -EINVAL;\n \n+\tif (ice_dcf_pre_aq_send_cmd(vf, aq_desc, aq_buf, aq_buf_size)) {\n+\t\tret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DCF_CMD_DESC,\n+\t\t\t\t\t VIRTCHNL_STATUS_SUCCESS,\n+\t\t\t\t\t (u8 *)aq_desc, sizeof(*aq_desc));\n+\t\tif (ret || !aq_buf_size)\n+\t\t\treturn ret;\n+\n+\t\tv_op = VIRTCHNL_OP_DCF_CMD_BUFF;\n+\t\tv_ret = VIRTCHNL_STATUS_SUCCESS;\n+\t\tgoto err;\n+\t}\n+\n \taq_ret = ice_aq_send_cmd(&pf->hw, aq_desc, aq_buf, aq_buf_size, NULL);\n \t/* It needs to send back the AQ response message if ICE_ERR_AQ_ERROR\n \t * returns, some AdminQ handlers will use the error code filled by FW\n@@ -3734,6 +3759,14 @@ ice_dcf_handle_aq_cmd(struct ice_vf *vf, struct ice_aq_desc *aq_desc,\n \t\tgoto err;\n \t}\n \n+\tif (aq_ret != ICE_ERR_AQ_ERROR) {\n+\t\tv_ret = ice_dcf_post_aq_send_cmd(pf, aq_desc, aq_buf);\n+\t\tif (v_ret != VIRTCHNL_STATUS_SUCCESS) {\n+\t\t\tv_op = VIRTCHNL_OP_DCF_CMD_DESC;\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n \tret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DCF_CMD_DESC, v_ret,\n \t\t\t\t (u8 *)aq_desc, sizeof(*aq_desc));\n \t/* Bail out so we don't send the VIRTCHNL_OP_DCF_CMD_BUFF message\n@@ -3840,6 +3873,7 @@ static int ice_vc_dis_dcf_cap(struct ice_vf *vf)\n \n \tif (vf->driver_caps & VIRTCHNL_VF_CAP_DCF) {\n \t\tvf->driver_caps &= ~VIRTCHNL_VF_CAP_DCF;\n+\t\tice_rm_all_dcf_sw_rules(vf->pf);\n \t\tice_dcf_set_state(vf->pf, ICE_DCF_STATE_OFF);\n \t\tvf->pf->dcf.vf = NULL;\n \t}\n@@ -4256,8 +4290,14 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)\n \tif (trusted == vf->trusted)\n \t\treturn 0;\n \n+\t/* If the trust mode of a given DCF is taken away without the DCF\n+\t * gracefully relinquishing the DCF functionality, remove ALL switch\n+\t * filters that were added by the DCF and treat this VF as any other\n+\t * untrusted AVF.\n+\t */\n \tif (ice_is_vf_dcf(vf) && !trusted &&\n \t ice_dcf_get_state(pf) != ICE_DCF_STATE_OFF) {\n+\t\tice_rm_all_dcf_sw_rules(pf);\n \t\tice_dcf_set_state(pf, ICE_DCF_STATE_OFF);\n \t\tpf->dcf.vf = NULL;\n \t\tvf->driver_caps &= ~VIRTCHNL_VF_CAP_DCF;\n", "prefixes": [ "net-next", "v7", "5/5" ] }