xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_rule.c (revision 486f9aac0cbe2598a76c853890c1d557747f71cf)
1405242c5SAlex Vesker /* SPDX-License-Identifier: BSD-3-Clause
2405242c5SAlex Vesker  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3405242c5SAlex Vesker  */
4405242c5SAlex Vesker 
5405242c5SAlex Vesker #include "mlx5dr_internal.h"
6405242c5SAlex Vesker 
7405242c5SAlex Vesker static void mlx5dr_rule_skip(struct mlx5dr_matcher *matcher,
8940b0ebaSAlex Vesker 			     struct mlx5dr_match_template *mt,
9405242c5SAlex Vesker 			     const struct rte_flow_item *items,
10405242c5SAlex Vesker 			     bool *skip_rx, bool *skip_tx)
11405242c5SAlex Vesker {
12405242c5SAlex Vesker 	const struct flow_hw_port_info *vport;
13405242c5SAlex Vesker 	const struct rte_flow_item_ethdev *v;
14405242c5SAlex Vesker 
15405242c5SAlex Vesker 	/* Flow_src is the 1st priority */
16405242c5SAlex Vesker 	if (matcher->attr.optimize_flow_src) {
17405242c5SAlex Vesker 		*skip_tx = matcher->attr.optimize_flow_src == MLX5DR_MATCHER_FLOW_SRC_WIRE;
18405242c5SAlex Vesker 		*skip_rx = matcher->attr.optimize_flow_src == MLX5DR_MATCHER_FLOW_SRC_VPORT;
19405242c5SAlex Vesker 		return;
20405242c5SAlex Vesker 	}
21405242c5SAlex Vesker 
22405242c5SAlex Vesker 	/* By default FDB rules are added to both RX and TX */
23405242c5SAlex Vesker 	*skip_rx = false;
24405242c5SAlex Vesker 	*skip_tx = false;
25405242c5SAlex Vesker 
26e23edbc5SItamar Gozlan 	if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
27e23edbc5SItamar Gozlan 		return;
28e23edbc5SItamar Gozlan 
29405242c5SAlex Vesker 	if (mt->item_flags & MLX5_FLOW_ITEM_REPRESENTED_PORT) {
30405242c5SAlex Vesker 		v = items[mt->vport_item_id].spec;
314cbeba6fSSuanming Mou 		vport = flow_hw_conv_port_id(matcher->tbl->ctx, v->port_id);
32405242c5SAlex Vesker 		if (unlikely(!vport)) {
33405242c5SAlex Vesker 			DR_LOG(ERR, "Fail to map port ID %d, ignoring", v->port_id);
34405242c5SAlex Vesker 			return;
35405242c5SAlex Vesker 		}
36405242c5SAlex Vesker 
37405242c5SAlex Vesker 		if (!vport->is_wire)
38405242c5SAlex Vesker 			/* Match vport ID is not WIRE -> Skip RX */
39405242c5SAlex Vesker 			*skip_rx = true;
40405242c5SAlex Vesker 		else
41405242c5SAlex Vesker 			/* Match vport ID is WIRE -> Skip TX */
42405242c5SAlex Vesker 			*skip_tx = true;
43405242c5SAlex Vesker 	}
44405242c5SAlex Vesker }
45405242c5SAlex Vesker 
46fa16feadSErez Shitrit static void
47fa16feadSErez Shitrit mlx5dr_rule_update_copy_tag(struct mlx5dr_rule *rule,
48fa16feadSErez Shitrit 			    struct mlx5dr_wqe_gta_data_seg_ste *wqe_data,
49fa16feadSErez Shitrit 			    bool is_jumbo)
50fa16feadSErez Shitrit {
51fa16feadSErez Shitrit 	if (is_jumbo)
52fa16feadSErez Shitrit 		memcpy(wqe_data->jumbo, rule->tag.jumbo, MLX5DR_JUMBO_TAG_SZ);
53fa16feadSErez Shitrit 	else
54fa16feadSErez Shitrit 		memcpy(wqe_data->tag, rule->tag.match, MLX5DR_MATCH_TAG_SZ);
55fa16feadSErez Shitrit }
56fa16feadSErez Shitrit 
57405242c5SAlex Vesker static void mlx5dr_rule_init_dep_wqe(struct mlx5dr_send_ring_dep_wqe *dep_wqe,
58405242c5SAlex Vesker 				     struct mlx5dr_rule *rule,
59405242c5SAlex Vesker 				     const struct rte_flow_item *items,
60940b0ebaSAlex Vesker 				     struct mlx5dr_match_template *mt,
61e28392b3SAlex Vesker 				     struct mlx5dr_rule_attr *attr)
62405242c5SAlex Vesker {
63405242c5SAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
64405242c5SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
65405242c5SAlex Vesker 	bool skip_rx, skip_tx;
66405242c5SAlex Vesker 
67405242c5SAlex Vesker 	dep_wqe->rule = rule;
68e28392b3SAlex Vesker 	dep_wqe->user_data = attr->user_data;
69e28392b3SAlex Vesker 	dep_wqe->direct_index = mlx5dr_matcher_is_insert_by_idx(matcher) ?
70e28392b3SAlex Vesker 		attr->rule_idx : 0;
71405242c5SAlex Vesker 
72fa16feadSErez Shitrit 	if (!items) { /* rule update */
73fa16feadSErez Shitrit 		dep_wqe->rtc_0 = rule->rtc_0;
74fa16feadSErez Shitrit 		dep_wqe->rtc_1 = rule->rtc_1;
75fa16feadSErez Shitrit 		dep_wqe->retry_rtc_1 = 0;
76fa16feadSErez Shitrit 		dep_wqe->retry_rtc_0 = 0;
77fa16feadSErez Shitrit 		return;
78fa16feadSErez Shitrit 	}
79fa16feadSErez Shitrit 
80405242c5SAlex Vesker 	switch (tbl->type) {
81405242c5SAlex Vesker 	case MLX5DR_TABLE_TYPE_NIC_RX:
82405242c5SAlex Vesker 	case MLX5DR_TABLE_TYPE_NIC_TX:
83405242c5SAlex Vesker 		dep_wqe->rtc_0 = matcher->match_ste.rtc_0->id;
84405242c5SAlex Vesker 		dep_wqe->retry_rtc_0 = matcher->col_matcher ?
85405242c5SAlex Vesker 				       matcher->col_matcher->match_ste.rtc_0->id : 0;
86405242c5SAlex Vesker 		dep_wqe->rtc_1 = 0;
87405242c5SAlex Vesker 		dep_wqe->retry_rtc_1 = 0;
88405242c5SAlex Vesker 		break;
89405242c5SAlex Vesker 
90405242c5SAlex Vesker 	case MLX5DR_TABLE_TYPE_FDB:
91940b0ebaSAlex Vesker 		mlx5dr_rule_skip(matcher, mt, items, &skip_rx, &skip_tx);
92405242c5SAlex Vesker 
93405242c5SAlex Vesker 		if (!skip_rx) {
94405242c5SAlex Vesker 			dep_wqe->rtc_0 = matcher->match_ste.rtc_0->id;
95405242c5SAlex Vesker 			dep_wqe->retry_rtc_0 = matcher->col_matcher ?
96405242c5SAlex Vesker 					       matcher->col_matcher->match_ste.rtc_0->id : 0;
97405242c5SAlex Vesker 		} else {
98405242c5SAlex Vesker 			dep_wqe->rtc_0 = 0;
99405242c5SAlex Vesker 			dep_wqe->retry_rtc_0 = 0;
100405242c5SAlex Vesker 		}
101405242c5SAlex Vesker 
102405242c5SAlex Vesker 		if (!skip_tx) {
103405242c5SAlex Vesker 			dep_wqe->rtc_1 = matcher->match_ste.rtc_1->id;
104405242c5SAlex Vesker 			dep_wqe->retry_rtc_1 = matcher->col_matcher ?
105405242c5SAlex Vesker 					       matcher->col_matcher->match_ste.rtc_1->id : 0;
106405242c5SAlex Vesker 		} else {
107405242c5SAlex Vesker 			dep_wqe->rtc_1 = 0;
108405242c5SAlex Vesker 			dep_wqe->retry_rtc_1 = 0;
109405242c5SAlex Vesker 		}
110405242c5SAlex Vesker 
111405242c5SAlex Vesker 		break;
112405242c5SAlex Vesker 
113405242c5SAlex Vesker 	default:
114405242c5SAlex Vesker 		assert(false);
115405242c5SAlex Vesker 		break;
116405242c5SAlex Vesker 	}
117405242c5SAlex Vesker }
118405242c5SAlex Vesker 
119762fecebSYevgeny Kliteynik static void mlx5dr_rule_move_get_rtc(struct mlx5dr_rule *rule,
120762fecebSYevgeny Kliteynik 				     struct mlx5dr_send_ste_attr *ste_attr)
121762fecebSYevgeny Kliteynik {
122762fecebSYevgeny Kliteynik 	struct mlx5dr_matcher *dst_matcher = rule->matcher->resize_dst;
123762fecebSYevgeny Kliteynik 
124762fecebSYevgeny Kliteynik 	if (rule->resize_info->rtc_0) {
125762fecebSYevgeny Kliteynik 		ste_attr->rtc_0 = dst_matcher->match_ste.rtc_0->id;
126762fecebSYevgeny Kliteynik 		ste_attr->retry_rtc_0 = dst_matcher->col_matcher ?
127762fecebSYevgeny Kliteynik 					dst_matcher->col_matcher->match_ste.rtc_0->id : 0;
128762fecebSYevgeny Kliteynik 	}
129762fecebSYevgeny Kliteynik 	if (rule->resize_info->rtc_1) {
130762fecebSYevgeny Kliteynik 		ste_attr->rtc_1 = dst_matcher->match_ste.rtc_1->id;
131762fecebSYevgeny Kliteynik 		ste_attr->retry_rtc_1 = dst_matcher->col_matcher ?
132762fecebSYevgeny Kliteynik 					dst_matcher->col_matcher->match_ste.rtc_1->id : 0;
133762fecebSYevgeny Kliteynik 	}
134762fecebSYevgeny Kliteynik }
135762fecebSYevgeny Kliteynik 
136405242c5SAlex Vesker static void mlx5dr_rule_gen_comp(struct mlx5dr_send_engine *queue,
137405242c5SAlex Vesker 				 struct mlx5dr_rule *rule,
138405242c5SAlex Vesker 				 bool err,
139405242c5SAlex Vesker 				 void *user_data,
140405242c5SAlex Vesker 				 enum mlx5dr_rule_status rule_status_on_succ)
141405242c5SAlex Vesker {
142405242c5SAlex Vesker 	enum rte_flow_op_status comp_status;
143405242c5SAlex Vesker 
144405242c5SAlex Vesker 	if (!err) {
145405242c5SAlex Vesker 		comp_status = RTE_FLOW_OP_SUCCESS;
146405242c5SAlex Vesker 		rule->status = rule_status_on_succ;
147405242c5SAlex Vesker 	} else {
148405242c5SAlex Vesker 		comp_status = RTE_FLOW_OP_ERROR;
149405242c5SAlex Vesker 		rule->status = MLX5DR_RULE_STATUS_FAILED;
150405242c5SAlex Vesker 	}
151405242c5SAlex Vesker 
152405242c5SAlex Vesker 	mlx5dr_send_engine_inc_rule(queue);
153405242c5SAlex Vesker 	mlx5dr_send_engine_gen_comp(queue, user_data, comp_status);
154405242c5SAlex Vesker }
155405242c5SAlex Vesker 
156348cdeecSAlex Vesker static void
157762fecebSYevgeny Kliteynik mlx5dr_rule_save_resize_info(struct mlx5dr_rule *rule,
158762fecebSYevgeny Kliteynik 			     struct mlx5dr_send_ste_attr *ste_attr)
159762fecebSYevgeny Kliteynik {
160c54d3949SYevgeny Kliteynik 	if (likely(!mlx5dr_matcher_is_resizable(rule->matcher)))
161c54d3949SYevgeny Kliteynik 		return;
162c54d3949SYevgeny Kliteynik 
163762fecebSYevgeny Kliteynik 	rule->resize_info = simple_calloc(1, sizeof(*rule->resize_info));
164762fecebSYevgeny Kliteynik 	if (unlikely(!rule->resize_info)) {
165762fecebSYevgeny Kliteynik 		assert(rule->resize_info);
166762fecebSYevgeny Kliteynik 		rte_errno = ENOMEM;
167762fecebSYevgeny Kliteynik 	}
168762fecebSYevgeny Kliteynik 
169762fecebSYevgeny Kliteynik 	memcpy(rule->resize_info->ctrl_seg, ste_attr->wqe_ctrl,
170762fecebSYevgeny Kliteynik 	       sizeof(rule->resize_info->ctrl_seg));
171762fecebSYevgeny Kliteynik 	memcpy(rule->resize_info->data_seg, ste_attr->wqe_data,
172762fecebSYevgeny Kliteynik 	       sizeof(rule->resize_info->data_seg));
173762fecebSYevgeny Kliteynik 
174c54d3949SYevgeny Kliteynik 	rule->resize_info->max_stes = rule->matcher->action_ste.max_stes;
175762fecebSYevgeny Kliteynik 	rule->resize_info->action_ste_pool = rule->matcher->action_ste.max_stes ?
176762fecebSYevgeny Kliteynik 					     rule->matcher->action_ste.pool :
177762fecebSYevgeny Kliteynik 					     NULL;
178762fecebSYevgeny Kliteynik }
179762fecebSYevgeny Kliteynik 
180c54d3949SYevgeny Kliteynik void mlx5dr_rule_clear_resize_info(struct mlx5dr_rule *rule)
181762fecebSYevgeny Kliteynik {
182c54d3949SYevgeny Kliteynik 	if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher) &&
183c54d3949SYevgeny Kliteynik 		     rule->resize_info)) {
184762fecebSYevgeny Kliteynik 		simple_free(rule->resize_info);
185762fecebSYevgeny Kliteynik 		rule->resize_info = NULL;
186762fecebSYevgeny Kliteynik 	}
187762fecebSYevgeny Kliteynik }
188762fecebSYevgeny Kliteynik 
189762fecebSYevgeny Kliteynik static void
190348cdeecSAlex Vesker mlx5dr_rule_save_delete_info(struct mlx5dr_rule *rule,
191348cdeecSAlex Vesker 			     struct mlx5dr_send_ste_attr *ste_attr)
192348cdeecSAlex Vesker {
19360e9bf4eSErez Shitrit 	struct mlx5dr_match_template *mt = rule->matcher->mt;
19460e9bf4eSErez Shitrit 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
19560e9bf4eSErez Shitrit 
196348cdeecSAlex Vesker 	if (unlikely(mlx5dr_matcher_req_fw_wqe(rule->matcher))) {
197348cdeecSAlex Vesker 		uint8_t *src_tag;
198348cdeecSAlex Vesker 
199348cdeecSAlex Vesker 		/* Save match definer id and tag for delete */
200348cdeecSAlex Vesker 		rule->tag_ptr = simple_calloc(2, sizeof(*rule->tag_ptr));
201348cdeecSAlex Vesker 		assert(rule->tag_ptr);
202348cdeecSAlex Vesker 
2038c163b6fSErez Shitrit 		if (is_jumbo)
2048c163b6fSErez Shitrit 			memcpy(rule->tag_ptr[0].jumbo, ste_attr->wqe_data->action,
2058c163b6fSErez Shitrit 			       MLX5DR_JUMBO_TAG_SZ);
2068c163b6fSErez Shitrit 		else
2078c163b6fSErez Shitrit 			memcpy(rule->tag_ptr[0].match, ste_attr->wqe_data->tag,
2088c163b6fSErez Shitrit 			       MLX5DR_MATCH_TAG_SZ);
2098c163b6fSErez Shitrit 
210348cdeecSAlex Vesker 		rule->tag_ptr[1].reserved[0] = ste_attr->send_attr.match_definer_id;
211348cdeecSAlex Vesker 
212348cdeecSAlex Vesker 		/* Save range definer id and tag for delete */
213348cdeecSAlex Vesker 		if (ste_attr->range_wqe_data) {
214348cdeecSAlex Vesker 			src_tag = (uint8_t *)ste_attr->range_wqe_data->tag;
215348cdeecSAlex Vesker 			memcpy(rule->tag_ptr[1].match, src_tag, MLX5DR_MATCH_TAG_SZ);
216348cdeecSAlex Vesker 			rule->tag_ptr[1].reserved[1] = ste_attr->send_attr.range_definer_id;
217348cdeecSAlex Vesker 		}
218348cdeecSAlex Vesker 		return;
219348cdeecSAlex Vesker 	}
220348cdeecSAlex Vesker 
221762fecebSYevgeny Kliteynik 	if (likely(!mlx5dr_matcher_is_resizable(rule->matcher))) {
22260e9bf4eSErez Shitrit 		if (is_jumbo)
223762fecebSYevgeny Kliteynik 			memcpy(&rule->tag.jumbo, ste_attr->wqe_data->action, MLX5DR_JUMBO_TAG_SZ);
224348cdeecSAlex Vesker 		else
225762fecebSYevgeny Kliteynik 			memcpy(&rule->tag.match, ste_attr->wqe_data->tag, MLX5DR_MATCH_TAG_SZ);
226762fecebSYevgeny Kliteynik 		return;
227762fecebSYevgeny Kliteynik 	}
228348cdeecSAlex Vesker }
229348cdeecSAlex Vesker 
230348cdeecSAlex Vesker static void
231348cdeecSAlex Vesker mlx5dr_rule_clear_delete_info(struct mlx5dr_rule *rule)
232348cdeecSAlex Vesker {
233762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_matcher_req_fw_wqe(rule->matcher))) {
234348cdeecSAlex Vesker 		simple_free(rule->tag_ptr);
235762fecebSYevgeny Kliteynik 		return;
236762fecebSYevgeny Kliteynik 	}
237348cdeecSAlex Vesker }
238348cdeecSAlex Vesker 
239348cdeecSAlex Vesker static void
240348cdeecSAlex Vesker mlx5dr_rule_load_delete_info(struct mlx5dr_rule *rule,
241348cdeecSAlex Vesker 			     struct mlx5dr_send_ste_attr *ste_attr)
242348cdeecSAlex Vesker {
243348cdeecSAlex Vesker 	if (unlikely(mlx5dr_matcher_req_fw_wqe(rule->matcher))) {
244348cdeecSAlex Vesker 		/* Load match definer id and tag for delete */
245348cdeecSAlex Vesker 		ste_attr->wqe_tag = &rule->tag_ptr[0];
246348cdeecSAlex Vesker 		ste_attr->send_attr.match_definer_id = rule->tag_ptr[1].reserved[0];
247348cdeecSAlex Vesker 
248348cdeecSAlex Vesker 		/* Load range definer id and tag for delete */
249348cdeecSAlex Vesker 		if (rule->matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) {
250348cdeecSAlex Vesker 			ste_attr->range_wqe_tag = &rule->tag_ptr[1];
251348cdeecSAlex Vesker 			ste_attr->send_attr.range_definer_id = rule->tag_ptr[1].reserved[1];
252348cdeecSAlex Vesker 		}
253762fecebSYevgeny Kliteynik 	} else if (likely(!mlx5dr_matcher_is_resizable(rule->matcher))) {
254348cdeecSAlex Vesker 		ste_attr->wqe_tag = &rule->tag;
255762fecebSYevgeny Kliteynik 	} else {
256762fecebSYevgeny Kliteynik 		ste_attr->wqe_tag = (struct mlx5dr_rule_match_tag *)
257762fecebSYevgeny Kliteynik 			&rule->resize_info->data_seg[MLX5DR_STE_CTRL_SZ];
258348cdeecSAlex Vesker 	}
259348cdeecSAlex Vesker }
260348cdeecSAlex Vesker 
261405242c5SAlex Vesker static int mlx5dr_rule_alloc_action_ste(struct mlx5dr_rule *rule,
262405242c5SAlex Vesker 					struct mlx5dr_rule_attr *attr)
263405242c5SAlex Vesker {
264405242c5SAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
265405242c5SAlex Vesker 	int ret;
266405242c5SAlex Vesker 
267405242c5SAlex Vesker 	/* Use rule_idx for locking optimzation, otherwise allocate from pool */
26838b5bf64SYevgeny Kliteynik 	if (matcher->attr.optimize_using_rule_idx ||
26938b5bf64SYevgeny Kliteynik 	    mlx5dr_matcher_is_insert_by_idx(matcher)) {
270405242c5SAlex Vesker 		rule->action_ste_idx = attr->rule_idx * matcher->action_ste.max_stes;
271405242c5SAlex Vesker 	} else {
272405242c5SAlex Vesker 		struct mlx5dr_pool_chunk ste = {0};
273405242c5SAlex Vesker 
274405242c5SAlex Vesker 		ste.order = rte_log2_u32(matcher->action_ste.max_stes);
275405242c5SAlex Vesker 		ret = mlx5dr_pool_chunk_alloc(matcher->action_ste.pool, &ste);
276405242c5SAlex Vesker 		if (ret) {
277405242c5SAlex Vesker 			DR_LOG(ERR, "Failed to allocate STE for rule actions");
278405242c5SAlex Vesker 			return ret;
279405242c5SAlex Vesker 		}
280405242c5SAlex Vesker 		rule->action_ste_idx = ste.offset;
281405242c5SAlex Vesker 	}
282405242c5SAlex Vesker 	return 0;
283405242c5SAlex Vesker }
284405242c5SAlex Vesker 
285405242c5SAlex Vesker void mlx5dr_rule_free_action_ste_idx(struct mlx5dr_rule *rule)
286405242c5SAlex Vesker {
287405242c5SAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
288762fecebSYevgeny Kliteynik 	struct mlx5dr_pool *pool;
289c54d3949SYevgeny Kliteynik 	uint8_t max_stes;
290405242c5SAlex Vesker 
29138b5bf64SYevgeny Kliteynik 	if (rule->action_ste_idx > -1 &&
29238b5bf64SYevgeny Kliteynik 	    !matcher->attr.optimize_using_rule_idx &&
29338b5bf64SYevgeny Kliteynik 	    !mlx5dr_matcher_is_insert_by_idx(matcher)) {
294405242c5SAlex Vesker 		struct mlx5dr_pool_chunk ste = {0};
295405242c5SAlex Vesker 
296c54d3949SYevgeny Kliteynik 		if (unlikely(mlx5dr_matcher_is_resizable(matcher))) {
297c54d3949SYevgeny Kliteynik 			/* Free the original action pool if rule was resized */
298c54d3949SYevgeny Kliteynik 			max_stes = rule->resize_info->max_stes;
299c54d3949SYevgeny Kliteynik 			pool = rule->resize_info->action_ste_pool;
300c54d3949SYevgeny Kliteynik 		} else {
301c54d3949SYevgeny Kliteynik 			max_stes = matcher->action_ste.max_stes;
302c54d3949SYevgeny Kliteynik 			pool = matcher->action_ste.pool;
303c54d3949SYevgeny Kliteynik 		}
304c54d3949SYevgeny Kliteynik 
305405242c5SAlex Vesker 		/* This release is safe only when the rule match part was deleted */
306c54d3949SYevgeny Kliteynik 		ste.order = rte_log2_u32(max_stes);
307405242c5SAlex Vesker 		ste.offset = rule->action_ste_idx;
308762fecebSYevgeny Kliteynik 
309762fecebSYevgeny Kliteynik 		mlx5dr_pool_chunk_free(pool, &ste);
310405242c5SAlex Vesker 	}
311405242c5SAlex Vesker }
312405242c5SAlex Vesker 
313405242c5SAlex Vesker static void mlx5dr_rule_create_init(struct mlx5dr_rule *rule,
314405242c5SAlex Vesker 				    struct mlx5dr_send_ste_attr *ste_attr,
315fa16feadSErez Shitrit 				    struct mlx5dr_actions_apply_data *apply,
316fa16feadSErez Shitrit 				    bool is_update)
317405242c5SAlex Vesker {
318405242c5SAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
319405242c5SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
320405242c5SAlex Vesker 	struct mlx5dr_context *ctx = tbl->ctx;
321405242c5SAlex Vesker 
322405242c5SAlex Vesker 	/* Init rule before reuse */
323fa16feadSErez Shitrit 	if (!is_update) {
324fa16feadSErez Shitrit 		/* In update we use these rtc's */
325405242c5SAlex Vesker 		rule->rtc_0 = 0;
326405242c5SAlex Vesker 		rule->rtc_1 = 0;
327fa16feadSErez Shitrit 	}
328fa16feadSErez Shitrit 
329405242c5SAlex Vesker 	rule->pending_wqes = 0;
330405242c5SAlex Vesker 	rule->action_ste_idx = -1;
331405242c5SAlex Vesker 	rule->status = MLX5DR_RULE_STATUS_CREATING;
332405242c5SAlex Vesker 
333405242c5SAlex Vesker 	/* Init default send STE attributes */
334405242c5SAlex Vesker 	ste_attr->gta_opcode = MLX5DR_WQE_GTA_OP_ACTIVATE;
335405242c5SAlex Vesker 	ste_attr->send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
336405242c5SAlex Vesker 	ste_attr->send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
337405242c5SAlex Vesker 	ste_attr->send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
338405242c5SAlex Vesker 
339405242c5SAlex Vesker 	/* Init default action apply */
340405242c5SAlex Vesker 	apply->tbl_type = tbl->type;
341405242c5SAlex Vesker 	apply->common_res = &ctx->common_res[tbl->type];
342405242c5SAlex Vesker 	apply->jump_to_action_stc = matcher->action_ste.stc.offset;
343405242c5SAlex Vesker 	apply->require_dep = 0;
344405242c5SAlex Vesker }
345405242c5SAlex Vesker 
346762fecebSYevgeny Kliteynik static void mlx5dr_rule_move_init(struct mlx5dr_rule *rule,
347762fecebSYevgeny Kliteynik 				  struct mlx5dr_rule_attr *attr)
348762fecebSYevgeny Kliteynik {
349762fecebSYevgeny Kliteynik 	/* Save the old RTC IDs to be later used in match STE delete */
350762fecebSYevgeny Kliteynik 	rule->resize_info->rtc_0 = rule->rtc_0;
351762fecebSYevgeny Kliteynik 	rule->resize_info->rtc_1 = rule->rtc_1;
352762fecebSYevgeny Kliteynik 	rule->resize_info->rule_idx = attr->rule_idx;
353762fecebSYevgeny Kliteynik 
354762fecebSYevgeny Kliteynik 	rule->rtc_0 = 0;
355762fecebSYevgeny Kliteynik 	rule->rtc_1 = 0;
356762fecebSYevgeny Kliteynik 
357762fecebSYevgeny Kliteynik 	rule->pending_wqes = 0;
358762fecebSYevgeny Kliteynik 	rule->action_ste_idx = -1;
359762fecebSYevgeny Kliteynik 	rule->status = MLX5DR_RULE_STATUS_CREATING;
360762fecebSYevgeny Kliteynik 	rule->resize_info->state = MLX5DR_RULE_RESIZE_STATE_WRITING;
361762fecebSYevgeny Kliteynik }
362762fecebSYevgeny Kliteynik 
36368b34daaSYevgeny Kliteynik bool mlx5dr_rule_move_in_progress(struct mlx5dr_rule *rule)
36468b34daaSYevgeny Kliteynik {
36568b34daaSYevgeny Kliteynik 	return mlx5dr_matcher_is_in_resize(rule->matcher) &&
36668b34daaSYevgeny Kliteynik 	       rule->resize_info &&
36768b34daaSYevgeny Kliteynik 	       rule->resize_info->state != MLX5DR_RULE_RESIZE_STATE_IDLE;
36868b34daaSYevgeny Kliteynik }
36968b34daaSYevgeny Kliteynik 
370348cdeecSAlex Vesker static int mlx5dr_rule_create_hws_fw_wqe(struct mlx5dr_rule *rule,
371348cdeecSAlex Vesker 					 struct mlx5dr_rule_attr *attr,
372348cdeecSAlex Vesker 					 uint8_t mt_idx,
373348cdeecSAlex Vesker 					 const struct rte_flow_item items[],
374348cdeecSAlex Vesker 					 uint8_t at_idx,
375348cdeecSAlex Vesker 					 struct mlx5dr_rule_action rule_actions[])
376348cdeecSAlex Vesker {
377348cdeecSAlex Vesker 	struct mlx5dr_action_template *at = &rule->matcher->at[at_idx];
378348cdeecSAlex Vesker 	struct mlx5dr_match_template *mt = &rule->matcher->mt[mt_idx];
379348cdeecSAlex Vesker 	struct mlx5dr_send_ring_dep_wqe range_wqe = {{0}};
380348cdeecSAlex Vesker 	struct mlx5dr_send_ring_dep_wqe match_wqe = {{0}};
381348cdeecSAlex Vesker 	bool is_range = mlx5dr_matcher_mt_is_range(mt);
382348cdeecSAlex Vesker 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
383348cdeecSAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
384348cdeecSAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
385348cdeecSAlex Vesker 	struct mlx5dr_send_ste_attr ste_attr = {0};
386348cdeecSAlex Vesker 	struct mlx5dr_actions_apply_data apply;
387348cdeecSAlex Vesker 	struct mlx5dr_send_engine *queue;
388348cdeecSAlex Vesker 
389348cdeecSAlex Vesker 	queue = &ctx->send_queue[attr->queue_id];
390348cdeecSAlex Vesker 	if (unlikely(mlx5dr_send_engine_err(queue))) {
391348cdeecSAlex Vesker 		rte_errno = EIO;
392348cdeecSAlex Vesker 		return rte_errno;
393348cdeecSAlex Vesker 	}
394348cdeecSAlex Vesker 
395fa16feadSErez Shitrit 	mlx5dr_rule_create_init(rule, &ste_attr, &apply, false);
396e28392b3SAlex Vesker 	mlx5dr_rule_init_dep_wqe(&match_wqe, rule, items, mt, attr);
397e28392b3SAlex Vesker 	mlx5dr_rule_init_dep_wqe(&range_wqe, rule, items, mt, attr);
398348cdeecSAlex Vesker 
399348cdeecSAlex Vesker 	ste_attr.direct_index = 0;
400348cdeecSAlex Vesker 	ste_attr.rtc_0 = match_wqe.rtc_0;
401348cdeecSAlex Vesker 	ste_attr.rtc_1 = match_wqe.rtc_1;
402348cdeecSAlex Vesker 	ste_attr.used_id_rtc_0 = &rule->rtc_0;
403348cdeecSAlex Vesker 	ste_attr.used_id_rtc_1 = &rule->rtc_1;
404348cdeecSAlex Vesker 	ste_attr.retry_rtc_0 = match_wqe.retry_rtc_0;
405348cdeecSAlex Vesker 	ste_attr.retry_rtc_1 = match_wqe.retry_rtc_1;
406348cdeecSAlex Vesker 	ste_attr.send_attr.rule = match_wqe.rule;
407348cdeecSAlex Vesker 	ste_attr.send_attr.user_data = match_wqe.user_data;
408348cdeecSAlex Vesker 
409348cdeecSAlex Vesker 	ste_attr.send_attr.fence = 1;
410348cdeecSAlex Vesker 	ste_attr.send_attr.notify_hw = 1;
411348cdeecSAlex Vesker 	ste_attr.wqe_tag_is_jumbo = is_jumbo;
412348cdeecSAlex Vesker 
413348cdeecSAlex Vesker 	/* Prepare match STE TAG */
414348cdeecSAlex Vesker 	ste_attr.wqe_ctrl = &match_wqe.wqe_ctrl;
415348cdeecSAlex Vesker 	ste_attr.wqe_data = &match_wqe.wqe_data;
416348cdeecSAlex Vesker 	ste_attr.send_attr.match_definer_id = mlx5dr_definer_get_id(mt->definer);
417348cdeecSAlex Vesker 
418348cdeecSAlex Vesker 	mlx5dr_definer_create_tag(items,
419348cdeecSAlex Vesker 				  mt->fc,
420348cdeecSAlex Vesker 				  mt->fc_sz,
421348cdeecSAlex Vesker 				  (uint8_t *)match_wqe.wqe_data.action);
422348cdeecSAlex Vesker 
423348cdeecSAlex Vesker 	/* Prepare range STE TAG */
424348cdeecSAlex Vesker 	if (is_range) {
425348cdeecSAlex Vesker 		ste_attr.range_wqe_data = &range_wqe.wqe_data;
426348cdeecSAlex Vesker 		ste_attr.send_attr.len += MLX5DR_WQE_SZ_GTA_DATA;
427348cdeecSAlex Vesker 		ste_attr.send_attr.range_definer_id = mlx5dr_definer_get_id(mt->range_definer);
428348cdeecSAlex Vesker 
429348cdeecSAlex Vesker 		mlx5dr_definer_create_tag_range(items,
430348cdeecSAlex Vesker 						mt->fcr,
431348cdeecSAlex Vesker 						mt->fcr_sz,
432348cdeecSAlex Vesker 						(uint8_t *)range_wqe.wqe_data.action);
433348cdeecSAlex Vesker 	}
434348cdeecSAlex Vesker 
435348cdeecSAlex Vesker 	/* Apply the actions on the last STE */
436348cdeecSAlex Vesker 	apply.queue = queue;
437348cdeecSAlex Vesker 	apply.next_direct_idx = 0;
438348cdeecSAlex Vesker 	apply.rule_action = rule_actions;
439348cdeecSAlex Vesker 	apply.wqe_ctrl = &match_wqe.wqe_ctrl;
440348cdeecSAlex Vesker 	apply.wqe_data = (uint32_t *)(is_range ?
441348cdeecSAlex Vesker 				      &range_wqe.wqe_data :
442348cdeecSAlex Vesker 				      &match_wqe.wqe_data);
443348cdeecSAlex Vesker 
444348cdeecSAlex Vesker 	/* Skip setters[0] used for jumbo STE since not support with FW WQE */
445348cdeecSAlex Vesker 	mlx5dr_action_apply_setter(&apply, &at->setters[1], 0);
446348cdeecSAlex Vesker 
447348cdeecSAlex Vesker 	/* Send WQEs to FW */
448348cdeecSAlex Vesker 	mlx5dr_send_stes_fw(queue, &ste_attr);
449348cdeecSAlex Vesker 
450c54d3949SYevgeny Kliteynik 	/* Backup TAG on the rule for deletion */
451348cdeecSAlex Vesker 	mlx5dr_rule_save_delete_info(rule, &ste_attr);
452348cdeecSAlex Vesker 	mlx5dr_send_engine_inc_rule(queue);
453348cdeecSAlex Vesker 
454348cdeecSAlex Vesker 	/* Send dependent WQEs */
455348cdeecSAlex Vesker 	if (!attr->burst)
456348cdeecSAlex Vesker 		mlx5dr_send_all_dep_wqe(queue);
457348cdeecSAlex Vesker 
458348cdeecSAlex Vesker 	return 0;
459348cdeecSAlex Vesker }
460348cdeecSAlex Vesker 
461405242c5SAlex Vesker static int mlx5dr_rule_create_hws(struct mlx5dr_rule *rule,
462405242c5SAlex Vesker 				  struct mlx5dr_rule_attr *attr,
463405242c5SAlex Vesker 				  uint8_t mt_idx,
464405242c5SAlex Vesker 				  const struct rte_flow_item items[],
465405242c5SAlex Vesker 				  uint8_t at_idx,
466405242c5SAlex Vesker 				  struct mlx5dr_rule_action rule_actions[])
467405242c5SAlex Vesker {
468940b0ebaSAlex Vesker 	struct mlx5dr_action_template *at = &rule->matcher->at[at_idx];
469940b0ebaSAlex Vesker 	struct mlx5dr_match_template *mt = &rule->matcher->mt[mt_idx];
470348cdeecSAlex Vesker 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
471405242c5SAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
472405242c5SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
473405242c5SAlex Vesker 	struct mlx5dr_send_ste_attr ste_attr = {0};
474405242c5SAlex Vesker 	struct mlx5dr_send_ring_dep_wqe *dep_wqe;
475405242c5SAlex Vesker 	struct mlx5dr_actions_wqe_setter *setter;
476405242c5SAlex Vesker 	struct mlx5dr_actions_apply_data apply;
477405242c5SAlex Vesker 	struct mlx5dr_send_engine *queue;
478405242c5SAlex Vesker 	uint8_t total_stes, action_stes;
479fa16feadSErez Shitrit 	bool is_update;
480405242c5SAlex Vesker 	int i, ret;
481405242c5SAlex Vesker 
482fa16feadSErez Shitrit 	is_update = (items == NULL);
483fa16feadSErez Shitrit 
484348cdeecSAlex Vesker 	/* Insert rule using FW WQE if cannot use GTA WQE */
485fa16feadSErez Shitrit 	if (unlikely(mlx5dr_matcher_req_fw_wqe(matcher) && !is_update))
486348cdeecSAlex Vesker 		return mlx5dr_rule_create_hws_fw_wqe(rule, attr, mt_idx, items,
487348cdeecSAlex Vesker 						     at_idx, rule_actions);
488348cdeecSAlex Vesker 
489405242c5SAlex Vesker 	queue = &ctx->send_queue[attr->queue_id];
490405242c5SAlex Vesker 	if (unlikely(mlx5dr_send_engine_err(queue))) {
491405242c5SAlex Vesker 		rte_errno = EIO;
492405242c5SAlex Vesker 		return rte_errno;
493405242c5SAlex Vesker 	}
494405242c5SAlex Vesker 
495fa16feadSErez Shitrit 	mlx5dr_rule_create_init(rule, &ste_attr, &apply, is_update);
496405242c5SAlex Vesker 
497405242c5SAlex Vesker 	/* Allocate dependent match WQE since rule might have dependent writes.
498405242c5SAlex Vesker 	 * The queued dependent WQE can be later aborted or kept as a dependency.
499405242c5SAlex Vesker 	 * dep_wqe buffers (ctrl, data) are also reused for all STE writes.
500405242c5SAlex Vesker 	 */
501405242c5SAlex Vesker 	dep_wqe = mlx5dr_send_add_new_dep_wqe(queue);
502e28392b3SAlex Vesker 	mlx5dr_rule_init_dep_wqe(dep_wqe, rule, items, mt, attr);
503405242c5SAlex Vesker 
504405242c5SAlex Vesker 	ste_attr.wqe_ctrl = &dep_wqe->wqe_ctrl;
505405242c5SAlex Vesker 	ste_attr.wqe_data = &dep_wqe->wqe_data;
506405242c5SAlex Vesker 	apply.wqe_ctrl = &dep_wqe->wqe_ctrl;
507405242c5SAlex Vesker 	apply.wqe_data = (uint32_t *)&dep_wqe->wqe_data;
508405242c5SAlex Vesker 	apply.rule_action = rule_actions;
509405242c5SAlex Vesker 	apply.queue = queue;
510405242c5SAlex Vesker 
511405242c5SAlex Vesker 	setter = &at->setters[at->num_of_action_stes];
512405242c5SAlex Vesker 	total_stes = at->num_of_action_stes + (is_jumbo && !at->only_term);
513405242c5SAlex Vesker 	action_stes = total_stes - 1;
514405242c5SAlex Vesker 
515405242c5SAlex Vesker 	if (action_stes) {
516405242c5SAlex Vesker 		/* Allocate action STEs for complex rules */
517405242c5SAlex Vesker 		ret = mlx5dr_rule_alloc_action_ste(rule, attr);
518405242c5SAlex Vesker 		if (ret) {
519405242c5SAlex Vesker 			DR_LOG(ERR, "Failed to allocate action memory %d", ret);
520405242c5SAlex Vesker 			mlx5dr_send_abort_new_dep_wqe(queue);
521405242c5SAlex Vesker 			return ret;
522405242c5SAlex Vesker 		}
523405242c5SAlex Vesker 		/* Skip RX/TX based on the dep_wqe init */
524405242c5SAlex Vesker 		ste_attr.rtc_0 = dep_wqe->rtc_0 ? matcher->action_ste.rtc_0->id : 0;
525405242c5SAlex Vesker 		ste_attr.rtc_1 = dep_wqe->rtc_1 ? matcher->action_ste.rtc_1->id : 0;
526405242c5SAlex Vesker 		/* Action STEs are written to a specific index last to first */
527405242c5SAlex Vesker 		ste_attr.direct_index = rule->action_ste_idx + action_stes;
528405242c5SAlex Vesker 		apply.next_direct_idx = ste_attr.direct_index;
529405242c5SAlex Vesker 	} else {
530405242c5SAlex Vesker 		apply.next_direct_idx = 0;
531405242c5SAlex Vesker 	}
532405242c5SAlex Vesker 
533405242c5SAlex Vesker 	for (i = total_stes; i-- > 0;) {
534405242c5SAlex Vesker 		mlx5dr_action_apply_setter(&apply, setter--, !i && is_jumbo);
535405242c5SAlex Vesker 
536405242c5SAlex Vesker 		if (i == 0) {
53738b5bf64SYevgeny Kliteynik 			/* Handle last match STE.
53838b5bf64SYevgeny Kliteynik 			 * For hash split / linear lookup RTCs, packets reaching any STE
53938b5bf64SYevgeny Kliteynik 			 * will always match and perform the specified actions, which
54038b5bf64SYevgeny Kliteynik 			 * makes the tag irrelevant.
54138b5bf64SYevgeny Kliteynik 			 */
542*486f9aacSHamdan Igbaria 			if (likely(!mlx5dr_matcher_is_always_hit(matcher) && !is_update))
543405242c5SAlex Vesker 				mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz,
544405242c5SAlex Vesker 							  (uint8_t *)dep_wqe->wqe_data.action);
545fa16feadSErez Shitrit 			else if (unlikely(is_update))
546fa16feadSErez Shitrit 				mlx5dr_rule_update_copy_tag(rule, &dep_wqe->wqe_data, is_jumbo);
547405242c5SAlex Vesker 
548405242c5SAlex Vesker 			/* Rule has dependent WQEs, match dep_wqe is queued */
549405242c5SAlex Vesker 			if (action_stes || apply.require_dep)
550405242c5SAlex Vesker 				break;
551405242c5SAlex Vesker 
552405242c5SAlex Vesker 			/* Rule has no dependencies, abort dep_wqe and send WQE now */
553405242c5SAlex Vesker 			mlx5dr_send_abort_new_dep_wqe(queue);
554405242c5SAlex Vesker 			ste_attr.wqe_tag_is_jumbo = is_jumbo;
555405242c5SAlex Vesker 			ste_attr.send_attr.notify_hw = !attr->burst;
556405242c5SAlex Vesker 			ste_attr.send_attr.user_data = dep_wqe->user_data;
557405242c5SAlex Vesker 			ste_attr.send_attr.rule = dep_wqe->rule;
558405242c5SAlex Vesker 			ste_attr.rtc_0 = dep_wqe->rtc_0;
559405242c5SAlex Vesker 			ste_attr.rtc_1 = dep_wqe->rtc_1;
560405242c5SAlex Vesker 			ste_attr.used_id_rtc_0 = &rule->rtc_0;
561405242c5SAlex Vesker 			ste_attr.used_id_rtc_1 = &rule->rtc_1;
562405242c5SAlex Vesker 			ste_attr.retry_rtc_0 = dep_wqe->retry_rtc_0;
563405242c5SAlex Vesker 			ste_attr.retry_rtc_1 = dep_wqe->retry_rtc_1;
564e28392b3SAlex Vesker 			ste_attr.direct_index = dep_wqe->direct_index;
565405242c5SAlex Vesker 		} else {
566405242c5SAlex Vesker 			apply.next_direct_idx = --ste_attr.direct_index;
567405242c5SAlex Vesker 		}
568405242c5SAlex Vesker 
569405242c5SAlex Vesker 		mlx5dr_send_ste(queue, &ste_attr);
570405242c5SAlex Vesker 	}
571405242c5SAlex Vesker 
572762fecebSYevgeny Kliteynik 	/* Backup TAG on the rule for deletion and resize info for
573762fecebSYevgeny Kliteynik 	 * moving rules to a new matcher, only after insertion.
574762fecebSYevgeny Kliteynik 	 */
575c54d3949SYevgeny Kliteynik 	if (!is_update) {
576348cdeecSAlex Vesker 		mlx5dr_rule_save_delete_info(rule, &ste_attr);
577c54d3949SYevgeny Kliteynik 		mlx5dr_rule_save_resize_info(rule, &ste_attr);
578c54d3949SYevgeny Kliteynik 	}
579fa16feadSErez Shitrit 
580405242c5SAlex Vesker 	mlx5dr_send_engine_inc_rule(queue);
581405242c5SAlex Vesker 
582405242c5SAlex Vesker 	/* Send dependent WQEs */
583405242c5SAlex Vesker 	if (!attr->burst)
584405242c5SAlex Vesker 		mlx5dr_send_all_dep_wqe(queue);
585405242c5SAlex Vesker 
586405242c5SAlex Vesker 	return 0;
587405242c5SAlex Vesker }
588405242c5SAlex Vesker 
589405242c5SAlex Vesker static void mlx5dr_rule_destroy_failed_hws(struct mlx5dr_rule *rule,
590405242c5SAlex Vesker 					   struct mlx5dr_rule_attr *attr)
591405242c5SAlex Vesker {
592405242c5SAlex Vesker 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
593405242c5SAlex Vesker 	struct mlx5dr_send_engine *queue;
594405242c5SAlex Vesker 
595405242c5SAlex Vesker 	queue = &ctx->send_queue[attr->queue_id];
596405242c5SAlex Vesker 
597405242c5SAlex Vesker 	mlx5dr_rule_gen_comp(queue, rule, false,
598405242c5SAlex Vesker 			     attr->user_data, MLX5DR_RULE_STATUS_DELETED);
599405242c5SAlex Vesker 
600405242c5SAlex Vesker 	/* Rule failed now we can safely release action STEs */
601405242c5SAlex Vesker 	mlx5dr_rule_free_action_ste_idx(rule);
602405242c5SAlex Vesker 
603c54d3949SYevgeny Kliteynik 	/* Clear complex tag */
604348cdeecSAlex Vesker 	mlx5dr_rule_clear_delete_info(rule);
605348cdeecSAlex Vesker 
606c54d3949SYevgeny Kliteynik 	/* Clear info that was saved for resizing */
607c54d3949SYevgeny Kliteynik 	mlx5dr_rule_clear_resize_info(rule);
608c54d3949SYevgeny Kliteynik 
609405242c5SAlex Vesker 	/* If a rule that was indicated as burst (need to trigger HW) has failed
610405242c5SAlex Vesker 	 * insertion we won't ring the HW as nothing is being written to the WQ.
611405242c5SAlex Vesker 	 * In such case update the last WQE and ring the HW with that work
612405242c5SAlex Vesker 	 */
613405242c5SAlex Vesker 	if (attr->burst)
614405242c5SAlex Vesker 		return;
615405242c5SAlex Vesker 
616405242c5SAlex Vesker 	mlx5dr_send_all_dep_wqe(queue);
617405242c5SAlex Vesker 	mlx5dr_send_engine_flush_queue(queue);
618405242c5SAlex Vesker }
619405242c5SAlex Vesker 
620405242c5SAlex Vesker static int mlx5dr_rule_destroy_hws(struct mlx5dr_rule *rule,
621405242c5SAlex Vesker 				   struct mlx5dr_rule_attr *attr)
622405242c5SAlex Vesker {
623405242c5SAlex Vesker 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
624405242c5SAlex Vesker 	struct mlx5dr_matcher *matcher = rule->matcher;
625348cdeecSAlex Vesker 	bool fw_wqe = mlx5dr_matcher_req_fw_wqe(matcher);
626348cdeecSAlex Vesker 	bool is_range = mlx5dr_matcher_mt_is_range(matcher->mt);
627348cdeecSAlex Vesker 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt);
628405242c5SAlex Vesker 	struct mlx5dr_wqe_gta_ctrl_seg wqe_ctrl = {0};
629405242c5SAlex Vesker 	struct mlx5dr_send_ste_attr ste_attr = {0};
630405242c5SAlex Vesker 	struct mlx5dr_send_engine *queue;
631405242c5SAlex Vesker 
632405242c5SAlex Vesker 	queue = &ctx->send_queue[attr->queue_id];
633405242c5SAlex Vesker 
634938646d9SAlex Vesker 	if (unlikely(mlx5dr_send_engine_err(queue))) {
635938646d9SAlex Vesker 		mlx5dr_rule_destroy_failed_hws(rule, attr);
636938646d9SAlex Vesker 		return 0;
637938646d9SAlex Vesker 	}
638938646d9SAlex Vesker 
639405242c5SAlex Vesker 	/* Rule is not completed yet */
640405242c5SAlex Vesker 	if (rule->status == MLX5DR_RULE_STATUS_CREATING) {
6410573a392SGavin Li 		DR_LOG(NOTICE, "Cannot destroy, rule creation still in progress");
642405242c5SAlex Vesker 		rte_errno = EBUSY;
643405242c5SAlex Vesker 		return rte_errno;
644405242c5SAlex Vesker 	}
645405242c5SAlex Vesker 
646405242c5SAlex Vesker 	/* Rule failed and doesn't require cleanup */
647405242c5SAlex Vesker 	if (rule->status == MLX5DR_RULE_STATUS_FAILED) {
648405242c5SAlex Vesker 		mlx5dr_rule_destroy_failed_hws(rule, attr);
649405242c5SAlex Vesker 		return 0;
650405242c5SAlex Vesker 	}
651405242c5SAlex Vesker 
652405242c5SAlex Vesker 	mlx5dr_send_engine_inc_rule(queue);
653405242c5SAlex Vesker 
654405242c5SAlex Vesker 	/* Send dependent WQE */
655405242c5SAlex Vesker 	if (!attr->burst)
656405242c5SAlex Vesker 		mlx5dr_send_all_dep_wqe(queue);
657405242c5SAlex Vesker 
658405242c5SAlex Vesker 	rule->status = MLX5DR_RULE_STATUS_DELETING;
659405242c5SAlex Vesker 
660405242c5SAlex Vesker 	ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
661405242c5SAlex Vesker 	ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
662405242c5SAlex Vesker 	ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
663348cdeecSAlex Vesker 	if (unlikely(is_range))
664348cdeecSAlex Vesker 		ste_attr.send_attr.len += MLX5DR_WQE_SZ_GTA_DATA;
665405242c5SAlex Vesker 
666405242c5SAlex Vesker 	ste_attr.send_attr.rule = rule;
667405242c5SAlex Vesker 	ste_attr.send_attr.notify_hw = !attr->burst;
668405242c5SAlex Vesker 	ste_attr.send_attr.user_data = attr->user_data;
669405242c5SAlex Vesker 
670405242c5SAlex Vesker 	ste_attr.rtc_0 = rule->rtc_0;
671405242c5SAlex Vesker 	ste_attr.rtc_1 = rule->rtc_1;
672405242c5SAlex Vesker 	ste_attr.used_id_rtc_0 = &rule->rtc_0;
673405242c5SAlex Vesker 	ste_attr.used_id_rtc_1 = &rule->rtc_1;
674405242c5SAlex Vesker 	ste_attr.wqe_ctrl = &wqe_ctrl;
675348cdeecSAlex Vesker 	ste_attr.wqe_tag_is_jumbo = is_jumbo;
676405242c5SAlex Vesker 	ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_DEACTIVATE;
67738b5bf64SYevgeny Kliteynik 	if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
67838b5bf64SYevgeny Kliteynik 		ste_attr.direct_index = attr->rule_idx;
679405242c5SAlex Vesker 
680348cdeecSAlex Vesker 	mlx5dr_rule_load_delete_info(rule, &ste_attr);
681348cdeecSAlex Vesker 
682762fecebSYevgeny Kliteynik 	if (unlikely(fw_wqe))
683348cdeecSAlex Vesker 		mlx5dr_send_stes_fw(queue, &ste_attr);
684762fecebSYevgeny Kliteynik 	else
685405242c5SAlex Vesker 		mlx5dr_send_ste(queue, &ste_attr);
686762fecebSYevgeny Kliteynik 
687762fecebSYevgeny Kliteynik 	mlx5dr_rule_clear_delete_info(rule);
688405242c5SAlex Vesker 
689405242c5SAlex Vesker 	return 0;
690405242c5SAlex Vesker }
691405242c5SAlex Vesker 
692fcee5d78SYevgeny Kliteynik int mlx5dr_rule_create_root_no_comp(struct mlx5dr_rule *rule,
693405242c5SAlex Vesker 				    const struct rte_flow_item items[],
694fcee5d78SYevgeny Kliteynik 				    uint8_t num_actions,
695405242c5SAlex Vesker 				    struct mlx5dr_rule_action rule_actions[])
696405242c5SAlex Vesker {
697405242c5SAlex Vesker 	struct mlx5dv_flow_matcher *dv_matcher = rule->matcher->dv_matcher;
698befb138bSAlex Vesker 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
699405242c5SAlex Vesker 	struct mlx5dv_flow_match_parameters *value;
700405242c5SAlex Vesker 	struct mlx5_flow_attr flow_attr = {0};
701405242c5SAlex Vesker 	struct mlx5dv_flow_action_attr *attr;
702405242c5SAlex Vesker 	struct rte_flow_error error;
703405242c5SAlex Vesker 	uint8_t match_criteria;
704405242c5SAlex Vesker 	int ret;
705405242c5SAlex Vesker 
706befb138bSAlex Vesker 	ret = flow_hw_get_port_id_from_ctx(ctx, &flow_attr.port_id);
707572fe9efSErez Shitrit 	if (ret) {
708befb138bSAlex Vesker 		DR_LOG(ERR, "Failed to get port id for dev %s", ctx->ibv_ctx->device->name);
709572fe9efSErez Shitrit 		rte_errno = EINVAL;
710572fe9efSErez Shitrit 		return rte_errno;
711572fe9efSErez Shitrit 	}
712572fe9efSErez Shitrit 
713405242c5SAlex Vesker 	attr = simple_calloc(num_actions, sizeof(*attr));
714405242c5SAlex Vesker 	if (!attr) {
715405242c5SAlex Vesker 		rte_errno = ENOMEM;
716405242c5SAlex Vesker 		return rte_errno;
717405242c5SAlex Vesker 	}
718405242c5SAlex Vesker 
719405242c5SAlex Vesker 	value = simple_calloc(1, MLX5_ST_SZ_BYTES(fte_match_param) +
720405242c5SAlex Vesker 			      offsetof(struct mlx5dv_flow_match_parameters, match_buf));
721405242c5SAlex Vesker 	if (!value) {
722405242c5SAlex Vesker 		rte_errno = ENOMEM;
723405242c5SAlex Vesker 		goto free_attr;
724405242c5SAlex Vesker 	}
725405242c5SAlex Vesker 
726405242c5SAlex Vesker 	flow_attr.tbl_type = rule->matcher->tbl->type;
727405242c5SAlex Vesker 
728405242c5SAlex Vesker 	ret = flow_dv_translate_items_hws(items, &flow_attr, value->match_buf,
729405242c5SAlex Vesker 					  MLX5_SET_MATCHER_HS_V, NULL,
730405242c5SAlex Vesker 					  &match_criteria,
731405242c5SAlex Vesker 					  &error);
732405242c5SAlex Vesker 	if (ret) {
733405242c5SAlex Vesker 		DR_LOG(ERR, "Failed to convert items to PRM [%s]", error.message);
734405242c5SAlex Vesker 		goto free_value;
735405242c5SAlex Vesker 	}
736405242c5SAlex Vesker 
737405242c5SAlex Vesker 	/* Convert actions to verb action attr */
738405242c5SAlex Vesker 	ret = mlx5dr_action_root_build_attr(rule_actions, num_actions, attr);
739405242c5SAlex Vesker 	if (ret)
740405242c5SAlex Vesker 		goto free_value;
741405242c5SAlex Vesker 
742405242c5SAlex Vesker 	/* Create verb flow */
743405242c5SAlex Vesker 	value->match_sz = MLX5_ST_SZ_BYTES(fte_match_param);
744405242c5SAlex Vesker 	rule->flow = mlx5_glue->dv_create_flow_root(dv_matcher,
745405242c5SAlex Vesker 						    value,
746405242c5SAlex Vesker 						    num_actions,
747405242c5SAlex Vesker 						    attr);
748405242c5SAlex Vesker 
749405242c5SAlex Vesker 	simple_free(value);
750405242c5SAlex Vesker 	simple_free(attr);
751405242c5SAlex Vesker 
752405242c5SAlex Vesker 	return 0;
753405242c5SAlex Vesker 
754405242c5SAlex Vesker free_value:
755405242c5SAlex Vesker 	simple_free(value);
756405242c5SAlex Vesker free_attr:
757405242c5SAlex Vesker 	simple_free(attr);
758405242c5SAlex Vesker 
759ba2c2679SYevgeny Kliteynik 	return rte_errno;
760405242c5SAlex Vesker }
761405242c5SAlex Vesker 
762fcee5d78SYevgeny Kliteynik static int mlx5dr_rule_create_root(struct mlx5dr_rule *rule,
763fcee5d78SYevgeny Kliteynik 				   struct mlx5dr_rule_attr *rule_attr,
764fcee5d78SYevgeny Kliteynik 				   const struct rte_flow_item items[],
765fcee5d78SYevgeny Kliteynik 				   uint8_t num_actions,
766fcee5d78SYevgeny Kliteynik 				   struct mlx5dr_rule_action rule_actions[])
767fcee5d78SYevgeny Kliteynik {
768fcee5d78SYevgeny Kliteynik 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
769fcee5d78SYevgeny Kliteynik 	int ret;
770fcee5d78SYevgeny Kliteynik 
771fcee5d78SYevgeny Kliteynik 	ret = mlx5dr_rule_create_root_no_comp(rule, items,
772fcee5d78SYevgeny Kliteynik 					      num_actions, rule_actions);
773fcee5d78SYevgeny Kliteynik 	if (ret)
774fcee5d78SYevgeny Kliteynik 		return rte_errno;
775fcee5d78SYevgeny Kliteynik 
776fcee5d78SYevgeny Kliteynik 	mlx5dr_rule_gen_comp(&ctx->send_queue[rule_attr->queue_id], rule, !rule->flow,
777fcee5d78SYevgeny Kliteynik 			     rule_attr->user_data, MLX5DR_RULE_STATUS_CREATED);
778fcee5d78SYevgeny Kliteynik 
779fcee5d78SYevgeny Kliteynik 	return 0;
780fcee5d78SYevgeny Kliteynik }
781fcee5d78SYevgeny Kliteynik 
782fcee5d78SYevgeny Kliteynik int mlx5dr_rule_destroy_root_no_comp(struct mlx5dr_rule *rule)
783fcee5d78SYevgeny Kliteynik {
784fcee5d78SYevgeny Kliteynik 	if (rule->flow)
785fcee5d78SYevgeny Kliteynik 		return ibv_destroy_flow(rule->flow);
786fcee5d78SYevgeny Kliteynik 
787fcee5d78SYevgeny Kliteynik 	return 0;
788fcee5d78SYevgeny Kliteynik }
789fcee5d78SYevgeny Kliteynik 
790405242c5SAlex Vesker static int mlx5dr_rule_destroy_root(struct mlx5dr_rule *rule,
791405242c5SAlex Vesker 				    struct mlx5dr_rule_attr *attr)
792405242c5SAlex Vesker {
793405242c5SAlex Vesker 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
794fcee5d78SYevgeny Kliteynik 	int err;
795405242c5SAlex Vesker 
796fcee5d78SYevgeny Kliteynik 	err = mlx5dr_rule_destroy_root_no_comp(rule);
797405242c5SAlex Vesker 
798405242c5SAlex Vesker 	mlx5dr_rule_gen_comp(&ctx->send_queue[attr->queue_id], rule, err,
799405242c5SAlex Vesker 			     attr->user_data, MLX5DR_RULE_STATUS_DELETED);
800405242c5SAlex Vesker 
801405242c5SAlex Vesker 	return 0;
802405242c5SAlex Vesker }
803405242c5SAlex Vesker 
804762fecebSYevgeny Kliteynik static int mlx5dr_rule_enqueue_precheck(struct mlx5dr_rule *rule,
80580f28422SErez Shitrit 					struct mlx5dr_rule_attr *attr)
80680f28422SErez Shitrit {
807762fecebSYevgeny Kliteynik 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
808762fecebSYevgeny Kliteynik 
80980f28422SErez Shitrit 	if (unlikely(!attr->user_data)) {
8100573a392SGavin Li 		DR_LOG(DEBUG, "User data must be provided for rule operations");
81180f28422SErez Shitrit 		rte_errno = EINVAL;
81280f28422SErez Shitrit 		return rte_errno;
81380f28422SErez Shitrit 	}
81480f28422SErez Shitrit 
81580f28422SErez Shitrit 	/* Check if there is room in queue */
81680f28422SErez Shitrit 	if (unlikely(mlx5dr_send_engine_full(&ctx->send_queue[attr->queue_id]))) {
8170573a392SGavin Li 		DR_LOG(NOTICE, "No room in queue[%d]", attr->queue_id);
81880f28422SErez Shitrit 		rte_errno = EBUSY;
81980f28422SErez Shitrit 		return rte_errno;
82080f28422SErez Shitrit 	}
82180f28422SErez Shitrit 
82280f28422SErez Shitrit 	return 0;
82380f28422SErez Shitrit }
82480f28422SErez Shitrit 
825762fecebSYevgeny Kliteynik static int mlx5dr_rule_enqueue_precheck_move(struct mlx5dr_rule *rule,
826762fecebSYevgeny Kliteynik 					     struct mlx5dr_rule_attr *attr)
827762fecebSYevgeny Kliteynik {
828762fecebSYevgeny Kliteynik 	if (unlikely(rule->status != MLX5DR_RULE_STATUS_CREATED)) {
8290573a392SGavin Li 		DR_LOG(DEBUG, "Cannot move, rule status is invalid");
830762fecebSYevgeny Kliteynik 		rte_errno = EINVAL;
831762fecebSYevgeny Kliteynik 		return rte_errno;
832762fecebSYevgeny Kliteynik 	}
833762fecebSYevgeny Kliteynik 
834762fecebSYevgeny Kliteynik 	return mlx5dr_rule_enqueue_precheck(rule, attr);
835762fecebSYevgeny Kliteynik }
836762fecebSYevgeny Kliteynik 
837762fecebSYevgeny Kliteynik static int mlx5dr_rule_enqueue_precheck_create(struct mlx5dr_rule *rule,
838762fecebSYevgeny Kliteynik 					       struct mlx5dr_rule_attr *attr)
839762fecebSYevgeny Kliteynik {
840762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_matcher_is_in_resize(rule->matcher))) {
841762fecebSYevgeny Kliteynik 		/* Matcher in resize - new rules are not allowed */
8420573a392SGavin Li 		DR_LOG(NOTICE, "Resizing in progress, cannot create rule");
843762fecebSYevgeny Kliteynik 		rte_errno = EAGAIN;
844762fecebSYevgeny Kliteynik 		return rte_errno;
845762fecebSYevgeny Kliteynik 	}
846762fecebSYevgeny Kliteynik 
847762fecebSYevgeny Kliteynik 	return mlx5dr_rule_enqueue_precheck(rule, attr);
848762fecebSYevgeny Kliteynik }
849762fecebSYevgeny Kliteynik 
850762fecebSYevgeny Kliteynik static int mlx5dr_rule_enqueue_precheck_update(struct mlx5dr_rule *rule,
851762fecebSYevgeny Kliteynik 					       struct mlx5dr_rule_attr *attr)
852762fecebSYevgeny Kliteynik {
853762fecebSYevgeny Kliteynik 	struct mlx5dr_matcher *matcher = rule->matcher;
854762fecebSYevgeny Kliteynik 
855762fecebSYevgeny Kliteynik 	if (unlikely((mlx5dr_table_is_root(matcher->tbl) ||
856762fecebSYevgeny Kliteynik 		     mlx5dr_matcher_req_fw_wqe(matcher)))) {
857762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Rule update is not supported on current matcher");
858762fecebSYevgeny Kliteynik 		rte_errno = ENOTSUP;
859762fecebSYevgeny Kliteynik 		return rte_errno;
860762fecebSYevgeny Kliteynik 	}
861762fecebSYevgeny Kliteynik 
862762fecebSYevgeny Kliteynik 	if (unlikely(!matcher->attr.optimize_using_rule_idx &&
863762fecebSYevgeny Kliteynik 		     !mlx5dr_matcher_is_insert_by_idx(matcher))) {
864762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Rule update requires optimize by idx matcher");
865762fecebSYevgeny Kliteynik 		rte_errno = ENOTSUP;
866762fecebSYevgeny Kliteynik 		return rte_errno;
867762fecebSYevgeny Kliteynik 	}
868762fecebSYevgeny Kliteynik 
869762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_matcher_is_resizable(rule->matcher))) {
870762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Rule update is not supported on resizable matcher");
871762fecebSYevgeny Kliteynik 		rte_errno = ENOTSUP;
872762fecebSYevgeny Kliteynik 		return rte_errno;
873762fecebSYevgeny Kliteynik 	}
874762fecebSYevgeny Kliteynik 
875762fecebSYevgeny Kliteynik 	if (unlikely(rule->status != MLX5DR_RULE_STATUS_CREATED)) {
876762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Current rule status does not allow update");
877762fecebSYevgeny Kliteynik 		rte_errno = EBUSY;
878762fecebSYevgeny Kliteynik 		return rte_errno;
879762fecebSYevgeny Kliteynik 	}
880762fecebSYevgeny Kliteynik 
881762fecebSYevgeny Kliteynik 	return mlx5dr_rule_enqueue_precheck_create(rule, attr);
882762fecebSYevgeny Kliteynik }
883762fecebSYevgeny Kliteynik 
884762fecebSYevgeny Kliteynik int mlx5dr_rule_move_hws_remove(struct mlx5dr_rule *rule,
885762fecebSYevgeny Kliteynik 				void *queue_ptr,
886762fecebSYevgeny Kliteynik 				void *user_data)
887762fecebSYevgeny Kliteynik {
888762fecebSYevgeny Kliteynik 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(rule->matcher->mt);
889762fecebSYevgeny Kliteynik 	struct mlx5dr_wqe_gta_ctrl_seg empty_wqe_ctrl = {0};
890762fecebSYevgeny Kliteynik 	struct mlx5dr_matcher *matcher = rule->matcher;
891762fecebSYevgeny Kliteynik 	struct mlx5dr_send_engine *queue = queue_ptr;
892762fecebSYevgeny Kliteynik 	struct mlx5dr_send_ste_attr ste_attr = {0};
893762fecebSYevgeny Kliteynik 
894762fecebSYevgeny Kliteynik 	/* Send dependent WQEs */
895762fecebSYevgeny Kliteynik 	mlx5dr_send_all_dep_wqe(queue);
896762fecebSYevgeny Kliteynik 
897762fecebSYevgeny Kliteynik 	rule->resize_info->state = MLX5DR_RULE_RESIZE_STATE_DELETING;
898762fecebSYevgeny Kliteynik 
899762fecebSYevgeny Kliteynik 	ste_attr.send_attr.fence = 0;
900762fecebSYevgeny Kliteynik 	ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
901762fecebSYevgeny Kliteynik 	ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
902762fecebSYevgeny Kliteynik 	ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
903762fecebSYevgeny Kliteynik 	ste_attr.send_attr.rule = rule;
904762fecebSYevgeny Kliteynik 	ste_attr.send_attr.notify_hw = 1;
905762fecebSYevgeny Kliteynik 	ste_attr.send_attr.user_data = user_data;
906762fecebSYevgeny Kliteynik 	ste_attr.rtc_0 = rule->resize_info->rtc_0;
907762fecebSYevgeny Kliteynik 	ste_attr.rtc_1 = rule->resize_info->rtc_1;
908762fecebSYevgeny Kliteynik 	ste_attr.used_id_rtc_0 = &rule->resize_info->rtc_0;
909762fecebSYevgeny Kliteynik 	ste_attr.used_id_rtc_1 = &rule->resize_info->rtc_1;
910762fecebSYevgeny Kliteynik 	ste_attr.wqe_ctrl = &empty_wqe_ctrl;
911762fecebSYevgeny Kliteynik 	ste_attr.wqe_tag_is_jumbo = is_jumbo;
912762fecebSYevgeny Kliteynik 	ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_DEACTIVATE;
913762fecebSYevgeny Kliteynik 
914762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_matcher_is_insert_by_idx(matcher)))
915762fecebSYevgeny Kliteynik 		ste_attr.direct_index = rule->resize_info->rule_idx;
916762fecebSYevgeny Kliteynik 
917762fecebSYevgeny Kliteynik 	mlx5dr_rule_load_delete_info(rule, &ste_attr);
918762fecebSYevgeny Kliteynik 	mlx5dr_send_ste(queue, &ste_attr);
919762fecebSYevgeny Kliteynik 
920762fecebSYevgeny Kliteynik 	return 0;
921762fecebSYevgeny Kliteynik }
922762fecebSYevgeny Kliteynik 
923762fecebSYevgeny Kliteynik int mlx5dr_rule_move_hws_add(struct mlx5dr_rule *rule,
924762fecebSYevgeny Kliteynik 			     struct mlx5dr_rule_attr *attr)
925762fecebSYevgeny Kliteynik {
926762fecebSYevgeny Kliteynik 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(rule->matcher->mt);
927762fecebSYevgeny Kliteynik 	struct mlx5dr_context *ctx = rule->matcher->tbl->ctx;
928762fecebSYevgeny Kliteynik 	struct mlx5dr_matcher *matcher = rule->matcher;
929762fecebSYevgeny Kliteynik 	struct mlx5dr_send_ste_attr ste_attr = {0};
930762fecebSYevgeny Kliteynik 	struct mlx5dr_send_engine *queue;
931762fecebSYevgeny Kliteynik 
932762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_rule_enqueue_precheck_move(rule, attr)))
933762fecebSYevgeny Kliteynik 		return -rte_errno;
934762fecebSYevgeny Kliteynik 
935762fecebSYevgeny Kliteynik 	queue = &ctx->send_queue[attr->queue_id];
936762fecebSYevgeny Kliteynik 
937762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_send_engine_err(queue))) {
938762fecebSYevgeny Kliteynik 		rte_errno = EIO;
939762fecebSYevgeny Kliteynik 		return rte_errno;
940762fecebSYevgeny Kliteynik 	}
941762fecebSYevgeny Kliteynik 
942762fecebSYevgeny Kliteynik 	mlx5dr_rule_move_init(rule, attr);
943762fecebSYevgeny Kliteynik 
944762fecebSYevgeny Kliteynik 	mlx5dr_rule_move_get_rtc(rule, &ste_attr);
945762fecebSYevgeny Kliteynik 
946762fecebSYevgeny Kliteynik 	ste_attr.send_attr.opmod = MLX5DR_WQE_GTA_OPMOD_STE;
947762fecebSYevgeny Kliteynik 	ste_attr.send_attr.opcode = MLX5DR_WQE_OPCODE_TBL_ACCESS;
948762fecebSYevgeny Kliteynik 	ste_attr.send_attr.len = MLX5DR_WQE_SZ_GTA_CTRL + MLX5DR_WQE_SZ_GTA_DATA;
949762fecebSYevgeny Kliteynik 	ste_attr.gta_opcode = MLX5DR_WQE_GTA_OP_ACTIVATE;
950762fecebSYevgeny Kliteynik 	ste_attr.wqe_tag_is_jumbo = is_jumbo;
951762fecebSYevgeny Kliteynik 
952762fecebSYevgeny Kliteynik 	ste_attr.send_attr.rule = rule;
953762fecebSYevgeny Kliteynik 	ste_attr.send_attr.fence = 0;
954762fecebSYevgeny Kliteynik 	ste_attr.send_attr.notify_hw = !attr->burst;
955762fecebSYevgeny Kliteynik 	ste_attr.send_attr.user_data = attr->user_data;
956762fecebSYevgeny Kliteynik 
957762fecebSYevgeny Kliteynik 	ste_attr.used_id_rtc_0 = &rule->rtc_0;
958762fecebSYevgeny Kliteynik 	ste_attr.used_id_rtc_1 = &rule->rtc_1;
959762fecebSYevgeny Kliteynik 	ste_attr.wqe_ctrl = (struct mlx5dr_wqe_gta_ctrl_seg *)rule->resize_info->ctrl_seg;
960762fecebSYevgeny Kliteynik 	ste_attr.wqe_data = (struct mlx5dr_wqe_gta_data_seg_ste *)rule->resize_info->data_seg;
961762fecebSYevgeny Kliteynik 	ste_attr.direct_index = mlx5dr_matcher_is_insert_by_idx(matcher) ?
962762fecebSYevgeny Kliteynik 				attr->rule_idx : 0;
963762fecebSYevgeny Kliteynik 
964762fecebSYevgeny Kliteynik 	mlx5dr_send_ste(queue, &ste_attr);
965762fecebSYevgeny Kliteynik 	mlx5dr_send_engine_inc_rule(queue);
966762fecebSYevgeny Kliteynik 
967762fecebSYevgeny Kliteynik 	/* Send dependent WQEs */
968762fecebSYevgeny Kliteynik 	if (!attr->burst)
969762fecebSYevgeny Kliteynik 		mlx5dr_send_all_dep_wqe(queue);
970762fecebSYevgeny Kliteynik 
971762fecebSYevgeny Kliteynik 	return 0;
972762fecebSYevgeny Kliteynik }
973762fecebSYevgeny Kliteynik 
974405242c5SAlex Vesker int mlx5dr_rule_create(struct mlx5dr_matcher *matcher,
975405242c5SAlex Vesker 		       uint8_t mt_idx,
976405242c5SAlex Vesker 		       const struct rte_flow_item items[],
977405242c5SAlex Vesker 		       uint8_t at_idx,
978405242c5SAlex Vesker 		       struct mlx5dr_rule_action rule_actions[],
979405242c5SAlex Vesker 		       struct mlx5dr_rule_attr *attr,
980405242c5SAlex Vesker 		       struct mlx5dr_rule *rule_handle)
981405242c5SAlex Vesker {
982405242c5SAlex Vesker 	int ret;
983405242c5SAlex Vesker 
984405242c5SAlex Vesker 	rule_handle->matcher = matcher;
985405242c5SAlex Vesker 
986762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_rule_enqueue_precheck_create(rule_handle, attr)))
987405242c5SAlex Vesker 		return -rte_errno;
988405242c5SAlex Vesker 
989405242c5SAlex Vesker 	assert(matcher->num_of_mt >= mt_idx);
990405242c5SAlex Vesker 	assert(matcher->num_of_at >= at_idx);
991fa16feadSErez Shitrit 	assert(items);
992405242c5SAlex Vesker 
993405242c5SAlex Vesker 	if (unlikely(mlx5dr_table_is_root(matcher->tbl)))
994405242c5SAlex Vesker 		ret = mlx5dr_rule_create_root(rule_handle,
995405242c5SAlex Vesker 					      attr,
996405242c5SAlex Vesker 					      items,
997fcee5d78SYevgeny Kliteynik 					      matcher->at[at_idx].num_actions,
998405242c5SAlex Vesker 					      rule_actions);
999405242c5SAlex Vesker 	else
1000405242c5SAlex Vesker 		ret = mlx5dr_rule_create_hws(rule_handle,
1001405242c5SAlex Vesker 					     attr,
1002405242c5SAlex Vesker 					     mt_idx,
1003405242c5SAlex Vesker 					     items,
1004405242c5SAlex Vesker 					     at_idx,
1005405242c5SAlex Vesker 					     rule_actions);
1006405242c5SAlex Vesker 	return -ret;
1007405242c5SAlex Vesker }
1008405242c5SAlex Vesker 
1009405242c5SAlex Vesker int mlx5dr_rule_destroy(struct mlx5dr_rule *rule,
1010405242c5SAlex Vesker 			struct mlx5dr_rule_attr *attr)
1011405242c5SAlex Vesker {
1012405242c5SAlex Vesker 	int ret;
1013405242c5SAlex Vesker 
1014762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_rule_enqueue_precheck(rule, attr)))
1015405242c5SAlex Vesker 		return -rte_errno;
1016405242c5SAlex Vesker 
1017405242c5SAlex Vesker 	if (unlikely(mlx5dr_table_is_root(rule->matcher->tbl)))
1018405242c5SAlex Vesker 		ret = mlx5dr_rule_destroy_root(rule, attr);
1019405242c5SAlex Vesker 	else
1020405242c5SAlex Vesker 		ret = mlx5dr_rule_destroy_hws(rule, attr);
1021405242c5SAlex Vesker 
1022405242c5SAlex Vesker 	return -ret;
1023405242c5SAlex Vesker }
1024405242c5SAlex Vesker 
1025fa16feadSErez Shitrit int mlx5dr_rule_action_update(struct mlx5dr_rule *rule_handle,
1026fa16feadSErez Shitrit 			      uint8_t at_idx,
1027fa16feadSErez Shitrit 			      struct mlx5dr_rule_action rule_actions[],
1028fa16feadSErez Shitrit 			      struct mlx5dr_rule_attr *attr)
1029fa16feadSErez Shitrit {
1030fa16feadSErez Shitrit 	int ret;
1031fa16feadSErez Shitrit 
1032762fecebSYevgeny Kliteynik 	if (unlikely(mlx5dr_rule_enqueue_precheck_update(rule_handle, attr)))
1033fa16feadSErez Shitrit 		return -rte_errno;
1034fa16feadSErez Shitrit 
1035e7594a81SHamdan Igbaria 	if (rule_handle->status != MLX5DR_RULE_STATUS_CREATED) {
1036e7594a81SHamdan Igbaria 		DR_LOG(ERR, "Current rule status does not allow update");
1037e7594a81SHamdan Igbaria 		rte_errno = EBUSY;
1038e7594a81SHamdan Igbaria 		return -rte_errno;
1039e7594a81SHamdan Igbaria 	}
1040e7594a81SHamdan Igbaria 
1041fa16feadSErez Shitrit 	ret = mlx5dr_rule_create_hws(rule_handle,
1042fa16feadSErez Shitrit 				     attr,
1043fa16feadSErez Shitrit 				     0,
1044fa16feadSErez Shitrit 				     NULL,
1045fa16feadSErez Shitrit 				     at_idx,
1046fa16feadSErez Shitrit 				     rule_actions);
1047fa16feadSErez Shitrit 
1048fa16feadSErez Shitrit 	return -ret;
1049fa16feadSErez Shitrit }
1050fa16feadSErez Shitrit 
1051405242c5SAlex Vesker size_t mlx5dr_rule_get_handle_size(void)
1052405242c5SAlex Vesker {
1053405242c5SAlex Vesker 	return sizeof(struct mlx5dr_rule);
1054405242c5SAlex Vesker }
10557f5e6de5SItamar Gozlan 
10567f5e6de5SItamar Gozlan int mlx5dr_rule_hash_calculate(struct mlx5dr_matcher *matcher,
10577f5e6de5SItamar Gozlan 			       const struct rte_flow_item items[],
10587f5e6de5SItamar Gozlan 			       uint8_t mt_idx,
10597f5e6de5SItamar Gozlan 			       enum mlx5dr_rule_hash_calc_mode mode,
10607f5e6de5SItamar Gozlan 			       uint32_t *ret_hash)
10617f5e6de5SItamar Gozlan {
1062762fecebSYevgeny Kliteynik 	uint8_t tag[MLX5DR_WQE_SZ_GTA_DATA] = {0};
10637f5e6de5SItamar Gozlan 	struct mlx5dr_match_template *mt;
10647f5e6de5SItamar Gozlan 
10657f5e6de5SItamar Gozlan 	if (!matcher || !matcher->mt) {
10667f5e6de5SItamar Gozlan 		rte_errno = EINVAL;
10677f5e6de5SItamar Gozlan 		return -rte_errno;
10687f5e6de5SItamar Gozlan 	}
10697f5e6de5SItamar Gozlan 
10707f5e6de5SItamar Gozlan 	mt = &matcher->mt[mt_idx];
10717f5e6de5SItamar Gozlan 
10727f5e6de5SItamar Gozlan 	if (mlx5dr_matcher_req_fw_wqe(matcher) ||
10737f5e6de5SItamar Gozlan 	    mlx5dr_table_is_root(matcher->tbl) ||
10747f5e6de5SItamar Gozlan 	    matcher->tbl->ctx->caps->access_index_mode == MLX5DR_MATCHER_INSERT_BY_HASH ||
10757f5e6de5SItamar Gozlan 	    matcher->tbl->ctx->caps->flow_table_hash_type != MLX5_FLOW_TABLE_HASH_TYPE_CRC32) {
10760573a392SGavin Li 		DR_LOG(DEBUG, "Matcher is not supported");
10777f5e6de5SItamar Gozlan 		rte_errno = ENOTSUP;
10787f5e6de5SItamar Gozlan 		return -rte_errno;
10797f5e6de5SItamar Gozlan 	}
10807f5e6de5SItamar Gozlan 
10817f5e6de5SItamar Gozlan 	mlx5dr_definer_create_tag(items, mt->fc, mt->fc_sz, tag);
10827f5e6de5SItamar Gozlan 	if (mlx5dr_matcher_mt_is_jumbo(mt))
10837f5e6de5SItamar Gozlan 		*ret_hash = mlx5dr_crc32_calc(tag, MLX5DR_JUMBO_TAG_SZ);
10847f5e6de5SItamar Gozlan 	else
10857f5e6de5SItamar Gozlan 		*ret_hash = mlx5dr_crc32_calc(tag + MLX5DR_ACTIONS_SZ,
10867f5e6de5SItamar Gozlan 					      MLX5DR_MATCH_TAG_SZ);
10877f5e6de5SItamar Gozlan 
10887f5e6de5SItamar Gozlan 	if (mode == MLX5DR_RULE_HASH_CALC_MODE_IDX)
10897f5e6de5SItamar Gozlan 		*ret_hash = *ret_hash & (BIT(matcher->attr.rule.num_log) - 1);
10907f5e6de5SItamar Gozlan 
10917f5e6de5SItamar Gozlan 	return 0;
10927f5e6de5SItamar Gozlan }
1093