165d6b6e5SMaxim Mikityanskiy // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 265d6b6e5SMaxim Mikityanskiy /* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */ 365d6b6e5SMaxim Mikityanskiy 465d6b6e5SMaxim Mikityanskiy #include "rx_res.h" 543ec0f41SMaxim Mikityanskiy #include "channels.h" 643ec0f41SMaxim Mikityanskiy #include "params.h" 765d6b6e5SMaxim Mikityanskiy 865d6b6e5SMaxim Mikityanskiy static const struct mlx5e_rss_params_traffic_type rss_default_config[MLX5E_NUM_INDIR_TIRS] = { 9d443c6f6SMaor Gottlieb [MLX5_TT_IPV4_TCP] = { 1065d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4, 1165d6b6e5SMaxim Mikityanskiy .l4_prot_type = MLX5_L4_PROT_TYPE_TCP, 1265d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_L4PORTS, 1365d6b6e5SMaxim Mikityanskiy }, 14d443c6f6SMaor Gottlieb [MLX5_TT_IPV6_TCP] = { 1565d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6, 1665d6b6e5SMaxim Mikityanskiy .l4_prot_type = MLX5_L4_PROT_TYPE_TCP, 1765d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_L4PORTS, 1865d6b6e5SMaxim Mikityanskiy }, 19d443c6f6SMaor Gottlieb [MLX5_TT_IPV4_UDP] = { 2065d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4, 2165d6b6e5SMaxim Mikityanskiy .l4_prot_type = MLX5_L4_PROT_TYPE_UDP, 2265d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_L4PORTS, 2365d6b6e5SMaxim Mikityanskiy }, 24d443c6f6SMaor Gottlieb [MLX5_TT_IPV6_UDP] = { 2565d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6, 2665d6b6e5SMaxim Mikityanskiy .l4_prot_type = MLX5_L4_PROT_TYPE_UDP, 2765d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_L4PORTS, 2865d6b6e5SMaxim Mikityanskiy }, 29d443c6f6SMaor Gottlieb [MLX5_TT_IPV4_IPSEC_AH] = { 3065d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4, 3165d6b6e5SMaxim Mikityanskiy .l4_prot_type = 0, 3265d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI, 3365d6b6e5SMaxim Mikityanskiy }, 34d443c6f6SMaor Gottlieb [MLX5_TT_IPV6_IPSEC_AH] = { 3565d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6, 3665d6b6e5SMaxim Mikityanskiy .l4_prot_type = 0, 3765d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI, 3865d6b6e5SMaxim Mikityanskiy }, 39d443c6f6SMaor Gottlieb [MLX5_TT_IPV4_IPSEC_ESP] = { 4065d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4, 4165d6b6e5SMaxim Mikityanskiy .l4_prot_type = 0, 4265d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI, 4365d6b6e5SMaxim Mikityanskiy }, 44d443c6f6SMaor Gottlieb [MLX5_TT_IPV6_IPSEC_ESP] = { 4565d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6, 4665d6b6e5SMaxim Mikityanskiy .l4_prot_type = 0, 4765d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI, 4865d6b6e5SMaxim Mikityanskiy }, 49d443c6f6SMaor Gottlieb [MLX5_TT_IPV4] = { 5065d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4, 5165d6b6e5SMaxim Mikityanskiy .l4_prot_type = 0, 5265d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP, 5365d6b6e5SMaxim Mikityanskiy }, 54d443c6f6SMaor Gottlieb [MLX5_TT_IPV6] = { 5565d6b6e5SMaxim Mikityanskiy .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6, 5665d6b6e5SMaxim Mikityanskiy .l4_prot_type = 0, 5765d6b6e5SMaxim Mikityanskiy .rx_hash_fields = MLX5_HASH_IP, 5865d6b6e5SMaxim Mikityanskiy }, 5965d6b6e5SMaxim Mikityanskiy }; 6065d6b6e5SMaxim Mikityanskiy 6165d6b6e5SMaxim Mikityanskiy struct mlx5e_rss_params_traffic_type 62d443c6f6SMaor Gottlieb mlx5e_rss_get_default_tt_config(enum mlx5_traffic_types tt) 6365d6b6e5SMaxim Mikityanskiy { 6465d6b6e5SMaxim Mikityanskiy return rss_default_config[tt]; 6565d6b6e5SMaxim Mikityanskiy } 6665d6b6e5SMaxim Mikityanskiy 6743ec0f41SMaxim Mikityanskiy struct mlx5e_rx_res { 6843ec0f41SMaxim Mikityanskiy struct mlx5_core_dev *mdev; 6943ec0f41SMaxim Mikityanskiy enum mlx5e_rx_res_features features; 7043ec0f41SMaxim Mikityanskiy unsigned int max_nch; 7143ec0f41SMaxim Mikityanskiy u32 drop_rqn; 7243ec0f41SMaxim Mikityanskiy 7343ec0f41SMaxim Mikityanskiy struct { 7443ec0f41SMaxim Mikityanskiy struct mlx5e_rss_params_hash hash; 7543ec0f41SMaxim Mikityanskiy struct mlx5e_rss_params_indir indir; 7643ec0f41SMaxim Mikityanskiy u32 rx_hash_fields[MLX5E_NUM_INDIR_TIRS]; 7743ec0f41SMaxim Mikityanskiy } rss_params; 7843ec0f41SMaxim Mikityanskiy 7943ec0f41SMaxim Mikityanskiy struct mlx5e_rqt indir_rqt; 8043ec0f41SMaxim Mikityanskiy struct { 8143ec0f41SMaxim Mikityanskiy struct mlx5e_tir indir_tir; 8243ec0f41SMaxim Mikityanskiy struct mlx5e_tir inner_indir_tir; 8343ec0f41SMaxim Mikityanskiy } rss[MLX5E_NUM_INDIR_TIRS]; 8443ec0f41SMaxim Mikityanskiy 8543ec0f41SMaxim Mikityanskiy bool rss_active; 8643ec0f41SMaxim Mikityanskiy u32 rss_rqns[MLX5E_INDIR_RQT_SIZE]; 8743ec0f41SMaxim Mikityanskiy unsigned int rss_nch; 8843ec0f41SMaxim Mikityanskiy 8943ec0f41SMaxim Mikityanskiy struct { 9043ec0f41SMaxim Mikityanskiy struct mlx5e_rqt direct_rqt; 9143ec0f41SMaxim Mikityanskiy struct mlx5e_tir direct_tir; 9243ec0f41SMaxim Mikityanskiy struct mlx5e_rqt xsk_rqt; 9343ec0f41SMaxim Mikityanskiy struct mlx5e_tir xsk_tir; 943ac90decSMaxim Mikityanskiy } *channels; 9543ec0f41SMaxim Mikityanskiy 9643ec0f41SMaxim Mikityanskiy struct { 9743ec0f41SMaxim Mikityanskiy struct mlx5e_rqt rqt; 9843ec0f41SMaxim Mikityanskiy struct mlx5e_tir tir; 9943ec0f41SMaxim Mikityanskiy } ptp; 10043ec0f41SMaxim Mikityanskiy }; 10143ec0f41SMaxim Mikityanskiy 10243ec0f41SMaxim Mikityanskiy struct mlx5e_rx_res *mlx5e_rx_res_alloc(void) 10343ec0f41SMaxim Mikityanskiy { 10443ec0f41SMaxim Mikityanskiy return kvzalloc(sizeof(struct mlx5e_rx_res), GFP_KERNEL); 10543ec0f41SMaxim Mikityanskiy } 10643ec0f41SMaxim Mikityanskiy 10743ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_params_init(struct mlx5e_rx_res *res, unsigned int init_nch) 10843ec0f41SMaxim Mikityanskiy { 109d443c6f6SMaor Gottlieb enum mlx5_traffic_types tt; 11043ec0f41SMaxim Mikityanskiy 11143ec0f41SMaxim Mikityanskiy res->rss_params.hash.hfunc = ETH_RSS_HASH_TOP; 11243ec0f41SMaxim Mikityanskiy netdev_rss_key_fill(res->rss_params.hash.toeplitz_hash_key, 11343ec0f41SMaxim Mikityanskiy sizeof(res->rss_params.hash.toeplitz_hash_key)); 11443ec0f41SMaxim Mikityanskiy mlx5e_rss_params_indir_init_uniform(&res->rss_params.indir, init_nch); 11543ec0f41SMaxim Mikityanskiy for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) 11643ec0f41SMaxim Mikityanskiy res->rss_params.rx_hash_fields[tt] = 11743ec0f41SMaxim Mikityanskiy mlx5e_rss_get_default_tt_config(tt).rx_hash_fields; 11843ec0f41SMaxim Mikityanskiy } 11943ec0f41SMaxim Mikityanskiy 120*fc651ff9STariq Toukan static void mlx5e_rx_res_rss_destroy_tir(struct mlx5e_rx_res *res, 121*fc651ff9STariq Toukan enum mlx5_traffic_types tt, 122*fc651ff9STariq Toukan bool inner) 123*fc651ff9STariq Toukan { 124*fc651ff9STariq Toukan struct mlx5e_tir *tir; 125*fc651ff9STariq Toukan 126*fc651ff9STariq Toukan tir = inner ? &res->rss[tt].inner_indir_tir : &res->rss[tt].indir_tir; 127*fc651ff9STariq Toukan mlx5e_tir_destroy(tir); 128*fc651ff9STariq Toukan } 129*fc651ff9STariq Toukan 130*fc651ff9STariq Toukan static int mlx5e_rx_res_rss_create_tir(struct mlx5e_rx_res *res, 131*fc651ff9STariq Toukan struct mlx5e_tir_builder *builder, 132*fc651ff9STariq Toukan enum mlx5_traffic_types tt, 133*fc651ff9STariq Toukan const struct mlx5e_lro_param *init_lro_param, 134*fc651ff9STariq Toukan bool inner) 13543ec0f41SMaxim Mikityanskiy { 13643ec0f41SMaxim Mikityanskiy bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 137*fc651ff9STariq Toukan struct mlx5e_rss_params_traffic_type rss_tt; 138*fc651ff9STariq Toukan struct mlx5e_tir *tir; 139*fc651ff9STariq Toukan u32 rqtn; 140*fc651ff9STariq Toukan int err; 141*fc651ff9STariq Toukan 142*fc651ff9STariq Toukan tir = inner ? &res->rss[tt].inner_indir_tir : &res->rss[tt].indir_tir; 143*fc651ff9STariq Toukan 144*fc651ff9STariq Toukan rqtn = mlx5e_rqt_get_rqtn(&res->indir_rqt); 145*fc651ff9STariq Toukan mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, 146*fc651ff9STariq Toukan rqtn, inner_ft_support); 147*fc651ff9STariq Toukan mlx5e_tir_builder_build_lro(builder, init_lro_param); 148*fc651ff9STariq Toukan rss_tt = mlx5e_rx_res_rss_get_current_tt_config(res, tt); 149*fc651ff9STariq Toukan mlx5e_tir_builder_build_rss(builder, &res->rss_params.hash, &rss_tt, inner); 150*fc651ff9STariq Toukan 151*fc651ff9STariq Toukan err = mlx5e_tir_init(tir, builder, res->mdev, true); 152*fc651ff9STariq Toukan if (err) { 153*fc651ff9STariq Toukan mlx5_core_warn(res->mdev, "Failed to create %sindirect TIR: err = %d, tt = %d\n", 154*fc651ff9STariq Toukan inner ? "inner " : "", err, tt); 155*fc651ff9STariq Toukan return err; 156*fc651ff9STariq Toukan } 157*fc651ff9STariq Toukan 158*fc651ff9STariq Toukan return 0; 159*fc651ff9STariq Toukan } 160*fc651ff9STariq Toukan 161*fc651ff9STariq Toukan static int mlx5e_rx_res_rss_create_tirs(struct mlx5e_rx_res *res, 162*fc651ff9STariq Toukan const struct mlx5e_lro_param *init_lro_param, 163*fc651ff9STariq Toukan bool inner) 164*fc651ff9STariq Toukan { 165d443c6f6SMaor Gottlieb enum mlx5_traffic_types tt, max_tt; 16643ec0f41SMaxim Mikityanskiy struct mlx5e_tir_builder *builder; 16743ec0f41SMaxim Mikityanskiy int err; 16843ec0f41SMaxim Mikityanskiy 16943ec0f41SMaxim Mikityanskiy builder = mlx5e_tir_builder_alloc(false); 17043ec0f41SMaxim Mikityanskiy if (!builder) 17143ec0f41SMaxim Mikityanskiy return -ENOMEM; 17243ec0f41SMaxim Mikityanskiy 173*fc651ff9STariq Toukan for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { 174*fc651ff9STariq Toukan err = mlx5e_rx_res_rss_create_tir(res, builder, tt, init_lro_param, inner); 17543ec0f41SMaxim Mikityanskiy if (err) 17643ec0f41SMaxim Mikityanskiy goto err_destroy_tirs; 17743ec0f41SMaxim Mikityanskiy 17843ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_clear(builder); 17943ec0f41SMaxim Mikityanskiy } 18043ec0f41SMaxim Mikityanskiy 18143ec0f41SMaxim Mikityanskiy out: 18243ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_free(builder); 183*fc651ff9STariq Toukan return err; 184*fc651ff9STariq Toukan 185*fc651ff9STariq Toukan err_destroy_tirs: 186*fc651ff9STariq Toukan max_tt = tt; 187*fc651ff9STariq Toukan for (tt = 0; tt < max_tt; tt++) 188*fc651ff9STariq Toukan mlx5e_rx_res_rss_destroy_tir(res, tt, inner); 189*fc651ff9STariq Toukan goto out; 190*fc651ff9STariq Toukan } 191*fc651ff9STariq Toukan 192*fc651ff9STariq Toukan static void mlx5e_rx_res_rss_destroy_tirs(struct mlx5e_rx_res *res, bool inner) 193*fc651ff9STariq Toukan { 194*fc651ff9STariq Toukan enum mlx5_traffic_types tt; 195*fc651ff9STariq Toukan 196*fc651ff9STariq Toukan for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) 197*fc651ff9STariq Toukan mlx5e_rx_res_rss_destroy_tir(res, tt, inner); 198*fc651ff9STariq Toukan } 199*fc651ff9STariq Toukan 200*fc651ff9STariq Toukan static int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, 201*fc651ff9STariq Toukan const struct mlx5e_lro_param *init_lro_param) 202*fc651ff9STariq Toukan { 203*fc651ff9STariq Toukan bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 204*fc651ff9STariq Toukan int err; 205*fc651ff9STariq Toukan 206*fc651ff9STariq Toukan err = mlx5e_rqt_init_direct(&res->indir_rqt, res->mdev, true, res->drop_rqn); 207*fc651ff9STariq Toukan if (err) 208*fc651ff9STariq Toukan return err; 209*fc651ff9STariq Toukan 210*fc651ff9STariq Toukan err = mlx5e_rx_res_rss_create_tirs(res, init_lro_param, false); 211*fc651ff9STariq Toukan if (err) 212*fc651ff9STariq Toukan goto err_destroy_rqt; 213*fc651ff9STariq Toukan 214*fc651ff9STariq Toukan if (inner_ft_support) { 215*fc651ff9STariq Toukan err = mlx5e_rx_res_rss_create_tirs(res, init_lro_param, true); 216*fc651ff9STariq Toukan if (err) 217*fc651ff9STariq Toukan goto err_destroy_tirs; 218*fc651ff9STariq Toukan } 219*fc651ff9STariq Toukan 220*fc651ff9STariq Toukan return 0; 221*fc651ff9STariq Toukan 222*fc651ff9STariq Toukan err_destroy_tirs: 223*fc651ff9STariq Toukan mlx5e_rx_res_rss_destroy_tirs(res, false); 224*fc651ff9STariq Toukan 225*fc651ff9STariq Toukan err_destroy_rqt: 226*fc651ff9STariq Toukan mlx5e_rqt_destroy(&res->indir_rqt); 22743ec0f41SMaxim Mikityanskiy 22843ec0f41SMaxim Mikityanskiy return err; 22943ec0f41SMaxim Mikityanskiy } 23043ec0f41SMaxim Mikityanskiy 23143ec0f41SMaxim Mikityanskiy static int mlx5e_rx_res_channels_init(struct mlx5e_rx_res *res, 23243ec0f41SMaxim Mikityanskiy const struct mlx5e_lro_param *init_lro_param) 23343ec0f41SMaxim Mikityanskiy { 23443ec0f41SMaxim Mikityanskiy bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 23543ec0f41SMaxim Mikityanskiy struct mlx5e_tir_builder *builder; 23643ec0f41SMaxim Mikityanskiy int err = 0; 23743ec0f41SMaxim Mikityanskiy int ix; 23843ec0f41SMaxim Mikityanskiy 23943ec0f41SMaxim Mikityanskiy builder = mlx5e_tir_builder_alloc(false); 24043ec0f41SMaxim Mikityanskiy if (!builder) 24143ec0f41SMaxim Mikityanskiy return -ENOMEM; 24243ec0f41SMaxim Mikityanskiy 2433ac90decSMaxim Mikityanskiy res->channels = kvcalloc(res->max_nch, sizeof(*res->channels), GFP_KERNEL); 2443ac90decSMaxim Mikityanskiy if (!res->channels) { 2453ac90decSMaxim Mikityanskiy err = -ENOMEM; 2463ac90decSMaxim Mikityanskiy goto out; 2473ac90decSMaxim Mikityanskiy } 2483ac90decSMaxim Mikityanskiy 24943ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 25043ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_init_direct(&res->channels[ix].direct_rqt, 25143ec0f41SMaxim Mikityanskiy res->mdev, false, res->drop_rqn); 25243ec0f41SMaxim Mikityanskiy if (err) { 25343ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to create a direct RQT: err = %d, ix = %u\n", 25443ec0f41SMaxim Mikityanskiy err, ix); 25543ec0f41SMaxim Mikityanskiy goto err_destroy_direct_rqts; 25643ec0f41SMaxim Mikityanskiy } 25743ec0f41SMaxim Mikityanskiy } 25843ec0f41SMaxim Mikityanskiy 25943ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 26043ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, 26143ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 26243ec0f41SMaxim Mikityanskiy inner_ft_support); 26343ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_lro(builder, init_lro_param); 26443ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_direct(builder); 26543ec0f41SMaxim Mikityanskiy 26643ec0f41SMaxim Mikityanskiy err = mlx5e_tir_init(&res->channels[ix].direct_tir, builder, res->mdev, true); 26743ec0f41SMaxim Mikityanskiy if (err) { 26843ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to create a direct TIR: err = %d, ix = %u\n", 26943ec0f41SMaxim Mikityanskiy err, ix); 27043ec0f41SMaxim Mikityanskiy goto err_destroy_direct_tirs; 27143ec0f41SMaxim Mikityanskiy } 27243ec0f41SMaxim Mikityanskiy 27343ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_clear(builder); 27443ec0f41SMaxim Mikityanskiy } 27543ec0f41SMaxim Mikityanskiy 27643ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_XSK)) 27743ec0f41SMaxim Mikityanskiy goto out; 27843ec0f41SMaxim Mikityanskiy 27943ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 28043ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_init_direct(&res->channels[ix].xsk_rqt, 28143ec0f41SMaxim Mikityanskiy res->mdev, false, res->drop_rqn); 28243ec0f41SMaxim Mikityanskiy if (err) { 28343ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to create an XSK RQT: err = %d, ix = %u\n", 28443ec0f41SMaxim Mikityanskiy err, ix); 28543ec0f41SMaxim Mikityanskiy goto err_destroy_xsk_rqts; 28643ec0f41SMaxim Mikityanskiy } 28743ec0f41SMaxim Mikityanskiy } 28843ec0f41SMaxim Mikityanskiy 28943ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 29043ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, 29143ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), 29243ec0f41SMaxim Mikityanskiy inner_ft_support); 29343ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_lro(builder, init_lro_param); 29443ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_direct(builder); 29543ec0f41SMaxim Mikityanskiy 29643ec0f41SMaxim Mikityanskiy err = mlx5e_tir_init(&res->channels[ix].xsk_tir, builder, res->mdev, true); 29743ec0f41SMaxim Mikityanskiy if (err) { 29843ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to create an XSK TIR: err = %d, ix = %u\n", 29943ec0f41SMaxim Mikityanskiy err, ix); 30043ec0f41SMaxim Mikityanskiy goto err_destroy_xsk_tirs; 30143ec0f41SMaxim Mikityanskiy } 30243ec0f41SMaxim Mikityanskiy 30343ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_clear(builder); 30443ec0f41SMaxim Mikityanskiy } 30543ec0f41SMaxim Mikityanskiy 30643ec0f41SMaxim Mikityanskiy goto out; 30743ec0f41SMaxim Mikityanskiy 30843ec0f41SMaxim Mikityanskiy err_destroy_xsk_tirs: 30943ec0f41SMaxim Mikityanskiy while (--ix >= 0) 31043ec0f41SMaxim Mikityanskiy mlx5e_tir_destroy(&res->channels[ix].xsk_tir); 31143ec0f41SMaxim Mikityanskiy 31243ec0f41SMaxim Mikityanskiy ix = res->max_nch; 31343ec0f41SMaxim Mikityanskiy err_destroy_xsk_rqts: 31443ec0f41SMaxim Mikityanskiy while (--ix >= 0) 31543ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->channels[ix].xsk_rqt); 31643ec0f41SMaxim Mikityanskiy 31743ec0f41SMaxim Mikityanskiy ix = res->max_nch; 31843ec0f41SMaxim Mikityanskiy err_destroy_direct_tirs: 31943ec0f41SMaxim Mikityanskiy while (--ix >= 0) 32043ec0f41SMaxim Mikityanskiy mlx5e_tir_destroy(&res->channels[ix].direct_tir); 32143ec0f41SMaxim Mikityanskiy 32243ec0f41SMaxim Mikityanskiy ix = res->max_nch; 32343ec0f41SMaxim Mikityanskiy err_destroy_direct_rqts: 32443ec0f41SMaxim Mikityanskiy while (--ix >= 0) 32543ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->channels[ix].direct_rqt); 32643ec0f41SMaxim Mikityanskiy 3273ac90decSMaxim Mikityanskiy kvfree(res->channels); 3283ac90decSMaxim Mikityanskiy 32943ec0f41SMaxim Mikityanskiy out: 33043ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_free(builder); 33143ec0f41SMaxim Mikityanskiy 33243ec0f41SMaxim Mikityanskiy return err; 33343ec0f41SMaxim Mikityanskiy } 33443ec0f41SMaxim Mikityanskiy 33543ec0f41SMaxim Mikityanskiy static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res) 33643ec0f41SMaxim Mikityanskiy { 33743ec0f41SMaxim Mikityanskiy bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; 33843ec0f41SMaxim Mikityanskiy struct mlx5e_tir_builder *builder; 33943ec0f41SMaxim Mikityanskiy int err; 34043ec0f41SMaxim Mikityanskiy 34143ec0f41SMaxim Mikityanskiy builder = mlx5e_tir_builder_alloc(false); 34243ec0f41SMaxim Mikityanskiy if (!builder) 34343ec0f41SMaxim Mikityanskiy return -ENOMEM; 34443ec0f41SMaxim Mikityanskiy 34543ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_init_direct(&res->ptp.rqt, res->mdev, false, res->drop_rqn); 34643ec0f41SMaxim Mikityanskiy if (err) 34743ec0f41SMaxim Mikityanskiy goto out; 34843ec0f41SMaxim Mikityanskiy 34943ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, 35043ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->ptp.rqt), 35143ec0f41SMaxim Mikityanskiy inner_ft_support); 35243ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_direct(builder); 35343ec0f41SMaxim Mikityanskiy 35443ec0f41SMaxim Mikityanskiy err = mlx5e_tir_init(&res->ptp.tir, builder, res->mdev, true); 35543ec0f41SMaxim Mikityanskiy if (err) 35643ec0f41SMaxim Mikityanskiy goto err_destroy_ptp_rqt; 35743ec0f41SMaxim Mikityanskiy 35843ec0f41SMaxim Mikityanskiy goto out; 35943ec0f41SMaxim Mikityanskiy 36043ec0f41SMaxim Mikityanskiy err_destroy_ptp_rqt: 36143ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->ptp.rqt); 36243ec0f41SMaxim Mikityanskiy 36343ec0f41SMaxim Mikityanskiy out: 36443ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_free(builder); 36543ec0f41SMaxim Mikityanskiy return err; 36643ec0f41SMaxim Mikityanskiy } 36743ec0f41SMaxim Mikityanskiy 36843ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res) 36943ec0f41SMaxim Mikityanskiy { 370*fc651ff9STariq Toukan mlx5e_rx_res_rss_destroy_tirs(res, false); 37143ec0f41SMaxim Mikityanskiy 37243ec0f41SMaxim Mikityanskiy if (res->features & MLX5E_RX_RES_FEATURE_INNER_FT) 373*fc651ff9STariq Toukan mlx5e_rx_res_rss_destroy_tirs(res, true); 37443ec0f41SMaxim Mikityanskiy 37543ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->indir_rqt); 37643ec0f41SMaxim Mikityanskiy } 37743ec0f41SMaxim Mikityanskiy 37843ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_channels_destroy(struct mlx5e_rx_res *res) 37943ec0f41SMaxim Mikityanskiy { 38043ec0f41SMaxim Mikityanskiy unsigned int ix; 38143ec0f41SMaxim Mikityanskiy 38243ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 38343ec0f41SMaxim Mikityanskiy mlx5e_tir_destroy(&res->channels[ix].direct_tir); 38443ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->channels[ix].direct_rqt); 38543ec0f41SMaxim Mikityanskiy 38643ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_XSK)) 38743ec0f41SMaxim Mikityanskiy continue; 38843ec0f41SMaxim Mikityanskiy 38943ec0f41SMaxim Mikityanskiy mlx5e_tir_destroy(&res->channels[ix].xsk_tir); 39043ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->channels[ix].xsk_rqt); 39143ec0f41SMaxim Mikityanskiy } 3923ac90decSMaxim Mikityanskiy 3933ac90decSMaxim Mikityanskiy kvfree(res->channels); 39443ec0f41SMaxim Mikityanskiy } 39543ec0f41SMaxim Mikityanskiy 39643ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_ptp_destroy(struct mlx5e_rx_res *res) 39743ec0f41SMaxim Mikityanskiy { 39843ec0f41SMaxim Mikityanskiy mlx5e_tir_destroy(&res->ptp.tir); 39943ec0f41SMaxim Mikityanskiy mlx5e_rqt_destroy(&res->ptp.rqt); 40043ec0f41SMaxim Mikityanskiy } 40143ec0f41SMaxim Mikityanskiy 40243ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, 40343ec0f41SMaxim Mikityanskiy enum mlx5e_rx_res_features features, unsigned int max_nch, 40443ec0f41SMaxim Mikityanskiy u32 drop_rqn, const struct mlx5e_lro_param *init_lro_param, 40543ec0f41SMaxim Mikityanskiy unsigned int init_nch) 40643ec0f41SMaxim Mikityanskiy { 40743ec0f41SMaxim Mikityanskiy int err; 40843ec0f41SMaxim Mikityanskiy 40943ec0f41SMaxim Mikityanskiy res->mdev = mdev; 41043ec0f41SMaxim Mikityanskiy res->features = features; 41143ec0f41SMaxim Mikityanskiy res->max_nch = max_nch; 41243ec0f41SMaxim Mikityanskiy res->drop_rqn = drop_rqn; 41343ec0f41SMaxim Mikityanskiy 41443ec0f41SMaxim Mikityanskiy mlx5e_rx_res_rss_params_init(res, init_nch); 41543ec0f41SMaxim Mikityanskiy 41643ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_rss_init(res, init_lro_param); 41743ec0f41SMaxim Mikityanskiy if (err) 41843ec0f41SMaxim Mikityanskiy return err; 41943ec0f41SMaxim Mikityanskiy 42043ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_channels_init(res, init_lro_param); 42143ec0f41SMaxim Mikityanskiy if (err) 42243ec0f41SMaxim Mikityanskiy goto err_rss_destroy; 42343ec0f41SMaxim Mikityanskiy 42443ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_ptp_init(res); 42543ec0f41SMaxim Mikityanskiy if (err) 42643ec0f41SMaxim Mikityanskiy goto err_channels_destroy; 42743ec0f41SMaxim Mikityanskiy 42843ec0f41SMaxim Mikityanskiy return 0; 42943ec0f41SMaxim Mikityanskiy 43043ec0f41SMaxim Mikityanskiy err_channels_destroy: 43143ec0f41SMaxim Mikityanskiy mlx5e_rx_res_channels_destroy(res); 43243ec0f41SMaxim Mikityanskiy err_rss_destroy: 43343ec0f41SMaxim Mikityanskiy mlx5e_rx_res_rss_destroy(res); 43443ec0f41SMaxim Mikityanskiy return err; 43543ec0f41SMaxim Mikityanskiy } 43643ec0f41SMaxim Mikityanskiy 43743ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_destroy(struct mlx5e_rx_res *res) 43843ec0f41SMaxim Mikityanskiy { 43943ec0f41SMaxim Mikityanskiy mlx5e_rx_res_ptp_destroy(res); 44043ec0f41SMaxim Mikityanskiy mlx5e_rx_res_channels_destroy(res); 44143ec0f41SMaxim Mikityanskiy mlx5e_rx_res_rss_destroy(res); 44243ec0f41SMaxim Mikityanskiy } 44343ec0f41SMaxim Mikityanskiy 44443ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_free(struct mlx5e_rx_res *res) 44543ec0f41SMaxim Mikityanskiy { 44643ec0f41SMaxim Mikityanskiy kvfree(res); 44743ec0f41SMaxim Mikityanskiy } 44843ec0f41SMaxim Mikityanskiy 44943ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_direct(struct mlx5e_rx_res *res, unsigned int ix) 45043ec0f41SMaxim Mikityanskiy { 45143ec0f41SMaxim Mikityanskiy return mlx5e_tir_get_tirn(&res->channels[ix].direct_tir); 45243ec0f41SMaxim Mikityanskiy } 45343ec0f41SMaxim Mikityanskiy 45443ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_xsk(struct mlx5e_rx_res *res, unsigned int ix) 45543ec0f41SMaxim Mikityanskiy { 45643ec0f41SMaxim Mikityanskiy WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_XSK)); 45743ec0f41SMaxim Mikityanskiy 45843ec0f41SMaxim Mikityanskiy return mlx5e_tir_get_tirn(&res->channels[ix].xsk_tir); 45943ec0f41SMaxim Mikityanskiy } 46043ec0f41SMaxim Mikityanskiy 461d443c6f6SMaor Gottlieb u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) 46243ec0f41SMaxim Mikityanskiy { 46343ec0f41SMaxim Mikityanskiy return mlx5e_tir_get_tirn(&res->rss[tt].indir_tir); 46443ec0f41SMaxim Mikityanskiy } 46543ec0f41SMaxim Mikityanskiy 466d443c6f6SMaor Gottlieb u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) 46743ec0f41SMaxim Mikityanskiy { 46843ec0f41SMaxim Mikityanskiy WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT)); 46943ec0f41SMaxim Mikityanskiy return mlx5e_tir_get_tirn(&res->rss[tt].inner_indir_tir); 47043ec0f41SMaxim Mikityanskiy } 47143ec0f41SMaxim Mikityanskiy 47243ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res) 47343ec0f41SMaxim Mikityanskiy { 47443ec0f41SMaxim Mikityanskiy WARN_ON(!(res->features & MLX5E_RX_RES_FEATURE_PTP)); 47543ec0f41SMaxim Mikityanskiy return mlx5e_tir_get_tirn(&res->ptp.tir); 47643ec0f41SMaxim Mikityanskiy } 47743ec0f41SMaxim Mikityanskiy 47843ec0f41SMaxim Mikityanskiy u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) 47943ec0f41SMaxim Mikityanskiy { 48043ec0f41SMaxim Mikityanskiy return mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt); 48143ec0f41SMaxim Mikityanskiy } 48243ec0f41SMaxim Mikityanskiy 48343ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_enable(struct mlx5e_rx_res *res) 48443ec0f41SMaxim Mikityanskiy { 48543ec0f41SMaxim Mikityanskiy int err; 48643ec0f41SMaxim Mikityanskiy 48743ec0f41SMaxim Mikityanskiy res->rss_active = true; 48843ec0f41SMaxim Mikityanskiy 48943ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_indir(&res->indir_rqt, res->rss_rqns, res->rss_nch, 49043ec0f41SMaxim Mikityanskiy res->rss_params.hash.hfunc, 49143ec0f41SMaxim Mikityanskiy &res->rss_params.indir); 49243ec0f41SMaxim Mikityanskiy if (err) 49343ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect indirect RQT %#x to channels: err = %d\n", 49443ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->indir_rqt), err); 49543ec0f41SMaxim Mikityanskiy } 49643ec0f41SMaxim Mikityanskiy 49743ec0f41SMaxim Mikityanskiy static void mlx5e_rx_res_rss_disable(struct mlx5e_rx_res *res) 49843ec0f41SMaxim Mikityanskiy { 49943ec0f41SMaxim Mikityanskiy int err; 50043ec0f41SMaxim Mikityanskiy 50143ec0f41SMaxim Mikityanskiy res->rss_active = false; 50243ec0f41SMaxim Mikityanskiy 50343ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->indir_rqt, res->drop_rqn); 50443ec0f41SMaxim Mikityanskiy if (err) 50543ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect indirect RQT %#x to drop RQ %#x: err = %d\n", 50643ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->indir_rqt), res->drop_rqn, err); 50743ec0f41SMaxim Mikityanskiy } 50843ec0f41SMaxim Mikityanskiy 50943ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs) 51043ec0f41SMaxim Mikityanskiy { 51143ec0f41SMaxim Mikityanskiy unsigned int nch, ix; 51243ec0f41SMaxim Mikityanskiy int err; 51343ec0f41SMaxim Mikityanskiy 51443ec0f41SMaxim Mikityanskiy nch = mlx5e_channels_get_num(chs); 51543ec0f41SMaxim Mikityanskiy 51643ec0f41SMaxim Mikityanskiy for (ix = 0; ix < chs->num; ix++) 51743ec0f41SMaxim Mikityanskiy mlx5e_channels_get_regular_rqn(chs, ix, &res->rss_rqns[ix]); 51843ec0f41SMaxim Mikityanskiy res->rss_nch = chs->num; 51943ec0f41SMaxim Mikityanskiy 52043ec0f41SMaxim Mikityanskiy mlx5e_rx_res_rss_enable(res); 52143ec0f41SMaxim Mikityanskiy 52243ec0f41SMaxim Mikityanskiy for (ix = 0; ix < nch; ix++) { 52343ec0f41SMaxim Mikityanskiy u32 rqn; 52443ec0f41SMaxim Mikityanskiy 52543ec0f41SMaxim Mikityanskiy mlx5e_channels_get_regular_rqn(chs, ix, &rqn); 52643ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, rqn); 52743ec0f41SMaxim Mikityanskiy if (err) 52843ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (channel %u): err = %d\n", 52943ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 53043ec0f41SMaxim Mikityanskiy rqn, ix, err); 53143ec0f41SMaxim Mikityanskiy 53243ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_XSK)) 53343ec0f41SMaxim Mikityanskiy continue; 53443ec0f41SMaxim Mikityanskiy 53543ec0f41SMaxim Mikityanskiy if (!mlx5e_channels_get_xsk_rqn(chs, ix, &rqn)) 53643ec0f41SMaxim Mikityanskiy rqn = res->drop_rqn; 53743ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, rqn); 53843ec0f41SMaxim Mikityanskiy if (err) 53943ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to RQ %#x (channel %u): err = %d\n", 54043ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), 54143ec0f41SMaxim Mikityanskiy rqn, ix, err); 54243ec0f41SMaxim Mikityanskiy } 54343ec0f41SMaxim Mikityanskiy for (ix = nch; ix < res->max_nch; ix++) { 54443ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn); 54543ec0f41SMaxim Mikityanskiy if (err) 54643ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n", 54743ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 54843ec0f41SMaxim Mikityanskiy res->drop_rqn, ix, err); 54943ec0f41SMaxim Mikityanskiy 55043ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_XSK)) 55143ec0f41SMaxim Mikityanskiy continue; 55243ec0f41SMaxim Mikityanskiy 55343ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, res->drop_rqn); 55443ec0f41SMaxim Mikityanskiy if (err) 55543ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to drop RQ %#x (channel %u): err = %d\n", 55643ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), 55743ec0f41SMaxim Mikityanskiy res->drop_rqn, ix, err); 55843ec0f41SMaxim Mikityanskiy } 55943ec0f41SMaxim Mikityanskiy 56043ec0f41SMaxim Mikityanskiy if (res->features & MLX5E_RX_RES_FEATURE_PTP) { 56143ec0f41SMaxim Mikityanskiy u32 rqn; 56243ec0f41SMaxim Mikityanskiy 56343ec0f41SMaxim Mikityanskiy if (mlx5e_channels_get_ptp_rqn(chs, &rqn)) 56443ec0f41SMaxim Mikityanskiy rqn = res->drop_rqn; 56543ec0f41SMaxim Mikityanskiy 56643ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, rqn); 56743ec0f41SMaxim Mikityanskiy if (err) 56843ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to RQ %#x (PTP): err = %d\n", 56943ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->ptp.rqt), 57043ec0f41SMaxim Mikityanskiy rqn, err); 57143ec0f41SMaxim Mikityanskiy } 57243ec0f41SMaxim Mikityanskiy } 57343ec0f41SMaxim Mikityanskiy 57443ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res) 57543ec0f41SMaxim Mikityanskiy { 57643ec0f41SMaxim Mikityanskiy unsigned int ix; 57743ec0f41SMaxim Mikityanskiy int err; 57843ec0f41SMaxim Mikityanskiy 57943ec0f41SMaxim Mikityanskiy mlx5e_rx_res_rss_disable(res); 58043ec0f41SMaxim Mikityanskiy 58143ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 58243ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].direct_rqt, res->drop_rqn); 58343ec0f41SMaxim Mikityanskiy if (err) 58443ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (channel %u): err = %d\n", 58543ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt), 58643ec0f41SMaxim Mikityanskiy res->drop_rqn, ix, err); 58743ec0f41SMaxim Mikityanskiy 58843ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_XSK)) 58943ec0f41SMaxim Mikityanskiy continue; 59043ec0f41SMaxim Mikityanskiy 59143ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, res->drop_rqn); 59243ec0f41SMaxim Mikityanskiy if (err) 59343ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to drop RQ %#x (channel %u): err = %d\n", 59443ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), 59543ec0f41SMaxim Mikityanskiy res->drop_rqn, ix, err); 59643ec0f41SMaxim Mikityanskiy } 59743ec0f41SMaxim Mikityanskiy 59843ec0f41SMaxim Mikityanskiy if (res->features & MLX5E_RX_RES_FEATURE_PTP) { 59943ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->ptp.rqt, res->drop_rqn); 60043ec0f41SMaxim Mikityanskiy if (err) 60143ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect direct RQT %#x to drop RQ %#x (PTP): err = %d\n", 60243ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->ptp.rqt), 60343ec0f41SMaxim Mikityanskiy res->drop_rqn, err); 60443ec0f41SMaxim Mikityanskiy } 60543ec0f41SMaxim Mikityanskiy } 60643ec0f41SMaxim Mikityanskiy 60743ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_xsk_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs, 60843ec0f41SMaxim Mikityanskiy unsigned int ix) 60943ec0f41SMaxim Mikityanskiy { 61043ec0f41SMaxim Mikityanskiy u32 rqn; 61143ec0f41SMaxim Mikityanskiy int err; 61243ec0f41SMaxim Mikityanskiy 61343ec0f41SMaxim Mikityanskiy if (!mlx5e_channels_get_xsk_rqn(chs, ix, &rqn)) 61443ec0f41SMaxim Mikityanskiy return -EINVAL; 61543ec0f41SMaxim Mikityanskiy 61643ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, rqn); 61743ec0f41SMaxim Mikityanskiy if (err) 61843ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to XSK RQ %#x (channel %u): err = %d\n", 61943ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), 62043ec0f41SMaxim Mikityanskiy rqn, ix, err); 62143ec0f41SMaxim Mikityanskiy return err; 62243ec0f41SMaxim Mikityanskiy } 62343ec0f41SMaxim Mikityanskiy 62443ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_xsk_deactivate(struct mlx5e_rx_res *res, unsigned int ix) 62543ec0f41SMaxim Mikityanskiy { 62643ec0f41SMaxim Mikityanskiy int err; 62743ec0f41SMaxim Mikityanskiy 62843ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_direct(&res->channels[ix].xsk_rqt, res->drop_rqn); 62943ec0f41SMaxim Mikityanskiy if (err) 63043ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect XSK RQT %#x to drop RQ %#x (channel %u): err = %d\n", 63143ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->channels[ix].xsk_rqt), 63243ec0f41SMaxim Mikityanskiy res->drop_rqn, ix, err); 63343ec0f41SMaxim Mikityanskiy return err; 63443ec0f41SMaxim Mikityanskiy } 63543ec0f41SMaxim Mikityanskiy 63665d6b6e5SMaxim Mikityanskiy struct mlx5e_rss_params_traffic_type 637d443c6f6SMaor Gottlieb mlx5e_rx_res_rss_get_current_tt_config(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) 63865d6b6e5SMaxim Mikityanskiy { 63965d6b6e5SMaxim Mikityanskiy struct mlx5e_rss_params_traffic_type rss_tt; 64065d6b6e5SMaxim Mikityanskiy 64165d6b6e5SMaxim Mikityanskiy rss_tt = mlx5e_rss_get_default_tt_config(tt); 64265d6b6e5SMaxim Mikityanskiy rss_tt.rx_hash_fields = res->rss_params.rx_hash_fields[tt]; 64365d6b6e5SMaxim Mikityanskiy return rss_tt; 64465d6b6e5SMaxim Mikityanskiy } 64543ec0f41SMaxim Mikityanskiy 6466e5fea51STariq Toukan /* Updates the indirection table SW shadow, does not update the HW resources yet */ 64743ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_rss_set_indir_uniform(struct mlx5e_rx_res *res, unsigned int nch) 64843ec0f41SMaxim Mikityanskiy { 6496e5fea51STariq Toukan WARN_ON_ONCE(res->rss_active); 65043ec0f41SMaxim Mikityanskiy mlx5e_rss_params_indir_init_uniform(&res->rss_params.indir, nch); 65143ec0f41SMaxim Mikityanskiy } 65243ec0f41SMaxim Mikityanskiy 65343ec0f41SMaxim Mikityanskiy void mlx5e_rx_res_rss_get_rxfh(struct mlx5e_rx_res *res, u32 *indir, u8 *key, u8 *hfunc) 65443ec0f41SMaxim Mikityanskiy { 65543ec0f41SMaxim Mikityanskiy unsigned int i; 65643ec0f41SMaxim Mikityanskiy 65743ec0f41SMaxim Mikityanskiy if (indir) 65843ec0f41SMaxim Mikityanskiy for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) 65943ec0f41SMaxim Mikityanskiy indir[i] = res->rss_params.indir.table[i]; 66043ec0f41SMaxim Mikityanskiy 66143ec0f41SMaxim Mikityanskiy if (key) 66243ec0f41SMaxim Mikityanskiy memcpy(key, res->rss_params.hash.toeplitz_hash_key, 66343ec0f41SMaxim Mikityanskiy sizeof(res->rss_params.hash.toeplitz_hash_key)); 66443ec0f41SMaxim Mikityanskiy 66543ec0f41SMaxim Mikityanskiy if (hfunc) 66643ec0f41SMaxim Mikityanskiy *hfunc = res->rss_params.hash.hfunc; 66743ec0f41SMaxim Mikityanskiy } 66843ec0f41SMaxim Mikityanskiy 669d443c6f6SMaor Gottlieb static int mlx5e_rx_res_rss_update_tir(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt, 67043ec0f41SMaxim Mikityanskiy bool inner) 67143ec0f41SMaxim Mikityanskiy { 67243ec0f41SMaxim Mikityanskiy struct mlx5e_rss_params_traffic_type rss_tt; 67343ec0f41SMaxim Mikityanskiy struct mlx5e_tir_builder *builder; 67443ec0f41SMaxim Mikityanskiy struct mlx5e_tir *tir; 67543ec0f41SMaxim Mikityanskiy int err; 67643ec0f41SMaxim Mikityanskiy 67743ec0f41SMaxim Mikityanskiy builder = mlx5e_tir_builder_alloc(true); 67843ec0f41SMaxim Mikityanskiy if (!builder) 67943ec0f41SMaxim Mikityanskiy return -ENOMEM; 68043ec0f41SMaxim Mikityanskiy 68143ec0f41SMaxim Mikityanskiy rss_tt = mlx5e_rx_res_rss_get_current_tt_config(res, tt); 68243ec0f41SMaxim Mikityanskiy 68343ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_rss(builder, &res->rss_params.hash, &rss_tt, inner); 68443ec0f41SMaxim Mikityanskiy tir = inner ? &res->rss[tt].inner_indir_tir : &res->rss[tt].indir_tir; 68543ec0f41SMaxim Mikityanskiy err = mlx5e_tir_modify(tir, builder); 68643ec0f41SMaxim Mikityanskiy 68743ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_free(builder); 68843ec0f41SMaxim Mikityanskiy return err; 68943ec0f41SMaxim Mikityanskiy } 69043ec0f41SMaxim Mikityanskiy 69143ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_rss_set_rxfh(struct mlx5e_rx_res *res, const u32 *indir, 69243ec0f41SMaxim Mikityanskiy const u8 *key, const u8 *hfunc) 69343ec0f41SMaxim Mikityanskiy { 694d443c6f6SMaor Gottlieb enum mlx5_traffic_types tt; 69543ec0f41SMaxim Mikityanskiy bool changed_indir = false; 69643ec0f41SMaxim Mikityanskiy bool changed_hash = false; 69743ec0f41SMaxim Mikityanskiy int err; 69843ec0f41SMaxim Mikityanskiy 69943ec0f41SMaxim Mikityanskiy if (hfunc && *hfunc != res->rss_params.hash.hfunc) { 70043ec0f41SMaxim Mikityanskiy switch (*hfunc) { 70143ec0f41SMaxim Mikityanskiy case ETH_RSS_HASH_XOR: 70243ec0f41SMaxim Mikityanskiy case ETH_RSS_HASH_TOP: 70343ec0f41SMaxim Mikityanskiy break; 70443ec0f41SMaxim Mikityanskiy default: 70543ec0f41SMaxim Mikityanskiy return -EINVAL; 70643ec0f41SMaxim Mikityanskiy } 70743ec0f41SMaxim Mikityanskiy changed_hash = true; 70843ec0f41SMaxim Mikityanskiy changed_indir = true; 70943ec0f41SMaxim Mikityanskiy res->rss_params.hash.hfunc = *hfunc; 71043ec0f41SMaxim Mikityanskiy } 71143ec0f41SMaxim Mikityanskiy 71243ec0f41SMaxim Mikityanskiy if (key) { 71343ec0f41SMaxim Mikityanskiy if (res->rss_params.hash.hfunc == ETH_RSS_HASH_TOP) 71443ec0f41SMaxim Mikityanskiy changed_hash = true; 71543ec0f41SMaxim Mikityanskiy memcpy(res->rss_params.hash.toeplitz_hash_key, key, 71643ec0f41SMaxim Mikityanskiy sizeof(res->rss_params.hash.toeplitz_hash_key)); 71743ec0f41SMaxim Mikityanskiy } 71843ec0f41SMaxim Mikityanskiy 71943ec0f41SMaxim Mikityanskiy if (indir) { 72043ec0f41SMaxim Mikityanskiy unsigned int i; 72143ec0f41SMaxim Mikityanskiy 72243ec0f41SMaxim Mikityanskiy changed_indir = true; 72343ec0f41SMaxim Mikityanskiy 72443ec0f41SMaxim Mikityanskiy for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) 72543ec0f41SMaxim Mikityanskiy res->rss_params.indir.table[i] = indir[i]; 72643ec0f41SMaxim Mikityanskiy } 72743ec0f41SMaxim Mikityanskiy 72843ec0f41SMaxim Mikityanskiy if (changed_indir && res->rss_active) { 72943ec0f41SMaxim Mikityanskiy err = mlx5e_rqt_redirect_indir(&res->indir_rqt, res->rss_rqns, res->rss_nch, 73043ec0f41SMaxim Mikityanskiy res->rss_params.hash.hfunc, 73143ec0f41SMaxim Mikityanskiy &res->rss_params.indir); 73243ec0f41SMaxim Mikityanskiy if (err) 73343ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to redirect indirect RQT %#x to channels: err = %d\n", 73443ec0f41SMaxim Mikityanskiy mlx5e_rqt_get_rqtn(&res->indir_rqt), err); 73543ec0f41SMaxim Mikityanskiy } 73643ec0f41SMaxim Mikityanskiy 73743ec0f41SMaxim Mikityanskiy if (changed_hash) 73843ec0f41SMaxim Mikityanskiy for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { 73943ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_rss_update_tir(res, tt, false); 74043ec0f41SMaxim Mikityanskiy if (err) 74143ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update RSS hash of indirect TIR for traffic type %d: err = %d\n", 74243ec0f41SMaxim Mikityanskiy tt, err); 74343ec0f41SMaxim Mikityanskiy 74443ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT)) 74543ec0f41SMaxim Mikityanskiy continue; 74643ec0f41SMaxim Mikityanskiy 74743ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_rss_update_tir(res, tt, true); 74843ec0f41SMaxim Mikityanskiy if (err) 74943ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update RSS hash of inner indirect TIR for traffic type %d: err = %d\n", 75043ec0f41SMaxim Mikityanskiy tt, err); 75143ec0f41SMaxim Mikityanskiy } 75243ec0f41SMaxim Mikityanskiy 75343ec0f41SMaxim Mikityanskiy return 0; 75443ec0f41SMaxim Mikityanskiy } 75543ec0f41SMaxim Mikityanskiy 756d443c6f6SMaor Gottlieb u8 mlx5e_rx_res_rss_get_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt) 75743ec0f41SMaxim Mikityanskiy { 75843ec0f41SMaxim Mikityanskiy return res->rss_params.rx_hash_fields[tt]; 75943ec0f41SMaxim Mikityanskiy } 76043ec0f41SMaxim Mikityanskiy 761d443c6f6SMaor Gottlieb int mlx5e_rx_res_rss_set_hash_fields(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt, 76243ec0f41SMaxim Mikityanskiy u8 rx_hash_fields) 76343ec0f41SMaxim Mikityanskiy { 76443ec0f41SMaxim Mikityanskiy u8 old_rx_hash_fields; 76543ec0f41SMaxim Mikityanskiy int err; 76643ec0f41SMaxim Mikityanskiy 76743ec0f41SMaxim Mikityanskiy old_rx_hash_fields = res->rss_params.rx_hash_fields[tt]; 76843ec0f41SMaxim Mikityanskiy 76943ec0f41SMaxim Mikityanskiy if (old_rx_hash_fields == rx_hash_fields) 77043ec0f41SMaxim Mikityanskiy return 0; 77143ec0f41SMaxim Mikityanskiy 77243ec0f41SMaxim Mikityanskiy res->rss_params.rx_hash_fields[tt] = rx_hash_fields; 77343ec0f41SMaxim Mikityanskiy 77443ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_rss_update_tir(res, tt, false); 77543ec0f41SMaxim Mikityanskiy if (err) { 77643ec0f41SMaxim Mikityanskiy res->rss_params.rx_hash_fields[tt] = old_rx_hash_fields; 77743ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update RSS hash fields of indirect TIR for traffic type %d: err = %d\n", 77843ec0f41SMaxim Mikityanskiy tt, err); 77943ec0f41SMaxim Mikityanskiy return err; 78043ec0f41SMaxim Mikityanskiy } 78143ec0f41SMaxim Mikityanskiy 78243ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT)) 78343ec0f41SMaxim Mikityanskiy return 0; 78443ec0f41SMaxim Mikityanskiy 78543ec0f41SMaxim Mikityanskiy err = mlx5e_rx_res_rss_update_tir(res, tt, true); 78643ec0f41SMaxim Mikityanskiy if (err) { 78743ec0f41SMaxim Mikityanskiy /* Partial update happened. Try to revert - it may fail too, but 78843ec0f41SMaxim Mikityanskiy * there is nothing more we can do. 78943ec0f41SMaxim Mikityanskiy */ 79043ec0f41SMaxim Mikityanskiy res->rss_params.rx_hash_fields[tt] = old_rx_hash_fields; 79143ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update RSS hash fields of inner indirect TIR for traffic type %d: err = %d\n", 79243ec0f41SMaxim Mikityanskiy tt, err); 79343ec0f41SMaxim Mikityanskiy if (mlx5e_rx_res_rss_update_tir(res, tt, false)) 79443ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Partial update of RSS hash fields happened: failed to revert indirect TIR for traffic type %d to the old values\n", 79543ec0f41SMaxim Mikityanskiy tt); 79643ec0f41SMaxim Mikityanskiy } 79743ec0f41SMaxim Mikityanskiy 79843ec0f41SMaxim Mikityanskiy return err; 79943ec0f41SMaxim Mikityanskiy } 80043ec0f41SMaxim Mikityanskiy 80143ec0f41SMaxim Mikityanskiy int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param *lro_param) 80243ec0f41SMaxim Mikityanskiy { 80343ec0f41SMaxim Mikityanskiy struct mlx5e_tir_builder *builder; 804d443c6f6SMaor Gottlieb enum mlx5_traffic_types tt; 80543ec0f41SMaxim Mikityanskiy int err, final_err; 80643ec0f41SMaxim Mikityanskiy unsigned int ix; 80743ec0f41SMaxim Mikityanskiy 80843ec0f41SMaxim Mikityanskiy builder = mlx5e_tir_builder_alloc(true); 80943ec0f41SMaxim Mikityanskiy if (!builder) 81043ec0f41SMaxim Mikityanskiy return -ENOMEM; 81143ec0f41SMaxim Mikityanskiy 81243ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_build_lro(builder, lro_param); 81343ec0f41SMaxim Mikityanskiy 81443ec0f41SMaxim Mikityanskiy final_err = 0; 81543ec0f41SMaxim Mikityanskiy 81643ec0f41SMaxim Mikityanskiy for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) { 81743ec0f41SMaxim Mikityanskiy err = mlx5e_tir_modify(&res->rss[tt].indir_tir, builder); 81843ec0f41SMaxim Mikityanskiy if (err) { 81943ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update LRO state of indirect TIR %#x for traffic type %d: err = %d\n", 82043ec0f41SMaxim Mikityanskiy mlx5e_tir_get_tirn(&res->rss[tt].indir_tir), tt, err); 82143ec0f41SMaxim Mikityanskiy if (!final_err) 82243ec0f41SMaxim Mikityanskiy final_err = err; 82343ec0f41SMaxim Mikityanskiy } 82443ec0f41SMaxim Mikityanskiy 82543ec0f41SMaxim Mikityanskiy if (!(res->features & MLX5E_RX_RES_FEATURE_INNER_FT)) 82643ec0f41SMaxim Mikityanskiy continue; 82743ec0f41SMaxim Mikityanskiy 82843ec0f41SMaxim Mikityanskiy err = mlx5e_tir_modify(&res->rss[tt].inner_indir_tir, builder); 82943ec0f41SMaxim Mikityanskiy if (err) { 83043ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update LRO state of inner indirect TIR %#x for traffic type %d: err = %d\n", 83143ec0f41SMaxim Mikityanskiy mlx5e_tir_get_tirn(&res->rss[tt].inner_indir_tir), tt, err); 83243ec0f41SMaxim Mikityanskiy if (!final_err) 83343ec0f41SMaxim Mikityanskiy final_err = err; 83443ec0f41SMaxim Mikityanskiy } 83543ec0f41SMaxim Mikityanskiy } 83643ec0f41SMaxim Mikityanskiy 83743ec0f41SMaxim Mikityanskiy for (ix = 0; ix < res->max_nch; ix++) { 83843ec0f41SMaxim Mikityanskiy err = mlx5e_tir_modify(&res->channels[ix].direct_tir, builder); 83943ec0f41SMaxim Mikityanskiy if (err) { 84043ec0f41SMaxim Mikityanskiy mlx5_core_warn(res->mdev, "Failed to update LRO state of direct TIR %#x for channel %u: err = %d\n", 84143ec0f41SMaxim Mikityanskiy mlx5e_tir_get_tirn(&res->channels[ix].direct_tir), ix, err); 84243ec0f41SMaxim Mikityanskiy if (!final_err) 84343ec0f41SMaxim Mikityanskiy final_err = err; 84443ec0f41SMaxim Mikityanskiy } 84543ec0f41SMaxim Mikityanskiy } 84643ec0f41SMaxim Mikityanskiy 84743ec0f41SMaxim Mikityanskiy mlx5e_tir_builder_free(builder); 84843ec0f41SMaxim Mikityanskiy return final_err; 84943ec0f41SMaxim Mikityanskiy } 85043ec0f41SMaxim Mikityanskiy 85143ec0f41SMaxim Mikityanskiy struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res) 85243ec0f41SMaxim Mikityanskiy { 85343ec0f41SMaxim Mikityanskiy return res->rss_params.hash; 85443ec0f41SMaxim Mikityanskiy } 855