xref: /dpdk/drivers/net/mlx5/hws/mlx5dr_context.c (revision 691326d15da263d068de71c468c74c225c4f75c3)
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