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