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