get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 50591,
    "url": "http://patches.dpdk.org/api/patches/50591/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190228055650.25237-33-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": "<20190228055650.25237-33-qi.z.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190228055650.25237-33-qi.z.zhang@intel.com",
    "date": "2019-02-28T05:56:45",
    "name": "[32/37] net/ice/base: add FDIR support",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "237bd2d3258d4ddb6e36633b3c858283bee1a078",
    "submitter": {
        "id": 504,
        "url": "http://patches.dpdk.org/api/people/504/?format=api",
        "name": "Qi Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190228055650.25237-33-qi.z.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 3567,
            "url": "http://patches.dpdk.org/api/series/3567/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=3567",
            "date": "2019-02-28T05:56:13",
            "name": "share code update.",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/3567/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/50591/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/50591/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 CE6FF1B1A0;\n\tThu, 28 Feb 2019 06:55:53 +0100 (CET)",
            "from mga12.intel.com (mga12.intel.com [192.55.52.136])\n\tby dpdk.org (Postfix) with ESMTP id B62F21B13A\n\tfor <dev@dpdk.org>; Thu, 28 Feb 2019 06:55:50 +0100 (CET)",
            "from fmsmga006.fm.intel.com ([10.253.24.20])\n\tby fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t27 Feb 2019 21:55:50 -0800",
            "from dpdk51.sh.intel.com ([10.67.110.190])\n\tby fmsmga006.fm.intel.com with ESMTP; 27 Feb 2019 21:55:49 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.58,422,1544515200\"; d=\"scan'208\";a=\"322784411\"",
        "From": "Qi Zhang <qi.z.zhang@intel.com>",
        "To": "wenzhuo.lu@intel.com,\n\tqiming.yang@intel.com",
        "Cc": "paul.m.stillwell.jr@intel.com, dev@dpdk.org, ferruh.yigit@intel.com,\n\tQi Zhang <qi.z.zhang@intel.com>",
        "Date": "Thu, 28 Feb 2019 13:56:45 +0800",
        "Message-Id": "<20190228055650.25237-33-qi.z.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.13.6",
        "In-Reply-To": "<20190228055650.25237-1-qi.z.zhang@intel.com>",
        "References": "<20190228055650.25237-1-qi.z.zhang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 32/37] net/ice/base: add FDIR support",
        "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": "Add flow director related support base code.\n\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/Makefile              |   1 +\n drivers/net/ice/base/ice_adminq_cmd.h |  13 +\n drivers/net/ice/base/ice_common.c     |  36 ++\n drivers/net/ice/base/ice_common.h     |   1 +\n drivers/net/ice/base/ice_fdir.c       | 742 ++++++++++++++++++++++++++++++++++\n drivers/net/ice/base/ice_fdir.h       | 202 +++++++++\n drivers/net/ice/base/ice_flex_pipe.c  | 232 +++++++++++\n drivers/net/ice/base/ice_type.h       |  55 +++\n drivers/net/ice/base/meson.build      |   1 +\n 9 files changed, 1283 insertions(+)\n create mode 100644 drivers/net/ice/base/ice_fdir.c\n create mode 100644 drivers/net/ice/base/ice_fdir.h",
    "diff": "diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile\nindex 89d21334e..a3aabccf1 100644\n--- a/drivers/net/ice/Makefile\n+++ b/drivers/net/ice/Makefile\n@@ -52,6 +52,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_nvm.c\n SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_flex_pipe.c\n SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_flow.c\n SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_dcb.c\n+SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_fdir.c\n \n SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_ethdev.c\n SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_rxtx.c\ndiff --git a/drivers/net/ice/base/ice_adminq_cmd.h b/drivers/net/ice/base/ice_adminq_cmd.h\nindex 4c5cf5419..d2ab9eeff 100644\n--- a/drivers/net/ice/base/ice_adminq_cmd.h\n+++ b/drivers/net/ice/base/ice_adminq_cmd.h\n@@ -105,6 +105,7 @@ struct ice_aqc_list_caps_elem {\n #define ICE_AQC_CAPS_RXQS\t\t\t\t0x0041\n #define ICE_AQC_CAPS_TXQS\t\t\t\t0x0042\n #define ICE_AQC_CAPS_MSIX\t\t\t\t0x0043\n+#define ICE_AQC_CAPS_FD\t\t\t\t\t0x0045\n #define ICE_AQC_CAPS_MAX_MTU\t\t\t\t0x0047\n \n \tu8 major_ver;\n@@ -1861,6 +1862,16 @@ struct ice_aqc_get_set_rss_lut {\n };\n \n \n+/* Clear FD Table Command (direct, 0x0B06) */\n+struct ice_aqc_clear_fd_table {\n+\tu8 clear_type;\n+#define CL_FD_VM_VF_TYPE_VSI_IDX\t1\n+#define CL_FD_VM_VF_TYPE_PF_IDX\t\t2\n+\tu8 rsvd;\n+\t__le16 vsi_index;\n+\tu8 reserved[12];\n+};\n+\n \n \n \n@@ -2210,6 +2221,7 @@ struct ice_aq_desc {\n \t\tstruct ice_aqc_lldp_stop_start_specific_agent lldp_agent_ctrl;\n \t\tstruct ice_aqc_get_set_rss_lut get_set_rss_lut;\n \t\tstruct ice_aqc_get_set_rss_key get_set_rss_key;\n+\t\tstruct ice_aqc_clear_fd_table clear_fd_table;\n \t\tstruct ice_aqc_add_txqs add_txqs;\n \t\tstruct ice_aqc_dis_txqs dis_txqs;\n \t\tstruct ice_aqc_txqs_cleanup txqs_cleanup;\n@@ -2415,6 +2427,7 @@ enum ice_adminq_opc {\n \tice_aqc_opc_set_rss_lut\t\t\t\t= 0x0B03,\n \tice_aqc_opc_get_rss_key\t\t\t\t= 0x0B04,\n \tice_aqc_opc_get_rss_lut\t\t\t\t= 0x0B05,\n+\tice_aqc_opc_clear_fd_table\t\t\t= 0x0B06,\n \n \t/* Tx queue handling commands/events */\n \tice_aqc_opc_add_txqs\t\t\t\t= 0x0C30,\ndiff --git a/drivers/net/ice/base/ice_common.c b/drivers/net/ice/base/ice_common.c\nindex 202592710..425f76e8d 100644\n--- a/drivers/net/ice/base/ice_common.c\n+++ b/drivers/net/ice/base/ice_common.c\n@@ -805,6 +805,9 @@ enum ice_status ice_init_hw(struct ice_hw *hw)\n \tif (status)\n \t\tgoto err_unroll_cqinit;\n \n+\t/* Set bit to enable Flow Director filters */\n+\twr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M);\n+\tINIT_LIST_HEAD(&hw->fdir_list_head);\n \n \tice_clear_pxe_mode(hw);\n \n@@ -901,6 +904,10 @@ enum ice_status ice_init_hw(struct ice_hw *hw)\n \tice_init_flex_flds(hw, ICE_RXDID_FLEX_NIC);\n \tice_init_flex_flds(hw, ICE_RXDID_FLEX_NIC_2);\n \n+\t/* Obtain counter base index which would be used by flow director */\n+\tstatus = ice_alloc_fd_res_cntr(hw, &hw->fd_ctr_base);\n+\tif (status)\n+\t\tgoto err_unroll_fltr_mgmt_struct;\n \n \treturn ICE_SUCCESS;\n \n@@ -926,6 +933,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw)\n  */\n void ice_deinit_hw(struct ice_hw *hw)\n {\n+\tice_free_fd_res_cntr(hw, hw->fd_ctr_base);\n \tice_cleanup_fltr_mgmt_struct(hw);\n \n \tice_sched_cleanup_all(hw);\n@@ -1980,6 +1988,34 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count,\n \t\t\t\t  \"HW caps: MSIX first vector index = %d\\n\",\n \t\t\t\t  caps->msix_vector_first_id);\n \t\t\tbreak;\n+\t\tcase ICE_AQC_CAPS_FD:\n+\t\t{\n+\t\t\tu32 reg_val, val;\n+\n+\t\t\tif (dev_p) {\n+\t\t\t\tdev_p->num_flow_director_fltr = number;\n+\t\t\t\tice_debug(hw, ICE_DBG_INIT,\n+\t\t\t\t\t  \"HW caps: Dev.fd_fltr =%d\\n\",\n+\t\t\t\t\t  dev_p->num_flow_director_fltr);\n+\t\t\t}\n+\t\t\tif (func_p) {\n+\t\t\t\treg_val = rd32(hw, GLQF_FD_SIZE);\n+\t\t\t\tval = (reg_val & GLQF_FD_SIZE_FD_GSIZE_M) >>\n+\t\t\t\t      GLQF_FD_SIZE_FD_GSIZE_S;\n+\t\t\t\tfunc_p->fd_fltr_guar =\n+\t\t\t\t\tice_get_num_per_func(hw, val);\n+\t\t\t\tval = (reg_val & GLQF_FD_SIZE_FD_BSIZE_M) >>\n+\t\t\t\t      GLQF_FD_SIZE_FD_BSIZE_S;\n+\t\t\t\tfunc_p->fd_fltr_best_effort = val;\n+\t\t\t\tice_debug(hw, ICE_DBG_INIT,\n+\t\t\t\t\t  \"HW:func.fd_fltr guar= %d\\n\",\n+\t\t\t\t\t  func_p->fd_fltr_guar);\n+\t\t\t\tice_debug(hw, ICE_DBG_INIT,\n+\t\t\t\t\t  \"HW:func.fd_fltr best effort=%d\\n\",\n+\t\t\t\t\t  func_p->fd_fltr_best_effort);\n+\t\t\t}\n+\t\t\tbreak;\n+\t\t}\n \t\tcase ICE_AQC_CAPS_MAX_MTU:\n \t\t\tcaps->max_mtu = number;\n \t\t\tif (dev_p)\ndiff --git a/drivers/net/ice/base/ice_common.h b/drivers/net/ice/base/ice_common.h\nindex 9665f3204..4dc43dcfe 100644\n--- a/drivers/net/ice/base/ice_common.h\n+++ b/drivers/net/ice/base/ice_common.h\n@@ -9,6 +9,7 @@\n \n #include \"ice_flex_pipe.h\"\n #include \"ice_switch.h\"\n+#include \"ice_fdir.h\"\n \n enum ice_fw_modes {\n \tICE_FW_MODE_NORMAL,\ndiff --git a/drivers/net/ice/base/ice_fdir.c b/drivers/net/ice/base/ice_fdir.c\nnew file mode 100644\nindex 000000000..4bc8e6dcb\n--- /dev/null\n+++ b/drivers/net/ice/base/ice_fdir.c\n@@ -0,0 +1,742 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2001-2019\n+ */\n+\n+#include \"ice_common.h\"\n+#include \"ice_fdir.h\"\n+\n+/* These are dummy packet headers used to program flow director filters. */\n+static const u8 ice_fdir_tcpv4_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,\n+\t0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,\n+\t0x20, 0x00, 0x00, 0x00, 0x00, 0x00\n+};\n+\n+static const u8 ice_fdir_udpv4_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,\n+\t0x00, 0x1C, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00,\n+};\n+\n+static const u8 ice_fdir_sctpv4_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,\n+\t0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x84,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+};\n+\n+static const u8 ice_fdir_ipv4_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,\n+\t0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x10,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00\n+};\n+\n+static const u8 ice_fdir_tcpv6_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,\n+\t0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00,\n+\t0x00, 0x00,\n+};\n+\n+static const u8 ice_fdir_udpv6_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,\n+\t0x00, 0x00, 0x00, 0x08, 0x11, 0x40, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x08, 0x00, 0x00,\n+};\n+\n+static const u8 ice_fdir_sctpv6_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,\n+\t0x00, 0x00, 0x00, 0x0C, 0x84, 0x40, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00,\n+};\n+\n+static const u8 ice_fdir_ipv6_pkt[] = {\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+\t0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n+};\n+\n+/* Flow Director dummy packet table */\n+static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV4_TCP,\n+\t\tsizeof(ice_fdir_tcpv4_pkt),\n+\t\tice_fdir_tcpv4_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV4_UDP,\n+\t\tsizeof(ice_fdir_udpv4_pkt),\n+\t\tice_fdir_udpv4_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV4_SCTP,\n+\t\tsizeof(ice_fdir_sctpv4_pkt),\n+\t\tice_fdir_sctpv4_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV4_OTHER,\n+\t\tsizeof(ice_fdir_ipv4_pkt),\n+\t\tice_fdir_ipv4_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV6_TCP,\n+\t\tsizeof(ice_fdir_tcpv6_pkt),\n+\t\tice_fdir_tcpv6_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV6_UDP,\n+\t\tsizeof(ice_fdir_udpv6_pkt),\n+\t\tice_fdir_udpv6_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV6_SCTP,\n+\t\tsizeof(ice_fdir_sctpv6_pkt),\n+\t\tice_fdir_sctpv6_pkt,\n+\t},\n+\t{\n+\t\tICE_FLTR_PTYPE_NONF_IPV6_OTHER,\n+\t\tsizeof(ice_fdir_ipv6_pkt),\n+\t\tice_fdir_ipv6_pkt,\n+\t},\n+};\n+\n+#define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)\n+\n+/* Flow Direcotr (FD) filter program descriptor Context */\n+static const struct ice_ctx_ele ice_fd_fltr_desc_ctx_info[] = {\n+\t\t\t\t\t   /* Field\t\tWidth\tLSB */\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, qindex,\t\t11,\t0),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_q,\t\t1,\t11),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, comp_report,\t2,\t12),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_space,\t\t2,\t14),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_index,\t\t13,\t16),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, cnt_ena,\t\t2,\t29),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, evict_ena,\t\t1,\t31),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq,\t\t3,\t32),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, toq_prio,\t\t3,\t35),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, dpu_recipe,\t\t2,\t38),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, drop,\t\t1,\t40),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_prio,\t\t3,\t41),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_mdid,\t\t4,\t44),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, flex_val,\t\t16,\t48),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, dtype,\t\t4,\t64),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, pcmd,\t\t1,\t68),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof_prio,\t3,\t69),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, desc_prof,\t\t6,\t72),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, fd_vsi,\t\t10,\t78),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, swap,\t\t1,\t88),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_prio,\t\t3,\t89),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid_mdid,\t\t4,\t92),\n+\tICE_CTX_STORE(ice_fd_fltr_desc_ctx, fdid,\t\t32,\t96),\n+\t{ 0 }\n+};\n+\n+/**\n+ * ice_set_dflt_val_fd_desc\n+ * @fd_fltr_ctx: pointer to fd filter descriptor\n+ */\n+void\n+ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)\n+{\n+\tfd_fltr_ctx->comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;\n+\tfd_fltr_ctx->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;\n+\tfd_fltr_ctx->fd_space = ICE_FXD_FLTR_QW0_FD_SPACE_GUAR_BEST;\n+\tfd_fltr_ctx->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;\n+\tfd_fltr_ctx->evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_TRUE;\n+\tfd_fltr_ctx->toq = ICE_FXD_FLTR_QW0_TO_Q_EQUALS_QINDEX;\n+\tfd_fltr_ctx->toq_prio = ICE_FXD_FLTR_QW0_TO_Q_PRIO1;\n+\tfd_fltr_ctx->dpu_recipe = ICE_FXD_FLTR_QW0_DPU_RECIPE_DFLT;\n+\tfd_fltr_ctx->drop = ICE_FXD_FLTR_QW0_DROP_NO;\n+\tfd_fltr_ctx->flex_prio = ICE_FXD_FLTR_QW0_FLEX_PRI_NONE;\n+\tfd_fltr_ctx->flex_mdid = ICE_FXD_FLTR_QW0_FLEX_MDID0;\n+\tfd_fltr_ctx->flex_val = ICE_FXD_FLTR_QW0_FLEX_VAL0;\n+\tfd_fltr_ctx->dtype = ICE_TX_DESC_DTYPE_FLTR_PROG;\n+\tfd_fltr_ctx->desc_prof_prio = ICE_FXD_FLTR_QW1_PROF_PRIO_ZERO;\n+\tfd_fltr_ctx->desc_prof = ICE_FXD_FLTR_QW1_PROF_ZERO;\n+\tfd_fltr_ctx->swap = ICE_FXD_FLTR_QW1_SWAP_SET;\n+\tfd_fltr_ctx->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ZERO;\n+\tfd_fltr_ctx->fdid_mdid = ICE_FXD_FLTR_QW1_FDID_MDID_FD;\n+\tfd_fltr_ctx->fdid = ICE_FXD_FLTR_QW1_FDID_ZERO;\n+}\n+\n+/**\n+ * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct\n+ * @hw: pointer to the hardware structure\n+ * @input: filter\n+ * @fdesc: filter descriptor\n+ * @add: if add is true, this is an add operation, false implies delete\n+ */\n+void\n+ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,\n+\t\t       struct ice_fltr_desc *fdesc, bool add)\n+{\n+\tstruct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };\n+\n+\t/* set default context info */\n+\tice_set_dflt_val_fd_desc(&fdir_fltr_ctx);\n+\n+\t/* change sideband filtering values */\n+\tfdir_fltr_ctx.fdid = input->fltr_id;\n+\tif (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) {\n+\t\tfdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES;\n+\t\tfdir_fltr_ctx.qindex = 0;\n+\t} else {\n+\t\tfdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;\n+\t\tfdir_fltr_ctx.qindex = input->q_index;\n+\t}\n+\tfdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;\n+\tfdir_fltr_ctx.cnt_index = input->cnt_index;\n+\tfdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);\n+\tfdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;\n+\tfdir_fltr_ctx.toq_prio = 3;\n+\tfdir_fltr_ctx.pcmd = (add) ? ICE_FXD_FLTR_QW1_PCMD_ADD :\n+\t\tICE_FXD_FLTR_QW1_PCMD_REMOVE;\n+\tfdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;\n+\tfdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;\n+\tfdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;\n+\tfdir_fltr_ctx.fdid_prio = 3;\n+\tfdir_fltr_ctx.desc_prof = 1;\n+\tfdir_fltr_ctx.desc_prof_prio = 3;\n+\tice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);\n+}\n+\n+/**\n+ * ice_set_fd_desc_val\n+ * @fd_fltr_ctx: pointer to fd filter descriptor context\n+ * @fdir_desc: populated with fd filter descriptor values\n+ */\n+void\n+ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx,\n+\t\t    struct ice_fltr_desc *fdir_desc)\n+{\n+\tu64 ctx_buf[2] = { 0 };\n+\n+\tice_set_ctx((u8 *)fd_fltr_ctx, (u8 *)ctx_buf,\n+\t\t    ice_fd_fltr_desc_ctx_info);\n+\tfdir_desc->qidx_compq_space_stat = CPU_TO_LE64(ctx_buf[0]);\n+\tfdir_desc->dtype_cmd_vsi_fdid = CPU_TO_LE64(ctx_buf[1]);\n+}\n+\n+/**\n+ * ice_alloc_fd_res_cntr - obtain counter resource for FD type\n+ * @hw: pointer to the hardware structure\n+ * @cntr_id: returns counter index\n+ */\n+enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)\n+{\n+\treturn ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,\n+\t\t\t\t  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);\n+}\n+\n+/**\n+ * ice_free_fd_res_cntr - Free counter resource for FD type\n+ * @hw: pointer to the hardware structure\n+ * @cntr_id: counter index to be freed\n+ */\n+enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)\n+{\n+\treturn ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,\n+\t\t\t\t ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);\n+}\n+\n+/**\n+ * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries\n+ * @hw: pointer to the hardware structure\n+ * @cntr_id: returns counter index\n+ * @num_fltr: number of filter entries to be allocated\n+ */\n+enum ice_status\n+ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)\n+{\n+\treturn ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,\n+\t\t\t\t  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,\n+\t\t\t\t  cntr_id);\n+}\n+\n+/**\n+ * ice_free_fd_guar_item - Free flow director guaranteed entries\n+ * @hw: pointer to the hardware structure\n+ * @cntr_id: counter index that needs to be freed\n+ * @num_fltr: number of filters to be freed\n+ */\n+enum ice_status\n+ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)\n+{\n+\treturn ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,\n+\t\t\t\t ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,\n+\t\t\t\t cntr_id);\n+}\n+\n+/**\n+ * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries\n+ * @hw: pointer to the hardware structure\n+ * @cntr_id: returns counter index\n+ * @num_fltr: number of filter entries to be allocated\n+ */\n+enum ice_status\n+ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)\n+{\n+\treturn ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,\n+\t\t\t\t  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,\n+\t\t\t\t  cntr_id);\n+}\n+\n+/**\n+ * ice_free_fd_shrd_item - Free flow director shared entries\n+ * @hw: pointer to the hardware structure\n+ * @cntr_id: counter index that needs to be freed\n+ * @num_fltr: number of filters to be freed\n+ */\n+enum ice_status\n+ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)\n+{\n+\treturn ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,\n+\t\t\t\t ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,\n+\t\t\t\t cntr_id);\n+}\n+\n+/**\n+ * ice_get_fdir_cnt_all - get the number of Flow Director filters\n+ * @hw: hardware data structure\n+ *\n+ * Returns the number of filters available on device\n+ */\n+int ice_get_fdir_cnt_all(struct ice_hw *hw)\n+{\n+\treturn hw->func_caps.fd_fltr_guar +\n+\t       hw->func_caps.fd_fltr_best_effort;\n+}\n+\n+/**\n+ * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer.\n+ * @pkt: packet buffer\n+ * @offset: offset into buffer\n+ * @addr: IPv6 address to convert and insert into pkt at offset\n+ */\n+static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)\n+{\n+\tint idx;\n+\n+\tfor (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)\n+\t\tice_memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],\n+\t\t\t   sizeof(*addr), ICE_NONDMA_TO_NONDMA);\n+}\n+\n+/**\n+ * ice_pkt_insert_u16 - insert a be16 value into a memory buffer.\n+ * @pkt: packet buffer\n+ * @offset: offset into buffer\n+ * @data: 16 bit value to convert and insert into pkt at offset\n+ */\n+static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)\n+{\n+\tice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);\n+}\n+\n+/**\n+ * ice_pkt_insert_u32 - insert a be32 value into a memory buffer.\n+ * @pkt: packet buffer\n+ * @offset: offset into buffer\n+ * @data: 32 bit value to convert and insert into pkt at offset\n+ */\n+static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)\n+{\n+\tice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);\n+}\n+\n+/**\n+ * ice_fdir_get_prgm_pkt - generate a dummy packet\n+ * @input: flow director filter data structure\n+ * @pkt: pointer to return filter packet\n+ * @frag: generate a fragment packet\n+ */\n+enum ice_status\n+ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag)\n+{\n+\tenum ice_fltr_ptype flow;\n+\tu16 idx;\n+\n+\tif (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {\n+\t\tswitch (input->ip.v4.proto) {\n+\t\tcase ICE_IP_PROTO_TCP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;\n+\t\t\tbreak;\n+\t\tcase ICE_IP_PROTO_UDP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;\n+\t\t\tbreak;\n+\t\tcase ICE_IP_PROTO_SCTP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;\n+\t\t\tbreak;\n+\t\tcase ICE_IP_PROTO_IP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn ICE_ERR_PARAM;\n+\t\t}\n+\t} else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {\n+\t\tswitch (input->ip.v6.proto) {\n+\t\tcase ICE_IP_PROTO_TCP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;\n+\t\t\tbreak;\n+\t\tcase ICE_IP_PROTO_UDP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;\n+\t\t\tbreak;\n+\t\tcase ICE_IP_PROTO_SCTP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;\n+\t\t\tbreak;\n+\t\tcase ICE_IP_PROTO_IP:\n+\t\t\tflow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\treturn ICE_ERR_PARAM;\n+\t\t}\n+\t} else {\n+\t\tflow = input->flow_type;\n+\t}\n+\n+\tfor (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)\n+\t\tif (ice_fdir_pkt[idx].flow == flow)\n+\t\t\tbreak;\n+\tif (idx == ICE_FDIR_NUM_PKT)\n+\t\treturn ICE_ERR_PARAM;\n+\tice_memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len,\n+\t\t   ICE_NONDMA_TO_NONDMA);\n+\n+\tswitch (flow) {\n+\tcase ICE_FLTR_PTYPE_NONF_IPV4_TCP:\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_TCP_DST_PORT_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_port);\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_TCP_SRC_PORT_OFFSET,\n+\t\t\t\t   input->ip.v4.src_port);\n+\t\tif (frag)\n+\t\t\tpkt[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV4_UDP:\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_port);\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_UDP_SRC_PORT_OFFSET,\n+\t\t\t\t   input->ip.v4.src_port);\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV4_SCTP:\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_SCTP_DST_PORT_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_port);\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_SCTP_SRC_PORT_OFFSET,\n+\t\t\t\t   input->ip.v4.src_port);\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV4_OTHER:\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_DST_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.dst_ip);\n+\t\tice_pkt_insert_u32(pkt, ICE_IPV4_SRC_ADDR_OFFSET,\n+\t\t\t\t   input->ip.v4.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV4_PROTO_OFFSET, 0);\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV6_TCP:\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.dst_ip);\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV6_TCP_DST_PORT_OFFSET,\n+\t\t\t\t   input->ip.v6.dst_port);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV6_TCP_SRC_PORT_OFFSET,\n+\t\t\t\t   input->ip.v6.src_port);\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV6_UDP:\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.dst_ip);\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV6_UDP_DST_PORT_OFFSET,\n+\t\t\t\t   input->ip.v6.dst_port);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV6_UDP_SRC_PORT_OFFSET,\n+\t\t\t\t   input->ip.v6.src_port);\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV6_SCTP:\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.dst_ip);\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.src_ip);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV6_SCTP_DST_PORT_OFFSET,\n+\t\t\t\t   input->ip.v6.dst_port);\n+\t\tice_pkt_insert_u16(pkt, ICE_IPV6_SCTP_SRC_PORT_OFFSET,\n+\t\t\t\t   input->ip.v6.src_port);\n+\t\tbreak;\n+\tcase ICE_FLTR_PTYPE_NONF_IPV6_OTHER:\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_DST_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.dst_ip);\n+\t\tice_pkt_insert_ipv6_addr(pkt, ICE_IPV6_SRC_ADDR_OFFSET,\n+\t\t\t\t\t input->ip.v6.src_ip);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn ICE_ERR_PARAM;\n+\t}\n+\n+\tif (input->flex_fltr)\n+\t\tice_pkt_insert_u16(pkt, input->flex_offset, input->flex_word);\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_fdir_has_frag - does flow type have 2 ptypes\n+ * @flow: flow ptype\n+ *\n+ * returns true is there is a fragment packet for this ptype\n+ */\n+bool ice_fdir_has_frag(enum ice_fltr_ptype flow)\n+{\n+\tif (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)\n+\t\treturn true;\n+\telse\n+\t\treturn false;\n+}\n+\n+/**\n+ * ice_fdir_find_by_idx - find filter with idx\n+ * @hw: pointer to hardware structure\n+ * @fltr_idx: index to find.\n+ *\n+ * Returns pointer to filter if found or null\n+ */\n+struct ice_fdir_fltr *\n+ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)\n+{\n+\tstruct ice_fdir_fltr *rule = NULL;\n+\n+\tLIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,\n+\t\t\t    fltr_node) {\n+\t\t/* rule ID found in the list */\n+\t\tif (fltr_idx == rule->fltr_id)\n+\t\t\treturn rule;\n+\t\tif (fltr_idx < rule->fltr_id)\n+\t\t\tbreak;\n+\t}\n+\treturn NULL;\n+}\n+\n+/**\n+ * ice_fdir_list_add_fltr - add a new node to the flow director filter list\n+ * @hw: hardware structure\n+ * @fltr: filter node to add to structure\n+ */\n+void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)\n+{\n+\tstruct ice_fdir_fltr *rule, *parent = NULL;\n+\n+\tLIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,\n+\t\t\t    fltr_node) {\n+\t\t/* rule ID found or pass its spot in the list */\n+\t\tif (rule->fltr_id >= fltr->fltr_id)\n+\t\t\tbreak;\n+\t\tparent = rule;\n+\t}\n+\n+\tif (parent)\n+\t\tLIST_ADD_AFTER(&fltr->fltr_node, &parent->fltr_node);\n+\telse\n+\t\tLIST_ADD(&fltr->fltr_node, &hw->fdir_list_head);\n+}\n+\n+/**\n+ * ice_fdir_update_cntrs - increment / decrement filter counter\n+ * @hw: pointer to hardware structure\n+ * @flow: filter flow type\n+ * @add: true implies filters added\n+ */\n+void\n+ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)\n+{\n+\tint incr;\n+\n+\tincr = (add) ? 1 : -1;\n+\thw->fdir_active_fltr += incr;\n+\tif (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)\n+\t\tice_debug(hw, ICE_DBG_SW, \"Unknown filter type %d\\n\", flow);\n+\telse\n+\t\thw->fdir_fltr_cnt[flow] += incr;\n+}\n+\n+/**\n+ * ice_cmp_ipv6_addr - compare 2 IP v6 addresses\n+ * @a: IP v6 address\n+ * @b: IP v6 address\n+ *\n+ * Returns 0 on equal, returns non-0 if different\n+ */\n+static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)\n+{\n+\treturn memcmp(a, b, 4 * sizeof(__be32));\n+}\n+\n+/**\n+ * ice_fdir_comp_ipv6_rules - compare 2 filters\n+ * @a: a Flow Director filter data structure\n+ * @b: a Flow Director filter data structure\n+ * @v6: bool true if v6 filter\n+ *\n+ * Returns true if the filters match\n+ */\n+static bool\n+ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)\n+{\n+\tenum ice_fltr_ptype flow_type = a->flow_type;\n+\n+\t/* The calling function already checks that the two filters have the\n+\t * same flow_type.\n+\t */\n+\tif (!v6) {\n+\t\tif (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||\n+\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||\n+\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {\n+\t\t\tif (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&\n+\t\t\t    a->ip.v4.src_ip == b->ip.v4.src_ip &&\n+\t\t\t    a->ip.v4.dst_port == b->ip.v4.dst_port &&\n+\t\t\t    a->ip.v4.src_port == b->ip.v4.src_port)\n+\t\t\t\treturn true;\n+\t\t} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {\n+\t\t\tif (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&\n+\t\t\t    a->ip.v4.src_ip == b->ip.v4.src_ip &&\n+\t\t\t    a->ip.v4.l4_header == b->ip.v4.l4_header &&\n+\t\t\t    a->ip.v4.proto == b->ip.v4.proto &&\n+\t\t\t    a->ip.v4.ip_ver == b->ip.v4.ip_ver &&\n+\t\t\t    a->ip.v4.tos == b->ip.v4.tos)\n+\t\t\t\treturn true;\n+\t\t}\n+\t} else {\n+\t\tif (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||\n+\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||\n+\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {\n+\t\t\tif (a->ip.v6.dst_port == b->ip.v6.dst_port &&\n+\t\t\t    a->ip.v6.src_port == b->ip.v6.src_port &&\n+\t\t\t    !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,\n+\t\t\t\t\t       b->ip.v6.dst_ip) &&\n+\t\t\t    !ice_cmp_ipv6_addr(a->ip.v6.src_ip,\n+\t\t\t\t\t       b->ip.v6.src_ip))\n+\t\t\t\treturn true;\n+\t\t} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {\n+\t\t\tif (a->ip.v6.dst_port == b->ip.v6.dst_port &&\n+\t\t\t    a->ip.v6.src_port == b->ip.v6.src_port)\n+\t\t\t\treturn true;\n+\t\t}\n+\t}\n+\n+\treturn false;\n+}\n+\n+/**\n+ * ice_fdir_is_dup_fltr - test if filter is already in list for PF\n+ * @hw: hardware data structure\n+ * @input: Flow Director filter data structure\n+ *\n+ * Returns true if the filter is found in the list\n+ */\n+bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)\n+{\n+\tenum ice_fltr_ptype flow_type;\n+\tstruct ice_fdir_fltr *rule;\n+\tbool ret = false;\n+\n+\trule = NULL;\n+\n+\tLIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,\n+\t\t\t    fltr_node) {\n+\t\tif (rule->flow_type == input->flow_type) {\n+\t\t\tflow_type = input->flow_type;\n+\t\t\tif (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||\n+\t\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||\n+\t\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||\n+\t\t\t    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)\n+\t\t\t\tret = ice_fdir_comp_rules(rule, input, false);\n+\t\t\telse\n+\t\t\t\tret = ice_fdir_comp_rules(rule, input, true);\n+\t\t\tif (ret)\n+\t\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\treturn ret;\n+}\n+\n+/**\n+ * ice_clear_vsi_fd_table - admin command to clear FD table for a VSI\n+ * @hw: hardware data structure\n+ * @vsi_num: vsi_num (HW VSI num)\n+ *\n+ * Clears FD table entries by issuing admin command (direct, 0x0B06)\n+ * Must to pass valid vsi_num as returned by \"AddVSI\".\n+ */\n+enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num)\n+{\n+\tstruct ice_aqc_clear_fd_table *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tcmd = &desc.params.clear_fd_table;\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);\n+\tcmd->clear_type = CL_FD_VM_VF_TYPE_VSI_IDX;\n+\n+\tcmd->vsi_index = CPU_TO_LE16(vsi_num);\n+\treturn ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);\n+}\n+\n+/**\n+ * ice_clear_pf_fd_table - admin command to clear FD table for PF\n+ * @hw: hardware data structure\n+ *\n+ * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06)\n+ */\n+enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw)\n+{\n+\tstruct ice_aqc_clear_fd_table *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tcmd = &desc.params.clear_fd_table;\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);\n+\tcmd->clear_type = CL_FD_VM_VF_TYPE_PF_IDX;\n+\t/* vsi_index must be 0 to clear FD table for a PF */\n+\tcmd->vsi_index = CPU_TO_LE16(0);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);\n+}\ndiff --git a/drivers/net/ice/base/ice_fdir.h b/drivers/net/ice/base/ice_fdir.h\nnew file mode 100644\nindex 000000000..2ecb147f1\n--- /dev/null\n+++ b/drivers/net/ice/base/ice_fdir.h\n@@ -0,0 +1,202 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2001-2019\n+ */\n+\n+#ifndef _ICE_FDIR_H_\n+#define _ICE_FDIR_H_\n+\n+#include \"ice_common.h\"\n+\n+/* Flow Director (FD) Filter Programming descriptor */\n+struct ice_fd_fltr_desc_ctx {\n+\tu32 fdid;\n+\tu16 qindex;\n+\tu16 cnt_index;\n+\tu16 fd_vsi;\n+\tu16 flex_val;\n+\tu8 comp_q;\n+\tu8 comp_report;\n+\tu8 fd_space;\n+\tu8 cnt_ena;\n+\tu8 evict_ena;\n+\tu8 toq;\n+\tu8 toq_prio;\n+\tu8 dpu_recipe;\n+\tu8 drop;\n+\tu8 flex_prio;\n+\tu8 flex_mdid;\n+\tu8 dtype;\n+\tu8 pcmd;\n+\tu8 desc_prof_prio;\n+\tu8 desc_prof;\n+\tu8 swap;\n+\tu8 fdid_prio;\n+\tu8 fdid_mdid;\n+};\n+\n+enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id);\n+enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id);\n+void\n+ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx,\n+\t\t    struct ice_fltr_desc *fdir_desc);\n+void ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx);\n+enum ice_status\n+ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr);\n+enum ice_status\n+ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr);\n+enum ice_status\n+ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr);\n+enum ice_status\n+ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr);\n+enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num);\n+enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw);\n+\n+#define ICE_FDIR_IP_PROTOCOLS\n+#define ICE_IP_PROTO_TCP\t\t6\n+#define ICE_IP_PROTO_UDP\t\t17\n+#define ICE_IP_PROTO_SCTP\t\t132\n+#define ICE_IP_PROTO_IP\t\t\t0\n+#define ICE_IP_PROTO_ESP\t\t50\n+\n+#define ICE_FDIR_MAX_RAW_PKT_SIZE\t512\n+#define ICE_FDIR_BUF_FULL_MARGIN\t10\n+#define ICE_FDIR_BUF_HEAD_ROOM\t\t32\n+\n+/* macros for offsets into packets for flow director programming */\n+#define ICE_IPV4_SRC_ADDR_OFFSET\t26\n+#define ICE_IPV4_DST_ADDR_OFFSET\t30\n+#define ICE_IPV4_TCP_SRC_PORT_OFFSET\t34\n+#define ICE_IPV4_TCP_DST_PORT_OFFSET\t36\n+#define ICE_IPV4_UDP_SRC_PORT_OFFSET\t34\n+#define ICE_IPV4_UDP_DST_PORT_OFFSET\t36\n+#define ICE_IPV4_SCTP_SRC_PORT_OFFSET\t34\n+#define ICE_IPV4_SCTP_DST_PORT_OFFSET\t36\n+#define ICE_IPV4_PROTO_OFFSET\t\t23\n+#define ICE_IPV6_SRC_ADDR_OFFSET\t22\n+#define ICE_IPV6_DST_ADDR_OFFSET\t38\n+#define ICE_IPV6_TCP_SRC_PORT_OFFSET\t54\n+#define ICE_IPV6_TCP_DST_PORT_OFFSET\t56\n+#define ICE_IPV6_UDP_SRC_PORT_OFFSET\t54\n+#define ICE_IPV6_UDP_DST_PORT_OFFSET\t56\n+#define ICE_IPV6_SCTP_SRC_PORT_OFFSET\t54\n+#define ICE_IPV6_SCTP_DST_PORT_OFFSET\t56\n+\n+#define ICE_FDIR_MAX_FLTRS\t\t16384\n+\n+/* IP v4 has 2 flag bits that enable fragment processing: DF and MF. DF\n+ * requests that the packet not be fragmented. MF indicates that a packet has\n+ * been fragmented.\n+ */\n+#define ICE_FDIR_IPV4_PKT_FLAG_DF\t\t0x20\n+#define ICE_FDIR_IPV4_PKT_FLAG_MF\t\t0x40\n+\n+enum ice_fltr_prgm_desc_dest {\n+\tICE_FLTR_PRGM_DESC_DEST_DROP_PKT,\n+\tICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX,\n+\tICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP,\n+\tICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER,\n+};\n+\n+enum ice_fltr_prgm_desc_fd_status {\n+\tICE_FLTR_PRGM_DESC_FD_STATUS_NONE,\n+\tICE_FLTR_PRGM_DESC_FD_STATUS_FD_ID,\n+\tICE_FLTR_PRGM_DESC_FD_STATUS_FD_ID_4FLEX_BYTES,\n+\tICE_FLTR_PRGM_DESC_FD_STATUS_8FLEX_BYTES,\n+};\n+\n+#define ICE_FLTR_PRGM_FLEX_WORD_SIZE\tsizeof(__be16)\n+\n+struct ice_rx_flow_userdef {\n+\tu16 flex_word;\n+\tu16 flex_offset;\n+\tu16 flex_fltr;\n+};\n+\n+struct ice_fdir_v4 {\n+\t__be32 dst_ip;\n+\t__be32 src_ip;\n+\t__be16 dst_port;\n+\t__be16 src_port;\n+\t__be32 l4_header;\n+\t__be32 sec_parm_idx;\t/* security parameter index */\n+\tu8 tos;\n+\tu8 ip_ver;\n+\tu8 proto;\n+};\n+\n+#define ICE_IPV6_ADDR_LEN_AS_U32\t\t4\n+\n+struct ice_fdir_v6 {\n+\t__be32 dst_ip[ICE_IPV6_ADDR_LEN_AS_U32];\n+\t__be32 src_ip[ICE_IPV6_ADDR_LEN_AS_U32];\n+\t__be16 dst_port;\n+\t__be16 src_port;\n+\t__be32 l4_header; /* next header */\n+\t__be32 sec_parm_idx; /* security parameter index */\n+\tu8 tc;\n+\tu8 proto;\n+};\n+\n+struct ice_fdir_extra {\n+\tu8 dst_mac[ETH_ALEN];\t/* dest MAC address */\n+\tu32 usr_def[2];\t\t/* user data */\n+\t__be16 vlan_type;\t/* VLAN ethertype */\n+\t__be16 vlan_tag;\t/* VLAN tag info */\n+};\n+\n+struct ice_fdir_fltr {\n+\tstruct LIST_ENTRY_TYPE fltr_node;\n+\tenum ice_fltr_ptype flow_type;\n+\n+\tunion {\n+\t\tstruct ice_fdir_v4 v4;\n+\t\tstruct ice_fdir_v6 v6;\n+\t} ip, mask;\n+\n+\tstruct ice_fdir_extra ext_data;\n+\tstruct ice_fdir_extra ext_mask;\n+\n+\t/* flex byte filter data */\n+\t__be16 flex_word;\n+\tu16 flex_offset;\n+\tu16 flex_fltr;\n+\n+\t/* filter control */\n+\tu16 q_index;\n+#ifdef ADQ_SUPPORT\n+\tu16 orig_q_index;\n+#endif /* ADQ_SUPPORT */\n+\tu16 dest_vsi;\n+\tu8 dest_ctl;\n+\tu8 fltr_status;\n+\tu16 cnt_index;\n+\tu32 fltr_id;\n+};\n+\n+\n+/* Dummy packet filter definition structure. */\n+struct ice_fdir_base_pkt {\n+\tenum ice_fltr_ptype flow;\n+\tu16 pkt_len;\n+\tconst u8 *pkt;\n+};\n+\n+void\n+ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,\n+\t\t       struct ice_fltr_desc *fdesc, bool add);\n+enum ice_status\n+ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag);\n+enum ice_status\n+ice_add_del_fdir(struct ice_hw *hw, struct ice_fdir_fltr *input, bool add);\n+int ice_get_fdir_cnt_all(struct ice_hw *hw);\n+bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input);\n+enum ice_status\n+ice_update_fdir_list_entry(struct ice_hw *hw, struct ice_fdir_fltr *input,\n+\t\t\t   u16 sw_idx);\n+bool ice_fdir_has_frag(enum ice_fltr_ptype flow);\n+struct ice_fdir_fltr *\n+ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx);\n+void\n+ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add);\n+void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input);\n+#endif /* _ICE_FDIR_H_ */\ndiff --git a/drivers/net/ice/base/ice_flex_pipe.c b/drivers/net/ice/base/ice_flex_pipe.c\nindex 99108d81c..37bb4cbb5 100644\n--- a/drivers/net/ice/base/ice_flex_pipe.c\n+++ b/drivers/net/ice/base/ice_flex_pipe.c\n@@ -1275,6 +1275,25 @@ void ice_free_seg(struct ice_hw *hw)\n }\n \n /**\n+ * ice_init_fd_mask_regs - initialize Flow Director mask registers\n+ * @hw: pointer to the HW struct\n+ *\n+ * This function sets up the Flow Director mask registers to allow for complete\n+ * masking off of any of the 24 Field Vector words. After this call, mask 0 will\n+ * mask off all of FV index 0, mask 1 will mask off all of FV index 1, etc.\n+ */\n+static void ice_init_fd_mask_regs(struct ice_hw *hw)\n+{\n+\tu16 i;\n+\n+\tfor (i = 0; i < hw->blk[ICE_BLK_FD].es.fvw; i++) {\n+\t\twr32(hw, GLQF_FDMASK(i), i);\n+\t\tice_debug(hw, ICE_DBG_INIT, \"init fd mask(%d): %x = %x\\n\", i,\n+\t\t\t  GLQF_FDMASK(i), i);\n+\t}\n+}\n+\n+/**\n  * ice_init_pkg_regs - initialize additional package registers\n  * @hw: pointer to the hardware structure\n  */\n@@ -1287,6 +1306,8 @@ static void ice_init_pkg_regs(struct ice_hw *hw)\n \t/* setup Switch block input mask, which is 48-bits in two parts */\n \twr32(hw, GL_PREEXT_L2_PMASK0(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_L);\n \twr32(hw, GL_PREEXT_L2_PMASK1(ICE_SW_BLK_IDX), ICE_SW_BLK_INP_MASK_H);\n+\t/* setup default flow director masks */\n+\tice_init_fd_mask_regs(hw);\n }\n \n /**\n@@ -3783,6 +3804,205 @@ ice_upd_prof_hw(struct ice_hw *hw, enum ice_block blk,\n }\n \n /**\n+ * ice_update_fd_mask - set Flow Director Field Vector mask for a profile\n+ * @hw: pointer to the HW struct\n+ * @prof_id: profile ID\n+ * @mask_sel: mask select\n+ *\n+ * This function enable any of the masks selected by the mask select parameter\n+ * for the profile specified.\n+ */\n+static void ice_update_fd_mask(struct ice_hw *hw, u16 prof_id, u32 mask_sel)\n+{\n+\twr32(hw, GLQF_FDMASK_SEL(prof_id), mask_sel);\n+\n+\tice_debug(hw, ICE_DBG_INIT, \"fd mask(%d): %x = %x\\n\", prof_id,\n+\t\t  GLQF_FDMASK_SEL(prof_id), mask_sel);\n+}\n+\n+#define ICE_SRC_DST_MAX_COUNT\t8\n+\n+struct ice_fd_src_dst_pair {\n+\tu8 prot_id;\n+\tu8 count;\n+\tu16 off;\n+};\n+\n+static const struct ice_fd_src_dst_pair ice_fd_pairs[] = {\n+\t/* These are defined in pairs */\n+\t{ ICE_PROT_IPV4_OF_OR_S, 2, 12 },\n+\t{ ICE_PROT_IPV4_OF_OR_S, 2, 16 },\n+\n+\t{ ICE_PROT_IPV4_IL, 2, 12 },\n+\t{ ICE_PROT_IPV4_IL, 2, 16 },\n+\n+\t{ ICE_PROT_IPV6_OF_OR_S, 8, 8 },\n+\t{ ICE_PROT_IPV6_OF_OR_S, 8, 24 },\n+\n+\t{ ICE_PROT_IPV6_IL, 8, 8 },\n+\t{ ICE_PROT_IPV6_IL, 8, 24 },\n+\n+\t{ ICE_PROT_TCP_IL, 1, 0 },\n+\t{ ICE_PROT_TCP_IL, 1, 2 },\n+\n+\t{ ICE_PROT_UDP_OF, 1, 0 },\n+\t{ ICE_PROT_UDP_OF, 1, 2 },\n+\n+\t{ ICE_PROT_UDP_IL_OR_S, 1, 0 },\n+\t{ ICE_PROT_UDP_IL_OR_S, 1, 2 },\n+\n+\t{ ICE_PROT_SCTP_IL, 1, 0 },\n+\t{ ICE_PROT_SCTP_IL, 1, 2 }\n+};\n+\n+#define ICE_FD_SRC_DST_PAIR_COUNT\tARRAY_SIZE(ice_fd_pairs)\n+\n+/**\n+ * ice_update_fd_swap - set register appropriately for a FD FV extraction\n+ * @hw: pointer to the HW struct\n+ * @prof_id: profile ID\n+ * @es: extraction sequence (length of array is determined by the block)\n+ */\n+static enum ice_status\n+ice_update_fd_swap(struct ice_hw *hw, u16 prof_id, struct ice_fv_word *es)\n+{\n+\tice_declare_bitmap(pair_list, ICE_FD_SRC_DST_PAIR_COUNT);\n+\tu8 pair_start[ICE_FD_SRC_DST_PAIR_COUNT] = { 0 };\n+#define ICE_FD_FV_NOT_FOUND (-2)\n+\ts8 first_free = ICE_FD_FV_NOT_FOUND;\n+\tu8 used[ICE_MAX_FV_WORDS] = { 0 };\n+\ts8 orig_free, si;\n+\tu32 mask_sel = 0;\n+\tu8 i, j, k;\n+\n+\tice_memset(pair_list, 0, sizeof(pair_list), ICE_NONDMA_MEM);\n+\n+\tice_init_fd_mask_regs(hw);\n+\n+\t/* This code assumes that the Flow Director field vectors are assigned\n+\t * from the end of the FV indexes working towards the zero index, that\n+\t * only complete fields will be included and will be consecutive, and\n+\t * that there are no gaps between valid indexes.\n+\t */\n+\n+\t/* Determine swap fields present */\n+\tfor (i = 0; i < hw->blk[ICE_BLK_FD].es.fvw; i++) {\n+\t\t/* Find the first free entry, assuming right to left population.\n+\t\t * This is where we can start adding additional pairs if needed.\n+\t\t */\n+\t\tif (first_free == ICE_FD_FV_NOT_FOUND && es[i].prot_id !=\n+\t\t    ICE_PROT_INVALID)\n+\t\t\tfirst_free = i - 1;\n+\n+\t\tfor (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) {\n+\t\t\tif (es[i].prot_id == ice_fd_pairs[j].prot_id &&\n+\t\t\t    es[i].off == ice_fd_pairs[j].off) {\n+\t\t\t\tice_set_bit(j, pair_list);\n+\t\t\t\tpair_start[j] = i;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\torig_free = first_free;\n+\n+\t/* determine missing swap fields that need to be added */\n+\tfor (i = 0; i < ICE_FD_SRC_DST_PAIR_COUNT; i += 2) {\n+\t\tu8 bit1 = ice_is_bit_set(pair_list, i + 1);\n+\t\tu8 bit0 = ice_is_bit_set(pair_list, i);\n+\n+\t\tif (bit0 ^ bit1) {\n+\t\t\tu8 index;\n+\n+\t\t\t/* add the appropriate 'paired' entry */\n+\t\t\tif (!bit0)\n+\t\t\t\tindex = i;\n+\t\t\telse\n+\t\t\t\tindex = i + 1;\n+\n+\t\t\t/* check for room */\n+\t\t\tif (first_free + 1 < ice_fd_pairs[index].count)\n+\t\t\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\t\t\t/* place in extraction sequence */\n+\t\t\tfor (k = 0; k < ice_fd_pairs[index].count; k++) {\n+\t\t\t\tes[first_free - k].prot_id =\n+\t\t\t\t\tice_fd_pairs[index].prot_id;\n+\t\t\t\tes[first_free - k].off =\n+\t\t\t\t\tice_fd_pairs[index].off + (k * 2);\n+\n+\t\t\t\t/* keep track of non-relevant fields */\n+\t\t\t\tmask_sel |= 1 << (first_free - k);\n+\t\t\t}\n+\n+\t\t\tpair_start[index] = first_free;\n+\t\t\tfirst_free -= ice_fd_pairs[index].count;\n+\t\t}\n+\t}\n+\n+\t/* fill in the swap array */\n+\tsi = hw->blk[ICE_BLK_FD].es.fvw - 1;\n+\tdo {\n+\t\tu8 indexes_used = 1;\n+\n+\t\t/* assume flat at this index */\n+#define ICE_SWAP_VALID\t0x80\n+\t\tused[si] = si | ICE_SWAP_VALID;\n+\n+\t\tif (orig_free == ICE_FD_FV_NOT_FOUND || si <= orig_free) {\n+\t\t\tsi -= indexes_used;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\t/* check for a swap location */\n+\t\tfor (j = 0; j < ICE_FD_SRC_DST_PAIR_COUNT; j++) {\n+\t\t\tif (es[si].prot_id == ice_fd_pairs[j].prot_id &&\n+\t\t\t    es[si].off == ice_fd_pairs[j].off) {\n+\t\t\t\tu8 idx;\n+\n+\t\t\t\t/* determine the appropriate matching field */\n+\t\t\t\tidx = j + ((j % 2) ? -1 : 1);\n+\n+\t\t\t\tindexes_used = ice_fd_pairs[idx].count;\n+\t\t\t\tfor (k = 0; k < indexes_used; k++) {\n+\t\t\t\t\tused[si - k] = (pair_start[idx] - k) |\n+\t\t\t\t\t\tICE_SWAP_VALID;\n+\t\t\t\t}\n+\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tsi -= indexes_used;\n+\t} while (si >= 0);\n+\n+\t/* for each set of 4 swap indexes, write the appropriate register */\n+\tfor (j = 0; j < hw->blk[ICE_BLK_FD].es.fvw / 4; j++) {\n+\t\tu32 raw_entry = 0;\n+\n+\t\tfor (k = 0; k < 4; k++) {\n+\t\t\tu8 idx;\n+\n+\t\t\tidx = (j * 4) + k;\n+\t\t\tif (used[idx])\n+\t\t\t\traw_entry |= used[idx] << (k * 8);\n+\t\t}\n+\n+\t\t/* write the appropriate register set, based on HW block */\n+\t\twr32(hw, GLQF_FDSWAP(prof_id, j), raw_entry);\n+\n+\t\tice_debug(hw, ICE_DBG_INIT, \"swap wr(%d, %d): %x = %x\\n\",\n+\t\t\t  prof_id, j, GLQF_FDSWAP(prof_id, j), raw_entry);\n+\t}\n+\n+\t/* update the masks for this profile to be sure we ignore fields that\n+\t * are not relevant to our match criteria\n+\t */\n+\tice_update_fd_mask(hw, prof_id, mask_sel);\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n  * ice_add_prof - add profile\n  * @hw: pointer to the HW struct\n  * @blk: hardware block\n@@ -3812,6 +4032,18 @@ ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[],\n \t\tstatus = ice_alloc_prof_id(hw, blk, &prof_id);\n \t\tif (status)\n \t\t\tgoto err_ice_add_prof;\n+\t\tif (blk == ICE_BLK_FD) {\n+\t\t\t/* For Flow Director block, the extraction sequence may\n+\t\t\t * need to be altered in the case where there are paired\n+\t\t\t * fields that have no match. This is necessary because\n+\t\t\t * for Flow Director, src and dest fields need to paired\n+\t\t\t * for filter programming and these values are swapped\n+\t\t\t * during Tx.\n+\t\t\t */\n+\t\t\tstatus = ice_update_fd_swap(hw, prof_id, es);\n+\t\t\tif (status)\n+\t\t\t\tgoto err_ice_add_prof;\n+\t\t}\n \n \t\t/* and write new es */\n \t\tice_write_es(hw, blk, prof_id, es);\ndiff --git a/drivers/net/ice/base/ice_type.h b/drivers/net/ice/base/ice_type.h\nindex 6a08b3d28..ef0b5bb52 100644\n--- a/drivers/net/ice/base/ice_type.h\n+++ b/drivers/net/ice/base/ice_type.h\n@@ -164,6 +164,7 @@ enum ice_media_type {\n /* Software VSI types. */\n enum ice_vsi_type {\n \tICE_VSI_PF = 0,\n+\tICE_VSI_CTRL = 3,\t/* equates to ICE_VSI_PF with 1 queue pair */\n #ifdef ADQ_SUPPORT\n \tICE_VSI_CHNL = 4,\n #endif /* ADQ_SUPPORT */\n@@ -218,6 +219,32 @@ struct ice_phy_info {\n \n #define ICE_MAX_NUM_MIRROR_RULES\t64\n \n+/* protocol enumeration for filters */\n+enum ice_fltr_ptype {\n+\t/* NONE - used for undef/error */\n+\tICE_FLTR_PTYPE_NONF_NONE = 0,\n+\tICE_FLTR_PTYPE_NONF_IPV4_UDP,\n+\tICE_FLTR_PTYPE_NONF_IPV4_TCP,\n+\tICE_FLTR_PTYPE_NONF_IPV4_SCTP,\n+\tICE_FLTR_PTYPE_NONF_IPV4_OTHER,\n+\tICE_FLTR_PTYPE_FRAG_IPV4,\n+\tICE_FLTR_PTYPE_NONF_IPV6_UDP,\n+\tICE_FLTR_PTYPE_NONF_IPV6_TCP,\n+\tICE_FLTR_PTYPE_NONF_IPV6_SCTP,\n+\tICE_FLTR_PTYPE_NONF_IPV6_OTHER,\n+\tICE_FLTR_PTYPE_MAX,\n+};\n+\n+/* 6 VSI = 1 ICE_VSI_PF + 1 ICE_VSI_CTRL + 4 ICE_VSI_CHNL */\n+#define ICE_MAX_FDIR_VSI_PER_FILTER\t6\n+\n+struct ice_fd_hw_prof {\n+\tstruct ice_flow_seg_info *fdir_seg;\n+\tint cnt;\n+\tu64 entry_h[ICE_MAX_FDIR_VSI_PER_FILTER];\n+\tu16 vsi_h[ICE_MAX_FDIR_VSI_PER_FILTER];\n+};\n+\n /* Common HW capabilities for SW use */\n struct ice_hw_common_caps {\n \t/* Write CSR protection */\n@@ -297,12 +324,15 @@ struct ice_hw_common_caps {\n struct ice_hw_func_caps {\n \tstruct ice_hw_common_caps common_cap;\n \tu32 guar_num_vsi;\n+\tu32 fd_fltr_guar;\t\t/* Number of filters guaranteed */\n+\tu32 fd_fltr_best_effort;\t/* Number of best effort filters */\n };\n \n /* Device wide capabilities */\n struct ice_hw_dev_caps {\n \tstruct ice_hw_common_caps common_cap;\n \tu32 num_vsi_allocd_to_host;\t/* Excluding EMP VSI */\n+\tu32 num_flow_director_fltr;\t/* Number of FD filters available */\n };\n \n \n@@ -651,6 +681,7 @@ struct ice_hw {\n \tu64 debug_mask;\t\t/* BITMAP for debug mask */\n \tenum ice_mac_type mac_type;\n \n+\tu16 fd_ctr_base;\t/* FD counter base index */\n \t/* pci info */\n \tu16 device_id;\n \tu16 vendor_id;\n@@ -748,6 +779,19 @@ struct ice_hw {\n \tstruct ice_blk_info blk[ICE_BLK_COUNT];\n \tstruct ice_lock fl_profs_locks[ICE_BLK_COUNT];\t/* lock fltr profiles */\n \tstruct LIST_HEAD_TYPE fl_profs[ICE_BLK_COUNT];\n+\t/* Flow Director filter info */\n+\tint fdir_active_fltr;\n+\n+\tstruct ice_lock fdir_fltr_lock;\t/* protect Flow Director */\n+\tstruct LIST_HEAD_TYPE fdir_list_head;\n+\n+\t/* Book-keeping of side-band filter count per flow-type.\n+\t * This is used to detect and handle input set changes for\n+\t * respective flow-type.\n+\t */\n+\tu16 fdir_fltr_cnt[ICE_FLTR_PTYPE_MAX];\n+\n+\tstruct ice_fd_hw_prof **fdir_prof;\n };\n \n /* Statistics collected by each port, VSI, VEB, and S-channel */\n@@ -792,6 +836,11 @@ struct ice_hw_port_stats {\n \tu64 link_xoff_rx;\t\t/* lxoffrxc */\n \tu64 link_xon_tx;\t\t/* lxontxc */\n \tu64 link_xoff_tx;\t\t/* lxofftxc */\n+\tu64 priority_xon_rx[8];\t\t/* pxonrxc[8] */\n+\tu64 priority_xoff_rx[8];\t/* pxoffrxc[8] */\n+\tu64 priority_xon_tx[8];\t\t/* pxontxc[8] */\n+\tu64 priority_xoff_tx[8];\t/* pxofftxc[8] */\n+\tu64 priority_xon_2_xoff[8];\t/* pxon2offc[8] */\n \tu64 rx_size_64;\t\t\t/* prc64 */\n \tu64 rx_size_127;\t\t/* prc127 */\n \tu64 rx_size_255;\t\t/* prc255 */\n@@ -811,6 +860,12 @@ struct ice_hw_port_stats {\n \tu64 tx_size_1522;\t\t/* ptc1522 */\n \tu64 tx_size_big;\t\t/* ptc9522 */\n \tu64 mac_short_pkt_dropped;\t/* mspdc */\n+\t/* flow director stats */\n+\tu32 fd_sb_status;\n+\tu64 fd_sb_match;\n+#ifdef ADQ_SUPPORT\n+\tu64 ch_atr_match;\n+#endif /* ADQ_SUPPORT */\n };\n \n enum ice_sw_fwd_act_type {\ndiff --git a/drivers/net/ice/base/meson.build b/drivers/net/ice/base/meson.build\nindex 755d2497b..624202567 100644\n--- a/drivers/net/ice/base/meson.build\n+++ b/drivers/net/ice/base/meson.build\n@@ -10,6 +10,7 @@ sources = [\n \t'ice_flex_pipe.c',\n \t'ice_flow.c',\n \t'ice_dcb.c',\n+\t'ice_fdir.c',\n ]\n \n error_cflags = ['-Wno-unused-value',\n",
    "prefixes": [
        "32/37"
    ]
}