{"id":2221409,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2221409/?format=json","project":{"id":46,"url":"http://patchwork.ozlabs.org/api/1.0/projects/46/?format=json","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-3-marcin.szycik@linux.intel.com>","date":"2026-04-09T11:59:55","name":"[iwl-next,v2,02/10] ice: initialize ACL table","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"14b60534c0e6ba325072939fcde8a1c9f2d1846a","submitter":{"id":82782,"url":"http://patchwork.ozlabs.org/api/1.0/people/82782/?format=json","name":"Marcin Szycik","email":"marcin.szycik@linux.intel.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260409120003.2719-3-marcin.szycik@linux.intel.com/mbox/","series":[{"id":499287,"url":"http://patchwork.ozlabs.org/api/1.0/series/499287/?format=json","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/2221409/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=Pxx2X/B6;\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 4fs0RG2Z46z1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 23:00:42 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 08CA540D49;\n\tThu,  9 Apr 2026 13:00:39 +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 7843CemlOKP1; Thu,  9 Apr 2026 13:00:34 +0000 (UTC)","from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 7AF0D41081;\n\tThu,  9 Apr 2026 13:00:34 +0000 (UTC)","from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists1.osuosl.org (Postfix) with ESMTP id EF77E1F6\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:30 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 9498A81B14\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 CrYM7mz8HkF1 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 CE07281A6F\n for <intel-wired-lan@lists.osuosl.org>; Thu,  9 Apr 2026 13:00:27 +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:18 -0700","from irvmail002.ir.intel.com ([10.43.11.120])\n by orviesa002.jf.intel.com with ESMTP; 09 Apr 2026 06:00:13 -0700","from gond.igk.intel.com (gond.igk.intel.com [10.123.220.52])\n by irvmail002.ir.intel.com (Postfix) with ESMTP id 3D6012FC5B;\n Thu,  9 Apr 2026 14:00:12 +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 7AF0D41081","OpenDKIM Filter v2.11.0 smtp1.osuosl.org CE07281A6F"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1775739634;\n\tbh=V9D72uGrrXCeuJYL/1JUDsRf9qaxen2eun+SupZTbMM=;\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=Pxx2X/B6hF+zeURZUBrQt9LbuOCDZ04OGk+OFhfZ5KZx8neZRGUQ0Wn6WfMOI77OE\n\t yY9p42SKTPxLlYS/XbCFKBniZLAjyaXNTGU5gHl3vTISybfumsfA4wCzN9YdILloDl\n\t Xyx+sxCLAXBCnXRF3YmhQUx3nkb2oVF9E/gC7kBLrBar9LHCmgmcZnEu330FTEdezs\n\t Ksh/noXxzMCZfsezljQP+eaZD3H7Yetyx8ObZhaPIKj9KHvStdWf5K/ZUqXo1RYrze\n\t 7OLfwnt6ZajzcSId/gh0vCQGz2eHYKc98yNbdlhXu5NMSIfSbRBP/Crwlzzv4xpjKL\n\t 96uH0DQmlzntw==","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 CE07281A6F","X-CSE-ConnectionGUID":["ZM88ABktTCa3qeZ93SBuMA==","bX5iJgHmQAObfvH915ZJlQ=="],"X-CSE-MsgGUID":["Shtbk3X9R9uJd/MdzTqidw==","JNi9HwThT7KyIlCmhmTCAw=="],"X-IronPort-AV":["E=McAfee;i=\"6800,10657,11753\"; a=\"75777529\"","E=Sophos;i=\"6.23,169,1770624000\"; d=\"scan'208\";a=\"75777529\"","E=Sophos;i=\"6.23,169,1770624000\"; d=\"scan'208\";a=\"259208119\""],"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:55 +0200","Message-ID":"<20260409120003.2719-3-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=aKOa4GX6ibYH2Iyp9M5M79t21MCvHNdYrgsQpgRQ3nM=;\n b=GRYTIZgUbUd6mguPACv6r4XFfd7WSTNwiarzuNJquZx7gQ0tpJZfUVOL\n 7su/h01RcCMhZYVs6SZMUgLyp0UT2/hD3UgeQJo4UN1Nb8EuDASk6sSyQ\n 3VPebTxByim3aCQ9ERVSJ0AumIV+m87OJBLi6Zl8NUCfz+q1d2i+IYknm\n ZnvgbgNbhlgh9fyTGKppv/DBYrWy6TROG3vYnpcgrWkp4JYVDpW1glCD7\n Nr0KvmgrVgamGx3mOTtzm44JlXnvCNp98SVJih6mCmTVDzkyXAbhSYYyl\n XcjW4sYIQyl20TJtJJ8g/ljLxBHiQvhMBczP5P69+bhvn0c01uhwf5gX3\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,\n unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256\n header.s=Intel header.b=GRYTIZgU"],"Subject":"[Intel-wired-lan] [PATCH iwl-next v2 02/10] ice: initialize ACL\n table","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\nE8xx hardware provides a Ternary Classifier block for implementing\nfunctions such as ACL (Access Control List). In this series it's simply\nreferred to as \"ACL\".\n\nACL filtering can be utilized to expand support of ntuple rules by allowing\nmask values to be specified for redirect to queue or drop.\n\nImplement support for specifying the 'm' value of ethtool ntuple command\nfor currently supported fields (src-ip, dst-ip, src-port, and dst-port).\n\nFor example:\n  ethtool -N eth0 flow-type tcp4 dst-port 8880 m 0x00ff action 10\nor\n  ethtool -N eth0 flow-type tcp4 src-ip 192.168.0.55 m 0.0.0.255 action -1\n\nAt this time the following flow-types support mask values: tcp4, udp4,\nsctp4, and ip4.\n\nBegin implementation of ACL filters by setting up structures, AdminQ\ncommands, and allocation of the ACL table in the hardware.\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: 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* Return -ERANGE in one branch in ice_aq_alloc_acl_tbl() to differenciate error\n  codes\n* Use GENMASK() for ICE_AQ_VSI_ACL_DEF_RX_*_M\n* Use plain alloc/kfree for hw->acl_tbl\n* Call ice_deinit_acl() unconditionally because ICE_FLAG_FD_ENA can be\n  disabled during operation\n* ice_acl_init_tbl(): remove first/last variables\n* Merge ice_aq_acl_entry() into ice_aq_program_acl_entry() and\n  ice_aq_actpair_p_q() into ice_aq_program_actpair() - wrappers with one user\n  make no sense\n* Rename ICE_AQC_ALLOC_ID_LESS_THAN_4K to more sensible ICE_AQC_ALLOC_ID_4K\n* Reorder members of struct ice_acl_tbl to minimize holes\n* Remove ICE_AQ_VSI_ACL_DEF_RX_*_S - will be unused after switching to\n  FIELD_PREP() in \"ice: program ACL entry\"\n* Replace memset() with = {} in ice_init_acl()\n---\n drivers/net/ethernet/intel/ice/Makefile       |   2 +\n drivers/net/ethernet/intel/ice/ice.h          |   3 +\n drivers/net/ethernet/intel/ice/ice_acl.h      | 117 +++++++\n .../net/ethernet/intel/ice/ice_adminq_cmd.h   | 208 +++++++++++-\n drivers/net/ethernet/intel/ice/ice_type.h     |   3 +\n drivers/net/ethernet/intel/ice/ice_acl.c      | 136 ++++++++\n drivers/net/ethernet/intel/ice/ice_acl_ctrl.c | 302 ++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_main.c     |  49 +++\n 8 files changed, 818 insertions(+), 2 deletions(-)\n create mode 100644 drivers/net/ethernet/intel/ice/ice_acl.h\n create mode 100644 drivers/net/ethernet/intel/ice/ice_acl.c\n create mode 100644 drivers/net/ethernet/intel/ice/ice_acl_ctrl.c","diff":"diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile\nindex c310c209bc7d..6afe7be056ba 100644\n--- a/drivers/net/ethernet/intel/ice/Makefile\n+++ b/drivers/net/ethernet/intel/ice/Makefile\n@@ -25,6 +25,8 @@ ice-y := ice_main.o\t\\\n \t ice_vsi_vlan_lib.o \\\n \t ice_fdir.o\t\\\n \t ice_ethtool_ntuple.o \\\n+\t ice_acl.o\t\\\n+\t ice_acl_ctrl.o\t\\\n \t ice_vlan_mode.o \\\n \t ice_flex_pipe.o \\\n \t ice_flow.o\t\\\ndiff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex ea1bddfa739d..3a51a033296c 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -157,6 +157,9 @@\n #define ICE_SWITCH_FLTR_PRIO_VSI\t5\n #define ICE_SWITCH_FLTR_PRIO_QGRP\tICE_SWITCH_FLTR_PRIO_VSI\n \n+#define ICE_ACL_ENTIRE_SLICE\t1\n+#define ICE_ACL_HALF_SLICE\t2\n+\n /* Macro for each VSI in a PF */\n #define ice_for_each_vsi(pf, i) \\\n \tfor ((i) = 0; (i) < (pf)->num_alloc_vsi; (i)++)\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl.h b/drivers/net/ethernet/intel/ice/ice_acl.h\nnew file mode 100644\nindex 000000000000..bb836f23d65e\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_acl.h\n@@ -0,0 +1,117 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (C) 2018-2026, Intel Corporation. */\n+\n+#ifndef _ICE_ACL_H_\n+#define _ICE_ACL_H_\n+\n+#include \"ice_common.h\"\n+\n+#define ICE_ACL_TBL_PARAMS_DEP_TBLS_MAX\t15\n+struct ice_acl_tbl_params {\n+\tu16 width;\t/* Select/match bytes */\n+\tu16 depth;\t/* Number of entries */\n+\tu16 dep_tbls[ICE_ACL_TBL_PARAMS_DEP_TBLS_MAX];\n+\tu8 entry_act_pairs;\t/* Action pairs per entry */\n+\tu8 concurr;\t\t/* Concurrent table lookup enable */\n+};\n+\n+#define ICE_ACL_ACT_MEM_ACT_MEM_INVAL\t0xff\n+struct ice_acl_act_mem {\n+\tu8 act_mem;\n+\tu8 member_of_tcam;\n+};\n+\n+struct ice_acl_tbl {\n+\t/* TCAM configuration */\n+\tu8 first_tcam;\n+\tu8 last_tcam;\n+\tu16 first_entry; /* Index of the first entry in the first TCAM */\n+\tu16 last_entry; /* Index of the last entry in the last TCAM */\n+\tu16 id;\n+\n+\t/* List of active scenarios */\n+\tstruct list_head scens;\n+\n+\tstruct ice_acl_tbl_params info;\n+\tstruct ice_acl_act_mem act_mems[ICE_AQC_MAX_ACTION_MEMORIES];\n+\n+\t/* Keep track of available 64-entry chunks in TCAMs */\n+\tDECLARE_BITMAP(avail, ICE_AQC_ACL_ALLOC_UNITS);\n+};\n+\n+enum ice_acl_entry_prio {\n+\tICE_ACL_PRIO_LOW = 0,\n+\tICE_ACL_PRIO_NORMAL,\n+\tICE_ACL_PRIO_HIGH,\n+\tICE_ACL_MAX_PRIO\n+};\n+\n+#define ICE_ACL_SCEN_MIN_WIDTH\t0x3\n+#define ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM\t0x2\n+#define ICE_ACL_SCEN_PID_IDX_IN_TCAM\t\t0x3\n+#define ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM\t0x4\n+/* Scenario structure\n+ * A scenario is a logical partition within an ACL table. It can span more\n+ * than one TCAM in cascade mode to support select/mask key widths larger\n+ * than the width of a TCAM. It can also span more than one TCAM in stacked\n+ * mode to support larger number of entries than what a TCAM can hold. It is\n+ * used to select values from selection bases (field vectors holding extract\n+ * protocol header fields) to form lookup keys, and to associate action memory\n+ * banks to the TCAMs used.\n+ */\n+struct ice_acl_scen {\n+\tstruct list_head list_entry;\n+\t/* If nth bit of act_mem_bitmap is set, then nth action memory will\n+\t * participate in this scenario\n+\t */\n+\tDECLARE_BITMAP(act_mem_bitmap, ICE_AQC_MAX_ACTION_MEMORIES);\n+\tu16 first_idx[ICE_ACL_MAX_PRIO];\n+\tu16 last_idx[ICE_ACL_MAX_PRIO];\n+\n+\tu16 id;\n+\tu16 start;\t/* Number of entry from the start of the parent table */\n+\tu16 width;\t/* Number of select/mask bytes */\n+\tu16 num_entry;\t/* Number of scenario entry */\n+\tu16 end;\t/* Last addressable entry from start of table */\n+\tu8 eff_width;\t/* Available width in bytes to match */\n+\tu8 pid_idx;\t/* Byte index used to match profile ID */\n+\tu8 rng_chk_idx;\t/* Byte index used to match range checkers result */\n+\tu8 pkt_dir_idx;\t/* Byte index used to match packet direction */\n+};\n+\n+/* Input fields needed to allocate ACL table */\n+struct ice_acl_alloc_tbl {\n+\t/* Table's width in number of bytes matched */\n+\tu16 width;\n+\t/* Table's depth in number of entries. */\n+\tu16 depth;\n+\tu8 num_dependent_alloc_ids;\n+\t/* true for concurrent table type */\n+\tu8 concurr;\n+\n+\t/* Amount of action pairs per table entry. Minimal valid\n+\t * value for this field is 1 (e.g. single pair of actions)\n+\t */\n+\tu8 act_pairs_per_entry;\n+\tunion {\n+\t\tstruct ice_aqc_acl_alloc_table_data data_buf;\n+\t\tstruct ice_aqc_acl_generic resp_buf;\n+\t} buf;\n+};\n+\n+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_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+\t\t\t   struct ice_aqc_acl_generic *buf,\n+\t\t\t   struct ice_sq_cd *cd);\n+int ice_aq_program_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n+\t\t\t     struct ice_aqc_acl_data *buf,\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_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+#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 07fc72da347c..87f215f47072 100644\n--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h\n@@ -303,6 +303,7 @@ struct ice_aqc_vsi_props {\n #define ICE_AQ_VSI_PROP_RXQ_MAP_VALID\t\tBIT(6)\n #define ICE_AQ_VSI_PROP_Q_OPT_VALID\t\tBIT(7)\n #define ICE_AQ_VSI_PROP_OUTER_UP_VALID\t\tBIT(8)\n+#define ICE_AQ_VSI_PROP_ACL_VALID\t\tBIT(10)\n #define ICE_AQ_VSI_PROP_FLOW_DIR_VALID\t\tBIT(11)\n #define ICE_AQ_VSI_PROP_PASID_VALID\t\tBIT(12)\n \t/* switch section */\n@@ -423,8 +424,10 @@ struct ice_aqc_vsi_props {\n \tu8 q_opt_reserved[3];\n \t/* outer up section */\n \t__le32 outer_up_table; /* same structure and defines as ingress tbl */\n-\t/* section 10 */\n-\t__le16 sect_10_reserved;\n+\t/* ACL section */\n+\t__le16 acl_def_act;\n+#define ICE_AQ_VSI_ACL_DEF_RX_PROF_M\tGENMASK(3, 0)\n+#define ICE_AQ_VSI_ACL_DEF_RX_TABLE_M\tGENMASK(7, 4)\n \t/* flow director section */\n \t__le16 fd_options;\n #define ICE_AQ_VSI_FD_ENABLE\t\t\tBIT(0)\n@@ -1976,6 +1979,199 @@ struct ice_aqc_neigh_dev_req {\n \t__le32 addr_low;\n };\n \n+/* Allocate ACL table (indirect 0x0C10) */\n+#define ICE_AQC_ACL_KEY_WIDTH_BYTES\t5\n+#define ICE_AQC_ACL_TCAM_DEPTH\t\t512\n+#define ICE_ACL_ENTRY_ALLOC_UNIT\t64\n+#define ICE_AQC_MAX_CONCURRENT_ACL_TBL\t15\n+#define ICE_AQC_MAX_ACTION_MEMORIES\t20\n+#define ICE_AQC_ACL_SLICES\t\t16\n+#define ICE_AQC_ALLOC_ID_4K\t\t0x1000\n+/* The ACL block supports up to 8 actions per a single output. */\n+#define ICE_AQC_TBL_MAX_ACTION_PAIRS\t4\n+\n+#define ICE_AQC_MAX_TCAM_ALLOC_UNITS\t(ICE_AQC_ACL_TCAM_DEPTH / \\\n+\t\t\t\t\t ICE_ACL_ENTRY_ALLOC_UNIT)\n+#define ICE_AQC_ACL_ALLOC_UNITS\t\t(ICE_AQC_ACL_SLICES * \\\n+\t\t\t\t\t ICE_AQC_MAX_TCAM_ALLOC_UNITS)\n+\n+struct ice_aqc_acl_alloc_table {\n+\t__le16 table_width;\n+\t__le16 table_depth;\n+\tu8 act_pairs_per_entry;\n+\tu8 table_type;\n+\t__le16 reserved;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+#define ICE_AQC_CONCURR_ID_INVALID\t0xffff\n+/* Allocate ACL table command buffer format */\n+struct ice_aqc_acl_alloc_table_data {\n+\t/* Dependent table AllocIDs. Each word in this 15 word array specifies\n+\t * a dependent table AllocID according to the amount specified in the\n+\t * \"table_type\" field. All unused words shall be set to\n+\t * ICE_AQC_CONCURR_ID_INVALID\n+\t */\n+\t__le16 alloc_ids[ICE_AQC_MAX_CONCURRENT_ACL_TBL];\n+};\n+\n+/* Deallocate ACL table (indirect 0x0C11) */\n+\n+/* Following structure is common and used in case of deallocation\n+ * of ACL table and action-pair\n+ */\n+struct ice_aqc_acl_tbl_actpair {\n+\t__le16 alloc_id;\n+\tu8 reserved[6];\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* This response structure is same in case of alloc/dealloc table,\n+ * alloc/dealloc action-pair\n+ */\n+struct ice_aqc_acl_generic {\n+\t/* if alloc_id is below 0x1000 then allocation failed due to\n+\t * unavailable resources, else this is set by FW to identify\n+\t * table allocation\n+\t */\n+\t__le16 alloc_id;\n+\n+\tunion {\n+\t\t/* to be used only in case of alloc/dealloc table */\n+\t\tstruct {\n+\t\t\t/* Set to 0xFF for a failed allocation */\n+\t\t\tu8 first_tcam;\n+\t\t\t/* This index shall be set to the value of first_tcam\n+\t\t\t * for single TCAM block allocation, otherwise set to\n+\t\t\t * 0xFF for a failed allocation.\n+\t\t\t */\n+\t\t\tu8 last_tcam;\n+\t\t} table;\n+\t\t/* reserved in case of alloc/dealloc action-pair */\n+\t\tstruct {\n+\t\t\t__le16 reserved;\n+\t\t} act_pair;\n+\t} ops;\n+\n+\t/* index of first entry (in both TCAM and action memories),\n+\t * otherwise set to 0xFF for a failed allocation\n+\t */\n+\t__le16 first_entry;\n+\t/* index of last entry (in both TCAM and action memories),\n+\t * otherwise set to 0xFF for a failed allocation\n+\t */\n+\t__le16 last_entry;\n+\n+\t/* Each act_mem element specifies the order of the memory\n+\t * otherwise 0xFF\n+\t */\n+\tu8 act_mem[ICE_AQC_MAX_ACTION_MEMORIES];\n+};\n+\n+/* Update ACL scenario (direct 0x0C1B)\n+ * Query ACL scenario (direct 0x0C23)\n+ */\n+struct ice_aqc_acl_update_query_scen {\n+\t__le16 scen_id;\n+\tu8 reserved[6];\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+#define ICE_AQC_ACL_BYTE_SEL_BASE\t\t0x20\n+#define ICE_AQC_ACL_BYTE_SEL_BASE_PID\t\t0x3E\n+#define ICE_AQC_ACL_BYTE_SEL_BASE_PKT_DIR\tICE_AQC_ACL_BYTE_SEL_BASE\n+#define ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK\t0x3F\n+\n+#define ICE_AQC_ACL_ALLOC_SCE_START_CMP\t\tBIT(0)\n+#define ICE_AQC_ACL_ALLOC_SCE_START_SET\t\tBIT(1)\n+\n+#define ICE_AQC_ACL_SCE_ACT_MEM_EN\t\tBIT(7)\n+\n+/* Input buffer format in case allocate/update ACL scenario and same format\n+ * is used for response buffer in case of query ACL scenario.\n+ * NOTE: de-allocate ACL scenario is direct command and doesn't require\n+ * \"buffer\", hence no buffer format.\n+ */\n+struct ice_aqc_acl_scen {\n+\tstruct {\n+\t\t/* Byte [x] selection for the TCAM key. This value must be set\n+\t\t * to 0x0 for unused TCAM.\n+\t\t * Only Bit 6..0 is used in each byte and MSB is reserved\n+\t\t */\n+\t\tu8 tcam_select[5];\n+\t\t/* TCAM Block entry masking. This value should be set to 0x0 for\n+\t\t * unused TCAM\n+\t\t */\n+\t\tu8 chnk_msk;\n+\t\t/* Bit 0 : masks TCAM entries 0-63\n+\t\t * Bit 1 : masks TCAM entries 64-127\n+\t\t * Bit 2 to 7 : follow the pattern of bit 0 and 1\n+\t\t */\n+\t\tu8 start_cmp_set;\n+\t} tcam_cfg[ICE_AQC_ACL_SLICES];\n+\n+\t/* Each byte, Bit 6..0: action memory association to a TCAM block,\n+\t * otherwise it shall be set to 0x0 for disabled memory action.\n+\t * Bit 7 (ICE_AQC_ACL_SCE_ACT_MEM_EN): action memory enable for this\n+\t * scenario\n+\t */\n+\tu8 act_mem_cfg[ICE_AQC_MAX_ACTION_MEMORIES];\n+};\n+\n+/* Program ACL actionpair (indirect 0x0C1C) */\n+struct ice_aqc_acl_actpair {\n+\tu8 act_mem_index;\n+\tu8 reserved;\n+\t/* Entry index in action memory */\n+\t__le16 act_entry_index;\n+\t__le32 reserved2;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Input buffer format for program/query action-pair admin command */\n+struct ice_acl_act_entry {\n+\t/* Action priority, values must be between 0..7 */\n+\tu8 prio;\n+\t/* Action meta-data identifier. This field should be set to 0x0\n+\t * for a NOP action\n+\t */\n+\tu8 mdid;\n+\t__le16 value;\n+};\n+\n+#define ICE_ACL_NUM_ACT_PER_ACT_PAIR 2\n+struct ice_aqc_actpair {\n+\tstruct ice_acl_act_entry act[ICE_ACL_NUM_ACT_PER_ACT_PAIR];\n+};\n+\n+/* Program ACL entry (indirect 0x0C20) */\n+struct ice_aqc_acl_entry {\n+\tu8 tcam_index;\n+\tu8 reserved;\n+\t__le16 entry_index;\n+\t__le32 reserved2;\n+\t__le32 addr_high;\n+\t__le32 addr_low;\n+};\n+\n+/* Input buffer format in case of program ACL entry and response buffer format\n+ * in case of query ACL entry\n+ */\n+struct ice_aqc_acl_data {\n+\t/* Entry key and entry key invert are 40 bits wide.\n+\t * Byte 0..4 : entry key and Byte 5..7 are reserved\n+\t * Byte 8..12: entry key invert and Byte 13..15 are reserved\n+\t */\n+\tstruct {\n+\t\tu8 val[5];\n+\t\tu8 reserved[3];\n+\t} entry_key, entry_key_invert;\n+};\n+\n /* Add Tx LAN Queues (indirect 0x0C30) */\n struct ice_aqc_add_txqs {\n \tu8 num_qgrps;\n@@ -2651,6 +2847,14 @@ enum ice_adminq_opc {\n \t/* Sideband Control Interface commands */\n \tice_aqc_opc_neighbour_device_request\t\t= 0x0C00,\n \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_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,\n+\tice_aqc_opc_query_acl_scen\t\t\t= 0x0C23,\n+\n \t/* Tx queue handling commands/events */\n \tice_aqc_opc_add_txqs\t\t\t\t= 0x0C30,\n \tice_aqc_opc_dis_txqs\t\t\t\t= 0x0C31,\ndiff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h\nindex 8492df497340..161acd1cf095 100644\n--- a/drivers/net/ethernet/intel/ice/ice_type.h\n+++ b/drivers/net/ethernet/intel/ice/ice_type.h\n@@ -54,6 +54,7 @@ static inline u32 ice_round_to_num(u32 N, u32 R)\n #define ICE_DBG_RDMA\t\tBIT_ULL(15)\n #define ICE_DBG_PKG\t\tBIT_ULL(16)\n #define ICE_DBG_RES\t\tBIT_ULL(17)\n+#define ICE_DBG_ACL\t\tBIT_ULL(18)\n #define ICE_DBG_PTP\t\tBIT_ULL(19)\n #define ICE_DBG_AQ_MSG\t\tBIT_ULL(24)\n #define ICE_DBG_AQ_DESC\t\tBIT_ULL(25)\n@@ -1009,6 +1010,8 @@ struct ice_hw {\n \tstruct udp_tunnel_nic_shared udp_tunnel_shared;\n \tstruct udp_tunnel_nic_info udp_tunnel_nic;\n \n+\tstruct ice_acl_tbl *acl_tbl;\n+\n \t/* dvm boost update information */\n \tstruct ice_dvm_table dvm_upd;\n \ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl.c b/drivers/net/ethernet/intel/ice/ice_acl.c\nnew file mode 100644\nindex 000000000000..3d963c6071dc\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_acl.c\n@@ -0,0 +1,136 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (C) 2018-2026, Intel Corporation. */\n+\n+#include \"ice_acl.h\"\n+\n+/**\n+ * ice_aq_alloc_acl_tbl - allocate ACL table\n+ * @hw: pointer to the HW struct\n+ * @tbl: pointer to ice_acl_alloc_tbl struct\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Allocate ACL table (indirect 0x0C10)\n+ *\n+ * Return: 0 on success, negative on error\n+ */\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+{\n+\tstruct ice_aqc_acl_alloc_table *cmd;\n+\tstruct libie_aq_desc desc;\n+\n+\tif (!tbl->act_pairs_per_entry)\n+\t\treturn -EINVAL;\n+\n+\tif (tbl->act_pairs_per_entry > ICE_AQC_MAX_ACTION_MEMORIES)\n+\t\treturn -ENOSPC;\n+\n+\t/* If this is concurrent table, then alloc_ids buffer shall be valid and\n+\t * contain AllocIDs of dependent tables. 'num_dependent_alloc_ids'\n+\t * should be non-zero and within limit.\n+\t */\n+\tif (tbl->concurr) {\n+\t\tif (!tbl->num_dependent_alloc_ids)\n+\t\t\treturn -EINVAL;\n+\t\tif (tbl->num_dependent_alloc_ids >\n+\t\t    ICE_AQC_MAX_CONCURRENT_ACL_TBL)\n+\t\t\treturn -ERANGE;\n+\t}\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_alloc_acl_tbl);\n+\tdesc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);\n+\n+\tcmd = libie_aq_raw(&desc);\n+\tcmd->table_width = cpu_to_le16(tbl->width * BITS_PER_BYTE);\n+\tcmd->table_depth = cpu_to_le16(tbl->depth);\n+\tcmd->act_pairs_per_entry = tbl->act_pairs_per_entry;\n+\tif (tbl->concurr)\n+\t\tcmd->table_type = tbl->num_dependent_alloc_ids;\n+\n+\treturn ice_aq_send_cmd(hw, &desc, &tbl->buf, sizeof(tbl->buf), cd);\n+}\n+\n+/**\n+ * ice_aq_dealloc_acl_tbl - deallocate ACL table\n+ * @hw: pointer to the HW struct\n+ * @alloc_id: allocation ID of the table being released\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Deallocate ACL table (indirect 0x0C11)\n+ *\n+ * NOTE: This command has no buffer format for command itself but response\n+ * format is 'struct ice_aqc_acl_generic', pass ptr to that struct\n+ * as 'buf' and its size as 'buf_size'\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_dealloc_acl_tbl(struct ice_hw *hw, u16 alloc_id,\n+\t\t\t   struct ice_aqc_acl_generic *buf,\n+\t\t\t   struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_tbl_actpair *cmd;\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dealloc_acl_tbl);\n+\tcmd = libie_aq_raw(&desc);\n+\tcmd->alloc_id = cpu_to_le16(alloc_id);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_program_acl_entry - program ACL entry\n+ * @hw: pointer to the HW struct\n+ * @tcam_idx: Updated TCAM block index\n+ * @entry_idx: updated entry index\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Program ACL entry (direct 0x0C20)\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int ice_aq_program_acl_entry(struct ice_hw *hw, u8 tcam_idx, u16 entry_idx,\n+\t\t\t     struct ice_aqc_acl_data *buf, struct ice_sq_cd *cd)\n+{\n+\tstruct ice_aqc_acl_entry *cmd;\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_program_acl_entry);\n+\tdesc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);\n+\n+\tcmd = libie_aq_raw(&desc);\n+\tcmd->tcam_index = tcam_idx;\n+\tcmd->entry_index = cpu_to_le16(entry_idx);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\n+\n+/**\n+ * ice_aq_program_actpair - program ACL action pair\n+ * @hw: pointer to the HW struct\n+ * @act_mem_idx: action memory index to program/update/query\n+ * @act_entry_idx: the entry index in action memory to be programmed/updated\n+ * @buf: address of indirect data buffer\n+ * @cd: pointer to command details structure or NULL\n+ *\n+ * Program action entries (indirect 0x0C1C)\n+ *\n+ * Return: 0 on success, negative on error\n+ */\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+{\n+\tstruct ice_aqc_acl_actpair *cmd;\n+\tstruct libie_aq_desc desc;\n+\n+\tice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_program_acl_actpair);\n+\tdesc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);\n+\n+\tcmd = libie_aq_raw(&desc);\n+\tcmd->act_mem_index = act_mem_idx;\n+\tcmd->act_entry_index = cpu_to_le16(act_entry_idx);\n+\n+\treturn ice_aq_send_cmd(hw, &desc, buf, sizeof(*buf), cd);\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c b/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c\nnew file mode 100644\nindex 000000000000..d821b2c923d5\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c\n@@ -0,0 +1,302 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (C) 2018-2026, Intel Corporation. */\n+\n+#include \"ice_acl.h\"\n+\n+/* Determine the TCAM index of entry 'e' within the ACL table */\n+#define ICE_ACL_TBL_TCAM_IDX(e) ((e) / ICE_AQC_ACL_TCAM_DEPTH)\n+\n+/**\n+ * ice_acl_init_tbl - initialize ACL table\n+ * @hw: pointer to the hardware structure\n+ *\n+ * Invalidate TCAM entries and action pairs.\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+static int ice_acl_init_tbl(struct ice_hw *hw)\n+{\n+\tstruct ice_aqc_actpair act_buf = {};\n+\tstruct ice_aqc_acl_data buf = {};\n+\tstruct ice_acl_tbl *tbl;\n+\tu8 tcam_idx;\n+\tint err = 0;\n+\tu16 idx;\n+\n+\ttbl = hw->acl_tbl;\n+\n+\ttcam_idx = tbl->first_tcam;\n+\tidx = tbl->first_entry;\n+\twhile (tcam_idx < tbl->last_tcam ||\n+\t       (tcam_idx == tbl->last_tcam && idx <= tbl->last_entry)) {\n+\t\t/* Use the same value for entry_key and entry_key_inv since\n+\t\t * we are initializing the fields to 0\n+\t\t */\n+\t\terr = ice_aq_program_acl_entry(hw, tcam_idx, idx, &buf, NULL);\n+\t\tif (err)\n+\t\t\treturn err;\n+\n+\t\tif (++idx > tbl->last_entry) {\n+\t\t\ttcam_idx++;\n+\t\t\tidx = tbl->first_entry;\n+\t\t}\n+\t}\n+\n+\tfor (int i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) {\n+\t\tu16 act_entry_idx;\n+\n+\t\tif (tbl->act_mems[i].act_mem == ICE_ACL_ACT_MEM_ACT_MEM_INVAL)\n+\t\t\tcontinue;\n+\n+\t\tfor (act_entry_idx = tbl->first_entry;\n+\t\t     act_entry_idx <= tbl->last_entry; act_entry_idx++) {\n+\t\t\t/* Invalidate all allocated action pairs */\n+\t\t\terr = ice_aq_program_actpair(hw, i, act_entry_idx,\n+\t\t\t\t\t\t     &act_buf, NULL);\n+\t\t\tif (err)\n+\t\t\t\treturn err;\n+\t\t}\n+\t}\n+\n+\treturn err;\n+}\n+\n+/**\n+ * ice_acl_assign_act_mems_to_tcam - assign number of action memories to TCAM\n+ * @tbl: pointer to ACL table structure\n+ * @cur_tcam: Index of current TCAM. Value = 0 to (ICE_AQC_ACL_SLICES - 1)\n+ * @cur_mem_idx: Index of current action memory bank. Value = 0 to\n+ *\t\t (ICE_AQC_MAX_ACTION_MEMORIES - 1)\n+ * @num_mem: Number of action memory banks for this TCAM\n+ *\n+ * Assign \"num_mem\" valid action memory banks from \"curr_mem_idx\" to\n+ * \"curr_tcam\" TCAM.\n+ */\n+static void\n+ice_acl_assign_act_mems_to_tcam(struct ice_acl_tbl *tbl, u8 cur_tcam,\n+\t\t\t\tu8 *cur_mem_idx, u8 num_mem)\n+{\n+\tu8 mem_cnt;\n+\n+\tfor (mem_cnt = 0;\n+\t     *cur_mem_idx < ICE_AQC_MAX_ACTION_MEMORIES && mem_cnt < num_mem;\n+\t     (*cur_mem_idx)++) {\n+\t\tstruct ice_acl_act_mem *p_mem = &tbl->act_mems[*cur_mem_idx];\n+\n+\t\tif (p_mem->act_mem == ICE_ACL_ACT_MEM_ACT_MEM_INVAL)\n+\t\t\tcontinue;\n+\n+\t\tp_mem->member_of_tcam = cur_tcam;\n+\n+\t\tmem_cnt++;\n+\t}\n+}\n+\n+/**\n+ * ice_acl_divide_act_mems_to_tcams - assign action memory banks to TCAMs\n+ * @tbl: pointer to ACL table structure\n+ *\n+ * Figure out how to divide given action memory banks to given TCAMs. This\n+ * division is for SW book keeping. In the time when scenario is created,\n+ * an action memory bank can be used for different TCAM.\n+ *\n+ * For example, given that we have 2x2 ACL table with each table entry has\n+ * 2 action memory pairs. As the result, we will have 4 TCAMs (T1,T2,T3,T4)\n+ * and 4 action memory banks (A1,A2,A3,A4)\n+ *\t[T1 - T2] { A1 - A2 }\n+ *\t[T3 - T4] { A3 - A4 }\n+ * In the time when we need to create a scenario, for example, 2x1 scenario,\n+ * we will use [T3,T4] in a cascaded layout. As it is a requirement that all\n+ * action memory banks in a cascaded TCAM's row will need to associate with\n+ * the last TCAM. Thus, we will associate action memory banks [A3] and [A4]\n+ * for TCAM [T4].\n+ * For SW book-keeping purpose, we will keep theoretical maps between TCAM\n+ * [Tn] to action memory bank [An].\n+ */\n+static void ice_acl_divide_act_mems_to_tcams(struct ice_acl_tbl *tbl)\n+{\n+\tu16 num_cscd, stack_level, stack_idx, min_act_mem;\n+\tu8 tcam_idx = tbl->first_tcam;\n+\tu16 max_idx_to_get_extra;\n+\tu8 mem_idx = 0;\n+\n+\t/* Determine number of stacked TCAMs */\n+\tstack_level = DIV_ROUND_UP(tbl->info.depth, ICE_AQC_ACL_TCAM_DEPTH);\n+\n+\t/* Determine number of cascaded TCAMs */\n+\tnum_cscd = DIV_ROUND_UP(tbl->info.width, ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\n+\t/* In a line of cascaded TCAM, given the number of action memory\n+\t * banks per ACL table entry, we want to fairly divide these action\n+\t * memory banks between these TCAMs.\n+\t *\n+\t * For example, there are 3 TCAMs (TCAM 3,4,5) in a line of\n+\t * cascaded TCAM, and there are 7 act_mems for each ACL table entry.\n+\t * The result is:\n+\t *\t[TCAM_3 will have 3 act_mems]\n+\t *\t[TCAM_4 will have 2 act_mems]\n+\t *\t[TCAM_5 will have 2 act_mems]\n+\t */\n+\tmin_act_mem = tbl->info.entry_act_pairs / num_cscd;\n+\tmax_idx_to_get_extra = tbl->info.entry_act_pairs % num_cscd;\n+\n+\tfor (stack_idx = 0; stack_idx < stack_level; stack_idx++) {\n+\t\tu16 i;\n+\n+\t\tfor (i = 0; i < num_cscd; i++) {\n+\t\t\tu8 total_act_mem = min_act_mem;\n+\n+\t\t\tif (i < max_idx_to_get_extra)\n+\t\t\t\ttotal_act_mem++;\n+\n+\t\t\tice_acl_assign_act_mems_to_tcam(tbl, tcam_idx,\n+\t\t\t\t\t\t\t&mem_idx,\n+\t\t\t\t\t\t\ttotal_act_mem);\n+\n+\t\t\ttcam_idx++;\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * ice_acl_create_tbl - create ACL table\n+ * @hw: pointer to the HW struct\n+ * @params: parameters for the table to be created\n+ *\n+ * Create a LEM table for ACL usage. We are currently starting with some fixed\n+ * values for the size of the table, but this will need to grow as more flow\n+ * entries are added by the user level.\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int\n+ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params)\n+{\n+\tstruct ice_acl_alloc_tbl tbl_alloc = {};\n+\tstruct ice_aqc_acl_generic *resp_buf;\n+\tu16 width, depth, first_e, last_e;\n+\tstruct ice_acl_tbl *tbl;\n+\tint err;\n+\n+\tif (hw->acl_tbl)\n+\t\treturn -EEXIST;\n+\n+\t/* round up the width to the next TCAM width boundary. */\n+\twidth = roundup(params->width, (u16)ICE_AQC_ACL_KEY_WIDTH_BYTES);\n+\t/* depth should be provided in chunk (64 entry) increments */\n+\tdepth = ALIGN(params->depth, ICE_ACL_ENTRY_ALLOC_UNIT);\n+\n+\tif (params->entry_act_pairs < width / ICE_AQC_ACL_KEY_WIDTH_BYTES) {\n+\t\tparams->entry_act_pairs = width / ICE_AQC_ACL_KEY_WIDTH_BYTES;\n+\n+\t\tif (params->entry_act_pairs > ICE_AQC_TBL_MAX_ACTION_PAIRS)\n+\t\t\tparams->entry_act_pairs = ICE_AQC_TBL_MAX_ACTION_PAIRS;\n+\t}\n+\n+\t/* Validate that width*depth will not exceed the TCAM limit */\n+\tif ((DIV_ROUND_UP(depth, ICE_AQC_ACL_TCAM_DEPTH) *\n+\t     (width / ICE_AQC_ACL_KEY_WIDTH_BYTES)) > ICE_AQC_ACL_SLICES)\n+\t\treturn -ENOSPC;\n+\n+\ttbl_alloc.width = width;\n+\ttbl_alloc.depth = depth;\n+\ttbl_alloc.act_pairs_per_entry = params->entry_act_pairs;\n+\ttbl_alloc.concurr = params->concurr;\n+\n+\tif (params->concurr) {\n+\t\ttbl_alloc.num_dependent_alloc_ids =\n+\t\t\tICE_AQC_MAX_CONCURRENT_ACL_TBL;\n+\n+\t\tfor (int i = 0; i < ICE_AQC_MAX_CONCURRENT_ACL_TBL; i++)\n+\t\t\ttbl_alloc.buf.data_buf.alloc_ids[i] =\n+\t\t\t\tcpu_to_le16(params->dep_tbls[i]);\n+\t}\n+\n+\terr = ice_aq_alloc_acl_tbl(hw, &tbl_alloc, NULL);\n+\tif (err) {\n+\t\tif (le16_to_cpu(tbl_alloc.buf.resp_buf.alloc_id) <\n+\t\t    ICE_AQC_ALLOC_ID_4K)\n+\t\t\tdev_err(ice_hw_to_dev(hw), \"Alloc ACL table failed. Unavailable resource.\\n\");\n+\t\telse\n+\t\t\tdev_err(ice_hw_to_dev(hw), \"AQ allocation of ACL failed with error. status: %d\\n\",\n+\t\t\t\terr);\n+\t\treturn err;\n+\t}\n+\n+\ttbl = kzalloc_obj(*tbl);\n+\tif (!tbl)\n+\t\treturn -ENOMEM;\n+\n+\tresp_buf = &tbl_alloc.buf.resp_buf;\n+\n+\t/* Retrieve information of the allocated table */\n+\ttbl->id = le16_to_cpu(resp_buf->alloc_id);\n+\ttbl->first_tcam = resp_buf->ops.table.first_tcam;\n+\ttbl->last_tcam = resp_buf->ops.table.last_tcam;\n+\ttbl->first_entry = le16_to_cpu(resp_buf->first_entry);\n+\ttbl->last_entry = le16_to_cpu(resp_buf->last_entry);\n+\n+\ttbl->info = *params;\n+\ttbl->info.width = width;\n+\ttbl->info.depth = depth;\n+\thw->acl_tbl = tbl;\n+\n+\tfor (int i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)\n+\t\ttbl->act_mems[i].act_mem = resp_buf->act_mem[i];\n+\n+\t/* Figure out which TCAMs that these newly allocated action memories\n+\t * belong to.\n+\t */\n+\tice_acl_divide_act_mems_to_tcams(tbl);\n+\n+\t/* Initialize the resources allocated by invalidating all TCAM entries\n+\t * and all the action pairs\n+\t */\n+\terr = ice_acl_init_tbl(hw);\n+\tif (err) {\n+\t\tkfree(tbl);\n+\t\thw->acl_tbl = NULL;\n+\t\tice_debug(hw, ICE_DBG_ACL, \"Initialization of TCAM entries failed. status: %d\\n\",\n+\t\t\t  err);\n+\t\treturn err;\n+\t}\n+\n+\tfirst_e = (tbl->first_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +\n+\t\t(tbl->first_entry / ICE_ACL_ENTRY_ALLOC_UNIT);\n+\tlast_e = (tbl->last_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) +\n+\t\t(tbl->last_entry / ICE_ACL_ENTRY_ALLOC_UNIT);\n+\n+\t/* Indicate available entries in the table */\n+\tbitmap_set(tbl->avail, first_e, last_e - first_e + 1);\n+\n+\tINIT_LIST_HEAD(&tbl->scens);\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+ *\n+ * Return: 0 on success, negative on error\n+ */\n+int ice_acl_destroy_tbl(struct ice_hw *hw)\n+{\n+\tstruct ice_aqc_acl_generic resp_buf;\n+\tint err;\n+\n+\tif (!hw->acl_tbl)\n+\t\treturn -ENOENT;\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\",\n+\t\t\t  err);\n+\t\treturn err;\n+\t}\n+\n+\tkfree(hw->acl_tbl);\n+\thw->acl_tbl = NULL;\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex ee604b49dd47..1cdb49cd42c3 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -17,6 +17,7 @@\n #include \"devlink/port.h\"\n #include \"ice_sf_eth.h\"\n #include \"ice_hwmon.h\"\n+#include \"ice_acl.h\"\n /* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the\n  * ice tracepoint functions. This must be done exactly once across the\n  * ice driver.\n@@ -4324,6 +4325,47 @@ static int ice_send_version(struct ice_pf *pf)\n \treturn ice_aq_send_driver_ver(&pf->hw, &dv, NULL);\n }\n \n+/**\n+ * ice_init_acl - Initializes the ACL block\n+ * @pf: ptr to PF device\n+ *\n+ * Return: 0 on success, negative on error\n+ */\n+static int ice_init_acl(struct ice_pf *pf)\n+{\n+\tstruct ice_acl_tbl_params params = {};\n+\tstruct ice_hw *hw = &pf->hw;\n+\tint divider;\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+\t * of 12 bytes (96 bits), hence 120 bit wide keys, i.e. 3 TCAM slices.\n+\t * If the given hardware card contains less than 8 PFs (ports) then\n+\t * each PF will have its own TCAM slices. For 8 PFs, a given slice will\n+\t * be shared by 2 different PFs.\n+\t */\n+\tif (hw->dev_caps.num_funcs < 8)\n+\t\tdivider = ICE_ACL_ENTIRE_SLICE;\n+\telse\n+\t\tdivider = ICE_ACL_HALF_SLICE;\n+\n+\tparams.width = ICE_AQC_ACL_KEY_WIDTH_BYTES * 3;\n+\tparams.depth = ICE_AQC_ACL_TCAM_DEPTH / divider;\n+\tparams.entry_act_pairs = 1;\n+\tparams.concurr = false;\n+\n+\treturn ice_acl_create_tbl(hw, &params);\n+}\n+\n+/**\n+ * ice_deinit_acl - Unroll the initialization of the ACL block\n+ * @pf: ptr to PF device\n+ */\n+static void ice_deinit_acl(struct ice_pf *pf)\n+{\n+\tice_acl_destroy_tbl(&pf->hw);\n+}\n+\n /**\n  * ice_init_fdir - Initialize flow director VSI and configuration\n  * @pf: pointer to the PF instance\n@@ -4745,6 +4787,12 @@ static void ice_init_features(struct ice_pf *pf)\n \tif (ice_init_fdir(pf))\n \t\tdev_err(dev, \"could not initialize flow director\\n\");\n \n+\tif (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {\n+\t\t/* Note: ACL init failure is non-fatal to load */\n+\t\tif (ice_init_acl(pf))\n+\t\t\tdev_err(dev, \"Failed to initialize ACL\\n\");\n+\t}\n+\n \t/* Note: DCB init failure is non-fatal to load */\n \tif (ice_init_pf_dcb(pf, false)) {\n \t\tclear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);\n@@ -4767,6 +4815,7 @@ static void ice_deinit_features(struct ice_pf *pf)\n \tice_deinit_lag(pf);\n \tif (test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))\n \t\tice_cfg_lldp_mib_change(&pf->hw, false);\n+\tice_deinit_acl(pf);\n \tice_deinit_fdir(pf);\n \tif (ice_is_feature_supported(pf, ICE_F_GNSS))\n \t\tice_gnss_exit(pf);\n","prefixes":["iwl-next","v2","02/10"]}