]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ice: improve TCAM priority handling for RSS profiles
authorAleksandr Loktionov <aleksandr.loktionov@intel.com>
Thu, 30 Oct 2025 13:59:48 +0000 (14:59 +0100)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Thu, 6 Nov 2025 22:19:43 +0000 (14:19 -0800)
Enhance TCAM priority logic to avoid conflicts between RSS profiles
with overlapping PTGs and attributes.

Track used PTG and attribute combinations.
Ensure higher-priority profiles override lower ones.
Add helper for setting TCAM flags and masks.

Ensure RSS rule consistency and prevent unintended matches.

Co-developed-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Dan Nowlin <dan.nowlin@intel.com>
Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ice/ice_flex_pipe.c
drivers/net/ethernet/intel/ice/ice_flex_type.h

index c8cb492fddf464ae1c3383e2818a64654a0d37b9..c0dbec3693669fd672e4db93c42846750695da9c 100644 (file)
@@ -3577,6 +3577,19 @@ ice_move_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi, u16 vsig,
        return 0;
 }
 
+/**
+ * ice_set_tcam_flags - set TCAM flag don't care mask
+ * @mask: mask for flags
+ * @dc_mask: pointer to the don't care mask
+ */
+static void ice_set_tcam_flags(u16 mask, u8 dc_mask[ICE_TCAM_KEY_VAL_SZ])
+{
+       u16 inverted_mask = ~mask;
+
+       /* flags are lowest u16 */
+       put_unaligned_le16(inverted_mask, dc_mask);
+}
+
 /**
  * ice_rem_chg_tcam_ent - remove a specific TCAM entry from change list
  * @hw: pointer to the HW struct
@@ -3647,6 +3660,9 @@ ice_prof_tcam_ena_dis(struct ice_hw *hw, enum ice_block blk, bool enable,
        if (!p)
                return -ENOMEM;
 
+       /* set don't care masks for TCAM flags */
+       ice_set_tcam_flags(tcam->attr.mask, dc_msk);
+
        status = ice_tcam_write_entry(hw, blk, tcam->tcam_idx, tcam->prof_id,
                                      tcam->ptg, vsig, 0, tcam->attr.flags,
                                      vl_msk, dc_msk, nm_msk);
@@ -3672,6 +3688,34 @@ err_ice_prof_tcam_ena_dis:
        return status;
 }
 
+/**
+ * ice_ptg_attr_in_use - determine if PTG and attribute pair is in use
+ * @ptg_attr: pointer to the PTG and attribute pair to check
+ * @ptgs_used: bitmap that denotes which PTGs are in use
+ * @attr_used: array of PTG and attributes pairs already used
+ * @attr_cnt: count of entries in the attr_used array
+ *
+ * Return: true if the PTG and attribute pair is in use, false otherwise.
+ */
+static bool
+ice_ptg_attr_in_use(struct ice_tcam_inf *ptg_attr, unsigned long *ptgs_used,
+                   struct ice_tcam_inf *attr_used[], u16 attr_cnt)
+{
+       u16 i;
+
+       if (!test_bit(ptg_attr->ptg, ptgs_used))
+               return false;
+
+       /* the PTG is used, so now look for correct attributes */
+       for (i = 0; i < attr_cnt; i++)
+               if (attr_used[i]->ptg == ptg_attr->ptg &&
+                   attr_used[i]->attr.flags == ptg_attr->attr.flags &&
+                   attr_used[i]->attr.mask == ptg_attr->attr.mask)
+                       return true;
+
+       return false;
+}
+
 /**
  * ice_adj_prof_priorities - adjust profile based on priorities
  * @hw: pointer to the HW struct
@@ -3684,10 +3728,16 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
                        struct list_head *chg)
 {
        DECLARE_BITMAP(ptgs_used, ICE_XLT1_CNT);
+       struct ice_tcam_inf **attr_used;
        struct ice_vsig_prof *t;
-       int status;
+       u16 attr_used_cnt = 0;
+       int status = 0;
        u16 idx;
 
+       attr_used = kcalloc(ICE_MAX_PTG_ATTRS, sizeof(*attr_used), GFP_KERNEL);
+       if (!attr_used)
+               return -ENOMEM;
+
        bitmap_zero(ptgs_used, ICE_XLT1_CNT);
        idx = vsig & ICE_VSIG_IDX_M;
 
@@ -3705,11 +3755,15 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
                u16 i;
 
                for (i = 0; i < t->tcam_count; i++) {
+                       bool used;
+
                        /* Scan the priorities from newest to oldest.
                         * Make sure that the newest profiles take priority.
                         */
