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