Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright (c) 2022 NVIDIA Corporation & Affiliates 3 : : */ 4 : : 5 : : #include "mlx5dr_internal.h" 6 : : 7 : 0 : bool mlx5dr_context_cap_dynamic_reparse(struct mlx5dr_context *ctx) 8 : : { 9 : 0 : return IS_BIT_SET(ctx->caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_BY_STC); 10 : : } 11 : : 12 : 0 : uint8_t mlx5dr_context_get_reparse_mode(struct mlx5dr_context *ctx) 13 : : { 14 : : /* Prefer to use dynamic reparse, reparse only specific actions */ 15 [ # # ]: 0 : if (mlx5dr_context_cap_dynamic_reparse(ctx)) 16 : 0 : return MLX5_IFC_RTC_REPARSE_NEVER; 17 : : 18 : : /* Otherwise use less efficient static */ 19 : : return MLX5_IFC_RTC_REPARSE_ALWAYS; 20 : : } 21 : : 22 : 0 : static int mlx5dr_context_pools_init(struct mlx5dr_context *ctx) 23 : : { 24 : 0 : struct mlx5dr_pool_attr pool_attr = {0}; 25 : : uint8_t max_log_sz; 26 : : int i; 27 : : 28 [ # # ]: 0 : if (mlx5dr_pat_init_pattern_cache(&ctx->pattern_cache)) 29 : 0 : return rte_errno; 30 : : 31 [ # # ]: 0 : if (mlx5dr_definer_init_cache(&ctx->definer_cache)) 32 : 0 : goto uninit_pat_cache; 33 : : 34 : : /* Create an STC pool per FT type */ 35 : 0 : pool_attr.pool_type = MLX5DR_POOL_TYPE_STC; 36 : 0 : pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_STC_POOL; 37 : 0 : max_log_sz = RTE_MIN(MLX5DR_POOL_STC_LOG_SZ, ctx->caps->stc_alloc_log_max); 38 : 0 : pool_attr.alloc_log_sz = RTE_MAX(max_log_sz, ctx->caps->stc_alloc_log_gran); 39 : : 40 [ # # ]: 0 : for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) { 41 : 0 : pool_attr.table_type = i; 42 : 0 : ctx->stc_pool[i] = mlx5dr_pool_create(ctx, &pool_attr); 43 [ # # ]: 0 : if (!ctx->stc_pool[i]) { 44 : 0 : DR_LOG(ERR, "Failed to allocate STC pool [%d]", i); 45 : 0 : goto free_stc_pools; 46 : : } 47 : : } 48 : : 49 : : return 0; 50 : : 51 : : free_stc_pools: 52 [ # # ]: 0 : for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) 53 [ # # ]: 0 : if (ctx->stc_pool[i]) 54 : 0 : mlx5dr_pool_destroy(ctx->stc_pool[i]); 55 : : 56 : 0 : mlx5dr_definer_uninit_cache(ctx->definer_cache); 57 : : 58 : 0 : uninit_pat_cache: 59 : 0 : mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache); 60 : 0 : return rte_errno; 61 : : } 62 : : 63 : 0 : static void mlx5dr_context_pools_uninit(struct mlx5dr_context *ctx) 64 : : { 65 : : int i; 66 : : 67 [ # # ]: 0 : for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) { 68 [ # # ]: 0 : if (ctx->stc_pool[i]) 69 : 0 : mlx5dr_pool_destroy(ctx->stc_pool[i]); 70 : : } 71 : : 72 : 0 : mlx5dr_definer_uninit_cache(ctx->definer_cache); 73 : 0 : mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache); 74 : 0 : } 75 : : 76 : 0 : static int mlx5dr_context_init_pd(struct mlx5dr_context *ctx, 77 : : struct ibv_pd *pd) 78 : : { 79 : 0 : struct mlx5dv_pd mlx5_pd = {0}; 80 : : struct mlx5dv_obj obj; 81 : : int ret; 82 : : 83 [ # # ]: 0 : if (pd) { 84 : 0 : ctx->pd = pd; 85 : : } else { 86 : 0 : ctx->pd = mlx5_glue->alloc_pd(ctx->ibv_ctx); 87 [ # # ]: 0 : if (!ctx->pd) { 88 : 0 : DR_LOG(ERR, "Failed to allocate PD"); 89 : 0 : rte_errno = errno; 90 : 0 : return rte_errno; 91 : : } 92 : 0 : ctx->flags |= MLX5DR_CONTEXT_FLAG_PRIVATE_PD; 93 : : } 94 : : 95 : 0 : obj.pd.in = ctx->pd; 96 : 0 : obj.pd.out = &mlx5_pd; 97 : : 98 : 0 : ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD); 99 [ # # ]: 0 : if (ret) 100 : 0 : goto free_private_pd; 101 : : 102 : 0 : ctx->pd_num = mlx5_pd.pdn; 103 : : 104 : 0 : return 0; 105 : : 106 : : free_private_pd: 107 [ # # ]: 0 : if (ctx->flags & MLX5DR_CONTEXT_FLAG_PRIVATE_PD) 108 : 0 : mlx5_glue->dealloc_pd(ctx->pd); 109 : : 110 : : return ret; 111 : : } 112 : : 113 : : static int mlx5dr_context_uninit_pd(struct mlx5dr_context *ctx) 114 : : { 115 [ # # ]: 0 : if (ctx->flags & MLX5DR_CONTEXT_FLAG_PRIVATE_PD) 116 : 0 : return mlx5_glue->dealloc_pd(ctx->pd); 117 : : 118 : : return 0; 119 : : } 120 : : 121 : 0 : static void mlx5dr_context_check_hws_supp(struct mlx5dr_context *ctx) 122 : : { 123 : 0 : struct mlx5dr_cmd_query_caps *caps = ctx->caps; 124 : : 125 : : /* HWS not supported on device / FW */ 126 [ # # ]: 0 : if (!caps->wqe_based_update) { 127 : 0 : DR_LOG(INFO, "Required HWS WQE based insertion cap not supported"); 128 : 0 : return; 129 : : } 130 : : 131 : : /* Current solution requires all rules to set reparse bit */ 132 [ # # ]: 0 : if ((!caps->nic_ft.reparse || 133 [ # # # # ]: 0 : (!caps->fdb_ft.reparse && caps->eswitch_manager)) || 134 [ # # ]: 0 : !IS_BIT_SET(caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_ALWAYS)) { 135 : 0 : DR_LOG(INFO, "Required HWS reparse cap not supported"); 136 : 0 : return; 137 : : } 138 : : 139 : : /* FW/HW must support 8DW STE */ 140 [ # # ]: 0 : if (!IS_BIT_SET(caps->ste_format, MLX5_IFC_RTC_STE_FORMAT_8DW)) { 141 : 0 : DR_LOG(INFO, "Required HWS STE format not supported"); 142 : 0 : return; 143 : : } 144 : : 145 : : /* Adding rules by hash and by offset are requirements */ 146 [ # # ]: 0 : if (!IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH) || 147 : : !IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET)) { 148 : 0 : DR_LOG(INFO, "Required HWS RTC update mode not supported"); 149 : 0 : return; 150 : : } 151 : : 152 : : /* Support for SELECT definer ID is required */ 153 [ # # ]: 0 : if (!IS_BIT_SET(caps->definer_format_sup, MLX5_IFC_DEFINER_FORMAT_ID_SELECT)) { 154 : 0 : DR_LOG(INFO, "Required HWS Dynamic definer not supported"); 155 : 0 : return; 156 : : } 157 : : 158 : 0 : ctx->flags |= MLX5DR_CONTEXT_FLAG_HWS_SUPPORT; 159 : : } 160 : : 161 : 0 : static int mlx5dr_context_init_hws(struct mlx5dr_context *ctx, 162 : : struct mlx5dr_context_attr *attr) 163 : : { 164 : : int ret; 165 : : 166 : 0 : mlx5dr_context_check_hws_supp(ctx); 167 : : 168 [ # # ]: 0 : if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) 169 : : return 0; 170 : : 171 : 0 : ret = mlx5dr_context_init_pd(ctx, attr->pd); 172 [ # # ]: 0 : if (ret) 173 : : return ret; 174 : : 175 : 0 : ret = mlx5dr_context_pools_init(ctx); 176 [ # # ]: 0 : if (ret) 177 : 0 : goto uninit_pd; 178 : : 179 : 0 : ret = mlx5dr_send_queues_open(ctx, attr->queues, attr->queue_size); 180 [ # # ]: 0 : if (ret) 181 : 0 : goto pools_uninit; 182 : : 183 : : return 0; 184 : : 185 : : pools_uninit: 186 : 0 : mlx5dr_context_pools_uninit(ctx); 187 [ # # ]: 0 : uninit_pd: 188 : : mlx5dr_context_uninit_pd(ctx); 189 : : return ret; 190 : : } 191 : : 192 : 0 : static void mlx5dr_context_uninit_hws(struct mlx5dr_context *ctx) 193 : : { 194 [ # # ]: 0 : if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) 195 : : return; 196 : : 197 : 0 : mlx5dr_send_queues_close(ctx); 198 : 0 : mlx5dr_context_pools_uninit(ctx); 199 : : mlx5dr_context_uninit_pd(ctx); 200 : : } 201 : : 202 : 0 : static int mlx5dr_context_init_shared_ctx(struct mlx5dr_context *ctx, 203 : : struct ibv_context *ibv_ctx, 204 : : struct mlx5dr_context_attr *attr) 205 : : { 206 : 0 : struct mlx5dr_cmd_query_caps shared_caps = {0}; 207 : : int ret; 208 : : 209 [ # # ]: 0 : if (!attr->shared_ibv_ctx) { 210 : 0 : ctx->ibv_ctx = ibv_ctx; 211 : : } else { 212 : 0 : ctx->ibv_ctx = attr->shared_ibv_ctx; 213 : 0 : ctx->local_ibv_ctx = ibv_ctx; 214 : 0 : ret = mlx5dr_cmd_query_caps(attr->shared_ibv_ctx, &shared_caps); 215 [ # # # # ]: 0 : if (ret || !shared_caps.cross_vhca_resources) { 216 : 0 : DR_LOG(INFO, "No cross_vhca_resources cap for shared ibv"); 217 : 0 : rte_errno = ENOTSUP; 218 : 0 : return rte_errno; 219 : : } 220 : 0 : ctx->caps->shared_vhca_id = shared_caps.vhca_id; 221 : : } 222 : : 223 [ # # # # ]: 0 : if (ctx->local_ibv_ctx && !ctx->caps->cross_vhca_resources) { 224 : 0 : DR_LOG(INFO, "No cross_vhca_resources cap for local ibv"); 225 : 0 : rte_errno = ENOTSUP; 226 : 0 : return rte_errno; 227 : : } 228 : : 229 : : return 0; 230 : : } 231 : : 232 : 0 : struct mlx5dr_context *mlx5dr_context_open(struct ibv_context *ibv_ctx, 233 : : struct mlx5dr_context_attr *attr) 234 : : { 235 : : struct mlx5dr_context *ctx; 236 : : int ret; 237 : : 238 : : ctx = simple_calloc(1, sizeof(*ctx)); 239 [ # # ]: 0 : if (!ctx) { 240 : 0 : rte_errno = ENOMEM; 241 : 0 : return NULL; 242 : : } 243 : : 244 : 0 : pthread_spin_init(&ctx->ctrl_lock, PTHREAD_PROCESS_PRIVATE); 245 : : 246 : 0 : ctx->caps = simple_calloc(1, sizeof(*ctx->caps)); 247 [ # # ]: 0 : if (!ctx->caps) 248 : 0 : goto free_ctx; 249 : : 250 : 0 : ret = mlx5dr_cmd_query_caps(ibv_ctx, ctx->caps); 251 [ # # ]: 0 : if (ret) 252 : 0 : goto free_caps; 253 : : 254 [ # # ]: 0 : if (mlx5dr_context_init_shared_ctx(ctx, ibv_ctx, attr)) 255 : 0 : goto free_caps; 256 : : 257 : 0 : ret = mlx5dr_context_init_hws(ctx, attr); 258 [ # # ]: 0 : if (ret) 259 : 0 : goto free_caps; 260 : : 261 : : return ctx; 262 : : 263 : 0 : free_caps: 264 : 0 : simple_free(ctx->caps); 265 : 0 : free_ctx: 266 : : simple_free(ctx); 267 : 0 : return NULL; 268 : : } 269 : : 270 : 0 : int mlx5dr_context_close(struct mlx5dr_context *ctx) 271 : : { 272 : 0 : mlx5dr_context_uninit_hws(ctx); 273 : 0 : simple_free(ctx->caps); 274 : 0 : pthread_spin_destroy(&ctx->ctrl_lock); 275 : : simple_free(ctx); 276 : 0 : return 0; 277 : : }