Commit b1f5921a authored by Ahmed Zaki's avatar Ahmed Zaki Committed by Jakub Kicinski
Browse files

ice: refactor the FD and RSS flow ID generation



The flow director and RSS blocks use separate methods to generate a
unique 64 bit ID for the flow. This is not extendable, especially for
the RSS that already uses all 64 bit space.

Refactor the flow generation API so that the ID is generated within
ice_flow_add_prof(). The FD and RSS blocks caches the generated ID for
later use.

Suggested-by: default avatarDan Nowlin <dan.nowlin@intel.com>
Reviewed-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: default avatarAhmed Zaki <ahmed.zaki@intel.com>
Link: https://lore.kernel.org/r/20231213003321.605376-7-ahmed.zaki@intel.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent dc6e44c9
Loading
Loading
Loading
Loading
+13 −18
Original line number Diff line number Diff line
@@ -302,9 +302,7 @@ void ice_fdir_rem_adq_chnl(struct ice_hw *hw, u16 vsi_idx)
			continue;

		for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) {
			u64 prof_id;

			prof_id = flow + tun * ICE_FLTR_PTYPE_MAX;
			u64 prof_id = prof->prof_id[tun];

			for (i = 0; i < prof->cnt; i++) {
				if (prof->vsi_h[i] != vsi_idx)
@@ -362,10 +360,9 @@ ice_fdir_erase_flow_from_hw(struct ice_hw *hw, enum ice_block blk, int flow)
		return;

	for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) {
		u64 prof_id;
		u64 prof_id = prof->prof_id[tun];
		int j;

		prof_id = flow + tun * ICE_FLTR_PTYPE_MAX;
		for (j = 0; j < prof->cnt; j++) {
			u16 vsi_num;

@@ -439,12 +436,10 @@ void ice_fdir_replay_flows(struct ice_hw *hw)
		for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) {
			struct ice_flow_prof *hw_prof;
			struct ice_fd_hw_prof *prof;
			u64 prof_id;
			int j;

			prof = hw->fdir_prof[flow];
			prof_id = flow + tun * ICE_FLTR_PTYPE_MAX;
			ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id,
			ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX,
					  prof->fdir_seg[tun], TNL_SEG_CNT(tun),
					  &hw_prof);
			for (j = 0; j < prof->cnt; j++) {
@@ -454,7 +449,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw)

				prio = ICE_FLOW_PRIO_NORMAL;
				err = ice_flow_add_entry(hw, ICE_BLK_FD,
							 prof_id,
							 hw_prof->id,
							 prof->vsi_h[0],
							 prof->vsi_h[j],
							 prio, prof->fdir_seg,
@@ -464,6 +459,7 @@ void ice_fdir_replay_flows(struct ice_hw *hw)
						flow);
					continue;
				}
				prof->prof_id[tun] = hw_prof->id;
				prof->entry_h[j][tun] = entry_h;
			}
		}
@@ -638,7 +634,6 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,
	u64 entry1_h = 0;
	u64 entry2_h = 0;
	bool del_last;
	u64 prof_id;
	int err;
	int idx;

@@ -686,23 +681,23 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,
	 * That is the final parameters are 1 header (segment), no
	 * actions (NULL) and zero actions 0.
	 */
	prof_id = flow + tun * ICE_FLTR_PTYPE_MAX;
	err = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id, seg,
	err = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg,
				TNL_SEG_CNT(tun), &prof);
	if (err)
		return err;
	err = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, main_vsi->idx,
	err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx,
				 main_vsi->idx, ICE_FLOW_PRIO_NORMAL,
				 seg, &entry1_h);
	if (err)
		goto err_prof;
	err = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, main_vsi->idx,
	err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, main_vsi->idx,
				 ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL,
				 seg, &entry2_h);
	if (err)
		goto err_entry;

	hw_prof->fdir_seg[tun] = seg;
	hw_prof->prof_id[tun] = prof->id;
	hw_prof->entry_h[0][tun] = entry1_h;
	hw_prof->entry_h[1][tun] = entry2_h;
	hw_prof->vsi_h[0] = main_vsi->idx;
@@ -719,7 +714,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,

		entry1_h = 0;
		vsi_h = main_vsi->tc_map_vsi[idx]->idx;
		err = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id,
		err = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id,
					 main_vsi->idx, vsi_h,
					 ICE_FLOW_PRIO_NORMAL, seg,
					 &entry1_h);
