xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_cmd.c (revision 9410645520e9b820069761f3450ef6661418e279)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3 
4 #include "mlx5hws_internal.h"
5 
6 static enum mlx5_ifc_flow_destination_type
hws_cmd_dest_type_to_ifc_dest_type(enum mlx5_flow_destination_type type)7 hws_cmd_dest_type_to_ifc_dest_type(enum mlx5_flow_destination_type type)
8 {
9 	switch (type) {
10 	case MLX5_FLOW_DESTINATION_TYPE_VPORT:
11 		return MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT;
12 	case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
13 		return MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
14 	case MLX5_FLOW_DESTINATION_TYPE_TIR:
15 		return MLX5_IFC_FLOW_DESTINATION_TYPE_TIR;
16 	case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
17 		return MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
18 	case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
19 		return MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK;
20 	case MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE:
21 		return MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE;
22 	case MLX5_FLOW_DESTINATION_TYPE_NONE:
23 	case MLX5_FLOW_DESTINATION_TYPE_PORT:
24 	case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
25 	case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
26 	case MLX5_FLOW_DESTINATION_TYPE_RANGE:
27 	default:
28 		pr_warn("HWS: unknown flow dest type %d\n", type);
29 		return 0;
30 	}
31 };
32 
hws_cmd_general_obj_destroy(struct mlx5_core_dev * mdev,u32 object_type,u32 object_id)33 static int hws_cmd_general_obj_destroy(struct mlx5_core_dev *mdev,
34 				       u32 object_type,
35 				       u32 object_id)
36 {
37 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
38 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
39 
40 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
41 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, object_type);
42 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, object_id);
43 
44 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
45 }
46 
mlx5hws_cmd_flow_table_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_ft_create_attr * ft_attr,u32 * table_id)47 int mlx5hws_cmd_flow_table_create(struct mlx5_core_dev *mdev,
48 				  struct mlx5hws_cmd_ft_create_attr *ft_attr,
49 				  u32 *table_id)
50 {
51 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
52 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
53 	void *ft_ctx;
54 	int ret;
55 
56 	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
57 	MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type);
58 
59 	ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
60 	MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level);
61 	MLX5_SET(flow_table_context, ft_ctx, rtc_valid, ft_attr->rtc_valid);
62 	MLX5_SET(flow_table_context, ft_ctx, reformat_en, ft_attr->reformat_en);
63 	MLX5_SET(flow_table_context, ft_ctx, decap_en, ft_attr->decap_en);
64 
65 	ret = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out);
66 	if (ret)
67 		return ret;
68 
69 	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
70 
71 	return 0;
72 }
73 
mlx5hws_cmd_flow_table_modify(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_ft_modify_attr * ft_attr,u32 table_id)74 int mlx5hws_cmd_flow_table_modify(struct mlx5_core_dev *mdev,
75 				  struct mlx5hws_cmd_ft_modify_attr *ft_attr,
76 				  u32 table_id)
77 {
78 	u32 in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {0};
79 	void *ft_ctx;
80 
81 	MLX5_SET(modify_flow_table_in, in, opcode, MLX5_CMD_OP_MODIFY_FLOW_TABLE);
82 	MLX5_SET(modify_flow_table_in, in, table_type, ft_attr->type);
83 	MLX5_SET(modify_flow_table_in, in, modify_field_select, ft_attr->modify_fs);
84 	MLX5_SET(modify_flow_table_in, in, table_id, table_id);
85 
86 	ft_ctx = MLX5_ADDR_OF(modify_flow_table_in, in, flow_table_context);
87 
88 	MLX5_SET(flow_table_context, ft_ctx, table_miss_action, ft_attr->table_miss_action);
89 	MLX5_SET(flow_table_context, ft_ctx, table_miss_id, ft_attr->table_miss_id);
90 	MLX5_SET(flow_table_context, ft_ctx, hws.rtc_id_0, ft_attr->rtc_id_0);
91 	MLX5_SET(flow_table_context, ft_ctx, hws.rtc_id_1, ft_attr->rtc_id_1);
92 
93 	return mlx5_cmd_exec_in(mdev, modify_flow_table, in);
94 }
95 
mlx5hws_cmd_flow_table_query(struct mlx5_core_dev * mdev,u32 table_id,struct mlx5hws_cmd_ft_query_attr * ft_attr,u64 * icm_addr_0,u64 * icm_addr_1)96 int mlx5hws_cmd_flow_table_query(struct mlx5_core_dev *mdev,
97 				 u32 table_id,
98 				 struct mlx5hws_cmd_ft_query_attr *ft_attr,
99 				 u64 *icm_addr_0, u64 *icm_addr_1)
100 {
101 	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {0};
102 	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {0};
103 	void *ft_ctx;
104 	int ret;
105 
106 	MLX5_SET(query_flow_table_in, in, opcode, MLX5_CMD_OP_QUERY_FLOW_TABLE);
107 	MLX5_SET(query_flow_table_in, in, table_type, ft_attr->type);
108 	MLX5_SET(query_flow_table_in, in, table_id, table_id);
109 
110 	ret = mlx5_cmd_exec_inout(mdev, query_flow_table, in, out);
111 	if (ret)
112 		return ret;
113 
114 	ft_ctx = MLX5_ADDR_OF(query_flow_table_out, out, flow_table_context);
115 	*icm_addr_0 = MLX5_GET64(flow_table_context, ft_ctx, sws.sw_owner_icm_root_0);
116 	*icm_addr_1 = MLX5_GET64(flow_table_context, ft_ctx, sws.sw_owner_icm_root_1);
117 
118 	return ret;
119 }
120 
mlx5hws_cmd_flow_table_destroy(struct mlx5_core_dev * mdev,u8 fw_ft_type,u32 table_id)121 int mlx5hws_cmd_flow_table_destroy(struct mlx5_core_dev *mdev,
122 				   u8 fw_ft_type, u32 table_id)
123 {
124 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {0};
125 
126 	MLX5_SET(destroy_flow_table_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_TABLE);
127 	MLX5_SET(destroy_flow_table_in, in, table_type, fw_ft_type);
128 	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
129 
130 	return mlx5_cmd_exec_in(mdev, destroy_flow_table, in);
131 }
132 
mlx5hws_cmd_alias_flow_table_destroy(struct mlx5_core_dev * mdev,u32 table_id)133 void mlx5hws_cmd_alias_flow_table_destroy(struct mlx5_core_dev *mdev,
134 					  u32 table_id)
135 {
136 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_FT_ALIAS, table_id);
137 }
138 
hws_cmd_flow_group_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_fg_attr * fg_attr,u32 * group_id)139 static int hws_cmd_flow_group_create(struct mlx5_core_dev *mdev,
140 				     struct mlx5hws_cmd_fg_attr *fg_attr,
141 				     u32 *group_id)
142 {
143 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
144 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
145 	u32 *in;
146 	int ret;
147 
148 	in = kvzalloc(inlen, GFP_KERNEL);
149 	if (!in)
150 		return -ENOMEM;
151 
152 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
153 	MLX5_SET(create_flow_group_in, in, table_type, fg_attr->table_type);
154 	MLX5_SET(create_flow_group_in, in, table_id, fg_attr->table_id);
155 
156 	ret = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
157 	if (ret)
158 		goto out;
159 
160 	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
161 
162 out:
163 	kvfree(in);
164 	return ret;
165 }
166 
hws_cmd_flow_group_destroy(struct mlx5_core_dev * mdev,u32 ft_id,u32 fg_id,u8 ft_type)167 static int hws_cmd_flow_group_destroy(struct mlx5_core_dev *mdev,
168 				      u32 ft_id, u32 fg_id, u8 ft_type)
169 {
170 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
171 
172 	MLX5_SET(destroy_flow_group_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_GROUP);
173 	MLX5_SET(destroy_flow_group_in, in, table_type, ft_type);
174 	MLX5_SET(destroy_flow_group_in, in, table_id, ft_id);
175 	MLX5_SET(destroy_flow_group_in, in, group_id, fg_id);
176 
177 	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
178 }
179 
mlx5hws_cmd_set_fte(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 group_id,struct mlx5hws_cmd_set_fte_attr * fte_attr)180 int mlx5hws_cmd_set_fte(struct mlx5_core_dev *mdev,
181 			u32 table_type,
182 			u32 table_id,
183 			u32 group_id,
184 			struct mlx5hws_cmd_set_fte_attr *fte_attr)
185 {
186 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
187 	void *in_flow_context;
188 	u32 dest_entry_sz;
189 	u32 total_dest_sz;
190 	u32 action_flags;
191 	u8 *in_dests;
192 	u32 inlen;
193 	u32 *in;
194 	int ret;
195 	u32 i;
196 
197 	dest_entry_sz = fte_attr->extended_dest ?
198 			MLX5_ST_SZ_BYTES(extended_dest_format) :
199 			MLX5_ST_SZ_BYTES(dest_format);
200 	total_dest_sz = dest_entry_sz * fte_attr->dests_num;
201 	inlen = align((MLX5_ST_SZ_BYTES(set_fte_in) + total_dest_sz), DW_SIZE);
202 	in = kzalloc(inlen, GFP_KERNEL);
203 	if (!in)
204 		return -ENOMEM;
205 
206 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
207 	MLX5_SET(set_fte_in, in, table_type, table_type);
208 	MLX5_SET(set_fte_in, in, table_id, table_id);
209 
210 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
211 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
212 	MLX5_SET(flow_context, in_flow_context, flow_source, fte_attr->flow_source);
213 	MLX5_SET(flow_context, in_flow_context, extended_destination, fte_attr->extended_dest);
214 	MLX5_SET(set_fte_in, in, ignore_flow_level, fte_attr->ignore_flow_level);
215 
216 	action_flags = fte_attr->action_flags;
217 	MLX5_SET(flow_context, in_flow_context, action, action_flags);
218 
219 	if (action_flags & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
220 		MLX5_SET(flow_context, in_flow_context,
221 			 packet_reformat_id, fte_attr->packet_reformat_id);
222 	}
223 
224 	if (action_flags & (MLX5_FLOW_CONTEXT_ACTION_DECRYPT | MLX5_FLOW_CONTEXT_ACTION_ENCRYPT)) {
225 		MLX5_SET(flow_context, in_flow_context,
226 			 encrypt_decrypt_type, fte_attr->encrypt_decrypt_type);
227 		MLX5_SET(flow_context, in_flow_context,
228 			 encrypt_decrypt_obj_id, fte_attr->encrypt_decrypt_obj_id);
229 	}
230 
231 	if (action_flags & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
232 		in_dests = (u8 *)MLX5_ADDR_OF(flow_context, in_flow_context, destination);
233 
234 		for (i = 0; i < fte_attr->dests_num; i++) {
235 			struct mlx5hws_cmd_set_fte_dest *dest = &fte_attr->dests[i];
236 			enum mlx5_ifc_flow_destination_type ifc_dest_type =
237 				hws_cmd_dest_type_to_ifc_dest_type(dest->destination_type);
238 
239 			switch (dest->destination_type) {
240 			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
241 				if (dest->ext_flags & MLX5HWS_CMD_EXT_DEST_ESW_OWNER_VHCA_ID) {
242 					MLX5_SET(dest_format, in_dests,
243 						 destination_eswitch_owner_vhca_id_valid, 1);
244 					MLX5_SET(dest_format, in_dests,
245 						 destination_eswitch_owner_vhca_id,
246 						 dest->esw_owner_vhca_id);
247 				}
248 				fallthrough;
249 			case MLX5_FLOW_DESTINATION_TYPE_TIR:
250 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
251 				MLX5_SET(dest_format, in_dests, destination_type, ifc_dest_type);
252 				MLX5_SET(dest_format, in_dests, destination_id,
253 					 dest->destination_id);
254 				if (dest->ext_flags & MLX5HWS_CMD_EXT_DEST_REFORMAT) {
255 					MLX5_SET(dest_format, in_dests, packet_reformat, 1);
256 					MLX5_SET(extended_dest_format, in_dests, packet_reformat_id,
257 						 dest->ext_reformat_id);
258 				}
259 				break;
260 			default:
261 				ret = -EOPNOTSUPP;
262 				goto out;
263 			}
264 
265 			in_dests = in_dests + dest_entry_sz;
266 		}
267 		MLX5_SET(flow_context, in_flow_context, destination_list_size, fte_attr->dests_num);
268 	}
269 
270 	ret = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
271 	if (ret)
272 		mlx5_core_err(mdev, "Failed creating FLOW_TABLE_ENTRY\n");
273 
274 out:
275 	kfree(in);
276 	return ret;
277 }
278 
mlx5hws_cmd_delete_fte(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id)279 int mlx5hws_cmd_delete_fte(struct mlx5_core_dev *mdev,
280 			   u32 table_type,
281 			   u32 table_id)
282 {
283 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
284 
285 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
286 	MLX5_SET(delete_fte_in, in, table_type, table_type);
287 	MLX5_SET(delete_fte_in, in, table_id, table_id);
288 
289 	return mlx5_cmd_exec_in(mdev, delete_fte, in);
290 }
291 
292 struct mlx5hws_cmd_forward_tbl *
mlx5hws_cmd_forward_tbl_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_ft_create_attr * ft_attr,struct mlx5hws_cmd_set_fte_attr * fte_attr)293 mlx5hws_cmd_forward_tbl_create(struct mlx5_core_dev *mdev,
294 			       struct mlx5hws_cmd_ft_create_attr *ft_attr,
295 			       struct mlx5hws_cmd_set_fte_attr *fte_attr)
296 {
297 	struct mlx5hws_cmd_fg_attr fg_attr = {0};
298 	struct mlx5hws_cmd_forward_tbl *tbl;
299 	int ret;
300 
301 	tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
302 	if (!tbl)
303 		return NULL;
304 
305 	ret = mlx5hws_cmd_flow_table_create(mdev, ft_attr, &tbl->ft_id);
306 	if (ret) {
307 		mlx5_core_err(mdev, "Failed to create FT\n");
308 		goto free_tbl;
309 	}
310 
311 	fg_attr.table_id = tbl->ft_id;
312 	fg_attr.table_type = ft_attr->type;
313 
314 	ret = hws_cmd_flow_group_create(mdev, &fg_attr, &tbl->fg_id);
315 	if (ret) {
316 		mlx5_core_err(mdev, "Failed to create FG\n");
317 		goto free_ft;
318 	}
319 
320 	ret = mlx5hws_cmd_set_fte(mdev, ft_attr->type,
321 				  tbl->ft_id, tbl->fg_id, fte_attr);
322 	if (ret) {
323 		mlx5_core_err(mdev, "Failed to create FTE\n");
324 		goto free_fg;
325 	}
326 
327 	tbl->type = ft_attr->type;
328 	return tbl;
329 
330 free_fg:
331 	hws_cmd_flow_group_destroy(mdev, tbl->ft_id, tbl->fg_id, ft_attr->type);
332 free_ft:
333 	mlx5hws_cmd_flow_table_destroy(mdev, ft_attr->type, tbl->ft_id);
334 free_tbl:
335 	kfree(tbl);
336 	return NULL;
337 }
338 
mlx5hws_cmd_forward_tbl_destroy(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_forward_tbl * tbl)339 void mlx5hws_cmd_forward_tbl_destroy(struct mlx5_core_dev *mdev,
340 				     struct mlx5hws_cmd_forward_tbl *tbl)
341 {
342 	mlx5hws_cmd_delete_fte(mdev, tbl->type, tbl->ft_id);
343 	hws_cmd_flow_group_destroy(mdev, tbl->ft_id, tbl->fg_id, tbl->type);
344 	mlx5hws_cmd_flow_table_destroy(mdev, tbl->type, tbl->ft_id);
345 	kfree(tbl);
346 }
347 
mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context * ctx,u32 fw_ft_type,enum mlx5hws_table_type type,struct mlx5hws_cmd_ft_modify_attr * ft_attr)348 void mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context *ctx,
349 					   u32 fw_ft_type,
350 					   enum mlx5hws_table_type type,
351 					   struct mlx5hws_cmd_ft_modify_attr *ft_attr)
352 {
353 	u32 default_miss_tbl;
354 
355 	if (type != MLX5HWS_TABLE_TYPE_FDB)
356 		return;
357 
358 	ft_attr->modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
359 	ft_attr->type = fw_ft_type;
360 	ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
361 
362 	default_miss_tbl = ctx->common_res[type].default_miss->ft_id;
363 	if (!default_miss_tbl) {
364 		pr_warn("HWS: no flow table ID for default miss\n");
365 		return;
366 	}
367 
368 	ft_attr->table_miss_id = default_miss_tbl;
369 }
370 
mlx5hws_cmd_rtc_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_rtc_create_attr * rtc_attr,u32 * rtc_id)371 int mlx5hws_cmd_rtc_create(struct mlx5_core_dev *mdev,
372 			   struct mlx5hws_cmd_rtc_create_attr *rtc_attr,
373 			   u32 *rtc_id)
374 {
375 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
376 	u32 in[MLX5_ST_SZ_DW(create_rtc_in)] = {0};
377 	void *attr;
378 	int ret;
379 
380 	attr = MLX5_ADDR_OF(create_rtc_in, in, hdr);
381 	MLX5_SET(general_obj_in_cmd_hdr,
382 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
383 	MLX5_SET(general_obj_in_cmd_hdr,
384 		 attr, obj_type, MLX5_OBJ_TYPE_RTC);
385 
386 	attr = MLX5_ADDR_OF(create_rtc_in, in, rtc);
387 	MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ?
388 		 MLX5_IFC_RTC_STE_FORMAT_11DW :
389 		 MLX5_IFC_RTC_STE_FORMAT_8DW);
390 
391 	if (rtc_attr->is_scnd_range) {
392 		MLX5_SET(rtc, attr, ste_format_1, MLX5_IFC_RTC_STE_FORMAT_RANGE);
393 		MLX5_SET(rtc, attr, num_match_ste, 2);
394 	}
395 
396 	MLX5_SET(rtc, attr, pd, rtc_attr->pd);
397 	MLX5_SET(rtc, attr, update_method, rtc_attr->fw_gen_wqe);
398 	MLX5_SET(rtc, attr, update_index_mode, rtc_attr->update_index_mode);
399 	MLX5_SET(rtc, attr, access_index_mode, rtc_attr->access_index_mode);
400 	MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer);
401 	MLX5_SET(rtc, attr, log_depth, rtc_attr->log_depth);
402 	MLX5_SET(rtc, attr, log_hash_size, rtc_attr->log_size);
403 	MLX5_SET(rtc, attr, table_type, rtc_attr->table_type);
404 	MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer);
405 	MLX5_SET(rtc, attr, match_definer_0, rtc_attr->match_definer_0);
406 	MLX5_SET(rtc, attr, match_definer_1, rtc_attr->match_definer_1);
407 	MLX5_SET(rtc, attr, stc_id, rtc_attr->stc_base);
408 	MLX5_SET(rtc, attr, ste_table_base_id, rtc_attr->ste_base);
409 	MLX5_SET(rtc, attr, ste_table_offset, rtc_attr->ste_offset);
410 	MLX5_SET(rtc, attr, miss_flow_table_id, rtc_attr->miss_ft_id);
411 	MLX5_SET(rtc, attr, reparse_mode, rtc_attr->reparse_mode);
412 
413 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
414 	if (ret) {
415 		mlx5_core_err(mdev, "Failed to create RTC\n");
416 		goto out;
417 	}
418 
419 	*rtc_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
420 out:
421 	return ret;
422 }
423 
mlx5hws_cmd_rtc_destroy(struct mlx5_core_dev * mdev,u32 rtc_id)424 void mlx5hws_cmd_rtc_destroy(struct mlx5_core_dev *mdev, u32 rtc_id)
425 {
426 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_RTC, rtc_id);
427 }
428 
mlx5hws_cmd_stc_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_stc_create_attr * stc_attr,u32 * stc_id)429 int mlx5hws_cmd_stc_create(struct mlx5_core_dev *mdev,
430 			   struct mlx5hws_cmd_stc_create_attr *stc_attr,
431 			   u32 *stc_id)
432 {
433 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
434 	u32 in[MLX5_ST_SZ_DW(create_stc_in)] = {0};
435 	void *attr;
436 	int ret;
437 
438 	attr = MLX5_ADDR_OF(create_stc_in, in, hdr);
439 	MLX5_SET(general_obj_in_cmd_hdr,
440 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
441 	MLX5_SET(general_obj_in_cmd_hdr,
442 		 attr, obj_type, MLX5_OBJ_TYPE_STC);
443 	MLX5_SET(general_obj_in_cmd_hdr,
444 		 attr, op_param.create.log_obj_range, stc_attr->log_obj_range);
445 
446 	attr = MLX5_ADDR_OF(create_stc_in, in, stc);
447 	MLX5_SET(stc, attr, table_type, stc_attr->table_type);
448 
449 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
450 	if (ret) {
451 		mlx5_core_err(mdev, "Failed to create STC\n");
452 		goto out;
453 	}
454 
455 	*stc_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
456 out:
457 	return ret;
458 }
459 
mlx5hws_cmd_stc_destroy(struct mlx5_core_dev * mdev,u32 stc_id)460 void mlx5hws_cmd_stc_destroy(struct mlx5_core_dev *mdev, u32 stc_id)
461 {
462 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_STC, stc_id);
463 }
464 
465 static int
hws_cmd_stc_modify_set_stc_param(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_stc_modify_attr * stc_attr,void * stc_param)466 hws_cmd_stc_modify_set_stc_param(struct mlx5_core_dev *mdev,
467 				 struct mlx5hws_cmd_stc_modify_attr *stc_attr,
468 				 void *stc_param)
469 {
470 	switch (stc_attr->action_type) {
471 	case MLX5_IFC_STC_ACTION_TYPE_COUNTER:
472 		MLX5_SET(stc_ste_param_flow_counter, stc_param, flow_counter_id, stc_attr->id);
473 		break;
474 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_TIR:
475 		MLX5_SET(stc_ste_param_tir, stc_param, tirn, stc_attr->dest_tir_num);
476 		break;
477 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT:
478 		MLX5_SET(stc_ste_param_table, stc_param, table_id, stc_attr->dest_table_id);
479 		break;
480 	case MLX5_IFC_STC_ACTION_TYPE_ACC_MODIFY_LIST:
481 		MLX5_SET(stc_ste_param_header_modify_list, stc_param,
482 			 header_modify_pattern_id, stc_attr->modify_header.pattern_id);
483 		MLX5_SET(stc_ste_param_header_modify_list, stc_param,
484 			 header_modify_argument_id, stc_attr->modify_header.arg_id);
485 		break;
486 	case MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE:
487 		MLX5_SET(stc_ste_param_remove, stc_param, action_type,
488 			 MLX5_MODIFICATION_TYPE_REMOVE);
489 		MLX5_SET(stc_ste_param_remove, stc_param, decap,
490 			 stc_attr->remove_header.decap);
491 		MLX5_SET(stc_ste_param_remove, stc_param, remove_start_anchor,
492 			 stc_attr->remove_header.start_anchor);
493 		MLX5_SET(stc_ste_param_remove, stc_param, remove_end_anchor,
494 			 stc_attr->remove_header.end_anchor);
495 		break;
496 	case MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT:
497 		MLX5_SET(stc_ste_param_insert, stc_param, action_type,
498 			 MLX5_MODIFICATION_TYPE_INSERT);
499 		MLX5_SET(stc_ste_param_insert, stc_param, encap,
500 			 stc_attr->insert_header.encap);
501 		MLX5_SET(stc_ste_param_insert, stc_param, inline_data,
502 			 stc_attr->insert_header.is_inline);
503 		MLX5_SET(stc_ste_param_insert, stc_param, insert_anchor,
504 			 stc_attr->insert_header.insert_anchor);
505 		/* HW gets the next 2 sizes in words */
506 		MLX5_SET(stc_ste_param_insert, stc_param, insert_size,
507 			 stc_attr->insert_header.header_size / W_SIZE);
508 		MLX5_SET(stc_ste_param_insert, stc_param, insert_offset,
509 			 stc_attr->insert_header.insert_offset / W_SIZE);
510 		MLX5_SET(stc_ste_param_insert, stc_param, insert_argument,
511 			 stc_attr->insert_header.arg_id);
512 		break;
513 	case MLX5_IFC_STC_ACTION_TYPE_COPY:
514 	case MLX5_IFC_STC_ACTION_TYPE_SET:
515 	case MLX5_IFC_STC_ACTION_TYPE_ADD:
516 	case MLX5_IFC_STC_ACTION_TYPE_ADD_FIELD:
517 		*(__be64 *)stc_param = stc_attr->modify_action.data;
518 		break;
519 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT:
520 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_UPLINK:
521 		MLX5_SET(stc_ste_param_vport, stc_param, vport_number,
522 			 stc_attr->vport.vport_num);
523 		MLX5_SET(stc_ste_param_vport, stc_param, eswitch_owner_vhca_id,
524 			 stc_attr->vport.esw_owner_vhca_id);
525 		MLX5_SET(stc_ste_param_vport, stc_param, eswitch_owner_vhca_id_valid,
526 			 stc_attr->vport.eswitch_owner_vhca_id_valid);
527 		break;
528 	case MLX5_IFC_STC_ACTION_TYPE_DROP:
529 	case MLX5_IFC_STC_ACTION_TYPE_NOP:
530 	case MLX5_IFC_STC_ACTION_TYPE_TAG:
531 	case MLX5_IFC_STC_ACTION_TYPE_ALLOW:
532 		break;
533 	case MLX5_IFC_STC_ACTION_TYPE_ASO:
534 		MLX5_SET(stc_ste_param_execute_aso, stc_param, aso_object_id,
535 			 stc_attr->aso.devx_obj_id);
536 		MLX5_SET(stc_ste_param_execute_aso, stc_param, return_reg_id,
537 			 stc_attr->aso.return_reg_id);
538 		MLX5_SET(stc_ste_param_execute_aso, stc_param, aso_type,
539 			 stc_attr->aso.aso_type);
540 		break;
541 	case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE:
542 		MLX5_SET(stc_ste_param_ste_table, stc_param, ste_obj_id,
543 			 stc_attr->ste_table.ste_obj_id);
544 		MLX5_SET(stc_ste_param_ste_table, stc_param, match_definer_id,
545 			 stc_attr->ste_table.match_definer_id);
546 		MLX5_SET(stc_ste_param_ste_table, stc_param, log_hash_size,
547 			 stc_attr->ste_table.log_hash_size);
548 		break;
549 	case MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS:
550 		MLX5_SET(stc_ste_param_remove_words, stc_param, action_type,
551 			 MLX5_MODIFICATION_TYPE_REMOVE_WORDS);
552 		MLX5_SET(stc_ste_param_remove_words, stc_param, remove_start_anchor,
553 			 stc_attr->remove_words.start_anchor);
554 		MLX5_SET(stc_ste_param_remove_words, stc_param,
555 			 remove_size, stc_attr->remove_words.num_of_words);
556 		break;
557 	case MLX5_IFC_STC_ACTION_TYPE_CRYPTO_IPSEC_ENCRYPTION:
558 		MLX5_SET(stc_ste_param_ipsec_encrypt, stc_param, ipsec_object_id,
559 			 stc_attr->id);
560 		break;
561 	case MLX5_IFC_STC_ACTION_TYPE_CRYPTO_IPSEC_DECRYPTION:
562 		MLX5_SET(stc_ste_param_ipsec_decrypt, stc_param, ipsec_object_id,
563 			 stc_attr->id);
564 		break;
565 	case MLX5_IFC_STC_ACTION_TYPE_TRAILER:
566 		MLX5_SET(stc_ste_param_trailer, stc_param, command,
567 			 stc_attr->reformat_trailer.op);
568 		MLX5_SET(stc_ste_param_trailer, stc_param, type,
569 			 stc_attr->reformat_trailer.type);
570 		MLX5_SET(stc_ste_param_trailer, stc_param, length,
571 			 stc_attr->reformat_trailer.size);
572 		break;
573 	default:
574 		mlx5_core_err(mdev, "Not supported type %d\n", stc_attr->action_type);
575 		return -EINVAL;
576 	}
577 	return 0;
578 }
579 
mlx5hws_cmd_stc_modify(struct mlx5_core_dev * mdev,u32 stc_id,struct mlx5hws_cmd_stc_modify_attr * stc_attr)580 int mlx5hws_cmd_stc_modify(struct mlx5_core_dev *mdev,
581 			   u32 stc_id,
582 			   struct mlx5hws_cmd_stc_modify_attr *stc_attr)
583 {
584 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
585 	u32 in[MLX5_ST_SZ_DW(create_stc_in)] = {0};
586 	void *stc_param;
587 	void *attr;
588 	int ret;
589 
590 	attr = MLX5_ADDR_OF(create_stc_in, in, hdr);
591 	MLX5_SET(general_obj_in_cmd_hdr,
592 		 attr, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
593 	MLX5_SET(general_obj_in_cmd_hdr,
594 		 attr, obj_type, MLX5_OBJ_TYPE_STC);
595 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, stc_id);
596 	MLX5_SET(general_obj_in_cmd_hdr, in,
597 		 op_param.query.obj_offset, stc_attr->stc_offset);
598 
599 	attr = MLX5_ADDR_OF(create_stc_in, in, stc);
600 	MLX5_SET(stc, attr, ste_action_offset, stc_attr->action_offset);
601 	MLX5_SET(stc, attr, action_type, stc_attr->action_type);
602 	MLX5_SET(stc, attr, reparse_mode, stc_attr->reparse_mode);
603 	MLX5_SET64(stc, attr, modify_field_select,
604 		   MLX5_IFC_MODIFY_STC_FIELD_SELECT_NEW_STC);
605 
606 	/* Set destination TIRN, TAG, FT ID, STE ID */
607 	stc_param = MLX5_ADDR_OF(stc, attr, stc_param);
608 	ret = hws_cmd_stc_modify_set_stc_param(mdev, stc_attr, stc_param);
609 	if (ret)
610 		return ret;
611 
612 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
613 	if (ret)
614 		mlx5_core_err(mdev, "Failed to modify STC FW action_type %d\n",
615 			      stc_attr->action_type);
616 
617 	return ret;
618 }
619 
mlx5hws_cmd_arg_create(struct mlx5_core_dev * mdev,u16 log_obj_range,u32 pd,u32 * arg_id)620 int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
621 			   u16 log_obj_range,
622 			   u32 pd,
623 			   u32 *arg_id)
624 {
625 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
626 	u32 in[MLX5_ST_SZ_DW(create_arg_in)] = {0};
627 	void *attr;
628 	int ret;
629 
630 	attr = MLX5_ADDR_OF(create_arg_in, in, hdr);
631 	MLX5_SET(general_obj_in_cmd_hdr,
632 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
633 	MLX5_SET(general_obj_in_cmd_hdr,
634 		 attr, obj_type, MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
635 	MLX5_SET(general_obj_in_cmd_hdr,
636 		 attr, op_param.create.log_obj_range, log_obj_range);
637 
638 	attr = MLX5_ADDR_OF(create_arg_in, in, arg);
639 	MLX5_SET(arg, attr, access_pd, pd);
640 
641 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
642 	if (ret) {
643 		mlx5_core_err(mdev, "Failed to create ARG\n");
644 		goto out;
645 	}
646 
647 	*arg_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
648 out:
649 	return ret;
650 }
651 
mlx5hws_cmd_arg_destroy(struct mlx5_core_dev * mdev,u32 arg_id)652 void mlx5hws_cmd_arg_destroy(struct mlx5_core_dev *mdev,
653 			     u32 arg_id)
654 {
655 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT, arg_id);
656 }
657 
mlx5hws_cmd_header_modify_pattern_create(struct mlx5_core_dev * mdev,u32 pattern_length,u8 * actions,u32 * ptrn_id)658 int mlx5hws_cmd_header_modify_pattern_create(struct mlx5_core_dev *mdev,
659 					     u32 pattern_length,
660 					     u8 *actions,
661 					     u32 *ptrn_id)
662 {
663 	u32 in[MLX5_ST_SZ_DW(create_header_modify_pattern_in)] = {0};
664 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
665 	int num_of_actions;
666 	u64 *pattern_data;
667 	void *pattern;
668 	void *attr;
669 	int ret;
670 	int i;
671 
672 	if (pattern_length > MLX5_MAX_ACTIONS_DATA_IN_HEADER_MODIFY) {
673 		mlx5_core_err(mdev, "Pattern length %d exceeds limit %d\n",
674 			      pattern_length, MLX5_MAX_ACTIONS_DATA_IN_HEADER_MODIFY);
675 		return -EINVAL;
676 	}
677 
678 	attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr);
679 	MLX5_SET(general_obj_in_cmd_hdr,
680 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
681 	MLX5_SET(general_obj_in_cmd_hdr,
682 		 attr, obj_type, MLX5_OBJ_TYPE_MODIFY_HDR_PATTERN);
683 
684 	pattern = MLX5_ADDR_OF(create_header_modify_pattern_in, in, pattern);
685 	/* Pattern_length is in ddwords */
686 	MLX5_SET(header_modify_pattern_in, pattern, pattern_length, pattern_length / (2 * DW_SIZE));
687 
688 	pattern_data = (u64 *)MLX5_ADDR_OF(header_modify_pattern_in, pattern, pattern_data);
689 	memcpy(pattern_data, actions, pattern_length);
690 
691 	num_of_actions = pattern_length / MLX5HWS_MODIFY_ACTION_SIZE;
692 	for (i = 0; i < num_of_actions; i++) {
693 		int type;
694 
695 		type = MLX5_GET(set_action_in, &pattern_data[i], action_type);
696 		if (type != MLX5_MODIFICATION_TYPE_COPY &&
697 		    type != MLX5_MODIFICATION_TYPE_ADD_FIELD)
698 			/* Action typ-copy use all bytes for control */
699 			MLX5_SET(set_action_in, &pattern_data[i], data, 0);
700 	}
701 
702 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
703 	if (ret) {
704 		mlx5_core_err(mdev, "Failed to create header_modify_pattern\n");
705 		goto out;
706 	}
707 
708 	*ptrn_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
709 out:
710 	return ret;
711 }
712 
mlx5hws_cmd_header_modify_pattern_destroy(struct mlx5_core_dev * mdev,u32 ptrn_id)713 void mlx5hws_cmd_header_modify_pattern_destroy(struct mlx5_core_dev *mdev,
714 					       u32 ptrn_id)
715 {
716 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_MODIFY_HDR_PATTERN, ptrn_id);
717 }
718 
mlx5hws_cmd_ste_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_ste_create_attr * ste_attr,u32 * ste_id)719 int mlx5hws_cmd_ste_create(struct mlx5_core_dev *mdev,
720 			   struct mlx5hws_cmd_ste_create_attr *ste_attr,
721 			   u32 *ste_id)
722 {
723 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
724 	u32 in[MLX5_ST_SZ_DW(create_ste_in)] = {0};
725 	void *attr;
726 	int ret;
727 
728 	attr = MLX5_ADDR_OF(create_ste_in, in, hdr);
729 	MLX5_SET(general_obj_in_cmd_hdr,
730 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
731 	MLX5_SET(general_obj_in_cmd_hdr,
732 		 attr, obj_type, MLX5_OBJ_TYPE_STE);
733 	MLX5_SET(general_obj_in_cmd_hdr,
734 		 attr, op_param.create.log_obj_range, ste_attr->log_obj_range);
735 
736 	attr = MLX5_ADDR_OF(create_ste_in, in, ste);
737 	MLX5_SET(ste, attr, table_type, ste_attr->table_type);
738 
739 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
740 	if (ret) {
741 		mlx5_core_err(mdev, "Failed to create STE\n");
742 		goto out;
743 	}
744 
745 	*ste_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
746 out:
747 	return ret;
748 }
749 
mlx5hws_cmd_ste_destroy(struct mlx5_core_dev * mdev,u32 ste_id)750 void mlx5hws_cmd_ste_destroy(struct mlx5_core_dev *mdev, u32 ste_id)
751 {
752 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_STE, ste_id);
753 }
754 
mlx5hws_cmd_definer_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_definer_create_attr * def_attr,u32 * definer_id)755 int mlx5hws_cmd_definer_create(struct mlx5_core_dev *mdev,
756 			       struct mlx5hws_cmd_definer_create_attr *def_attr,
757 			       u32 *definer_id)
758 {
759 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
760 	u32 in[MLX5_ST_SZ_DW(create_definer_in)] = {0};
761 	void *ptr;
762 	int ret;
763 
764 	MLX5_SET(general_obj_in_cmd_hdr,
765 		 in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
766 	MLX5_SET(general_obj_in_cmd_hdr,
767 		 in, obj_type, MLX5_OBJ_TYPE_MATCH_DEFINER);
768 
769 	ptr = MLX5_ADDR_OF(create_definer_in, in, definer);
770 	MLX5_SET(definer, ptr, format_id, MLX5_IFC_DEFINER_FORMAT_ID_SELECT);
771 
772 	MLX5_SET(definer, ptr, format_select_dw0, def_attr->dw_selector[0]);
773 	MLX5_SET(definer, ptr, format_select_dw1, def_attr->dw_selector[1]);
774 	MLX5_SET(definer, ptr, format_select_dw2, def_attr->dw_selector[2]);
775 	MLX5_SET(definer, ptr, format_select_dw3, def_attr->dw_selector[3]);
776 	MLX5_SET(definer, ptr, format_select_dw4, def_attr->dw_selector[4]);
777 	MLX5_SET(definer, ptr, format_select_dw5, def_attr->dw_selector[5]);
778 	MLX5_SET(definer, ptr, format_select_dw6, def_attr->dw_selector[6]);
779 	MLX5_SET(definer, ptr, format_select_dw7, def_attr->dw_selector[7]);
780 	MLX5_SET(definer, ptr, format_select_dw8, def_attr->dw_selector[8]);
781 
782 	MLX5_SET(definer, ptr, format_select_byte0, def_attr->byte_selector[0]);
783 	MLX5_SET(definer, ptr, format_select_byte1, def_attr->byte_selector[1]);
784 	MLX5_SET(definer, ptr, format_select_byte2, def_attr->byte_selector[2]);
785 	MLX5_SET(definer, ptr, format_select_byte3, def_attr->byte_selector[3]);
786 	MLX5_SET(definer, ptr, format_select_byte4, def_attr->byte_selector[4]);
787 	MLX5_SET(definer, ptr, format_select_byte5, def_attr->byte_selector[5]);
788 	MLX5_SET(definer, ptr, format_select_byte6, def_attr->byte_selector[6]);
789 	MLX5_SET(definer, ptr, format_select_byte7, def_attr->byte_selector[7]);
790 
791 	ptr = MLX5_ADDR_OF(definer, ptr, match_mask);
792 	memcpy(ptr, def_attr->match_mask, MLX5_FLD_SZ_BYTES(definer, match_mask));
793 
794 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
795 	if (ret) {
796 		mlx5_core_err(mdev, "Failed to create Definer\n");
797 		goto out;
798 	}
799 
800 	*definer_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
801 out:
802 	return ret;
803 }
804 
mlx5hws_cmd_definer_destroy(struct mlx5_core_dev * mdev,u32 definer_id)805 void mlx5hws_cmd_definer_destroy(struct mlx5_core_dev *mdev,
806 				 u32 definer_id)
807 {
808 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_MATCH_DEFINER, definer_id);
809 }
810 
mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_packet_reformat_create_attr * attr,u32 * reformat_id)811 int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
812 				       struct mlx5hws_cmd_packet_reformat_create_attr *attr,
813 				       u32 *reformat_id)
814 {
815 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_out)] = {0};
816 	size_t insz, cmd_data_sz, cmd_total_sz;
817 	void *prctx;
818 	void *pdata;
819 	void *in;
820 	int ret;
821 
822 	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
823 	cmd_total_sz += MLX5_ST_SZ_BYTES(packet_reformat_context_in);
824 	cmd_data_sz = MLX5_FLD_SZ_BYTES(packet_reformat_context_in, reformat_data);
825 	insz = align(cmd_total_sz + attr->data_sz - cmd_data_sz, DW_SIZE);
826 	in = kzalloc(insz, GFP_KERNEL);
827 	if (!in)
828 		return -ENOMEM;
829 
830 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
831 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
832 
833 	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in,
834 			     packet_reformat_context);
835 	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
836 
837 	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, attr->type);
838 	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, attr->reformat_param_0);
839 	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, attr->data_sz);
840 	memcpy(pdata, attr->data, attr->data_sz);
841 
842 	ret = mlx5_cmd_exec(mdev, in, insz, out, sizeof(out));
843 	if (ret) {
844 		mlx5_core_err(mdev, "Failed to create packet reformat\n");
845 		goto out;
846 	}
847 
848 	*reformat_id = MLX5_GET(alloc_packet_reformat_out, out, packet_reformat_id);
849 out:
850 	kfree(in);
851 	return ret;
852 }
853 
mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev * mdev,u32 reformat_id)854 int mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev *mdev,
855 					u32 reformat_id)
856 {
857 	u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_out)] = {0};
858 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_in)] = {0};
859 	int ret;
860 
861 	MLX5_SET(dealloc_packet_reformat_in, in, opcode,
862 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
863 	MLX5_SET(dealloc_packet_reformat_in, in,
864 		 packet_reformat_id, reformat_id);
865 
866 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
867 	if (ret)
868 		mlx5_core_err(mdev, "Failed to destroy packet_reformat\n");
869 
870 	return ret;
871 }
872 
mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev * mdev,u32 sqn)873 int mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev *mdev, u32 sqn)
874 {
875 	u32 out[MLX5_ST_SZ_DW(modify_sq_out)] = {0};
876 	u32 in[MLX5_ST_SZ_DW(modify_sq_in)] = {0};
877 	void *sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
878 	int ret;
879 
880 	MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ);
881 	MLX5_SET(modify_sq_in, in, sqn, sqn);
882 	MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST);
883 	MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY);
884 
885 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
886 	if (ret)
887 		mlx5_core_err(mdev, "Failed to modify SQ\n");
888 
889 	return ret;
890 }
891 
mlx5hws_cmd_allow_other_vhca_access(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_allow_other_vhca_access_attr * attr)892 int mlx5hws_cmd_allow_other_vhca_access(struct mlx5_core_dev *mdev,
893 					struct mlx5hws_cmd_allow_other_vhca_access_attr *attr)
894 {
895 	u32 out[MLX5_ST_SZ_DW(allow_other_vhca_access_out)] = {0};
896 	u32 in[MLX5_ST_SZ_DW(allow_other_vhca_access_in)] = {0};
897 	void *key;
898 	int ret;
899 
900 	MLX5_SET(allow_other_vhca_access_in,
901 		 in, opcode, MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS);
902 	MLX5_SET(allow_other_vhca_access_in,
903 		 in, object_type_to_be_accessed, attr->obj_type);
904 	MLX5_SET(allow_other_vhca_access_in,
905 		 in, object_id_to_be_accessed, attr->obj_id);
906 
907 	key = MLX5_ADDR_OF(allow_other_vhca_access_in, in, access_key);
908 	memcpy(key, attr->access_key, sizeof(attr->access_key));
909 
910 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
911 	if (ret)
912 		mlx5_core_err(mdev, "Failed to execute ALLOW_OTHER_VHCA_ACCESS command\n");
913 
914 	return ret;
915 }
916 
mlx5hws_cmd_alias_obj_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_alias_obj_create_attr * alias_attr,u32 * obj_id)917 int mlx5hws_cmd_alias_obj_create(struct mlx5_core_dev *mdev,
918 				 struct mlx5hws_cmd_alias_obj_create_attr *alias_attr,
919 				 u32 *obj_id)
920 {
921 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
922 	u32 in[MLX5_ST_SZ_DW(create_alias_obj_in)] = {0};
923 	void *attr;
924 	void *key;
925 	int ret;
926 
927 	attr = MLX5_ADDR_OF(create_alias_obj_in, in, hdr);
928 	MLX5_SET(general_obj_in_cmd_hdr,
929 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
930 	MLX5_SET(general_obj_in_cmd_hdr,
931 		 attr, obj_type, alias_attr->obj_type);
932 	MLX5_SET(general_obj_in_cmd_hdr, attr, op_param.create.alias_object, 1);
933 
934 	attr = MLX5_ADDR_OF(create_alias_obj_in, in, alias_ctx);
935 	MLX5_SET(alias_context, attr, vhca_id_to_be_accessed, alias_attr->vhca_id);
936 	MLX5_SET(alias_context, attr, object_id_to_be_accessed, alias_attr->obj_id);
937 
938 	key = MLX5_ADDR_OF(alias_context, attr, access_key);
939 	memcpy(key, alias_attr->access_key, sizeof(alias_attr->access_key));
940 
941 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
942 	if (ret) {
943 		mlx5_core_err(mdev, "Failed to create ALIAS OBJ\n");
944 		goto out;
945 	}
946 
947 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
948 out:
949 	return ret;
950 }
951 
mlx5hws_cmd_alias_obj_destroy(struct mlx5_core_dev * mdev,u16 obj_type,u32 obj_id)952 int mlx5hws_cmd_alias_obj_destroy(struct mlx5_core_dev *mdev,
953 				  u16 obj_type,
954 				  u32 obj_id)
955 {
956 	return hws_cmd_general_obj_destroy(mdev, obj_type, obj_id);
957 }
958 
mlx5hws_cmd_generate_wqe(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_generate_wqe_attr * attr,struct mlx5_cqe64 * ret_cqe)959 int mlx5hws_cmd_generate_wqe(struct mlx5_core_dev *mdev,
960 			     struct mlx5hws_cmd_generate_wqe_attr *attr,
961 			     struct mlx5_cqe64 *ret_cqe)
962 {
963 	u32 out[MLX5_ST_SZ_DW(generate_wqe_out)] = {0};
964 	u32 in[MLX5_ST_SZ_DW(generate_wqe_in)] = {0};
965 	u8 status;
966 	void *ptr;
967 	int ret;
968 
969 	MLX5_SET(generate_wqe_in, in, opcode, MLX5_CMD_OP_GENERATE_WQE);
970 	MLX5_SET(generate_wqe_in, in, pdn, attr->pdn);
971 
972 	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_ctrl);
973 	memcpy(ptr, attr->wqe_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_ctrl));
974 
975 	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_ctrl);
976 	memcpy(ptr, attr->gta_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_ctrl));
977 
978 	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_0);
979 	memcpy(ptr, attr->gta_data_0, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_0));
980 
981 	if (attr->gta_data_1) {
982 		ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_1);
983 		memcpy(ptr, attr->gta_data_1, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_1));
984 	}
985 
986 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
987 	if (ret) {
988 		mlx5_core_err(mdev, "Failed to write GTA WQE using FW\n");
989 		return ret;
990 	}
991 
992 	status = MLX5_GET(generate_wqe_out, out, status);
993 	if (status) {
994 		mlx5_core_err(mdev, "Invalid FW CQE status %d\n", status);
995 		return -EINVAL;
996 	}
997 
998 	ptr = MLX5_ADDR_OF(generate_wqe_out, out, cqe_data);
999 	memcpy(ret_cqe, ptr, sizeof(*ret_cqe));
1000 
1001 	return ret;
1002 }
1003 
mlx5hws_cmd_query_caps(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_query_caps * caps)1004 int mlx5hws_cmd_query_caps(struct mlx5_core_dev *mdev,
1005 			   struct mlx5hws_cmd_query_caps *caps)
1006 {
1007 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0};
1008 	u32 out_size;
1009 	u32 *out;
1010 	int ret;
1011 
1012 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
1013 	out = kzalloc(out_size, GFP_KERNEL);
1014 	if (!out)
1015 		return -ENOMEM;
1016 
1017 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
1018 	MLX5_SET(query_hca_cap_in, in, op_mod,
1019 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE | HCA_CAP_OPMOD_GET_CUR);
1020 
1021 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1022 	if (ret) {
1023 		mlx5_core_err(mdev, "Failed to query device caps\n");
1024 		goto out;
1025 	}
1026 
1027 	caps->wqe_based_update =
1028 		MLX5_GET(query_hca_cap_out, out,
1029 			 capability.cmd_hca_cap.wqe_based_flow_table_update_cap);
1030 
1031 	caps->eswitch_manager = MLX5_GET(query_hca_cap_out, out,
1032 					 capability.cmd_hca_cap.eswitch_manager);
1033 
1034 	caps->flex_protocols = MLX5_GET(query_hca_cap_out, out,
1035 					capability.cmd_hca_cap.flex_parser_protocols);
1036 
1037 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
1038 		caps->flex_parser_id_geneve_tlv_option_0 =
1039 			MLX5_GET(query_hca_cap_out, out,
1040 				 capability.cmd_hca_cap.flex_parser_id_geneve_tlv_option_0);
1041 
1042 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)
1043 		caps->flex_parser_id_mpls_over_gre =
1044 			MLX5_GET(query_hca_cap_out, out,
1045 				 capability.cmd_hca_cap.flex_parser_id_outer_first_mpls_over_gre);
1046 
1047 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)
1048 		caps->flex_parser_id_mpls_over_udp =
1049 			MLX5_GET(query_hca_cap_out, out,
1050 				 capability.cmd_hca_cap.flex_parser_id_outer_first_mpls_over_udp_label);
1051 
1052 	caps->log_header_modify_argument_granularity =
1053 		MLX5_GET(query_hca_cap_out, out,
1054 			 capability.cmd_hca_cap.log_header_modify_argument_granularity);
1055 
1056 	caps->log_header_modify_argument_granularity -=
1057 		MLX5_GET(query_hca_cap_out, out,
1058 			 capability.cmd_hca_cap.log_header_modify_argument_granularity_offset);
1059 
1060 	caps->log_header_modify_argument_max_alloc =
1061 		MLX5_GET(query_hca_cap_out, out,
1062 			 capability.cmd_hca_cap.log_header_modify_argument_max_alloc);
1063 
1064 	caps->definer_format_sup =
1065 		MLX5_GET64(query_hca_cap_out, out,
1066 			   capability.cmd_hca_cap.match_definer_format_supported);
1067 
1068 	caps->vhca_id = MLX5_GET(query_hca_cap_out, out,
1069 				 capability.cmd_hca_cap.vhca_id);
1070 
1071 	caps->sq_ts_format = MLX5_GET(query_hca_cap_out, out,
1072 				      capability.cmd_hca_cap.sq_ts_format);
1073 
1074 	caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out,
1075 				       capability.cmd_hca_cap.ipsec_offload);
1076 
1077 	MLX5_SET(query_hca_cap_in, in, op_mod,
1078 		 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 | HCA_CAP_OPMOD_GET_CUR);
1079 
1080 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1081 	if (ret) {
1082 		mlx5_core_err(mdev, "Failed to query device caps 2\n");
1083 		goto out;
1084 	}
1085 
1086 	caps->full_dw_jumbo_support =
1087 		MLX5_GET(query_hca_cap_out, out,
1088 			 capability.cmd_hca_cap_2.format_select_dw_8_6_ext);
1089 
1090 	caps->format_select_gtpu_dw_0 =
1091 		MLX5_GET(query_hca_cap_out, out,
1092 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_0);
1093 
1094 	caps->format_select_gtpu_dw_1 =
1095 		MLX5_GET(query_hca_cap_out, out,
1096 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_1);
1097 
1098 	caps->format_select_gtpu_dw_2 =
1099 		MLX5_GET(query_hca_cap_out, out,
1100 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_2);
1101 
1102 	caps->format_select_gtpu_ext_dw_0 =
1103 		MLX5_GET(query_hca_cap_out, out,
1104 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_first_ext_dw_0);
1105 
1106 	caps->supp_type_gen_wqe =
1107 		MLX5_GET(query_hca_cap_out, out,
1108 			 capability.cmd_hca_cap_2.generate_wqe_type);
1109 
1110 	caps->flow_table_hash_type =
1111 		MLX5_GET(query_hca_cap_out, out,
1112 			 capability.cmd_hca_cap_2.flow_table_hash_type);
1113 
1114 	MLX5_SET(query_hca_cap_in, in, op_mod,
1115 		 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1116 
1117 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1118 	if (ret) {
1119 		mlx5_core_err(mdev, "Failed to query flow table caps\n");
1120 		goto out;
1121 	}
1122 
1123 	caps->nic_ft.max_level =
1124 		MLX5_GET(query_hca_cap_out, out,
1125 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.max_ft_level);
1126 
1127 	caps->nic_ft.reparse =
1128 		MLX5_GET(query_hca_cap_out, out,
1129 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.reparse);
1130 
1131 	caps->nic_ft.ignore_flow_level_rtc_valid =
1132 		MLX5_GET(query_hca_cap_out, out,
1133 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.ignore_flow_level_rtc_valid);
1134 
1135 	caps->flex_parser_ok_bits_supp =
1136 		MLX5_GET(query_hca_cap_out, out,
1137 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.ft_field_support.geneve_tlv_option_0_exist);
1138 
1139 	if (caps->wqe_based_update) {
1140 		MLX5_SET(query_hca_cap_in, in, op_mod,
1141 			 MLX5_GET_HCA_CAP_OP_MOD_WQE_BASED_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1142 
1143 		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1144 		if (ret) {
1145 			mlx5_core_err(mdev, "Failed to query WQE based FT caps\n");
1146 			goto out;
1147 		}
1148 
1149 		caps->rtc_reparse_mode =
1150 			MLX5_GET(query_hca_cap_out, out,
1151 				 capability.wqe_based_flow_table_cap.rtc_reparse_mode);
1152 
1153 		caps->ste_format =
1154 			MLX5_GET(query_hca_cap_out, out,
1155 				 capability.wqe_based_flow_table_cap.ste_format);
1156 
1157 		caps->rtc_index_mode =
1158 			MLX5_GET(query_hca_cap_out, out,
1159 				 capability.wqe_based_flow_table_cap.rtc_index_mode);
1160 
1161 		caps->rtc_log_depth_max =
1162 			MLX5_GET(query_hca_cap_out, out,
1163 				 capability.wqe_based_flow_table_cap.rtc_log_depth_max);
1164 
1165 		caps->ste_alloc_log_max =
1166 			MLX5_GET(query_hca_cap_out, out,
1167 				 capability.wqe_based_flow_table_cap.ste_alloc_log_max);
1168 
1169 		caps->ste_alloc_log_gran =
1170 			MLX5_GET(query_hca_cap_out, out,
1171 				 capability.wqe_based_flow_table_cap.ste_alloc_log_granularity);
1172 
1173 		caps->trivial_match_definer =
1174 			MLX5_GET(query_hca_cap_out, out,
1175 				 capability.wqe_based_flow_table_cap.trivial_match_definer);
1176 
1177 		caps->stc_alloc_log_max =
1178 			MLX5_GET(query_hca_cap_out, out,
1179 				 capability.wqe_based_flow_table_cap.stc_alloc_log_max);
1180 
1181 		caps->stc_alloc_log_gran =
1182 			MLX5_GET(query_hca_cap_out, out,
1183 				 capability.wqe_based_flow_table_cap.stc_alloc_log_granularity);
1184 
1185 		caps->rtc_hash_split_table =
1186 			MLX5_GET(query_hca_cap_out, out,
1187 				 capability.wqe_based_flow_table_cap.rtc_hash_split_table);
1188 
1189 		caps->rtc_linear_lookup_table =
1190 			MLX5_GET(query_hca_cap_out, out,
1191 				 capability.wqe_based_flow_table_cap.rtc_linear_lookup_table);
1192 
1193 		caps->access_index_mode =
1194 			MLX5_GET(query_hca_cap_out, out,
1195 				 capability.wqe_based_flow_table_cap.access_index_mode);
1196 
1197 		caps->linear_match_definer =
1198 			MLX5_GET(query_hca_cap_out, out,
1199 				 capability.wqe_based_flow_table_cap.linear_match_definer_reg_c3);
1200 
1201 		caps->rtc_max_hash_def_gen_wqe =
1202 			MLX5_GET(query_hca_cap_out, out,
1203 				 capability.wqe_based_flow_table_cap.rtc_max_num_hash_definer_gen_wqe);
1204 
1205 		caps->supp_ste_format_gen_wqe =
1206 			MLX5_GET(query_hca_cap_out, out,
1207 				 capability.wqe_based_flow_table_cap.ste_format_gen_wqe);
1208 
1209 		caps->fdb_tir_stc =
1210 			MLX5_GET(query_hca_cap_out, out,
1211 				 capability.wqe_based_flow_table_cap.fdb_jump_to_tir_stc);
1212 	}
1213 
1214 	if (caps->eswitch_manager) {
1215 		MLX5_SET(query_hca_cap_in, in, op_mod,
1216 			 MLX5_GET_HCA_CAP_OP_MOD_ESW_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1217 
1218 		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1219 		if (ret) {
1220 			mlx5_core_err(mdev, "Failed to query flow table esw caps\n");
1221 			goto out;
1222 		}
1223 
1224 		caps->fdb_ft.max_level =
1225 			MLX5_GET(query_hca_cap_out, out,
1226 				 capability.flow_table_nic_cap.flow_table_properties_nic_receive.max_ft_level);
1227 
1228 		caps->fdb_ft.reparse =
1229 			MLX5_GET(query_hca_cap_out, out,
1230 				 capability.flow_table_nic_cap.flow_table_properties_nic_receive.reparse);
1231 
1232 		MLX5_SET(query_hca_cap_in, in, op_mod,
1233 			 MLX5_SET_HCA_CAP_OP_MOD_ESW | HCA_CAP_OPMOD_GET_CUR);
1234 
1235 		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1236 		if (ret) {
1237 			mlx5_core_err(mdev, "Failed to query eswitch capabilities\n");
1238 			goto out;
1239 		}
1240 
1241 		if (MLX5_GET(query_hca_cap_out, out,
1242 			     capability.esw_cap.esw_manager_vport_number_valid))
1243 			caps->eswitch_manager_vport_number =
1244 				MLX5_GET(query_hca_cap_out, out,
1245 					 capability.esw_cap.esw_manager_vport_number);
1246 
1247 		caps->merged_eswitch = MLX5_GET(query_hca_cap_out, out,
1248 						capability.esw_cap.merged_eswitch);
1249 	}
1250 
1251 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1252 	if (ret) {
1253 		mlx5_core_err(mdev, "Failed to query device attributes\n");
1254 		goto out;
1255 	}
1256 
1257 	snprintf(caps->fw_ver, sizeof(caps->fw_ver), "%d.%d.%d",
1258 		 fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev));
1259 
1260 	caps->is_ecpf = mlx5_core_is_ecpf_esw_manager(mdev);
1261 
1262 out:
1263 	kfree(out);
1264 	return ret;
1265 }
1266 
mlx5hws_cmd_query_gvmi(struct mlx5_core_dev * mdev,bool other_function,u16 vport_number,u16 * gvmi)1267 int mlx5hws_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_function,
1268 			   u16 vport_number, u16 *gvmi)
1269 {
1270 	bool ec_vf_func = other_function ? mlx5_core_is_ec_vf_vport(mdev, vport_number) : false;
1271 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
1272 	int out_size;
1273 	void *out;
1274 	int err;
1275 
1276 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
1277 	out = kzalloc(out_size, GFP_KERNEL);
1278 	if (!out)
1279 		return -ENOMEM;
1280 
1281 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
1282 	MLX5_SET(query_hca_cap_in, in, other_function, other_function);
1283 	MLX5_SET(query_hca_cap_in, in, function_id,
1284 		 mlx5_vport_to_func_id(mdev, vport_number, ec_vf_func));
1285 	MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
1286 	MLX5_SET(query_hca_cap_in, in, op_mod,
1287 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 | HCA_CAP_OPMOD_GET_CUR);
1288 
1289 	err = mlx5_cmd_exec_inout(mdev, query_hca_cap, in, out);
1290 	if (err) {
1291 		kfree(out);
1292 		return err;
1293 	}
1294 
1295 	*gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id);
1296 
1297 	kfree(out);
1298 
1299 	return 0;
1300 }
1301