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