1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
7 #include <rte_common.h>
13 #include "tf_common.h"
17 #include "tf_ext_flow_handle.h"
20 #define TF_EM_DB_EM_REC 0
25 #if (TF_EM_ALLOC == 1)
30 * Create EM Tbl pool of memory indexes.
35 * number of entries to write
40 * 0 - Success, entry allocated - no search support
41 * -ENOMEM -EINVAL -EOPNOTSUPP
42 * - Failure, entry not allocated, out of resources
45 tf_create_em_pool(struct tf_session *tfs,
50 struct tfp_calloc_parms parms;
59 parms.size = sizeof(struct stack);
62 rc = tfp_calloc(&parms);
66 "%s, EM stack allocation failure %s\n",
72 pool = (struct stack *)parms.mem_va;
73 tfs->em_pool[dir] = (void *)pool;
75 /* Assumes that num_entries has been checked before we get here */
76 parms.nitems = num_entries / TF_SESSION_EM_ENTRY_SIZE;
77 parms.size = sizeof(uint32_t);
80 rc = tfp_calloc(&parms);
84 "%s, EM pool allocation failure %s\n",
92 rc = stack_init(num_entries / TF_SESSION_EM_ENTRY_SIZE,
93 (uint32_t *)parms.mem_va,
98 "%s, EM pool stack init failure %s\n",
104 /* Fill pool with indexes
106 j = start + num_entries - TF_SESSION_EM_ENTRY_SIZE;
108 for (i = 0; i < (num_entries / TF_SESSION_EM_ENTRY_SIZE); i++) {
109 rc = stack_push(pool, j);
112 "%s, EM pool stack push failure %s\n",
118 j -= TF_SESSION_EM_ENTRY_SIZE;
121 if (!stack_is_full(pool)) {
124 "%s, EM pool stack failure %s\n",
132 tfp_free((void *)parms.mem_va);
133 tfp_free((void *)tfs->em_pool[dir]);
134 tfs->em_pool[dir] = NULL;
139 * Create EM Tbl pool of memory indexes.
147 tf_free_em_pool(struct tf_session *tfs,
150 struct stack *pool = (struct stack *)tfs->em_pool[dir];
154 ptr = stack_items(pool);
160 tfs->em_pool[dir] = NULL;
163 #endif /* TF_EM_ALLOC != 1 */
166 * Insert EM internal entry API
172 tf_em_insert_int_entry(struct tf *tfp,
173 struct tf_insert_em_entry_parms *parms)
177 uint16_t rptr_index = 0;
178 uint8_t rptr_entry = 0;
179 uint8_t num_of_entries = 0;
180 struct tf_session *tfs;
181 #if (TF_EM_ALLOC == 1)
188 /* Retrieve the session information */
189 rc = tf_session_get_session(tfp, &tfs);
192 "%s: Failed to lookup session, rc:%s\n",
193 tf_dir_2_str(parms->dir),
198 #if (TF_EM_ALLOC == 1)
199 pool = (struct dpool *)tfs->em_pool[parms->dir];
200 index = dpool_alloc(pool, TF_SESSION_EM_ENTRY_SIZE, 0);
201 if (index == DP_INVALID_INDEX) {
203 "%s, EM entry index allocation failed\n",
204 tf_dir_2_str(parms->dir));
208 pool = (struct stack *)tfs->em_pool[parms->dir];
209 rc = stack_pop(pool, &index);
212 "%s, EM entry index allocation failed\n",
213 tf_dir_2_str(parms->dir));
220 rc = tf_msg_insert_em_internal_entry(tfp,
226 /* Free the allocated index before returning */
227 #if (TF_EM_ALLOC == 1)
228 dpool_free(pool, index);
230 stack_push(pool, index);
235 ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
237 0); /* N/A for internal table */
239 TF_SET_FLOW_ID(parms->flow_id,
241 TF_GFID_TABLE_INTERNAL,
244 TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
245 (uint32_t)num_of_entries,
247 TF_FLAGS_FLOW_HANDLE_INTERNAL,
255 /** Delete EM internal entry API
262 tf_em_delete_int_entry(struct tf *tfp,
263 struct tf_delete_em_entry_parms *parms)
266 struct tf_session *tfs;
267 #if (TF_EM_ALLOC == 1)
272 /* Retrieve the session information */
273 rc = tf_session_get_session(tfp, &tfs);
276 "%s: Failed to lookup session, rc:%s\n",
277 tf_dir_2_str(parms->dir),
282 rc = tf_msg_delete_em_entry(tfp, parms);
284 /* Return resource to pool */
286 #if (TF_EM_ALLOC == 1)
287 pool = (struct dpool *)tfs->em_pool[parms->dir];
288 dpool_free(pool, parms->index);
290 pool = (struct stack *)tfs->em_pool[parms->dir];
291 stack_push(pool, parms->index);
298 #if (TF_EM_ALLOC == 1)
300 tf_em_move_callback(void *user_data,
305 struct tf *tfp = (struct tf *)user_data;
306 struct tf_move_em_entry_parms parms;
307 struct tf_dev_info *dev;
308 struct tf_session *tfs;
310 memset(&parms, 0, sizeof(parms));
312 parms.tbl_scope_id = 0;
313 parms.flow_handle = entry_data;
314 parms.new_index = new_index;
315 TF_GET_DIR_FROM_FLOW_ID(entry_data, parms.dir);
316 parms.mem = TF_MEM_INTERNAL;
318 /* Retrieve the session information */
319 rc = tf_session_get_session(tfp, &tfs);
322 "%s: Failed to lookup session, rc:%s\n",
323 tf_dir_2_str(parms.dir),
328 /* Retrieve the device information */
329 rc = tf_session_get_device(tfs, &dev);
332 "%s: Failed to lookup device, rc:%s\n",
333 tf_dir_2_str(parms.dir),
338 if (dev->ops->tf_dev_move_int_em_entry != NULL)
339 rc = dev->ops->tf_dev_move_int_em_entry(tfp, &parms);
348 tf_em_int_bind(struct tf *tfp,
349 struct tf_em_cfg_parms *parms)
352 int db_rc[TF_DIR_MAX] = { 0 };
354 struct tf_rm_create_db_parms db_cfg = { 0 };
355 struct tf_rm_get_alloc_info_parms iparms;
356 struct tf_rm_alloc_info info;
357 struct em_rm_db *em_db;
358 struct tfp_calloc_parms cparms;
359 struct tf_session *tfs;
361 TF_CHECK_PARMS2(tfp, parms);
363 /* Retrieve the session information */
364 rc = tf_session_get_session_internal(tfp, &tfs);
368 memset(&db_cfg, 0, sizeof(db_cfg));
370 cparms.size = sizeof(struct em_rm_db);
371 cparms.alignment = 0;
372 if (tfp_calloc(&cparms) != 0) {
373 TFP_DRV_LOG(ERR, "em_rm_db alloc error %s\n",
378 em_db = cparms.mem_va;
379 for (i = 0; i < TF_DIR_MAX; i++)
380 em_db->em_db[i] = NULL;
381 tf_session_set_db(tfp, TF_MODULE_TYPE_EM, em_db);
383 db_cfg.module = TF_MODULE_TYPE_EM;
384 db_cfg.num_elements = parms->num_elements;
385 db_cfg.cfg = parms->cfg;
387 for (i = 0; i < TF_DIR_MAX; i++) {
389 db_cfg.alloc_cnt = parms->resources->em_cnt[i].cnt;
391 /* Check if we got any request to support EEM, if so
392 * we build an EM Int DB holding Table Scopes.
394 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] == 0)
397 if (db_cfg.alloc_cnt[TF_EM_TBL_TYPE_EM_RECORD] %
398 TF_SESSION_EM_ENTRY_SIZE != 0) {
401 "%s, EM Allocation must be in blocks of %d, failure %s\n",
403 TF_SESSION_EM_ENTRY_SIZE,
409 db_cfg.rm_db = (void *)&em_db->em_db[i];
410 if (tf_session_is_shared_session(tfs) &&
411 (!tf_session_is_shared_session_creator(tfs)))
412 db_rc[i] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
414 db_rc[i] = tf_rm_create_db(tfp, &db_cfg);
417 "%s: EM Int DB creation failed\n",
424 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX])
425 return db_rc[TF_DIR_RX];
428 if (!tf_session_is_shared_session(tfs)) {
429 for (i = 0; i < TF_DIR_MAX; i++) {
430 iparms.rm_db = em_db->em_db[i];
431 iparms.subtype = TF_EM_DB_EM_REC;
434 rc = tf_rm_get_info(&iparms);
437 "%s: EM DB get info failed\n",
441 #if (TF_EM_ALLOC == 1)
443 * Allocate stack pool
446 cparms.size = sizeof(struct dpool);
447 cparms.alignment = 0;
449 rc = tfp_calloc(&cparms);
453 "%s, EM stack allocation failure %s\n",
459 tfs->em_pool[i] = (struct dpool *)cparms.mem_va;
461 rc = dpool_init(tfs->em_pool[i],
462 iparms.info->entry.start,
463 iparms.info->entry.stride,
466 tf_em_move_callback);
468 rc = tf_create_em_pool(tfs,
470 iparms.info->entry.stride,
471 iparms.info->entry.start);
473 /* Logging handled in tf_create_em_pool */
480 "%s: EM pool init failed\n",
490 tf_em_int_unbind(struct tf *tfp)
494 struct tf_rm_free_db_parms fparms = { 0 };
495 struct em_rm_db *em_db;
496 void *em_db_ptr = NULL;
497 struct tf_session *tfs;
499 TF_CHECK_PARMS1(tfp);
501 /* Retrieve the session information */
502 rc = tf_session_get_session_internal(tfp, &tfs);
506 if (!tf_session_is_shared_session(tfs)) {
507 for (i = 0; i < TF_DIR_MAX; i++)
508 #if (TF_EM_ALLOC == 1)
509 dpool_free_all(tfs->em_pool[i]);
511 tf_free_em_pool(tfs, i);
515 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
518 "Em_db is not initialized, rc:%s\n",
522 em_db = (struct em_rm_db *)em_db_ptr;
524 for (i = 0; i < TF_DIR_MAX; i++) {
525 if (em_db->em_db[i] == NULL)
528 fparms.rm_db = em_db->em_db[i];
529 rc = tf_rm_free_db(tfp, &fparms);
533 em_db->em_db[i] = NULL;
540 tf_em_get_resc_info(struct tf *tfp,
541 struct tf_em_resource_info *em)
545 struct tf_resource_info *dinfo;
546 struct tf_rm_get_alloc_info_parms ainfo;
547 void *em_db_ptr = NULL;
548 struct em_rm_db *em_db;
550 TF_CHECK_PARMS2(tfp, em);
552 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
555 "No resource allocated for em from session\n");
558 em_db = (struct em_rm_db *)em_db_ptr;
560 /* check if reserved resource for WC is multiple of num_slices */
561 for (d = 0; d < TF_DIR_MAX; d++) {
562 ainfo.rm_db = em_db->em_db[d];
565 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
567 rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX);
568 if (rc && rc != -ENOTSUP)