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