1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
7 #include <rte_common.h>
9 #include "tf_tcam_shared.h"
11 #include "tf_common.h"
14 #include "tf_device.h"
16 #include "tf_session.h"
23 /** Shared WC TCAM pool identifiers
25 enum tf_tcam_shared_wc_pool_id {
26 TF_TCAM_SHARED_WC_POOL_HI = 0,
27 TF_TCAM_SHARED_WC_POOL_LO = 1,
28 TF_TCAM_SHARED_WC_POOL_MAX = 2
31 /** Get string representation of a WC TCAM shared pool id
34 tf_pool_2_str(enum tf_tcam_shared_wc_pool_id id)
37 case TF_TCAM_SHARED_WC_POOL_HI:
38 return "TCAM_SHARED_WC_POOL_HI";
39 case TF_TCAM_SHARED_WC_POOL_LO:
40 return "TCAM_SHARED_WC_POOL_LO";
42 return "Invalid TCAM_SHARED_WC_POOL";
46 /** The WC TCAM shared pool datastructure
48 struct tf_tcam_shared_wc_pool {
49 /** Start and stride data */
50 struct tf_resource_info info;
52 struct bitalloc *pool;
55 /** The WC TCAM shared pool declarations
56 * TODO: add tcam_shared_wc_db
58 struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX];
60 /** Create a WC TCAM shared pool
63 tf_tcam_shared_create_wc_pool(int dir,
64 enum tf_tcam_shared_wc_pool_id id,
70 struct tfp_calloc_parms cparms;
74 pool_size = (BITALLOC_SIZEOF(stride) / sizeof(struct bitalloc));
75 cparms.nitems = pool_size;
77 cparms.size = sizeof(struct bitalloc);
78 rc = tfp_calloc(&cparms);
81 "%s: pool memory alloc failed %s:%s\n",
82 tf_dir_2_str(dir), tf_pool_2_str(id),
86 tcam_shared_wc[dir][id].pool = (struct bitalloc *)cparms.mem_va;
88 rc = ba_init(tcam_shared_wc[dir][id].pool,
94 "%s: pool bitalloc failed %s\n",
95 tf_dir_2_str(dir), tf_pool_2_str(id));
99 tcam_shared_wc[dir][id].info.start = start;
100 tcam_shared_wc[dir][id].info.stride = stride;
103 /** Free a WC TCAM shared pool
106 tf_tcam_shared_free_wc_pool(int dir,
107 enum tf_tcam_shared_wc_pool_id id)
109 tcam_shared_wc[dir][id].info.start = 0;
110 tcam_shared_wc[dir][id].info.stride = 0;
112 if (tcam_shared_wc[dir][id].pool)
113 tfp_free((void *)tcam_shared_wc[dir][id].pool);
116 /** Get the number of WC TCAM slices allocated during 1 allocation/free
119 tf_tcam_shared_get_slices(struct tf *tfp,
120 struct tf_dev_info *dev,
121 uint16_t *num_slices)
125 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
128 "Operation not supported, rc:%s\n", strerror(-rc));
131 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
132 TF_TCAM_TBL_TYPE_WC_TCAM,
139 tf_tcam_shared_db_valid(struct tf *tfp,
142 struct tcam_rm_db *tcam_db;
143 void *tcam_db_ptr = NULL;
146 TF_CHECK_PARMS1(tfp);
148 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
152 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
154 if (tcam_db->tcam_db[dir])
161 tf_tcam_shared_get_rm_info(struct tf *tfp,
163 uint16_t *hcapi_type,
164 struct tf_rm_alloc_info *info)
167 struct tcam_rm_db *tcam_db;
168 void *tcam_db_ptr = NULL;
169 struct tf_rm_get_alloc_info_parms ainfo;
170 struct tf_rm_get_hcapi_parms hparms;
172 TF_CHECK_PARMS3(tfp, hcapi_type, info);
174 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
177 "Tcam_db is not initialized, rc:%s\n",
181 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
183 /* Convert TF type to HCAPI RM type */
184 memset(&hparms, 0, sizeof(hparms));
185 hparms.rm_db = tcam_db->tcam_db[dir];
186 hparms.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
187 hparms.hcapi_type = hcapi_type;
189 rc = tf_rm_get_hcapi_type(&hparms);
192 "%s: Get RM hcapi type failed %s\n",
198 memset(info, 0, sizeof(struct tf_rm_alloc_info));
199 ainfo.rm_db = tcam_db->tcam_db[dir];
200 ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
203 rc = tf_rm_get_info(&ainfo);
206 "%s: TCAM rm info get failed %s\n",
215 * tf_tcam_shared_bind
218 tf_tcam_shared_bind(struct tf *tfp,
219 struct tf_tcam_cfg_parms *parms)
222 struct tf_session *tfs;
223 struct tf_dev_info *dev;
224 struct tf_rm_alloc_info info;
225 uint16_t start, stride;
229 TF_CHECK_PARMS2(tfp, parms);
231 /* Perform normal bind
233 rc = tf_tcam_bind(tfp, parms);
237 /* After the normal TCAM bind, if this is a shared session
238 * create all required databases for the WC_HI and WC_LO pools
240 rc = tf_session_get_session_internal(tfp, &tfs);
243 "Session access failure: %s\n", strerror(-rc));
246 if (tf_session_is_shared_session(tfs)) {
247 /* Retrieve the device information */
248 rc = tf_session_get_device(tfs, &dev);
252 rc = tf_tcam_shared_get_slices(tfp,
258 /* If there are WC TCAM entries, create 2 pools each with 1/2
259 * the total number of entries
261 for (dir = 0; dir < TF_DIR_MAX; dir++) {
262 if (!tf_tcam_shared_db_valid(tfp, dir))
265 rc = tf_tcam_shared_get_rm_info(tfp,
271 "%s: TCAM rm info get failed\n",
276 start = info.entry.start;
277 stride = info.entry.stride / 2;
279 tf_tcam_shared_create_wc_pool(dir,
280 TF_TCAM_SHARED_WC_POOL_HI,
285 tf_tcam_shared_create_wc_pool(dir,
286 TF_TCAM_SHARED_WC_POOL_LO,
295 * tf_tcam_shared_unbind
298 tf_tcam_shared_unbind(struct tf *tfp)
301 struct tf_session *tfs;
303 TF_CHECK_PARMS1(tfp);
305 /* Perform normal unbind, this will write all the
306 * allocated TCAM entries in the shared session.
308 rc = tf_tcam_unbind(tfp);
312 /* Retrieve the session information */
313 rc = tf_session_get_session_internal(tfp, &tfs);
317 /* If we are the shared session
319 if (tf_session_is_shared_session(tfs)) {
320 /* If there are WC TCAM entries allocated, free them
322 for (dir = 0; dir < TF_DIR_MAX; dir++) {
323 tf_tcam_shared_free_wc_pool(dir,
324 TF_TCAM_SHARED_WC_POOL_HI);
325 tf_tcam_shared_free_wc_pool(dir,
326 TF_TCAM_SHARED_WC_POOL_LO);
332 * tf_tcam_shared_alloc
335 tf_tcam_shared_alloc(struct tf *tfp,
336 struct tf_tcam_alloc_parms *parms)
339 struct tf_session *tfs;
340 struct tf_dev_info *dev;
342 struct bitalloc *pool;
343 enum tf_tcam_shared_wc_pool_id id;
346 TF_CHECK_PARMS2(tfp, parms);
348 /* Retrieve the session information */
349 rc = tf_session_get_session_internal(tfp, &tfs);
353 /* If we aren't the shared session or the type is
354 * not one of the special WC TCAM types, call the normal
357 if (!tf_session_is_shared_session(tfs) ||
358 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
359 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
360 /* Perform normal alloc
362 rc = tf_tcam_alloc(tfp, parms);
366 if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
368 "%s: tcam shared pool doesn't exist\n",
369 tf_dir_2_str(parms->dir));
373 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
374 id = TF_TCAM_SHARED_WC_POOL_HI;
376 id = TF_TCAM_SHARED_WC_POOL_LO;
378 /* Retrieve the device information */
379 rc = tf_session_get_device(tfs, &dev);
383 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
387 pool = tcam_shared_wc[parms->dir][id].pool;
389 for (i = 0; i < num_slices; i++) {
391 * priority 0: allocate from top of the tcam i.e. high
392 * priority !0: allocate index from bottom i.e lowest
395 log_idx = ba_alloc_reverse(pool);
397 log_idx = ba_alloc(pool);
398 if (log_idx == BA_FAIL) {
400 "%s: Allocation failed, rc:%s\n",
401 tf_dir_2_str(parms->dir),
405 /* return the index without the start of each row */
407 parms->idx = log_idx;
413 tf_tcam_shared_free(struct tf *tfp,
414 struct tf_tcam_free_parms *parms)
417 struct tf_session *tfs;
418 struct tf_dev_info *dev;
423 struct bitalloc *pool;
424 enum tf_tcam_shared_wc_pool_id id;
425 struct tf_tcam_free_parms nparms;
428 struct tf_rm_alloc_info info;
430 TF_CHECK_PARMS2(tfp, parms);
432 /* Retrieve the session information */
433 rc = tf_session_get_session_internal(tfp, &tfs);
437 /* If we aren't the shared session or the type is
438 * not one of the special WC TCAM types, call the normal
441 if (!tf_session_is_shared_session(tfs) ||
442 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
443 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
444 /* Perform normal free
446 rc = tf_tcam_free(tfp, parms);
450 if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
452 "%s: tcam shared pool doesn't exist\n",
453 tf_dir_2_str(parms->dir));
457 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
458 id = TF_TCAM_SHARED_WC_POOL_HI;
460 id = TF_TCAM_SHARED_WC_POOL_LO;
462 /* Retrieve the device information */
463 rc = tf_session_get_device(tfs, &dev);
467 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
471 rc = tf_tcam_shared_get_rm_info(tfp,
477 "%s: TCAM rm info get failed\n",
478 tf_dir_2_str(parms->dir));
482 pool = tcam_shared_wc[parms->dir][id].pool;
483 start = tcam_shared_wc[parms->dir][id].info.start;
485 if (parms->idx % num_slices) {
487 "%s: TCAM reserved resource is not multiple of %d\n",
488 tf_dir_2_str(parms->dir), num_slices);
492 phy_idx = parms->idx + start;
493 allocated = ba_inuse(pool, parms->idx);
495 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
497 "%s: Entry already free, type:%d, idx:%d\n",
498 tf_dir_2_str(parms->dir), parms->type, parms->idx);
502 for (i = 0; i < num_slices; i++) {
503 rc = ba_free(pool, parms->idx + i);
506 "%s: Free failed, type:%s, idx:%d\n",
507 tf_dir_2_str(parms->dir),
508 tf_tcam_tbl_2_str(parms->type),
514 /* Override HI/LO type with parent WC TCAM type */
516 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
517 nparms.hcapi_type = hcapi_type;
518 nparms.idx = phy_idx;
520 rc = tf_msg_tcam_entry_free(tfp, dev, &nparms);
524 "%s: %s: log%d free failed, rc:%s\n",
525 tf_dir_2_str(nparms.dir),
526 tf_tcam_tbl_2_str(nparms.type),
535 tf_tcam_shared_set(struct tf *tfp __rte_unused,
536 struct tf_tcam_set_parms *parms __rte_unused)
539 struct tf_session *tfs;
540 struct tf_dev_info *dev;
542 int phy_idx, log_idx;
544 struct tf_tcam_set_parms nparms;
545 struct bitalloc *pool;
547 enum tf_tcam_shared_wc_pool_id id;
549 struct tf_rm_alloc_info info;
551 TF_CHECK_PARMS2(tfp, parms);
553 /* Retrieve the session information */
554 rc = tf_session_get_session_internal(tfp, &tfs);
558 /* If we aren't the shared session or one of our
561 if (!tf_session_is_shared_session(tfs) ||
562 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
563 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
564 /* Perform normal set and exit
566 rc = tf_tcam_set(tfp, parms);
570 if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
572 "%s: tcam shared pool doesn't exist\n",
573 tf_dir_2_str(parms->dir));
577 /* Retrieve the device information */
578 rc = tf_session_get_device(tfs, &dev);
582 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
583 id = TF_TCAM_SHARED_WC_POOL_HI;
585 id = TF_TCAM_SHARED_WC_POOL_LO;
587 pool = tcam_shared_wc[parms->dir][id].pool;
588 start = tcam_shared_wc[parms->dir][id].info.start;
590 log_idx = parms->idx;
591 phy_idx = parms->idx + start;
592 allocated = ba_inuse(pool, parms->idx);
594 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
596 "%s: Entry is not allocated, type:%d, logid:%d\n",
597 tf_dir_2_str(parms->dir), parms->type, log_idx);
600 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
604 if (parms->idx % num_slices) {
606 "%s: TCAM reserved resource is not multiple of %d\n",
607 tf_dir_2_str(parms->dir), num_slices);
610 rc = tf_tcam_shared_get_rm_info(tfp,
617 /* Override HI/LO type with parent WC TCAM type */
618 nparms.hcapi_type = hcapi_type;
619 nparms.dir = parms->dir;
620 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
621 nparms.idx = phy_idx;
622 nparms.key = parms->key;
623 nparms.mask = parms->mask;
624 nparms.key_size = parms->key_size;
625 nparms.result = parms->result;
626 nparms.result_size = parms->result_size;
628 rc = tf_msg_tcam_entry_set(tfp, dev, &nparms);
632 "%s: %s: phy entry %d set failed, rc:%s",
633 tf_dir_2_str(parms->dir),
634 tf_tcam_tbl_2_str(nparms.type),
643 tf_tcam_shared_get(struct tf *tfp __rte_unused,
644 struct tf_tcam_get_parms *parms)
647 struct tf_session *tfs;
648 struct tf_dev_info *dev;
650 int phy_idx, log_idx;
652 struct tf_tcam_get_parms nparms;
653 struct bitalloc *pool;
655 enum tf_tcam_shared_wc_pool_id id;
657 struct tf_rm_alloc_info info;
659 TF_CHECK_PARMS2(tfp, parms);
661 /* Retrieve the session information */
662 rc = tf_session_get_session_internal(tfp, &tfs);
666 /* If we aren't the shared session or one of our
669 if (!tf_session_is_shared_session(tfs) ||
670 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
671 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
672 /* Perform normal get and exit
674 rc = tf_tcam_get(tfp, parms);
678 if (!tf_tcam_shared_db_valid(tfp, parms->dir)) {
680 "%s: tcam shared pool doesn't exist\n",
681 tf_dir_2_str(parms->dir));
685 /* Retrieve the device information */
686 rc = tf_session_get_device(tfs, &dev);
689 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
690 id = TF_TCAM_SHARED_WC_POOL_HI;
692 id = TF_TCAM_SHARED_WC_POOL_LO;
694 pool = tcam_shared_wc[parms->dir][id].pool;
695 start = tcam_shared_wc[parms->dir][id].info.start;
697 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
701 if (parms->idx % num_slices) {
703 "%s: TCAM reserved resource is not multiple of %d\n",
704 tf_dir_2_str(parms->dir), num_slices);
707 log_idx = parms->idx;
708 phy_idx = parms->idx + start;
709 allocated = ba_inuse(pool, parms->idx);
711 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
713 "%s: Entry is not allocated, type:%d, logid:%d\n",
714 tf_dir_2_str(parms->dir), parms->type, log_idx);
718 rc = tf_tcam_shared_get_rm_info(tfp,
725 /* Override HI/LO type with parent WC TCAM type */
727 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
728 nparms.hcapi_type = hcapi_type;
729 nparms.idx = phy_idx;
731 rc = tf_msg_tcam_entry_get(tfp, dev, &nparms);
735 "%s: %s: Entry %d set failed, rc:%s",
736 tf_dir_2_str(nparms.dir),
737 tf_tcam_tbl_2_str(nparms.type),