126d688e3SAlex Vesker // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
226d688e3SAlex Vesker /* Copyright (c) 2019 Mellanox Technologies. */
326d688e3SAlex Vesker 
426d688e3SAlex Vesker #include <linux/types.h>
540416d8eSHamdan Igbaria #include <linux/crc32.h>
626d688e3SAlex Vesker #include "dr_types.h"
726d688e3SAlex Vesker 
826d688e3SAlex Vesker #define DR_STE_CRC_POLY 0xEDB88320L
926d688e3SAlex Vesker #define STE_IPV4 0x1
1026d688e3SAlex Vesker #define STE_IPV6 0x2
1126d688e3SAlex Vesker #define STE_TCP 0x1
1226d688e3SAlex Vesker #define STE_UDP 0x2
1326d688e3SAlex Vesker #define STE_SPI 0x3
1426d688e3SAlex Vesker #define IP_VERSION_IPV4 0x4
1526d688e3SAlex Vesker #define IP_VERSION_IPV6 0x6
1626d688e3SAlex Vesker #define STE_SVLAN 0x1
1726d688e3SAlex Vesker #define STE_CVLAN 0x2
1826d688e3SAlex Vesker 
1926d688e3SAlex Vesker #define DR_STE_ENABLE_FLOW_TAG BIT(31)
2026d688e3SAlex Vesker 
2126d688e3SAlex Vesker /* Set to STE a specific value using DR_STE_SET */
2226d688e3SAlex Vesker #define DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, value) do { \
2326d688e3SAlex Vesker 	if ((spec)->s_fname) { \
2426d688e3SAlex Vesker 		MLX5_SET(ste_##lookup_type, tag, t_fname, value); \
2526d688e3SAlex Vesker 		(spec)->s_fname = 0; \
2626d688e3SAlex Vesker 	} \
2726d688e3SAlex Vesker } while (0)
2826d688e3SAlex Vesker 
2926d688e3SAlex Vesker /* Set to STE spec->s_fname to tag->t_fname */
3026d688e3SAlex Vesker #define DR_STE_SET_TAG(lookup_type, tag, t_fname, spec, s_fname) \
3126d688e3SAlex Vesker 	DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, spec->s_fname)
3226d688e3SAlex Vesker 
3326d688e3SAlex Vesker /* Set to STE -1 to bit_mask->bm_fname and set spec->s_fname as used */
3426d688e3SAlex Vesker #define DR_STE_SET_MASK(lookup_type, bit_mask, bm_fname, spec, s_fname) \
3526d688e3SAlex Vesker 	DR_STE_SET_VAL(lookup_type, bit_mask, bm_fname, spec, s_fname, -1)
3626d688e3SAlex Vesker 
3726d688e3SAlex Vesker /* Set to STE spec->s_fname to bit_mask->bm_fname and set spec->s_fname as used */
3826d688e3SAlex Vesker #define DR_STE_SET_MASK_V(lookup_type, bit_mask, bm_fname, spec, s_fname) \
3926d688e3SAlex Vesker 	DR_STE_SET_VAL(lookup_type, bit_mask, bm_fname, spec, s_fname, (spec)->s_fname)
4026d688e3SAlex Vesker 
4126d688e3SAlex Vesker #define DR_STE_SET_TCP_FLAGS(lookup_type, tag, spec) do { \
4226d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_ns, !!((spec)->tcp_flags & (1 << 8))); \
4326d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_cwr, !!((spec)->tcp_flags & (1 << 7))); \
4426d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_ece, !!((spec)->tcp_flags & (1 << 6))); \
4526d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_urg, !!((spec)->tcp_flags & (1 << 5))); \
4626d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_ack, !!((spec)->tcp_flags & (1 << 4))); \
4726d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_psh, !!((spec)->tcp_flags & (1 << 3))); \
4826d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_rst, !!((spec)->tcp_flags & (1 << 2))); \
4926d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_syn, !!((spec)->tcp_flags & (1 << 1))); \
5026d688e3SAlex Vesker 	MLX5_SET(ste_##lookup_type, tag, tcp_fin, !!((spec)->tcp_flags & (1 << 0))); \
5126d688e3SAlex Vesker } while (0)
5226d688e3SAlex Vesker 
5326d688e3SAlex Vesker #define DR_STE_SET_MPLS_MASK(lookup_type, mask, in_out, bit_mask) do { \
5426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(lookup_type, mask, mpls0_label, mask, \
5526d688e3SAlex Vesker 			  in_out##_first_mpls_label);\
5626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(lookup_type, mask, mpls0_s_bos, mask, \
5726d688e3SAlex Vesker 			  in_out##_first_mpls_s_bos); \
5826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(lookup_type, mask, mpls0_exp, mask, \
5926d688e3SAlex Vesker 			  in_out##_first_mpls_exp); \
6026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(lookup_type, mask, mpls0_ttl, mask, \
6126d688e3SAlex Vesker 			  in_out##_first_mpls_ttl); \
6226d688e3SAlex Vesker } while (0)
6326d688e3SAlex Vesker 
6426d688e3SAlex Vesker #define DR_STE_SET_MPLS_TAG(lookup_type, mask, in_out, tag) do { \
6526d688e3SAlex Vesker 	DR_STE_SET_TAG(lookup_type, tag, mpls0_label, mask, \
6626d688e3SAlex Vesker 		       in_out##_first_mpls_label);\
6726d688e3SAlex Vesker 	DR_STE_SET_TAG(lookup_type, tag, mpls0_s_bos, mask, \
6826d688e3SAlex Vesker 		       in_out##_first_mpls_s_bos); \
6926d688e3SAlex Vesker 	DR_STE_SET_TAG(lookup_type, tag, mpls0_exp, mask, \
7026d688e3SAlex Vesker 		       in_out##_first_mpls_exp); \
7126d688e3SAlex Vesker 	DR_STE_SET_TAG(lookup_type, tag, mpls0_ttl, mask, \
7226d688e3SAlex Vesker 		       in_out##_first_mpls_ttl); \
7326d688e3SAlex Vesker } while (0)
7426d688e3SAlex Vesker 
7526d688e3SAlex Vesker #define DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(_misc) (\
7626d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_gre_label || \
7726d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_gre_exp || \
7826d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_gre_s_bos || \
7926d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_gre_ttl)
8026d688e3SAlex Vesker #define DR_STE_IS_OUTER_MPLS_OVER_UDP_SET(_misc) (\
8126d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_udp_label || \
8226d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_udp_exp || \
8326d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_udp_s_bos || \
8426d688e3SAlex Vesker 	(_misc)->outer_first_mpls_over_udp_ttl)
8526d688e3SAlex Vesker 
8626d688e3SAlex Vesker #define DR_STE_CALC_LU_TYPE(lookup_type, rx, inner) \
8726d688e3SAlex Vesker 	((inner) ? MLX5DR_STE_LU_TYPE_##lookup_type##_I : \
8826d688e3SAlex Vesker 		   (rx) ? MLX5DR_STE_LU_TYPE_##lookup_type##_D : \
8926d688e3SAlex Vesker 			  MLX5DR_STE_LU_TYPE_##lookup_type##_O)
9026d688e3SAlex Vesker 
9126d688e3SAlex Vesker enum dr_ste_tunl_action {
9226d688e3SAlex Vesker 	DR_STE_TUNL_ACTION_NONE		= 0,
9326d688e3SAlex Vesker 	DR_STE_TUNL_ACTION_ENABLE	= 1,
9426d688e3SAlex Vesker 	DR_STE_TUNL_ACTION_DECAP	= 2,
9526d688e3SAlex Vesker 	DR_STE_TUNL_ACTION_L3_DECAP	= 3,
9626d688e3SAlex Vesker 	DR_STE_TUNL_ACTION_POP_VLAN	= 4,
9726d688e3SAlex Vesker };
9826d688e3SAlex Vesker 
9926d688e3SAlex Vesker enum dr_ste_action_type {
10026d688e3SAlex Vesker 	DR_STE_ACTION_TYPE_PUSH_VLAN	= 1,
10126d688e3SAlex Vesker 	DR_STE_ACTION_TYPE_ENCAP_L3	= 3,
10226d688e3SAlex Vesker 	DR_STE_ACTION_TYPE_ENCAP	= 4,
10326d688e3SAlex Vesker };
10426d688e3SAlex Vesker 
10526d688e3SAlex Vesker struct dr_hw_ste_format {
10626d688e3SAlex Vesker 	u8 ctrl[DR_STE_SIZE_CTRL];
10726d688e3SAlex Vesker 	u8 tag[DR_STE_SIZE_TAG];
10826d688e3SAlex Vesker 	u8 mask[DR_STE_SIZE_MASK];
10926d688e3SAlex Vesker };
11026d688e3SAlex Vesker 
11140416d8eSHamdan Igbaria static u32 dr_ste_crc32_calc(const void *input_data, size_t length)
11240416d8eSHamdan Igbaria {
11340416d8eSHamdan Igbaria 	u32 crc = crc32(0, input_data, length);
11440416d8eSHamdan Igbaria 
1159ff2e92cSSaeed Mahameed 	return (__force u32)htonl(crc);
11640416d8eSHamdan Igbaria }
11740416d8eSHamdan Igbaria 
11826d688e3SAlex Vesker u32 mlx5dr_ste_calc_hash_index(u8 *hw_ste_p, struct mlx5dr_ste_htbl *htbl)
11926d688e3SAlex Vesker {
12026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
12126d688e3SAlex Vesker 	u8 masked[DR_STE_SIZE_TAG] = {};
12226d688e3SAlex Vesker 	u32 crc32, index;
12326d688e3SAlex Vesker 	u16 bit;
12426d688e3SAlex Vesker 	int i;
12526d688e3SAlex Vesker 
12626d688e3SAlex Vesker 	/* Don't calculate CRC if the result is predicted */
12726d688e3SAlex Vesker 	if (htbl->chunk->num_of_entries == 1 || htbl->byte_mask == 0)
12826d688e3SAlex Vesker 		return 0;
12926d688e3SAlex Vesker 
13026d688e3SAlex Vesker 	/* Mask tag using byte mask, bit per byte */
13126d688e3SAlex Vesker 	bit = 1 << (DR_STE_SIZE_TAG - 1);
13226d688e3SAlex Vesker 	for (i = 0; i < DR_STE_SIZE_TAG; i++) {
13326d688e3SAlex Vesker 		if (htbl->byte_mask & bit)
13426d688e3SAlex Vesker 			masked[i] = hw_ste->tag[i];
13526d688e3SAlex Vesker 
13626d688e3SAlex Vesker 		bit = bit >> 1;
13726d688e3SAlex Vesker 	}
13826d688e3SAlex Vesker 
13940416d8eSHamdan Igbaria 	crc32 = dr_ste_crc32_calc(masked, DR_STE_SIZE_TAG);
14026d688e3SAlex Vesker 	index = crc32 & (htbl->chunk->num_of_entries - 1);
14126d688e3SAlex Vesker 
14226d688e3SAlex Vesker 	return index;
14326d688e3SAlex Vesker }
14426d688e3SAlex Vesker 
14526d688e3SAlex Vesker static u16 dr_ste_conv_bit_to_byte_mask(u8 *bit_mask)
14626d688e3SAlex Vesker {
14726d688e3SAlex Vesker 	u16 byte_mask = 0;
14826d688e3SAlex Vesker 	int i;
14926d688e3SAlex Vesker 
15026d688e3SAlex Vesker 	for (i = 0; i < DR_STE_SIZE_MASK; i++) {
15126d688e3SAlex Vesker 		byte_mask = byte_mask << 1;
15226d688e3SAlex Vesker 		if (bit_mask[i] == 0xff)
15326d688e3SAlex Vesker 			byte_mask |= 1;
15426d688e3SAlex Vesker 	}
15526d688e3SAlex Vesker 	return byte_mask;
15626d688e3SAlex Vesker }
15726d688e3SAlex Vesker 
15826d688e3SAlex Vesker void mlx5dr_ste_set_bit_mask(u8 *hw_ste_p, u8 *bit_mask)
15926d688e3SAlex Vesker {
16026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
16126d688e3SAlex Vesker 
16226d688e3SAlex Vesker 	memcpy(hw_ste->mask, bit_mask, DR_STE_SIZE_MASK);
16326d688e3SAlex Vesker }
16426d688e3SAlex Vesker 
16526d688e3SAlex Vesker void mlx5dr_ste_rx_set_flow_tag(u8 *hw_ste_p, u32 flow_tag)
16626d688e3SAlex Vesker {
16726d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, qp_list_pointer,
16826d688e3SAlex Vesker 		 DR_STE_ENABLE_FLOW_TAG | flow_tag);
16926d688e3SAlex Vesker }
17026d688e3SAlex Vesker 
17126d688e3SAlex Vesker void mlx5dr_ste_set_counter_id(u8 *hw_ste_p, u32 ctr_id)
17226d688e3SAlex Vesker {
17326d688e3SAlex Vesker 	/* This can be used for both rx_steering_mult and for sx_transmit */
17426d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, counter_trigger_15_0, ctr_id);
17526d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, counter_trigger_23_16, ctr_id >> 16);
17626d688e3SAlex Vesker }
17726d688e3SAlex Vesker 
17826d688e3SAlex Vesker void mlx5dr_ste_set_go_back_bit(u8 *hw_ste_p)
17926d688e3SAlex Vesker {
18026d688e3SAlex Vesker 	MLX5_SET(ste_sx_transmit, hw_ste_p, go_back, 1);
18126d688e3SAlex Vesker }
18226d688e3SAlex Vesker 
18326d688e3SAlex Vesker void mlx5dr_ste_set_tx_push_vlan(u8 *hw_ste_p, u32 vlan_hdr,
18426d688e3SAlex Vesker 				 bool go_back)
18526d688e3SAlex Vesker {
18626d688e3SAlex Vesker 	MLX5_SET(ste_sx_transmit, hw_ste_p, action_type,
18726d688e3SAlex Vesker 		 DR_STE_ACTION_TYPE_PUSH_VLAN);
18826d688e3SAlex Vesker 	MLX5_SET(ste_sx_transmit, hw_ste_p, encap_pointer_vlan_data, vlan_hdr);
18926d688e3SAlex Vesker 	/* Due to HW limitation we need to set this bit, otherwise reforamt +
19026d688e3SAlex Vesker 	 * push vlan will not work.
19126d688e3SAlex Vesker 	 */
19226d688e3SAlex Vesker 	if (go_back)
19326d688e3SAlex Vesker 		mlx5dr_ste_set_go_back_bit(hw_ste_p);
19426d688e3SAlex Vesker }
19526d688e3SAlex Vesker 
19626d688e3SAlex Vesker void mlx5dr_ste_set_tx_encap(void *hw_ste_p, u32 reformat_id, int size, bool encap_l3)
19726d688e3SAlex Vesker {
19826d688e3SAlex Vesker 	MLX5_SET(ste_sx_transmit, hw_ste_p, action_type,
19926d688e3SAlex Vesker 		 encap_l3 ? DR_STE_ACTION_TYPE_ENCAP_L3 : DR_STE_ACTION_TYPE_ENCAP);
20026d688e3SAlex Vesker 	/* The hardware expects here size in words (2 byte) */
20126d688e3SAlex Vesker 	MLX5_SET(ste_sx_transmit, hw_ste_p, action_description, size / 2);
20226d688e3SAlex Vesker 	MLX5_SET(ste_sx_transmit, hw_ste_p, encap_pointer_vlan_data, reformat_id);
20326d688e3SAlex Vesker }
20426d688e3SAlex Vesker 
20526d688e3SAlex Vesker void mlx5dr_ste_set_rx_decap(u8 *hw_ste_p)
20626d688e3SAlex Vesker {
20726d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
20826d688e3SAlex Vesker 		 DR_STE_TUNL_ACTION_DECAP);
20926d688e3SAlex Vesker }
21026d688e3SAlex Vesker 
21126d688e3SAlex Vesker void mlx5dr_ste_set_rx_pop_vlan(u8 *hw_ste_p)
21226d688e3SAlex Vesker {
21326d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
21426d688e3SAlex Vesker 		 DR_STE_TUNL_ACTION_POP_VLAN);
21526d688e3SAlex Vesker }
21626d688e3SAlex Vesker 
21726d688e3SAlex Vesker void mlx5dr_ste_set_rx_decap_l3(u8 *hw_ste_p, bool vlan)
21826d688e3SAlex Vesker {
21926d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
22026d688e3SAlex Vesker 		 DR_STE_TUNL_ACTION_L3_DECAP);
22126d688e3SAlex Vesker 	MLX5_SET(ste_modify_packet, hw_ste_p, action_description, vlan ? 1 : 0);
22226d688e3SAlex Vesker }
22326d688e3SAlex Vesker 
22426d688e3SAlex Vesker void mlx5dr_ste_set_entry_type(u8 *hw_ste_p, u8 entry_type)
22526d688e3SAlex Vesker {
22626d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste_p, entry_type, entry_type);
22726d688e3SAlex Vesker }
22826d688e3SAlex Vesker 
22926d688e3SAlex Vesker u8 mlx5dr_ste_get_entry_type(u8 *hw_ste_p)
23026d688e3SAlex Vesker {
23126d688e3SAlex Vesker 	return MLX5_GET(ste_general, hw_ste_p, entry_type);
23226d688e3SAlex Vesker }
23326d688e3SAlex Vesker 
23426d688e3SAlex Vesker void mlx5dr_ste_set_rewrite_actions(u8 *hw_ste_p, u16 num_of_actions,
23526d688e3SAlex Vesker 				    u32 re_write_index)
23626d688e3SAlex Vesker {
23726d688e3SAlex Vesker 	MLX5_SET(ste_modify_packet, hw_ste_p, number_of_re_write_actions,
23826d688e3SAlex Vesker 		 num_of_actions);
23926d688e3SAlex Vesker 	MLX5_SET(ste_modify_packet, hw_ste_p, header_re_write_actions_pointer,
24026d688e3SAlex Vesker 		 re_write_index);
24126d688e3SAlex Vesker }
24226d688e3SAlex Vesker 
24326d688e3SAlex Vesker void mlx5dr_ste_set_hit_gvmi(u8 *hw_ste_p, u16 gvmi)
24426d688e3SAlex Vesker {
24526d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste_p, next_table_base_63_48, gvmi);
24626d688e3SAlex Vesker }
24726d688e3SAlex Vesker 
24826d688e3SAlex Vesker void mlx5dr_ste_init(u8 *hw_ste_p, u8 lu_type, u8 entry_type,
24926d688e3SAlex Vesker 		     u16 gvmi)
25026d688e3SAlex Vesker {
25126d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste_p, entry_type, entry_type);
25226d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste_p, entry_sub_type, lu_type);
25326d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste_p, next_lu_type, MLX5DR_STE_LU_TYPE_DONT_CARE);
25426d688e3SAlex Vesker 
25526d688e3SAlex Vesker 	/* Set GVMI once, this is the same for RX/TX
25626d688e3SAlex Vesker 	 * bits 63_48 of next table base / miss address encode the next GVMI
25726d688e3SAlex Vesker 	 */
25826d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, gvmi, gvmi);
25926d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, next_table_base_63_48, gvmi);
26026d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_63_48, gvmi);
26126d688e3SAlex Vesker }
26226d688e3SAlex Vesker 
26326d688e3SAlex Vesker static void dr_ste_set_always_hit(struct dr_hw_ste_format *hw_ste)
26426d688e3SAlex Vesker {
26526d688e3SAlex Vesker 	memset(&hw_ste->tag, 0, sizeof(hw_ste->tag));
26626d688e3SAlex Vesker 	memset(&hw_ste->mask, 0, sizeof(hw_ste->mask));
26726d688e3SAlex Vesker }
26826d688e3SAlex Vesker 
26926d688e3SAlex Vesker static void dr_ste_set_always_miss(struct dr_hw_ste_format *hw_ste)
27026d688e3SAlex Vesker {
27126d688e3SAlex Vesker 	hw_ste->tag[0] = 0xdc;
27226d688e3SAlex Vesker 	hw_ste->mask[0] = 0;
27326d688e3SAlex Vesker }
27426d688e3SAlex Vesker 
27526d688e3SAlex Vesker u64 mlx5dr_ste_get_miss_addr(u8 *hw_ste)
27626d688e3SAlex Vesker {
27726d688e3SAlex Vesker 	u64 index =
27826d688e3SAlex Vesker 		(MLX5_GET(ste_rx_steering_mult, hw_ste, miss_address_31_6) |
27926d688e3SAlex Vesker 		 MLX5_GET(ste_rx_steering_mult, hw_ste, miss_address_39_32) << 26);
28026d688e3SAlex Vesker 
28126d688e3SAlex Vesker 	return index << 6;
28226d688e3SAlex Vesker }
28326d688e3SAlex Vesker 
28426d688e3SAlex Vesker void mlx5dr_ste_set_hit_addr(u8 *hw_ste, u64 icm_addr, u32 ht_size)
28526d688e3SAlex Vesker {
28626d688e3SAlex Vesker 	u64 index = (icm_addr >> 5) | ht_size;
28726d688e3SAlex Vesker 
28826d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste, next_table_base_39_32_size, index >> 27);
28926d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste, next_table_base_31_5_size, index);
29026d688e3SAlex Vesker }
29126d688e3SAlex Vesker 
29226d688e3SAlex Vesker u64 mlx5dr_ste_get_icm_addr(struct mlx5dr_ste *ste)
29326d688e3SAlex Vesker {
29426d688e3SAlex Vesker 	u32 index = ste - ste->htbl->ste_arr;
29526d688e3SAlex Vesker 
29626d688e3SAlex Vesker 	return ste->htbl->chunk->icm_addr + DR_STE_SIZE * index;
29726d688e3SAlex Vesker }
29826d688e3SAlex Vesker 
29926d688e3SAlex Vesker u64 mlx5dr_ste_get_mr_addr(struct mlx5dr_ste *ste)
30026d688e3SAlex Vesker {
30126d688e3SAlex Vesker 	u32 index = ste - ste->htbl->ste_arr;
30226d688e3SAlex Vesker 
30326d688e3SAlex Vesker 	return ste->htbl->chunk->mr_addr + DR_STE_SIZE * index;
30426d688e3SAlex Vesker }
30526d688e3SAlex Vesker 
30626d688e3SAlex Vesker struct list_head *mlx5dr_ste_get_miss_list(struct mlx5dr_ste *ste)
30726d688e3SAlex Vesker {
30826d688e3SAlex Vesker 	u32 index = ste - ste->htbl->ste_arr;
30926d688e3SAlex Vesker 
31026d688e3SAlex Vesker 	return &ste->htbl->miss_list[index];
31126d688e3SAlex Vesker }
31226d688e3SAlex Vesker 
31326d688e3SAlex Vesker static void dr_ste_always_hit_htbl(struct mlx5dr_ste *ste,
31426d688e3SAlex Vesker 				   struct mlx5dr_ste_htbl *next_htbl)
31526d688e3SAlex Vesker {
31626d688e3SAlex Vesker 	struct mlx5dr_icm_chunk *chunk = next_htbl->chunk;
31726d688e3SAlex Vesker 	u8 *hw_ste = ste->hw_ste;
31826d688e3SAlex Vesker 
31926d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste, byte_mask, next_htbl->byte_mask);
32026d688e3SAlex Vesker 	MLX5_SET(ste_general, hw_ste, next_lu_type, next_htbl->lu_type);
32126d688e3SAlex Vesker 	mlx5dr_ste_set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries);
32226d688e3SAlex Vesker 
32326d688e3SAlex Vesker 	dr_ste_set_always_hit((struct dr_hw_ste_format *)ste->hw_ste);
32426d688e3SAlex Vesker }
32526d688e3SAlex Vesker 
32626d688e3SAlex Vesker bool mlx5dr_ste_is_last_in_rule(struct mlx5dr_matcher_rx_tx *nic_matcher,
32726d688e3SAlex Vesker 				u8 ste_location)
32826d688e3SAlex Vesker {
32926d688e3SAlex Vesker 	return ste_location == nic_matcher->num_of_builders;
33026d688e3SAlex Vesker }
33126d688e3SAlex Vesker 
33226d688e3SAlex Vesker /* Replace relevant fields, except of:
33326d688e3SAlex Vesker  * htbl - keep the origin htbl
33426d688e3SAlex Vesker  * miss_list + list - already took the src from the list.
33526d688e3SAlex Vesker  * icm_addr/mr_addr - depends on the hosting table.
33626d688e3SAlex Vesker  *
33726d688e3SAlex Vesker  * Before:
33826d688e3SAlex Vesker  * | a | -> | b | -> | c | ->
33926d688e3SAlex Vesker  *
34026d688e3SAlex Vesker  * After:
34126d688e3SAlex Vesker  * | a | -> | c | ->
34226d688e3SAlex Vesker  * While the data that was in b copied to a.
34326d688e3SAlex Vesker  */
34426d688e3SAlex Vesker static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src)
34526d688e3SAlex Vesker {
34626d688e3SAlex Vesker 	memcpy(dst->hw_ste, src->hw_ste, DR_STE_SIZE_REDUCED);
34726d688e3SAlex Vesker 	dst->next_htbl = src->next_htbl;
34826d688e3SAlex Vesker 	if (dst->next_htbl)
34926d688e3SAlex Vesker 		dst->next_htbl->pointing_ste = dst;
35026d688e3SAlex Vesker 
3514ce380caSYevgeny Kliteynik 	dst->refcount = src->refcount;
35226d688e3SAlex Vesker 
35326d688e3SAlex Vesker 	INIT_LIST_HEAD(&dst->rule_list);
35426d688e3SAlex Vesker 	list_splice_tail_init(&src->rule_list, &dst->rule_list);
35526d688e3SAlex Vesker }
35626d688e3SAlex Vesker 
35726d688e3SAlex Vesker /* Free ste which is the head and the only one in miss_list */
35826d688e3SAlex Vesker static void
35926d688e3SAlex Vesker dr_ste_remove_head_ste(struct mlx5dr_ste *ste,
36026d688e3SAlex Vesker 		       struct mlx5dr_matcher_rx_tx *nic_matcher,
36126d688e3SAlex Vesker 		       struct mlx5dr_ste_send_info *ste_info_head,
36226d688e3SAlex Vesker 		       struct list_head *send_ste_list,
36326d688e3SAlex Vesker 		       struct mlx5dr_ste_htbl *stats_tbl)
36426d688e3SAlex Vesker {
36526d688e3SAlex Vesker 	u8 tmp_data_ste[DR_STE_SIZE] = {};
36626d688e3SAlex Vesker 	struct mlx5dr_ste tmp_ste = {};
36726d688e3SAlex Vesker 	u64 miss_addr;
36826d688e3SAlex Vesker 
36926d688e3SAlex Vesker 	tmp_ste.hw_ste = tmp_data_ste;
37026d688e3SAlex Vesker 
37126d688e3SAlex Vesker 	/* Use temp ste because dr_ste_always_miss_addr
37226d688e3SAlex Vesker 	 * touches bit_mask area which doesn't exist at ste->hw_ste.
37326d688e3SAlex Vesker 	 */
37426d688e3SAlex Vesker 	memcpy(tmp_ste.hw_ste, ste->hw_ste, DR_STE_SIZE_REDUCED);
37526d688e3SAlex Vesker 	miss_addr = nic_matcher->e_anchor->chunk->icm_addr;
37626d688e3SAlex Vesker 	mlx5dr_ste_always_miss_addr(&tmp_ste, miss_addr);
37726d688e3SAlex Vesker 	memcpy(ste->hw_ste, tmp_ste.hw_ste, DR_STE_SIZE_REDUCED);
37826d688e3SAlex Vesker 
37926d688e3SAlex Vesker 	list_del_init(&ste->miss_list_node);
38026d688e3SAlex Vesker 
38126d688e3SAlex Vesker 	/* Write full STE size in order to have "always_miss" */
38226d688e3SAlex Vesker 	mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE,
38326d688e3SAlex Vesker 						  0, tmp_data_ste,
38426d688e3SAlex Vesker 						  ste_info_head,
38526d688e3SAlex Vesker 						  send_ste_list,
38626d688e3SAlex Vesker 						  true /* Copy data */);
38726d688e3SAlex Vesker 
38826d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_valid_entries--;
38926d688e3SAlex Vesker }
39026d688e3SAlex Vesker 
39126d688e3SAlex Vesker /* Free ste which is the head but NOT the only one in miss_list:
39226d688e3SAlex Vesker  * |_ste_| --> |_next_ste_| -->|__| -->|__| -->/0
39326d688e3SAlex Vesker  */
39426d688e3SAlex Vesker static void
39526d688e3SAlex Vesker dr_ste_replace_head_ste(struct mlx5dr_ste *ste, struct mlx5dr_ste *next_ste,
39626d688e3SAlex Vesker 			struct mlx5dr_ste_send_info *ste_info_head,
39726d688e3SAlex Vesker 			struct list_head *send_ste_list,
39826d688e3SAlex Vesker 			struct mlx5dr_ste_htbl *stats_tbl)
39926d688e3SAlex Vesker 
40026d688e3SAlex Vesker {
40126d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *next_miss_htbl;
40226d688e3SAlex Vesker 
40326d688e3SAlex Vesker 	next_miss_htbl = next_ste->htbl;
40426d688e3SAlex Vesker 
40526d688e3SAlex Vesker 	/* Remove from the miss_list the next_ste before copy */
40626d688e3SAlex Vesker 	list_del_init(&next_ste->miss_list_node);
40726d688e3SAlex Vesker 
40826d688e3SAlex Vesker 	/* All rule-members that use next_ste should know about that */
40926d688e3SAlex Vesker 	mlx5dr_rule_update_rule_member(next_ste, ste);
41026d688e3SAlex Vesker 
41126d688e3SAlex Vesker 	/* Move data from next into ste */
41226d688e3SAlex Vesker 	dr_ste_replace(ste, next_ste);
41326d688e3SAlex Vesker 
41426d688e3SAlex Vesker 	/* Del the htbl that contains the next_ste.
41526d688e3SAlex Vesker 	 * The origin htbl stay with the same number of entries.
41626d688e3SAlex Vesker 	 */
41726d688e3SAlex Vesker 	mlx5dr_htbl_put(next_miss_htbl);
41826d688e3SAlex Vesker 
41926d688e3SAlex Vesker 	mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE_REDUCED,
42026d688e3SAlex Vesker 						  0, ste->hw_ste,
42126d688e3SAlex Vesker 						  ste_info_head,
42226d688e3SAlex Vesker 						  send_ste_list,
42326d688e3SAlex Vesker 						  true /* Copy data */);
42426d688e3SAlex Vesker 
42526d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_collisions--;
42626d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_valid_entries--;
42726d688e3SAlex Vesker }
42826d688e3SAlex Vesker 
42926d688e3SAlex Vesker /* Free ste that is located in the middle of the miss list:
43026d688e3SAlex Vesker  * |__| -->|_prev_ste_|->|_ste_|-->|_next_ste_|
43126d688e3SAlex Vesker  */
43226d688e3SAlex Vesker static void dr_ste_remove_middle_ste(struct mlx5dr_ste *ste,
43326d688e3SAlex Vesker 				     struct mlx5dr_ste_send_info *ste_info,
43426d688e3SAlex Vesker 				     struct list_head *send_ste_list,
43526d688e3SAlex Vesker 				     struct mlx5dr_ste_htbl *stats_tbl)
43626d688e3SAlex Vesker {
43726d688e3SAlex Vesker 	struct mlx5dr_ste *prev_ste;
43826d688e3SAlex Vesker 	u64 miss_addr;
43926d688e3SAlex Vesker 
44048cbde4bSAlex Vesker 	prev_ste = list_prev_entry(ste, miss_list_node);
44148cbde4bSAlex Vesker 	if (WARN_ON(!prev_ste))
44226d688e3SAlex Vesker 		return;
44326d688e3SAlex Vesker 
44426d688e3SAlex Vesker 	miss_addr = mlx5dr_ste_get_miss_addr(ste->hw_ste);
44526d688e3SAlex Vesker 	mlx5dr_ste_set_miss_addr(prev_ste->hw_ste, miss_addr);
44626d688e3SAlex Vesker 
44726d688e3SAlex Vesker 	mlx5dr_send_fill_and_append_ste_send_info(prev_ste, DR_STE_SIZE_REDUCED, 0,
44826d688e3SAlex Vesker 						  prev_ste->hw_ste, ste_info,
44926d688e3SAlex Vesker 						  send_ste_list, true /* Copy data*/);
45026d688e3SAlex Vesker 
45126d688e3SAlex Vesker 	list_del_init(&ste->miss_list_node);
45226d688e3SAlex Vesker 
45326d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_valid_entries--;
45426d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_collisions--;
45526d688e3SAlex Vesker }
45626d688e3SAlex Vesker 
45726d688e3SAlex Vesker void mlx5dr_ste_free(struct mlx5dr_ste *ste,
45826d688e3SAlex Vesker 		     struct mlx5dr_matcher *matcher,
45926d688e3SAlex Vesker 		     struct mlx5dr_matcher_rx_tx *nic_matcher)
46026d688e3SAlex Vesker {
46126d688e3SAlex Vesker 	struct mlx5dr_ste_send_info *cur_ste_info, *tmp_ste_info;
46226d688e3SAlex Vesker 	struct mlx5dr_domain *dmn = matcher->tbl->dmn;
46326d688e3SAlex Vesker 	struct mlx5dr_ste_send_info ste_info_head;
46426d688e3SAlex Vesker 	struct mlx5dr_ste *next_ste, *first_ste;
46526d688e3SAlex Vesker 	bool put_on_origin_table = true;
46626d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *stats_tbl;
46726d688e3SAlex Vesker 	LIST_HEAD(send_ste_list);
46826d688e3SAlex Vesker 
46948cbde4bSAlex Vesker 	first_ste = list_first_entry(mlx5dr_ste_get_miss_list(ste),
47026d688e3SAlex Vesker 				     struct mlx5dr_ste, miss_list_node);
47126d688e3SAlex Vesker 	stats_tbl = first_ste->htbl;
47226d688e3SAlex Vesker 
47326d688e3SAlex Vesker 	/* Two options:
47426d688e3SAlex Vesker 	 * 1. ste is head:
47526d688e3SAlex Vesker 	 *	a. head ste is the only ste in the miss list
47626d688e3SAlex Vesker 	 *	b. head ste is not the only ste in the miss-list
47726d688e3SAlex Vesker 	 * 2. ste is not head
47826d688e3SAlex Vesker 	 */
47926d688e3SAlex Vesker 	if (first_ste == ste) { /* Ste is the head */
48026d688e3SAlex Vesker 		struct mlx5dr_ste *last_ste;
48126d688e3SAlex Vesker 
48226d688e3SAlex Vesker 		last_ste = list_last_entry(mlx5dr_ste_get_miss_list(ste),
48326d688e3SAlex Vesker 					   struct mlx5dr_ste, miss_list_node);
48426d688e3SAlex Vesker 		if (last_ste == first_ste)
48526d688e3SAlex Vesker 			next_ste = NULL;
48626d688e3SAlex Vesker 		else
48748cbde4bSAlex Vesker 			next_ste = list_next_entry(ste, miss_list_node);
48826d688e3SAlex Vesker 
48926d688e3SAlex Vesker 		if (!next_ste) {
49026d688e3SAlex Vesker 			/* One and only entry in the list */
49126d688e3SAlex Vesker 			dr_ste_remove_head_ste(ste, nic_matcher,
49226d688e3SAlex Vesker 					       &ste_info_head,
49326d688e3SAlex Vesker 					       &send_ste_list,
49426d688e3SAlex Vesker 					       stats_tbl);
49526d688e3SAlex Vesker 		} else {
49626d688e3SAlex Vesker 			/* First but not only entry in the list */
49726d688e3SAlex Vesker 			dr_ste_replace_head_ste(ste, next_ste, &ste_info_head,
49826d688e3SAlex Vesker 						&send_ste_list, stats_tbl);
49926d688e3SAlex Vesker 			put_on_origin_table = false;
50026d688e3SAlex Vesker 		}
50126d688e3SAlex Vesker 	} else { /* Ste in the middle of the list */
50226d688e3SAlex Vesker 		dr_ste_remove_middle_ste(ste, &ste_info_head, &send_ste_list, stats_tbl);
50326d688e3SAlex Vesker 	}
50426d688e3SAlex Vesker 
50526d688e3SAlex Vesker 	/* Update HW */
50626d688e3SAlex Vesker 	list_for_each_entry_safe(cur_ste_info, tmp_ste_info,
50726d688e3SAlex Vesker 				 &send_ste_list, send_list) {
50826d688e3SAlex Vesker 		list_del(&cur_ste_info->send_list);
50926d688e3SAlex Vesker 		mlx5dr_send_postsend_ste(dmn, cur_ste_info->ste,
51026d688e3SAlex Vesker 					 cur_ste_info->data, cur_ste_info->size,
51126d688e3SAlex Vesker 					 cur_ste_info->offset);
51226d688e3SAlex Vesker 	}
51326d688e3SAlex Vesker 
51426d688e3SAlex Vesker 	if (put_on_origin_table)
51526d688e3SAlex Vesker 		mlx5dr_htbl_put(ste->htbl);
51626d688e3SAlex Vesker }
51726d688e3SAlex Vesker 
51826d688e3SAlex Vesker bool mlx5dr_ste_equal_tag(void *src, void *dst)
51926d688e3SAlex Vesker {
52026d688e3SAlex Vesker 	struct dr_hw_ste_format *s_hw_ste = (struct dr_hw_ste_format *)src;
52126d688e3SAlex Vesker 	struct dr_hw_ste_format *d_hw_ste = (struct dr_hw_ste_format *)dst;
52226d688e3SAlex Vesker 
52326d688e3SAlex Vesker 	return !memcmp(s_hw_ste->tag, d_hw_ste->tag, DR_STE_SIZE_TAG);
52426d688e3SAlex Vesker }
52526d688e3SAlex Vesker 
52626d688e3SAlex Vesker void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
52726d688e3SAlex Vesker 					  struct mlx5dr_ste_htbl *next_htbl)
52826d688e3SAlex Vesker {
52926d688e3SAlex Vesker 	struct mlx5dr_icm_chunk *chunk = next_htbl->chunk;
53026d688e3SAlex Vesker 
53126d688e3SAlex Vesker 	mlx5dr_ste_set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries);
53226d688e3SAlex Vesker }
53326d688e3SAlex Vesker 
53426d688e3SAlex Vesker void mlx5dr_ste_set_miss_addr(u8 *hw_ste_p, u64 miss_addr)
53526d688e3SAlex Vesker {
53626d688e3SAlex Vesker 	u64 index = miss_addr >> 6;
53726d688e3SAlex Vesker 
53826d688e3SAlex Vesker 	/* Miss address for TX and RX STEs located in the same offsets */
53926d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_39_32, index >> 26);
54026d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_31_6, index);
54126d688e3SAlex Vesker }
54226d688e3SAlex Vesker 
54326d688e3SAlex Vesker void mlx5dr_ste_always_miss_addr(struct mlx5dr_ste *ste, u64 miss_addr)
54426d688e3SAlex Vesker {
54526d688e3SAlex Vesker 	u8 *hw_ste = ste->hw_ste;
54626d688e3SAlex Vesker 
54726d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste, next_lu_type, MLX5DR_STE_LU_TYPE_DONT_CARE);
54826d688e3SAlex Vesker 	mlx5dr_ste_set_miss_addr(hw_ste, miss_addr);
54926d688e3SAlex Vesker 	dr_ste_set_always_miss((struct dr_hw_ste_format *)ste->hw_ste);
55026d688e3SAlex Vesker }
55126d688e3SAlex Vesker 
55226d688e3SAlex Vesker /* The assumption here is that we don't update the ste->hw_ste if it is not
55326d688e3SAlex Vesker  * used ste, so it will be all zero, checking the next_lu_type.
55426d688e3SAlex Vesker  */
55526d688e3SAlex Vesker bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_ste)
55626d688e3SAlex Vesker {
55726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)p_hw_ste;
55826d688e3SAlex Vesker 
55926d688e3SAlex Vesker 	if (MLX5_GET(ste_general, hw_ste, next_lu_type) ==
56026d688e3SAlex Vesker 	    MLX5DR_STE_LU_TYPE_NOP)
56126d688e3SAlex Vesker 		return true;
56226d688e3SAlex Vesker 
56326d688e3SAlex Vesker 	return false;
56426d688e3SAlex Vesker }
56526d688e3SAlex Vesker 
56626d688e3SAlex Vesker bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
56726d688e3SAlex Vesker {
5684ce380caSYevgeny Kliteynik 	return !ste->refcount;
56926d688e3SAlex Vesker }
57026d688e3SAlex Vesker 
57126d688e3SAlex Vesker /* Init one ste as a pattern for ste data array */
57226d688e3SAlex Vesker void mlx5dr_ste_set_formatted_ste(u16 gvmi,
57326d688e3SAlex Vesker 				  struct mlx5dr_domain_rx_tx *nic_dmn,
57426d688e3SAlex Vesker 				  struct mlx5dr_ste_htbl *htbl,
57526d688e3SAlex Vesker 				  u8 *formatted_ste,
57626d688e3SAlex Vesker 				  struct mlx5dr_htbl_connect_info *connect_info)
57726d688e3SAlex Vesker {
57826d688e3SAlex Vesker 	struct mlx5dr_ste ste = {};
57926d688e3SAlex Vesker 
58026d688e3SAlex Vesker 	mlx5dr_ste_init(formatted_ste, htbl->lu_type, nic_dmn->ste_type, gvmi);
58126d688e3SAlex Vesker 	ste.hw_ste = formatted_ste;
58226d688e3SAlex Vesker 
58326d688e3SAlex Vesker 	if (connect_info->type == CONNECT_HIT)
58426d688e3SAlex Vesker 		dr_ste_always_hit_htbl(&ste, connect_info->hit_next_htbl);
58526d688e3SAlex Vesker 	else
58626d688e3SAlex Vesker 		mlx5dr_ste_always_miss_addr(&ste, connect_info->miss_icm_addr);
58726d688e3SAlex Vesker }
58826d688e3SAlex Vesker 
58926d688e3SAlex Vesker int mlx5dr_ste_htbl_init_and_postsend(struct mlx5dr_domain *dmn,
59026d688e3SAlex Vesker 				      struct mlx5dr_domain_rx_tx *nic_dmn,
59126d688e3SAlex Vesker 				      struct mlx5dr_ste_htbl *htbl,
59226d688e3SAlex Vesker 				      struct mlx5dr_htbl_connect_info *connect_info,
59326d688e3SAlex Vesker 				      bool update_hw_ste)
59426d688e3SAlex Vesker {
59526d688e3SAlex Vesker 	u8 formatted_ste[DR_STE_SIZE] = {};
59626d688e3SAlex Vesker 
59726d688e3SAlex Vesker 	mlx5dr_ste_set_formatted_ste(dmn->info.caps.gvmi,
59826d688e3SAlex Vesker 				     nic_dmn,
59926d688e3SAlex Vesker 				     htbl,
60026d688e3SAlex Vesker 				     formatted_ste,
60126d688e3SAlex Vesker 				     connect_info);
60226d688e3SAlex Vesker 
60326d688e3SAlex Vesker 	return mlx5dr_send_postsend_formatted_htbl(dmn, htbl, formatted_ste, update_hw_ste);
60426d688e3SAlex Vesker }
60526d688e3SAlex Vesker 
60626d688e3SAlex Vesker int mlx5dr_ste_create_next_htbl(struct mlx5dr_matcher *matcher,
60726d688e3SAlex Vesker 				struct mlx5dr_matcher_rx_tx *nic_matcher,
60826d688e3SAlex Vesker 				struct mlx5dr_ste *ste,
60926d688e3SAlex Vesker 				u8 *cur_hw_ste,
61026d688e3SAlex Vesker 				enum mlx5dr_icm_chunk_size log_table_size)
61126d688e3SAlex Vesker {
61226d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)cur_hw_ste;
61326d688e3SAlex Vesker 	struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
61426d688e3SAlex Vesker 	struct mlx5dr_domain *dmn = matcher->tbl->dmn;
61526d688e3SAlex Vesker 	struct mlx5dr_htbl_connect_info info;
61626d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *next_htbl;
61726d688e3SAlex Vesker 
61826d688e3SAlex Vesker 	if (!mlx5dr_ste_is_last_in_rule(nic_matcher, ste->ste_chain_location)) {
61926d688e3SAlex Vesker 		u8 next_lu_type;
62026d688e3SAlex Vesker 		u16 byte_mask;
62126d688e3SAlex Vesker 
62226d688e3SAlex Vesker 		next_lu_type = MLX5_GET(ste_general, hw_ste, next_lu_type);
62326d688e3SAlex Vesker 		byte_mask = MLX5_GET(ste_general, hw_ste, byte_mask);
62426d688e3SAlex Vesker 
62526d688e3SAlex Vesker 		next_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
62626d688e3SAlex Vesker 						  log_table_size,
62726d688e3SAlex Vesker 						  next_lu_type,
62826d688e3SAlex Vesker 						  byte_mask);
62926d688e3SAlex Vesker 		if (!next_htbl) {
63026d688e3SAlex Vesker 			mlx5dr_dbg(dmn, "Failed allocating table\n");
63126d688e3SAlex Vesker 			return -ENOMEM;
63226d688e3SAlex Vesker 		}
63326d688e3SAlex Vesker 
63426d688e3SAlex Vesker 		/* Write new table to HW */
63526d688e3SAlex Vesker 		info.type = CONNECT_MISS;
63626d688e3SAlex Vesker 		info.miss_icm_addr = nic_matcher->e_anchor->chunk->icm_addr;
63726d688e3SAlex Vesker 		if (mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, next_htbl,
63826d688e3SAlex Vesker 						      &info, false)) {
63926d688e3SAlex Vesker 			mlx5dr_info(dmn, "Failed writing table to HW\n");
64026d688e3SAlex Vesker 			goto free_table;
64126d688e3SAlex Vesker 		}
64226d688e3SAlex Vesker 
64326d688e3SAlex Vesker 		mlx5dr_ste_set_hit_addr_by_next_htbl(cur_hw_ste, next_htbl);
64426d688e3SAlex Vesker 		ste->next_htbl = next_htbl;
64526d688e3SAlex Vesker 		next_htbl->pointing_ste = ste;
64626d688e3SAlex Vesker 	}
64726d688e3SAlex Vesker 
64826d688e3SAlex Vesker 	return 0;
64926d688e3SAlex Vesker 
65026d688e3SAlex Vesker free_table:
65126d688e3SAlex Vesker 	mlx5dr_ste_htbl_free(next_htbl);
65226d688e3SAlex Vesker 	return -ENOENT;
65326d688e3SAlex Vesker }
65426d688e3SAlex Vesker 
65526d688e3SAlex Vesker static void dr_ste_set_ctrl(struct mlx5dr_ste_htbl *htbl)
65626d688e3SAlex Vesker {
65726d688e3SAlex Vesker 	struct mlx5dr_ste_htbl_ctrl *ctrl = &htbl->ctrl;
65826d688e3SAlex Vesker 	int num_of_entries;
65926d688e3SAlex Vesker 
66026d688e3SAlex Vesker 	htbl->ctrl.may_grow = true;
66126d688e3SAlex Vesker 
66283e79489SAlex Vesker 	if (htbl->chunk_size == DR_CHUNK_SIZE_MAX - 1 || !htbl->byte_mask)
66326d688e3SAlex Vesker 		htbl->ctrl.may_grow = false;
66426d688e3SAlex Vesker 
66526d688e3SAlex Vesker 	/* Threshold is 50%, one is added to table of size 1 */
66626d688e3SAlex Vesker 	num_of_entries = mlx5dr_icm_pool_chunk_size_to_entries(htbl->chunk_size);
66726d688e3SAlex Vesker 	ctrl->increase_threshold = (num_of_entries + 1) / 2;
66826d688e3SAlex Vesker }
66926d688e3SAlex Vesker 
67026d688e3SAlex Vesker struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
67126d688e3SAlex Vesker 					      enum mlx5dr_icm_chunk_size chunk_size,
67226d688e3SAlex Vesker 					      u8 lu_type, u16 byte_mask)
67326d688e3SAlex Vesker {
67426d688e3SAlex Vesker 	struct mlx5dr_icm_chunk *chunk;
67526d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *htbl;
67626d688e3SAlex Vesker 	int i;
67726d688e3SAlex Vesker 
67826d688e3SAlex Vesker 	htbl = kzalloc(sizeof(*htbl), GFP_KERNEL);
67926d688e3SAlex Vesker 	if (!htbl)
68026d688e3SAlex Vesker 		return NULL;
68126d688e3SAlex Vesker 
68226d688e3SAlex Vesker 	chunk = mlx5dr_icm_alloc_chunk(pool, chunk_size);
68326d688e3SAlex Vesker 	if (!chunk)
68426d688e3SAlex Vesker 		goto out_free_htbl;
68526d688e3SAlex Vesker 
68626d688e3SAlex Vesker 	htbl->chunk = chunk;
68726d688e3SAlex Vesker 	htbl->lu_type = lu_type;
68826d688e3SAlex Vesker 	htbl->byte_mask = byte_mask;
68926d688e3SAlex Vesker 	htbl->ste_arr = chunk->ste_arr;
69026d688e3SAlex Vesker 	htbl->hw_ste_arr = chunk->hw_ste_arr;
69126d688e3SAlex Vesker 	htbl->miss_list = chunk->miss_list;
6924ce380caSYevgeny Kliteynik 	htbl->refcount = 0;
69326d688e3SAlex Vesker 
69426d688e3SAlex Vesker 	for (i = 0; i < chunk->num_of_entries; i++) {
69526d688e3SAlex Vesker 		struct mlx5dr_ste *ste = &htbl->ste_arr[i];
69626d688e3SAlex Vesker 
69726d688e3SAlex Vesker 		ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
69826d688e3SAlex Vesker 		ste->htbl = htbl;
6994ce380caSYevgeny Kliteynik 		ste->refcount = 0;
70026d688e3SAlex Vesker 		INIT_LIST_HEAD(&ste->miss_list_node);
70126d688e3SAlex Vesker 		INIT_LIST_HEAD(&htbl->miss_list[i]);
70226d688e3SAlex Vesker 		INIT_LIST_HEAD(&ste->rule_list);
70326d688e3SAlex Vesker 	}
70426d688e3SAlex Vesker 
70526d688e3SAlex Vesker 	htbl->chunk_size = chunk_size;
70626d688e3SAlex Vesker 	dr_ste_set_ctrl(htbl);
70726d688e3SAlex Vesker 	return htbl;
70826d688e3SAlex Vesker 
70926d688e3SAlex Vesker out_free_htbl:
71026d688e3SAlex Vesker 	kfree(htbl);
71126d688e3SAlex Vesker 	return NULL;
71226d688e3SAlex Vesker }
71326d688e3SAlex Vesker 
71426d688e3SAlex Vesker int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
71526d688e3SAlex Vesker {
7164ce380caSYevgeny Kliteynik 	if (htbl->refcount)
71726d688e3SAlex Vesker 		return -EBUSY;
71826d688e3SAlex Vesker 
71926d688e3SAlex Vesker 	mlx5dr_icm_free_chunk(htbl->chunk);
72026d688e3SAlex Vesker 	kfree(htbl);
72126d688e3SAlex Vesker 	return 0;
72226d688e3SAlex Vesker }
72326d688e3SAlex Vesker 
72426d688e3SAlex Vesker int mlx5dr_ste_build_pre_check(struct mlx5dr_domain *dmn,
72526d688e3SAlex Vesker 			       u8 match_criteria,
72626d688e3SAlex Vesker 			       struct mlx5dr_match_param *mask,
72726d688e3SAlex Vesker 			       struct mlx5dr_match_param *value)
72826d688e3SAlex Vesker {
72926d688e3SAlex Vesker 	if (!value && (match_criteria & DR_MATCHER_CRITERIA_MISC)) {
73026d688e3SAlex Vesker 		if (mask->misc.source_port && mask->misc.source_port != 0xffff) {
731b7d0db55SErez Shitrit 			mlx5dr_err(dmn, "Partial mask source_port is not supported\n");
73226d688e3SAlex Vesker 			return -EINVAL;
73326d688e3SAlex Vesker 		}
73426d688e3SAlex Vesker 	}
73526d688e3SAlex Vesker 
73626d688e3SAlex Vesker 	return 0;
73726d688e3SAlex Vesker }
73826d688e3SAlex Vesker 
73926d688e3SAlex Vesker int mlx5dr_ste_build_ste_arr(struct mlx5dr_matcher *matcher,
74026d688e3SAlex Vesker 			     struct mlx5dr_matcher_rx_tx *nic_matcher,
74126d688e3SAlex Vesker 			     struct mlx5dr_match_param *value,
74226d688e3SAlex Vesker 			     u8 *ste_arr)
74326d688e3SAlex Vesker {
74426d688e3SAlex Vesker 	struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
74526d688e3SAlex Vesker 	struct mlx5dr_domain *dmn = matcher->tbl->dmn;
74626d688e3SAlex Vesker 	struct mlx5dr_ste_build *sb;
74726d688e3SAlex Vesker 	int ret, i;
74826d688e3SAlex Vesker 
74926d688e3SAlex Vesker 	ret = mlx5dr_ste_build_pre_check(dmn, matcher->match_criteria,
75026d688e3SAlex Vesker 					 &matcher->mask, value);
75126d688e3SAlex Vesker 	if (ret)
75226d688e3SAlex Vesker 		return ret;
75326d688e3SAlex Vesker 
75426d688e3SAlex Vesker 	sb = nic_matcher->ste_builder;
75526d688e3SAlex Vesker 	for (i = 0; i < nic_matcher->num_of_builders; i++) {
75626d688e3SAlex Vesker 		mlx5dr_ste_init(ste_arr,
75726d688e3SAlex Vesker 				sb->lu_type,
75826d688e3SAlex Vesker 				nic_dmn->ste_type,
75926d688e3SAlex Vesker 				dmn->info.caps.gvmi);
76026d688e3SAlex Vesker 
76126d688e3SAlex Vesker 		mlx5dr_ste_set_bit_mask(ste_arr, sb->bit_mask);
76226d688e3SAlex Vesker 
76326d688e3SAlex Vesker 		ret = sb->ste_build_tag_func(value, sb, ste_arr);
76426d688e3SAlex Vesker 		if (ret)
76526d688e3SAlex Vesker 			return ret;
76626d688e3SAlex Vesker 
76726d688e3SAlex Vesker 		/* Connect the STEs */
76826d688e3SAlex Vesker 		if (i < (nic_matcher->num_of_builders - 1)) {
76926d688e3SAlex Vesker 			/* Need the next builder for these fields,
77026d688e3SAlex Vesker 			 * not relevant for the last ste in the chain.
77126d688e3SAlex Vesker 			 */
77226d688e3SAlex Vesker 			sb++;
77326d688e3SAlex Vesker 			MLX5_SET(ste_general, ste_arr, next_lu_type, sb->lu_type);
77426d688e3SAlex Vesker 			MLX5_SET(ste_general, ste_arr, byte_mask, sb->byte_mask);
77526d688e3SAlex Vesker 		}
77626d688e3SAlex Vesker 		ste_arr += DR_STE_SIZE;
77726d688e3SAlex Vesker 	}
77826d688e3SAlex Vesker 	return 0;
77926d688e3SAlex Vesker }
78026d688e3SAlex Vesker 
78126d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_des_bit_mask(struct mlx5dr_match_param *value,
78226d688e3SAlex Vesker 						bool inner, u8 *bit_mask)
78326d688e3SAlex Vesker {
78426d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
78526d688e3SAlex Vesker 
78626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, dmac_47_16, mask, dmac_47_16);
78726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, dmac_15_0, mask, dmac_15_0);
78826d688e3SAlex Vesker 
78926d688e3SAlex Vesker 	if (mask->smac_47_16 || mask->smac_15_0) {
79026d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, smac_47_32,
79126d688e3SAlex Vesker 			 mask->smac_47_16 >> 16);
79226d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, smac_31_0,
79326d688e3SAlex Vesker 			 mask->smac_47_16 << 16 | mask->smac_15_0);
79426d688e3SAlex Vesker 		mask->smac_47_16 = 0;
79526d688e3SAlex Vesker 		mask->smac_15_0 = 0;
79626d688e3SAlex Vesker 	}
79726d688e3SAlex Vesker 
79826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_vlan_id, mask, first_vid);
79926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_cfi, mask, first_cfi);
80026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_priority, mask, first_prio);
80126d688e3SAlex Vesker 	DR_STE_SET_MASK(eth_l2_src_dst, bit_mask, l3_type, mask, ip_version);
80226d688e3SAlex Vesker 
80326d688e3SAlex Vesker 	if (mask->cvlan_tag) {
80426d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, first_vlan_qualifier, -1);
80526d688e3SAlex Vesker 		mask->cvlan_tag = 0;
80626d688e3SAlex Vesker 	} else if (mask->svlan_tag) {
80726d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, first_vlan_qualifier, -1);
80826d688e3SAlex Vesker 		mask->svlan_tag = 0;
80926d688e3SAlex Vesker 	}
81026d688e3SAlex Vesker 
81126d688e3SAlex Vesker 	if (mask->cvlan_tag || mask->svlan_tag) {
81226d688e3SAlex Vesker 		pr_info("Invalid c/svlan mask configuration\n");
81326d688e3SAlex Vesker 		return -EINVAL;
81426d688e3SAlex Vesker 	}
81526d688e3SAlex Vesker 
81626d688e3SAlex Vesker 	return 0;
81726d688e3SAlex Vesker }
81826d688e3SAlex Vesker 
81926d688e3SAlex Vesker static void dr_ste_copy_mask_misc(char *mask, struct mlx5dr_match_misc *spec)
82026d688e3SAlex Vesker {
82126d688e3SAlex Vesker 	spec->gre_c_present = MLX5_GET(fte_match_set_misc, mask, gre_c_present);
82226d688e3SAlex Vesker 	spec->gre_k_present = MLX5_GET(fte_match_set_misc, mask, gre_k_present);
82326d688e3SAlex Vesker 	spec->gre_s_present = MLX5_GET(fte_match_set_misc, mask, gre_s_present);
82426d688e3SAlex Vesker 	spec->source_vhca_port = MLX5_GET(fte_match_set_misc, mask, source_vhca_port);
82526d688e3SAlex Vesker 	spec->source_sqn = MLX5_GET(fte_match_set_misc, mask, source_sqn);
82626d688e3SAlex Vesker 
82726d688e3SAlex Vesker 	spec->source_port = MLX5_GET(fte_match_set_misc, mask, source_port);
828640bdb1fSAlaa Hleihel 	spec->source_eswitch_owner_vhca_id = MLX5_GET(fte_match_set_misc, mask,
829640bdb1fSAlaa Hleihel 						      source_eswitch_owner_vhca_id);
83026d688e3SAlex Vesker 
83126d688e3SAlex Vesker 	spec->outer_second_prio = MLX5_GET(fte_match_set_misc, mask, outer_second_prio);
83226d688e3SAlex Vesker 	spec->outer_second_cfi = MLX5_GET(fte_match_set_misc, mask, outer_second_cfi);
83326d688e3SAlex Vesker 	spec->outer_second_vid = MLX5_GET(fte_match_set_misc, mask, outer_second_vid);
83426d688e3SAlex Vesker 	spec->inner_second_prio = MLX5_GET(fte_match_set_misc, mask, inner_second_prio);
83526d688e3SAlex Vesker 	spec->inner_second_cfi = MLX5_GET(fte_match_set_misc, mask, inner_second_cfi);
83626d688e3SAlex Vesker 	spec->inner_second_vid = MLX5_GET(fte_match_set_misc, mask, inner_second_vid);
83726d688e3SAlex Vesker 
83826d688e3SAlex Vesker 	spec->outer_second_cvlan_tag =
83926d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, outer_second_cvlan_tag);
84026d688e3SAlex Vesker 	spec->inner_second_cvlan_tag =
84126d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, inner_second_cvlan_tag);
84226d688e3SAlex Vesker 	spec->outer_second_svlan_tag =
84326d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, outer_second_svlan_tag);
84426d688e3SAlex Vesker 	spec->inner_second_svlan_tag =
84526d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, inner_second_svlan_tag);
84626d688e3SAlex Vesker 
84726d688e3SAlex Vesker 	spec->gre_protocol = MLX5_GET(fte_match_set_misc, mask, gre_protocol);
84826d688e3SAlex Vesker 
84926d688e3SAlex Vesker 	spec->gre_key_h = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.hi);
85026d688e3SAlex Vesker 	spec->gre_key_l = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.lo);
85126d688e3SAlex Vesker 
85226d688e3SAlex Vesker 	spec->vxlan_vni = MLX5_GET(fte_match_set_misc, mask, vxlan_vni);
85326d688e3SAlex Vesker 
85426d688e3SAlex Vesker 	spec->geneve_vni = MLX5_GET(fte_match_set_misc, mask, geneve_vni);
85526d688e3SAlex Vesker 	spec->geneve_oam = MLX5_GET(fte_match_set_misc, mask, geneve_oam);
85626d688e3SAlex Vesker 
85726d688e3SAlex Vesker 	spec->outer_ipv6_flow_label =
85826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, outer_ipv6_flow_label);
85926d688e3SAlex Vesker 
86026d688e3SAlex Vesker 	spec->inner_ipv6_flow_label =
86126d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, inner_ipv6_flow_label);
86226d688e3SAlex Vesker 
86326d688e3SAlex Vesker 	spec->geneve_opt_len = MLX5_GET(fte_match_set_misc, mask, geneve_opt_len);
86426d688e3SAlex Vesker 	spec->geneve_protocol_type =
86526d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, geneve_protocol_type);
86626d688e3SAlex Vesker 
86726d688e3SAlex Vesker 	spec->bth_dst_qp = MLX5_GET(fte_match_set_misc, mask, bth_dst_qp);
86826d688e3SAlex Vesker }
86926d688e3SAlex Vesker 
87026d688e3SAlex Vesker static void dr_ste_copy_mask_spec(char *mask, struct mlx5dr_match_spec *spec)
87126d688e3SAlex Vesker {
872c2ba2c22SSaeed Mahameed 	__be32 raw_ip[4];
87326d688e3SAlex Vesker 
87426d688e3SAlex Vesker 	spec->smac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_47_16);
87526d688e3SAlex Vesker 
87626d688e3SAlex Vesker 	spec->smac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_15_0);
87726d688e3SAlex Vesker 	spec->ethertype = MLX5_GET(fte_match_set_lyr_2_4, mask, ethertype);
87826d688e3SAlex Vesker 
87926d688e3SAlex Vesker 	spec->dmac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_47_16);
88026d688e3SAlex Vesker 
88126d688e3SAlex Vesker 	spec->dmac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_15_0);
88226d688e3SAlex Vesker 	spec->first_prio = MLX5_GET(fte_match_set_lyr_2_4, mask, first_prio);
88326d688e3SAlex Vesker 	spec->first_cfi = MLX5_GET(fte_match_set_lyr_2_4, mask, first_cfi);
88426d688e3SAlex Vesker 	spec->first_vid = MLX5_GET(fte_match_set_lyr_2_4, mask, first_vid);
88526d688e3SAlex Vesker 
88626d688e3SAlex Vesker 	spec->ip_protocol = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_protocol);
88726d688e3SAlex Vesker 	spec->ip_dscp = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_dscp);
88826d688e3SAlex Vesker 	spec->ip_ecn = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_ecn);
88926d688e3SAlex Vesker 	spec->cvlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, cvlan_tag);
89026d688e3SAlex Vesker 	spec->svlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, svlan_tag);
89126d688e3SAlex Vesker 	spec->frag = MLX5_GET(fte_match_set_lyr_2_4, mask, frag);
89226d688e3SAlex Vesker 	spec->ip_version = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_version);
89326d688e3SAlex Vesker 	spec->tcp_flags = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_flags);
89426d688e3SAlex Vesker 	spec->tcp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_sport);
89526d688e3SAlex Vesker 	spec->tcp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_dport);
89626d688e3SAlex Vesker 
89726d688e3SAlex Vesker 	spec->ttl_hoplimit = MLX5_GET(fte_match_set_lyr_2_4, mask, ttl_hoplimit);
89826d688e3SAlex Vesker 
89926d688e3SAlex Vesker 	spec->udp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_sport);
90026d688e3SAlex Vesker 	spec->udp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_dport);
90126d688e3SAlex Vesker 
90226d688e3SAlex Vesker 	memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
90326d688e3SAlex Vesker 				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
90426d688e3SAlex Vesker 				    sizeof(raw_ip));
90526d688e3SAlex Vesker 
90626d688e3SAlex Vesker 	spec->src_ip_127_96 = be32_to_cpu(raw_ip[0]);
90726d688e3SAlex Vesker 	spec->src_ip_95_64 = be32_to_cpu(raw_ip[1]);
90826d688e3SAlex Vesker 	spec->src_ip_63_32 = be32_to_cpu(raw_ip[2]);
90926d688e3SAlex Vesker 	spec->src_ip_31_0 = be32_to_cpu(raw_ip[3]);
91026d688e3SAlex Vesker 
91126d688e3SAlex Vesker 	memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
91226d688e3SAlex Vesker 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
91326d688e3SAlex Vesker 				    sizeof(raw_ip));
91426d688e3SAlex Vesker 
91526d688e3SAlex Vesker 	spec->dst_ip_127_96 = be32_to_cpu(raw_ip[0]);
91626d688e3SAlex Vesker 	spec->dst_ip_95_64 = be32_to_cpu(raw_ip[1]);
91726d688e3SAlex Vesker 	spec->dst_ip_63_32 = be32_to_cpu(raw_ip[2]);
91826d688e3SAlex Vesker 	spec->dst_ip_31_0 = be32_to_cpu(raw_ip[3]);
91926d688e3SAlex Vesker }
92026d688e3SAlex Vesker 
92126d688e3SAlex Vesker static void dr_ste_copy_mask_misc2(char *mask, struct mlx5dr_match_misc2 *spec)
92226d688e3SAlex Vesker {
92326d688e3SAlex Vesker 	spec->outer_first_mpls_label =
92426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_label);
92526d688e3SAlex Vesker 	spec->outer_first_mpls_exp =
92626d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_exp);
92726d688e3SAlex Vesker 	spec->outer_first_mpls_s_bos =
92826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_s_bos);
92926d688e3SAlex Vesker 	spec->outer_first_mpls_ttl =
93026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_ttl);
93126d688e3SAlex Vesker 	spec->inner_first_mpls_label =
93226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_label);
93326d688e3SAlex Vesker 	spec->inner_first_mpls_exp =
93426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_exp);
93526d688e3SAlex Vesker 	spec->inner_first_mpls_s_bos =
93626d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_s_bos);
93726d688e3SAlex Vesker 	spec->inner_first_mpls_ttl =
93826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_ttl);
93926d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_label =
94026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_label);
94126d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_exp =
94226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_exp);
94326d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_s_bos =
94426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_s_bos);
94526d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_ttl =
94626d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_ttl);
94726d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_label =
94826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_label);
94926d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_exp =
95026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_exp);
95126d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_s_bos =
95226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_s_bos);
95326d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_ttl =
95426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_ttl);
95526d688e3SAlex Vesker 	spec->metadata_reg_c_7 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_7);
95626d688e3SAlex Vesker 	spec->metadata_reg_c_6 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_6);
95726d688e3SAlex Vesker 	spec->metadata_reg_c_5 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_5);
95826d688e3SAlex Vesker 	spec->metadata_reg_c_4 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_4);
95926d688e3SAlex Vesker 	spec->metadata_reg_c_3 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_3);
96026d688e3SAlex Vesker 	spec->metadata_reg_c_2 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_2);
96126d688e3SAlex Vesker 	spec->metadata_reg_c_1 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_1);
96226d688e3SAlex Vesker 	spec->metadata_reg_c_0 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_0);
96326d688e3SAlex Vesker 	spec->metadata_reg_a = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_a);
96426d688e3SAlex Vesker }
96526d688e3SAlex Vesker 
96626d688e3SAlex Vesker static void dr_ste_copy_mask_misc3(char *mask, struct mlx5dr_match_misc3 *spec)
96726d688e3SAlex Vesker {
96826d688e3SAlex Vesker 	spec->inner_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_seq_num);
96926d688e3SAlex Vesker 	spec->outer_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_seq_num);
97026d688e3SAlex Vesker 	spec->inner_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_ack_num);
97126d688e3SAlex Vesker 	spec->outer_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_ack_num);
97226d688e3SAlex Vesker 	spec->outer_vxlan_gpe_vni =
97326d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_vni);
97426d688e3SAlex Vesker 	spec->outer_vxlan_gpe_next_protocol =
97526d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_next_protocol);
97626d688e3SAlex Vesker 	spec->outer_vxlan_gpe_flags =
97726d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_flags);
97826d688e3SAlex Vesker 	spec->icmpv4_header_data = MLX5_GET(fte_match_set_misc3, mask, icmp_header_data);
97926d688e3SAlex Vesker 	spec->icmpv6_header_data =
98026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, icmpv6_header_data);
98126d688e3SAlex Vesker 	spec->icmpv4_type = MLX5_GET(fte_match_set_misc3, mask, icmp_type);
98226d688e3SAlex Vesker 	spec->icmpv4_code = MLX5_GET(fte_match_set_misc3, mask, icmp_code);
98326d688e3SAlex Vesker 	spec->icmpv6_type = MLX5_GET(fte_match_set_misc3, mask, icmpv6_type);
98426d688e3SAlex Vesker 	spec->icmpv6_code = MLX5_GET(fte_match_set_misc3, mask, icmpv6_code);
98526d688e3SAlex Vesker }
98626d688e3SAlex Vesker 
98726d688e3SAlex Vesker void mlx5dr_ste_copy_param(u8 match_criteria,
98826d688e3SAlex Vesker 			   struct mlx5dr_match_param *set_param,
98926d688e3SAlex Vesker 			   struct mlx5dr_match_parameters *mask)
99026d688e3SAlex Vesker {
99126d688e3SAlex Vesker 	u8 tail_param[MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4)] = {};
99226d688e3SAlex Vesker 	u8 *data = (u8 *)mask->match_buf;
99326d688e3SAlex Vesker 	size_t param_location;
99426d688e3SAlex Vesker 	void *buff;
99526d688e3SAlex Vesker 
99626d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_OUTER) {
99726d688e3SAlex Vesker 		if (mask->match_sz < sizeof(struct mlx5dr_match_spec)) {
99826d688e3SAlex Vesker 			memcpy(tail_param, data, mask->match_sz);
99926d688e3SAlex Vesker 			buff = tail_param;
100026d688e3SAlex Vesker 		} else {
100126d688e3SAlex Vesker 			buff = mask->match_buf;
100226d688e3SAlex Vesker 		}
100326d688e3SAlex Vesker 		dr_ste_copy_mask_spec(buff, &set_param->outer);
100426d688e3SAlex Vesker 	}
100526d688e3SAlex Vesker 	param_location = sizeof(struct mlx5dr_match_spec);
100626d688e3SAlex Vesker 
100726d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_MISC) {
100826d688e3SAlex Vesker 		if (mask->match_sz < param_location +
100926d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_misc)) {
101026d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
101126d688e3SAlex Vesker 			       mask->match_sz - param_location);
101226d688e3SAlex Vesker 			buff = tail_param;
101326d688e3SAlex Vesker 		} else {
101426d688e3SAlex Vesker 			buff = data + param_location;
101526d688e3SAlex Vesker 		}
101626d688e3SAlex Vesker 		dr_ste_copy_mask_misc(buff, &set_param->misc);
101726d688e3SAlex Vesker 	}
101826d688e3SAlex Vesker 	param_location += sizeof(struct mlx5dr_match_misc);
101926d688e3SAlex Vesker 
102026d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_INNER) {
102126d688e3SAlex Vesker 		if (mask->match_sz < param_location +
102226d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_spec)) {
102326d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
102426d688e3SAlex Vesker 			       mask->match_sz - param_location);
102526d688e3SAlex Vesker 			buff = tail_param;
102626d688e3SAlex Vesker 		} else {
102726d688e3SAlex Vesker 			buff = data + param_location;
102826d688e3SAlex Vesker 		}
102926d688e3SAlex Vesker 		dr_ste_copy_mask_spec(buff, &set_param->inner);
103026d688e3SAlex Vesker 	}
103126d688e3SAlex Vesker 	param_location += sizeof(struct mlx5dr_match_spec);
103226d688e3SAlex Vesker 
103326d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_MISC2) {
103426d688e3SAlex Vesker 		if (mask->match_sz < param_location +
103526d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_misc2)) {
103626d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
103726d688e3SAlex Vesker 			       mask->match_sz - param_location);
103826d688e3SAlex Vesker 			buff = tail_param;
103926d688e3SAlex Vesker 		} else {
104026d688e3SAlex Vesker 			buff = data + param_location;
104126d688e3SAlex Vesker 		}
104226d688e3SAlex Vesker 		dr_ste_copy_mask_misc2(buff, &set_param->misc2);
104326d688e3SAlex Vesker 	}
104426d688e3SAlex Vesker 
104526d688e3SAlex Vesker 	param_location += sizeof(struct mlx5dr_match_misc2);
104626d688e3SAlex Vesker 
104726d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_MISC3) {
104826d688e3SAlex Vesker 		if (mask->match_sz < param_location +
104926d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_misc3)) {
105026d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
105126d688e3SAlex Vesker 			       mask->match_sz - param_location);
105226d688e3SAlex Vesker 			buff = tail_param;
105326d688e3SAlex Vesker 		} else {
105426d688e3SAlex Vesker 			buff = data + param_location;
105526d688e3SAlex Vesker 		}
105626d688e3SAlex Vesker 		dr_ste_copy_mask_misc3(buff, &set_param->misc3);
105726d688e3SAlex Vesker 	}
105826d688e3SAlex Vesker }
105926d688e3SAlex Vesker 
106026d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_des_tag(struct mlx5dr_match_param *value,
106126d688e3SAlex Vesker 					   struct mlx5dr_ste_build *sb,
106226d688e3SAlex Vesker 					   u8 *hw_ste_p)
106326d688e3SAlex Vesker {
106426d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
106526d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
106626d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
106726d688e3SAlex Vesker 
106826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, dmac_47_16, spec, dmac_47_16);
106926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, dmac_15_0, spec, dmac_15_0);
107026d688e3SAlex Vesker 
107126d688e3SAlex Vesker 	if (spec->smac_47_16 || spec->smac_15_0) {
107226d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, smac_47_32,
107326d688e3SAlex Vesker 			 spec->smac_47_16 >> 16);
107426d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, smac_31_0,
107526d688e3SAlex Vesker 			 spec->smac_47_16 << 16 | spec->smac_15_0);
107626d688e3SAlex Vesker 		spec->smac_47_16 = 0;
107726d688e3SAlex Vesker 		spec->smac_15_0 = 0;
107826d688e3SAlex Vesker 	}
107926d688e3SAlex Vesker 
108026d688e3SAlex Vesker 	if (spec->ip_version) {
108126d688e3SAlex Vesker 		if (spec->ip_version == IP_VERSION_IPV4) {
108226d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src_dst, tag, l3_type, STE_IPV4);
108326d688e3SAlex Vesker 			spec->ip_version = 0;
108426d688e3SAlex Vesker 		} else if (spec->ip_version == IP_VERSION_IPV6) {
108526d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src_dst, tag, l3_type, STE_IPV6);
108626d688e3SAlex Vesker 			spec->ip_version = 0;
108726d688e3SAlex Vesker 		} else {
108826d688e3SAlex Vesker 			pr_info("Unsupported ip_version value\n");
108926d688e3SAlex Vesker 			return -EINVAL;
109026d688e3SAlex Vesker 		}
109126d688e3SAlex Vesker 	}
109226d688e3SAlex Vesker 
109326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, first_vlan_id, spec, first_vid);
109426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, first_cfi, spec, first_cfi);
109526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, first_priority, spec, first_prio);
109626d688e3SAlex Vesker 
109726d688e3SAlex Vesker 	if (spec->cvlan_tag) {
109826d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, first_vlan_qualifier, DR_STE_CVLAN);
109926d688e3SAlex Vesker 		spec->cvlan_tag = 0;
110026d688e3SAlex Vesker 	} else if (spec->svlan_tag) {
110126d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, first_vlan_qualifier, DR_STE_SVLAN);
110226d688e3SAlex Vesker 		spec->svlan_tag = 0;
110326d688e3SAlex Vesker 	}
110426d688e3SAlex Vesker 	return 0;
110526d688e3SAlex Vesker }
110626d688e3SAlex Vesker 
110726d688e3SAlex Vesker int mlx5dr_ste_build_eth_l2_src_des(struct mlx5dr_ste_build *sb,
110826d688e3SAlex Vesker 				    struct mlx5dr_match_param *mask,
110926d688e3SAlex Vesker 				    bool inner, bool rx)
111026d688e3SAlex Vesker {
111126d688e3SAlex Vesker 	int ret;
111226d688e3SAlex Vesker 
111326d688e3SAlex Vesker 	ret = dr_ste_build_eth_l2_src_des_bit_mask(mask, inner, sb->bit_mask);
111426d688e3SAlex Vesker 	if (ret)
111526d688e3SAlex Vesker 		return ret;
111626d688e3SAlex Vesker 
111726d688e3SAlex Vesker 	sb->rx = rx;
111826d688e3SAlex Vesker 	sb->inner = inner;
111926d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_SRC_DST, rx, inner);
112026d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
112126d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_src_des_tag;
112226d688e3SAlex Vesker 
112326d688e3SAlex Vesker 	return 0;
112426d688e3SAlex Vesker }
112526d688e3SAlex Vesker 
112626d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv6_dst_bit_mask(struct mlx5dr_match_param *value,
112726d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
112826d688e3SAlex Vesker {
112926d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
113026d688e3SAlex Vesker 
113126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_127_96, mask, dst_ip_127_96);
113226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_95_64, mask, dst_ip_95_64);
113326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_63_32, mask, dst_ip_63_32);
113426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_31_0, mask, dst_ip_31_0);
113526d688e3SAlex Vesker }
113626d688e3SAlex Vesker 
113726d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv6_dst_tag(struct mlx5dr_match_param *value,
113826d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
113926d688e3SAlex Vesker 					    u8 *hw_ste_p)
114026d688e3SAlex Vesker {
114126d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
114226d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
114326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
114426d688e3SAlex Vesker 
114526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_127_96, spec, dst_ip_127_96);
114626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_95_64, spec, dst_ip_95_64);
114726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_63_32, spec, dst_ip_63_32);
114826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_31_0, spec, dst_ip_31_0);
114926d688e3SAlex Vesker 
115026d688e3SAlex Vesker 	return 0;
115126d688e3SAlex Vesker }
115226d688e3SAlex Vesker 
115326d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv6_dst(struct mlx5dr_ste_build *sb,
115426d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
115526d688e3SAlex Vesker 				      bool inner, bool rx)
115626d688e3SAlex Vesker {
115726d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv6_dst_bit_mask(mask, inner, sb->bit_mask);
115826d688e3SAlex Vesker 
115926d688e3SAlex Vesker 	sb->rx = rx;
116026d688e3SAlex Vesker 	sb->inner = inner;
116126d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV6_DST, rx, inner);
116226d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
116326d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv6_dst_tag;
116426d688e3SAlex Vesker }
116526d688e3SAlex Vesker 
116626d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv6_src_bit_mask(struct mlx5dr_match_param *value,
116726d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
116826d688e3SAlex Vesker {
116926d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
117026d688e3SAlex Vesker 
117126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_127_96, mask, src_ip_127_96);
117226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_95_64, mask, src_ip_95_64);
117326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_63_32, mask, src_ip_63_32);
117426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_31_0, mask, src_ip_31_0);
117526d688e3SAlex Vesker }
117626d688e3SAlex Vesker 
117726d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv6_src_tag(struct mlx5dr_match_param *value,
117826d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
117926d688e3SAlex Vesker 					    u8 *hw_ste_p)
118026d688e3SAlex Vesker {
118126d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
118226d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
118326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
118426d688e3SAlex Vesker 
118526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_127_96, spec, src_ip_127_96);
118626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_95_64, spec, src_ip_95_64);
118726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_63_32, spec, src_ip_63_32);
118826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_31_0, spec, src_ip_31_0);
118926d688e3SAlex Vesker 
119026d688e3SAlex Vesker 	return 0;
119126d688e3SAlex Vesker }
119226d688e3SAlex Vesker 
119326d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv6_src(struct mlx5dr_ste_build *sb,
119426d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
119526d688e3SAlex Vesker 				      bool inner, bool rx)
119626d688e3SAlex Vesker {
119726d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv6_src_bit_mask(mask, inner, sb->bit_mask);
119826d688e3SAlex Vesker 
119926d688e3SAlex Vesker 	sb->rx = rx;
120026d688e3SAlex Vesker 	sb->inner = inner;
120126d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV6_SRC, rx, inner);
120226d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
120326d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv6_src_tag;
120426d688e3SAlex Vesker }
120526d688e3SAlex Vesker 
120626d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv4_5_tuple_bit_mask(struct mlx5dr_match_param *value,
120726d688e3SAlex Vesker 						      bool inner,
120826d688e3SAlex Vesker 						      u8 *bit_mask)
120926d688e3SAlex Vesker {
121026d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
121126d688e3SAlex Vesker 
121226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
121326d688e3SAlex Vesker 			  destination_address, mask, dst_ip_31_0);
121426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
121526d688e3SAlex Vesker 			  source_address, mask, src_ip_31_0);
121626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
121726d688e3SAlex Vesker 			  destination_port, mask, tcp_dport);
121826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
121926d688e3SAlex Vesker 			  destination_port, mask, udp_dport);
122026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
122126d688e3SAlex Vesker 			  source_port, mask, tcp_sport);
122226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
122326d688e3SAlex Vesker 			  source_port, mask, udp_sport);
122426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
122526d688e3SAlex Vesker 			  protocol, mask, ip_protocol);
122626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
122726d688e3SAlex Vesker 			  fragmented, mask, frag);
122826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
122926d688e3SAlex Vesker 			  dscp, mask, ip_dscp);
123026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
123126d688e3SAlex Vesker 			  ecn, mask, ip_ecn);
123226d688e3SAlex Vesker 
123326d688e3SAlex Vesker 	if (mask->tcp_flags) {
123426d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l3_ipv4_5_tuple, bit_mask, mask);
123526d688e3SAlex Vesker 		mask->tcp_flags = 0;
123626d688e3SAlex Vesker 	}
123726d688e3SAlex Vesker }
123826d688e3SAlex Vesker 
123926d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv4_5_tuple_tag(struct mlx5dr_match_param *value,
124026d688e3SAlex Vesker 						struct mlx5dr_ste_build *sb,
124126d688e3SAlex Vesker 						u8 *hw_ste_p)
124226d688e3SAlex Vesker {
124326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
124426d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
124526d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
124626d688e3SAlex Vesker 
124726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_address, spec, dst_ip_31_0);
124826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_address, spec, src_ip_31_0);
124926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_port, spec, tcp_dport);
125026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_port, spec, udp_dport);
125126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_port, spec, tcp_sport);
125226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_port, spec, udp_sport);
125326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, protocol, spec, ip_protocol);
125426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, fragmented, spec, frag);
125526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, dscp, spec, ip_dscp);
125626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, ecn, spec, ip_ecn);
125726d688e3SAlex Vesker 
125826d688e3SAlex Vesker 	if (spec->tcp_flags) {
125926d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l3_ipv4_5_tuple, tag, spec);
126026d688e3SAlex Vesker 		spec->tcp_flags = 0;
126126d688e3SAlex Vesker 	}
126226d688e3SAlex Vesker 
126326d688e3SAlex Vesker 	return 0;
126426d688e3SAlex Vesker }
126526d688e3SAlex Vesker 
126626d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv4_5_tuple(struct mlx5dr_ste_build *sb,
126726d688e3SAlex Vesker 					  struct mlx5dr_match_param *mask,
126826d688e3SAlex Vesker 					  bool inner, bool rx)
126926d688e3SAlex Vesker {
127026d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv4_5_tuple_bit_mask(mask, inner, sb->bit_mask);
127126d688e3SAlex Vesker 
127226d688e3SAlex Vesker 	sb->rx = rx;
127326d688e3SAlex Vesker 	sb->inner = inner;
127426d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV4_5_TUPLE, rx, inner);
127526d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
127626d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv4_5_tuple_tag;
127726d688e3SAlex Vesker }
127826d688e3SAlex Vesker 
127926d688e3SAlex Vesker static void
128026d688e3SAlex Vesker dr_ste_build_eth_l2_src_or_dst_bit_mask(struct mlx5dr_match_param *value,
128126d688e3SAlex Vesker 					bool inner, u8 *bit_mask)
128226d688e3SAlex Vesker {
128326d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
128426d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_mask = &value->misc;
128526d688e3SAlex Vesker 
128626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_vlan_id, mask, first_vid);
128726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_cfi, mask, first_cfi);
128826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_priority, mask, first_prio);
128926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, ip_fragmented, mask, frag);
129026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, l3_ethertype, mask, ethertype);
129126d688e3SAlex Vesker 	DR_STE_SET_MASK(eth_l2_src, bit_mask, l3_type, mask, ip_version);
129226d688e3SAlex Vesker 
129326d688e3SAlex Vesker 	if (mask->svlan_tag || mask->cvlan_tag) {
129426d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src, bit_mask, first_vlan_qualifier, -1);
129526d688e3SAlex Vesker 		mask->cvlan_tag = 0;
129626d688e3SAlex Vesker 		mask->svlan_tag = 0;
129726d688e3SAlex Vesker 	}
129826d688e3SAlex Vesker 
129926d688e3SAlex Vesker 	if (inner) {
130026d688e3SAlex Vesker 		if (misc_mask->inner_second_cvlan_tag ||
130126d688e3SAlex Vesker 		    misc_mask->inner_second_svlan_tag) {
130226d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, bit_mask, second_vlan_qualifier, -1);
130326d688e3SAlex Vesker 			misc_mask->inner_second_cvlan_tag = 0;
130426d688e3SAlex Vesker 			misc_mask->inner_second_svlan_tag = 0;
130526d688e3SAlex Vesker 		}
130626d688e3SAlex Vesker 
130726d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
130826d688e3SAlex Vesker 				  second_vlan_id, misc_mask, inner_second_vid);
130926d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
131026d688e3SAlex Vesker 				  second_cfi, misc_mask, inner_second_cfi);
131126d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
131226d688e3SAlex Vesker 				  second_priority, misc_mask, inner_second_prio);
131326d688e3SAlex Vesker 	} else {
131426d688e3SAlex Vesker 		if (misc_mask->outer_second_cvlan_tag ||
131526d688e3SAlex Vesker 		    misc_mask->outer_second_svlan_tag) {
131626d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, bit_mask, second_vlan_qualifier, -1);
131726d688e3SAlex Vesker 			misc_mask->outer_second_cvlan_tag = 0;
131826d688e3SAlex Vesker 			misc_mask->outer_second_svlan_tag = 0;
131926d688e3SAlex Vesker 		}
132026d688e3SAlex Vesker 
132126d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
132226d688e3SAlex Vesker 				  second_vlan_id, misc_mask, outer_second_vid);
132326d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
132426d688e3SAlex Vesker 				  second_cfi, misc_mask, outer_second_cfi);
132526d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
132626d688e3SAlex Vesker 				  second_priority, misc_mask, outer_second_prio);
132726d688e3SAlex Vesker 	}
132826d688e3SAlex Vesker }
132926d688e3SAlex Vesker 
133026d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_or_dst_tag(struct mlx5dr_match_param *value,
133126d688e3SAlex Vesker 					      bool inner, u8 *hw_ste_p)
133226d688e3SAlex Vesker {
133326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
133426d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = inner ? &value->inner : &value->outer;
133526d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_spec = &value->misc;
133626d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
133726d688e3SAlex Vesker 
133826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, first_vlan_id, spec, first_vid);
133926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, first_cfi, spec, first_cfi);
134026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, first_priority, spec, first_prio);
134126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, ip_fragmented, spec, frag);
134226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, l3_ethertype, spec, ethertype);
134326d688e3SAlex Vesker 
134426d688e3SAlex Vesker 	if (spec->ip_version) {
134526d688e3SAlex Vesker 		if (spec->ip_version == IP_VERSION_IPV4) {
134626d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, l3_type, STE_IPV4);
134726d688e3SAlex Vesker 			spec->ip_version = 0;
134826d688e3SAlex Vesker 		} else if (spec->ip_version == IP_VERSION_IPV6) {
134926d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, l3_type, STE_IPV6);
135026d688e3SAlex Vesker 			spec->ip_version = 0;
135126d688e3SAlex Vesker 		} else {
135226d688e3SAlex Vesker 			pr_info("Unsupported ip_version value\n");
135326d688e3SAlex Vesker 			return -EINVAL;
135426d688e3SAlex Vesker 		}
135526d688e3SAlex Vesker 	}
135626d688e3SAlex Vesker 
135726d688e3SAlex Vesker 	if (spec->cvlan_tag) {
135826d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src, tag, first_vlan_qualifier, DR_STE_CVLAN);
135926d688e3SAlex Vesker 		spec->cvlan_tag = 0;
136026d688e3SAlex Vesker 	} else if (spec->svlan_tag) {
136126d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src, tag, first_vlan_qualifier, DR_STE_SVLAN);
136226d688e3SAlex Vesker 		spec->svlan_tag = 0;
136326d688e3SAlex Vesker 	}
136426d688e3SAlex Vesker 
136526d688e3SAlex Vesker 	if (inner) {
136626d688e3SAlex Vesker 		if (misc_spec->inner_second_cvlan_tag) {
136726d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_CVLAN);
136826d688e3SAlex Vesker 			misc_spec->inner_second_cvlan_tag = 0;
136926d688e3SAlex Vesker 		} else if (misc_spec->inner_second_svlan_tag) {
137026d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_SVLAN);
137126d688e3SAlex Vesker 			misc_spec->inner_second_svlan_tag = 0;
137226d688e3SAlex Vesker 		}
137326d688e3SAlex Vesker 
137426d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_vlan_id, misc_spec, inner_second_vid);
137526d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_cfi, misc_spec, inner_second_cfi);
137626d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_priority, misc_spec, inner_second_prio);
137726d688e3SAlex Vesker 	} else {
137826d688e3SAlex Vesker 		if (misc_spec->outer_second_cvlan_tag) {
137926d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_CVLAN);
138026d688e3SAlex Vesker 			misc_spec->outer_second_cvlan_tag = 0;
138126d688e3SAlex Vesker 		} else if (misc_spec->outer_second_svlan_tag) {
138226d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_SVLAN);
138326d688e3SAlex Vesker 			misc_spec->outer_second_svlan_tag = 0;
138426d688e3SAlex Vesker 		}
138526d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_vlan_id, misc_spec, outer_second_vid);
138626d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_cfi, misc_spec, outer_second_cfi);
138726d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_priority, misc_spec, outer_second_prio);
138826d688e3SAlex Vesker 	}
138926d688e3SAlex Vesker 
139026d688e3SAlex Vesker 	return 0;
139126d688e3SAlex Vesker }
139226d688e3SAlex Vesker 
139326d688e3SAlex Vesker static void dr_ste_build_eth_l2_src_bit_mask(struct mlx5dr_match_param *value,
139426d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
139526d688e3SAlex Vesker {
139626d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
139726d688e3SAlex Vesker 
139826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, smac_47_16, mask, smac_47_16);
139926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, smac_15_0, mask, smac_15_0);
140026d688e3SAlex Vesker 
140126d688e3SAlex Vesker 	dr_ste_build_eth_l2_src_or_dst_bit_mask(value, inner, bit_mask);
140226d688e3SAlex Vesker }
140326d688e3SAlex Vesker 
140426d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_tag(struct mlx5dr_match_param *value,
140526d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
140626d688e3SAlex Vesker 				       u8 *hw_ste_p)
140726d688e3SAlex Vesker {
140826d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
140926d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
141026d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
141126d688e3SAlex Vesker 
141226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, smac_47_16, spec, smac_47_16);
141326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, smac_15_0, spec, smac_15_0);
141426d688e3SAlex Vesker 
141526d688e3SAlex Vesker 	return dr_ste_build_eth_l2_src_or_dst_tag(value, sb->inner, hw_ste_p);
141626d688e3SAlex Vesker }
141726d688e3SAlex Vesker 
141826d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_src(struct mlx5dr_ste_build *sb,
141926d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
142026d688e3SAlex Vesker 				 bool inner, bool rx)
142126d688e3SAlex Vesker {
142226d688e3SAlex Vesker 	dr_ste_build_eth_l2_src_bit_mask(mask, inner, sb->bit_mask);
142326d688e3SAlex Vesker 	sb->rx = rx;
142426d688e3SAlex Vesker 	sb->inner = inner;
142526d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_SRC, rx, inner);
142626d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
142726d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_src_tag;
142826d688e3SAlex Vesker }
142926d688e3SAlex Vesker 
143026d688e3SAlex Vesker static void dr_ste_build_eth_l2_dst_bit_mask(struct mlx5dr_match_param *value,
143126d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
143226d688e3SAlex Vesker {
143326d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
143426d688e3SAlex Vesker 
143526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_dst, bit_mask, dmac_47_16, mask, dmac_47_16);
143626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_dst, bit_mask, dmac_15_0, mask, dmac_15_0);
143726d688e3SAlex Vesker 
143826d688e3SAlex Vesker 	dr_ste_build_eth_l2_src_or_dst_bit_mask(value, inner, bit_mask);
143926d688e3SAlex Vesker }
144026d688e3SAlex Vesker 
144126d688e3SAlex Vesker static int dr_ste_build_eth_l2_dst_tag(struct mlx5dr_match_param *value,
144226d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
144326d688e3SAlex Vesker 				       u8 *hw_ste_p)
144426d688e3SAlex Vesker {
144526d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
144626d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
144726d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
144826d688e3SAlex Vesker 
144926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_dst, tag, dmac_47_16, spec, dmac_47_16);
145026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_dst, tag, dmac_15_0, spec, dmac_15_0);
145126d688e3SAlex Vesker 
145226d688e3SAlex Vesker 	return dr_ste_build_eth_l2_src_or_dst_tag(value, sb->inner, hw_ste_p);
145326d688e3SAlex Vesker }
145426d688e3SAlex Vesker 
145526d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_dst(struct mlx5dr_ste_build *sb,
145626d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
145726d688e3SAlex Vesker 				 bool inner, bool rx)
145826d688e3SAlex Vesker {
145926d688e3SAlex Vesker 	dr_ste_build_eth_l2_dst_bit_mask(mask, inner, sb->bit_mask);
146026d688e3SAlex Vesker 
146126d688e3SAlex Vesker 	sb->rx = rx;
146226d688e3SAlex Vesker 	sb->inner = inner;
146326d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_DST, rx, inner);
146426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
146526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_dst_tag;
146626d688e3SAlex Vesker }
146726d688e3SAlex Vesker 
146826d688e3SAlex Vesker static void dr_ste_build_eth_l2_tnl_bit_mask(struct mlx5dr_match_param *value,
146926d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
147026d688e3SAlex Vesker {
147126d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
147226d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc = &value->misc;
147326d688e3SAlex Vesker 
147426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, dmac_47_16, mask, dmac_47_16);
147526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, dmac_15_0, mask, dmac_15_0);
147626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_vlan_id, mask, first_vid);
147726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_cfi, mask, first_cfi);
147826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_priority, mask, first_prio);
147926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, ip_fragmented, mask, frag);
148026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, l3_ethertype, mask, ethertype);
148126d688e3SAlex Vesker 	DR_STE_SET_MASK(eth_l2_tnl, bit_mask, l3_type, mask, ip_version);
148226d688e3SAlex Vesker 
148326d688e3SAlex Vesker 	if (misc->vxlan_vni) {
148426d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, bit_mask,
148526d688e3SAlex Vesker 			 l2_tunneling_network_id, (misc->vxlan_vni << 8));
148626d688e3SAlex Vesker 		misc->vxlan_vni = 0;
148726d688e3SAlex Vesker 	}
148826d688e3SAlex Vesker 
148926d688e3SAlex Vesker 	if (mask->svlan_tag || mask->cvlan_tag) {
149026d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, bit_mask, first_vlan_qualifier, -1);
149126d688e3SAlex Vesker 		mask->cvlan_tag = 0;
149226d688e3SAlex Vesker 		mask->svlan_tag = 0;
149326d688e3SAlex Vesker 	}
149426d688e3SAlex Vesker }
149526d688e3SAlex Vesker 
149626d688e3SAlex Vesker static int dr_ste_build_eth_l2_tnl_tag(struct mlx5dr_match_param *value,
149726d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
149826d688e3SAlex Vesker 				       u8 *hw_ste_p)
149926d688e3SAlex Vesker {
150026d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
150126d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
150226d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc = &value->misc;
150326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
150426d688e3SAlex Vesker 
150526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, dmac_47_16, spec, dmac_47_16);
150626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, dmac_15_0, spec, dmac_15_0);
150726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, first_vlan_id, spec, first_vid);
150826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, first_cfi, spec, first_cfi);
150926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, ip_fragmented, spec, frag);
151026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, first_priority, spec, first_prio);
151126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, l3_ethertype, spec, ethertype);
151226d688e3SAlex Vesker 
151326d688e3SAlex Vesker 	if (misc->vxlan_vni) {
151426d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, tag, l2_tunneling_network_id,
151526d688e3SAlex Vesker 			 (misc->vxlan_vni << 8));
151626d688e3SAlex Vesker 		misc->vxlan_vni = 0;
151726d688e3SAlex Vesker 	}
151826d688e3SAlex Vesker 
151926d688e3SAlex Vesker 	if (spec->cvlan_tag) {
152026d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, tag, first_vlan_qualifier, DR_STE_CVLAN);
152126d688e3SAlex Vesker 		spec->cvlan_tag = 0;
152226d688e3SAlex Vesker 	} else if (spec->svlan_tag) {
152326d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, tag, first_vlan_qualifier, DR_STE_SVLAN);
152426d688e3SAlex Vesker 		spec->svlan_tag = 0;
152526d688e3SAlex Vesker 	}
152626d688e3SAlex Vesker 
152726d688e3SAlex Vesker 	if (spec->ip_version) {
152826d688e3SAlex Vesker 		if (spec->ip_version == IP_VERSION_IPV4) {
152926d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_tnl, tag, l3_type, STE_IPV4);
153026d688e3SAlex Vesker 			spec->ip_version = 0;
153126d688e3SAlex Vesker 		} else if (spec->ip_version == IP_VERSION_IPV6) {
153226d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_tnl, tag, l3_type, STE_IPV6);
153326d688e3SAlex Vesker 			spec->ip_version = 0;
153426d688e3SAlex Vesker 		} else {
153526d688e3SAlex Vesker 			return -EINVAL;
153626d688e3SAlex Vesker 		}
153726d688e3SAlex Vesker 	}
153826d688e3SAlex Vesker 
153926d688e3SAlex Vesker 	return 0;
154026d688e3SAlex Vesker }
154126d688e3SAlex Vesker 
154226d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_tnl(struct mlx5dr_ste_build *sb,
154326d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask, bool inner, bool rx)
154426d688e3SAlex Vesker {
154526d688e3SAlex Vesker 	dr_ste_build_eth_l2_tnl_bit_mask(mask, inner, sb->bit_mask);
154626d688e3SAlex Vesker 
154726d688e3SAlex Vesker 	sb->rx = rx;
154826d688e3SAlex Vesker 	sb->inner = inner;
154926d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_ETHL2_TUNNELING_I;
155026d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
155126d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_tnl_tag;
155226d688e3SAlex Vesker }
155326d688e3SAlex Vesker 
155426d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv4_misc_bit_mask(struct mlx5dr_match_param *value,
155526d688e3SAlex Vesker 						   bool inner, u8 *bit_mask)
155626d688e3SAlex Vesker {
155726d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
155826d688e3SAlex Vesker 
155926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_misc, bit_mask, time_to_live, mask, ttl_hoplimit);
156026d688e3SAlex Vesker }
156126d688e3SAlex Vesker 
156226d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv4_misc_tag(struct mlx5dr_match_param *value,
156326d688e3SAlex Vesker 					     struct mlx5dr_ste_build *sb,
156426d688e3SAlex Vesker 					     u8 *hw_ste_p)
156526d688e3SAlex Vesker {
156626d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
156726d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
156826d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
156926d688e3SAlex Vesker 
157026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_misc, tag, time_to_live, spec, ttl_hoplimit);
157126d688e3SAlex Vesker 
157226d688e3SAlex Vesker 	return 0;
157326d688e3SAlex Vesker }
157426d688e3SAlex Vesker 
157526d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv4_misc(struct mlx5dr_ste_build *sb,
157626d688e3SAlex Vesker 				       struct mlx5dr_match_param *mask,
157726d688e3SAlex Vesker 				       bool inner, bool rx)
157826d688e3SAlex Vesker {
157926d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv4_misc_bit_mask(mask, inner, sb->bit_mask);
158026d688e3SAlex Vesker 
158126d688e3SAlex Vesker 	sb->rx = rx;
158226d688e3SAlex Vesker 	sb->inner = inner;
158326d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV4_MISC, rx, inner);
158426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
158526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv4_misc_tag;
158626d688e3SAlex Vesker }
158726d688e3SAlex Vesker 
158826d688e3SAlex Vesker static void dr_ste_build_ipv6_l3_l4_bit_mask(struct mlx5dr_match_param *value,
158926d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
159026d688e3SAlex Vesker {
159126d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
159226d688e3SAlex Vesker 
159326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, dst_port, mask, tcp_dport);
159426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, src_port, mask, tcp_sport);
159526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, dst_port, mask, udp_dport);
159626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, src_port, mask, udp_sport);
159726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, protocol, mask, ip_protocol);
159826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, fragmented, mask, frag);
159926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, dscp, mask, ip_dscp);
160026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, ecn, mask, ip_ecn);
160126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, ipv6_hop_limit, mask, ttl_hoplimit);
160226d688e3SAlex Vesker 
160326d688e3SAlex Vesker 	if (mask->tcp_flags) {
160426d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l4, bit_mask, mask);
160526d688e3SAlex Vesker 		mask->tcp_flags = 0;
160626d688e3SAlex Vesker 	}
160726d688e3SAlex Vesker }
160826d688e3SAlex Vesker 
160926d688e3SAlex Vesker static int dr_ste_build_ipv6_l3_l4_tag(struct mlx5dr_match_param *value,
161026d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
161126d688e3SAlex Vesker 				       u8 *hw_ste_p)
161226d688e3SAlex Vesker {
161326d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
161426d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
161526d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
161626d688e3SAlex Vesker 
161726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, dst_port, spec, tcp_dport);
161826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, src_port, spec, tcp_sport);
161926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, dst_port, spec, udp_dport);
162026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, src_port, spec, udp_sport);
162126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, protocol, spec, ip_protocol);
162226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, fragmented, spec, frag);
162326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, dscp, spec, ip_dscp);
162426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, ecn, spec, ip_ecn);
162526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, ipv6_hop_limit, spec, ttl_hoplimit);
162626d688e3SAlex Vesker 
162726d688e3SAlex Vesker 	if (spec->tcp_flags) {
162826d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l4, tag, spec);
162926d688e3SAlex Vesker 		spec->tcp_flags = 0;
163026d688e3SAlex Vesker 	}
163126d688e3SAlex Vesker 
163226d688e3SAlex Vesker 	return 0;
163326d688e3SAlex Vesker }
163426d688e3SAlex Vesker 
163526d688e3SAlex Vesker void mlx5dr_ste_build_ipv6_l3_l4(struct mlx5dr_ste_build *sb,
163626d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
163726d688e3SAlex Vesker 				 bool inner, bool rx)
163826d688e3SAlex Vesker {
163926d688e3SAlex Vesker 	dr_ste_build_ipv6_l3_l4_bit_mask(mask, inner, sb->bit_mask);
164026d688e3SAlex Vesker 
164126d688e3SAlex Vesker 	sb->rx = rx;
164226d688e3SAlex Vesker 	sb->inner = inner;
164326d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL4, rx, inner);
164426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
164526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_ipv6_l3_l4_tag;
164626d688e3SAlex Vesker }
164726d688e3SAlex Vesker 
164826d688e3SAlex Vesker static int dr_ste_build_empty_always_hit_tag(struct mlx5dr_match_param *value,
164926d688e3SAlex Vesker 					     struct mlx5dr_ste_build *sb,
165026d688e3SAlex Vesker 					     u8 *hw_ste_p)
165126d688e3SAlex Vesker {
165226d688e3SAlex Vesker 	return 0;
165326d688e3SAlex Vesker }
165426d688e3SAlex Vesker 
165526d688e3SAlex Vesker void mlx5dr_ste_build_empty_always_hit(struct mlx5dr_ste_build *sb, bool rx)
165626d688e3SAlex Vesker {
165726d688e3SAlex Vesker 	sb->rx = rx;
165826d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_DONT_CARE;
165926d688e3SAlex Vesker 	sb->byte_mask = 0;
166026d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_empty_always_hit_tag;
166126d688e3SAlex Vesker }
166226d688e3SAlex Vesker 
166326d688e3SAlex Vesker static void dr_ste_build_mpls_bit_mask(struct mlx5dr_match_param *value,
166426d688e3SAlex Vesker 				       bool inner, u8 *bit_mask)
166526d688e3SAlex Vesker {
166626d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2_mask = &value->misc2;
166726d688e3SAlex Vesker 
166826d688e3SAlex Vesker 	if (inner)
166926d688e3SAlex Vesker 		DR_STE_SET_MPLS_MASK(mpls, misc2_mask, inner, bit_mask);
167026d688e3SAlex Vesker 	else
167126d688e3SAlex Vesker 		DR_STE_SET_MPLS_MASK(mpls, misc2_mask, outer, bit_mask);
167226d688e3SAlex Vesker }
167326d688e3SAlex Vesker 
167426d688e3SAlex Vesker static int dr_ste_build_mpls_tag(struct mlx5dr_match_param *value,
167526d688e3SAlex Vesker 				 struct mlx5dr_ste_build *sb,
167626d688e3SAlex Vesker 				 u8 *hw_ste_p)
167726d688e3SAlex Vesker {
167826d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
167926d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2_mask = &value->misc2;
168026d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
168126d688e3SAlex Vesker 
168226d688e3SAlex Vesker 	if (sb->inner)
168326d688e3SAlex Vesker 		DR_STE_SET_MPLS_TAG(mpls, misc2_mask, inner, tag);
168426d688e3SAlex Vesker 	else
168526d688e3SAlex Vesker 		DR_STE_SET_MPLS_TAG(mpls, misc2_mask, outer, tag);
168626d688e3SAlex Vesker 
168726d688e3SAlex Vesker 	return 0;
168826d688e3SAlex Vesker }
168926d688e3SAlex Vesker 
169026d688e3SAlex Vesker void mlx5dr_ste_build_mpls(struct mlx5dr_ste_build *sb,
169126d688e3SAlex Vesker 			   struct mlx5dr_match_param *mask,
169226d688e3SAlex Vesker 			   bool inner, bool rx)
169326d688e3SAlex Vesker {
169426d688e3SAlex Vesker 	dr_ste_build_mpls_bit_mask(mask, inner, sb->bit_mask);
169526d688e3SAlex Vesker 
169626d688e3SAlex Vesker 	sb->rx = rx;
169726d688e3SAlex Vesker 	sb->inner = inner;
169826d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(MPLS_FIRST, rx, inner);
169926d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
170026d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_mpls_tag;
170126d688e3SAlex Vesker }
170226d688e3SAlex Vesker 
170326d688e3SAlex Vesker static void dr_ste_build_gre_bit_mask(struct mlx5dr_match_param *value,
170426d688e3SAlex Vesker 				      bool inner, u8 *bit_mask)
170526d688e3SAlex Vesker {
170626d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_mask = &value->misc;
170726d688e3SAlex Vesker 
170826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_protocol, misc_mask, gre_protocol);
170926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_k_present, misc_mask, gre_k_present);
171026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_key_h, misc_mask, gre_key_h);
171126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_key_l, misc_mask, gre_key_l);
171226d688e3SAlex Vesker 
171326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_c_present, misc_mask, gre_c_present);
171426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_s_present, misc_mask, gre_s_present);
171526d688e3SAlex Vesker }
171626d688e3SAlex Vesker 
171726d688e3SAlex Vesker static int dr_ste_build_gre_tag(struct mlx5dr_match_param *value,
171826d688e3SAlex Vesker 				struct mlx5dr_ste_build *sb,
171926d688e3SAlex Vesker 				u8 *hw_ste_p)
172026d688e3SAlex Vesker {
172126d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
172226d688e3SAlex Vesker 	struct  mlx5dr_match_misc *misc = &value->misc;
172326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
172426d688e3SAlex Vesker 
172526d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_protocol, misc, gre_protocol);
172626d688e3SAlex Vesker 
172726d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_k_present, misc, gre_k_present);
172826d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_key_h, misc, gre_key_h);
172926d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_key_l, misc, gre_key_l);
173026d688e3SAlex Vesker 
173126d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_c_present, misc, gre_c_present);
173226d688e3SAlex Vesker 
173326d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_s_present, misc, gre_s_present);
173426d688e3SAlex Vesker 
173526d688e3SAlex Vesker 	return 0;
173626d688e3SAlex Vesker }
173726d688e3SAlex Vesker 
173826d688e3SAlex Vesker void mlx5dr_ste_build_gre(struct mlx5dr_ste_build *sb,
173926d688e3SAlex Vesker 			  struct mlx5dr_match_param *mask, bool inner, bool rx)
174026d688e3SAlex Vesker {
174126d688e3SAlex Vesker 	dr_ste_build_gre_bit_mask(mask, inner, sb->bit_mask);
174226d688e3SAlex Vesker 
174326d688e3SAlex Vesker 	sb->rx = rx;
174426d688e3SAlex Vesker 	sb->inner = inner;
174526d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_GRE;
174626d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
174726d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_gre_tag;
174826d688e3SAlex Vesker }
174926d688e3SAlex Vesker 
175026d688e3SAlex Vesker static void dr_ste_build_flex_parser_0_bit_mask(struct mlx5dr_match_param *value,
175126d688e3SAlex Vesker 						bool inner, u8 *bit_mask)
175226d688e3SAlex Vesker {
175326d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
175426d688e3SAlex Vesker 
175526d688e3SAlex Vesker 	if (DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(misc_2_mask)) {
175626d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_label,
175726d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_label);
175826d688e3SAlex Vesker 
175926d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_exp,
176026d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_exp);
176126d688e3SAlex Vesker 
176226d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_s_bos,
176326d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_s_bos);
176426d688e3SAlex Vesker 
176526d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_ttl,
176626d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_ttl);
176726d688e3SAlex Vesker 	} else {
176826d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_label,
176926d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_label);
177026d688e3SAlex Vesker 
177126d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_exp,
177226d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_exp);
177326d688e3SAlex Vesker 
177426d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_s_bos,
177526d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_s_bos);
177626d688e3SAlex Vesker 
177726d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_ttl,
177826d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_ttl);
177926d688e3SAlex Vesker 	}
178026d688e3SAlex Vesker }
178126d688e3SAlex Vesker 
178226d688e3SAlex Vesker static int dr_ste_build_flex_parser_0_tag(struct mlx5dr_match_param *value,
178326d688e3SAlex Vesker 					  struct mlx5dr_ste_build *sb,
178426d688e3SAlex Vesker 					  u8 *hw_ste_p)
178526d688e3SAlex Vesker {
178626d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
178726d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
178826d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
178926d688e3SAlex Vesker 
179026d688e3SAlex Vesker 	if (DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(misc_2_mask)) {
179126d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_label,
179226d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_label);
179326d688e3SAlex Vesker 
179426d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_exp,
179526d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_exp);
179626d688e3SAlex Vesker 
179726d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_s_bos,
179826d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_s_bos);
179926d688e3SAlex Vesker 
180026d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_ttl,
180126d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_ttl);
180226d688e3SAlex Vesker 	} else {
180326d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_label,
180426d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_label);
180526d688e3SAlex Vesker 
180626d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_exp,
180726d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_exp);
180826d688e3SAlex Vesker 
180926d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_s_bos,
181026d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_s_bos);
181126d688e3SAlex Vesker 
181226d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_ttl,
181326d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_ttl);
181426d688e3SAlex Vesker 	}
181526d688e3SAlex Vesker 	return 0;
181626d688e3SAlex Vesker }
181726d688e3SAlex Vesker 
181826d688e3SAlex Vesker void mlx5dr_ste_build_flex_parser_0(struct mlx5dr_ste_build *sb,
181926d688e3SAlex Vesker 				    struct mlx5dr_match_param *mask,
182026d688e3SAlex Vesker 				    bool inner, bool rx)
182126d688e3SAlex Vesker {
182226d688e3SAlex Vesker 	dr_ste_build_flex_parser_0_bit_mask(mask, inner, sb->bit_mask);
182326d688e3SAlex Vesker 
182426d688e3SAlex Vesker 	sb->rx = rx;
182526d688e3SAlex Vesker 	sb->inner = inner;
182626d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_0;
182726d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
182826d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_0_tag;
182926d688e3SAlex Vesker }
183026d688e3SAlex Vesker 
183126d688e3SAlex Vesker #define ICMP_TYPE_OFFSET_FIRST_DW		24
183226d688e3SAlex Vesker #define ICMP_CODE_OFFSET_FIRST_DW		16
183326d688e3SAlex Vesker #define ICMP_HEADER_DATA_OFFSET_SECOND_DW	0
183426d688e3SAlex Vesker 
183526d688e3SAlex Vesker static int dr_ste_build_flex_parser_1_bit_mask(struct mlx5dr_match_param *mask,
183626d688e3SAlex Vesker 					       struct mlx5dr_cmd_caps *caps,
183726d688e3SAlex Vesker 					       u8 *bit_mask)
183826d688e3SAlex Vesker {
183926d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3_mask = &mask->misc3;
184026d688e3SAlex Vesker 	bool is_ipv4_mask = DR_MASK_IS_FLEX_PARSER_ICMPV4_SET(misc_3_mask);
184126d688e3SAlex Vesker 	u32 icmp_header_data_mask;
184226d688e3SAlex Vesker 	u32 icmp_type_mask;
184326d688e3SAlex Vesker 	u32 icmp_code_mask;
184426d688e3SAlex Vesker 	int dw0_location;
184526d688e3SAlex Vesker 	int dw1_location;
184626d688e3SAlex Vesker 
184726d688e3SAlex Vesker 	if (is_ipv4_mask) {
184826d688e3SAlex Vesker 		icmp_header_data_mask	= misc_3_mask->icmpv4_header_data;
184926d688e3SAlex Vesker 		icmp_type_mask		= misc_3_mask->icmpv4_type;
185026d688e3SAlex Vesker 		icmp_code_mask		= misc_3_mask->icmpv4_code;
185126d688e3SAlex Vesker 		dw0_location		= caps->flex_parser_id_icmp_dw0;
185226d688e3SAlex Vesker 		dw1_location		= caps->flex_parser_id_icmp_dw1;
185326d688e3SAlex Vesker 	} else {
185426d688e3SAlex Vesker 		icmp_header_data_mask	= misc_3_mask->icmpv6_header_data;
185526d688e3SAlex Vesker 		icmp_type_mask		= misc_3_mask->icmpv6_type;
185626d688e3SAlex Vesker 		icmp_code_mask		= misc_3_mask->icmpv6_code;
185726d688e3SAlex Vesker 		dw0_location		= caps->flex_parser_id_icmpv6_dw0;
185826d688e3SAlex Vesker 		dw1_location		= caps->flex_parser_id_icmpv6_dw1;
185926d688e3SAlex Vesker 	}
186026d688e3SAlex Vesker 
186126d688e3SAlex Vesker 	switch (dw0_location) {
186226d688e3SAlex Vesker 	case 4:
186326d688e3SAlex Vesker 		if (icmp_type_mask) {
186426d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_4,
186526d688e3SAlex Vesker 				 (icmp_type_mask << ICMP_TYPE_OFFSET_FIRST_DW));
186626d688e3SAlex Vesker 			if (is_ipv4_mask)
186726d688e3SAlex Vesker 				misc_3_mask->icmpv4_type = 0;
186826d688e3SAlex Vesker 			else
186926d688e3SAlex Vesker 				misc_3_mask->icmpv6_type = 0;
187026d688e3SAlex Vesker 		}
187126d688e3SAlex Vesker 		if (icmp_code_mask) {
187226d688e3SAlex Vesker 			u32 cur_val = MLX5_GET(ste_flex_parser_1, bit_mask,
187326d688e3SAlex Vesker 					       flex_parser_4);
187426d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_4,
187526d688e3SAlex Vesker 				 cur_val | (icmp_code_mask << ICMP_CODE_OFFSET_FIRST_DW));
187626d688e3SAlex Vesker 			if (is_ipv4_mask)
187726d688e3SAlex Vesker 				misc_3_mask->icmpv4_code = 0;
187826d688e3SAlex Vesker 			else
187926d688e3SAlex Vesker 				misc_3_mask->icmpv6_code = 0;
188026d688e3SAlex Vesker 		}
188126d688e3SAlex Vesker 		break;
188226d688e3SAlex Vesker 	default:
188326d688e3SAlex Vesker 		return -EINVAL;
188426d688e3SAlex Vesker 	}
188526d688e3SAlex Vesker 
188626d688e3SAlex Vesker 	switch (dw1_location) {
188726d688e3SAlex Vesker 	case 5:
188826d688e3SAlex Vesker 		if (icmp_header_data_mask) {
188926d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_5,
189026d688e3SAlex Vesker 				 (icmp_header_data_mask << ICMP_HEADER_DATA_OFFSET_SECOND_DW));
189126d688e3SAlex Vesker 			if (is_ipv4_mask)
189226d688e3SAlex Vesker 				misc_3_mask->icmpv4_header_data = 0;
189326d688e3SAlex Vesker 			else
189426d688e3SAlex Vesker 				misc_3_mask->icmpv6_header_data = 0;
189526d688e3SAlex Vesker 		}
189626d688e3SAlex Vesker 		break;
189726d688e3SAlex Vesker 	default:
189826d688e3SAlex Vesker 		return -EINVAL;
189926d688e3SAlex Vesker 	}
190026d688e3SAlex Vesker 
190126d688e3SAlex Vesker 	return 0;
190226d688e3SAlex Vesker }
190326d688e3SAlex Vesker 
190426d688e3SAlex Vesker static int dr_ste_build_flex_parser_1_tag(struct mlx5dr_match_param *value,
190526d688e3SAlex Vesker 					  struct mlx5dr_ste_build *sb,
190626d688e3SAlex Vesker 					  u8 *hw_ste_p)
190726d688e3SAlex Vesker {
190826d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
190926d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3 = &value->misc3;
191026d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
191126d688e3SAlex Vesker 	u32 icmp_header_data;
191226d688e3SAlex Vesker 	int dw0_location;
191326d688e3SAlex Vesker 	int dw1_location;
191426d688e3SAlex Vesker 	u32 icmp_type;
191526d688e3SAlex Vesker 	u32 icmp_code;
191626d688e3SAlex Vesker 	bool is_ipv4;
191726d688e3SAlex Vesker 
191826d688e3SAlex Vesker 	is_ipv4 = DR_MASK_IS_FLEX_PARSER_ICMPV4_SET(misc_3);
191926d688e3SAlex Vesker 	if (is_ipv4) {
192026d688e3SAlex Vesker 		icmp_header_data	= misc_3->icmpv4_header_data;
192126d688e3SAlex Vesker 		icmp_type		= misc_3->icmpv4_type;
192226d688e3SAlex Vesker 		icmp_code		= misc_3->icmpv4_code;
192326d688e3SAlex Vesker 		dw0_location		= sb->caps->flex_parser_id_icmp_dw0;
192426d688e3SAlex Vesker 		dw1_location		= sb->caps->flex_parser_id_icmp_dw1;
192526d688e3SAlex Vesker 	} else {
192626d688e3SAlex Vesker 		icmp_header_data	= misc_3->icmpv6_header_data;
192726d688e3SAlex Vesker 		icmp_type		= misc_3->icmpv6_type;
192826d688e3SAlex Vesker 		icmp_code		= misc_3->icmpv6_code;
192926d688e3SAlex Vesker 		dw0_location		= sb->caps->flex_parser_id_icmpv6_dw0;
193026d688e3SAlex Vesker 		dw1_location		= sb->caps->flex_parser_id_icmpv6_dw1;
193126d688e3SAlex Vesker 	}
193226d688e3SAlex Vesker 
193326d688e3SAlex Vesker 	switch (dw0_location) {
193426d688e3SAlex Vesker 	case 4:
193526d688e3SAlex Vesker 		if (icmp_type) {
193626d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, tag, flex_parser_4,
193726d688e3SAlex Vesker 				 (icmp_type << ICMP_TYPE_OFFSET_FIRST_DW));
193826d688e3SAlex Vesker 			if (is_ipv4)
193926d688e3SAlex Vesker 				misc_3->icmpv4_type = 0;
194026d688e3SAlex Vesker 			else
194126d688e3SAlex Vesker 				misc_3->icmpv6_type = 0;
194226d688e3SAlex Vesker 		}
194326d688e3SAlex Vesker 
194426d688e3SAlex Vesker 		if (icmp_code) {
194526d688e3SAlex Vesker 			u32 cur_val = MLX5_GET(ste_flex_parser_1, tag,
194626d688e3SAlex Vesker 					       flex_parser_4);
194726d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, tag, flex_parser_4,
194826d688e3SAlex Vesker 				 cur_val | (icmp_code << ICMP_CODE_OFFSET_FIRST_DW));
194926d688e3SAlex Vesker 			if (is_ipv4)
195026d688e3SAlex Vesker 				misc_3->icmpv4_code = 0;
195126d688e3SAlex Vesker 			else
195226d688e3SAlex Vesker 				misc_3->icmpv6_code = 0;
195326d688e3SAlex Vesker 		}
195426d688e3SAlex Vesker 		break;
195526d688e3SAlex Vesker 	default:
195626d688e3SAlex Vesker 		return -EINVAL;
195726d688e3SAlex Vesker 	}
195826d688e3SAlex Vesker 
195926d688e3SAlex Vesker 	switch (dw1_location) {
196026d688e3SAlex Vesker 	case 5:
196126d688e3SAlex Vesker 		if (icmp_header_data) {
196226d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, tag, flex_parser_5,
196326d688e3SAlex Vesker 				 (icmp_header_data << ICMP_HEADER_DATA_OFFSET_SECOND_DW));
196426d688e3SAlex Vesker 			if (is_ipv4)
196526d688e3SAlex Vesker 				misc_3->icmpv4_header_data = 0;
196626d688e3SAlex Vesker 			else
196726d688e3SAlex Vesker 				misc_3->icmpv6_header_data = 0;
196826d688e3SAlex Vesker 		}
196926d688e3SAlex Vesker 		break;
197026d688e3SAlex Vesker 	default:
197126d688e3SAlex Vesker 		return -EINVAL;
197226d688e3SAlex Vesker 	}
197326d688e3SAlex Vesker 
197426d688e3SAlex Vesker 	return 0;
197526d688e3SAlex Vesker }
197626d688e3SAlex Vesker 
197726d688e3SAlex Vesker int mlx5dr_ste_build_flex_parser_1(struct mlx5dr_ste_build *sb,
197826d688e3SAlex Vesker 				   struct mlx5dr_match_param *mask,
197926d688e3SAlex Vesker 				   struct mlx5dr_cmd_caps *caps,
198026d688e3SAlex Vesker 				   bool inner, bool rx)
198126d688e3SAlex Vesker {
198226d688e3SAlex Vesker 	int ret;
198326d688e3SAlex Vesker 
198426d688e3SAlex Vesker 	ret = dr_ste_build_flex_parser_1_bit_mask(mask, caps, sb->bit_mask);
198526d688e3SAlex Vesker 	if (ret)
198626d688e3SAlex Vesker 		return ret;
198726d688e3SAlex Vesker 
198826d688e3SAlex Vesker 	sb->rx = rx;
198926d688e3SAlex Vesker 	sb->inner = inner;
199026d688e3SAlex Vesker 	sb->caps = caps;
199126d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_1;
199226d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
199326d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_1_tag;
199426d688e3SAlex Vesker 
199526d688e3SAlex Vesker 	return 0;
199626d688e3SAlex Vesker }
199726d688e3SAlex Vesker 
199826d688e3SAlex Vesker static void dr_ste_build_general_purpose_bit_mask(struct mlx5dr_match_param *value,
199926d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
200026d688e3SAlex Vesker {
200126d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
200226d688e3SAlex Vesker 
200326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(general_purpose, bit_mask,
200426d688e3SAlex Vesker 			  general_purpose_lookup_field, misc_2_mask,
200526d688e3SAlex Vesker 			  metadata_reg_a);
200626d688e3SAlex Vesker }
200726d688e3SAlex Vesker 
200826d688e3SAlex Vesker static int dr_ste_build_general_purpose_tag(struct mlx5dr_match_param *value,
200926d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
201026d688e3SAlex Vesker 					    u8 *hw_ste_p)
201126d688e3SAlex Vesker {
201226d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
201326d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
201426d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
201526d688e3SAlex Vesker 
201626d688e3SAlex Vesker 	DR_STE_SET_TAG(general_purpose, tag, general_purpose_lookup_field,
201726d688e3SAlex Vesker 		       misc_2_mask, metadata_reg_a);
201826d688e3SAlex Vesker 
201926d688e3SAlex Vesker 	return 0;
202026d688e3SAlex Vesker }
202126d688e3SAlex Vesker 
202226d688e3SAlex Vesker void mlx5dr_ste_build_general_purpose(struct mlx5dr_ste_build *sb,
202326d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
202426d688e3SAlex Vesker 				      bool inner, bool rx)
202526d688e3SAlex Vesker {
202626d688e3SAlex Vesker 	dr_ste_build_general_purpose_bit_mask(mask, inner, sb->bit_mask);
202726d688e3SAlex Vesker 
202826d688e3SAlex Vesker 	sb->rx = rx;
202926d688e3SAlex Vesker 	sb->inner = inner;
203026d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_GENERAL_PURPOSE;
203126d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
203226d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_general_purpose_tag;
203326d688e3SAlex Vesker }
203426d688e3SAlex Vesker 
203526d688e3SAlex Vesker static void dr_ste_build_eth_l4_misc_bit_mask(struct mlx5dr_match_param *value,
203626d688e3SAlex Vesker 					      bool inner, u8 *bit_mask)
203726d688e3SAlex Vesker {
203826d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3_mask = &value->misc3;
203926d688e3SAlex Vesker 
204026d688e3SAlex Vesker 	if (inner) {
204126d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, seq_num, misc_3_mask,
204226d688e3SAlex Vesker 				  inner_tcp_seq_num);
204326d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, ack_num, misc_3_mask,
204426d688e3SAlex Vesker 				  inner_tcp_ack_num);
204526d688e3SAlex Vesker 	} else {
204626d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, seq_num, misc_3_mask,
204726d688e3SAlex Vesker 				  outer_tcp_seq_num);
204826d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, ack_num, misc_3_mask,
204926d688e3SAlex Vesker 				  outer_tcp_ack_num);
205026d688e3SAlex Vesker 	}
205126d688e3SAlex Vesker }
205226d688e3SAlex Vesker 
205326d688e3SAlex Vesker static int dr_ste_build_eth_l4_misc_tag(struct mlx5dr_match_param *value,
205426d688e3SAlex Vesker 					struct mlx5dr_ste_build *sb,
205526d688e3SAlex Vesker 					u8 *hw_ste_p)
205626d688e3SAlex Vesker {
205726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
205826d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc3 = &value->misc3;
205926d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
206026d688e3SAlex Vesker 
206126d688e3SAlex Vesker 	if (sb->inner) {
206226d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, seq_num, misc3, inner_tcp_seq_num);
206326d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, ack_num, misc3, inner_tcp_ack_num);
206426d688e3SAlex Vesker 	} else {
206526d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, seq_num, misc3, outer_tcp_seq_num);
206626d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, ack_num, misc3, outer_tcp_ack_num);
206726d688e3SAlex Vesker 	}
206826d688e3SAlex Vesker 
206926d688e3SAlex Vesker 	return 0;
207026d688e3SAlex Vesker }
207126d688e3SAlex Vesker 
207226d688e3SAlex Vesker void mlx5dr_ste_build_eth_l4_misc(struct mlx5dr_ste_build *sb,
207326d688e3SAlex Vesker 				  struct mlx5dr_match_param *mask,
207426d688e3SAlex Vesker 				  bool inner, bool rx)
207526d688e3SAlex Vesker {
207626d688e3SAlex Vesker 	dr_ste_build_eth_l4_misc_bit_mask(mask, inner, sb->bit_mask);
207726d688e3SAlex Vesker 
207826d688e3SAlex Vesker 	sb->rx = rx;
207926d688e3SAlex Vesker 	sb->inner = inner;
208026d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL4_MISC, rx, inner);
208126d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
208226d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l4_misc_tag;
208326d688e3SAlex Vesker }
208426d688e3SAlex Vesker 
20856e9e286eSYevgeny Kliteynik static void
20866e9e286eSYevgeny Kliteynik dr_ste_build_flex_parser_tnl_vxlan_gpe_bit_mask(struct mlx5dr_match_param *value,
208726d688e3SAlex Vesker 						bool inner, u8 *bit_mask)
208826d688e3SAlex Vesker {
208926d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3_mask = &value->misc3;
209026d688e3SAlex Vesker 
20916e9e286eSYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_vxlan_gpe, bit_mask,
20926e9e286eSYevgeny Kliteynik 			  outer_vxlan_gpe_flags,
20936e9e286eSYevgeny Kliteynik 			  misc_3_mask, outer_vxlan_gpe_flags);
20946e9e286eSYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_vxlan_gpe, bit_mask,
20956e9e286eSYevgeny Kliteynik 			  outer_vxlan_gpe_next_protocol,
20966e9e286eSYevgeny Kliteynik 			  misc_3_mask, outer_vxlan_gpe_next_protocol);
20976e9e286eSYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_vxlan_gpe, bit_mask,
20986e9e286eSYevgeny Kliteynik 			  outer_vxlan_gpe_vni,
20996e9e286eSYevgeny Kliteynik 			  misc_3_mask, outer_vxlan_gpe_vni);
210026d688e3SAlex Vesker }
210126d688e3SAlex Vesker 
21026e9e286eSYevgeny Kliteynik static int
21036e9e286eSYevgeny Kliteynik dr_ste_build_flex_parser_tnl_vxlan_gpe_tag(struct mlx5dr_match_param *value,
210426d688e3SAlex Vesker 					   struct mlx5dr_ste_build *sb,
210526d688e3SAlex Vesker 					   u8 *hw_ste_p)
210626d688e3SAlex Vesker {
210726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
210826d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc3 = &value->misc3;
210926d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
211026d688e3SAlex Vesker 
21116e9e286eSYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_vxlan_gpe, tag,
21126e9e286eSYevgeny Kliteynik 		       outer_vxlan_gpe_flags, misc3,
21136e9e286eSYevgeny Kliteynik 		       outer_vxlan_gpe_flags);
21146e9e286eSYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_vxlan_gpe, tag,
21156e9e286eSYevgeny Kliteynik 		       outer_vxlan_gpe_next_protocol, misc3,
21166e9e286eSYevgeny Kliteynik 		       outer_vxlan_gpe_next_protocol);
21176e9e286eSYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_vxlan_gpe, tag,
21186e9e286eSYevgeny Kliteynik 		       outer_vxlan_gpe_vni, misc3,
21196e9e286eSYevgeny Kliteynik 		       outer_vxlan_gpe_vni);
212026d688e3SAlex Vesker 
212126d688e3SAlex Vesker 	return 0;
212226d688e3SAlex Vesker }
212326d688e3SAlex Vesker 
21246e9e286eSYevgeny Kliteynik void mlx5dr_ste_build_flex_parser_tnl_vxlan_gpe(struct mlx5dr_ste_build *sb,
212526d688e3SAlex Vesker 						struct mlx5dr_match_param *mask,
212626d688e3SAlex Vesker 						bool inner, bool rx)
212726d688e3SAlex Vesker {
21286e9e286eSYevgeny Kliteynik 	dr_ste_build_flex_parser_tnl_vxlan_gpe_bit_mask(mask, inner,
21296e9e286eSYevgeny Kliteynik 							sb->bit_mask);
213026d688e3SAlex Vesker 
213126d688e3SAlex Vesker 	sb->rx = rx;
213226d688e3SAlex Vesker 	sb->inner = inner;
213326d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_TNL_HEADER;
213426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
21356e9e286eSYevgeny Kliteynik 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_tnl_vxlan_gpe_tag;
213626d688e3SAlex Vesker }
213726d688e3SAlex Vesker 
2138b6d12238SYevgeny Kliteynik static void
2139b6d12238SYevgeny Kliteynik dr_ste_build_flex_parser_tnl_geneve_bit_mask(struct mlx5dr_match_param *value,
2140b6d12238SYevgeny Kliteynik 					     u8 *bit_mask)
2141b6d12238SYevgeny Kliteynik {
2142b6d12238SYevgeny Kliteynik 	struct mlx5dr_match_misc *misc_mask = &value->misc;
2143b6d12238SYevgeny Kliteynik 
2144b6d12238SYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask,
2145b6d12238SYevgeny Kliteynik 			  geneve_protocol_type,
2146b6d12238SYevgeny Kliteynik 			  misc_mask, geneve_protocol_type);
2147b6d12238SYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask,
2148b6d12238SYevgeny Kliteynik 			  geneve_oam,
2149b6d12238SYevgeny Kliteynik 			  misc_mask, geneve_oam);
2150b6d12238SYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask,
2151b6d12238SYevgeny Kliteynik 			  geneve_opt_len,
2152b6d12238SYevgeny Kliteynik 			  misc_mask, geneve_opt_len);
2153b6d12238SYevgeny Kliteynik 	DR_STE_SET_MASK_V(flex_parser_tnl_geneve, bit_mask,
2154b6d12238SYevgeny Kliteynik 			  geneve_vni,
2155b6d12238SYevgeny Kliteynik 			  misc_mask, geneve_vni);
2156b6d12238SYevgeny Kliteynik }
2157b6d12238SYevgeny Kliteynik 
2158b6d12238SYevgeny Kliteynik static int
2159b6d12238SYevgeny Kliteynik dr_ste_build_flex_parser_tnl_geneve_tag(struct mlx5dr_match_param *value,
2160b6d12238SYevgeny Kliteynik 					struct mlx5dr_ste_build *sb,
2161b6d12238SYevgeny Kliteynik 					u8 *hw_ste_p)
2162b6d12238SYevgeny Kliteynik {
2163b6d12238SYevgeny Kliteynik 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
2164b6d12238SYevgeny Kliteynik 	struct mlx5dr_match_misc *misc = &value->misc;
2165b6d12238SYevgeny Kliteynik 	u8 *tag = hw_ste->tag;
2166b6d12238SYevgeny Kliteynik 
2167b6d12238SYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_geneve, tag,
2168b6d12238SYevgeny Kliteynik 		       geneve_protocol_type, misc, geneve_protocol_type);
2169b6d12238SYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_geneve, tag,
2170b6d12238SYevgeny Kliteynik 		       geneve_oam, misc, geneve_oam);
2171b6d12238SYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_geneve, tag,
2172b6d12238SYevgeny Kliteynik 		       geneve_opt_len, misc, geneve_opt_len);
2173b6d12238SYevgeny Kliteynik 	DR_STE_SET_TAG(flex_parser_tnl_geneve, tag,
2174b6d12238SYevgeny Kliteynik 		       geneve_vni, misc, geneve_vni);
2175b6d12238SYevgeny Kliteynik 
2176b6d12238SYevgeny Kliteynik 	return 0;
2177b6d12238SYevgeny Kliteynik }
2178b6d12238SYevgeny Kliteynik 
2179b6d12238SYevgeny Kliteynik void mlx5dr_ste_build_flex_parser_tnl_geneve(struct mlx5dr_ste_build *sb,
2180b6d12238SYevgeny Kliteynik 					     struct mlx5dr_match_param *mask,
2181b6d12238SYevgeny Kliteynik 					     bool inner, bool rx)
2182b6d12238SYevgeny Kliteynik {
2183b6d12238SYevgeny Kliteynik 	dr_ste_build_flex_parser_tnl_geneve_bit_mask(mask, sb->bit_mask);
2184b6d12238SYevgeny Kliteynik 	sb->rx = rx;
2185b6d12238SYevgeny Kliteynik 	sb->inner = inner;
2186b6d12238SYevgeny Kliteynik 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_TNL_HEADER;
2187b6d12238SYevgeny Kliteynik 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
2188b6d12238SYevgeny Kliteynik 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_tnl_geneve_tag;
218926d688e3SAlex Vesker }
219026d688e3SAlex Vesker 
219126d688e3SAlex Vesker static void dr_ste_build_register_0_bit_mask(struct mlx5dr_match_param *value,
219226d688e3SAlex Vesker 					     u8 *bit_mask)
219326d688e3SAlex Vesker {
219426d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
219526d688e3SAlex Vesker 
219626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_0_h,
219726d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_0);
219826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_0_l,
219926d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_1);
220026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_1_h,
220126d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_2);
220226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_1_l,
220326d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_3);
220426d688e3SAlex Vesker }
220526d688e3SAlex Vesker 
220626d688e3SAlex Vesker static int dr_ste_build_register_0_tag(struct mlx5dr_match_param *value,
220726d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
220826d688e3SAlex Vesker 				       u8 *hw_ste_p)
220926d688e3SAlex Vesker {
221026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
221126d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2 = &value->misc2;
221226d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
221326d688e3SAlex Vesker 
221426d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_0_h, misc2, metadata_reg_c_0);
221526d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_0_l, misc2, metadata_reg_c_1);
221626d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_1_h, misc2, metadata_reg_c_2);
221726d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_1_l, misc2, metadata_reg_c_3);
221826d688e3SAlex Vesker 
221926d688e3SAlex Vesker 	return 0;
222026d688e3SAlex Vesker }
222126d688e3SAlex Vesker 
222226d688e3SAlex Vesker void mlx5dr_ste_build_register_0(struct mlx5dr_ste_build *sb,
222326d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
222426d688e3SAlex Vesker 				 bool inner, bool rx)
222526d688e3SAlex Vesker {
222626d688e3SAlex Vesker 	dr_ste_build_register_0_bit_mask(mask, sb->bit_mask);
222726d688e3SAlex Vesker 
222826d688e3SAlex Vesker 	sb->rx = rx;
222926d688e3SAlex Vesker 	sb->inner = inner;
223026d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_STEERING_REGISTERS_0;
223126d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
223226d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_register_0_tag;
223326d688e3SAlex Vesker }
223426d688e3SAlex Vesker 
223526d688e3SAlex Vesker static void dr_ste_build_register_1_bit_mask(struct mlx5dr_match_param *value,
223626d688e3SAlex Vesker 					     u8 *bit_mask)
223726d688e3SAlex Vesker {
223826d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
223926d688e3SAlex Vesker 
224026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_2_h,
224126d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_4);
224226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_2_l,
224326d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_5);
224426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_3_h,
224526d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_6);
224626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_3_l,
224726d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_7);
224826d688e3SAlex Vesker }
224926d688e3SAlex Vesker 
225026d688e3SAlex Vesker static int dr_ste_build_register_1_tag(struct mlx5dr_match_param *value,
225126d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
225226d688e3SAlex Vesker 				       u8 *hw_ste_p)
225326d688e3SAlex Vesker {
225426d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
225526d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2 = &value->misc2;
225626d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
225726d688e3SAlex Vesker 
225826d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_2_h, misc2, metadata_reg_c_4);
225926d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_2_l, misc2, metadata_reg_c_5);
226026d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_3_h, misc2, metadata_reg_c_6);
226126d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_3_l, misc2, metadata_reg_c_7);
226226d688e3SAlex Vesker 
226326d688e3SAlex Vesker 	return 0;
226426d688e3SAlex Vesker }
226526d688e3SAlex Vesker 
226626d688e3SAlex Vesker void mlx5dr_ste_build_register_1(struct mlx5dr_ste_build *sb,
226726d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
226826d688e3SAlex Vesker 				 bool inner, bool rx)
226926d688e3SAlex Vesker {
227026d688e3SAlex Vesker 	dr_ste_build_register_1_bit_mask(mask, sb->bit_mask);
227126d688e3SAlex Vesker 
227226d688e3SAlex Vesker 	sb->rx = rx;
227326d688e3SAlex Vesker 	sb->inner = inner;
227426d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_STEERING_REGISTERS_1;
227526d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
227626d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_register_1_tag;
227726d688e3SAlex Vesker }
227826d688e3SAlex Vesker 
227926d688e3SAlex Vesker static int dr_ste_build_src_gvmi_qpn_bit_mask(struct mlx5dr_match_param *value,
228026d688e3SAlex Vesker 					      u8 *bit_mask)
228126d688e3SAlex Vesker {
228226d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_mask = &value->misc;
228326d688e3SAlex Vesker 
2284640bdb1fSAlaa Hleihel 	/* Partial misc source_port is not supported */
2285640bdb1fSAlaa Hleihel 	if (misc_mask->source_port && misc_mask->source_port != 0xffff)
2286640bdb1fSAlaa Hleihel 		return -EINVAL;
2287640bdb1fSAlaa Hleihel 
2288640bdb1fSAlaa Hleihel 	/* Partial misc source_eswitch_owner_vhca_id is not supported */
2289640bdb1fSAlaa Hleihel 	if (misc_mask->source_eswitch_owner_vhca_id &&
2290640bdb1fSAlaa Hleihel 	    misc_mask->source_eswitch_owner_vhca_id != 0xffff)
229126d688e3SAlex Vesker 		return -EINVAL;
229226d688e3SAlex Vesker 
229326d688e3SAlex Vesker 	DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_gvmi, misc_mask, source_port);
229426d688e3SAlex Vesker 	DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_qp, misc_mask, source_sqn);
2295640bdb1fSAlaa Hleihel 	misc_mask->source_eswitch_owner_vhca_id = 0;
229626d688e3SAlex Vesker 
229726d688e3SAlex Vesker 	return 0;
229826d688e3SAlex Vesker }
229926d688e3SAlex Vesker 
230026d688e3SAlex Vesker static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
230126d688e3SAlex Vesker 					 struct mlx5dr_ste_build *sb,
230226d688e3SAlex Vesker 					 u8 *hw_ste_p)
230326d688e3SAlex Vesker {
230426d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
230526d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc = &value->misc;
230626d688e3SAlex Vesker 	struct mlx5dr_cmd_vport_cap *vport_cap;
2307640bdb1fSAlaa Hleihel 	struct mlx5dr_domain *dmn = sb->dmn;
2308640bdb1fSAlaa Hleihel 	struct mlx5dr_cmd_caps *caps;
230952d21497SHamdan Igbaria 	u8 *bit_mask = sb->bit_mask;
231026d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
231152d21497SHamdan Igbaria 	bool source_gvmi_set;
231226d688e3SAlex Vesker 
231326d688e3SAlex Vesker 	DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
231426d688e3SAlex Vesker 
2315640bdb1fSAlaa Hleihel 	if (sb->vhca_id_valid) {
2316640bdb1fSAlaa Hleihel 		/* Find port GVMI based on the eswitch_owner_vhca_id */
2317640bdb1fSAlaa Hleihel 		if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi)
2318640bdb1fSAlaa Hleihel 			caps = &dmn->info.caps;
2319640bdb1fSAlaa Hleihel 		else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id ==
2320640bdb1fSAlaa Hleihel 					   dmn->peer_dmn->info.caps.gvmi))
2321640bdb1fSAlaa Hleihel 			caps = &dmn->peer_dmn->info.caps;
2322640bdb1fSAlaa Hleihel 		else
2323640bdb1fSAlaa Hleihel 			return -EINVAL;
2324640bdb1fSAlaa Hleihel 	} else {
2325640bdb1fSAlaa Hleihel 		caps = &dmn->info.caps;
2326640bdb1fSAlaa Hleihel 	}
2327640bdb1fSAlaa Hleihel 
2328640bdb1fSAlaa Hleihel 	vport_cap = mlx5dr_get_vport_cap(caps, misc->source_port);
232926d688e3SAlex Vesker 	if (!vport_cap)
233026d688e3SAlex Vesker 		return -EINVAL;
233126d688e3SAlex Vesker 
233252d21497SHamdan Igbaria 	source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi);
233352d21497SHamdan Igbaria 	if (vport_cap->vport_gvmi && source_gvmi_set)
233426d688e3SAlex Vesker 		MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi);
233526d688e3SAlex Vesker 
2336640bdb1fSAlaa Hleihel 	misc->source_eswitch_owner_vhca_id = 0;
233726d688e3SAlex Vesker 	misc->source_port = 0;
233826d688e3SAlex Vesker 
233926d688e3SAlex Vesker 	return 0;
234026d688e3SAlex Vesker }
234126d688e3SAlex Vesker 
234226d688e3SAlex Vesker int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb,
234326d688e3SAlex Vesker 				  struct mlx5dr_match_param *mask,
2344640bdb1fSAlaa Hleihel 				  struct mlx5dr_domain *dmn,
234526d688e3SAlex Vesker 				  bool inner, bool rx)
234626d688e3SAlex Vesker {
234726d688e3SAlex Vesker 	int ret;
234826d688e3SAlex Vesker 
2349640bdb1fSAlaa Hleihel 	/* Set vhca_id_valid before we reset source_eswitch_owner_vhca_id */
2350640bdb1fSAlaa Hleihel 	sb->vhca_id_valid = mask->misc.source_eswitch_owner_vhca_id;
2351640bdb1fSAlaa Hleihel 
235226d688e3SAlex Vesker 	ret = dr_ste_build_src_gvmi_qpn_bit_mask(mask, sb->bit_mask);
235326d688e3SAlex Vesker 	if (ret)
235426d688e3SAlex Vesker 		return ret;
235526d688e3SAlex Vesker 
235626d688e3SAlex Vesker 	sb->rx = rx;
2357640bdb1fSAlaa Hleihel 	sb->dmn = dmn;
235826d688e3SAlex Vesker 	sb->inner = inner;
235926d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_SRC_GVMI_AND_QP;
236026d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
236126d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_src_gvmi_qpn_tag;
236226d688e3SAlex Vesker 
236326d688e3SAlex Vesker 	return 0;
236426d688e3SAlex Vesker }
2365