FILE
context.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2/* Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved. */ 3 4#include "internal.h" 5 6bool mlx5hws_context_cap_dynamic_reparse(struct mlx5hws_context *ctx) 7{ 8 return IS_BIT_SET(ctx->caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_BY_STC); 9} 10 11u8 mlx5hws_context_get_reparse_mode(struct mlx5hws_context *ctx) 12{ 13 /* Prefer to use dynamic reparse, reparse only specific actions */ 14 if (mlx5hws_context_cap_dynamic_reparse(ctx)) 15 return MLX5_IFC_RTC_REPARSE_NEVER; 16 17 /* Otherwise use less efficient static */ 18 return MLX5_IFC_RTC_REPARSE_ALWAYS; 19} 20 21static int hws_context_pools_init(struct mlx5hws_context *ctx) 22{ 23 struct mlx5hws_pool_attr pool_attr = {0}; 24 u8 max_log_sz; 25 int ret; 26 27 ret = mlx5hws_pat_init_pattern_cache(&ctx->pattern_cache); 28 if (ret) 29 return ret; 30 31 ret = mlx5hws_definer_init_cache(&ctx->definer_cache); 32 if (ret) 33 goto uninit_pat_cache; 34 35 /* Create an STC pool per FT type */ 36 pool_attr.pool_type = MLX5HWS_POOL_TYPE_STC; 37 max_log_sz = min(MLX5HWS_POOL_STC_LOG_SZ, ctx->caps->stc_alloc_log_max); 38 pool_attr.alloc_log_sz = max(max_log_sz, ctx->caps->stc_alloc_log_gran); 39 40 pool_attr.table_type = MLX5HWS_TABLE_TYPE_FDB; 41 ctx->stc_pool = mlx5hws_pool_create(ctx, &pool_attr); 42 if (!ctx->stc_pool) { 43 mlx5hws_err(ctx, "Failed to allocate STC pool\n"); 44 ret = -ENOMEM; 45 goto uninit_cache; 46 } 47 48 return 0; 49 50uninit_cache: 51 mlx5hws_definer_uninit_cache(ctx->definer_cache); 52uninit_pat_cache: 53 mlx5hws_pat_uninit_pattern_cache(ctx->pattern_cache); 54 return ret; 55} 56 57static void hws_context_pools_uninit(struct mlx5hws_context *ctx) 58{ 59 if (ctx->stc_pool) 60 mlx5hws_pool_destroy(ctx->stc_pool); 61 62 mlx5hws_definer_uninit_cache(ctx->definer_cache); 63 mlx5hws_pat_uninit_pattern_cache(ctx->pattern_cache); 64} 65 66static int hws_context_init_pd(struct mlx5hws_context *ctx) 67{ 68 int ret = 0; 69 70 ret = mlx5_core_alloc_pd(ctx->mdev, &ctx->pd_num); 71 if (ret) { 72 mlx5hws_err(ctx, "Failed to allocate PD\n"); 73 return ret; 74 } 75 76 ctx->flags |= MLX5HWS_CONTEXT_FLAG_PRIVATE_PD; 77 78 return 0; 79} 80 81static int hws_context_uninit_pd(struct mlx5hws_context *ctx) 82{ 83 if (ctx->flags & MLX5HWS_CONTEXT_FLAG_PRIVATE_PD) 84 mlx5_core_dealloc_pd(ctx->mdev, ctx->pd_num); 85 86 return 0; 87} 88 89static void hws_context_check_hws_supp(struct mlx5hws_context *ctx) 90{ 91 struct mlx5hws_cmd_query_caps *caps = ctx->caps; 92 93 /* HWS not supported on device / FW */ 94 if (!caps->wqe_based_update) { 95 mlx5hws_err(ctx, "Required HWS WQE based insertion cap not supported\n"); 96 return; 97 } 98 99 if (!caps->eswitch_manager) { 100 mlx5hws_err(ctx, "HWS is not supported for non eswitch manager port\n"); 101 return; 102 } 103 104 /* Current solution requires all rules to set reparse bit */ 105 if ((!caps->nic_ft.reparse || 106 (!caps->fdb_ft.reparse && caps->eswitch_manager)) || 107 !IS_BIT_SET(caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_ALWAYS)) { 108 mlx5hws_err(ctx, "Required HWS reparse cap not supported\n"); 109 return; 110 } 111 112 /* FW/HW must support 8DW STE */ 113 if (!IS_BIT_SET(caps->ste_format, MLX5_IFC_RTC_STE_FORMAT_8DW)) { 114 mlx5hws_err(ctx, "Required HWS STE format not supported\n"); 115 return; 116 } 117 118 /* Adding rules by hash and by offset are requirements */ 119 if (!IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH) || 120 !IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET)) { 121 mlx5hws_err(ctx, "Required HWS RTC update mode not supported\n"); 122 return; 123 } 124 125 /* Support for SELECT definer ID is required */ 126 if (!IS_BIT_SET(caps->definer_format_sup, MLX5_IFC_DEFINER_FORMAT_ID_SELECT)) { 127 mlx5hws_err(ctx, "Required HWS Dynamic definer not supported\n"); 128 return; 129 } 130 131 ctx->flags |= MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT; 132} 133 134static int hws_context_init_hws(struct mlx5hws_context *ctx, 135 struct mlx5hws_context_attr *attr) 136{ 137 int ret; 138 139 hws_context_check_hws_supp(ctx); 140 141 if (!(ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT)) 142 return 0; 143 144 ret = hws_context_init_pd(ctx); 145 if (ret) 146 return ret; 147 148 ret = hws_context_pools_init(ctx); 149 if (ret) 150 goto uninit_pd; 151 152 /* Context has support for backward compatible API, 153 * and does not have support for native HWS API. 154 */ 155 ctx->flags |= MLX5HWS_CONTEXT_FLAG_BWC_SUPPORT; 156 157 ret = mlx5hws_send_queues_open(ctx, attr->queues, attr->queue_size); 158 if (ret) 159 goto pools_uninit; 160 161 ret = mlx5hws_action_ste_pool_init(ctx); 162 if (ret) 163 goto close_queues; 164 165 INIT_LIST_HEAD(&ctx->tbl_list); 166 167 return 0; 168 169close_queues: 170 mlx5hws_send_queues_close(ctx); 171pools_uninit: 172 hws_context_pools_uninit(ctx); 173uninit_pd: 174 hws_context_uninit_pd(ctx); 175 return ret; 176} 177 178static void hws_context_uninit_hws(struct mlx5hws_context *ctx) 179{ 180 if (!(ctx->flags & MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT)) 181 return; 182 183 mlx5hws_action_ste_pool_uninit(ctx); 184 mlx5hws_send_queues_close(ctx); 185 hws_context_pools_uninit(ctx); 186 hws_context_uninit_pd(ctx); 187} 188 189struct mlx5hws_context *mlx5hws_context_open(struct mlx5_core_dev *mdev, 190 struct mlx5hws_context_attr *attr) 191{ 192 struct mlx5hws_context *ctx; 193 int ret; 194 195 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 196 if (!ctx) 197 return NULL; 198 199 ctx->mdev = mdev; 200 201 mutex_init(&ctx->ctrl_lock); 202 xa_init(&ctx->peer_ctx_xa); 203 204 ctx->caps = kzalloc(sizeof(*ctx->caps), GFP_KERNEL); 205 if (!ctx->caps) 206 goto free_ctx; 207 208 ret = mlx5hws_cmd_query_caps(mdev, ctx->caps); 209 if (ret) 210 goto free_caps; 211 212 ret = mlx5hws_vport_init_vports(ctx); 213 if (ret) 214 goto free_caps; 215 216 ret = hws_context_init_hws(ctx, attr); 217 if (ret) 218 goto uninit_vports; 219 220 mlx5hws_debug_init_dump(ctx); 221 222 return ctx; 223 224uninit_vports: 225 mlx5hws_vport_uninit_vports(ctx); 226free_caps: 227 kfree(ctx->caps); 228free_ctx: 229 xa_destroy(&ctx->peer_ctx_xa); 230 mutex_destroy(&ctx->ctrl_lock); 231 kfree(ctx); 232 return NULL; 233} 234 235int mlx5hws_context_close(struct mlx5hws_context *ctx) 236{ 237 mlx5hws_debug_uninit_dump(ctx); 238 hws_context_uninit_hws(ctx); 239 mlx5hws_vport_uninit_vports(ctx); 240 kfree(ctx->caps); 241 xa_destroy(&ctx->peer_ctx_xa); 242 mutex_destroy(&ctx->ctrl_lock); 243 kfree(ctx); 244 return 0; 245} 246 247void mlx5hws_context_set_peer(struct mlx5hws_context *ctx, 248 struct mlx5hws_context *peer_ctx, 249 u16 peer_vhca_id) 250{ 251 mutex_lock(&ctx->ctrl_lock); 252 253 if (xa_err(xa_store(&ctx->peer_ctx_xa, peer_vhca_id, peer_ctx, GFP_KERNEL))) 254 pr_warn("HWS: failed storing peer vhca ID in peer xarray\n"); 255 256 mutex_unlock(&ctx->ctrl_lock); 257}
~/
Read-only file preview.