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