-                       if (test_bit(t->tcam[i].ptg, ptgs_used) &&
-                           t->tcam[i].in_use) {
+                       used = ice_ptg_attr_in_use(&t->tcam[i], ptgs_used,
+                                                  attr_used, attr_used_cnt);
+
+                       if (used && t->tcam[i].in_use) {
                                /* need to mark this PTG as never match, as it
                                 * was already in use and therefore duplicate
                                 * (and lower priority)
@@ -3719,9 +3773,8 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
                                                               &t->tcam[i],
                                                               chg);
                                if (status)
-                                       return status;
-                       } else if (!test_bit(t->tcam[i].ptg, ptgs_used) &&
-                                  !t->tcam[i].in_use) {
+                                       goto free_attr_used;
+                       } else if (!used && !t->tcam[i].in_use) {
                                /* need to enable this PTG, as it in not in use
                                 * and not enabled (highest priority)
                                 */
@@ -3730,15 +3783,21 @@ ice_adj_prof_priorities(struct ice_hw *hw, enum ice_block blk, u16 vsig,
                                                               &t->tcam[i],
                                                               chg);
                                if (status)
-                                       return status;
+                                       goto free_attr_used;
                        }
 
                        /* keep track of used ptgs */
-                       __set_bit(t->tcam[i].ptg, ptgs_used);
+                       set_bit(t->tcam[i].ptg, ptgs_used);
+                       if (attr_used_cnt < ICE_MAX_PTG_ATTRS)
+                               attr_used[attr_used_cnt++] = &t->tcam[i];
+                       else
+                               ice_debug(hw, ICE_DBG_INIT, "Warn: ICE_MAX_PTG_ATTRS exceeded\n");
                }
        }
 
-       return 0;
+free_attr_used:
+       kfree(attr_used);
+       return status;
 }
 
 /**
@@ -3821,11 +3880,15 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,
                p->vsig = vsig;
                p->tcam_idx = t->tcam[i].tcam_idx;
 
+               /* set don't care masks for TCAM flags */
+               ice_set_tcam_flags(t->tcam[i].attr.mask, dc_msk);
+
                /* write the TCAM entry */
                status = ice_tcam_write_entry(hw, blk, t->tcam[i].tcam_idx,
                                              t->tcam[i].prof_id,
-                                             t->tcam[i].ptg, vsig, 0, 0,
-                                             vl_msk, dc_msk, nm_msk);
+                                             t->tcam[i].ptg, vsig, 0,
+                                             t->tcam[i].attr.flags, vl_msk,
+                                             dc_msk, nm_msk);
                if (status) {
                        devm_kfree(ice_hw_to_dev(hw), p);
                        goto err_ice_add_prof_id_vsig;
@@ -4139,9 +4202,6 @@ ice_flow_assoc_fdir_prof(struct ice_hw *hw, enum ice_block blk,
        u16 vsi_num;
        int status;
 
-       if (blk != ICE_BLK_FD)
-               return -EINVAL;
-
        vsi_num = ice_get_hw_vsi_num(hw, dest_vsi);
        status = ice_add_prof_id_flow(hw, blk, vsi_num, hdl);
        if (status) {
@@ -4150,6 +4210,9 @@ ice_flow_assoc_fdir_prof(struct ice_hw *hw, enum ice_block blk,
                return status;
        }
 
+       if (blk != ICE_BLK_FD)
+               return 0;
+
        vsi_num = ice_get_hw_vsi_num(hw, fdir_vsi);
        status = ice_add_prof_id_flow(hw, blk, vsi_num, hdl);
        if (status) {
index 817beca591e0c291c547e439216626b72b8e6908..80c9e7c749c22212f763f5fdf8c9e86fe4fb4ae6 100644 (file)
@@ -187,6 +187,7 @@ struct ice_prof_map {
 };
 
 #define ICE_INVALID_TCAM       0xFFFF
+#define ICE_MAX_PTG_ATTRS      1024
 
 struct ice_tcam_inf {
        u16 tcam_idx;