Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
0003 
0004 #include "tir.h"
0005 #include "params.h"
0006 #include <linux/mlx5/transobj.h>
0007 
0008 #define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)
0009 
0010 /* max() doesn't work inside square brackets. */
0011 #define MLX5E_TIR_CMD_IN_SZ_DW ( \
0012     MLX5_ST_SZ_DW(create_tir_in) > MLX5_ST_SZ_DW(modify_tir_in) ? \
0013     MLX5_ST_SZ_DW(create_tir_in) : MLX5_ST_SZ_DW(modify_tir_in) \
0014 )
0015 
0016 struct mlx5e_tir_builder {
0017     u32 in[MLX5E_TIR_CMD_IN_SZ_DW];
0018     bool modify;
0019 };
0020 
0021 struct mlx5e_tir_builder *mlx5e_tir_builder_alloc(bool modify)
0022 {
0023     struct mlx5e_tir_builder *builder;
0024 
0025     builder = kvzalloc(sizeof(*builder), GFP_KERNEL);
0026     builder->modify = modify;
0027 
0028     return builder;
0029 }
0030 
0031 void mlx5e_tir_builder_free(struct mlx5e_tir_builder *builder)
0032 {
0033     kvfree(builder);
0034 }
0035 
0036 void mlx5e_tir_builder_clear(struct mlx5e_tir_builder *builder)
0037 {
0038     memset(builder->in, 0, sizeof(builder->in));
0039 }
0040 
0041 static void *mlx5e_tir_builder_get_tirc(struct mlx5e_tir_builder *builder)
0042 {
0043     if (builder->modify)
0044         return MLX5_ADDR_OF(modify_tir_in, builder->in, ctx);
0045     return MLX5_ADDR_OF(create_tir_in, builder->in, ctx);
0046 }
0047 
0048 void mlx5e_tir_builder_build_inline(struct mlx5e_tir_builder *builder, u32 tdn, u32 rqn)
0049 {
0050     void *tirc = mlx5e_tir_builder_get_tirc(builder);
0051 
0052     WARN_ON(builder->modify);
0053 
0054     MLX5_SET(tirc, tirc, transport_domain, tdn);
0055     MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_DIRECT);
0056     MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_NONE);
0057     MLX5_SET(tirc, tirc, inline_rqn, rqn);
0058 }
0059 
0060 void mlx5e_tir_builder_build_rqt(struct mlx5e_tir_builder *builder, u32 tdn,
0061                  u32 rqtn, bool inner_ft_support)
0062 {
0063     void *tirc = mlx5e_tir_builder_get_tirc(builder);
0064 
0065     WARN_ON(builder->modify);
0066 
0067     MLX5_SET(tirc, tirc, transport_domain, tdn);
0068     MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
0069     MLX5_SET(tirc, tirc, indirect_table, rqtn);
0070     MLX5_SET(tirc, tirc, tunneled_offload_en, inner_ft_support);
0071 }
0072 
0073 void mlx5e_tir_builder_build_packet_merge(struct mlx5e_tir_builder *builder,
0074                       const struct mlx5e_packet_merge_param *pkt_merge_param)
0075 {
0076     void *tirc = mlx5e_tir_builder_get_tirc(builder);
0077     const unsigned int rough_max_l2_l3_hdr_sz = 256;
0078 
0079     if (builder->modify)
0080         MLX5_SET(modify_tir_in, builder->in, bitmask.packet_merge, 1);
0081 
0082     switch (pkt_merge_param->type) {
0083     case MLX5E_PACKET_MERGE_LRO:
0084         MLX5_SET(tirc, tirc, packet_merge_mask,
0085              MLX5_TIRC_PACKET_MERGE_MASK_IPV4_LRO |
0086              MLX5_TIRC_PACKET_MERGE_MASK_IPV6_LRO);
0087         MLX5_SET(tirc, tirc, lro_max_ip_payload_size,
0088              (MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ - rough_max_l2_l3_hdr_sz) >> 8);
0089         MLX5_SET(tirc, tirc, lro_timeout_period_usecs, pkt_merge_param->timeout);
0090         break;
0091     default:
0092         break;
0093     }
0094 }
0095 
0096 static int mlx5e_hfunc_to_hw(u8 hfunc)
0097 {
0098     switch (hfunc) {
0099     case ETH_RSS_HASH_TOP:
0100         return MLX5_RX_HASH_FN_TOEPLITZ;
0101     case ETH_RSS_HASH_XOR:
0102         return MLX5_RX_HASH_FN_INVERTED_XOR8;
0103     default:
0104         return MLX5_RX_HASH_FN_NONE;
0105     }
0106 }
0107 
0108 void mlx5e_tir_builder_build_rss(struct mlx5e_tir_builder *builder,
0109                  const struct mlx5e_rss_params_hash *rss_hash,
0110                  const struct mlx5e_rss_params_traffic_type *rss_tt,
0111                  bool inner)
0112 {
0113     void *tirc = mlx5e_tir_builder_get_tirc(builder);
0114     void *hfso;
0115 
0116     if (builder->modify)
0117         MLX5_SET(modify_tir_in, builder->in, bitmask.hash, 1);
0118 
0119     MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_hfunc_to_hw(rss_hash->hfunc));
0120     if (rss_hash->hfunc == ETH_RSS_HASH_TOP) {
0121         const size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
0122         void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);
0123 
0124         MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
0125         memcpy(rss_key, rss_hash->toeplitz_hash_key, len);
0126     }
0127 
0128     if (inner)
0129         hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner);
0130     else
0131         hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
0132     MLX5_SET(rx_hash_field_select, hfso, l3_prot_type, rss_tt->l3_prot_type);
0133     MLX5_SET(rx_hash_field_select, hfso, l4_prot_type, rss_tt->l4_prot_type);
0134     MLX5_SET(rx_hash_field_select, hfso, selected_fields, rss_tt->rx_hash_fields);
0135 }
0136 
0137 void mlx5e_tir_builder_build_direct(struct mlx5e_tir_builder *builder)
0138 {
0139     void *tirc = mlx5e_tir_builder_get_tirc(builder);
0140 
0141     WARN_ON(builder->modify);
0142 
0143     MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_INVERTED_XOR8);
0144 }
0145 
0146 void mlx5e_tir_builder_build_tls(struct mlx5e_tir_builder *builder)
0147 {
0148     void *tirc = mlx5e_tir_builder_get_tirc(builder);
0149 
0150     WARN_ON(builder->modify);
0151 
0152     MLX5_SET(tirc, tirc, tls_en, 1);
0153     MLX5_SET(tirc, tirc, self_lb_block,
0154          MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST |
0155          MLX5_TIRC_SELF_LB_BLOCK_BLOCK_MULTICAST);
0156 }
0157 
0158 int mlx5e_tir_init(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder,
0159            struct mlx5_core_dev *mdev, bool reg)
0160 {
0161     int err;
0162 
0163     tir->mdev = mdev;
0164 
0165     err = mlx5_core_create_tir(tir->mdev, builder->in, &tir->tirn);
0166     if (err)
0167         return err;
0168 
0169     if (reg) {
0170         struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;
0171 
0172         mutex_lock(&res->td.list_lock);
0173         list_add(&tir->list, &res->td.tirs_list);
0174         mutex_unlock(&res->td.list_lock);
0175     } else {
0176         INIT_LIST_HEAD(&tir->list);
0177     }
0178 
0179     return 0;
0180 }
0181 
0182 void mlx5e_tir_destroy(struct mlx5e_tir *tir)
0183 {
0184     struct mlx5e_hw_objs *res = &tir->mdev->mlx5e_res.hw_objs;
0185 
0186     /* Skip mutex if list_del is no-op (the TIR wasn't registered in the
0187      * list). list_empty will never return true for an item of tirs_list,
0188      * and READ_ONCE/WRITE_ONCE in list_empty/list_del guarantee consistency
0189      * of the list->next value.
0190      */
0191     if (!list_empty(&tir->list)) {
0192         mutex_lock(&res->td.list_lock);
0193         list_del(&tir->list);
0194         mutex_unlock(&res->td.list_lock);
0195     }
0196 
0197     mlx5_core_destroy_tir(tir->mdev, tir->tirn);
0198 }
0199 
0200 int mlx5e_tir_modify(struct mlx5e_tir *tir, struct mlx5e_tir_builder *builder)
0201 {
0202     return mlx5_core_modify_tir(tir->mdev, tir->tirn, builder->in);
0203 }