get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2221411,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2221411/?format=api",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/1.0/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": ""
    },
    "msgid": "<20260409120003.2719-8-marcin.szycik@linux.intel.com>",
    "date": "2026-04-09T12:00:00",
    "name": "[iwl-next,v2,07/10] ice: create ACL entry",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "0ebdedb45a5d36c1fa3a8d4f9552f8fd0b6d3a64",
    "submitter": {
        "id": 82782,
        "url": "http://patchwork.ozlabs.org/api/1.0/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-8-marcin.szycik@linux.intel.com/mbox/",
    "series": [
        {
            "id": 499287,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/499287/?format=api",
            "date": "2026-04-09T11:59:53",
            "name": "Add ACL support",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/499287/mbox/"
        }
    ],
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2221411/checks/",
    "tags": {},
    "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=KUlLL0Dw;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=2605:bc80:3010::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 [IPv6:2605:bc80:3010::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 4fs0RM2S99z1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 23:00:47 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id F0C0D40CAA;\n\tThu,  9 Apr 2026 13:00:43 +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 5J0HHszpg4n5; Thu,  9 Apr 2026 13:00:38 +0000 (UTC)",
            "from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 471D74108E;\n\tThu,  9 Apr 2026 13:00:36 +0000 (UTC)",
            "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists1.osuosl.org (Postfix) with ESMTP id 168EB1F6\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:32 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id DBA4D80BA3\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:30 +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 FtDd17-CtDSM 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 A0D0681BF4\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:22 -0700",
            "from irvmail002.ir.intel.com ([10.43.11.120])\n by orviesa002.jf.intel.com with ESMTP; 09 Apr 2026 06:00:17 -0700",
            "from gond.igk.intel.com (gond.igk.intel.com [10.123.220.52])\n by irvmail002.ir.intel.com (Postfix) with ESMTP id 3A9682FC5F;\n Thu,  9 Apr 2026 14:00:16 +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 471D74108E",
            "OpenDKIM Filter v2.11.0 smtp1.osuosl.org A0D0681BF4"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1775739636;\n\tbh=bDT5PCXit1oBewKLwuFBxxy1oIp8D/IU9kmoda6GZiQ=;\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=KUlLL0Dwc3C3a7gKc7lRDSMdTjqUkAGXFrgvzs4yDDcplLKXsLGDpXE6TouvQ1dQu\n\t v0sNVLLsA1w9pL6orcV+Tdb4HVhpvwaKtHhzAE6fUGqBhIzx9m2YPViYNVNB7DePSB\n\t wBqgyXix/+J9YLK1AMQt4kTMd8caOnmS+bJElM0ZWRFksIaY4tc1PTNlOY1AaBF0GU\n\t FBVPaLg0xTc/KmesaS47zii7mP6GHS793CxGFjSXdj597JDI8jaxEM88G588/5n7pQ\n\t IMXyITMck3/YcbsPYeVGKxrxGWIAQGT9WBech+e5glEv2n5yhimSx/TlowyCUG3u9J\n\t ebqEaDMPWsdBg==",
        "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 A0D0681BF4",
        "X-CSE-ConnectionGUID": [
            "e4/nQJsWQ1+VP/4JMmbG0A==",
            "K/8LxpukR8y58rnikdZpTA=="
        ],
        "X-CSE-MsgGUID": [
            "vWWpPvQzQ66IWocUEnkSkw==",
            "8BebgB/PQbeLF/yudbo8ZQ=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6800,10657,11753\"; a=\"75777551\"",
            "E=Sophos;i=\"6.23,169,1770624000\"; d=\"scan'208\";a=\"75777551\"",
            "E=Sophos;i=\"6.23,169,1770624000\"; d=\"scan'208\";a=\"259208150\""
        ],
        "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 14:00:00 +0200",
        "Message-ID": "<20260409120003.2719-8-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=1775739629; x=1807275629;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=PuOrxGOXsus7y4JJWQtGQkbxoui0lcTxtb2iDAFUqPk=;\n b=cTrP2YZ7N7kuLZYEtOkq2jk0g2AA393p/JByBPtDNH+4x5sEcdNDy0m8\n EaFLyZRb1E7PXG+c+w86OeBwwRZhRv6umkD9MrFX1AhO+BVUwlFV4T2i3\n SZRwR005ZUP4zkNYkdHIrRsC0USlzO8le295OIHQf9ywA96zL3skdYFdW\n bzeAuPAwVM9M+/KDWcBkrJS7pjnlQhYx7Jd9+9TheRDAau03dNzBz83gt\n d8yMOPz7Yyt/7ZyHWC5Gc0zscdCJ824r6Y3rZgBdWhVcTMppGn4PfCxvA\n mu4kg4zf2YWoA9UEDHQs3SG8zxneQhBYRdL5t+hz5fmDy4B/Vl8PxBO2s\n A==;",
        "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=cTrP2YZ7"
        ],
        "Subject": "[Intel-wired-lan] [PATCH iwl-next v2 07/10] ice: create ACL entry",
        "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\nCreate an ACL entry for the mask match data and set the desired action.\nGenerate and program the associated extraction sequence.\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>\nCo-developed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>\nSigned-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>\nCo-developed-by: Marcin Szycik <marcin.szycik@linux.intel.com>\nSigned-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>\nReviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>\n---\nv2:\n* Fix invalid profile ID passed to ice_flow_add_entry() in\n  ice_acl_add_rule_ethtool()\n* Fix uninitialized cntrs.amount field in ice_aq_dealloc_acl_cntrs()\n* Make ice_flow_acl_is_prof_in_use() more readable and return bool\n* Add ice_flow_acl_is_cntr_act() helper\n* Remove prof_id initialization when it's immediately set by\n  ice_flow_get_hw_prof() anyway\n* Check if src overflows in ice_flow_acl_set_xtrct_seq_fld()\n* Adjust error codes in ice_flow_acl_check_actions() to more reasonable\n  ones\n* Add ICE_RX_PKT_DROP_DROP instead of using a magic number\n* Reverse condition to decrease indent level in ice_aq_alloc_acl_cntrs()\n* Get rid of useless variable in ice_acl_add_rule_ethtool()\n* Use plain alloc and kfree instead of devm_ for ice_ntuple_fltr in\n  ice_acl_add_rule_ethtool(), ice_flow_entry::entry and\n  ice_flow_entry::range_buf\n* Use plain kmemdup and kfree instead of devm_ for ice_flow_entry::acts\n* ice_flow_entry members are being deallocated on device unload via\n  ice_deinit_fdir -> ice_vsi_manage_fdir -> ice_fdir_rem_flow ->\n  ice_fdir_erase_flow_from_hw -> ice_flow_rem_entry ->\n  ice_flow_rem_entry_sync\n* Add missing entry->range_buf and entry->acts dealloc in\n  ice_flow_add_entry() unroll\n* Remove redundant checks from ice_flow_acl_frmt_entry() unroll\n---\n drivers/net/ethernet/intel/ice/ice.h          |   3 +\n drivers/net/ethernet/intel/ice/ice_acl.h      |  24 +\n .../net/ethernet/intel/ice/ice_adminq_cmd.h   | 123 +++-\n .../net/ethernet/intel/ice/ice_flex_pipe.h    |   2 +\n drivers/net/ethernet/intel/ice/ice_flow.h     |   9 +-\n .../net/ethernet/intel/ice/ice_lan_tx_rx.h    |   3 +\n drivers/net/ethernet/intel/ice/ice_acl.c      | 183 +++++\n drivers/net/ethernet/intel/ice/ice_acl_main.c |  62 +-\n .../ethernet/intel/ice/ice_ethtool_ntuple.c   |  37 +-\n .../net/ethernet/intel/ice/ice_flex_pipe.c    |   5 +-\n drivers/net/ethernet/intel/ice/ice_flow.c     | 626 +++++++++++++++++-\n drivers/net/ethernet/intel/ice/ice_main.c     |   2 +-\n drivers/net/ethernet/intel/ice/virt/fdir.c    |   4 +-\n 13 files changed, 1044 insertions(+), 39 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex d10e67d8bf02..9e6643931022 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -1025,6 +1025,9 @@ 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 ice_ntuple_set_input_set(struct ice_vsi *vsi, enum ice_block blk,\n+\t\t\t     struct ethtool_rx_flow_spec *fsp,\n+\t\t\t     struct ice_ntuple_fltr *input);\n int ice_ntuple_l4_proto_to_port(enum ice_flow_seg_hdr l4_proto,\n \t\t\t\tenum ice_flow_field *src_port,\n \t\t\t\tenum ice_flow_field *dst_port);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl.h b/drivers/net/ethernet/intel/ice/ice_acl.h\nindex d4e6f0e25a12..3a4adcf368cf 100644\n--- a/drivers/net/ethernet/intel/ice/ice_acl.h\n+++ b/drivers/net/ethernet/intel/ice/ice_acl.h\n@@ -99,6 +99,20 @@ struct ice_acl_alloc_tbl {\n \t} buf;\n };\n \n+/* Input and output params for [de]allocate_acl_counters */\n+struct ice_acl_cntrs {\n+\tu8 amount;\n+\tu8 type;\n+\tu8 bank;\n+\n+\t/* first/last:\n+\t * Output in case of alloc_acl_counters\n+\t * Input in case of deallocate_acl_counters\n+\t */\n+\tu16 first_cntr;\n+\tu16 last_cntr;\n+};\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@@ -113,6 +127,16 @@ int ice_aq_program_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n \t\t\t     struct ice_sq_cd *cd);\n 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_prgm_acl_prof_xtrct(struct ice_hw *hw, u8 prof_id,\n+\t\t\t    struct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t\t    struct ice_sq_cd *cd);\n+int 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+int ice_aq_alloc_acl_cntrs(struct ice_hw *hw, struct ice_acl_cntrs *cntrs,\n+\t\t\t   struct ice_sq_cd *cd);\n+int ice_aq_dealloc_acl_cntrs(struct ice_hw *hw, struct ice_acl_cntrs *cntrs,\n+\t\t\t     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,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\nindex 1a32400e70bd..b494fa6e0943 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -2150,6 +2150,67 @@ struct ice_aqc_acl_scen {\n \tu8 act_mem_cfg[ICE_AQC_MAX_ACTION_MEMORIES];\n };\n \n+/* Allocate ACL counters (indirect 0x0C16) */\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+\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+\t/* counter bank allocation shall be 0-1 for 'byte and packet counter\n+\t * dual'\n+\t */\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+/* De-allocate ACL counters (direct 0x0C17) */\n+struct ice_aqc_acl_dealloc_counters {\n+\t__le16 first_counter;\n+\t__le16 last_counter;\n+\t/* single/dual */\n+\tu8 counters_type;\n+\tu8 bank_alloc;\n+\tu8 reserved[10];\n+};\n+\n /* Program ACL actionpair (indirect 0x0C1C) */\n struct ice_aqc_acl_actpair {\n \tu8 act_mem_index;\n@@ -2161,6 +2222,8 @@ struct ice_aqc_acl_actpair {\n \t__le32 addr_low;\n };\n \n+#define ICE_RX_PKT_DROP_DROP 0x1\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@@ -2177,13 +2240,59 @@ struct ice_aqc_actpair {\n \tstruct ice_acl_act_entry act[ICE_ACL_NUM_ACT_PER_ACT_PAIR];\n };\n \n-/* The first byte of the byte selection base is reserved to keep the\n- * first byte of the field vector where the packet direction info is\n- * available. Thus we should start at index 1 of the field vector to\n- * map its entries to the byte selection base.\n- */\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+\n #define ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS\t\t30\n+#define ICE_AQC_ACL_PROF_WORD_SEL_ELEMS\t\t32\n+#define ICE_AQC_ACL_PROF_DWORD_SEL_ELEMS\t15\n+#define ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS\t8\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/* 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+\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+\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+\tu8 dword_selection[ICE_AQC_ACL_PROF_DWORD_SEL_ELEMS];\n+\t/* Scenario numbers for individual Physical Function's */\n+\tu8 pf_scenario_num[ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS];\n+};\n+\n+/* Program ACL profile extraction (indirect 0x0C1D)\n+ * Program ACL profile ranges (indirect 0x0C1E)\n+ * Query ACL profile (indirect 0x0C21)\n+ * Query ACL profile ranges (indirect 0x0C22)\n+ */\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@@ -2918,9 +3027,13 @@ enum ice_adminq_opc {\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_alloc_acl_counters\t\t\t= 0x0C16,\n+\tice_aqc_opc_dealloc_acl_counters\t\t= 0x0C17,\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_entry\t\t\t= 0x0C20,\n+\tice_aqc_opc_query_acl_prof\t\t\t= 0x0C21,\n \tice_aqc_opc_query_acl_scen\t\t\t= 0x0C23,\n \n \t/* Tx queue handling commands/events */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\nindex ee5d9f9c9d53..edb98afe200b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.h\n@@ -8,6 +8,8 @@\n \n #define ICE_FDIR_REG_SET_SIZE\t4\n \n+int ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off,\n+\t\tu16 len);\n int\n ice_acquire_change_lock(struct ice_hw *hw, enum ice_aq_res_access_type access);\n void ice_release_change_lock(struct ice_hw *hw);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.h b/drivers/net/ethernet/intel/ice/ice_flow.h\nindex ff6af6589862..53456d48f6ae 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.h\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.h\n@@ -452,17 +452,23 @@ struct ice_flow_seg_info {\n \tstruct ice_flow_seg_fld_raw raws[ICE_FLOW_SEG_RAW_FLD_MAX];\n };\n \n+#define ICE_FLOW_ACL_MAX_NUM_ACT\t2\n /* This structure describes a flow entry, and is tracked only in this file */\n struct ice_flow_entry {\n \tstruct list_head l_entry;\n \n \tu64 id;\n \tstruct ice_flow_prof *prof;\n+\t/* Action list */\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+\tu8 acts_cnt;\n };\n \n #define ICE_FLOW_ENTRY_HNDL(e)\t((u64)(uintptr_t)e)\n@@ -535,7 +541,8 @@ ice_flow_set_parser_prof(struct ice_hw *hw, u16 dest_vsi, u16 fdir_vsi,\n int\n 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, u64 *entry_h);\n+\t\t   void *data, struct ice_flow_action *acts, u8 acts_cnt,\n+\t\t   u64 *entry_h);\n int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h);\n void\n ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h\nindex 185672c7e17d..7010afb787c3 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h\n+++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h\n@@ -312,6 +312,8 @@ enum ice_flex_mdid_pkt_flags {\n enum ice_flex_rx_mdid {\n \tICE_RX_MDID_FLOW_ID_LOWER\t= 5,\n \tICE_RX_MDID_FLOW_ID_HIGH,\n+\tICE_MDID_RX_PKT_DROP\t\t= 8,\n+\tICE_MDID_RX_DST_Q\t\t= 12,\n \tICE_RX_MDID_SRC_VSI\t\t= 19,\n \tICE_RX_MDID_HASH_LOW\t\t= 56,\n \tICE_RX_MDID_HASH_HIGH,\n@@ -320,6 +322,7 @@ enum ice_flex_rx_mdid {\n /* Rx/Tx Flag64 packet flag bits */\n enum ice_flg64_bits {\n \tICE_FLG_PKT_DSI\t\t= 0,\n+\tICE_FLG_PKT_DIR\t\t= 4,\n \tICE_FLG_EVLAN_x8100\t= 14,\n \tICE_FLG_EVLAN_x9100,\n \tICE_FLG_VLAN_x8100,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl.c b/drivers/net/ethernet/intel/ice/ice_acl.c\nindex 81bddac8d0a2..837adbda14e0 100644\n--- a/drivers/net/ethernet/intel/ice/ice_acl.c\n+++ b/drivers/net/ethernet/intel/ice/ice_acl.c\n@@ -135,6 +135,189 @@ int ice_aq_program_actpair(struct ice_hw *hw, u8 act_mem_idx, u16 act_entry_idx,\n \treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n }\n \n+/**\n+ * ice_acl_prof_aq_send - send 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+ * Return: 0 on success, negative on error\n+ */\n+static int ice_acl_prof_aq_send(struct ice_hw *hw, u16 opc, u8 prof_id,\n+\t\t\t\tstruct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t\t\tstruct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_profile *cmd;\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, opc);\n+\tcmd = libie_aq_raw(&desc);\n+\tcmd->profile_id = prof_id;\n+\n+\tif (opc == ice_aqc_opc_program_acl_prof_extraction)\n+\t\tdesc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_prgm_acl_prof_xtrct - 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+ * Program ACL profile extraction (indirect 0x0C1D)\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int ice_prgm_acl_prof_xtrct(struct ice_hw *hw, u8 prof_id,\n+\t\t\t    struct ice_aqc_acl_prof_generic_frmt *buf,\n+\t\t\t    struct 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+ * Query ACL profile (indirect 0x0C21)\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int 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+ * Return: 0 on success, negative on error\n+ */\n+static int ice_aq_acl_cntrs_chk_params(struct ice_acl_cntrs *cntrs)\n+{\n+\tint err = 0;\n+\n+\tif (!cntrs->amount)\n+\t\treturn -EINVAL;\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\terr = -EIO;\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\terr = -EIO;\n+\t\tbreak;\n+\tdefault:\n+\t\terr = -EINVAL;\n+\t}\n+\n+\treturn err;\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+ * Allocate ACL counters (indirect 0x0C16). 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+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_alloc_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_alloc_counters *cmd;\n+\tu16 first_cntr, last_cntr;\n+\tstruct libie_aq_desc desc;\n+\tint err;\n+\n+\terr = ice_aq_acl_cntrs_chk_params(cntrs);\n+\tif (err)\n+\t\treturn err;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_alloc_acl_counters);\n+\tcmd = libie_aq_raw(&desc);\n+\tcmd->counter_amount = cntrs->amount;\n+\tcmd->counters_type = cntrs->type;\n+\tcmd->bank_alloc = cntrs->bank;\n+\n+\terr = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);\n+\tif (err)\n+\t\treturn err;\n+\n+\tfirst_cntr = le16_to_cpu(cmd->ops.resp.first_counter);\n+\tlast_cntr = le16_to_cpu(cmd->ops.resp.last_counter);\n+\n+\tif (first_cntr == ICE_AQC_ACL_ALLOC_CNT_INVAL ||\n+\t    last_cntr == ICE_AQC_ACL_ALLOC_CNT_INVAL)\n+\t\treturn -EIO;\n+\n+\tcntrs->first_cntr = first_cntr;\n+\tcntrs->last_cntr = last_cntr;\n+\n+\treturn 0;\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+ * De-allocate ACL counters (direct 0x0C17)\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int 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 libie_aq_desc desc;\n+\tint err;\n+\n+\terr = ice_aq_acl_cntrs_chk_params(cntrs);\n+\tif (err)\n+\t\treturn err;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_counters);\n+\tcmd = libie_aq_raw(&desc);\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_alloc_acl_scen - allocate ACL scenario\n  * @hw: pointer to the HW struct\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl_main.c b/drivers/net/ethernet/intel/ice/ice_acl_main.c\nindex 841e4d567ff2..53cca0526756 100644\n--- a/drivers/net/ethernet/intel/ice/ice_acl_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_acl_main.c\n@@ -5,6 +5,9 @@\n #include \"ice_lib.h\"\n #include \"ice_acl_main.h\"\n \n+/* Default ACL Action priority */\n+#define ICE_ACL_ACT_PRIO\t3\n+\n /* Number of action */\n #define ICE_ACL_NUM_ACT\t\t1\n \n@@ -218,12 +221,69 @@ static int ice_acl_prof_add_ethtool(struct ice_pf *pf,\n  */\n int ice_acl_add_rule_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)\n {\n+\tstruct ice_flow_action acts[ICE_ACL_NUM_ACT];\n \tstruct ethtool_rx_flow_spec *fsp;\n+\tstruct ice_fd_hw_prof *hw_prof;\n+\tstruct ice_ntuple_fltr *input;\n+\tenum ice_fltr_ptype flow;\n+\tstruct device *dev;\n \tstruct ice_pf *pf;\n+\tstruct ice_hw *hw;\n+\tu64 entry_h = 0;\n+\tint err;\n \n \tpf = vsi->back;\n+\thw = &pf->hw;\n+\tdev = ice_pf_to_dev(pf);\n \n \tfsp = (struct ethtool_rx_flow_spec *)&cmd->fs;\n \n-\treturn ice_acl_prof_add_ethtool(pf, fsp);\n+\terr = ice_acl_prof_add_ethtool(pf, fsp);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* Add new rule */\n+\tinput = kzalloc_obj(*input);\n+\tif (!input)\n+\t\treturn -ENOMEM;\n+\n+\terr = ice_ntuple_set_input_set(vsi, ICE_BLK_ACL, fsp, input);\n+\tif (err)\n+\t\tgoto free_input;\n+\n+\tmemset(&acts, 0, sizeof(acts));\n+\tif (fsp->ring_cookie == RX_CLS_FLOW_DISC) {\n+\t\tacts[0].type = ICE_FLOW_ACT_DROP;\n+\t\tacts[0].data.acl_act.mdid = ICE_MDID_RX_PKT_DROP;\n+\t\tacts[0].data.acl_act.prio = ICE_ACL_ACT_PRIO;\n+\t\tacts[0].data.acl_act.value = cpu_to_le16(ICE_RX_PKT_DROP_DROP);\n+\t} else {\n+\t\tacts[0].type = ICE_FLOW_ACT_FWD_QUEUE;\n+\t\tacts[0].data.acl_act.mdid = ICE_MDID_RX_DST_Q;\n+\t\tacts[0].data.acl_act.prio = ICE_ACL_ACT_PRIO;\n+\t\tacts[0].data.acl_act.value = cpu_to_le16(input->q_index);\n+\t}\n+\n+\tflow = ice_ethtool_flow_to_fltr(fsp->flow_type & ~FLOW_EXT);\n+\thw_prof = hw->acl_prof[flow];\n+\n+\terr = ice_flow_add_entry(hw, ICE_BLK_ACL, hw_prof->prof_id[0],\n+\t\t\t\t fsp->location, vsi->idx, ICE_FLOW_PRIO_NORMAL,\n+\t\t\t\t input, acts, ICE_ACL_NUM_ACT, &entry_h);\n+\tif (err) {\n+\t\tdev_err(dev, \"Could not add flow entry %d\\n\", flow);\n+\t\tgoto free_input;\n+\t}\n+\n+\tif (!hw_prof->cnt || vsi->idx != hw_prof->vsi_h[hw_prof->cnt - 1]) {\n+\t\thw_prof->vsi_h[hw_prof->cnt] = vsi->idx;\n+\t\thw_prof->entry_h[hw_prof->cnt++][0] = entry_h;\n+\t}\n+\n+\treturn 0;\n+\n+free_input:\n+\tkfree(input);\n+\n+\treturn err;\n }\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c b/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c\nindex b5a841732b58..3e79c0bf40f4 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c\n@@ -486,7 +486,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw)\n \t\t\t\t\t\t\t prof->vsi_h[0],\n \t\t\t\t\t\t\t prof->vsi_h[j],\n \t\t\t\t\t\t\t prio, prof->fdir_seg,\n-\t\t\t\t\t\t\t &entry_h);\n+\t\t\t\t\t\t\t NULL, 0, &entry_h);\n \t\t\t\tif (err) {\n \t\t\t\t\tdev_err(ice_hw_to_dev(hw), \"Could not replay Flow Director, flow type %d\\n\",\n \t\t\t\t\t\tflow);\n@@ -719,12 +719,12 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,\n \t\treturn err;\n \terr = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx,\n \t\t\t\t main_vsi->idx, ICE_FLOW_PRIO_NORMAL,\n-\t\t\t\t seg, &entry1_h);\n+\t\t\t\t seg, NULL, 0, &entry1_h);\n \tif (err)\n \t\tgoto err_prof;\n \terr = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx,\n \t\t\t\t ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL,\n-\t\t\t\t seg, &entry2_h);\n+\t\t\t\t seg, NULL, 0, &entry2_h);\n \tif (err)\n \t\tgoto err_entry;\n \n@@ -748,7 +748,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,\n \t\tvsi_h = main_vsi->tc_map_vsi[idx]->idx;\n \t\terr = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id,\n \t\t\t\t\t main_vsi->idx, vsi_h,\n-\t\t\t\t\t ICE_FLOW_PRIO_NORMAL, seg,\n+\t\t\t\t\t ICE_FLOW_PRIO_NORMAL, seg, NULL, 0,\n \t\t\t\t\t &entry1_h);\n \t\tif (err) {\n \t\t\tdev_err(dev, \"Could not add Channel VSI %d to flow group\\n\",\n@@ -1988,28 +1988,36 @@ ice_update_ring_dest_vsi(struct ice_vsi *vsi, u16 *dest_vsi, u32 *ring)\n }\n \n /**\n- * ice_ntuple_set_input_set - Set the input set for Flow Director\n+ * ice_ntuple_set_input_set - Set the input set for specified block\n  * @vsi: pointer to target VSI\n+ * @blk: filter block to configure\n  * @fsp: pointer to ethtool Rx flow specification\n  * @input: filter structure\n  *\n  * Return: 0 on success, negative on failure\n  */\n-static int\n-ice_ntuple_set_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,\n-\t\t\t struct ice_ntuple_fltr *input)\n+int ice_ntuple_set_input_set(struct ice_vsi *vsi, enum ice_block blk,\n+\t\t\t     struct ethtool_rx_flow_spec *fsp,\n+\t\t\t     struct ice_ntuple_fltr *input)\n {\n \ts16 q_index = ICE_FDIR_NO_QUEUE_IDX;\n+\tint flow_type, flow_mask;\n \tu16 orig_q_index = 0;\n \tstruct ice_pf *pf;\n \tstruct ice_hw *hw;\n-\tint flow_type;\n \tu16 dest_vsi;\n \tu8 dest_ctl;\n \n \tif (!vsi || !fsp || !input)\n \t\treturn -EINVAL;\n \n+\tif (blk == ICE_BLK_FD)\n+\t\tflow_mask = FLOW_EXT;\n+\telse if (blk == ICE_BLK_ACL)\n+\t\tflow_mask = FLOW_MAC_EXT;\n+\telse\n+\t\treturn -EINVAL;\n+\n \tpf = vsi->back;\n \thw = &pf->hw;\n \n@@ -2021,7 +2029,8 @@ ice_ntuple_set_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,\n \t\tu8 vf = ethtool_get_flow_spec_ring_vf(fsp->ring_cookie);\n \n \t\tif (vf) {\n-\t\t\tdev_err(ice_pf_to_dev(pf), \"Failed to add filter. Flow director filters are not supported on VF queues.\\n\");\n+\t\t\tdev_err(ice_pf_to_dev(pf), \"Failed to add filter. %s filters are not supported on VF queues.\\n\",\n+\t\t\t\tblk == ICE_BLK_FD ? \"Flow Director\" : \"ACL\");\n \t\t\treturn -EINVAL;\n \t\t}\n \n@@ -2036,7 +2045,7 @@ ice_ntuple_set_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,\n \n \tinput->fltr_id = fsp->location;\n \tinput->q_index = q_index;\n-\tflow_type = fsp->flow_type & ~FLOW_EXT;\n+\tflow_type = fsp->flow_type & ~flow_mask;\n \n \t/* Record the original queue index as specified by user.\n \t * with channel configuration 'q_index' becomes relative\n@@ -2090,9 +2099,9 @@ ice_ntuple_set_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,\n \tcase TCP_V6_FLOW:\n \tcase UDP_V6_FLOW:\n \tcase SCTP_V6_FLOW:\n-\t\tmemcpy(input->ip.v6.dst_ip, fsp->h_u.usr_ip6_spec.ip6dst,\n+\t\tmemcpy(input->ip.v6.dst_ip, fsp->h_u.tcp_ip6_spec.ip6dst,\n \t\t       sizeof(struct in6_addr));\n-\t\tmemcpy(input->ip.v6.src_ip, fsp->h_u.usr_ip6_spec.ip6src,\n+\t\tmemcpy(input->ip.v6.src_ip, fsp->h_u.tcp_ip6_spec.ip6src,\n \t\t       sizeof(struct in6_addr));\n \t\tinput->ip.v6.dst_port = fsp->h_u.tcp_ip6_spec.pdst;\n \t\tinput->ip.v6.src_port = fsp->h_u.tcp_ip6_spec.psrc;\n@@ -2210,7 +2219,7 @@ int ice_add_ntuple_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)\n \tif (!input)\n \t\treturn -ENOMEM;\n \n-\tret = ice_ntuple_set_input_set(vsi, fsp, input);\n+\tret = ice_ntuple_set_input_set(vsi, ICE_BLK_FD, fsp, input);\n \tif (ret)\n \t\tgoto free_input;\n \ndiff --git a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\nindex d255ffcd5c86..92289b97117a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flex_pipe.c\n@@ -235,9 +235,8 @@ static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max)\n  *\tdc == NULL --> dc mask is all 0's (no don't care bits)\n  *\tnm == NULL --> nm mask is all 0's (no never match bits)\n  */\n-static int\n-ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off,\n-\t    u16 len)\n+int ice_set_key(u8 *key, u16 size, u8 *val, u8 *upd, u8 *dc, u8 *nm, u16 off,\n+\t\tu16 len)\n {\n \tu16 half_size;\n \tu16 i;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_flow.c b/drivers/net/ethernet/intel/ice/ice_flow.c\nindex 440e9fdb6b5b..dce6d2ffcb15 100644\n--- a/drivers/net/ethernet/intel/ice/ice_flow.c\n+++ b/drivers/net/ethernet/intel/ice/ice_flow.c\n@@ -1589,22 +1589,171 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)\n \treturn NULL;\n }\n \n+/**\n+ * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle\n+ * @hw: pointer to the HW struct\n+ * @blk: classification stage\n+ * @prof_id: the profile ID handle\n+ * @hw_prof_id: pointer to variable to return the HW profile ID\n+ *\n+ * Return: 0 on success, negative on failure\n+ */\n+static int ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk,\n+\t\t\t\tu64 prof_id, u8 *hw_prof_id)\n+{\n+\tstruct ice_prof_map *map;\n+\tint err = -ENOENT;\n+\n+\tmutex_lock(&hw->blk[blk].es.prof_map_lock);\n+\n+\tmap = ice_search_prof_id(hw, blk, prof_id);\n+\tif (map) {\n+\t\t*hw_prof_id = map->prof_id;\n+\t\terr = 0;\n+\t}\n+\n+\tmutex_unlock(&hw->blk[blk].es.prof_map_lock);\n+\n+\treturn err;\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+ * @buf: ACL profile buffer\n+ *\n+ * Return: true if at least one PF is associated to the given profile\n+ */\n+static bool\n+ice_flow_acl_is_prof_in_use(const struct ice_aqc_acl_prof_generic_frmt *buf)\n+{\n+\tu8 first = buf->pf_scenario_num[0];\n+\n+\t/* If all PF's associated scenarios are all 0 or all\n+\t * ICE_ACL_INVALID_SCEN for the given profile, then the profile has not\n+\t * been configured yet.\n+\t */\n+\n+\tif (first != 0 && first != ICE_ACL_INVALID_SCEN)\n+\t\treturn true;\n+\n+\tfor (int i = 1; i < ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS; i++) {\n+\t\tif (buf->pf_scenario_num[i] != first)\n+\t\t\treturn true;\n+\t}\n+\n+\treturn false;\n+}\n+\n+/**\n+ * ice_flow_acl_is_cntr_act - check if flow action is a counter action\n+ * @type: action type\n+ *\n+ * Return: true if counter action, false otherwise\n+ */\n+static bool ice_flow_acl_is_cntr_act(enum ice_flow_action_type type)\n+{\n+\treturn type == ICE_FLOW_ACT_CNTR_PKT ||\n+\t       type == ICE_FLOW_ACT_CNTR_BYTES ||\n+\t       type == ICE_FLOW_ACT_CNTR_PKT_BYTES;\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+ * Return: 0 on success, negative on failure\n+ */\n+static int ice_flow_acl_free_act_cntr(struct ice_hw *hw,\n+\t\t\t\t      struct ice_flow_action *acts, u8 acts_cnt)\n+{\n+\tfor (int i = 0; i < acts_cnt; i++) {\n+\t\tif (ice_flow_acl_is_cntr_act(acts[i].type)) {\n+\t\t\tstruct ice_acl_cntrs cntrs = { 0 };\n+\t\t\tint err;\n+\n+\t\t\t/* amount is unused in the dealloc path but the common\n+\t\t\t * parameter check routine wants a value set, as zero\n+\t\t\t * is invalid for the check. Just set it.\n+\t\t\t */\n+\t\t\tcntrs.amount = 1;\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\terr = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL);\n+\t\t\tif (err)\n+\t\t\t\treturn err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile\n+ * @hw: pointer to the hardware structure\n+ * @prof: pointer to flow profile\n+ *\n+ * Disassociate the scenario from the profile for the PF of the VSI.\n+ *\n+ * Return: 0 on success, negative on failure\n+ */\n+static int ice_flow_acl_disassoc_scen(struct ice_hw *hw,\n+\t\t\t\t      struct ice_flow_prof *prof)\n+{\n+\tstruct ice_aqc_acl_prof_generic_frmt buf = {};\n+\tint err = 0;\n+\tu8 prof_id;\n+\n+\terr = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = ice_query_acl_prof(hw, prof_id, &buf, NULL);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* Clear scenario for this PF */\n+\tbuf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN;\n+\treturn ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);\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+ * Return: 0 on success, negative on failure\n  */\n-static int\n-ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,\n-\t\t\tstruct ice_flow_entry *entry)\n+static int ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk,\n+\t\t\t\t   struct ice_flow_entry *entry)\n {\n \tif (!entry)\n \t\treturn -EINVAL;\n \n+\tif (blk == ICE_BLK_ACL) {\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-\tdevm_kfree(ice_hw_to_dev(hw), entry->entry);\n+\tkfree(entry->entry);\n+\tkfree(entry->range_buf);\n+\tkfree(entry->acts);\n \tdevm_kfree(ice_hw_to_dev(hw), entry);\n \n \treturn 0;\n@@ -1729,6 +1878,13 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,\n \t\tmutex_unlock(&prof->entries_lock);\n \t}\n \n+\tif (blk == ICE_BLK_ACL) {\n+\t\t/* Disassociate the scenario from 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+\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@@ -1741,6 +1897,101 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,\n \treturn status;\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+ * Return: 0 on success, negative on failure\n+ */\n+static int\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 src, dst;\n+\n+\tsrc = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ +\n+\t\tinfo->xtrct.disp / BITS_PER_BYTE;\n+\tif (src > U8_MAX)\n+\t\treturn -ERANGE;\n+\n+\tdst = info->entry.val;\n+\tfor (int 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+\treturn 0;\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+ * Return: 0 on success, negative on failure\n+ */\n+static int ice_flow_acl_set_xtrct_seq(struct ice_hw *hw,\n+\t\t\t\t      struct ice_flow_prof *prof)\n+{\n+\tstruct ice_aqc_acl_prof_generic_frmt buf = {};\n+\tstruct ice_flow_fld_info *info;\n+\tu8 prof_id = 0;\n+\tint err;\n+\n+\terr = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (err)\n+\t\treturn err;\n+\n+\terr = ice_query_acl_prof(hw, prof_id, &buf, NULL);\n+\tif (err)\n+\t\treturn err;\n+\n+\tif (!ice_flow_acl_is_prof_in_use(&buf)) {\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\tmemset(&buf, 0, sizeof(buf));\n+\n+\t\tfor (int i = 0; i < prof->segs_cnt; i++) {\n+\t\t\tstruct ice_flow_seg_info *seg = &prof->segs[i];\n+\t\t\tu16 j;\n+\n+\t\t\tfor_each_set_bit(j, (unsigned long *)&seg->match,\n+\t\t\t\t\t ICE_FLOW_FIELD_IDX_MAX) {\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\tinfo->xtrct.idx;\n+\t\t\t\t\tcontinue;\n+\t\t\t\t}\n+\n+\t\t\t\terr = ice_flow_acl_set_xtrct_seq_fld(&buf,\n+\t\t\t\t\t\t\t\t     info);\n+\t\t\t\tif (err)\n+\t\t\t\t\treturn err;\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\terr = ice_flow_acl_set_xtrct_seq_fld(&buf,\n+\t\t\t\t\t\t\t\t     info);\n+\t\t\t\tif (err)\n+\t\t\t\t\treturn err;\n+\t\t\t}\n+\t\t}\n+\n+\t\tmemset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN,\n+\t\t       ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS);\n+\t}\n+\n+\t/* Update the current PF */\n+\tbuf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id;\n+\treturn ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);\n+}\n+\n /**\n  * ice_flow_assoc_prof - associate a VSI with a flow profile\n  * @hw: pointer to the hardware structure\n@@ -1758,6 +2009,12 @@ ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,\n \tint status = 0;\n \n \tif (!test_bit(vsi_handle, prof->vsis)) {\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+\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@@ -1957,6 +2214,333 @@ int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)\n \treturn status;\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 an ACL counter has been allocated.\n+ *\n+ * Return: 0 on success, negative on failure\n+ */\n+static int ice_flow_acl_check_actions(struct ice_hw *hw,\n+\t\t\t\t      struct ice_flow_action *acts, u8 acts_cnt,\n+\t\t\t\t      bool *cnt_alloc)\n+{\n+\tDECLARE_BITMAP(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);\n+\n+\tbitmap_zero(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 -ERANGE;\n+\n+\tfor (int 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 -EINVAL;\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 (test_and_set_bit(acts[i].type, dup_check))\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Checks if ACL counters are needed. */\n+\tfor (int i = 0; i < acts_cnt; i++) {\n+\t\tif (ice_flow_acl_is_cntr_act(acts[i].type)) {\n+\t\t\tstruct ice_acl_cntrs cntrs = { 0 };\n+\t\t\tint err;\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\terr = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL);\n+\t\t\tif (err)\n+\t\t\t\treturn err;\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 0;\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 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info,\n+\t\t\t\t\tu8 *buf, u8 *dontcare, u8 *data)\n+{\n+\tu16 dst, src, mask, 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 (u16 i = 0; i < info->entry.last; i++, 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 || i < 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 (int i = 0; i < disp; i++)\n+\t\t\tdontcare[dst] |= BIT(i);\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 (int i = end_disp; i < BITS_PER_BYTE; i++)\n+\t\t\tdontcare[dst] |= BIT(i);\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+ * Return: 0 on success, negative on failure\n+ */\n+static int ice_flow_acl_frmt_entry(struct ice_hw *hw,\n+\t\t\t\t   struct ice_flow_prof *prof,\n+\t\t\t\t   struct ice_flow_entry *e, u8 *data,\n+\t\t\t\t   struct ice_flow_action *acts, u8 acts_cnt)\n+{\n+\tu8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk,\n+\t\tprof_id;\n+\tstruct ice_aqc_acl_profile_ranges *range_buf = NULL;\n+\tbool cnt_alloc;\n+\tu16 buf_sz;\n+\tint err;\n+\n+\terr = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* Format the result action */\n+\n+\terr = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc);\n+\tif (err)\n+\t\treturn err;\n+\n+\te->acts = kmemdup(acts, acts_cnt * sizeof(*acts), GFP_KERNEL);\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 = kzalloc_objs(*buf, buf_sz);\n+\tif (!buf)\n+\t\tgoto out;\n+\n+\tdontcare = kzalloc_objs(*dontcare, 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 = kzalloc_objs(*key, buf_sz * 2);\n+\tif (!key)\n+\t\tgoto out;\n+\n+\trange_buf = kzalloc_obj(*range_buf);\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+\tmemset(dontcare, 0xff, buf_sz);\n+\n+\tfor (int i = 0; i < prof->segs_cnt; i++) {\n+\t\tstruct ice_flow_seg_info *seg = &prof->segs[i];\n+\t\tu8 j;\n+\n+\t\tfor_each_set_bit(j, (unsigned long *)&seg->match,\n+\t\t\t\t ICE_FLOW_FIELD_IDX_MAX) {\n+\t\t\tstruct ice_flow_fld_info *info = &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+\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\tkfree(range_buf);\n+\t}\n+\n+\terr = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0,\n+\t\t\t  buf_sz);\n+\tif (err)\n+\t\tgoto out;\n+\n+\te->entry = key;\n+\te->entry_sz = buf_sz * 2;\n+\n+out:\n+\tkfree(buf);\n+\tkfree(dontcare);\n+\n+\tif (err) {\n+\t\tkfree(key);\n+\n+\t\tkfree(range_buf);\n+\t\te->range_buf = NULL;\n+\n+\t\tkfree(e->acts);\n+\t\te->acts = NULL;\n+\t\te->acts_cnt = 0;\n+\n+\t\tif (cnt_alloc)\n+\t\t\tice_flow_acl_free_act_cntr(hw, acts, acts_cnt);\n+\t}\n+\n+\treturn err;\n+}\n /**\n  * ice_flow_add_entry - Add a flow entry\n  * @hw: pointer to the HW struct\n@@ -1966,17 +2550,23 @@ int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)\n  * @vsi_handle: software VSI handle for the flow entry\n  * @prio: priority of 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  * @entry_h: pointer to buffer that receives the new flow entry's handle\n  */\n-int\n-ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n-\t\t   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,\n-\t\t   void *data, u64 *entry_h)\n+int ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n+\t\t       u64 entry_id, u16 vsi_handle,\n+\t\t       enum ice_flow_priority prio, void *data,\n+\t\t       struct ice_flow_action *acts, u8 acts_cnt, u64 *entry_h)\n {\n \tstruct ice_flow_entry *e = NULL;\n \tstruct ice_flow_prof *prof;\n \tint status;\n \n+\t/* ACL entries must indicate an action */\n+\tif (blk == ICE_BLK_ACL && (!acts || !acts_cnt))\n+\t\treturn -EINVAL;\n+\n \t/* No flow entry data is expected for RSS */\n \tif (!entry_h || (!data && blk != ICE_BLK_RSS))\n \t\treturn -EINVAL;\n@@ -2013,20 +2603,32 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,\n \tcase ICE_BLK_FD:\n \tcase ICE_BLK_RSS:\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+\t\tbreak;\n \tdefault:\n \t\tstatus = -EOPNOTSUPP;\n \t\tgoto out;\n \t}\n \n-\tmutex_lock(&prof->entries_lock);\n-\tlist_add(&e->l_entry, &prof->entries);\n-\tmutex_unlock(&prof->entries_lock);\n+\tif (blk != ICE_BLK_ACL) {\n+\t\t/* ACL will handle the entry management */\n+\t\tmutex_lock(&prof->entries_lock);\n+\t\tlist_add(&e->l_entry, &prof->entries);\n+\t\tmutex_unlock(&prof->entries_lock);\n+\t}\n \n \t*entry_h = ICE_FLOW_ENTRY_HNDL(e);\n \n out:\n \tif (status && e) {\n-\t\tdevm_kfree(ice_hw_to_dev(hw), e->entry);\n+\t\tkfree(e->entry);\n+\t\tkfree(e->range_buf);\n+\t\tkfree(e->acts);\n \t\tdevm_kfree(ice_hw_to_dev(hw), e);\n \t}\n \ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex 59036a22ba91..02be10710687 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -8658,7 +8658,7 @@ static int ice_add_vsi_to_fdir(struct ice_pf *pf, struct ice_vsi *vsi)\n \t\t\t\t\t\t    prof->prof_id[tun],\n \t\t\t\t\t\t    prof->vsi_h[0], vsi->idx,\n \t\t\t\t\t\t    prio, prof->fdir_seg[tun],\n-\t\t\t\t\t\t    &entry_h);\n+\t\t\t\t\t\t    NULL, 0, &entry_h);\n \t\t\tif (status) {\n \t\t\t\tdev_err(dev, \"channel VSI idx %d, not able to add to group %d\\n\",\n \t\t\t\t\tvsi->idx, flow);\ndiff --git a/drivers/net/ethernet/intel/ice/virt/fdir.c b/drivers/net/ethernet/intel/ice/virt/fdir.c\nindex eca9eda04f31..38e68d3d030c 100644\n--- a/drivers/net/ethernet/intel/ice/virt/fdir.c\n+++ b/drivers/net/ethernet/intel/ice/virt/fdir.c\n@@ -688,7 +688,7 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow,\n \n \tret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx,\n \t\t\t\t vf_vsi->idx, ICE_FLOW_PRIO_NORMAL,\n-\t\t\t\t seg, &entry1_h);\n+\t\t\t\t seg, NULL, 0, &entry1_h);\n \tif (ret) {\n \t\tdev_dbg(dev, \"Could not add flow 0x%x VSI entry for VF %d\\n\",\n \t\t\tflow, vf->vf_id);\n@@ -697,7 +697,7 @@ ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow,\n \n \tret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx,\n \t\t\t\t ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL,\n-\t\t\t\t seg, &entry2_h);\n+\t\t\t\t seg, NULL, 0, &entry2_h);\n \tif (ret) {\n \t\tdev_dbg(dev,\n \t\t\t\"Could not add flow 0x%x Ctrl VSI entry for VF %d\\n\",\n",
    "prefixes": [
        "iwl-next",
        "v2",
        "07/10"
    ]
}