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