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 struct tf_tcam_shared_wc_pools {
56 struct tf_tcam_shared_wc_pool db[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX];
59 /** The WC TCAM shared pool declarations
61 /* struct tf_tcam_shared_wc_pool tcam_shared_wc[TF_DIR_MAX][TF_TCAM_SHARED_WC_POOL_MAX]; */
64 tf_tcam_shared_create_db(struct tf_tcam_shared_wc_pools **db)
66 struct tfp_calloc_parms cparms;
71 cparms.size = sizeof(struct tf_tcam_shared_wc_pools);
72 rc = tfp_calloc(&cparms);
75 "TCAM shared db allocation failed (%s)\n",
84 /** Create a WC TCAM shared pool
87 tf_tcam_shared_create_wc_pool(int dir,
88 enum tf_tcam_shared_wc_pool_id id,
91 struct tf_tcam_shared_wc_pools *tcam_shared_wc)
95 struct tfp_calloc_parms cparms;
99 pool_size = (BITALLOC_SIZEOF(stride) / sizeof(struct bitalloc));
100 cparms.nitems = pool_size;
101 cparms.alignment = 0;
102 cparms.size = sizeof(struct bitalloc);
103 rc = tfp_calloc(&cparms);
106 "%s: pool memory alloc failed %s:%s\n",
107 tf_dir_2_str(dir), tf_pool_2_str(id),
111 tcam_shared_wc->db[dir][id].pool = (struct bitalloc *)cparms.mem_va;
113 rc = ba_init(tcam_shared_wc->db[dir][id].pool,
119 "%s: pool bitalloc failed %s\n",
120 tf_dir_2_str(dir), tf_pool_2_str(id));
124 tcam_shared_wc->db[dir][id].info.start = start;
125 tcam_shared_wc->db[dir][id].info.stride = stride;
129 /** Free a WC TCAM shared pool
132 tf_tcam_shared_free_wc_pool(int dir,
133 enum tf_tcam_shared_wc_pool_id id,
134 struct tf_tcam_shared_wc_pools *tcam_shared_wc)
137 TF_CHECK_PARMS1(tcam_shared_wc);
139 tcam_shared_wc->db[dir][id].info.start = 0;
140 tcam_shared_wc->db[dir][id].info.stride = 0;
142 if (tcam_shared_wc->db[dir][id].pool)
143 tfp_free((void *)tcam_shared_wc->db[dir][id].pool);
147 /** Get the number of WC TCAM slices allocated during 1 allocation/free
150 tf_tcam_shared_get_slices(struct tf *tfp,
151 struct tf_dev_info *dev,
152 uint16_t *num_slices)
156 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
159 "Operation not supported, rc:%s\n", strerror(-rc));
162 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
163 TF_TCAM_TBL_TYPE_WC_TCAM,
170 tf_tcam_db_valid(struct tf *tfp,
173 struct tcam_rm_db *tcam_db;
174 void *tcam_db_ptr = NULL;
177 TF_CHECK_PARMS1(tfp);
179 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
183 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
185 if (tcam_db->tcam_db[dir])
192 tf_tcam_shared_get_rm_info(struct tf *tfp,
194 uint16_t *hcapi_type,
195 struct tf_rm_alloc_info *info)
198 struct tcam_rm_db *tcam_db;
199 void *tcam_db_ptr = NULL;
200 struct tf_rm_get_alloc_info_parms ainfo;
201 struct tf_rm_get_hcapi_parms hparms;
203 TF_CHECK_PARMS3(tfp, hcapi_type, info);
205 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
208 "Tcam_db is not initialized, rc:%s\n",
212 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
214 /* Convert TF type to HCAPI RM type */
215 memset(&hparms, 0, sizeof(hparms));
216 hparms.rm_db = tcam_db->tcam_db[dir];
217 hparms.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
218 hparms.hcapi_type = hcapi_type;
220 rc = tf_rm_get_hcapi_type(&hparms);
223 "%s: Get RM hcapi type failed %s\n",
229 memset(info, 0, sizeof(struct tf_rm_alloc_info));
230 ainfo.rm_db = tcam_db->tcam_db[dir];
231 ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
234 rc = tf_rm_get_info(&ainfo);
237 "%s: TCAM rm info get failed %s\n",
246 * tf_tcam_shared_bind
249 tf_tcam_shared_bind(struct tf *tfp,
250 struct tf_tcam_cfg_parms *parms)
253 struct tf_session *tfs;
254 struct tf_dev_info *dev;
255 struct tf_rm_alloc_info info;
256 uint16_t start, stride;
259 struct tf_tcam_shared_wc_pools *tcam_shared_wc = NULL;
261 TF_CHECK_PARMS2(tfp, parms);
263 /* Perform normal bind
265 rc = tf_tcam_bind(tfp, parms);
269 /* After the normal TCAM bind, if this is a shared session
270 * create all required databases for the WC_HI and WC_LO pools
272 rc = tf_session_get_session_internal(tfp, &tfs);
275 "Session access failure: %s\n", strerror(-rc));
278 if (tf_session_is_shared_session(tfs)) {
279 /* Retrieve the device information */
280 rc = tf_session_get_device(tfs, &dev);
284 rc = tf_tcam_shared_get_slices(tfp,
290 tf_tcam_shared_create_db(&tcam_shared_wc);
293 /* If there are WC TCAM entries, create 2 pools each with 1/2
294 * the total number of entries
296 for (dir = 0; dir < TF_DIR_MAX; dir++) {
297 if (!tf_tcam_db_valid(tfp, dir))
300 rc = tf_tcam_shared_get_rm_info(tfp,
306 "%s: TCAM rm info get failed\n",
311 start = info.entry.start;
312 stride = info.entry.stride / 2;
314 tf_tcam_shared_create_wc_pool(dir,
315 TF_TCAM_SHARED_WC_POOL_HI,
321 tf_tcam_shared_create_wc_pool(dir,
322 TF_TCAM_SHARED_WC_POOL_LO,
327 tf_session_set_tcam_shared_db(tfp, (void *)tcam_shared_wc);
334 * tf_tcam_shared_unbind
337 tf_tcam_shared_unbind(struct tf *tfp)
340 struct tf_session *tfs;
341 void *tcam_shared_db_ptr = NULL;
342 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
344 TF_CHECK_PARMS1(tfp);
346 /* Perform normal unbind, this will write all the
347 * allocated TCAM entries in the shared session.
349 rc = tf_tcam_unbind(tfp);
353 /* Retrieve the session information */
354 rc = tf_session_get_session_internal(tfp, &tfs);
358 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
361 "Failed to get tcam_shared_db from session, rc:%s\n",
365 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
367 /* If we are the shared session
369 if (tf_session_is_shared_session(tfs)) {
370 /* If there are WC TCAM entries allocated, free them
372 for (dir = 0; dir < TF_DIR_MAX; dir++) {
373 tf_tcam_shared_free_wc_pool(dir,
374 TF_TCAM_SHARED_WC_POOL_HI,
376 tf_tcam_shared_free_wc_pool(dir,
377 TF_TCAM_SHARED_WC_POOL_LO,
384 * tf_tcam_shared_alloc
387 tf_tcam_shared_alloc(struct tf *tfp,
388 struct tf_tcam_alloc_parms *parms)
391 struct tf_session *tfs;
392 struct tf_dev_info *dev;
394 struct bitalloc *pool;
395 enum tf_tcam_shared_wc_pool_id id;
397 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
398 void *tcam_shared_db_ptr = NULL;
400 TF_CHECK_PARMS2(tfp, parms);
402 /* Retrieve the session information */
403 rc = tf_session_get_session_internal(tfp, &tfs);
407 /* If we aren't the shared session or the type is
408 * not one of the special WC TCAM types, call the normal
411 if (!tf_session_is_shared_session(tfs) ||
412 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
413 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
414 /* Perform normal alloc
416 rc = tf_tcam_alloc(tfp, parms);
420 if (!tf_tcam_db_valid(tfp, parms->dir)) {
422 "%s: tcam shared pool doesn't exist\n",
423 tf_dir_2_str(parms->dir));
427 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
430 "Failed to get tcam_shared_db from session, rc:%s\n",
434 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
436 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
437 id = TF_TCAM_SHARED_WC_POOL_HI;
439 id = TF_TCAM_SHARED_WC_POOL_LO;
441 /* Retrieve the device information */
442 rc = tf_session_get_device(tfs, &dev);
446 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
450 pool = tcam_shared_wc->db[parms->dir][id].pool;
452 for (i = 0; i < num_slices; i++) {
454 * priority 0: allocate from top of the tcam i.e. high
455 * priority !0: allocate index from bottom i.e lowest
458 log_idx = ba_alloc_reverse(pool);
460 log_idx = ba_alloc(pool);
461 if (log_idx == BA_FAIL) {
463 "%s: Allocation failed, rc:%s\n",
464 tf_dir_2_str(parms->dir),
468 /* return the index without the start of each row */
470 parms->idx = log_idx;
476 tf_tcam_shared_free(struct tf *tfp,
477 struct tf_tcam_free_parms *parms)
480 struct tf_session *tfs;
481 struct tf_dev_info *dev;
486 struct bitalloc *pool;
487 enum tf_tcam_shared_wc_pool_id id;
488 struct tf_tcam_free_parms nparms;
491 struct tf_rm_alloc_info info;
492 void *tcam_shared_db_ptr = NULL;
493 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
495 TF_CHECK_PARMS2(tfp, parms);
497 /* Retrieve the session information */
498 rc = tf_session_get_session_internal(tfp, &tfs);
502 /* If we aren't the shared session or the type is
503 * not one of the special WC TCAM types, call the normal
506 if (!tf_session_is_shared_session(tfs) ||
507 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
508 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
509 /* Perform normal free
511 rc = tf_tcam_free(tfp, parms);
515 if (!tf_tcam_db_valid(tfp, parms->dir)) {
517 "%s: tcam shared pool doesn't exist\n",
518 tf_dir_2_str(parms->dir));
522 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
525 "Failed to get tcam_shared_db from session, rc:%s\n",
529 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
532 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
533 id = TF_TCAM_SHARED_WC_POOL_HI;
535 id = TF_TCAM_SHARED_WC_POOL_LO;
537 /* Retrieve the device information */
538 rc = tf_session_get_device(tfs, &dev);
542 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
546 rc = tf_tcam_shared_get_rm_info(tfp,
552 "%s: TCAM rm info get failed\n",
553 tf_dir_2_str(parms->dir));
557 pool = tcam_shared_wc->db[parms->dir][id].pool;
558 start = tcam_shared_wc->db[parms->dir][id].info.start;
560 if (parms->idx % num_slices) {
562 "%s: TCAM reserved resource is not multiple of %d\n",
563 tf_dir_2_str(parms->dir), num_slices);
567 phy_idx = parms->idx + start;
568 allocated = ba_inuse(pool, parms->idx);
570 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
572 "%s: Entry already free, type:%d, idx:%d\n",
573 tf_dir_2_str(parms->dir), parms->type, parms->idx);
577 for (i = 0; i < num_slices; i++) {
578 rc = ba_free(pool, parms->idx + i);
581 "%s: Free failed, type:%s, idx:%d\n",
582 tf_dir_2_str(parms->dir),
583 tf_tcam_tbl_2_str(parms->type),
589 /* Override HI/LO type with parent WC TCAM type */
591 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
592 nparms.hcapi_type = hcapi_type;
593 nparms.idx = phy_idx;
595 rc = tf_msg_tcam_entry_free(tfp, dev, &nparms);
599 "%s: %s: log%d free failed, rc:%s\n",
600 tf_dir_2_str(nparms.dir),
601 tf_tcam_tbl_2_str(nparms.type),
610 tf_tcam_shared_set(struct tf *tfp __rte_unused,
611 struct tf_tcam_set_parms *parms __rte_unused)
614 struct tf_session *tfs;
615 struct tf_dev_info *dev;
617 int phy_idx, log_idx;
619 struct tf_tcam_set_parms nparms;
620 struct bitalloc *pool;
622 enum tf_tcam_shared_wc_pool_id id;
624 struct tf_rm_alloc_info info;
625 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
626 void *tcam_shared_db_ptr = NULL;
629 TF_CHECK_PARMS2(tfp, parms);
631 /* Retrieve the session information */
632 rc = tf_session_get_session_internal(tfp, &tfs);
636 /* If we aren't the shared session or one of our
639 if (!tf_session_is_shared_session(tfs) ||
640 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
641 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
642 /* Perform normal set and exit
644 rc = tf_tcam_set(tfp, parms);
648 if (!tf_tcam_db_valid(tfp, parms->dir)) {
650 "%s: tcam shared pool doesn't exist\n",
651 tf_dir_2_str(parms->dir));
655 /* Retrieve the device information */
656 rc = tf_session_get_device(tfs, &dev);
660 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
661 id = TF_TCAM_SHARED_WC_POOL_HI;
663 id = TF_TCAM_SHARED_WC_POOL_LO;
665 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
668 "Failed to get tcam_shared_db from session, rc:%s\n",
672 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
674 pool = tcam_shared_wc->db[parms->dir][id].pool;
675 start = tcam_shared_wc->db[parms->dir][id].info.start;
677 log_idx = parms->idx;
678 phy_idx = parms->idx + start;
679 allocated = ba_inuse(pool, parms->idx);
681 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
683 "%s: Entry is not allocated, type:%d, logid:%d\n",
684 tf_dir_2_str(parms->dir), parms->type, log_idx);
687 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
691 if (parms->idx % num_slices) {
693 "%s: TCAM reserved resource is not multiple of %d\n",
694 tf_dir_2_str(parms->dir), num_slices);
697 rc = tf_tcam_shared_get_rm_info(tfp,
704 /* Override HI/LO type with parent WC TCAM type */
705 nparms.hcapi_type = hcapi_type;
706 nparms.dir = parms->dir;
707 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
708 nparms.idx = phy_idx;
709 nparms.key = parms->key;
710 nparms.mask = parms->mask;
711 nparms.key_size = parms->key_size;
712 nparms.result = parms->result;
713 nparms.result_size = parms->result_size;
715 rc = tf_msg_tcam_entry_set(tfp, dev, &nparms);
719 "%s: %s: phy entry %d set failed, rc:%s",
720 tf_dir_2_str(parms->dir),
721 tf_tcam_tbl_2_str(nparms.type),
730 tf_tcam_shared_get(struct tf *tfp __rte_unused,
731 struct tf_tcam_get_parms *parms)
734 struct tf_session *tfs;
735 struct tf_dev_info *dev;
737 int phy_idx, log_idx;
739 struct tf_tcam_get_parms nparms;
740 struct bitalloc *pool;
742 enum tf_tcam_shared_wc_pool_id id;
744 struct tf_rm_alloc_info info;
745 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
746 void *tcam_shared_db_ptr = NULL;
748 TF_CHECK_PARMS2(tfp, parms);
750 /* Retrieve the session information */
751 rc = tf_session_get_session_internal(tfp, &tfs);
755 /* If we aren't the shared session or one of our
758 if (!tf_session_is_shared_session(tfs) ||
759 (parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
760 parms->type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
761 /* Perform normal get and exit
763 rc = tf_tcam_get(tfp, parms);
767 if (!tf_tcam_db_valid(tfp, parms->dir)) {
769 "%s: tcam shared pool doesn't exist\n",
770 tf_dir_2_str(parms->dir));
774 /* Retrieve the device information */
775 rc = tf_session_get_device(tfs, &dev);
778 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH)
779 id = TF_TCAM_SHARED_WC_POOL_HI;
781 id = TF_TCAM_SHARED_WC_POOL_LO;
784 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
787 "Failed to get tcam_shared_db from session, rc:%s\n",
791 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
793 pool = tcam_shared_wc->db[parms->dir][id].pool;
794 start = tcam_shared_wc->db[parms->dir][id].info.start;
796 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
800 if (parms->idx % num_slices) {
802 "%s: TCAM reserved resource is not multiple of %d\n",
803 tf_dir_2_str(parms->dir), num_slices);
806 log_idx = parms->idx;
807 phy_idx = parms->idx + start;
808 allocated = ba_inuse(pool, parms->idx);
810 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
812 "%s: Entry is not allocated, type:%d, logid:%d\n",
813 tf_dir_2_str(parms->dir), parms->type, log_idx);
817 rc = tf_tcam_shared_get_rm_info(tfp,
824 /* Override HI/LO type with parent WC TCAM type */
826 nparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
827 nparms.hcapi_type = hcapi_type;
828 nparms.idx = phy_idx;
830 rc = tf_msg_tcam_entry_get(tfp, dev, &nparms);
834 "%s: %s: Entry %d set failed, rc:%s",
835 tf_dir_2_str(nparms.dir),
836 tf_tcam_tbl_2_str(nparms.type),
844 /* Temporary builder defines pulled in here and renamed
846 #define TF_TMP_MAX_FIELD_BITLEN 512
848 union tf_tmp_field_obj {
849 uint8_t bytes[(TF_TMP_MAX_FIELD_BITLEN + 7) / 8];
852 #define TF_TMP_MAX_KEY_BITLEN 768
853 #define TF_TMP_MAX_KEY_WORDLEN ((TF_TMP_MAX_KEY_BITLEN + 63) / 64)
856 uint32_t words[(TF_TMP_MAX_KEY_BITLEN + 31) / 32];
857 uint8_t bytes[(TF_TMP_MAX_KEY_BITLEN + 7) / 8];
860 /** Move a WC TCAM entry from the high offset to the same low offset
863 tf_tcam_shared_move_entry(struct tf *tfp,
864 struct tf_dev_info *dev,
874 struct tf_tcam_get_parms gparms;
875 struct tf_tcam_set_parms sparms;
876 struct tf_tcam_free_parms fparms;
877 union tf_tmp_key tcam_key_obj;
878 union tf_tmp_key tcam_key_msk_obj;
879 union tf_tmp_field_obj tcam_remap_obj;
881 memset(&tcam_key_obj, 0, sizeof(tcam_key_obj));
882 memset(&tcam_key_msk_obj, 0, sizeof(tcam_key_msk_obj));
883 memset(&tcam_remap_obj, 0, sizeof(tcam_remap_obj));
884 memset(&gparms, 0, sizeof(gparms));
886 if (num_slices > 1) {
888 "Only single slice supported");
892 gparms.hcapi_type = hcapi_type;
894 gparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
895 gparms.idx = sphy_idx;
896 gparms.key = (uint8_t *)&tcam_key_obj;
897 gparms.key_size = key_sz_bytes;
898 gparms.mask = (uint8_t *)&tcam_key_msk_obj;
899 gparms.result = (uint8_t *)&tcam_remap_obj;
900 gparms.result_size = remap_sz_bytes;
902 rc = tf_msg_tcam_entry_get(tfp, dev, &gparms);
906 "%s: WC_TCAM_HIGH: phyid(%d) get failed, rc:%s",
913 /* Override HI/LO type with parent WC TCAM type */
914 sparms.hcapi_type = hcapi_type;
916 sparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
917 sparms.idx = dphy_idx;
918 sparms.key = gparms.key;
919 sparms.mask = gparms.mask;
920 sparms.key_size = gparms.key_size;
921 sparms.result = gparms.result;
922 sparms.result_size = gparms.result_size;
924 rc = tf_msg_tcam_entry_set(tfp, dev, &sparms);
928 "%s: WC_TCAM_LOW phyid(%d) set failed, rc:%s",
935 /* Override HI/LO type with parent WC TCAM type */
937 fparms.type = TF_TCAM_TBL_TYPE_WC_TCAM;
938 fparms.hcapi_type = hcapi_type;
939 fparms.idx = sphy_idx;
941 rc = tf_msg_tcam_entry_free(tfp, dev, &fparms);
945 "%s: %s: phyid(%d) free failed, rc:%s\n",
947 tf_tcam_tbl_2_str(fparms.type),
955 /** Move all shared WC TCAM entries from the high pool into the low pool
956 * and clear out the high pool entries.
959 int tf_tcam_shared_move(struct tf *tfp,
960 struct tf_move_tcam_shared_entries_parms *parms,
965 struct tf_session *tfs;
966 struct tf_dev_info *dev;
969 struct bitalloc *hi_pool, *lo_pool;
970 uint16_t hi_start, lo_start;
971 enum tf_tcam_shared_wc_pool_id hi_id, lo_id;
973 struct tf_rm_alloc_info info;
975 struct tf_tcam_shared_wc_pools *tcam_shared_wc;
976 void *tcam_shared_db_ptr = NULL;
978 TF_CHECK_PARMS2(tfp, parms);
980 /* Retrieve the session information */
981 rc = tf_session_get_session_internal(tfp, &tfs);
985 /* If we aren't the shared session or one of our
988 if (!tf_session_is_shared_session(tfs) ||
989 (parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_HIGH &&
990 parms->tcam_tbl_type != TF_TCAM_TBL_TYPE_WC_TCAM_LOW)) {
992 "%s: Session must be shared with HI/LO type\n",
993 tf_dir_2_str(parms->dir));
997 if (!tf_tcam_db_valid(tfp, parms->dir)) {
999 "%s: tcam shared pool doesn't exist\n",
1000 tf_dir_2_str(parms->dir));
1004 /* Retrieve the device information */
1005 rc = tf_session_get_device(tfs, &dev);
1007 /* TODO print amazing error */
1010 rc = tf_tcam_shared_get_slices(tfp, dev, &num_slices);
1014 rc = tf_tcam_shared_get_rm_info(tfp,
1020 "%s: TCAM rm info get failed\n",
1021 tf_dir_2_str(parms->dir));
1025 rc = tf_session_get_tcam_shared_db(tfp, (void *)&tcam_shared_db_ptr);
1028 "Failed to get tcam_shared_db from session, rc:%s\n",
1032 tcam_shared_wc = (struct tf_tcam_shared_wc_pools *)tcam_shared_db_ptr;
1034 hi_id = TF_TCAM_SHARED_WC_POOL_HI;
1035 hi_pool = tcam_shared_wc->db[parms->dir][hi_id].pool;
1036 hi_start = tcam_shared_wc->db[parms->dir][hi_id].info.start;
1038 lo_id = TF_TCAM_SHARED_WC_POOL_LO;
1039 lo_pool = tcam_shared_wc->db[parms->dir][lo_id].pool;
1040 lo_start = tcam_shared_wc->db[parms->dir][lo_id].info.start;
1042 if (hi_pool == NULL || lo_pool == NULL)
1045 /* Get the total count of in use entries in the high pool
1047 hi_cnt = ba_inuse_count(hi_pool);
1049 /* Copy each valid entry to the same low pool logical offset
1051 for (i = 0; i < hi_cnt; i++) {
1052 /* Go through all the slices
1054 for (j = 0; j < num_slices; j++) {
1055 /* Find next free starting from where we left off
1057 log_idx = ba_find_next_inuse(hi_pool, i);
1061 "Expected a found %s entry %d\n",
1062 tf_pool_2_str(hi_id),
1066 /* The user should have never allocated from the low
1067 * pool because the move only happens when switching
1068 * from the high to the low pool
1070 if (ba_alloc_index(lo_pool, log_idx) < 0) {
1072 "Cannot allocate %s index %d\n",
1073 tf_pool_2_str(lo_id),
1079 rc = tf_tcam_shared_move_entry(tfp, dev,
1089 "Cannot allocate %s index %d\n",
1090 tf_pool_2_str(hi_id),
1094 ba_free(hi_pool, log_idx);
1096 "%s: TCAM shared move pool(%s) phyid(%d)\n",
1097 tf_dir_2_str(parms->dir),
1098 tf_pool_2_str(hi_id),
1099 hi_start + log_idx);
1101 "to pool(%s) phyid(%d)\n",
1102 tf_pool_2_str(lo_id),
1103 lo_start + log_idx);
1111 /* Normally, device specific code wouldn't reside here, it belongs
1112 * in a separate device specific function in tf_device_pxx.c.
1113 * But this code is placed here as it is not a long term solution
1114 * and we would like to have this code centrally located for easy
1117 #define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4 12
1118 #define TF_TCAM_SHARED_REMAP_SZ_BYTES_P4 4
1120 int tf_tcam_shared_move_p4(struct tf *tfp,
1121 struct tf_move_tcam_shared_entries_parms *parms)
1124 rc = tf_tcam_shared_move(tfp,
1126 TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P4,
1127 TF_TCAM_SHARED_REMAP_SZ_BYTES_P4);
1131 #define TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58 24
1132 #define TF_TCAM_SHARED_REMAP_SZ_BYTES_P58 8
1134 int tf_tcam_shared_move_p58(struct tf *tfp,
1135 struct tf_move_tcam_shared_entries_parms *parms)
1138 rc = tf_tcam_shared_move(tfp,
1140 TF_TCAM_SHARED_KEY_SLICE_SZ_BYTES_P58,
1141 TF_TCAM_SHARED_REMAP_SZ_BYTES_P58);