xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c (revision 43a2038c6d8a810e8e70f0e7fcb965f431c92bfb)
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 
hws_cmd_flow_group_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_fg_attr * fg_attr,u32 * group_id)133 static int hws_cmd_flow_group_create(struct mlx5_core_dev *mdev,
134 				     struct mlx5hws_cmd_fg_attr *fg_attr,
135 				     u32 *group_id)
136 {
137 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
138 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
139 	u32 *in;
140 	int ret;
141 
142 	in = kvzalloc(inlen, GFP_KERNEL);
143 	if (!in)
144 		return -ENOMEM;
145 
146 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
147 	MLX5_SET(create_flow_group_in, in, table_type, fg_attr->table_type);
148 	MLX5_SET(create_flow_group_in, in, table_id, fg_attr->table_id);
149 
150 	ret = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
151 	if (ret)
152 		goto out;
153 
154 	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
155 
156 out:
157 	kvfree(in);
158 	return ret;
159 }
160 
hws_cmd_flow_group_destroy(struct mlx5_core_dev * mdev,u32 ft_id,u32 fg_id,u8 ft_type)161 static int hws_cmd_flow_group_destroy(struct mlx5_core_dev *mdev,
162 				      u32 ft_id, u32 fg_id, u8 ft_type)
163 {
164 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
165 
166 	MLX5_SET(destroy_flow_group_in, in, opcode, MLX5_CMD_OP_DESTROY_FLOW_GROUP);
167 	MLX5_SET(destroy_flow_group_in, in, table_type, ft_type);
168 	MLX5_SET(destroy_flow_group_in, in, table_id, ft_id);
169 	MLX5_SET(destroy_flow_group_in, in, group_id, fg_id);
170 
171 	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
172 }
173 
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)174 int mlx5hws_cmd_set_fte(struct mlx5_core_dev *mdev,
175 			u32 table_type,
176 			u32 table_id,
177 			u32 group_id,
178 			struct mlx5hws_cmd_set_fte_attr *fte_attr)
179 {
180 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
181 	void *in_flow_context;
182 	u32 dest_entry_sz;
183 	u32 total_dest_sz;
184 	u32 action_flags;
185 	u8 *in_dests;
186 	u32 inlen;
187 	u32 *in;
188 	int ret;
189 	u32 i;
190 
191 	dest_entry_sz = fte_attr->extended_dest ?
192 			MLX5_ST_SZ_BYTES(extended_dest_format) :
193 			MLX5_ST_SZ_BYTES(dest_format);
194 	total_dest_sz = dest_entry_sz * fte_attr->dests_num;
195 	inlen = align((MLX5_ST_SZ_BYTES(set_fte_in) + total_dest_sz), DW_SIZE);
196 	in = kzalloc(inlen, GFP_KERNEL);
197 	if (!in)
198 		return -ENOMEM;
199 
200 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
201 	MLX5_SET(set_fte_in, in, table_type, table_type);
202 	MLX5_SET(set_fte_in, in, table_id, table_id);
203 
204 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
205 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
206 	MLX5_SET(flow_context, in_flow_context, flow_source, fte_attr->flow_source);
207 	MLX5_SET(flow_context, in_flow_context, extended_destination, fte_attr->extended_dest);
208 	MLX5_SET(set_fte_in, in, ignore_flow_level, fte_attr->ignore_flow_level);
209 
210 	action_flags = fte_attr->action_flags;
211 	MLX5_SET(flow_context, in_flow_context, action, action_flags);
212 
213 	if (action_flags & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
214 		MLX5_SET(flow_context, in_flow_context,
215 			 packet_reformat_id, fte_attr->packet_reformat_id);
216 	}
217 
218 	if (action_flags & (MLX5_FLOW_CONTEXT_ACTION_DECRYPT | MLX5_FLOW_CONTEXT_ACTION_ENCRYPT)) {
219 		MLX5_SET(flow_context, in_flow_context,
220 			 encrypt_decrypt_type, fte_attr->encrypt_decrypt_type);
221 		MLX5_SET(flow_context, in_flow_context,
222 			 encrypt_decrypt_obj_id, fte_attr->encrypt_decrypt_obj_id);
223 	}
224 
225 	if (action_flags & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
226 		in_dests = (u8 *)MLX5_ADDR_OF(flow_context, in_flow_context, destination);
227 
228 		for (i = 0; i < fte_attr->dests_num; i++) {
229 			struct mlx5hws_cmd_set_fte_dest *dest = &fte_attr->dests[i];
230 			enum mlx5_ifc_flow_destination_type ifc_dest_type =
231 				hws_cmd_dest_type_to_ifc_dest_type(dest->destination_type);
232 
233 			switch (dest->destination_type) {
234 			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
235 				if (dest->ext_flags & MLX5HWS_CMD_EXT_DEST_ESW_OWNER_VHCA_ID) {
236 					MLX5_SET(dest_format, in_dests,
237 						 destination_eswitch_owner_vhca_id_valid, 1);
238 					MLX5_SET(dest_format, in_dests,
239 						 destination_eswitch_owner_vhca_id,
240 						 dest->esw_owner_vhca_id);
241 				}
242 				fallthrough;
243 			case MLX5_FLOW_DESTINATION_TYPE_TIR:
244 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
245 				MLX5_SET(dest_format, in_dests, destination_type, ifc_dest_type);
246 				MLX5_SET(dest_format, in_dests, destination_id,
247 					 dest->destination_id);
248 				if (dest->ext_flags & MLX5HWS_CMD_EXT_DEST_REFORMAT) {
249 					MLX5_SET(dest_format, in_dests, packet_reformat, 1);
250 					MLX5_SET(extended_dest_format, in_dests, packet_reformat_id,
251 						 dest->ext_reformat_id);
252 				}
253 				break;
254 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
255 				MLX5_SET(dest_format, in_dests,
256 					 destination_type, ifc_dest_type);
257 				MLX5_SET(dest_format, in_dests, destination_id,
258 					 dest->destination_id);
259 				break;
260 			default:
261 				ret = -EOPNOTSUPP;
262 				goto out;
263 			}
264 
265 			in_dests = in_dests + dest_entry_sz;
266 		}
267 		MLX5_SET(flow_context, in_flow_context, destination_list_size, fte_attr->dests_num);
268 	}
269 
270 	ret = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
271 	if (ret)
272 		mlx5_core_err(mdev, "Failed creating FLOW_TABLE_ENTRY\n");
273 
274 out:
275 	kfree(in);
276 	return ret;
277 }
278 
mlx5hws_cmd_delete_fte(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id)279 int mlx5hws_cmd_delete_fte(struct mlx5_core_dev *mdev,
280 			   u32 table_type,
281 			   u32 table_id)
282 {
283 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
284 
285 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
286 	MLX5_SET(delete_fte_in, in, table_type, table_type);
287 	MLX5_SET(delete_fte_in, in, table_id, table_id);
288 
289 	return mlx5_cmd_exec_in(mdev, delete_fte, in);
290 }
291 
292 struct mlx5hws_cmd_forward_tbl *
mlx5hws_cmd_forward_tbl_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_ft_create_attr * ft_attr,struct mlx5hws_cmd_set_fte_attr * fte_attr)293 mlx5hws_cmd_forward_tbl_create(struct mlx5_core_dev *mdev,
294 			       struct mlx5hws_cmd_ft_create_attr *ft_attr,
295 			       struct mlx5hws_cmd_set_fte_attr *fte_attr)
296 {
297 	struct mlx5hws_cmd_fg_attr fg_attr = {0};
298 	struct mlx5hws_cmd_forward_tbl *tbl;
299 	int ret;
300 
301 	tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
302 	if (!tbl)
303 		return NULL;
304 
305 	ret = mlx5hws_cmd_flow_table_create(mdev, ft_attr, &tbl->ft_id);
306 	if (ret) {
307 		mlx5_core_err(mdev, "Failed to create FT\n");
308 		goto free_tbl;
309 	}
310 
311 	fg_attr.table_id = tbl->ft_id;
312 	fg_attr.table_type = ft_attr->type;
313 
314 	ret = hws_cmd_flow_group_create(mdev, &fg_attr, &tbl->fg_id);
315 	if (ret) {
316 		mlx5_core_err(mdev, "Failed to create FG\n");
317 		goto free_ft;
318 	}
319 
320 	ret = mlx5hws_cmd_set_fte(mdev, ft_attr->type,
321 				  tbl->ft_id, tbl->fg_id, fte_attr);
322 	if (ret) {
323 		mlx5_core_err(mdev, "Failed to create FTE\n");
324 		goto free_fg;
325 	}
326 
327 	tbl->type = ft_attr->type;
328 	return tbl;
329 
330 free_fg:
331 	hws_cmd_flow_group_destroy(mdev, tbl->ft_id, tbl->fg_id, ft_attr->type);
332 free_ft:
333 	mlx5hws_cmd_flow_table_destroy(mdev, ft_attr->type, tbl->ft_id);
334 free_tbl:
335 	kfree(tbl);
336 	return NULL;
337 }
338 
mlx5hws_cmd_forward_tbl_destroy(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_forward_tbl * tbl)339 void mlx5hws_cmd_forward_tbl_destroy(struct mlx5_core_dev *mdev,
340 				     struct mlx5hws_cmd_forward_tbl *tbl)
341 {
342 	mlx5hws_cmd_delete_fte(mdev, tbl->type, tbl->ft_id);
343 	hws_cmd_flow_group_destroy(mdev, tbl->ft_id, tbl->fg_id, tbl->type);
344 	mlx5hws_cmd_flow_table_destroy(mdev, tbl->type, tbl->ft_id);
345 	kfree(tbl);
346 }
347 
mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context * ctx,u32 fw_ft_type,enum mlx5hws_table_type type,struct mlx5hws_cmd_ft_modify_attr * ft_attr)348 void mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context *ctx,
349 					   u32 fw_ft_type,
350 					   enum mlx5hws_table_type type,
351 					   struct mlx5hws_cmd_ft_modify_attr *ft_attr)
352 {
353 	u32 default_miss_tbl;
354 
355 	if (type != MLX5HWS_TABLE_TYPE_FDB)
356 		return;
357 
358 	ft_attr->modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
359 	ft_attr->type = fw_ft_type;
360 	ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
361 
362 	default_miss_tbl = ctx->common_res.default_miss->ft_id;
363 	if (!default_miss_tbl) {
364 		pr_warn("HWS: no flow table ID for default miss\n");
365 		return;
366 	}
367 
368 	ft_attr->table_miss_id = default_miss_tbl;
369 }
370 
mlx5hws_cmd_rtc_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_rtc_create_attr * rtc_attr,u32 * rtc_id)371 int mlx5hws_cmd_rtc_create(struct mlx5_core_dev *mdev,
372 			   struct mlx5hws_cmd_rtc_create_attr *rtc_attr,
373 			   u32 *rtc_id)
374 {
375 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
376 	u32 in[MLX5_ST_SZ_DW(create_rtc_in)] = {0};
377 	void *attr;
378 	int ret;
379 
380 	attr = MLX5_ADDR_OF(create_rtc_in, in, hdr);
381 	MLX5_SET(general_obj_in_cmd_hdr,
382 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
383 	MLX5_SET(general_obj_in_cmd_hdr,
384 		 attr, obj_type, MLX5_OBJ_TYPE_RTC);
385 
386 	attr = MLX5_ADDR_OF(create_rtc_in, in, rtc);
387 	MLX5_SET(rtc, attr, ste_format_0, rtc_attr->is_frst_jumbo ?
388 		 MLX5_IFC_RTC_STE_FORMAT_11DW :
389 		 MLX5_IFC_RTC_STE_FORMAT_8DW);
390 
391 	if (rtc_attr->is_scnd_range) {
392 		MLX5_SET(rtc, attr, ste_format_1, MLX5_IFC_RTC_STE_FORMAT_RANGE);
393 		MLX5_SET(rtc, attr, num_match_ste, 2);
394 	}
395 
396 	MLX5_SET(rtc, attr, pd, rtc_attr->pd);
397 	MLX5_SET(rtc, attr, update_method, rtc_attr->fw_gen_wqe);
398 	MLX5_SET(rtc, attr, update_index_mode, rtc_attr->update_index_mode);
399 	MLX5_SET(rtc, attr, access_index_mode, rtc_attr->access_index_mode);
400 	MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer);
401 	MLX5_SET(rtc, attr, log_depth, rtc_attr->log_depth);
402 	MLX5_SET(rtc, attr, log_hash_size, rtc_attr->log_size);
403 	MLX5_SET(rtc, attr, table_type, rtc_attr->table_type);
404 	MLX5_SET(rtc, attr, num_hash_definer, rtc_attr->num_hash_definer);
405 	MLX5_SET(rtc, attr, match_definer_0, rtc_attr->match_definer_0);
406 	MLX5_SET(rtc, attr, match_definer_1, rtc_attr->match_definer_1);
407 	MLX5_SET(rtc, attr, stc_id, rtc_attr->stc_base);
408 	MLX5_SET(rtc, attr, ste_table_base_id, rtc_attr->ste_base);
409 	MLX5_SET(rtc, attr, 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, "Failed to modify STC FW action_type %d\n",
614 			      stc_attr->action_type);
615 
616 	return ret;
617 }
618 
mlx5hws_cmd_arg_create(struct mlx5_core_dev * mdev,u16 log_obj_range,u32 pd,u32 * arg_id)619 int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
620 			   u16 log_obj_range,
621 			   u32 pd,
622 			   u32 *arg_id)
623 {
624 	u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {0};
625 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
626 	void *attr;
627 	int ret;
628 
629 	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
630 	MLX5_SET(general_obj_in_cmd_hdr,
631 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
632 	MLX5_SET(general_obj_in_cmd_hdr,
633 		 attr, obj_type, MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
634 	MLX5_SET(general_obj_in_cmd_hdr,
635 		 attr, op_param.create.log_obj_range, log_obj_range);
636 
637 	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
638 	MLX5_SET(modify_header_arg, attr, access_pd, pd);
639 
640 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
641 	if (ret) {
642 		mlx5_core_err(mdev, "Failed to create ARG\n");
643 		goto out;
644 	}
645 
646 	*arg_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
647 out:
648 	return ret;
649 }
650 
mlx5hws_cmd_arg_destroy(struct mlx5_core_dev * mdev,u32 arg_id)651 void mlx5hws_cmd_arg_destroy(struct mlx5_core_dev *mdev,
652 			     u32 arg_id)
653 {
654 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT, arg_id);
655 }
656 
mlx5hws_cmd_header_modify_pattern_create(struct mlx5_core_dev * mdev,u32 pattern_length,u8 * actions,u32 * ptrn_id)657 int mlx5hws_cmd_header_modify_pattern_create(struct mlx5_core_dev *mdev,
658 					     u32 pattern_length,
659 					     u8 *actions,
660 					     u32 *ptrn_id)
661 {
662 	u32 in[MLX5_ST_SZ_DW(create_header_modify_pattern_in)] = {0};
663 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
664 	int num_of_actions;
665 	u64 *pattern_data;
666 	void *pattern;
667 	void *attr;
668 	int ret;
669 	int i;
670 
671 	if (pattern_length > MLX5_MAX_ACTIONS_DATA_IN_HEADER_MODIFY) {
672 		mlx5_core_err(mdev, "Pattern length %d exceeds limit %d\n",
673 			      pattern_length, MLX5_MAX_ACTIONS_DATA_IN_HEADER_MODIFY);
674 		return -EINVAL;
675 	}
676 
677 	attr = MLX5_ADDR_OF(create_header_modify_pattern_in, in, hdr);
678 	MLX5_SET(general_obj_in_cmd_hdr,
679 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
680 	MLX5_SET(general_obj_in_cmd_hdr,
681 		 attr, obj_type, MLX5_OBJ_TYPE_MODIFY_HDR_PATTERN);
682 
683 	pattern = MLX5_ADDR_OF(create_header_modify_pattern_in, in, pattern);
684 	/* Pattern_length is in ddwords */
685 	MLX5_SET(header_modify_pattern_in, pattern, pattern_length, pattern_length / (2 * DW_SIZE));
686 
687 	pattern_data = (u64 *)MLX5_ADDR_OF(header_modify_pattern_in, pattern, pattern_data);
688 	memcpy(pattern_data, actions, pattern_length);
689 
690 	num_of_actions = pattern_length / MLX5HWS_MODIFY_ACTION_SIZE;
691 	for (i = 0; i < num_of_actions; i++) {
692 		int type;
693 
694 		type = MLX5_GET(set_action_in, &pattern_data[i], action_type);
695 		if (type != MLX5_MODIFICATION_TYPE_COPY &&
696 		    type != MLX5_MODIFICATION_TYPE_ADD_FIELD)
697 			/* Action typ-copy use all bytes for control */
698 			MLX5_SET(set_action_in, &pattern_data[i], data, 0);
699 	}
700 
701 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
702 	if (ret) {
703 		mlx5_core_err(mdev, "Failed to create header_modify_pattern\n");
704 		goto out;
705 	}
706 
707 	*ptrn_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
708 out:
709 	return ret;
710 }
711 
mlx5hws_cmd_header_modify_pattern_destroy(struct mlx5_core_dev * mdev,u32 ptrn_id)712 void mlx5hws_cmd_header_modify_pattern_destroy(struct mlx5_core_dev *mdev,
713 					       u32 ptrn_id)
714 {
715 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_MODIFY_HDR_PATTERN, ptrn_id);
716 }
717 
mlx5hws_cmd_ste_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_ste_create_attr * ste_attr,u32 * ste_id)718 int mlx5hws_cmd_ste_create(struct mlx5_core_dev *mdev,
719 			   struct mlx5hws_cmd_ste_create_attr *ste_attr,
720 			   u32 *ste_id)
721 {
722 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
723 	u32 in[MLX5_ST_SZ_DW(create_ste_in)] = {0};
724 	void *attr;
725 	int ret;
726 
727 	attr = MLX5_ADDR_OF(create_ste_in, in, hdr);
728 	MLX5_SET(general_obj_in_cmd_hdr,
729 		 attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
730 	MLX5_SET(general_obj_in_cmd_hdr,
731 		 attr, obj_type, MLX5_OBJ_TYPE_STE);
732 	MLX5_SET(general_obj_in_cmd_hdr,
733 		 attr, op_param.create.log_obj_range, ste_attr->log_obj_range);
734 
735 	attr = MLX5_ADDR_OF(create_ste_in, in, ste);
736 	MLX5_SET(ste, attr, table_type, ste_attr->table_type);
737 
738 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
739 	if (ret) {
740 		mlx5_core_err(mdev, "Failed to create STE\n");
741 		goto out;
742 	}
743 
744 	*ste_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
745 out:
746 	return ret;
747 }
748 
mlx5hws_cmd_ste_destroy(struct mlx5_core_dev * mdev,u32 ste_id)749 void mlx5hws_cmd_ste_destroy(struct mlx5_core_dev *mdev, u32 ste_id)
750 {
751 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_STE, ste_id);
752 }
753 
mlx5hws_cmd_definer_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_definer_create_attr * def_attr,u32 * definer_id)754 int mlx5hws_cmd_definer_create(struct mlx5_core_dev *mdev,
755 			       struct mlx5hws_cmd_definer_create_attr *def_attr,
756 			       u32 *definer_id)
757 {
758 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
759 	u32 in[MLX5_ST_SZ_DW(create_definer_in)] = {0};
760 	void *ptr;
761 	int ret;
762 
763 	MLX5_SET(general_obj_in_cmd_hdr,
764 		 in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
765 	MLX5_SET(general_obj_in_cmd_hdr,
766 		 in, obj_type, MLX5_OBJ_TYPE_MATCH_DEFINER);
767 
768 	ptr = MLX5_ADDR_OF(create_definer_in, in, definer);
769 	MLX5_SET(definer, ptr, format_id, MLX5_IFC_DEFINER_FORMAT_ID_SELECT);
770 
771 	MLX5_SET(definer, ptr, format_select_dw0, def_attr->dw_selector[0]);
772 	MLX5_SET(definer, ptr, format_select_dw1, def_attr->dw_selector[1]);
773 	MLX5_SET(definer, ptr, format_select_dw2, def_attr->dw_selector[2]);
774 	MLX5_SET(definer, ptr, format_select_dw3, def_attr->dw_selector[3]);
775 	MLX5_SET(definer, ptr, format_select_dw4, def_attr->dw_selector[4]);
776 	MLX5_SET(definer, ptr, format_select_dw5, def_attr->dw_selector[5]);
777 	MLX5_SET(definer, ptr, format_select_dw6, def_attr->dw_selector[6]);
778 	MLX5_SET(definer, ptr, format_select_dw7, def_attr->dw_selector[7]);
779 	MLX5_SET(definer, ptr, format_select_dw8, def_attr->dw_selector[8]);
780 
781 	MLX5_SET(definer, ptr, format_select_byte0, def_attr->byte_selector[0]);
782 	MLX5_SET(definer, ptr, format_select_byte1, def_attr->byte_selector[1]);
783 	MLX5_SET(definer, ptr, format_select_byte2, def_attr->byte_selector[2]);
784 	MLX5_SET(definer, ptr, format_select_byte3, def_attr->byte_selector[3]);
785 	MLX5_SET(definer, ptr, format_select_byte4, def_attr->byte_selector[4]);
786 	MLX5_SET(definer, ptr, format_select_byte5, def_attr->byte_selector[5]);
787 	MLX5_SET(definer, ptr, format_select_byte6, def_attr->byte_selector[6]);
788 	MLX5_SET(definer, ptr, format_select_byte7, def_attr->byte_selector[7]);
789 
790 	ptr = MLX5_ADDR_OF(definer, ptr, match_mask);
791 	memcpy(ptr, def_attr->match_mask, MLX5_FLD_SZ_BYTES(definer, match_mask));
792 
793 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
794 	if (ret) {
795 		mlx5_core_err(mdev, "Failed to create Definer\n");
796 		goto out;
797 	}
798 
799 	*definer_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
800 out:
801 	return ret;
802 }
803 
mlx5hws_cmd_definer_destroy(struct mlx5_core_dev * mdev,u32 definer_id)804 void mlx5hws_cmd_definer_destroy(struct mlx5_core_dev *mdev,
805 				 u32 definer_id)
806 {
807 	hws_cmd_general_obj_destroy(mdev, MLX5_OBJ_TYPE_MATCH_DEFINER, definer_id);
808 }
809 
mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_packet_reformat_create_attr * attr,u32 * reformat_id)810 int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
811 				       struct mlx5hws_cmd_packet_reformat_create_attr *attr,
812 				       u32 *reformat_id)
813 {
814 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {0};
815 	size_t insz, cmd_data_sz, cmd_total_sz;
816 	void *prctx;
817 	void *pdata;
818 	void *in;
819 	int ret;
820 
821 	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
822 	cmd_total_sz += MLX5_ST_SZ_BYTES(packet_reformat_context_in);
823 	cmd_data_sz = MLX5_FLD_SZ_BYTES(packet_reformat_context_in, reformat_data);
824 	insz = align(cmd_total_sz + attr->data_sz - cmd_data_sz, DW_SIZE);
825 	in = kzalloc(insz, GFP_KERNEL);
826 	if (!in)
827 		return -ENOMEM;
828 
829 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
830 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
831 
832 	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in,
833 			     packet_reformat_context);
834 	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
835 
836 	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, attr->type);
837 	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, attr->reformat_param_0);
838 	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, attr->data_sz);
839 	memcpy(pdata, attr->data, attr->data_sz);
840 
841 	ret = mlx5_cmd_exec(mdev, in, insz, out, sizeof(out));
842 	if (ret) {
843 		mlx5_core_err(mdev, "Failed to create packet reformat\n");
844 		goto out;
845 	}
846 
847 	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
848 out:
849 	kfree(in);
850 	return ret;
851 }
852 
mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev * mdev,u32 reformat_id)853 int mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev *mdev,
854 					u32 reformat_id)
855 {
856 	u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_out)] = {0};
857 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {0};
858 	int ret;
859 
860 	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
861 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
862 	MLX5_SET(dealloc_packet_reformat_context_in, in,
863 		 packet_reformat_id, reformat_id);
864 
865 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
866 	if (ret)
867 		mlx5_core_err(mdev, "Failed to destroy packet_reformat\n");
868 
869 	return ret;
870 }
871 
mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev * mdev,u32 sqn)872 int mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev *mdev, u32 sqn)
873 {
874 	u32 out[MLX5_ST_SZ_DW(modify_sq_out)] = {0};
875 	u32 in[MLX5_ST_SZ_DW(modify_sq_in)] = {0};
876 	void *sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
877 	int ret;
878 
879 	MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ);
880 	MLX5_SET(modify_sq_in, in, sqn, sqn);
881 	MLX5_SET(modify_sq_in, in, sq_state, MLX5_SQC_STATE_RST);
882 	MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RDY);
883 
884 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
885 	if (ret)
886 		mlx5_core_err(mdev, "Failed to modify SQ\n");
887 
888 	return ret;
889 }
890 
mlx5hws_cmd_generate_wqe(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_generate_wqe_attr * attr,struct mlx5_cqe64 * ret_cqe)891 int mlx5hws_cmd_generate_wqe(struct mlx5_core_dev *mdev,
892 			     struct mlx5hws_cmd_generate_wqe_attr *attr,
893 			     struct mlx5_cqe64 *ret_cqe)
894 {
895 	u32 out[MLX5_ST_SZ_DW(generate_wqe_out)] = {0};
896 	u32 in[MLX5_ST_SZ_DW(generate_wqe_in)] = {0};
897 	u8 status;
898 	void *ptr;
899 	int ret;
900 
901 	MLX5_SET(generate_wqe_in, in, opcode, MLX5_CMD_OP_GENERATE_WQE);
902 	MLX5_SET(generate_wqe_in, in, pdn, attr->pdn);
903 
904 	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_ctrl);
905 	memcpy(ptr, attr->wqe_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_ctrl));
906 
907 	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_ctrl);
908 	memcpy(ptr, attr->gta_ctrl, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_ctrl));
909 
910 	ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_0);
911 	memcpy(ptr, attr->gta_data_0, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_0));
912 
913 	if (attr->gta_data_1) {
914 		ptr = MLX5_ADDR_OF(generate_wqe_in, in, wqe_gta_data_1);
915 		memcpy(ptr, attr->gta_data_1, MLX5_FLD_SZ_BYTES(generate_wqe_in, wqe_gta_data_1));
916 	}
917 
918 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
919 	if (ret) {
920 		mlx5_core_err(mdev, "Failed to write GTA WQE using FW\n");
921 		return ret;
922 	}
923 
924 	status = MLX5_GET(generate_wqe_out, out, status);
925 	if (status) {
926 		mlx5_core_err(mdev, "Invalid FW CQE status %d\n", status);
927 		return -EINVAL;
928 	}
929 
930 	ptr = MLX5_ADDR_OF(generate_wqe_out, out, cqe_data);
931 	memcpy(ret_cqe, ptr, sizeof(*ret_cqe));
932 
933 	return ret;
934 }
935 
mlx5hws_cmd_query_caps(struct mlx5_core_dev * mdev,struct mlx5hws_cmd_query_caps * caps)936 int mlx5hws_cmd_query_caps(struct mlx5_core_dev *mdev,
937 			   struct mlx5hws_cmd_query_caps *caps)
938 {
939 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {0};
940 	u32 out_size;
941 	u32 *out;
942 	int ret;
943 
944 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
945 	out = kzalloc(out_size, GFP_KERNEL);
946 	if (!out)
947 		return -ENOMEM;
948 
949 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
950 	MLX5_SET(query_hca_cap_in, in, op_mod,
951 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE | HCA_CAP_OPMOD_GET_CUR);
952 
953 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
954 	if (ret) {
955 		mlx5_core_err(mdev, "Failed to query device caps\n");
956 		goto out;
957 	}
958 
959 	caps->wqe_based_update =
960 		MLX5_GET(query_hca_cap_out, out,
961 			 capability.cmd_hca_cap.wqe_based_flow_table_update_cap);
962 
963 	caps->eswitch_manager = MLX5_GET(query_hca_cap_out, out,
964 					 capability.cmd_hca_cap.eswitch_manager);
965 
966 	caps->flex_protocols = MLX5_GET(query_hca_cap_out, out,
967 					capability.cmd_hca_cap.flex_parser_protocols);
968 
969 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
970 		caps->flex_parser_id_geneve_tlv_option_0 =
971 			MLX5_GET(query_hca_cap_out, out,
972 				 capability.cmd_hca_cap.flex_parser_id_geneve_tlv_option_0);
973 
974 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)
975 		caps->flex_parser_id_mpls_over_gre =
976 			MLX5_GET(query_hca_cap_out, out,
977 				 capability.cmd_hca_cap.flex_parser_id_outer_first_mpls_over_gre);
978 
979 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)
980 		caps->flex_parser_id_mpls_over_udp =
981 			MLX5_GET(query_hca_cap_out, out,
982 				 capability.cmd_hca_cap.flex_parser_id_outer_first_mpls_over_udp_label);
983 
984 	caps->log_header_modify_argument_granularity =
985 		MLX5_GET(query_hca_cap_out, out,
986 			 capability.cmd_hca_cap.log_header_modify_argument_granularity);
987 
988 	caps->log_header_modify_argument_granularity -=
989 		MLX5_GET(query_hca_cap_out, out,
990 			 capability.cmd_hca_cap.log_header_modify_argument_granularity_offset);
991 
992 	caps->log_header_modify_argument_max_alloc =
993 		MLX5_GET(query_hca_cap_out, out,
994 			 capability.cmd_hca_cap.log_header_modify_argument_max_alloc);
995 
996 	caps->definer_format_sup =
997 		MLX5_GET64(query_hca_cap_out, out,
998 			   capability.cmd_hca_cap.match_definer_format_supported);
999 
1000 	caps->vhca_id = MLX5_GET(query_hca_cap_out, out,
1001 				 capability.cmd_hca_cap.vhca_id);
1002 
1003 	caps->sq_ts_format = MLX5_GET(query_hca_cap_out, out,
1004 				      capability.cmd_hca_cap.sq_ts_format);
1005 
1006 	caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out,
1007 				       capability.cmd_hca_cap.ipsec_offload);
1008 
1009 	MLX5_SET(query_hca_cap_in, in, op_mod,
1010 		 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 | HCA_CAP_OPMOD_GET_CUR);
1011 
1012 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1013 	if (ret) {
1014 		mlx5_core_err(mdev, "Failed to query device caps 2\n");
1015 		goto out;
1016 	}
1017 
1018 	caps->full_dw_jumbo_support =
1019 		MLX5_GET(query_hca_cap_out, out,
1020 			 capability.cmd_hca_cap_2.format_select_dw_8_6_ext);
1021 
1022 	caps->format_select_gtpu_dw_0 =
1023 		MLX5_GET(query_hca_cap_out, out,
1024 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_0);
1025 
1026 	caps->format_select_gtpu_dw_1 =
1027 		MLX5_GET(query_hca_cap_out, out,
1028 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_1);
1029 
1030 	caps->format_select_gtpu_dw_2 =
1031 		MLX5_GET(query_hca_cap_out, out,
1032 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_dw_2);
1033 
1034 	caps->format_select_gtpu_ext_dw_0 =
1035 		MLX5_GET(query_hca_cap_out, out,
1036 			 capability.cmd_hca_cap_2.format_select_dw_gtpu_first_ext_dw_0);
1037 
1038 	caps->supp_type_gen_wqe =
1039 		MLX5_GET(query_hca_cap_out, out,
1040 			 capability.cmd_hca_cap_2.generate_wqe_type);
1041 
1042 	caps->flow_table_hash_type =
1043 		MLX5_GET(query_hca_cap_out, out,
1044 			 capability.cmd_hca_cap_2.flow_table_hash_type);
1045 
1046 	MLX5_SET(query_hca_cap_in, in, op_mod,
1047 		 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1048 
1049 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1050 	if (ret) {
1051 		mlx5_core_err(mdev, "Failed to query flow table caps\n");
1052 		goto out;
1053 	}
1054 
1055 	caps->nic_ft.max_level =
1056 		MLX5_GET(query_hca_cap_out, out,
1057 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.max_ft_level);
1058 
1059 	caps->nic_ft.reparse =
1060 		MLX5_GET(query_hca_cap_out, out,
1061 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.reparse);
1062 
1063 	caps->nic_ft.ignore_flow_level_rtc_valid =
1064 		MLX5_GET(query_hca_cap_out, out,
1065 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.ignore_flow_level_rtc_valid);
1066 
1067 	caps->flex_parser_ok_bits_supp =
1068 		MLX5_GET(query_hca_cap_out, out,
1069 			 capability.flow_table_nic_cap.flow_table_properties_nic_receive.ft_field_support.geneve_tlv_option_0_exist);
1070 
1071 	if (caps->wqe_based_update) {
1072 		MLX5_SET(query_hca_cap_in, in, op_mod,
1073 			 MLX5_GET_HCA_CAP_OP_MOD_WQE_BASED_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1074 
1075 		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1076 		if (ret) {
1077 			mlx5_core_err(mdev, "Failed to query WQE based FT caps\n");
1078 			goto out;
1079 		}
1080 
1081 		caps->rtc_reparse_mode =
1082 			MLX5_GET(query_hca_cap_out, out,
1083 				 capability.wqe_based_flow_table_cap.rtc_reparse_mode);
1084 
1085 		caps->ste_format =
1086 			MLX5_GET(query_hca_cap_out, out,
1087 				 capability.wqe_based_flow_table_cap.ste_format);
1088 
1089 		caps->rtc_index_mode =
1090 			MLX5_GET(query_hca_cap_out, out,
1091 				 capability.wqe_based_flow_table_cap.rtc_index_mode);
1092 
1093 		caps->rtc_log_depth_max =
1094 			MLX5_GET(query_hca_cap_out, out,
1095 				 capability.wqe_based_flow_table_cap.rtc_log_depth_max);
1096 
1097 		caps->ste_alloc_log_max =
1098 			MLX5_GET(query_hca_cap_out, out,
1099 				 capability.wqe_based_flow_table_cap.ste_alloc_log_max);
1100 
1101 		caps->ste_alloc_log_gran =
1102 			MLX5_GET(query_hca_cap_out, out,
1103 				 capability.wqe_based_flow_table_cap.ste_alloc_log_granularity);
1104 
1105 		caps->trivial_match_definer =
1106 			MLX5_GET(query_hca_cap_out, out,
1107 				 capability.wqe_based_flow_table_cap.trivial_match_definer);
1108 
1109 		caps->stc_alloc_log_max =
1110 			MLX5_GET(query_hca_cap_out, out,
1111 				 capability.wqe_based_flow_table_cap.stc_alloc_log_max);
1112 
1113 		caps->stc_alloc_log_gran =
1114 			MLX5_GET(query_hca_cap_out, out,
1115 				 capability.wqe_based_flow_table_cap.stc_alloc_log_granularity);
1116 
1117 		caps->rtc_hash_split_table =
1118 			MLX5_GET(query_hca_cap_out, out,
1119 				 capability.wqe_based_flow_table_cap.rtc_hash_split_table);
1120 
1121 		caps->rtc_linear_lookup_table =
1122 			MLX5_GET(query_hca_cap_out, out,
1123 				 capability.wqe_based_flow_table_cap.rtc_linear_lookup_table);
1124 
1125 		caps->access_index_mode =
1126 			MLX5_GET(query_hca_cap_out, out,
1127 				 capability.wqe_based_flow_table_cap.access_index_mode);
1128 
1129 		caps->linear_match_definer =
1130 			MLX5_GET(query_hca_cap_out, out,
1131 				 capability.wqe_based_flow_table_cap.linear_match_definer_reg_c3);
1132 
1133 		caps->rtc_max_hash_def_gen_wqe =
1134 			MLX5_GET(query_hca_cap_out, out,
1135 				 capability.wqe_based_flow_table_cap.rtc_max_num_hash_definer_gen_wqe);
1136 
1137 		caps->supp_ste_format_gen_wqe =
1138 			MLX5_GET(query_hca_cap_out, out,
1139 				 capability.wqe_based_flow_table_cap.ste_format_gen_wqe);
1140 
1141 		caps->fdb_tir_stc =
1142 			MLX5_GET(query_hca_cap_out, out,
1143 				 capability.wqe_based_flow_table_cap.fdb_jump_to_tir_stc);
1144 	}
1145 
1146 	if (caps->eswitch_manager) {
1147 		MLX5_SET(query_hca_cap_in, in, op_mod,
1148 			 MLX5_GET_HCA_CAP_OP_MOD_ESW_FLOW_TABLE | HCA_CAP_OPMOD_GET_CUR);
1149 
1150 		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1151 		if (ret) {
1152 			mlx5_core_err(mdev, "Failed to query flow table esw caps\n");
1153 			goto out;
1154 		}
1155 
1156 		caps->fdb_ft.max_level =
1157 			MLX5_GET(query_hca_cap_out, out,
1158 				 capability.flow_table_nic_cap.flow_table_properties_nic_receive.max_ft_level);
1159 
1160 		caps->fdb_ft.reparse =
1161 			MLX5_GET(query_hca_cap_out, out,
1162 				 capability.flow_table_nic_cap.flow_table_properties_nic_receive.reparse);
1163 
1164 		MLX5_SET(query_hca_cap_in, in, op_mod,
1165 			 MLX5_SET_HCA_CAP_OP_MOD_ESW | HCA_CAP_OPMOD_GET_CUR);
1166 
1167 		ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1168 		if (ret) {
1169 			mlx5_core_err(mdev, "Failed to query eswitch capabilities\n");
1170 			goto out;
1171 		}
1172 
1173 		if (MLX5_GET(query_hca_cap_out, out,
1174 			     capability.esw_cap.esw_manager_vport_number_valid))
1175 			caps->eswitch_manager_vport_number =
1176 				MLX5_GET(query_hca_cap_out, out,
1177 					 capability.esw_cap.esw_manager_vport_number);
1178 
1179 		caps->merged_eswitch = MLX5_GET(query_hca_cap_out, out,
1180 						capability.esw_cap.merged_eswitch);
1181 	}
1182 
1183 	ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, out_size);
1184 	if (ret) {
1185 		mlx5_core_err(mdev, "Failed to query device attributes\n");
1186 		goto out;
1187 	}
1188 
1189 	snprintf(caps->fw_ver, sizeof(caps->fw_ver), "%d.%d.%d",
1190 		 fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev));
1191 
1192 	caps->is_ecpf = mlx5_core_is_ecpf_esw_manager(mdev);
1193 
1194 out:
1195 	kfree(out);
1196 	return ret;
1197 }
1198 
mlx5hws_cmd_query_gvmi(struct mlx5_core_dev * mdev,bool other_function,u16 vport_number,u16 * gvmi)1199 int mlx5hws_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_function,
1200 			   u16 vport_number, u16 *gvmi)
1201 {
1202 	bool ec_vf_func = other_function ? mlx5_core_is_ec_vf_vport(mdev, vport_number) : false;
1203 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
1204 	int out_size;
1205 	void *out;
1206 	int err;
1207 
1208 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
1209 	out = kzalloc(out_size, GFP_KERNEL);
1210 	if (!out)
1211 		return -ENOMEM;
1212 
1213 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
1214 	MLX5_SET(query_hca_cap_in, in, other_function, other_function);
1215 	MLX5_SET(query_hca_cap_in, in, function_id,
1216 		 mlx5_vport_to_func_id(mdev, vport_number, ec_vf_func));
1217 	MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
1218 	MLX5_SET(query_hca_cap_in, in, op_mod,
1219 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 | HCA_CAP_OPMOD_GET_CUR);
1220 
1221 	err = mlx5_cmd_exec_inout(mdev, query_hca_cap, in, out);
1222 	if (err) {
1223 		kfree(out);
1224 		return err;
1225 	}
1226 
1227 	*gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id);
1228 
1229 	kfree(out);
1230 
1231 	return 0;
1232 }
1233