get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 66442,
    "url": "http://patches.dpdk.org/api/patches/66442/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200309114357.31800-26-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": "<20200309114357.31800-26-qi.z.zhang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200309114357.31800-26-qi.z.zhang@intel.com",
    "date": "2020-03-09T11:43:54",
    "name": "[25/28] net/ice/base: add ACL module",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "d37b8052b5d530f5bc6da30c6873bfe842f125c4",
    "submitter": {
        "id": 504,
        "url": "http://patches.dpdk.org/api/people/504/?format=api",
        "name": "Qi Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "delegate": {
        "id": 31221,
        "url": "http://patches.dpdk.org/api/users/31221/?format=api",
        "username": "yexl",
        "first_name": "xiaolong",
        "last_name": "ye",
        "email": "xiaolong.ye@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20200309114357.31800-26-qi.z.zhang@intel.com/mbox/",
    "series": [
        {
            "id": 8843,
            "url": "http://patches.dpdk.org/api/series/8843/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8843",
            "date": "2020-03-09T11:43:29",
            "name": "update ice base code",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/8843/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/66442/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/66442/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id F13FCA052E;\n\tMon,  9 Mar 2020 12:44:36 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 9A87D1C037;\n\tMon,  9 Mar 2020 12:41:24 +0100 (CET)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n by dpdk.org (Postfix) with ESMTP id 73E141C1CC\n for <dev@dpdk.org>; Mon,  9 Mar 2020 12:41:22 +0100 (CET)",
            "from fmsmga002.fm.intel.com ([10.253.24.26])\n by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n 09 Mar 2020 04:41:21 -0700",
            "from dpdk51.sh.intel.com ([10.67.110.245])\n by fmsmga002.fm.intel.com with ESMTP; 09 Mar 2020 04:41:18 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.70,533,1574150400\"; d=\"scan'208\";a=\"276483659\"",
        "From": "Qi Zhang <qi.z.zhang@intel.com>",
        "To": "qiming.yang@intel.com,\n\tbeilei.xing@intel.com",
        "Cc": "xiaolong.ye@intel.com, dev@dpdk.org, Qi Zhang <qi.z.zhang@intel.com>,\n Real Valiquette <real.valiquette@intel.com>,\n Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>",
        "Date": "Mon,  9 Mar 2020 19:43:54 +0800",
        "Message-Id": "<20200309114357.31800-26-qi.z.zhang@intel.com>",
        "X-Mailer": "git-send-email 2.13.6",
        "In-Reply-To": "<20200309114357.31800-1-qi.z.zhang@intel.com>",
        "References": "<20200309114357.31800-1-qi.z.zhang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 25/28] net/ice/base: add ACL module",
        "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 <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add all ACL related code.\n\nSigned-off-by: Real Valiquette <real.valiquette@intel.com>\nSigned-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>\nSigned-off-by: Qi Zhang <qi.z.zhang@intel.com>\n---\n drivers/net/ice/Makefile              |    2 +\n drivers/net/ice/base/ice_acl.c        |  629 +++++++++++++++++\n drivers/net/ice/base/ice_acl.h        |  206 ++++++\n drivers/net/ice/base/ice_acl_ctrl.c   | 1185 +++++++++++++++++++++++++++++++++\n drivers/net/ice/base/ice_adminq_cmd.h |  459 ++++++++++++-\n drivers/net/ice/base/ice_fdir.c       |   14 +-\n drivers/net/ice/base/ice_fdir.h       |    5 +-\n drivers/net/ice/base/ice_flex_pipe.c  |    3 +-\n drivers/net/ice/base/ice_flow.c       | 1112 ++++++++++++++++++++++++++++++-\n drivers/net/ice/base/ice_flow.h       |   11 +-\n drivers/net/ice/base/ice_type.h       |    7 +\n drivers/net/ice/base/meson.build      |    2 +\n drivers/net/ice/ice_fdir_filter.c     |    4 +-\n 13 files changed, 3620 insertions(+), 19 deletions(-)\n create mode 100644 drivers/net/ice/base/ice_acl.c\n create mode 100644 drivers/net/ice/base/ice_acl.h\n create mode 100644 drivers/net/ice/base/ice_acl_ctrl.c",
    "diff": "diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile\nindex 6c4d15526..e22c34287 100644\n--- a/drivers/net/ice/Makefile\n+++ b/drivers/net/ice/Makefile\n@@ -52,6 +52,8 @@ 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+SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_acl.c\n+SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_acl_ctrl.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_acl.c b/drivers/net/ice/base/ice_acl.c\nnew file mode 100644\nindex 000000000..26e03aa33\n--- /dev/null\n+++ b/drivers/net/ice/base/ice_acl.c\n@@ -0,0 +1,629 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2001-2020\n+ */\n+\n+#include \"ice_acl.h\"\n+#include \"ice_adminq_cmd.h\"\n+\n+/**\n+ * ice_aq_alloc_acl_tbl - allocate ACL table\n+ * @hw: pointer to the HW struct\n+ * @tbl: pointer to ice_acl_alloc_tbl struct\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Allocate ACL table (indirect 0x0C10)\n+ */\n+enum ice_status\n+ice_aq_alloc_acl_tbl(struct ice_hw *hw, struct ice_acl_alloc_tbl *tbl,\n+\t\t     struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_alloc_table *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tif (!tbl->act_pairs_per_entry)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tif (tbl->act_pairs_per_entry > ICE_AQC_MAX_ACTION_MEMORIES)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\t/* If this is concurrent table, then buffer shall be valid and\n+\t * contain DependentAllocIDs, 'num_dependent_alloc_ids' should be valid\n+\t * and within limit\n+\t */\n+\tif (tbl->concurr) {\n+\t\tif (!tbl->num_dependent_alloc_ids)\n+\t\t\treturn ICE_ERR_PARAM;\n+\t\tif (tbl->num_dependent_alloc_ids >\n+\t\t    ICE_AQC_MAX_CONCURRENT_ACL_TBL)\n+\t\t\treturn ICE_ERR_INVAL_SIZE;\n+\t}\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_alloc_acl_tbl);\n+\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\n+\tcmd = &desc.params.alloc_table;\n+\tcmd->table_width = CPU_TO_LE16(tbl->width * BITS_PER_BYTE);\n+\tcmd->table_depth = CPU_TO_LE16(tbl->depth);\n+\tcmd->act_pairs_per_entry = tbl->act_pairs_per_entry;\n+\tif (tbl->concurr)\n+\t\tcmd->table_type = tbl->num_dependent_alloc_ids;\n+\n+\treturn ice_aq_send_cmd(hw, &desc, &tbl->buf, sizeof(tbl->buf), cd);\n+}\n+\n+/**\n+ * ice_aq_dealloc_acl_tbl - deallocate ACL table\n+ * @hw: pointer to the HW struct\n+ * @alloc_id: allocation ID of the table being released\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Deallocate ACL table (indirect 0x0C11)\n+ *\n+ * NOTE: This command has no buffer format for command itself but response\n+ * format is 'struct ice_aqc_acl_generic', pass ptr to that struct\n+ * as 'buf' and its size as 'buf_size'\n+ */\n+enum ice_status\n+ice_aq_dealloc_acl_tbl(struct ice_hw *hw, u16 alloc_id,\n+\t\t       struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_tbl_actpair *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_tbl);\n+\tcmd = &desc.params.tbl_actpair;\n+\tcmd->alloc_id = CPU_TO_LE16(alloc_id);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+static enum ice_status\n+ice_aq_acl_entry(struct ice_hw *hw, u16 opcode, u8 tcam_idx, u16 entry_idx,\n+\t\t struct ice_aqc_acl_data *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_entry *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opcode);\n+\n+\tif (opcode == ice_aqc_opc_program_acl_entry)\n+\t\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\n+\tcmd = &desc.params.program_query_entry;\n+\tcmd->tcam_index = tcam_idx;\n+\tcmd->entry_index = CPU_TO_LE16(entry_idx);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_program_acl_entry - program ACL entry\n+ * @hw: pointer to the HW struct\n+ * @tcam_idx: Updated TCAM block index\n+ * @entry_idx: updated entry index\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Program ACL entry (direct 0x0C20)\n+ */\n+enum ice_status\n+ice_aq_program_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n+\t\t\t struct ice_aqc_acl_data *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_acl_entry(hw, ice_aqc_opc_program_acl_entry, tcam_idx,\n+\t\t\t\tentry_idx, buf, cd);\n+}\n+\n+/**\n+ * ice_aq_query_acl_entry - query ACL entry\n+ * @hw: pointer to the HW struct\n+ * @tcam_idx: Updated TCAM block index\n+ * @entry_idx: updated entry index\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ *  Query ACL entry (direct 0x0C24)\n+ *\n+ * NOTE: Caller of this API to parse 'buf' appropriately since it contains\n+ * response (key and key invert)\n+ */\n+enum ice_status\n+ice_aq_query_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n+\t\t       struct ice_aqc_acl_data *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_acl_entry(hw, ice_aqc_opc_query_acl_entry, tcam_idx,\n+\t\t\t\tentry_idx, buf, cd);\n+}\n+\n+/* Helper function to alloc/dealloc ACL action pair */\n+static enum ice_status\n+ice_aq_actpair_a_d(struct ice_hw *hw, u16 opcode, u16 alloc_id,\n+\t\t   struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_tbl_actpair *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opcode);\n+\tcmd = &desc.params.tbl_actpair;\n+\tcmd->alloc_id = CPU_TO_LE16(alloc_id);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_alloc_actpair - allocate actionpair for specified ACL table\n+ * @hw: pointer to the HW struct\n+ * @alloc_id: allocation ID of the table being associated with the actionpair\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Allocate ACL actionpair (direct 0x0C12)\n+ *\n+ * This command doesn't need and doesn't have its own command buffer\n+ * but for response format is as specified in 'struct ice_aqc_acl_generic'\n+ */\n+enum ice_status\n+ice_aq_alloc_actpair(struct ice_hw *hw, u16 alloc_id,\n+\t\t     struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_actpair_a_d(hw, ice_aqc_opc_alloc_acl_actpair, alloc_id,\n+\t\t\t\t  buf, cd);\n+}\n+\n+/**\n+ * ice_aq_dealloc_actpair - dealloc actionpair for specified ACL table\n+ * @hw: pointer to the HW struct\n+ * @alloc_id: allocation ID of the table being associated with the actionpair\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ *  Deallocate ACL actionpair (direct 0x0C13)\n+ */\n+enum ice_status\n+ice_aq_dealloc_actpair(struct ice_hw *hw, u16 alloc_id,\n+\t\t       struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_actpair_a_d(hw, ice_aqc_opc_dealloc_acl_actpair, alloc_id,\n+\t\t\t\t  buf, cd);\n+}\n+\n+/* Helper function to program/query ACL action pair */\n+static enum ice_status\n+ice_aq_actpair_p_q(struct ice_hw *hw, u16 opcode, u8 act_mem_idx,\n+\t\t   u16 act_entry_idx, struct ice_aqc_actpair *buf,\n+\t\t   struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_actpair *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opcode);\n+\n+\tif (opcode == ice_aqc_opc_program_acl_actpair)\n+\t\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\n+\tcmd = &desc.params.program_query_actpair;\n+\tcmd->act_mem_index = act_mem_idx;\n+\tcmd->act_entry_index = CPU_TO_LE16(act_entry_idx);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_program_actpair - program ACL actionpair\n+ * @hw: pointer to the HW struct\n+ * @act_mem_idx: action memory index to program/update/query\n+ * @act_entry_idx: the entry index in action memory to be programmed/updated\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Program action entries (indirect 0x0C1C)\n+ */\n+enum ice_status\n+ice_aq_program_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n+\t\t       struct ice_aqc_actpair *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_actpair_p_q(hw, ice_aqc_opc_program_acl_actpair,\n+\t\t\t\t  act_mem_idx, act_entry_idx, buf, cd);\n+}\n+\n+/**\n+ * ice_aq_query_actpair - query ACL actionpair\n+ * @hw: pointer to the HW struct\n+ * @act_mem_idx: action memory index to program/update/query\n+ * @act_entry_idx: the entry index in action memory to be programmed/updated\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Query ACL actionpair (indirect 0x0C25)\n+ */\n+enum ice_status\n+ice_aq_query_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n+\t\t     struct ice_aqc_actpair *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_actpair_p_q(hw, ice_aqc_opc_query_acl_actpair,\n+\t\t\t\t  act_mem_idx, act_entry_idx, buf, cd);\n+}\n+\n+/**\n+ * ice_aq_dealloc_acl_res - deallocate ACL resources\n+ * @hw: pointer to the HW struct\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - de-allocate (direct 0x0C1A) resources. Used by SW to release all the\n+ * resources allocated for it using a single command\n+ */\n+enum ice_status ice_aq_dealloc_acl_res(struct ice_hw *hw, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_res);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+}\n+\n+/**\n+ * ice_acl_prof_aq_send - sending acl profile aq commands\n+ * @hw: pointer to the HW struct\n+ * @opc: command opcode\n+ * @prof_id: profile ID\n+ * @buf: ptr to buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * This function sends ACL profile commands\n+ */\n+static enum ice_status\n+ice_acl_prof_aq_send(struct ice_hw *hw, u16 opc, u8 prof_id,\n+\t\t     struct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t     struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opc);\n+\tdesc.params.profile.profile_id = prof_id;\n+\tif (opc == ice_aqc_opc_program_acl_prof_extraction ||\n+\t    opc == ice_aqc_opc_program_acl_prof_ranges)\n+\t\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_prgm_acl_prof_extrt - program ACL profile extraction sequence\n+ * @hw: pointer to the HW struct\n+ * @prof_id: profile ID\n+ * @buf: ptr to buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - program ACL profile extraction (indirect 0x0C1D)\n+ */\n+enum ice_status\n+ice_prgm_acl_prof_extrt(struct ice_hw *hw, u8 prof_id,\n+\t\t\tstruct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t\tstruct ice_sq_cd *cd)\n+{\n+\treturn ice_acl_prof_aq_send(hw, ice_aqc_opc_program_acl_prof_extraction,\n+\t\t\t\t    prof_id, buf, cd);\n+}\n+\n+/**\n+ * ice_query_acl_prof - query ACL profile\n+ * @hw: pointer to the HW struct\n+ * @prof_id: profile ID\n+ * @buf: ptr to buffer (which will contain response of this command)\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - query ACL profile (indirect 0x0C21)\n+ */\n+enum ice_status\n+ice_query_acl_prof(struct ice_hw *hw, u8 prof_id,\n+\t\t   struct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t   struct ice_sq_cd *cd)\n+{\n+\treturn ice_acl_prof_aq_send(hw, ice_aqc_opc_query_acl_prof, prof_id,\n+\t\t\t\t    buf, cd);\n+}\n+\n+/**\n+ * ice_aq_acl_cntrs_chk_params - Checks ACL counter parameters\n+ * @cntrs: ptr to buffer describing input and output params\n+ *\n+ * This function checks the counter bank range for counter type and returns\n+ * success or failure.\n+ */\n+static enum ice_status ice_aq_acl_cntrs_chk_params(struct ice_acl_cntrs *cntrs)\n+{\n+\tenum ice_status status = ICE_SUCCESS;\n+\n+\tif (!cntrs || !cntrs->amount)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tswitch (cntrs->type) {\n+\tcase ICE_AQC_ACL_CNT_TYPE_SINGLE:\n+\t\t/* Single counter type - configured to count either bytes\n+\t\t * or packets, the valid values for byte or packet counters\n+\t\t * shall be 0-3.\n+\t\t */\n+\t\tif (cntrs->bank > ICE_AQC_ACL_MAX_CNT_SINGLE)\n+\t\t\tstatus = ICE_ERR_OUT_OF_RANGE;\n+\t\tbreak;\n+\tcase ICE_AQC_ACL_CNT_TYPE_DUAL:\n+\t\t/* Pair counter type - counts number of bytes and packets\n+\t\t * The valid values for byte/packet counter duals shall be 0-1\n+\t\t */\n+\t\tif (cntrs->bank > ICE_AQC_ACL_MAX_CNT_DUAL)\n+\t\t\tstatus = ICE_ERR_OUT_OF_RANGE;\n+\t\tbreak;\n+\tdefault:\n+\t\t/* Unspecified counter type - Invalid or error*/\n+\t\tstatus = ICE_ERR_PARAM;\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_aq_alloc_acl_cntrs - allocate ACL counters\n+ * @hw: pointer to the HW struct\n+ * @cntrs: ptr to buffer describing input and output params\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - allocate (indirect 0x0C16) counters. This function attempts to\n+ * allocate a contiguous block of counters. In case of failures, caller can\n+ * attempt to allocate a smaller chunk. The allocation is considered\n+ * unsuccessful if returned counter value is invalid. In this case it returns\n+ * an error otherwise success.\n+ */\n+enum ice_status\n+ice_aq_alloc_acl_cntrs(struct ice_hw *hw, struct ice_acl_cntrs *cntrs,\n+\t\t       struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_alloc_counters *cmd;\n+\tu16 first_cntr, last_cntr;\n+\tstruct ice_aq_desc desc;\n+\tenum ice_status status;\n+\n+\t/* check for invalid params */\n+\tstatus = ice_aq_acl_cntrs_chk_params(cntrs);\n+\tif (status)\n+\t\treturn status;\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_alloc_acl_counters);\n+\tcmd = &desc.params.alloc_counters;\n+\tcmd->counter_amount = cntrs->amount;\n+\tcmd->counters_type = cntrs->type;\n+\tcmd->bank_alloc = cntrs->bank;\n+\tstatus = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+\tif (!status) {\n+\t\tfirst_cntr = LE16_TO_CPU(cmd->ops.resp.first_counter);\n+\t\tlast_cntr = LE16_TO_CPU(cmd->ops.resp.last_counter);\n+\t\tif (first_cntr == ICE_AQC_ACL_ALLOC_CNT_INVAL ||\n+\t\t    last_cntr == ICE_AQC_ACL_ALLOC_CNT_INVAL)\n+\t\t\treturn ICE_ERR_OUT_OF_RANGE;\n+\t\tcntrs->first_cntr = first_cntr;\n+\t\tcntrs->last_cntr = last_cntr;\n+\t}\n+\treturn status;\n+}\n+\n+/**\n+ * ice_aq_dealloc_acl_cntrs - deallocate ACL counters\n+ * @hw: pointer to the HW struct\n+ * @cntrs: ptr to buffer describing input and output params\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - de-allocate (direct 0x0C17) counters.\n+ * This function deallocate ACL counters.\n+ */\n+enum ice_status\n+ice_aq_dealloc_acl_cntrs(struct ice_hw *hw, struct ice_acl_cntrs *cntrs,\n+\t\t\t struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_dealloc_counters *cmd;\n+\tstruct ice_aq_desc desc;\n+\tenum ice_status status;\n+\n+\t/* check for invalid params */\n+\tstatus = ice_aq_acl_cntrs_chk_params(cntrs);\n+\tif (status)\n+\t\treturn status;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_counters);\n+\tcmd = &desc.params.dealloc_counters;\n+\tcmd->first_counter = CPU_TO_LE16(cntrs->first_cntr);\n+\tcmd->last_counter = CPU_TO_LE16(cntrs->last_cntr);\n+\tcmd->counters_type = cntrs->type;\n+\tcmd->bank_alloc = cntrs->bank;\n+\treturn ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+}\n+\n+/**\n+ * ice_aq_query_acl_cntrs - query ACL counter\n+ * @hw: pointer to the HW struct\n+ * @bank: queries counter bank\n+ * @index: queried counter index\n+ * @cntr_val: pointer to counter or packet counter value\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - query ACL counter (direct 0x0C27)\n+ */\n+enum ice_status\n+ice_aq_query_acl_cntrs(struct ice_hw *hw, u8 bank, u16 index, u64 *cntr_val,\n+\t\t       struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_query_counter *cmd;\n+\tstruct ice_aq_desc desc;\n+\tenum ice_status status;\n+\n+\tif (!cntr_val)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_query_acl_counter);\n+\tcmd = &desc.params.query_counter;\n+\tcmd->counter_index = CPU_TO_LE16(index);\n+\tcmd->counter_bank = bank;\n+\tstatus = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+\tif (!status) {\n+\t\t__le64 resp_val = 0;\n+\n+\t\tice_memcpy(&resp_val, cmd->ops.resp.val,\n+\t\t\t   sizeof(cmd->ops.resp.val), ICE_NONDMA_TO_NONDMA);\n+\t\t*cntr_val = LE64_TO_CPU(resp_val);\n+\t}\n+\treturn status;\n+}\n+\n+/**\n+ * ice_prog_acl_prof_ranges - program ACL profile ranges\n+ * @hw: pointer to the HW struct\n+ * @prof_id: programmed or updated profile ID\n+ * @buf: pointer to input buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - program ACL profile ranges (indirect 0x0C1E)\n+ */\n+enum ice_status\n+ice_prog_acl_prof_ranges(struct ice_hw *hw, u8 prof_id,\n+\t\t\t struct ice_aqc_acl_profile_ranges *buf,\n+\t\t\t struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc,\n+\t\t\t\t      ice_aqc_opc_program_acl_prof_ranges);\n+\tdesc.params.profile.profile_id = prof_id;\n+\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_query_acl_prof_ranges - query ACL profile ranges\n+ * @hw: pointer to the HW struct\n+ * @prof_id: programmed or updated profile ID\n+ * @buf: pointer to response buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * ACL - query ACL profile ranges (indirect 0x0C22)\n+ */\n+enum ice_status\n+ice_query_acl_prof_ranges(struct ice_hw *hw, u8 prof_id,\n+\t\t\t  struct ice_aqc_acl_profile_ranges *buf,\n+\t\t\t  struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc,\n+\t\t\t\t      ice_aqc_opc_query_acl_prof_ranges);\n+\tdesc.params.profile.profile_id = prof_id;\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_alloc_acl_scen - allocate ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen_id: memory location to receive allocated scenario ID\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Allocate ACL scenario (indirect 0x0C14)\n+ */\n+enum ice_status\n+ice_aq_alloc_acl_scen(struct ice_hw *hw, u16 *scen_id,\n+\t\t      struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_alloc_scen *cmd;\n+\tstruct ice_aq_desc desc;\n+\tenum ice_status status;\n+\n+\tif (!scen_id)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_alloc_acl_scen);\n+\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\tcmd = &desc.params.alloc_scen;\n+\n+\tstatus = ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+\tif (!status)\n+\t\t*scen_id = LE16_TO_CPU(cmd->ops.resp.scen_id);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_aq_dealloc_acl_scen - deallocate ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen_id: scen_id to be deallocated (input and output field)\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Deallocate ACL scenario (direct 0x0C15)\n+ */\n+enum ice_status\n+ice_aq_dealloc_acl_scen(struct ice_hw *hw, u16 scen_id, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_dealloc_scen *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_scen);\n+\tcmd = &desc.params.dealloc_scen;\n+\tcmd->scen_id = CPU_TO_LE16(scen_id);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+}\n+\n+/**\n+ * ice_aq_update_query_scen - update or query ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @opcode: aq command opcode for either query or update scenario\n+ * @scen_id: scen_id to be updated or queried\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Calls update or query ACL scenario\n+ */\n+static enum ice_status\n+ice_aq_update_query_scen(struct ice_hw *hw, u16 opcode, u16 scen_id,\n+\t\t\t struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_update_query_scen *cmd;\n+\tstruct ice_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opcode);\n+\tif (opcode == ice_aqc_opc_update_acl_scen)\n+\t\tdesc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);\n+\tcmd = &desc.params.update_query_scen;\n+\tcmd->scen_id = CPU_TO_LE16(scen_id);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_update_acl_scen - update ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen_id: scen_id to be updated\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Update ACL scenario (indirect 0x0C1B)\n+ */\n+enum ice_status\n+ice_aq_update_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t       struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_update_query_scen(hw, ice_aqc_opc_update_acl_scen,\n+\t\t\t\t\tscen_id, buf, cd);\n+}\n+\n+/**\n+ * ice_aq_query_acl_scen - query ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen_id: scen_id to be queried\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Query ACL scenario (indirect 0x0C23)\n+ */\n+enum ice_status\n+ice_aq_query_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t      struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd)\n+{\n+\treturn ice_aq_update_query_scen(hw, ice_aqc_opc_query_acl_scen,\n+\t\t\t\t\tscen_id, buf, cd);\n+}\ndiff --git a/drivers/net/ice/base/ice_acl.h b/drivers/net/ice/base/ice_acl.h\nnew file mode 100644\nindex 000000000..00296300b\n--- /dev/null\n+++ b/drivers/net/ice/base/ice_acl.h\n@@ -0,0 +1,206 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2001-2020\n+ */\n+\n+#ifndef _ICE_ACL_H_\n+#define _ICE_ACL_H_\n+\n+#include \"ice_common.h\"\n+#include \"ice_adminq_cmd.h\"\n+\n+struct ice_acl_tbl_params {\n+\tu16 width;\t/* Select/match bytes */\n+\tu16 depth;\t/* Number of entries */\n+\n+#define ICE_ACL_TBL_MAX_DEP_TBLS\t15\n+\tu16 dep_tbls[ICE_ACL_TBL_MAX_DEP_TBLS];\n+\n+\tu8 entry_act_pairs;\t/* Action pairs per entry */\n+\tu8 concurr;\t\t/* Concurrent table lookup enable */\n+};\n+\n+struct ice_acl_act_mem {\n+\tu8 act_mem;\n+#define ICE_ACL_ACT_PAIR_MEM_INVAL\t0xff\n+\tu8 member_of_tcam;\n+};\n+\n+struct ice_acl_tbl {\n+\t/* TCAM configuration */\n+\tu8 first_tcam;\t/* Index of the first TCAM block */\n+\tu8 last_tcam;\t/* Index of the last TCAM block */\n+\t/* Index of the first entry in the first TCAM */\n+\tu16 first_entry;\n+\t/* Index of the last entry in the last TCAM */\n+\tu16 last_entry;\n+\n+\t/* List of active scenarios */\n+\tstruct LIST_HEAD_TYPE scens;\n+\n+\tstruct ice_acl_tbl_params info;\n+\tstruct ice_acl_act_mem act_mems[ICE_AQC_MAX_ACTION_MEMORIES];\n+\n+\t/* Keep track of available 64-entry chunks in TCAMs */\n+\tice_declare_bitmap(avail, ICE_AQC_ACL_ALLOC_UNITS);\n+\n+\tu16 id;\n+};\n+\n+#define ICE_MAX_ACL_TCAM_ENTRY (ICE_AQC_ACL_TCAM_DEPTH * ICE_AQC_ACL_SLICES)\n+enum ice_acl_entry_prior {\n+\tICE_LOW = 0,\n+\tICE_NORMAL,\n+\tICE_HIGH,\n+\tICE_MAX_PRIOR\n+};\n+\n+/* Scenario structure\n+ * A scenario is a logical partition within an ACL table. It can span more\n+ * than one TCAM in cascade mode to support select/mask key widths larger.\n+ * than the width of a TCAM. It can also span more than one TCAM in stacked\n+ * mode to support larger number of entries than what a TCAM can hold. It is\n+ * used to select values from selection bases (field vectors holding extract\n+ * protocol header fields) to form lookup keys, and to associate action memory\n+ * banks to the TCAMs used.\n+ */\n+struct ice_acl_scen {\n+\tstruct LIST_ENTRY_TYPE list_entry;\n+\t/* If nth bit of act_mem_bitmap is set, then nth action memory will\n+\t * participate in this scenario\n+\t */\n+\tice_declare_bitmap(act_mem_bitmap, ICE_AQC_MAX_ACTION_MEMORIES);\n+\n+\t/* If nth bit of entry_bitmap is set, then nth entry will\n+\t * be available in this scenario\n+\t */\n+\tice_declare_bitmap(entry_bitmap, ICE_MAX_ACL_TCAM_ENTRY);\n+\tu16 first_idx[ICE_MAX_PRIOR];\n+\tu16 last_idx[ICE_MAX_PRIOR];\n+\n+\tu16 id;\n+\tu16 start;\t/* Number of entry from the start of the parent table */\n+#define ICE_ACL_SCEN_MIN_WIDTH\t0x3\n+\tu16 width;\t/* Number of select/mask bytes */\n+\tu16 num_entry;\t/* Number of scenario entry */\n+\tu16 end;\t/* Last addressable entry from start of table */\n+\tu8 eff_width;\t/* Available width in bytes to match */\n+#define ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM\t0x2\n+#define ICE_ACL_SCEN_PID_IDX_IN_TCAM\t\t0x3\n+#define ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM\t0x4\n+\tu8 pid_idx;\t/* Byte index used to match profile ID */\n+\tu8 rng_chk_idx;\t/* Byte index used to match range checkers result */\n+\tu8 pkt_dir_idx;\t/* Byte index used to match packet direction */\n+};\n+\n+/* This structure represents input fields needed to allocate ACL table */\n+struct ice_acl_alloc_tbl {\n+\t/* Table's width in number of bytes matched */\n+\tu16 width;\n+\t/* Table's depth in number of entries. */\n+\tu16 depth;\n+\tu8 num_dependent_alloc_ids;\t/* number of depdendent alloc IDs */\n+\tu8 concurr;\t\t\t/* true for concurrent table type */\n+\n+\t/* Amount of action pairs per table entry. Minimal valid\n+\t * value for this field is 1 (e.g. single pair of actions)\n+\t */\n+\tu8 act_pairs_per_entry;\n+\tunion {\n+\t\tstruct ice_aqc_acl_alloc_table_data data_buf;\n+\t\tstruct ice_aqc_acl_generic resp_buf;\n+\t} buf;\n+};\n+\n+/* This structure is used to communicate input and output params for\n+ * [de]allocate_acl_counters\n+ */\n+struct ice_acl_cntrs {\n+\tu8 amount;\n+\tu8 type;\n+\tu8 bank;\n+\n+\t/* Next 2 variables are used for output in case of alloc_acl_counters\n+\t * and input in case of deallocate_acl_counters\n+\t */\n+\tu16 first_cntr;\n+\tu16 last_cntr;\n+};\n+\n+enum ice_status\n+ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params);\n+enum ice_status ice_acl_destroy_tbl(struct ice_hw *hw);\n+enum ice_status\n+ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16 num_entries,\n+\t\t    u16 *scen_id);\n+enum ice_status ice_acl_destroy_scen(struct ice_hw *hw, u16 scen_id);\n+enum ice_status\n+ice_aq_alloc_acl_tbl(struct ice_hw *hw, struct ice_acl_alloc_tbl *tbl,\n+\t\t     struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_dealloc_acl_tbl(struct ice_hw *hw, u16 alloc_id,\n+\t\t       struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_program_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n+\t\t\t struct ice_aqc_acl_data *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_query_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n+\t\t       struct ice_aqc_acl_data *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_alloc_actpair(struct ice_hw *hw, u16 alloc_id,\n+\t\t     struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_dealloc_actpair(struct ice_hw *hw, u16 alloc_id,\n+\t\t       struct ice_aqc_acl_generic *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_program_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n+\t\t       struct ice_aqc_actpair *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_query_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n+\t\t     struct ice_aqc_actpair *buf, struct ice_sq_cd *cd);\n+enum ice_status ice_aq_dealloc_acl_res(struct ice_hw *hw, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_prgm_acl_prof_extrt(struct ice_hw *hw, u8 prof_id,\n+\t\t\tstruct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t\tstruct ice_sq_cd *cd);\n+enum ice_status\n+ice_query_acl_prof(struct ice_hw *hw, u8 prof_id,\n+\t\t   struct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t   struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_alloc_acl_cntrs(struct ice_hw *hw, struct ice_acl_cntrs *cntrs,\n+\t\t       struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_dealloc_acl_cntrs(struct ice_hw *hw, struct ice_acl_cntrs *cntrs,\n+\t\t\t struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_query_acl_cntrs(struct ice_hw *hw, u8 bank, u16 index, u64 *cntr_val,\n+\t\t       struct ice_sq_cd *cd);\n+enum ice_status\n+ice_prog_acl_prof_ranges(struct ice_hw *hw, u8 prof_id,\n+\t\t\t struct ice_aqc_acl_profile_ranges *buf,\n+\t\t\t struct ice_sq_cd *cd);\n+enum ice_status\n+ice_query_acl_prof_ranges(struct ice_hw *hw, u8 prof_id,\n+\t\t\t  struct ice_aqc_acl_profile_ranges *buf,\n+\t\t\t  struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_alloc_acl_scen(struct ice_hw *hw, u16 *scen_id,\n+\t\t      struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_dealloc_acl_scen(struct ice_hw *hw, u16 scen_id, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_update_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t       struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_aq_query_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t      struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd);\n+enum ice_status\n+ice_acl_add_entry(struct ice_hw *hw, struct ice_acl_scen *scen,\n+\t\t  enum ice_acl_entry_prior prior, u8 *keys, u8 *inverts,\n+\t\t  struct ice_acl_act_entry *acts, u8 acts_cnt, u16 *entry_idx);\n+enum ice_status\n+ice_acl_prog_act(struct ice_hw *hw, struct ice_acl_scen *scen,\n+\t\t struct ice_acl_act_entry *acts, u8 acts_cnt, u16 entry_idx);\n+enum ice_status\n+ice_acl_rem_entry(struct ice_hw *hw, struct ice_acl_scen *scen, u16 entry_idx);\n+#endif /* _ICE_ACL_H_ */\ndiff --git a/drivers/net/ice/base/ice_acl_ctrl.c b/drivers/net/ice/base/ice_acl_ctrl.c\nnew file mode 100644\nindex 000000000..06daff4de\n--- /dev/null\n+++ b/drivers/net/ice/base/ice_acl_ctrl.c\n@@ -0,0 +1,1185 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2001-2020\n+ */\n+\n+#include \"ice_acl.h\"\n+#include \"ice_flow.h\"\n+\n+/* Determine the TCAM index of entry 'e' within the ACL table */\n+#define ICE_ACL_TBL_TCAM_IDX(e) ((e) / ICE_AQC_ACL_TCAM_DEPTH)\n+\n+/* Determine the entry index within the TCAM */\n+#define ICE_ACL_TBL_TCAM_ENTRY_IDX(e) ((e) % ICE_AQC_ACL_TCAM_DEPTH)\n+\n+#define ICE_ACL_SCEN_ENTRY_INVAL 0xFFFF\n+/**\n+ * ice_acl_init_entry\n+ * @scen: pointer to the scenario struct\n+ *\n+ * Initialize the scenario control structure.\n+ */\n+static void ice_acl_init_entry(struct ice_acl_scen *scen)\n+{\n+\t/**\n+\t * low priority: start from the highest index, 25% of total entries\n+\t * normal priority: start from the highest index, 50% of total entries\n+\t * high priority: start from the lowest index, 25% of total entries\n+\t */\n+\tscen->first_idx[ICE_LOW] = scen->num_entry - 1;\n+\tscen->first_idx[ICE_NORMAL] = scen->num_entry - scen->num_entry / 4 - 1;\n+\tscen->first_idx[ICE_HIGH] = 0;\n+\n+\tscen->last_idx[ICE_LOW] = scen->num_entry - scen->num_entry / 4;\n+\tscen->last_idx[ICE_NORMAL] = scen->num_entry / 4;\n+\tscen->last_idx[ICE_HIGH] = scen->num_entry / 4 - 1;\n+}\n+\n+/**\n+ * ice_acl_scen_assign_entry_idx\n+ * @scen: pointer to the scenario struct\n+ * @prior: the priority of the flow entry being allocated\n+ *\n+ * To find the index of an available entry in scenario\n+ *\n+ * Returns ICE_ACL_SCEN_ENTRY_INVAL if fails\n+ * Returns index on success\n+ */\n+static u16 ice_acl_scen_assign_entry_idx(struct ice_acl_scen *scen,\n+\t\t\t\t\t enum ice_acl_entry_prior prior)\n+{\n+\tu16 first_idx, last_idx, i;\n+\ts8 step;\n+\n+\tif (prior >= ICE_MAX_PRIOR)\n+\t\treturn ICE_ACL_SCEN_ENTRY_INVAL;\n+\n+\tfirst_idx = scen->first_idx[prior];\n+\tlast_idx = scen->last_idx[prior];\n+\tstep = first_idx <= last_idx ? 1 : -1;\n+\n+\tfor (i = first_idx; i != last_idx + step; i += step)\n+\t\tif (!ice_test_and_set_bit(i, scen->entry_bitmap))\n+\t\t\treturn i;\n+\n+\treturn ICE_ACL_SCEN_ENTRY_INVAL;\n+}\n+\n+/**\n+ * ice_acl_scen_free_entry_idx\n+ * @scen: pointer to the scenario struct\n+ * @idx: the index of the flow entry being de-allocated\n+ *\n+ * To mark an entry available in scenario\n+ */\n+static enum ice_status\n+ice_acl_scen_free_entry_idx(struct ice_acl_scen *scen, u16 idx)\n+{\n+\tif (idx >= scen->num_entry)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\tif (!ice_test_and_clear_bit(idx, scen->entry_bitmap))\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_acl_tbl_calc_end_idx\n+ * @start: start index of the TCAM entry of this partition\n+ * @num_entries: number of entries in this partition\n+ * @width: width of a partition in number of TCAMs\n+ *\n+ * Calculate the end entry index for a partition with starting entry index\n+ * 'start', entries 'num_entries', and width 'width'.\n+ */\n+static u16 ice_acl_tbl_calc_end_idx(u16 start, u16 num_entries, u16 width)\n+{\n+\tu16 end_idx, add_entries = 0;\n+\n+\tend_idx = start + (num_entries - 1);\n+\n+\t/* In case that our ACL partition requires cascading TCAMs */\n+\tif (width > 1) {\n+\t\tu16 num_stack_level;\n+\n+\t\t/* Figure out the TCAM stacked level in this ACL scenario */\n+\t\tnum_stack_level = (start % ICE_AQC_ACL_TCAM_DEPTH) +\n+\t\t\tnum_entries;\n+\t\tnum_stack_level = DIVIDE_AND_ROUND_UP(num_stack_level,\n+\t\t\t\t\t\t      ICE_AQC_ACL_TCAM_DEPTH);\n+\n+\t\t/* In this case, each entries in our ACL partition span\n+\t\t * multiple TCAMs. Thus, we will need to add\n+\t\t * ((width - 1) * num_stack_level) TCAM's entries to\n+\t\t * end_idx.\n+\t\t *\n+\t\t * For example : In our case, our scenario is 2x2:\n+\t\t *\t[TCAM 0]\t[TCAM 1]\n+\t\t *\t[TCAM 2]\t[TCAM 3]\n+\t\t * Assuming that a TCAM will have 512 entries. If \"start\"\n+\t\t * is 500, \"num_entries\" is 3 and \"width\" = 2, then end_idx\n+\t\t * should be 1024 (belongs to TCAM 2).\n+\t\t * Before going to this if statement, end_idx will have the\n+\t\t * value of 512. If \"width\" is 1, then the final value of\n+\t\t * end_idx is 512. However, in our case, width is 2, then we\n+\t\t * will need add (2 - 1) * 1 * 512. As result, end_idx will\n+\t\t * have the value of 1024.\n+\t\t */\n+\t\tadd_entries = (width - 1) * num_stack_level *\n+\t\t\tICE_AQC_ACL_TCAM_DEPTH;\n+\t}\n+\n+\treturn end_idx + add_entries;\n+}\n+\n+/**\n+ * ice_acl_init_tbl\n+ * @hw: pointer to the hardware structure\n+ *\n+ * Initialize the ACL table by invalidating TCAM entries and action pairs.\n+ */\n+static enum ice_status ice_acl_init_tbl(struct ice_hw *hw)\n+{\n+\tstruct ice_aqc_actpair act_buf;\n+\tstruct ice_aqc_acl_data buf;\n+\tenum ice_status status = ICE_SUCCESS;\n+\tstruct ice_acl_tbl *tbl;\n+\tu8 tcam_idx, i;\n+\tu16 idx;\n+\n+\ttbl = hw->acl_tbl;\n+\tif (!tbl) {\n+\t\tstatus = ICE_ERR_CFG;\n+\t\treturn status;\n+\t}\n+\n+\tice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);\n+\tice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM);\n+\n+\ttcam_idx = tbl->first_tcam;\n+\tidx = tbl->first_entry;\n+\twhile (tcam_idx < tbl->last_tcam ||\n+\t       (tcam_idx == tbl->last_tcam && idx <= tbl->last_entry)) {\n+\t\t/* Use the same value for entry_key and entry_key_inv since\n+\t\t * we are initializing the fields to 0\n+\t\t */\n+\t\tstatus = ice_aq_program_acl_entry(hw, tcam_idx, idx, &buf,\n+\t\t\t\t\t\t  NULL);\n+\t\tif (status)\n+\t\t\treturn status;\n+\n+\t\tif (++idx > tbl->last_entry) {\n+\t\t\ttcam_idx++;\n+\t\t\tidx = tbl->first_entry;\n+\t\t}\n+\t}\n+\n+\tfor (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) {\n+\t\tu16 act_entry_idx, start, end;\n+\n+\t\tif (tbl->act_mems[i].act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL)\n+\t\t\tcontinue;\n+\n+\t\tstart = tbl->first_entry;\n+\t\tend = tbl->last_entry;\n+\n+\t\tfor (act_entry_idx = start; act_entry_idx <= end;\n+\t\t     act_entry_idx++) {\n+\t\t\t/* Invalidate all allocated action pairs */\n+\t\t\tstatus = ice_aq_program_actpair(hw, i, act_entry_idx,\n+\t\t\t\t\t\t\t&act_buf, NULL);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\t\t}\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_acl_assign_act_mems_to_tcam\n+ * @tbl: pointer to acl table structure\n+ * @cur_tcam: Index of current TCAM. Value = 0 to (ICE_AQC_ACL_SLICES - 1)\n+ * @cur_mem_idx: Index of current action memory bank. Value = 0 to\n+ *\t\t (ICE_AQC_MAX_ACTION_MEMORIES - 1)\n+ * @num_mem: Number of action memory banks for this TCAM\n+ *\n+ * Assign \"num_mem\" valid action memory banks from \"curr_mem_idx\" to\n+ * \"curr_tcam\" TCAM.\n+ */\n+static void\n+ice_acl_assign_act_mems_to_tcam(struct ice_acl_tbl *tbl, u16 cur_tcam,\n+\t\t\t\tu8 *cur_mem_idx, u8 num_mem)\n+{\n+\tu8 mem_cnt;\n+\n+\tfor (mem_cnt = 0;\n+\t     *cur_mem_idx < ICE_AQC_MAX_ACTION_MEMORIES && mem_cnt < num_mem;\n+\t     (*cur_mem_idx)++) {\n+\t\tstruct ice_acl_act_mem *p_mem = &tbl->act_mems[*cur_mem_idx];\n+\n+\t\tif (p_mem->act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL)\n+\t\t\tcontinue;\n+\n+\t\tp_mem->member_of_tcam = cur_tcam;\n+\n+\t\tmem_cnt++;\n+\t}\n+}\n+\n+/**\n+ * ice_acl_divide_act_mems_to_tcams\n+ * @tbl: pointer to acl table structure\n+ *\n+ * Figure out how to divide given action memory banks to given TCAMs. This\n+ * division is for SW book keeping. In the time when scenario is created,\n+ * an action memory bank can be used for different TCAM.\n+ *\n+ * For example, given that we have 2x2 ACL table with each table entry has\n+ * 2 action memory pairs. As the result, we will have 4 TCAMs (T1,T2,T3,T4)\n+ * and 4 action memory banks (A1,A2,A3,A4)\n+ *\t[T1 - T2] { A1 - A2 }\n+ *\t[T3 - T4] { A3 - A4 }\n+ * In the time when we need to create a scenario, for example, 2x1 scenario,\n+ * we will use [T3,T4] in a cascaded layout. As it is a requirement that all\n+ * action memory banks in a cascaded TCAM's row will need to associate with\n+ * the last TCAM. Thus, we will associate action memory banks [A3] and [A4]\n+ * for TCAM [T4].\n+ * For SW book-keeping purpose, we will keep theoretical maps between TCAM\n+ * [Tn] to action memory bank [An].\n+ */\n+static void ice_acl_divide_act_mems_to_tcams(struct ice_acl_tbl *tbl)\n+{\n+\tu16 num_cscd, stack_level, stack_idx, min_act_mem;\n+\tu16 tcam_idx = tbl->first_tcam;\n+\tu16 max_idx_to_get_extra;\n+\tu8 mem_idx = 0;\n+\n+\t/* Determine number of stacked TCAMs */\n+\tstack_level = DIVIDE_AND_ROUND_UP(tbl->info.depth,\n+\t\t\t\t\t  ICE_AQC_ACL_TCAM_DEPTH);\n+\n+\t/* Determine number of cascaded TCAMs */\n+\tnum_cscd = DIVIDE_AND_ROUND_UP(tbl->info.width,\n+\t\t\t\t       ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\t/* In a line of cascaded TCAM, given the number of action memory\n+\t * banks per ACL table entry, we want to fairly divide these action\n+\t * memory banks between these TCAMs.\n+\t *\n+\t * For example, there are 3 TCAMs (TCAM 3,4,5) in a line of\n+\t * cascaded TCAM, and there are 7 act_mems for each ACL table entry.\n+\t * The result is:\n+\t *\t[TCAM_3 will have 3 act_mems]\n+\t *\t[TCAM_4 will have 2 act_mems]\n+\t *\t[TCAM_5 will have 2 act_mems]\n+\t */\n+\tmin_act_mem = tbl->info.entry_act_pairs / num_cscd;\n+\tmax_idx_to_get_extra = tbl->info.entry_act_pairs % num_cscd;\n+\n+\tfor (stack_idx = 0; stack_idx < stack_level; stack_idx++) {\n+\t\tu16 i;\n+\n+\t\tfor (i = 0; i < num_cscd; i++) {\n+\t\t\tu8 total_act_mem = min_act_mem;\n+\n+\t\t\tif (i < max_idx_to_get_extra)\n+\t\t\t\ttotal_act_mem++;\n+\n+\t\t\tice_acl_assign_act_mems_to_tcam(tbl, tcam_idx,\n+\t\t\t\t\t\t\t&mem_idx,\n+\t\t\t\t\t\t\ttotal_act_mem);\n+\n+\t\t\ttcam_idx++;\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * ice_acl_create_tbl\n+ * @hw: pointer to the HW struct\n+ * @params: parameters for the table to be created\n+ *\n+ * Create a LEM table for ACL usage. We are currently starting with some fixed\n+ * values for the size of the table, but this will need to grow as more flow\n+ * entries are added by the user level.\n+ */\n+enum ice_status\n+ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params)\n+{\n+\tu16 width, depth, first_e, last_e, i;\n+\tstruct ice_aqc_acl_generic *resp_buf;\n+\tstruct ice_acl_alloc_tbl tbl_alloc;\n+\tstruct ice_acl_tbl *tbl;\n+\tenum ice_status status;\n+\n+\tif (hw->acl_tbl)\n+\t\treturn ICE_ERR_ALREADY_EXISTS;\n+\n+\tif (!params)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\t/* round up the width to the next TCAM width boundary. */\n+\twidth = ROUND_UP(params->width, (u16)ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\t/* depth should be provided in chunk (64 entry) increments */\n+\tdepth = ICE_ALIGN(params->depth, ICE_ACL_ENTRY_ALLOC_UNIT);\n+\n+\tif (params->entry_act_pairs < width / ICE_AQC_ACL_KEY_WIDTH_BYTES) {\n+\t\tparams->entry_act_pairs = width / ICE_AQC_ACL_KEY_WIDTH_BYTES;\n+\n+\t\tif (params->entry_act_pairs > ICE_AQC_TBL_MAX_ACTION_PAIRS)\n+\t\t\tparams->entry_act_pairs = ICE_AQC_TBL_MAX_ACTION_PAIRS;\n+\t}\n+\n+\t/* Validate that width*depth will not exceed the TCAM limit */\n+\tif ((DIVIDE_AND_ROUND_UP(depth, ICE_AQC_ACL_TCAM_DEPTH) *\n+\t     (width / ICE_AQC_ACL_KEY_WIDTH_BYTES)) > ICE_AQC_ACL_SLICES)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\tice_memset(&tbl_alloc, 0, sizeof(tbl_alloc), ICE_NONDMA_MEM);\n+\ttbl_alloc.width = width;\n+\ttbl_alloc.depth = depth;\n+\ttbl_alloc.act_pairs_per_entry = params->entry_act_pairs;\n+\ttbl_alloc.concurr = params->concurr;\n+\t/* Set dependent_alloc_id only for concurrent table type */\n+\tif (params->concurr) {\n+\t\ttbl_alloc.num_dependent_alloc_ids =\n+\t\t\tICE_AQC_MAX_CONCURRENT_ACL_TBL;\n+\n+\t\tfor (i = 0; i < ICE_AQC_MAX_CONCURRENT_ACL_TBL; i++)\n+\t\t\ttbl_alloc.buf.data_buf.alloc_ids[i] =\n+\t\t\t\tCPU_TO_LE16(params->dep_tbls[i]);\n+\t}\n+\n+\t/* call the aq command to create the ACL table with these values */\n+\tstatus = ice_aq_alloc_acl_tbl(hw, &tbl_alloc, NULL);\n+\n+\tif (status) {\n+\t\tif (LE16_TO_CPU(tbl_alloc.buf.resp_buf.alloc_id) <\n+\t\t    ICE_AQC_ALLOC_ID_LESS_THAN_4K)\n+\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t  \"Alloc ACL table failed. Unavailable resource.\\n\");\n+\t\telse\n+\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t  \"AQ allocation of ACL failed with error. status: %d\\n\",\n+\t\t\t\t   status);\n+\t\treturn status;\n+\t}\n+\n+\ttbl = (struct ice_acl_tbl *)ice_malloc(hw, sizeof(*tbl));\n+\tif (!tbl) {\n+\t\tstatus = ICE_ERR_NO_MEMORY;\n+\n+\t\tgoto out;\n+\t}\n+\n+\tresp_buf = &tbl_alloc.buf.resp_buf;\n+\n+\t/* Retrieve information of the allocated table */\n+\ttbl->id = LE16_TO_CPU(resp_buf->alloc_id);\n+\ttbl->first_tcam = resp_buf->ops.table.first_tcam;\n+\ttbl->last_tcam = resp_buf->ops.table.last_tcam;\n+\ttbl->first_entry = LE16_TO_CPU(resp_buf->first_entry);\n+\ttbl->last_entry = LE16_TO_CPU(resp_buf->last_entry);\n+\n+\ttbl->info = *params;\n+\ttbl->info.width = width;\n+\ttbl->info.depth = depth;\n+\thw->acl_tbl = tbl;\n+\n+\tfor (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)\n+\t\ttbl->act_mems[i].act_mem = resp_buf->act_mem[i];\n+\n+\t/* Figure out which TCAMs that these newly allocated action memories\n+\t * belong to.\n+\t */\n+\tice_acl_divide_act_mems_to_tcams(tbl);\n+\n+\t/* Initialize the resources allocated by invalidating all TCAM entries\n+\t * and all the action pairs\n+\t */\n+\tstatus = ice_acl_init_tbl(hw);\n+\tif (status) {\n+\t\tice_free(hw, tbl);\n+\t\thw->acl_tbl = NULL;\n+\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t  \"Initialization of TCAM entries failed. status: %d\\n\",\n+\t\t\t  status);\n+\t\tgoto out;\n+\t}\n+\n+\tfirst_e = (tbl->first_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +\n+\t\t(tbl->first_entry / ICE_ACL_ENTRY_ALLOC_UNIT);\n+\tlast_e = (tbl->last_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +\n+\t\t(tbl->last_entry / ICE_ACL_ENTRY_ALLOC_UNIT);\n+\n+\t/* Indicate available entries in the table */\n+\tfor (i = first_e; i <= last_e; i++)\n+\t\tice_set_bit(i, tbl->avail);\n+\n+\tINIT_LIST_HEAD(&tbl->scens);\n+out:\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_acl_alloc_partition - Allocate a partition from the ACL table\n+ * @hw: pointer to the hardware structure\n+ * @req: info of partition being allocated\n+ */\n+static enum ice_status\n+ice_acl_alloc_partition(struct ice_hw *hw, struct ice_acl_scen *req)\n+{\n+\tu16 start = 0, cnt = 0, off = 0;\n+\tu16 width, r_entries, row;\n+\tbool done = false;\n+\tint dir;\n+\n+\t/* Determine the number of TCAMs each entry overlaps */\n+\twidth = DIVIDE_AND_ROUND_UP(req->width, ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\t/* Check if we have enough TCAMs to accommodate the width */\n+\tif (width > hw->acl_tbl->last_tcam - hw->acl_tbl->first_tcam + 1)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\t/* Number of entries must be multiple of ICE_ACL_ENTRY_ALLOC_UNIT's */\n+\tr_entries = ICE_ALIGN(req->num_entry, ICE_ACL_ENTRY_ALLOC_UNIT);\n+\n+\t/* To look for an available partition that can accommodate the request,\n+\t * the process first logically arranges available TCAMs in rows such\n+\t * that each row produces entries with the requested width. It then\n+\t * scans the TCAMs' available bitmap, one bit at a time, and\n+\t * accumulates contiguous available 64-entry chunks until there are\n+\t * enough of them or when all TCAM configurations have been checked.\n+\t *\n+\t * For width of 1 TCAM, the scanning process starts from the top most\n+\t * TCAM, and goes downward. Available bitmaps are examined from LSB\n+\t * to MSB.\n+\t *\n+\t * For width of multiple TCAMs, the process starts from the bottom-most\n+\t * row of TCAMs, and goes upward. Available bitmaps are examined from\n+\t * the MSB to the LSB.\n+\t *\n+\t * To make sure that adjacent TCAMs can be logically arranged in the\n+\t * same row, the scanning process may have multiple passes. In each\n+\t * pass, the first TCAM of the bottom-most row is displaced by one\n+\t * additional TCAM. The width of the row and the number of the TCAMs\n+\t * available determine the number of passes. When the displacement is\n+\t * more than the size of width, the TCAM row configurations will\n+\t * repeat. The process will terminate when the configurations repeat.\n+\t *\n+\t * Available partitions can span more than one row of TCAMs.\n+\t */\n+\tif (width == 1) {\n+\t\trow = hw->acl_tbl->first_tcam;\n+\t\tdir = 1;\n+\t} else {\n+\t\t/* Start with the bottom-most row, and scan for available\n+\t\t * entries upward\n+\t\t */\n+\t\trow = hw->acl_tbl->last_tcam + 1 - width;\n+\t\tdir = -1;\n+\t}\n+\n+\tdo {\n+\t\tu16 i;\n+\n+\t\t/* Scan all 64-entry chunks, one chunk at a time, in the\n+\t\t * current TCAM row\n+\t\t */\n+\t\tfor (i = 0;\n+\t\t     i < ICE_AQC_MAX_TCAM_ALLOC_UNITS && cnt < r_entries;\n+\t\t     i++) {\n+\t\t\tbool avail = true;\n+\t\t\tu16 w, p;\n+\n+\t\t\t/* Compute the cumulative available mask across the\n+\t\t\t * TCAM row to determine if the current 64-entry chunk\n+\t\t\t * is available.\n+\t\t\t */\n+\t\t\tp = dir > 0 ? i : ICE_AQC_MAX_TCAM_ALLOC_UNITS - i - 1;\n+\t\t\tfor (w = row; w < row + width && avail; w++) {\n+\t\t\t\tu16 b;\n+\n+\t\t\t\tb = (w * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + p;\n+\t\t\t\tavail &= ice_is_bit_set(hw->acl_tbl->avail, b);\n+\t\t\t}\n+\n+\t\t\tif (!avail) {\n+\t\t\t\tcnt = 0;\n+\t\t\t} else {\n+\t\t\t\t/* Compute the starting index of the newly\n+\t\t\t\t * found partition. When 'dir' is negative, the\n+\t\t\t\t * scan processes is going upward. If so, the\n+\t\t\t\t * starting index needs to be updated for every\n+\t\t\t\t * available 64-entry chunk found.\n+\t\t\t\t */\n+\t\t\t\tif (!cnt || dir < 0)\n+\t\t\t\t\tstart = (row * ICE_AQC_ACL_TCAM_DEPTH) +\n+\t\t\t\t\t\t(p * ICE_ACL_ENTRY_ALLOC_UNIT);\n+\t\t\t\tcnt += ICE_ACL_ENTRY_ALLOC_UNIT;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (cnt >= r_entries) {\n+\t\t\treq->start = start;\n+\t\t\treq->num_entry = r_entries;\n+\t\t\treq->end = ice_acl_tbl_calc_end_idx(start, r_entries,\n+\t\t\t\t\t\t\t    width);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\trow = (dir > 0) ? (row + width) : (row - width);\n+\t\tif (row > hw->acl_tbl->last_tcam ||\n+\t\t    row < hw->acl_tbl->first_tcam) {\n+\t\t\t/* All rows have been checked. Increment 'off' that\n+\t\t\t * will help yield a different TCAM configuration in\n+\t\t\t * which adjacent TCAMs can be alternatively in the\n+\t\t\t * same row.\n+\t\t\t */\n+\t\t\toff++;\n+\n+\t\t\t/* However, if the new 'off' value yields previously\n+\t\t\t * checked configurations, then exit.\n+\t\t\t */\n+\t\t\tif (off >= width)\n+\t\t\t\tdone = true;\n+\t\t\telse\n+\t\t\t\trow = dir > 0 ? off :\n+\t\t\t\t\thw->acl_tbl->last_tcam + 1 - off -\n+\t\t\t\t\twidth;\n+\t\t}\n+\t} while (!done);\n+\n+\treturn cnt >= r_entries ? ICE_SUCCESS : ICE_ERR_MAX_LIMIT;\n+}\n+\n+/**\n+ * ice_acl_fill_tcam_select\n+ * @scen_buf: Pointer to the scenario buffer that needs to be populated\n+ * @scen: Pointer to the available space for the scenario\n+ * @tcam_idx: Index of the TCAM used for this scenario\n+ * @tcam_idx_in_cascade : Local index of the TCAM in the cascade scenario\n+ *\n+ * For all TCAM that participate in this scenario, fill out the tcam_select\n+ * value.\n+ */\n+static void\n+ice_acl_fill_tcam_select(struct ice_aqc_acl_scen *scen_buf,\n+\t\t\t struct ice_acl_scen *scen, u16 tcam_idx,\n+\t\t\t u16 tcam_idx_in_cascade)\n+{\n+\tu16 cascade_cnt, idx;\n+\tu8 j;\n+\n+\tidx = tcam_idx_in_cascade * ICE_AQC_ACL_KEY_WIDTH_BYTES;\n+\tcascade_cnt = DIVIDE_AND_ROUND_UP(scen->width,\n+\t\t\t\t\t  ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\t/* For each scenario, we reserved last three bytes of scenario width for\n+\t * profile ID, range checker, and packet direction. Thus, the last three\n+\t * bytes of the last cascaded TCAMs will have value of 1st, 31st and\n+\t * 32nd byte location of BYTE selection base.\n+\t *\n+\t * For other bytes in the TCAMs:\n+\t * For non-cascade mode (1 TCAM wide) scenario, TCAM[x]'s Select {0-1}\n+\t * select indices 0-1 of the Byte Selection Base\n+\t * For cascade mode, the leftmost TCAM of the first cascade row selects\n+\t * indices 0-4 of the Byte Selection Base; the second TCAM in the\n+\t * cascade row selects indices starting with 5-n\n+\t */\n+\tfor (j = 0; j < ICE_AQC_ACL_KEY_WIDTH_BYTES; j++) {\n+\t\t/* PKT DIR uses the 1st location of Byte Selection Base: + 1 */\n+\t\tu8 val = ICE_AQC_ACL_BYTE_SEL_BASE + 1 + idx;\n+\n+\t\tif (tcam_idx_in_cascade == cascade_cnt - 1) {\n+\t\t\tif (j == ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM)\n+\t\t\t\tval = ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK;\n+\t\t\telse if (j == ICE_ACL_SCEN_PID_IDX_IN_TCAM)\n+\t\t\t\tval = ICE_AQC_ACL_BYTE_SEL_BASE_PID;\n+\t\t\telse if (j == ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM)\n+\t\t\t\tval = ICE_AQC_ACL_BYTE_SEL_BASE_PKT_DIR;\n+\t\t}\n+\n+\t\t/* In case that scenario's width is greater than the width of\n+\t\t * the Byte selection base, we will not assign a value to the\n+\t\t * tcam_select[j]. As a result, the tcam_select[j] will have\n+\t\t * default value which is zero.\n+\t\t */\n+\t\tif (val > ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK)\n+\t\t\tcontinue;\n+\n+\t\tscen_buf->tcam_cfg[tcam_idx].tcam_select[j] = val;\n+\n+\t\tidx++;\n+\t}\n+}\n+\n+/**\n+ * ice_acl_set_scen_chnk_msk\n+ * @scen_buf: Pointer to the scenario buffer that needs to be populated\n+ * @scen: pointer to the available space for the scenario\n+ *\n+ * Set the chunk mask for the entries that will be used by this scenario\n+ */\n+static void\n+ice_acl_set_scen_chnk_msk(struct ice_aqc_acl_scen *scen_buf,\n+\t\t\t  struct ice_acl_scen *scen)\n+{\n+\tu16 tcam_idx, num_cscd, units, cnt;\n+\tu8 chnk_offst;\n+\n+\t/* Determine the starting TCAM index and offset of the start entry */\n+\ttcam_idx = ICE_ACL_TBL_TCAM_IDX(scen->start);\n+\tchnk_offst = (u8)((scen->start % ICE_AQC_ACL_TCAM_DEPTH) /\n+\t\t\t  ICE_ACL_ENTRY_ALLOC_UNIT);\n+\n+\t/* Entries are allocated and tracked in multiple of 64's */\n+\tunits = scen->num_entry / ICE_ACL_ENTRY_ALLOC_UNIT;\n+\n+\t/* Determine number of cascaded TCAMs */\n+\tnum_cscd = scen->width / ICE_AQC_ACL_KEY_WIDTH_BYTES;\n+\n+\tfor (cnt = 0; cnt < units; cnt++) {\n+\t\tu16 i;\n+\n+\t\t/* Set the corresponding bitmap of individual 64-entry\n+\t\t * chunk spans across a cascade of 1 or more TCAMs\n+\t\t * For each TCAM, there will be (ICE_AQC_ACL_TCAM_DEPTH\n+\t\t * / ICE_ACL_ENTRY_ALLOC_UNIT) or 8 chunks.\n+\t\t */\n+\t\tfor (i = tcam_idx; i < tcam_idx + num_cscd; i++)\n+\t\t\tscen_buf->tcam_cfg[i].chnk_msk |= BIT(chnk_offst);\n+\n+\t\tchnk_offst = (chnk_offst + 1) % ICE_AQC_MAX_TCAM_ALLOC_UNITS;\n+\t\tif (!chnk_offst)\n+\t\t\ttcam_idx += num_cscd;\n+\t}\n+}\n+\n+/**\n+ * ice_acl_assign_act_mem_for_scen\n+ * @tbl: pointer to acl table structure\n+ * @scen: pointer to the scenario struct\n+ * @scen_buf: pointer to the available space for the scenario\n+ * @current_tcam_idx: theoretical index of the TCAM that we associated those\n+ *\t\t      action memory banks with, at the table creation time.\n+ * @target_tcam_idx: index of the TCAM that we want to associate those action\n+ *\t\t     memory banks with.\n+ */\n+static void\n+ice_acl_assign_act_mem_for_scen(struct ice_acl_tbl *tbl,\n+\t\t\t\tstruct ice_acl_scen *scen,\n+\t\t\t\tstruct ice_aqc_acl_scen *scen_buf,\n+\t\t\t\tu8 current_tcam_idx,\n+\t\t\t\tu8 target_tcam_idx)\n+{\n+\tu8 i;\n+\n+\tfor (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) {\n+\t\tstruct ice_acl_act_mem *p_mem = &tbl->act_mems[i];\n+\n+\t\tif (p_mem->act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL ||\n+\t\t    p_mem->member_of_tcam != current_tcam_idx)\n+\t\t\tcontinue;\n+\n+\t\tscen_buf->act_mem_cfg[i] = target_tcam_idx;\n+\t\tscen_buf->act_mem_cfg[i] |= ICE_AQC_ACL_SCE_ACT_MEM_EN;\n+\t\tice_set_bit(i, scen->act_mem_bitmap);\n+\t}\n+}\n+\n+/**\n+ * ice_acl_commit_partition - Indicate if the specified partition is active\n+ * @hw: pointer to the hardware structure\n+ * @scen: pointer to the scenario struct\n+ * @commit: true if the partition is being commit\n+ */\n+static void\n+ice_acl_commit_partition(struct ice_hw *hw, struct ice_acl_scen *scen,\n+\t\t\t bool commit)\n+{\n+\tu16 tcam_idx, off, num_cscd, units, cnt;\n+\n+\t/* Determine the starting TCAM index and offset of the start entry */\n+\ttcam_idx = ICE_ACL_TBL_TCAM_IDX(scen->start);\n+\toff = (scen->start % ICE_AQC_ACL_TCAM_DEPTH) /\n+\t\tICE_ACL_ENTRY_ALLOC_UNIT;\n+\n+\t/* Entries are allocated and tracked in multiple of 64's */\n+\tunits = scen->num_entry / ICE_ACL_ENTRY_ALLOC_UNIT;\n+\n+\t/* Determine number of cascaded TCAM */\n+\tnum_cscd = scen->width / ICE_AQC_ACL_KEY_WIDTH_BYTES;\n+\n+\tfor (cnt = 0; cnt < units; cnt++) {\n+\t\tu16 w;\n+\n+\t\t/* Set/clear the corresponding bitmap of individual 64-entry\n+\t\t * chunk spans across a row of 1 or more TCAMs\n+\t\t */\n+\t\tfor (w = 0; w < num_cscd; w++) {\n+\t\t\tu16 b;\n+\n+\t\t\tb = ((tcam_idx + w) * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +\n+\t\t\t\toff;\n+\t\t\tif (commit)\n+\t\t\t\tice_set_bit(b, hw->acl_tbl->avail);\n+\t\t\telse\n+\t\t\t\tice_clear_bit(b, hw->acl_tbl->avail);\n+\t\t}\n+\n+\t\toff = (off + 1) % ICE_AQC_MAX_TCAM_ALLOC_UNITS;\n+\t\tif (!off)\n+\t\t\ttcam_idx += num_cscd;\n+\t}\n+}\n+\n+/**\n+ * ice_acl_create_scen\n+ * @hw: pointer to the hardware structure\n+ * @match_width: number of bytes to be matched in this scenario\n+ * @num_entries: number of entries to be allocated for the scenario\n+ * @scen_id: holds returned scenario ID if successful\n+ */\n+enum ice_status\n+ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16 num_entries,\n+\t\t    u16 *scen_id)\n+{\n+\tu8 cascade_cnt, first_tcam, last_tcam, i, k;\n+\tstruct ice_aqc_acl_scen scen_buf;\n+\tstruct ice_acl_scen *scen;\n+\tenum ice_status status;\n+\n+\tif (!hw->acl_tbl)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\tscen = (struct ice_acl_scen *)ice_malloc(hw, sizeof(*scen));\n+\tif (!scen)\n+\t\treturn ICE_ERR_NO_MEMORY;\n+\n+\tscen->start = hw->acl_tbl->first_entry;\n+\tscen->width = ICE_AQC_ACL_KEY_WIDTH_BYTES *\n+\t\tDIVIDE_AND_ROUND_UP(match_width, ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\tscen->num_entry = num_entries;\n+\n+\tstatus = ice_acl_alloc_partition(hw, scen);\n+\tif (status) {\n+\t\tice_free(hw, scen);\n+\t\treturn status;\n+\t}\n+\n+\tice_memset(&scen_buf, 0, sizeof(scen_buf), ICE_NONDMA_MEM);\n+\n+\t/* Determine the number of cascade TCAMs, given the scenario's width */\n+\tcascade_cnt = DIVIDE_AND_ROUND_UP(scen->width,\n+\t\t\t\t\t  ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\tfirst_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);\n+\tlast_tcam = ICE_ACL_TBL_TCAM_IDX(scen->end);\n+\n+\t/* For each scenario, we reserved last three bytes of scenario width for\n+\t * packet direction flag, profile ID and range checker. Thus, we want to\n+\t * return back to the caller the eff_width, pkt_dir_idx, rng_chk_idx and\n+\t * pid_idx.\n+\t */\n+\tscen->eff_width = cascade_cnt * ICE_AQC_ACL_KEY_WIDTH_BYTES -\n+\t\tICE_ACL_SCEN_MIN_WIDTH;\n+\tscen->rng_chk_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES +\n+\t\tICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM;\n+\tscen->pid_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES +\n+\t\tICE_ACL_SCEN_PID_IDX_IN_TCAM;\n+\tscen->pkt_dir_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES +\n+\t\tICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM;\n+\n+\t/* set the chunk mask for the tcams */\n+\tice_acl_set_scen_chnk_msk(&scen_buf, scen);\n+\n+\t/* set the TCAM select and start_cmp and start_set bits */\n+\tk = first_tcam;\n+\t/* set the START_SET bit at the beginning of the stack */\n+\tscen_buf.tcam_cfg[k].start_cmp_set |= ICE_AQC_ACL_ALLOC_SCE_START_SET;\n+\twhile (k <= last_tcam) {\n+\t\tu8 last_tcam_idx_cascade = cascade_cnt + k - 1;\n+\n+\t\t/* set start_cmp for the first cascaded TCAM */\n+\t\tscen_buf.tcam_cfg[k].start_cmp_set |=\n+\t\t\tICE_AQC_ACL_ALLOC_SCE_START_CMP;\n+\n+\t\t/* cascade TCAMs up to the width of the scenario */\n+\t\tfor (i = k; i < cascade_cnt + k; i++) {\n+\t\t\tice_acl_fill_tcam_select(&scen_buf, scen, i, i - k);\n+\t\t\tice_acl_assign_act_mem_for_scen(hw->acl_tbl, scen,\n+\t\t\t\t\t\t\t&scen_buf,\n+\t\t\t\t\t\t\ti,\n+\t\t\t\t\t\t\tlast_tcam_idx_cascade);\n+\t\t}\n+\n+\t\tk = i;\n+\t}\n+\n+\t/* We need to set the start_cmp bit for the unused TCAMs. */\n+\ti = 0;\n+\twhile (i < first_tcam)\n+\t\tscen_buf.tcam_cfg[i++].start_cmp_set =\n+\t\t\t\t\tICE_AQC_ACL_ALLOC_SCE_START_CMP;\n+\n+\ti = last_tcam + 1;\n+\twhile (i < ICE_AQC_ACL_SLICES)\n+\t\tscen_buf.tcam_cfg[i++].start_cmp_set =\n+\t\t\t\t\tICE_AQC_ACL_ALLOC_SCE_START_CMP;\n+\n+\tstatus = ice_aq_alloc_acl_scen(hw, scen_id, &scen_buf, NULL);\n+\tif (status) {\n+\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t  \"AQ allocation of ACL scenario failed. status: %d\\n\",\n+\t\t\t  status);\n+\t\tice_free(hw, scen);\n+\t\treturn status;\n+\t}\n+\n+\tscen->id = *scen_id;\n+\tice_acl_commit_partition(hw, scen, false);\n+\tice_acl_init_entry(scen);\n+\tLIST_ADD(&scen->list_entry, &hw->acl_tbl->scens);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_acl_destroy_tbl - Destroy a previously created LEM table for ACL\n+ * @hw: pointer to the HW struct\n+ */\n+enum ice_status ice_acl_destroy_tbl(struct ice_hw *hw)\n+{\n+\tstruct ice_acl_scen *pos_scen, *tmp_scen;\n+\tstruct ice_aqc_acl_generic resp_buf;\n+\tstruct ice_aqc_acl_scen buf;\n+\tenum ice_status status;\n+\tu8 i;\n+\n+\tif (!hw->acl_tbl)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t/* Mark all the created scenario's TCAM to stop the packet lookup and\n+\t * delete them afterward\n+\t */\n+\tLIST_FOR_EACH_ENTRY_SAFE(pos_scen, tmp_scen, &hw->acl_tbl->scens,\n+\t\t\t\t ice_acl_scen, list_entry) {\n+\t\tstatus = ice_aq_query_acl_scen(hw, pos_scen->id, &buf, NULL);\n+\t\tif (status) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL, \"ice_aq_query_acl_scen() failed. status: %d\\n\",\n+\t\t\t\t  status);\n+\t\t\treturn status;\n+\t\t}\n+\n+\t\tfor (i = 0; i < ICE_AQC_ACL_SLICES; i++) {\n+\t\t\tbuf.tcam_cfg[i].chnk_msk = 0;\n+\t\t\tbuf.tcam_cfg[i].start_cmp_set =\n+\t\t\t\t\tICE_AQC_ACL_ALLOC_SCE_START_CMP;\n+\t\t}\n+\n+\t\tfor (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)\n+\t\t\tbuf.act_mem_cfg[i] = 0;\n+\n+\t\tstatus = ice_aq_update_acl_scen(hw, pos_scen->id, &buf, NULL);\n+\t\tif (status) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL, \"ice_aq_update_acl_scen() failed. status: %d\\n\",\n+\t\t\t\t  status);\n+\t\t\treturn status;\n+\t\t}\n+\n+\t\tstatus = ice_acl_destroy_scen(hw, pos_scen->id);\n+\t\tif (status) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL, \"deletion of scenario failed. status: %d\\n\",\n+\t\t\t\t  status);\n+\t\t\treturn status;\n+\t\t}\n+\t}\n+\n+\t/* call the aq command to destroy the ACL table */\n+\tstatus = ice_aq_dealloc_acl_tbl(hw, hw->acl_tbl->id, &resp_buf, NULL);\n+\n+\tif (status) {\n+\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t  \"AQ de-allocation of ACL failed. status: %d\\n\",\n+\t\t\t  status);\n+\t\treturn status;\n+\t}\n+\n+\tice_free(hw, hw->acl_tbl);\n+\thw->acl_tbl = NULL;\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_acl_add_entry - Add a flow entry to an ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen: scenario to add the entry to\n+ * @prior: priority level of the entry being added\n+ * @keys: buffer of the value of the key to be programmed to the ACL entry\n+ * @inverts: buffer of the value of the key inverts to be programmed\n+ * @acts: pointer to a buffer containing formatted actions\n+ * @acts_cnt: indicates the number of actions stored in \"acts\"\n+ * @entry_idx: returned scenario relative index of the added flow entry\n+ *\n+ * Given an ACL table and a scenario, to add the specified key and key invert\n+ * to an available entry in the specified scenario.\n+ * The \"keys\" and \"inverts\" buffers must be of the size which is the same as\n+ * the scenario's width\n+ */\n+enum ice_status\n+ice_acl_add_entry(struct ice_hw *hw, struct ice_acl_scen *scen,\n+\t\t  enum ice_acl_entry_prior prior, u8 *keys, u8 *inverts,\n+\t\t  struct ice_acl_act_entry *acts, u8 acts_cnt, u16 *entry_idx)\n+{\n+\tu16 i, entry_tcam, num_cscd, idx, offset;\n+\tstruct ice_aqc_acl_data buf;\n+\tenum ice_status status = ICE_SUCCESS;\n+\n+\tif (!scen)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t*entry_idx = ice_acl_scen_assign_entry_idx(scen, prior);\n+\tif (*entry_idx >= scen->num_entry) {\n+\t\t*entry_idx = 0;\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\t}\n+\n+\t/* Determine number of cascaded TCAMs */\n+\tnum_cscd = DIVIDE_AND_ROUND_UP(scen->width,\n+\t\t\t\t       ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\tentry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);\n+\tidx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + *entry_idx);\n+\n+\tice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);\n+\tfor (i = 0; i < num_cscd; i++) {\n+\t\t/* If the key spans more than one TCAM in the case of cascaded\n+\t\t * TCAMs, the key and key inverts need to be properly split\n+\t\t * among TCAMs.E.g.bytes 0 - 4 go to an index in the first TCAM\n+\t\t * and bytes 5 - 9 go to the same index in the next TCAM, etc.\n+\t\t * If the entry spans more than one TCAM in a cascaded TCAM\n+\t\t * mode, the programming of the entries in the TCAMs must be in\n+\t\t * reversed order - the TCAM entry of the rightmost TCAM should\n+\t\t * be programmed first; the TCAM entry of the leftmost TCAM\n+\t\t * should be programmed last.\n+\t\t */\n+\t\toffset = num_cscd - i - 1;\n+\t\tice_memcpy(&buf.entry_key.val,\n+\t\t\t   &keys[offset * sizeof(buf.entry_key.val)],\n+\t\t\t   sizeof(buf.entry_key.val), ICE_NONDMA_TO_NONDMA);\n+\t\tice_memcpy(&buf.entry_key_invert.val,\n+\t\t\t   &inverts[offset * sizeof(buf.entry_key_invert.val)],\n+\t\t\t   sizeof(buf.entry_key_invert.val),\n+\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\t\tstatus = ice_aq_program_acl_entry(hw, entry_tcam + offset, idx,\n+\t\t\t\t\t\t  &buf, NULL);\n+\t\tif (status) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t  \"aq program acl entry failed status: %d\\n\",\n+\t\t\t\t  status);\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+\t/* Program the action memory */\n+\tstatus = ice_acl_prog_act(hw, scen, acts, acts_cnt, *entry_idx);\n+\n+out:\n+\tif (status) {\n+\t\tice_acl_rem_entry(hw, scen, *entry_idx);\n+\t\t*entry_idx = 0;\n+\t}\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_acl_prog_act - Program a scenario's action memory\n+ * @hw: pointer to the HW struct\n+ * @scen: scenario to add the entry to\n+ * @acts: pointer to a buffer containing formatted actions\n+ * @acts_cnt: indicates the number of actions stored in \"acts\"\n+ * @entry_idx: scenario relative index of the added flow entry\n+ *\n+ * Program a scenario's action memory\n+ */\n+enum ice_status\n+ice_acl_prog_act(struct ice_hw *hw, struct ice_acl_scen *scen,\n+\t\t struct ice_acl_act_entry *acts, u8 acts_cnt,\n+\t\t u16 entry_idx)\n+{\n+\tu8 entry_tcam, num_cscd, i, actx_idx = 0;\n+\tstruct ice_aqc_actpair act_buf;\n+\tenum ice_status status = ICE_SUCCESS;\n+\tu16 idx;\n+\n+\tif (entry_idx >= scen->num_entry)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\tice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM);\n+\n+\t/* Determine number of cascaded TCAMs */\n+\tnum_cscd = DIVIDE_AND_ROUND_UP(scen->width,\n+\t\t\t\t       ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\tentry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);\n+\tidx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + entry_idx);\n+\n+\ti = ice_find_first_bit(scen->act_mem_bitmap,\n+\t\t\t       ICE_AQC_MAX_ACTION_MEMORIES);\n+\twhile (i < ICE_AQC_MAX_ACTION_MEMORIES) {\n+\t\tstruct ice_acl_act_mem *mem = &hw->acl_tbl->act_mems[i];\n+\n+\t\tif (actx_idx >= acts_cnt)\n+\t\t\tbreak;\n+\t\tif (mem->member_of_tcam >= entry_tcam &&\n+\t\t    mem->member_of_tcam < entry_tcam + num_cscd) {\n+\t\t\tice_memcpy(&act_buf.act[0], &acts[actx_idx],\n+\t\t\t\t   sizeof(struct ice_acl_act_entry),\n+\t\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\n+\t\t\tif (++actx_idx < acts_cnt) {\n+\t\t\t\tice_memcpy(&act_buf.act[1], &acts[actx_idx],\n+\t\t\t\t\t   sizeof(struct ice_acl_act_entry),\n+\t\t\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\t\t\t}\n+\n+\t\t\tstatus = ice_aq_program_actpair(hw, i, idx, &act_buf,\n+\t\t\t\t\t\t\tNULL);\n+\t\t\tif (status) {\n+\t\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t\t  \"program actpair failed status: %d\\n\",\n+\t\t\t\t\t  status);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tactx_idx++;\n+\t\t}\n+\n+\t\ti = ice_find_next_bit(scen->act_mem_bitmap,\n+\t\t\t\t      ICE_AQC_MAX_ACTION_MEMORIES, i + 1);\n+\t}\n+\n+\tif (!status && actx_idx < acts_cnt)\n+\t\tstatus = ICE_ERR_MAX_LIMIT;\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_acl_rem_entry - Remove a flow entry from an ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen: scenario to remove the entry from\n+ * @entry_idx: the scenario-relative index of the flow entry being removed\n+ */\n+enum ice_status\n+ice_acl_rem_entry(struct ice_hw *hw, struct ice_acl_scen *scen, u16 entry_idx)\n+{\n+\tstruct ice_aqc_actpair act_buf;\n+\tstruct ice_aqc_acl_data buf;\n+\tu8 entry_tcam, num_cscd, i;\n+\tenum ice_status status = ICE_SUCCESS;\n+\tu16 idx;\n+\n+\tif (!scen)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\tif (entry_idx >= scen->num_entry)\n+\t\treturn ICE_ERR_MAX_LIMIT;\n+\n+\tif (!ice_is_bit_set(scen->entry_bitmap, entry_idx))\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t/* Determine number of cascaded TCAMs */\n+\tnum_cscd = DIVIDE_AND_ROUND_UP(scen->width,\n+\t\t\t\t       ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\tentry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start);\n+\tidx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + entry_idx);\n+\n+\t/* invalidate the flow entry */\n+\tice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);\n+\tfor (i = 0; i < num_cscd; i++) {\n+\t\tstatus = ice_aq_program_acl_entry(hw, entry_tcam + i, idx, &buf,\n+\t\t\t\t\t\t  NULL);\n+\t\tif (status)\n+\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t  \"aq program acl entry failed status: %d\\n\",\n+\t\t\t\t  status);\n+\t}\n+\n+\tice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM);\n+\ti = ice_find_first_bit(scen->act_mem_bitmap,\n+\t\t\t       ICE_AQC_MAX_ACTION_MEMORIES);\n+\twhile (i < ICE_AQC_MAX_ACTION_MEMORIES) {\n+\t\tstruct ice_acl_act_mem *mem = &hw->acl_tbl->act_mems[i];\n+\n+\t\tif (mem->member_of_tcam >= entry_tcam &&\n+\t\t    mem->member_of_tcam < entry_tcam + num_cscd) {\n+\t\t\t/* Invalidate allocated action pairs */\n+\t\t\tstatus = ice_aq_program_actpair(hw, i, idx, &act_buf,\n+\t\t\t\t\t\t\tNULL);\n+\t\t\tif (status)\n+\t\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t\t  \"program actpair failed.status: %d\\n\",\n+\t\t\t\t\t  status);\n+\t\t}\n+\n+\t\ti = ice_find_next_bit(scen->act_mem_bitmap,\n+\t\t\t\t      ICE_AQC_MAX_ACTION_MEMORIES, i + 1);\n+\t}\n+\n+\tice_acl_scen_free_entry_idx(scen, entry_idx);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_acl_destroy_scen - Destroy an ACL scenario\n+ * @hw: pointer to the HW struct\n+ * @scen_id: ID of the remove scenario\n+ */\n+enum ice_status ice_acl_destroy_scen(struct ice_hw *hw, u16 scen_id)\n+{\n+\tstruct ice_acl_scen *scen, *tmp_scen;\n+\tstruct ice_flow_prof *p, *tmp;\n+\tenum ice_status status;\n+\n+\tif (!hw->acl_tbl)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t/* Remove profiles that use \"scen_id\" scenario */\n+\tLIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[ICE_BLK_ACL],\n+\t\t\t\t ice_flow_prof, l_entry)\n+\t\tif (p->cfg.scen && p->cfg.scen->id == scen_id) {\n+\t\t\tstatus = ice_flow_rem_prof(hw, ICE_BLK_ACL, p->id);\n+\t\t\tif (status) {\n+\t\t\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t\t\t  \"ice_flow_rem_prof failed. status: %d\\n\",\n+\t\t\t\t\t  status);\n+\t\t\t\tgoto exit;\n+\t\t\t}\n+\t\t}\n+\n+\t/* Call the aq command to destroy the targeted scenario */\n+\tstatus = ice_aq_dealloc_acl_scen(hw, scen_id, NULL);\n+\n+\tif (status) {\n+\t\tice_debug(hw, ICE_DBG_ACL,\n+\t\t\t  \"AQ de-allocation of scenario failed. status: %d\\n\",\n+\t\t\t  status);\n+\t\tgoto exit;\n+\t}\n+\n+\t/* Remove scenario from hw->acl_tbl->scens */\n+\tLIST_FOR_EACH_ENTRY_SAFE(scen, tmp_scen, &hw->acl_tbl->scens,\n+\t\t\t\t ice_acl_scen, list_entry)\n+\t\tif (scen->id == scen_id) {\n+\t\t\tLIST_DEL(&scen->list_entry);\n+\t\t\tice_free(hw, scen);\n+\t\t}\n+exit:\n+\treturn status;\n+}\ndiff --git a/drivers/net/ice/base/ice_adminq_cmd.h b/drivers/net/ice/base/ice_adminq_cmd.h\nindex 73f5e7090..2c899b90a 100644\n--- a/drivers/net/ice/base/ice_adminq_cmd.h\n+++ b/drivers/net/ice/base/ice_adminq_cmd.h\n@@ -419,6 +419,7 @@ struct ice_aqc_vsi_props {\n #define ICE_AQ_VSI_PROP_RXQ_MAP_VALID\t\tBIT(6)\n #define ICE_AQ_VSI_PROP_Q_OPT_VALID\t\tBIT(7)\n #define ICE_AQ_VSI_PROP_OUTER_UP_VALID\t\tBIT(8)\n+#define ICE_AQ_VSI_PROP_ACL_VALID\t\tBIT(10)\n #define ICE_AQ_VSI_PROP_FLOW_DIR_VALID\t\tBIT(11)\n #define ICE_AQ_VSI_PROP_PASID_VALID\t\tBIT(12)\n \t/* switch section */\n@@ -534,8 +535,16 @@ struct ice_aqc_vsi_props {\n \tu8 q_opt_reserved[3];\n \t/* outer up section */\n \t__le32 outer_up_table; /* same structure and defines as ingress tbl */\n-\t/* section 10 */\n-\t__le16 sect_10_reserved;\n+\t/* acl section */\n+\t__le16 acl_def_act;\n+#define ICE_AQ_VSI_ACL_DEF_RX_PROF_S\t0\n+#define ICE_AQ_VSI_ACL_DEF_RX_PROF_M\t(0xF << ICE_AQ_VSI_ACL_DEF_RX_PROF_S)\n+#define ICE_AQ_VSI_ACL_DEF_RX_TABLE_S\t4\n+#define ICE_AQ_VSI_ACL_DEF_RX_TABLE_M\t(0xF << ICE_AQ_VSI_ACL_DEF_RX_TABLE_S)\n+#define ICE_AQ_VSI_ACL_DEF_TX_PROF_S\t8\n+#define ICE_AQ_VSI_ACL_DEF_TX_PROF_M\t(0xF << ICE_AQ_VSI_ACL_DEF_TX_PROF_S)\n+#define ICE_AQ_VSI_ACL_DEF_TX_TABLE_S\t12\n+#define ICE_AQ_VSI_ACL_DEF_TX_TABLE_M\t(0xF << ICE_AQ_VSI_ACL_DEF_TX_TABLE_S)\n \t/* flow director section */\n \t__le16 fd_options;\n #define ICE_AQ_VSI_FD_ENABLE\t\tBIT(0)\n@@ -1694,6 +1703,7 @@ struct ice_aqc_nvm {\n #define ICE_AQC_NVM_ACTIV_SEL_OROM\tBIT(4)\n #define ICE_AQC_NVM_ACTIV_SEL_NETLIST\tBIT(5)\n #define ICE_AQC_NVM_SPECIAL_UPDATE\tBIT(6)\n+#define ICE_AQC_NVM_REVERT_LAST_ACTIV\tBIT(6) /* Write Activate only */\n #define ICE_AQC_NVM_ACTIV_SEL_MASK\tMAKEMASK(0x7, 3)\n #define ICE_AQC_NVM_FLASH_ONLY\t\tBIT(7)\n \t__le16 module_typeid;\n@@ -2010,6 +2020,418 @@ struct ice_aqc_clear_fd_table {\n \tu8 reserved[12];\n };\n \n+/* ACL - allocate (indirect 0x0C10) table */\n+#define ICE_AQC_ACL_KEY_WIDTH\t\t40\n+#define ICE_AQC_ACL_KEY_WIDTH_BYTES\t5\n+#define ICE_AQC_ACL_TCAM_DEPTH\t\t512\n+#define ICE_ACL_ENTRY_ALLOC_UNIT\t64\n+#define ICE_AQC_MAX_CONCURRENT_ACL_TBL\t15\n+#define ICE_AQC_MAX_ACTION_MEMORIES\t20\n+#define ICE_AQC_MAX_ACTION_ENTRIES\t512\n+#define ICE_AQC_ACL_SLICES\t\t16\n+#define ICE_AQC_ALLOC_ID_LESS_THAN_4K\t0x1000\n+/* The ACL block supports up to 8 actions per a single output. */\n+#define ICE_AQC_TBL_MAX_ACTION_PAIRS\t4\n+\n+#define ICE_AQC_MAX_TCAM_ALLOC_UNITS\t(ICE_AQC_ACL_TCAM_DEPTH / \\\n+\t\t\t\t\t ICE_ACL_ENTRY_ALLOC_UNIT)\n+#define ICE_AQC_ACL_ALLOC_UNITS\t\t(ICE_AQC_ACL_SLICES * \\\n+\t\t\t\t\t ICE_AQC_MAX_TCAM_ALLOC_UNITS)\n+\n+struct ice_aqc_acl_alloc_table {\n+\t__le16 table_width;\n+\t__le16 table_depth;\n+\tu8 act_pairs_per_entry;\n+\t/* For non-concurrent table allocation, this field needs\n+\t * to be set to zero(0) otherwise it shall specify the\n+\t * amount of concurrent tables whose AllocIDs are\n+\t * specified in buffer. Thus the newly allocated table\n+\t * is concurrent with table IDs specified in AllocIDs.\n+\t */\n+#define ICE_AQC_ACL_ALLOC_TABLE_TYPE_NONCONCURR\t0\n+\tu8 table_type;\n+\t__le16 reserved;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Allocate ACL table command buffer format */\n+struct ice_aqc_acl_alloc_table_data {\n+\t/* Dependent table AllocIDs. Each word in this 15 word array specifies\n+\t * a dependent table AllocID according to the amount specified in the\n+\t * \"table_type\" field. All unused words shall be set to 0xFFFF\n+\t */\n+#define ICE_AQC_CONCURR_ID_INVALID\t0xffff\n+\t__le16 alloc_ids[ICE_AQC_MAX_CONCURRENT_ACL_TBL];\n+};\n+\n+/* ACL - deallocate (indirect 0x0C11) table\n+ * ACL - allocate (indirect 0x0C12) action-pair\n+ * ACL - deallocate (indirect 0x0C13) action-pair\n+ */\n+\n+/* Following structure is common and used in case of deallocation\n+ * of ACL table and action-pair\n+ */\n+struct ice_aqc_acl_tbl_actpair {\n+\t/* Alloc ID of the table being released */\n+\t__le16 alloc_id;\n+\tu8 reserved[6];\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* This response structure is same in case of alloc/dealloc table,\n+ * alloc/dealloc action-pair\n+ */\n+struct ice_aqc_acl_generic {\n+\t/* if alloc_id is below 0x1000 then alllocation failed due to\n+\t * unavailable resources, else this is set by FW to identify\n+\t * table allocation\n+\t */\n+\t__le16 alloc_id;\n+\n+\tunion {\n+\t\t/* to be used only in case of alloc/dealloc table */\n+\t\tstruct {\n+\t\t\t/* Index of the first TCAM block, otherwise set to 0xFF\n+\t\t\t * for a failed allocation\n+\t\t\t */\n+\t\t\tu8 first_tcam;\n+\t\t\t/* Index of the last TCAM block. This index shall be\n+\t\t\t * set to the value of first_tcam for single TCAM block\n+\t\t\t * allocation, otherwise set to 0xFF for a failed\n+\t\t\t * allocation\n+\t\t\t */\n+\t\t\tu8 last_tcam;\n+\t\t} table;\n+\t\t/* reserved in case of alloc/dealloc action-pair */\n+\t\tstruct {\n+\t\t\t__le16 reserved;\n+\t\t} act_pair;\n+\t} ops;\n+\n+\t/* index of first entry (in both TCAM and action memories),\n+\t * otherwise set to 0xFF for a failed allocation\n+\t */\n+\t__le16 first_entry;\n+\t/* index of last entry (in both TCAM and action memories),\n+\t * otherwise set to 0xFF for a failed allocation\n+\t */\n+\t__le16 last_entry;\n+\n+\t/* Each act_mem element specifies the order of the memory\n+\t * otherwise 0xFF\n+\t */\n+\tu8 act_mem[ICE_AQC_MAX_ACTION_MEMORIES];\n+};\n+\n+/* ACL - allocate (indirect 0x0C14) scenario. This command doesn't have separate\n+ * response buffer since original command buffer gets updated with\n+ * 'scen_id' in case of success\n+ */\n+struct ice_aqc_acl_alloc_scen {\n+\tunion {\n+\t\tstruct {\n+\t\t\tu8 reserved[8];\n+\t\t} cmd;\n+\t\tstruct {\n+\t\t\t__le16 scen_id;\n+\t\t\tu8 reserved[6];\n+\t\t} resp;\n+\t} ops;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* ACL - de-allocate (direct 0x0C15) scenario. This command doesn't need\n+ * separate response buffer since nothing to be returned as a response\n+ * except status.\n+ */\n+struct ice_aqc_acl_dealloc_scen {\n+\t__le16 scen_id;\n+\tu8 reserved[14];\n+};\n+\n+/* ACL - update (direct 0x0C1B) scenario */\n+/* ACL - query (direct 0x0C23) scenario */\n+struct ice_aqc_acl_update_query_scen {\n+\t__le16 scen_id;\n+\tu8 reserved[6];\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Input buffer format in case allocate/update ACL scenario and same format\n+ * is used for response buffer in case of query ACL scenario.\n+ * NOTE: de-allocate ACL scenario is direct command and doesn't require\n+ * \"buffer\", hence no buffer format.\n+ */\n+struct ice_aqc_acl_scen {\n+\tstruct {\n+\t\t/* Byte [x] selection for the TCAM key. This value must be set\n+\t\t * set to 0x0 for unusued TCAM.\n+\t\t * Only Bit 6..0 is used in each byte and MSB is reserved\n+\t\t */\n+#define ICE_AQC_ACL_ALLOC_SCE_SELECT_M\t\t0x7F\n+#define ICE_AQC_ACL_BYTE_SEL_BASE\t\t0x20\n+#define ICE_AQC_ACL_BYTE_SEL_BASE_PID\t\t0x3E\n+#define ICE_AQC_ACL_BYTE_SEL_BASE_PKT_DIR\tICE_AQC_ACL_BYTE_SEL_BASE\n+#define ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK\t0x3F\n+\t\tu8 tcam_select[5];\n+\t\t/* TCAM Block entry masking. This value should be set to 0x0 for\n+\t\t * unused TCAM\n+\t\t */\n+\t\tu8 chnk_msk;\n+\t\t/* Bit 0 : masks TCAM entries 0-63\n+\t\t * Bit 1 : masks TCAM entries 64-127\n+\t\t * Bit 2 to 7 : follow the pattern of bit 0 and 1\n+\t\t */\n+#define ICE_AQC_ACL_ALLOC_SCE_START_CMP\t\tBIT(0)\n+#define ICE_AQC_ACL_ALLOC_SCE_START_SET\t\tBIT(1)\n+\t\tu8 start_cmp_set;\n+\n+\t} tcam_cfg[ICE_AQC_ACL_SLICES];\n+\n+\t/* Each byte, Bit 6..0: Action memory association to a TCAM block,\n+\t * otherwise it shall be set to 0x0 for disabled memory action.\n+\t * Bit 7 : Action memory enable for this scenario\n+\t */\n+#define ICE_AQC_ACL_SCE_ACT_MEM_TCAM_ASSOC_M\t0x7F\n+#define ICE_AQC_ACL_SCE_ACT_MEM_EN\t\tBIT(7)\n+\tu8 act_mem_cfg[ICE_AQC_MAX_ACTION_MEMORIES];\n+};\n+\n+/* ACL - allocate (indirect 0x0C16) counters */\n+struct ice_aqc_acl_alloc_counters {\n+\t/* Amount of contiguous counters requested. Min value is 1 and\n+\t * max value is 255\n+\t */\n+#define ICE_AQC_ACL_ALLOC_CNT_MIN_AMT\t0x1\n+#define ICE_AQC_ACL_ALLOC_CNT_MAX_AMT\t0xFF\n+\tu8 counter_amount;\n+\n+\t/* Counter type: 'single counter' which can be configured to count\n+\t * either bytes or packets\n+\t */\n+#define ICE_AQC_ACL_CNT_TYPE_SINGLE\t0x0\n+\n+\t/* Counter type: 'counter pair' which counts number of bytes and number\n+\t * of packets.\n+\t */\n+#define ICE_AQC_ACL_CNT_TYPE_DUAL\t0x1\n+\t/* requested counter type, single/dual */\n+\tu8 counters_type;\n+\n+\t/* counter bank allocation shall be 0-3 for 'byte or packet counter' */\n+#define ICE_AQC_ACL_MAX_CNT_SINGLE\t0x3\n+/* counter bank allocation shall be 0-1 for 'byte and packet counter dual' */\n+#define ICE_AQC_ACL_MAX_CNT_DUAL\t0x1\n+\t/* requested counter bank allocation */\n+\tu8 bank_alloc;\n+\n+\tu8 reserved;\n+\n+\tunion {\n+\t\t/* Applicable only in case of command */\n+\t\tstruct {\n+\t\t\tu8 reserved[12];\n+\t\t} cmd;\n+\t\t/* Applicable only in case of response */\n+#define ICE_AQC_ACL_ALLOC_CNT_INVAL\t0xFFFF\n+\t\tstruct {\n+\t\t\t/* Index of first allocated counter. 0xFFFF in case\n+\t\t\t * of unsuccessful allocation\n+\t\t\t */\n+\t\t\t__le16 first_counter;\n+\t\t\t/* Index of last allocated counter. 0xFFFF in case\n+\t\t\t * of unsuccessful allocation\n+\t\t\t */\n+\t\t\t__le16 last_counter;\n+\t\t\tu8 rsvd[8];\n+\t\t} resp;\n+\t} ops;\n+};\n+\n+/* ACL - de-allocate (direct 0x0C17) counters */\n+struct ice_aqc_acl_dealloc_counters {\n+\t/* first counter being released */\n+\t__le16 first_counter;\n+\t/* last counter being released */\n+\t__le16 last_counter;\n+\t/* requested counter type, single/dual */\n+\tu8 counters_type;\n+\t/* requested counter bank allocation */\n+\tu8 bank_alloc;\n+\tu8 reserved[10];\n+};\n+\n+/* ACL - de-allocate (direct 0x0C1A) resources. Used by SW to release all the\n+ * resources allocated for it using a single command\n+ */\n+struct ice_aqc_acl_dealloc_res {\n+\tu8 reserved[16];\n+};\n+\n+/* ACL - program actionpair (indirect 0x0C1C) */\n+/* ACL - query actionpair (indirect 0x0C25) */\n+struct ice_aqc_acl_actpair {\n+\t/* action mem index to program/update */\n+\tu8 act_mem_index;\n+\tu8 reserved;\n+\t/* The entry index in action memory to be programmed/updated */\n+\t__le16 act_entry_index;\n+\t__le32 reserved2;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Input buffer format for program/query action-pair admin command */\n+struct ice_acl_act_entry {\n+\t/* Action priority, values must be between 0..7 */\n+#define ICE_AQC_ACT_PRIO_VALID_MAX\t7\n+#define ICE_AQC_ACT_PRIO_MSK\t\tMAKEMASK(0xff, 0)\n+\tu8 prio;\n+\t/* Action meta-data identifier. This field should be set to 0x0\n+\t * for a NOP action\n+\t */\n+#define ICE_AQC_ACT_MDID_S\t\t8\n+#define ICE_AQC_ACT_MDID_MSK\t\tMAKEMASK(0xff00, ICE_AQC_ACT_MDID_S)\n+\tu8 mdid;\n+\t/* Action value */\n+#define ICE_AQC_ACT_VALUE_S\t\t16\n+#define ICE_AQC_ACT_VALUE_MSK\t\tMAKEMASK(0xffff0000, 16)\n+\t__le16 value;\n+};\n+\n+#define ICE_ACL_NUM_ACT_PER_ACT_PAIR 2\n+struct ice_aqc_actpair {\n+\tstruct ice_acl_act_entry act[ICE_ACL_NUM_ACT_PER_ACT_PAIR];\n+};\n+\n+/* Generic format used to describe either input or response buffer\n+ * for admin commands related to ACL profile\n+ */\n+struct ice_aqc_acl_prof_generic_frmt {\n+\t/* The first byte of the byte selection base is reserved to keep the\n+\t * first byte of the field vector where the packet direction info is\n+\t * available. Thus we should start at index 1 of the field vector to\n+\t * map its entries to the byte selection base.\n+\t */\n+#define ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX\t1\n+\t/* In each byte:\n+\t * Bit 0..5 = Byte selection for the byte selection base from the\n+\t * extracted fields (expressed as byte offset in extracted fields).\n+\t * Applicable values are 0..63\n+\t * Bit 6..7 = Reserved\n+\t */\n+#define ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS\t\t30\n+\tu8 byte_selection[ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS];\n+\t/* In each byte:\n+\t * Bit 0..4 = Word selection for the word selection base from the\n+\t * extracted fields (expressed as word offset in extracted fields).\n+\t * Applicable values are 0..31\n+\t * Bit 5..7 = Reserved\n+\t */\n+#define ICE_AQC_ACL_PROF_WORD_SEL_ELEMS\t\t32\n+\tu8 word_selection[ICE_AQC_ACL_PROF_WORD_SEL_ELEMS];\n+\t/* In each byte:\n+\t * Bit 0..3 = Double word selection for the double-word selection base\n+\t * from the extracted fields (expressed as double-word offset in\n+\t * extracted fields).\n+\t * Applicable values are 0..15\n+\t * Bit 4..7 = Reserved\n+\t */\n+#define ICE_AQC_ACL_PROF_DWORD_SEL_ELEMS\t15\n+\tu8 dword_selection[ICE_AQC_ACL_PROF_DWORD_SEL_ELEMS];\n+\t/* Scenario numbers for individual Physical Function's */\n+#define ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS\t8\n+\tu8 pf_scenario_num[ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS];\n+};\n+\n+/* ACL - program ACL profile extraction (indirect 0x0C1D) */\n+/* ACL - program ACL profile ranges (indirect 0x0C1E) */\n+/* ACL - query ACL profile (indirect 0x0C21) */\n+/* ACL - query ACL profile ranges (indirect 0x0C22) */\n+struct ice_aqc_acl_profile {\n+\tu8 profile_id; /* Programmed/Updated profile ID */\n+\tu8 reserved[7];\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Input buffer format for program profile extraction admin command and\n+ * response buffer format for query profile admin command is as defined\n+ * in struct ice_aqc_acl_prof_generic_frmt\n+ */\n+\n+/* Input buffer format for program profile ranges and query profile ranges\n+ * admin commands. Same format is used for response buffer in case of query\n+ * profile ranges command\n+ */\n+struct ice_acl_rng_data {\n+\t/* The range checker output shall be sent when the value\n+\t * related to this range checker is lower than low boundary\n+\t */\n+\t__be16 low_boundary;\n+\t/* The range checker output shall be sent when the value\n+\t * related to this range checker is higher than high boundary\n+\t */\n+\t__be16 high_boundary;\n+\t/* A value of '0' in bit shall clear the relevant bit input\n+\t * to the range checker\n+\t */\n+\t__be16 mask;\n+};\n+\n+struct ice_aqc_acl_profile_ranges {\n+#define ICE_AQC_ACL_PROF_RANGES_NUM_CFG 8\n+\tstruct ice_acl_rng_data checker_cfg[ICE_AQC_ACL_PROF_RANGES_NUM_CFG];\n+};\n+\n+/* ACL - program ACL entry (indirect 0x0C20) */\n+/* ACL - query ACL entry (indirect 0x0C24) */\n+struct ice_aqc_acl_entry {\n+\tu8 tcam_index; /* Updated TCAM block index */\n+\tu8 reserved;\n+\t__le16 entry_index; /* Updated entry index */\n+\t__le32 reserved2;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Input buffer format in case of program ACL entry and response buffer format\n+ * in case of query ACL entry\n+ */\n+struct ice_aqc_acl_data {\n+\t/* Entry key and entry key invert are 40 bits wide.\n+\t * Byte 0..4 : entry key and Byte 5..7 are reserved\n+\t * Byte 8..12: entry key invert and Byte 13..15 are reserved\n+\t */\n+\tstruct {\n+\t\tu8 val[5];\n+\t\tu8 reserved[3];\n+\t} entry_key, entry_key_invert;\n+};\n+\n+/* ACL - query ACL counter (direct 0x0C27) */\n+struct ice_aqc_acl_query_counter {\n+\t/* Queried counter index */\n+\t__le16 counter_index;\n+\t/* Queried counter bank */\n+\tu8 counter_bank;\n+\tunion {\n+\t\tstruct {\n+\t\t\tu8 reserved[13];\n+\t\t} cmd;\n+\t\tstruct {\n+\t\t\t/* Holds counter value/packet counter value */\n+\t\t\tu8 val[5];\n+\t\t\tu8 reserved[8];\n+\t\t} resp;\n+\t} ops;\n+};\n+\n /* Add Tx LAN Queues (indirect 0x0C30) */\n struct ice_aqc_add_txqs {\n \tu8 num_qgrps;\n@@ -2277,6 +2699,18 @@ struct ice_aq_desc {\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_acl_alloc_table alloc_table;\n+\t\tstruct ice_aqc_acl_tbl_actpair tbl_actpair;\n+\t\tstruct ice_aqc_acl_alloc_scen alloc_scen;\n+\t\tstruct ice_aqc_acl_dealloc_scen dealloc_scen;\n+\t\tstruct ice_aqc_acl_update_query_scen update_query_scen;\n+\t\tstruct ice_aqc_acl_alloc_counters alloc_counters;\n+\t\tstruct ice_aqc_acl_dealloc_counters dealloc_counters;\n+\t\tstruct ice_aqc_acl_dealloc_res dealloc_res;\n+\t\tstruct ice_aqc_acl_entry program_query_entry;\n+\t\tstruct ice_aqc_acl_actpair program_query_actpair;\n+\t\tstruct ice_aqc_acl_profile profile;\n+\t\tstruct ice_aqc_acl_query_counter query_counter;\n \t\tstruct ice_aqc_add_txqs add_txqs;\n \t\tstruct ice_aqc_dis_txqs dis_txqs;\n \t\tstruct ice_aqc_move_txqs move_txqs;\n@@ -2496,6 +2930,27 @@ enum ice_adminq_opc {\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+\t/* ACL commands */\n+\tice_aqc_opc_alloc_acl_tbl\t\t\t= 0x0C10,\n+\tice_aqc_opc_dealloc_acl_tbl\t\t\t= 0x0C11,\n+\tice_aqc_opc_alloc_acl_actpair\t\t\t= 0x0C12,\n+\tice_aqc_opc_dealloc_acl_actpair\t\t\t= 0x0C13,\n+\tice_aqc_opc_alloc_acl_scen\t\t\t= 0x0C14,\n+\tice_aqc_opc_dealloc_acl_scen\t\t\t= 0x0C15,\n+\tice_aqc_opc_alloc_acl_counters\t\t\t= 0x0C16,\n+\tice_aqc_opc_dealloc_acl_counters\t\t= 0x0C17,\n+\tice_aqc_opc_dealloc_acl_res\t\t\t= 0x0C1A,\n+\tice_aqc_opc_update_acl_scen\t\t\t= 0x0C1B,\n+\tice_aqc_opc_program_acl_actpair\t\t\t= 0x0C1C,\n+\tice_aqc_opc_program_acl_prof_extraction\t\t= 0x0C1D,\n+\tice_aqc_opc_program_acl_prof_ranges\t\t= 0x0C1E,\n+\tice_aqc_opc_program_acl_entry\t\t\t= 0x0C20,\n+\tice_aqc_opc_query_acl_prof\t\t\t= 0x0C21,\n+\tice_aqc_opc_query_acl_prof_ranges\t\t= 0x0C22,\n+\tice_aqc_opc_query_acl_scen\t\t\t= 0x0C23,\n+\tice_aqc_opc_query_acl_entry\t\t\t= 0x0C24,\n+\tice_aqc_opc_query_acl_actpair\t\t\t= 0x0C25,\n+\tice_aqc_opc_query_acl_counter\t\t\t= 0x0C27,\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_fdir.c b/drivers/net/ice/base/ice_fdir.c\nindex 90e7e082f..c78782e5a 100644\n--- a/drivers/net/ice/base/ice_fdir.c\n+++ b/drivers/net/ice/base/ice_fdir.c\n@@ -956,19 +956,25 @@ void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)\n  * ice_fdir_update_cntrs - increment / decrement filter counter\n  * @hw: pointer to hardware structure\n  * @flow: filter flow type\n+ * @acl_fltr: true indicates an ACL filter\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+ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow,\n+\t\t      bool acl_fltr, 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+\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+\t} else {\n+\t\tif (acl_fltr)\n+\t\t\thw->acl_fltr_cnt[flow] += incr;\n+\t\telse\n+\t\t\thw->fdir_fltr_cnt[flow] += incr;\n+\t}\n }\n \n /**\ndiff --git a/drivers/net/ice/base/ice_fdir.h b/drivers/net/ice/base/ice_fdir.h\nindex c811f7606..ff42d2e34 100644\n--- a/drivers/net/ice/base/ice_fdir.h\n+++ b/drivers/net/ice/base/ice_fdir.h\n@@ -204,6 +204,8 @@ struct ice_fdir_fltr {\n \tu16 cnt_index;\n \tu8 fdid_prio;\n \tu32 fltr_id;\n+\t/* Set to true for an ACL filter */\n+\tbool acl_fltr;\n };\n \n /* Dummy packet filter definition structure. */\n@@ -234,6 +236,7 @@ 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+ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow,\n+\t\t      bool acl_fltr, 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 1ad7026c7..6059ad87d 100644\n--- a/drivers/net/ice/base/ice_flex_pipe.c\n+++ b/drivers/net/ice/base/ice_flex_pipe.c\n@@ -3526,7 +3526,8 @@ static void ice_free_flow_profs(struct ice_hw *hw, u8 blk_idx)\n \n \t\tLIST_FOR_EACH_ENTRY_SAFE(e, t, &p->entries,\n \t\t\t\t\t ice_flow_entry, l_entry)\n-\t\t\tice_flow_rem_entry(hw, ICE_FLOW_ENTRY_HNDL(e));\n+\t\t\tice_flow_rem_entry(hw, (enum ice_block)blk_idx,\n+\t\t\t\t\t   ICE_FLOW_ENTRY_HNDL(e));\n \n \t\tLIST_DEL(&p->l_entry);\n \t\tif (p->acts)\ndiff --git a/drivers/net/ice/base/ice_flow.c b/drivers/net/ice/base/ice_flow.c\nindex 17fd2423e..f480153f7 100644\n--- a/drivers/net/ice/base/ice_flow.c\n+++ b/drivers/net/ice/base/ice_flow.c\n@@ -1024,6 +1024,126 @@ ice_flow_create_xtrct_seq(struct ice_hw *hw,\n }\n \n /**\n+ * ice_flow_sel_acl_scen - returns the specific scenario\n+ * @hw: pointer to the hardware structure\n+ * @params: information about the flow to be processed\n+ *\n+ * This function will return the specific scenario based on the\n+ * params passed to it\n+ */\n+static enum ice_status\n+ice_flow_sel_acl_scen(struct ice_hw *hw, struct ice_flow_prof_params *params)\n+{\n+\t/* Find the best-fit scenario for the provided match width */\n+\tstruct ice_acl_scen *cand_scen = NULL, *scen;\n+\n+\tif (!hw->acl_tbl)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\t/* Loop through each scenario and match against the scenario width\n+\t * to select the specific scenario\n+\t */\n+\tLIST_FOR_EACH_ENTRY(scen, &hw->acl_tbl->scens, ice_acl_scen, list_entry)\n+\t\tif (scen->eff_width >= params->entry_length &&\n+\t\t    (!cand_scen || cand_scen->eff_width > scen->eff_width))\n+\t\t\tcand_scen = scen;\n+\tif (!cand_scen)\n+\t\treturn ICE_ERR_DOES_NOT_EXIST;\n+\n+\tparams->prof->cfg.scen = cand_scen;\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_flow_acl_def_entry_frmt - Determine the layout of flow entries\n+ * @params: information about the flow to be processed\n+ */\n+static enum ice_status\n+ice_flow_acl_def_entry_frmt(struct ice_flow_prof_params *params)\n+{\n+\tu16 index, i, range_idx = 0;\n+\n+\tindex = ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;\n+\n+\tfor (i = 0; i < params->prof->segs_cnt; i++) {\n+\t\tstruct ice_flow_seg_info *seg = &params->prof->segs[i];\n+\t\tu64 match = seg->match;\n+\t\tu8 j;\n+\n+\t\tfor (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {\n+\t\t\tstruct ice_flow_fld_info *fld;\n+\t\t\tconst u64 bit = BIT_ULL(j);\n+\n+\t\t\tif (!(match & bit))\n+\t\t\t\tcontinue;\n+\n+\t\t\tfld = &seg->fields[j];\n+\t\t\tfld->entry.mask = ICE_FLOW_FLD_OFF_INVAL;\n+\n+\t\t\tif (fld->type == ICE_FLOW_FLD_TYPE_RANGE) {\n+\t\t\t\tfld->entry.last = ICE_FLOW_FLD_OFF_INVAL;\n+\n+\t\t\t\t/* Range checking only supported for single\n+\t\t\t\t * words\n+\t\t\t\t */\n+\t\t\t\tif (DIVIDE_AND_ROUND_UP(ice_flds_info[j].size +\n+\t\t\t\t\t\t\tfld->xtrct.disp,\n+\t\t\t\t\t\t\tBITS_PER_BYTE * 2) > 1)\n+\t\t\t\t\treturn ICE_ERR_PARAM;\n+\n+\t\t\t\t/* Ranges must define low and high values */\n+\t\t\t\tif (fld->src.val == ICE_FLOW_FLD_OFF_INVAL ||\n+\t\t\t\t    fld->src.last == ICE_FLOW_FLD_OFF_INVAL)\n+\t\t\t\t\treturn ICE_ERR_PARAM;\n+\n+\t\t\t\tfld->entry.val = range_idx++;\n+\t\t\t} else {\n+\t\t\t\t/* Store adjusted byte-length of field for later\n+\t\t\t\t * use, taking into account potential\n+\t\t\t\t * non-byte-aligned displacement\n+\t\t\t\t */\n+\t\t\t\tfld->entry.last = DIVIDE_AND_ROUND_UP\n+\t\t\t\t\t(ice_flds_info[j].size +\n+\t\t\t\t\t (fld->xtrct.disp % BITS_PER_BYTE),\n+\t\t\t\t\t BITS_PER_BYTE);\n+\t\t\t\tfld->entry.val = index;\n+\t\t\t\tindex += fld->entry.last;\n+\t\t\t}\n+\n+\t\t\tmatch &= ~bit;\n+\t\t}\n+\n+\t\tfor (j = 0; j < seg->raws_cnt; j++) {\n+\t\t\tstruct ice_flow_seg_fld_raw *raw = &seg->raws[j];\n+\n+\t\t\traw->info.entry.mask = ICE_FLOW_FLD_OFF_INVAL;\n+\t\t\traw->info.entry.val = index;\n+\t\t\traw->info.entry.last = raw->info.src.last;\n+\t\t\tindex += raw->info.entry.last;\n+\t\t}\n+\t}\n+\n+\t/* Currently only support using the byte selection base, which only\n+\t * allows for an effective entry size of 30 bytes. Reject anything\n+\t * larger.\n+\t */\n+\tif (index > ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\t/* Only 8 range checkers per profile, reject anything trying to use\n+\t * more\n+\t */\n+\tif (range_idx > ICE_AQC_ACL_PROF_RANGES_NUM_CFG)\n+\t\treturn ICE_ERR_PARAM;\n+\n+\t/* Store # bytes required for entry for later use */\n+\tparams->entry_length = index - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n  * ice_flow_proc_segs - process all packet segments associated with a profile\n  * @hw: pointer to the HW struct\n  * @params: information about the flow to be processed\n@@ -1048,6 +1168,14 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)\n \t\t */\n \t\tstatus = ICE_SUCCESS;\n \t\tbreak;\n+\tcase ICE_BLK_ACL:\n+\t\tstatus = ice_flow_acl_def_entry_frmt(params);\n+\t\tif (status)\n+\t\t\treturn status;\n+\t\tstatus = ice_flow_sel_acl_scen(hw, params);\n+\t\tif (status)\n+\t\t\treturn status;\n+\t\tbreak;\n \tcase ICE_BLK_FD:\n \t\tstatus = ICE_SUCCESS;\n \t\tbreak;\n@@ -1166,6 +1294,11 @@ ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)\n \tif (entry->entry)\n \t\tice_free(hw, entry->entry);\n \n+\tif (entry->range_buf) {\n+\t\tice_free(hw, entry->range_buf);\n+\t\tentry->range_buf = NULL;\n+\t}\n+\n \tif (entry->acts) {\n \t\tice_free(hw, entry->acts);\n \t\tentry->acts = NULL;\n@@ -1175,17 +1308,155 @@ ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)\n \tice_free(hw, entry);\n }\n \n+#define ICE_ACL_INVALID_SCEN\t0x3f\n+\n+/**\n+ * ice_flow_acl_is_prof_in_use - Verify if the profile is associated to any pf\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ * @buf: destination buffer function writes partial xtrct sequence to\n+ *\n+ * returns ICE_SUCCESS if no pf is associated to the given profile\n+ * returns ICE_ERR_IN_USE if at least one pf is associated to the given profile\n+ * returns other error code for real error\n+ */\n+static enum ice_status\n+ice_flow_acl_is_prof_in_use(struct ice_hw *hw, struct ice_flow_prof *prof,\n+\t\t\t    struct ice_aqc_acl_prof_generic_frmt *buf)\n+{\n+\tenum ice_status status;\n+\tu8 prof_id = 0;\n+\n+\tstatus = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (status)\n+\t\treturn status;\n+\n+\tstatus = ice_query_acl_prof(hw, prof_id, buf, NULL);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* If all pf's associated scenarios are all 0 or all\n+\t * ICE_ACL_INVALID_SCEN (63) for the given profile then the latter has\n+\t * not been configured yet.\n+\t */\n+\tif (buf->pf_scenario_num[0] == 0 && buf->pf_scenario_num[1] == 0 &&\n+\t    buf->pf_scenario_num[2] == 0 && buf->pf_scenario_num[3] == 0 &&\n+\t    buf->pf_scenario_num[4] == 0 && buf->pf_scenario_num[5] == 0 &&\n+\t    buf->pf_scenario_num[6] == 0 && buf->pf_scenario_num[7] == 0)\n+\t\treturn ICE_SUCCESS;\n+\n+\tif (buf->pf_scenario_num[0] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[1] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[2] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[3] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[4] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[5] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[6] == ICE_ACL_INVALID_SCEN &&\n+\t    buf->pf_scenario_num[7] == ICE_ACL_INVALID_SCEN)\n+\t\treturn ICE_SUCCESS;\n+\telse\n+\t\treturn ICE_ERR_IN_USE;\n+}\n+\n+/**\n+ * ice_flow_acl_free_act_cntr - Free the acl rule's actions\n+ * @hw: pointer to the hardware structure\n+ * @acts: array of actions to be performed on a match\n+ * @acts_cnt: number of actions\n+ */\n+static enum ice_status\n+ice_flow_acl_free_act_cntr(struct ice_hw *hw, struct ice_flow_action *acts,\n+\t\t\t   u8 acts_cnt)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < acts_cnt; i++) {\n+\t\tif (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||\n+\t\t    acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||\n+\t\t    acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {\n+\t\t\tstruct ice_acl_cntrs cntrs;\n+\t\t\tenum ice_status status;\n+\n+\t\t\tcntrs.bank = 0; /* Only bank0 for the moment */\n+\t\t\tcntrs.first_cntr =\n+\t\t\t\t\tLE16_TO_CPU(acts[i].data.acl_act.value);\n+\t\t\tcntrs.last_cntr =\n+\t\t\t\t\tLE16_TO_CPU(acts[i].data.acl_act.value);\n+\n+\t\t\tif (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)\n+\t\t\t\tcntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;\n+\t\t\telse\n+\t\t\t\tcntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;\n+\n+\t\t\tstatus = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\t\t}\n+\t}\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_flow_acl_disassoc_scen - Disassociate the scenario to the Profile\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ *\n+ * Disassociate the scenario to the Profile for the PF of the VSI.\n+ */\n+static enum ice_status\n+ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof)\n+{\n+\tstruct ice_aqc_acl_prof_generic_frmt buf;\n+\tenum ice_status status = ICE_SUCCESS;\n+\tu8 prof_id = 0;\n+\n+\tice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);\n+\n+\tstatus = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (status)\n+\t\treturn status;\n+\n+\tstatus = ice_query_acl_prof(hw, prof_id, &buf, NULL);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Clear scenario for this pf */\n+\tbuf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN;\n+\tstatus = ice_prgm_acl_prof_extrt(hw, prof_id, &buf, NULL);\n+\n+\treturn status;\n+}\n+\n /**\n  * ice_flow_rem_entry_sync - Remove a flow entry\n  * @hw: pointer to the HW struct\n+ * @blk: classification stage\n  * @entry: flow entry to be removed\n  */\n static enum ice_status\n-ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)\n+ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk,\n+\t\t\tstruct ice_flow_entry *entry)\n {\n \tif (!entry)\n \t\treturn ICE_ERR_BAD_PTR;\n \n+\tif (blk == ICE_BLK_ACL) {\n+\t\tenum ice_status status;\n+\n+\t\tif (!entry->prof)\n+\t\t\treturn ICE_ERR_BAD_PTR;\n+\n+\t\tstatus = ice_acl_rem_entry(hw, entry->prof->cfg.scen,\n+\t\t\t\t\t   entry->scen_entry_idx);\n+\t\tif (status)\n+\t\t\treturn status;\n+\n+\t\t/* Checks if we need to release an ACL counter. */\n+\t\tif (entry->acts_cnt && entry->acts)\n+\t\t\tice_flow_acl_free_act_cntr(hw, entry->acts,\n+\t\t\t\t\t\t   entry->acts_cnt);\n+\t}\n+\n \tLIST_DEL(&entry->l_entry);\n \n \tice_dealloc_flow_entry(hw, entry);\n@@ -1311,7 +1582,7 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,\n \n \t\tLIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,\n \t\t\t\t\t l_entry) {\n-\t\t\tstatus = ice_flow_rem_entry_sync(hw, e);\n+\t\t\tstatus = ice_flow_rem_entry_sync(hw, blk, e);\n \t\t\tif (status)\n \t\t\t\tbreak;\n \t\t}\n@@ -1319,6 +1590,40 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,\n \t\tice_release_lock(&prof->entries_lock);\n \t}\n \n+\tif (blk == ICE_BLK_ACL) {\n+\t\tstruct ice_aqc_acl_profile_ranges query_rng_buf;\n+\t\tstruct ice_aqc_acl_prof_generic_frmt buf;\n+\t\tu8 prof_id = 0;\n+\n+\t\t/* Deassociate the scenario to the Profile for the PF */\n+\t\tstatus = ice_flow_acl_disassoc_scen(hw, prof);\n+\t\tif (status)\n+\t\t\treturn status;\n+\n+\t\t/* Clear the range-checker if the profile ID is no longer\n+\t\t * used by any PF\n+\t\t */\n+\t\tstatus = ice_flow_acl_is_prof_in_use(hw, prof, &buf);\n+\t\tif (status && status != ICE_ERR_IN_USE) {\n+\t\t\treturn status;\n+\t\t} else if (!status) {\n+\t\t\t/* Clear the range-checker value for profile ID */\n+\t\t\tice_memset(&query_rng_buf, 0,\n+\t\t\t\t   sizeof(struct ice_aqc_acl_profile_ranges),\n+\t\t\t\t   ICE_NONDMA_MEM);\n+\n+\t\t\tstatus = ice_flow_get_hw_prof(hw, blk, prof->id,\n+\t\t\t\t\t\t      &prof_id);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\n+\t\t\tstatus = ice_prog_acl_prof_ranges(hw, prof_id,\n+\t\t\t\t\t\t\t  &query_rng_buf, NULL);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\t\t}\n+\t}\n+\n \t/* Remove all hardware profiles associated with this flow profile */\n \tstatus = ice_rem_prof(hw, blk, prof->id);\n \tif (!status) {\n@@ -1333,6 +1638,99 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,\n }\n \n /**\n+ * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field\n+ * @buf: Destination buffer function writes partial xtrct sequence to\n+ * @info: Info about field\n+ */\n+static void\n+ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t\t       struct ice_flow_fld_info *info)\n+{\n+\tu16 dst, i;\n+\tu8 src;\n+\n+\tsrc = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ +\n+\t\tinfo->xtrct.disp / BITS_PER_BYTE;\n+\tdst = info->entry.val;\n+\tfor (i = 0; i < info->entry.last; i++)\n+\t\t/* HW stores field vector words in LE, convert words back to BE\n+\t\t * so constructed entries will end up in network order\n+\t\t */\n+\t\tbuf->byte_selection[dst++] = src++ ^ 1;\n+}\n+\n+/**\n+ * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ */\n+static enum ice_status\n+ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof)\n+{\n+\tstruct ice_aqc_acl_prof_generic_frmt buf;\n+\tstruct ice_flow_fld_info *info;\n+\tenum ice_status status;\n+\tu8 prof_id = 0;\n+\tu16 i;\n+\n+\tice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);\n+\n+\tstatus = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (status)\n+\t\treturn status;\n+\n+\tstatus = ice_flow_acl_is_prof_in_use(hw, prof, &buf);\n+\tif (status && status != ICE_ERR_IN_USE)\n+\t\treturn status;\n+\n+\tif (!status) {\n+\t\t/* Program the profile dependent configuration. This is done\n+\t\t * only once regardless of the number of PFs using that profile\n+\t\t */\n+\t\tice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);\n+\n+\t\tfor (i = 0; i < prof->segs_cnt; i++) {\n+\t\t\tstruct ice_flow_seg_info *seg = &prof->segs[i];\n+\t\t\tu64 match = seg->match;\n+\t\t\tu16 j;\n+\n+\t\t\tfor (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {\n+\t\t\t\tconst u64 bit = BIT_ULL(j);\n+\n+\t\t\t\tif (!(match & bit))\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tinfo = &seg->fields[j];\n+\n+\t\t\t\tif (info->type == ICE_FLOW_FLD_TYPE_RANGE)\n+\t\t\t\t\tbuf.word_selection[info->entry.val] =\n+\t\t\t\t\t\t\t\tinfo->xtrct.idx;\n+\t\t\t\telse\n+\t\t\t\t\tice_flow_acl_set_xtrct_seq_fld(&buf,\n+\t\t\t\t\t\t\t\t       info);\n+\n+\t\t\t\tmatch &= ~bit;\n+\t\t\t}\n+\n+\t\t\tfor (j = 0; j < seg->raws_cnt; j++) {\n+\t\t\t\tinfo = &seg->raws[j].info;\n+\t\t\t\tice_flow_acl_set_xtrct_seq_fld(&buf, info);\n+\t\t\t}\n+\t\t}\n+\n+\t\tice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN,\n+\t\t\t   ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS,\n+\t\t\t   ICE_NONDMA_MEM);\n+\t}\n+\n+\t/* Update the current PF */\n+\tbuf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id;\n+\tstatus = ice_prgm_acl_prof_extrt(hw, prof_id, &buf, NULL);\n+\n+\treturn status;\n+}\n+\n+/**\n  * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG\n  * @hw: pointer to the hardware structure\n  * @blk: classification stage\n@@ -1377,6 +1775,11 @@ ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,\n \tenum ice_status status = ICE_SUCCESS;\n \n \tif (!ice_is_bit_set(prof->vsis, vsi_handle)) {\n+\t\tif (blk == ICE_BLK_ACL) {\n+\t\t\tstatus = ice_flow_acl_set_xtrct_seq(hw, prof);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\t\t}\n \t\tstatus = ice_add_prof_id_flow(hw, blk,\n \t\t\t\t\t      ice_get_hw_vsi_num(hw,\n \t\t\t\t\t\t\t\t vsi_handle),\n@@ -1559,6 +1962,682 @@ u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)\n }\n \n /**\n+ * ice_flow_acl_check_actions - Checks the acl rule's actions\n+ * @hw: pointer to the hardware structure\n+ * @acts: array of actions to be performed on a match\n+ * @acts_cnt: number of actions\n+ * @cnt_alloc: indicates if a ACL counter has been allocated.\n+ */\n+static enum ice_status\n+ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts,\n+\t\t\t   u8 acts_cnt, bool *cnt_alloc)\n+{\n+\tice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);\n+\tint i;\n+\n+\tice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);\n+\t*cnt_alloc = false;\n+\n+\tif (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT)\n+\t\treturn ICE_ERR_OUT_OF_RANGE;\n+\n+\tfor (i = 0; i < acts_cnt; i++) {\n+\t\tif (acts[i].type != ICE_FLOW_ACT_NOP &&\n+\t\t    acts[i].type != ICE_FLOW_ACT_DROP &&\n+\t\t    acts[i].type != ICE_FLOW_ACT_CNTR_PKT &&\n+\t\t    acts[i].type != ICE_FLOW_ACT_FWD_QUEUE)\n+\t\t\treturn ICE_ERR_CFG;\n+\n+\t\t/* If the caller want to add two actions of the same type, then\n+\t\t * it is considered invalid configuration.\n+\t\t */\n+\t\tif (ice_test_and_set_bit(acts[i].type, dup_check))\n+\t\t\treturn ICE_ERR_PARAM;\n+\t}\n+\n+\t/* Checks if ACL counters are needed. */\n+\tfor (i = 0; i < acts_cnt; i++) {\n+\t\tif (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||\n+\t\t    acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||\n+\t\t    acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {\n+\t\t\tstruct ice_acl_cntrs cntrs;\n+\t\t\tenum ice_status status;\n+\n+\t\t\tcntrs.amount = 1;\n+\t\t\tcntrs.bank = 0; /* Only bank0 for the moment */\n+\n+\t\t\tif (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)\n+\t\t\t\tcntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;\n+\t\t\telse\n+\t\t\t\tcntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;\n+\n+\t\t\tstatus = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\t\t\t/* Counter index within the bank */\n+\t\t\tacts[i].data.acl_act.value =\n+\t\t\t\t\t\tCPU_TO_LE16(cntrs.first_cntr);\n+\t\t\t*cnt_alloc = true;\n+\t\t}\n+\t}\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_flow_acl_frmt_entry_range - Format an acl range checker for a given field\n+ * @fld: number of the given field\n+ * @info: info about field\n+ * @range_buf: range checker configuration buffer\n+ * @data: pointer to a data buffer containing flow entry's match values/masks\n+ * @range: Input/output param indicating which range checkers are being used\n+ */\n+static void\n+ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info,\n+\t\t\t      struct ice_aqc_acl_profile_ranges *range_buf,\n+\t\t\t      u8 *data, u8 *range)\n+{\n+\tu16 new_mask;\n+\n+\t/* If not specified, default mask is all bits in field */\n+\tnew_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ?\n+\t\t    BIT(ice_flds_info[fld].size) - 1 :\n+\t\t    (*(u16 *)(data + info->src.mask))) << info->xtrct.disp;\n+\n+\t/* If the mask is 0, then we don't need to worry about this input\n+\t * range checker value.\n+\t */\n+\tif (new_mask) {\n+\t\tu16 new_high =\n+\t\t\t(*(u16 *)(data + info->src.last)) << info->xtrct.disp;\n+\t\tu16 new_low =\n+\t\t\t(*(u16 *)(data + info->src.val)) << info->xtrct.disp;\n+\t\tu8 range_idx = info->entry.val;\n+\n+\t\trange_buf->checker_cfg[range_idx].low_boundary =\n+\t\t\tCPU_TO_BE16(new_low);\n+\t\trange_buf->checker_cfg[range_idx].high_boundary =\n+\t\t\tCPU_TO_BE16(new_high);\n+\t\trange_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask);\n+\n+\t\t/* Indicate which range checker is being used */\n+\t\t*range |= BIT(range_idx);\n+\t}\n+}\n+\n+/**\n+ * ice_flow_acl_frmt_entry_fld - Partially format acl entry for a given field\n+ * @fld: number of the given field\n+ * @info: info about the field\n+ * @buf: buffer containing the entry\n+ * @dontcare: buffer containing don't care mask for entry\n+ * @data: pointer to a data buffer containing flow entry's match values/masks\n+ */\n+static void\n+ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf,\n+\t\t\t    u8 *dontcare, u8 *data)\n+{\n+\tu16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0;\n+\tbool use_mask = false;\n+\tu8 disp;\n+\n+\tsrc = info->src.val;\n+\tmask = info->src.mask;\n+\tdst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;\n+\tdisp = info->xtrct.disp % BITS_PER_BYTE;\n+\n+\tif (mask != ICE_FLOW_FLD_OFF_INVAL)\n+\t\tuse_mask = true;\n+\n+\tfor (k = 0; k < info->entry.last; k++, dst++) {\n+\t\t/* Add overflow bits from previous byte */\n+\t\tbuf[dst] = (tmp_s & 0xff00) >> 8;\n+\n+\t\t/* If mask is not valid, tmp_m is always zero, so just setting\n+\t\t * dontcare to 0 (no masked bits). If mask is valid, pulls in\n+\t\t * overflow bits of mask from prev byte\n+\t\t */\n+\t\tdontcare[dst] = (tmp_m & 0xff00) >> 8;\n+\n+\t\t/* If there is displacement, last byte will only contain\n+\t\t * displaced data, but there is no more data to read from user\n+\t\t * buffer, so skip so as not to potentially read beyond end of\n+\t\t * user buffer\n+\t\t */\n+\t\tif (!disp || k < info->entry.last - 1) {\n+\t\t\t/* Store shifted data to use in next byte */\n+\t\t\ttmp_s = data[src++] << disp;\n+\n+\t\t\t/* Add current (shifted) byte */\n+\t\t\tbuf[dst] |= tmp_s & 0xff;\n+\n+\t\t\t/* Handle mask if valid */\n+\t\t\tif (use_mask) {\n+\t\t\t\ttmp_m = (~data[mask++] & 0xff) << disp;\n+\t\t\t\tdontcare[dst] |= tmp_m & 0xff;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Fill in don't care bits at beginning of field */\n+\tif (disp) {\n+\t\tdst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;\n+\t\tfor (k = 0; k < disp; k++)\n+\t\t\tdontcare[dst] |= BIT(k);\n+\t}\n+\n+\tend_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE;\n+\n+\t/* Fill in don't care bits at end of field */\n+\tif (end_disp) {\n+\t\tdst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX +\n+\t\t      info->entry.last - 1;\n+\t\tfor (k = end_disp; k < BITS_PER_BYTE; k++)\n+\t\t\tdontcare[dst] |= BIT(k);\n+\t}\n+}\n+\n+/**\n+ * ice_flow_acl_frmt_entry - Format acl entry\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ * @e: pointer to the flow entry\n+ * @data: pointer to a data buffer containing flow entry's match values/masks\n+ * @acts: array of actions to be performed on a match\n+ * @acts_cnt: number of actions\n+ *\n+ * Formats the key (and key_inverse) to be matched from the data passed in,\n+ * along with data from the flow profile. This key/key_inverse pair makes up\n+ * the 'entry' for an acl flow entry.\n+ */\n+static enum ice_status\n+ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof,\n+\t\t\tstruct ice_flow_entry *e, u8 *data,\n+\t\t\tstruct ice_flow_action *acts, u8 acts_cnt)\n+{\n+\tu8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk;\n+\tstruct ice_aqc_acl_profile_ranges *range_buf = NULL;\n+\tenum ice_status status;\n+\tbool cnt_alloc;\n+\tu8 prof_id = 0;\n+\tu16 i, buf_sz;\n+\n+\tstatus = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (status)\n+\t\treturn status;\n+\n+\t/* Format the result action */\n+\n+\tstatus = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc);\n+\tif (status)\n+\t\treturn status;\n+\n+\tstatus = ICE_ERR_NO_MEMORY;\n+\n+\te->acts = (struct ice_flow_action *)\n+\t\tice_memdup(hw, acts, acts_cnt * sizeof(*acts),\n+\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\n+\tif (!e->acts)\n+\t\tgoto out;\n+\n+\te->acts_cnt = acts_cnt;\n+\n+\t/* Format the matching data */\n+\tbuf_sz = prof->cfg.scen->width;\n+\tbuf = (u8 *)ice_malloc(hw, buf_sz);\n+\tif (!buf)\n+\t\tgoto out;\n+\n+\tdontcare = (u8 *)ice_malloc(hw, buf_sz);\n+\tif (!dontcare)\n+\t\tgoto out;\n+\n+\t/* 'key' buffer will store both key and key_inverse, so must be twice\n+\t * size of buf\n+\t */\n+\tkey = (u8 *)ice_malloc(hw, buf_sz * 2);\n+\tif (!key)\n+\t\tgoto out;\n+\n+\trange_buf = (struct ice_aqc_acl_profile_ranges *)\n+\t\tice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges));\n+\tif (!range_buf)\n+\t\tgoto out;\n+\n+\t/* Set don't care mask to all 1's to start, will zero out used bytes */\n+\tice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM);\n+\n+\tfor (i = 0; i < prof->segs_cnt; i++) {\n+\t\tstruct ice_flow_seg_info *seg = &prof->segs[i];\n+\t\tu64 match = seg->match;\n+\t\tu16 j;\n+\n+\t\tfor (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {\n+\t\t\tstruct ice_flow_fld_info *info;\n+\t\t\tconst u64 bit = BIT_ULL(j);\n+\n+\t\t\tif (!(match & bit))\n+\t\t\t\tcontinue;\n+\n+\t\t\tinfo = &seg->fields[j];\n+\n+\t\t\tif (info->type == ICE_FLOW_FLD_TYPE_RANGE)\n+\t\t\t\tice_flow_acl_frmt_entry_range(j, info,\n+\t\t\t\t\t\t\t      range_buf, data,\n+\t\t\t\t\t\t\t      &range);\n+\t\t\telse\n+\t\t\t\tice_flow_acl_frmt_entry_fld(j, info, buf,\n+\t\t\t\t\t\t\t    dontcare, data);\n+\n+\t\t\tmatch &= ~bit;\n+\t\t}\n+\n+\t\tfor (j = 0; j < seg->raws_cnt; j++) {\n+\t\t\tstruct ice_flow_fld_info *info = &seg->raws[j].info;\n+\t\t\tu16 dst, src, mask, k;\n+\t\t\tbool use_mask = false;\n+\n+\t\t\tsrc = info->src.val;\n+\t\t\tdst = info->entry.val -\n+\t\t\t\t\tICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;\n+\t\t\tmask = info->src.mask;\n+\n+\t\t\tif (mask != ICE_FLOW_FLD_OFF_INVAL)\n+\t\t\t\tuse_mask = true;\n+\n+\t\t\tfor (k = 0; k < info->entry.last; k++, dst++) {\n+\t\t\t\tbuf[dst] = data[src++];\n+\t\t\t\tif (use_mask)\n+\t\t\t\t\tdontcare[dst] = ~data[mask++];\n+\t\t\t\telse\n+\t\t\t\t\tdontcare[dst] = 0;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tbuf[prof->cfg.scen->pid_idx] = (u8)prof_id;\n+\tdontcare[prof->cfg.scen->pid_idx] = 0;\n+\n+\t/* Format the buffer for direction flags */\n+\tdir_flag_msk = BIT(ICE_FLG_PKT_DIR);\n+\n+\tif (prof->dir == ICE_FLOW_RX)\n+\t\tbuf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk;\n+\n+\tif (range) {\n+\t\tbuf[prof->cfg.scen->rng_chk_idx] = range;\n+\t\t/* Mark any unused range checkers as don't care */\n+\t\tdontcare[prof->cfg.scen->rng_chk_idx] = ~range;\n+\t\te->range_buf = range_buf;\n+\t} else {\n+\t\tice_free(hw, range_buf);\n+\t}\n+\n+\tstatus = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0,\n+\t\t\t     buf_sz);\n+\tif (status)\n+\t\tgoto out;\n+\n+\te->entry = key;\n+\te->entry_sz = buf_sz * 2;\n+\n+out:\n+\tif (buf)\n+\t\tice_free(hw, buf);\n+\n+\tif (dontcare)\n+\t\tice_free(hw, dontcare);\n+\n+\tif (status && key)\n+\t\tice_free(hw, key);\n+\n+\tif (status && range_buf) {\n+\t\tice_free(hw, range_buf);\n+\t\te->range_buf = NULL;\n+\t}\n+\n+\tif (status && e->acts) {\n+\t\tice_free(hw, e->acts);\n+\t\te->acts = NULL;\n+\t\te->acts_cnt = 0;\n+\t}\n+\n+\tif (status && cnt_alloc)\n+\t\tice_flow_acl_free_act_cntr(hw, acts, acts_cnt);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches\n+ *\t\t\t\t       the compared data.\n+ * @prof: pointer to flow profile\n+ * @e: pointer to the comparing flow entry\n+ * @do_chg_action: decide if we want to change the ACL action\n+ * @do_add_entry: decide if we want to add the new ACL entry\n+ * @do_rem_entry: decide if we want to remove the current ACL entry\n+ *\n+ * Find an ACL scenario entry that matches the compared data. In the same time,\n+ * this function also figure out:\n+ * a/ If we want to change the ACL action\n+ * b/ If we want to add the new ACL entry\n+ * c/ If we want to remove the current ACL entry\n+ */\n+static struct ice_flow_entry *\n+ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof,\n+\t\t\t\t  struct ice_flow_entry *e, bool *do_chg_action,\n+\t\t\t\t  bool *do_add_entry, bool *do_rem_entry)\n+{\n+\tstruct ice_flow_entry *p, *return_entry = NULL;\n+\tu8 i, j;\n+\n+\t/* Check if:\n+\t * a/ There exists an entry with same matching data, but different\n+\t *    priority, then we remove this existing ACL entry. Then, we\n+\t *    will add the new entry to the ACL scenario.\n+\t * b/ There exists an entry with same matching data, priority, and\n+\t *    result action, then we do nothing\n+\t * c/ There exists an entry with same matching data, priority, but\n+\t *    different, action, then do only change the action's entry.\n+\t * d/ Else, we add this new entry to the ACL scenario.\n+\t */\n+\t*do_chg_action = false;\n+\t*do_add_entry = true;\n+\t*do_rem_entry = false;\n+\tLIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) {\n+\t\tif (memcmp(p->entry, e->entry, p->entry_sz))\n+\t\t\tcontinue;\n+\n+\t\t/* From this point, we have the same matching_data. */\n+\t\t*do_add_entry = false;\n+\t\treturn_entry = p;\n+\n+\t\tif (p->priority != e->priority) {\n+\t\t\t/* matching data && !priority */\n+\t\t\t*do_add_entry = true;\n+\t\t\t*do_rem_entry = true;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\t/* From this point, we will have matching_data && priority */\n+\t\tif (p->acts_cnt != e->acts_cnt)\n+\t\t\t*do_chg_action = true;\n+\t\tfor (i = 0; i < p->acts_cnt; i++) {\n+\t\t\tbool found_not_match = false;\n+\n+\t\t\tfor (j = 0; j < e->acts_cnt; j++)\n+\t\t\t\tif (memcmp(&p->acts[i], &e->acts[j],\n+\t\t\t\t\t   sizeof(struct ice_flow_action))) {\n+\t\t\t\t\tfound_not_match = true;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\n+\t\t\tif (found_not_match) {\n+\t\t\t\t*do_chg_action = true;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* (do_chg_action = true) means :\n+\t\t *    matching_data && priority && !result_action\n+\t\t * (do_chg_action = false) means :\n+\t\t *    matching_data && priority && result_action\n+\t\t */\n+\t\tbreak;\n+\t}\n+\n+\treturn return_entry;\n+}\n+\n+/**\n+ * ice_flow_acl_convert_to_acl_prior - Convert to ACL priority\n+ * @p: flow priority\n+ */\n+static enum ice_acl_entry_prior\n+ice_flow_acl_convert_to_acl_prior(enum ice_flow_priority p)\n+{\n+\tenum ice_acl_entry_prior acl_prior;\n+\n+\tswitch (p) {\n+\tcase ICE_FLOW_PRIO_LOW:\n+\t\tacl_prior = ICE_LOW;\n+\t\tbreak;\n+\tcase ICE_FLOW_PRIO_NORMAL:\n+\t\tacl_prior = ICE_NORMAL;\n+\t\tbreak;\n+\tcase ICE_FLOW_PRIO_HIGH:\n+\t\tacl_prior = ICE_HIGH;\n+\t\tbreak;\n+\tdefault:\n+\t\tacl_prior = ICE_NORMAL;\n+\t\tbreak;\n+\t}\n+\n+\treturn acl_prior;\n+}\n+\n+/**\n+ * ice_flow_acl_union_rng_chk - Perform union operation between two\n+ *                              range-range checker buffers\n+ * @dst_buf: pointer to destination range checker buffer\n+ * @src_buf: pointer to source range checker buffer\n+ *\n+ * For this function, we do the union between dst_buf and src_buf\n+ * range checker buffer, and we will save the result back to dst_buf\n+ */\n+static enum ice_status\n+ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf,\n+\t\t\t   struct ice_aqc_acl_profile_ranges *src_buf)\n+{\n+\tu8 i, j;\n+\n+\tif (!dst_buf || !src_buf)\n+\t\treturn ICE_ERR_BAD_PTR;\n+\n+\tfor (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) {\n+\t\tstruct ice_acl_rng_data *cfg_data = NULL, *in_data;\n+\t\tbool will_populate = false;\n+\n+\t\tin_data = &src_buf->checker_cfg[i];\n+\n+\t\tif (!in_data->mask)\n+\t\t\tbreak;\n+\n+\t\tfor (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) {\n+\t\t\tcfg_data = &dst_buf->checker_cfg[j];\n+\n+\t\t\tif (!cfg_data->mask ||\n+\t\t\t    !memcmp(cfg_data, in_data,\n+\t\t\t\t    sizeof(struct ice_acl_rng_data))) {\n+\t\t\t\twill_populate = true;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (will_populate) {\n+\t\t\tice_memcpy(cfg_data, in_data,\n+\t\t\t\t   sizeof(struct ice_acl_rng_data),\n+\t\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\t\t} else {\n+\t\t\t/* No available slot left to program range checker */\n+\t\t\treturn ICE_ERR_MAX_LIMIT;\n+\t\t}\n+\t}\n+\n+\treturn ICE_SUCCESS;\n+}\n+\n+/**\n+ * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ * @entry: double pointer to the flow entry\n+ *\n+ * For this function, we will look at the current added entries in the\n+ * corresponding ACL scenario. Then, we will perform matching logic to\n+ * see if we want to add/modify/do nothing with this new entry.\n+ */\n+static enum ice_status\n+ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof,\n+\t\t\t\t struct ice_flow_entry **entry)\n+{\n+\tbool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk;\n+\tstruct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf;\n+\tstruct ice_acl_act_entry *acts = NULL;\n+\tstruct ice_flow_entry *exist;\n+\tenum ice_status status = ICE_SUCCESS;\n+\tstruct ice_flow_entry *e;\n+\tu8 i;\n+\n+\tif (!entry || !(*entry) || !prof)\n+\t\treturn ICE_ERR_BAD_PTR;\n+\n+\te = *(entry);\n+\n+\tdo_chg_rng_chk = false;\n+\tif (e->range_buf) {\n+\t\tu8 prof_id = 0;\n+\n+\t\tstatus = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id,\n+\t\t\t\t\t      &prof_id);\n+\t\tif (status)\n+\t\t\treturn status;\n+\n+\t\t/* Query the current range-checker value in FW */\n+\t\tstatus = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf,\n+\t\t\t\t\t\t   NULL);\n+\t\tif (status)\n+\t\t\treturn status;\n+\t\tice_memcpy(&cfg_rng_buf, &query_rng_buf,\n+\t\t\t   sizeof(struct ice_aqc_acl_profile_ranges),\n+\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\n+\t\t/* Generate the new range-checker value */\n+\t\tstatus = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf);\n+\t\tif (status)\n+\t\t\treturn status;\n+\n+\t\t/* Reconfigure the range check if the buffer is changed. */\n+\t\tdo_chg_rng_chk = false;\n+\t\tif (memcmp(&query_rng_buf, &cfg_rng_buf,\n+\t\t\t   sizeof(struct ice_aqc_acl_profile_ranges))) {\n+\t\t\tstatus = ice_prog_acl_prof_ranges(hw, prof_id,\n+\t\t\t\t\t\t\t  &cfg_rng_buf, NULL);\n+\t\t\tif (status)\n+\t\t\t\treturn status;\n+\n+\t\t\tdo_chg_rng_chk = true;\n+\t\t}\n+\t}\n+\n+\t/* Figure out if we want to (change the ACL action) and/or\n+\t * (Add the new ACL entry) and/or (Remove the current ACL entry)\n+\t */\n+\texist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action,\n+\t\t\t\t\t\t  &do_add_entry, &do_rem_entry);\n+\n+\tif (do_rem_entry) {\n+\t\tstatus = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist);\n+\t\tif (status)\n+\t\t\treturn status;\n+\t}\n+\n+\t/* Prepare the result action buffer */\n+\tacts = (struct ice_acl_act_entry *)ice_calloc\n+\t\t(hw, e->entry_sz, sizeof(struct ice_acl_act_entry));\n+\tfor (i = 0; i < e->acts_cnt; i++)\n+\t\tice_memcpy(&acts[i], &e->acts[i].data.acl_act,\n+\t\t\t   sizeof(struct ice_acl_act_entry),\n+\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\n+\tif (do_add_entry) {\n+\t\tenum ice_acl_entry_prior prior;\n+\t\tu8 *keys, *inverts;\n+\t\tu16 entry_idx;\n+\n+\t\tkeys = (u8 *)e->entry;\n+\t\tinverts = keys + (e->entry_sz / 2);\n+\t\tprior = ice_flow_acl_convert_to_acl_prior(e->priority);\n+\n+\t\tstatus = ice_acl_add_entry(hw, prof->cfg.scen, prior, keys,\n+\t\t\t\t\t   inverts, acts, e->acts_cnt,\n+\t\t\t\t\t   &entry_idx);\n+\t\tif (status)\n+\t\t\tgoto out;\n+\n+\t\te->scen_entry_idx = entry_idx;\n+\t\tLIST_ADD(&e->l_entry, &prof->entries);\n+\t} else {\n+\t\tif (do_chg_action) {\n+\t\t\t/* For the action memory info, update the SW's copy of\n+\t\t\t * exist entry with e's action memory info\n+\t\t\t */\n+\t\t\tice_free(hw, exist->acts);\n+\t\t\texist->acts_cnt = e->acts_cnt;\n+\t\t\texist->acts = (struct ice_flow_action *)\n+\t\t\t\tice_calloc(hw, exist->acts_cnt,\n+\t\t\t\t\t   sizeof(struct ice_flow_action));\n+\n+\t\t\tif (!exist->acts) {\n+\t\t\t\tstatus = ICE_ERR_NO_MEMORY;\n+\t\t\t\tgoto out;\n+\t\t\t}\n+\n+\t\t\tice_memcpy(exist->acts, e->acts,\n+\t\t\t\t   sizeof(struct ice_flow_action) * e->acts_cnt,\n+\t\t\t\t   ICE_NONDMA_TO_NONDMA);\n+\n+\t\t\tstatus = ice_acl_prog_act(hw, prof->cfg.scen, acts,\n+\t\t\t\t\t\t  e->acts_cnt,\n+\t\t\t\t\t\t  exist->scen_entry_idx);\n+\t\t\tif (status)\n+\t\t\t\tgoto out;\n+\t\t}\n+\n+\t\tif (do_chg_rng_chk) {\n+\t\t\t/* In this case, we want to update the range checker\n+\t\t\t * information of the exist entry\n+\t\t\t */\n+\t\t\tstatus = ice_flow_acl_union_rng_chk(exist->range_buf,\n+\t\t\t\t\t\t\t    e->range_buf);\n+\t\t\tif (status)\n+\t\t\t\tgoto out;\n+\t\t}\n+\n+\t\t/* As we don't add the new entry to our SW DB, deallocate its\n+\t\t * memories, and return the exist entry to the caller\n+\t\t */\n+\t\tice_dealloc_flow_entry(hw, e);\n+\t\t*(entry) = exist;\n+\t}\n+out:\n+\tif (acts)\n+\t\tice_free(hw, acts);\n+\n+\treturn status;\n+}\n+\n+/**\n+ * ice_flow_acl_add_scen_entry - Add entry to ACL scenario\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ * @e: double pointer to the flow entry\n+ */\n+static enum ice_status\n+ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof,\n+\t\t\t    struct ice_flow_entry **e)\n+{\n+\tenum ice_status status;\n+\n+\tice_acquire_lock(&prof->entries_lock);\n+\tstatus = ice_flow_acl_add_scen_entry_sync(hw, prof, e);\n+\tice_release_lock(&prof->entries_lock);\n+\n+\treturn status;\n+}\n+\n+/**\n  * ice_flow_add_entry - Add a flow entry\n  * @hw: pointer to the HW struct\n  * @blk: classification stage\n@@ -1581,7 +2660,8 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n \tstruct ice_flow_entry *e = NULL;\n \tenum ice_status status = ICE_SUCCESS;\n \n-\tif (acts_cnt && !acts)\n+\t/* ACL entries must indicate an action */\n+\tif (blk == ICE_BLK_ACL && (!acts || !acts_cnt))\n \t\treturn ICE_ERR_PARAM;\n \n \t/* No flow entry data is expected for RSS */\n@@ -1620,6 +2700,18 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n \tcase ICE_BLK_RSS:\n \t\t/* RSS will add only one entry per VSI per profile */\n \t\tbreak;\n+\tcase ICE_BLK_ACL:\n+\t\t/* ACL will handle the entry management */\n+\t\tstatus = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts,\n+\t\t\t\t\t\t acts_cnt);\n+\t\tif (status)\n+\t\t\tgoto out;\n+\n+\t\tstatus = ice_flow_acl_add_scen_entry(hw, prof, &e);\n+\t\tif (status)\n+\t\t\tgoto out;\n+\n+\t\tbreak;\n \tcase ICE_BLK_FD:\n \t\tbreak;\n \tcase ICE_BLK_SW:\n@@ -1651,13 +2743,15 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n /**\n  * ice_flow_rem_entry - Remove a flow entry\n  * @hw: pointer to the HW struct\n+ * @blk: classification stage\n  * @entry_h: handle to the flow entry to be removed\n  */\n-enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)\n+enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,\n+\t\t\t\t   u64 entry_h)\n {\n \tstruct ice_flow_entry *entry;\n \tstruct ice_flow_prof *prof;\n-\tenum ice_status status;\n+\tenum ice_status status = ICE_SUCCESS;\n \n \tif (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)\n \t\treturn ICE_ERR_PARAM;\n@@ -1667,9 +2761,11 @@ enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)\n \t/* Retain the pointer to the flow profile as the entry will be freed */\n \tprof = entry->prof;\n \n-\tice_acquire_lock(&prof->entries_lock);\n-\tstatus = ice_flow_rem_entry_sync(hw, entry);\n-\tice_release_lock(&prof->entries_lock);\n+\tif (prof) {\n+\t\tice_acquire_lock(&prof->entries_lock);\n+\t\tstatus = ice_flow_rem_entry_sync(hw, blk, entry);\n+\t\tice_release_lock(&prof->entries_lock);\n+\t}\n \n \treturn status;\n }\ndiff --git a/drivers/net/ice/base/ice_flow.h b/drivers/net/ice/base/ice_flow.h\nindex 4c2067f0c..ec50b85ac 100644\n--- a/drivers/net/ice/base/ice_flow.h\n+++ b/drivers/net/ice/base/ice_flow.h\n@@ -6,6 +6,7 @@\n #define _ICE_FLOW_H_\n \n #include \"ice_flex_type.h\"\n+#include \"ice_acl.h\"\n #define ICE_IPV4_MAKE_PREFIX_MASK(prefix) ((u32)(~0) << (32 - (prefix)))\n #define ICE_FLOW_PROF_ID_INVAL\t\t0xfffffffffffffffful\n #define ICE_FLOW_PROF_ID_BYPASS\t\t0\n@@ -308,9 +309,14 @@ struct ice_flow_entry {\n \tstruct ice_flow_action *acts;\n \t/* Flow entry's content */\n \tvoid *entry;\n+\t/* Range buffer (For ACL only) */\n+\tstruct ice_aqc_acl_profile_ranges *range_buf;\n \tenum ice_flow_priority priority;\n \tu16 vsi_handle;\n \tu16 entry_sz;\n+\t/* Entry index in the ACL's scenario */\n+\tu16 scen_entry_idx;\n+#define ICE_FLOW_ACL_MAX_NUM_ACT\t2\n \tu8 acts_cnt;\n };\n \n@@ -336,6 +342,7 @@ struct ice_flow_prof {\n \n \tunion {\n \t\t/* struct sw_recipe */\n+\t\tstruct ice_acl_scen *scen;\n \t\t/* struct fd */\n \t\tu32 data;\n \t\t/* Symmetric Hash for RSS */\n@@ -381,6 +388,7 @@ enum ice_flow_action_type {\n struct ice_flow_action {\n \tenum ice_flow_action_type type;\n \tunion {\n+\t\tstruct ice_acl_act_entry acl_act;\n \t\tu32 dummy;\n \t} data;\n };\n@@ -408,7 +416,8 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n \t\t   u64 entry_id, u16 vsi, enum ice_flow_priority prio,\n \t\t   void *data, struct ice_flow_action *acts, u8 acts_cnt,\n \t\t   u64 *entry_h);\n-enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h);\n+enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,\n+\t\t\t\t   u64 entry_h);\n void\n ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,\n \t\t u16 val_loc, u16 mask_loc, u16 last_loc, bool range);\ndiff --git a/drivers/net/ice/base/ice_type.h b/drivers/net/ice/base/ice_type.h\nindex 89d476482..a89c6572b 100644\n--- a/drivers/net/ice/base/ice_type.h\n+++ b/drivers/net/ice/base/ice_type.h\n@@ -99,6 +99,7 @@ static inline u32 ice_round_to_num(u32 N, u32 R)\n #define ICE_HI_DWORD(x)\t\t((u32)((((x) >> 16) >> 16) & 0xFFFFFFFF))\n #define ICE_LO_DWORD(x)\t\t((u32)((x) & 0xFFFFFFFF))\n #define ICE_HI_WORD(x)\t\t((u16)(((x) >> 16) & 0xFFFF))\n+#define ICE_LO_WORD(x)\t\t((u16)((x) & 0xFFFF))\n \n /* debug masks - set these bits in hw->debug_mask to control output */\n #define ICE_DBG_TRACE\t\tBIT_ULL(0) /* for function-trace only */\n@@ -119,6 +120,7 @@ static inline u32 ice_round_to_num(u32 N, u32 R)\n \n #define ICE_DBG_PKG\t\tBIT_ULL(16)\n #define ICE_DBG_RES\t\tBIT_ULL(17)\n+#define ICE_DBG_ACL\t\tBIT_ULL(18)\n #define ICE_DBG_AQ_MSG\t\tBIT_ULL(24)\n #define ICE_DBG_AQ_DESC\t\tBIT_ULL(25)\n #define ICE_DBG_AQ_DESC_BUF\tBIT_ULL(26)\n@@ -389,6 +391,8 @@ struct ice_hw_common_caps {\n \tu8 apm_wol_support;\n \tu8 acpi_prog_mthd;\n \tu8 proxy_support;\n+\tbool nvm_unified_update;\n+#define ICE_NVM_MGMT_UNIFIED_UPD_SUPPORT\tBIT(3)\n };\n \n /* Function specific capabilities */\n@@ -879,6 +883,9 @@ struct ice_hw {\n \t/* tunneling info */\n \tstruct ice_tunnel_table tnl;\n \n+\tstruct ice_acl_tbl *acl_tbl;\n+\tstruct ice_fd_hw_prof **acl_prof;\n+\tu16 acl_fltr_cnt[ICE_FLTR_PTYPE_MAX];\n \t/* HW block tables */\n \tstruct ice_blk_info blk[ICE_BLK_COUNT];\n \tstruct ice_lock fl_profs_locks[ICE_BLK_COUNT];\t/* lock fltr profiles */\ndiff --git a/drivers/net/ice/base/meson.build b/drivers/net/ice/base/meson.build\nindex eff155574..100630c5f 100644\n--- a/drivers/net/ice/base/meson.build\n+++ b/drivers/net/ice/base/meson.build\n@@ -11,6 +11,8 @@ sources = [\n \t'ice_flow.c',\n \t'ice_dcb.c',\n \t'ice_fdir.c',\n+\t'ice_acl.c',\n+\t'ice_acl_ctrl.c',\n ]\n \n error_cflags = ['-Wno-unused-value',\ndiff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir_filter.c\nindex 5a791610f..d737c1acd 100644\n--- a/drivers/net/ice/ice_fdir_filter.c\n+++ b/drivers/net/ice/ice_fdir_filter.c\n@@ -584,7 +584,7 @@ ice_fdir_prof_rm(struct ice_pf *pf, enum ice_fltr_ptype ptype, bool is_tunnel)\n \t\t\t\t\t\t     hw_prof->vsi_h[i]);\n \t\t\tice_rem_prof_id_flow(hw, ICE_BLK_FD,\n \t\t\t\t\t     vsi_num, ptype);\n-\t\t\tice_flow_rem_entry(hw,\n+\t\t\tice_flow_rem_entry(hw, ICE_BLK_FD,\n \t\t\t\t\t   hw_prof->entry_h[i][is_tunnel]);\n \t\t\thw_prof->entry_h[i][is_tunnel] = 0;\n \t\t}\n@@ -876,7 +876,7 @@ ice_fdir_hw_tbl_conf(struct ice_pf *pf, struct ice_vsi *vsi,\n err_add_entry:\n \tvsi_num = ice_get_hw_vsi_num(hw, vsi->idx);\n \tice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof_id);\n-\tice_flow_rem_entry(hw, entry_1);\n+\tice_flow_rem_entry(hw, ICE_BLK_FD, entry_1);\n err_add_prof:\n \tice_flow_rem_prof(hw, ICE_BLK_FD, prof_id);\n \n",
    "prefixes": [
        "25/28"
    ]
}