get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2221410,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2221410/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260409120003.2719-4-marcin.szycik@linux.intel.com/",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/46/?format=api",
        "name": "Intel Wired Ethernet development",
        "link_name": "intel-wired-lan",
        "list_id": "intel-wired-lan.osuosl.org",
        "list_email": "intel-wired-lan@osuosl.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260409120003.2719-4-marcin.szycik@linux.intel.com>",
    "list_archive_url": null,
    "date": "2026-04-09T11:59:56",
    "name": "[iwl-next,v2,03/10] ice: initialize ACL scenario",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "477349ae9c5e4bed6c86d4092d1f4a7c219e1194",
    "submitter": {
        "id": 82782,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/82782/?format=api",
        "name": "Marcin Szycik",
        "email": "marcin.szycik@linux.intel.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260409120003.2719-4-marcin.szycik@linux.intel.com/mbox/",
    "series": [
        {
            "id": 499287,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/499287/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=499287",
            "date": "2026-04-09T11:59:53",
            "name": "Add ACL support",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/499287/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2221410/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2221410/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@osuosl.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=osuosl.org header.i=@osuosl.org header.a=rsa-sha256\n header.s=default header.b=qFYtXi8i;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=140.211.166.137; helo=smtp4.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fs0RJ6hj6z1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 23:00:44 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 4E89F41088;\n\tThu,  9 Apr 2026 13:00:41 +0000 (UTC)",
            "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id j7CbaRFreDyX; Thu,  9 Apr 2026 13:00:35 +0000 (UTC)",
            "from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id AB7FC40C8D;\n\tThu,  9 Apr 2026 13:00:35 +0000 (UTC)",
            "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists1.osuosl.org (Postfix) with ESMTP id 8BA7F237\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:31 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id D3DA381A6F\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:29 +0000 (UTC)",
            "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id LlThNnzbXKKL for <intel-wired-lan@lists.osuosl.org>;\n Thu,  9 Apr 2026 13:00:28 +0000 (UTC)",
            "from mgamail.intel.com (mgamail.intel.com [192.198.163.19])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 1B41780BA3\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:28 +0000 (UTC)",
            "from orviesa002.jf.intel.com ([10.64.159.142])\n by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 09 Apr 2026 06:00:20 -0700",
            "from irvmail002.ir.intel.com ([10.43.11.120])\n by orviesa002.jf.intel.com with ESMTP; 09 Apr 2026 06:00:14 -0700",
            "from gond.igk.intel.com (gond.igk.intel.com [10.123.220.52])\n by irvmail002.ir.intel.com (Postfix) with ESMTP id 307172FC61;\n Thu,  9 Apr 2026 14:00:13 +0100 (IST)"
        ],
        "X-Virus-Scanned": [
            "amavis at osuosl.org",
            "amavis at osuosl.org"
        ],
        "X-Comment": "SPF check N/A for local connections - client-ip=140.211.166.142;\n helo=lists1.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=<UNKNOWN> ",
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 smtp4.osuosl.org AB7FC40C8D",
            "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 1B41780BA3"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1775739635;\n\tbh=XO8VBYgCkLSiSWMc/rs76fki+2Zc/LOe+adkxbygKhU=;\n\th=From:To:Cc:Date:In-Reply-To:References:Subject:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t From;\n\tb=qFYtXi8i9DVVpBvE5K9qsYTMiqvP5eKkPmtT5BcxkWNTUUUyo+1LSQpPiX7ei+MA+\n\t skSuzmh9tfgezg7SkWlHuNws5ub/tQLMoEvbv2uYBE/lBM/njjJfMI3dI3TrZJPykB\n\t nbFkIIgaRSJ5Gt3TQF5s0Ecg9XHsFUBhbgG4jL6Cc3pArN7fJp6gs4BU2PhkDx2Ncr\n\t jyQj6S74WTPKMPwT05qjYd+Y6Rnx9buQ6S6Qa8eiY3VpjefZ9H/BgkqcQkA9FSwCGa\n\t X3FFkxtYEEs1FXP7dXZYrAI7fcGd6kmSYTXNhGr64AzN5LNFe2Dya3o50ivxXRTwK3\n\t JlFpHqKB107eQ==",
        "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=192.198.163.19;\n helo=mgamail.intel.com; envelope-from=marcin.szycik@linux.intel.com;\n receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 1B41780BA3",
        "X-CSE-ConnectionGUID": [
            "CYqGBEpTQ1GNn2qQ8OikZA==",
            "JB6NToD0QTCrCi1paQZ4IQ=="
        ],
        "X-CSE-MsgGUID": [
            "QahPx3YvTUisgaZPuBmWCg==",
            "VZ7qTrlfQqGQ3btSdzSN7g=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6800,10657,11753\"; a=\"75777532\"",
            "E=Sophos;i=\"6.23,169,1770624000\"; d=\"scan'208\";a=\"75777532\"",
            "E=Sophos;i=\"6.23,169,1770624000\"; d=\"scan'208\";a=\"259208131\""
        ],
        "X-ExtLoop1": "1",
        "From": "Marcin Szycik <marcin.szycik@linux.intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Cc": "netdev@vger.kernel.org, sandeep.penigalapati@intel.com,\n ananth.s@intel.com,\n alexander.duyck@gmail.com, Marcin Szycik <marcin.szycik@linux.intel.com>,\n Chinh Cao <chinh.t.cao@intel.com>,\n Tony Nguyen <anthony.l.nguyen@intel.com>,\n Aleksandr Loktionov <aleksandr.loktionov@intel.com>",
        "Date": "Thu,  9 Apr 2026 13:59:56 +0200",
        "Message-ID": "<20260409120003.2719-4-marcin.szycik@linux.intel.com>",
        "X-Mailer": "git-send-email 2.49.0",
        "In-Reply-To": "<20260409120003.2719-1-marcin.szycik@linux.intel.com>",
        "References": "<20260409120003.2719-1-marcin.szycik@linux.intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Mailman-Original-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1775739628; x=1807275628;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=c4eMOXyp2LN1lLk+Z9r8zAZxvsRhHPYKFvwJeeR8GBk=;\n b=hcz5CN/uiZldIqi6JfCk9Qi6uqhSb6ZOO4YK8b6NmG8+M5bZwVuRPcIX\n r9wizvPQ8HfnkibW3X9cL+JLrUnC9LDsFUksFxPJR6XydyQVOwZZGzcoA\n mMVOsfq3+v1xZMqTXpA3STc4DBJegSydWfn9BAjm5sNrqfU2d8N4YXvF/\n /D+HmTrXhMN2xpescFM3T/cmgnkrdJIjyg4QEQZY9B9xFrWt0ATB33W2C\n boPvtDwxRcSkkkuZu7lbtd6m0vLQR3z3bPnBVOk5zwOAO2Lw0cR6IVk1N\n LftYMK7opguTVL+d5ydl9QhjAbY8Z0fz4drJ6wVl66hzfgF/RxzVgbeCA\n w==;",
        "X-Mailman-Original-Authentication-Results": [
            "smtp1.osuosl.org;\n dmarc=none (p=none dis=none)\n header.from=linux.intel.com",
            "smtp1.osuosl.org;\n dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com\n header.a=rsa-sha256 header.s=Intel header.b=hcz5CN/u"
        ],
        "Subject": "[Intel-wired-lan] [PATCH iwl-next v2 03/10] ice: initialize ACL\n scenario",
        "X-BeenThere": "intel-wired-lan@osuosl.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n <intel-wired-lan.osuosl.org>",
        "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>",
        "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>",
        "Errors-To": "intel-wired-lan-bounces@osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"
    },
    "content": "From: Real Valiquette <real.valiquette@intel.com>\n\nComplete initialization of the ACL table by programming the table with an\ninitial scenario. The scenario stores the data for the filtering rules.\nAdjust reporting of ntuple filters to include ACL filters.\n\nCo-developed-by: Chinh Cao <chinh.t.cao@intel.com>\nSigned-off-by: Chinh Cao <chinh.t.cao@intel.com>\nSigned-off-by: Real Valiquette <real.valiquette@intel.com>\nCo-developed-by: Tony Nguyen <anthony.l.nguyen@intel.com>\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\nReviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>\nSigned-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>\n---\nv2:\n* Add unroll in ice_init_acl() in case of ice_acl_create_scen() failure\n---\n drivers/net/ethernet/intel/ice/ice.h          |   1 +\n drivers/net/ethernet/intel/ice/ice_acl.h      |   8 +\n .../net/ethernet/intel/ice/ice_adminq_cmd.h   |  29 +\n drivers/net/ethernet/intel/ice/ice_fdir.h     |   6 +-\n drivers/net/ethernet/intel/ice/ice_flow.h     |   7 +\n drivers/net/ethernet/intel/ice/ice_type.h     |   2 +\n drivers/net/ethernet/intel/ice/ice_acl.c      | 116 ++++\n drivers/net/ethernet/intel/ice/ice_acl_ctrl.c | 558 ++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_ethtool.c  |   4 +-\n .../ethernet/intel/ice/ice_ethtool_ntuple.c   |  45 +-\n drivers/net/ethernet/intel/ice/ice_fdir.c     |  12 +-\n drivers/net/ethernet/intel/ice/ice_main.c     |  17 +-\n 12 files changed, 789 insertions(+), 16 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex 3a51a033296c..e064323d983c 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -1024,6 +1024,7 @@ void ice_vsi_manage_fdir(struct ice_vsi *vsi, bool ena);\n int ice_add_ntuple_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd);\n int ice_del_ntuple_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd);\n int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd);\n+u32 ice_ntuple_get_max_fltr_cnt(struct ice_hw *hw);\n int\n ice_get_fdir_fltr_ids(struct ice_hw *hw, struct ethtool_rxnfc *cmd,\n \t\t      u32 *rule_locs);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl.h b/drivers/net/ethernet/intel/ice/ice_acl.h\nindex bb836f23d65e..d4e6f0e25a12 100644\n--- a/drivers/net/ethernet/intel/ice/ice_acl.h\n+++ b/drivers/net/ethernet/intel/ice/ice_acl.h\n@@ -101,6 +101,8 @@ struct ice_acl_alloc_tbl {\n \n int ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params);\n int ice_acl_destroy_tbl(struct ice_hw *hw);\n+int ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16 num_entries,\n+\t\t\tu16 *scen_id);\n int ice_aq_alloc_acl_tbl(struct ice_hw *hw, struct ice_acl_alloc_tbl *tbl,\n \t\t\t struct ice_sq_cd *cd);\n int ice_aq_dealloc_acl_tbl(struct ice_hw *hw, u16 alloc_id,\n@@ -113,5 +115,11 @@ int ice_aq_program_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n \t\t\t   struct ice_aqc_actpair *buf, struct ice_sq_cd *cd);\n int ice_aq_alloc_acl_scen(struct ice_hw *hw, u16 *scen_id,\n \t\t\t  struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd);\n+int ice_aq_dealloc_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t\t    struct ice_sq_cd *cd);\n+int ice_aq_update_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t\t   struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd);\n+int ice_aq_query_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t\t  struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd);\n \n #endif /* _ICE_ACL_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\nindex 87f215f47072..46d2675baa4e 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -2070,6 +2070,33 @@ struct ice_aqc_acl_generic {\n \tu8 act_mem[ICE_AQC_MAX_ACTION_MEMORIES];\n };\n \n+/* Allocate ACL scenario (indirect 0x0C14). 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+/* De-allocate ACL scenario (direct 0x0C15). 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 /* Update ACL scenario (direct 0x0C1B)\n  * Query ACL scenario (direct 0x0C23)\n  */\n@@ -2850,6 +2877,8 @@ enum ice_adminq_opc {\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_scen\t\t\t= 0x0C14,\n+\tice_aqc_opc_dealloc_acl_scen\t\t\t= 0x0C15,\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_entry\t\t\t= 0x0C20,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_fdir.h b/drivers/net/ethernet/intel/ice/ice_fdir.h\nindex 26d79b1364e7..4d802b6be0ee 100644\n--- a/drivers/net/ethernet/intel/ice/ice_fdir.h\n+++ b/drivers/net/ethernet/intel/ice/ice_fdir.h\n@@ -198,6 +198,8 @@ struct ice_ntuple_fltr {\n \tu32 fltr_id;\n \tu8 fdid_prio;\n \tu8 comp_report;\n+\n+\tbool acl_fltr;\n };\n \n /* Dummy packet filter definition structure */\n@@ -227,7 +229,7 @@ bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_ntuple_fltr *input);\n bool ice_fdir_has_frag(enum ice_fltr_ptype flow);\n struct ice_ntuple_fltr *\n ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx);\n-void\n-ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add);\n+void ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow,\n+\t\t\t   bool acl_fltr, bool add);\n void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_ntuple_fltr *input);\n #endif /* _ICE_FDIR_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h\nindex 7323e26afc0b..a20ef320e1f9 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.h\n@@ -482,6 +482,13 @@ struct ice_flow_prof {\n \tDECLARE_BITMAP(vsis, ICE_MAX_VSI);\n \n \tbool symm; /* Symmetric Hash for RSS */\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} cfg;\n };\n \n struct ice_rss_raw_cfg {\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex 161acd1cf095..8ee8eeb7679b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -1011,6 +1011,8 @@ struct ice_hw {\n \tstruct udp_tunnel_nic_info udp_tunnel_nic;\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 \n \t/* dvm boost update information */\n \tstruct ice_dvm_table dvm_upd;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl.c b/drivers/net/ethernet/intel/ice/ice_acl.c\nindex 3d963c6071dc..81bddac8d0a2 100644\n--- a/drivers/net/ethernet/intel/ice/ice_acl.c\n+++ b/drivers/net/ethernet/intel/ice/ice_acl.c\n@@ -134,3 +134,119 @@ int ice_aq_program_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n \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+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_alloc_acl_scen(struct ice_hw *hw, u16 *scen_id,\n+\t\t\t  struct ice_aqc_acl_scen *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_alloc_scen *cmd;\n+\tstruct libie_aq_desc desc;\n+\tint err;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_alloc_acl_scen);\n+\tdesc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);\n+\tcmd = libie_aq_raw(&desc);\n+\n+\terr = ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+\tif (!err)\n+\t\t*scen_id = le16_to_cpu(cmd->ops.resp.scen_id);\n+\n+\treturn err;\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+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_dealloc_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\t\t    struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_dealloc_scen *cmd;\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_scen);\n+\tcmd = libie_aq_raw(&desc);\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+ * Return: 0 on success, negative on error\n+ */\n+static int ice_aq_update_query_scen(struct ice_hw *hw, u16 opcode, u16 scen_id,\n+\t\t\t\t    struct ice_aqc_acl_scen *buf,\n+\t\t\t\t    struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_update_query_scen *cmd;\n+\tstruct libie_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(LIBIE_AQ_FLAG_RD);\n+\tcmd = libie_aq_raw(&desc);\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+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_update_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\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+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_query_acl_scen(struct ice_hw *hw, u16 scen_id,\n+\t\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/ethernet/intel/ice/ice_acl_ctrl.c b/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c\nindex d821b2c923d5..c6148192dc6e 100644\n--- a/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c\n+++ b/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c\n@@ -6,6 +6,80 @@\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+/**\n+ * ice_acl_init_entry - initialize ACL 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/* 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_ACL_PRIO_LOW] = scen->num_entry - 1;\n+\tscen->first_idx[ICE_ACL_PRIO_NORMAL] = scen->num_entry -\n+\t\tscen->num_entry / 4 - 1;\n+\tscen->first_idx[ICE_ACL_PRIO_HIGH] = 0;\n+\n+\tscen->last_idx[ICE_ACL_PRIO_LOW] = scen->num_entry -\n+\t\tscen->num_entry / 4;\n+\tscen->last_idx[ICE_ACL_PRIO_NORMAL] = scen->num_entry / 4;\n+\tscen->last_idx[ICE_ACL_PRIO_HIGH] = scen->num_entry / 4 - 1;\n+}\n+\n+/**\n+ * ice_acl_tbl_calc_end_idx - get end ACL entry index\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+ * Returns: end entry index\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 = DIV_ROUND_UP(num_stack_level,\n+\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 - initialize ACL table\n  * @hw: pointer to the hardware structure\n@@ -274,6 +348,452 @@ ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params)\n \treturn 0;\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+ * Returns: 0 on success, negative on error\n+ */\n+static int 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 = DIV_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 -ENOSPC;\n+\n+\t/* Number of entries must be multiple of ICE_ACL_ENTRY_ALLOC_UNIT's */\n+\tr_entries = 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\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 (u16 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 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 (u16 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 &= test_bit(b, hw->acl_tbl->avail);\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 ? 0 : -ENOSPC;\n+}\n+\n+/**\n+ * ice_acl_fill_tcam_select - fill key byte selection for scenario's TCAM\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 ice_acl_fill_tcam_select(struct ice_aqc_acl_scen *scen_buf,\n+\t\t\t\t     struct ice_acl_scen *scen, u16 tcam_idx,\n+\t\t\t\t     u16 tcam_idx_in_cascade)\n+{\n+\tu16 cascade_cnt, idx;\n+\n+\tidx = tcam_idx_in_cascade * ICE_AQC_ACL_KEY_WIDTH_BYTES;\n+\tcascade_cnt = DIV_ROUND_UP(scen->width, 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 (int 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 - set entries chunk masks\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 ice_acl_set_scen_chnk_msk(struct ice_aqc_acl_scen *scen_buf,\n+\t\t\t\t      struct ice_acl_scen *scen)\n+{\n+\tu16 tcam_idx, num_cscd, units;\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 (u16 cnt = 0; cnt < units; cnt++) {\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 (u16 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 - associate action memories to new TCAM\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 ice_acl_assign_act_mem_for_scen(struct ice_acl_tbl *tbl,\n+\t\t\t\t\t    struct ice_acl_scen *scen,\n+\t\t\t\t\t    struct ice_aqc_acl_scen *scen_buf,\n+\t\t\t\t\t    u8 current_tcam_idx,\n+\t\t\t\t\t    u8 target_tcam_idx)\n+{\n+\tfor (int 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_MEM_ACT_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\tset_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 ice_acl_commit_partition(struct ice_hw *hw,\n+\t\t\t\t     struct ice_acl_scen *scen, bool commit)\n+{\n+\tu16 tcam_idx, off, num_cscd, units;\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 (u16 cnt = 0; cnt < units; cnt++) {\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 (u16 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\tset_bit(b, hw->acl_tbl->avail);\n+\t\t\telse\n+\t\t\t\tclear_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 - create ACL scenario\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+ * Return: 0 on success, negative on error\n+ */\n+int ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16 num_entries,\n+\t\t\tu16 *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+\tint err;\n+\n+\tscen = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*scen), GFP_KERNEL);\n+\tif (!scen)\n+\t\treturn -ENOMEM;\n+\n+\tscen->start = hw->acl_tbl->first_entry;\n+\tscen->width = ICE_AQC_ACL_KEY_WIDTH_BYTES *\n+\t\tDIV_ROUND_UP(match_width, ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\tscen->num_entry = num_entries;\n+\n+\terr = ice_acl_alloc_partition(hw, scen);\n+\tif (err)\n+\t\tgoto out;\n+\n+\t/* Determine the number of cascade TCAMs, given the scenario's width */\n+\tcascade_cnt = DIV_ROUND_UP(scen->width, 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, i,\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+\terr = ice_aq_alloc_acl_scen(hw, scen_id, &scen_buf, NULL);\n+\tif (err) {\n+\t\tice_debug(hw, ICE_DBG_ACL, \"AQ allocation of ACL scenario failed. status: %d\\n\",\n+\t\t\t  err);\n+\t\tgoto out;\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+out:\n+\tif (err)\n+\t\tdevm_kfree(ice_hw_to_dev(hw), scen);\n+\n+\treturn err;\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+ * Return: 0 on success, negative on error\n+ */\n+static int 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+\tint err;\n+\n+\t/* Remove profiles that use \"scen_id\" scenario */\n+\tlist_for_each_entry_safe(p, tmp, &hw->fl_profs[ICE_BLK_ACL], l_entry)\n+\t\tif (p->cfg.scen && p->cfg.scen->id == scen_id) {\n+\t\t\terr = ice_flow_rem_prof(hw, ICE_BLK_ACL, p->id);\n+\t\t\tif (err) {\n+\t\t\t\tice_debug(hw, ICE_DBG_ACL, \"ice_flow_rem_prof failed. status: %d\\n\",\n+\t\t\t\t\t  err);\n+\t\t\t\treturn err;\n+\t\t\t}\n+\t\t}\n+\n+\terr = ice_aq_dealloc_acl_scen(hw, scen_id, NULL);\n+\tif (err) {\n+\t\tice_debug(hw, ICE_DBG_ACL, \"AQ de-allocation of scenario failed. status: %d\\n\",\n+\t\t\t  err);\n+\t\treturn err;\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 list_entry)\n+\t\tif (scen->id == scen_id) {\n+\t\t\tlist_del(&scen->list_entry);\n+\t\t\tdevm_kfree(ice_hw_to_dev(hw), scen);\n+\t\t}\n+\n+\treturn 0;\n+}\n+\n /**\n  * ice_acl_destroy_tbl - Destroy a previously created LEM table for ACL\n  * @hw: pointer to the HW struct\n@@ -282,12 +802,50 @@ ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params)\n  */\n int 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 \tint err;\n \n \tif (!hw->acl_tbl)\n \t\treturn -ENOENT;\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 list_entry) {\n+\t\terr = ice_aq_query_acl_scen(hw, pos_scen->id, &buf, NULL);\n+\t\tif (err) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL, \"ice_aq_query_acl_scen() failed. status: %d\\n\",\n+\t\t\t\t  err);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\tfor (int 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 (int i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)\n+\t\t\tbuf.act_mem_cfg[i] = 0;\n+\n+\t\terr = ice_aq_update_acl_scen(hw, pos_scen->id, &buf, NULL);\n+\t\tif (err) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL, \"ice_aq_update_acl_scen() failed. status: %d\\n\",\n+\t\t\t\t  err);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\terr = ice_acl_destroy_scen(hw, pos_scen->id);\n+\t\tif (err) {\n+\t\t\tice_debug(hw, ICE_DBG_ACL, \"deletion of scenario failed. status: %d\\n\",\n+\t\t\t\t  err);\n+\t\t\treturn err;\n+\t\t}\n+\t}\n+\n \terr = ice_aq_dealloc_acl_tbl(hw, hw->acl_tbl->id, &resp_buf, NULL);\n \tif (err) {\n \t\tice_debug(hw, ICE_DBG_ACL, \"AQ de-allocation of ACL failed. status: %d\\n\",\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c\nindex 1495d96b5c98..6683a16c888a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c\n@@ -3151,8 +3151,8 @@ ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,\n \tswitch (cmd->cmd) {\n \tcase ETHTOOL_GRXCLSRLCNT:\n \t\tcmd->rule_cnt = hw->fdir_active_fltr;\n-\t\t/* report total rule count */\n-\t\tcmd->data = ice_get_fdir_cnt_all(hw);\n+\t\t/* report max rule count */\n+\t\tcmd->data = ice_ntuple_get_max_fltr_cnt(hw);\n \t\tret = 0;\n \t\tbreak;\n \tcase ETHTOOL_GRXCLSRULE:\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c b/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c\nindex a6136e640418..053d6b7a66bd 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c\n@@ -228,6 +228,24 @@ int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd)\n \treturn ret;\n }\n \n+/**\n+ * ice_ntuple_get_max_fltr_cnt - get max number of allowed filters\n+ * @hw: hardware structure containing filter information\n+ *\n+ * Return: maximum number of allowed filters\n+ */\n+u32 ice_ntuple_get_max_fltr_cnt(struct ice_hw *hw)\n+{\n+\tint acl_cnt;\n+\n+\tif (hw->dev_caps.num_funcs < 8)\n+\t\tacl_cnt = ICE_AQC_ACL_TCAM_DEPTH / ICE_ACL_ENTIRE_SLICE;\n+\telse\n+\t\tacl_cnt = ICE_AQC_ACL_TCAM_DEPTH / ICE_ACL_HALF_SLICE;\n+\n+\treturn ice_get_fdir_cnt_all(hw) + acl_cnt;\n+}\n+\n /**\n  * ice_get_fdir_fltr_ids - fill buffer with filter IDs of active filters\n  * @hw: hardware structure containing the filter list\n@@ -244,8 +262,8 @@ ice_get_fdir_fltr_ids(struct ice_hw *hw, struct ethtool_rxnfc *cmd,\n \tunsigned int cnt = 0;\n \tint val = 0;\n \n-\t/* report total rule count */\n-\tcmd->data = ice_get_fdir_cnt_all(hw);\n+\t/* report max rule count */\n+\tcmd->data = ice_ntuple_get_max_fltr_cnt(hw);\n \n \tmutex_lock(&hw->fdir_fltr_lock);\n \n@@ -346,6 +364,9 @@ void ice_fdir_rem_adq_chnl(struct ice_hw *hw, u16 vsi_idx)\n static struct ice_fd_hw_prof *\n ice_fdir_get_hw_prof(struct ice_hw *hw, enum ice_block blk, int flow)\n {\n+\tif (blk == ICE_BLK_ACL && hw->acl_prof)\n+\t\treturn hw->acl_prof[flow];\n+\n \tif (blk == ICE_BLK_FD && hw->fdir_prof)\n \t\treturn hw->fdir_prof[flow];\n \n@@ -1635,8 +1656,10 @@ void ice_fdir_del_all_fltrs(struct ice_vsi *vsi)\n \tstruct ice_hw *hw = &pf->hw;\n \n \tlist_for_each_entry_safe(f_rule, tmp, &hw->fdir_list_head, fltr_node) {\n-\t\tice_fdir_write_all_fltr(pf, f_rule, false);\n-\t\tice_fdir_update_cntrs(hw, f_rule->flow_type, false);\n+\t\tif (!f_rule->acl_fltr)\n+\t\t\tice_fdir_write_all_fltr(pf, f_rule, false);\n+\t\tice_fdir_update_cntrs(hw, f_rule->flow_type, f_rule->acl_fltr,\n+\t\t\t\t      false);\n \t\tlist_del(&f_rule->fltr_node);\n \t\tdevm_kfree(ice_pf_to_dev(pf), f_rule);\n \t}\n@@ -1671,6 +1694,12 @@ void ice_vsi_manage_fdir(struct ice_vsi *vsi, bool ena)\n \t\t\tif (hw->fdir_prof[flow])\n \t\t\t\tice_fdir_rem_flow(hw, ICE_BLK_FD, flow);\n \n+\tif (hw->acl_prof)\n+\t\tfor (flow = ICE_FLTR_PTYPE_NONF_NONE; flow < ICE_FLTR_PTYPE_MAX;\n+\t\t     flow++)\n+\t\t\tif (hw->acl_prof[flow])\n+\t\t\t\tice_fdir_rem_flow(hw, ICE_BLK_ACL, flow);\n+\n release_lock:\n \tmutex_unlock(&hw->fdir_fltr_lock);\n }\n@@ -1730,7 +1759,7 @@ ice_ntuple_update_list_entry(struct ice_pf *pf, struct ice_ntuple_fltr *input,\n \t\terr = ice_fdir_write_all_fltr(pf, old_fltr, false);\n \t\tif (err)\n \t\t\treturn err;\n-\t\tice_fdir_update_cntrs(hw, old_fltr->flow_type, false);\n+\t\tice_fdir_update_cntrs(hw, old_fltr->flow_type, false, false);\n \t\t/* update sb-filters count, specific to ring->channel */\n \t\tice_update_per_q_fltr(vsi, old_fltr->orig_q_index, false);\n \t\tif (!input && !hw->fdir_fltr_cnt[old_fltr->flow_type])\n@@ -1746,7 +1775,7 @@ ice_ntuple_update_list_entry(struct ice_pf *pf, struct ice_ntuple_fltr *input,\n \tice_fdir_list_add_fltr(hw, input);\n \t/* update sb-filters count, specific to ring->channel */\n \tice_update_per_q_fltr(vsi, input->orig_q_index, true);\n-\tice_fdir_update_cntrs(hw, input->flow_type, true);\n+\tice_fdir_update_cntrs(hw, input->flow_type, input->acl_fltr, true);\n \treturn 0;\n }\n \n@@ -2017,7 +2046,7 @@ int ice_add_ntuple_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)\n \tif (ret)\n \t\treturn ret;\n \n-\tmax_location = ice_get_fdir_cnt_all(hw);\n+\tmax_location = ice_ntuple_get_max_fltr_cnt(hw);\n \tif (fsp->location >= max_location) {\n \t\tdev_err(dev, \"Failed to add filter. The number of ntuple filters or provided location exceed max %d.\\n\",\n \t\t\tmax_location);\n@@ -2068,7 +2097,7 @@ int ice_add_ntuple_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)\n \tgoto release_lock;\n \n remove_sw_rule:\n-\tice_fdir_update_cntrs(hw, input->flow_type, false);\n+\tice_fdir_update_cntrs(hw, input->flow_type, false, false);\n \t/* update sb-filters count, specific to ring->channel */\n \tice_update_per_q_fltr(vsi, input->orig_q_index, false);\n \tlist_del(&input->fltr_node);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_fdir.c b/drivers/net/ethernet/intel/ice/ice_fdir.c\nindex 5b25f6414b58..e55d6a91f03a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_fdir.c\n+++ b/drivers/net/ethernet/intel/ice/ice_fdir.c\n@@ -1179,18 +1179,24 @@ void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_ntuple_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+void ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow,\n+\t\t\t   bool acl_fltr, bool add)\n {\n \tint incr;\n \n \tincr = add ? 1 : -1;\n \thw->fdir_active_fltr += incr;\n \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+\t\treturn;\n+\t}\n+\n+\tif (acl_fltr)\n+\t\thw->acl_fltr_cnt[flow] += incr;\n \telse\n \t\thw->fdir_fltr_cnt[flow] += incr;\n }\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex 1cdb49cd42c3..23d6b8311ff9 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -4336,6 +4336,8 @@ static int ice_init_acl(struct ice_pf *pf)\n \tstruct ice_acl_tbl_params params = {};\n \tstruct ice_hw *hw = &pf->hw;\n \tint divider;\n+\tu16 scen_id;\n+\tint err;\n \n \t/* Creates a single ACL table that consist of src_ip(4 byte),\n \t * dest_ip(4 byte), src_port(2 byte) and dst_port(2 byte) for a total\n@@ -4354,7 +4356,20 @@ static int ice_init_acl(struct ice_pf *pf)\n \tparams.entry_act_pairs = 1;\n \tparams.concurr = false;\n \n-\treturn ice_acl_create_tbl(hw, &params);\n+\terr = ice_acl_create_tbl(hw, &params);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = ice_acl_create_scen(hw, params.width, params.depth, &scen_id);\n+\tif (err)\n+\t\tgoto destroy_table;\n+\n+\treturn 0;\n+\n+destroy_table:\n+\tice_acl_destroy_tbl(hw);\n+\n+\treturn err;\n }\n \n /**\n",
    "prefixes": [
        "iwl-next",
        "v2",
        "03/10"
    ]
}