xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_matcher.c (revision 486f9aac0cbe2598a76c853890c1d557747f71cf)
1c4676082SAlex Vesker /* SPDX-License-Identifier: BSD-3-Clause
2c4676082SAlex Vesker  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3c4676082SAlex Vesker  */
4c4676082SAlex Vesker 
5c4676082SAlex Vesker #include "mlx5dr_internal.h"
6c4676082SAlex Vesker 
738b5bf64SYevgeny Kliteynik enum mlx5dr_matcher_rtc_type {
838b5bf64SYevgeny Kliteynik 	DR_MATCHER_RTC_TYPE_MATCH,
938b5bf64SYevgeny Kliteynik 	DR_MATCHER_RTC_TYPE_STE_ARRAY,
1038b5bf64SYevgeny Kliteynik 	DR_MATCHER_RTC_TYPE_MAX,
1138b5bf64SYevgeny Kliteynik };
1238b5bf64SYevgeny Kliteynik 
1338b5bf64SYevgeny Kliteynik static const char * const mlx5dr_matcher_rtc_type_str[] = {
1438b5bf64SYevgeny Kliteynik 	[DR_MATCHER_RTC_TYPE_MATCH] = "MATCH",
1538b5bf64SYevgeny Kliteynik 	[DR_MATCHER_RTC_TYPE_STE_ARRAY] = "STE_ARRAY",
1638b5bf64SYevgeny Kliteynik 	[DR_MATCHER_RTC_TYPE_MAX] = "UNKNOWN",
1738b5bf64SYevgeny Kliteynik };
1838b5bf64SYevgeny Kliteynik 
1938b5bf64SYevgeny Kliteynik static const char *mlx5dr_matcher_rtc_type_to_str(enum mlx5dr_matcher_rtc_type rtc_type)
2038b5bf64SYevgeny Kliteynik {
2138b5bf64SYevgeny Kliteynik 	if (rtc_type > DR_MATCHER_RTC_TYPE_MAX)
2238b5bf64SYevgeny Kliteynik 		rtc_type = DR_MATCHER_RTC_TYPE_MAX;
2338b5bf64SYevgeny Kliteynik 	return mlx5dr_matcher_rtc_type_str[rtc_type];
2438b5bf64SYevgeny Kliteynik }
2538b5bf64SYevgeny Kliteynik 
26c4676082SAlex Vesker static bool mlx5dr_matcher_requires_col_tbl(uint8_t log_num_of_rules)
27c4676082SAlex Vesker {
28c4676082SAlex Vesker 	/* Collision table concatenation is done only for large rule tables */
29c4676082SAlex Vesker 	return log_num_of_rules > MLX5DR_MATCHER_ASSURED_RULES_TH;
30c4676082SAlex Vesker }
31c4676082SAlex Vesker 
32c4676082SAlex Vesker static uint8_t mlx5dr_matcher_rules_to_tbl_depth(uint8_t log_num_of_rules)
33c4676082SAlex Vesker {
34c4676082SAlex Vesker 	if (mlx5dr_matcher_requires_col_tbl(log_num_of_rules))
35c4676082SAlex Vesker 		return MLX5DR_MATCHER_ASSURED_MAIN_TBL_DEPTH;
36c4676082SAlex Vesker 
37c4676082SAlex Vesker 	/* For small rule tables we use a single deep table to assure insertion */
38c4676082SAlex Vesker 	return RTE_MIN(log_num_of_rules, MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH);
39c4676082SAlex Vesker }
40c4676082SAlex Vesker 
41c4676082SAlex Vesker static void mlx5dr_matcher_destroy_end_ft(struct mlx5dr_matcher *matcher)
42c4676082SAlex Vesker {
43c4676082SAlex Vesker 	mlx5dr_table_destroy_default_ft(matcher->tbl, matcher->end_ft);
44c4676082SAlex Vesker }
45c4676082SAlex Vesker 
46b81f95caSItamar Gozlan int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
47ce946c7dSErez Shitrit 				     uint32_t fw_ft_type,
4873be9af4SErez Shitrit 				     enum mlx5dr_table_type type,
4973be9af4SErez Shitrit 				     struct mlx5dr_devx_obj *devx_obj)
5073be9af4SErez Shitrit {
5173be9af4SErez Shitrit 	int ret;
5273be9af4SErez Shitrit 
53ce946c7dSErez Shitrit 	if (type != MLX5DR_TABLE_TYPE_FDB && !mlx5dr_context_shared_gvmi_used(ctx))
5473be9af4SErez Shitrit 		return 0;
5573be9af4SErez Shitrit 
56b81f95caSItamar Gozlan 	ret = mlx5dr_table_ft_set_next_rtc(devx_obj, fw_ft_type, NULL, NULL);
57b81f95caSItamar Gozlan 	if (ret)
5873be9af4SErez Shitrit 		DR_LOG(ERR, "Failed to disconnect previous RTC");
5973be9af4SErez Shitrit 
60b81f95caSItamar Gozlan 	return ret;
6173be9af4SErez Shitrit }
6273be9af4SErez Shitrit 
63ce946c7dSErez Shitrit static int mlx5dr_matcher_shared_point_end_ft(struct mlx5dr_matcher *matcher)
64ce946c7dSErez Shitrit {
65ce946c7dSErez Shitrit 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
66ce946c7dSErez Shitrit 	int ret;
67ce946c7dSErez Shitrit 
68ce946c7dSErez Shitrit 	mlx5dr_cmd_set_attr_connect_miss_tbl(matcher->tbl->ctx,
69ce946c7dSErez Shitrit 					     matcher->tbl->fw_ft_type,
70ce946c7dSErez Shitrit 					     matcher->tbl->type,
71ce946c7dSErez Shitrit 					     &ft_attr);
72ce946c7dSErez Shitrit 
73ce946c7dSErez Shitrit 	ret = mlx5dr_cmd_flow_table_modify(matcher->end_ft, &ft_attr);
74ce946c7dSErez Shitrit 	if (ret) {
75ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to connect new matcher to default miss alias RTC");
76ce946c7dSErez Shitrit 		return ret;
77ce946c7dSErez Shitrit 	}
78ce946c7dSErez Shitrit 
79ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_free_rtc_pointing(matcher->tbl->ctx,
80ce946c7dSErez Shitrit 					       matcher->tbl->fw_ft_type,
81ce946c7dSErez Shitrit 					       matcher->tbl->type,
82ce946c7dSErez Shitrit 					       matcher->end_ft);
83ce946c7dSErez Shitrit 
84ce946c7dSErez Shitrit 	return ret;
85ce946c7dSErez Shitrit }
86ce946c7dSErez Shitrit 
87ce946c7dSErez Shitrit static int mlx5dr_matcher_shared_create_alias_rtc(struct mlx5dr_matcher *matcher)
88ce946c7dSErez Shitrit {
89ce946c7dSErez Shitrit 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
90ce946c7dSErez Shitrit 	int ret;
91ce946c7dSErez Shitrit 
92ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_create_aliased_obj(ctx,
93ce946c7dSErez Shitrit 						ctx->ibv_ctx,
94ce946c7dSErez Shitrit 						ctx->local_ibv_ctx,
95ce946c7dSErez Shitrit 						ctx->caps->shared_vhca_id,
96ce946c7dSErez Shitrit 						matcher->match_ste.rtc_0->id,
97ce946c7dSErez Shitrit 						MLX5_GENERAL_OBJ_TYPE_RTC,
98ce946c7dSErez Shitrit 						&matcher->match_ste.aliased_rtc_0);
99ce946c7dSErez Shitrit 	if (ret) {
100ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to allocate alias RTC");
101ce946c7dSErez Shitrit 		return ret;
102ce946c7dSErez Shitrit 	}
103ce946c7dSErez Shitrit 	return 0;
104ce946c7dSErez Shitrit }
105ce946c7dSErez Shitrit 
106ce946c7dSErez Shitrit static int mlx5dr_matcher_create_init_shared(struct mlx5dr_matcher *matcher)
107ce946c7dSErez Shitrit {
108ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx))
109ce946c7dSErez Shitrit 		return 0;
110ce946c7dSErez Shitrit 
111ce946c7dSErez Shitrit 	if (mlx5dr_matcher_shared_point_end_ft(matcher)) {
112ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to point shared matcher end flow table");
113ce946c7dSErez Shitrit 		return rte_errno;
114ce946c7dSErez Shitrit 	}
115ce946c7dSErez Shitrit 
116ce946c7dSErez Shitrit 	if (mlx5dr_matcher_shared_create_alias_rtc(matcher)) {
117ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create alias RTC");
118ce946c7dSErez Shitrit 		return rte_errno;
119ce946c7dSErez Shitrit 	}
120ce946c7dSErez Shitrit 
121ce946c7dSErez Shitrit 	return 0;
122ce946c7dSErez Shitrit }
123ce946c7dSErez Shitrit 
124ce946c7dSErez Shitrit static void mlx5dr_matcher_create_uninit_shared(struct mlx5dr_matcher *matcher)
125ce946c7dSErez Shitrit {
126ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx))
127ce946c7dSErez Shitrit 		return;
128ce946c7dSErez Shitrit 
129ce946c7dSErez Shitrit 	if (matcher->match_ste.aliased_rtc_0) {
130ce946c7dSErez Shitrit 		mlx5dr_cmd_destroy_obj(matcher->match_ste.aliased_rtc_0);
131ce946c7dSErez Shitrit 		matcher->match_ste.aliased_rtc_0 = NULL;
132ce946c7dSErez Shitrit 	}
133ce946c7dSErez Shitrit }
134ce946c7dSErez Shitrit 
135ce946c7dSErez Shitrit static int mlx5dr_matcher_create_end_ft(struct mlx5dr_matcher *matcher)
136ce946c7dSErez Shitrit {
137ce946c7dSErez Shitrit 	struct mlx5dr_table *tbl = matcher->tbl;
138ce946c7dSErez Shitrit 
139ce946c7dSErez Shitrit 	matcher->end_ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl);
140ce946c7dSErez Shitrit 	if (!matcher->end_ft) {
141ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create matcher end flow table");
142ce946c7dSErez Shitrit 		return rte_errno;
143ce946c7dSErez Shitrit 	}
144ce946c7dSErez Shitrit 	return 0;
145ce946c7dSErez Shitrit }
146ce946c7dSErez Shitrit 
147ce946c7dSErez Shitrit static uint32_t
148ce946c7dSErez Shitrit mlx5dr_matcher_connect_get_rtc0(struct mlx5dr_matcher *matcher)
149ce946c7dSErez Shitrit {
150ce946c7dSErez Shitrit 	if (!matcher->match_ste.aliased_rtc_0)
151ce946c7dSErez Shitrit 		return matcher->match_ste.rtc_0->id;
152ce946c7dSErez Shitrit 	else
153ce946c7dSErez Shitrit 		return matcher->match_ste.aliased_rtc_0->id;
154ce946c7dSErez Shitrit }
155ce946c7dSErez Shitrit 
156ce946c7dSErez Shitrit /* The function updates tbl->local_ft to the first RTC or 0 if no more matchers */
157ce946c7dSErez Shitrit static int mlx5dr_matcher_shared_update_local_ft(struct mlx5dr_table *tbl)
158ce946c7dSErez Shitrit {
159ce946c7dSErez Shitrit 	struct mlx5dr_cmd_ft_modify_attr cur_ft_attr = {0};
160ce946c7dSErez Shitrit 	struct mlx5dr_matcher *first_matcher;
161ce946c7dSErez Shitrit 	int ret;
162ce946c7dSErez Shitrit 
163ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(tbl->ctx))
164ce946c7dSErez Shitrit 		return 0;
165ce946c7dSErez Shitrit 
166ce946c7dSErez Shitrit 	first_matcher = LIST_FIRST(&tbl->head);
167ce946c7dSErez Shitrit 	if (!first_matcher) {
168ce946c7dSErez Shitrit 		/* local ft no longer points to any RTC, drop refcount */
169ce946c7dSErez Shitrit 		ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx,
170ce946c7dSErez Shitrit 						       tbl->fw_ft_type,
171ce946c7dSErez Shitrit 						       tbl->type,
172ce946c7dSErez Shitrit 						       tbl->local_ft);
173ce946c7dSErez Shitrit 		if (ret)
174ce946c7dSErez Shitrit 			DR_LOG(ERR, "Failed to clear local FT to prev alias RTC");
175ce946c7dSErez Shitrit 
176ce946c7dSErez Shitrit 		return ret;
177ce946c7dSErez Shitrit 	}
178ce946c7dSErez Shitrit 
179ce946c7dSErez Shitrit 	/* point local_ft to the first RTC */
180ce946c7dSErez Shitrit 	cur_ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
181ce946c7dSErez Shitrit 	cur_ft_attr.type = tbl->fw_ft_type;
182ce946c7dSErez Shitrit 	cur_ft_attr.rtc_id_0 = mlx5dr_matcher_connect_get_rtc0(first_matcher);
183ce946c7dSErez Shitrit 
184ce946c7dSErez Shitrit 	ret = mlx5dr_cmd_flow_table_modify(tbl->local_ft, &cur_ft_attr);
185ce946c7dSErez Shitrit 	if (ret) {
186ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to point local FT to alias RTC");
187ce946c7dSErez Shitrit 		return ret;
188ce946c7dSErez Shitrit 	}
189ce946c7dSErez Shitrit 
190ce946c7dSErez Shitrit 	return 0;
191ce946c7dSErez Shitrit }
192ce946c7dSErez Shitrit 
193c4676082SAlex Vesker static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
194c4676082SAlex Vesker {
195c4676082SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
196c4676082SAlex Vesker 	struct mlx5dr_matcher *prev = NULL;
197c4676082SAlex Vesker 	struct mlx5dr_matcher *next = NULL;
198c4676082SAlex Vesker 	struct mlx5dr_matcher *tmp_matcher;
199c4676082SAlex Vesker 	int ret;
200c4676082SAlex Vesker 
201*486f9aacSHamdan Igbaria 	if (matcher->attr.isolated) {
202*486f9aacSHamdan Igbaria 		LIST_INSERT_HEAD(&tbl->isolated_matchers, matcher, next);
203*486f9aacSHamdan Igbaria 		ret = mlx5dr_table_connect_src_ft_to_miss_table(tbl, matcher->end_ft,
204*486f9aacSHamdan Igbaria 								tbl->default_miss.miss_tbl);
205*486f9aacSHamdan Igbaria 		if (ret) {
206*486f9aacSHamdan Igbaria 			DR_LOG(ERR, "Failed to connect the new matcher to the miss_tbl");
207*486f9aacSHamdan Igbaria 			goto remove_from_list;
208*486f9aacSHamdan Igbaria 		}
209*486f9aacSHamdan Igbaria 
210*486f9aacSHamdan Igbaria 		return 0;
211*486f9aacSHamdan Igbaria 	}
212*486f9aacSHamdan Igbaria 
213c4676082SAlex Vesker 	/* Find location in matcher list */
214c4676082SAlex Vesker 	if (LIST_EMPTY(&tbl->head)) {
215c4676082SAlex Vesker 		LIST_INSERT_HEAD(&tbl->head, matcher, next);
216c4676082SAlex Vesker 		goto connect;
217c4676082SAlex Vesker 	}
218c4676082SAlex Vesker 
219c4676082SAlex Vesker 	LIST_FOREACH(tmp_matcher, &tbl->head, next) {
220c4676082SAlex Vesker 		if (tmp_matcher->attr.priority > matcher->attr.priority) {
221c4676082SAlex Vesker 			next = tmp_matcher;
222c4676082SAlex Vesker 			break;
223c4676082SAlex Vesker 		}
224c4676082SAlex Vesker 		prev = tmp_matcher;
225c4676082SAlex Vesker 	}
226c4676082SAlex Vesker 
227c4676082SAlex Vesker 	if (next)
228c4676082SAlex Vesker 		LIST_INSERT_BEFORE(next, matcher, next);
229c4676082SAlex Vesker 	else
230c4676082SAlex Vesker 		LIST_INSERT_AFTER(prev, matcher, next);
231c4676082SAlex Vesker 
232c4676082SAlex Vesker connect:
233c4676082SAlex Vesker 	if (next) {
234b81f95caSItamar Gozlan 		/* Connect to next RTC */
235b81f95caSItamar Gozlan 		ret = mlx5dr_table_ft_set_next_rtc(matcher->end_ft,
236b81f95caSItamar Gozlan 						   tbl->fw_ft_type,
237b81f95caSItamar Gozlan 						   next->match_ste.rtc_0,
238b81f95caSItamar Gozlan 						   next->match_ste.rtc_1);
239c4676082SAlex Vesker 		if (ret) {
240c4676082SAlex Vesker 			DR_LOG(ERR, "Failed to connect new matcher to next RTC");
241c4676082SAlex Vesker 			goto remove_from_list;
242c4676082SAlex Vesker 		}
243b81f95caSItamar Gozlan 	} else {
244b81f95caSItamar Gozlan 		/* Connect last matcher to next miss_tbl if exists */
245*486f9aacSHamdan Igbaria 		ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
246b81f95caSItamar Gozlan 		if (ret) {
247b81f95caSItamar Gozlan 			DR_LOG(ERR, "Failed connect new matcher to miss_tbl");
248b81f95caSItamar Gozlan 			goto remove_from_list;
249b81f95caSItamar Gozlan 		}
250c4676082SAlex Vesker 	}
251c4676082SAlex Vesker 
252b81f95caSItamar Gozlan 	/* Connect to previous FT */
253b81f95caSItamar Gozlan 	ret = mlx5dr_table_ft_set_next_rtc(prev ? prev->end_ft : tbl->ft,
254b81f95caSItamar Gozlan 					   tbl->fw_ft_type,
255b81f95caSItamar Gozlan 					   matcher->match_ste.rtc_0,
256b81f95caSItamar Gozlan 					   matcher->match_ste.rtc_1);
257c4676082SAlex Vesker 	if (ret) {
258c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to connect new matcher to previous FT");
259c4676082SAlex Vesker 		goto remove_from_list;
260c4676082SAlex Vesker 	}
261c4676082SAlex Vesker 
262ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_shared_update_local_ft(tbl);
263ce946c7dSErez Shitrit 	if (ret) {
264ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to update local_ft anchor in shared table");
265ce946c7dSErez Shitrit 		goto remove_from_list;
266ce946c7dSErez Shitrit 	}
267ce946c7dSErez Shitrit 
268b81f95caSItamar Gozlan 	/* Reset next miss FT to default (drop refcount) */
269eb8d268aSItamar Gozlan 	ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev ? prev->end_ft : tbl->ft);
270b81f95caSItamar Gozlan 	if (ret) {
271b81f95caSItamar Gozlan 		DR_LOG(ERR, "Failed to reset matcher ft default miss");
272b81f95caSItamar Gozlan 		goto remove_from_list;
273b81f95caSItamar Gozlan 	}
274eb8d268aSItamar Gozlan 
275eb8d268aSItamar Gozlan 	if (!prev) {
276eb8d268aSItamar Gozlan 		/* Update tables missing to current matcher in the table */
277b81f95caSItamar Gozlan 		ret = mlx5dr_table_update_connected_miss_tables(tbl);
278b81f95caSItamar Gozlan 		if (ret) {
279b81f95caSItamar Gozlan 			DR_LOG(ERR, "Fatal error, failed to update connected miss table");
280b81f95caSItamar Gozlan 			goto remove_from_list;
281b81f95caSItamar Gozlan 		}
282b81f95caSItamar Gozlan 	}
283b81f95caSItamar Gozlan 
284c4676082SAlex Vesker 	return 0;
285c4676082SAlex Vesker 
286c4676082SAlex Vesker remove_from_list:
287c4676082SAlex Vesker 	LIST_REMOVE(matcher, next);
288c4676082SAlex Vesker 	return ret;
289c4676082SAlex Vesker }
290c4676082SAlex Vesker 
291b81f95caSItamar Gozlan static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
292b81f95caSItamar Gozlan {
293b81f95caSItamar Gozlan 	struct mlx5dr_matcher *tmp_matcher, *prev_matcher;
294b81f95caSItamar Gozlan 	struct mlx5dr_table *tbl = matcher->tbl;
295b81f95caSItamar Gozlan 	struct mlx5dr_devx_obj *prev_ft;
296b81f95caSItamar Gozlan 	struct mlx5dr_matcher *next;
297b81f95caSItamar Gozlan 	int ret;
298b81f95caSItamar Gozlan 
299*486f9aacSHamdan Igbaria 	if (matcher->attr.isolated) {
300*486f9aacSHamdan Igbaria 		LIST_REMOVE(matcher, next);
301*486f9aacSHamdan Igbaria 		return 0;
302*486f9aacSHamdan Igbaria 	}
303*486f9aacSHamdan Igbaria 
304b81f95caSItamar Gozlan 	prev_ft = tbl->ft;
305b81f95caSItamar Gozlan 	prev_matcher = LIST_FIRST(&tbl->head);
306b81f95caSItamar Gozlan 	LIST_FOREACH(tmp_matcher, &tbl->head, next) {
307b81f95caSItamar Gozlan 		if (tmp_matcher == matcher)
308b81f95caSItamar Gozlan 			break;
309b81f95caSItamar Gozlan 
310b81f95caSItamar Gozlan 		prev_ft = tmp_matcher->end_ft;
311b81f95caSItamar Gozlan 		prev_matcher = tmp_matcher;
312c4676082SAlex Vesker 	}
313c4676082SAlex Vesker 
314b81f95caSItamar Gozlan 	next = matcher->next.le_next;
315b81f95caSItamar Gozlan 
316c4676082SAlex Vesker 	LIST_REMOVE(matcher, next);
317c4676082SAlex Vesker 
318b81f95caSItamar Gozlan 	if (next) {
319b81f95caSItamar Gozlan 		/* Connect previous end FT to next RTC */
320b81f95caSItamar Gozlan 		ret = mlx5dr_table_ft_set_next_rtc(prev_ft,
321ce946c7dSErez Shitrit 						   tbl->fw_ft_type,
322b81f95caSItamar Gozlan 						   next->match_ste.rtc_0,
323b81f95caSItamar Gozlan 						   next->match_ste.rtc_1);
32473be9af4SErez Shitrit 		if (ret) {
325b81f95caSItamar Gozlan 			DR_LOG(ERR, "Failed to disconnect matcher");
326b81f95caSItamar Gozlan 			goto matcher_reconnect;
327b81f95caSItamar Gozlan 		}
328b81f95caSItamar Gozlan 	} else {
329*486f9aacSHamdan Igbaria 		ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true);
330b81f95caSItamar Gozlan 		if (ret) {
331b81f95caSItamar Gozlan 			DR_LOG(ERR, "Failed to disconnect last matcher");
332b81f95caSItamar Gozlan 			goto matcher_reconnect;
33373be9af4SErez Shitrit 		}
33473be9af4SErez Shitrit 	}
33573be9af4SErez Shitrit 
336ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_shared_update_local_ft(tbl);
337ce946c7dSErez Shitrit 	if (ret) {
338ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to update local_ft in shared table");
339b81f95caSItamar Gozlan 		goto matcher_reconnect;
340ce946c7dSErez Shitrit 	}
341ce946c7dSErez Shitrit 
342b81f95caSItamar Gozlan 	/* Removing first matcher, update connected miss tables if exists */
343b81f95caSItamar Gozlan 	if (prev_ft == tbl->ft) {
344b81f95caSItamar Gozlan 		ret = mlx5dr_table_update_connected_miss_tables(tbl);
3452234c15dSErez Shitrit 		if (ret) {
346b81f95caSItamar Gozlan 			DR_LOG(ERR, "Fatal error, failed to update connected miss table");
347b81f95caSItamar Gozlan 			goto matcher_reconnect;
3482234c15dSErez Shitrit 		}
3492234c15dSErez Shitrit 	}
3502234c15dSErez Shitrit 
351b81f95caSItamar Gozlan 	ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev_ft);
352b81f95caSItamar Gozlan 	if (ret) {
353b81f95caSItamar Gozlan 		DR_LOG(ERR, "Fatal error, failed to restore matcher ft default miss");
354b81f95caSItamar Gozlan 		goto matcher_reconnect;
355b81f95caSItamar Gozlan 	}
356b81f95caSItamar Gozlan 
357c4676082SAlex Vesker 	return 0;
358b81f95caSItamar Gozlan 
359b81f95caSItamar Gozlan matcher_reconnect:
360f21215b7SYevgeny Kliteynik 	if (LIST_EMPTY(&tbl->head) || prev_matcher == matcher)
361b81f95caSItamar Gozlan 		LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
362b81f95caSItamar Gozlan 	else
363b81f95caSItamar Gozlan 		LIST_INSERT_AFTER(prev_matcher, matcher, next);
364b81f95caSItamar Gozlan 
365b81f95caSItamar Gozlan 	return ret;
366c4676082SAlex Vesker }
367c4676082SAlex Vesker 
368238190f3SAlex Vesker static bool mlx5dr_matcher_supp_fw_wqe(struct mlx5dr_matcher *matcher)
369238190f3SAlex Vesker {
370238190f3SAlex Vesker 	struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps;
371238190f3SAlex Vesker 
372238190f3SAlex Vesker 	if (matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER) {
373238190f3SAlex Vesker 		if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_MATCH &&
374238190f3SAlex Vesker 		    !IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_8DW)) {
375238190f3SAlex Vesker 			DR_LOG(ERR, "Gen WQE MATCH format not supported");
376238190f3SAlex Vesker 			return false;
377238190f3SAlex Vesker 		}
378238190f3SAlex Vesker 
379238190f3SAlex Vesker 		if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_JUMBO) {
380238190f3SAlex Vesker 			DR_LOG(ERR, "Gen WQE JUMBO format not supported");
381238190f3SAlex Vesker 			return false;
382238190f3SAlex Vesker 		}
383238190f3SAlex Vesker 	}
384238190f3SAlex Vesker 
385238190f3SAlex Vesker 	if (matcher->attr.insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH ||
386238190f3SAlex Vesker 	    matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
387238190f3SAlex Vesker 		DR_LOG(ERR, "Gen WQE must be inserted and distribute by hash");
388238190f3SAlex Vesker 		return false;
389238190f3SAlex Vesker 	}
390238190f3SAlex Vesker 
3919732ffe1SAlex Vesker 	if ((matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) &&
3929732ffe1SAlex Vesker 	    !IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_RANGE)) {
3939732ffe1SAlex Vesker 		DR_LOG(INFO, "Extended match gen wqe RANGE format not supported");
3949732ffe1SAlex Vesker 		return false;
3959732ffe1SAlex Vesker 	}
3969732ffe1SAlex Vesker 
397238190f3SAlex Vesker 	if (!(caps->supp_type_gen_wqe & MLX5_GENERATE_WQE_TYPE_FLOW_UPDATE)) {
398238190f3SAlex Vesker 		DR_LOG(ERR, "Gen WQE command not supporting GTA");
399238190f3SAlex Vesker 		return false;
400238190f3SAlex Vesker 	}
401238190f3SAlex Vesker 
402238190f3SAlex Vesker 	if (!caps->rtc_max_hash_def_gen_wqe) {
403238190f3SAlex Vesker 		DR_LOG(ERR, "Hash definer not supported");
404238190f3SAlex Vesker 		return false;
405238190f3SAlex Vesker 	}
406238190f3SAlex Vesker 
407238190f3SAlex Vesker 	return true;
408238190f3SAlex Vesker }
409238190f3SAlex Vesker 
410c4676082SAlex Vesker static void mlx5dr_matcher_set_rtc_attr_sz(struct mlx5dr_matcher *matcher,
411c4676082SAlex Vesker 					   struct mlx5dr_cmd_rtc_create_attr *rtc_attr,
41238b5bf64SYevgeny Kliteynik 					   enum mlx5dr_matcher_rtc_type rtc_type,
413c4676082SAlex Vesker 					   bool is_mirror)
414c4676082SAlex Vesker {
415c4676082SAlex Vesker 	enum mlx5dr_matcher_flow_src flow_src = matcher->attr.optimize_flow_src;
41638b5bf64SYevgeny Kliteynik 	bool is_match_rtc = rtc_type == DR_MATCHER_RTC_TYPE_MATCH;
417c4676082SAlex Vesker 	struct mlx5dr_pool_chunk *ste = &matcher->action_ste.ste;
418c4676082SAlex Vesker 
419c4676082SAlex Vesker 	if ((flow_src == MLX5DR_MATCHER_FLOW_SRC_VPORT && !is_mirror) ||
420c4676082SAlex Vesker 	    (flow_src == MLX5DR_MATCHER_FLOW_SRC_WIRE && is_mirror)) {
421c4676082SAlex Vesker 		/* Optimize FDB RTC */
422c4676082SAlex Vesker 		rtc_attr->log_size = 0;
423c4676082SAlex Vesker 		rtc_attr->log_depth = 0;
424c4676082SAlex Vesker 	} else {
425c4676082SAlex Vesker 		/* Keep original values */
426c4676082SAlex Vesker 		rtc_attr->log_size = is_match_rtc ? matcher->attr.table.sz_row_log : ste->order;
427c4676082SAlex Vesker 		rtc_attr->log_depth = is_match_rtc ? matcher->attr.table.sz_col_log : 0;
428c4676082SAlex Vesker 	}
429c4676082SAlex Vesker }
430c4676082SAlex Vesker 
431ce946c7dSErez Shitrit int mlx5dr_matcher_create_aliased_obj(struct mlx5dr_context *ctx,
432ce946c7dSErez Shitrit 				      struct ibv_context *ibv_owner,
433ce946c7dSErez Shitrit 				      struct ibv_context *ibv_allowed,
434ce946c7dSErez Shitrit 				      uint16_t vhca_id_to_be_accessed,
435ce946c7dSErez Shitrit 				      uint32_t aliased_object_id,
436ce946c7dSErez Shitrit 				      uint16_t object_type,
437ce946c7dSErez Shitrit 				      struct mlx5dr_devx_obj **obj)
438ce946c7dSErez Shitrit {
439ce946c7dSErez Shitrit 	struct mlx5dr_cmd_allow_other_vhca_access_attr allow_attr = {0};
440ce946c7dSErez Shitrit 	struct mlx5dr_cmd_alias_obj_create_attr alias_attr = {0};
441ce946c7dSErez Shitrit 	char key[ACCESS_KEY_LEN];
442ce946c7dSErez Shitrit 	int ret;
443ce946c7dSErez Shitrit 	int i;
444ce946c7dSErez Shitrit 
445ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
446ce946c7dSErez Shitrit 		return 0;
447ce946c7dSErez Shitrit 
448ce946c7dSErez Shitrit 	for (i = 0; i < ACCESS_KEY_LEN; i++)
449ce946c7dSErez Shitrit 		key[i] = rte_rand() & 0xFF;
450ce946c7dSErez Shitrit 
451ce946c7dSErez Shitrit 	memcpy(allow_attr.access_key, key, ACCESS_KEY_LEN);
452ce946c7dSErez Shitrit 	allow_attr.obj_type = object_type;
453ce946c7dSErez Shitrit 	allow_attr.obj_id = aliased_object_id;
454ce946c7dSErez Shitrit 
455ce946c7dSErez Shitrit 	ret = mlx5dr_cmd_allow_other_vhca_access(ibv_owner, &allow_attr);
456ce946c7dSErez Shitrit 	if (ret) {
457ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to allow RTC to be aliased");
458ce946c7dSErez Shitrit 		return ret;
459ce946c7dSErez Shitrit 	}
460ce946c7dSErez Shitrit 
461ce946c7dSErez Shitrit 	memcpy(alias_attr.access_key, key, ACCESS_KEY_LEN);
462ce946c7dSErez Shitrit 	alias_attr.obj_id = aliased_object_id;
463ce946c7dSErez Shitrit 	alias_attr.obj_type = object_type;
464ce946c7dSErez Shitrit 	alias_attr.vhca_id = vhca_id_to_be_accessed;
465ce946c7dSErez Shitrit 	*obj = mlx5dr_cmd_alias_obj_create(ibv_allowed, &alias_attr);
466ce946c7dSErez Shitrit 	if (!*obj) {
467ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create alias object");
468ce946c7dSErez Shitrit 		return rte_errno;
469ce946c7dSErez Shitrit 	}
470ce946c7dSErez Shitrit 
471ce946c7dSErez Shitrit 	return 0;
472ce946c7dSErez Shitrit }
473ce946c7dSErez Shitrit 
474c4676082SAlex Vesker static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher,
47538b5bf64SYevgeny Kliteynik 				     enum mlx5dr_matcher_rtc_type rtc_type)
476c4676082SAlex Vesker {
47738b5bf64SYevgeny Kliteynik 	struct mlx5dr_matcher_attr *attr = &matcher->attr;
478c4676082SAlex Vesker 	struct mlx5dr_cmd_rtc_create_attr rtc_attr = {0};
47927ac2da9SAlex Vesker 	struct mlx5dr_match_template *mt = matcher->mt;
480c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
481c4676082SAlex Vesker 	struct mlx5dr_action_default_stc *default_stc;
482c4676082SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
483c4676082SAlex Vesker 	struct mlx5dr_devx_obj **rtc_0, **rtc_1;
484c4676082SAlex Vesker 	struct mlx5dr_pool *ste_pool, *stc_pool;
485c4676082SAlex Vesker 	struct mlx5dr_devx_obj *devx_obj;
486c4676082SAlex Vesker 	struct mlx5dr_pool_chunk *ste;
487c4676082SAlex Vesker 	int ret;
488c4676082SAlex Vesker 
48938b5bf64SYevgeny Kliteynik 	switch (rtc_type) {
49038b5bf64SYevgeny Kliteynik 	case DR_MATCHER_RTC_TYPE_MATCH:
491c4676082SAlex Vesker 		rtc_0 = &matcher->match_ste.rtc_0;
492c4676082SAlex Vesker 		rtc_1 = &matcher->match_ste.rtc_1;
493c4676082SAlex Vesker 		ste_pool = matcher->match_ste.pool;
494c4676082SAlex Vesker 		ste = &matcher->match_ste.ste;
49538b5bf64SYevgeny Kliteynik 		ste->order = attr->table.sz_col_log + attr->table.sz_row_log;
49627ac2da9SAlex Vesker 
4979732ffe1SAlex Vesker 		/* Add additional rows due to additional range STE */
4989732ffe1SAlex Vesker 		if (mlx5dr_matcher_mt_is_range(mt))
4999732ffe1SAlex Vesker 			ste->order++;
5009732ffe1SAlex Vesker 
50138b5bf64SYevgeny Kliteynik 		rtc_attr.log_size = attr->table.sz_row_log;
50238b5bf64SYevgeny Kliteynik 		rtc_attr.log_depth = attr->table.sz_col_log;
50327ac2da9SAlex Vesker 		rtc_attr.is_frst_jumbo = mlx5dr_matcher_mt_is_jumbo(mt);
5049732ffe1SAlex Vesker 		rtc_attr.is_scnd_range = mlx5dr_matcher_mt_is_range(mt);
505a5230507SHamdan Igbaria 		rtc_attr.is_compare = mlx5dr_matcher_is_compare(matcher);
50638b5bf64SYevgeny Kliteynik 		rtc_attr.miss_ft_id = matcher->end_ft->id;
50738b5bf64SYevgeny Kliteynik 
50838b5bf64SYevgeny Kliteynik 		if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH) {
50938b5bf64SYevgeny Kliteynik 			/* The usual Hash Table */
510c4676082SAlex Vesker 			rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH;
5119732ffe1SAlex Vesker 
512238190f3SAlex Vesker 			if (matcher->hash_definer) {
513238190f3SAlex Vesker 				/* Specify definer_id_0 is used for hashing */
514238190f3SAlex Vesker 				rtc_attr.fw_gen_wqe = true;
515238190f3SAlex Vesker 				rtc_attr.num_hash_definer = 1;
516238190f3SAlex Vesker 				rtc_attr.match_definer_0 =
517238190f3SAlex Vesker 					mlx5dr_definer_get_id(matcher->hash_definer);
518a5230507SHamdan Igbaria 			} else if (mlx5dr_matcher_is_compare(matcher)) {
519a5230507SHamdan Igbaria 				rtc_attr.match_definer_0 = ctx->caps->trivial_match_definer;
520a5230507SHamdan Igbaria 				rtc_attr.fw_gen_wqe = true;
521a5230507SHamdan Igbaria 				rtc_attr.num_hash_definer = 1;
522238190f3SAlex Vesker 			} else {
523238190f3SAlex Vesker 				/* The first mt is used since all share the same definer */
52427ac2da9SAlex Vesker 				rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
5259732ffe1SAlex Vesker 
5269732ffe1SAlex Vesker 				/* This is tricky, instead of passing two definers for
5279732ffe1SAlex Vesker 				 * match and range, we specify that this RTC uses a hash
5289732ffe1SAlex Vesker 				 * definer, this will allow us to use any range definer
5299732ffe1SAlex Vesker 				 * since only first STE is used for hashing anyways.
5309732ffe1SAlex Vesker 				 */
5319732ffe1SAlex Vesker 				if (matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) {
5329732ffe1SAlex Vesker 					rtc_attr.fw_gen_wqe = true;
5339732ffe1SAlex Vesker 					rtc_attr.num_hash_definer = 1;
5349732ffe1SAlex Vesker 				}
535238190f3SAlex Vesker 			}
53638b5bf64SYevgeny Kliteynik 		} else if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
53738b5bf64SYevgeny Kliteynik 			rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
53838b5bf64SYevgeny Kliteynik 
53938b5bf64SYevgeny Kliteynik 			if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
54038b5bf64SYevgeny Kliteynik 				/* Hash Split Table */
541*486f9aacSHamdan Igbaria 				if (mlx5dr_matcher_is_always_hit(matcher))
542*486f9aacSHamdan Igbaria 					rtc_attr.num_hash_definer = 1;
543*486f9aacSHamdan Igbaria 
54438b5bf64SYevgeny Kliteynik 				rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_BY_HASH;
54527ac2da9SAlex Vesker 				rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer);
54638b5bf64SYevgeny Kliteynik 			} else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
54738b5bf64SYevgeny Kliteynik 				/* Linear Lookup Table */
548*486f9aacSHamdan Igbaria 				rtc_attr.num_hash_definer = 1;
54938b5bf64SYevgeny Kliteynik 				rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR;
55093ee3bd8SAlex Vesker 				rtc_attr.match_definer_0 = ctx->caps->linear_match_definer;
55138b5bf64SYevgeny Kliteynik 			}
55238b5bf64SYevgeny Kliteynik 		}
55338b5bf64SYevgeny Kliteynik 
554c4676082SAlex Vesker 		/* Match pool requires implicit allocation */
555c4676082SAlex Vesker 		ret = mlx5dr_pool_chunk_alloc(ste_pool, ste);
556c4676082SAlex Vesker 		if (ret) {
55738b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Failed to allocate STE for %s RTC",
55838b5bf64SYevgeny Kliteynik 			       mlx5dr_matcher_rtc_type_to_str(rtc_type));
559c4676082SAlex Vesker 			return ret;
560c4676082SAlex Vesker 		}
56138b5bf64SYevgeny Kliteynik 		break;
56238b5bf64SYevgeny Kliteynik 
56338b5bf64SYevgeny Kliteynik 	case DR_MATCHER_RTC_TYPE_STE_ARRAY:
564c4676082SAlex Vesker 		rtc_0 = &matcher->action_ste.rtc_0;
565c4676082SAlex Vesker 		rtc_1 = &matcher->action_ste.rtc_1;
566c4676082SAlex Vesker 		ste_pool = matcher->action_ste.pool;
567c4676082SAlex Vesker 		ste = &matcher->action_ste.ste;
568c4676082SAlex Vesker 		ste->order = rte_log2_u32(matcher->action_ste.max_stes) +
56938b5bf64SYevgeny Kliteynik 			     attr->table.sz_row_log;
570c4676082SAlex Vesker 		rtc_attr.log_size = ste->order;
571c4676082SAlex Vesker 		rtc_attr.log_depth = 0;
572c4676082SAlex Vesker 		rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
573c4676082SAlex Vesker 		/* The action STEs use the default always hit definer */
57493ee3bd8SAlex Vesker 		rtc_attr.match_definer_0 = ctx->caps->trivial_match_definer;
57593ee3bd8SAlex Vesker 		rtc_attr.is_frst_jumbo = false;
576c4676082SAlex Vesker 		rtc_attr.miss_ft_id = 0;
57738b5bf64SYevgeny Kliteynik 		break;
57838b5bf64SYevgeny Kliteynik 
57938b5bf64SYevgeny Kliteynik 	default:
58038b5bf64SYevgeny Kliteynik 		DR_LOG(ERR, "HWS Invalid RTC type");
58138b5bf64SYevgeny Kliteynik 		rte_errno = EINVAL;
58238b5bf64SYevgeny Kliteynik 		return rte_errno;
583c4676082SAlex Vesker 	}
584c4676082SAlex Vesker 
585c4676082SAlex Vesker 	devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste);
586c4676082SAlex Vesker 
587c4676082SAlex Vesker 	rtc_attr.pd = ctx->pd_num;
588c4676082SAlex Vesker 	rtc_attr.ste_base = devx_obj->id;
589c4676082SAlex Vesker 	rtc_attr.ste_offset = ste->offset;
590bbddd062SAlex Vesker 	rtc_attr.reparse_mode = mlx5dr_context_get_reparse_mode(ctx);
591c4676082SAlex Vesker 	rtc_attr.table_type = mlx5dr_table_get_res_fw_ft_type(tbl->type, false);
59238b5bf64SYevgeny Kliteynik 	mlx5dr_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, false);
593c4676082SAlex Vesker 
594c4676082SAlex Vesker 	/* STC is a single resource (devx_obj), use any STC for the ID */
595c4676082SAlex Vesker 	stc_pool = ctx->stc_pool[tbl->type];
596c4676082SAlex Vesker 	default_stc = ctx->common_res[tbl->type].default_stc;
597c4676082SAlex Vesker 	devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(stc_pool, &default_stc->default_hit);
598c4676082SAlex Vesker 	rtc_attr.stc_base = devx_obj->id;
599c4676082SAlex Vesker 
600c4676082SAlex Vesker 	*rtc_0 = mlx5dr_cmd_rtc_create(ctx->ibv_ctx, &rtc_attr);
601c4676082SAlex Vesker 	if (!*rtc_0) {
60238b5bf64SYevgeny Kliteynik 		DR_LOG(ERR, "Failed to create matcher RTC of type %s",
60338b5bf64SYevgeny Kliteynik 		       mlx5dr_matcher_rtc_type_to_str(rtc_type));
604c4676082SAlex Vesker 		goto free_ste;
605c4676082SAlex Vesker 	}
606c4676082SAlex Vesker 
607c4676082SAlex Vesker 	if (tbl->type == MLX5DR_TABLE_TYPE_FDB) {
608c4676082SAlex Vesker 		devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste);
609c4676082SAlex Vesker 		rtc_attr.ste_base = devx_obj->id;
610c4676082SAlex Vesker 		rtc_attr.table_type = mlx5dr_table_get_res_fw_ft_type(tbl->type, true);
611c4676082SAlex Vesker 
612c4676082SAlex Vesker 		devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(stc_pool, &default_stc->default_hit);
613c4676082SAlex Vesker 		rtc_attr.stc_base = devx_obj->id;
61438b5bf64SYevgeny Kliteynik 		mlx5dr_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, true);
615c4676082SAlex Vesker 
616c4676082SAlex Vesker 		*rtc_1 = mlx5dr_cmd_rtc_create(ctx->ibv_ctx, &rtc_attr);
617c4676082SAlex Vesker 		if (!*rtc_1) {
61838b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Failed to create peer matcher RTC of type %s",
61938b5bf64SYevgeny Kliteynik 			       mlx5dr_matcher_rtc_type_to_str(rtc_type));
620c4676082SAlex Vesker 			goto destroy_rtc_0;
621c4676082SAlex Vesker 		}
622c4676082SAlex Vesker 	}
623c4676082SAlex Vesker 
624c4676082SAlex Vesker 	return 0;
625c4676082SAlex Vesker 
626c4676082SAlex Vesker destroy_rtc_0:
627c4676082SAlex Vesker 	mlx5dr_cmd_destroy_obj(*rtc_0);
628c4676082SAlex Vesker free_ste:
62938b5bf64SYevgeny Kliteynik 	if (rtc_type == DR_MATCHER_RTC_TYPE_MATCH)
630c4676082SAlex Vesker 		mlx5dr_pool_chunk_free(ste_pool, ste);
631c4676082SAlex Vesker 	return rte_errno;
632c4676082SAlex Vesker }
633c4676082SAlex Vesker 
634c4676082SAlex Vesker static void mlx5dr_matcher_destroy_rtc(struct mlx5dr_matcher *matcher,
63538b5bf64SYevgeny Kliteynik 				       enum mlx5dr_matcher_rtc_type rtc_type)
636c4676082SAlex Vesker {
637c4676082SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
638c4676082SAlex Vesker 	struct mlx5dr_devx_obj *rtc_0, *rtc_1;
639c4676082SAlex Vesker 	struct mlx5dr_pool_chunk *ste;
640c4676082SAlex Vesker 	struct mlx5dr_pool *ste_pool;
641c4676082SAlex Vesker 
64238b5bf64SYevgeny Kliteynik 	switch (rtc_type) {
64338b5bf64SYevgeny Kliteynik 	case DR_MATCHER_RTC_TYPE_MATCH:
644c4676082SAlex Vesker 		rtc_0 = matcher->match_ste.rtc_0;
645c4676082SAlex Vesker 		rtc_1 = matcher->match_ste.rtc_1;
646c4676082SAlex Vesker 		ste_pool = matcher->match_ste.pool;
647c4676082SAlex Vesker 		ste = &matcher->match_ste.ste;
64838b5bf64SYevgeny Kliteynik 		break;
64938b5bf64SYevgeny Kliteynik 	case DR_MATCHER_RTC_TYPE_STE_ARRAY:
650c4676082SAlex Vesker 		rtc_0 = matcher->action_ste.rtc_0;
651c4676082SAlex Vesker 		rtc_1 = matcher->action_ste.rtc_1;
652c4676082SAlex Vesker 		ste_pool = matcher->action_ste.pool;
653c4676082SAlex Vesker 		ste = &matcher->action_ste.ste;
65438b5bf64SYevgeny Kliteynik 		break;
65538b5bf64SYevgeny Kliteynik 	default:
65638b5bf64SYevgeny Kliteynik 		return;
657c4676082SAlex Vesker 	}
658c4676082SAlex Vesker 
659c4676082SAlex Vesker 	if (tbl->type == MLX5DR_TABLE_TYPE_FDB)
660c4676082SAlex Vesker 		mlx5dr_cmd_destroy_obj(rtc_1);
661c4676082SAlex Vesker 
662c4676082SAlex Vesker 	mlx5dr_cmd_destroy_obj(rtc_0);
66338b5bf64SYevgeny Kliteynik 	if (rtc_type == DR_MATCHER_RTC_TYPE_MATCH)
664c4676082SAlex Vesker 		mlx5dr_pool_chunk_free(ste_pool, ste);
665c4676082SAlex Vesker }
666c4676082SAlex Vesker 
667186561f9SAlex Vesker static int
668186561f9SAlex Vesker mlx5dr_matcher_check_attr_sz(struct mlx5dr_cmd_query_caps *caps,
669186561f9SAlex Vesker 			     struct mlx5dr_matcher_attr *attr)
670186561f9SAlex Vesker {
671186561f9SAlex Vesker 	if (attr->table.sz_col_log > caps->rtc_log_depth_max) {
672186561f9SAlex Vesker 		DR_LOG(ERR, "Matcher depth exceeds limit %d", caps->rtc_log_depth_max);
673186561f9SAlex Vesker 		goto not_supported;
674186561f9SAlex Vesker 	}
675186561f9SAlex Vesker 
676186561f9SAlex Vesker 	if (attr->table.sz_col_log + attr->table.sz_row_log > caps->ste_alloc_log_max) {
677186561f9SAlex Vesker 		DR_LOG(ERR, "Total matcher size exceeds limit %d", caps->ste_alloc_log_max);
678186561f9SAlex Vesker 		goto not_supported;
679186561f9SAlex Vesker 	}
680186561f9SAlex Vesker 
681186561f9SAlex Vesker 	if (attr->table.sz_col_log + attr->table.sz_row_log < caps->ste_alloc_log_gran) {
682186561f9SAlex Vesker 		DR_LOG(ERR, "Total matcher size below limit %d", caps->ste_alloc_log_gran);
683186561f9SAlex Vesker 		goto not_supported;
684186561f9SAlex Vesker 	}
685186561f9SAlex Vesker 
686186561f9SAlex Vesker 	return 0;
687186561f9SAlex Vesker 
688186561f9SAlex Vesker not_supported:
689186561f9SAlex Vesker 	rte_errno = EOPNOTSUPP;
690186561f9SAlex Vesker 	return rte_errno;
691186561f9SAlex Vesker }
692186561f9SAlex Vesker 
693c4676082SAlex Vesker static void mlx5dr_matcher_set_pool_attr(struct mlx5dr_pool_attr *attr,
694c4676082SAlex Vesker 					 struct mlx5dr_matcher *matcher)
695c4676082SAlex Vesker {
696c4676082SAlex Vesker 	switch (matcher->attr.optimize_flow_src) {
697c4676082SAlex Vesker 	case MLX5DR_MATCHER_FLOW_SRC_VPORT:
698c4676082SAlex Vesker 		attr->opt_type = MLX5DR_POOL_OPTIMIZE_ORIG;
699c4676082SAlex Vesker 		break;
700c4676082SAlex Vesker 	case MLX5DR_MATCHER_FLOW_SRC_WIRE:
701c4676082SAlex Vesker 		attr->opt_type = MLX5DR_POOL_OPTIMIZE_MIRROR;
702c4676082SAlex Vesker 		break;
703c4676082SAlex Vesker 	default:
704c4676082SAlex Vesker 		break;
705c4676082SAlex Vesker 	}
706c4676082SAlex Vesker }
707c4676082SAlex Vesker 
708c5713fc1SErez Shitrit static int mlx5dr_matcher_check_and_process_at(struct mlx5dr_matcher *matcher,
709c5713fc1SErez Shitrit 					       struct mlx5dr_action_template *at)
710c5713fc1SErez Shitrit {
711c5713fc1SErez Shitrit 	bool valid;
712c5713fc1SErez Shitrit 	int ret;
713c5713fc1SErez Shitrit 
714d586f522SHamdan Igbaria 	if (!(at->flags & MLX5DR_ACTION_TEMPLATE_FLAG_RELAXED_ORDER)) {
715d586f522SHamdan Igbaria 		/* Check if actions combinabtion is valid,
716d586f522SHamdan Igbaria 		 * in the case of not relaxed actions order.
717d586f522SHamdan Igbaria 		 */
718c5713fc1SErez Shitrit 		valid = mlx5dr_action_check_combo(at->action_type_arr, matcher->tbl->type);
719c5713fc1SErez Shitrit 		if (!valid) {
720c5713fc1SErez Shitrit 			DR_LOG(ERR, "Invalid combination in action template");
721c5713fc1SErez Shitrit 			rte_errno = EINVAL;
722c5713fc1SErez Shitrit 			return rte_errno;
723c5713fc1SErez Shitrit 		}
724d586f522SHamdan Igbaria 	}
725c5713fc1SErez Shitrit 
726c5713fc1SErez Shitrit 	/* Process action template to setters */
727c5713fc1SErez Shitrit 	ret = mlx5dr_action_template_process(at);
728c5713fc1SErez Shitrit 	if (ret) {
729c5713fc1SErez Shitrit 		DR_LOG(ERR, "Failed to process action template");
730c5713fc1SErez Shitrit 		return ret;
731c5713fc1SErez Shitrit 	}
732c5713fc1SErez Shitrit 
733c5713fc1SErez Shitrit 	return 0;
734c5713fc1SErez Shitrit }
735c5713fc1SErez Shitrit 
736762fecebSYevgeny Kliteynik static int
737762fecebSYevgeny Kliteynik mlx5dr_matcher_resize_init(struct mlx5dr_matcher *src_matcher)
738762fecebSYevgeny Kliteynik {
739762fecebSYevgeny Kliteynik 	struct mlx5dr_matcher_resize_data *resize_data;
740762fecebSYevgeny Kliteynik 
741762fecebSYevgeny Kliteynik 	resize_data = simple_calloc(1, sizeof(*resize_data));
742762fecebSYevgeny Kliteynik 	if (!resize_data) {
743762fecebSYevgeny Kliteynik 		rte_errno = ENOMEM;
744762fecebSYevgeny Kliteynik 		return rte_errno;
745762fecebSYevgeny Kliteynik 	}
746762fecebSYevgeny Kliteynik 
74719e9ad26SYevgeny Kliteynik 	resize_data->max_stes = src_matcher->action_ste.max_stes;
748fd821625SHamdan Igbaria 	resize_data->ste = src_matcher->action_ste.ste;
749762fecebSYevgeny Kliteynik 	resize_data->stc = src_matcher->action_ste.stc;
750762fecebSYevgeny Kliteynik 	resize_data->action_ste_rtc_0 = src_matcher->action_ste.rtc_0;
751762fecebSYevgeny Kliteynik 	resize_data->action_ste_rtc_1 = src_matcher->action_ste.rtc_1;
752762fecebSYevgeny Kliteynik 	resize_data->action_ste_pool = src_matcher->action_ste.max_stes ?
753762fecebSYevgeny Kliteynik 				       src_matcher->action_ste.pool :
754762fecebSYevgeny Kliteynik 				       NULL;
755762fecebSYevgeny Kliteynik 
756762fecebSYevgeny Kliteynik 	/* Place the new resized matcher on the dst matcher's list */
757762fecebSYevgeny Kliteynik 	LIST_INSERT_HEAD(&src_matcher->resize_dst->resize_data,
758762fecebSYevgeny Kliteynik 			 resize_data, next);
759762fecebSYevgeny Kliteynik 
760762fecebSYevgeny Kliteynik 	/* Move all the previous resized matchers to the dst matcher's list */
761762fecebSYevgeny Kliteynik 	while (!LIST_EMPTY(&src_matcher->resize_data)) {
762762fecebSYevgeny Kliteynik 		resize_data = LIST_FIRST(&src_matcher->resize_data);
763762fecebSYevgeny Kliteynik 		LIST_REMOVE(resize_data, next);
764762fecebSYevgeny Kliteynik 		LIST_INSERT_HEAD(&src_matcher->resize_dst->resize_data,
765762fecebSYevgeny Kliteynik 				 resize_data, next);
766762fecebSYevgeny Kliteynik 	}
767762fecebSYevgeny Kliteynik 
768762fecebSYevgeny Kliteynik 	return 0;
769762fecebSYevgeny Kliteynik }
770762fecebSYevgeny Kliteynik 
771762fecebSYevgeny Kliteynik static void
772762fecebSYevgeny Kliteynik mlx5dr_matcher_resize_uninit(struct mlx5dr_matcher *matcher)
773762fecebSYevgeny Kliteynik {
774762fecebSYevgeny Kliteynik 	struct mlx5dr_matcher_resize_data *resize_data;
775762fecebSYevgeny Kliteynik 
77619e9ad26SYevgeny Kliteynik 	if (!mlx5dr_matcher_is_resizable(matcher))
777762fecebSYevgeny Kliteynik 		return;
778762fecebSYevgeny Kliteynik 
779762fecebSYevgeny Kliteynik 	while (!LIST_EMPTY(&matcher->resize_data)) {
780762fecebSYevgeny Kliteynik 		resize_data = LIST_FIRST(&matcher->resize_data);
781762fecebSYevgeny Kliteynik 		LIST_REMOVE(resize_data, next);
782762fecebSYevgeny Kliteynik 
78319e9ad26SYevgeny Kliteynik 		if (resize_data->max_stes) {
784762fecebSYevgeny Kliteynik 			mlx5dr_action_free_single_stc(matcher->tbl->ctx,
785762fecebSYevgeny Kliteynik 						matcher->tbl->type,
786762fecebSYevgeny Kliteynik 						&resize_data->stc);
787762fecebSYevgeny Kliteynik 
788762fecebSYevgeny Kliteynik 			if (matcher->tbl->type == MLX5DR_TABLE_TYPE_FDB)
789762fecebSYevgeny Kliteynik 				mlx5dr_cmd_destroy_obj(resize_data->action_ste_rtc_1);
790762fecebSYevgeny Kliteynik 			mlx5dr_cmd_destroy_obj(resize_data->action_ste_rtc_0);
791762fecebSYevgeny Kliteynik 			if (resize_data->action_ste_pool)
792762fecebSYevgeny Kliteynik 				mlx5dr_pool_destroy(resize_data->action_ste_pool);
79319e9ad26SYevgeny Kliteynik 		}
79419e9ad26SYevgeny Kliteynik 
795762fecebSYevgeny Kliteynik 		simple_free(resize_data);
796762fecebSYevgeny Kliteynik 	}
797762fecebSYevgeny Kliteynik }
798762fecebSYevgeny Kliteynik 
799c4676082SAlex Vesker static int mlx5dr_matcher_bind_at(struct mlx5dr_matcher *matcher)
800c4676082SAlex Vesker {
80127ac2da9SAlex Vesker 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt);
802c4676082SAlex Vesker 	struct mlx5dr_cmd_stc_modify_attr stc_attr = {0};
803c4676082SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
804c4676082SAlex Vesker 	struct mlx5dr_pool_attr pool_attr = {0};
805c4676082SAlex Vesker 	struct mlx5dr_context *ctx = tbl->ctx;
806c4676082SAlex Vesker 	uint32_t required_stes;
807c4676082SAlex Vesker 	int i, ret;
808c4676082SAlex Vesker 
8091fe7e58aSErez Shitrit 	if (matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION)
8101fe7e58aSErez Shitrit 		return 0;
8111fe7e58aSErez Shitrit 
81292d6bf66SAlex Vesker 	if (matcher->attr.max_num_of_at_attach &&
81392d6bf66SAlex Vesker 	    mlx5dr_matcher_req_fw_wqe(matcher)) {
81492d6bf66SAlex Vesker 		DR_LOG(ERR, "FW extended matcher doesn't support additional at");
81592d6bf66SAlex Vesker 		rte_errno = ENOTSUP;
81692d6bf66SAlex Vesker 		return rte_errno;
81792d6bf66SAlex Vesker 	}
81892d6bf66SAlex Vesker 
819c4676082SAlex Vesker 	for (i = 0; i < matcher->num_of_at; i++) {
820940b0ebaSAlex Vesker 		struct mlx5dr_action_template *at = &matcher->at[i];
821c4676082SAlex Vesker 
822c5713fc1SErez Shitrit 		ret = mlx5dr_matcher_check_and_process_at(matcher, at);
823c4676082SAlex Vesker 		if (ret) {
824c5713fc1SErez Shitrit 			DR_LOG(ERR, "Invalid at %d", i);
825c4676082SAlex Vesker 			return rte_errno;
826c4676082SAlex Vesker 		}
827c4676082SAlex Vesker 
828c4676082SAlex Vesker 		required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term);
829c4676082SAlex Vesker 		matcher->action_ste.max_stes = RTE_MAX(matcher->action_ste.max_stes, required_stes);
830c4676082SAlex Vesker 
831c4676082SAlex Vesker 		/* Future: Optimize reparse */
832c4676082SAlex Vesker 	}
833c4676082SAlex Vesker 
834c4676082SAlex Vesker 	/* There are no additioanl STEs required for matcher */
835c4676082SAlex Vesker 	if (!matcher->action_ste.max_stes)
836c4676082SAlex Vesker 		return 0;
837c4676082SAlex Vesker 
838238190f3SAlex Vesker 	if (mlx5dr_matcher_req_fw_wqe(matcher)) {
839238190f3SAlex Vesker 		DR_LOG(ERR, "FW extended matcher cannot be binded to complex at");
840238190f3SAlex Vesker 		rte_errno = ENOTSUP;
841238190f3SAlex Vesker 		return rte_errno;
842238190f3SAlex Vesker 	}
843238190f3SAlex Vesker 
844c4676082SAlex Vesker 	/* Allocate action STE mempool */
845c4676082SAlex Vesker 	pool_attr.table_type = tbl->type;
846c4676082SAlex Vesker 	pool_attr.pool_type = MLX5DR_POOL_TYPE_STE;
847c4676082SAlex Vesker 	pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_STE_ACTION_POOL;
848c4676082SAlex Vesker 	pool_attr.alloc_log_sz = rte_log2_u32(matcher->action_ste.max_stes) +
849c4676082SAlex Vesker 				 matcher->attr.table.sz_row_log;
850c4676082SAlex Vesker 	mlx5dr_matcher_set_pool_attr(&pool_attr, matcher);
851c4676082SAlex Vesker 	matcher->action_ste.pool = mlx5dr_pool_create(ctx, &pool_attr);
852c4676082SAlex Vesker 	if (!matcher->action_ste.pool) {
853c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to create action ste pool");
854c4676082SAlex Vesker 		return rte_errno;
855c4676082SAlex Vesker 	}
856c4676082SAlex Vesker 
857c4676082SAlex Vesker 	/* Allocate action RTC */
85838b5bf64SYevgeny Kliteynik 	ret = mlx5dr_matcher_create_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY);
859c4676082SAlex Vesker 	if (ret) {
860c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to create action RTC");
861c4676082SAlex Vesker 		goto free_ste_pool;
862c4676082SAlex Vesker 	}
863c4676082SAlex Vesker 
864c4676082SAlex Vesker 	/* Allocate STC for jumps to STE */
865c4676082SAlex Vesker 	stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT;
866c4676082SAlex Vesker 	stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE;
867bbddd062SAlex Vesker 	stc_attr.reparse_mode = MLX5_IFC_STC_REPARSE_IGNORE;
868c4676082SAlex Vesker 	stc_attr.ste_table.ste = matcher->action_ste.ste;
869c4676082SAlex Vesker 	stc_attr.ste_table.ste_pool = matcher->action_ste.pool;
870c4676082SAlex Vesker 	stc_attr.ste_table.match_definer_id = ctx->caps->trivial_match_definer;
871c4676082SAlex Vesker 
872c4676082SAlex Vesker 	ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl->type,
873c4676082SAlex Vesker 					     &matcher->action_ste.stc);
874c4676082SAlex Vesker 	if (ret) {
875c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to create action jump to table STC");
876c4676082SAlex Vesker 		goto free_rtc;
877c4676082SAlex Vesker 	}
878c4676082SAlex Vesker 
879c4676082SAlex Vesker 	return 0;
880c4676082SAlex Vesker 
881c4676082SAlex Vesker free_rtc:
88238b5bf64SYevgeny Kliteynik 	mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY);
883c4676082SAlex Vesker free_ste_pool:
884c4676082SAlex Vesker 	mlx5dr_pool_destroy(matcher->action_ste.pool);
885c4676082SAlex Vesker 	return rte_errno;
886c4676082SAlex Vesker }
887c4676082SAlex Vesker 
888c4676082SAlex Vesker static void mlx5dr_matcher_unbind_at(struct mlx5dr_matcher *matcher)
889c4676082SAlex Vesker {
890c4676082SAlex Vesker 	struct mlx5dr_table *tbl = matcher->tbl;
891c4676082SAlex Vesker 
892762fecebSYevgeny Kliteynik 	if (!matcher->action_ste.max_stes ||
893762fecebSYevgeny Kliteynik 	    matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION ||
894762fecebSYevgeny Kliteynik 	    mlx5dr_matcher_is_in_resize(matcher))
895c4676082SAlex Vesker 		return;
896c4676082SAlex Vesker 
897c4676082SAlex Vesker 	mlx5dr_action_free_single_stc(tbl->ctx, tbl->type, &matcher->action_ste.stc);
89838b5bf64SYevgeny Kliteynik 	mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY);
899c4676082SAlex Vesker 	mlx5dr_pool_destroy(matcher->action_ste.pool);
900c4676082SAlex Vesker }
901c4676082SAlex Vesker 
902c4676082SAlex Vesker static int mlx5dr_matcher_bind_mt(struct mlx5dr_matcher *matcher)
903c4676082SAlex Vesker {
904c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
905c4676082SAlex Vesker 	struct mlx5dr_pool_attr pool_attr = {0};
90627ac2da9SAlex Vesker 	int ret;
907c4676082SAlex Vesker 
9089732ffe1SAlex Vesker 	/* Calculate match, range and hash definers */
90927ac2da9SAlex Vesker 	ret = mlx5dr_definer_matcher_init(ctx, matcher);
910c4676082SAlex Vesker 	if (ret) {
911e014d5e2SErez Shitrit 		DR_LOG(DEBUG, "Failed to set matcher templates with match definers");
91227ac2da9SAlex Vesker 		return ret;
913c4676082SAlex Vesker 	}
914c4676082SAlex Vesker 
915238190f3SAlex Vesker 	if (mlx5dr_matcher_req_fw_wqe(matcher) &&
916238190f3SAlex Vesker 	    !mlx5dr_matcher_supp_fw_wqe(matcher)) {
917238190f3SAlex Vesker 		DR_LOG(ERR, "Matcher requires FW WQE which is not supported");
918238190f3SAlex Vesker 		rte_errno = ENOTSUP;
919238190f3SAlex Vesker 		ret = rte_errno;
920238190f3SAlex Vesker 		goto uninit_match_definer;
921238190f3SAlex Vesker 	}
922238190f3SAlex Vesker 
923c4676082SAlex Vesker 	/* Create an STE pool per matcher*/
92427ac2da9SAlex Vesker 	pool_attr.table_type = matcher->tbl->type;
925c4676082SAlex Vesker 	pool_attr.pool_type = MLX5DR_POOL_TYPE_STE;
926c4676082SAlex Vesker 	pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_MATCHER_STE_POOL;
927c4676082SAlex Vesker 	pool_attr.alloc_log_sz = matcher->attr.table.sz_col_log +
928c4676082SAlex Vesker 				 matcher->attr.table.sz_row_log;
9299732ffe1SAlex Vesker 	/* Add additional rows due to additional range STE */
9309732ffe1SAlex Vesker 	if (matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER)
9319732ffe1SAlex Vesker 		pool_attr.alloc_log_sz++;
932c4676082SAlex Vesker 	mlx5dr_matcher_set_pool_attr(&pool_attr, matcher);
933c4676082SAlex Vesker 
934c4676082SAlex Vesker 	matcher->match_ste.pool = mlx5dr_pool_create(ctx, &pool_attr);
935c4676082SAlex Vesker 	if (!matcher->match_ste.pool) {
936c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to allocate matcher STE pool");
937238190f3SAlex Vesker 		ret = ENOTSUP;
93827ac2da9SAlex Vesker 		goto uninit_match_definer;
939c4676082SAlex Vesker 	}
940c4676082SAlex Vesker 
941c4676082SAlex Vesker 	return 0;
942c4676082SAlex Vesker 
94327ac2da9SAlex Vesker uninit_match_definer:
94427ac2da9SAlex Vesker 	mlx5dr_definer_matcher_uninit(matcher);
945c4676082SAlex Vesker 	return ret;
946c4676082SAlex Vesker }
947c4676082SAlex Vesker 
948c4676082SAlex Vesker static void mlx5dr_matcher_unbind_mt(struct mlx5dr_matcher *matcher)
949c4676082SAlex Vesker {
950c4676082SAlex Vesker 	mlx5dr_pool_destroy(matcher->match_ste.pool);
95127ac2da9SAlex Vesker 	mlx5dr_definer_matcher_uninit(matcher);
952c4676082SAlex Vesker }
953c4676082SAlex Vesker 
954c4676082SAlex Vesker static int
95538b5bf64SYevgeny Kliteynik mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps,
956c4676082SAlex Vesker 				    struct mlx5dr_matcher *matcher,
957c4676082SAlex Vesker 				    bool is_root)
958c4676082SAlex Vesker {
959c4676082SAlex Vesker 	struct mlx5dr_matcher_attr *attr = &matcher->attr;
960c4676082SAlex Vesker 
961c4676082SAlex Vesker 	if (is_root) {
962c4676082SAlex Vesker 		if (attr->mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE) {
963c4676082SAlex Vesker 			DR_LOG(ERR, "Root matcher supports only rule resource mode");
964c4676082SAlex Vesker 			goto not_supported;
965c4676082SAlex Vesker 		}
96638b5bf64SYevgeny Kliteynik 		if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH) {
96738b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Root matcher supports only insert by hash mode");
96838b5bf64SYevgeny Kliteynik 			goto not_supported;
96938b5bf64SYevgeny Kliteynik 		}
97038b5bf64SYevgeny Kliteynik 		if (attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
97138b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Root matcher supports only distribute by hash mode");
97238b5bf64SYevgeny Kliteynik 			goto not_supported;
97338b5bf64SYevgeny Kliteynik 		}
97438b5bf64SYevgeny Kliteynik 		if (attr->optimize_flow_src) {
97538b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Root matcher can't specify FDB direction");
97638b5bf64SYevgeny Kliteynik 			goto not_supported;
97738b5bf64SYevgeny Kliteynik 		}
97838b5bf64SYevgeny Kliteynik 	}
97938b5bf64SYevgeny Kliteynik 
98038b5bf64SYevgeny Kliteynik 	switch (attr->insert_mode) {
98138b5bf64SYevgeny Kliteynik 	case MLX5DR_MATCHER_INSERT_BY_HASH:
98238b5bf64SYevgeny Kliteynik 		if (matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
98338b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Invalid matcher distribute mode");
98438b5bf64SYevgeny Kliteynik 			goto not_supported;
98538b5bf64SYevgeny Kliteynik 		}
98638b5bf64SYevgeny Kliteynik 		break;
98738b5bf64SYevgeny Kliteynik 
98838b5bf64SYevgeny Kliteynik 	case MLX5DR_MATCHER_INSERT_BY_INDEX:
98938b5bf64SYevgeny Kliteynik 		if (attr->table.sz_col_log) {
99038b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Matcher with INSERT_BY_INDEX supports only Nx1 table size");
99138b5bf64SYevgeny Kliteynik 			goto not_supported;
99238b5bf64SYevgeny Kliteynik 		}
99338b5bf64SYevgeny Kliteynik 
99438b5bf64SYevgeny Kliteynik 		if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
99538b5bf64SYevgeny Kliteynik 			/* Hash Split Table */
996*486f9aacSHamdan Igbaria 			if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT &&
997*486f9aacSHamdan Igbaria 			    !caps->rtc_hash_split_table) {
99838b5bf64SYevgeny Kliteynik 				DR_LOG(ERR, "FW doesn't support insert by index and hash distribute");
99938b5bf64SYevgeny Kliteynik 				goto not_supported;
100038b5bf64SYevgeny Kliteynik 			}
1001*486f9aacSHamdan Igbaria 
1002*486f9aacSHamdan Igbaria 			if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_DEFAULT &&
1003*486f9aacSHamdan Igbaria 			    !attr->isolated) {
1004*486f9aacSHamdan Igbaria 				DR_LOG(ERR, "STE array matcher supported only as an isolated matcher");
1005*486f9aacSHamdan Igbaria 				goto not_supported;
1006*486f9aacSHamdan Igbaria 			}
100738b5bf64SYevgeny Kliteynik 		} else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) {
100838b5bf64SYevgeny Kliteynik 			/* Linear Lookup Table */
100938b5bf64SYevgeny Kliteynik 			if (!caps->rtc_linear_lookup_table ||
101038b5bf64SYevgeny Kliteynik 			    !IS_BIT_SET(caps->access_index_mode,
101138b5bf64SYevgeny Kliteynik 					MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR)) {
101238b5bf64SYevgeny Kliteynik 				DR_LOG(ERR, "FW doesn't support insert by index and linear distribute");
101338b5bf64SYevgeny Kliteynik 				goto not_supported;
101438b5bf64SYevgeny Kliteynik 			}
101538b5bf64SYevgeny Kliteynik 
101638b5bf64SYevgeny Kliteynik 			if (attr->table.sz_row_log > MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX) {
101738b5bf64SYevgeny Kliteynik 				DR_LOG(ERR, "Matcher with linear distribute: rows exceed limit %d",
101838b5bf64SYevgeny Kliteynik 				       MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX);
101938b5bf64SYevgeny Kliteynik 				goto not_supported;
102038b5bf64SYevgeny Kliteynik 			}
1021*486f9aacSHamdan Igbaria 
1022*486f9aacSHamdan Igbaria 			if (attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT) {
1023*486f9aacSHamdan Igbaria 				DR_LOG(ERR, "Linear lookup tables will always hit, given match mode is not supported %d\n",
1024*486f9aacSHamdan Igbaria 				       attr->match_mode);
1025*486f9aacSHamdan Igbaria 				goto not_supported;
1026*486f9aacSHamdan Igbaria 			}
102738b5bf64SYevgeny Kliteynik 		} else {
102838b5bf64SYevgeny Kliteynik 			DR_LOG(ERR, "Matcher has unsupported distribute mode");
102938b5bf64SYevgeny Kliteynik 			goto not_supported;
103038b5bf64SYevgeny Kliteynik 		}
103138b5bf64SYevgeny Kliteynik 		break;
103238b5bf64SYevgeny Kliteynik 
103338b5bf64SYevgeny Kliteynik 	default:
103438b5bf64SYevgeny Kliteynik 		DR_LOG(ERR, "Matcher has unsupported insert mode");
103538b5bf64SYevgeny Kliteynik 		goto not_supported;
103638b5bf64SYevgeny Kliteynik 	}
103738b5bf64SYevgeny Kliteynik 
103838b5bf64SYevgeny Kliteynik 	return 0;
103938b5bf64SYevgeny Kliteynik 
104038b5bf64SYevgeny Kliteynik not_supported:
104138b5bf64SYevgeny Kliteynik 	rte_errno = EOPNOTSUPP;
104238b5bf64SYevgeny Kliteynik 	return rte_errno;
104338b5bf64SYevgeny Kliteynik }
104438b5bf64SYevgeny Kliteynik 
104538b5bf64SYevgeny Kliteynik static int
104638b5bf64SYevgeny Kliteynik mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps,
104738b5bf64SYevgeny Kliteynik 			    struct mlx5dr_matcher *matcher,
104838b5bf64SYevgeny Kliteynik 			    bool is_root)
104938b5bf64SYevgeny Kliteynik {
105038b5bf64SYevgeny Kliteynik 	struct mlx5dr_matcher_attr *attr = &matcher->attr;
105138b5bf64SYevgeny Kliteynik 
105238b5bf64SYevgeny Kliteynik 	if (mlx5dr_matcher_validate_insert_mode(caps, matcher, is_root))
105338b5bf64SYevgeny Kliteynik 		goto not_supported;
105438b5bf64SYevgeny Kliteynik 
105538b5bf64SYevgeny Kliteynik 	if (is_root) {
1056c4676082SAlex Vesker 		if (attr->optimize_flow_src) {
1057c4676082SAlex Vesker 			DR_LOG(ERR, "Root matcher can't specify FDB direction");
1058c4676082SAlex Vesker 			goto not_supported;
1059c4676082SAlex Vesker 		}
1060c5713fc1SErez Shitrit 		if (attr->max_num_of_at_attach) {
1061c5713fc1SErez Shitrit 			DR_LOG(ERR, "Root matcher does not support at attaching");
1062c5713fc1SErez Shitrit 			goto not_supported;
1063c5713fc1SErez Shitrit 		}
1064762fecebSYevgeny Kliteynik 		if (attr->resizable) {
1065762fecebSYevgeny Kliteynik 			DR_LOG(ERR, "Root matcher does not support resizing");
1066762fecebSYevgeny Kliteynik 			goto not_supported;
1067762fecebSYevgeny Kliteynik 		}
1068*486f9aacSHamdan Igbaria 		if (attr->isolated) {
1069*486f9aacSHamdan Igbaria 			DR_LOG(ERR, "Root matcher can not be isolated");
1070*486f9aacSHamdan Igbaria 			goto not_supported;
1071*486f9aacSHamdan Igbaria 		}
1072*486f9aacSHamdan Igbaria 
1073c4676082SAlex Vesker 		return 0;
1074c4676082SAlex Vesker 	}
1075c4676082SAlex Vesker 
107638b5bf64SYevgeny Kliteynik 	if (matcher->tbl->type != MLX5DR_TABLE_TYPE_FDB  && attr->optimize_flow_src) {
107738b5bf64SYevgeny Kliteynik 		DR_LOG(ERR, "NIC domain doesn't support flow_src");
107838b5bf64SYevgeny Kliteynik 		goto not_supported;
107938b5bf64SYevgeny Kliteynik 	}
108038b5bf64SYevgeny Kliteynik 
1081c4676082SAlex Vesker 	/* Convert number of rules to the required depth */
108238b5bf64SYevgeny Kliteynik 	if (attr->mode == MLX5DR_MATCHER_RESOURCE_MODE_RULE &&
108338b5bf64SYevgeny Kliteynik 	    attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH)
1084c4676082SAlex Vesker 		attr->table.sz_col_log = mlx5dr_matcher_rules_to_tbl_depth(attr->rule.num_log);
1085c4676082SAlex Vesker 
1086*486f9aacSHamdan Igbaria 	if (attr->isolated) {
1087*486f9aacSHamdan Igbaria 		if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_INDEX ||
1088*486f9aacSHamdan Igbaria 		    attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH ||
1089*486f9aacSHamdan Igbaria 		    attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_DEFAULT) {
1090*486f9aacSHamdan Igbaria 			DR_LOG(ERR, "Isolated matcher only supported for STE array matcher");
1091*486f9aacSHamdan Igbaria 			goto not_supported;
1092*486f9aacSHamdan Igbaria 		}
1093*486f9aacSHamdan Igbaria 
1094*486f9aacSHamdan Igbaria 		/* We reach here only in case of STE array */
1095*486f9aacSHamdan Igbaria 		matcher->flags |= MLX5DR_MATCHER_FLAGS_STE_ARRAY;
1096*486f9aacSHamdan Igbaria 	}
1097*486f9aacSHamdan Igbaria 
1098762fecebSYevgeny Kliteynik 	matcher->flags |= attr->resizable ? MLX5DR_MATCHER_FLAGS_RESIZABLE : 0;
1099762fecebSYevgeny Kliteynik 
1100186561f9SAlex Vesker 	return mlx5dr_matcher_check_attr_sz(caps, attr);
1101c4676082SAlex Vesker 
1102c4676082SAlex Vesker not_supported:
1103c4676082SAlex Vesker 	rte_errno = EOPNOTSUPP;
1104c4676082SAlex Vesker 	return rte_errno;
1105c4676082SAlex Vesker }
1106c4676082SAlex Vesker 
1107c4676082SAlex Vesker static int mlx5dr_matcher_create_and_connect(struct mlx5dr_matcher *matcher)
1108c4676082SAlex Vesker {
1109c4676082SAlex Vesker 	int ret;
1110c4676082SAlex Vesker 
1111c4676082SAlex Vesker 	/* Select and create the definers for current matcher */
1112c4676082SAlex Vesker 	ret = mlx5dr_matcher_bind_mt(matcher);
1113c4676082SAlex Vesker 	if (ret)
1114c4676082SAlex Vesker 		return ret;
1115c4676082SAlex Vesker 
1116c4676082SAlex Vesker 	/* Calculate and verify action combination */
1117c4676082SAlex Vesker 	ret = mlx5dr_matcher_bind_at(matcher);
1118c4676082SAlex Vesker 	if (ret)
1119c4676082SAlex Vesker 		goto unbind_mt;
1120c4676082SAlex Vesker 
1121c4676082SAlex Vesker 	/* Create matcher end flow table anchor */
1122c4676082SAlex Vesker 	ret = mlx5dr_matcher_create_end_ft(matcher);
1123c4676082SAlex Vesker 	if (ret)
1124c4676082SAlex Vesker 		goto unbind_at;
1125c4676082SAlex Vesker 
1126c4676082SAlex Vesker 	/* Allocate the RTC for the new matcher */
112738b5bf64SYevgeny Kliteynik 	ret = mlx5dr_matcher_create_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH);
1128c4676082SAlex Vesker 	if (ret)
1129c4676082SAlex Vesker 		goto destroy_end_ft;
1130c4676082SAlex Vesker 
1131ce946c7dSErez Shitrit 	/* Allocate and set shared resources */
1132ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_create_init_shared(matcher);
1133c4676082SAlex Vesker 	if (ret)
1134c4676082SAlex Vesker 		goto destroy_rtc;
1135c4676082SAlex Vesker 
1136ce946c7dSErez Shitrit 	/* Connect the matcher to the matcher list */
1137ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_connect(matcher);
1138ce946c7dSErez Shitrit 	if (ret)
1139ce946c7dSErez Shitrit 		goto destroy_shared;
1140ce946c7dSErez Shitrit 
1141c4676082SAlex Vesker 	return 0;
1142c4676082SAlex Vesker 
1143ce946c7dSErez Shitrit destroy_shared:
1144ce946c7dSErez Shitrit 	mlx5dr_matcher_create_uninit_shared(matcher);
1145c4676082SAlex Vesker destroy_rtc:
114638b5bf64SYevgeny Kliteynik 	mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH);
1147c4676082SAlex Vesker destroy_end_ft:
1148c4676082SAlex Vesker 	mlx5dr_matcher_destroy_end_ft(matcher);
1149c4676082SAlex Vesker unbind_at:
1150c4676082SAlex Vesker 	mlx5dr_matcher_unbind_at(matcher);
1151c4676082SAlex Vesker unbind_mt:
1152c4676082SAlex Vesker 	mlx5dr_matcher_unbind_mt(matcher);
1153c4676082SAlex Vesker 	return ret;
1154c4676082SAlex Vesker }
1155c4676082SAlex Vesker 
1156c4676082SAlex Vesker static void mlx5dr_matcher_destroy_and_disconnect(struct mlx5dr_matcher *matcher)
1157c4676082SAlex Vesker {
1158762fecebSYevgeny Kliteynik 	mlx5dr_matcher_resize_uninit(matcher);
1159c4676082SAlex Vesker 	mlx5dr_matcher_disconnect(matcher);
1160ce946c7dSErez Shitrit 	mlx5dr_matcher_create_uninit_shared(matcher);
116138b5bf64SYevgeny Kliteynik 	mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH);
1162c4676082SAlex Vesker 	mlx5dr_matcher_destroy_end_ft(matcher);
1163c4676082SAlex Vesker 	mlx5dr_matcher_unbind_at(matcher);
1164c4676082SAlex Vesker 	mlx5dr_matcher_unbind_mt(matcher);
1165c4676082SAlex Vesker }
1166c4676082SAlex Vesker 
1167c4676082SAlex Vesker static int
1168c4676082SAlex Vesker mlx5dr_matcher_create_col_matcher(struct mlx5dr_matcher *matcher)
1169c4676082SAlex Vesker {
1170c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
1171c4676082SAlex Vesker 	struct mlx5dr_matcher *col_matcher;
1172c4676082SAlex Vesker 	int ret;
1173c4676082SAlex Vesker 
117417a62e0bSYevgeny Kliteynik 	if (matcher->attr.mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE ||
117517a62e0bSYevgeny Kliteynik 	    matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX)
1176c4676082SAlex Vesker 		return 0;
1177c4676082SAlex Vesker 
1178c4676082SAlex Vesker 	if (!mlx5dr_matcher_requires_col_tbl(matcher->attr.rule.num_log))
1179c4676082SAlex Vesker 		return 0;
1180c4676082SAlex Vesker 
1181c4676082SAlex Vesker 	col_matcher = simple_calloc(1, sizeof(*matcher));
1182c4676082SAlex Vesker 	if (!col_matcher) {
1183c4676082SAlex Vesker 		rte_errno = ENOMEM;
1184c4676082SAlex Vesker 		return rte_errno;
1185c4676082SAlex Vesker 	}
1186c4676082SAlex Vesker 
1187c4676082SAlex Vesker 	col_matcher->tbl = matcher->tbl;
1188940b0ebaSAlex Vesker 	col_matcher->mt = matcher->mt;
1189940b0ebaSAlex Vesker 	col_matcher->at = matcher->at;
1190c4676082SAlex Vesker 	col_matcher->num_of_at = matcher->num_of_at;
1191940b0ebaSAlex Vesker 	col_matcher->num_of_mt = matcher->num_of_mt;
1192238190f3SAlex Vesker 	col_matcher->hash_definer = matcher->hash_definer;
1193c4676082SAlex Vesker 	col_matcher->attr.priority = matcher->attr.priority;
119427ac2da9SAlex Vesker 	col_matcher->flags = matcher->flags;
119527ac2da9SAlex Vesker 	col_matcher->flags |= MLX5DR_MATCHER_FLAGS_COLLISION;
1196c4676082SAlex Vesker 	col_matcher->attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE;
1197c4676082SAlex Vesker 	col_matcher->attr.optimize_flow_src = matcher->attr.optimize_flow_src;
1198c4676082SAlex Vesker 	col_matcher->attr.table.sz_row_log = matcher->attr.rule.num_log;
1199c4676082SAlex Vesker 	col_matcher->attr.table.sz_col_log = MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH;
1200c4676082SAlex Vesker 	if (col_matcher->attr.table.sz_row_log > MLX5DR_MATCHER_ASSURED_ROW_RATIO)
1201c4676082SAlex Vesker 		col_matcher->attr.table.sz_row_log -= MLX5DR_MATCHER_ASSURED_ROW_RATIO;
1202c4676082SAlex Vesker 
1203c5713fc1SErez Shitrit 	col_matcher->attr.max_num_of_at_attach = matcher->attr.max_num_of_at_attach;
1204c5713fc1SErez Shitrit 
1205c4676082SAlex Vesker 	ret = mlx5dr_matcher_process_attr(ctx->caps, col_matcher, false);
1206c4676082SAlex Vesker 	if (ret)
1207c4676082SAlex Vesker 		goto free_col_matcher;
1208c4676082SAlex Vesker 
1209c4676082SAlex Vesker 	ret = mlx5dr_matcher_create_and_connect(col_matcher);
1210c4676082SAlex Vesker 	if (ret)
1211c4676082SAlex Vesker 		goto free_col_matcher;
1212c4676082SAlex Vesker 
1213c4676082SAlex Vesker 	matcher->col_matcher = col_matcher;
1214c4676082SAlex Vesker 
1215c4676082SAlex Vesker 	return 0;
1216c4676082SAlex Vesker 
1217c4676082SAlex Vesker free_col_matcher:
1218c4676082SAlex Vesker 	simple_free(col_matcher);
1219c4676082SAlex Vesker 	DR_LOG(ERR, "Failed to create assured collision matcher");
1220c4676082SAlex Vesker 	return ret;
1221c4676082SAlex Vesker }
1222c4676082SAlex Vesker 
1223c4676082SAlex Vesker static void
1224c4676082SAlex Vesker mlx5dr_matcher_destroy_col_matcher(struct mlx5dr_matcher *matcher)
1225c4676082SAlex Vesker {
122617a62e0bSYevgeny Kliteynik 	if (matcher->attr.mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE ||
122717a62e0bSYevgeny Kliteynik 	    matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX)
1228c4676082SAlex Vesker 		return;
1229c4676082SAlex Vesker 
1230c4676082SAlex Vesker 	if (matcher->col_matcher) {
1231c4676082SAlex Vesker 		mlx5dr_matcher_destroy_and_disconnect(matcher->col_matcher);
1232c4676082SAlex Vesker 		simple_free(matcher->col_matcher);
1233c4676082SAlex Vesker 	}
1234c4676082SAlex Vesker }
1235c4676082SAlex Vesker 
1236c4676082SAlex Vesker static int mlx5dr_matcher_init(struct mlx5dr_matcher *matcher)
1237c4676082SAlex Vesker {
1238c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
1239c4676082SAlex Vesker 	int ret;
1240c4676082SAlex Vesker 
1241c4676082SAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
1242c4676082SAlex Vesker 
1243c4676082SAlex Vesker 	/* Allocate matcher resource and connect to the packet pipe */
1244c4676082SAlex Vesker 	ret = mlx5dr_matcher_create_and_connect(matcher);
1245c4676082SAlex Vesker 	if (ret)
1246c4676082SAlex Vesker 		goto unlock_err;
1247c4676082SAlex Vesker 
1248c4676082SAlex Vesker 	/* Create additional matcher for collision handling */
1249c4676082SAlex Vesker 	ret = mlx5dr_matcher_create_col_matcher(matcher);
1250c4676082SAlex Vesker 	if (ret)
1251c4676082SAlex Vesker 		goto destory_and_disconnect;
1252c4676082SAlex Vesker 
1253c4676082SAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
1254c4676082SAlex Vesker 
1255c4676082SAlex Vesker 	return 0;
1256c4676082SAlex Vesker 
1257c4676082SAlex Vesker destory_and_disconnect:
1258c4676082SAlex Vesker 	mlx5dr_matcher_destroy_and_disconnect(matcher);
1259c4676082SAlex Vesker unlock_err:
1260c4676082SAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
1261c4676082SAlex Vesker 	return ret;
1262c4676082SAlex Vesker }
1263c4676082SAlex Vesker 
1264c4676082SAlex Vesker static int mlx5dr_matcher_uninit(struct mlx5dr_matcher *matcher)
1265c4676082SAlex Vesker {
1266c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
1267c4676082SAlex Vesker 
1268c4676082SAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
1269c4676082SAlex Vesker 	mlx5dr_matcher_destroy_col_matcher(matcher);
1270c4676082SAlex Vesker 	mlx5dr_matcher_destroy_and_disconnect(matcher);
1271c4676082SAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
1272c4676082SAlex Vesker 
1273c4676082SAlex Vesker 	return 0;
1274c4676082SAlex Vesker }
1275c4676082SAlex Vesker 
1276c4676082SAlex Vesker static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher)
1277c4676082SAlex Vesker {
1278c4676082SAlex Vesker 	enum mlx5dr_table_type type = matcher->tbl->type;
1279c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
1280c4676082SAlex Vesker 	struct mlx5dv_flow_matcher_attr attr = {0};
1281c4676082SAlex Vesker 	struct mlx5dv_flow_match_parameters *mask;
1282c4676082SAlex Vesker 	struct mlx5_flow_attr flow_attr = {0};
1283c4676082SAlex Vesker 	struct rte_flow_error rte_error;
1284c4676082SAlex Vesker 	uint8_t match_criteria;
1285c4676082SAlex Vesker 	int ret;
1286c4676082SAlex Vesker 
1287c4676082SAlex Vesker #ifdef HAVE_MLX5DV_FLOW_MATCHER_FT_TYPE
1288c4676082SAlex Vesker 	attr.comp_mask = MLX5DV_FLOW_MATCHER_MASK_FT_TYPE;
1289c4676082SAlex Vesker 
1290c4676082SAlex Vesker 	switch (type) {
1291c4676082SAlex Vesker 	case MLX5DR_TABLE_TYPE_NIC_RX:
1292c4676082SAlex Vesker 		attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
1293c4676082SAlex Vesker 		break;
1294c4676082SAlex Vesker 	case MLX5DR_TABLE_TYPE_NIC_TX:
1295c4676082SAlex Vesker 		attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX;
1296c4676082SAlex Vesker 		break;
1297c4676082SAlex Vesker 	case MLX5DR_TABLE_TYPE_FDB:
1298c4676082SAlex Vesker 		attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
1299c4676082SAlex Vesker 		break;
1300c4676082SAlex Vesker 	default:
1301c4676082SAlex Vesker 		assert(0);
1302c4676082SAlex Vesker 		break;
1303c4676082SAlex Vesker 	}
1304c4676082SAlex Vesker #endif
1305c4676082SAlex Vesker 
1306c4676082SAlex Vesker 	if (matcher->attr.priority > UINT16_MAX) {
1307c4676082SAlex Vesker 		DR_LOG(ERR, "Root matcher priority exceeds allowed limit");
1308c4676082SAlex Vesker 		rte_errno = EINVAL;
1309c4676082SAlex Vesker 		return rte_errno;
1310c4676082SAlex Vesker 	}
1311c4676082SAlex Vesker 
1312572fe9efSErez Shitrit 	ret = flow_hw_get_port_id_from_ctx(ctx, &flow_attr.port_id);
1313572fe9efSErez Shitrit 	if (ret) {
1314befb138bSAlex Vesker 		DR_LOG(ERR, "Failed to get port id for dev %s", ctx->ibv_ctx->device->name);
1315572fe9efSErez Shitrit 		rte_errno = EINVAL;
1316572fe9efSErez Shitrit 		return rte_errno;
1317572fe9efSErez Shitrit 	}
1318572fe9efSErez Shitrit 
1319c4676082SAlex Vesker 	mask = simple_calloc(1, MLX5_ST_SZ_BYTES(fte_match_param) +
1320c4676082SAlex Vesker 			     offsetof(struct mlx5dv_flow_match_parameters, match_buf));
1321c4676082SAlex Vesker 	if (!mask) {
1322c4676082SAlex Vesker 		rte_errno = ENOMEM;
1323c4676082SAlex Vesker 		return rte_errno;
1324c4676082SAlex Vesker 	}
1325c4676082SAlex Vesker 
1326c4676082SAlex Vesker 	flow_attr.tbl_type = type;
1327c4676082SAlex Vesker 
1328c4676082SAlex Vesker 	/* On root table matcher, only a single match template is supported */
1329940b0ebaSAlex Vesker 	ret = flow_dv_translate_items_hws(matcher->mt[0].items,
1330c4676082SAlex Vesker 					  &flow_attr, mask->match_buf,
1331c4676082SAlex Vesker 					  MLX5_SET_MATCHER_HS_M, NULL,
1332c4676082SAlex Vesker 					  &match_criteria,
1333c4676082SAlex Vesker 					  &rte_error);
1334c4676082SAlex Vesker 	if (ret) {
1335c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to convert items to PRM [%s]", rte_error.message);
1336c4676082SAlex Vesker 		goto free_mask;
1337c4676082SAlex Vesker 	}
1338c4676082SAlex Vesker 
1339c4676082SAlex Vesker 	mask->match_sz = MLX5_ST_SZ_BYTES(fte_match_param);
1340c4676082SAlex Vesker 	attr.match_mask = mask;
1341c4676082SAlex Vesker 	attr.match_criteria_enable = match_criteria;
1342c4676082SAlex Vesker 	attr.type = IBV_FLOW_ATTR_NORMAL;
1343c4676082SAlex Vesker 	attr.priority = matcher->attr.priority;
1344c4676082SAlex Vesker 
1345c4676082SAlex Vesker 	matcher->dv_matcher =
1346ce946c7dSErez Shitrit 		mlx5_glue->dv_create_flow_matcher_root(mlx5dr_context_get_local_ibv(ctx),
1347ce946c7dSErez Shitrit 						       &attr);
1348c4676082SAlex Vesker 	if (!matcher->dv_matcher) {
1349c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to create DV flow matcher");
1350c4676082SAlex Vesker 		rte_errno = errno;
1351c4676082SAlex Vesker 		goto free_mask;
1352c4676082SAlex Vesker 	}
1353c4676082SAlex Vesker 
1354c4676082SAlex Vesker 	simple_free(mask);
1355c4676082SAlex Vesker 
1356c4676082SAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
1357c4676082SAlex Vesker 	LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
1358c4676082SAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
1359c4676082SAlex Vesker 
1360c4676082SAlex Vesker 	return 0;
1361c4676082SAlex Vesker 
1362c4676082SAlex Vesker free_mask:
1363c4676082SAlex Vesker 	simple_free(mask);
1364c4676082SAlex Vesker 	return rte_errno;
1365c4676082SAlex Vesker }
1366c4676082SAlex Vesker 
1367c4676082SAlex Vesker static int mlx5dr_matcher_uninit_root(struct mlx5dr_matcher *matcher)
1368c4676082SAlex Vesker {
1369c4676082SAlex Vesker 	struct mlx5dr_context *ctx = matcher->tbl->ctx;
1370c4676082SAlex Vesker 	int ret;
1371c4676082SAlex Vesker 
1372c4676082SAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
1373c4676082SAlex Vesker 	LIST_REMOVE(matcher, next);
1374c4676082SAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
1375c4676082SAlex Vesker 
1376c4676082SAlex Vesker 	ret = mlx5_glue->dv_destroy_flow_matcher_root(matcher->dv_matcher);
1377c4676082SAlex Vesker 	if (ret) {
1378c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to Destroy DV flow matcher");
1379c4676082SAlex Vesker 		rte_errno = errno;
1380c4676082SAlex Vesker 	}
1381c4676082SAlex Vesker 
1382c4676082SAlex Vesker 	return ret;
1383c4676082SAlex Vesker }
1384c4676082SAlex Vesker 
1385c5713fc1SErez Shitrit int mlx5dr_matcher_attach_at(struct mlx5dr_matcher *matcher,
1386c5713fc1SErez Shitrit 			     struct mlx5dr_action_template *at)
1387c5713fc1SErez Shitrit {
1388c5713fc1SErez Shitrit 	bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt);
1389c5713fc1SErez Shitrit 	uint32_t required_stes;
1390c5713fc1SErez Shitrit 	int ret;
1391c5713fc1SErez Shitrit 
1392c5713fc1SErez Shitrit 	if (!matcher->attr.max_num_of_at_attach) {
139363911723SYevgeny Kliteynik 		DR_LOG(DEBUG, "Num of current at (%d) exceed allowed value",
1394c5713fc1SErez Shitrit 		       matcher->num_of_at);
1395c5713fc1SErez Shitrit 		rte_errno = ENOTSUP;
1396c5713fc1SErez Shitrit 		return -rte_errno;
1397c5713fc1SErez Shitrit 	}
1398c5713fc1SErez Shitrit 
1399c5713fc1SErez Shitrit 	ret = mlx5dr_matcher_check_and_process_at(matcher, at);
1400c5713fc1SErez Shitrit 	if (ret)
1401c5713fc1SErez Shitrit 		return -rte_errno;
1402c5713fc1SErez Shitrit 
1403c5713fc1SErez Shitrit 	required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term);
1404c5713fc1SErez Shitrit 	if (matcher->action_ste.max_stes < required_stes) {
140563911723SYevgeny Kliteynik 		DR_LOG(DEBUG, "Required STEs [%d] exceeds initial action template STE [%d]",
1406c5713fc1SErez Shitrit 		       required_stes, matcher->action_ste.max_stes);
1407c5713fc1SErez Shitrit 		rte_errno = ENOMEM;
1408c5713fc1SErez Shitrit 		return -rte_errno;
1409c5713fc1SErez Shitrit 	}
1410c5713fc1SErez Shitrit 
1411c5713fc1SErez Shitrit 	matcher->at[matcher->num_of_at] = *at;
1412c5713fc1SErez Shitrit 	matcher->num_of_at += 1;
1413c5713fc1SErez Shitrit 	matcher->attr.max_num_of_at_attach -= 1;
1414c5713fc1SErez Shitrit 
1415c5713fc1SErez Shitrit 	if (matcher->col_matcher)
1416c5713fc1SErez Shitrit 		matcher->col_matcher->num_of_at = matcher->num_of_at;
1417c5713fc1SErez Shitrit 
1418c5713fc1SErez Shitrit 	return 0;
1419c5713fc1SErez Shitrit }
1420c5713fc1SErez Shitrit 
1421c4676082SAlex Vesker static int
1422940b0ebaSAlex Vesker mlx5dr_matcher_set_templates(struct mlx5dr_matcher *matcher,
1423940b0ebaSAlex Vesker 			     struct mlx5dr_match_template *mt[],
1424940b0ebaSAlex Vesker 			     uint8_t num_of_mt,
1425940b0ebaSAlex Vesker 			     struct mlx5dr_action_template *at[],
1426940b0ebaSAlex Vesker 			     uint8_t num_of_at)
1427c4676082SAlex Vesker {
1428940b0ebaSAlex Vesker 	bool is_root = mlx5dr_table_is_root(matcher->tbl);
1429940b0ebaSAlex Vesker 	int i;
1430c4676082SAlex Vesker 
1431c4676082SAlex Vesker 	if (!num_of_mt || !num_of_at) {
1432c4676082SAlex Vesker 		DR_LOG(ERR, "Number of action/match template cannot be zero");
1433940b0ebaSAlex Vesker 		rte_errno = ENOTSUP;
1434940b0ebaSAlex Vesker 		return rte_errno;
1435c4676082SAlex Vesker 	}
1436c4676082SAlex Vesker 
1437940b0ebaSAlex Vesker 	if (is_root && num_of_mt > MLX5DR_MATCHER_MAX_MT_ROOT) {
1438c4676082SAlex Vesker 		DR_LOG(ERR, "Number of match templates exceeds limit");
1439940b0ebaSAlex Vesker 		rte_errno = ENOTSUP;
1440940b0ebaSAlex Vesker 		return rte_errno;
1441c4676082SAlex Vesker 	}
1442c4676082SAlex Vesker 
1443940b0ebaSAlex Vesker 	matcher->mt = simple_calloc(num_of_mt, sizeof(*matcher->mt));
1444940b0ebaSAlex Vesker 	if (!matcher->mt) {
1445940b0ebaSAlex Vesker 		DR_LOG(ERR, "Failed to allocate match template array");
1446940b0ebaSAlex Vesker 		rte_errno = ENOMEM;
1447940b0ebaSAlex Vesker 		return rte_errno;
1448940b0ebaSAlex Vesker 	}
1449940b0ebaSAlex Vesker 
1450c5713fc1SErez Shitrit 	matcher->at = simple_calloc(num_of_at + matcher->attr.max_num_of_at_attach,
1451c5713fc1SErez Shitrit 				    sizeof(*matcher->at));
1452940b0ebaSAlex Vesker 	if (!matcher->at) {
1453940b0ebaSAlex Vesker 		DR_LOG(ERR, "Failed to allocate action template array");
1454940b0ebaSAlex Vesker 		rte_errno = ENOMEM;
1455940b0ebaSAlex Vesker 		goto free_mt;
1456940b0ebaSAlex Vesker 	}
1457940b0ebaSAlex Vesker 
1458940b0ebaSAlex Vesker 	for (i = 0; i < num_of_mt; i++)
1459940b0ebaSAlex Vesker 		matcher->mt[i] = *mt[i];
1460940b0ebaSAlex Vesker 
1461940b0ebaSAlex Vesker 	for (i = 0; i < num_of_at; i++)
1462940b0ebaSAlex Vesker 		matcher->at[i] = *at[i];
1463940b0ebaSAlex Vesker 
1464940b0ebaSAlex Vesker 	matcher->num_of_mt = num_of_mt;
1465940b0ebaSAlex Vesker 	matcher->num_of_at = num_of_at;
1466940b0ebaSAlex Vesker 
1467c4676082SAlex Vesker 	return 0;
1468c4676082SAlex Vesker 
1469940b0ebaSAlex Vesker free_mt:
1470940b0ebaSAlex Vesker 	simple_free(matcher->mt);
1471c4676082SAlex Vesker 	return rte_errno;
1472c4676082SAlex Vesker }
1473c4676082SAlex Vesker 
1474940b0ebaSAlex Vesker static void
1475940b0ebaSAlex Vesker mlx5dr_matcher_unset_templates(struct mlx5dr_matcher *matcher)
1476940b0ebaSAlex Vesker {
1477940b0ebaSAlex Vesker 	simple_free(matcher->at);
1478940b0ebaSAlex Vesker 	simple_free(matcher->mt);
1479940b0ebaSAlex Vesker }
1480940b0ebaSAlex Vesker 
1481c4676082SAlex Vesker struct mlx5dr_matcher *
1482c4676082SAlex Vesker mlx5dr_matcher_create(struct mlx5dr_table *tbl,
1483c4676082SAlex Vesker 		      struct mlx5dr_match_template *mt[],
1484c4676082SAlex Vesker 		      uint8_t num_of_mt,
1485c4676082SAlex Vesker 		      struct mlx5dr_action_template *at[],
1486c4676082SAlex Vesker 		      uint8_t num_of_at,
1487c4676082SAlex Vesker 		      struct mlx5dr_matcher_attr *attr)
1488c4676082SAlex Vesker {
1489c4676082SAlex Vesker 	bool is_root = mlx5dr_table_is_root(tbl);
1490c4676082SAlex Vesker 	struct mlx5dr_matcher *matcher;
1491c4676082SAlex Vesker 	int ret;
1492c4676082SAlex Vesker 
1493c4676082SAlex Vesker 	matcher = simple_calloc(1, sizeof(*matcher));
1494c4676082SAlex Vesker 	if (!matcher) {
1495c4676082SAlex Vesker 		rte_errno = ENOMEM;
1496c4676082SAlex Vesker 		return NULL;
1497c4676082SAlex Vesker 	}
1498c4676082SAlex Vesker 
1499c4676082SAlex Vesker 	matcher->tbl = tbl;
1500c4676082SAlex Vesker 	matcher->attr = *attr;
1501c4676082SAlex Vesker 
1502c4676082SAlex Vesker 	ret = mlx5dr_matcher_process_attr(tbl->ctx->caps, matcher, is_root);
1503c4676082SAlex Vesker 	if (ret)
1504c4676082SAlex Vesker 		goto free_matcher;
1505c4676082SAlex Vesker 
1506940b0ebaSAlex Vesker 	ret = mlx5dr_matcher_set_templates(matcher, mt, num_of_mt, at, num_of_at);
1507940b0ebaSAlex Vesker 	if (ret)
1508940b0ebaSAlex Vesker 		goto free_matcher;
1509940b0ebaSAlex Vesker 
1510c4676082SAlex Vesker 	if (is_root)
1511c4676082SAlex Vesker 		ret = mlx5dr_matcher_init_root(matcher);
1512c4676082SAlex Vesker 	else
1513c4676082SAlex Vesker 		ret = mlx5dr_matcher_init(matcher);
1514c4676082SAlex Vesker 
1515c4676082SAlex Vesker 	if (ret) {
1516c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to initialise matcher: %d", ret);
1517940b0ebaSAlex Vesker 		goto unset_templates;
1518c4676082SAlex Vesker 	}
1519c4676082SAlex Vesker 
1520c4676082SAlex Vesker 	return matcher;
1521c4676082SAlex Vesker 
1522940b0ebaSAlex Vesker unset_templates:
1523940b0ebaSAlex Vesker 	mlx5dr_matcher_unset_templates(matcher);
1524c4676082SAlex Vesker free_matcher:
1525c4676082SAlex Vesker 	simple_free(matcher);
1526c4676082SAlex Vesker 	return NULL;
1527c4676082SAlex Vesker }
1528c4676082SAlex Vesker 
1529c4676082SAlex Vesker int mlx5dr_matcher_destroy(struct mlx5dr_matcher *matcher)
1530c4676082SAlex Vesker {
1531c4676082SAlex Vesker 	if (mlx5dr_table_is_root(matcher->tbl))
1532c4676082SAlex Vesker 		mlx5dr_matcher_uninit_root(matcher);
1533c4676082SAlex Vesker 	else
1534c4676082SAlex Vesker 		mlx5dr_matcher_uninit(matcher);
1535c4676082SAlex Vesker 
1536940b0ebaSAlex Vesker 	mlx5dr_matcher_unset_templates(matcher);
1537c4676082SAlex Vesker 	simple_free(matcher);
1538c4676082SAlex Vesker 	return 0;
1539c4676082SAlex Vesker }
1540c4676082SAlex Vesker 
1541c4676082SAlex Vesker struct mlx5dr_match_template *
1542c4676082SAlex Vesker mlx5dr_match_template_create(const struct rte_flow_item items[],
1543c4676082SAlex Vesker 			     enum mlx5dr_match_template_flags flags)
1544c4676082SAlex Vesker {
1545c4676082SAlex Vesker 	struct mlx5dr_match_template *mt;
1546c4676082SAlex Vesker 	struct rte_flow_error error;
1547c4676082SAlex Vesker 	int ret, len;
1548c4676082SAlex Vesker 
1549c4676082SAlex Vesker 	if (flags > MLX5DR_MATCH_TEMPLATE_FLAG_RELAXED_MATCH) {
1550c4676082SAlex Vesker 		DR_LOG(ERR, "Unsupported match template flag provided");
1551c4676082SAlex Vesker 		rte_errno = EINVAL;
1552c4676082SAlex Vesker 		return NULL;
1553c4676082SAlex Vesker 	}
1554c4676082SAlex Vesker 
1555c4676082SAlex Vesker 	mt = simple_calloc(1, sizeof(*mt));
1556c4676082SAlex Vesker 	if (!mt) {
1557c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to allocate match template");
1558c4676082SAlex Vesker 		rte_errno = ENOMEM;
1559c4676082SAlex Vesker 		return NULL;
1560c4676082SAlex Vesker 	}
1561c4676082SAlex Vesker 
1562c4676082SAlex Vesker 	mt->flags = flags;
1563c4676082SAlex Vesker 
1564c4676082SAlex Vesker 	/* Duplicate the user given items */
1565c4676082SAlex Vesker 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, NULL, 0, items, &error);
1566c4676082SAlex Vesker 	if (ret <= 0) {
1567c4676082SAlex Vesker 		DR_LOG(ERR, "Unable to process items (%s): %s",
1568c4676082SAlex Vesker 		       error.message ? error.message : "unspecified",
1569c4676082SAlex Vesker 		       strerror(rte_errno));
1570c4676082SAlex Vesker 		goto free_template;
1571c4676082SAlex Vesker 	}
1572c4676082SAlex Vesker 
1573c4676082SAlex Vesker 	len = RTE_ALIGN(ret, 16);
1574c4676082SAlex Vesker 	mt->items = simple_calloc(1, len);
1575c4676082SAlex Vesker 	if (!mt->items) {
1576c4676082SAlex Vesker 		DR_LOG(ERR, "Failed to allocate item copy");
1577c4676082SAlex Vesker 		rte_errno = ENOMEM;
1578c4676082SAlex Vesker 		goto free_template;
1579c4676082SAlex Vesker 	}
1580c4676082SAlex Vesker 
1581c4676082SAlex Vesker 	ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, mt->items, ret, items, &error);
1582c4676082SAlex Vesker 	if (ret <= 0)
1583c4676082SAlex Vesker 		goto free_dst;
1584c4676082SAlex Vesker 
1585c4676082SAlex Vesker 	return mt;
1586c4676082SAlex Vesker 
1587c4676082SAlex Vesker free_dst:
1588c4676082SAlex Vesker 	simple_free(mt->items);
1589c4676082SAlex Vesker free_template:
1590c4676082SAlex Vesker 	simple_free(mt);
1591c4676082SAlex Vesker 	return NULL;
1592c4676082SAlex Vesker }
1593c4676082SAlex Vesker 
1594c4676082SAlex Vesker int mlx5dr_match_template_destroy(struct mlx5dr_match_template *mt)
1595c4676082SAlex Vesker {
1596c4676082SAlex Vesker 	simple_free(mt->items);
1597c4676082SAlex Vesker 	simple_free(mt);
1598c4676082SAlex Vesker 	return 0;
1599c4676082SAlex Vesker }
1600762fecebSYevgeny Kliteynik 
1601d64bbe7bSErez Shitrit bool mlx5dr_matcher_is_updatable(struct mlx5dr_matcher *matcher)
1602d64bbe7bSErez Shitrit {
1603d64bbe7bSErez Shitrit 	if (mlx5dr_table_is_root(matcher->tbl) ||
1604d64bbe7bSErez Shitrit 	    mlx5dr_matcher_req_fw_wqe(matcher) ||
1605d64bbe7bSErez Shitrit 	    mlx5dr_matcher_is_resizable(matcher) ||
1606d64bbe7bSErez Shitrit 	    (!matcher->attr.optimize_using_rule_idx &&
1607d64bbe7bSErez Shitrit 	    !mlx5dr_matcher_is_insert_by_idx(matcher)))
1608d64bbe7bSErez Shitrit 		return false;
1609d64bbe7bSErez Shitrit 
1610d64bbe7bSErez Shitrit 	return true;
1611d64bbe7bSErez Shitrit }
1612d64bbe7bSErez Shitrit 
16133af4ed67SErez Shitrit bool mlx5dr_matcher_is_dependent(struct mlx5dr_matcher *matcher)
16143af4ed67SErez Shitrit {
16153af4ed67SErez Shitrit 	int i;
16163af4ed67SErez Shitrit 
16173af4ed67SErez Shitrit 	if (matcher->action_ste.max_stes || mlx5dr_matcher_req_fw_wqe(matcher))
16183af4ed67SErez Shitrit 		return true;
16193af4ed67SErez Shitrit 
16203af4ed67SErez Shitrit 	for (i = 0; i < matcher->num_of_at; i++) {
16213af4ed67SErez Shitrit 		struct mlx5dr_action_template *at = &matcher->at[i];
16223af4ed67SErez Shitrit 
16233af4ed67SErez Shitrit 		if (at->need_dep_write)
16243af4ed67SErez Shitrit 			return true;
16253af4ed67SErez Shitrit 	}
16263af4ed67SErez Shitrit 
16273af4ed67SErez Shitrit 	return false;
16283af4ed67SErez Shitrit }
16293af4ed67SErez Shitrit 
1630762fecebSYevgeny Kliteynik static int mlx5dr_matcher_resize_precheck(struct mlx5dr_matcher *src_matcher,
1631762fecebSYevgeny Kliteynik 					  struct mlx5dr_matcher *dst_matcher)
1632762fecebSYevgeny Kliteynik {
1633762fecebSYevgeny Kliteynik 	int i;
1634762fecebSYevgeny Kliteynik 
1635762fecebSYevgeny Kliteynik 	if (mlx5dr_table_is_root(src_matcher->tbl) ||
1636762fecebSYevgeny Kliteynik 	    mlx5dr_table_is_root(dst_matcher->tbl)) {
1637762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Src/dst matcher belongs to root table - resize unsupported");
1638762fecebSYevgeny Kliteynik 		goto out_einval;
1639762fecebSYevgeny Kliteynik 	}
1640762fecebSYevgeny Kliteynik 
1641762fecebSYevgeny Kliteynik 	if (src_matcher->tbl->type != dst_matcher->tbl->type) {
1642762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Table type mismatch for src/dst matchers");
1643762fecebSYevgeny Kliteynik 		goto out_einval;
1644762fecebSYevgeny Kliteynik 	}
1645762fecebSYevgeny Kliteynik 
1646762fecebSYevgeny Kliteynik 	if (mlx5dr_matcher_req_fw_wqe(src_matcher) ||
1647762fecebSYevgeny Kliteynik 	    mlx5dr_matcher_req_fw_wqe(dst_matcher)) {
1648762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Matchers require FW WQE - resize unsupported");
1649762fecebSYevgeny Kliteynik 		goto out_einval;
1650762fecebSYevgeny Kliteynik 	}
1651762fecebSYevgeny Kliteynik 
1652762fecebSYevgeny Kliteynik 	if (!mlx5dr_matcher_is_resizable(src_matcher) ||
1653762fecebSYevgeny Kliteynik 	    !mlx5dr_matcher_is_resizable(dst_matcher)) {
1654762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Src/dst matcher is not resizable");
1655762fecebSYevgeny Kliteynik 		goto out_einval;
1656762fecebSYevgeny Kliteynik 	}
1657762fecebSYevgeny Kliteynik 
1658762fecebSYevgeny Kliteynik 	if (mlx5dr_matcher_is_insert_by_idx(src_matcher) !=
1659762fecebSYevgeny Kliteynik 	    mlx5dr_matcher_is_insert_by_idx(dst_matcher)) {
1660762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Src/dst matchers insert mode mismatch");
1661762fecebSYevgeny Kliteynik 		goto out_einval;
1662762fecebSYevgeny Kliteynik 	}
1663762fecebSYevgeny Kliteynik 
1664762fecebSYevgeny Kliteynik 	if (mlx5dr_matcher_is_in_resize(src_matcher) ||
1665762fecebSYevgeny Kliteynik 	    mlx5dr_matcher_is_in_resize(dst_matcher)) {
1666762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Src/dst matcher is already in resize");
1667762fecebSYevgeny Kliteynik 		goto out_einval;
1668762fecebSYevgeny Kliteynik 	}
1669762fecebSYevgeny Kliteynik 
1670762fecebSYevgeny Kliteynik 	/* Compare match templates - make sure the definers are equivalent */
1671762fecebSYevgeny Kliteynik 	if (src_matcher->num_of_mt != dst_matcher->num_of_mt) {
1672762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Src/dst matcher match templates mismatch");
1673762fecebSYevgeny Kliteynik 		goto out_einval;
1674762fecebSYevgeny Kliteynik 	}
1675762fecebSYevgeny Kliteynik 
1676762fecebSYevgeny Kliteynik 	if (src_matcher->action_ste.max_stes > dst_matcher->action_ste.max_stes) {
1677762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Src/dst matcher max STEs mismatch");
1678762fecebSYevgeny Kliteynik 		goto out_einval;
1679762fecebSYevgeny Kliteynik 	}
1680762fecebSYevgeny Kliteynik 
1681762fecebSYevgeny Kliteynik 	for (i = 0; i < src_matcher->num_of_mt; i++) {
1682762fecebSYevgeny Kliteynik 		if (mlx5dr_definer_compare(src_matcher->mt[i].definer,
1683762fecebSYevgeny Kliteynik 					   dst_matcher->mt[i].definer)) {
1684762fecebSYevgeny Kliteynik 			DR_LOG(ERR, "Src/dst matcher definers mismatch");
1685762fecebSYevgeny Kliteynik 			goto out_einval;
1686762fecebSYevgeny Kliteynik 		}
1687762fecebSYevgeny Kliteynik 	}
1688762fecebSYevgeny Kliteynik 
1689762fecebSYevgeny Kliteynik 	return 0;
1690762fecebSYevgeny Kliteynik 
1691762fecebSYevgeny Kliteynik out_einval:
1692762fecebSYevgeny Kliteynik 	rte_errno = EINVAL;
1693762fecebSYevgeny Kliteynik 	return rte_errno;
1694762fecebSYevgeny Kliteynik }
1695762fecebSYevgeny Kliteynik 
1696762fecebSYevgeny Kliteynik int mlx5dr_matcher_resize_set_target(struct mlx5dr_matcher *src_matcher,
1697762fecebSYevgeny Kliteynik 				     struct mlx5dr_matcher *dst_matcher)
1698762fecebSYevgeny Kliteynik {
1699762fecebSYevgeny Kliteynik 	int ret = 0;
1700762fecebSYevgeny Kliteynik 
1701762fecebSYevgeny Kliteynik 	pthread_spin_lock(&src_matcher->tbl->ctx->ctrl_lock);
1702762fecebSYevgeny Kliteynik 
1703762fecebSYevgeny Kliteynik 	if (mlx5dr_matcher_resize_precheck(src_matcher, dst_matcher)) {
1704762fecebSYevgeny Kliteynik 		ret = -rte_errno;
1705762fecebSYevgeny Kliteynik 		goto out;
1706762fecebSYevgeny Kliteynik 	}
1707762fecebSYevgeny Kliteynik 
1708762fecebSYevgeny Kliteynik 	src_matcher->resize_dst = dst_matcher;
1709762fecebSYevgeny Kliteynik 
1710762fecebSYevgeny Kliteynik 	if (mlx5dr_matcher_resize_init(src_matcher)) {
1711762fecebSYevgeny Kliteynik 		src_matcher->resize_dst = NULL;
1712762fecebSYevgeny Kliteynik 		ret = -rte_errno;
1713762fecebSYevgeny Kliteynik 	}
1714762fecebSYevgeny Kliteynik 
1715762fecebSYevgeny Kliteynik out:
1716762fecebSYevgeny Kliteynik 	pthread_spin_unlock(&src_matcher->tbl->ctx->ctrl_lock);
1717762fecebSYevgeny Kliteynik 	return ret;
1718762fecebSYevgeny Kliteynik }
1719762fecebSYevgeny Kliteynik 
1720762fecebSYevgeny Kliteynik int mlx5dr_matcher_resize_rule_move(struct mlx5dr_matcher *src_matcher,
1721762fecebSYevgeny Kliteynik 				    struct mlx5dr_rule *rule,
1722762fecebSYevgeny Kliteynik 				    struct mlx5dr_rule_attr *attr)
1723762fecebSYevgeny Kliteynik {
1724762fecebSYevgeny Kliteynik 	if (unlikely(!mlx5dr_matcher_is_in_resize(src_matcher))) {
1725762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Matcher is not resizable or not in resize");
1726762fecebSYevgeny Kliteynik 		goto out_einval;
1727762fecebSYevgeny Kliteynik 	}
1728762fecebSYevgeny Kliteynik 
1729762fecebSYevgeny Kliteynik 	if (unlikely(src_matcher != rule->matcher)) {
1730762fecebSYevgeny Kliteynik 		DR_LOG(ERR, "Rule doesn't belong to src matcher");
1731762fecebSYevgeny Kliteynik 		goto out_einval;
1732762fecebSYevgeny Kliteynik 	}
1733762fecebSYevgeny Kliteynik 
1734762fecebSYevgeny Kliteynik 	return mlx5dr_rule_move_hws_add(rule, attr);
1735762fecebSYevgeny Kliteynik 
1736762fecebSYevgeny Kliteynik out_einval:
1737762fecebSYevgeny Kliteynik 	rte_errno = EINVAL;
1738762fecebSYevgeny Kliteynik 	return -rte_errno;
1739762fecebSYevgeny Kliteynik }
1740a5230507SHamdan Igbaria 
1741a5230507SHamdan Igbaria int mlx5dr_matcher_validate_compare_attr(struct mlx5dr_matcher *matcher)
1742a5230507SHamdan Igbaria {
1743a5230507SHamdan Igbaria 	struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps;
1744a5230507SHamdan Igbaria 	struct mlx5dr_matcher_attr *attr = &matcher->attr;
1745a5230507SHamdan Igbaria 
1746a5230507SHamdan Igbaria 	if (mlx5dr_table_is_root(matcher->tbl)) {
1747a5230507SHamdan Igbaria 		DR_LOG(ERR, "Compare matcher is not supported for root tables");
1748a5230507SHamdan Igbaria 		goto err;
1749a5230507SHamdan Igbaria 	}
1750a5230507SHamdan Igbaria 
1751a5230507SHamdan Igbaria 	if (attr->mode != MLX5DR_MATCHER_RESOURCE_MODE_HTABLE) {
1752a5230507SHamdan Igbaria 		DR_LOG(ERR, "Compare matcher is only supported with pre-defined table size");
1753a5230507SHamdan Igbaria 		goto err;
1754a5230507SHamdan Igbaria 	}
1755a5230507SHamdan Igbaria 
1756a5230507SHamdan Igbaria 	if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH ||
1757a5230507SHamdan Igbaria 		attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) {
1758a5230507SHamdan Igbaria 		DR_LOG(ERR, "Gen WQE for compare matcher must be inserted and distribute by hash");
1759a5230507SHamdan Igbaria 		goto err;
1760a5230507SHamdan Igbaria 	}
1761a5230507SHamdan Igbaria 
1762a5230507SHamdan Igbaria 	if (matcher->num_of_mt != 1 || matcher->num_of_at != 1) {
1763a5230507SHamdan Igbaria 		DR_LOG(ERR, "Compare matcher match templates and action templates must be 1 for each");
1764a5230507SHamdan Igbaria 		goto err;
1765a5230507SHamdan Igbaria 	}
1766a5230507SHamdan Igbaria 
1767a5230507SHamdan Igbaria 	if (attr->table.sz_col_log || attr->table.sz_row_log) {
1768a5230507SHamdan Igbaria 		DR_LOG(ERR, "Compare matcher supports only 1x1 table size");
1769a5230507SHamdan Igbaria 		goto err;
1770a5230507SHamdan Igbaria 	}
1771a5230507SHamdan Igbaria 
1772a5230507SHamdan Igbaria 	if (attr->resizable) {
1773a5230507SHamdan Igbaria 		DR_LOG(ERR, "Compare matcher does not support resizeing");
1774a5230507SHamdan Igbaria 		goto err;
1775a5230507SHamdan Igbaria 	}
1776a5230507SHamdan Igbaria 
1777a5230507SHamdan Igbaria 	if (!IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_4DW_RANGE)) {
1778a5230507SHamdan Igbaria 		DR_LOG(ERR, "Gen WQE Compare match format not supported");
1779a5230507SHamdan Igbaria 		goto err;
1780a5230507SHamdan Igbaria 	}
1781a5230507SHamdan Igbaria 
1782a5230507SHamdan Igbaria 	return 0;
1783a5230507SHamdan Igbaria 
1784a5230507SHamdan Igbaria err:
1785a5230507SHamdan Igbaria 	rte_errno = ENOTSUP;
1786a5230507SHamdan Igbaria 	return rte_errno;
1787a5230507SHamdan Igbaria }
1788