@@ -756,7 +751,7 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,

		if (!hw_prof->entry_h[idx][tun])
			continue;
		ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof_id);
		ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof->id);
		ice_flow_rem_entry(hw, ICE_BLK_FD, hw_prof->entry_h[idx][tun]);
		hw_prof->entry_h[idx][tun] = 0;
		if (del_last)
@@ -766,10 +761,10 @@ ice_fdir_set_hw_fltr_rule(struct ice_pf *pf, struct ice_flow_seg_info *seg,
		hw_prof->cnt = 0;
err_entry:
	ice_rem_prof_id_flow(hw, ICE_BLK_FD,
			     ice_get_hw_vsi_num(hw, main_vsi->idx), prof_id);
			     ice_get_hw_vsi_num(hw, main_vsi->idx), prof->id);
	ice_flow_rem_entry(hw, ICE_BLK_FD, entry1_h);
err_prof:
	ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id);
	ice_flow_rem_prof(hw, ICE_BLK_FD, prof->id);
	dev_err(dev, "Failed to add filter. Flow director filters on each port must have the same input set.\n");

	return err;
+11 −0
Original line number Diff line number Diff line
@@ -2118,6 +2118,7 @@ void ice_free_hw_tbls(struct ice_hw *hw)
		devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.ref_count);
		devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.written);
		devm_kfree(ice_hw_to_dev(hw), hw->blk[i].es.mask_ena);
		devm_kfree(ice_hw_to_dev(hw), hw->blk[i].prof_id.id);
	}

	list_for_each_entry_safe(r, rt, &hw->rss_list_head, l_entry) {
@@ -2150,6 +2151,7 @@ void ice_clear_hw_tbls(struct ice_hw *hw)

	for (i = 0; i < ICE_BLK_COUNT; i++) {
		struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;
		struct ice_prof_id *prof_id = &hw->blk[i].prof_id;
		struct ice_prof_tcam *prof = &hw->blk[i].prof;
		struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;
		struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;
@@ -2180,6 +2182,8 @@ void ice_clear_hw_tbls(struct ice_hw *hw)
		memset(es->ref_count, 0, es->count * sizeof(*es->ref_count));
		memset(es->written, 0, es->count * sizeof(*es->written));
		memset(es->mask_ena, 0, es->count * sizeof(*es->mask_ena));

		memset(prof_id->id, 0, prof_id->count * sizeof(*prof_id->id));
	}
}

@@ -2196,6 +2200,7 @@ int ice_init_hw_tbls(struct ice_hw *hw)
	ice_init_all_prof_masks(hw);
	for (i = 0; i < ICE_BLK_COUNT; i++) {
		struct ice_prof_redir *prof_redir = &hw->blk[i].prof_redir;
		struct ice_prof_id *prof_id = &hw->blk[i].prof_id;
		struct ice_prof_tcam *prof = &hw->blk[i].prof;
		struct ice_xlt1 *xlt1 = &hw->blk[i].xlt1;
		struct ice_xlt2 *xlt2 = &hw->blk[i].xlt2;
@@ -2301,6 +2306,12 @@ int ice_init_hw_tbls(struct ice_hw *hw)
					    sizeof(*es->mask_ena), GFP_KERNEL);
		if (!es->mask_ena)
			goto err;

		prof_id->count = blk_sizes[i].prof_id;
		prof_id->id = devm_kcalloc(ice_hw_to_dev(hw), prof_id->count,
					   sizeof(*prof_id->id), GFP_KERNEL);
		if (!prof_id->id)
			goto err;
	}
	return 0;

+6 −0
Original line number Diff line number Diff line
@@ -304,10 +304,16 @@ struct ice_masks {
	struct ice_mask masks[ICE_PROF_MASK_COUNT];
};

struct ice_prof_id {
	unsigned long *id;
	int count;
};

