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"
21 /** Shared WC TCAM pool identifiers
23 enum tf_tcam_shared_wc_pool_id {
24 TF_TCAM_SHARED_WC_POOL_HI = 0,
25 TF_TCAM_SHARED_WC_POOL_LO = 1,
26 TF_TCAM_SHARED_WC_POOL_MAX = 2
29 /** Get string representation of a WC TCAM shared pool id
32 tf_pool_2_str(enum tf_tcam_shared_wc_pool_id id)
35 case TF_TCAM_SHARED_WC_POOL_HI:
36 return "TCAM_SHARED_WC_POOL_HI";
37 case TF_TCAM_SHARED_WC_POOL_LO:
38 return "TCAM_SHARED_WC_POOL_LO";
40 return "Invalid TCAM_SHARED_WC_POOL";
44 /** The WC TCAM shared pool datastructure
46 struct tf_tcam_shared_wc_pool {
47 /** Start and stride data */
48 struct tf_resource_info info;
50 struct bitalloc *pool;
53 struct tf_tcam_shared_wc_pools {
54 struct tf_tcam_shared_wc_pool db[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX];
57 /** The WC TCAM shared pool declarations
59 /* struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX]; */
62 tf_tcam_shared_create_db(struct tf_tcam_shared_wc_pools **db)
64 struct tfp_calloc_parms cparms;
69 cparms.size = sizeof(struct tf_tcam_shared_wc_pools);
70 rc = tfp_calloc(&cparms);
73 "TCAM shared db allocation failed (%s)\n",
82 /** Create a WC TCAM shared pool
85 tf_tcam_shared_create_wc_pool(int dir,
86 enum tf_tcam_shared_wc_pool_id id,
89 struct tf_tcam_shared_wc_pools *tcam_shared_wc)
93 struct tfp_calloc_parms cparms;
97 pool_size = (BITALLOC_SIZEOF(stride) / sizeof(struct bitalloc));
98 cparms.nitems = pool_size;
100 cparms.size = sizeof(struct bitalloc);
101 rc = tfp_calloc(&cparms);
104 "%s: pool memory alloc failed %s:%s\n",
105 tf_dir_2_str(dir), tf_pool_2_str(id),
109 tcam_shared_wc->db[dir][id].pool = (struct bitalloc *)cparms.mem_va;
111 rc = ba_init(tcam_shared_wc->db[dir][id].pool,
117 "%s: pool bitalloc failed %s\n",
118 tf_dir_2_str(dir), tf_pool_2_str(id));
122 tcam_shared_wc->db[dir][id].info.start = start;
123 tcam_shared_wc->db[dir][id].info.stride = stride;
127 /** Free a WC TCAM shared pool
130 tf_tcam_shared_free_wc_pool(int dir,
131 enum tf_tcam_shared_wc_pool_id id,
132 struct tf_tcam_shared_wc_pools *tcam_shared_wc)
135 TF_CHECK_PARMS1(tcam_shared_wc);
137 tcam_shared_wc->db[dir][id].info.start = 0;
138 tcam_shared_wc->db[dir][id].info.stride = 0;
140 if (tcam_shared_wc->db[dir][id].pool)
141 tfp_free((void *)tcam_shared_wc->db[dir][id].pool);
145 /** Get the number of WC TCAM slices allocated during 1 allocation/free
148 tf_tcam_shared_get_slices(struct tf *tfp,
149 struct tf_dev_info *dev,
150 uint16_t *num_slices)
154 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
157 "Operation not supported, rc:%s\n", strerror(-rc));
160 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
161 TF_TCAM_TBL_TYPE_WC_TCAM,
168 tf_tcam_db_valid(struct tf *tfp,
171 struct tcam_rm_db *tcam_db;
172 void *tcam_db_ptr = NULL;
175 TF_CHECK_PARMS1(tfp);
177 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
181 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
183 if (tcam_db->tcam_db[dir])
190 tf_tcam_shared_get_rm_info(struct tf *tfp,
192 uint16_t *hcapi_type,
193 struct tf_rm_alloc_info *info)
196 struct tcam_rm_db *tcam_db;
197 void *tcam_db_ptr = NULL;
198 struct tf_rm_get_alloc_info_parms ainfo;
199 struct tf_rm_get_hcapi_parms hparms;
201 TF_CHECK_PARMS3(tfp, hcapi_type, info);
203 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
206 "Tcam_db is not initialized, rc:%s\n",
210 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
212 /* Convert TF type to HCAPI RM type */
213 memset(&hparms, 0, sizeof(hparms));
214 hparms.rm_db = tcam_db->tcam_db[dir];
215 hparms.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
216 hparms.hcapi_type = hcapi_type;
218 rc = tf_rm_get_hcapi_type(&hparms);
221 "%s: Get RM hcapi type failed %s\n",
227 memset(info, 0, sizeof(struct tf_rm_alloc_info));
228 ainfo.rm_db = tcam_db->tcam_db[dir];
229 ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
232 rc = tf_rm_get_info(&ainfo);
235 "%s: TCAM rm info get failed %s\n",
244 * tf_tcam_shared_bind
247 tf_tcam_shared_bind(struct tf *tfp,
248 struct tf_tcam_cfg_parms *parms)
251 struct tf_session *tfs;
252 struct tf_dev_info *dev;
253 struct tf_rm_alloc_info info;
254 uint16_t start, stride;
257 struct tf_tcam_shared_wc_pools *tcam_shared_wc = NULL;
259 TF_CHECK_PARMS2(tfp, parms);
261 /* Perform normal bind
263 rc = tf_tcam_bind(tfp, parms);
267 /* After the normal TCAM bind, if this is a shared session
268 * create all required databases for the WC_HI and WC_LO pools
270 rc = tf_session_get_session_internal(tfp, &tfs);
273 "Session access failure: %s\n", strerror(-rc));
276 if (tf_session_is_shared_session(tfs)) {
277 /* Retrieve the device information */
278 rc = tf_session_get_device(tfs, &dev);
282 tf_tcam_shared_create_db(&tcam_shared_wc);
285 /* If there are WC TCAM entries, create 2 pools each with 1/2
286 * the total number of entries
288 for (dir = 0; dir < TF_DIR_MAX; dir++) {
289 if (!tf_tcam_db_valid(tfp, dir))
292 rc = tf_tcam_shared_get_rm_info(tfp,
298 "%s: TCAM rm info get failed\n",
303 start = info.entry.start;
304 stride = info.entry.stride / 2;
306 tf_tcam_shared_create_wc_pool(dir,
307 TF_TCAM_SHARED_WC_POOL_HI,
313 tf_tcam_shared_create_wc_pool(dir,
314 TF_TCAM_SHARED_WC_POOL_LO,
319 tf_session_set_tcam_shared_db(tfp, (void *)tcam_shared_wc);
322 rc = tf_tcam_shared_get_slices(tfp,
328 if (num_slices > 1) {
330 "Only single slice supported\n");
338 * tf_tcam_shared_unbind
341 tf_tcam_shared_unbind(struct tf *tfp)
344 struct tf_dev_info *dev;
345 struct tf_session *tfs;
346 void *tcam_shared_db_ptr = NULL;
347 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
348 enum tf_tcam_shared_wc_pool_id pool_id;
349 struct tf_tcam_free_parms parms;
350 struct bitalloc *pool;
352 int log_idx, phy_idx;
354 struct tf_rm_alloc_info info;
357 TF_CHECK_PARMS1(tfp);
359 /* Retrieve the session information */
360 rc = tf_session_get_session_internal(tfp, &tfs);
364 /* If not the shared session, call the normal
365 * tcam unbind and exit
367 if (!tf_session_is_shared_session(tfs)) {
368 rc = tf_tcam_unbind(tfp);
372 /* We must be a shared session, get the database
374 rc = tf_session_get_tcam_shared_db(tfp,
375 (void *)&tcam_shared_db_ptr);
378 "Failed to get tcam_shared_db, rc:%s\n",
384 (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
389 rc = tf_session_get_device(tfs, &dev);
394 /* If there are WC TCAM entries allocated, free them
396 for (dir = 0; dir < TF_DIR_MAX; dir++) {
397 /* If the database is invalid, skip
399 if (!tf_tcam_db_valid(tfp, dir))
402 rc = tf_tcam_shared_get_rm_info(tfp,
408 "%s: TCAM shared rm info get failed\n",
413 for (pool_id = TF_TCAM_SHARED_WC_POOL_HI;
414 pool_id < TF_TCAM_SHARED_WC_POOL_MAX;
416 pool = tcam_shared_wc->db[dir][pool_id].pool;
417 start = tcam_shared_wc->db[dir][pool_id].info.start;
418 pool_cnt = ba_inuse_count(pool);
422 "%s: %s: %d residuals found, freeing\n",
424 tf_pool_2_str(pool_id),
430 for (i = 0; i < pool_cnt; i++) {
431 log_idx = ba_find_next_inuse(pool, log_idx);
435 "Expected a found %s entry %d\n",
436 tf_pool_2_str(pool_id),
438 /* attempt normal unbind
442 phy_idx = start + log_idx;
444 parms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
445 parms.hcapi_type = hcapi_type;
448 rc = tf_msg_tcam_entry_free(tfp, dev, &parms);
452 "%s: %s: %d free failed, rc:%s\n",
453 tf_dir_2_str(parms.dir),
454 tf_tcam_tbl_2_str(parms.type),
460 /* Free the pool once all the entries
463 tf_tcam_shared_free_wc_pool(dir,
469 rc = tf_tcam_unbind(tfp);
474 * tf_tcam_shared_alloc
477 tf_tcam_shared_alloc(struct tf *tfp,
478 struct tf_tcam_alloc_parms *parms)
481 struct tf_session *tfs;
482 struct tf_dev_info *dev;
484 struct bitalloc *pool;
485 enum tf_tcam_shared_wc_pool_id id;
486 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
487 void *tcam_shared_db_ptr = NULL;
489 TF_CHECK_PARMS2(tfp, parms);
491 /* Retrieve the session information */
492 rc = tf_session_get_session_internal(tfp, &tfs);
496 /* If we aren't the shared session or the type is
497 * not one of the special WC TCAM types, call the normal
500 if (!tf_session_is_shared_session(tfs) ||
501 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
502 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
503 /* Perform normal alloc
505 rc = tf_tcam_alloc(tfp, parms);
509 if (!tf_tcam_db_valid(tfp, parms->dir)) {
511 "%s: tcam shared pool doesn't exist\n",
512 tf_dir_2_str(parms->dir));
516 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
519 "Failed to get tcam_shared_db from session, rc:%s\n",
523 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
525 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
526 id = TF_TCAM_SHARED_WC_POOL_HI;
528 id = TF_TCAM_SHARED_WC_POOL_LO;
530 /* Retrieve the device information */
531 rc = tf_session_get_device(tfs, &dev);
535 pool = tcam_shared_wc->db[parms->dir][id].pool;
538 * priority 0: allocate from top of the tcam i.e. high
539 * priority !0: allocate index from bottom i.e lowest
542 log_idx = ba_alloc_reverse(pool);
544 log_idx = ba_alloc(pool);
545 if (log_idx == BA_FAIL) {
547 "%s: Allocation failed, rc:%s\n",
548 tf_dir_2_str(parms->dir),
552 parms->idx = log_idx;
557 tf_tcam_shared_free(struct tf *tfp,
558 struct tf_tcam_free_parms *parms)
561 struct tf_session *tfs;
562 struct tf_dev_info *dev;
566 struct bitalloc *pool;
567 enum tf_tcam_shared_wc_pool_id id;
568 struct tf_tcam_free_parms nparms;
570 struct tf_rm_alloc_info info;
571 void *tcam_shared_db_ptr = NULL;
572 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
574 TF_CHECK_PARMS2(tfp, parms);
576 /* Retrieve the session information */
577 rc = tf_session_get_session_internal(tfp, &tfs);
581 /* If we aren't the shared session or the type is
582 * not one of the special WC TCAM types, call the normal
585 if (!tf_session_is_shared_session(tfs) ||
586 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
587 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
588 /* Perform normal free
590 rc = tf_tcam_free(tfp, parms);
594 if (!tf_tcam_db_valid(tfp, parms->dir)) {
596 "%s: tcam shared pool doesn't exist\n",
597 tf_dir_2_str(parms->dir));
601 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
604 "Failed to get tcam_shared_db from session, rc:%s\n",
608 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
611 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
612 id = TF_TCAM_SHARED_WC_POOL_HI;
614 id = TF_TCAM_SHARED_WC_POOL_LO;
616 /* Retrieve the device information */
617 rc = tf_session_get_device(tfs, &dev);
621 rc = tf_tcam_shared_get_rm_info(tfp,
627 "%s: TCAM rm info get failed\n",
628 tf_dir_2_str(parms->dir));
632 pool = tcam_shared_wc->db[parms->dir][id].pool;
633 start = tcam_shared_wc->db[parms->dir][id].info.start;
635 phy_idx = parms->idx + start;
636 allocated = ba_inuse(pool, parms->idx);
638 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
640 "%s: Entry already free, type:%d, idx:%d\n",
641 tf_dir_2_str(parms->dir), parms->type, parms->idx);
645 rc = ba_free(pool, parms->idx);
648 "%s: Free failed, type:%s, idx:%d\n",
649 tf_dir_2_str(parms->dir),
650 tf_tcam_tbl_2_str(parms->type),
655 /* Override HI/LO type with parent WC TCAM type */
657 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
658 nparms.hcapi_type = hcapi_type;
659 nparms.idx = phy_idx;
661 rc = tf_msg_tcam_entry_free(tfp, dev, &nparms);
665 "%s: %s: log%d free failed, rc:%s\n",
666 tf_dir_2_str(nparms.dir),
667 tf_tcam_tbl_2_str(nparms.type),
676 tf_tcam_shared_set(struct tf *tfp __rte_unused,
677 struct tf_tcam_set_parms *parms __rte_unused)
680 struct tf_session *tfs;
681 struct tf_dev_info *dev;
683 int phy_idx, log_idx;
684 struct tf_tcam_set_parms nparms;
685 struct bitalloc *pool;
687 enum tf_tcam_shared_wc_pool_id id;
689 struct tf_rm_alloc_info info;
690 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
691 void *tcam_shared_db_ptr = NULL;
694 TF_CHECK_PARMS2(tfp, parms);
696 /* Retrieve the session information */
697 rc = tf_session_get_session_internal(tfp, &tfs);
701 /* If we aren't the shared session or one of our
704 if (!tf_session_is_shared_session(tfs) ||
705 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
706 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
707 /* Perform normal set and exit
709 rc = tf_tcam_set(tfp, parms);
713 if (!tf_tcam_db_valid(tfp, parms->dir)) {
715 "%s: tcam shared pool doesn't exist\n",
716 tf_dir_2_str(parms->dir));
720 /* Retrieve the device information */
721 rc = tf_session_get_device(tfs, &dev);
725 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
726 id = TF_TCAM_SHARED_WC_POOL_HI;
728 id = TF_TCAM_SHARED_WC_POOL_LO;
730 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
733 "Failed to get tcam_shared_db from session, rc:%s\n",
737 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
739 pool = tcam_shared_wc->db[parms->dir][id].pool;
740 start = tcam_shared_wc->db[parms->dir][id].info.start;
742 log_idx = parms->idx;
743 phy_idx = parms->idx + start;
744 allocated = ba_inuse(pool, parms->idx);
746 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
748 "%s: Entry is not allocated, type:%d, logid:%d\n",
749 tf_dir_2_str(parms->dir), parms->type, log_idx);
753 rc = tf_tcam_shared_get_rm_info(tfp,
760 /* Override HI/LO type with parent WC TCAM type */
761 nparms.hcapi_type = hcapi_type;
762 nparms.dir = parms->dir;
763 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
764 nparms.idx = phy_idx;
765 nparms.key = parms->key;
766 nparms.mask = parms->mask;
767 nparms.key_size = parms->key_size;
768 nparms.result = parms->result;
769 nparms.result_size = parms->result_size;
771 rc = tf_msg_tcam_entry_set(tfp, dev, &nparms);
775 "%s: %s: phy entry %d set failed, rc:%s",
776 tf_dir_2_str(parms->dir),
777 tf_tcam_tbl_2_str(nparms.type),
786 tf_tcam_shared_get(struct tf *tfp __rte_unused,
787 struct tf_tcam_get_parms *parms)
790 struct tf_session *tfs;
791 struct tf_dev_info *dev;
793 int phy_idx, log_idx;
794 struct tf_tcam_get_parms nparms;
795 struct bitalloc *pool;
797 enum tf_tcam_shared_wc_pool_id id;
799 struct tf_rm_alloc_info info;
800 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
801 void *tcam_shared_db_ptr = NULL;
803 TF_CHECK_PARMS2(tfp, parms);
805 /* Retrieve the session information */
806 rc = tf_session_get_session_internal(tfp, &tfs);
810 /* If we aren't the shared session or one of our
813 if (!tf_session_is_shared_session(tfs) ||
814 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
815 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
816 /* Perform normal get and exit
818 rc = tf_tcam_get(tfp, parms);
822 if (!tf_tcam_db_valid(tfp, parms->dir)) {
824 "%s: tcam shared pool doesn't exist\n",
825 tf_dir_2_str(parms->dir));
829 /* Retrieve the device information */
830 rc = tf_session_get_device(tfs, &dev);
833 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
834 id = TF_TCAM_SHARED_WC_POOL_HI;
836 id = TF_TCAM_SHARED_WC_POOL_LO;
839 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
842 "Failed to get tcam_shared_db from session, rc:%s\n",
846 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
848 pool = tcam_shared_wc->db[parms->dir][id].pool;
849 start = tcam_shared_wc->db[parms->dir][id].info.start;
851 log_idx = parms->idx;
852 phy_idx = parms->idx + start;
853 allocated = ba_inuse(pool, parms->idx);
855 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
857 "%s: Entry is not allocated, type:%d, logid:%d\n",
858 tf_dir_2_str(parms->dir), parms->type, log_idx);
862 rc = tf_tcam_shared_get_rm_info(tfp,
869 /* Override HI/LO type with parent WC TCAM type */
871 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
872 nparms.hcapi_type = hcapi_type;
873 nparms.idx = phy_idx;
875 rc = tf_msg_tcam_entry_get(tfp, dev, &nparms);
879 "%s: %s: Entry %d set failed, rc:%s",
880 tf_dir_2_str(nparms.dir),
881 tf_tcam_tbl_2_str(nparms.type),
889 /* Normally, device specific code wouldn't reside here, it belongs
890 * in a separate device specific function in tf_device_pxx.c.
891 * But this code is placed here as it is not a long term solution
892 * and we would like to have this code centrally located for easy
895 #define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4 12
896 #define TF_TCAM_SHARED_REMAP_SZ_BYTES_P4 4
897 #define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 24
898 #define TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 8
900 /* Temporary builder defines pulled in here and adjusted
901 * for max WC TCAM values
903 union tf_tmp_field_obj {
904 uint32_t words[(TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 + 3) / 4];
905 uint8_t bytes[TF_TCAM_SHARED_REMAP_SZ_BYTES_P58];
909 uint32_t words[(TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 + 3) / 4];
910 uint8_t bytes[TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58];
913 /** p58 has an enable bit, p4 does not
915 #define TF_TCAM_SHARED_ENTRY_ENABLE 0x8
917 /** Move a WC TCAM entry from the high offset to the same low offset
920 tf_tcam_shared_move_entry(struct tf *tfp,
921 struct tf_dev_info *dev,
931 struct tf_tcam_get_parms gparms;
932 struct tf_tcam_set_parms sparms;
933 struct tf_tcam_free_parms fparms;
934 union tf_tmp_key tcam_key_obj;
935 union tf_tmp_key tcam_key_msk_obj;
936 union tf_tmp_field_obj tcam_remap_obj;
938 memset(&tcam_key_obj, 0, sizeof(tcam_key_obj));
939 memset(&tcam_key_msk_obj, 0, sizeof(tcam_key_msk_obj));
940 memset(&tcam_remap_obj, 0, sizeof(tcam_remap_obj));
941 memset(&gparms, 0, sizeof(gparms));
943 gparms.hcapi_type = hcapi_type;
945 gparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
946 gparms.idx = sphy_idx;
947 gparms.key = (uint8_t *)&tcam_key_obj;
948 gparms.key_size = key_sz_bytes;
949 gparms.mask = (uint8_t *)&tcam_key_msk_obj;
950 gparms.result = (uint8_t *)&tcam_remap_obj;
951 gparms.result_size = remap_sz_bytes;
953 rc = tf_msg_tcam_entry_get(tfp, dev, &gparms);
957 "%s: %s: phyid(%d) get failed, rc:%s\n",
958 tf_tcam_tbl_2_str(gparms.type),
966 tcam_key_obj.bytes[0] |= TF_TCAM_SHARED_ENTRY_ENABLE;
968 /* Override HI/LO type with parent WC TCAM type */
969 sparms.hcapi_type = hcapi_type;
971 sparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
972 sparms.idx = dphy_idx;
973 sparms.key = gparms.key;
974 sparms.mask = gparms.mask;
975 sparms.key_size = key_sz_bytes;
976 sparms.result = gparms.result;
977 sparms.result_size = remap_sz_bytes;
979 rc = tf_msg_tcam_entry_set(tfp, dev, &sparms);
983 "%s: %s phyid(%d/0x%x) set failed, rc:%s\n",
984 tf_tcam_tbl_2_str(sparms.type),
992 /* Override HI/LO type with parent WC TCAM type */
994 fparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
995 fparms.hcapi_type = hcapi_type;
996 fparms.idx = sphy_idx;
998 rc = tf_msg_tcam_entry_free(tfp, dev, &fparms);
1002 "%s: %s: phyid(%d/0x%x) free failed, rc:%s\n",
1004 tf_tcam_tbl_2_str(fparms.type),
1013 /** Move all shared WC TCAM entries from the high pool into the low pool
1014 * and clear out the high pool entries.
1017 int tf_tcam_shared_move(struct tf *tfp,
1018 struct tf_move_tcam_shared_entries_parms *parms,
1021 bool set_enable_bit)
1024 struct tf_session *tfs;
1025 struct tf_dev_info *dev;
1027 struct bitalloc *hi_pool, *lo_pool;
1028 uint16_t hi_start, lo_start;
1029 enum tf_tcam_shared_wc_pool_id hi_id, lo_id;
1030 uint16_t hcapi_type;
1031 struct tf_rm_alloc_info info;
1033 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
1034 void *tcam_shared_db_ptr = NULL;
1036 TF_CHECK_PARMS2(tfp, parms);
1038 /* Retrieve the session information */
1039 rc = tf_session_get_session_internal(tfp, &tfs);
1043 /* If we aren't the shared session or one of our
1046 if (!tf_session_is_shared_session(tfs) ||
1047 (parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
1048 parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
1050 "%s: Session must be shared with HI/LO type\n",
1051 tf_dir_2_str(parms->dir));
1055 if (!tf_tcam_db_valid(tfp, parms->dir)) {
1057 "%s: tcam shared pool doesn't exist\n",
1058 tf_dir_2_str(parms->dir));
1062 /* Retrieve the device information */
1063 rc = tf_session_get_device(tfs, &dev);
1065 /* TODO print amazing error */
1069 rc = tf_tcam_shared_get_rm_info(tfp,
1075 "%s: TCAM rm info get failed\n",
1076 tf_dir_2_str(parms->dir));
1080 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
1083 "Failed to get tcam_shared_db from session, rc:%s\n",
1087 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
1089 hi_id = TF_TCAM_SHARED_WC_POOL_HI;
1090 hi_pool = tcam_shared_wc->db[parms->dir][hi_id].pool;
1091 hi_start = tcam_shared_wc->db[parms->dir][hi_id].info.start;
1093 lo_id = TF_TCAM_SHARED_WC_POOL_LO;
1094 lo_pool = tcam_shared_wc->db[parms->dir][lo_id].pool;
1095 lo_start = tcam_shared_wc->db[parms->dir][lo_id].info.start;
1097 if (hi_pool == NULL || lo_pool == NULL)
1100 /* Get the total count of in use entries in the high pool
1102 hi_cnt = ba_inuse_count(hi_pool);
1104 /* Copy each valid entry to the same low pool logical offset
1108 for (i = 0; i < hi_cnt; i++) {
1109 /* Find next free index starting from where we left off
1111 log_idx = ba_find_next_inuse(hi_pool, log_idx);
1114 "Expected a found %s entry %d\n",
1115 tf_pool_2_str(hi_id),
1119 /* The user should have never allocated from the low
1120 * pool because the move only happens when switching
1121 * from the high to the low pool
1123 if (ba_alloc_index(lo_pool, log_idx) < 0) {
1125 "Warning %s index %d already allocated\n",
1126 tf_pool_2_str(lo_id),
1129 /* Since already allocated, continue with move
1133 rc = tf_tcam_shared_move_entry(tfp, dev,
1143 "%s: Move error %s to %s index %d\n",
1144 tf_dir_2_str(parms->dir),
1145 tf_pool_2_str(hi_id),
1146 tf_pool_2_str(lo_id),
1150 ba_free(hi_pool, log_idx);
1157 tf_tcam_shared_move_p4(struct tf *tfp,
1158 struct tf_move_tcam_shared_entries_parms *parms)
1161 rc = tf_tcam_shared_move(tfp,
1163 TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4,
1164 TF_TCAM_SHARED_REMAP_SZ_BYTES_P4,
1165 false); /* no enable bit */
1171 tf_tcam_shared_move_p58(struct tf *tfp,
1172 struct tf_move_tcam_shared_entries_parms *parms)
1175 rc = tf_tcam_shared_move(tfp,
1177 TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58,
1178 TF_TCAM_SHARED_REMAP_SZ_BYTES_P58,
1179 true); /* set enable bit */
1184 tf_tcam_shared_clear(struct tf *tfp,
1185 struct tf_clear_tcam_shared_entries_parms *parms)
1188 struct tf_session *tfs;
1189 struct tf_dev_info *dev;
1192 enum tf_tcam_shared_wc_pool_id id;
1193 struct tf_tcam_free_parms nparms;
1194 uint16_t hcapi_type;
1195 struct tf_rm_alloc_info info;
1196 void *tcam_shared_db_ptr = NULL;
1197 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
1200 TF_CHECK_PARMS2(tfp, parms);
1202 /* Retrieve the session information */
1203 rc = tf_session_get_session_internal(tfp, &tfs);
1207 if (!tf_session_is_shared_session(tfs) ||
1208 (parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
1209 parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW))
1212 if (!tf_tcam_db_valid(tfp, parms->dir)) {
1214 "%s: tcam shared pool doesn't exist\n",
1215 tf_dir_2_str(parms->dir));
1219 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
1222 "Failed to get tcam_shared_db from session, rc:%s\n",
1226 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
1229 if (parms->tcam_tbl_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
1230 id = TF_TCAM_SHARED_WC_POOL_HI;
1232 id = TF_TCAM_SHARED_WC_POOL_LO;
1235 /* Retrieve the device information */
1236 rc = tf_session_get_device(tfs, &dev);
1240 rc = tf_tcam_shared_get_rm_info(tfp,
1246 "%s: TCAM rm info get failed\n",
1247 tf_dir_2_str(parms->dir));
1251 start = tcam_shared_wc->db[parms->dir][id].info.start;
1252 cnt = tcam_shared_wc->db[parms->dir][id].info.stride;
1254 /* Override HI/LO type with parent WC TCAM type */
1255 nparms.dir = parms->dir;
1256 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
1257 nparms.hcapi_type = hcapi_type;
1259 for (i = 0; i < cnt; i++) {
1260 phy_idx = start + i;
1261 nparms.idx = phy_idx;
1264 rc = tf_msg_tcam_entry_free(tfp, dev, &nparms);
1268 "%s: %s: log%d free failed, rc:%s\n",
1269 tf_dir_2_str(nparms.dir),
1270 tf_tcam_tbl_2_str(nparms.type),
1278 "%s: TCAM shared clear pool(%s)\n",
1279 tf_dir_2_str(nparms.dir),