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