11d918647SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
21d918647SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */
31d918647SAlex Vesker 
41d918647SAlex Vesker #include "dr_types.h"
51d918647SAlex Vesker 
61d918647SAlex Vesker int mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev *mdev,
71d918647SAlex Vesker 				       bool other_vport,
81d918647SAlex Vesker 				       u16 vport_number,
91d918647SAlex Vesker 				       u64 *icm_address_rx,
101d918647SAlex Vesker 				       u64 *icm_address_tx)
111d918647SAlex Vesker {
121d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_esw_vport_context_out)] = {};
131d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_esw_vport_context_in)] = {};
141d918647SAlex Vesker 	int err;
151d918647SAlex Vesker 
161d918647SAlex Vesker 	MLX5_SET(query_esw_vport_context_in, in, opcode,
171d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT);
181d918647SAlex Vesker 	MLX5_SET(query_esw_vport_context_in, in, other_vport, other_vport);
191d918647SAlex Vesker 	MLX5_SET(query_esw_vport_context_in, in, vport_number, vport_number);
201d918647SAlex Vesker 
217ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, query_esw_vport_context, in, out);
221d918647SAlex Vesker 	if (err)
231d918647SAlex Vesker 		return err;
241d918647SAlex Vesker 
251d918647SAlex Vesker 	*icm_address_rx =
261d918647SAlex Vesker 		MLX5_GET64(query_esw_vport_context_out, out,
271d918647SAlex Vesker 			   esw_vport_context.sw_steering_vport_icm_address_rx);
281d918647SAlex Vesker 	*icm_address_tx =
291d918647SAlex Vesker 		MLX5_GET64(query_esw_vport_context_out, out,
301d918647SAlex Vesker 			   esw_vport_context.sw_steering_vport_icm_address_tx);
311d918647SAlex Vesker 	return 0;
321d918647SAlex Vesker }
331d918647SAlex Vesker 
341d918647SAlex Vesker int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
351d918647SAlex Vesker 			  u16 vport_number, u16 *gvmi)
361d918647SAlex Vesker {
371d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
381d918647SAlex Vesker 	int out_size;
391d918647SAlex Vesker 	void *out;
401d918647SAlex Vesker 	int err;
411d918647SAlex Vesker 
421d918647SAlex Vesker 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
431d918647SAlex Vesker 	out = kzalloc(out_size, GFP_KERNEL);
441d918647SAlex Vesker 	if (!out)
451d918647SAlex Vesker 		return -ENOMEM;
461d918647SAlex Vesker 
471d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
481d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, other_function, other_vport);
491d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, function_id, vport_number);
501d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, op_mod,
511d918647SAlex Vesker 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 |
521d918647SAlex Vesker 		 HCA_CAP_OPMOD_GET_CUR);
531d918647SAlex Vesker 
547ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, query_hca_cap, in, out);
551d918647SAlex Vesker 	if (err) {
561d918647SAlex Vesker 		kfree(out);
571d918647SAlex Vesker 		return err;
581d918647SAlex Vesker 	}
591d918647SAlex Vesker 
601d918647SAlex Vesker 	*gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id);
611d918647SAlex Vesker 
621d918647SAlex Vesker 	kfree(out);
631d918647SAlex Vesker 	return 0;
641d918647SAlex Vesker }
651d918647SAlex Vesker 
661d918647SAlex Vesker int mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev *mdev,
671d918647SAlex Vesker 			      struct mlx5dr_esw_caps *caps)
681d918647SAlex Vesker {
691d918647SAlex Vesker 	caps->drop_icm_address_rx =
701d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
711d918647SAlex Vesker 					 sw_steering_fdb_action_drop_icm_address_rx);
721d918647SAlex Vesker 	caps->drop_icm_address_tx =
731d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
741d918647SAlex Vesker 					 sw_steering_fdb_action_drop_icm_address_tx);
751d918647SAlex Vesker 	caps->uplink_icm_address_rx =
761d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
771d918647SAlex Vesker 					 sw_steering_uplink_icm_address_rx);
781d918647SAlex Vesker 	caps->uplink_icm_address_tx =
791d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
801d918647SAlex Vesker 					 sw_steering_uplink_icm_address_tx);
8164f45c0fSYevgeny Kliteynik 	caps->sw_owner_v2 = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner_v2);
8264f45c0fSYevgeny Kliteynik 	if (!caps->sw_owner_v2)
8364f45c0fSYevgeny Kliteynik 		caps->sw_owner = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner);
841d918647SAlex Vesker 
851d918647SAlex Vesker 	return 0;
861d918647SAlex Vesker }
871d918647SAlex Vesker 
881d918647SAlex Vesker int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
891d918647SAlex Vesker 			    struct mlx5dr_cmd_caps *caps)
901d918647SAlex Vesker {
911d918647SAlex Vesker 	caps->prio_tag_required	= MLX5_CAP_GEN(mdev, prio_tag_required);
921d918647SAlex Vesker 	caps->eswitch_manager	= MLX5_CAP_GEN(mdev, eswitch_manager);
931d918647SAlex Vesker 	caps->gvmi		= MLX5_CAP_GEN(mdev, vhca_id);
941d918647SAlex Vesker 	caps->flex_protocols	= MLX5_CAP_GEN(mdev, flex_parser_protocols);
95d421e466SYevgeny Kliteynik 	caps->sw_format_ver	= MLX5_CAP_GEN(mdev, steering_format_version);
961d918647SAlex Vesker 
978a8a1023SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED) {
981d918647SAlex Vesker 		caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
991d918647SAlex Vesker 		caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1);
1001d918647SAlex Vesker 	}
1011d918647SAlex Vesker 
1028a8a1023SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED) {
1031d918647SAlex Vesker 		caps->flex_parser_id_icmpv6_dw0 =
1041d918647SAlex Vesker 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0);
1051d918647SAlex Vesker 		caps->flex_parser_id_icmpv6_dw1 =
1061d918647SAlex Vesker 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1);
1071d918647SAlex Vesker 	}
1081d918647SAlex Vesker 
109*3442e033SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
110*3442e033SYevgeny Kliteynik 		caps->flex_parser_id_geneve_tlv_option_0 =
111*3442e033SYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_geneve_tlv_option_0);
112*3442e033SYevgeny Kliteynik 
1131d918647SAlex Vesker 	caps->nic_rx_drop_address =
1141d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address);
1151d918647SAlex Vesker 	caps->nic_tx_drop_address =
1161d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address);
1171d918647SAlex Vesker 	caps->nic_tx_allow_address =
1181d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address);
1191d918647SAlex Vesker 
12064f45c0fSYevgeny Kliteynik 	caps->rx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner_v2);
12164f45c0fSYevgeny Kliteynik 	caps->tx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner_v2);
1221d918647SAlex Vesker 
12364f45c0fSYevgeny Kliteynik 	if (!caps->rx_sw_owner_v2)
12464f45c0fSYevgeny Kliteynik 		caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner);
12564f45c0fSYevgeny Kliteynik 	if (!caps->tx_sw_owner_v2)
1261d918647SAlex Vesker 		caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner);
1271d918647SAlex Vesker 
12864f45c0fSYevgeny Kliteynik 	caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level);
12964f45c0fSYevgeny Kliteynik 
1301d918647SAlex Vesker 	caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size);
1311d918647SAlex Vesker 	caps->hdr_modify_icm_addr =
1321d918647SAlex Vesker 		MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address);
1331d918647SAlex Vesker 
1341d918647SAlex Vesker 	caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port);
1351d918647SAlex Vesker 
1361d918647SAlex Vesker 	return 0;
1371d918647SAlex Vesker }
1381d918647SAlex Vesker 
1391d918647SAlex Vesker int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev,
1401d918647SAlex Vesker 				enum fs_flow_table_type type,
1411d918647SAlex Vesker 				u32 table_id,
1421d918647SAlex Vesker 				struct mlx5dr_cmd_query_flow_table_details *output)
1431d918647SAlex Vesker {
1441d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {};
1451d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {};
1461d918647SAlex Vesker 	int err;
1471d918647SAlex Vesker 
1481d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, opcode,
1491d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_FLOW_TABLE);
1501d918647SAlex Vesker 
1511d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, table_type, type);
1521d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, table_id, table_id);
1531d918647SAlex Vesker 
1547ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(dev, query_flow_table, in, out);
1551d918647SAlex Vesker 	if (err)
1561d918647SAlex Vesker 		return err;
1571d918647SAlex Vesker 
1581d918647SAlex Vesker 	output->status = MLX5_GET(query_flow_table_out, out, status);
1591d918647SAlex Vesker 	output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level);
1601d918647SAlex Vesker 
1611d918647SAlex Vesker 	output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out,
1621d918647SAlex Vesker 						 flow_table_context.sw_owner_icm_root_1);
1631d918647SAlex Vesker 	output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out,
1641d918647SAlex Vesker 						 flow_table_context.sw_owner_icm_root_0);
1651d918647SAlex Vesker 
1661d918647SAlex Vesker 	return 0;
1671d918647SAlex Vesker }
1681d918647SAlex Vesker 
1691d918647SAlex Vesker int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev)
1701d918647SAlex Vesker {
1711d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {};
1721d918647SAlex Vesker 
1731d918647SAlex Vesker 	MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING);
1741d918647SAlex Vesker 
1757ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, sync_steering, in);
1761d918647SAlex Vesker }
1771d918647SAlex Vesker 
1781d918647SAlex Vesker int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev,
1791d918647SAlex Vesker 					u32 table_type,
1801d918647SAlex Vesker 					u32 table_id,
1811d918647SAlex Vesker 					u32 group_id,
1821d918647SAlex Vesker 					u32 modify_header_id,
1831d918647SAlex Vesker 					u32 vport_id)
1841d918647SAlex Vesker {
1851d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
1861d918647SAlex Vesker 	void *in_flow_context;
1871d918647SAlex Vesker 	unsigned int inlen;
1881d918647SAlex Vesker 	void *in_dests;
1891d918647SAlex Vesker 	u32 *in;
1901d918647SAlex Vesker 	int err;
1911d918647SAlex Vesker 
1921d918647SAlex Vesker 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
1931d918647SAlex Vesker 		1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */
1941d918647SAlex Vesker 
1951d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
1961d918647SAlex Vesker 	if (!in)
1971d918647SAlex Vesker 		return -ENOMEM;
1981d918647SAlex Vesker 
1991d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
2001d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, table_type, table_type);
2011d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, table_id, table_id);
2021d918647SAlex Vesker 
2031d918647SAlex Vesker 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
2041d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
2051d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, modify_header_id, modify_header_id);
2061d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
2071d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, action,
2081d918647SAlex Vesker 		 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
2091d918647SAlex Vesker 		 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR);
2101d918647SAlex Vesker 
2111d918647SAlex Vesker 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
2121d918647SAlex Vesker 	MLX5_SET(dest_format_struct, in_dests, destination_type,
2131d918647SAlex Vesker 		 MLX5_FLOW_DESTINATION_TYPE_VPORT);
2141d918647SAlex Vesker 	MLX5_SET(dest_format_struct, in_dests, destination_id, vport_id);
2151d918647SAlex Vesker 
2161d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
2171d918647SAlex Vesker 	kvfree(in);
2181d918647SAlex Vesker 
2191d918647SAlex Vesker 	return err;
2201d918647SAlex Vesker }
2211d918647SAlex Vesker 
2221d918647SAlex Vesker int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev,
2231d918647SAlex Vesker 				    u32 table_type,
2241d918647SAlex Vesker 				    u32 table_id)
2251d918647SAlex Vesker {
2261d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
2271d918647SAlex Vesker 
2281d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
2291d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, table_type, table_type);
2301d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, table_id, table_id);
2311d918647SAlex Vesker 
2327ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, delete_fte, in);
2331d918647SAlex Vesker }
2341d918647SAlex Vesker 
2351d918647SAlex Vesker int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev,
2361d918647SAlex Vesker 				   u32 table_type,
2371d918647SAlex Vesker 				   u8 num_of_actions,
2381d918647SAlex Vesker 				   u64 *actions,
2391d918647SAlex Vesker 				   u32 *modify_header_id)
2401d918647SAlex Vesker {
2411d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
2421d918647SAlex Vesker 	void *p_actions;
2431d918647SAlex Vesker 	u32 inlen;
2441d918647SAlex Vesker 	u32 *in;
2451d918647SAlex Vesker 	int err;
2461d918647SAlex Vesker 
2471d918647SAlex Vesker 	inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) +
2481d918647SAlex Vesker 		 num_of_actions * sizeof(u64);
2491d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
2501d918647SAlex Vesker 	if (!in)
2511d918647SAlex Vesker 		return -ENOMEM;
2521d918647SAlex Vesker 
2531d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, opcode,
2541d918647SAlex Vesker 		 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
2551d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
2561d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions);
2571d918647SAlex Vesker 	p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
2581d918647SAlex Vesker 	memcpy(p_actions, actions, num_of_actions * sizeof(u64));
2591d918647SAlex Vesker 
2601d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
2611d918647SAlex Vesker 	if (err)
2621d918647SAlex Vesker 		goto out;
2631d918647SAlex Vesker 
2641d918647SAlex Vesker 	*modify_header_id = MLX5_GET(alloc_modify_header_context_out, out,
2651d918647SAlex Vesker 				     modify_header_id);
2661d918647SAlex Vesker out:
2671d918647SAlex Vesker 	kvfree(in);
2681d918647SAlex Vesker 	return err;
2691d918647SAlex Vesker }
2701d918647SAlex Vesker 
2711d918647SAlex Vesker int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev,
2721d918647SAlex Vesker 				     u32 modify_header_id)
2731d918647SAlex Vesker {
2741d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
2751d918647SAlex Vesker 
2761d918647SAlex Vesker 	MLX5_SET(dealloc_modify_header_context_in, in, opcode,
2771d918647SAlex Vesker 		 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
2781d918647SAlex Vesker 	MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
2791d918647SAlex Vesker 		 modify_header_id);
2801d918647SAlex Vesker 
2817ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, dealloc_modify_header_context, in);
2821d918647SAlex Vesker }
2831d918647SAlex Vesker 
2841d918647SAlex Vesker int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
2851d918647SAlex Vesker 				       u32 table_type,
2861d918647SAlex Vesker 				       u32 table_id,
2871d918647SAlex Vesker 				       u32 *group_id)
2881d918647SAlex Vesker {
2891d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
2901d918647SAlex Vesker 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
2911d918647SAlex Vesker 	u32 *in;
2921d918647SAlex Vesker 	int err;
2931d918647SAlex Vesker 
294b7f86258SRoi Dayan 	in = kvzalloc(inlen, GFP_KERNEL);
2951d918647SAlex Vesker 	if (!in)
2961d918647SAlex Vesker 		return -ENOMEM;
2971d918647SAlex Vesker 
2981d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
2991d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, table_type, table_type);
3001d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, table_id, table_id);
3011d918647SAlex Vesker 
3027ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
3031d918647SAlex Vesker 	if (err)
3041d918647SAlex Vesker 		goto out;
3051d918647SAlex Vesker 
3061d918647SAlex Vesker 	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
3071d918647SAlex Vesker 
3081d918647SAlex Vesker out:
309b7f86258SRoi Dayan 	kvfree(in);
3101d918647SAlex Vesker 	return err;
3111d918647SAlex Vesker }
3121d918647SAlex Vesker 
3131d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev,
3141d918647SAlex Vesker 				  u32 table_type,
3151d918647SAlex Vesker 				  u32 table_id,
3161d918647SAlex Vesker 				  u32 group_id)
3171d918647SAlex Vesker {
3181d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
3191d918647SAlex Vesker 
3207ba294e4SLeon Romanovsky 	MLX5_SET(destroy_flow_group_in, in, opcode,
3217ba294e4SLeon Romanovsky 		 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
3221d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, table_type, table_type);
3231d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
3241d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
3251d918647SAlex Vesker 
3267ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
3271d918647SAlex Vesker }
3281d918647SAlex Vesker 
3291d918647SAlex Vesker int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev,
330cc78dbd7SAlex Vesker 				 struct mlx5dr_cmd_create_flow_table_attr *attr,
3311d918647SAlex Vesker 				 u64 *fdb_rx_icm_addr,
3321d918647SAlex Vesker 				 u32 *table_id)
3331d918647SAlex Vesker {
3341d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
3351d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
3361d918647SAlex Vesker 	void *ft_mdev;
3371d918647SAlex Vesker 	int err;
3381d918647SAlex Vesker 
3391d918647SAlex Vesker 	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
340cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, table_type, attr->table_type);
3411d918647SAlex Vesker 
3421d918647SAlex Vesker 	ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
343cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, termination_table, attr->term_tbl);
344cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, sw_owner, attr->sw_owner);
345cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, level, attr->level);
3461d918647SAlex Vesker 
347cc78dbd7SAlex Vesker 	if (attr->sw_owner) {
3481d918647SAlex Vesker 		/* icm_addr_0 used for FDB RX / NIC TX / NIC_RX
3491d918647SAlex Vesker 		 * icm_addr_1 used for FDB TX
3501d918647SAlex Vesker 		 */
351cc78dbd7SAlex Vesker 		if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) {
3521d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
353cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_rx);
354cc78dbd7SAlex Vesker 		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) {
3551d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
356cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_tx);
357cc78dbd7SAlex Vesker 		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB) {
3581d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
359cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_rx);
3601d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
361cc78dbd7SAlex Vesker 				   sw_owner_icm_root_1, attr->icm_addr_tx);
3621d918647SAlex Vesker 		}
3631d918647SAlex Vesker 	}
3641d918647SAlex Vesker 
365cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
366cc78dbd7SAlex Vesker 		 attr->decap_en);
367cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en,
368cc78dbd7SAlex Vesker 		 attr->reformat_en);
369cc78dbd7SAlex Vesker 
3707ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out);
3711d918647SAlex Vesker 	if (err)
3721d918647SAlex Vesker 		return err;
3731d918647SAlex Vesker 
3741d918647SAlex Vesker 	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
375cc78dbd7SAlex Vesker 	if (!attr->sw_owner && attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB &&
376cc78dbd7SAlex Vesker 	    fdb_rx_icm_addr)
3771d918647SAlex Vesker 		*fdb_rx_icm_addr =
3781d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) |
3791d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 |
3801d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40;
3811d918647SAlex Vesker 
3821d918647SAlex Vesker 	return 0;
3831d918647SAlex Vesker }
3841d918647SAlex Vesker 
3851d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev,
3861d918647SAlex Vesker 				  u32 table_id,
3871d918647SAlex Vesker 				  u32 table_type)
3881d918647SAlex Vesker {
3891d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
3901d918647SAlex Vesker 
3911d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, opcode,
3921d918647SAlex Vesker 		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
3931d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, table_type, table_type);
3941d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
3951d918647SAlex Vesker 
3967ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, destroy_flow_table, in);
3971d918647SAlex Vesker }
3981d918647SAlex Vesker 
3991d918647SAlex Vesker int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
4001d918647SAlex Vesker 				   enum mlx5_reformat_ctx_type rt,
4011d918647SAlex Vesker 				   size_t reformat_size,
4021d918647SAlex Vesker 				   void *reformat_data,
4031d918647SAlex Vesker 				   u32 *reformat_id)
4041d918647SAlex Vesker {
4051d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
4061d918647SAlex Vesker 	size_t inlen, cmd_data_sz, cmd_total_sz;
4071d918647SAlex Vesker 	void *prctx;
4081d918647SAlex Vesker 	void *pdata;
4091d918647SAlex Vesker 	void *in;
4101d918647SAlex Vesker 	int err;
4111d918647SAlex Vesker 
4121d918647SAlex Vesker 	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
4131d918647SAlex Vesker 	cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in,
4141d918647SAlex Vesker 					packet_reformat_context.reformat_data);
4151d918647SAlex Vesker 	inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4);
4161d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
4171d918647SAlex Vesker 	if (!in)
4181d918647SAlex Vesker 		return -ENOMEM;
4191d918647SAlex Vesker 
4201d918647SAlex Vesker 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
4211d918647SAlex Vesker 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
4221d918647SAlex Vesker 
4231d918647SAlex Vesker 	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context);
4241d918647SAlex Vesker 	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
4251d918647SAlex Vesker 
4261d918647SAlex Vesker 	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt);
4271d918647SAlex Vesker 	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size);
4281d918647SAlex Vesker 	memcpy(pdata, reformat_data, reformat_size);
4291d918647SAlex Vesker 
4301d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
4311d918647SAlex Vesker 	if (err)
4321d918647SAlex Vesker 		return err;
4331d918647SAlex Vesker 
4341d918647SAlex Vesker 	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
4351d918647SAlex Vesker 	kvfree(in);
4361d918647SAlex Vesker 
4371d918647SAlex Vesker 	return err;
4381d918647SAlex Vesker }
4391d918647SAlex Vesker 
4401d918647SAlex Vesker void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev,
4411d918647SAlex Vesker 				     u32 reformat_id)
4421d918647SAlex Vesker {
4431d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
4441d918647SAlex Vesker 
4451d918647SAlex Vesker 	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
4461d918647SAlex Vesker 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
4471d918647SAlex Vesker 	MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
4481d918647SAlex Vesker 		 reformat_id);
4491d918647SAlex Vesker 
4507ba294e4SLeon Romanovsky 	mlx5_cmd_exec_in(mdev, dealloc_packet_reformat_context, in);
4511d918647SAlex Vesker }
4521d918647SAlex Vesker 
4531d918647SAlex Vesker int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num,
4541d918647SAlex Vesker 			 u16 index, struct mlx5dr_cmd_gid_attr *attr)
4551d918647SAlex Vesker {
4561d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {};
4571d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {};
4581d918647SAlex Vesker 	int err;
4591d918647SAlex Vesker 
4601d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, opcode,
4611d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_ROCE_ADDRESS);
4621d918647SAlex Vesker 
4631d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, roce_address_index, index);
4641d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num);
4651d918647SAlex Vesker 
4667ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, query_roce_address, in, out);
4671d918647SAlex Vesker 	if (err)
4681d918647SAlex Vesker 		return err;
4691d918647SAlex Vesker 
4701d918647SAlex Vesker 	memcpy(&attr->gid,
4711d918647SAlex Vesker 	       MLX5_ADDR_OF(query_roce_address_out,
4721d918647SAlex Vesker 			    out, roce_address.source_l3_address),
4731d918647SAlex Vesker 	       sizeof(attr->gid));
4741d918647SAlex Vesker 	memcpy(attr->mac,
4751d918647SAlex Vesker 	       MLX5_ADDR_OF(query_roce_address_out, out,
4761d918647SAlex Vesker 			    roce_address.source_mac_47_32),
4771d918647SAlex Vesker 	       sizeof(attr->mac));
4781d918647SAlex Vesker 
4791d918647SAlex Vesker 	if (MLX5_GET(query_roce_address_out, out,
4801d918647SAlex Vesker 		     roce_address.roce_version) == MLX5_ROCE_VERSION_2)
4811d918647SAlex Vesker 		attr->roce_ver = MLX5_ROCE_VERSION_2;
4821d918647SAlex Vesker 	else
4831d918647SAlex Vesker 		attr->roce_ver = MLX5_ROCE_VERSION_1;
4841d918647SAlex Vesker 
4851d918647SAlex Vesker 	return 0;
4861d918647SAlex Vesker }
4876de03d2dSErez Shitrit 
4886de03d2dSErez Shitrit static int mlx5dr_cmd_set_extended_dest(struct mlx5_core_dev *dev,
4896de03d2dSErez Shitrit 					struct mlx5dr_cmd_fte_info *fte,
4906de03d2dSErez Shitrit 					bool *extended_dest)
4916de03d2dSErez Shitrit {
4926de03d2dSErez Shitrit 	int fw_log_max_fdb_encap_uplink = MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink);
4936de03d2dSErez Shitrit 	int num_fwd_destinations = 0;
4946de03d2dSErez Shitrit 	int num_encap = 0;
4956de03d2dSErez Shitrit 	int i;
4966de03d2dSErez Shitrit 
4976de03d2dSErez Shitrit 	*extended_dest = false;
4986de03d2dSErez Shitrit 	if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
4996de03d2dSErez Shitrit 		return 0;
5006de03d2dSErez Shitrit 	for (i = 0; i < fte->dests_size; i++) {
5016de03d2dSErez Shitrit 		if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
5026de03d2dSErez Shitrit 			continue;
5036de03d2dSErez Shitrit 		if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
5046de03d2dSErez Shitrit 		    fte->dest_arr[i].vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
5056de03d2dSErez Shitrit 			num_encap++;
5066de03d2dSErez Shitrit 		num_fwd_destinations++;
5076de03d2dSErez Shitrit 	}
5086de03d2dSErez Shitrit 
5096de03d2dSErez Shitrit 	if (num_fwd_destinations > 1 && num_encap > 0)
5106de03d2dSErez Shitrit 		*extended_dest = true;
5116de03d2dSErez Shitrit 
5126de03d2dSErez Shitrit 	if (*extended_dest && !fw_log_max_fdb_encap_uplink) {
5136de03d2dSErez Shitrit 		mlx5_core_warn(dev, "FW does not support extended destination");
5146de03d2dSErez Shitrit 		return -EOPNOTSUPP;
5156de03d2dSErez Shitrit 	}
5166de03d2dSErez Shitrit 	if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) {
5176de03d2dSErez Shitrit 		mlx5_core_warn(dev, "FW does not support more than %d encaps",
5186de03d2dSErez Shitrit 			       1 << fw_log_max_fdb_encap_uplink);
5196de03d2dSErez Shitrit 		return -EOPNOTSUPP;
5206de03d2dSErez Shitrit 	}
5216de03d2dSErez Shitrit 
5226de03d2dSErez Shitrit 	return 0;
5236de03d2dSErez Shitrit }
5246de03d2dSErez Shitrit 
5256de03d2dSErez Shitrit int mlx5dr_cmd_set_fte(struct mlx5_core_dev *dev,
5266de03d2dSErez Shitrit 		       int opmod, int modify_mask,
5276de03d2dSErez Shitrit 		       struct mlx5dr_cmd_ft_info *ft,
5286de03d2dSErez Shitrit 		       u32 group_id,
5296de03d2dSErez Shitrit 		       struct mlx5dr_cmd_fte_info *fte)
5306de03d2dSErez Shitrit {
5316de03d2dSErez Shitrit 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
5326de03d2dSErez Shitrit 	void *in_flow_context, *vlan;
5336de03d2dSErez Shitrit 	bool extended_dest = false;
5346de03d2dSErez Shitrit 	void *in_match_value;
5356de03d2dSErez Shitrit 	unsigned int inlen;
5366de03d2dSErez Shitrit 	int dst_cnt_size;
5376de03d2dSErez Shitrit 	void *in_dests;
5386de03d2dSErez Shitrit 	u32 *in;
5396de03d2dSErez Shitrit 	int err;
5406de03d2dSErez Shitrit 	int i;
5416de03d2dSErez Shitrit 
5426de03d2dSErez Shitrit 	if (mlx5dr_cmd_set_extended_dest(dev, fte, &extended_dest))
5436de03d2dSErez Shitrit 		return -EOPNOTSUPP;
5446de03d2dSErez Shitrit 
5456de03d2dSErez Shitrit 	if (!extended_dest)
5466de03d2dSErez Shitrit 		dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct);
5476de03d2dSErez Shitrit 	else
5486de03d2dSErez Shitrit 		dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format);
5496de03d2dSErez Shitrit 
5506de03d2dSErez Shitrit 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size;
5516de03d2dSErez Shitrit 	in = kvzalloc(inlen, GFP_KERNEL);
5526de03d2dSErez Shitrit 	if (!in)
5536de03d2dSErez Shitrit 		return -ENOMEM;
5546de03d2dSErez Shitrit 
5556de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
5566de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, op_mod, opmod);
5576de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
5586de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, table_type, ft->type);
5596de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, table_id, ft->id);
5606de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, flow_index, fte->index);
5616de03d2dSErez Shitrit 	if (ft->vport) {
5626de03d2dSErez Shitrit 		MLX5_SET(set_fte_in, in, vport_number, ft->vport);
5636de03d2dSErez Shitrit 		MLX5_SET(set_fte_in, in, other_vport, 1);
5646de03d2dSErez Shitrit 	}
5656de03d2dSErez Shitrit 
5666de03d2dSErez Shitrit 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
5676de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
5686de03d2dSErez Shitrit 
5696de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, flow_tag,
5706de03d2dSErez Shitrit 		 fte->flow_context.flow_tag);
5716de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, flow_source,
5726de03d2dSErez Shitrit 		 fte->flow_context.flow_source);
5736de03d2dSErez Shitrit 
5746de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, extended_destination,
5756de03d2dSErez Shitrit 		 extended_dest);
5766de03d2dSErez Shitrit 	if (extended_dest) {
5776de03d2dSErez Shitrit 		u32 action;
5786de03d2dSErez Shitrit 
5796de03d2dSErez Shitrit 		action = fte->action.action &
5806de03d2dSErez Shitrit 			~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
5816de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, action, action);
5826de03d2dSErez Shitrit 	} else {
5836de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, action,
5846de03d2dSErez Shitrit 			 fte->action.action);
5856de03d2dSErez Shitrit 		if (fte->action.pkt_reformat)
5866de03d2dSErez Shitrit 			MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
5876de03d2dSErez Shitrit 				 fte->action.pkt_reformat->id);
5886de03d2dSErez Shitrit 	}
5896de03d2dSErez Shitrit 	if (fte->action.modify_hdr)
5906de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, modify_header_id,
5916de03d2dSErez Shitrit 			 fte->action.modify_hdr->id);
5926de03d2dSErez Shitrit 
5936de03d2dSErez Shitrit 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan);
5946de03d2dSErez Shitrit 
5956de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype);
5966de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid);
5976de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio);
5986de03d2dSErez Shitrit 
5996de03d2dSErez Shitrit 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2);
6006de03d2dSErez Shitrit 
6016de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype);
6026de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid);
6036de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio);
6046de03d2dSErez Shitrit 
6056de03d2dSErez Shitrit 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
6066de03d2dSErez Shitrit 				      match_value);
6076de03d2dSErez Shitrit 	memcpy(in_match_value, fte->val, sizeof(u32) * MLX5_ST_SZ_DW_MATCH_PARAM);
6086de03d2dSErez Shitrit 
6096de03d2dSErez Shitrit 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
6106de03d2dSErez Shitrit 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
6116de03d2dSErez Shitrit 		int list_size = 0;
6126de03d2dSErez Shitrit 
6136de03d2dSErez Shitrit 		for (i = 0; i < fte->dests_size; i++) {
6146de03d2dSErez Shitrit 			unsigned int id, type = fte->dest_arr[i].type;
6156de03d2dSErez Shitrit 
6166de03d2dSErez Shitrit 			if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
6176de03d2dSErez Shitrit 				continue;
6186de03d2dSErez Shitrit 
6196de03d2dSErez Shitrit 			switch (type) {
6206de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
6216de03d2dSErez Shitrit 				id = fte->dest_arr[i].ft_num;
6226de03d2dSErez Shitrit 				type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
6236de03d2dSErez Shitrit 				break;
6246de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
6256de03d2dSErez Shitrit 				id = fte->dest_arr[i].ft_id;
6266de03d2dSErez Shitrit 				break;
6276de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
6286de03d2dSErez Shitrit 				id = fte->dest_arr[i].vport.num;
6296de03d2dSErez Shitrit 				MLX5_SET(dest_format_struct, in_dests,
6306de03d2dSErez Shitrit 					 destination_eswitch_owner_vhca_id_valid,
6316de03d2dSErez Shitrit 					 !!(fte->dest_arr[i].vport.flags &
6326de03d2dSErez Shitrit 					    MLX5_FLOW_DEST_VPORT_VHCA_ID));
6336de03d2dSErez Shitrit 				MLX5_SET(dest_format_struct, in_dests,
6346de03d2dSErez Shitrit 					 destination_eswitch_owner_vhca_id,
6356de03d2dSErez Shitrit 					 fte->dest_arr[i].vport.vhca_id);
6366de03d2dSErez Shitrit 				if (extended_dest && (fte->dest_arr[i].vport.flags &
6376de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID)) {
6386de03d2dSErez Shitrit 					MLX5_SET(dest_format_struct, in_dests,
6396de03d2dSErez Shitrit 						 packet_reformat,
6406de03d2dSErez Shitrit 						 !!(fte->dest_arr[i].vport.flags &
6416de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID));
6426de03d2dSErez Shitrit 					MLX5_SET(extended_dest_format, in_dests,
6436de03d2dSErez Shitrit 						 packet_reformat_id,
6446de03d2dSErez Shitrit 						 fte->dest_arr[i].vport.reformat_id);
6456de03d2dSErez Shitrit 				}
6466de03d2dSErez Shitrit 				break;
6476de03d2dSErez Shitrit 			default:
6486de03d2dSErez Shitrit 				id = fte->dest_arr[i].tir_num;
6496de03d2dSErez Shitrit 			}
6506de03d2dSErez Shitrit 
6516de03d2dSErez Shitrit 			MLX5_SET(dest_format_struct, in_dests, destination_type,
6526de03d2dSErez Shitrit 				 type);
6536de03d2dSErez Shitrit 			MLX5_SET(dest_format_struct, in_dests, destination_id, id);
6546de03d2dSErez Shitrit 			in_dests += dst_cnt_size;
6556de03d2dSErez Shitrit 			list_size++;
6566de03d2dSErez Shitrit 		}
6576de03d2dSErez Shitrit 
6586de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, destination_list_size,
6596de03d2dSErez Shitrit 			 list_size);
6606de03d2dSErez Shitrit 	}
6616de03d2dSErez Shitrit 
6626de03d2dSErez Shitrit 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
6636de03d2dSErez Shitrit 		int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev,
6646de03d2dSErez Shitrit 					log_max_flow_counter,
6656de03d2dSErez Shitrit 					ft->type));
6666de03d2dSErez Shitrit 		int list_size = 0;
6676de03d2dSErez Shitrit 
6686de03d2dSErez Shitrit 		for (i = 0; i < fte->dests_size; i++) {
6696de03d2dSErez Shitrit 			if (fte->dest_arr[i].type !=
6706de03d2dSErez Shitrit 			    MLX5_FLOW_DESTINATION_TYPE_COUNTER)
6716de03d2dSErez Shitrit 				continue;
6726de03d2dSErez Shitrit 
6736de03d2dSErez Shitrit 			MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
6746de03d2dSErez Shitrit 				 fte->dest_arr[i].counter_id);
6756de03d2dSErez Shitrit 			in_dests += dst_cnt_size;
6766de03d2dSErez Shitrit 			list_size++;
6776de03d2dSErez Shitrit 		}
6786de03d2dSErez Shitrit 		if (list_size > max_list_size) {
6796de03d2dSErez Shitrit 			err = -EINVAL;
6806de03d2dSErez Shitrit 			goto err_out;
6816de03d2dSErez Shitrit 		}
6826de03d2dSErez Shitrit 
6836de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
6846de03d2dSErez Shitrit 			 list_size);
6856de03d2dSErez Shitrit 	}
6866de03d2dSErez Shitrit 
6876de03d2dSErez Shitrit 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
6886de03d2dSErez Shitrit err_out:
6896de03d2dSErez Shitrit 	kvfree(in);
6906de03d2dSErez Shitrit 	return err;
6916de03d2dSErez Shitrit }
692