Thread (25 messages) flat view 25 messages, 4 authors, 19h ago

RE: [PATCH net-next v2 10/12] ice: add ACL reset recovery and NTUPLE feature toggle

From: Loktionov, Aleksandr <hidden>
Date: 2026-09-18 15:44:31

quoted hunk ↗ jump to hunk
-----Original Message-----
From: Nguyen, Anthony L <anthony.l.nguyen@intel.com>
Sent: Thursday, September 17, 2026 8:39 PM
To: davem@davemloft.net; kuba@kernel.org; pabeni@redhat.com;
edumazet@google.com; andrew+netdev@lunn.ch; netdev@vger.kernel.org
Cc: Marcin Szycik <redacted>; Nguyen, Anthony L
[off-list ref]; Loktionov, Aleksandr
[off-list ref]; Penigalapati, Sandeep
[off-list ref]; S, Ananth [off-list ref];
alexander.duyck@gmail.com; Rinitha, SX [off-list ref]
Subject: [PATCH net-next v2 10/12] ice: add ACL reset recovery and
NTUPLE feature toggle

From: Marcin Szycik <redacted>

Extend ACL support to survive PF resets. Add ice_acl_replay_flows() to
rebuild HW flow profiles from preserved SW state, and
ice_acl_replay_fltrs() to reprogram TCAM entries from the SW filter
list. Wire both into ice_rebuild(). On failure, don't fail reset,
rather delete all ACL filters from the SW list.

Reset per-profile HW extraction sequences and range checkers for all
profiles inside ice_acl_create_hw(). This state is separate from the
TCAM entries and survives a PF reset. Explicitly clearing it ensures
that the old configuration is erased.

Add the ICE_FLAG_ACL_ENA PF flag to track ACL status. ACL is always
available, so set it unconditionally in driver initialization. Use the
new flag to track the NTUPLE ethtool feature flag, alongside Flow
Director, as both blocks are used to implement ethtool NTUPLE filters.
Like with Flow Director, disabling the flag deletes all filters, but
enabling it does not reprogram filters.

Signed-off-by: Marcin Szycik <redacted>
Tested-by: Rinitha S <redacted> (A Contingent worker at
Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
---
 drivers/net/ethernet/intel/ice/ice.h          |  4 +
 drivers/net/ethernet/intel/ice/ice_acl.h      |  5 +-
 drivers/net/ethernet/intel/ice/ice_acl_ctrl.c | 43 +++++-----
drivers/net/ethernet/intel/ice/ice_acl_main.c | 47 +++++++++++
drivers/net/ethernet/intel/ice/ice_acl_main.h |  1 +
 .../ethernet/intel/ice/ice_ethtool_ntuple.c   | 79
+++++++++++++++++++
 drivers/net/ethernet/intel/ice/ice_main.c     | 47 +++++++++++
 7 files changed, 201 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice.h
b/drivers/net/ethernet/intel/ice/ice.h
index 61a320eaf3c5..fcf1130f511f 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -503,6 +503,7 @@ enum ice_pf_flags {
 	ICE_FLAG_DCB_CAPABLE,
 	ICE_FLAG_DCB_ENA,
 	ICE_FLAG_FD_ENA,
+	ICE_FLAG_ACL_ENA,
 	ICE_FLAG_PTP_SUPPORTED,		/* PTP is supported by NVM */
 	ICE_FLAG_ADV_FEATURES,
 	ICE_FLAG_TC_MQPRIO,		/* support for Multi queue TC */
@@ -1019,10 +1020,12 @@ int ice_init_rdma(struct ice_pf *pf);  void
ice_deinit_rdma(struct ice_pf *pf);  bool ice_is_wol_supported(struct
ice_hw *hw);  void ice_fdir_del_all_fltrs(struct ice_vsi *vsi);
+void ice_acl_del_all_fltrs(struct ice_vsi *vsi);
 int
 ice_fdir_write_fltr(struct ice_pf *pf, struct ice_ntuple_fltr *input,
bool add,
 		    bool is_tun);
 void ice_vsi_manage_fdir(struct ice_vsi *vsi, bool ena);
+void ice_vsi_manage_acl(struct ice_vsi *vsi, bool ena);
 int ice_add_ntuple_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc
*cmd);  int ice_del_ntuple_ethtool(struct ice_vsi *vsi, struct
ethtool_rxnfc *cmd);  int ice_get_ethtool_fdir_entry(struct ice_hw
*hw, struct ethtool_rxnfc *cmd); @@ -1040,6 +1043,7 @@
ice_get_fdir_fltr_ids(struct ice_hw *hw, struct ethtool_rxnfc *cmd,
 		      u32 *rule_locs);
 void ice_fdir_rem_adq_chnl(struct ice_hw *hw, u16 vsi_idx);  void
ice_acl_rem_flows(struct ice_hw *hw);
+void ice_acl_replay_flows(struct ice_hw *hw);
 void ice_fdir_release_flows(struct ice_hw *hw);  void
ice_fdir_replay_flows(struct ice_hw *hw);  void
ice_fdir_replay_fltrs(struct ice_pf *pf); diff --git
a/drivers/net/ethernet/intel/ice/ice_acl.h
b/drivers/net/ethernet/intel/ice/ice_acl.h
index 0c8163e585d9..65e16ad1c783 100644
--- a/drivers/net/ethernet/intel/ice/ice_acl.h
+++ b/drivers/net/ethernet/intel/ice/ice_acl.h
@@ -6,6 +6,9 @@

 #include "ice_common.h"

+/* Maximum number of ACL HW profiles */
+#define ICE_ACL_MAX_PROF		128
+
 /* Marks a PF scenario slot as unused in the ACL profile extraction
table */
 #define ICE_ACL_INVALID_SCEN		0x3f
@@ -124,7 +127,7 @@ struct ice_acl_cntrs {  };

 int ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params
*params); -int ice_acl_destroy_tbl(struct ice_hw *hw);
+void ice_acl_destroy_tbl(struct ice_hw *hw);
 int ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16
