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 : void mlx5dr_context_set_pool_tbl_attr(struct mlx5dr_pool_attr *attr,
23 : : enum mlx5dr_table_type table_type)
24 : : {
25 : 0 : attr->table_type = table_type;
26 : :
27 [ # # # ]: 0 : switch (table_type) {
28 : 0 : case MLX5DR_TABLE_TYPE_FDB_TX:
29 : 0 : attr->opt_type = MLX5DR_POOL_OPTIMIZE_ORIG;
30 : 0 : break;
31 : 0 : case MLX5DR_TABLE_TYPE_FDB_RX:
32 : 0 : attr->opt_type = MLX5DR_POOL_OPTIMIZE_MIRROR;
33 : 0 : break;
34 : 0 : default:
35 : 0 : attr->opt_type = MLX5DR_POOL_OPTIMIZE_NONE;
36 : 0 : break;
37 : : }
38 : 0 : }
39 : :
40 : 0 : static int mlx5dr_context_pools_init(struct mlx5dr_context *ctx,
41 : : struct mlx5dr_context_attr *attr)
42 : : {
43 : 0 : struct mlx5dr_pool_attr pool_attr = {0};
44 : : uint8_t max_log_sz;
45 : : int i;
46 : :
47 [ # # ]: 0 : if (mlx5dr_pat_init_pattern_cache(&ctx->pattern_cache))
48 : 0 : return rte_errno;
49 : :
50 [ # # ]: 0 : if (mlx5dr_definer_init_cache(&ctx->definer_cache))
51 : 0 : goto uninit_pat_cache;
52 : :
53 : : /* Create an STC pool per FT type */
54 : 0 : pool_attr.pool_type = MLX5DR_POOL_TYPE_STC;
55 : 0 : pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_STC_POOL;
56 [ # # ]: 0 : if (!attr->initial_log_stc_memory)
57 : 0 : attr->initial_log_stc_memory = MLX5DR_POOL_STC_LOG_SZ;
58 : 0 : max_log_sz = RTE_MIN(attr->initial_log_stc_memory, ctx->caps->stc_alloc_log_max);
59 : 0 : pool_attr.alloc_log_sz = RTE_MAX(max_log_sz, ctx->caps->stc_alloc_log_gran);
60 : :
61 [ # # ]: 0 : for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) {
62 : 0 : mlx5dr_context_set_pool_tbl_attr(&pool_attr,
63 : : (enum mlx5dr_table_type)i);
64 : 0 : ctx->stc_pool[i] = mlx5dr_pool_create(ctx, &pool_attr);
65 [ # # ]: 0 : if (!ctx->stc_pool[i]) {
66 : 0 : DR_LOG(ERR, "Failed to allocate STC pool [%d]", i);
67 : 0 : goto free_stc_pools;
68 : : }
69 : : }
70 : :
71 : : return 0;
72 : :
73 : : free_stc_pools:
74 [ # # ]: 0 : for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++)
75 [ # # ]: 0 : if (ctx->stc_pool[i])
76 : 0 : mlx5dr_pool_destroy(ctx->stc_pool[i]);
77 : :
78 : 0 : mlx5dr_definer_uninit_cache(ctx->definer_cache);
79 : :
80 : 0 : uninit_pat_cache:
81 : 0 : mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache);
82 : 0 : return rte_errno;
83 : : }
84 : :
85 : 0 : static void mlx5dr_context_pools_uninit(struct mlx5dr_context *ctx)
86 : : {
87 : : int i;
88 : :
89 [ # # ]: 0 : for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) {
90 [ # # ]: 0 : if (ctx->stc_pool[i])
91 : 0 : mlx5dr_pool_destroy(ctx->stc_pool[i]);
92 : : }
93 : :
94 : 0 : mlx5dr_definer_uninit_cache(ctx->definer_cache);
95 : 0 : mlx5dr_pat_uninit_pattern_cache(ctx->pattern_cache);
96 : 0 : }
97 : :
98 : 0 : static int mlx5dr_context_init_pd(struct mlx5dr_context *ctx,
99 : : struct ibv_pd *pd)
100 : : {
101 : 0 : struct mlx5dv_pd mlx5_pd = {0};
102 : : struct mlx5dv_obj obj;
103 : : int ret;
104 : :
105 [ # # ]: 0 : if (pd) {
106 : 0 : ctx->pd = pd;
107 : : } else {
108 : 0 : ctx->pd = mlx5_glue->alloc_pd(ctx->ibv_ctx);
109 [ # # ]: 0 : if (!ctx->pd) {
110 : 0 : DR_LOG(ERR, "Failed to allocate PD");
111 : 0 : rte_errno = errno;
112 : 0 : return rte_errno;
113 : : }
114 : 0 : ctx->flags |= MLX5DR_CONTEXT_FLAG_PRIVATE_PD;
115 : : }
116 : :
117 : 0 : obj.pd.in = ctx->pd;
118 : 0 : obj.pd.out = &mlx5_pd;
119 : :
120 : 0 : ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD);
121 [ # # ]: 0 : if (ret)
122 : 0 : goto free_private_pd;
123 : :
124 : 0 : ctx->pd_num = mlx5_pd.pdn;
125 : :
126 : 0 : return 0;
127 : :
128 : : free_private_pd:
129 [ # # ]: 0 : if (ctx->flags & MLX5DR_CONTEXT_FLAG_PRIVATE_PD)
130 : 0 : mlx5_glue->dealloc_pd(ctx->pd);
131 : :
132 : : return ret;
133 : : }
134 : :
135 : : static int mlx5dr_context_uninit_pd(struct mlx5dr_context *ctx)
136 : : {
137 [ # # ]: 0 : if (ctx->flags & MLX5DR_CONTEXT_FLAG_PRIVATE_PD)
138 : 0 : return mlx5_glue->dealloc_pd(ctx->pd);
139 : :
140 : : return 0;
141 : : }
142 : :
143 : 0 : bool mlx5dr_context_cap_stc(struct mlx5dr_context *ctx, uint32_t bit)
144 : : {
145 : : uint32_t test_bit = bit;
146 : :
147 [ # # ]: 0 : if (bit >= MLX5_IFC_STC_ACTION_TYPE_BIT_64_INDEX)
148 : 0 : test_bit -= MLX5_IFC_STC_ACTION_TYPE_BIT_64_INDEX;
149 : :
150 [ # # ]: 0 : switch (bit) {
151 : 0 : case MLX5_IFC_STC_ACTION_TYPE_JUMP_FLOW_TABLE_FDB_RX_BIT_INDEX:
152 : 0 : return ctx->caps->stc_action_type_127_64 & (0x1ull << test_bit);
153 : : default:
154 : : break;
155 : : }
156 : :
157 : : return false;
158 : : }
159 : :
160 : 0 : static void mlx5dr_context_check_hws_supp(struct mlx5dr_context *ctx)
161 : : {
162 : 0 : struct mlx5dr_cmd_query_caps *caps = ctx->caps;
163 : :
164 : : /* HWS not supported on device / FW */
165 [ # # ]: 0 : if (!caps->wqe_based_update) {
166 : 0 : DR_LOG(INFO, "Required HWS WQE based insertion cap not supported");
167 : 0 : return;
168 : : }
169 : :
170 : : /* Current solution requires all rules to set reparse bit */
171 [ # # ]: 0 : if ((!caps->nic_ft.reparse ||
172 [ # # # # ]: 0 : (!caps->fdb_ft.reparse && caps->eswitch_manager)) ||
173 [ # # ]: 0 : !IS_BIT_SET(caps->rtc_reparse_mode, MLX5_IFC_RTC_REPARSE_ALWAYS)) {
174 : 0 : DR_LOG(INFO, "Required HWS reparse cap not supported");
175 : 0 : return;
176 : : }
177 : :
178 : : /* FW/HW must support 8DW STE */
179 [ # # ]: 0 : if (!IS_BIT_SET(caps->ste_format, MLX5_IFC_RTC_STE_FORMAT_8DW)) {
180 : 0 : DR_LOG(INFO, "Required HWS STE format not supported");
181 : 0 : return;
182 : : }
183 : :
184 : : /* Adding rules by hash and by offset are requirements */
185 [ # # ]: 0 : if (!IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH) ||
186 : : !IS_BIT_SET(caps->rtc_index_mode, MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET)) {
187 : 0 : DR_LOG(INFO, "Required HWS RTC update mode not supported");
188 : 0 : return;
189 : : }
190 : :
191 : : /* Support for SELECT definer ID is required */
192 [ # # ]: 0 : if (!IS_BIT_SET(caps->definer_format_sup, MLX5_IFC_DEFINER_FORMAT_ID_SELECT)) {
193 : 0 : DR_LOG(INFO, "Required HWS Dynamic definer not supported");
194 : 0 : return;
195 : : }
196 : :
197 : 0 : ctx->flags |= MLX5DR_CONTEXT_FLAG_HWS_SUPPORT;
198 : : }
199 : :
200 : 0 : static int mlx5dr_context_init_hws(struct mlx5dr_context *ctx,
201 : : struct mlx5dr_context_attr *attr)
202 : : {
203 : : int ret;
204 : :
205 : 0 : mlx5dr_context_check_hws_supp(ctx);
206 : :
207 [ # # ]: 0 : if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT))
208 : : return 0;
209 : :
210 : 0 : ret = mlx5dr_context_init_pd(ctx, attr->pd);
211 [ # # ]: 0 : if (ret)
212 : : return ret;
213 : :
214 : 0 : ret = mlx5dr_context_pools_init(ctx, attr);
215 [ # # ]: 0 : if (ret)
216 : 0 : goto uninit_pd;
217 : :
218 [ # # ]: 0 : if (attr->bwc)
219 : 0 : ctx->flags |= MLX5DR_CONTEXT_FLAG_BWC_SUPPORT;
220 : :
221 : 0 : ret = mlx5dr_send_queues_open(ctx, attr->queues, attr->queue_size);
222 [ # # ]: 0 : if (ret)
223 : 0 : goto pools_uninit;
224 : :
225 : : return 0;
226 : :
227 : : pools_uninit:
228 : 0 : mlx5dr_context_pools_uninit(ctx);
229 [ # # ]: 0 : uninit_pd:
230 : : mlx5dr_context_uninit_pd(ctx);
231 : : return ret;
232 : : }
233 : :
234 : 0 : static void mlx5dr_context_uninit_hws(struct mlx5dr_context *ctx)
235 : : {
236 [ # # ]: 0 : if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT))
237 : : return;
238 : :
239 : 0 : mlx5dr_send_queues_close(ctx);
240 : 0 : mlx5dr_context_pools_uninit(ctx);
241 : : mlx5dr_context_uninit_pd(ctx);
242 : : }
243 : :
244 : 0 : static int mlx5dr_context_init_shared_ctx(struct mlx5dr_context *ctx,
245 : : struct ibv_context *ibv_ctx,
246 : : struct mlx5dr_context_attr *attr)
247 : : {
248 : 0 : struct mlx5dr_cmd_query_caps shared_caps = {0};
249 : : int ret;
250 : :
251 [ # # ]: 0 : if (!attr->shared_ibv_ctx) {
252 : 0 : ctx->ibv_ctx = ibv_ctx;
253 : : } else {
254 : 0 : ctx->ibv_ctx = attr->shared_ibv_ctx;
255 : 0 : ctx->local_ibv_ctx = ibv_ctx;
256 : 0 : ret = mlx5dr_cmd_query_caps(attr->shared_ibv_ctx, &shared_caps);
257 [ # # # # ]: 0 : if (ret || !shared_caps.cross_vhca_resources) {
258 : 0 : DR_LOG(INFO, "No cross_vhca_resources cap for shared ibv");
259 : 0 : rte_errno = ENOTSUP;
260 : 0 : return rte_errno;
261 : : }
262 : 0 : ctx->caps->shared_vhca_id = shared_caps.vhca_id;
263 : : }
264 : :
265 [ # # # # ]: 0 : if (ctx->local_ibv_ctx && !ctx->caps->cross_vhca_resources) {
266 : 0 : DR_LOG(INFO, "No cross_vhca_resources cap for local ibv");
267 : 0 : rte_errno = ENOTSUP;
268 : 0 : return rte_errno;
269 : : }
270 : :
271 : : return 0;
272 : : }
273 : :
274 : 0 : struct mlx5dr_context *mlx5dr_context_open(struct ibv_context *ibv_ctx,
275 : : struct mlx5dr_context_attr *attr)
276 : : {
277 : : struct mlx5dr_context *ctx;
278 : : int ret;
279 : :
280 : : ctx = simple_calloc(1, sizeof(*ctx));
281 [ # # ]: 0 : if (!ctx) {
282 : 0 : rte_errno = ENOMEM;
283 : 0 : return NULL;
284 : : }
285 : :
286 : 0 : pthread_spin_init(&ctx->ctrl_lock, PTHREAD_PROCESS_PRIVATE);
287 : :
288 : 0 : ctx->caps = simple_calloc(1, sizeof(*ctx->caps));
289 [ # # ]: 0 : if (!ctx->caps)
290 : 0 : goto free_ctx;
291 : :
292 : 0 : ret = mlx5dr_cmd_query_caps(ibv_ctx, ctx->caps);
293 [ # # ]: 0 : if (ret)
294 : 0 : goto free_caps;
295 : :
296 [ # # ]: 0 : if (mlx5dr_context_init_shared_ctx(ctx, ibv_ctx, attr))
297 : 0 : goto free_caps;
298 : :
299 : 0 : ret = mlx5dr_context_init_hws(ctx, attr);
300 [ # # ]: 0 : if (ret)
301 : 0 : goto free_caps;
302 : :
303 : : return ctx;
304 : :
305 : 0 : free_caps:
306 : 0 : simple_free(ctx->caps);
307 : 0 : free_ctx:
308 : 0 : pthread_spin_destroy(&ctx->ctrl_lock);
309 : : simple_free(ctx);
310 : 0 : return NULL;
311 : : }
312 : :
313 : 0 : int mlx5dr_context_close(struct mlx5dr_context *ctx)
314 : : {
315 : 0 : mlx5dr_context_uninit_hws(ctx);
316 : 0 : simple_free(ctx->caps);
317 : 0 : pthread_spin_destroy(&ctx->ctrl_lock);
318 : : simple_free(ctx);
319 : 0 : return 0;
320 : : }
|