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