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 
887304d603SYevgeny Kliteynik static int dr_cmd_query_nic_vport_roce_en(struct mlx5_core_dev *mdev,
897304d603SYevgeny Kliteynik 					  u16 vport, bool *roce_en)
907304d603SYevgeny Kliteynik {
917304d603SYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
927304d603SYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
937304d603SYevgeny Kliteynik 	int err;
947304d603SYevgeny Kliteynik 
957304d603SYevgeny Kliteynik 	MLX5_SET(query_nic_vport_context_in, in, opcode,
967304d603SYevgeny Kliteynik 		 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
977304d603SYevgeny Kliteynik 	MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
987304d603SYevgeny Kliteynik 	MLX5_SET(query_nic_vport_context_in, in, other_vport, !!vport);
997304d603SYevgeny Kliteynik 
1007304d603SYevgeny Kliteynik 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
1017304d603SYevgeny Kliteynik 	if (err)
1027304d603SYevgeny Kliteynik 		return err;
1037304d603SYevgeny Kliteynik 
1047304d603SYevgeny Kliteynik 	*roce_en = MLX5_GET(query_nic_vport_context_out, out,
1057304d603SYevgeny Kliteynik 			    nic_vport_context.roce_en);
1067304d603SYevgeny Kliteynik 	return 0;
1077304d603SYevgeny Kliteynik }
1087304d603SYevgeny Kliteynik 
1091d918647SAlex Vesker int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
1101d918647SAlex Vesker 			    struct mlx5dr_cmd_caps *caps)
1111d918647SAlex Vesker {
1127304d603SYevgeny Kliteynik 	bool roce_en;
1137304d603SYevgeny Kliteynik 	int err;
1147304d603SYevgeny Kliteynik 
1151d918647SAlex Vesker 	caps->prio_tag_required	= MLX5_CAP_GEN(mdev, prio_tag_required);
1161d918647SAlex Vesker 	caps->eswitch_manager	= MLX5_CAP_GEN(mdev, eswitch_manager);
1171d918647SAlex Vesker 	caps->gvmi		= MLX5_CAP_GEN(mdev, vhca_id);
1181d918647SAlex Vesker 	caps->flex_protocols	= MLX5_CAP_GEN(mdev, flex_parser_protocols);
119d421e466SYevgeny Kliteynik 	caps->sw_format_ver	= MLX5_CAP_GEN(mdev, steering_format_version);
120*c7dd225bSYevgeny Kliteynik 	caps->roce_caps.fl_rc_qp_when_roce_disabled =
121*c7dd225bSYevgeny Kliteynik 		MLX5_CAP_GEN(mdev, fl_rc_qp_when_roce_disabled);
1221d918647SAlex Vesker 
1237304d603SYevgeny Kliteynik 	if (MLX5_CAP_GEN(mdev, roce)) {
1247304d603SYevgeny Kliteynik 		err = dr_cmd_query_nic_vport_roce_en(mdev, 0, &roce_en);
1257304d603SYevgeny Kliteynik 		if (err)
1267304d603SYevgeny Kliteynik 			return err;
1277304d603SYevgeny Kliteynik 
1287304d603SYevgeny Kliteynik 		caps->roce_caps.roce_en = roce_en;
129*c7dd225bSYevgeny Kliteynik 		caps->roce_caps.fl_rc_qp_when_roce_disabled |=
1307304d603SYevgeny Kliteynik 			MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_disabled);
1317304d603SYevgeny Kliteynik 		caps->roce_caps.fl_rc_qp_when_roce_enabled =
1327304d603SYevgeny Kliteynik 			MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_enabled);
1337304d603SYevgeny Kliteynik 	}
1347304d603SYevgeny Kliteynik 
135aeacb52aSYevgeny Kliteynik 	caps->isolate_vl_tc = MLX5_CAP_GEN(mdev, isolate_vl_tc_new);
136aeacb52aSYevgeny Kliteynik 
137b7ba743aSYevgeny Kliteynik 	caps->support_modify_argument =
138b7ba743aSYevgeny Kliteynik 		MLX5_CAP_GEN_64(mdev, general_obj_types) &
139b7ba743aSYevgeny Kliteynik 		MLX5_GENERAL_OBJ_TYPES_CAP_HEADER_MODIFY_ARGUMENT;
140b7ba743aSYevgeny Kliteynik 
141b7ba743aSYevgeny Kliteynik 	if (caps->support_modify_argument) {
142b7ba743aSYevgeny Kliteynik 		caps->log_header_modify_argument_granularity =
143b7ba743aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, log_header_modify_argument_granularity);
144b7ba743aSYevgeny Kliteynik 		caps->log_header_modify_argument_max_alloc =
145b7ba743aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, log_header_modify_argument_max_alloc);
146b7ba743aSYevgeny Kliteynik 	}
147b7ba743aSYevgeny Kliteynik 
148f59464e2SYevgeny Kliteynik 	/* geneve_tlv_option_0_exist is the indication of
149f59464e2SYevgeny Kliteynik 	 * STE support for lookup type flex_parser_ok
150f59464e2SYevgeny Kliteynik 	 */
151f59464e2SYevgeny Kliteynik 	caps->flex_parser_ok_bits_supp =
152f59464e2SYevgeny Kliteynik 		MLX5_CAP_FLOWTABLE(mdev,
153f59464e2SYevgeny Kliteynik 				   flow_table_properties_nic_receive.ft_field_support.geneve_tlv_option_0_exist);
154f59464e2SYevgeny Kliteynik 
1558a8a1023SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED) {
1561d918647SAlex Vesker 		caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
1571d918647SAlex Vesker 		caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1);
1581d918647SAlex Vesker 	}
1591d918647SAlex Vesker 
1608a8a1023SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED) {
1611d918647SAlex Vesker 		caps->flex_parser_id_icmpv6_dw0 =
1621d918647SAlex Vesker 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0);
1631d918647SAlex Vesker 		caps->flex_parser_id_icmpv6_dw1 =
1641d918647SAlex Vesker 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1);
1651d918647SAlex Vesker 	}
1661d918647SAlex Vesker 
1673442e033SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
1683442e033SYevgeny Kliteynik 		caps->flex_parser_id_geneve_tlv_option_0 =
1693442e033SYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_geneve_tlv_option_0);
1703442e033SYevgeny Kliteynik 
17135ba005dSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)
17235ba005dSYevgeny Kliteynik 		caps->flex_parser_id_mpls_over_gre =
17335ba005dSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_outer_first_mpls_over_gre);
17435ba005dSYevgeny Kliteynik 
175c3fb0e28SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)
17635ba005dSYevgeny Kliteynik 		caps->flex_parser_id_mpls_over_udp =
17735ba005dSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_outer_first_mpls_over_udp_label);
17835ba005dSYevgeny Kliteynik 
179df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_0_ENABLED)
180df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_dw_0 =
181df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_dw_0);
182df9dd15aSYevgeny Kliteynik 
183df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_TEID_ENABLED)
184df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_teid =
185df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_teid);
186df9dd15aSYevgeny Kliteynik 
187df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_2_ENABLED)
188df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_dw_2 =
189df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_dw_2);
190df9dd15aSYevgeny Kliteynik 
191df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_FIRST_EXT_DW_0_ENABLED)
192df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_first_ext_dw_0 =
193df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_first_ext_dw_0);
194df9dd15aSYevgeny Kliteynik 
1951d918647SAlex Vesker 	caps->nic_rx_drop_address =
1961d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address);
1971d918647SAlex Vesker 	caps->nic_tx_drop_address =
1981d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address);
1991d918647SAlex Vesker 	caps->nic_tx_allow_address =
2001d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address);
2011d918647SAlex Vesker 
20264f45c0fSYevgeny Kliteynik 	caps->rx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner_v2);
20364f45c0fSYevgeny Kliteynik 	caps->tx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner_v2);
2041d918647SAlex Vesker 
20564f45c0fSYevgeny Kliteynik 	if (!caps->rx_sw_owner_v2)
20664f45c0fSYevgeny Kliteynik 		caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner);
20764f45c0fSYevgeny Kliteynik 	if (!caps->tx_sw_owner_v2)
2081d918647SAlex Vesker 		caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner);
2091d918647SAlex Vesker 
21064f45c0fSYevgeny Kliteynik 	caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level);
21164f45c0fSYevgeny Kliteynik 
2121d918647SAlex Vesker 	caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size);
2131d918647SAlex Vesker 	caps->hdr_modify_icm_addr =
2141d918647SAlex Vesker 		MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address);
2151d918647SAlex Vesker 
216108ff821SYevgeny Kliteynik 	caps->log_modify_pattern_icm_size =
217108ff821SYevgeny Kliteynik 		MLX5_CAP_DEV_MEM(mdev, log_header_modify_pattern_sw_icm_size);
218108ff821SYevgeny Kliteynik 
219108ff821SYevgeny Kliteynik 	caps->hdr_modify_pattern_icm_addr =
220108ff821SYevgeny Kliteynik 		MLX5_CAP64_DEV_MEM(mdev, header_modify_pattern_sw_icm_start_address);
221108ff821SYevgeny Kliteynik 
2221d918647SAlex Vesker 	caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port);
2231d918647SAlex Vesker 
224dd4acb2aSYevgeny Kliteynik 	caps->is_ecpf = mlx5_core_is_ecpf_esw_manager(mdev);
225dd4acb2aSYevgeny Kliteynik 
2261d918647SAlex Vesker 	return 0;
2271d918647SAlex Vesker }
2281d918647SAlex Vesker 
2291d918647SAlex Vesker int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev,
2301d918647SAlex Vesker 				enum fs_flow_table_type type,
2311d918647SAlex Vesker 				u32 table_id,
2321d918647SAlex Vesker 				struct mlx5dr_cmd_query_flow_table_details *output)
2331d918647SAlex Vesker {
2341d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {};
2351d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {};
2361d918647SAlex Vesker 	int err;
2371d918647SAlex Vesker 
2381d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, opcode,
2391d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_FLOW_TABLE);
2401d918647SAlex Vesker 
2411d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, table_type, type);
2421d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, table_id, table_id);
2431d918647SAlex Vesker 
2447ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(dev, query_flow_table, in, out);
2451d918647SAlex Vesker 	if (err)
2461d918647SAlex Vesker 		return err;
2471d918647SAlex Vesker 
2481d918647SAlex Vesker 	output->status = MLX5_GET(query_flow_table_out, out, status);
2491d918647SAlex Vesker 	output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level);
2501d918647SAlex Vesker 
2511d918647SAlex Vesker 	output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out,
2521d918647SAlex Vesker 						 flow_table_context.sw_owner_icm_root_1);
2531d918647SAlex Vesker 	output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out,
2541d918647SAlex Vesker 						 flow_table_context.sw_owner_icm_root_0);
2551d918647SAlex Vesker 
2561d918647SAlex Vesker 	return 0;
2571d918647SAlex Vesker }
2581d918647SAlex Vesker 
2591ab6dc35SYevgeny Kliteynik int mlx5dr_cmd_query_flow_sampler(struct mlx5_core_dev *dev,
2601ab6dc35SYevgeny Kliteynik 				  u32 sampler_id,
2611ab6dc35SYevgeny Kliteynik 				  u64 *rx_icm_addr,
2621ab6dc35SYevgeny Kliteynik 				  u64 *tx_icm_addr)
2631ab6dc35SYevgeny Kliteynik {
2641ab6dc35SYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(query_sampler_obj_out)] = {};
2651ab6dc35SYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
2661ab6dc35SYevgeny Kliteynik 	void *attr;
2671ab6dc35SYevgeny Kliteynik 	int ret;
2681ab6dc35SYevgeny Kliteynik 
2691ab6dc35SYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
2701ab6dc35SYevgeny Kliteynik 		 MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
2711ab6dc35SYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
2721ab6dc35SYevgeny Kliteynik 		 MLX5_GENERAL_OBJECT_TYPES_SAMPLER);
2731ab6dc35SYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, sampler_id);
2741ab6dc35SYevgeny Kliteynik 
2751ab6dc35SYevgeny Kliteynik 	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
2761ab6dc35SYevgeny Kliteynik 	if (ret)
2771ab6dc35SYevgeny Kliteynik 		return ret;
2781ab6dc35SYevgeny Kliteynik 
2791ab6dc35SYevgeny Kliteynik 	attr = MLX5_ADDR_OF(query_sampler_obj_out, out, sampler_object);
2801ab6dc35SYevgeny Kliteynik 
2811ab6dc35SYevgeny Kliteynik 	*rx_icm_addr = MLX5_GET64(sampler_obj, attr,
2821ab6dc35SYevgeny Kliteynik 				  sw_steering_icm_address_rx);
2831ab6dc35SYevgeny Kliteynik 	*tx_icm_addr = MLX5_GET64(sampler_obj, attr,
2841ab6dc35SYevgeny Kliteynik 				  sw_steering_icm_address_tx);
2851ab6dc35SYevgeny Kliteynik 
2861ab6dc35SYevgeny Kliteynik 	return 0;
2871ab6dc35SYevgeny Kliteynik }
2881ab6dc35SYevgeny Kliteynik 
2891d918647SAlex Vesker int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev)
2901d918647SAlex Vesker {
2911d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {};
2921d918647SAlex Vesker 
293c4193a12SYevgeny Kliteynik 	/* Skip SYNC in case the device is internal error state.
294c4193a12SYevgeny Kliteynik 	 * Besides a device error, this also happens when we're
295c4193a12SYevgeny Kliteynik 	 * in fast teardown
296c4193a12SYevgeny Kliteynik 	 */
297c4193a12SYevgeny Kliteynik 	if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
298c4193a12SYevgeny Kliteynik 		return 0;
299c4193a12SYevgeny Kliteynik 
3001d918647SAlex Vesker 	MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING);
3011d918647SAlex Vesker 
3027ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, sync_steering, in);
3031d918647SAlex Vesker }
3041d918647SAlex Vesker 
3051d918647SAlex Vesker int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev,
3061d918647SAlex Vesker 					u32 table_type,
3071d918647SAlex Vesker 					u32 table_id,
3081d918647SAlex Vesker 					u32 group_id,
3091d918647SAlex Vesker 					u32 modify_header_id,
310f9f93bd5SYevgeny Kliteynik 					u16 vport)
3111d918647SAlex Vesker {
3121d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
3131d918647SAlex Vesker 	void *in_flow_context;
3141d918647SAlex Vesker 	unsigned int inlen;
3151d918647SAlex Vesker 	void *in_dests;
3161d918647SAlex Vesker 	u32 *in;
3171d918647SAlex Vesker 	int err;
3181d918647SAlex Vesker 
3191d918647SAlex Vesker 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
3201d918647SAlex Vesker 		1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */
3211d918647SAlex Vesker 
3221d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
3231d918647SAlex Vesker 	if (!in)
3241d918647SAlex Vesker 		return -ENOMEM;
3251d918647SAlex Vesker 
3261d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
3271d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, table_type, table_type);
3281d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, table_id, table_id);
3291d918647SAlex Vesker 
3301d918647SAlex Vesker 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
3311d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
3321d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, modify_header_id, modify_header_id);
3331d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
3341d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, action,
3351d918647SAlex Vesker 		 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3361d918647SAlex Vesker 		 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR);
3371d918647SAlex Vesker 
3381d918647SAlex Vesker 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
3391d918647SAlex Vesker 	MLX5_SET(dest_format_struct, in_dests, destination_type,
340d639af62SMark Bloch 		 MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT);
341f9f93bd5SYevgeny Kliteynik 	MLX5_SET(dest_format_struct, in_dests, destination_id, vport);
3421d918647SAlex Vesker 
3431d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
3441d918647SAlex Vesker 	kvfree(in);
3451d918647SAlex Vesker 
3461d918647SAlex Vesker 	return err;
3471d918647SAlex Vesker }
3481d918647SAlex Vesker 
3491d918647SAlex Vesker int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev,
3501d918647SAlex Vesker 				    u32 table_type,
3511d918647SAlex Vesker 				    u32 table_id)
3521d918647SAlex Vesker {
3531d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
3541d918647SAlex Vesker 
3551d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
3561d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, table_type, table_type);
3571d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, table_id, table_id);
3581d918647SAlex Vesker 
3597ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, delete_fte, in);
3601d918647SAlex Vesker }
3611d918647SAlex Vesker 
3621d918647SAlex Vesker int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev,
3631d918647SAlex Vesker 				   u32 table_type,
3641d918647SAlex Vesker 				   u8 num_of_actions,
3651d918647SAlex Vesker 				   u64 *actions,
3661d918647SAlex Vesker 				   u32 *modify_header_id)
3671d918647SAlex Vesker {
3681d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
3691d918647SAlex Vesker 	void *p_actions;
3701d918647SAlex Vesker 	u32 inlen;
3711d918647SAlex Vesker 	u32 *in;
3721d918647SAlex Vesker 	int err;
3731d918647SAlex Vesker 
3741d918647SAlex Vesker 	inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) +
3751d918647SAlex Vesker 		 num_of_actions * sizeof(u64);
3761d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
3771d918647SAlex Vesker 	if (!in)
3781d918647SAlex Vesker 		return -ENOMEM;
3791d918647SAlex Vesker 
3801d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, opcode,
3811d918647SAlex Vesker 		 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
3821d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
3831d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions);
3841d918647SAlex Vesker 	p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
3851d918647SAlex Vesker 	memcpy(p_actions, actions, num_of_actions * sizeof(u64));
3861d918647SAlex Vesker 
3871d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
3881d918647SAlex Vesker 	if (err)
3891d918647SAlex Vesker 		goto out;
3901d918647SAlex Vesker 
3911d918647SAlex Vesker 	*modify_header_id = MLX5_GET(alloc_modify_header_context_out, out,
3921d918647SAlex Vesker 				     modify_header_id);
3931d918647SAlex Vesker out:
3941d918647SAlex Vesker 	kvfree(in);
3951d918647SAlex Vesker 	return err;
3961d918647SAlex Vesker }
3971d918647SAlex Vesker 
3981d918647SAlex Vesker int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev,
3991d918647SAlex Vesker 				     u32 modify_header_id)
4001d918647SAlex Vesker {
4011d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
4021d918647SAlex Vesker 
4031d918647SAlex Vesker 	MLX5_SET(dealloc_modify_header_context_in, in, opcode,
4041d918647SAlex Vesker 		 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
4051d918647SAlex Vesker 	MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
4061d918647SAlex Vesker 		 modify_header_id);
4071d918647SAlex Vesker 
4087ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, dealloc_modify_header_context, in);
4091d918647SAlex Vesker }
4101d918647SAlex Vesker 
4111d918647SAlex Vesker int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
4121d918647SAlex Vesker 				       u32 table_type,
4131d918647SAlex Vesker 				       u32 table_id,
4141d918647SAlex Vesker 				       u32 *group_id)
4151d918647SAlex Vesker {
4161d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
4171d918647SAlex Vesker 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
4181d918647SAlex Vesker 	u32 *in;
4191d918647SAlex Vesker 	int err;
4201d918647SAlex Vesker 
421b7f86258SRoi Dayan 	in = kvzalloc(inlen, GFP_KERNEL);
4221d918647SAlex Vesker 	if (!in)
4231d918647SAlex Vesker 		return -ENOMEM;
4241d918647SAlex Vesker 
4251d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
4261d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, table_type, table_type);
4271d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, table_id, table_id);
4281d918647SAlex Vesker 
4297ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
4301d918647SAlex Vesker 	if (err)
4311d918647SAlex Vesker 		goto out;
4321d918647SAlex Vesker 
4331d918647SAlex Vesker 	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
4341d918647SAlex Vesker 
4351d918647SAlex Vesker out:
436b7f86258SRoi Dayan 	kvfree(in);
4371d918647SAlex Vesker 	return err;
4381d918647SAlex Vesker }
4391d918647SAlex Vesker 
4401d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev,
4411d918647SAlex Vesker 				  u32 table_type,
4421d918647SAlex Vesker 				  u32 table_id,
4431d918647SAlex Vesker 				  u32 group_id)
4441d918647SAlex Vesker {
4451d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
4461d918647SAlex Vesker 
4477ba294e4SLeon Romanovsky 	MLX5_SET(destroy_flow_group_in, in, opcode,
4487ba294e4SLeon Romanovsky 		 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
4491d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, table_type, table_type);
4501d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
4511d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
4521d918647SAlex Vesker 
4537ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
4541d918647SAlex Vesker }
4551d918647SAlex Vesker 
4561d918647SAlex Vesker int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev,
457cc78dbd7SAlex Vesker 				 struct mlx5dr_cmd_create_flow_table_attr *attr,
4581d918647SAlex Vesker 				 u64 *fdb_rx_icm_addr,
4591d918647SAlex Vesker 				 u32 *table_id)
4601d918647SAlex Vesker {
4611d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
4621d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
4631d918647SAlex Vesker 	void *ft_mdev;
4641d918647SAlex Vesker 	int err;
4651d918647SAlex Vesker 
4661d918647SAlex Vesker 	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
467cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, table_type, attr->table_type);
468b0bb369eSMark Bloch 	MLX5_SET(create_flow_table_in, in, uid, attr->uid);
4691d918647SAlex Vesker 
4701d918647SAlex Vesker 	ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
471cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, termination_table, attr->term_tbl);
472cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, sw_owner, attr->sw_owner);
473cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, level, attr->level);
4741d918647SAlex Vesker 
475cc78dbd7SAlex Vesker 	if (attr->sw_owner) {
4761d918647SAlex Vesker 		/* icm_addr_0 used for FDB RX / NIC TX / NIC_RX
4771d918647SAlex Vesker 		 * icm_addr_1 used for FDB TX
4781d918647SAlex Vesker 		 */
479cc78dbd7SAlex Vesker 		if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) {
4801d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
481cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_rx);
482cc78dbd7SAlex Vesker 		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) {
4831d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
484cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_tx);
485cc78dbd7SAlex Vesker 		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB) {
4861d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
487cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_rx);
4881d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
489cc78dbd7SAlex Vesker 				   sw_owner_icm_root_1, attr->icm_addr_tx);
4901d918647SAlex Vesker 		}
4911d918647SAlex Vesker 	}
4921d918647SAlex Vesker 
493cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
494cc78dbd7SAlex Vesker 		 attr->decap_en);
495cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en,
496cc78dbd7SAlex Vesker 		 attr->reformat_en);
497cc78dbd7SAlex Vesker 
4987ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out);
4991d918647SAlex Vesker 	if (err)
5001d918647SAlex Vesker 		return err;
5011d918647SAlex Vesker 
5021d918647SAlex Vesker 	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
503cc78dbd7SAlex Vesker 	if (!attr->sw_owner && attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB &&
504cc78dbd7SAlex Vesker 	    fdb_rx_icm_addr)
5051d918647SAlex Vesker 		*fdb_rx_icm_addr =
5061d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) |
5071d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 |
5081d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40;
5091d918647SAlex Vesker 
5101d918647SAlex Vesker 	return 0;
5111d918647SAlex Vesker }
5121d918647SAlex Vesker 
5131d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev,
5141d918647SAlex Vesker 				  u32 table_id,
5151d918647SAlex Vesker 				  u32 table_type)
5161d918647SAlex Vesker {
5171d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
5181d918647SAlex Vesker 
5191d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, opcode,
5201d918647SAlex Vesker 		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
5211d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, table_type, table_type);
5221d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
5231d918647SAlex Vesker 
5247ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, destroy_flow_table, in);
5251d918647SAlex Vesker }
5261d918647SAlex Vesker 
5271d918647SAlex Vesker int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
5281d918647SAlex Vesker 				   enum mlx5_reformat_ctx_type rt,
5297ea9b398SYevgeny Kliteynik 				   u8 reformat_param_0,
5307ea9b398SYevgeny Kliteynik 				   u8 reformat_param_1,
5311d918647SAlex Vesker 				   size_t reformat_size,
5321d918647SAlex Vesker 				   void *reformat_data,
5331d918647SAlex Vesker 				   u32 *reformat_id)
5341d918647SAlex Vesker {
5351d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
5361d918647SAlex Vesker 	size_t inlen, cmd_data_sz, cmd_total_sz;
5371d918647SAlex Vesker 	void *prctx;
5381d918647SAlex Vesker 	void *pdata;
5391d918647SAlex Vesker 	void *in;
5401d918647SAlex Vesker 	int err;
5411d918647SAlex Vesker 
5421d918647SAlex Vesker 	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
5431d918647SAlex Vesker 	cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in,
5441d918647SAlex Vesker 					packet_reformat_context.reformat_data);
5451d918647SAlex Vesker 	inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4);
5461d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
5471d918647SAlex Vesker 	if (!in)
5481d918647SAlex Vesker 		return -ENOMEM;
5491d918647SAlex Vesker 
5501d918647SAlex Vesker 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
5511d918647SAlex Vesker 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
5521d918647SAlex Vesker 
5531d918647SAlex Vesker 	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context);
5541d918647SAlex Vesker 	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
5551d918647SAlex Vesker 
5561d918647SAlex Vesker 	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt);
5577ea9b398SYevgeny Kliteynik 	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, reformat_param_0);
5587ea9b398SYevgeny Kliteynik 	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_1, reformat_param_1);
5591d918647SAlex Vesker 	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size);
5607ea9b398SYevgeny Kliteynik 	if (reformat_data && reformat_size)
5611d918647SAlex Vesker 		memcpy(pdata, reformat_data, reformat_size);
5621d918647SAlex Vesker 
5631d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
5641d918647SAlex Vesker 	if (err)
5651d918647SAlex Vesker 		return err;
5661d918647SAlex Vesker 
5671d918647SAlex Vesker 	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
5681d918647SAlex Vesker 	kvfree(in);
5691d918647SAlex Vesker 
5701d918647SAlex Vesker 	return err;
5711d918647SAlex Vesker }
5721d918647SAlex Vesker 
5731d918647SAlex Vesker void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev,
5741d918647SAlex Vesker 				     u32 reformat_id)
5751d918647SAlex Vesker {
5761d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
5771d918647SAlex Vesker 
5781d918647SAlex Vesker 	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
5791d918647SAlex Vesker 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
5801d918647SAlex Vesker 	MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
5811d918647SAlex Vesker 		 reformat_id);
5821d918647SAlex Vesker 
5837ba294e4SLeon Romanovsky 	mlx5_cmd_exec_in(mdev, dealloc_packet_reformat_context, in);
5841d918647SAlex Vesker }
5851d918647SAlex Vesker 
586e046b86eSYevgeny Kliteynik static void dr_cmd_set_definer_format(void *ptr, u16 format_id,
587e046b86eSYevgeny Kliteynik 				      u8 *dw_selectors,
588e046b86eSYevgeny Kliteynik 				      u8 *byte_selectors)
589e046b86eSYevgeny Kliteynik {
590e046b86eSYevgeny Kliteynik 	if (format_id != MLX5_IFC_DEFINER_FORMAT_ID_SELECT)
591e046b86eSYevgeny Kliteynik 		return;
592e046b86eSYevgeny Kliteynik 
593e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw0, dw_selectors[0]);
594e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw1, dw_selectors[1]);
595e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw2, dw_selectors[2]);
596e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw3, dw_selectors[3]);
597e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw4, dw_selectors[4]);
598e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw5, dw_selectors[5]);
599e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw6, dw_selectors[6]);
600e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw7, dw_selectors[7]);
601e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw8, dw_selectors[8]);
602e046b86eSYevgeny Kliteynik 
603e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte0, byte_selectors[0]);
604e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte1, byte_selectors[1]);
605e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte2, byte_selectors[2]);
606e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte3, byte_selectors[3]);
607e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte4, byte_selectors[4]);
608e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte5, byte_selectors[5]);
609e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte6, byte_selectors[6]);
610e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte7, byte_selectors[7]);
611e046b86eSYevgeny Kliteynik }
612e046b86eSYevgeny Kliteynik 
613e046b86eSYevgeny Kliteynik int mlx5dr_cmd_create_definer(struct mlx5_core_dev *mdev,
614e046b86eSYevgeny Kliteynik 			      u16 format_id,
615e046b86eSYevgeny Kliteynik 			      u8 *dw_selectors,
616e046b86eSYevgeny Kliteynik 			      u8 *byte_selectors,
617e046b86eSYevgeny Kliteynik 			      u8 *match_mask,
618e046b86eSYevgeny Kliteynik 			      u32 *definer_id)
619e046b86eSYevgeny Kliteynik {
620e046b86eSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
621e046b86eSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(create_match_definer_in)] = {};
622e046b86eSYevgeny Kliteynik 	void *ptr;
623e046b86eSYevgeny Kliteynik 	int err;
624e046b86eSYevgeny Kliteynik 
625e046b86eSYevgeny Kliteynik 	ptr = MLX5_ADDR_OF(create_match_definer_in, in,
626e046b86eSYevgeny Kliteynik 			   general_obj_in_cmd_hdr);
627e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, ptr, opcode,
628e046b86eSYevgeny Kliteynik 		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
629e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, ptr, obj_type,
630e046b86eSYevgeny Kliteynik 		 MLX5_OBJ_TYPE_MATCH_DEFINER);
631e046b86eSYevgeny Kliteynik 
632e046b86eSYevgeny Kliteynik 	ptr = MLX5_ADDR_OF(create_match_definer_in, in, obj_context);
633e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_id, format_id);
634e046b86eSYevgeny Kliteynik 
635e046b86eSYevgeny Kliteynik 	dr_cmd_set_definer_format(ptr, format_id,
636e046b86eSYevgeny Kliteynik 				  dw_selectors, byte_selectors);
637e046b86eSYevgeny Kliteynik 
638e046b86eSYevgeny Kliteynik 	ptr = MLX5_ADDR_OF(match_definer, ptr, match_mask);
639e046b86eSYevgeny Kliteynik 	memcpy(ptr, match_mask, MLX5_FLD_SZ_BYTES(match_definer, match_mask));
640e046b86eSYevgeny Kliteynik 
641e046b86eSYevgeny Kliteynik 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
642e046b86eSYevgeny Kliteynik 	if (err)
643e046b86eSYevgeny Kliteynik 		return err;
644e046b86eSYevgeny Kliteynik 
645e046b86eSYevgeny Kliteynik 	*definer_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
646e046b86eSYevgeny Kliteynik 
647e046b86eSYevgeny Kliteynik 	return 0;
648e046b86eSYevgeny Kliteynik }
649e046b86eSYevgeny Kliteynik 
650e046b86eSYevgeny Kliteynik void
651e046b86eSYevgeny Kliteynik mlx5dr_cmd_destroy_definer(struct mlx5_core_dev *mdev, u32 definer_id)
652e046b86eSYevgeny Kliteynik {
653e046b86eSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
654e046b86eSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
655e046b86eSYevgeny Kliteynik 
656e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
657e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_MATCH_DEFINER);
658e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, definer_id);
659e046b86eSYevgeny Kliteynik 
660e046b86eSYevgeny Kliteynik 	mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
661e046b86eSYevgeny Kliteynik }
662e046b86eSYevgeny Kliteynik 
6631d918647SAlex Vesker int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num,
6641d918647SAlex Vesker 			 u16 index, struct mlx5dr_cmd_gid_attr *attr)
6651d918647SAlex Vesker {
6661d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {};
6671d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {};
6681d918647SAlex Vesker 	int err;
6691d918647SAlex Vesker 
6701d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, opcode,
6711d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_ROCE_ADDRESS);
6721d918647SAlex Vesker 
6731d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, roce_address_index, index);
6741d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num);
6751d918647SAlex Vesker 
6767ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, query_roce_address, in, out);
6771d918647SAlex Vesker 	if (err)
6781d918647SAlex Vesker 		return err;
6791d918647SAlex Vesker 
6801d918647SAlex Vesker 	memcpy(&attr->gid,
6811d918647SAlex Vesker 	       MLX5_ADDR_OF(query_roce_address_out,
6821d918647SAlex Vesker 			    out, roce_address.source_l3_address),
6831d918647SAlex Vesker 	       sizeof(attr->gid));
6841d918647SAlex Vesker 	memcpy(attr->mac,
6851d918647SAlex Vesker 	       MLX5_ADDR_OF(query_roce_address_out, out,
6861d918647SAlex Vesker 			    roce_address.source_mac_47_32),
6871d918647SAlex Vesker 	       sizeof(attr->mac));
6881d918647SAlex Vesker 
6891d918647SAlex Vesker 	if (MLX5_GET(query_roce_address_out, out,
6901d918647SAlex Vesker 		     roce_address.roce_version) == MLX5_ROCE_VERSION_2)
6911d918647SAlex Vesker 		attr->roce_ver = MLX5_ROCE_VERSION_2;
6921d918647SAlex Vesker 	else
6931d918647SAlex Vesker 		attr->roce_ver = MLX5_ROCE_VERSION_1;
6941d918647SAlex Vesker 
6951d918647SAlex Vesker 	return 0;
6961d918647SAlex Vesker }
6976de03d2dSErez Shitrit 
698de69696bSYevgeny Kliteynik int mlx5dr_cmd_create_modify_header_arg(struct mlx5_core_dev *dev,
699de69696bSYevgeny Kliteynik 					u16 log_obj_range, u32 pd,
700de69696bSYevgeny Kliteynik 					u32 *obj_id)
701de69696bSYevgeny Kliteynik {
702de69696bSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {};
703de69696bSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
704de69696bSYevgeny Kliteynik 	void *attr;
705de69696bSYevgeny Kliteynik 	int ret;
706de69696bSYevgeny Kliteynik 
707de69696bSYevgeny Kliteynik 	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
708de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, attr, opcode,
709de69696bSYevgeny Kliteynik 		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
710de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, attr, obj_type,
711de69696bSYevgeny Kliteynik 		 MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
712de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, attr,
713de69696bSYevgeny Kliteynik 		 op_param.create.log_obj_range, log_obj_range);
714de69696bSYevgeny Kliteynik 
715de69696bSYevgeny Kliteynik 	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
716de69696bSYevgeny Kliteynik 	MLX5_SET(modify_header_arg, attr, access_pd, pd);
717de69696bSYevgeny Kliteynik 
718de69696bSYevgeny Kliteynik 	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
719de69696bSYevgeny Kliteynik 	if (ret)
720de69696bSYevgeny Kliteynik 		return ret;
721de69696bSYevgeny Kliteynik 
722de69696bSYevgeny Kliteynik 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
723de69696bSYevgeny Kliteynik 	return 0;
724de69696bSYevgeny Kliteynik }
725de69696bSYevgeny Kliteynik 
726de69696bSYevgeny Kliteynik void mlx5dr_cmd_destroy_modify_header_arg(struct mlx5_core_dev *dev,
727de69696bSYevgeny Kliteynik 					  u32 obj_id)
728de69696bSYevgeny Kliteynik {
729de69696bSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
730de69696bSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
731de69696bSYevgeny Kliteynik 
732de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
733de69696bSYevgeny Kliteynik 		 MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
734de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
735de69696bSYevgeny Kliteynik 		 MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
736de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, obj_id);
737de69696bSYevgeny Kliteynik 
738de69696bSYevgeny Kliteynik 	mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
739de69696bSYevgeny Kliteynik }
740de69696bSYevgeny Kliteynik 
7416de03d2dSErez Shitrit static int mlx5dr_cmd_set_extended_dest(struct mlx5_core_dev *dev,
7426de03d2dSErez Shitrit 					struct mlx5dr_cmd_fte_info *fte,
7436de03d2dSErez Shitrit 					bool *extended_dest)
7446de03d2dSErez Shitrit {
7456de03d2dSErez Shitrit 	int fw_log_max_fdb_encap_uplink = MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink);
7466de03d2dSErez Shitrit 	int num_fwd_destinations = 0;
7476de03d2dSErez Shitrit 	int num_encap = 0;
7486de03d2dSErez Shitrit 	int i;
7496de03d2dSErez Shitrit 
7506de03d2dSErez Shitrit 	*extended_dest = false;
7516de03d2dSErez Shitrit 	if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
7526de03d2dSErez Shitrit 		return 0;
7536de03d2dSErez Shitrit 	for (i = 0; i < fte->dests_size; i++) {
7546510bc0dSMark Bloch 		if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ||
7556510bc0dSMark Bloch 		    fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_NONE)
7566de03d2dSErez Shitrit 			continue;
757e3a0f40bSYevgeny Kliteynik 		if ((fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_VPORT ||
758e3a0f40bSYevgeny Kliteynik 		     fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) &&
7596de03d2dSErez Shitrit 		    fte->dest_arr[i].vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
7606de03d2dSErez Shitrit 			num_encap++;
7616de03d2dSErez Shitrit 		num_fwd_destinations++;
7626de03d2dSErez Shitrit 	}
7636de03d2dSErez Shitrit 
7646de03d2dSErez Shitrit 	if (num_fwd_destinations > 1 && num_encap > 0)
7656de03d2dSErez Shitrit 		*extended_dest = true;
7666de03d2dSErez Shitrit 
7676de03d2dSErez Shitrit 	if (*extended_dest && !fw_log_max_fdb_encap_uplink) {
7686de03d2dSErez Shitrit 		mlx5_core_warn(dev, "FW does not support extended destination");
7696de03d2dSErez Shitrit 		return -EOPNOTSUPP;
7706de03d2dSErez Shitrit 	}
7716de03d2dSErez Shitrit 	if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) {
7726de03d2dSErez Shitrit 		mlx5_core_warn(dev, "FW does not support more than %d encaps",
7736de03d2dSErez Shitrit 			       1 << fw_log_max_fdb_encap_uplink);
7746de03d2dSErez Shitrit 		return -EOPNOTSUPP;
7756de03d2dSErez Shitrit 	}
7766de03d2dSErez Shitrit 
7776de03d2dSErez Shitrit 	return 0;
7786de03d2dSErez Shitrit }
7796de03d2dSErez Shitrit 
7806de03d2dSErez Shitrit int mlx5dr_cmd_set_fte(struct mlx5_core_dev *dev,
7816de03d2dSErez Shitrit 		       int opmod, int modify_mask,
7826de03d2dSErez Shitrit 		       struct mlx5dr_cmd_ft_info *ft,
7836de03d2dSErez Shitrit 		       u32 group_id,
7846de03d2dSErez Shitrit 		       struct mlx5dr_cmd_fte_info *fte)
7856de03d2dSErez Shitrit {
7866de03d2dSErez Shitrit 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
7876de03d2dSErez Shitrit 	void *in_flow_context, *vlan;
7886de03d2dSErez Shitrit 	bool extended_dest = false;
7896de03d2dSErez Shitrit 	void *in_match_value;
7906de03d2dSErez Shitrit 	unsigned int inlen;
7916de03d2dSErez Shitrit 	int dst_cnt_size;
7926de03d2dSErez Shitrit 	void *in_dests;
7936de03d2dSErez Shitrit 	u32 *in;
7946de03d2dSErez Shitrit 	int err;
7956de03d2dSErez Shitrit 	int i;
7966de03d2dSErez Shitrit 
7976de03d2dSErez Shitrit 	if (mlx5dr_cmd_set_extended_dest(dev, fte, &extended_dest))
7986de03d2dSErez Shitrit 		return -EOPNOTSUPP;
7996de03d2dSErez Shitrit 
8006de03d2dSErez Shitrit 	if (!extended_dest)
8016de03d2dSErez Shitrit 		dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct);
8026de03d2dSErez Shitrit 	else
8036de03d2dSErez Shitrit 		dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format);
8046de03d2dSErez Shitrit 
8056de03d2dSErez Shitrit 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size;
8066de03d2dSErez Shitrit 	in = kvzalloc(inlen, GFP_KERNEL);
8076de03d2dSErez Shitrit 	if (!in)
8086de03d2dSErez Shitrit 		return -ENOMEM;
8096de03d2dSErez Shitrit 
8106de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
8116de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, op_mod, opmod);
8126de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
8136de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, table_type, ft->type);
8146de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, table_id, ft->id);
8156de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, flow_index, fte->index);
81663b85f49SYevgeny Kliteynik 	MLX5_SET(set_fte_in, in, ignore_flow_level, fte->ignore_flow_level);
8176de03d2dSErez Shitrit 	if (ft->vport) {
8186de03d2dSErez Shitrit 		MLX5_SET(set_fte_in, in, vport_number, ft->vport);
8196de03d2dSErez Shitrit 		MLX5_SET(set_fte_in, in, other_vport, 1);
8206de03d2dSErez Shitrit 	}
8216de03d2dSErez Shitrit 
8226de03d2dSErez Shitrit 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
8236de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
8246de03d2dSErez Shitrit 
8256de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, flow_tag,
8266de03d2dSErez Shitrit 		 fte->flow_context.flow_tag);
8276de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, flow_source,
8286de03d2dSErez Shitrit 		 fte->flow_context.flow_source);
8296de03d2dSErez Shitrit 
8306de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, extended_destination,
8316de03d2dSErez Shitrit 		 extended_dest);
8326de03d2dSErez Shitrit 	if (extended_dest) {
8336de03d2dSErez Shitrit 		u32 action;
8346de03d2dSErez Shitrit 
8356de03d2dSErez Shitrit 		action = fte->action.action &
8366de03d2dSErez Shitrit 			~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
8376de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, action, action);
8386de03d2dSErez Shitrit 	} else {
8396de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, action,
8406de03d2dSErez Shitrit 			 fte->action.action);
8416de03d2dSErez Shitrit 		if (fte->action.pkt_reformat)
8426de03d2dSErez Shitrit 			MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
8436de03d2dSErez Shitrit 				 fte->action.pkt_reformat->id);
8446de03d2dSErez Shitrit 	}
8456de03d2dSErez Shitrit 	if (fte->action.modify_hdr)
8466de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, modify_header_id,
8476de03d2dSErez Shitrit 			 fte->action.modify_hdr->id);
8486de03d2dSErez Shitrit 
8496de03d2dSErez Shitrit 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan);
8506de03d2dSErez Shitrit 
8516de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype);
8526de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid);
8536de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio);
8546de03d2dSErez Shitrit 
8556de03d2dSErez Shitrit 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2);
8566de03d2dSErez Shitrit 
8576de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype);
8586de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid);
8596de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio);
8606de03d2dSErez Shitrit 
8616de03d2dSErez Shitrit 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
8626de03d2dSErez Shitrit 				      match_value);
8636de03d2dSErez Shitrit 	memcpy(in_match_value, fte->val, sizeof(u32) * MLX5_ST_SZ_DW_MATCH_PARAM);
8646de03d2dSErez Shitrit 
8656de03d2dSErez Shitrit 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
8666de03d2dSErez Shitrit 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
8676de03d2dSErez Shitrit 		int list_size = 0;
8686de03d2dSErez Shitrit 
8696de03d2dSErez Shitrit 		for (i = 0; i < fte->dests_size; i++) {
870d639af62SMark Bloch 			enum mlx5_flow_destination_type type = fte->dest_arr[i].type;
871d639af62SMark Bloch 			enum mlx5_ifc_flow_destination_type ifc_type;
872d639af62SMark Bloch 			unsigned int id;
8736de03d2dSErez Shitrit 
8746de03d2dSErez Shitrit 			if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
8756de03d2dSErez Shitrit 				continue;
8766de03d2dSErez Shitrit 
8776de03d2dSErez Shitrit 			switch (type) {
8786510bc0dSMark Bloch 			case MLX5_FLOW_DESTINATION_TYPE_NONE:
8796510bc0dSMark Bloch 				continue;
8806de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
8816de03d2dSErez Shitrit 				id = fte->dest_arr[i].ft_num;
882d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
8836de03d2dSErez Shitrit 				break;
8846de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
8856de03d2dSErez Shitrit 				id = fte->dest_arr[i].ft_id;
886d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
887d639af62SMark Bloch 
8886de03d2dSErez Shitrit 				break;
889e3a0f40bSYevgeny Kliteynik 			case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
8906de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
891e3a0f40bSYevgeny Kliteynik 				if (type == MLX5_FLOW_DESTINATION_TYPE_VPORT) {
8926de03d2dSErez Shitrit 					id = fte->dest_arr[i].vport.num;
8936de03d2dSErez Shitrit 					MLX5_SET(dest_format_struct, in_dests,
8946de03d2dSErez Shitrit 						 destination_eswitch_owner_vhca_id_valid,
8956de03d2dSErez Shitrit 						 !!(fte->dest_arr[i].vport.flags &
8966de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_VHCA_ID));
897d639af62SMark Bloch 					ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT;
898e3a0f40bSYevgeny Kliteynik 				} else {
899e3a0f40bSYevgeny Kliteynik 					id = 0;
900d639af62SMark Bloch 					ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK;
901e3a0f40bSYevgeny Kliteynik 					MLX5_SET(dest_format_struct, in_dests,
902e3a0f40bSYevgeny Kliteynik 						 destination_eswitch_owner_vhca_id_valid, 1);
903e3a0f40bSYevgeny Kliteynik 				}
9046de03d2dSErez Shitrit 				MLX5_SET(dest_format_struct, in_dests,
9056de03d2dSErez Shitrit 					 destination_eswitch_owner_vhca_id,
9066de03d2dSErez Shitrit 					 fte->dest_arr[i].vport.vhca_id);
9076de03d2dSErez Shitrit 				if (extended_dest && (fte->dest_arr[i].vport.flags &
9086de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID)) {
9096de03d2dSErez Shitrit 					MLX5_SET(dest_format_struct, in_dests,
9106de03d2dSErez Shitrit 						 packet_reformat,
9116de03d2dSErez Shitrit 						 !!(fte->dest_arr[i].vport.flags &
9126de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID));
9136de03d2dSErez Shitrit 					MLX5_SET(extended_dest_format, in_dests,
9146de03d2dSErez Shitrit 						 packet_reformat_id,
9156de03d2dSErez Shitrit 						 fte->dest_arr[i].vport.reformat_id);
9166de03d2dSErez Shitrit 				}
9176de03d2dSErez Shitrit 				break;
9181ab6dc35SYevgeny Kliteynik 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
9191ab6dc35SYevgeny Kliteynik 				id = fte->dest_arr[i].sampler_id;
920d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
9211ab6dc35SYevgeny Kliteynik 				break;
9226de03d2dSErez Shitrit 			default:
9236de03d2dSErez Shitrit 				id = fte->dest_arr[i].tir_num;
924d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TIR;
9256de03d2dSErez Shitrit 			}
9266de03d2dSErez Shitrit 
9276de03d2dSErez Shitrit 			MLX5_SET(dest_format_struct, in_dests, destination_type,
928d639af62SMark Bloch 				 ifc_type);
9296de03d2dSErez Shitrit 			MLX5_SET(dest_format_struct, in_dests, destination_id, id);
9306de03d2dSErez Shitrit 			in_dests += dst_cnt_size;
9316de03d2dSErez Shitrit 			list_size++;
9326de03d2dSErez Shitrit 		}
9336de03d2dSErez Shitrit 
9346de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, destination_list_size,
9356de03d2dSErez Shitrit 			 list_size);
9366de03d2dSErez Shitrit 	}
9376de03d2dSErez Shitrit 
9386de03d2dSErez Shitrit 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
9396de03d2dSErez Shitrit 		int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev,
9406de03d2dSErez Shitrit 					log_max_flow_counter,
9416de03d2dSErez Shitrit 					ft->type));
9426de03d2dSErez Shitrit 		int list_size = 0;
9436de03d2dSErez Shitrit 
9446de03d2dSErez Shitrit 		for (i = 0; i < fte->dests_size; i++) {
9456de03d2dSErez Shitrit 			if (fte->dest_arr[i].type !=
9466de03d2dSErez Shitrit 			    MLX5_FLOW_DESTINATION_TYPE_COUNTER)
9476de03d2dSErez Shitrit 				continue;
9486de03d2dSErez Shitrit 
9496de03d2dSErez Shitrit 			MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
9506de03d2dSErez Shitrit 				 fte->dest_arr[i].counter_id);
9516de03d2dSErez Shitrit 			in_dests += dst_cnt_size;
9526de03d2dSErez Shitrit 			list_size++;
9536de03d2dSErez Shitrit 		}
9546de03d2dSErez Shitrit 		if (list_size > max_list_size) {
9556de03d2dSErez Shitrit 			err = -EINVAL;
9566de03d2dSErez Shitrit 			goto err_out;
9576de03d2dSErez Shitrit 		}
9586de03d2dSErez Shitrit 
9596de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
9606de03d2dSErez Shitrit 			 list_size);
9616de03d2dSErez Shitrit 	}
9626de03d2dSErez Shitrit 
9636de03d2dSErez Shitrit 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
9646de03d2dSErez Shitrit err_out:
9656de03d2dSErez Shitrit 	kvfree(in);
9666de03d2dSErez Shitrit 	return err;
9676de03d2dSErez Shitrit }
968