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 
mlx5dr_cmd_query_esw_vport_context(struct mlx5_core_dev * mdev,bool other_vport,u16 vport_number,u64 * icm_address_rx,u64 * icm_address_tx)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 
mlx5dr_cmd_query_gvmi(struct mlx5_core_dev * mdev,bool other_vport,u16 vport_number,u16 * gvmi)341d918647SAlex Vesker int mlx5dr_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_vport,
351d918647SAlex Vesker 			  u16 vport_number, u16 *gvmi)
361d918647SAlex Vesker {
378bbe544eSDaniel Jurgens 	bool ec_vf_func = other_vport ? mlx5_core_is_ec_vf_vport(mdev, vport_number) : false;
381d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_hca_cap_in)] = {};
391d918647SAlex Vesker 	int out_size;
401d918647SAlex Vesker 	void *out;
411d918647SAlex Vesker 	int err;
421d918647SAlex Vesker 
431d918647SAlex Vesker 	out_size = MLX5_ST_SZ_BYTES(query_hca_cap_out);
441d918647SAlex Vesker 	out = kzalloc(out_size, GFP_KERNEL);
451d918647SAlex Vesker 	if (!out)
461d918647SAlex Vesker 		return -ENOMEM;
471d918647SAlex Vesker 
481d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP);
491d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, other_function, other_vport);
508bbe544eSDaniel Jurgens 	MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(mdev, vport_number, ec_vf_func));
518bbe544eSDaniel Jurgens 	MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func);
521d918647SAlex Vesker 	MLX5_SET(query_hca_cap_in, in, op_mod,
531d918647SAlex Vesker 		 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1 |
541d918647SAlex Vesker 		 HCA_CAP_OPMOD_GET_CUR);
551d918647SAlex Vesker 
567ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, query_hca_cap, in, out);
571d918647SAlex Vesker 	if (err) {
581d918647SAlex Vesker 		kfree(out);
591d918647SAlex Vesker 		return err;
601d918647SAlex Vesker 	}
611d918647SAlex Vesker 
621d918647SAlex Vesker 	*gvmi = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.vhca_id);
631d918647SAlex Vesker 
641d918647SAlex Vesker 	kfree(out);
651d918647SAlex Vesker 	return 0;
661d918647SAlex Vesker }
671d918647SAlex Vesker 
mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev * mdev,struct mlx5dr_esw_caps * caps)681d918647SAlex Vesker int mlx5dr_cmd_query_esw_caps(struct mlx5_core_dev *mdev,
691d918647SAlex Vesker 			      struct mlx5dr_esw_caps *caps)
701d918647SAlex Vesker {
711d918647SAlex Vesker 	caps->drop_icm_address_rx =
721d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
731d918647SAlex Vesker 					 sw_steering_fdb_action_drop_icm_address_rx);
741d918647SAlex Vesker 	caps->drop_icm_address_tx =
751d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
761d918647SAlex Vesker 					 sw_steering_fdb_action_drop_icm_address_tx);
771d918647SAlex Vesker 	caps->uplink_icm_address_rx =
781d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
791d918647SAlex Vesker 					 sw_steering_uplink_icm_address_rx);
801d918647SAlex Vesker 	caps->uplink_icm_address_tx =
811d918647SAlex Vesker 		MLX5_CAP64_ESW_FLOWTABLE(mdev,
821d918647SAlex Vesker 					 sw_steering_uplink_icm_address_tx);
8364f45c0fSYevgeny Kliteynik 	caps->sw_owner_v2 = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner_v2);
8464f45c0fSYevgeny Kliteynik 	if (!caps->sw_owner_v2)
8564f45c0fSYevgeny Kliteynik 		caps->sw_owner = MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, sw_owner);
861d918647SAlex Vesker 
871d918647SAlex Vesker 	return 0;
881d918647SAlex Vesker }
891d918647SAlex Vesker 
dr_cmd_query_nic_vport_roce_en(struct mlx5_core_dev * mdev,u16 vport,bool * roce_en)907304d603SYevgeny Kliteynik static int dr_cmd_query_nic_vport_roce_en(struct mlx5_core_dev *mdev,
917304d603SYevgeny Kliteynik 					  u16 vport, bool *roce_en)
927304d603SYevgeny Kliteynik {
937304d603SYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {};
947304d603SYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {};
957304d603SYevgeny Kliteynik 	int err;
967304d603SYevgeny Kliteynik 
977304d603SYevgeny Kliteynik 	MLX5_SET(query_nic_vport_context_in, in, opcode,
987304d603SYevgeny Kliteynik 		 MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT);
997304d603SYevgeny Kliteynik 	MLX5_SET(query_nic_vport_context_in, in, vport_number, vport);
1007304d603SYevgeny Kliteynik 	MLX5_SET(query_nic_vport_context_in, in, other_vport, !!vport);
1017304d603SYevgeny Kliteynik 
1027304d603SYevgeny Kliteynik 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
1037304d603SYevgeny Kliteynik 	if (err)
1047304d603SYevgeny Kliteynik 		return err;
1057304d603SYevgeny Kliteynik 
1067304d603SYevgeny Kliteynik 	*roce_en = MLX5_GET(query_nic_vport_context_out, out,
1077304d603SYevgeny Kliteynik 			    nic_vport_context.roce_en);
1087304d603SYevgeny Kliteynik 	return 0;
1097304d603SYevgeny Kliteynik }
1107304d603SYevgeny Kliteynik 
mlx5dr_cmd_query_device(struct mlx5_core_dev * mdev,struct mlx5dr_cmd_caps * caps)1111d918647SAlex Vesker int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev,
1121d918647SAlex Vesker 			    struct mlx5dr_cmd_caps *caps)
1131d918647SAlex Vesker {
1147304d603SYevgeny Kliteynik 	bool roce_en;
1157304d603SYevgeny Kliteynik 	int err;
1167304d603SYevgeny Kliteynik 
1171d918647SAlex Vesker 	caps->prio_tag_required	= MLX5_CAP_GEN(mdev, prio_tag_required);
1181d918647SAlex Vesker 	caps->eswitch_manager	= MLX5_CAP_GEN(mdev, eswitch_manager);
1191d918647SAlex Vesker 	caps->gvmi		= MLX5_CAP_GEN(mdev, vhca_id);
1201d918647SAlex Vesker 	caps->flex_protocols	= MLX5_CAP_GEN(mdev, flex_parser_protocols);
121d421e466SYevgeny Kliteynik 	caps->sw_format_ver	= MLX5_CAP_GEN(mdev, steering_format_version);
122c7dd225bSYevgeny Kliteynik 	caps->roce_caps.fl_rc_qp_when_roce_disabled =
123c7dd225bSYevgeny Kliteynik 		MLX5_CAP_GEN(mdev, fl_rc_qp_when_roce_disabled);
1241d918647SAlex Vesker 
1257304d603SYevgeny Kliteynik 	if (MLX5_CAP_GEN(mdev, roce)) {
1267304d603SYevgeny Kliteynik 		err = dr_cmd_query_nic_vport_roce_en(mdev, 0, &roce_en);
1277304d603SYevgeny Kliteynik 		if (err)
1287304d603SYevgeny Kliteynik 			return err;
1297304d603SYevgeny Kliteynik 
1307304d603SYevgeny Kliteynik 		caps->roce_caps.roce_en = roce_en;
131c7dd225bSYevgeny Kliteynik 		caps->roce_caps.fl_rc_qp_when_roce_disabled |=
1327304d603SYevgeny Kliteynik 			MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_disabled);
1337304d603SYevgeny Kliteynik 		caps->roce_caps.fl_rc_qp_when_roce_enabled =
1347304d603SYevgeny Kliteynik 			MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_enabled);
1357304d603SYevgeny Kliteynik 	}
1367304d603SYevgeny Kliteynik 
137aeacb52aSYevgeny Kliteynik 	caps->isolate_vl_tc = MLX5_CAP_GEN(mdev, isolate_vl_tc_new);
138aeacb52aSYevgeny Kliteynik 
139b7ba743aSYevgeny Kliteynik 	caps->support_modify_argument =
140b7ba743aSYevgeny Kliteynik 		MLX5_CAP_GEN_64(mdev, general_obj_types) &
141b7ba743aSYevgeny Kliteynik 		MLX5_GENERAL_OBJ_TYPES_CAP_HEADER_MODIFY_ARGUMENT;
142b7ba743aSYevgeny Kliteynik 
143b7ba743aSYevgeny Kliteynik 	if (caps->support_modify_argument) {
144b7ba743aSYevgeny Kliteynik 		caps->log_header_modify_argument_granularity =
145b7ba743aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, log_header_modify_argument_granularity);
146b7ba743aSYevgeny Kliteynik 		caps->log_header_modify_argument_max_alloc =
147b7ba743aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, log_header_modify_argument_max_alloc);
148b7ba743aSYevgeny Kliteynik 	}
149b7ba743aSYevgeny Kliteynik 
150f59464e2SYevgeny Kliteynik 	/* geneve_tlv_option_0_exist is the indication of
151f59464e2SYevgeny Kliteynik 	 * STE support for lookup type flex_parser_ok
152f59464e2SYevgeny Kliteynik 	 */
153f59464e2SYevgeny Kliteynik 	caps->flex_parser_ok_bits_supp =
154f59464e2SYevgeny Kliteynik 		MLX5_CAP_FLOWTABLE(mdev,
155f59464e2SYevgeny Kliteynik 				   flow_table_properties_nic_receive.ft_field_support.geneve_tlv_option_0_exist);
156f59464e2SYevgeny Kliteynik 
1578a8a1023SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED) {
1581d918647SAlex Vesker 		caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
1591d918647SAlex Vesker 		caps->flex_parser_id_icmp_dw1 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw1);
1601d918647SAlex Vesker 	}
1611d918647SAlex Vesker 
1628a8a1023SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED) {
1631d918647SAlex Vesker 		caps->flex_parser_id_icmpv6_dw0 =
1641d918647SAlex Vesker 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw0);
1651d918647SAlex Vesker 		caps->flex_parser_id_icmpv6_dw1 =
1661d918647SAlex Vesker 			MLX5_CAP_GEN(mdev, flex_parser_id_icmpv6_dw1);
1671d918647SAlex Vesker 	}
1681d918647SAlex Vesker 
1693442e033SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_TLV_OPTION_0_ENABLED)
1703442e033SYevgeny Kliteynik 		caps->flex_parser_id_geneve_tlv_option_0 =
1713442e033SYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_geneve_tlv_option_0);
1723442e033SYevgeny Kliteynik 
17335ba005dSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)
17435ba005dSYevgeny Kliteynik 		caps->flex_parser_id_mpls_over_gre =
17535ba005dSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_outer_first_mpls_over_gre);
17635ba005dSYevgeny Kliteynik 
177c3fb0e28SYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)
17835ba005dSYevgeny Kliteynik 		caps->flex_parser_id_mpls_over_udp =
17935ba005dSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_outer_first_mpls_over_udp_label);
18035ba005dSYevgeny Kliteynik 
181df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_0_ENABLED)
182df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_dw_0 =
183df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_dw_0);
184df9dd15aSYevgeny Kliteynik 
185df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_TEID_ENABLED)
186df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_teid =
187df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_teid);
188df9dd15aSYevgeny Kliteynik 
189df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_2_ENABLED)
190df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_dw_2 =
191df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_dw_2);
192df9dd15aSYevgeny Kliteynik 
193df9dd15aSYevgeny Kliteynik 	if (caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_FIRST_EXT_DW_0_ENABLED)
194df9dd15aSYevgeny Kliteynik 		caps->flex_parser_id_gtpu_first_ext_dw_0 =
195df9dd15aSYevgeny Kliteynik 			MLX5_CAP_GEN(mdev, flex_parser_id_gtpu_first_ext_dw_0);
196df9dd15aSYevgeny Kliteynik 
1971d918647SAlex Vesker 	caps->nic_rx_drop_address =
1981d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_rx_action_drop_icm_address);
1991d918647SAlex Vesker 	caps->nic_tx_drop_address =
2001d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_drop_icm_address);
2011d918647SAlex Vesker 	caps->nic_tx_allow_address =
2021d918647SAlex Vesker 		MLX5_CAP64_FLOWTABLE(mdev, sw_steering_nic_tx_action_allow_icm_address);
2031d918647SAlex Vesker 
20464f45c0fSYevgeny Kliteynik 	caps->rx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner_v2);
20564f45c0fSYevgeny Kliteynik 	caps->tx_sw_owner_v2 = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner_v2);
2061d918647SAlex Vesker 
20764f45c0fSYevgeny Kliteynik 	if (!caps->rx_sw_owner_v2)
20864f45c0fSYevgeny Kliteynik 		caps->rx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, sw_owner);
20964f45c0fSYevgeny Kliteynik 	if (!caps->tx_sw_owner_v2)
2101d918647SAlex Vesker 		caps->tx_sw_owner = MLX5_CAP_FLOWTABLE_NIC_TX(mdev, sw_owner);
2111d918647SAlex Vesker 
21264f45c0fSYevgeny Kliteynik 	caps->max_ft_level = MLX5_CAP_FLOWTABLE_NIC_RX(mdev, max_ft_level);
21364f45c0fSYevgeny Kliteynik 
2141d918647SAlex Vesker 	caps->log_icm_size = MLX5_CAP_DEV_MEM(mdev, log_steering_sw_icm_size);
2151d918647SAlex Vesker 	caps->hdr_modify_icm_addr =
2161d918647SAlex Vesker 		MLX5_CAP64_DEV_MEM(mdev, header_modify_sw_icm_start_address);
2171d918647SAlex Vesker 
218108ff821SYevgeny Kliteynik 	caps->log_modify_pattern_icm_size =
219108ff821SYevgeny Kliteynik 		MLX5_CAP_DEV_MEM(mdev, log_header_modify_pattern_sw_icm_size);
220108ff821SYevgeny Kliteynik 
221108ff821SYevgeny Kliteynik 	caps->hdr_modify_pattern_icm_addr =
222108ff821SYevgeny Kliteynik 		MLX5_CAP64_DEV_MEM(mdev, header_modify_pattern_sw_icm_start_address);
223108ff821SYevgeny Kliteynik 
2241d918647SAlex Vesker 	caps->roce_min_src_udp = MLX5_CAP_ROCE(mdev, r_roce_min_src_udp_port);
2251d918647SAlex Vesker 
226dd4acb2aSYevgeny Kliteynik 	caps->is_ecpf = mlx5_core_is_ecpf_esw_manager(mdev);
227dd4acb2aSYevgeny Kliteynik 
2281d918647SAlex Vesker 	return 0;
2291d918647SAlex Vesker }
2301d918647SAlex Vesker 
mlx5dr_cmd_query_flow_table(struct mlx5_core_dev * dev,enum fs_flow_table_type type,u32 table_id,struct mlx5dr_cmd_query_flow_table_details * output)2311d918647SAlex Vesker int mlx5dr_cmd_query_flow_table(struct mlx5_core_dev *dev,
2321d918647SAlex Vesker 				enum fs_flow_table_type type,
2331d918647SAlex Vesker 				u32 table_id,
2341d918647SAlex Vesker 				struct mlx5dr_cmd_query_flow_table_details *output)
2351d918647SAlex Vesker {
2361d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_flow_table_out)] = {};
2371d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_flow_table_in)] = {};
2381d918647SAlex Vesker 	int err;
2391d918647SAlex Vesker 
2401d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, opcode,
2411d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_FLOW_TABLE);
2421d918647SAlex Vesker 
2431d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, table_type, type);
2441d918647SAlex Vesker 	MLX5_SET(query_flow_table_in, in, table_id, table_id);
2451d918647SAlex Vesker 
2467ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(dev, query_flow_table, in, out);
2471d918647SAlex Vesker 	if (err)
2481d918647SAlex Vesker 		return err;
2491d918647SAlex Vesker 
2501d918647SAlex Vesker 	output->status = MLX5_GET(query_flow_table_out, out, status);
2511d918647SAlex Vesker 	output->level = MLX5_GET(query_flow_table_out, out, flow_table_context.level);
2521d918647SAlex Vesker 
2531d918647SAlex Vesker 	output->sw_owner_icm_root_1 = MLX5_GET64(query_flow_table_out, out,
2541d918647SAlex Vesker 						 flow_table_context.sw_owner_icm_root_1);
2551d918647SAlex Vesker 	output->sw_owner_icm_root_0 = MLX5_GET64(query_flow_table_out, out,
2561d918647SAlex Vesker 						 flow_table_context.sw_owner_icm_root_0);
2571d918647SAlex Vesker 
2581d918647SAlex Vesker 	return 0;
2591d918647SAlex Vesker }
2601d918647SAlex Vesker 
mlx5dr_cmd_query_flow_sampler(struct mlx5_core_dev * dev,u32 sampler_id,u64 * rx_icm_addr,u64 * tx_icm_addr)2611ab6dc35SYevgeny Kliteynik int mlx5dr_cmd_query_flow_sampler(struct mlx5_core_dev *dev,
2621ab6dc35SYevgeny Kliteynik 				  u32 sampler_id,
2631ab6dc35SYevgeny Kliteynik 				  u64 *rx_icm_addr,
2641ab6dc35SYevgeny Kliteynik 				  u64 *tx_icm_addr)
2651ab6dc35SYevgeny Kliteynik {
2661ab6dc35SYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(query_sampler_obj_out)] = {};
2671ab6dc35SYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
2681ab6dc35SYevgeny Kliteynik 	void *attr;
2691ab6dc35SYevgeny Kliteynik 	int ret;
2701ab6dc35SYevgeny Kliteynik 
2711ab6dc35SYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
2721ab6dc35SYevgeny Kliteynik 		 MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
2731ab6dc35SYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
2741ab6dc35SYevgeny Kliteynik 		 MLX5_GENERAL_OBJECT_TYPES_SAMPLER);
2751ab6dc35SYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, sampler_id);
2761ab6dc35SYevgeny Kliteynik 
2771ab6dc35SYevgeny Kliteynik 	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
2781ab6dc35SYevgeny Kliteynik 	if (ret)
2791ab6dc35SYevgeny Kliteynik 		return ret;
2801ab6dc35SYevgeny Kliteynik 
2811ab6dc35SYevgeny Kliteynik 	attr = MLX5_ADDR_OF(query_sampler_obj_out, out, sampler_object);
2821ab6dc35SYevgeny Kliteynik 
2831ab6dc35SYevgeny Kliteynik 	*rx_icm_addr = MLX5_GET64(sampler_obj, attr,
2841ab6dc35SYevgeny Kliteynik 				  sw_steering_icm_address_rx);
2851ab6dc35SYevgeny Kliteynik 	*tx_icm_addr = MLX5_GET64(sampler_obj, attr,
2861ab6dc35SYevgeny Kliteynik 				  sw_steering_icm_address_tx);
2871ab6dc35SYevgeny Kliteynik 
2881ab6dc35SYevgeny Kliteynik 	return 0;
2891ab6dc35SYevgeny Kliteynik }
2901ab6dc35SYevgeny Kliteynik 
mlx5dr_cmd_sync_steering(struct mlx5_core_dev * mdev)2911d918647SAlex Vesker int mlx5dr_cmd_sync_steering(struct mlx5_core_dev *mdev)
2921d918647SAlex Vesker {
2931d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(sync_steering_in)] = {};
2941d918647SAlex Vesker 
295c4193a12SYevgeny Kliteynik 	/* Skip SYNC in case the device is internal error state.
296c4193a12SYevgeny Kliteynik 	 * Besides a device error, this also happens when we're
297c4193a12SYevgeny Kliteynik 	 * in fast teardown
298c4193a12SYevgeny Kliteynik 	 */
299c4193a12SYevgeny Kliteynik 	if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
300c4193a12SYevgeny Kliteynik 		return 0;
301c4193a12SYevgeny Kliteynik 
3021d918647SAlex Vesker 	MLX5_SET(sync_steering_in, in, opcode, MLX5_CMD_OP_SYNC_STEERING);
3031d918647SAlex Vesker 
3047ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, sync_steering, in);
3051d918647SAlex Vesker }
3061d918647SAlex Vesker 
mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 group_id,u32 modify_header_id,u16 vport)3071d918647SAlex Vesker int mlx5dr_cmd_set_fte_modify_and_vport(struct mlx5_core_dev *mdev,
3081d918647SAlex Vesker 					u32 table_type,
3091d918647SAlex Vesker 					u32 table_id,
3101d918647SAlex Vesker 					u32 group_id,
3111d918647SAlex Vesker 					u32 modify_header_id,
312f9f93bd5SYevgeny Kliteynik 					u16 vport)
3131d918647SAlex Vesker {
3141d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
3151d918647SAlex Vesker 	void *in_flow_context;
3161d918647SAlex Vesker 	unsigned int inlen;
3171d918647SAlex Vesker 	void *in_dests;
3181d918647SAlex Vesker 	u32 *in;
3191d918647SAlex Vesker 	int err;
3201d918647SAlex Vesker 
3211d918647SAlex Vesker 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
3221d918647SAlex Vesker 		1 * MLX5_ST_SZ_BYTES(dest_format_struct); /* One destination only */
3231d918647SAlex Vesker 
3241d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
3251d918647SAlex Vesker 	if (!in)
3261d918647SAlex Vesker 		return -ENOMEM;
3271d918647SAlex Vesker 
3281d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
3291d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, table_type, table_type);
3301d918647SAlex Vesker 	MLX5_SET(set_fte_in, in, table_id, table_id);
3311d918647SAlex Vesker 
3321d918647SAlex Vesker 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
3331d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
3341d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, modify_header_id, modify_header_id);
3351d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, destination_list_size, 1);
3361d918647SAlex Vesker 	MLX5_SET(flow_context, in_flow_context, action,
3371d918647SAlex Vesker 		 MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
3381d918647SAlex Vesker 		 MLX5_FLOW_CONTEXT_ACTION_MOD_HDR);
3391d918647SAlex Vesker 
3401d918647SAlex Vesker 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
3411d918647SAlex Vesker 	MLX5_SET(dest_format_struct, in_dests, destination_type,
342d639af62SMark Bloch 		 MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT);
343f9f93bd5SYevgeny Kliteynik 	MLX5_SET(dest_format_struct, in_dests, destination_id, vport);
3441d918647SAlex Vesker 
3451d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
3461d918647SAlex Vesker 	kvfree(in);
3471d918647SAlex Vesker 
3481d918647SAlex Vesker 	return err;
3491d918647SAlex Vesker }
3501d918647SAlex Vesker 
mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id)3511d918647SAlex Vesker int mlx5dr_cmd_del_flow_table_entry(struct mlx5_core_dev *mdev,
3521d918647SAlex Vesker 				    u32 table_type,
3531d918647SAlex Vesker 				    u32 table_id)
3541d918647SAlex Vesker {
3551d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {};
3561d918647SAlex Vesker 
3571d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
3581d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, table_type, table_type);
3591d918647SAlex Vesker 	MLX5_SET(delete_fte_in, in, table_id, table_id);
3601d918647SAlex Vesker 
3617ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, delete_fte, in);
3621d918647SAlex Vesker }
3631d918647SAlex Vesker 
mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev * mdev,u32 table_type,u8 num_of_actions,u64 * actions,u32 * modify_header_id)3641d918647SAlex Vesker int mlx5dr_cmd_alloc_modify_header(struct mlx5_core_dev *mdev,
3651d918647SAlex Vesker 				   u32 table_type,
3661d918647SAlex Vesker 				   u8 num_of_actions,
3671d918647SAlex Vesker 				   u64 *actions,
3681d918647SAlex Vesker 				   u32 *modify_header_id)
3691d918647SAlex Vesker {
3701d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {};
3711d918647SAlex Vesker 	void *p_actions;
3721d918647SAlex Vesker 	u32 inlen;
3731d918647SAlex Vesker 	u32 *in;
3741d918647SAlex Vesker 	int err;
3751d918647SAlex Vesker 
3761d918647SAlex Vesker 	inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) +
3771d918647SAlex Vesker 		 num_of_actions * sizeof(u64);
3781d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
3791d918647SAlex Vesker 	if (!in)
3801d918647SAlex Vesker 		return -ENOMEM;
3811d918647SAlex Vesker 
3821d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, opcode,
3831d918647SAlex Vesker 		 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT);
3841d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type);
3851d918647SAlex Vesker 	MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_of_actions);
3861d918647SAlex Vesker 	p_actions = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions);
3871d918647SAlex Vesker 	memcpy(p_actions, actions, num_of_actions * sizeof(u64));
3881d918647SAlex Vesker 
3891d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
3901d918647SAlex Vesker 	if (err)
3911d918647SAlex Vesker 		goto out;
3921d918647SAlex Vesker 
3931d918647SAlex Vesker 	*modify_header_id = MLX5_GET(alloc_modify_header_context_out, out,
3941d918647SAlex Vesker 				     modify_header_id);
3951d918647SAlex Vesker out:
3961d918647SAlex Vesker 	kvfree(in);
3971d918647SAlex Vesker 	return err;
3981d918647SAlex Vesker }
3991d918647SAlex Vesker 
mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev * mdev,u32 modify_header_id)4001d918647SAlex Vesker int mlx5dr_cmd_dealloc_modify_header(struct mlx5_core_dev *mdev,
4011d918647SAlex Vesker 				     u32 modify_header_id)
4021d918647SAlex Vesker {
4031d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {};
4041d918647SAlex Vesker 
4051d918647SAlex Vesker 	MLX5_SET(dealloc_modify_header_context_in, in, opcode,
4061d918647SAlex Vesker 		 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
4071d918647SAlex Vesker 	MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id,
4081d918647SAlex Vesker 		 modify_header_id);
4091d918647SAlex Vesker 
4107ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, dealloc_modify_header_context, in);
4111d918647SAlex Vesker }
4121d918647SAlex Vesker 
mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 * group_id)4131d918647SAlex Vesker int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
4141d918647SAlex Vesker 				       u32 table_type,
4151d918647SAlex Vesker 				       u32 table_id,
4161d918647SAlex Vesker 				       u32 *group_id)
4171d918647SAlex Vesker {
4181d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {};
4191d918647SAlex Vesker 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
4201d918647SAlex Vesker 	u32 *in;
4211d918647SAlex Vesker 	int err;
4221d918647SAlex Vesker 
423b7f86258SRoi Dayan 	in = kvzalloc(inlen, GFP_KERNEL);
4241d918647SAlex Vesker 	if (!in)
4251d918647SAlex Vesker 		return -ENOMEM;
4261d918647SAlex Vesker 
4271d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_GROUP);
4281d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, table_type, table_type);
4291d918647SAlex Vesker 	MLX5_SET(create_flow_group_in, in, table_id, table_id);
4301d918647SAlex Vesker 
4317ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, create_flow_group, in, out);
4321d918647SAlex Vesker 	if (err)
4331d918647SAlex Vesker 		goto out;
4341d918647SAlex Vesker 
4351d918647SAlex Vesker 	*group_id = MLX5_GET(create_flow_group_out, out, group_id);
4361d918647SAlex Vesker 
4371d918647SAlex Vesker out:
438b7f86258SRoi Dayan 	kvfree(in);
4391d918647SAlex Vesker 	return err;
4401d918647SAlex Vesker }
4411d918647SAlex Vesker 
mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev * mdev,u32 table_type,u32 table_id,u32 group_id)4421d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_group(struct mlx5_core_dev *mdev,
4431d918647SAlex Vesker 				  u32 table_type,
4441d918647SAlex Vesker 				  u32 table_id,
4451d918647SAlex Vesker 				  u32 group_id)
4461d918647SAlex Vesker {
4471d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {};
4481d918647SAlex Vesker 
4497ba294e4SLeon Romanovsky 	MLX5_SET(destroy_flow_group_in, in, opcode,
4507ba294e4SLeon Romanovsky 		 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
4511d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, table_type, table_type);
4521d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
4531d918647SAlex Vesker 	MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
4541d918647SAlex Vesker 
4557ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, destroy_flow_group, in);
4561d918647SAlex Vesker }
4571d918647SAlex Vesker 
mlx5dr_cmd_create_flow_table(struct mlx5_core_dev * mdev,struct mlx5dr_cmd_create_flow_table_attr * attr,u64 * fdb_rx_icm_addr,u32 * table_id)4581d918647SAlex Vesker int mlx5dr_cmd_create_flow_table(struct mlx5_core_dev *mdev,
459cc78dbd7SAlex Vesker 				 struct mlx5dr_cmd_create_flow_table_attr *attr,
4601d918647SAlex Vesker 				 u64 *fdb_rx_icm_addr,
4611d918647SAlex Vesker 				 u32 *table_id)
4621d918647SAlex Vesker {
4631d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {};
4641d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {};
4651d918647SAlex Vesker 	void *ft_mdev;
4661d918647SAlex Vesker 	int err;
4671d918647SAlex Vesker 
4681d918647SAlex Vesker 	MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE);
469cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, table_type, attr->table_type);
470b0bb369eSMark Bloch 	MLX5_SET(create_flow_table_in, in, uid, attr->uid);
4711d918647SAlex Vesker 
4721d918647SAlex Vesker 	ft_mdev = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context);
473cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, termination_table, attr->term_tbl);
474cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, sw_owner, attr->sw_owner);
475cc78dbd7SAlex Vesker 	MLX5_SET(flow_table_context, ft_mdev, level, attr->level);
4761d918647SAlex Vesker 
477cc78dbd7SAlex Vesker 	if (attr->sw_owner) {
4781d918647SAlex Vesker 		/* icm_addr_0 used for FDB RX / NIC TX / NIC_RX
4791d918647SAlex Vesker 		 * icm_addr_1 used for FDB TX
4801d918647SAlex Vesker 		 */
481cc78dbd7SAlex Vesker 		if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_RX) {
4821d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
483cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_rx);
484cc78dbd7SAlex Vesker 		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_NIC_TX) {
4851d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
486cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_tx);
487cc78dbd7SAlex Vesker 		} else if (attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB) {
4881d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
489cc78dbd7SAlex Vesker 				   sw_owner_icm_root_0, attr->icm_addr_rx);
4901d918647SAlex Vesker 			MLX5_SET64(flow_table_context, ft_mdev,
491cc78dbd7SAlex Vesker 				   sw_owner_icm_root_1, attr->icm_addr_tx);
4921d918647SAlex Vesker 		}
4931d918647SAlex Vesker 	}
4941d918647SAlex Vesker 
495cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
496cc78dbd7SAlex Vesker 		 attr->decap_en);
497cc78dbd7SAlex Vesker 	MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en,
498cc78dbd7SAlex Vesker 		 attr->reformat_en);
499cc78dbd7SAlex Vesker 
5007ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, create_flow_table, in, out);
5011d918647SAlex Vesker 	if (err)
5021d918647SAlex Vesker 		return err;
5031d918647SAlex Vesker 
5041d918647SAlex Vesker 	*table_id = MLX5_GET(create_flow_table_out, out, table_id);
505cc78dbd7SAlex Vesker 	if (!attr->sw_owner && attr->table_type == MLX5_FLOW_TABLE_TYPE_FDB &&
506cc78dbd7SAlex Vesker 	    fdb_rx_icm_addr)
5071d918647SAlex Vesker 		*fdb_rx_icm_addr =
5081d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_31_0) |
5091d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_39_32) << 32 |
5101d918647SAlex Vesker 		(u64)MLX5_GET(create_flow_table_out, out, icm_address_63_40) << 40;
5111d918647SAlex Vesker 
5121d918647SAlex Vesker 	return 0;
5131d918647SAlex Vesker }
5141d918647SAlex Vesker 
mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev * mdev,u32 table_id,u32 table_type)5151d918647SAlex Vesker int mlx5dr_cmd_destroy_flow_table(struct mlx5_core_dev *mdev,
5161d918647SAlex Vesker 				  u32 table_id,
5171d918647SAlex Vesker 				  u32 table_type)
5181d918647SAlex Vesker {
5191d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {};
5201d918647SAlex Vesker 
5211d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, opcode,
5221d918647SAlex Vesker 		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
5231d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, table_type, table_type);
5241d918647SAlex Vesker 	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
5251d918647SAlex Vesker 
5267ba294e4SLeon Romanovsky 	return mlx5_cmd_exec_in(mdev, destroy_flow_table, in);
5271d918647SAlex Vesker }
5281d918647SAlex Vesker 
mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev * mdev,enum mlx5_reformat_ctx_type rt,u8 reformat_param_0,u8 reformat_param_1,size_t reformat_size,void * reformat_data,u32 * reformat_id)5291d918647SAlex Vesker int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
5301d918647SAlex Vesker 				   enum mlx5_reformat_ctx_type rt,
5317ea9b398SYevgeny Kliteynik 				   u8 reformat_param_0,
5327ea9b398SYevgeny Kliteynik 				   u8 reformat_param_1,
5331d918647SAlex Vesker 				   size_t reformat_size,
5341d918647SAlex Vesker 				   void *reformat_data,
5351d918647SAlex Vesker 				   u32 *reformat_id)
5361d918647SAlex Vesker {
5371d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {};
5381d918647SAlex Vesker 	size_t inlen, cmd_data_sz, cmd_total_sz;
5391d918647SAlex Vesker 	void *prctx;
5401d918647SAlex Vesker 	void *pdata;
5411d918647SAlex Vesker 	void *in;
5421d918647SAlex Vesker 	int err;
5431d918647SAlex Vesker 
5441d918647SAlex Vesker 	cmd_total_sz = MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in);
5451d918647SAlex Vesker 	cmd_data_sz = MLX5_FLD_SZ_BYTES(alloc_packet_reformat_context_in,
5461d918647SAlex Vesker 					packet_reformat_context.reformat_data);
5471d918647SAlex Vesker 	inlen = ALIGN(cmd_total_sz + reformat_size - cmd_data_sz, 4);
5481d918647SAlex Vesker 	in = kvzalloc(inlen, GFP_KERNEL);
5491d918647SAlex Vesker 	if (!in)
5501d918647SAlex Vesker 		return -ENOMEM;
5511d918647SAlex Vesker 
5521d918647SAlex Vesker 	MLX5_SET(alloc_packet_reformat_context_in, in, opcode,
5531d918647SAlex Vesker 		 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT);
5541d918647SAlex Vesker 
5551d918647SAlex Vesker 	prctx = MLX5_ADDR_OF(alloc_packet_reformat_context_in, in, packet_reformat_context);
5561d918647SAlex Vesker 	pdata = MLX5_ADDR_OF(packet_reformat_context_in, prctx, reformat_data);
5571d918647SAlex Vesker 
5581d918647SAlex Vesker 	MLX5_SET(packet_reformat_context_in, prctx, reformat_type, rt);
5597ea9b398SYevgeny Kliteynik 	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_0, reformat_param_0);
5607ea9b398SYevgeny Kliteynik 	MLX5_SET(packet_reformat_context_in, prctx, reformat_param_1, reformat_param_1);
5611d918647SAlex Vesker 	MLX5_SET(packet_reformat_context_in, prctx, reformat_data_size, reformat_size);
5627ea9b398SYevgeny Kliteynik 	if (reformat_data && reformat_size)
5631d918647SAlex Vesker 		memcpy(pdata, reformat_data, reformat_size);
5641d918647SAlex Vesker 
5651d918647SAlex Vesker 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
5661d918647SAlex Vesker 	if (err)
567*5dd77585SZhengchao Shao 		goto err_free_in;
5681d918647SAlex Vesker 
5691d918647SAlex Vesker 	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
5701d918647SAlex Vesker 
571*5dd77585SZhengchao Shao err_free_in:
572*5dd77585SZhengchao Shao 	kvfree(in);
5731d918647SAlex Vesker 	return err;
5741d918647SAlex Vesker }
5751d918647SAlex Vesker 
mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev * mdev,u32 reformat_id)5761d918647SAlex Vesker void mlx5dr_cmd_destroy_reformat_ctx(struct mlx5_core_dev *mdev,
5771d918647SAlex Vesker 				     u32 reformat_id)
5781d918647SAlex Vesker {
5791d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {};
5801d918647SAlex Vesker 
5811d918647SAlex Vesker 	MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
5821d918647SAlex Vesker 		 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
5831d918647SAlex Vesker 	MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id,
5841d918647SAlex Vesker 		 reformat_id);
5851d918647SAlex Vesker 
5867ba294e4SLeon Romanovsky 	mlx5_cmd_exec_in(mdev, dealloc_packet_reformat_context, in);
5871d918647SAlex Vesker }
5881d918647SAlex Vesker 
dr_cmd_set_definer_format(void * ptr,u16 format_id,u8 * dw_selectors,u8 * byte_selectors)589e046b86eSYevgeny Kliteynik static void dr_cmd_set_definer_format(void *ptr, u16 format_id,
590e046b86eSYevgeny Kliteynik 				      u8 *dw_selectors,
591e046b86eSYevgeny Kliteynik 				      u8 *byte_selectors)
592e046b86eSYevgeny Kliteynik {
593e046b86eSYevgeny Kliteynik 	if (format_id != MLX5_IFC_DEFINER_FORMAT_ID_SELECT)
594e046b86eSYevgeny Kliteynik 		return;
595e046b86eSYevgeny Kliteynik 
596e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw0, dw_selectors[0]);
597e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw1, dw_selectors[1]);
598e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw2, dw_selectors[2]);
599e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw3, dw_selectors[3]);
600e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw4, dw_selectors[4]);
601e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw5, dw_selectors[5]);
602e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw6, dw_selectors[6]);
603e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw7, dw_selectors[7]);
604e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_dw8, dw_selectors[8]);
605e046b86eSYevgeny Kliteynik 
606e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte0, byte_selectors[0]);
607e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte1, byte_selectors[1]);
608e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte2, byte_selectors[2]);
609e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte3, byte_selectors[3]);
610e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte4, byte_selectors[4]);
611e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte5, byte_selectors[5]);
612e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte6, byte_selectors[6]);
613e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_select_byte7, byte_selectors[7]);
614e046b86eSYevgeny Kliteynik }
615e046b86eSYevgeny Kliteynik 
mlx5dr_cmd_create_definer(struct mlx5_core_dev * mdev,u16 format_id,u8 * dw_selectors,u8 * byte_selectors,u8 * match_mask,u32 * definer_id)616e046b86eSYevgeny Kliteynik int mlx5dr_cmd_create_definer(struct mlx5_core_dev *mdev,
617e046b86eSYevgeny Kliteynik 			      u16 format_id,
618e046b86eSYevgeny Kliteynik 			      u8 *dw_selectors,
619e046b86eSYevgeny Kliteynik 			      u8 *byte_selectors,
620e046b86eSYevgeny Kliteynik 			      u8 *match_mask,
621e046b86eSYevgeny Kliteynik 			      u32 *definer_id)
622e046b86eSYevgeny Kliteynik {
623e046b86eSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
624e046b86eSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(create_match_definer_in)] = {};
625e046b86eSYevgeny Kliteynik 	void *ptr;
626e046b86eSYevgeny Kliteynik 	int err;
627e046b86eSYevgeny Kliteynik 
628e046b86eSYevgeny Kliteynik 	ptr = MLX5_ADDR_OF(create_match_definer_in, in,
629e046b86eSYevgeny Kliteynik 			   general_obj_in_cmd_hdr);
630e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, ptr, opcode,
631e046b86eSYevgeny Kliteynik 		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
632e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, ptr, obj_type,
633e046b86eSYevgeny Kliteynik 		 MLX5_OBJ_TYPE_MATCH_DEFINER);
634e046b86eSYevgeny Kliteynik 
635e046b86eSYevgeny Kliteynik 	ptr = MLX5_ADDR_OF(create_match_definer_in, in, obj_context);
636e046b86eSYevgeny Kliteynik 	MLX5_SET(match_definer, ptr, format_id, format_id);
637e046b86eSYevgeny Kliteynik 
638e046b86eSYevgeny Kliteynik 	dr_cmd_set_definer_format(ptr, format_id,
639e046b86eSYevgeny Kliteynik 				  dw_selectors, byte_selectors);
640e046b86eSYevgeny Kliteynik 
641e046b86eSYevgeny Kliteynik 	ptr = MLX5_ADDR_OF(match_definer, ptr, match_mask);
642e046b86eSYevgeny Kliteynik 	memcpy(ptr, match_mask, MLX5_FLD_SZ_BYTES(match_definer, match_mask));
643e046b86eSYevgeny Kliteynik 
644e046b86eSYevgeny Kliteynik 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
645e046b86eSYevgeny Kliteynik 	if (err)
646e046b86eSYevgeny Kliteynik 		return err;
647e046b86eSYevgeny Kliteynik 
648e046b86eSYevgeny Kliteynik 	*definer_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
649e046b86eSYevgeny Kliteynik 
650e046b86eSYevgeny Kliteynik 	return 0;
651e046b86eSYevgeny Kliteynik }
652e046b86eSYevgeny Kliteynik 
653e046b86eSYevgeny Kliteynik void
mlx5dr_cmd_destroy_definer(struct mlx5_core_dev * mdev,u32 definer_id)654e046b86eSYevgeny Kliteynik mlx5dr_cmd_destroy_definer(struct mlx5_core_dev *mdev, u32 definer_id)
655e046b86eSYevgeny Kliteynik {
656e046b86eSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
657e046b86eSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
658e046b86eSYevgeny Kliteynik 
659e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
660e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_MATCH_DEFINER);
661e046b86eSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, definer_id);
662e046b86eSYevgeny Kliteynik 
663e046b86eSYevgeny Kliteynik 	mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
664e046b86eSYevgeny Kliteynik }
665e046b86eSYevgeny Kliteynik 
mlx5dr_cmd_query_gid(struct mlx5_core_dev * mdev,u8 vhca_port_num,u16 index,struct mlx5dr_cmd_gid_attr * attr)6661d918647SAlex Vesker int mlx5dr_cmd_query_gid(struct mlx5_core_dev *mdev, u8 vhca_port_num,
6671d918647SAlex Vesker 			 u16 index, struct mlx5dr_cmd_gid_attr *attr)
6681d918647SAlex Vesker {
6691d918647SAlex Vesker 	u32 out[MLX5_ST_SZ_DW(query_roce_address_out)] = {};
6701d918647SAlex Vesker 	u32 in[MLX5_ST_SZ_DW(query_roce_address_in)] = {};
6711d918647SAlex Vesker 	int err;
6721d918647SAlex Vesker 
6731d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, opcode,
6741d918647SAlex Vesker 		 MLX5_CMD_OP_QUERY_ROCE_ADDRESS);
6751d918647SAlex Vesker 
6761d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, roce_address_index, index);
6771d918647SAlex Vesker 	MLX5_SET(query_roce_address_in, in, vhca_port_num, vhca_port_num);
6781d918647SAlex Vesker 
6797ba294e4SLeon Romanovsky 	err = mlx5_cmd_exec_inout(mdev, query_roce_address, in, out);
6801d918647SAlex Vesker 	if (err)
6811d918647SAlex Vesker 		return err;
6821d918647SAlex Vesker 
6831d918647SAlex Vesker 	memcpy(&attr->gid,
6841d918647SAlex Vesker 	       MLX5_ADDR_OF(query_roce_address_out,
6851d918647SAlex Vesker 			    out, roce_address.source_l3_address),
6861d918647SAlex Vesker 	       sizeof(attr->gid));
6871d918647SAlex Vesker 	memcpy(attr->mac,
6881d918647SAlex Vesker 	       MLX5_ADDR_OF(query_roce_address_out, out,
6891d918647SAlex Vesker 			    roce_address.source_mac_47_32),
6901d918647SAlex Vesker 	       sizeof(attr->mac));
6911d918647SAlex Vesker 
6921d918647SAlex Vesker 	if (MLX5_GET(query_roce_address_out, out,
6931d918647SAlex Vesker 		     roce_address.roce_version) == MLX5_ROCE_VERSION_2)
6941d918647SAlex Vesker 		attr->roce_ver = MLX5_ROCE_VERSION_2;
6951d918647SAlex Vesker 	else
6961d918647SAlex Vesker 		attr->roce_ver = MLX5_ROCE_VERSION_1;
6971d918647SAlex Vesker 
6981d918647SAlex Vesker 	return 0;
6991d918647SAlex Vesker }
7006de03d2dSErez Shitrit 
mlx5dr_cmd_create_modify_header_arg(struct mlx5_core_dev * dev,u16 log_obj_range,u32 pd,u32 * obj_id)701de69696bSYevgeny Kliteynik int mlx5dr_cmd_create_modify_header_arg(struct mlx5_core_dev *dev,
702de69696bSYevgeny Kliteynik 					u16 log_obj_range, u32 pd,
703de69696bSYevgeny Kliteynik 					u32 *obj_id)
704de69696bSYevgeny Kliteynik {
705de69696bSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {};
706de69696bSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
707de69696bSYevgeny Kliteynik 	void *attr;
708de69696bSYevgeny Kliteynik 	int ret;
709de69696bSYevgeny Kliteynik 
710de69696bSYevgeny Kliteynik 	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
711de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, attr, opcode,
712de69696bSYevgeny Kliteynik 		 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
713de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, attr, obj_type,
714de69696bSYevgeny Kliteynik 		 MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
715de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, attr,
716de69696bSYevgeny Kliteynik 		 op_param.create.log_obj_range, log_obj_range);
717de69696bSYevgeny Kliteynik 
718de69696bSYevgeny Kliteynik 	attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
719de69696bSYevgeny Kliteynik 	MLX5_SET(modify_header_arg, attr, access_pd, pd);
720de69696bSYevgeny Kliteynik 
721de69696bSYevgeny Kliteynik 	ret = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
722de69696bSYevgeny Kliteynik 	if (ret)
723de69696bSYevgeny Kliteynik 		return ret;
724de69696bSYevgeny Kliteynik 
725de69696bSYevgeny Kliteynik 	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
726de69696bSYevgeny Kliteynik 	return 0;
727de69696bSYevgeny Kliteynik }
728de69696bSYevgeny Kliteynik 
mlx5dr_cmd_destroy_modify_header_arg(struct mlx5_core_dev * dev,u32 obj_id)729de69696bSYevgeny Kliteynik void mlx5dr_cmd_destroy_modify_header_arg(struct mlx5_core_dev *dev,
730de69696bSYevgeny Kliteynik 					  u32 obj_id)
731de69696bSYevgeny Kliteynik {
732de69696bSYevgeny Kliteynik 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
733de69696bSYevgeny Kliteynik 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
734de69696bSYevgeny Kliteynik 
735de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
736de69696bSYevgeny Kliteynik 		 MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
737de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
738de69696bSYevgeny Kliteynik 		 MLX5_OBJ_TYPE_HEADER_MODIFY_ARGUMENT);
739de69696bSYevgeny Kliteynik 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, obj_id);
740de69696bSYevgeny Kliteynik 
741de69696bSYevgeny Kliteynik 	mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
742de69696bSYevgeny Kliteynik }
743de69696bSYevgeny Kliteynik 
mlx5dr_cmd_set_extended_dest(struct mlx5_core_dev * dev,struct mlx5dr_cmd_fte_info * fte,bool * extended_dest)7446de03d2dSErez Shitrit static int mlx5dr_cmd_set_extended_dest(struct mlx5_core_dev *dev,
7456de03d2dSErez Shitrit 					struct mlx5dr_cmd_fte_info *fte,
7466de03d2dSErez Shitrit 					bool *extended_dest)
7476de03d2dSErez Shitrit {
7486de03d2dSErez Shitrit 	int fw_log_max_fdb_encap_uplink = MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink);
7496de03d2dSErez Shitrit 	int num_fwd_destinations = 0;
7506de03d2dSErez Shitrit 	int num_encap = 0;
7516de03d2dSErez Shitrit 	int i;
7526de03d2dSErez Shitrit 
7536de03d2dSErez Shitrit 	*extended_dest = false;
7546de03d2dSErez Shitrit 	if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
7556de03d2dSErez Shitrit 		return 0;
7566de03d2dSErez Shitrit 	for (i = 0; i < fte->dests_size; i++) {
7576510bc0dSMark Bloch 		if (fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ||
7586510bc0dSMark Bloch 		    fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_NONE)
7596de03d2dSErez Shitrit 			continue;
760e3a0f40bSYevgeny Kliteynik 		if ((fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_VPORT ||
761e3a0f40bSYevgeny Kliteynik 		     fte->dest_arr[i].type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) &&
7626de03d2dSErez Shitrit 		    fte->dest_arr[i].vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
7636de03d2dSErez Shitrit 			num_encap++;
7646de03d2dSErez Shitrit 		num_fwd_destinations++;
7656de03d2dSErez Shitrit 	}
7666de03d2dSErez Shitrit 
7676de03d2dSErez Shitrit 	if (num_fwd_destinations > 1 && num_encap > 0)
7686de03d2dSErez Shitrit 		*extended_dest = true;
7696de03d2dSErez Shitrit 
7706de03d2dSErez Shitrit 	if (*extended_dest && !fw_log_max_fdb_encap_uplink) {
7716de03d2dSErez Shitrit 		mlx5_core_warn(dev, "FW does not support extended destination");
7726de03d2dSErez Shitrit 		return -EOPNOTSUPP;
7736de03d2dSErez Shitrit 	}
7746de03d2dSErez Shitrit 	if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) {
7756de03d2dSErez Shitrit 		mlx5_core_warn(dev, "FW does not support more than %d encaps",
7766de03d2dSErez Shitrit 			       1 << fw_log_max_fdb_encap_uplink);
7776de03d2dSErez Shitrit 		return -EOPNOTSUPP;
7786de03d2dSErez Shitrit 	}
7796de03d2dSErez Shitrit 
7806de03d2dSErez Shitrit 	return 0;
7816de03d2dSErez Shitrit }
7826de03d2dSErez Shitrit 
mlx5dr_cmd_set_fte(struct mlx5_core_dev * dev,int opmod,int modify_mask,struct mlx5dr_cmd_ft_info * ft,u32 group_id,struct mlx5dr_cmd_fte_info * fte)7836de03d2dSErez Shitrit int mlx5dr_cmd_set_fte(struct mlx5_core_dev *dev,
7846de03d2dSErez Shitrit 		       int opmod, int modify_mask,
7856de03d2dSErez Shitrit 		       struct mlx5dr_cmd_ft_info *ft,
7866de03d2dSErez Shitrit 		       u32 group_id,
7876de03d2dSErez Shitrit 		       struct mlx5dr_cmd_fte_info *fte)
7886de03d2dSErez Shitrit {
7896de03d2dSErez Shitrit 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {};
7906de03d2dSErez Shitrit 	void *in_flow_context, *vlan;
7916de03d2dSErez Shitrit 	bool extended_dest = false;
7926de03d2dSErez Shitrit 	void *in_match_value;
7936de03d2dSErez Shitrit 	unsigned int inlen;
7946de03d2dSErez Shitrit 	int dst_cnt_size;
7956de03d2dSErez Shitrit 	void *in_dests;
7966de03d2dSErez Shitrit 	u32 *in;
7976de03d2dSErez Shitrit 	int err;
7986de03d2dSErez Shitrit 	int i;
7996de03d2dSErez Shitrit 
8006de03d2dSErez Shitrit 	if (mlx5dr_cmd_set_extended_dest(dev, fte, &extended_dest))
8016de03d2dSErez Shitrit 		return -EOPNOTSUPP;
8026de03d2dSErez Shitrit 
8036de03d2dSErez Shitrit 	if (!extended_dest)
8046de03d2dSErez Shitrit 		dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct);
8056de03d2dSErez Shitrit 	else
8066de03d2dSErez Shitrit 		dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format);
8076de03d2dSErez Shitrit 
8086de03d2dSErez Shitrit 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size;
8096de03d2dSErez Shitrit 	in = kvzalloc(inlen, GFP_KERNEL);
8106de03d2dSErez Shitrit 	if (!in)
8116de03d2dSErez Shitrit 		return -ENOMEM;
8126de03d2dSErez Shitrit 
8136de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
8146de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, op_mod, opmod);
8156de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
8166de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, table_type, ft->type);
8176de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, table_id, ft->id);
8186de03d2dSErez Shitrit 	MLX5_SET(set_fte_in, in, flow_index, fte->index);
81963b85f49SYevgeny Kliteynik 	MLX5_SET(set_fte_in, in, ignore_flow_level, fte->ignore_flow_level);
8206de03d2dSErez Shitrit 	if (ft->vport) {
8216de03d2dSErez Shitrit 		MLX5_SET(set_fte_in, in, vport_number, ft->vport);
8226de03d2dSErez Shitrit 		MLX5_SET(set_fte_in, in, other_vport, 1);
8236de03d2dSErez Shitrit 	}
8246de03d2dSErez Shitrit 
8256de03d2dSErez Shitrit 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
8266de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
8276de03d2dSErez Shitrit 
8286de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, flow_tag,
8296de03d2dSErez Shitrit 		 fte->flow_context.flow_tag);
8306de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, flow_source,
8316de03d2dSErez Shitrit 		 fte->flow_context.flow_source);
8326de03d2dSErez Shitrit 
8336de03d2dSErez Shitrit 	MLX5_SET(flow_context, in_flow_context, extended_destination,
8346de03d2dSErez Shitrit 		 extended_dest);
8356de03d2dSErez Shitrit 	if (extended_dest) {
8366de03d2dSErez Shitrit 		u32 action;
8376de03d2dSErez Shitrit 
8386de03d2dSErez Shitrit 		action = fte->action.action &
8396de03d2dSErez Shitrit 			~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
8406de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, action, action);
8416de03d2dSErez Shitrit 	} else {
8426de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, action,
8436de03d2dSErez Shitrit 			 fte->action.action);
8446de03d2dSErez Shitrit 		if (fte->action.pkt_reformat)
8456de03d2dSErez Shitrit 			MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
8466de03d2dSErez Shitrit 				 fte->action.pkt_reformat->id);
8476de03d2dSErez Shitrit 	}
8486de03d2dSErez Shitrit 	if (fte->action.modify_hdr)
8496de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, modify_header_id,
8506de03d2dSErez Shitrit 			 fte->action.modify_hdr->id);
8516de03d2dSErez Shitrit 
8526de03d2dSErez Shitrit 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan);
8536de03d2dSErez Shitrit 
8546de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype);
8556de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid);
8566de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio);
8576de03d2dSErez Shitrit 
8586de03d2dSErez Shitrit 	vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2);
8596de03d2dSErez Shitrit 
8606de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype);
8616de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid);
8626de03d2dSErez Shitrit 	MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio);
8636de03d2dSErez Shitrit 
8646de03d2dSErez Shitrit 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
8656de03d2dSErez Shitrit 				      match_value);
8666de03d2dSErez Shitrit 	memcpy(in_match_value, fte->val, sizeof(u32) * MLX5_ST_SZ_DW_MATCH_PARAM);
8676de03d2dSErez Shitrit 
8686de03d2dSErez Shitrit 	in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
8696de03d2dSErez Shitrit 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
8706de03d2dSErez Shitrit 		int list_size = 0;
8716de03d2dSErez Shitrit 
8726de03d2dSErez Shitrit 		for (i = 0; i < fte->dests_size; i++) {
873d639af62SMark Bloch 			enum mlx5_flow_destination_type type = fte->dest_arr[i].type;
874d639af62SMark Bloch 			enum mlx5_ifc_flow_destination_type ifc_type;
875d639af62SMark Bloch 			unsigned int id;
8766de03d2dSErez Shitrit 
8776de03d2dSErez Shitrit 			if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
8786de03d2dSErez Shitrit 				continue;
8796de03d2dSErez Shitrit 
8806de03d2dSErez Shitrit 			switch (type) {
8816510bc0dSMark Bloch 			case MLX5_FLOW_DESTINATION_TYPE_NONE:
8826510bc0dSMark Bloch 				continue;
8836de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
8846de03d2dSErez Shitrit 				id = fte->dest_arr[i].ft_num;
885d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
8866de03d2dSErez Shitrit 				break;
8876de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
8886de03d2dSErez Shitrit 				id = fte->dest_arr[i].ft_id;
889d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE;
890d639af62SMark Bloch 
8916de03d2dSErez Shitrit 				break;
892e3a0f40bSYevgeny Kliteynik 			case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
8936de03d2dSErez Shitrit 			case MLX5_FLOW_DESTINATION_TYPE_VPORT:
894e3a0f40bSYevgeny Kliteynik 				if (type == MLX5_FLOW_DESTINATION_TYPE_VPORT) {
8956de03d2dSErez Shitrit 					id = fte->dest_arr[i].vport.num;
8966de03d2dSErez Shitrit 					MLX5_SET(dest_format_struct, in_dests,
8976de03d2dSErez Shitrit 						 destination_eswitch_owner_vhca_id_valid,
8986de03d2dSErez Shitrit 						 !!(fte->dest_arr[i].vport.flags &
8996de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_VHCA_ID));
900d639af62SMark Bloch 					ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT;
901e3a0f40bSYevgeny Kliteynik 				} else {
902e3a0f40bSYevgeny Kliteynik 					id = 0;
903d639af62SMark Bloch 					ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK;
904e3a0f40bSYevgeny Kliteynik 					MLX5_SET(dest_format_struct, in_dests,
905e3a0f40bSYevgeny Kliteynik 						 destination_eswitch_owner_vhca_id_valid, 1);
906e3a0f40bSYevgeny Kliteynik 				}
9076de03d2dSErez Shitrit 				MLX5_SET(dest_format_struct, in_dests,
9086de03d2dSErez Shitrit 					 destination_eswitch_owner_vhca_id,
9096de03d2dSErez Shitrit 					 fte->dest_arr[i].vport.vhca_id);
9106de03d2dSErez Shitrit 				if (extended_dest && (fte->dest_arr[i].vport.flags &
9116de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID)) {
9126de03d2dSErez Shitrit 					MLX5_SET(dest_format_struct, in_dests,
9136de03d2dSErez Shitrit 						 packet_reformat,
9146de03d2dSErez Shitrit 						 !!(fte->dest_arr[i].vport.flags &
9156de03d2dSErez Shitrit 						    MLX5_FLOW_DEST_VPORT_REFORMAT_ID));
9166de03d2dSErez Shitrit 					MLX5_SET(extended_dest_format, in_dests,
9176de03d2dSErez Shitrit 						 packet_reformat_id,
9186de03d2dSErez Shitrit 						 fte->dest_arr[i].vport.reformat_id);
9196de03d2dSErez Shitrit 				}
9206de03d2dSErez Shitrit 				break;
9211ab6dc35SYevgeny Kliteynik 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
9221ab6dc35SYevgeny Kliteynik 				id = fte->dest_arr[i].sampler_id;
923d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
9241ab6dc35SYevgeny Kliteynik 				break;
9256de03d2dSErez Shitrit 			default:
9266de03d2dSErez Shitrit 				id = fte->dest_arr[i].tir_num;
927d639af62SMark Bloch 				ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TIR;
9286de03d2dSErez Shitrit 			}
9296de03d2dSErez Shitrit 
9306de03d2dSErez Shitrit 			MLX5_SET(dest_format_struct, in_dests, destination_type,
931d639af62SMark Bloch 				 ifc_type);
9326de03d2dSErez Shitrit 			MLX5_SET(dest_format_struct, in_dests, destination_id, id);
9336de03d2dSErez Shitrit 			in_dests += dst_cnt_size;
9346de03d2dSErez Shitrit 			list_size++;
9356de03d2dSErez Shitrit 		}
9366de03d2dSErez Shitrit 
9376de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, destination_list_size,
9386de03d2dSErez Shitrit 			 list_size);
9396de03d2dSErez Shitrit 	}
9406de03d2dSErez Shitrit 
9416de03d2dSErez Shitrit 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
9426de03d2dSErez Shitrit 		int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev,
9436de03d2dSErez Shitrit 					log_max_flow_counter,
9446de03d2dSErez Shitrit 					ft->type));
9456de03d2dSErez Shitrit 		int list_size = 0;
9466de03d2dSErez Shitrit 
9476de03d2dSErez Shitrit 		for (i = 0; i < fte->dests_size; i++) {
9486de03d2dSErez Shitrit 			if (fte->dest_arr[i].type !=
9496de03d2dSErez Shitrit 			    MLX5_FLOW_DESTINATION_TYPE_COUNTER)
9506de03d2dSErez Shitrit 				continue;
9516de03d2dSErez Shitrit 
9526de03d2dSErez Shitrit 			MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
9536de03d2dSErez Shitrit 				 fte->dest_arr[i].counter_id);
9546de03d2dSErez Shitrit 			in_dests += dst_cnt_size;
9556de03d2dSErez Shitrit 			list_size++;
9566de03d2dSErez Shitrit 		}
9576de03d2dSErez Shitrit 		if (list_size > max_list_size) {
9586de03d2dSErez Shitrit 			err = -EINVAL;
9596de03d2dSErez Shitrit 			goto err_out;
9606de03d2dSErez Shitrit 		}
9616de03d2dSErez Shitrit 
9626de03d2dSErez Shitrit 		MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
9636de03d2dSErez Shitrit 			 list_size);
9646de03d2dSErez Shitrit 	}
9656de03d2dSErez Shitrit 
9666de03d2dSErez Shitrit 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
9676de03d2dSErez Shitrit err_out:
9686de03d2dSErez Shitrit 	kvfree(in);
9696de03d2dSErez Shitrit 	return err;
9706de03d2dSErez Shitrit }
971