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.hb/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); voidice_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 extractiontable */ #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 packetlookup 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.cb/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(structice_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 filterdiff --git a/drivers/net/ethernet/intel/ice/ice_acl_main.hb/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, structethtool_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.cb/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>