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);
418 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
419 TFP_DRV_LOG(ERR, "EM Int DB creation failed\n");
420 return db_rc[TF_DIR_RX];
424 if (!tf_session_is_shared_session(tfs)) {
425 for (i = 0; i < TF_DIR_MAX; i++) {
426 iparms.rm_db = em_db->em_db[i];
427 iparms.subtype = TF_EM_DB_EM_REC;
430 rc = tf_rm_get_info(&iparms);
433 "%s: EM DB get info failed\n",
437 #if (TF_EM_ALLOC == 1)
439 * Allocate stack pool
442 cparms.size = sizeof(struct dpool);
443 cparms.alignment = 0;
445 rc = tfp_calloc(&cparms);
449 "%s, EM stack allocation failure %s\n",
455 tfs->em_pool[i] = (struct dpool *)cparms.mem_va;
457 rc = dpool_init(tfs->em_pool[i],
458 iparms.info->entry.start,
459 iparms.info->entry.stride,
462 tf_em_move_callback);
464 rc = tf_create_em_pool(tfs,
466 iparms.info->entry.stride,
467 iparms.info->entry.start);
469 /* Logging handled in tf_create_em_pool */
476 "%s: EM pool init failed\n",
486 tf_em_int_unbind(struct tf *tfp)
490 struct tf_rm_free_db_parms fparms = { 0 };
491 struct em_rm_db *em_db;
492 void *em_db_ptr = NULL;
493 struct tf_session *tfs;
495 TF_CHECK_PARMS1(tfp);
497 /* Retrieve the session information */
498 rc = tf_session_get_session_internal(tfp, &tfs);
502 if (!tf_session_is_shared_session(tfs)) {
503 for (i = 0; i < TF_DIR_MAX; i++)
504 #if (TF_EM_ALLOC == 1)
505 dpool_free_all(tfs->em_pool[i]);
507 tf_free_em_pool(tfs, i);
511 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
515 em_db = (struct em_rm_db *)em_db_ptr;
517 for (i = 0; i < TF_DIR_MAX; i++) {
518 if (em_db->em_db[i] == NULL)
521 fparms.rm_db = em_db->em_db[i];
522 rc = tf_rm_free_db(tfp, &fparms);
526 em_db->em_db[i] = NULL;
533 tf_em_get_resc_info(struct tf *tfp,
534 struct tf_em_resource_info *em)
538 struct tf_resource_info *dinfo;
539 struct tf_rm_get_alloc_info_parms ainfo;
540 void *em_db_ptr = NULL;
541 struct em_rm_db *em_db;
543 TF_CHECK_PARMS2(tfp, em);
545 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_EM, &em_db_ptr);
548 "No resource allocated for em from session\n");
551 em_db = (struct em_rm_db *)em_db_ptr;
553 /* check if reserved resource for WC is multiple of num_slices */
554 for (d = 0; d < TF_DIR_MAX; d++) {
555 ainfo.rm_db = em_db->em_db[d];
558 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
560 rc = tf_rm_get_all_info(&ainfo, TF_EM_TBL_TYPE_MAX);
561 if (rc && rc != -ENOTSUP)