1 /*
2  * Copyright (c) 2015, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 
33 #include <linux/mlx5/driver.h>
34 #include <linux/mlx5/device.h>
35 #include <linux/mlx5/mlx5_ifc.h>
36 
37 #include "fs_core.h"
38 #include "fs_cmd.h"
39 #include "fs_ft_pool.h"
40 #include "mlx5_core.h"
41 #include "eswitch.h"
42 
43 static int mlx5_cmd_stub_update_root_ft(struct mlx5_flow_root_namespace *ns,
44 					struct mlx5_flow_table *ft,
45 					u32 underlay_qpn,
46 					bool disconnect)
47 {
48 	return 0;
49 }
50 
51 static int mlx5_cmd_stub_create_flow_table(struct mlx5_flow_root_namespace *ns,
52 					   struct mlx5_flow_table *ft,
53 					   unsigned int size,
54 					   struct mlx5_flow_table *next_ft)
55 {
56 	ft->max_fte = size ? roundup_pow_of_two(size) : 1;
57 
58 	return 0;
59 }
60 
61 static int mlx5_cmd_stub_destroy_flow_table(struct mlx5_flow_root_namespace *ns,
62 					    struct mlx5_flow_table *ft)
63 {
64 	return 0;
65 }
66 
67 static int mlx5_cmd_stub_modify_flow_table(struct mlx5_flow_root_namespace *ns,
68 					   struct mlx5_flow_table *ft,
69 					   struct mlx5_flow_table *next_ft)
70 {
71 	return 0;
72 }
73 
74 static int mlx5_cmd_stub_create_flow_group(struct mlx5_flow_root_namespace *ns,
75 					   struct mlx5_flow_table *ft,
76 					   u32 *in,
77 					   struct mlx5_flow_group *fg)
78 {
79 	return 0;
80 }
81 
82 static int mlx5_cmd_stub_destroy_flow_group(struct mlx5_flow_root_namespace *ns,
83 					    struct mlx5_flow_table *ft,
84 					    struct mlx5_flow_group *fg)
85 {
86 	return 0;
87 }
88 
89 static int mlx5_cmd_stub_create_fte(struct mlx5_flow_root_namespace *ns,
90 				    struct mlx5_flow_table *ft,
91 				    struct mlx5_flow_group *group,
92 				    struct fs_fte *fte)
93 {
94 	return 0;
95 }
96 
97 static int mlx5_cmd_stub_update_fte(struct mlx5_flow_root_namespace *ns,
98 				    struct mlx5_flow_table *ft,
99 				    struct mlx5_flow_group *group,
100 				    int modify_mask,
101 				    struct fs_fte *fte)
102 {
103 	return -EOPNOTSUPP;
104 }
105 
106 static int mlx5_cmd_stub_delete_fte(struct mlx5_flow_root_namespace *ns,
107 				    struct mlx5_flow_table *ft,
108 				    struct fs_fte *fte)
109 {
110 	return 0;
111 }
112 
113 static int mlx5_cmd_stub_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
114 					       struct mlx5_pkt_reformat_params *params,
115 					       enum mlx5_flow_namespace_type namespace,
116 					       struct mlx5_pkt_reformat *pkt_reformat)
117 {
118 	return 0;
119 }
120 
121 static void mlx5_cmd_stub_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns,
122 						  struct mlx5_pkt_reformat *pkt_reformat)
123 {
124 }
125 
126 static int mlx5_cmd_stub_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
127 					     u8 namespace, u8 num_actions,
128 					     void *modify_actions,
129 					     struct mlx5_modify_hdr *modify_hdr)
130 {
131 	return 0;
132 }
133 
134 static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace *ns,
135 						struct mlx5_modify_hdr *modify_hdr)
136 {
137 }
138 
139 static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns,
140 				  struct mlx5_flow_root_namespace *peer_ns)
141 {
142 	return 0;
143 }
144 
145 static int mlx5_cmd_stub_create_ns(struct mlx5_flow_root_namespace *ns)
146 {
147 	return 0;
148 }
149 
150 static int mlx5_cmd_stub_destroy_ns(struct mlx5_flow_root_namespace *ns)
151 {
152 	return 0;
153 }
154 
155 static u32 mlx5_cmd_stub_get_capabilities(struct mlx5_flow_root_namespace *ns,
156 					  enum fs_flow_table_type ft_type)
157 {
158 	return 0;
159 }
160 
161 static int mlx5_cmd_set_slave_root_fdb(struct mlx5_core_dev *master,
162 				       struct mlx5_core_dev *slave,
163 				       bool ft_id_valid,
164 				       u32 ft_id)
165 {
166 	u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {};
167 	u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {};
168 	struct mlx5_flow_root_namespace *root;
169 	struct mlx5_flow_namespace *ns;
170 
171 	MLX5_SET(set_flow_table_root_in, in, opcode,
172 		 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
173 	MLX5_SET(set_flow_table_root_in, in, table_type,
174 		 FS_FT_FDB);
175 	if (ft_id_valid) {
176 		MLX5_SET(set_flow_table_root_in, in,
177 			 table_eswitch_owner_vhca_id_valid, 1);
178 		MLX5_SET(set_flow_table_root_in, in,
179 			 table_eswitch_owner_vhca_id,
180 			 MLX5_CAP_GEN(master, vhca_id));
181 		MLX5_SET(set_flow_table_root_in, in, table_id,
182 			 ft_id);
183 	} else {
184 		ns = mlx5_get_flow_namespace(slave,
185 					     MLX5_FLOW_NAMESPACE_FDB);
186 		root = find_root(&ns->node);
187 		MLX5_SET(set_flow_table_root_in, in, table_id,
188 			 root->root_ft->id);
189 	}
190 
191 	return mlx5_cmd_exec(slave, in, sizeof(in), out, sizeof(out));
192 }
193 
194 static int
195 mlx5_cmd_stub_destroy_match_definer(struct mlx5_flow_root_namespace *ns,
196 				    int definer_id)
197 {
198 	return 0;
199 }
200 
201 static int
202 mlx5_cmd_stub_create_match_definer(struct mlx5_flow_root_namespace *ns,
203 				   u16 format_id, u32 *match_mask)
204 {
205 	return 0;
206 }
207 
208 static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns,
209 				   struct mlx5_flow_table *ft, u32 underlay_qpn,
210 				   bool disconnect)
211 {
212 	u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {};
213 	struct mlx5_core_dev *dev = ns->dev;
214 	int err;
215 
216 	if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
217 	    underlay_qpn == 0)
218 		return 0;
219 
220 	if (ft->type == FS_FT_FDB &&
221 	    mlx5_lag_is_shared_fdb(dev) &&
222 	    !mlx5_lag_is_master(dev))
223 		return 0;
224 
225 	MLX5_SET(set_flow_table_root_in, in, opcode,
226 		 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
227 	MLX5_SET(set_flow_table_root_in, in, table_type, ft->type);
228 
229 	if (disconnect)
230 		MLX5_SET(set_flow_table_root_in, in, op_mod, 1);
231 	else
232 		MLX5_SET(set_flow_table_root_in, in, table_id, ft->id);
233 
234 	MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn);
235 	MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport);
236 	MLX5_SET(set_flow_table_root_in, in, other_vport,
237 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
238 
239 	err = mlx5_cmd_exec_in(dev, set_flow_table_root, in);
240 	if (!err &&
241 	    ft->type == FS_FT_FDB &&
242 	    mlx5_lag_is_shared_fdb(dev) &&
243 	    mlx5_lag_is_master(dev)) {
244 		err = mlx5_cmd_set_slave_root_fdb(dev,
245 						  mlx5_lag_get_peer_mdev(dev),
246 						  !disconnect, (!disconnect) ?
247 						  ft->id : 0);
248 		if (err && !disconnect) {
249 			MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
250 			MLX5_SET(set_flow_table_root_in, in, table_id,
251 				 ns->root_ft->id);
252 			mlx5_cmd_exec_in(dev, set_flow_table_root, in);
253 		}
254 	}
255 
256 	return err;
257 }
258 
259 static int mlx5_cmd_create_flow_table(struct mlx5_flow_root_namespace *ns,
260 				      struct mlx5_flow_table *ft,
261 				      unsigned int size,
262 				      struct mlx5_flow_table *next_ft)
263 {
264 	int en_encap = !!(ft->flags & MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT);
265 	int en_decap = !!(ft->flags & MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
266 	int term = !!(ft->flags & MLX5_FLOW_TABLE_TERMINATION);
267 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
268 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
269 	struct mlx5_core_dev *dev = ns->dev;
270 	int err;
271 
272 	if (size != POOL_NEXT_SIZE)
273 		size = roundup_pow_of_two(size);
274 	size = mlx5_ft_pool_get_avail_sz(dev, ft->type, size);
275 	if (!size)
276 		return -ENOSPC;
277 
278 	MLX5_SET(create_flow_table_in, in, opcode,
279 		 MLX5_CMD_OP_CREATE_FLOW_TABLE);
280 
281 	MLX5_SET(create_flow_table_in, in, table_type, ft->type);
282 	MLX5_SET(create_flow_table_in, in, flow_table_context.level, ft->level);
283 	MLX5_SET(create_flow_table_in, in, flow_table_context.log_size, size ? ilog2(size) : 0);
284 	MLX5_SET(create_flow_table_in, in, vport_number, ft->vport);
285 	MLX5_SET(create_flow_table_in, in, other_vport,
286 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
287 
288 	MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
289 		 en_decap);
290 	MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en,
291 		 en_encap);
292 	MLX5_SET(create_flow_table_in, in, flow_table_context.termination_table,
293 		 term);
294 
295 	switch (ft->op_mod) {
296 	case FS_FT_OP_MOD_NORMAL:
297 		if (next_ft) {
298 			MLX5_SET(create_flow_table_in, in,
299 				 flow_table_context.table_miss_action,
300 				 MLX5_FLOW_TABLE_MISS_ACTION_FWD);
301 			MLX5_SET(create_flow_table_in, in,
302 				 flow_table_context.table_miss_id, next_ft->id);
303 		} else {
304 			MLX5_SET(create_flow_table_in, in,
305 				 flow_table_context.table_miss_action,
306 				 ft->def_miss_action);
307 		}
308 		break;
309 
310 	case FS_FT_OP_MOD_LAG_DEMUX:
311 		MLX5_SET(create_flow_table_in, in, op_mod, 0x1);
312 		if (next_ft)
313 			MLX5_SET(create_flow_table_in, in,
314 				 flow_table_context.lag_master_next_table_id,
315 				 next_ft->id);
316 		break;
317 	}
318 
319 	err = mlx5_cmd_exec_inout(dev, create_flow_table, in, out);
320 	if (!err) {
321 		ft->id = MLX5_GET(create_flow_table_out, out,
322 				  table_id);
323 		ft->max_fte = size;
324 	} else {
325 		mlx5_ft_pool_put_sz(ns->dev, size);
326 	}
327 
328 	return err;
329 }
330 
331 static int mlx5_cmd_destroy_flow_table(struct mlx5_flow_root_namespace *ns,
332 				       struct mlx5_flow_table *ft)
333 {
334 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
335 	struct mlx5_core_dev *dev = ns->dev;
336 	int err;
337 
338 	MLX5_SET(destroy_flow_table_in, in, opcode,
339 		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
340 	MLX5_SET(destroy_flow_table_in, in, table_type, ft->type);
341 	MLX5_SET(destroy_flow_table_in, in, table_id, ft->id);
342 	MLX5_SET(destroy_flow_table_in, in, vport_number, ft->vport);
343 	MLX5_SET(destroy_flow_table_in, in, other_vport,
344 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
345 
346 	err = mlx5_cmd_exec_in(dev, destroy_flow_table, in);
347 	if (!err)
348 		mlx5_ft_pool_put_sz(ns->dev, ft->max_fte);
349 
350 	return err;
351 }
352 
353 static int mlx5_cmd_modify_flow_table(struct mlx5_flow_root_namespace *ns,
354 				      struct mlx5_flow_table *ft,
355 				      struct mlx5_flow_table *next_ft)
356 {
357 	u32 in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {};
358 	struct mlx5_core_dev *dev = ns->dev;
359 
360 	MLX5_SET(modify_flow_table_in, in, opcode,
361 		 MLX5_CMD_OP_MODIFY_FLOW_TABLE);
362 	MLX5_SET(modify_flow_table_in, in, table_type, ft->type);
363 	MLX5_SET(modify_flow_table_in, in, table_id, ft->id);
364 
365 	if (ft->op_mod == FS_FT_OP_MOD_LAG_DEMUX) {
366 		MLX5_SET(modify_flow_table_in, in, modify_field_select,
367 			 MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID);
368 		if (next_ft) {
369 			MLX5_SET(modify_flow_table_in, in,
370 				 flow_table_context.lag_master_next_table_id, next_ft->id);
371 		} else {
372 			MLX5_SET(modify_flow_table_in, in,
373 				 flow_table_context.lag_master_next_table_id, 0);
374 		}
375 	} else {
376 		MLX5_SET(modify_flow_table_in, in, vport_number, ft->vport);
377 		MLX5_SET(modify_flow_table_in, in, other_vport,
378 			 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
379 		MLX5_SET(modify_flow_table_in, in, modify_field_select,
380 			 MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID);
381 		if (next_ft) {
382 			MLX5_SET(modify_flow_table_in, in,
383 				 flow_table_context.table_miss_action,
384 				 MLX5_FLOW_TABLE_MISS_ACTION_FWD);
385 			MLX5_SET(modify_flow_table_in, in,
386 				 flow_table_context.table_miss_id,
387 				 next_ft->id);
388 		} else {
389 			MLX5_SET(modify_flow_table_in, in,
390 				 flow_table_context.table_miss_action,
391 				 ft->def_miss_action);
392 		}
393 	}
394 
395 	return mlx5_cmd_exec_in(dev, modify_flow_table, in);
396 }
397 
398 static int mlx5_cmd_create_flow_group(struct mlx5_flow_root_namespace *ns,
399 				      struct mlx5_flow_table *ft,
400 				      u32 *in,
401 				      struct mlx5_flow_group *fg)
402 {
403 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
404 	struct mlx5_core_dev *dev = ns->dev;
405 	int err;
406 
407 	MLX5_SET(create_flow_group_in, in, opcode,
408 		 MLX5_CMD_OP_CREATE_FLOW_GROUP);
409 	MLX5_SET(create_flow_group_in, in, table_type, ft->type);
410 	MLX5_SET(create_flow_group_in, in, table_id, ft->id);
411 	if (ft->vport) {
412 		MLX5_SET(create_flow_group_in, in, vport_number, ft->vport);
413 		MLX5_SET(create_flow_group_in, in, other_vport, 1);
414 	}
415 
416 	MLX5_SET(create_flow_group_in, in, vport_number, ft->vport);
417 	MLX5_SET(create_flow_group_in, in, other_vport,
418 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
419 	err = mlx5_cmd_exec_inout(dev, create_flow_group, in, out);
420 	if (!err)
421 		fg->id = MLX5_GET(create_flow_group_out, out,
422 				  group_id);
423 	return err;
424 }
425 
426 static int mlx5_cmd_destroy_flow_group(struct mlx5_flow_root_namespace *ns,
427 				       struct mlx5_flow_table *ft,
428 				       struct mlx5_flow_group *fg)
429 {
430 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
431 	struct mlx5_core_dev *dev = ns->dev;
432 
433 	MLX5_SET(destroy_flow_group_in, in, opcode,
434 		 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
435 	MLX5_SET(destroy_flow_group_in, in, table_type, ft->type);
436 	MLX5_SET(destroy_flow_group_in, in, table_id, ft->id);
437 	MLX5_SET(destroy_flow_group_in, in, group_id, fg->id);
438 	MLX5_SET(destroy_flow_group_in, in, vport_number, ft->vport);
439 	MLX5_SET(destroy_flow_group_in, in, other_vport,
440 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
441 	return mlx5_cmd_exec_in(dev, destroy_flow_group, in);
442 }
443 
444 static int mlx5_set_extended_dest(struct mlx5_core_dev *dev,
445 				  struct fs_fte *fte, bool *extended_dest)
446 {
447 	int fw_log_max_fdb_encap_uplink =
448 		MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink);
449 	int num_fwd_destinations = 0;
450 	struct mlx5_flow_rule *dst;
451 	int num_encap = 0;
452 
453 	*extended_dest = false;
454 	if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
455 		return 0;
456 
457 	list_for_each_entry(dst, &fte->node.children, node.list) {
458 		if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
459 			continue;
460 		if ((dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_VPORT ||
461 		     dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) &&
462 		    dst->dest_attr.vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
463 			num_encap++;
464 		num_fwd_destinations++;
465 	}
466 	if (num_fwd_destinations > 1 && num_encap > 0)
467 		*extended_dest = true;
468 
469 	if (*extended_dest && !fw_log_max_fdb_encap_uplink) {
470 		mlx5_core_warn(dev, "FW does not support extended destination");
471 		return -EOPNOTSUPP;
472 	}
473 	if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) {
474 		mlx5_core_warn(dev, "FW does not support more than %d encaps",
475 			       1 << fw_log_max_fdb_encap_uplink);
476 		return -EOPNOTSUPP;
477 	}
478 
479 	return 0;
480 }
481 static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
482 			    int opmod, int modify_mask,
483 			    struct mlx5_flow_table *ft,
484 			    unsigned group_id,
485 			    struct fs_fte *fte)
486 {
487 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
488 	bool extended_dest = false;
489 	struct mlx5_flow_rule *dst;
490 	void *in_flow_context, *vlan;
491 	void *in_match_value;
492 	unsigned int inlen;
493 	int dst_cnt_size;
494 	void *in_dests;
495 	u32 *in;
496 	int err;
497 
498 	if (mlx5_set_extended_dest(dev, fte, &extended_dest))
499 		return -EOPNOTSUPP;
500 
501 	if (!extended_dest)
502 		dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct);
503 	else
504 		dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format);
505 
506 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size;
507 	in = kvzalloc(inlen, GFP_KERNEL);
508 	if (!in)
509 		return -ENOMEM;
510 
511 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
512 	MLX5_SET(set_fte_in, in, op_mod, opmod);
513 	MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
514 	MLX5_SET(set_fte_in, in, table_type, ft->type);
515 	MLX5_SET(set_fte_in, in, table_id,   ft->id);
516 	MLX5_SET(set_fte_in, in, flow_index, fte->index);
517 	MLX5_SET(set_fte_in, in, ignore_flow_level,
518 		 !!(fte->action.flags & FLOW_ACT_IGNORE_FLOW_LEVEL));
519 
520 	MLX5_SET(set_fte_in, in, vport_number, ft->vport);
521 	MLX5_SET(set_fte_in, in, other_vport,
522 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
523 
524 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
525 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
526 
527 	MLX5_SET(flow_context, in_flow_context, flow_tag,
528 		 fte->flow_context.flow_tag);
529 	MLX5_SET(flow_context, in_flow_context, flow_source,
530 		 fte->flow_context.flow_source);
531 
532 	MLX5_SET(flow_context, in_flow_context, extended_destination,
533 		 extended_dest);
534 	if (extended_dest) {
535 		u32 action;
536 
537 		action = fte->action.action &
538 			~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
539 		MLX5_SET(flow_context, in_flow_context, action, action);
540 	} else {
541 		MLX5_SET(flow_context, in_flow_context, action,
542 			 fte->action.action);
543 		if (fte->action.pkt_reformat)
544 			MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
545 				 fte->action.pkt_reformat->id);
546 	}
547 	if (fte->action.modify_hdr)
548 		MLX5_SET(flow_context, in_flow_context, modify_header_id,
549 			 fte->action.modify_hdr->id);
550 
551 	MLX5_SET(flow_context, in_flow_context, ipsec_obj_id, fte->action.ipsec_obj_id);
552 
553 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan);
554 
555 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype);
556 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid);
557 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio);
558 
559 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2);
560 
561 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype);
562 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid);
563 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio);
564 
565 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
566 				      match_value);
567 	memcpy(in_match_value, &fte->val, sizeof(fte->val));
568 
569 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
570 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
571 		int list_size = 0;
572 
573 		list_for_each_entry(dst, &fte->node.children, node.list) {
574 			unsigned int id, type = dst->dest_attr.type;
575 
576 			if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
577 				continue;
578 
579 			switch (type) {
580 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
581 				id = dst->dest_attr.ft_num;
582 				type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
583 				break;
584 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
585 				id = dst->dest_attr.ft->id;
586 				break;
587 			case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
588 			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
589 				MLX5_SET(dest_format_struct, in_dests,
590 					 destination_eswitch_owner_vhca_id_valid,
591 					 !!(dst->dest_attr.vport.flags &
592 					    MLX5_FLOW_DEST_VPORT_VHCA_ID));
593 				MLX5_SET(dest_format_struct, in_dests,
594 					 destination_eswitch_owner_vhca_id,
595 					 dst->dest_attr.vport.vhca_id);
596 				if (type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) {
597 					/* destination_id is reserved */
598 					id = 0;
599 					break;
600 				}
601 				id = dst->dest_attr.vport.num;
602 				if (extended_dest &&
603 				    dst->dest_attr.vport.pkt_reformat) {
604 					MLX5_SET(dest_format_struct, in_dests,
605 						 packet_reformat,
606 						 !!(dst->dest_attr.vport.flags &
607 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID));
608 					MLX5_SET(extended_dest_format, in_dests,
609 						 packet_reformat_id,
610 						 dst->dest_attr.vport.pkt_reformat->id);
611 				}
612 				break;
613 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
614 				id = dst->dest_attr.sampler_id;
615 				break;
616 			default:
617 				id = dst->dest_attr.tir_num;
618 			}
619 
620 			MLX5_SET(dest_format_struct, in_dests, destination_type,
621 				 type);
622 			MLX5_SET(dest_format_struct, in_dests, destination_id, id);
623 			in_dests += dst_cnt_size;
624 			list_size++;
625 		}
626 
627 		MLX5_SET(flow_context, in_flow_context, destination_list_size,
628 			 list_size);
629 	}
630 
631 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
632 		int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev,
633 					log_max_flow_counter,
634 					ft->type));
635 		int list_size = 0;
636 
637 		list_for_each_entry(dst, &fte->node.children, node.list) {
638 			if (dst->dest_attr.type !=
639 			    MLX5_FLOW_DESTINATION_TYPE_COUNTER)
640 				continue;
641 
642 			MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
643 				 dst->dest_attr.counter_id);
644 			in_dests += dst_cnt_size;
645 			list_size++;
646 		}
647 		if (list_size > max_list_size) {
648 			err = -EINVAL;
649 			goto err_out;
650 		}
651 
652 		MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
653 			 list_size);
654 	}
655 
656 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
657 err_out:
658 	kvfree(in);
659 	return err;
660 }
661 
662 static int mlx5_cmd_create_fte(struct mlx5_flow_root_namespace *ns,
663 			       struct mlx5_flow_table *ft,
664 			       struct mlx5_flow_group *group,
665 			       struct fs_fte *fte)
666 {
667 	struct mlx5_core_dev *dev = ns->dev;
668 	unsigned int group_id = group->id;
669 
670 	return mlx5_cmd_set_fte(dev, 0, 0, ft, group_id, fte);
671 }
672 
673 static int mlx5_cmd_update_fte(struct mlx5_flow_root_namespace *ns,
674 			       struct mlx5_flow_table *ft,
675 			       struct mlx5_flow_group *fg,
676 			       int modify_mask,
677 			       struct fs_fte *fte)
678 {
679 	int opmod;
680 	struct mlx5_core_dev *dev = ns->dev;
681 	int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev,
682 						flow_table_properties_nic_receive.
683 						flow_modify_en);
684 	if (!atomic_mod_cap)
685 		return -EOPNOTSUPP;
686 	opmod = 1;
687 
688 	return	mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, fg->id, fte);
689 }
690 
691 static int mlx5_cmd_delete_fte(struct mlx5_flow_root_namespace *ns,
692 			       struct mlx5_flow_table *ft,
693 			       struct fs_fte *fte)
694 {
695 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
696 	struct mlx5_core_dev *dev = ns->dev;
697 
698 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
699 	MLX5_SET(delete_fte_in, in, table_type, ft->type);
700 	MLX5_SET(delete_fte_in, in, table_id, ft->id);
701 	MLX5_SET(delete_fte_in, in, flow_index, fte->index);
702 	MLX5_SET(delete_fte_in, in, vport_number, ft->vport);
703 	MLX5_SET(delete_fte_in, in, other_vport,
704 		 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT));
705 
706 	return mlx5_cmd_exec_in(dev, delete_fte, in);
707 }
708 
709 int mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev,
710 			   enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask,
711 			   u32 *id)
712 {
713 	u32 out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {};
714 	u32 in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {};
715 	int err;
716 
717 	MLX5_SET(alloc_flow_counter_in, in, opcode,
718 		 MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
719 	MLX5_SET(alloc_flow_counter_in, in, flow_counter_bulk, alloc_bitmask);
720 
721 	err = mlx5_cmd_exec_inout(dev, alloc_flow_counter, in, out);
722 	if (!err)
723 		*id = MLX5_GET(alloc_flow_counter_out, out, flow_counter_id);
724 	return err;
725 }
726 
727 int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id)
728 {
729 	return mlx5_cmd_fc_bulk_alloc(dev, 0, id);
730 }
731 
732 int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id)
733 {
734 	u32 in[MLX5_ST_SZ_DW(dealloc_flow_counter_in)] = {};
735 
736 	MLX5_SET(dealloc_flow_counter_in, in, opcode,
737 		 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
738 	MLX5_SET(dealloc_flow_counter_in, in, flow_counter_id, id);
739 	return mlx5_cmd_exec_in(dev, dealloc_flow_counter, in);
740 }
741 
742 int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id,
743 		      u64 *packets, u64 *bytes)
744 {
745 	u32 out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
746 		MLX5_ST_SZ_BYTES(traffic_counter)] = {};
747 	u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {};
748 	void *stats;
749 	int err = 0;
750 
751 	MLX5_SET(query_flow_counter_in, in, opcode,
752 		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
753 	MLX5_SET(query_flow_counter_in, in, op_mod, 0);
754 	MLX5_SET(query_flow_counter_in, in, flow_counter_id, id);
755 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
756 	if (err)
757 		return err;
758 
759 	stats = MLX5_ADDR_OF(query_flow_counter_out, out, flow_statistics);
760 	*packets = MLX5_GET64(traffic_counter, stats, packets);
761 	*bytes = MLX5_GET64(traffic_counter, stats, octets);
762 	return 0;
763 }
764 
765 int mlx5_cmd_fc_get_bulk_query_out_len(int bulk_len)
766 {
767 	return MLX5_ST_SZ_BYTES(query_flow_counter_out) +
768 		MLX5_ST_SZ_BYTES(traffic_counter) * bulk_len;
769 }
770 
771 int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, u32 base_id, int bulk_len,
772 			   u32 *out)
773 {
774 	int outlen = mlx5_cmd_fc_get_bulk_query_out_len(bulk_len);
775 	u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {};
776 
777 	MLX5_SET(query_flow_counter_in, in, opcode,
778 		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
779 	MLX5_SET(query_flow_counter_in, in, flow_counter_id, base_id);
780 	MLX5_SET(query_flow_counter_in, in, num_of_counters, bulk_len);
781 	return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
782 }
783 
784 static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
785 					  struct mlx5_pkt_reformat_params *params,
786 					  enum mlx5_flow_namespace_type namespace,
787 					  struct mlx5_pkt_reformat *pkt_reformat)
788 {
789 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
790 	struct mlx5_core_dev *dev = ns->dev;
791 	void *packet_reformat_context_in;
792 	int max_encap_size;
793 	void *reformat;
794 	int inlen;
795 	int err;
796 	u32 *in;
797 
798 	if (namespace == MLX5_FLOW_NAMESPACE_FDB ||
799 	    namespace == MLX5_FLOW_NAMESPACE_FDB_BYPASS)
800 		max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size);
801 	else
802 		max_encap_size = MLX5_CAP_FLOWTABLE(dev, max_encap_header_size);
803 
804 	if (params->size > max_encap_size) {
805 		mlx5_core_warn(dev, "encap size %zd too big, max supported is %d\n",
806 			       params->size, max_encap_size);
807 		return -EINVAL;
808 	}
809 
810 	in = kzalloc(MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in) +
811 		     params->size, GFP_KERNEL);
812 	if (!in)
813 		return -ENOMEM;
814 
815 	packet_reformat_context_in = MLX5_ADDR_OF(alloc_packet_reformat_context_in,
816 						  in, packet_reformat_context);
817 	reformat = MLX5_ADDR_OF(packet_reformat_context_in,
818 				packet_reformat_context_in,
819 				reformat_data);
820 	inlen = reformat - (void *)in + params->size;
821 
822 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
823 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
824 	MLX5_SET(packet_reformat_context_in, packet_reformat_context_in,
825 		 reformat_data_size, params->size);
826 	MLX5_SET(packet_reformat_context_in, packet_reformat_context_in,
827 		 reformat_type, params->type);
828 	MLX5_SET(packet_reformat_context_in, packet_reformat_context_in,
829 		 reformat_param_0, params->param_0);
830 	MLX5_SET(packet_reformat_context_in, packet_reformat_context_in,
831 		 reformat_param_1, params->param_1);
832 	if (params->data && params->size)
833 		memcpy(reformat, params->data, params->size);
834 
835 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
836 
837 	pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out,
838 				    out, packet_reformat_id);
839 	kfree(in);
840 	return err;
841 }
842 
843 static void mlx5_cmd_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns,
844 					     struct mlx5_pkt_reformat *pkt_reformat)
845 {
846 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
847 	struct mlx5_core_dev *dev = ns->dev;
848 
849 	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
850 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
851 	MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
852 		 pkt_reformat->id);
853 
854 	mlx5_cmd_exec_in(dev, dealloc_packet_reformat_context, in);
855 }
856 
857 static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
858 					u8 namespace, u8 num_actions,
859 					void *modify_actions,
860 					struct mlx5_modify_hdr *modify_hdr)
861 {
862 	u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
863 	int max_actions, actions_size, inlen, err;
864 	struct mlx5_core_dev *dev = ns->dev;
865 	void *actions_in;
866 	u8 table_type;
867 	u32 *in;
868 
869 	switch (namespace) {
870 	case MLX5_FLOW_NAMESPACE_FDB:
871 	case MLX5_FLOW_NAMESPACE_FDB_BYPASS:
872 		max_actions = MLX5_CAP_ESW_FLOWTABLE_FDB(dev, max_modify_header_actions);
873 		table_type = FS_FT_FDB;
874 		break;
875 	case MLX5_FLOW_NAMESPACE_KERNEL:
876 	case MLX5_FLOW_NAMESPACE_BYPASS:
877 		max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(dev, max_modify_header_actions);
878 		table_type = FS_FT_NIC_RX;
879 		break;
880 	case MLX5_FLOW_NAMESPACE_EGRESS:
881 #ifdef CONFIG_MLX5_IPSEC
882 	case MLX5_FLOW_NAMESPACE_EGRESS_KERNEL:
883 #endif
884 		max_actions = MLX5_CAP_FLOWTABLE_NIC_TX(dev, max_modify_header_actions);
885 		table_type = FS_FT_NIC_TX;
886 		break;
887 	case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
888 		max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions);
889 		table_type = FS_FT_ESW_INGRESS_ACL;
890 		break;
891 	case MLX5_FLOW_NAMESPACE_RDMA_TX:
892 		max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions);
893 		table_type = FS_FT_RDMA_TX;
894 		break;
895 	default:
896 		return -EOPNOTSUPP;
897 	}
898 
899 	if (num_actions > max_actions) {
900 		mlx5_core_warn(dev, "too many modify header actions %d, max supported %d\n",
901 			       num_actions, max_actions);
902 		return -EOPNOTSUPP;
903 	}
904 
905 	actions_size = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto) * num_actions;
906 	inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) + actions_size;
907 
908 	in = kzalloc(inlen, GFP_KERNEL);
909 	if (!in)
910 		return -ENOMEM;
911 
912 	MLX5_SET(alloc_modify_header_context_in, in, opcode,
913 		 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
914 	MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
915 	MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_actions);
916 
917 	actions_in = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
918 	memcpy(actions_in, modify_actions, actions_size);
919 
920 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
921 
922 	modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id);
923 	kfree(in);
924 	return err;
925 }
926 
927 static void mlx5_cmd_modify_header_dealloc(struct mlx5_flow_root_namespace *ns,
928 					   struct mlx5_modify_hdr *modify_hdr)
929 {
930 	u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
931 	struct mlx5_core_dev *dev = ns->dev;
932 
933 	MLX5_SET(dealloc_modify_header_context_in, in, opcode,
934 		 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
935 	MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
936 		 modify_hdr->id);
937 
938 	mlx5_cmd_exec_in(dev, dealloc_modify_header_context, in);
939 }
940 
941 static int mlx5_cmd_destroy_match_definer(struct mlx5_flow_root_namespace *ns,
942 					  int definer_id)
943 {
944 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
945 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
946 
947 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
948 		 MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
949 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
950 		 MLX5_OBJ_TYPE_MATCH_DEFINER);
951 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, definer_id);
952 
953 	return mlx5_cmd_exec(ns->dev, in, sizeof(in), out, sizeof(out));
954 }
955 
956 static int mlx5_cmd_create_match_definer(struct mlx5_flow_root_namespace *ns,
957 					 u16 format_id, u32 *match_mask)
958 {
959 	u32 out[MLX5_ST_SZ_DW(create_match_definer_out)] = {};
960 	u32 in[MLX5_ST_SZ_DW(create_match_definer_in)] = {};
961 	struct mlx5_core_dev *dev = ns->dev;
962 	void *ptr;
963 	int err;
964 
965 	MLX5_SET(create_match_definer_in, in, general_obj_in_cmd_hdr.opcode,
966 		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
967 	MLX5_SET(create_match_definer_in, in, general_obj_in_cmd_hdr.obj_type,
968 		 MLX5_OBJ_TYPE_MATCH_DEFINER);
969 
970 	ptr = MLX5_ADDR_OF(create_match_definer_in, in, obj_context);
971 	MLX5_SET(match_definer, ptr, format_id, format_id);
972 
973 	ptr = MLX5_ADDR_OF(match_definer, ptr, match_mask);
974 	memcpy(ptr, match_mask, MLX5_FLD_SZ_BYTES(match_definer, match_mask));
975 
976 	err = mlx5_cmd_exec_inout(dev, create_match_definer, in, out);
977 	return err ? err : MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
978 }
979 
980 static u32 mlx5_cmd_get_capabilities(struct mlx5_flow_root_namespace *ns,
981 				     enum fs_flow_table_type ft_type)
982 {
983 	return 0;
984 }
985 
986 static const struct mlx5_flow_cmds mlx5_flow_cmds = {
987 	.create_flow_table = mlx5_cmd_create_flow_table,
988 	.destroy_flow_table = mlx5_cmd_destroy_flow_table,
989 	.modify_flow_table = mlx5_cmd_modify_flow_table,
990 	.create_flow_group = mlx5_cmd_create_flow_group,
991 	.destroy_flow_group = mlx5_cmd_destroy_flow_group,
992 	.create_fte = mlx5_cmd_create_fte,
993 	.update_fte = mlx5_cmd_update_fte,
994 	.delete_fte = mlx5_cmd_delete_fte,
995 	.update_root_ft = mlx5_cmd_update_root_ft,
996 	.packet_reformat_alloc = mlx5_cmd_packet_reformat_alloc,
997 	.packet_reformat_dealloc = mlx5_cmd_packet_reformat_dealloc,
998 	.modify_header_alloc = mlx5_cmd_modify_header_alloc,
999 	.modify_header_dealloc = mlx5_cmd_modify_header_dealloc,
1000 	.create_match_definer = mlx5_cmd_create_match_definer,
1001 	.destroy_match_definer = mlx5_cmd_destroy_match_definer,
1002 	.set_peer = mlx5_cmd_stub_set_peer,
1003 	.create_ns = mlx5_cmd_stub_create_ns,
1004 	.destroy_ns = mlx5_cmd_stub_destroy_ns,
1005 	.get_capabilities = mlx5_cmd_get_capabilities,
1006 };
1007 
1008 static const struct mlx5_flow_cmds mlx5_flow_cmd_stubs = {
1009 	.create_flow_table = mlx5_cmd_stub_create_flow_table,
1010 	.destroy_flow_table = mlx5_cmd_stub_destroy_flow_table,
1011 	.modify_flow_table = mlx5_cmd_stub_modify_flow_table,
1012 	.create_flow_group = mlx5_cmd_stub_create_flow_group,
1013 	.destroy_flow_group = mlx5_cmd_stub_destroy_flow_group,
1014 	.create_fte = mlx5_cmd_stub_create_fte,
1015 	.update_fte = mlx5_cmd_stub_update_fte,
1016 	.delete_fte = mlx5_cmd_stub_delete_fte,
1017 	.update_root_ft = mlx5_cmd_stub_update_root_ft,
1018 	.packet_reformat_alloc = mlx5_cmd_stub_packet_reformat_alloc,
1019 	.packet_reformat_dealloc = mlx5_cmd_stub_packet_reformat_dealloc,
1020 	.modify_header_alloc = mlx5_cmd_stub_modify_header_alloc,
1021 	.modify_header_dealloc = mlx5_cmd_stub_modify_header_dealloc,
1022 	.create_match_definer = mlx5_cmd_stub_create_match_definer,
1023 	.destroy_match_definer = mlx5_cmd_stub_destroy_match_definer,
1024 	.set_peer = mlx5_cmd_stub_set_peer,
1025 	.create_ns = mlx5_cmd_stub_create_ns,
1026 	.destroy_ns = mlx5_cmd_stub_destroy_ns,
1027 	.get_capabilities = mlx5_cmd_stub_get_capabilities,
1028 };
1029 
1030 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void)
1031 {
1032 	return &mlx5_flow_cmds;
1033 }
1034 
1035 static const struct mlx5_flow_cmds *mlx5_fs_cmd_get_stub_cmds(void)
1036 {
1037 	return &mlx5_flow_cmd_stubs;
1038 }
1039 
1040 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type type)
1041 {
1042 	switch (type) {
1043 	case FS_FT_NIC_RX:
1044 	case FS_FT_ESW_EGRESS_ACL:
1045 	case FS_FT_ESW_INGRESS_ACL:
1046 	case FS_FT_FDB:
1047 	case FS_FT_SNIFFER_RX:
1048 	case FS_FT_SNIFFER_TX:
1049 	case FS_FT_NIC_TX:
1050 	case FS_FT_RDMA_RX:
1051 	case FS_FT_RDMA_TX:
1052 	case FS_FT_PORT_SEL:
1053 		return mlx5_fs_cmd_get_fw_cmds();
1054 	default:
1055 		return mlx5_fs_cmd_get_stub_cmds();
1056 	}
1057 }
1058