/* Tables per block */
struct ice_blk_info {
	struct ice_xlt1 xlt1;
	struct ice_xlt2 xlt2;
	struct ice_prof_id prof_id;
	struct ice_prof_tcam prof;
	struct ice_prof_redir prof_redir;
	struct ice_es es;
+13 −34
Original line number Diff line number Diff line
@@ -1328,7 +1328,6 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
 * @hw: pointer to the HW struct
 * @blk: classification stage
 * @dir: flow direction
 * @prof_id: unique ID to identify this flow profile
 * @segs: array of one or more packet segments that describe the flow
 * @segs_cnt: number of packet segments provided
 * @prof: stores the returned flow profile added
@@ -1337,17 +1336,24 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
 */
static int
ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
		       enum ice_flow_dir dir, u64 prof_id,
		       enum ice_flow_dir dir,
		       struct ice_flow_seg_info *segs, u8 segs_cnt,
		       struct ice_flow_prof **prof)
{
	struct ice_flow_prof_params *params;
	struct ice_prof_id *ids;
	int status;
	u64 prof_id;
	u8 i;

	if (!prof)
		return -EINVAL;

	ids = &hw->blk[blk].prof_id;
	prof_id = find_first_zero_bit(ids->id, ids->count);
	if (prof_id >= ids->count)
		return -ENOSPC;

	params = kzalloc(sizeof(*params), GFP_KERNEL);
	if (!params)
		return -ENOMEM;
@@ -1393,6 +1399,7 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,

	INIT_LIST_HEAD(&params->prof->entries);
	mutex_init(&params->prof->entries_lock);
	set_bit(prof_id, ids->id);
	*prof = params->prof;

out:
@@ -1436,6 +1443,7 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
	/* Remove all hardware profiles associated with this flow profile */
	status = ice_rem_prof(hw, blk, prof->id);
	if (!status) {
		clear_bit(prof->id, hw->blk[blk].prof_id.id);
		list_del(&prof->l_entry);
		mutex_destroy(&prof->entries_lock);
		devm_kfree(ice_hw_to_dev(hw), prof);
@@ -1511,14 +1519,13 @@ ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
 * @hw: pointer to the HW struct
 * @blk: classification stage
 * @dir: flow direction
 * @prof_id: unique ID to identify this flow profile
 * @segs: array of one or more packet segments that describe the flow
 * @segs_cnt: number of packet segments provided
 * @prof: stores the returned flow profile added
 */
int
ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
		  struct ice_flow_seg_info *segs, u8 segs_cnt,
		  struct ice_flow_prof **prof)
{
	int status;
@@ -1538,8 +1545,7 @@ ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,

	mutex_lock(&hw->fl_profs_locks[blk]);

	status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
					prof);
	status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt, prof);
	if (!status)
		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);

@@ -2066,28 +2072,6 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
	return 0;
}

#define ICE_FLOW_PROF_HASH_S	0
#define ICE_FLOW_PROF_HASH_M	GENMASK_ULL(31, 0)
#define ICE_FLOW_PROF_HDR_S	32
#define ICE_FLOW_PROF_HDR_M	GENMASK_ULL(61, 32)
#define ICE_FLOW_PROF_ENCAP_S	62
#define ICE_FLOW_PROF_ENCAP_M	GENMASK_ULL(63, 62)

/* Flow profile ID format:
 * [0:31] - Packet match fields
 * [32:61] - Protocol header
 * [62:63] - Encapsulation flag:
 *	     0 if non-tunneled
 *	     1 if tunneled
 *	     2 for tunneled with outer ipv4
 *	     3 for tunneled with outer ipv6
 */
#define ICE_FLOW_GEN_PROFID(hash, hdr, encap)                                \
	((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) |                        \
	       (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
	       (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) &                    \
		ICE_FLOW_PROF_ENCAP_M)))

/**
 * ice_add_rss_cfg_sync - add an RSS configuration
 * @hw: pointer to the hardware structure
@@ -2165,13 +2149,8 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
		goto exit;
	}

	/* Create a new flow profile with generated profile and packet
	 * segment information.
	 */
	/* Create a new flow profile with packet segment information. */
	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
				   ICE_FLOW_GEN_PROFID(cfg->hash_flds,
						       segs[segs_cnt - 1].hdrs,
						       cfg->hdr_type),
				   segs, segs_cnt, &prof);
	if (status)
		goto exit;
+1 −1
Original line number Diff line number Diff line
@@ -403,7 +403,7 @@ struct ice_rss_cfg {

int
ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
		  u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
		  struct ice_flow_seg_info *segs, u8 segs_cnt,
		  struct ice_flow_prof **prof);
int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id);
int
Loading