xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_table.c (revision 486f9aac0cbe2598a76c853890c1d557747f71cf)
1394cc7baSAlex Vesker /* SPDX-License-Identifier: BSD-3-Clause
2394cc7baSAlex Vesker  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3394cc7baSAlex Vesker  */
4394cc7baSAlex Vesker 
5394cc7baSAlex Vesker #include "mlx5dr_internal.h"
6394cc7baSAlex Vesker 
7394cc7baSAlex Vesker static void mlx5dr_table_init_next_ft_attr(struct mlx5dr_table *tbl,
8394cc7baSAlex Vesker 					   struct mlx5dr_cmd_ft_create_attr *ft_attr)
9394cc7baSAlex Vesker {
10394cc7baSAlex Vesker 	ft_attr->type = tbl->fw_ft_type;
11394cc7baSAlex Vesker 	if (tbl->type == MLX5DR_TABLE_TYPE_FDB)
12394cc7baSAlex Vesker 		ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1;
13394cc7baSAlex Vesker 	else
14394cc7baSAlex Vesker 		ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1;
15394cc7baSAlex Vesker 	ft_attr->rtc_valid = true;
16394cc7baSAlex Vesker }
17394cc7baSAlex Vesker 
18394cc7baSAlex Vesker /* Call this under ctx->ctrl_lock */
19394cc7baSAlex Vesker static int
20394cc7baSAlex Vesker mlx5dr_table_up_default_fdb_miss_tbl(struct mlx5dr_table *tbl)
21394cc7baSAlex Vesker {
22394cc7baSAlex Vesker 	struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
23e1df1578SHamdan Igbaria 	struct mlx5dr_cmd_set_fte_attr fte_attr = {0};
24394cc7baSAlex Vesker 	struct mlx5dr_cmd_forward_tbl *default_miss;
25eefaf43dSShun Hao 	struct mlx5dr_cmd_set_fte_dest dest = {0};
26394cc7baSAlex Vesker 	struct mlx5dr_context *ctx = tbl->ctx;
27394cc7baSAlex Vesker 	uint8_t tbl_type = tbl->type;
28394cc7baSAlex Vesker 
29394cc7baSAlex Vesker 	if (tbl->type != MLX5DR_TABLE_TYPE_FDB)
30394cc7baSAlex Vesker 		return 0;
31394cc7baSAlex Vesker 
32394cc7baSAlex Vesker 	if (ctx->common_res[tbl_type].default_miss) {
33394cc7baSAlex Vesker 		ctx->common_res[tbl_type].default_miss->refcount++;
34394cc7baSAlex Vesker 		return 0;
35394cc7baSAlex Vesker 	}
36394cc7baSAlex Vesker 
37394cc7baSAlex Vesker 	ft_attr.type = tbl->fw_ft_type;
38394cc7baSAlex Vesker 	ft_attr.level = tbl->ctx->caps->fdb_ft.max_level; /* The last level */
39394cc7baSAlex Vesker 	ft_attr.rtc_valid = false;
40394cc7baSAlex Vesker 
41eefaf43dSShun Hao 	dest.destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
42eefaf43dSShun Hao 	dest.destination_id = ctx->caps->eswitch_manager_vport_number;
43e1df1578SHamdan Igbaria 	fte_attr.action_flags = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
44eefaf43dSShun Hao 	fte_attr.dests_num = 1;
45eefaf43dSShun Hao 	fte_attr.dests = &dest;
46e1df1578SHamdan Igbaria 
47e1df1578SHamdan Igbaria 	default_miss = mlx5dr_cmd_forward_tbl_create(mlx5dr_context_get_local_ibv(ctx),
48e1df1578SHamdan Igbaria 						     &ft_attr, &fte_attr);
49394cc7baSAlex Vesker 	if (!default_miss) {
50394cc7baSAlex Vesker 		DR_LOG(ERR, "Failed to default miss table type: 0x%x", tbl_type);
51394cc7baSAlex Vesker 		return rte_errno;
52394cc7baSAlex Vesker 	}
53394cc7baSAlex Vesker 
54394cc7baSAlex Vesker 	ctx->common_res[tbl_type].default_miss = default_miss;
55394cc7baSAlex Vesker 	ctx->common_res[tbl_type].default_miss->refcount++;
56394cc7baSAlex Vesker 	return 0;
57394cc7baSAlex Vesker }
58394cc7baSAlex Vesker 
59394cc7baSAlex Vesker /* Called under pthread_spin_lock(&ctx->ctrl_lock) */
60394cc7baSAlex Vesker static void mlx5dr_table_down_default_fdb_miss_tbl(struct mlx5dr_table *tbl)
61394cc7baSAlex Vesker {
62394cc7baSAlex Vesker 	struct mlx5dr_cmd_forward_tbl *default_miss;
63394cc7baSAlex Vesker 	struct mlx5dr_context *ctx = tbl->ctx;
64394cc7baSAlex Vesker 	uint8_t tbl_type = tbl->type;
65394cc7baSAlex Vesker 
66394cc7baSAlex Vesker 	if (tbl->type != MLX5DR_TABLE_TYPE_FDB)
67394cc7baSAlex Vesker 		return;
68394cc7baSAlex Vesker 
69394cc7baSAlex Vesker 	default_miss = ctx->common_res[tbl_type].default_miss;
70394cc7baSAlex Vesker 	if (--default_miss->refcount)
71394cc7baSAlex Vesker 		return;
72394cc7baSAlex Vesker 
73e1df1578SHamdan Igbaria 	mlx5dr_cmd_forward_tbl_destroy(default_miss);
74394cc7baSAlex Vesker 	ctx->common_res[tbl_type].default_miss = NULL;
75394cc7baSAlex Vesker }
76394cc7baSAlex Vesker 
77394cc7baSAlex Vesker static int
78394cc7baSAlex Vesker mlx5dr_table_connect_to_default_miss_tbl(struct mlx5dr_table *tbl,
79394cc7baSAlex Vesker 					 struct mlx5dr_devx_obj *ft)
80394cc7baSAlex Vesker {
81394cc7baSAlex Vesker 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
82394cc7baSAlex Vesker 	int ret;
83394cc7baSAlex Vesker 
84394cc7baSAlex Vesker 	assert(tbl->type == MLX5DR_TABLE_TYPE_FDB);
85394cc7baSAlex Vesker 
86394cc7baSAlex Vesker 	mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx,
87394cc7baSAlex Vesker 					     tbl->fw_ft_type,
88394cc7baSAlex Vesker 					     tbl->type,
89394cc7baSAlex Vesker 					     &ft_attr);
90394cc7baSAlex Vesker 
91394cc7baSAlex Vesker 	/* Connect to next */
92394cc7baSAlex Vesker 	ret = mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
93394cc7baSAlex Vesker 	if (ret) {
94394cc7baSAlex Vesker 		DR_LOG(ERR, "Failed to connect FT to default FDB FT");
95b81f95caSItamar Gozlan 		return ret;
96394cc7baSAlex Vesker 	}
97394cc7baSAlex Vesker 
98394cc7baSAlex Vesker 	return 0;
99394cc7baSAlex Vesker }
100394cc7baSAlex Vesker 
101394cc7baSAlex Vesker struct mlx5dr_devx_obj *
102ce946c7dSErez Shitrit mlx5dr_table_create_default_ft(struct ibv_context *ibv,
103ce946c7dSErez Shitrit 			       struct mlx5dr_table *tbl)
104394cc7baSAlex Vesker {
105394cc7baSAlex Vesker 	struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
106394cc7baSAlex Vesker 	struct mlx5dr_devx_obj *ft_obj;
107394cc7baSAlex Vesker 	int ret;
108394cc7baSAlex Vesker 
109394cc7baSAlex Vesker 	mlx5dr_table_init_next_ft_attr(tbl, &ft_attr);
110394cc7baSAlex Vesker 
111ce946c7dSErez Shitrit 	ft_obj = mlx5dr_cmd_flow_table_create(ibv, &ft_attr);
112394cc7baSAlex Vesker 	if (ft_obj && tbl->type == MLX5DR_TABLE_TYPE_FDB) {
113394cc7baSAlex Vesker 		/* Take/create ref over the default miss */
114394cc7baSAlex Vesker 		ret = mlx5dr_table_up_default_fdb_miss_tbl(tbl);
115394cc7baSAlex Vesker 		if (ret) {
116394cc7baSAlex Vesker 			DR_LOG(ERR, "Failed to get default fdb miss");
117394cc7baSAlex Vesker 			goto free_ft_obj;
118394cc7baSAlex Vesker 		}
119394cc7baSAlex Vesker 		ret = mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj);
120394cc7baSAlex Vesker 		if (ret) {
121394cc7baSAlex Vesker 			DR_LOG(ERR, "Failed connecting to default miss tbl");
122394cc7baSAlex Vesker 			goto down_miss_tbl;
123394cc7baSAlex Vesker 		}
124394cc7baSAlex Vesker 	}
125394cc7baSAlex Vesker 
126394cc7baSAlex Vesker 	return ft_obj;
127394cc7baSAlex Vesker 
128394cc7baSAlex Vesker down_miss_tbl:
129394cc7baSAlex Vesker 	mlx5dr_table_down_default_fdb_miss_tbl(tbl);
130394cc7baSAlex Vesker free_ft_obj:
131394cc7baSAlex Vesker 	mlx5dr_cmd_destroy_obj(ft_obj);
132394cc7baSAlex Vesker 	return NULL;
133394cc7baSAlex Vesker }
134394cc7baSAlex Vesker 
135ce946c7dSErez Shitrit static int
136ce946c7dSErez Shitrit mlx5dr_table_init_check_hws_support(struct mlx5dr_context *ctx,
137ce946c7dSErez Shitrit 				    struct mlx5dr_table *tbl)
138ce946c7dSErez Shitrit {
139ce946c7dSErez Shitrit 	if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) {
140ce946c7dSErez Shitrit 		DR_LOG(ERR, "HWS not supported, cannot create mlx5dr_table");
141ce946c7dSErez Shitrit 		rte_errno = EOPNOTSUPP;
142ce946c7dSErez Shitrit 		return rte_errno;
143ce946c7dSErez Shitrit 	}
144ce946c7dSErez Shitrit 
145ce946c7dSErez Shitrit 	if (mlx5dr_context_shared_gvmi_used(ctx) && tbl->type == MLX5DR_TABLE_TYPE_FDB) {
146ce946c7dSErez Shitrit 		DR_LOG(ERR, "FDB with shared port resources is not supported");
147ce946c7dSErez Shitrit 		rte_errno = EOPNOTSUPP;
148ce946c7dSErez Shitrit 		return rte_errno;
149ce946c7dSErez Shitrit 	}
150ce946c7dSErez Shitrit 
151ce946c7dSErez Shitrit 	return 0;
152ce946c7dSErez Shitrit }
153ce946c7dSErez Shitrit 
154ce946c7dSErez Shitrit static int
155ce946c7dSErez Shitrit mlx5dr_table_shared_gvmi_resource_create(struct mlx5dr_context *ctx,
156ce946c7dSErez Shitrit 					 enum mlx5dr_table_type type,
157ce946c7dSErez Shitrit 					 struct mlx5dr_context_shared_gvmi_res *gvmi_res)
158ce946c7dSErez Shitrit {
159ce946c7dSErez Shitrit 	struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
160ce946c7dSErez Shitrit 	uint32_t calculated_ft_id;
161ce946c7dSErez Shitrit 	int ret;
162ce946c7dSErez Shitrit 
163ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
164ce946c7dSErez Shitrit 		return 0;
165ce946c7dSErez Shitrit 
166ce946c7dSErez Shitrit 	ft_attr.type = mlx5dr_table_get_res_fw_ft_type(type, false);
167ce946c7dSErez Shitrit 	ft_attr.level = ctx->caps->nic_ft.max_level - 1;
168ce946c7dSErez Shitrit 	ft_attr.rtc_valid = true;
169ce946c7dSErez Shitrit 
170ce946c7dSErez Shitrit 	gvmi_res->end_ft =
171ce946c7dSErez Shitrit 		mlx5dr_cmd_flow_table_create(mlx5dr_context_get_local_ibv(ctx),
172ce946c7dSErez Shitrit 					     &ft_attr);
173ce946c7dSErez Shitrit 	if (!gvmi_res->end_ft) {
174ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create end-ft");
175ce946c7dSErez Shitrit 		return rte_errno;
176ce946c7dSErez Shitrit 	}
177ce946c7dSErez Shitrit 
178ce946c7dSErez Shitrit 	calculated_ft_id =
179ce946c7dSErez Shitrit 		mlx5dr_table_get_res_fw_ft_type(type, false) << FT_ID_FT_TYPE_OFFSET;
180ce946c7dSErez Shitrit 	calculated_ft_id |= gvmi_res->end_ft->id;
181ce946c7dSErez Shitrit 
182ce946c7dSErez Shitrit 	/* create alias to that FT */
183ce946c7dSErez Shitrit 	ret = mlx5dr_matcher_create_aliased_obj(ctx,
184ce946c7dSErez Shitrit 						ctx->local_ibv_ctx,
185ce946c7dSErez Shitrit 						ctx->ibv_ctx,
186ce946c7dSErez Shitrit 						ctx->caps->vhca_id,
187ce946c7dSErez Shitrit 						calculated_ft_id,
188ce946c7dSErez Shitrit 						MLX5_GENERAL_OBJ_TYPE_FT_ALIAS,
189ce946c7dSErez Shitrit 						&gvmi_res->aliased_end_ft);
190ce946c7dSErez Shitrit 	if (ret) {
191ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create alias end-ft");
192ce946c7dSErez Shitrit 		goto free_end_ft;
193ce946c7dSErez Shitrit 	}
194ce946c7dSErez Shitrit 
195ce946c7dSErez Shitrit 	return 0;
196ce946c7dSErez Shitrit 
197ce946c7dSErez Shitrit free_end_ft:
198ce946c7dSErez Shitrit 	mlx5dr_cmd_destroy_obj(gvmi_res->end_ft);
199ce946c7dSErez Shitrit 
200ce946c7dSErez Shitrit 	return rte_errno;
201ce946c7dSErez Shitrit }
202ce946c7dSErez Shitrit 
203ce946c7dSErez Shitrit static void
204ce946c7dSErez Shitrit mlx5dr_table_shared_gvmi_resourse_destroy(struct mlx5dr_context *ctx,
205ce946c7dSErez Shitrit 					  struct mlx5dr_context_shared_gvmi_res *gvmi_res)
206ce946c7dSErez Shitrit {
207ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
208ce946c7dSErez Shitrit 		return;
209ce946c7dSErez Shitrit 
210ce946c7dSErez Shitrit 	if (gvmi_res->aliased_end_ft) {
211ce946c7dSErez Shitrit 		mlx5dr_cmd_destroy_obj(gvmi_res->aliased_end_ft);
212ce946c7dSErez Shitrit 		gvmi_res->aliased_end_ft = NULL;
213ce946c7dSErez Shitrit 	}
214ce946c7dSErez Shitrit 	if (gvmi_res->end_ft) {
215ce946c7dSErez Shitrit 		mlx5dr_cmd_destroy_obj(gvmi_res->end_ft);
216ce946c7dSErez Shitrit 		gvmi_res->end_ft = NULL;
217ce946c7dSErez Shitrit 	}
218ce946c7dSErez Shitrit }
219ce946c7dSErez Shitrit 
220ce946c7dSErez Shitrit /* called under spinlock ctx->ctrl_lock */
221ce946c7dSErez Shitrit static struct mlx5dr_context_shared_gvmi_res *
222ce946c7dSErez Shitrit mlx5dr_table_get_shared_gvmi_res(struct mlx5dr_context *ctx, enum mlx5dr_table_type type)
223ce946c7dSErez Shitrit {
224ce946c7dSErez Shitrit 	int ret;
225ce946c7dSErez Shitrit 
226ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
227ce946c7dSErez Shitrit 		return NULL;
228ce946c7dSErez Shitrit 
229ce946c7dSErez Shitrit 	if (ctx->gvmi_res[type].aliased_end_ft) {
230ce946c7dSErez Shitrit 		ctx->gvmi_res[type].refcount++;
231ce946c7dSErez Shitrit 		return &ctx->gvmi_res[type];
232ce946c7dSErez Shitrit 	}
233ce946c7dSErez Shitrit 
234ce946c7dSErez Shitrit 	ret = mlx5dr_table_shared_gvmi_resource_create(ctx, type, &ctx->gvmi_res[type]);
235ce946c7dSErez Shitrit 	if (ret) {
236ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create shared gvmi res for type: %d", type);
237ce946c7dSErez Shitrit 		goto out;
238ce946c7dSErez Shitrit 	}
239ce946c7dSErez Shitrit 
240ce946c7dSErez Shitrit 	ctx->gvmi_res[type].refcount = 1;
241ce946c7dSErez Shitrit 
242ce946c7dSErez Shitrit 	return &ctx->gvmi_res[type];
243ce946c7dSErez Shitrit 
244ce946c7dSErez Shitrit out:
245ce946c7dSErez Shitrit 	return NULL;
246ce946c7dSErez Shitrit }
247ce946c7dSErez Shitrit 
248ce946c7dSErez Shitrit /* called under spinlock ctx->ctrl_lock */
249ce946c7dSErez Shitrit static void mlx5dr_table_put_shared_gvmi_res(struct mlx5dr_table *tbl)
250ce946c7dSErez Shitrit {
251ce946c7dSErez Shitrit 	struct mlx5dr_context *ctx = tbl->ctx;
252ce946c7dSErez Shitrit 
253ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
254ce946c7dSErez Shitrit 		return;
255ce946c7dSErez Shitrit 
256ce946c7dSErez Shitrit 	if (--ctx->gvmi_res[tbl->type].refcount)
257ce946c7dSErez Shitrit 		return;
258ce946c7dSErez Shitrit 
259ce946c7dSErez Shitrit 	mlx5dr_table_shared_gvmi_resourse_destroy(ctx, &ctx->gvmi_res[tbl->type]);
260ce946c7dSErez Shitrit }
261ce946c7dSErez Shitrit 
262ce946c7dSErez Shitrit static void mlx5dr_table_uninit_shared_ctx_res(struct mlx5dr_table *tbl)
263ce946c7dSErez Shitrit {
264ce946c7dSErez Shitrit 	struct mlx5dr_context *ctx = tbl->ctx;
265ce946c7dSErez Shitrit 
266ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
267ce946c7dSErez Shitrit 		return;
268ce946c7dSErez Shitrit 
269ce946c7dSErez Shitrit 	mlx5dr_cmd_destroy_obj(tbl->local_ft);
270ce946c7dSErez Shitrit 
271ce946c7dSErez Shitrit 	mlx5dr_table_put_shared_gvmi_res(tbl);
272ce946c7dSErez Shitrit }
273ce946c7dSErez Shitrit 
274ce946c7dSErez Shitrit /* called under spin_lock ctx->ctrl_lock */
275ce946c7dSErez Shitrit static int mlx5dr_table_init_shared_ctx_res(struct mlx5dr_context *ctx, struct mlx5dr_table *tbl)
276ce946c7dSErez Shitrit {
277a5b44bc2SErez Shitrit 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
278a5b44bc2SErez Shitrit 	int ret;
279a5b44bc2SErez Shitrit 
280ce946c7dSErez Shitrit 	if (!mlx5dr_context_shared_gvmi_used(ctx))
281ce946c7dSErez Shitrit 		return 0;
282ce946c7dSErez Shitrit 
283ce946c7dSErez Shitrit 	/* create local-ft for root access */
284ce946c7dSErez Shitrit 	tbl->local_ft =
285ce946c7dSErez Shitrit 		mlx5dr_table_create_default_ft(mlx5dr_context_get_local_ibv(ctx), tbl);
286ce946c7dSErez Shitrit 	if (!tbl->local_ft) {
287ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to create local-ft");
288ce946c7dSErez Shitrit 		return rte_errno;
289ce946c7dSErez Shitrit 	}
290ce946c7dSErez Shitrit 
291ce946c7dSErez Shitrit 	if (!mlx5dr_table_get_shared_gvmi_res(tbl->ctx, tbl->type)) {
292ce946c7dSErez Shitrit 		DR_LOG(ERR, "Failed to shared gvmi resources");
293ce946c7dSErez Shitrit 		goto clean_local_ft;
294ce946c7dSErez Shitrit 	}
295ce946c7dSErez Shitrit 
296a5b44bc2SErez Shitrit 	/* On shared gvmi the default behavior is jump to alias end ft */
297a5b44bc2SErez Shitrit 	mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx,
298a5b44bc2SErez Shitrit 					     tbl->fw_ft_type,
299a5b44bc2SErez Shitrit 					     tbl->type,
300a5b44bc2SErez Shitrit 					     &ft_attr);
301a5b44bc2SErez Shitrit 
302a5b44bc2SErez Shitrit 	ret = mlx5dr_cmd_flow_table_modify(tbl->ft, &ft_attr);
303a5b44bc2SErez Shitrit 	if (ret) {
304a5b44bc2SErez Shitrit 		DR_LOG(ERR, "Failed to point table to its default miss");
305a5b44bc2SErez Shitrit 		goto clean_shared_res;
306a5b44bc2SErez Shitrit 	}
307a5b44bc2SErez Shitrit 
308ce946c7dSErez Shitrit 	return 0;
309ce946c7dSErez Shitrit 
310a5b44bc2SErez Shitrit clean_shared_res:
311a5b44bc2SErez Shitrit 	mlx5dr_table_put_shared_gvmi_res(tbl);
312ce946c7dSErez Shitrit clean_local_ft:
313ce946c7dSErez Shitrit 	mlx5dr_table_destroy_default_ft(tbl, tbl->local_ft);
314ce946c7dSErez Shitrit 	return rte_errno;
315ce946c7dSErez Shitrit }
316ce946c7dSErez Shitrit 
317394cc7baSAlex Vesker void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
318394cc7baSAlex Vesker 				     struct mlx5dr_devx_obj *ft_obj)
319394cc7baSAlex Vesker {
320394cc7baSAlex Vesker 	mlx5dr_cmd_destroy_obj(ft_obj);
32101895651SErez Shitrit 	mlx5dr_table_down_default_fdb_miss_tbl(tbl);
322394cc7baSAlex Vesker }
323394cc7baSAlex Vesker 
324394cc7baSAlex Vesker static int mlx5dr_table_init(struct mlx5dr_table *tbl)
325394cc7baSAlex Vesker {
326394cc7baSAlex Vesker 	struct mlx5dr_context *ctx = tbl->ctx;
327394cc7baSAlex Vesker 	int ret;
328394cc7baSAlex Vesker 
329394cc7baSAlex Vesker 	if (mlx5dr_table_is_root(tbl))
330394cc7baSAlex Vesker 		return 0;
331394cc7baSAlex Vesker 
332ce946c7dSErez Shitrit 	ret = mlx5dr_table_init_check_hws_support(ctx, tbl);
333ce946c7dSErez Shitrit 	if (ret)
334ce946c7dSErez Shitrit 		return ret;
335394cc7baSAlex Vesker 
336394cc7baSAlex Vesker 	switch (tbl->type) {
337394cc7baSAlex Vesker 	case MLX5DR_TABLE_TYPE_NIC_RX:
338394cc7baSAlex Vesker 		tbl->fw_ft_type = FS_FT_NIC_RX;
339394cc7baSAlex Vesker 		break;
340394cc7baSAlex Vesker 	case MLX5DR_TABLE_TYPE_NIC_TX:
341394cc7baSAlex Vesker 		tbl->fw_ft_type = FS_FT_NIC_TX;
342394cc7baSAlex Vesker 		break;
343394cc7baSAlex Vesker 	case MLX5DR_TABLE_TYPE_FDB:
344394cc7baSAlex Vesker 		tbl->fw_ft_type = FS_FT_FDB;
345394cc7baSAlex Vesker 		break;
346394cc7baSAlex Vesker 	default:
347394cc7baSAlex Vesker 		assert(0);
348394cc7baSAlex Vesker 		break;
349394cc7baSAlex Vesker 	}
350394cc7baSAlex Vesker 
351394cc7baSAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
352ce946c7dSErez Shitrit 	tbl->ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl);
353394cc7baSAlex Vesker 	if (!tbl->ft) {
354394cc7baSAlex Vesker 		DR_LOG(ERR, "Failed to create flow table devx object");
355394cc7baSAlex Vesker 		pthread_spin_unlock(&ctx->ctrl_lock);
356394cc7baSAlex Vesker 		return rte_errno;
357394cc7baSAlex Vesker 	}
358394cc7baSAlex Vesker 
359a5b44bc2SErez Shitrit 	ret = mlx5dr_table_init_shared_ctx_res(ctx, tbl);
360394cc7baSAlex Vesker 	if (ret)
361394cc7baSAlex Vesker 		goto tbl_destroy;
362ce946c7dSErez Shitrit 
363a5b44bc2SErez Shitrit 	ret = mlx5dr_action_get_default_stc(ctx, tbl->type);
364ce946c7dSErez Shitrit 	if (ret)
365a5b44bc2SErez Shitrit 		goto free_shared_ctx;
366ce946c7dSErez Shitrit 
367394cc7baSAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
368394cc7baSAlex Vesker 
369394cc7baSAlex Vesker 	return 0;
370394cc7baSAlex Vesker 
371a5b44bc2SErez Shitrit free_shared_ctx:
372a5b44bc2SErez Shitrit 	mlx5dr_table_uninit_shared_ctx_res(tbl);
373394cc7baSAlex Vesker tbl_destroy:
374394cc7baSAlex Vesker 	mlx5dr_table_destroy_default_ft(tbl, tbl->ft);
375394cc7baSAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
376394cc7baSAlex Vesker 	return rte_errno;
377394cc7baSAlex Vesker }
378394cc7baSAlex Vesker 
379394cc7baSAlex Vesker static void mlx5dr_table_uninit(struct mlx5dr_table *tbl)
380394cc7baSAlex Vesker {
381394cc7baSAlex Vesker 	if (mlx5dr_table_is_root(tbl))
382394cc7baSAlex Vesker 		return;
383394cc7baSAlex Vesker 	pthread_spin_lock(&tbl->ctx->ctrl_lock);
384394cc7baSAlex Vesker 	mlx5dr_action_put_default_stc(tbl->ctx, tbl->type);
385ce946c7dSErez Shitrit 	mlx5dr_table_uninit_shared_ctx_res(tbl);
386a5b44bc2SErez Shitrit 	mlx5dr_table_destroy_default_ft(tbl, tbl->ft);
387394cc7baSAlex Vesker 	pthread_spin_unlock(&tbl->ctx->ctrl_lock);
388394cc7baSAlex Vesker }
389394cc7baSAlex Vesker 
390394cc7baSAlex Vesker struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx,
391394cc7baSAlex Vesker 					 struct mlx5dr_table_attr *attr)
392394cc7baSAlex Vesker {
393394cc7baSAlex Vesker 	struct mlx5dr_table *tbl;
394394cc7baSAlex Vesker 	int ret;
395394cc7baSAlex Vesker 
396394cc7baSAlex Vesker 	if (attr->type > MLX5DR_TABLE_TYPE_FDB) {
397394cc7baSAlex Vesker 		DR_LOG(ERR, "Invalid table type %d", attr->type);
398394cc7baSAlex Vesker 		return NULL;
399394cc7baSAlex Vesker 	}
400394cc7baSAlex Vesker 
401b81f95caSItamar Gozlan 	tbl = simple_calloc(1, sizeof(*tbl));
402394cc7baSAlex Vesker 	if (!tbl) {
403394cc7baSAlex Vesker 		rte_errno = ENOMEM;
404394cc7baSAlex Vesker 		return NULL;
405394cc7baSAlex Vesker 	}
406394cc7baSAlex Vesker 
407394cc7baSAlex Vesker 	tbl->ctx = ctx;
408394cc7baSAlex Vesker 	tbl->type = attr->type;
409394cc7baSAlex Vesker 	tbl->level = attr->level;
410394cc7baSAlex Vesker 
411394cc7baSAlex Vesker 	ret = mlx5dr_table_init(tbl);
412394cc7baSAlex Vesker 	if (ret) {
413394cc7baSAlex Vesker 		DR_LOG(ERR, "Failed to initialise table");
414394cc7baSAlex Vesker 		goto free_tbl;
415394cc7baSAlex Vesker 	}
416394cc7baSAlex Vesker 
417394cc7baSAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
418394cc7baSAlex Vesker 	LIST_INSERT_HEAD(&ctx->head, tbl, next);
419394cc7baSAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
420394cc7baSAlex Vesker 
421394cc7baSAlex Vesker 	return tbl;
422394cc7baSAlex Vesker 
423394cc7baSAlex Vesker free_tbl:
424394cc7baSAlex Vesker 	simple_free(tbl);
425394cc7baSAlex Vesker 	return NULL;
426394cc7baSAlex Vesker }
427394cc7baSAlex Vesker 
428394cc7baSAlex Vesker int mlx5dr_table_destroy(struct mlx5dr_table *tbl)
429394cc7baSAlex Vesker {
430394cc7baSAlex Vesker 	struct mlx5dr_context *ctx = tbl->ctx;
431394cc7baSAlex Vesker 	pthread_spin_lock(&ctx->ctrl_lock);
432*486f9aacSHamdan Igbaria 	if (!LIST_EMPTY(&tbl->head) || !LIST_EMPTY(&tbl->isolated_matchers)) {
433b81f95caSItamar Gozlan 		DR_LOG(ERR, "Cannot destroy table containing matchers");
434b81f95caSItamar Gozlan 		rte_errno = EBUSY;
435b81f95caSItamar Gozlan 		goto unlock_err;
436b81f95caSItamar Gozlan 	}
437b81f95caSItamar Gozlan 
438b81f95caSItamar Gozlan 	if (!LIST_EMPTY(&tbl->default_miss.head)) {
439b81f95caSItamar Gozlan 		DR_LOG(ERR, "Cannot destroy table pointed by default miss");
440b81f95caSItamar Gozlan 		rte_errno = EBUSY;
441b81f95caSItamar Gozlan 		goto unlock_err;
442b81f95caSItamar Gozlan 	}
443b81f95caSItamar Gozlan 
444394cc7baSAlex Vesker 	LIST_REMOVE(tbl, next);
445394cc7baSAlex Vesker 	pthread_spin_unlock(&ctx->ctrl_lock);
446394cc7baSAlex Vesker 	mlx5dr_table_uninit(tbl);
447394cc7baSAlex Vesker 	simple_free(tbl);
448394cc7baSAlex Vesker 
449394cc7baSAlex Vesker 	return 0;
450b81f95caSItamar Gozlan 
451b81f95caSItamar Gozlan unlock_err:
452b81f95caSItamar Gozlan 	pthread_spin_unlock(&ctx->ctrl_lock);
453b81f95caSItamar Gozlan 	return -rte_errno;
454b81f95caSItamar Gozlan }
455b81f95caSItamar Gozlan 
456b81f95caSItamar Gozlan static struct mlx5dr_devx_obj *
457b81f95caSItamar Gozlan mlx5dr_table_get_last_ft(struct mlx5dr_table *tbl)
458b81f95caSItamar Gozlan {
459b81f95caSItamar Gozlan 	struct mlx5dr_devx_obj *last_ft = tbl->ft;
460b81f95caSItamar Gozlan 	struct mlx5dr_matcher *matcher;
461b81f95caSItamar Gozlan 
462b81f95caSItamar Gozlan 	LIST_FOREACH(matcher, &tbl->head, next)
463b81f95caSItamar Gozlan 		last_ft = matcher->end_ft;
464b81f95caSItamar Gozlan 
465b81f95caSItamar Gozlan 	return last_ft;
466b81f95caSItamar Gozlan }
467b81f95caSItamar Gozlan 
468b81f95caSItamar Gozlan int mlx5dr_table_ft_set_default_next_ft(struct mlx5dr_table *tbl,
469b81f95caSItamar Gozlan 					struct mlx5dr_devx_obj *ft_obj)
470b81f95caSItamar Gozlan {
471b81f95caSItamar Gozlan 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
472b81f95caSItamar Gozlan 	int ret;
473b81f95caSItamar Gozlan 
474b81f95caSItamar Gozlan 	/* Due to FW limitation, resetting the flow table to default action will
475b81f95caSItamar Gozlan 	 * disconnect RTC when ignore_flow_level_rtc_valid is not supported.
476b81f95caSItamar Gozlan 	 */
477b81f95caSItamar Gozlan 	if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid)
478b81f95caSItamar Gozlan 		return 0;
479b81f95caSItamar Gozlan 
480b81f95caSItamar Gozlan 	if (tbl->type == MLX5DR_TABLE_TYPE_FDB)
481b81f95caSItamar Gozlan 		return mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj);
482b81f95caSItamar Gozlan 
483b81f95caSItamar Gozlan 	ft_attr.type = tbl->fw_ft_type;
484b81f95caSItamar Gozlan 	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
485b81f95caSItamar Gozlan 	ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_DEFAULT;
486b81f95caSItamar Gozlan 
487b81f95caSItamar Gozlan 	ret = mlx5dr_cmd_flow_table_modify(ft_obj, &ft_attr);
488b81f95caSItamar Gozlan 	if (ret) {
489b81f95caSItamar Gozlan 		DR_LOG(ERR, "Failed to set FT default miss action");
490b81f95caSItamar Gozlan 		return ret;
491b81f95caSItamar Gozlan 	}
492b81f95caSItamar Gozlan 
493b81f95caSItamar Gozlan 	return 0;
494b81f95caSItamar Gozlan }
495b81f95caSItamar Gozlan 
496b81f95caSItamar Gozlan int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft,
497b81f95caSItamar Gozlan 				 uint32_t fw_ft_type,
498b81f95caSItamar Gozlan 				 struct mlx5dr_devx_obj *rtc_0,
499b81f95caSItamar Gozlan 				 struct mlx5dr_devx_obj *rtc_1)
500b81f95caSItamar Gozlan {
501b81f95caSItamar Gozlan 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
502b81f95caSItamar Gozlan 
503b81f95caSItamar Gozlan 	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
504b81f95caSItamar Gozlan 	ft_attr.type = fw_ft_type;
505b81f95caSItamar Gozlan 	ft_attr.rtc_id_0 = rtc_0 ? rtc_0->id : 0;
506b81f95caSItamar Gozlan 	ft_attr.rtc_id_1 = rtc_1 ? rtc_1->id : 0;
507b81f95caSItamar Gozlan 
508b81f95caSItamar Gozlan 	return mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
509b81f95caSItamar Gozlan }
510b81f95caSItamar Gozlan 
511b81f95caSItamar Gozlan static int mlx5dr_table_ft_set_next_ft(struct mlx5dr_devx_obj *ft,
512b81f95caSItamar Gozlan 				       uint32_t fw_ft_type,
513b81f95caSItamar Gozlan 				       uint32_t next_ft_id)
514b81f95caSItamar Gozlan {
515b81f95caSItamar Gozlan 	struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
516b81f95caSItamar Gozlan 
517b81f95caSItamar Gozlan 	ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
518b81f95caSItamar Gozlan 	ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
519b81f95caSItamar Gozlan 	ft_attr.type = fw_ft_type;
520b81f95caSItamar Gozlan 	ft_attr.table_miss_id = next_ft_id;
521b81f95caSItamar Gozlan 
522b81f95caSItamar Gozlan 	return mlx5dr_cmd_flow_table_modify(ft, &ft_attr);
523b81f95caSItamar Gozlan }
524b81f95caSItamar Gozlan 
525b81f95caSItamar Gozlan int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl)
526b81f95caSItamar Gozlan {
527b81f95caSItamar Gozlan 	struct mlx5dr_table *src_tbl;
528b81f95caSItamar Gozlan 	int ret;
529b81f95caSItamar Gozlan 
530b81f95caSItamar Gozlan 	if (LIST_EMPTY(&dst_tbl->default_miss.head))
531b81f95caSItamar Gozlan 		return 0;
532b81f95caSItamar Gozlan 
533b81f95caSItamar Gozlan 	LIST_FOREACH(src_tbl, &dst_tbl->default_miss.head, default_miss.next) {
534*486f9aacSHamdan Igbaria 		ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl, false);
535b81f95caSItamar Gozlan 		if (ret) {
536b81f95caSItamar Gozlan 			DR_LOG(ERR, "Failed to update source miss table, unexpected behavior");
537b81f95caSItamar Gozlan 			return ret;
538b81f95caSItamar Gozlan 		}
539b81f95caSItamar Gozlan 	}
540b81f95caSItamar Gozlan 
541b81f95caSItamar Gozlan 	return 0;
542b81f95caSItamar Gozlan }
543b81f95caSItamar Gozlan 
544*486f9aacSHamdan Igbaria int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl,
545*486f9aacSHamdan Igbaria 					      struct mlx5dr_devx_obj *ft,
546b81f95caSItamar Gozlan 					      struct mlx5dr_table *dst_tbl)
547b81f95caSItamar Gozlan {
548b81f95caSItamar Gozlan 	struct mlx5dr_matcher *matcher;
549b81f95caSItamar Gozlan 	int ret;
550b81f95caSItamar Gozlan 
551b81f95caSItamar Gozlan 	if (dst_tbl) {
552b81f95caSItamar Gozlan 		if (LIST_EMPTY(&dst_tbl->head)) {
553*486f9aacSHamdan Igbaria 			/* Connect src_tbl ft to dst_tbl start anchor */
554*486f9aacSHamdan Igbaria 			ret = mlx5dr_table_ft_set_next_ft(ft,
555b81f95caSItamar Gozlan 							  src_tbl->fw_ft_type,
556b81f95caSItamar Gozlan 							  dst_tbl->ft->id);
557b81f95caSItamar Gozlan 			if (ret)
558b81f95caSItamar Gozlan 				return ret;
559b81f95caSItamar Gozlan 
560*486f9aacSHamdan Igbaria 			/* Reset ft RTC to default RTC */
561*486f9aacSHamdan Igbaria 			ret = mlx5dr_table_ft_set_next_rtc(ft,
562b81f95caSItamar Gozlan 							   src_tbl->fw_ft_type,
563b81f95caSItamar Gozlan 							   NULL, NULL);
564b81f95caSItamar Gozlan 			if (ret)
565b81f95caSItamar Gozlan 				return ret;
566b81f95caSItamar Gozlan 		} else {
567*486f9aacSHamdan Igbaria 			/* Connect src_tbl ft to first matcher RTC */
568b81f95caSItamar Gozlan 			matcher = LIST_FIRST(&dst_tbl->head);
569*486f9aacSHamdan Igbaria 			ret = mlx5dr_table_ft_set_next_rtc(ft,
570b81f95caSItamar Gozlan 							   src_tbl->fw_ft_type,
571b81f95caSItamar Gozlan 							   matcher->match_ste.rtc_0,
572b81f95caSItamar Gozlan 							   matcher->match_ste.rtc_1);
573b81f95caSItamar Gozlan 			if (ret)
574b81f95caSItamar Gozlan 				return ret;
575b81f95caSItamar Gozlan 
576b81f95caSItamar Gozlan 			/* Reset next miss FT to default */
577*486f9aacSHamdan Igbaria 			ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
578b81f95caSItamar Gozlan 			if (ret)
579b81f95caSItamar Gozlan 				return ret;
580b81f95caSItamar Gozlan 		}
581b81f95caSItamar Gozlan 	} else {
582b81f95caSItamar Gozlan 		/* Reset next miss FT to default */
583*486f9aacSHamdan Igbaria 		ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft);
584b81f95caSItamar Gozlan 		if (ret)
585b81f95caSItamar Gozlan 			return ret;
586b81f95caSItamar Gozlan 
587*486f9aacSHamdan Igbaria 		/* Reset ft RTC to default RTC */
588*486f9aacSHamdan Igbaria 		ret = mlx5dr_table_ft_set_next_rtc(ft,
589b81f95caSItamar Gozlan 						   src_tbl->fw_ft_type,
590b81f95caSItamar Gozlan 						   NULL, NULL);
591b81f95caSItamar Gozlan 		if (ret)
592b81f95caSItamar Gozlan 			return ret;
593b81f95caSItamar Gozlan 	}
594b81f95caSItamar Gozlan 
595*486f9aacSHamdan Igbaria 	return 0;
596*486f9aacSHamdan Igbaria }
597*486f9aacSHamdan Igbaria 
598*486f9aacSHamdan Igbaria int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl,
599*486f9aacSHamdan Igbaria 				       struct mlx5dr_table *dst_tbl,
600*486f9aacSHamdan Igbaria 				       bool only_update_last_ft)
601*486f9aacSHamdan Igbaria {
602*486f9aacSHamdan Igbaria 	struct mlx5dr_matcher *matcher;
603*486f9aacSHamdan Igbaria 	struct mlx5dr_devx_obj *ft;
604*486f9aacSHamdan Igbaria 	int ret;
605*486f9aacSHamdan Igbaria 
606*486f9aacSHamdan Igbaria 	/* Connect last FT in the src_tbl matchers chain */
607*486f9aacSHamdan Igbaria 	ft = mlx5dr_table_get_last_ft(src_tbl);
608*486f9aacSHamdan Igbaria 	ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
609*486f9aacSHamdan Igbaria 	if (ret)
610*486f9aacSHamdan Igbaria 		return ret;
611*486f9aacSHamdan Igbaria 
612*486f9aacSHamdan Igbaria 	if (!only_update_last_ft) {
613*486f9aacSHamdan Igbaria 		/* Connect isolated matchers FT */
614*486f9aacSHamdan Igbaria 		LIST_FOREACH(matcher, &src_tbl->isolated_matchers, next) {
615*486f9aacSHamdan Igbaria 			ft = matcher->end_ft;
616*486f9aacSHamdan Igbaria 			ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl);
617*486f9aacSHamdan Igbaria 			if (ret)
618*486f9aacSHamdan Igbaria 				return ret;
619*486f9aacSHamdan Igbaria 		}
620*486f9aacSHamdan Igbaria 	}
621*486f9aacSHamdan Igbaria 
622b81f95caSItamar Gozlan 	src_tbl->default_miss.miss_tbl = dst_tbl;
623b81f95caSItamar Gozlan 
624b81f95caSItamar Gozlan 	return 0;
625b81f95caSItamar Gozlan }
626b81f95caSItamar Gozlan 
627b81f95caSItamar Gozlan static int mlx5dr_table_set_default_miss_not_valid(struct mlx5dr_table *tbl,
628b81f95caSItamar Gozlan 						   struct mlx5dr_table *miss_tbl)
629b81f95caSItamar Gozlan {
630b81f95caSItamar Gozlan 	if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid ||
631b81f95caSItamar Gozlan 	    mlx5dr_context_shared_gvmi_used(tbl->ctx)) {
632b81f95caSItamar Gozlan 		DR_LOG(ERR, "Default miss table is not supported");
633b81f95caSItamar Gozlan 		rte_errno = EOPNOTSUPP;
634b81f95caSItamar Gozlan 		return -rte_errno;
635b81f95caSItamar Gozlan 	}
636b81f95caSItamar Gozlan 
637b81f95caSItamar Gozlan 	if (mlx5dr_table_is_root(tbl) ||
638b81f95caSItamar Gozlan 	    (miss_tbl && mlx5dr_table_is_root(miss_tbl)) ||
6394711950bSItamar Gozlan 	    (miss_tbl && miss_tbl->type != tbl->type)) {
640b81f95caSItamar Gozlan 		DR_LOG(ERR, "Invalid arguments");
641b81f95caSItamar Gozlan 		rte_errno = EINVAL;
642b81f95caSItamar Gozlan 		return -rte_errno;
643b81f95caSItamar Gozlan 	}
644b81f95caSItamar Gozlan 
645b81f95caSItamar Gozlan 	return 0;
646b81f95caSItamar Gozlan }
647b81f95caSItamar Gozlan 
648b81f95caSItamar Gozlan int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl,
649b81f95caSItamar Gozlan 				  struct mlx5dr_table *miss_tbl)
650b81f95caSItamar Gozlan {
651b81f95caSItamar Gozlan 	struct mlx5dr_context *ctx = tbl->ctx;
6524711950bSItamar Gozlan 	struct mlx5dr_table *old_miss_tbl;
653b81f95caSItamar Gozlan 	int ret;
654b81f95caSItamar Gozlan 
655b81f95caSItamar Gozlan 	ret = mlx5dr_table_set_default_miss_not_valid(tbl, miss_tbl);
656b81f95caSItamar Gozlan 	if (ret)
657b81f95caSItamar Gozlan 		return ret;
658b81f95caSItamar Gozlan 
659b81f95caSItamar Gozlan 	pthread_spin_lock(&ctx->ctrl_lock);
6604711950bSItamar Gozlan 	old_miss_tbl = tbl->default_miss.miss_tbl;
661*486f9aacSHamdan Igbaria 	ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl, false);
662b81f95caSItamar Gozlan 	if (ret)
663b81f95caSItamar Gozlan 		goto out;
664b81f95caSItamar Gozlan 
6654711950bSItamar Gozlan 	if (old_miss_tbl)
6664711950bSItamar Gozlan 		LIST_REMOVE(tbl, default_miss.next);
6674711950bSItamar Gozlan 
668b81f95caSItamar Gozlan 	if (miss_tbl)
669b81f95caSItamar Gozlan 		LIST_INSERT_HEAD(&miss_tbl->default_miss.head, tbl, default_miss.next);
670b81f95caSItamar Gozlan 
671b81f95caSItamar Gozlan 	pthread_spin_unlock(&ctx->ctrl_lock);
672b81f95caSItamar Gozlan 	return 0;
673b81f95caSItamar Gozlan out:
674b81f95caSItamar Gozlan 	pthread_spin_unlock(&ctx->ctrl_lock);
675b81f95caSItamar Gozlan 	return -ret;
676394cc7baSAlex Vesker }
677