xref: /dpdk/drivers/net/bnxt/tf_core/tf_em_internal.c (revision 580fcb3d718069a8058f4395dd64d19fed0c1f65)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2024 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <string.h>
7 #include <rte_common.h>
8 #include <rte_errno.h>
9 #include <rte_log.h>
10 #include "tf_core.h"
11 #include "tf_util.h"
12 #include "tf_common.h"
13 #include "tf_em.h"
14 #include "tf_msg.h"
15 #include "tfp.h"
16 #include "tf_ext_flow_handle.h"
17 
18 #include "bnxt.h"
19 
20 #define TF_EM_DB_EM_REC 0
21 
22 /**
23  * EM Pool
24  */
25 #include "dpool.h"
26 
27 /**
28  * Insert EM internal entry API
29  *
30  *  returns:
31  *     0 - Success
32  */
33 int
34 tf_em_insert_int_entry(struct tf *tfp,
35 		       struct tf_insert_em_entry_parms *parms)
36 {
37 	int rc;
38 	uint32_t gfid;
39 	uint16_t rptr_index = 0;
40 	uint8_t rptr_entry = 0;
41 	uint8_t num_of_entries = 0;
42 	struct tf_session *tfs;
43 	struct dpool *pool;
44 	uint32_t index;
45 
46 	/* Retrieve the session information */
47 	rc = tf_session_get_session(tfp, &tfs);
48 	if (rc) {
49 		TFP_DRV_LOG(ERR,
50 			    "%s: Failed to lookup session, rc:%s\n",
51 			    tf_dir_2_str(parms->dir),
52 			    strerror(-rc));
53 		return rc;
54 	}
55 
56 	pool = (struct dpool *)tfs->em_pool[parms->dir];
57 	index = dpool_alloc(pool, TF_SESSION_EM_ENTRY_SIZE, 0);
58 	if (index == DP_INVALID_INDEX) {
59 		PMD_DRV_LOG_LINE(ERR,
60 			    "%s, EM entry index allocation failed",
61 			    tf_dir_2_str(parms->dir));
62 		return -1;
63 	}
64 
65 	rptr_index = index;
66 	rc = tf_msg_insert_em_internal_entry(tfp,
67 					     parms,
68 					     &rptr_index,
69 					     &rptr_entry,
70 					     &num_of_entries);
71 	if (rc) {
72 		/* Free the allocated index before returning */
73 		dpool_free(pool, index);
74 		return -1;
75 	}
76 
77 	TF_SET_GFID(gfid,
78 		    ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
79 		     rptr_entry),
80 		    0); /* N/A for internal table */
81 
82 	TF_SET_FLOW_ID(parms->flow_id,
83 		       gfid,
84 		       TF_GFID_TABLE_INTERNAL,
85 		       parms->dir);
86 
87 	TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
88 				     (uint32_t)num_of_entries,
89 				     0,
90 				     TF_FLAGS_FLOW_HANDLE_INTERNAL,
91 				     rptr_index,
92 				     rptr_entry,
93 				     0);
94 	return 0;
95 }
96 
97 /** Delete EM internal entry API
98  *
99  * returns:
100  * 0
101  * -EINVAL
102  */
103 int
104 tf_em_delete_int_entry(struct tf *tfp,
105 		       struct tf_delete_em_entry_parms *parms)
106 {
107 	int rc = 0;
108 	struct tf_session *tfs;
109 	struct dpool *pool;
110 	/* Retrieve the session information */
111 	rc = tf_session_get_session(tfp, &tfs);
112 	if (rc) {
113 		TFP_DRV_LOG(ERR,
114 			    "%s: Failed to lookup session, rc:%s\n",
115 			    tf_dir_2_str(parms->dir),
116 			    strerror(-rc));
117 		return rc;
118 	}
119 
120 	rc = tf_msg_delete_em_entry(tfp, parms);
121 
122 	/* Return resource to pool */
123 	if (rc == 0) {
124 		pool = (struct dpool *)tfs->em_pool[parms->dir];
125 		dpool_free(pool, parms->index);
126 	}
127 
128 	return rc;
129 }
130 
131 static int
132 tf_em_move_callback(void *user_data,
133 		    uint64_t entry_data,
134 		    uint32_t new_index)
135 {
136 	int rc;
137 	struct tf *tfp = (struct tf *)user_data;
138 	struct tf_move_em_entry_parms parms;
139 	struct tf_dev_info     *dev;
140 	struct tf_session      *tfs;
141 
142 	memset(&parms, 0, sizeof(parms));
143 
144 	parms.tbl_scope_id = 0;
145 	parms.flow_handle  = entry_data;
146 	parms.new_index    = new_index;
147 	TF_GET_DIR_FROM_FLOW_ID(entry_data, parms.dir);
148 	parms.mem          = TF_MEM_INTERNAL;
149 
150 	/* Retrieve the session information */
151 	rc = tf_session_get_session(tfp, &tfs);
152 	if (rc) {
153 		TFP_DRV_LOG(ERR,
154 			    "%s: Failed to lookup session, rc:%s\n",
155 			    tf_dir_2_str(parms.dir),
156 			    strerror(-rc));
157 		return rc;
158 	}
159 
160 	/* Retrieve the device information */
161 	rc = tf_session_get_device(tfs, &dev);
162 	if (rc) {
163 		TFP_DRV_LOG(ERR,
164 			    "%s: Failed to lookup device, rc:%s\n",
165 			    tf_dir_2_str(parms.dir),
166 			    strerror(-rc));
167 		return rc;
168 	}
169 
170 	if (dev->ops->tf_dev_move_int_em_entry != NULL)
171 		rc = dev->ops->tf_dev_move_int_em_entry(tfp, &parms);
172 	else
173 		rc = -EOPNOTSUPP;
174 
175 	return rc;
176 }
177 
178 int
179 tf_em_int_bind(struct tf *tfp,
180 	       struct tf_em_cfg_parms *parms)
181 {
182 	int rc;
183 	int db_rc[TF_DIR_MAX] = { 0 };
184 	int i;
185 	struct tf_rm_create_db_parms db_cfg = { 0 };
186 	struct tf_rm_get_alloc_info_parms iparms;
187 	struct tf_rm_alloc_info info;
188 	struct em_rm_db *em_db;
189 	struct tfp_calloc_parms cparms;
190 	struct tf_session *tfs;
191 
192 	TF_CHECK_PARMS2(tfp, parms);
193 
194 	/* Retrieve the session information */
195 	rc = tf_session_get_session_internal(tfp, &tfs);
196 	if (rc)
197 		return rc;
198 
199 	memset(&db_cfg, 0, sizeof(db_cfg));
200 	cparms.nitems = 1;
201 	cparms.size = sizeof(struct em_rm_db);
202 	cparms.alignment = 0;
203 	if (tfp_calloc(&cparms) != 0) {
204 		TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n",
205 			    strerror(ENOMEM));
206 		return -ENOMEM;
207 	}
208 
209 	em_db = cparms.mem_va;
210 	for (i = 0; i < TF_DIR_MAX; i++)
211 		em_db->em_db[i] = NULL;
212 	tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db);
213 
214 	db_cfg.module = TF_MODULE_TYPE_EM;
215 	db_cfg.num_elements = parms->num_elements;
216 	db_cfg.cfg = parms->cfg;
217 
218 	for (i = 0; i < TF_DIR_MAX; i++) {
219 		db_cfg.dir = i;
220 		db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
221 
222 		/* Check if we got any request to support EEM, if so
223 		 * we build an EM Int DB holding Table Scopes.
224 		 */
225 		if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0)
226 			continue;
227 
228 		if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] %
229 		    TF_SESSION_EM_ENTRY_SIZE != 0) {
230 			rc = -ENOMEM;
231 			TFP_DRV_LOG(ERR,
232 				    "%s, EM Allocation must be in blocks of %d, failure %s\n",
233 				    tf_dir_2_str(i),
234 				    TF_SESSION_EM_ENTRY_SIZE,
235 				    strerror(-rc));
236 
237 			return rc;
238 		}
239 
240 		db_cfg.rm_db = (void *)&em_db->em_db[i];
241 		if (tf_session_is_shared_session(tfs) &&
242 			(!tf_session_is_shared_session_creator(tfs)))
243 			db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
244 		else
245 			db_rc[i] = tf_rm_create_db(tfp, &db_cfg);
246 	}
247 
248 	/* No db created */
249 	if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
250 		TFP_DRV_LOG(ERR, "EM Int DB creation failed\n");
251 		return db_rc[TF_DIR_RX];
252 	}
253 
254 	if (!tf_session_is_shared_session(tfs)) {
255 		for (i = 0; i < TF_DIR_MAX; i++) {
256 			iparms.rm_db = em_db->em_db[i];
257 			iparms.subtype = TF_EM_DB_EM_REC;
258 			iparms.info = &info;
259 
260 			rc = tf_rm_get_info(&iparms);
261 			if (rc) {
262 				TFP_DRV_LOG(ERR,
263 					    "%s: EM DB get info failed\n",
264 					    tf_dir_2_str(i));
265 				return rc;
266 			}
267 
268 			/*
269 			 * Allocate stack pool
270 			 */
271 			cparms.nitems = 1;
272 			cparms.size = sizeof(struct dpool);
273 			cparms.alignment = 0;
274 
275 			rc = tfp_calloc(&cparms);
276 
277 			if (rc) {
278 				TFP_DRV_LOG(ERR,
279 					 "%s, EM stack allocation failure %s\n",
280 					 tf_dir_2_str(i),
281 					 strerror(-rc));
282 				return rc;
283 			}
284 
285 			tfs->em_pool[i] = (struct dpool *)cparms.mem_va;
286 
287 			rc = dpool_init(tfs->em_pool[i],
288 					iparms.info->entry.start,
289 					iparms.info->entry.stride,
290 					7,
291 					(void *)tfp,
292 					tf_em_move_callback);
293 			/* Logging handled in tf_create_em_pool */
294 			if (rc)
295 				return rc;
296 
297 #ifdef TF_FLOW_SCALE_QUERY
298 			/* Initialize the usage state buffer for EM */
299 			tf_em_usage_init(tfp,
300 					 i,
301 					 iparms.info->entry.stride);
302 #endif /* TF_FLOW_SCALE_QUERY */
303 		}
304 
305 		if (rc) {
306 			TFP_DRV_LOG(ERR,
307 				    "%s: EM pool init failed\n",
308 				    tf_dir_2_str(i));
309 			return rc;
310 		}
311 	}
312 
313 	return 0;
314 }
315 
316 int
317 tf_em_int_unbind(struct tf *tfp)
318 {
319 	int rc;
320 	int i;
321 	struct tf_rm_free_db_parms fparms = { 0 };
322 	struct em_rm_db *em_db;
323 	void *em_db_ptr = NULL;
324 	struct tf_session *tfs;
325 
326 	TF_CHECK_PARMS1(tfp);
327 
328 	/* Retrieve the session information */
329 	rc = tf_session_get_session_internal(tfp, &tfs);
330 	if (rc)
331 		return rc;
332 
333 	if (!tf_session_is_shared_session(tfs)) {
334 		for (i = 0; i < TF_DIR_MAX; i++) {
335 			if (tfs->em_pool[i] == NULL)
336 				continue;
337 			dpool_free_all(tfs->em_pool[i]);
338 		}
339 	}
340 
341 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
342 	if (rc)
343 		return 0;
344 
345 	em_db = (struct em_rm_db *)em_db_ptr;
346 	for (i = 0; i < TF_DIR_MAX; i++) {
347 		if (em_db->em_db[i] == NULL)
348 			continue;
349 		fparms.dir = i;
350 		fparms.rm_db = em_db->em_db[i];
351 		rc = tf_rm_free_db(tfp, &fparms);
352 		if (rc)
353 			return rc;
354 
355 		em_db->em_db[i] = NULL;
356 	}
357 
358 	return 0;
359 }
360 
361 int
362 tf_em_get_resc_info(struct tf *tfp,
363 		    struct tf_em_resource_info *em)
364 {
365 	int rc;
366 	int d;
367 	struct tf_resource_info *dinfo;
368 	struct tf_rm_get_alloc_info_parms ainfo;
369 	void *em_db_ptr = NULL;
370 	struct em_rm_db *em_db;
371 
372 	TF_CHECK_PARMS2(tfp, em);
373 
374 	rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
375 	if (rc == -ENOMEM)
376 		return 0;  /* db does not exist */
377 	else if (rc)
378 		return rc; /* db error */
379 
380 	em_db = (struct em_rm_db *)em_db_ptr;
381 
382 	/* check if reserved resource for EM is multiple of num_slices */
383 	for (d = 0; d < TF_DIR_MAX; d++) {
384 		ainfo.rm_db = em_db->em_db[d];
385 		dinfo = em[d].info;
386 
387 		if (!ainfo.rm_db)
388 			continue;
389 
390 		ainfo.info = (struct tf_rm_alloc_info *)dinfo;
391 		ainfo.subtype = 0;
392 		rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX);
393 		if (rc && rc != -ENOTSUP)
394 			return rc;
395 	}
396 
397 	return 0;
398 }
399