xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_cmd.c (revision 4b53e9802b6b6040ad5622b1414aaa93d9581d0c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3  */
4 
5 #include "mlx5dr_internal.h"
6 
7 int mlx5dr_cmd_destroy_obj(struct mlx5dr_devx_obj *devx_obj)
8 {
9 	int ret;
10 
11 	ret = mlx5_glue->devx_obj_destroy(devx_obj->obj);
12 	simple_free(devx_obj);
13 
14 	return ret;
15 }
16 
17 struct mlx5dr_devx_obj *
18 mlx5dr_cmd_flow_table_create(struct ibv_context *ctx,
19 			     struct mlx5dr_cmd_ft_create_attr *ft_attr)
20 {
21 	uint32_t out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
22 	uint32_t in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
23 	struct mlx5dr_devx_obj *devx_obj;
24 	void *ft_ctx;
25 
26 	devx_obj = simple_malloc(sizeof(*devx_obj));
27 	if (!devx_obj) {
28 		DR_LOG(ERR, "Failed to allocate memory for flow table object");
29 		rte_errno = ENOMEM;
30 		return NULL;
31 	}
32 
33 	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
34 	MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type);
35 
36 	ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
37 	MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level);
38 	MLX5_SET(flow_table_context, ft_ctx, rtc_valid, ft_attr->rtc_valid);
39 
40 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
41 	if (!devx_obj->obj) {
42 		DR_LOG(ERR, "Failed to create FT");
43 		simple_free(devx_obj);
44 		rte_errno = errno;
45 		return NULL;
46 	}
47 
48 	devx_obj->id = MLX5_GET(create_flow_table_out, out, table_id);
49 
50 	return devx_obj;
51 }
52 
53 int
54 mlx5dr_cmd_flow_table_modify(struct mlx5dr_devx_obj *devx_obj,
55 			     struct mlx5dr_cmd_ft_modify_attr *ft_attr)
56 {
57 	uint32_t out[MLX5_ST_SZ_DW(modify_flow_table_out)] = {0};
58 	uint32_t in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {0};
59 	void *ft_ctx;
60 	int ret;
61 
62 	MLX5_SET(modify_flow_table_in, in, opcode, MLX5_CMD_OP_MODIFY_FLOW_TABLE);
63 	MLX5_SET(modify_flow_table_in, in, table_type, ft_attr->type);
64 	MLX5_SET(modify_flow_table_in, in, modify_field_select, ft_attr->modify_fs);
65 	MLX5_SET(modify_flow_table_in, in, table_id, devx_obj->id);
66 
67 	ft_ctx = MLX5_ADDR_OF(modify_flow_table_in, in, flow_table_context);
68 
69 	MLX5_SET(flow_table_context, ft_ctx, table_miss_action, ft_attr->table_miss_action);
70 	MLX5_SET(flow_table_context, ft_ctx, table_miss_id, ft_attr->table_miss_id);
71 	MLX5_SET(flow_table_context, ft_ctx, rtc_id_0, ft_attr->rtc_id_0);
72 	MLX5_SET(flow_table_context, ft_ctx, rtc_id_1, ft_attr->rtc_id_1);
73 
74 	ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out));
75 	if (ret) {
76 		DR_LOG(ERR, "Failed to modify FT");
77 		rte_errno = errno;
78 	}
79 
80 	return ret;
81 }
82 
83 static struct mlx5dr_devx_obj *
84 mlx5dr_cmd_flow_group_create(struct ibv_context *ctx,
85 			     struct mlx5dr_cmd_fg_attr *fg_attr)
86 {
87 	uint32_t out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
88 	uint32_t in[MLX5_ST_SZ_DW(create_flow_group_in)] = {0};
89 	struct mlx5dr_devx_obj *devx_obj;
90 
91 	devx_obj = simple_malloc(sizeof(*devx_obj));
92 	if (!devx_obj) {
93 		DR_LOG(ERR, "Failed to allocate memory for flow group object");
94 		rte_errno = ENOMEM;
95 		return NULL;
96 	}
97 
98 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
99 	MLX5_SET(create_flow_group_in, in, table_type, fg_attr->table_type);
100 	MLX5_SET(create_flow_group_in, in, table_id, fg_attr->table_id);
101 
102 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
103 	if (!devx_obj->obj) {
104 		DR_LOG(ERR, "Failed to create Flow group");
105 		simple_free(devx_obj);
106 		rte_errno = errno;
107 		return NULL;
108 	}
109 
110 	devx_obj->id = MLX5_GET(create_flow_group_out, out, group_id);
111 
112 	return devx_obj;
113 }
114 
115 static struct mlx5dr_devx_obj *
116 mlx5dr_cmd_set_vport_fte(struct ibv_context *ctx,
117 			 uint32_t table_type,
118 			 uint32_t table_id,
119 			 uint32_t group_id,
120 			 uint32_t vport_id)
121 {
122 	uint32_t in[MLX5_ST_SZ_DW(set_fte_in) + MLX5_ST_SZ_DW(dest_format)] = {0};
123 	uint32_t out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
124 	struct mlx5dr_devx_obj *devx_obj;
125 	void *in_flow_context;
126 	void *in_dests;
127 
128 	devx_obj = simple_malloc(sizeof(*devx_obj));
129 	if (!devx_obj) {
130 		DR_LOG(ERR, "Failed to allocate memory for fte object");
131 		rte_errno = ENOMEM;
132 		return NULL;
133 	}
134 
135 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
136 	MLX5_SET(set_fte_in, in, table_type, table_type);
137 	MLX5_SET(set_fte_in, in, table_id, table_id);
138 
139 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
140 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
141 	MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
142 	MLX5_SET(flow_context, in_flow_context, action, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST);
143 
144 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
145 	MLX5_SET(dest_format, in_dests, destination_type,
146 		 MLX5_FLOW_DESTINATION_TYPE_VPORT);
147 	MLX5_SET(dest_format, in_dests, destination_id, vport_id);
148 
149 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
150 	if (!devx_obj->obj) {
151 		DR_LOG(ERR, "Failed to create FTE");
152 		simple_free(devx_obj);
153 		rte_errno = errno;
154 		return NULL;
155 	}
156 
157 	return devx_obj;
158 }
159 
160 void mlx5dr_cmd_miss_ft_destroy(struct mlx5dr_cmd_forward_tbl *tbl)
161 {
162 	mlx5dr_cmd_destroy_obj(tbl->fte);
163 	mlx5dr_cmd_destroy_obj(tbl->fg);
164 	mlx5dr_cmd_destroy_obj(tbl->ft);
165 }
166 
167 struct mlx5dr_cmd_forward_tbl *
168 mlx5dr_cmd_miss_ft_create(struct ibv_context *ctx,
169 			  struct mlx5dr_cmd_ft_create_attr *ft_attr,
170 			  uint32_t vport)
171 {
172 	struct mlx5dr_cmd_fg_attr fg_attr = {0};
173 	struct mlx5dr_cmd_forward_tbl *tbl;
174 
175 	tbl = simple_calloc(1, sizeof(*tbl));
176 	if (!tbl) {
177 		DR_LOG(ERR, "Failed to allocate memory for forward default");
178 		rte_errno = ENOMEM;
179 		return NULL;
180 	}
181 
182 	tbl->ft = mlx5dr_cmd_flow_table_create(ctx, ft_attr);
183 	if (!tbl->ft) {
184 		DR_LOG(ERR, "Failed to create FT for miss-table");
185 		goto free_tbl;
186 	}
187 
188 	fg_attr.table_id = tbl->ft->id;
189 	fg_attr.table_type = ft_attr->type;
190 
191 	tbl->fg = mlx5dr_cmd_flow_group_create(ctx, &fg_attr);
192 	if (!tbl->fg) {
193 		DR_LOG(ERR, "Failed to create FG for miss-table");
194 		goto free_ft;
195 	}
196 
197 	tbl->fte = mlx5dr_cmd_set_vport_fte(ctx, ft_attr->type, tbl->ft->id, tbl->fg->id, vport);
198 	if (!tbl->fte) {
199 		DR_LOG(ERR, "Failed to create FTE for miss-table");
200 		goto free_fg;
201 	}
202 	return tbl;
203 
204 free_fg:
205 	mlx5dr_cmd_destroy_obj(tbl->fg);
206 free_ft:
207 	mlx5dr_cmd_destroy_obj(tbl->ft);
208 free_tbl:
209 	simple_free(tbl);
210 	return NULL;
211 }
212 
213 void mlx5dr_cmd_set_attr_connect_miss_tbl(struct mlx5dr_context *ctx,
214 					  uint32_t fw_ft_type,
215 					  enum mlx5dr_table_type type,
216 					  struct mlx5dr_cmd_ft_modify_attr *ft_attr)
217 {
218 	struct mlx5dr_devx_obj *default_miss_tbl;
219 
220 	if (type != MLX5DR_TABLE_TYPE_FDB)
221 		return;
222 
223 	default_miss_tbl = ctx->common_res[type].default_miss->ft;
224 	if (!default_miss_tbl) {
225 		assert(false);
226 		return;
227 	}
228 	ft_attr->modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
229 	ft_attr->type = fw_ft_type;
230 	ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
231 	ft_attr->table_miss_id = default_miss_tbl->id;
232 }
233 
234 struct mlx5dr_devx_obj *
235 mlx5dr_cmd_rtc_create(struct ibv_context *ctx,
236 		      struct mlx5dr_cmd_rtc_create_attr *rtc_attr)
237 {
238 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
239 	uint32_t in[MLX5_ST_SZ_DW(create_rtc_in)] = {0};
240 	struct mlx5dr_devx_obj *devx_obj;
241 	void *attr;
242 
243 	devx_obj = simple_malloc(sizeof(*devx_obj));
244 	if (!devx_obj) {
245 		DR_LOG(ERR, "Failed to allocate memory for RTC object");
246 		rte_errno = ENOMEM;
247 		return NULL;
248 	}
249 
250 	attr = MLX5_ADDR_OF(create_rtc_in, in, hdr);
251 	MLX5_SET(general_obj_in_cmd_hdr,
252 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
253 	MLX5_SET(general_obj_in_cmd_hdr,
254 		 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_RTC);
255 
256 	attr = MLX5_ADDR_OF(create_rtc_in, in, rtc);
257 	MLX5_SET(rtc, attr, ste_format, rtc_attr->is_jumbo ?
258 		MLX5_IFC_RTC_STE_FORMAT_11DW :
259 		MLX5_IFC_RTC_STE_FORMAT_8DW);
260 	MLX5_SET(rtc, attr, pd, rtc_attr->pd);
261 	MLX5_SET(rtc, attr, update_index_mode, rtc_attr->update_index_mode);
262 	MLX5_SET(rtc, attr, log_depth, rtc_attr->log_depth);
263 	MLX5_SET(rtc, attr, log_hash_size, rtc_attr->log_size);
264 	MLX5_SET(rtc, attr, table_type, rtc_attr->table_type);
265 	MLX5_SET(rtc, attr, match_definer_id, rtc_attr->definer_id);
266 	MLX5_SET(rtc, attr, stc_id, rtc_attr->stc_base);
267 	MLX5_SET(rtc, attr, ste_table_base_id, rtc_attr->ste_base);
268 	MLX5_SET(rtc, attr, ste_table_offset, rtc_attr->ste_offset);
269 	MLX5_SET(rtc, attr, miss_flow_table_id, rtc_attr->miss_ft_id);
270 	MLX5_SET(rtc, attr, reparse_mode, MLX5_IFC_RTC_REPARSE_ALWAYS);
271 
272 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
273 	if (!devx_obj->obj) {
274 		DR_LOG(ERR, "Failed to create RTC");
275 		simple_free(devx_obj);
276 		rte_errno = errno;
277 		return NULL;
278 	}
279 
280 	devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
281 
282 	return devx_obj;
283 }
284 
285 struct mlx5dr_devx_obj *
286 mlx5dr_cmd_stc_create(struct ibv_context *ctx,
287 		      struct mlx5dr_cmd_stc_create_attr *stc_attr)
288 {
289 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
290 	uint32_t in[MLX5_ST_SZ_DW(create_stc_in)] = {0};
291 	struct mlx5dr_devx_obj *devx_obj;
292 	void *attr;
293 
294 	devx_obj = simple_malloc(sizeof(*devx_obj));
295 	if (!devx_obj) {
296 		DR_LOG(ERR, "Failed to allocate memory for STC object");
297 		rte_errno = ENOMEM;
298 		return NULL;
299 	}
300 
301 	attr = MLX5_ADDR_OF(create_stc_in, in, hdr);
302 	MLX5_SET(general_obj_in_cmd_hdr,
303 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
304 	MLX5_SET(general_obj_in_cmd_hdr,
305 		 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STC);
306 	MLX5_SET(general_obj_in_cmd_hdr,
307 		 attr, log_obj_range, stc_attr->log_obj_range);
308 
309 	attr = MLX5_ADDR_OF(create_stc_in, in, stc);
310 	MLX5_SET(stc, attr, table_type, stc_attr->table_type);
311 
312 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
313 	if (!devx_obj->obj) {
314 		DR_LOG(ERR, "Failed to create STC");
315 		simple_free(devx_obj);
316 		rte_errno = errno;
317 		return NULL;
318 	}
319 
320 	devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
321 
322 	return devx_obj;
323 }
324 
325 static int
326 mlx5dr_cmd_stc_modify_set_stc_param(struct mlx5dr_cmd_stc_modify_attr *stc_attr,
327 				    void *stc_parm)
328 {
329 	switch (stc_attr->action_type) {
330 	case MLX5_IFC_STC_ACTION_TYPE_COUNTER:
331 		MLX5_SET(stc_ste_param_flow_counter, stc_parm, flow_counter_id, stc_attr->id);
332 		break;
333 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_TIR:
334 		MLX5_SET(stc_ste_param_tir, stc_parm, tirn, stc_attr->dest_tir_num);
335 		break;
336 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT:
337 		MLX5_SET(stc_ste_param_table, stc_parm, table_id, stc_attr->dest_table_id);
338 		break;
339 	case MLX5_IFC_STC_ACTION_TYPE_ACC_MODIFY_LIST:
340 		MLX5_SET(stc_ste_param_header_modify_list, stc_parm,
341 			 header_modify_pattern_id, stc_attr->modify_header.pattern_id);
342 		MLX5_SET(stc_ste_param_header_modify_list, stc_parm,
343 			 header_modify_argument_id, stc_attr->modify_header.arg_id);
344 		break;
345 	case MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE:
346 		MLX5_SET(stc_ste_param_remove, stc_parm, action_type,
347 			 MLX5_MODIFICATION_TYPE_REMOVE);
348 		MLX5_SET(stc_ste_param_remove, stc_parm, decap,
349 			 stc_attr->remove_header.decap);
350 		MLX5_SET(stc_ste_param_remove, stc_parm, remove_start_anchor,
351 			 stc_attr->remove_header.start_anchor);
352 		MLX5_SET(stc_ste_param_remove, stc_parm, remove_end_anchor,
353 			 stc_attr->remove_header.end_anchor);
354 		break;
355 	case MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT:
356 		MLX5_SET(stc_ste_param_insert, stc_parm, action_type,
357 			 MLX5_MODIFICATION_TYPE_INSERT);
358 		MLX5_SET(stc_ste_param_insert, stc_parm, encap,
359 			 stc_attr->insert_header.encap);
360 		MLX5_SET(stc_ste_param_insert, stc_parm, inline_data,
361 			 stc_attr->insert_header.is_inline);
362 		MLX5_SET(stc_ste_param_insert, stc_parm, insert_anchor,
363 			 stc_attr->insert_header.insert_anchor);
364 		/* HW gets the next 2 sizes in words */
365 		MLX5_SET(stc_ste_param_insert, stc_parm, insert_size,
366 			 stc_attr->insert_header.header_size / 2);
367 		MLX5_SET(stc_ste_param_insert, stc_parm, insert_offset,
368 			 stc_attr->insert_header.insert_offset / 2);
369 		MLX5_SET(stc_ste_param_insert, stc_parm, insert_argument,
370 			 stc_attr->insert_header.arg_id);
371 		break;
372 	case MLX5_IFC_STC_ACTION_TYPE_COPY:
373 	case MLX5_IFC_STC_ACTION_TYPE_SET:
374 	case MLX5_IFC_STC_ACTION_TYPE_ADD:
375 		*(__be64 *)stc_parm = stc_attr->modify_action.data;
376 		break;
377 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT:
378 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_UPLINK:
379 		MLX5_SET(stc_ste_param_vport, stc_parm, vport_number,
380 			 stc_attr->vport.vport_num);
381 		MLX5_SET(stc_ste_param_vport, stc_parm, eswitch_owner_vhca_id,
382 			 stc_attr->vport.esw_owner_vhca_id);
383 		MLX5_SET(stc_ste_param_vport, stc_parm, eswitch_owner_vhca_id_valid, 1);
384 		break;
385 	case MLX5_IFC_STC_ACTION_TYPE_DROP:
386 	case MLX5_IFC_STC_ACTION_TYPE_NOP:
387 	case MLX5_IFC_STC_ACTION_TYPE_TAG:
388 	case MLX5_IFC_STC_ACTION_TYPE_ALLOW:
389 		break;
390 	case MLX5_IFC_STC_ACTION_TYPE_ASO:
391 		MLX5_SET(stc_ste_param_execute_aso, stc_parm, aso_object_id,
392 			 stc_attr->aso.devx_obj_id);
393 		MLX5_SET(stc_ste_param_execute_aso, stc_parm, return_reg_id,
394 			 stc_attr->aso.return_reg_id);
395 		MLX5_SET(stc_ste_param_execute_aso, stc_parm, aso_type,
396 			 stc_attr->aso.aso_type);
397 		break;
398 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE:
399 		MLX5_SET(stc_ste_param_ste_table, stc_parm, ste_obj_id,
400 			 stc_attr->ste_table.ste_obj_id);
401 		MLX5_SET(stc_ste_param_ste_table, stc_parm, match_definer_id,
402 			 stc_attr->ste_table.match_definer_id);
403 		MLX5_SET(stc_ste_param_ste_table, stc_parm, log_hash_size,
404 			 stc_attr->ste_table.log_hash_size);
405 		break;
406 	case MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS:
407 		MLX5_SET(stc_ste_param_remove_words, stc_parm, action_type,
408 			 MLX5_MODIFICATION_TYPE_REMOVE_WORDS);
409 		MLX5_SET(stc_ste_param_remove_words, stc_parm, remove_start_anchor,
410 			 stc_attr->remove_words.start_anchor);
411 		MLX5_SET(stc_ste_param_remove_words, stc_parm,
412 			 remove_size, stc_attr->remove_words.num_of_words);
413 		break;
414 	default:
415 		DR_LOG(ERR, "Not supported type %d", stc_attr->action_type);
416 		rte_errno = EINVAL;
417 		return rte_errno;
418 	}
419 	return 0;
420 }
421 
422 int
423 mlx5dr_cmd_stc_modify(struct mlx5dr_devx_obj *devx_obj,
424 		      struct mlx5dr_cmd_stc_modify_attr *stc_attr)
425 {
426 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
427 	uint32_t in[MLX5_ST_SZ_DW(create_stc_in)] = {0};
428 	void *stc_parm;
429 	void *attr;
430 	int ret;
431 
432 	attr = MLX5_ADDR_OF(create_stc_in, in, hdr);
433 	MLX5_SET(general_obj_in_cmd_hdr,
434 		 attr, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
435 	MLX5_SET(general_obj_in_cmd_hdr,
436 		 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STC);
437 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, devx_obj->id);
438 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_offset, stc_attr->stc_offset);
439 
440 	attr = MLX5_ADDR_OF(create_stc_in, in, stc);
441 	MLX5_SET(stc, attr, ste_action_offset, stc_attr->action_offset);
442 	MLX5_SET(stc, attr, action_type, stc_attr->action_type);
443 	MLX5_SET64(stc, attr, modify_field_select,
444 		   MLX5_IFC_MODIFY_STC_FIELD_SELECT_NEW_STC);
445 
446 	/* Set destination TIRN, TAG, FT ID, STE ID */
447 	stc_parm = MLX5_ADDR_OF(stc, attr, stc_param);
448 	ret = mlx5dr_cmd_stc_modify_set_stc_param(stc_attr, stc_parm);
449 	if (ret)
450 		return ret;
451 
452 	ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out));
453 	if (ret) {
454 		DR_LOG(ERR, "Failed to modify STC FW action_type %d", stc_attr->action_type);
455 		rte_errno = errno;
456 	}
457 
458 	return ret;
459 }
460 
461 struct mlx5dr_devx_obj *
462 mlx5dr_cmd_arg_create(struct ibv_context *ctx,
463 		      uint16_t log_obj_range,
464 		      uint32_t pd)
465 {
466 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
467 	uint32_t in[MLX5_ST_SZ_DW(create_arg_in)] = {0};
468 	struct mlx5dr_devx_obj *devx_obj;
469 	void *attr;
470 
471 	devx_obj = simple_malloc(sizeof(*devx_obj));
472 	if (!devx_obj) {
473 		DR_LOG(ERR, "Failed to allocate memory for ARG object");
474 		rte_errno = ENOMEM;
475 		return NULL;
476 	}
477 
478 	attr = MLX5_ADDR_OF(create_arg_in, in, hdr);
479 	MLX5_SET(general_obj_in_cmd_hdr,
480 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
481 	MLX5_SET(general_obj_in_cmd_hdr,
482 		 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_ARG);
483 	MLX5_SET(general_obj_in_cmd_hdr,
484 		 attr, log_obj_range, log_obj_range);
485 
486 	attr = MLX5_ADDR_OF(create_arg_in, in, arg);
487 	MLX5_SET(arg, attr, access_pd, pd);
488 
489 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
490 	if (!devx_obj->obj) {
491 		DR_LOG(ERR, "Failed to create ARG");
492 		simple_free(devx_obj);
493 		rte_errno = errno;
494 		return NULL;
495 	}
496 
497 	devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
498 
499 	return devx_obj;
500 }
501 
502 struct mlx5dr_devx_obj *
503 mlx5dr_cmd_header_modify_pattern_create(struct ibv_context *ctx,
504 					uint32_t pattern_length,
505 					uint8_t *actions)
506 {
507 	uint32_t in[MLX5_ST_SZ_DW(create_header_modify_pattern_in)] = {0};
508 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
509 	struct mlx5dr_devx_obj *devx_obj;
510 	void *pattern_data;
511 	void *pattern;
512 	void *attr;
513 
514 	if (pattern_length > MAX_ACTIONS_DATA_IN_HEADER_MODIFY) {
515 		DR_LOG(ERR, "Pattern length %d exceeds limit %d",
516 			pattern_length, MAX_ACTIONS_DATA_IN_HEADER_MODIFY);
517 		rte_errno = EINVAL;
518 		return NULL;
519 	}
520 
521 	devx_obj = simple_malloc(sizeof(*devx_obj));
522 	if (!devx_obj) {
523 		DR_LOG(ERR, "Failed to allocate memory for header_modify_pattern object");
524 		rte_errno = ENOMEM;
525 		return NULL;
526 	}
527 
528 	attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr);
529 	MLX5_SET(general_obj_in_cmd_hdr,
530 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
531 	MLX5_SET(general_obj_in_cmd_hdr,
532 		 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_MODIFY_HEADER_PATTERN);
533 
534 	pattern = MLX5_ADDR_OF(create_header_modify_pattern_in, in, pattern);
535 	/* Pattern_length is in ddwords */
536 	MLX5_SET(header_modify_pattern_in, pattern, pattern_length, pattern_length / (2 * DW_SIZE));
537 
538 	pattern_data = MLX5_ADDR_OF(header_modify_pattern_in, pattern, pattern_data);
539 	memcpy(pattern_data, actions, pattern_length);
540 
541 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
542 	if (!devx_obj->obj) {
543 		DR_LOG(ERR, "Failed to create header_modify_pattern");
544 		rte_errno = errno;
545 		goto free_obj;
546 	}
547 
548 	devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
549 
550 	return devx_obj;
551 
552 free_obj:
553 	simple_free(devx_obj);
554 	return NULL;
555 }
556 
557 struct mlx5dr_devx_obj *
558 mlx5dr_cmd_ste_create(struct ibv_context *ctx,
559 		      struct mlx5dr_cmd_ste_create_attr *ste_attr)
560 {
561 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
562 	uint32_t in[MLX5_ST_SZ_DW(create_ste_in)] = {0};
563 	struct mlx5dr_devx_obj *devx_obj;
564 	void *attr;
565 
566 	devx_obj = simple_malloc(sizeof(*devx_obj));
567 	if (!devx_obj) {
568 		DR_LOG(ERR, "Failed to allocate memory for STE object");
569 		rte_errno = ENOMEM;
570 		return NULL;
571 	}
572 
573 	attr = MLX5_ADDR_OF(create_ste_in, in, hdr);
574 	MLX5_SET(general_obj_in_cmd_hdr,
575 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
576 	MLX5_SET(general_obj_in_cmd_hdr,
577 		 attr, obj_type, MLX5_GENERAL_OBJ_TYPE_STE);
578 	MLX5_SET(general_obj_in_cmd_hdr,
579 		 attr, log_obj_range, ste_attr->log_obj_range);
580 
581 	attr = MLX5_ADDR_OF(create_ste_in, in, ste);
582 	MLX5_SET(ste, attr, table_type, ste_attr->table_type);
583 
584 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
585 	if (!devx_obj->obj) {
586 		DR_LOG(ERR, "Failed to create STE");
587 		simple_free(devx_obj);
588 		rte_errno = errno;
589 		return NULL;
590 	}
591 
592 	devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
593 
594 	return devx_obj;
595 }
596 
597 struct mlx5dr_devx_obj *
598 mlx5dr_cmd_definer_create(struct ibv_context *ctx,
599 			  struct mlx5dr_cmd_definer_create_attr *def_attr)
600 {
601 	uint32_t out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
602 	uint32_t in[MLX5_ST_SZ_DW(create_definer_in)] = {0};
603 	struct mlx5dr_devx_obj *devx_obj;
604 	void *ptr;
605 
606 	devx_obj = simple_malloc(sizeof(*devx_obj));
607 	if (!devx_obj) {
608 		DR_LOG(ERR, "Failed to allocate memory for definer object");
609 		rte_errno = ENOMEM;
610 		return NULL;
611 	}
612 
613 	MLX5_SET(general_obj_in_cmd_hdr,
614 		 in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
615 	MLX5_SET(general_obj_in_cmd_hdr,
616 		 in, obj_type, MLX5_GENERAL_OBJ_TYPE_DEFINER);
617 
618 	ptr = MLX5_ADDR_OF(create_definer_in, in, definer);
619 	MLX5_SET(definer, ptr, format_id, MLX5_IFC_DEFINER_FORMAT_ID_SELECT);
620 
621 	MLX5_SET(definer, ptr, format_select_dw0, def_attr->dw_selector[0]);
622 	MLX5_SET(definer, ptr, format_select_dw1, def_attr->dw_selector[1]);
623 	MLX5_SET(definer, ptr, format_select_dw2, def_attr->dw_selector[2]);
624 	MLX5_SET(definer, ptr, format_select_dw3, def_attr->dw_selector[3]);
625 	MLX5_SET(definer, ptr, format_select_dw4, def_attr->dw_selector[4]);
626 	MLX5_SET(definer, ptr, format_select_dw5, def_attr->dw_selector[5]);
627 	MLX5_SET(definer, ptr, format_select_dw6, def_attr->dw_selector[6]);
628 	MLX5_SET(definer, ptr, format_select_dw7, def_attr->dw_selector[7]);
629 	MLX5_SET(definer, ptr, format_select_dw8, def_attr->dw_selector[8]);
630 
631 	MLX5_SET(definer, ptr, format_select_byte0, def_attr->byte_selector[0]);
632 	MLX5_SET(definer, ptr, format_select_byte1, def_attr->byte_selector[1]);
633 	MLX5_SET(definer, ptr, format_select_byte2, def_attr->byte_selector[2]);
634 	MLX5_SET(definer, ptr, format_select_byte3, def_attr->byte_selector[3]);
635 	MLX5_SET(definer, ptr, format_select_byte4, def_attr->byte_selector[4]);
636 	MLX5_SET(definer, ptr, format_select_byte5, def_attr->byte_selector[5]);
637 	MLX5_SET(definer, ptr, format_select_byte6, def_attr->byte_selector[6]);
638 	MLX5_SET(definer, ptr, format_select_byte7, def_attr->byte_selector[7]);
639 
640 	ptr = MLX5_ADDR_OF(definer, ptr, match_mask);
641 	memcpy(ptr, def_attr->match_mask, MLX5_FLD_SZ_BYTES(definer, match_mask));
642 
643 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
644 	if (!devx_obj->obj) {
645 		DR_LOG(ERR, "Failed to create Definer");
646 		simple_free(devx_obj);
647 		rte_errno = errno;
648 		return NULL;
649 	}
650 
651 	devx_obj->id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
652 
653 	return devx_obj;
654 }
655 
656 struct mlx5dr_devx_obj *
657 mlx5dr_cmd_sq_create(struct ibv_context *ctx,
658 		     struct mlx5dr_cmd_sq_create_attr *attr)
659 {
660 	uint32_t out[MLX5_ST_SZ_DW(create_sq_out)] = {0};
661 	uint32_t in[MLX5_ST_SZ_DW(create_sq_in)] = {0};
662 	void *sqc = MLX5_ADDR_OF(create_sq_in, in, ctx);
663 	void *wqc = MLX5_ADDR_OF(sqc, sqc, wq);
664 	struct mlx5dr_devx_obj *devx_obj;
665 
666 	devx_obj = simple_malloc(sizeof(*devx_obj));
667 	if (!devx_obj) {
668 		DR_LOG(ERR, "Failed to create SQ");
669 		rte_errno = ENOMEM;
670 		return NULL;
671 	}
672 
673 	MLX5_SET(create_sq_in, in, opcode, MLX5_CMD_OP_CREATE_SQ);
674 	MLX5_SET(sqc, sqc, cqn, attr->cqn);
675 	MLX5_SET(sqc, sqc, flush_in_error_en, 1);
676 	MLX5_SET(sqc, sqc, non_wire, 1);
677 	MLX5_SET(wq, wqc, wq_type, MLX5_WQ_TYPE_CYCLIC);
678 	MLX5_SET(wq, wqc, pd, attr->pdn);
679 	MLX5_SET(wq, wqc, uar_page, attr->page_id);
680 	MLX5_SET(wq, wqc, log_wq_stride, log2above(MLX5_SEND_WQE_BB));
681 	MLX5_SET(wq, wqc, log_wq_sz, attr->log_wq_sz);
682 	MLX5_SET(wq, wqc, dbr_umem_id, attr->dbr_id);
683 	MLX5_SET(wq, wqc, wq_umem_id, attr->wq_id);
684 
685 	devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, sizeof(out));
686 	if (!devx_obj->obj) {
687 		simple_free(devx_obj);
688 		rte_errno = errno;
689 		return NULL;
690 	}
691 
692 	devx_obj->id = MLX5_GET(create_sq_out, out, sqn);
693 
694 	return devx_obj;
695 }
696 
697 int mlx5dr_cmd_sq_modify_rdy(struct mlx5dr_devx_obj *devx_obj)
698 {
699 	uint32_t out[MLX5_ST_SZ_DW(modify_sq_out)] = {0};
700 	uint32_t in[MLX5_ST_SZ_DW(modify_sq_in)] = {0};
701 	void *sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
702 	int ret;
703 
704 	MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ);
705 	MLX5_SET(modify_sq_in, in, sqn, devx_obj->id);
706 	MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST);
707 	MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY);
708 
709 	ret = mlx5_glue->devx_obj_modify(devx_obj->obj, in, sizeof(in), out, sizeof(out));
710 	if (ret) {
711 		DR_LOG(ERR, "Failed to modify SQ");
712 		rte_errno = errno;
713 	}
714 
715 	return ret;
716 }
717 
718 int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
719 			  struct mlx5dr_cmd_query_caps *caps)
720 {
721 	uint32_t out[MLX5_ST_SZ_DW(query_hca_cap_out)] = {0};
722 	uint32_t in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0};
723 	const struct flow_hw_port_info *port_info;
724 	struct ibv_device_attr_ex attr_ex;
725 	int ret;
726 
727 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
728 	MLX5_SET(query_hca_cap_in, in, op_mod,
729 		 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE |
730 		 MLX5_HCA_CAP_OPMOD_GET_CUR);
731 
732 	ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
733 	if (ret) {
734 		DR_LOG(ERR, "Failed to query device caps");
735 		rte_errno = errno;
736 		return rte_errno;
737 	}
738 
739 	caps->wqe_based_update =
740 		MLX5_GET(query_hca_cap_out, out,
741 			 capability.cmd_hca_cap.wqe_based_flow_table_update_cap);
742 
743 	caps->eswitch_manager = MLX5_GET(query_hca_cap_out, out,
744 					 capability.cmd_hca_cap.eswitch_manager);
745 
746 	caps->flex_protocols = MLX5_GET(query_hca_cap_out, out,
747 					capability.cmd_hca_cap.flex_parser_protocols);
748 
749 	caps->log_header_modify_argument_granularity =
750 		MLX5_GET(query_hca_cap_out, out,
751 			 capability.cmd_hca_cap.log_header_modify_argument_granularity);
752 
753 	caps->log_header_modify_argument_granularity -=
754 			MLX5_GET(query_hca_cap_out, out,
755 				 capability.cmd_hca_cap.
756 				 log_header_modify_argument_granularity_offset);
757 
758 	caps->log_header_modify_argument_max_alloc =
759 		MLX5_GET(query_hca_cap_out, out,
760 			 capability.cmd_hca_cap.log_header_modify_argument_max_alloc);
761 
762 	caps->definer_format_sup =
763 		MLX5_GET64(query_hca_cap_out, out,
764 			   capability.cmd_hca_cap.match_definer_format_supported);
765 
766 	MLX5_SET(query_hca_cap_in, in, op_mod,
767 		 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 |
768 		 MLX5_HCA_CAP_OPMOD_GET_CUR);
769 
770 	ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
771 	if (ret) {
772 		DR_LOG(ERR, "Failed to query device caps");
773 		rte_errno = errno;
774 		return rte_errno;
775 	}
776 
777 	caps->full_dw_jumbo_support = MLX5_GET(query_hca_cap_out, out,
778 					       capability.cmd_hca_cap_2.
779 					       format_select_dw_8_6_ext);
780 
781 	caps->format_select_gtpu_dw_0 = MLX5_GET(query_hca_cap_out, out,
782 						 capability.cmd_hca_cap_2.
783 						 format_select_dw_gtpu_dw_0);
784 
785 	caps->format_select_gtpu_dw_1 = MLX5_GET(query_hca_cap_out, out,
786 						 capability.cmd_hca_cap_2.
787 						 format_select_dw_gtpu_dw_1);
788 
789 	caps->format_select_gtpu_dw_2 = MLX5_GET(query_hca_cap_out, out,
790 						 capability.cmd_hca_cap_2.
791 						 format_select_dw_gtpu_dw_2);
792 
793 	caps->format_select_gtpu_ext_dw_0 = MLX5_GET(query_hca_cap_out, out,
794 						     capability.cmd_hca_cap_2.
795 						     format_select_dw_gtpu_first_ext_dw_0);
796 
797 	MLX5_SET(query_hca_cap_in, in, op_mod,
798 		 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE |
799 		 MLX5_HCA_CAP_OPMOD_GET_CUR);
800 
801 	ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
802 	if (ret) {
803 		DR_LOG(ERR, "Failed to query flow table caps");
804 		rte_errno = errno;
805 		return rte_errno;
806 	}
807 
808 	caps->nic_ft.max_level = MLX5_GET(query_hca_cap_out, out,
809 					  capability.flow_table_nic_cap.
810 					  flow_table_properties_nic_receive.max_ft_level);
811 
812 	caps->nic_ft.reparse = MLX5_GET(query_hca_cap_out, out,
813 					capability.flow_table_nic_cap.
814 					flow_table_properties_nic_receive.reparse);
815 
816 	if (caps->wqe_based_update) {
817 		MLX5_SET(query_hca_cap_in, in, op_mod,
818 			 MLX5_GET_HCA_CAP_OP_MOD_WQE_BASED_FLOW_TABLE |
819 			 MLX5_HCA_CAP_OPMOD_GET_CUR);
820 
821 		ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
822 		if (ret) {
823 			DR_LOG(ERR, "Failed to query WQE based FT caps");
824 			rte_errno = errno;
825 			return rte_errno;
826 		}
827 
828 		caps->rtc_reparse_mode = MLX5_GET(query_hca_cap_out, out,
829 						  capability.wqe_based_flow_table_cap.
830 						  rtc_reparse_mode);
831 
832 		caps->ste_format = MLX5_GET(query_hca_cap_out, out,
833 					    capability.wqe_based_flow_table_cap.
834 					    ste_format);
835 
836 		caps->rtc_index_mode = MLX5_GET(query_hca_cap_out, out,
837 						capability.wqe_based_flow_table_cap.
838 						rtc_index_mode);
839 
840 		caps->rtc_log_depth_max = MLX5_GET(query_hca_cap_out, out,
841 						   capability.wqe_based_flow_table_cap.
842 						   rtc_log_depth_max);
843 
844 		caps->ste_alloc_log_max = MLX5_GET(query_hca_cap_out, out,
845 						   capability.wqe_based_flow_table_cap.
846 						   ste_alloc_log_max);
847 
848 		caps->ste_alloc_log_gran = MLX5_GET(query_hca_cap_out, out,
849 						    capability.wqe_based_flow_table_cap.
850 						    ste_alloc_log_granularity);
851 
852 		caps->trivial_match_definer = MLX5_GET(query_hca_cap_out, out,
853 						       capability.wqe_based_flow_table_cap.
854 						       trivial_match_definer);
855 
856 		caps->stc_alloc_log_max = MLX5_GET(query_hca_cap_out, out,
857 						   capability.wqe_based_flow_table_cap.
858 						   stc_alloc_log_max);
859 
860 		caps->stc_alloc_log_gran = MLX5_GET(query_hca_cap_out, out,
861 						    capability.wqe_based_flow_table_cap.
862 						    stc_alloc_log_granularity);
863 	}
864 
865 	if (caps->eswitch_manager) {
866 		MLX5_SET(query_hca_cap_in, in, op_mod,
867 			 MLX5_GET_HCA_CAP_OP_MOD_ESW_FLOW_TABLE |
868 			 MLX5_HCA_CAP_OPMOD_GET_CUR);
869 
870 		ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
871 		if (ret) {
872 			DR_LOG(ERR, "Failed to query flow table esw caps");
873 			rte_errno = errno;
874 			return rte_errno;
875 		}
876 
877 		caps->fdb_ft.max_level = MLX5_GET(query_hca_cap_out, out,
878 						  capability.flow_table_nic_cap.
879 						  flow_table_properties_nic_receive.max_ft_level);
880 
881 		caps->fdb_ft.reparse = MLX5_GET(query_hca_cap_out, out,
882 						capability.flow_table_nic_cap.
883 						flow_table_properties_nic_receive.reparse);
884 
885 		MLX5_SET(query_hca_cap_in, in, op_mod,
886 			 MLX5_SET_HCA_CAP_OP_MOD_ESW | MLX5_HCA_CAP_OPMOD_GET_CUR);
887 
888 		ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
889 		if (ret) {
890 			DR_LOG(ERR, "Query eswitch capabilities failed %d\n", ret);
891 			rte_errno = errno;
892 			return rte_errno;
893 		}
894 
895 		if (MLX5_GET(query_hca_cap_out, out,
896 			     capability.esw_cap.esw_manager_vport_number_valid))
897 			caps->eswitch_manager_vport_number =
898 			MLX5_GET(query_hca_cap_out, out,
899 				 capability.esw_cap.esw_manager_vport_number);
900 	}
901 
902 	ret = mlx5_glue->query_device_ex(ctx, NULL, &attr_ex);
903 	if (ret) {
904 		DR_LOG(ERR, "Failed to query device attributes");
905 		rte_errno = ret;
906 		return rte_errno;
907 	}
908 
909 	strlcpy(caps->fw_ver, attr_ex.orig_attr.fw_ver, sizeof(caps->fw_ver));
910 
911 	port_info = flow_hw_get_wire_port(ctx);
912 	if (port_info) {
913 		caps->wire_regc = port_info->regc_value;
914 		caps->wire_regc_mask = port_info->regc_mask;
915 	} else {
916 		DR_LOG(INFO, "Failed to query wire port regc value");
917 	}
918 
919 	return ret;
920 }
921 
922 int mlx5dr_cmd_query_ib_port(struct ibv_context *ctx,
923 			     struct mlx5dr_cmd_query_vport_caps *vport_caps,
924 			     uint32_t port_num)
925 {
926 	struct mlx5_port_info port_info = {0};
927 	uint32_t flags;
928 	int ret;
929 
930 	flags = MLX5_PORT_QUERY_VPORT | MLX5_PORT_QUERY_ESW_OWNER_VHCA_ID;
931 
932 	ret = mlx5_glue->devx_port_query(ctx, port_num, &port_info);
933 	/* Check if query succeed and vport is enabled */
934 	if (ret || (port_info.query_flags & flags) != flags) {
935 		rte_errno = ENOTSUP;
936 		return rte_errno;
937 	}
938 
939 	vport_caps->vport_num = port_info.vport_id;
940 	vport_caps->esw_owner_vhca_id = port_info.esw_owner_vhca_id;
941 
942 	if (port_info.query_flags & MLX5_PORT_QUERY_REG_C0) {
943 		vport_caps->metadata_c = port_info.vport_meta_tag;
944 		vport_caps->metadata_c_mask = port_info.vport_meta_mask;
945 	}
946 
947 	return 0;
948 }
949