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