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 
43226d688e3SAlex Vesker 	prev_ste = list_entry(mlx5dr_ste_get_miss_list(ste)->prev, struct mlx5dr_ste,
43326d688e3SAlex Vesker 			      miss_list_node);
43426d688e3SAlex Vesker 	if (!prev_ste) {
43526d688e3SAlex Vesker 		WARN_ON(true);
43626d688e3SAlex Vesker 		return;
43726d688e3SAlex Vesker 	}
43826d688e3SAlex Vesker 
43926d688e3SAlex Vesker 	miss_addr = mlx5dr_ste_get_miss_addr(ste->hw_ste);
44026d688e3SAlex Vesker 	mlx5dr_ste_set_miss_addr(prev_ste->hw_ste, miss_addr);
44126d688e3SAlex Vesker 
44226d688e3SAlex Vesker 	mlx5dr_send_fill_and_append_ste_send_info(prev_ste, DR_STE_SIZE_REDUCED, 0,
44326d688e3SAlex Vesker 						  prev_ste->hw_ste, ste_info,
44426d688e3SAlex Vesker 						  send_ste_list, true /* Copy data*/);
44526d688e3SAlex Vesker 
44626d688e3SAlex Vesker 	list_del_init(&ste->miss_list_node);
44726d688e3SAlex Vesker 
44826d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_valid_entries--;
44926d688e3SAlex Vesker 	stats_tbl->ctrl.num_of_collisions--;
45026d688e3SAlex Vesker }
45126d688e3SAlex Vesker 
45226d688e3SAlex Vesker void mlx5dr_ste_free(struct mlx5dr_ste *ste,
45326d688e3SAlex Vesker 		     struct mlx5dr_matcher *matcher,
45426d688e3SAlex Vesker 		     struct mlx5dr_matcher_rx_tx *nic_matcher)
45526d688e3SAlex Vesker {
45626d688e3SAlex Vesker 	struct mlx5dr_ste_send_info *cur_ste_info, *tmp_ste_info;
45726d688e3SAlex Vesker 	struct mlx5dr_domain *dmn = matcher->tbl->dmn;
45826d688e3SAlex Vesker 	struct mlx5dr_ste_send_info ste_info_head;
45926d688e3SAlex Vesker 	struct mlx5dr_ste *next_ste, *first_ste;
46026d688e3SAlex Vesker 	bool put_on_origin_table = true;
46126d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *stats_tbl;
46226d688e3SAlex Vesker 	LIST_HEAD(send_ste_list);
46326d688e3SAlex Vesker 
46426d688e3SAlex Vesker 	first_ste = list_entry(mlx5dr_ste_get_miss_list(ste)->next,
46526d688e3SAlex Vesker 			       struct mlx5dr_ste, miss_list_node);
46626d688e3SAlex Vesker 	stats_tbl = first_ste->htbl;
46726d688e3SAlex Vesker 
46826d688e3SAlex Vesker 	/* Two options:
46926d688e3SAlex Vesker 	 * 1. ste is head:
47026d688e3SAlex Vesker 	 *	a. head ste is the only ste in the miss list
47126d688e3SAlex Vesker 	 *	b. head ste is not the only ste in the miss-list
47226d688e3SAlex Vesker 	 * 2. ste is not head
47326d688e3SAlex Vesker 	 */
47426d688e3SAlex Vesker 	if (first_ste == ste) { /* Ste is the head */
47526d688e3SAlex Vesker 		struct mlx5dr_ste *last_ste;
47626d688e3SAlex Vesker 
47726d688e3SAlex Vesker 		last_ste = list_last_entry(mlx5dr_ste_get_miss_list(ste),
47826d688e3SAlex Vesker 					   struct mlx5dr_ste, miss_list_node);
47926d688e3SAlex Vesker 		if (last_ste == first_ste)
48026d688e3SAlex Vesker 			next_ste = NULL;
48126d688e3SAlex Vesker 		else
48226d688e3SAlex Vesker 			next_ste = list_entry(ste->miss_list_node.next,
48326d688e3SAlex Vesker 					      struct mlx5dr_ste, miss_list_node);
48426d688e3SAlex Vesker 
48526d688e3SAlex Vesker 		if (!next_ste) {
48626d688e3SAlex Vesker 			/* One and only entry in the list */
48726d688e3SAlex Vesker 			dr_ste_remove_head_ste(ste, nic_matcher,
48826d688e3SAlex Vesker 					       &ste_info_head,
48926d688e3SAlex Vesker 					       &send_ste_list,
49026d688e3SAlex Vesker 					       stats_tbl);
49126d688e3SAlex Vesker 		} else {
49226d688e3SAlex Vesker 			/* First but not only entry in the list */
49326d688e3SAlex Vesker 			dr_ste_replace_head_ste(ste, next_ste, &ste_info_head,
49426d688e3SAlex Vesker 						&send_ste_list, stats_tbl);
49526d688e3SAlex Vesker 			put_on_origin_table = false;
49626d688e3SAlex Vesker 		}
49726d688e3SAlex Vesker 	} else { /* Ste in the middle of the list */
49826d688e3SAlex Vesker 		dr_ste_remove_middle_ste(ste, &ste_info_head, &send_ste_list, stats_tbl);
49926d688e3SAlex Vesker 	}
50026d688e3SAlex Vesker 
50126d688e3SAlex Vesker 	/* Update HW */
50226d688e3SAlex Vesker 	list_for_each_entry_safe(cur_ste_info, tmp_ste_info,
50326d688e3SAlex Vesker 				 &send_ste_list, send_list) {
50426d688e3SAlex Vesker 		list_del(&cur_ste_info->send_list);
50526d688e3SAlex Vesker 		mlx5dr_send_postsend_ste(dmn, cur_ste_info->ste,
50626d688e3SAlex Vesker 					 cur_ste_info->data, cur_ste_info->size,
50726d688e3SAlex Vesker 					 cur_ste_info->offset);
50826d688e3SAlex Vesker 	}
50926d688e3SAlex Vesker 
51026d688e3SAlex Vesker 	if (put_on_origin_table)
51126d688e3SAlex Vesker 		mlx5dr_htbl_put(ste->htbl);
51226d688e3SAlex Vesker }
51326d688e3SAlex Vesker 
51426d688e3SAlex Vesker bool mlx5dr_ste_equal_tag(void *src, void *dst)
51526d688e3SAlex Vesker {
51626d688e3SAlex Vesker 	struct dr_hw_ste_format *s_hw_ste = (struct dr_hw_ste_format *)src;
51726d688e3SAlex Vesker 	struct dr_hw_ste_format *d_hw_ste = (struct dr_hw_ste_format *)dst;
51826d688e3SAlex Vesker 
51926d688e3SAlex Vesker 	return !memcmp(s_hw_ste->tag, d_hw_ste->tag, DR_STE_SIZE_TAG);
52026d688e3SAlex Vesker }
52126d688e3SAlex Vesker 
52226d688e3SAlex Vesker void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
52326d688e3SAlex Vesker 					  struct mlx5dr_ste_htbl *next_htbl)
52426d688e3SAlex Vesker {
52526d688e3SAlex Vesker 	struct mlx5dr_icm_chunk *chunk = next_htbl->chunk;
52626d688e3SAlex Vesker 
52726d688e3SAlex Vesker 	mlx5dr_ste_set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries);
52826d688e3SAlex Vesker }
52926d688e3SAlex Vesker 
53026d688e3SAlex Vesker void mlx5dr_ste_set_miss_addr(u8 *hw_ste_p, u64 miss_addr)
53126d688e3SAlex Vesker {
53226d688e3SAlex Vesker 	u64 index = miss_addr >> 6;
53326d688e3SAlex Vesker 
53426d688e3SAlex Vesker 	/* Miss address for TX and RX STEs located in the same offsets */
53526d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_39_32, index >> 26);
53626d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste_p, miss_address_31_6, index);
53726d688e3SAlex Vesker }
53826d688e3SAlex Vesker 
53926d688e3SAlex Vesker void mlx5dr_ste_always_miss_addr(struct mlx5dr_ste *ste, u64 miss_addr)
54026d688e3SAlex Vesker {
54126d688e3SAlex Vesker 	u8 *hw_ste = ste->hw_ste;
54226d688e3SAlex Vesker 
54326d688e3SAlex Vesker 	MLX5_SET(ste_rx_steering_mult, hw_ste, next_lu_type, MLX5DR_STE_LU_TYPE_DONT_CARE);
54426d688e3SAlex Vesker 	mlx5dr_ste_set_miss_addr(hw_ste, miss_addr);
54526d688e3SAlex Vesker 	dr_ste_set_always_miss((struct dr_hw_ste_format *)ste->hw_ste);
54626d688e3SAlex Vesker }
54726d688e3SAlex Vesker 
54826d688e3SAlex Vesker /* The assumption here is that we don't update the ste->hw_ste if it is not
54926d688e3SAlex Vesker  * used ste, so it will be all zero, checking the next_lu_type.
55026d688e3SAlex Vesker  */
55126d688e3SAlex Vesker bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_ste)
55226d688e3SAlex Vesker {
55326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)p_hw_ste;
55426d688e3SAlex Vesker 
55526d688e3SAlex Vesker 	if (MLX5_GET(ste_general, hw_ste, next_lu_type) ==
55626d688e3SAlex Vesker 	    MLX5DR_STE_LU_TYPE_NOP)
55726d688e3SAlex Vesker 		return true;
55826d688e3SAlex Vesker 
55926d688e3SAlex Vesker 	return false;
56026d688e3SAlex Vesker }
56126d688e3SAlex Vesker 
56226d688e3SAlex Vesker bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
56326d688e3SAlex Vesker {
56426d688e3SAlex Vesker 	return !refcount_read(&ste->refcount);
56526d688e3SAlex Vesker }
56626d688e3SAlex Vesker 
56726d688e3SAlex Vesker static u16 get_bits_per_mask(u16 byte_mask)
56826d688e3SAlex Vesker {
56926d688e3SAlex Vesker 	u16 bits = 0;
57026d688e3SAlex Vesker 
57126d688e3SAlex Vesker 	while (byte_mask) {
57226d688e3SAlex Vesker 		byte_mask = byte_mask & (byte_mask - 1);
57326d688e3SAlex Vesker 		bits++;
57426d688e3SAlex Vesker 	}
57526d688e3SAlex Vesker 
57626d688e3SAlex Vesker 	return bits;
57726d688e3SAlex Vesker }
57826d688e3SAlex Vesker 
57926d688e3SAlex Vesker /* Init one ste as a pattern for ste data array */
58026d688e3SAlex Vesker void mlx5dr_ste_set_formatted_ste(u16 gvmi,
58126d688e3SAlex Vesker 				  struct mlx5dr_domain_rx_tx *nic_dmn,
58226d688e3SAlex Vesker 				  struct mlx5dr_ste_htbl *htbl,
58326d688e3SAlex Vesker 				  u8 *formatted_ste,
58426d688e3SAlex Vesker 				  struct mlx5dr_htbl_connect_info *connect_info)
58526d688e3SAlex Vesker {
58626d688e3SAlex Vesker 	struct mlx5dr_ste ste = {};
58726d688e3SAlex Vesker 
58826d688e3SAlex Vesker 	mlx5dr_ste_init(formatted_ste, htbl->lu_type, nic_dmn->ste_type, gvmi);
58926d688e3SAlex Vesker 	ste.hw_ste = formatted_ste;
59026d688e3SAlex Vesker 
59126d688e3SAlex Vesker 	if (connect_info->type == CONNECT_HIT)
59226d688e3SAlex Vesker 		dr_ste_always_hit_htbl(&ste, connect_info->hit_next_htbl);
59326d688e3SAlex Vesker 	else
59426d688e3SAlex Vesker 		mlx5dr_ste_always_miss_addr(&ste, connect_info->miss_icm_addr);
59526d688e3SAlex Vesker }
59626d688e3SAlex Vesker 
59726d688e3SAlex Vesker int mlx5dr_ste_htbl_init_and_postsend(struct mlx5dr_domain *dmn,
59826d688e3SAlex Vesker 				      struct mlx5dr_domain_rx_tx *nic_dmn,
59926d688e3SAlex Vesker 				      struct mlx5dr_ste_htbl *htbl,
60026d688e3SAlex Vesker 				      struct mlx5dr_htbl_connect_info *connect_info,
60126d688e3SAlex Vesker 				      bool update_hw_ste)
60226d688e3SAlex Vesker {
60326d688e3SAlex Vesker 	u8 formatted_ste[DR_STE_SIZE] = {};
60426d688e3SAlex Vesker 
60526d688e3SAlex Vesker 	mlx5dr_ste_set_formatted_ste(dmn->info.caps.gvmi,
60626d688e3SAlex Vesker 				     nic_dmn,
60726d688e3SAlex Vesker 				     htbl,
60826d688e3SAlex Vesker 				     formatted_ste,
60926d688e3SAlex Vesker 				     connect_info);
61026d688e3SAlex Vesker 
61126d688e3SAlex Vesker 	return mlx5dr_send_postsend_formatted_htbl(dmn, htbl, formatted_ste, update_hw_ste);
61226d688e3SAlex Vesker }
61326d688e3SAlex Vesker 
61426d688e3SAlex Vesker int mlx5dr_ste_create_next_htbl(struct mlx5dr_matcher *matcher,
61526d688e3SAlex Vesker 				struct mlx5dr_matcher_rx_tx *nic_matcher,
61626d688e3SAlex Vesker 				struct mlx5dr_ste *ste,
61726d688e3SAlex Vesker 				u8 *cur_hw_ste,
61826d688e3SAlex Vesker 				enum mlx5dr_icm_chunk_size log_table_size)
61926d688e3SAlex Vesker {
62026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)cur_hw_ste;
62126d688e3SAlex Vesker 	struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
62226d688e3SAlex Vesker 	struct mlx5dr_domain *dmn = matcher->tbl->dmn;
62326d688e3SAlex Vesker 	struct mlx5dr_htbl_connect_info info;
62426d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *next_htbl;
62526d688e3SAlex Vesker 
62626d688e3SAlex Vesker 	if (!mlx5dr_ste_is_last_in_rule(nic_matcher, ste->ste_chain_location)) {
62726d688e3SAlex Vesker 		u32 bits_in_mask;
62826d688e3SAlex Vesker 		u8 next_lu_type;
62926d688e3SAlex Vesker 		u16 byte_mask;
63026d688e3SAlex Vesker 
63126d688e3SAlex Vesker 		next_lu_type = MLX5_GET(ste_general, hw_ste, next_lu_type);
63226d688e3SAlex Vesker 		byte_mask = MLX5_GET(ste_general, hw_ste, byte_mask);
63326d688e3SAlex Vesker 
63426d688e3SAlex Vesker 		/* Don't allocate table more than required,
63526d688e3SAlex Vesker 		 * the size of the table defined via the byte_mask, so no need
63626d688e3SAlex Vesker 		 * to allocate more than that.
63726d688e3SAlex Vesker 		 */
63826d688e3SAlex Vesker 		bits_in_mask = get_bits_per_mask(byte_mask) * BITS_PER_BYTE;
63926d688e3SAlex Vesker 		log_table_size = min(log_table_size, bits_in_mask);
64026d688e3SAlex Vesker 
64126d688e3SAlex Vesker 		next_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
64226d688e3SAlex Vesker 						  log_table_size,
64326d688e3SAlex Vesker 						  next_lu_type,
64426d688e3SAlex Vesker 						  byte_mask);
64526d688e3SAlex Vesker 		if (!next_htbl) {
64626d688e3SAlex Vesker 			mlx5dr_dbg(dmn, "Failed allocating table\n");
64726d688e3SAlex Vesker 			return -ENOMEM;
64826d688e3SAlex Vesker 		}
64926d688e3SAlex Vesker 
65026d688e3SAlex Vesker 		/* Write new table to HW */
65126d688e3SAlex Vesker 		info.type = CONNECT_MISS;
65226d688e3SAlex Vesker 		info.miss_icm_addr = nic_matcher->e_anchor->chunk->icm_addr;
65326d688e3SAlex Vesker 		if (mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, next_htbl,
65426d688e3SAlex Vesker 						      &info, false)) {
65526d688e3SAlex Vesker 			mlx5dr_info(dmn, "Failed writing table to HW\n");
65626d688e3SAlex Vesker 			goto free_table;
65726d688e3SAlex Vesker 		}
65826d688e3SAlex Vesker 
65926d688e3SAlex Vesker 		mlx5dr_ste_set_hit_addr_by_next_htbl(cur_hw_ste, next_htbl);
66026d688e3SAlex Vesker 		ste->next_htbl = next_htbl;
66126d688e3SAlex Vesker 		next_htbl->pointing_ste = ste;
66226d688e3SAlex Vesker 	}
66326d688e3SAlex Vesker 
66426d688e3SAlex Vesker 	return 0;
66526d688e3SAlex Vesker 
66626d688e3SAlex Vesker free_table:
66726d688e3SAlex Vesker 	mlx5dr_ste_htbl_free(next_htbl);
66826d688e3SAlex Vesker 	return -ENOENT;
66926d688e3SAlex Vesker }
67026d688e3SAlex Vesker 
67126d688e3SAlex Vesker static void dr_ste_set_ctrl(struct mlx5dr_ste_htbl *htbl)
67226d688e3SAlex Vesker {
67326d688e3SAlex Vesker 	struct mlx5dr_ste_htbl_ctrl *ctrl = &htbl->ctrl;
67426d688e3SAlex Vesker 	int num_of_entries;
67526d688e3SAlex Vesker 
67626d688e3SAlex Vesker 	htbl->ctrl.may_grow = true;
67726d688e3SAlex Vesker 
67826d688e3SAlex Vesker 	if (htbl->chunk_size == DR_CHUNK_SIZE_MAX - 1)
67926d688e3SAlex Vesker 		htbl->ctrl.may_grow = false;
68026d688e3SAlex Vesker 
68126d688e3SAlex Vesker 	/* Threshold is 50%, one is added to table of size 1 */
68226d688e3SAlex Vesker 	num_of_entries = mlx5dr_icm_pool_chunk_size_to_entries(htbl->chunk_size);
68326d688e3SAlex Vesker 	ctrl->increase_threshold = (num_of_entries + 1) / 2;
68426d688e3SAlex Vesker }
68526d688e3SAlex Vesker 
68626d688e3SAlex Vesker struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
68726d688e3SAlex Vesker 					      enum mlx5dr_icm_chunk_size chunk_size,
68826d688e3SAlex Vesker 					      u8 lu_type, u16 byte_mask)
68926d688e3SAlex Vesker {
69026d688e3SAlex Vesker 	struct mlx5dr_icm_chunk *chunk;
69126d688e3SAlex Vesker 	struct mlx5dr_ste_htbl *htbl;
69226d688e3SAlex Vesker 	int i;
69326d688e3SAlex Vesker 
69426d688e3SAlex Vesker 	htbl = kzalloc(sizeof(*htbl), GFP_KERNEL);
69526d688e3SAlex Vesker 	if (!htbl)
69626d688e3SAlex Vesker 		return NULL;
69726d688e3SAlex Vesker 
69826d688e3SAlex Vesker 	chunk = mlx5dr_icm_alloc_chunk(pool, chunk_size);
69926d688e3SAlex Vesker 	if (!chunk)
70026d688e3SAlex Vesker 		goto out_free_htbl;
70126d688e3SAlex Vesker 
70226d688e3SAlex Vesker 	htbl->chunk = chunk;
70326d688e3SAlex Vesker 	htbl->lu_type = lu_type;
70426d688e3SAlex Vesker 	htbl->byte_mask = byte_mask;
70526d688e3SAlex Vesker 	htbl->ste_arr = chunk->ste_arr;
70626d688e3SAlex Vesker 	htbl->hw_ste_arr = chunk->hw_ste_arr;
70726d688e3SAlex Vesker 	htbl->miss_list = chunk->miss_list;
70826d688e3SAlex Vesker 	refcount_set(&htbl->refcount, 0);
70926d688e3SAlex Vesker 
71026d688e3SAlex Vesker 	for (i = 0; i < chunk->num_of_entries; i++) {
71126d688e3SAlex Vesker 		struct mlx5dr_ste *ste = &htbl->ste_arr[i];
71226d688e3SAlex Vesker 
71326d688e3SAlex Vesker 		ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
71426d688e3SAlex Vesker 		ste->htbl = htbl;
71526d688e3SAlex Vesker 		refcount_set(&ste->refcount, 0);
71626d688e3SAlex Vesker 		INIT_LIST_HEAD(&ste->miss_list_node);
71726d688e3SAlex Vesker 		INIT_LIST_HEAD(&htbl->miss_list[i]);
71826d688e3SAlex Vesker 		INIT_LIST_HEAD(&ste->rule_list);
71926d688e3SAlex Vesker 	}
72026d688e3SAlex Vesker 
72126d688e3SAlex Vesker 	htbl->chunk_size = chunk_size;
72226d688e3SAlex Vesker 	dr_ste_set_ctrl(htbl);
72326d688e3SAlex Vesker 	return htbl;
72426d688e3SAlex Vesker 
72526d688e3SAlex Vesker out_free_htbl:
72626d688e3SAlex Vesker 	kfree(htbl);
72726d688e3SAlex Vesker 	return NULL;
72826d688e3SAlex Vesker }
72926d688e3SAlex Vesker 
73026d688e3SAlex Vesker int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
73126d688e3SAlex Vesker {
73226d688e3SAlex Vesker 	if (refcount_read(&htbl->refcount))
73326d688e3SAlex Vesker 		return -EBUSY;
73426d688e3SAlex Vesker 
73526d688e3SAlex Vesker 	mlx5dr_icm_free_chunk(htbl->chunk);
73626d688e3SAlex Vesker 	kfree(htbl);
73726d688e3SAlex Vesker 	return 0;
73826d688e3SAlex Vesker }
73926d688e3SAlex Vesker 
74026d688e3SAlex Vesker int mlx5dr_ste_build_pre_check(struct mlx5dr_domain *dmn,
74126d688e3SAlex Vesker 			       u8 match_criteria,
74226d688e3SAlex Vesker 			       struct mlx5dr_match_param *mask,
74326d688e3SAlex Vesker 			       struct mlx5dr_match_param *value)
74426d688e3SAlex Vesker {
74526d688e3SAlex Vesker 	if (!value && (match_criteria & DR_MATCHER_CRITERIA_MISC)) {
74626d688e3SAlex Vesker 		if (mask->misc.source_port && mask->misc.source_port != 0xffff) {
74726d688e3SAlex Vesker 			mlx5dr_dbg(dmn, "Partial mask source_port is not supported\n");
74826d688e3SAlex Vesker 			return -EINVAL;
74926d688e3SAlex Vesker 		}
75026d688e3SAlex Vesker 	}
75126d688e3SAlex Vesker 
75226d688e3SAlex Vesker 	return 0;
75326d688e3SAlex Vesker }
75426d688e3SAlex Vesker 
75526d688e3SAlex Vesker int mlx5dr_ste_build_ste_arr(struct mlx5dr_matcher *matcher,
75626d688e3SAlex Vesker 			     struct mlx5dr_matcher_rx_tx *nic_matcher,
75726d688e3SAlex Vesker 			     struct mlx5dr_match_param *value,
75826d688e3SAlex Vesker 			     u8 *ste_arr)
75926d688e3SAlex Vesker {
76026d688e3SAlex Vesker 	struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
76126d688e3SAlex Vesker 	struct mlx5dr_domain *dmn = matcher->tbl->dmn;
76226d688e3SAlex Vesker 	struct mlx5dr_ste_build *sb;
76326d688e3SAlex Vesker 	int ret, i;
76426d688e3SAlex Vesker 
76526d688e3SAlex Vesker 	ret = mlx5dr_ste_build_pre_check(dmn, matcher->match_criteria,
76626d688e3SAlex Vesker 					 &matcher->mask, value);
76726d688e3SAlex Vesker 	if (ret)
76826d688e3SAlex Vesker 		return ret;
76926d688e3SAlex Vesker 
77026d688e3SAlex Vesker 	sb = nic_matcher->ste_builder;
77126d688e3SAlex Vesker 	for (i = 0; i < nic_matcher->num_of_builders; i++) {
77226d688e3SAlex Vesker 		mlx5dr_ste_init(ste_arr,
77326d688e3SAlex Vesker 				sb->lu_type,
77426d688e3SAlex Vesker 				nic_dmn->ste_type,
77526d688e3SAlex Vesker 				dmn->info.caps.gvmi);
77626d688e3SAlex Vesker 
77726d688e3SAlex Vesker 		mlx5dr_ste_set_bit_mask(ste_arr, sb->bit_mask);
77826d688e3SAlex Vesker 
77926d688e3SAlex Vesker 		ret = sb->ste_build_tag_func(value, sb, ste_arr);
78026d688e3SAlex Vesker 		if (ret)
78126d688e3SAlex Vesker 			return ret;
78226d688e3SAlex Vesker 
78326d688e3SAlex Vesker 		/* Connect the STEs */
78426d688e3SAlex Vesker 		if (i < (nic_matcher->num_of_builders - 1)) {
78526d688e3SAlex Vesker 			/* Need the next builder for these fields,
78626d688e3SAlex Vesker 			 * not relevant for the last ste in the chain.
78726d688e3SAlex Vesker 			 */
78826d688e3SAlex Vesker 			sb++;
78926d688e3SAlex Vesker 			MLX5_SET(ste_general, ste_arr, next_lu_type, sb->lu_type);
79026d688e3SAlex Vesker 			MLX5_SET(ste_general, ste_arr, byte_mask, sb->byte_mask);
79126d688e3SAlex Vesker 		}
79226d688e3SAlex Vesker 		ste_arr += DR_STE_SIZE;
79326d688e3SAlex Vesker 	}
79426d688e3SAlex Vesker 	return 0;
79526d688e3SAlex Vesker }
79626d688e3SAlex Vesker 
79726d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_des_bit_mask(struct mlx5dr_match_param *value,
79826d688e3SAlex Vesker 						bool inner, u8 *bit_mask)
79926d688e3SAlex Vesker {
80026d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
80126d688e3SAlex Vesker 
80226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, dmac_47_16, mask, dmac_47_16);
80326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, dmac_15_0, mask, dmac_15_0);
80426d688e3SAlex Vesker 
80526d688e3SAlex Vesker 	if (mask->smac_47_16 || mask->smac_15_0) {
80626d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, smac_47_32,
80726d688e3SAlex Vesker 			 mask->smac_47_16 >> 16);
80826d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, smac_31_0,
80926d688e3SAlex Vesker 			 mask->smac_47_16 << 16 | mask->smac_15_0);
81026d688e3SAlex Vesker 		mask->smac_47_16 = 0;
81126d688e3SAlex Vesker 		mask->smac_15_0 = 0;
81226d688e3SAlex Vesker 	}
81326d688e3SAlex Vesker 
81426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_vlan_id, mask, first_vid);
81526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_cfi, mask, first_cfi);
81626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src_dst, bit_mask, first_priority, mask, first_prio);
81726d688e3SAlex Vesker 	DR_STE_SET_MASK(eth_l2_src_dst, bit_mask, l3_type, mask, ip_version);
81826d688e3SAlex Vesker 
81926d688e3SAlex Vesker 	if (mask->cvlan_tag) {
82026d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, first_vlan_qualifier, -1);
82126d688e3SAlex Vesker 		mask->cvlan_tag = 0;
82226d688e3SAlex Vesker 	} else if (mask->svlan_tag) {
82326d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, bit_mask, first_vlan_qualifier, -1);
82426d688e3SAlex Vesker 		mask->svlan_tag = 0;
82526d688e3SAlex Vesker 	}
82626d688e3SAlex Vesker 
82726d688e3SAlex Vesker 	if (mask->cvlan_tag || mask->svlan_tag) {
82826d688e3SAlex Vesker 		pr_info("Invalid c/svlan mask configuration\n");
82926d688e3SAlex Vesker 		return -EINVAL;
83026d688e3SAlex Vesker 	}
83126d688e3SAlex Vesker 
83226d688e3SAlex Vesker 	return 0;
83326d688e3SAlex Vesker }
83426d688e3SAlex Vesker 
83526d688e3SAlex Vesker static void dr_ste_copy_mask_misc(char *mask, struct mlx5dr_match_misc *spec)
83626d688e3SAlex Vesker {
83726d688e3SAlex Vesker 	spec->gre_c_present = MLX5_GET(fte_match_set_misc, mask, gre_c_present);
83826d688e3SAlex Vesker 	spec->gre_k_present = MLX5_GET(fte_match_set_misc, mask, gre_k_present);
83926d688e3SAlex Vesker 	spec->gre_s_present = MLX5_GET(fte_match_set_misc, mask, gre_s_present);
84026d688e3SAlex Vesker 	spec->source_vhca_port = MLX5_GET(fte_match_set_misc, mask, source_vhca_port);
84126d688e3SAlex Vesker 	spec->source_sqn = MLX5_GET(fte_match_set_misc, mask, source_sqn);
84226d688e3SAlex Vesker 
84326d688e3SAlex Vesker 	spec->source_port = MLX5_GET(fte_match_set_misc, mask, source_port);
84426d688e3SAlex Vesker 
84526d688e3SAlex Vesker 	spec->outer_second_prio = MLX5_GET(fte_match_set_misc, mask, outer_second_prio);
84626d688e3SAlex Vesker 	spec->outer_second_cfi = MLX5_GET(fte_match_set_misc, mask, outer_second_cfi);
84726d688e3SAlex Vesker 	spec->outer_second_vid = MLX5_GET(fte_match_set_misc, mask, outer_second_vid);
84826d688e3SAlex Vesker 	spec->inner_second_prio = MLX5_GET(fte_match_set_misc, mask, inner_second_prio);
84926d688e3SAlex Vesker 	spec->inner_second_cfi = MLX5_GET(fte_match_set_misc, mask, inner_second_cfi);
85026d688e3SAlex Vesker 	spec->inner_second_vid = MLX5_GET(fte_match_set_misc, mask, inner_second_vid);
85126d688e3SAlex Vesker 
85226d688e3SAlex Vesker 	spec->outer_second_cvlan_tag =
85326d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, outer_second_cvlan_tag);
85426d688e3SAlex Vesker 	spec->inner_second_cvlan_tag =
85526d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, inner_second_cvlan_tag);
85626d688e3SAlex Vesker 	spec->outer_second_svlan_tag =
85726d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, outer_second_svlan_tag);
85826d688e3SAlex Vesker 	spec->inner_second_svlan_tag =
85926d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, inner_second_svlan_tag);
86026d688e3SAlex Vesker 
86126d688e3SAlex Vesker 	spec->gre_protocol = MLX5_GET(fte_match_set_misc, mask, gre_protocol);
86226d688e3SAlex Vesker 
86326d688e3SAlex Vesker 	spec->gre_key_h = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.hi);
86426d688e3SAlex Vesker 	spec->gre_key_l = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.lo);
86526d688e3SAlex Vesker 
86626d688e3SAlex Vesker 	spec->vxlan_vni = MLX5_GET(fte_match_set_misc, mask, vxlan_vni);
86726d688e3SAlex Vesker 
86826d688e3SAlex Vesker 	spec->geneve_vni = MLX5_GET(fte_match_set_misc, mask, geneve_vni);
86926d688e3SAlex Vesker 	spec->geneve_oam = MLX5_GET(fte_match_set_misc, mask, geneve_oam);
87026d688e3SAlex Vesker 
87126d688e3SAlex Vesker 	spec->outer_ipv6_flow_label =
87226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, outer_ipv6_flow_label);
87326d688e3SAlex Vesker 
87426d688e3SAlex Vesker 	spec->inner_ipv6_flow_label =
87526d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, inner_ipv6_flow_label);
87626d688e3SAlex Vesker 
87726d688e3SAlex Vesker 	spec->geneve_opt_len = MLX5_GET(fte_match_set_misc, mask, geneve_opt_len);
87826d688e3SAlex Vesker 	spec->geneve_protocol_type =
87926d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc, mask, geneve_protocol_type);
88026d688e3SAlex Vesker 
88126d688e3SAlex Vesker 	spec->bth_dst_qp = MLX5_GET(fte_match_set_misc, mask, bth_dst_qp);
88226d688e3SAlex Vesker }
88326d688e3SAlex Vesker 
88426d688e3SAlex Vesker static void dr_ste_copy_mask_spec(char *mask, struct mlx5dr_match_spec *spec)
88526d688e3SAlex Vesker {
88626d688e3SAlex Vesker 	u32 raw_ip[4];
88726d688e3SAlex Vesker 
88826d688e3SAlex Vesker 	spec->smac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_47_16);
88926d688e3SAlex Vesker 
89026d688e3SAlex Vesker 	spec->smac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_15_0);
89126d688e3SAlex Vesker 	spec->ethertype = MLX5_GET(fte_match_set_lyr_2_4, mask, ethertype);
89226d688e3SAlex Vesker 
89326d688e3SAlex Vesker 	spec->dmac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_47_16);
89426d688e3SAlex Vesker 
89526d688e3SAlex Vesker 	spec->dmac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_15_0);
89626d688e3SAlex Vesker 	spec->first_prio = MLX5_GET(fte_match_set_lyr_2_4, mask, first_prio);
89726d688e3SAlex Vesker 	spec->first_cfi = MLX5_GET(fte_match_set_lyr_2_4, mask, first_cfi);
89826d688e3SAlex Vesker 	spec->first_vid = MLX5_GET(fte_match_set_lyr_2_4, mask, first_vid);
89926d688e3SAlex Vesker 
90026d688e3SAlex Vesker 	spec->ip_protocol = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_protocol);
90126d688e3SAlex Vesker 	spec->ip_dscp = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_dscp);
90226d688e3SAlex Vesker 	spec->ip_ecn = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_ecn);
90326d688e3SAlex Vesker 	spec->cvlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, cvlan_tag);
90426d688e3SAlex Vesker 	spec->svlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, svlan_tag);
90526d688e3SAlex Vesker 	spec->frag = MLX5_GET(fte_match_set_lyr_2_4, mask, frag);
90626d688e3SAlex Vesker 	spec->ip_version = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_version);
90726d688e3SAlex Vesker 	spec->tcp_flags = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_flags);
90826d688e3SAlex Vesker 	spec->tcp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_sport);
90926d688e3SAlex Vesker 	spec->tcp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_dport);
91026d688e3SAlex Vesker 
91126d688e3SAlex Vesker 	spec->ttl_hoplimit = MLX5_GET(fte_match_set_lyr_2_4, mask, ttl_hoplimit);
91226d688e3SAlex Vesker 
91326d688e3SAlex Vesker 	spec->udp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_sport);
91426d688e3SAlex Vesker 	spec->udp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_dport);
91526d688e3SAlex Vesker 
91626d688e3SAlex Vesker 	memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
91726d688e3SAlex Vesker 				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
91826d688e3SAlex Vesker 				    sizeof(raw_ip));
91926d688e3SAlex Vesker 
92026d688e3SAlex Vesker 	spec->src_ip_127_96 = be32_to_cpu(raw_ip[0]);
92126d688e3SAlex Vesker 	spec->src_ip_95_64 = be32_to_cpu(raw_ip[1]);
92226d688e3SAlex Vesker 	spec->src_ip_63_32 = be32_to_cpu(raw_ip[2]);
92326d688e3SAlex Vesker 	spec->src_ip_31_0 = be32_to_cpu(raw_ip[3]);
92426d688e3SAlex Vesker 
92526d688e3SAlex Vesker 	memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
92626d688e3SAlex Vesker 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
92726d688e3SAlex Vesker 				    sizeof(raw_ip));
92826d688e3SAlex Vesker 
92926d688e3SAlex Vesker 	spec->dst_ip_127_96 = be32_to_cpu(raw_ip[0]);
93026d688e3SAlex Vesker 	spec->dst_ip_95_64 = be32_to_cpu(raw_ip[1]);
93126d688e3SAlex Vesker 	spec->dst_ip_63_32 = be32_to_cpu(raw_ip[2]);
93226d688e3SAlex Vesker 	spec->dst_ip_31_0 = be32_to_cpu(raw_ip[3]);
93326d688e3SAlex Vesker }
93426d688e3SAlex Vesker 
93526d688e3SAlex Vesker static void dr_ste_copy_mask_misc2(char *mask, struct mlx5dr_match_misc2 *spec)
93626d688e3SAlex Vesker {
93726d688e3SAlex Vesker 	spec->outer_first_mpls_label =
93826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_label);
93926d688e3SAlex Vesker 	spec->outer_first_mpls_exp =
94026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_exp);
94126d688e3SAlex Vesker 	spec->outer_first_mpls_s_bos =
94226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_s_bos);
94326d688e3SAlex Vesker 	spec->outer_first_mpls_ttl =
94426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_ttl);
94526d688e3SAlex Vesker 	spec->inner_first_mpls_label =
94626d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_label);
94726d688e3SAlex Vesker 	spec->inner_first_mpls_exp =
94826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_exp);
94926d688e3SAlex Vesker 	spec->inner_first_mpls_s_bos =
95026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_s_bos);
95126d688e3SAlex Vesker 	spec->inner_first_mpls_ttl =
95226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_ttl);
95326d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_label =
95426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_label);
95526d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_exp =
95626d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_exp);
95726d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_s_bos =
95826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_s_bos);
95926d688e3SAlex Vesker 	spec->outer_first_mpls_over_gre_ttl =
96026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_ttl);
96126d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_label =
96226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_label);
96326d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_exp =
96426d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_exp);
96526d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_s_bos =
96626d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_s_bos);
96726d688e3SAlex Vesker 	spec->outer_first_mpls_over_udp_ttl =
96826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_ttl);
96926d688e3SAlex Vesker 	spec->metadata_reg_c_7 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_7);
97026d688e3SAlex Vesker 	spec->metadata_reg_c_6 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_6);
97126d688e3SAlex Vesker 	spec->metadata_reg_c_5 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_5);
97226d688e3SAlex Vesker 	spec->metadata_reg_c_4 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_4);
97326d688e3SAlex Vesker 	spec->metadata_reg_c_3 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_3);
97426d688e3SAlex Vesker 	spec->metadata_reg_c_2 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_2);
97526d688e3SAlex Vesker 	spec->metadata_reg_c_1 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_1);
97626d688e3SAlex Vesker 	spec->metadata_reg_c_0 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_0);
97726d688e3SAlex Vesker 	spec->metadata_reg_a = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_a);
97826d688e3SAlex Vesker 	spec->metadata_reg_b = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_b);
97926d688e3SAlex Vesker }
98026d688e3SAlex Vesker 
98126d688e3SAlex Vesker static void dr_ste_copy_mask_misc3(char *mask, struct mlx5dr_match_misc3 *spec)
98226d688e3SAlex Vesker {
98326d688e3SAlex Vesker 	spec->inner_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_seq_num);
98426d688e3SAlex Vesker 	spec->outer_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_seq_num);
98526d688e3SAlex Vesker 	spec->inner_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_ack_num);
98626d688e3SAlex Vesker 	spec->outer_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_ack_num);
98726d688e3SAlex Vesker 	spec->outer_vxlan_gpe_vni =
98826d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_vni);
98926d688e3SAlex Vesker 	spec->outer_vxlan_gpe_next_protocol =
99026d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_next_protocol);
99126d688e3SAlex Vesker 	spec->outer_vxlan_gpe_flags =
99226d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_flags);
99326d688e3SAlex Vesker 	spec->icmpv4_header_data = MLX5_GET(fte_match_set_misc3, mask, icmp_header_data);
99426d688e3SAlex Vesker 	spec->icmpv6_header_data =
99526d688e3SAlex Vesker 		MLX5_GET(fte_match_set_misc3, mask, icmpv6_header_data);
99626d688e3SAlex Vesker 	spec->icmpv4_type = MLX5_GET(fte_match_set_misc3, mask, icmp_type);
99726d688e3SAlex Vesker 	spec->icmpv4_code = MLX5_GET(fte_match_set_misc3, mask, icmp_code);
99826d688e3SAlex Vesker 	spec->icmpv6_type = MLX5_GET(fte_match_set_misc3, mask, icmpv6_type);
99926d688e3SAlex Vesker 	spec->icmpv6_code = MLX5_GET(fte_match_set_misc3, mask, icmpv6_code);
100026d688e3SAlex Vesker }
100126d688e3SAlex Vesker 
100226d688e3SAlex Vesker void mlx5dr_ste_copy_param(u8 match_criteria,
100326d688e3SAlex Vesker 			   struct mlx5dr_match_param *set_param,
100426d688e3SAlex Vesker 			   struct mlx5dr_match_parameters *mask)
100526d688e3SAlex Vesker {
100626d688e3SAlex Vesker 	u8 tail_param[MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4)] = {};
100726d688e3SAlex Vesker 	u8 *data = (u8 *)mask->match_buf;
100826d688e3SAlex Vesker 	size_t param_location;
100926d688e3SAlex Vesker 	void *buff;
101026d688e3SAlex Vesker 
101126d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_OUTER) {
101226d688e3SAlex Vesker 		if (mask->match_sz < sizeof(struct mlx5dr_match_spec)) {
101326d688e3SAlex Vesker 			memcpy(tail_param, data, mask->match_sz);
101426d688e3SAlex Vesker 			buff = tail_param;
101526d688e3SAlex Vesker 		} else {
101626d688e3SAlex Vesker 			buff = mask->match_buf;
101726d688e3SAlex Vesker 		}
101826d688e3SAlex Vesker 		dr_ste_copy_mask_spec(buff, &set_param->outer);
101926d688e3SAlex Vesker 	}
102026d688e3SAlex Vesker 	param_location = sizeof(struct mlx5dr_match_spec);
102126d688e3SAlex Vesker 
102226d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_MISC) {
102326d688e3SAlex Vesker 		if (mask->match_sz < param_location +
102426d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_misc)) {
102526d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
102626d688e3SAlex Vesker 			       mask->match_sz - param_location);
102726d688e3SAlex Vesker 			buff = tail_param;
102826d688e3SAlex Vesker 		} else {
102926d688e3SAlex Vesker 			buff = data + param_location;
103026d688e3SAlex Vesker 		}
103126d688e3SAlex Vesker 		dr_ste_copy_mask_misc(buff, &set_param->misc);
103226d688e3SAlex Vesker 	}
103326d688e3SAlex Vesker 	param_location += sizeof(struct mlx5dr_match_misc);
103426d688e3SAlex Vesker 
103526d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_INNER) {
103626d688e3SAlex Vesker 		if (mask->match_sz < param_location +
103726d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_spec)) {
103826d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
103926d688e3SAlex Vesker 			       mask->match_sz - param_location);
104026d688e3SAlex Vesker 			buff = tail_param;
104126d688e3SAlex Vesker 		} else {
104226d688e3SAlex Vesker 			buff = data + param_location;
104326d688e3SAlex Vesker 		}
104426d688e3SAlex Vesker 		dr_ste_copy_mask_spec(buff, &set_param->inner);
104526d688e3SAlex Vesker 	}
104626d688e3SAlex Vesker 	param_location += sizeof(struct mlx5dr_match_spec);
104726d688e3SAlex Vesker 
104826d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_MISC2) {
104926d688e3SAlex Vesker 		if (mask->match_sz < param_location +
105026d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_misc2)) {
105126d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
105226d688e3SAlex Vesker 			       mask->match_sz - param_location);
105326d688e3SAlex Vesker 			buff = tail_param;
105426d688e3SAlex Vesker 		} else {
105526d688e3SAlex Vesker 			buff = data + param_location;
105626d688e3SAlex Vesker 		}
105726d688e3SAlex Vesker 		dr_ste_copy_mask_misc2(buff, &set_param->misc2);
105826d688e3SAlex Vesker 	}
105926d688e3SAlex Vesker 
106026d688e3SAlex Vesker 	param_location += sizeof(struct mlx5dr_match_misc2);
106126d688e3SAlex Vesker 
106226d688e3SAlex Vesker 	if (match_criteria & DR_MATCHER_CRITERIA_MISC3) {
106326d688e3SAlex Vesker 		if (mask->match_sz < param_location +
106426d688e3SAlex Vesker 		    sizeof(struct mlx5dr_match_misc3)) {
106526d688e3SAlex Vesker 			memcpy(tail_param, data + param_location,
106626d688e3SAlex Vesker 			       mask->match_sz - param_location);
106726d688e3SAlex Vesker 			buff = tail_param;
106826d688e3SAlex Vesker 		} else {
106926d688e3SAlex Vesker 			buff = data + param_location;
107026d688e3SAlex Vesker 		}
107126d688e3SAlex Vesker 		dr_ste_copy_mask_misc3(buff, &set_param->misc3);
107226d688e3SAlex Vesker 	}
107326d688e3SAlex Vesker }
107426d688e3SAlex Vesker 
107526d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_des_tag(struct mlx5dr_match_param *value,
107626d688e3SAlex Vesker 					   struct mlx5dr_ste_build *sb,
107726d688e3SAlex Vesker 					   u8 *hw_ste_p)
107826d688e3SAlex Vesker {
107926d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
108026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
108126d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
108226d688e3SAlex Vesker 
108326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, dmac_47_16, spec, dmac_47_16);
108426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, dmac_15_0, spec, dmac_15_0);
108526d688e3SAlex Vesker 
108626d688e3SAlex Vesker 	if (spec->smac_47_16 || spec->smac_15_0) {
108726d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, smac_47_32,
108826d688e3SAlex Vesker 			 spec->smac_47_16 >> 16);
108926d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, smac_31_0,
109026d688e3SAlex Vesker 			 spec->smac_47_16 << 16 | spec->smac_15_0);
109126d688e3SAlex Vesker 		spec->smac_47_16 = 0;
109226d688e3SAlex Vesker 		spec->smac_15_0 = 0;
109326d688e3SAlex Vesker 	}
109426d688e3SAlex Vesker 
109526d688e3SAlex Vesker 	if (spec->ip_version) {
109626d688e3SAlex Vesker 		if (spec->ip_version == IP_VERSION_IPV4) {
109726d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src_dst, tag, l3_type, STE_IPV4);
109826d688e3SAlex Vesker 			spec->ip_version = 0;
109926d688e3SAlex Vesker 		} else if (spec->ip_version == IP_VERSION_IPV6) {
110026d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src_dst, tag, l3_type, STE_IPV6);
110126d688e3SAlex Vesker 			spec->ip_version = 0;
110226d688e3SAlex Vesker 		} else {
110326d688e3SAlex Vesker 			pr_info("Unsupported ip_version value\n");
110426d688e3SAlex Vesker 			return -EINVAL;
110526d688e3SAlex Vesker 		}
110626d688e3SAlex Vesker 	}
110726d688e3SAlex Vesker 
110826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, first_vlan_id, spec, first_vid);
110926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, first_cfi, spec, first_cfi);
111026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src_dst, tag, first_priority, spec, first_prio);
111126d688e3SAlex Vesker 
111226d688e3SAlex Vesker 	if (spec->cvlan_tag) {
111326d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, first_vlan_qualifier, DR_STE_CVLAN);
111426d688e3SAlex Vesker 		spec->cvlan_tag = 0;
111526d688e3SAlex Vesker 	} else if (spec->svlan_tag) {
111626d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src_dst, tag, first_vlan_qualifier, DR_STE_SVLAN);
111726d688e3SAlex Vesker 		spec->svlan_tag = 0;
111826d688e3SAlex Vesker 	}
111926d688e3SAlex Vesker 	return 0;
112026d688e3SAlex Vesker }
112126d688e3SAlex Vesker 
112226d688e3SAlex Vesker int mlx5dr_ste_build_eth_l2_src_des(struct mlx5dr_ste_build *sb,
112326d688e3SAlex Vesker 				    struct mlx5dr_match_param *mask,
112426d688e3SAlex Vesker 				    bool inner, bool rx)
112526d688e3SAlex Vesker {
112626d688e3SAlex Vesker 	int ret;
112726d688e3SAlex Vesker 
112826d688e3SAlex Vesker 	ret = dr_ste_build_eth_l2_src_des_bit_mask(mask, inner, sb->bit_mask);
112926d688e3SAlex Vesker 	if (ret)
113026d688e3SAlex Vesker 		return ret;
113126d688e3SAlex Vesker 
113226d688e3SAlex Vesker 	sb->rx = rx;
113326d688e3SAlex Vesker 	sb->inner = inner;
113426d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_SRC_DST, rx, inner);
113526d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
113626d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_src_des_tag;
113726d688e3SAlex Vesker 
113826d688e3SAlex Vesker 	return 0;
113926d688e3SAlex Vesker }
114026d688e3SAlex Vesker 
114126d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv6_dst_bit_mask(struct mlx5dr_match_param *value,
114226d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
114326d688e3SAlex Vesker {
114426d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
114526d688e3SAlex Vesker 
114626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_127_96, mask, dst_ip_127_96);
114726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_95_64, mask, dst_ip_95_64);
114826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_63_32, mask, dst_ip_63_32);
114926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_dst, bit_mask, dst_ip_31_0, mask, dst_ip_31_0);
115026d688e3SAlex Vesker }
115126d688e3SAlex Vesker 
115226d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv6_dst_tag(struct mlx5dr_match_param *value,
115326d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
115426d688e3SAlex Vesker 					    u8 *hw_ste_p)
115526d688e3SAlex Vesker {
115626d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
115726d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
115826d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
115926d688e3SAlex Vesker 
116026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_127_96, spec, dst_ip_127_96);
116126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_95_64, spec, dst_ip_95_64);
116226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_63_32, spec, dst_ip_63_32);
116326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_dst, tag, dst_ip_31_0, spec, dst_ip_31_0);
116426d688e3SAlex Vesker 
116526d688e3SAlex Vesker 	return 0;
116626d688e3SAlex Vesker }
116726d688e3SAlex Vesker 
116826d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv6_dst(struct mlx5dr_ste_build *sb,
116926d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
117026d688e3SAlex Vesker 				      bool inner, bool rx)
117126d688e3SAlex Vesker {
117226d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv6_dst_bit_mask(mask, inner, sb->bit_mask);
117326d688e3SAlex Vesker 
117426d688e3SAlex Vesker 	sb->rx = rx;
117526d688e3SAlex Vesker 	sb->inner = inner;
117626d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV6_DST, rx, inner);
117726d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
117826d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv6_dst_tag;
117926d688e3SAlex Vesker }
118026d688e3SAlex Vesker 
118126d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv6_src_bit_mask(struct mlx5dr_match_param *value,
118226d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
118326d688e3SAlex Vesker {
118426d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
118526d688e3SAlex Vesker 
118626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_127_96, mask, src_ip_127_96);
118726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_95_64, mask, src_ip_95_64);
118826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_63_32, mask, src_ip_63_32);
118926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv6_src, bit_mask, src_ip_31_0, mask, src_ip_31_0);
119026d688e3SAlex Vesker }
119126d688e3SAlex Vesker 
119226d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv6_src_tag(struct mlx5dr_match_param *value,
119326d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
119426d688e3SAlex Vesker 					    u8 *hw_ste_p)
119526d688e3SAlex Vesker {
119626d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
119726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
119826d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
119926d688e3SAlex Vesker 
120026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_127_96, spec, src_ip_127_96);
120126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_95_64, spec, src_ip_95_64);
120226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_63_32, spec, src_ip_63_32);
120326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv6_src, tag, src_ip_31_0, spec, src_ip_31_0);
120426d688e3SAlex Vesker 
120526d688e3SAlex Vesker 	return 0;
120626d688e3SAlex Vesker }
120726d688e3SAlex Vesker 
120826d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv6_src(struct mlx5dr_ste_build *sb,
120926d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
121026d688e3SAlex Vesker 				      bool inner, bool rx)
121126d688e3SAlex Vesker {
121226d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv6_src_bit_mask(mask, inner, sb->bit_mask);
121326d688e3SAlex Vesker 
121426d688e3SAlex Vesker 	sb->rx = rx;
121526d688e3SAlex Vesker 	sb->inner = inner;
121626d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV6_SRC, rx, inner);
121726d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
121826d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv6_src_tag;
121926d688e3SAlex Vesker }
122026d688e3SAlex Vesker 
122126d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv4_5_tuple_bit_mask(struct mlx5dr_match_param *value,
122226d688e3SAlex Vesker 						      bool inner,
122326d688e3SAlex Vesker 						      u8 *bit_mask)
122426d688e3SAlex Vesker {
122526d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
122626d688e3SAlex Vesker 
122726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
122826d688e3SAlex Vesker 			  destination_address, mask, dst_ip_31_0);
122926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
123026d688e3SAlex Vesker 			  source_address, mask, src_ip_31_0);
123126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
123226d688e3SAlex Vesker 			  destination_port, mask, tcp_dport);
123326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
123426d688e3SAlex Vesker 			  destination_port, mask, udp_dport);
123526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
123626d688e3SAlex Vesker 			  source_port, mask, tcp_sport);
123726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
123826d688e3SAlex Vesker 			  source_port, mask, udp_sport);
123926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
124026d688e3SAlex Vesker 			  protocol, mask, ip_protocol);
124126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
124226d688e3SAlex Vesker 			  fragmented, mask, frag);
124326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
124426d688e3SAlex Vesker 			  dscp, mask, ip_dscp);
124526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_5_tuple, bit_mask,
124626d688e3SAlex Vesker 			  ecn, mask, ip_ecn);
124726d688e3SAlex Vesker 
124826d688e3SAlex Vesker 	if (mask->tcp_flags) {
124926d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l3_ipv4_5_tuple, bit_mask, mask);
125026d688e3SAlex Vesker 		mask->tcp_flags = 0;
125126d688e3SAlex Vesker 	}
125226d688e3SAlex Vesker }
125326d688e3SAlex Vesker 
125426d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv4_5_tuple_tag(struct mlx5dr_match_param *value,
125526d688e3SAlex Vesker 						struct mlx5dr_ste_build *sb,
125626d688e3SAlex Vesker 						u8 *hw_ste_p)
125726d688e3SAlex Vesker {
125826d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
125926d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
126026d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
126126d688e3SAlex Vesker 
126226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_address, spec, dst_ip_31_0);
126326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_address, spec, src_ip_31_0);
126426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_port, spec, tcp_dport);
126526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, destination_port, spec, udp_dport);
126626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_port, spec, tcp_sport);
126726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, source_port, spec, udp_sport);
126826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, protocol, spec, ip_protocol);
126926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, fragmented, spec, frag);
127026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, dscp, spec, ip_dscp);
127126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_5_tuple, tag, ecn, spec, ip_ecn);
127226d688e3SAlex Vesker 
127326d688e3SAlex Vesker 	if (spec->tcp_flags) {
127426d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l3_ipv4_5_tuple, tag, spec);
127526d688e3SAlex Vesker 		spec->tcp_flags = 0;
127626d688e3SAlex Vesker 	}
127726d688e3SAlex Vesker 
127826d688e3SAlex Vesker 	return 0;
127926d688e3SAlex Vesker }
128026d688e3SAlex Vesker 
128126d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv4_5_tuple(struct mlx5dr_ste_build *sb,
128226d688e3SAlex Vesker 					  struct mlx5dr_match_param *mask,
128326d688e3SAlex Vesker 					  bool inner, bool rx)
128426d688e3SAlex Vesker {
128526d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv4_5_tuple_bit_mask(mask, inner, sb->bit_mask);
128626d688e3SAlex Vesker 
128726d688e3SAlex Vesker 	sb->rx = rx;
128826d688e3SAlex Vesker 	sb->inner = inner;
128926d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV4_5_TUPLE, rx, inner);
129026d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
129126d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv4_5_tuple_tag;
129226d688e3SAlex Vesker }
129326d688e3SAlex Vesker 
129426d688e3SAlex Vesker static void
129526d688e3SAlex Vesker dr_ste_build_eth_l2_src_or_dst_bit_mask(struct mlx5dr_match_param *value,
129626d688e3SAlex Vesker 					bool inner, u8 *bit_mask)
129726d688e3SAlex Vesker {
129826d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
129926d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_mask = &value->misc;
130026d688e3SAlex Vesker 
130126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_vlan_id, mask, first_vid);
130226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_cfi, mask, first_cfi);
130326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, first_priority, mask, first_prio);
130426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, ip_fragmented, mask, frag);
130526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, l3_ethertype, mask, ethertype);
130626d688e3SAlex Vesker 	DR_STE_SET_MASK(eth_l2_src, bit_mask, l3_type, mask, ip_version);
130726d688e3SAlex Vesker 
130826d688e3SAlex Vesker 	if (mask->svlan_tag || mask->cvlan_tag) {
130926d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src, bit_mask, first_vlan_qualifier, -1);
131026d688e3SAlex Vesker 		mask->cvlan_tag = 0;
131126d688e3SAlex Vesker 		mask->svlan_tag = 0;
131226d688e3SAlex Vesker 	}
131326d688e3SAlex Vesker 
131426d688e3SAlex Vesker 	if (inner) {
131526d688e3SAlex Vesker 		if (misc_mask->inner_second_cvlan_tag ||
131626d688e3SAlex Vesker 		    misc_mask->inner_second_svlan_tag) {
131726d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, bit_mask, second_vlan_qualifier, -1);
131826d688e3SAlex Vesker 			misc_mask->inner_second_cvlan_tag = 0;
131926d688e3SAlex Vesker 			misc_mask->inner_second_svlan_tag = 0;
132026d688e3SAlex Vesker 		}
132126d688e3SAlex Vesker 
132226d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
132326d688e3SAlex Vesker 				  second_vlan_id, misc_mask, inner_second_vid);
132426d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
132526d688e3SAlex Vesker 				  second_cfi, misc_mask, inner_second_cfi);
132626d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
132726d688e3SAlex Vesker 				  second_priority, misc_mask, inner_second_prio);
132826d688e3SAlex Vesker 	} else {
132926d688e3SAlex Vesker 		if (misc_mask->outer_second_cvlan_tag ||
133026d688e3SAlex Vesker 		    misc_mask->outer_second_svlan_tag) {
133126d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, bit_mask, second_vlan_qualifier, -1);
133226d688e3SAlex Vesker 			misc_mask->outer_second_cvlan_tag = 0;
133326d688e3SAlex Vesker 			misc_mask->outer_second_svlan_tag = 0;
133426d688e3SAlex Vesker 		}
133526d688e3SAlex Vesker 
133626d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
133726d688e3SAlex Vesker 				  second_vlan_id, misc_mask, outer_second_vid);
133826d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
133926d688e3SAlex Vesker 				  second_cfi, misc_mask, outer_second_cfi);
134026d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l2_src, bit_mask,
134126d688e3SAlex Vesker 				  second_priority, misc_mask, outer_second_prio);
134226d688e3SAlex Vesker 	}
134326d688e3SAlex Vesker }
134426d688e3SAlex Vesker 
134526d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_or_dst_tag(struct mlx5dr_match_param *value,
134626d688e3SAlex Vesker 					      bool inner, u8 *hw_ste_p)
134726d688e3SAlex Vesker {
134826d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
134926d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = inner ? &value->inner : &value->outer;
135026d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_spec = &value->misc;
135126d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
135226d688e3SAlex Vesker 
135326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, first_vlan_id, spec, first_vid);
135426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, first_cfi, spec, first_cfi);
135526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, first_priority, spec, first_prio);
135626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, ip_fragmented, spec, frag);
135726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, l3_ethertype, spec, ethertype);
135826d688e3SAlex Vesker 
135926d688e3SAlex Vesker 	if (spec->ip_version) {
136026d688e3SAlex Vesker 		if (spec->ip_version == IP_VERSION_IPV4) {
136126d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, l3_type, STE_IPV4);
136226d688e3SAlex Vesker 			spec->ip_version = 0;
136326d688e3SAlex Vesker 		} else if (spec->ip_version == IP_VERSION_IPV6) {
136426d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, l3_type, STE_IPV6);
136526d688e3SAlex Vesker 			spec->ip_version = 0;
136626d688e3SAlex Vesker 		} else {
136726d688e3SAlex Vesker 			pr_info("Unsupported ip_version value\n");
136826d688e3SAlex Vesker 			return -EINVAL;
136926d688e3SAlex Vesker 		}
137026d688e3SAlex Vesker 	}
137126d688e3SAlex Vesker 
137226d688e3SAlex Vesker 	if (spec->cvlan_tag) {
137326d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src, tag, first_vlan_qualifier, DR_STE_CVLAN);
137426d688e3SAlex Vesker 		spec->cvlan_tag = 0;
137526d688e3SAlex Vesker 	} else if (spec->svlan_tag) {
137626d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_src, tag, first_vlan_qualifier, DR_STE_SVLAN);
137726d688e3SAlex Vesker 		spec->svlan_tag = 0;
137826d688e3SAlex Vesker 	}
137926d688e3SAlex Vesker 
138026d688e3SAlex Vesker 	if (inner) {
138126d688e3SAlex Vesker 		if (misc_spec->inner_second_cvlan_tag) {
138226d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_CVLAN);
138326d688e3SAlex Vesker 			misc_spec->inner_second_cvlan_tag = 0;
138426d688e3SAlex Vesker 		} else if (misc_spec->inner_second_svlan_tag) {
138526d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_SVLAN);
138626d688e3SAlex Vesker 			misc_spec->inner_second_svlan_tag = 0;
138726d688e3SAlex Vesker 		}
138826d688e3SAlex Vesker 
138926d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_vlan_id, misc_spec, inner_second_vid);
139026d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_cfi, misc_spec, inner_second_cfi);
139126d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_priority, misc_spec, inner_second_prio);
139226d688e3SAlex Vesker 	} else {
139326d688e3SAlex Vesker 		if (misc_spec->outer_second_cvlan_tag) {
139426d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_CVLAN);
139526d688e3SAlex Vesker 			misc_spec->outer_second_cvlan_tag = 0;
139626d688e3SAlex Vesker 		} else if (misc_spec->outer_second_svlan_tag) {
139726d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_src, tag, second_vlan_qualifier, DR_STE_SVLAN);
139826d688e3SAlex Vesker 			misc_spec->outer_second_svlan_tag = 0;
139926d688e3SAlex Vesker 		}
140026d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_vlan_id, misc_spec, outer_second_vid);
140126d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_cfi, misc_spec, outer_second_cfi);
140226d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l2_src, tag, second_priority, misc_spec, outer_second_prio);
140326d688e3SAlex Vesker 	}
140426d688e3SAlex Vesker 
140526d688e3SAlex Vesker 	return 0;
140626d688e3SAlex Vesker }
140726d688e3SAlex Vesker 
140826d688e3SAlex Vesker static void dr_ste_build_eth_l2_src_bit_mask(struct mlx5dr_match_param *value,
140926d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
141026d688e3SAlex Vesker {
141126d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
141226d688e3SAlex Vesker 
141326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, smac_47_16, mask, smac_47_16);
141426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_src, bit_mask, smac_15_0, mask, smac_15_0);
141526d688e3SAlex Vesker 
141626d688e3SAlex Vesker 	dr_ste_build_eth_l2_src_or_dst_bit_mask(value, inner, bit_mask);
141726d688e3SAlex Vesker }
141826d688e3SAlex Vesker 
141926d688e3SAlex Vesker static int dr_ste_build_eth_l2_src_tag(struct mlx5dr_match_param *value,
142026d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
142126d688e3SAlex Vesker 				       u8 *hw_ste_p)
142226d688e3SAlex Vesker {
142326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
142426d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
142526d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
142626d688e3SAlex Vesker 
142726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, smac_47_16, spec, smac_47_16);
142826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_src, tag, smac_15_0, spec, smac_15_0);
142926d688e3SAlex Vesker 
143026d688e3SAlex Vesker 	return dr_ste_build_eth_l2_src_or_dst_tag(value, sb->inner, hw_ste_p);
143126d688e3SAlex Vesker }
143226d688e3SAlex Vesker 
143326d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_src(struct mlx5dr_ste_build *sb,
143426d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
143526d688e3SAlex Vesker 				 bool inner, bool rx)
143626d688e3SAlex Vesker {
143726d688e3SAlex Vesker 	dr_ste_build_eth_l2_src_bit_mask(mask, inner, sb->bit_mask);
143826d688e3SAlex Vesker 	sb->rx = rx;
143926d688e3SAlex Vesker 	sb->inner = inner;
144026d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_SRC, rx, inner);
144126d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
144226d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_src_tag;
144326d688e3SAlex Vesker }
144426d688e3SAlex Vesker 
144526d688e3SAlex Vesker static void dr_ste_build_eth_l2_dst_bit_mask(struct mlx5dr_match_param *value,
144626d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
144726d688e3SAlex Vesker {
144826d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
144926d688e3SAlex Vesker 
145026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_dst, bit_mask, dmac_47_16, mask, dmac_47_16);
145126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_dst, bit_mask, dmac_15_0, mask, dmac_15_0);
145226d688e3SAlex Vesker 
145326d688e3SAlex Vesker 	dr_ste_build_eth_l2_src_or_dst_bit_mask(value, inner, bit_mask);
145426d688e3SAlex Vesker }
145526d688e3SAlex Vesker 
145626d688e3SAlex Vesker static int dr_ste_build_eth_l2_dst_tag(struct mlx5dr_match_param *value,
145726d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
145826d688e3SAlex Vesker 				       u8 *hw_ste_p)
145926d688e3SAlex Vesker {
146026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
146126d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
146226d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
146326d688e3SAlex Vesker 
146426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_dst, tag, dmac_47_16, spec, dmac_47_16);
146526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_dst, tag, dmac_15_0, spec, dmac_15_0);
146626d688e3SAlex Vesker 
146726d688e3SAlex Vesker 	return dr_ste_build_eth_l2_src_or_dst_tag(value, sb->inner, hw_ste_p);
146826d688e3SAlex Vesker }
146926d688e3SAlex Vesker 
147026d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_dst(struct mlx5dr_ste_build *sb,
147126d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
147226d688e3SAlex Vesker 				 bool inner, bool rx)
147326d688e3SAlex Vesker {
147426d688e3SAlex Vesker 	dr_ste_build_eth_l2_dst_bit_mask(mask, inner, sb->bit_mask);
147526d688e3SAlex Vesker 
147626d688e3SAlex Vesker 	sb->rx = rx;
147726d688e3SAlex Vesker 	sb->inner = inner;
147826d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL2_DST, rx, inner);
147926d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
148026d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_dst_tag;
148126d688e3SAlex Vesker }
148226d688e3SAlex Vesker 
148326d688e3SAlex Vesker static void dr_ste_build_eth_l2_tnl_bit_mask(struct mlx5dr_match_param *value,
148426d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
148526d688e3SAlex Vesker {
148626d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
148726d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc = &value->misc;
148826d688e3SAlex Vesker 
148926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, dmac_47_16, mask, dmac_47_16);
149026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, dmac_15_0, mask, dmac_15_0);
149126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_vlan_id, mask, first_vid);
149226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_cfi, mask, first_cfi);
149326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, first_priority, mask, first_prio);
149426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, ip_fragmented, mask, frag);
149526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l2_tnl, bit_mask, l3_ethertype, mask, ethertype);
149626d688e3SAlex Vesker 	DR_STE_SET_MASK(eth_l2_tnl, bit_mask, l3_type, mask, ip_version);
149726d688e3SAlex Vesker 
149826d688e3SAlex Vesker 	if (misc->vxlan_vni) {
149926d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, bit_mask,
150026d688e3SAlex Vesker 			 l2_tunneling_network_id, (misc->vxlan_vni << 8));
150126d688e3SAlex Vesker 		misc->vxlan_vni = 0;
150226d688e3SAlex Vesker 	}
150326d688e3SAlex Vesker 
150426d688e3SAlex Vesker 	if (mask->svlan_tag || mask->cvlan_tag) {
150526d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, bit_mask, first_vlan_qualifier, -1);
150626d688e3SAlex Vesker 		mask->cvlan_tag = 0;
150726d688e3SAlex Vesker 		mask->svlan_tag = 0;
150826d688e3SAlex Vesker 	}
150926d688e3SAlex Vesker }
151026d688e3SAlex Vesker 
151126d688e3SAlex Vesker static int dr_ste_build_eth_l2_tnl_tag(struct mlx5dr_match_param *value,
151226d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
151326d688e3SAlex Vesker 				       u8 *hw_ste_p)
151426d688e3SAlex Vesker {
151526d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
151626d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
151726d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc = &value->misc;
151826d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
151926d688e3SAlex Vesker 
152026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, dmac_47_16, spec, dmac_47_16);
152126d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, dmac_15_0, spec, dmac_15_0);
152226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, first_vlan_id, spec, first_vid);
152326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, first_cfi, spec, first_cfi);
152426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, ip_fragmented, spec, frag);
152526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, first_priority, spec, first_prio);
152626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l2_tnl, tag, l3_ethertype, spec, ethertype);
152726d688e3SAlex Vesker 
152826d688e3SAlex Vesker 	if (misc->vxlan_vni) {
152926d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, tag, l2_tunneling_network_id,
153026d688e3SAlex Vesker 			 (misc->vxlan_vni << 8));
153126d688e3SAlex Vesker 		misc->vxlan_vni = 0;
153226d688e3SAlex Vesker 	}
153326d688e3SAlex Vesker 
153426d688e3SAlex Vesker 	if (spec->cvlan_tag) {
153526d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, tag, first_vlan_qualifier, DR_STE_CVLAN);
153626d688e3SAlex Vesker 		spec->cvlan_tag = 0;
153726d688e3SAlex Vesker 	} else if (spec->svlan_tag) {
153826d688e3SAlex Vesker 		MLX5_SET(ste_eth_l2_tnl, tag, first_vlan_qualifier, DR_STE_SVLAN);
153926d688e3SAlex Vesker 		spec->svlan_tag = 0;
154026d688e3SAlex Vesker 	}
154126d688e3SAlex Vesker 
154226d688e3SAlex Vesker 	if (spec->ip_version) {
154326d688e3SAlex Vesker 		if (spec->ip_version == IP_VERSION_IPV4) {
154426d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_tnl, tag, l3_type, STE_IPV4);
154526d688e3SAlex Vesker 			spec->ip_version = 0;
154626d688e3SAlex Vesker 		} else if (spec->ip_version == IP_VERSION_IPV6) {
154726d688e3SAlex Vesker 			MLX5_SET(ste_eth_l2_tnl, tag, l3_type, STE_IPV6);
154826d688e3SAlex Vesker 			spec->ip_version = 0;
154926d688e3SAlex Vesker 		} else {
155026d688e3SAlex Vesker 			return -EINVAL;
155126d688e3SAlex Vesker 		}
155226d688e3SAlex Vesker 	}
155326d688e3SAlex Vesker 
155426d688e3SAlex Vesker 	return 0;
155526d688e3SAlex Vesker }
155626d688e3SAlex Vesker 
155726d688e3SAlex Vesker void mlx5dr_ste_build_eth_l2_tnl(struct mlx5dr_ste_build *sb,
155826d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask, bool inner, bool rx)
155926d688e3SAlex Vesker {
156026d688e3SAlex Vesker 	dr_ste_build_eth_l2_tnl_bit_mask(mask, inner, sb->bit_mask);
156126d688e3SAlex Vesker 
156226d688e3SAlex Vesker 	sb->rx = rx;
156326d688e3SAlex Vesker 	sb->inner = inner;
156426d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_ETHL2_TUNNELING_I;
156526d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
156626d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l2_tnl_tag;
156726d688e3SAlex Vesker }
156826d688e3SAlex Vesker 
156926d688e3SAlex Vesker static void dr_ste_build_eth_l3_ipv4_misc_bit_mask(struct mlx5dr_match_param *value,
157026d688e3SAlex Vesker 						   bool inner, u8 *bit_mask)
157126d688e3SAlex Vesker {
157226d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
157326d688e3SAlex Vesker 
157426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l3_ipv4_misc, bit_mask, time_to_live, mask, ttl_hoplimit);
157526d688e3SAlex Vesker }
157626d688e3SAlex Vesker 
157726d688e3SAlex Vesker static int dr_ste_build_eth_l3_ipv4_misc_tag(struct mlx5dr_match_param *value,
157826d688e3SAlex Vesker 					     struct mlx5dr_ste_build *sb,
157926d688e3SAlex Vesker 					     u8 *hw_ste_p)
158026d688e3SAlex Vesker {
158126d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
158226d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
158326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
158426d688e3SAlex Vesker 
158526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l3_ipv4_misc, tag, time_to_live, spec, ttl_hoplimit);
158626d688e3SAlex Vesker 
158726d688e3SAlex Vesker 	return 0;
158826d688e3SAlex Vesker }
158926d688e3SAlex Vesker 
159026d688e3SAlex Vesker void mlx5dr_ste_build_eth_l3_ipv4_misc(struct mlx5dr_ste_build *sb,
159126d688e3SAlex Vesker 				       struct mlx5dr_match_param *mask,
159226d688e3SAlex Vesker 				       bool inner, bool rx)
159326d688e3SAlex Vesker {
159426d688e3SAlex Vesker 	dr_ste_build_eth_l3_ipv4_misc_bit_mask(mask, inner, sb->bit_mask);
159526d688e3SAlex Vesker 
159626d688e3SAlex Vesker 	sb->rx = rx;
159726d688e3SAlex Vesker 	sb->inner = inner;
159826d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL3_IPV4_MISC, rx, inner);
159926d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
160026d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l3_ipv4_misc_tag;
160126d688e3SAlex Vesker }
160226d688e3SAlex Vesker 
160326d688e3SAlex Vesker static void dr_ste_build_ipv6_l3_l4_bit_mask(struct mlx5dr_match_param *value,
160426d688e3SAlex Vesker 					     bool inner, u8 *bit_mask)
160526d688e3SAlex Vesker {
160626d688e3SAlex Vesker 	struct mlx5dr_match_spec *mask = inner ? &value->inner : &value->outer;
160726d688e3SAlex Vesker 
160826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, dst_port, mask, tcp_dport);
160926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, src_port, mask, tcp_sport);
161026d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, dst_port, mask, udp_dport);
161126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, src_port, mask, udp_sport);
161226d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, protocol, mask, ip_protocol);
161326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, fragmented, mask, frag);
161426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, dscp, mask, ip_dscp);
161526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, ecn, mask, ip_ecn);
161626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(eth_l4, bit_mask, ipv6_hop_limit, mask, ttl_hoplimit);
161726d688e3SAlex Vesker 
161826d688e3SAlex Vesker 	if (mask->tcp_flags) {
161926d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l4, bit_mask, mask);
162026d688e3SAlex Vesker 		mask->tcp_flags = 0;
162126d688e3SAlex Vesker 	}
162226d688e3SAlex Vesker }
162326d688e3SAlex Vesker 
162426d688e3SAlex Vesker static int dr_ste_build_ipv6_l3_l4_tag(struct mlx5dr_match_param *value,
162526d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
162626d688e3SAlex Vesker 				       u8 *hw_ste_p)
162726d688e3SAlex Vesker {
162826d688e3SAlex Vesker 	struct mlx5dr_match_spec *spec = sb->inner ? &value->inner : &value->outer;
162926d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
163026d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
163126d688e3SAlex Vesker 
163226d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, dst_port, spec, tcp_dport);
163326d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, src_port, spec, tcp_sport);
163426d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, dst_port, spec, udp_dport);
163526d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, src_port, spec, udp_sport);
163626d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, protocol, spec, ip_protocol);
163726d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, fragmented, spec, frag);
163826d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, dscp, spec, ip_dscp);
163926d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, ecn, spec, ip_ecn);
164026d688e3SAlex Vesker 	DR_STE_SET_TAG(eth_l4, tag, ipv6_hop_limit, spec, ttl_hoplimit);
164126d688e3SAlex Vesker 
164226d688e3SAlex Vesker 	if (spec->tcp_flags) {
164326d688e3SAlex Vesker 		DR_STE_SET_TCP_FLAGS(eth_l4, tag, spec);
164426d688e3SAlex Vesker 		spec->tcp_flags = 0;
164526d688e3SAlex Vesker 	}
164626d688e3SAlex Vesker 
164726d688e3SAlex Vesker 	return 0;
164826d688e3SAlex Vesker }
164926d688e3SAlex Vesker 
165026d688e3SAlex Vesker void mlx5dr_ste_build_ipv6_l3_l4(struct mlx5dr_ste_build *sb,
165126d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
165226d688e3SAlex Vesker 				 bool inner, bool rx)
165326d688e3SAlex Vesker {
165426d688e3SAlex Vesker 	dr_ste_build_ipv6_l3_l4_bit_mask(mask, inner, sb->bit_mask);
165526d688e3SAlex Vesker 
165626d688e3SAlex Vesker 	sb->rx = rx;
165726d688e3SAlex Vesker 	sb->inner = inner;
165826d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL4, rx, inner);
165926d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
166026d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_ipv6_l3_l4_tag;
166126d688e3SAlex Vesker }
166226d688e3SAlex Vesker 
166326d688e3SAlex Vesker static int dr_ste_build_empty_always_hit_tag(struct mlx5dr_match_param *value,
166426d688e3SAlex Vesker 					     struct mlx5dr_ste_build *sb,
166526d688e3SAlex Vesker 					     u8 *hw_ste_p)
166626d688e3SAlex Vesker {
166726d688e3SAlex Vesker 	return 0;
166826d688e3SAlex Vesker }
166926d688e3SAlex Vesker 
167026d688e3SAlex Vesker void mlx5dr_ste_build_empty_always_hit(struct mlx5dr_ste_build *sb, bool rx)
167126d688e3SAlex Vesker {
167226d688e3SAlex Vesker 	sb->rx = rx;
167326d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_DONT_CARE;
167426d688e3SAlex Vesker 	sb->byte_mask = 0;
167526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_empty_always_hit_tag;
167626d688e3SAlex Vesker }
167726d688e3SAlex Vesker 
167826d688e3SAlex Vesker static void dr_ste_build_mpls_bit_mask(struct mlx5dr_match_param *value,
167926d688e3SAlex Vesker 				       bool inner, u8 *bit_mask)
168026d688e3SAlex Vesker {
168126d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2_mask = &value->misc2;
168226d688e3SAlex Vesker 
168326d688e3SAlex Vesker 	if (inner)
168426d688e3SAlex Vesker 		DR_STE_SET_MPLS_MASK(mpls, misc2_mask, inner, bit_mask);
168526d688e3SAlex Vesker 	else
168626d688e3SAlex Vesker 		DR_STE_SET_MPLS_MASK(mpls, misc2_mask, outer, bit_mask);
168726d688e3SAlex Vesker }
168826d688e3SAlex Vesker 
168926d688e3SAlex Vesker static int dr_ste_build_mpls_tag(struct mlx5dr_match_param *value,
169026d688e3SAlex Vesker 				 struct mlx5dr_ste_build *sb,
169126d688e3SAlex Vesker 				 u8 *hw_ste_p)
169226d688e3SAlex Vesker {
169326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
169426d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2_mask = &value->misc2;
169526d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
169626d688e3SAlex Vesker 
169726d688e3SAlex Vesker 	if (sb->inner)
169826d688e3SAlex Vesker 		DR_STE_SET_MPLS_TAG(mpls, misc2_mask, inner, tag);
169926d688e3SAlex Vesker 	else
170026d688e3SAlex Vesker 		DR_STE_SET_MPLS_TAG(mpls, misc2_mask, outer, tag);
170126d688e3SAlex Vesker 
170226d688e3SAlex Vesker 	return 0;
170326d688e3SAlex Vesker }
170426d688e3SAlex Vesker 
170526d688e3SAlex Vesker void mlx5dr_ste_build_mpls(struct mlx5dr_ste_build *sb,
170626d688e3SAlex Vesker 			   struct mlx5dr_match_param *mask,
170726d688e3SAlex Vesker 			   bool inner, bool rx)
170826d688e3SAlex Vesker {
170926d688e3SAlex Vesker 	dr_ste_build_mpls_bit_mask(mask, inner, sb->bit_mask);
171026d688e3SAlex Vesker 
171126d688e3SAlex Vesker 	sb->rx = rx;
171226d688e3SAlex Vesker 	sb->inner = inner;
171326d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(MPLS_FIRST, rx, inner);
171426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
171526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_mpls_tag;
171626d688e3SAlex Vesker }
171726d688e3SAlex Vesker 
171826d688e3SAlex Vesker static void dr_ste_build_gre_bit_mask(struct mlx5dr_match_param *value,
171926d688e3SAlex Vesker 				      bool inner, u8 *bit_mask)
172026d688e3SAlex Vesker {
172126d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_mask = &value->misc;
172226d688e3SAlex Vesker 
172326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_protocol, misc_mask, gre_protocol);
172426d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_k_present, misc_mask, gre_k_present);
172526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_key_h, misc_mask, gre_key_h);
172626d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_key_l, misc_mask, gre_key_l);
172726d688e3SAlex Vesker 
172826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_c_present, misc_mask, gre_c_present);
172926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(gre, bit_mask, gre_s_present, misc_mask, gre_s_present);
173026d688e3SAlex Vesker }
173126d688e3SAlex Vesker 
173226d688e3SAlex Vesker static int dr_ste_build_gre_tag(struct mlx5dr_match_param *value,
173326d688e3SAlex Vesker 				struct mlx5dr_ste_build *sb,
173426d688e3SAlex Vesker 				u8 *hw_ste_p)
173526d688e3SAlex Vesker {
173626d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
173726d688e3SAlex Vesker 	struct  mlx5dr_match_misc *misc = &value->misc;
173826d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
173926d688e3SAlex Vesker 
174026d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_protocol, misc, gre_protocol);
174126d688e3SAlex Vesker 
174226d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_k_present, misc, gre_k_present);
174326d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_key_h, misc, gre_key_h);
174426d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_key_l, misc, gre_key_l);
174526d688e3SAlex Vesker 
174626d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_c_present, misc, gre_c_present);
174726d688e3SAlex Vesker 
174826d688e3SAlex Vesker 	DR_STE_SET_TAG(gre, tag, gre_s_present, misc, gre_s_present);
174926d688e3SAlex Vesker 
175026d688e3SAlex Vesker 	return 0;
175126d688e3SAlex Vesker }
175226d688e3SAlex Vesker 
175326d688e3SAlex Vesker void mlx5dr_ste_build_gre(struct mlx5dr_ste_build *sb,
175426d688e3SAlex Vesker 			  struct mlx5dr_match_param *mask, bool inner, bool rx)
175526d688e3SAlex Vesker {
175626d688e3SAlex Vesker 	dr_ste_build_gre_bit_mask(mask, inner, sb->bit_mask);
175726d688e3SAlex Vesker 
175826d688e3SAlex Vesker 	sb->rx = rx;
175926d688e3SAlex Vesker 	sb->inner = inner;
176026d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_GRE;
176126d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
176226d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_gre_tag;
176326d688e3SAlex Vesker }
176426d688e3SAlex Vesker 
176526d688e3SAlex Vesker static void dr_ste_build_flex_parser_0_bit_mask(struct mlx5dr_match_param *value,
176626d688e3SAlex Vesker 						bool inner, u8 *bit_mask)
176726d688e3SAlex Vesker {
176826d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
176926d688e3SAlex Vesker 
177026d688e3SAlex Vesker 	if (DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(misc_2_mask)) {
177126d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_label,
177226d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_label);
177326d688e3SAlex Vesker 
177426d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_exp,
177526d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_exp);
177626d688e3SAlex Vesker 
177726d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_s_bos,
177826d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_s_bos);
177926d688e3SAlex Vesker 
178026d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_ttl,
178126d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_gre_ttl);
178226d688e3SAlex Vesker 	} else {
178326d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_label,
178426d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_label);
178526d688e3SAlex Vesker 
178626d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_exp,
178726d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_exp);
178826d688e3SAlex Vesker 
178926d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_s_bos,
179026d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_s_bos);
179126d688e3SAlex Vesker 
179226d688e3SAlex Vesker 		DR_STE_SET_MASK_V(flex_parser_0, bit_mask, parser_3_ttl,
179326d688e3SAlex Vesker 				  misc_2_mask, outer_first_mpls_over_udp_ttl);
179426d688e3SAlex Vesker 	}
179526d688e3SAlex Vesker }
179626d688e3SAlex Vesker 
179726d688e3SAlex Vesker static int dr_ste_build_flex_parser_0_tag(struct mlx5dr_match_param *value,
179826d688e3SAlex Vesker 					  struct mlx5dr_ste_build *sb,
179926d688e3SAlex Vesker 					  u8 *hw_ste_p)
180026d688e3SAlex Vesker {
180126d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
180226d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
180326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
180426d688e3SAlex Vesker 
180526d688e3SAlex Vesker 	if (DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(misc_2_mask)) {
180626d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_label,
180726d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_label);
180826d688e3SAlex Vesker 
180926d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_exp,
181026d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_exp);
181126d688e3SAlex Vesker 
181226d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_s_bos,
181326d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_s_bos);
181426d688e3SAlex Vesker 
181526d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_ttl,
181626d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_gre_ttl);
181726d688e3SAlex Vesker 	} else {
181826d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_label,
181926d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_label);
182026d688e3SAlex Vesker 
182126d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_exp,
182226d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_exp);
182326d688e3SAlex Vesker 
182426d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_s_bos,
182526d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_s_bos);
182626d688e3SAlex Vesker 
182726d688e3SAlex Vesker 		DR_STE_SET_TAG(flex_parser_0, tag, parser_3_ttl,
182826d688e3SAlex Vesker 			       misc_2_mask, outer_first_mpls_over_udp_ttl);
182926d688e3SAlex Vesker 	}
183026d688e3SAlex Vesker 	return 0;
183126d688e3SAlex Vesker }
183226d688e3SAlex Vesker 
183326d688e3SAlex Vesker void mlx5dr_ste_build_flex_parser_0(struct mlx5dr_ste_build *sb,
183426d688e3SAlex Vesker 				    struct mlx5dr_match_param *mask,
183526d688e3SAlex Vesker 				    bool inner, bool rx)
183626d688e3SAlex Vesker {
183726d688e3SAlex Vesker 	dr_ste_build_flex_parser_0_bit_mask(mask, inner, sb->bit_mask);
183826d688e3SAlex Vesker 
183926d688e3SAlex Vesker 	sb->rx = rx;
184026d688e3SAlex Vesker 	sb->inner = inner;
184126d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_0;
184226d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
184326d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_0_tag;
184426d688e3SAlex Vesker }
184526d688e3SAlex Vesker 
184626d688e3SAlex Vesker #define ICMP_TYPE_OFFSET_FIRST_DW		24
184726d688e3SAlex Vesker #define ICMP_CODE_OFFSET_FIRST_DW		16
184826d688e3SAlex Vesker #define ICMP_HEADER_DATA_OFFSET_SECOND_DW	0
184926d688e3SAlex Vesker 
185026d688e3SAlex Vesker static int dr_ste_build_flex_parser_1_bit_mask(struct mlx5dr_match_param *mask,
185126d688e3SAlex Vesker 					       struct mlx5dr_cmd_caps *caps,
185226d688e3SAlex Vesker 					       u8 *bit_mask)
185326d688e3SAlex Vesker {
185426d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3_mask = &mask->misc3;
185526d688e3SAlex Vesker 	bool is_ipv4_mask = DR_MASK_IS_FLEX_PARSER_ICMPV4_SET(misc_3_mask);
185626d688e3SAlex Vesker 	u32 icmp_header_data_mask;
185726d688e3SAlex Vesker 	u32 icmp_type_mask;
185826d688e3SAlex Vesker 	u32 icmp_code_mask;
185926d688e3SAlex Vesker 	int dw0_location;
186026d688e3SAlex Vesker 	int dw1_location;
186126d688e3SAlex Vesker 
186226d688e3SAlex Vesker 	if (is_ipv4_mask) {
186326d688e3SAlex Vesker 		icmp_header_data_mask	= misc_3_mask->icmpv4_header_data;
186426d688e3SAlex Vesker 		icmp_type_mask		= misc_3_mask->icmpv4_type;
186526d688e3SAlex Vesker 		icmp_code_mask		= misc_3_mask->icmpv4_code;
186626d688e3SAlex Vesker 		dw0_location		= caps->flex_parser_id_icmp_dw0;
186726d688e3SAlex Vesker 		dw1_location		= caps->flex_parser_id_icmp_dw1;
186826d688e3SAlex Vesker 	} else {
186926d688e3SAlex Vesker 		icmp_header_data_mask	= misc_3_mask->icmpv6_header_data;
187026d688e3SAlex Vesker 		icmp_type_mask		= misc_3_mask->icmpv6_type;
187126d688e3SAlex Vesker 		icmp_code_mask		= misc_3_mask->icmpv6_code;
187226d688e3SAlex Vesker 		dw0_location		= caps->flex_parser_id_icmpv6_dw0;
187326d688e3SAlex Vesker 		dw1_location		= caps->flex_parser_id_icmpv6_dw1;
187426d688e3SAlex Vesker 	}
187526d688e3SAlex Vesker 
187626d688e3SAlex Vesker 	switch (dw0_location) {
187726d688e3SAlex Vesker 	case 4:
187826d688e3SAlex Vesker 		if (icmp_type_mask) {
187926d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_4,
188026d688e3SAlex Vesker 				 (icmp_type_mask << ICMP_TYPE_OFFSET_FIRST_DW));
188126d688e3SAlex Vesker 			if (is_ipv4_mask)
188226d688e3SAlex Vesker 				misc_3_mask->icmpv4_type = 0;
188326d688e3SAlex Vesker 			else
188426d688e3SAlex Vesker 				misc_3_mask->icmpv6_type = 0;
188526d688e3SAlex Vesker 		}
188626d688e3SAlex Vesker 		if (icmp_code_mask) {
188726d688e3SAlex Vesker 			u32 cur_val = MLX5_GET(ste_flex_parser_1, bit_mask,
188826d688e3SAlex Vesker 					       flex_parser_4);
188926d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_4,
189026d688e3SAlex Vesker 				 cur_val | (icmp_code_mask << ICMP_CODE_OFFSET_FIRST_DW));
189126d688e3SAlex Vesker 			if (is_ipv4_mask)
189226d688e3SAlex Vesker 				misc_3_mask->icmpv4_code = 0;
189326d688e3SAlex Vesker 			else
189426d688e3SAlex Vesker 				misc_3_mask->icmpv6_code = 0;
189526d688e3SAlex Vesker 		}
189626d688e3SAlex Vesker 		break;
189726d688e3SAlex Vesker 	default:
189826d688e3SAlex Vesker 		return -EINVAL;
189926d688e3SAlex Vesker 	}
190026d688e3SAlex Vesker 
190126d688e3SAlex Vesker 	switch (dw1_location) {
190226d688e3SAlex Vesker 	case 5:
190326d688e3SAlex Vesker 		if (icmp_header_data_mask) {
190426d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, bit_mask, flex_parser_5,
190526d688e3SAlex Vesker 				 (icmp_header_data_mask << ICMP_HEADER_DATA_OFFSET_SECOND_DW));
190626d688e3SAlex Vesker 			if (is_ipv4_mask)
190726d688e3SAlex Vesker 				misc_3_mask->icmpv4_header_data = 0;
190826d688e3SAlex Vesker 			else
190926d688e3SAlex Vesker 				misc_3_mask->icmpv6_header_data = 0;
191026d688e3SAlex Vesker 		}
191126d688e3SAlex Vesker 		break;
191226d688e3SAlex Vesker 	default:
191326d688e3SAlex Vesker 		return -EINVAL;
191426d688e3SAlex Vesker 	}
191526d688e3SAlex Vesker 
191626d688e3SAlex Vesker 	return 0;
191726d688e3SAlex Vesker }
191826d688e3SAlex Vesker 
191926d688e3SAlex Vesker static int dr_ste_build_flex_parser_1_tag(struct mlx5dr_match_param *value,
192026d688e3SAlex Vesker 					  struct mlx5dr_ste_build *sb,
192126d688e3SAlex Vesker 					  u8 *hw_ste_p)
192226d688e3SAlex Vesker {
192326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
192426d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3 = &value->misc3;
192526d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
192626d688e3SAlex Vesker 	u32 icmp_header_data;
192726d688e3SAlex Vesker 	int dw0_location;
192826d688e3SAlex Vesker 	int dw1_location;
192926d688e3SAlex Vesker 	u32 icmp_type;
193026d688e3SAlex Vesker 	u32 icmp_code;
193126d688e3SAlex Vesker 	bool is_ipv4;
193226d688e3SAlex Vesker 
193326d688e3SAlex Vesker 	is_ipv4 = DR_MASK_IS_FLEX_PARSER_ICMPV4_SET(misc_3);
193426d688e3SAlex Vesker 	if (is_ipv4) {
193526d688e3SAlex Vesker 		icmp_header_data	= misc_3->icmpv4_header_data;
193626d688e3SAlex Vesker 		icmp_type		= misc_3->icmpv4_type;
193726d688e3SAlex Vesker 		icmp_code		= misc_3->icmpv4_code;
193826d688e3SAlex Vesker 		dw0_location		= sb->caps->flex_parser_id_icmp_dw0;
193926d688e3SAlex Vesker 		dw1_location		= sb->caps->flex_parser_id_icmp_dw1;
194026d688e3SAlex Vesker 	} else {
194126d688e3SAlex Vesker 		icmp_header_data	= misc_3->icmpv6_header_data;
194226d688e3SAlex Vesker 		icmp_type		= misc_3->icmpv6_type;
194326d688e3SAlex Vesker 		icmp_code		= misc_3->icmpv6_code;
194426d688e3SAlex Vesker 		dw0_location		= sb->caps->flex_parser_id_icmpv6_dw0;
194526d688e3SAlex Vesker 		dw1_location		= sb->caps->flex_parser_id_icmpv6_dw1;
194626d688e3SAlex Vesker 	}
194726d688e3SAlex Vesker 
194826d688e3SAlex Vesker 	switch (dw0_location) {
194926d688e3SAlex Vesker 	case 4:
195026d688e3SAlex Vesker 		if (icmp_type) {
195126d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, tag, flex_parser_4,
195226d688e3SAlex Vesker 				 (icmp_type << ICMP_TYPE_OFFSET_FIRST_DW));
195326d688e3SAlex Vesker 			if (is_ipv4)
195426d688e3SAlex Vesker 				misc_3->icmpv4_type = 0;
195526d688e3SAlex Vesker 			else
195626d688e3SAlex Vesker 				misc_3->icmpv6_type = 0;
195726d688e3SAlex Vesker 		}
195826d688e3SAlex Vesker 
195926d688e3SAlex Vesker 		if (icmp_code) {
196026d688e3SAlex Vesker 			u32 cur_val = MLX5_GET(ste_flex_parser_1, tag,
196126d688e3SAlex Vesker 					       flex_parser_4);
196226d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, tag, flex_parser_4,
196326d688e3SAlex Vesker 				 cur_val | (icmp_code << ICMP_CODE_OFFSET_FIRST_DW));
196426d688e3SAlex Vesker 			if (is_ipv4)
196526d688e3SAlex Vesker 				misc_3->icmpv4_code = 0;
196626d688e3SAlex Vesker 			else
196726d688e3SAlex Vesker 				misc_3->icmpv6_code = 0;
196826d688e3SAlex Vesker 		}
196926d688e3SAlex Vesker 		break;
197026d688e3SAlex Vesker 	default:
197126d688e3SAlex Vesker 		return -EINVAL;
197226d688e3SAlex Vesker 	}
197326d688e3SAlex Vesker 
197426d688e3SAlex Vesker 	switch (dw1_location) {
197526d688e3SAlex Vesker 	case 5:
197626d688e3SAlex Vesker 		if (icmp_header_data) {
197726d688e3SAlex Vesker 			MLX5_SET(ste_flex_parser_1, tag, flex_parser_5,
197826d688e3SAlex Vesker 				 (icmp_header_data << ICMP_HEADER_DATA_OFFSET_SECOND_DW));
197926d688e3SAlex Vesker 			if (is_ipv4)
198026d688e3SAlex Vesker 				misc_3->icmpv4_header_data = 0;
198126d688e3SAlex Vesker 			else
198226d688e3SAlex Vesker 				misc_3->icmpv6_header_data = 0;
198326d688e3SAlex Vesker 		}
198426d688e3SAlex Vesker 		break;
198526d688e3SAlex Vesker 	default:
198626d688e3SAlex Vesker 		return -EINVAL;
198726d688e3SAlex Vesker 	}
198826d688e3SAlex Vesker 
198926d688e3SAlex Vesker 	return 0;
199026d688e3SAlex Vesker }
199126d688e3SAlex Vesker 
199226d688e3SAlex Vesker int mlx5dr_ste_build_flex_parser_1(struct mlx5dr_ste_build *sb,
199326d688e3SAlex Vesker 				   struct mlx5dr_match_param *mask,
199426d688e3SAlex Vesker 				   struct mlx5dr_cmd_caps *caps,
199526d688e3SAlex Vesker 				   bool inner, bool rx)
199626d688e3SAlex Vesker {
199726d688e3SAlex Vesker 	int ret;
199826d688e3SAlex Vesker 
199926d688e3SAlex Vesker 	ret = dr_ste_build_flex_parser_1_bit_mask(mask, caps, sb->bit_mask);
200026d688e3SAlex Vesker 	if (ret)
200126d688e3SAlex Vesker 		return ret;
200226d688e3SAlex Vesker 
200326d688e3SAlex Vesker 	sb->rx = rx;
200426d688e3SAlex Vesker 	sb->inner = inner;
200526d688e3SAlex Vesker 	sb->caps = caps;
200626d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_1;
200726d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
200826d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_1_tag;
200926d688e3SAlex Vesker 
201026d688e3SAlex Vesker 	return 0;
201126d688e3SAlex Vesker }
201226d688e3SAlex Vesker 
201326d688e3SAlex Vesker static void dr_ste_build_general_purpose_bit_mask(struct mlx5dr_match_param *value,
201426d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
201526d688e3SAlex Vesker {
201626d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
201726d688e3SAlex Vesker 
201826d688e3SAlex Vesker 	DR_STE_SET_MASK_V(general_purpose, bit_mask,
201926d688e3SAlex Vesker 			  general_purpose_lookup_field, misc_2_mask,
202026d688e3SAlex Vesker 			  metadata_reg_a);
202126d688e3SAlex Vesker }
202226d688e3SAlex Vesker 
202326d688e3SAlex Vesker static int dr_ste_build_general_purpose_tag(struct mlx5dr_match_param *value,
202426d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
202526d688e3SAlex Vesker 					    u8 *hw_ste_p)
202626d688e3SAlex Vesker {
202726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
202826d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
202926d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
203026d688e3SAlex Vesker 
203126d688e3SAlex Vesker 	DR_STE_SET_TAG(general_purpose, tag, general_purpose_lookup_field,
203226d688e3SAlex Vesker 		       misc_2_mask, metadata_reg_a);
203326d688e3SAlex Vesker 
203426d688e3SAlex Vesker 	return 0;
203526d688e3SAlex Vesker }
203626d688e3SAlex Vesker 
203726d688e3SAlex Vesker void mlx5dr_ste_build_general_purpose(struct mlx5dr_ste_build *sb,
203826d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
203926d688e3SAlex Vesker 				      bool inner, bool rx)
204026d688e3SAlex Vesker {
204126d688e3SAlex Vesker 	dr_ste_build_general_purpose_bit_mask(mask, inner, sb->bit_mask);
204226d688e3SAlex Vesker 
204326d688e3SAlex Vesker 	sb->rx = rx;
204426d688e3SAlex Vesker 	sb->inner = inner;
204526d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_GENERAL_PURPOSE;
204626d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
204726d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_general_purpose_tag;
204826d688e3SAlex Vesker }
204926d688e3SAlex Vesker 
205026d688e3SAlex Vesker static void dr_ste_build_eth_l4_misc_bit_mask(struct mlx5dr_match_param *value,
205126d688e3SAlex Vesker 					      bool inner, u8 *bit_mask)
205226d688e3SAlex Vesker {
205326d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3_mask = &value->misc3;
205426d688e3SAlex Vesker 
205526d688e3SAlex Vesker 	if (inner) {
205626d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, seq_num, misc_3_mask,
205726d688e3SAlex Vesker 				  inner_tcp_seq_num);
205826d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, ack_num, misc_3_mask,
205926d688e3SAlex Vesker 				  inner_tcp_ack_num);
206026d688e3SAlex Vesker 	} else {
206126d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, seq_num, misc_3_mask,
206226d688e3SAlex Vesker 				  outer_tcp_seq_num);
206326d688e3SAlex Vesker 		DR_STE_SET_MASK_V(eth_l4_misc, bit_mask, ack_num, misc_3_mask,
206426d688e3SAlex Vesker 				  outer_tcp_ack_num);
206526d688e3SAlex Vesker 	}
206626d688e3SAlex Vesker }
206726d688e3SAlex Vesker 
206826d688e3SAlex Vesker static int dr_ste_build_eth_l4_misc_tag(struct mlx5dr_match_param *value,
206926d688e3SAlex Vesker 					struct mlx5dr_ste_build *sb,
207026d688e3SAlex Vesker 					u8 *hw_ste_p)
207126d688e3SAlex Vesker {
207226d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
207326d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc3 = &value->misc3;
207426d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
207526d688e3SAlex Vesker 
207626d688e3SAlex Vesker 	if (sb->inner) {
207726d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, seq_num, misc3, inner_tcp_seq_num);
207826d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, ack_num, misc3, inner_tcp_ack_num);
207926d688e3SAlex Vesker 	} else {
208026d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, seq_num, misc3, outer_tcp_seq_num);
208126d688e3SAlex Vesker 		DR_STE_SET_TAG(eth_l4_misc, tag, ack_num, misc3, outer_tcp_ack_num);
208226d688e3SAlex Vesker 	}
208326d688e3SAlex Vesker 
208426d688e3SAlex Vesker 	return 0;
208526d688e3SAlex Vesker }
208626d688e3SAlex Vesker 
208726d688e3SAlex Vesker void mlx5dr_ste_build_eth_l4_misc(struct mlx5dr_ste_build *sb,
208826d688e3SAlex Vesker 				  struct mlx5dr_match_param *mask,
208926d688e3SAlex Vesker 				  bool inner, bool rx)
209026d688e3SAlex Vesker {
209126d688e3SAlex Vesker 	dr_ste_build_eth_l4_misc_bit_mask(mask, inner, sb->bit_mask);
209226d688e3SAlex Vesker 
209326d688e3SAlex Vesker 	sb->rx = rx;
209426d688e3SAlex Vesker 	sb->inner = inner;
209526d688e3SAlex Vesker 	sb->lu_type = DR_STE_CALC_LU_TYPE(ETHL4_MISC, rx, inner);
209626d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
209726d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_eth_l4_misc_tag;
209826d688e3SAlex Vesker }
209926d688e3SAlex Vesker 
210026d688e3SAlex Vesker static void dr_ste_build_flex_parser_tnl_bit_mask(struct mlx5dr_match_param *value,
210126d688e3SAlex Vesker 						  bool inner, u8 *bit_mask)
210226d688e3SAlex Vesker {
210326d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc_3_mask = &value->misc3;
210426d688e3SAlex Vesker 
210526d688e3SAlex Vesker 	if (misc_3_mask->outer_vxlan_gpe_flags ||
210626d688e3SAlex Vesker 	    misc_3_mask->outer_vxlan_gpe_next_protocol) {
210726d688e3SAlex Vesker 		MLX5_SET(ste_flex_parser_tnl, bit_mask,
210826d688e3SAlex Vesker 			 flex_parser_tunneling_header_63_32,
210926d688e3SAlex Vesker 			 (misc_3_mask->outer_vxlan_gpe_flags << 24) |
211026d688e3SAlex Vesker 			 (misc_3_mask->outer_vxlan_gpe_next_protocol));
211126d688e3SAlex Vesker 		misc_3_mask->outer_vxlan_gpe_flags = 0;
211226d688e3SAlex Vesker 		misc_3_mask->outer_vxlan_gpe_next_protocol = 0;
211326d688e3SAlex Vesker 	}
211426d688e3SAlex Vesker 
211526d688e3SAlex Vesker 	if (misc_3_mask->outer_vxlan_gpe_vni) {
211626d688e3SAlex Vesker 		MLX5_SET(ste_flex_parser_tnl, bit_mask,
211726d688e3SAlex Vesker 			 flex_parser_tunneling_header_31_0,
211826d688e3SAlex Vesker 			 misc_3_mask->outer_vxlan_gpe_vni << 8);
211926d688e3SAlex Vesker 		misc_3_mask->outer_vxlan_gpe_vni = 0;
212026d688e3SAlex Vesker 	}
212126d688e3SAlex Vesker }
212226d688e3SAlex Vesker 
212326d688e3SAlex Vesker static int dr_ste_build_flex_parser_tnl_tag(struct mlx5dr_match_param *value,
212426d688e3SAlex Vesker 					    struct mlx5dr_ste_build *sb,
212526d688e3SAlex Vesker 					    u8 *hw_ste_p)
212626d688e3SAlex Vesker {
212726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
212826d688e3SAlex Vesker 	struct mlx5dr_match_misc3 *misc3 = &value->misc3;
212926d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
213026d688e3SAlex Vesker 
213126d688e3SAlex Vesker 	if (misc3->outer_vxlan_gpe_flags ||
213226d688e3SAlex Vesker 	    misc3->outer_vxlan_gpe_next_protocol) {
213326d688e3SAlex Vesker 		MLX5_SET(ste_flex_parser_tnl, tag,
213426d688e3SAlex Vesker 			 flex_parser_tunneling_header_63_32,
213526d688e3SAlex Vesker 			 (misc3->outer_vxlan_gpe_flags << 24) |
213626d688e3SAlex Vesker 			 (misc3->outer_vxlan_gpe_next_protocol));
213726d688e3SAlex Vesker 		misc3->outer_vxlan_gpe_flags = 0;
213826d688e3SAlex Vesker 		misc3->outer_vxlan_gpe_next_protocol = 0;
213926d688e3SAlex Vesker 	}
214026d688e3SAlex Vesker 
214126d688e3SAlex Vesker 	if (misc3->outer_vxlan_gpe_vni) {
214226d688e3SAlex Vesker 		MLX5_SET(ste_flex_parser_tnl, tag,
214326d688e3SAlex Vesker 			 flex_parser_tunneling_header_31_0,
214426d688e3SAlex Vesker 			 misc3->outer_vxlan_gpe_vni << 8);
214526d688e3SAlex Vesker 		misc3->outer_vxlan_gpe_vni = 0;
214626d688e3SAlex Vesker 	}
214726d688e3SAlex Vesker 
214826d688e3SAlex Vesker 	return 0;
214926d688e3SAlex Vesker }
215026d688e3SAlex Vesker 
215126d688e3SAlex Vesker void mlx5dr_ste_build_flex_parser_tnl(struct mlx5dr_ste_build *sb,
215226d688e3SAlex Vesker 				      struct mlx5dr_match_param *mask,
215326d688e3SAlex Vesker 				      bool inner, bool rx)
215426d688e3SAlex Vesker {
215526d688e3SAlex Vesker 	dr_ste_build_flex_parser_tnl_bit_mask(mask, inner, sb->bit_mask);
215626d688e3SAlex Vesker 
215726d688e3SAlex Vesker 	sb->rx = rx;
215826d688e3SAlex Vesker 	sb->inner = inner;
215926d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_FLEX_PARSER_TNL_HEADER;
216026d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
216126d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_flex_parser_tnl_tag;
216226d688e3SAlex Vesker }
216326d688e3SAlex Vesker 
216426d688e3SAlex Vesker static void dr_ste_build_register_0_bit_mask(struct mlx5dr_match_param *value,
216526d688e3SAlex Vesker 					     u8 *bit_mask)
216626d688e3SAlex Vesker {
216726d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
216826d688e3SAlex Vesker 
216926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_0_h,
217026d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_0);
217126d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_0_l,
217226d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_1);
217326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_1_h,
217426d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_2);
217526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_0, bit_mask, register_1_l,
217626d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_3);
217726d688e3SAlex Vesker }
217826d688e3SAlex Vesker 
217926d688e3SAlex Vesker static int dr_ste_build_register_0_tag(struct mlx5dr_match_param *value,
218026d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
218126d688e3SAlex Vesker 				       u8 *hw_ste_p)
218226d688e3SAlex Vesker {
218326d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
218426d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2 = &value->misc2;
218526d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
218626d688e3SAlex Vesker 
218726d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_0_h, misc2, metadata_reg_c_0);
218826d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_0_l, misc2, metadata_reg_c_1);
218926d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_1_h, misc2, metadata_reg_c_2);
219026d688e3SAlex Vesker 	DR_STE_SET_TAG(register_0, tag, register_1_l, misc2, metadata_reg_c_3);
219126d688e3SAlex Vesker 
219226d688e3SAlex Vesker 	return 0;
219326d688e3SAlex Vesker }
219426d688e3SAlex Vesker 
219526d688e3SAlex Vesker void mlx5dr_ste_build_register_0(struct mlx5dr_ste_build *sb,
219626d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
219726d688e3SAlex Vesker 				 bool inner, bool rx)
219826d688e3SAlex Vesker {
219926d688e3SAlex Vesker 	dr_ste_build_register_0_bit_mask(mask, sb->bit_mask);
220026d688e3SAlex Vesker 
220126d688e3SAlex Vesker 	sb->rx = rx;
220226d688e3SAlex Vesker 	sb->inner = inner;
220326d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_STEERING_REGISTERS_0;
220426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
220526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_register_0_tag;
220626d688e3SAlex Vesker }
220726d688e3SAlex Vesker 
220826d688e3SAlex Vesker static void dr_ste_build_register_1_bit_mask(struct mlx5dr_match_param *value,
220926d688e3SAlex Vesker 					     u8 *bit_mask)
221026d688e3SAlex Vesker {
221126d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc_2_mask = &value->misc2;
221226d688e3SAlex Vesker 
221326d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_2_h,
221426d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_4);
221526d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_2_l,
221626d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_5);
221726d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_3_h,
221826d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_6);
221926d688e3SAlex Vesker 	DR_STE_SET_MASK_V(register_1, bit_mask, register_3_l,
222026d688e3SAlex Vesker 			  misc_2_mask, metadata_reg_c_7);
222126d688e3SAlex Vesker }
222226d688e3SAlex Vesker 
222326d688e3SAlex Vesker static int dr_ste_build_register_1_tag(struct mlx5dr_match_param *value,
222426d688e3SAlex Vesker 				       struct mlx5dr_ste_build *sb,
222526d688e3SAlex Vesker 				       u8 *hw_ste_p)
222626d688e3SAlex Vesker {
222726d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
222826d688e3SAlex Vesker 	struct mlx5dr_match_misc2 *misc2 = &value->misc2;
222926d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
223026d688e3SAlex Vesker 
223126d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_2_h, misc2, metadata_reg_c_4);
223226d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_2_l, misc2, metadata_reg_c_5);
223326d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_3_h, misc2, metadata_reg_c_6);
223426d688e3SAlex Vesker 	DR_STE_SET_TAG(register_1, tag, register_3_l, misc2, metadata_reg_c_7);
223526d688e3SAlex Vesker 
223626d688e3SAlex Vesker 	return 0;
223726d688e3SAlex Vesker }
223826d688e3SAlex Vesker 
223926d688e3SAlex Vesker void mlx5dr_ste_build_register_1(struct mlx5dr_ste_build *sb,
224026d688e3SAlex Vesker 				 struct mlx5dr_match_param *mask,
224126d688e3SAlex Vesker 				 bool inner, bool rx)
224226d688e3SAlex Vesker {
224326d688e3SAlex Vesker 	dr_ste_build_register_1_bit_mask(mask, sb->bit_mask);
224426d688e3SAlex Vesker 
224526d688e3SAlex Vesker 	sb->rx = rx;
224626d688e3SAlex Vesker 	sb->inner = inner;
224726d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_STEERING_REGISTERS_1;
224826d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
224926d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_register_1_tag;
225026d688e3SAlex Vesker }
225126d688e3SAlex Vesker 
225226d688e3SAlex Vesker static int dr_ste_build_src_gvmi_qpn_bit_mask(struct mlx5dr_match_param *value,
225326d688e3SAlex Vesker 					      u8 *bit_mask)
225426d688e3SAlex Vesker {
225526d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc_mask = &value->misc;
225626d688e3SAlex Vesker 
225726d688e3SAlex Vesker 	if (misc_mask->source_port != 0xffff)
225826d688e3SAlex Vesker 		return -EINVAL;
225926d688e3SAlex Vesker 
226026d688e3SAlex Vesker 	DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_gvmi, misc_mask, source_port);
226126d688e3SAlex Vesker 	DR_STE_SET_MASK(src_gvmi_qp, bit_mask, source_qp, misc_mask, source_sqn);
226226d688e3SAlex Vesker 
226326d688e3SAlex Vesker 	return 0;
226426d688e3SAlex Vesker }
226526d688e3SAlex Vesker 
226626d688e3SAlex Vesker static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
226726d688e3SAlex Vesker 					 struct mlx5dr_ste_build *sb,
226826d688e3SAlex Vesker 					 u8 *hw_ste_p)
226926d688e3SAlex Vesker {
227026d688e3SAlex Vesker 	struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p;
227126d688e3SAlex Vesker 	struct mlx5dr_match_misc *misc = &value->misc;
227226d688e3SAlex Vesker 	struct mlx5dr_cmd_vport_cap *vport_cap;
227326d688e3SAlex Vesker 	u8 *tag = hw_ste->tag;
227426d688e3SAlex Vesker 
227526d688e3SAlex Vesker 	DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
227626d688e3SAlex Vesker 
227726d688e3SAlex Vesker 	vport_cap = mlx5dr_get_vport_cap(sb->caps, misc->source_port);
227826d688e3SAlex Vesker 	if (!vport_cap)
227926d688e3SAlex Vesker 		return -EINVAL;
228026d688e3SAlex Vesker 
228126d688e3SAlex Vesker 	if (vport_cap->vport_gvmi)
228226d688e3SAlex Vesker 		MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi);
228326d688e3SAlex Vesker 
228426d688e3SAlex Vesker 	misc->source_port = 0;
228526d688e3SAlex Vesker 
228626d688e3SAlex Vesker 	return 0;
228726d688e3SAlex Vesker }
228826d688e3SAlex Vesker 
228926d688e3SAlex Vesker int mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_build *sb,
229026d688e3SAlex Vesker 				  struct mlx5dr_match_param *mask,
229126d688e3SAlex Vesker 				  struct mlx5dr_cmd_caps *caps,
229226d688e3SAlex Vesker 				  bool inner, bool rx)
229326d688e3SAlex Vesker {
229426d688e3SAlex Vesker 	int ret;
229526d688e3SAlex Vesker 
229626d688e3SAlex Vesker 	ret = dr_ste_build_src_gvmi_qpn_bit_mask(mask, sb->bit_mask);
229726d688e3SAlex Vesker 	if (ret)
229826d688e3SAlex Vesker 		return ret;
229926d688e3SAlex Vesker 
230026d688e3SAlex Vesker 	sb->rx = rx;
230126d688e3SAlex Vesker 	sb->caps = caps;
230226d688e3SAlex Vesker 	sb->inner = inner;
230326d688e3SAlex Vesker 	sb->lu_type = MLX5DR_STE_LU_TYPE_SRC_GVMI_AND_QP;
230426d688e3SAlex Vesker 	sb->byte_mask = dr_ste_conv_bit_to_byte_mask(sb->bit_mask);
230526d688e3SAlex Vesker 	sb->ste_build_tag_func = &dr_ste_build_src_gvmi_qpn_tag;
230626d688e3SAlex Vesker 
230726d688e3SAlex Vesker 	return 0;
230826d688e3SAlex Vesker }
2309