num_entries,
 			u16 *scen_id);
 int ice_aq_alloc_acl_tbl(struct ice_hw *hw, struct ice_acl_alloc_tbl
*tbl, diff --git a/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c
b/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c
index 0ee86236bc37..4ea08bd9784c 100644
--- a/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c
+++ b/drivers/net/ethernet/intel/ice/ice_acl_ctrl.c
@@ -877,9 +877,10 @@ static int ice_acl_destroy_scen(struct ice_hw
*hw, u16 scen_id)
  * ice_acl_destroy_tbl - Destroy a previously created LEM table for
ACL
  * @hw: pointer to the HW struct
  *
- * Return: 0 on success, negative on error
+ * Continue on AQ errors so SW state is always cleaned up - e.g.
after
+ a reset,
+ * where the HW tables might be already gone.
  */
-int ice_acl_destroy_tbl(struct ice_hw *hw)
+void ice_acl_destroy_tbl(struct ice_hw *hw)
 {
 	struct ice_acl_scen *pos_scen, *tmp_scen;
 	struct ice_aqc_acl_generic resp_buf;
@@ -887,7 +888,7 @@ int ice_acl_destroy_tbl(struct ice_hw *hw)
 	int err;

 	if (!hw->acl_tbl)
-		return -ENOENT;
+		return;

 	/* Mark all the created scenario's TCAM to stop the packet
lookup and
 	 * delete them afterward
@@ -898,44 +899,38 @@ int ice_acl_destroy_tbl(struct ice_hw *hw)
 		if (err) {
 			ice_debug(hw, ICE_DBG_ACL,
"ice_aq_query_acl_scen() failed. status: %d\n",
 				  err);
-			return err;
-		}
-
-		for (int i = 0; i < ICE_AQC_ACL_SLICES; i++) {
-			buf.tcam_cfg[i].chnk_msk = 0;
-			buf.tcam_cfg[i].start_cmp_set =
-					ICE_AQC_ACL_ALLOC_SCE_START_CMP;
-		}
+		} else {
+			for (int i = 0; i < ICE_AQC_ACL_SLICES; i++) {
+				buf.tcam_cfg[i].chnk_msk = 0;
+				buf.tcam_cfg[i].start_cmp_set =
+
	ICE_AQC_ACL_ALLOC_SCE_START_CMP;
+			}

-		for (int i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++)
-			buf.act_mem_cfg[i] = 0;
+			for (int i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES;
i++)
+				buf.act_mem_cfg[i] = 0;

-		err = ice_aq_update_acl_scen(hw, pos_scen->id, &buf,
NULL);
-		if (err) {
-			ice_debug(hw, ICE_DBG_ACL,
"ice_aq_update_acl_scen() failed. status: %d\n",
-				  err);
-			return err;
+			err = ice_aq_update_acl_scen(hw, pos_scen->id,
&buf,
+						     NULL);
+			if (err)
+				ice_debug(hw, ICE_DBG_ACL, "scenario update
failed, status: %d\n",
+					  err);
 		}

 		err = ice_acl_destroy_scen(hw, pos_scen->id);
 		if (err) {
-			ice_debug(hw, ICE_DBG_ACL, "deletion of scenario
failed. status: %d\n",
+			ice_debug(hw, ICE_DBG_ACL, "deletion of scenario
failed, status:
+%d\n",
 				  err);
-			return err;
 		}
 	}

 	err = ice_aq_dealloc_acl_tbl(hw, hw->acl_tbl->id, &resp_buf,
NULL);
 	if (err) {
-		ice_debug(hw, ICE_DBG_ACL, "AQ de-allocation of ACL
failed. status: %d\n",
+		ice_debug(hw, ICE_DBG_ACL, "AQ de-allocation of ACL
failed, status:
+%d\n",
 			  err);
-		return err;
 	}

 	kfree(hw->acl_tbl);
 	hw->acl_tbl = NULL;
-
-	return 0;
 }

 /**
diff --git a/drivers/net/ethernet/intel/ice/ice_acl_main.c
b/drivers/net/ethernet/intel/ice/ice_acl_main.c
index 171b7bf8519c..d13e8bc1b701 100644
--- a/drivers/net/ethernet/intel/ice/ice_acl_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_acl_main.c
@@ -236,6 +236,53 @@ static void ice_acl_set_act_fwd_queue(struct
ice_flow_action *action,
 	action->data.acl_act.value = cpu_to_le16(queue_index);  }

+/*
+ * ice_acl_replay_fltrs - replay ACL filters from the SW filter list
+ * @pf: board private structure
+ *
+ * Reprograms ACL TCAM entries after a reset using data preserved in
+the
+ * SW filter list. Relies on ice_acl_replay_flows() having been
called
+first
+ * to restore the flow profiles.
+ */
+void ice_acl_replay_fltrs(struct ice_pf *pf) {
+	struct ice_vsi *vsi = ice_get_main_vsi(pf);
+	struct ice_hw *hw = &pf->hw;
+	struct ice_ntuple_fltr *f_rule;
+
+	if (!vsi)
+		return;
+
+	list_for_each_entry(f_rule, &hw->fdir_list_head, fltr_node) {
+		struct ice_flow_action acts[ICE_ACL_NUM_ACT];
+		struct ice_acl_hw_prof *hw_prof;
+		u64 entry_h = 0;
+		int err;
+
+		if (!f_rule->acl_fltr)
+			continue;
+
+		if (!hw->acl_prof || !hw->acl_prof[f_rule->flow_type])
+			continue;
+
+		hw_prof = hw->acl_prof[f_rule->flow_type];
+
+		memset(&acts, 0, sizeof(acts));
+		if (f_rule->dest_ctl ==
ICE_FLTR_PRGM_DESC_DEST_DROP_PKT)
+			ice_acl_set_act_drop(&acts[0]);
+		else
+			ice_acl_set_act_fwd_queue(&acts[0], f_rule-
quoted
q_index);
+
+		err = ice_flow_add_entry(hw, ICE_BLK_ACL, hw_prof-
quoted
prof_id,
+					 f_rule->fltr_id, vsi->idx,
+					 ICE_FLOW_PRIO_NORMAL, f_rule, acts,
+					 ICE_ACL_NUM_ACT, &entry_h);
+		if (err)
+			dev_warn(ice_pf_to_dev(pf), "Could not reprogram
filter %d, status %d\n",
+				 f_rule->fltr_id, err);
+	}
+}
+
 /**
  * ice_acl_comp_rules - compare two ACL filters
  * @a: first ACL filter
diff --git a/drivers/net/ethernet/intel/ice/ice_acl_main.h
b/drivers/net/ethernet/intel/ice/ice_acl_main.h
index 6665af2e7053..54053954b244 100644
--- a/drivers/net/ethernet/intel/ice/ice_acl_main.h
+++ b/drivers/net/ethernet/intel/ice/ice_acl_main.h
@@ -6,4 +6,5 @@
 #include "ice.h"
 #include <linux/ethtool.h>
 int ice_acl_add_rule_ethtool(struct ice_vsi *vsi, struct
ethtool_rxnfc *cmd);
+void ice_acl_replay_fltrs(struct ice_pf *pf);
 #endif /* _ICE_ACL_MAIN_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c
b/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c
index 0ac44d38fdbd..fef8640d23fb 100644
--- a/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool_ntuple.c
@@ -527,6 +527,37 @@ void ice_fdir_replay_flows(struct ice_hw *hw)
 	}
 }
...
 	if (vsi && vsi->netdev)
 		netif_device_attach(vsi->netdev);

--
2.47.1
Reviewed-by: Aleksandr Loktionov <redacted>
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help