1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
7 #include <rte_common.h>
10 #include "tf_common.h"
13 #include "tf_device.h"
15 #include "tf_session.h"
17 #include "tf_shadow_tcam.h"
24 static void *shadow_tcam_db[TF_DIR_MAX];
27 * Init flag, set on bind and cleared on unbind
32 * Shadow init flag, set on bind and cleared on unbind
34 static uint8_t shadow_init;
37 tf_tcam_bind(struct tf *tfp,
38 struct tf_tcam_cfg_parms *parms)
42 struct tf_rm_alloc_info info;
43 struct tf_rm_free_db_parms fparms;
44 struct tf_rm_create_db_parms db_cfg;
45 struct tf_tcam_resources *tcam_cnt;
46 struct tf_rm_get_alloc_info_parms ainfo;
47 struct tf_shadow_tcam_free_db_parms fshadow;
48 struct tf_shadow_tcam_cfg_parms shadow_cfg;
49 struct tf_shadow_tcam_create_db_parms shadow_cdb;
50 uint16_t num_slices = 1;
51 struct tf_session *tfs;
52 struct tf_dev_info *dev;
53 struct tcam_rm_db *tcam_db;
54 struct tfp_calloc_parms cparms;
56 TF_CHECK_PARMS2(tfp, parms);
60 "TCAM DB already initialized\n");
64 /* Retrieve the session information */
65 rc = tf_session_get_session_internal(tfp, &tfs);
69 /* Retrieve the device information */
70 rc = tf_session_get_device(tfs, &dev);
74 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
77 "Operation not supported, rc:%s\n",
82 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
83 TF_TCAM_TBL_TYPE_WC_TCAM,
89 tcam_cnt = parms->resources->tcam_cnt;
90 if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices) ||
91 (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices)) {
93 "Requested num of WC TCAM entries has to be multiple %d\n",
98 memset(&db_cfg, 0, sizeof(db_cfg));
100 cparms.size = sizeof(struct tcam_rm_db);
101 cparms.alignment = 0;
102 if (tfp_calloc(&cparms) != 0) {
103 TFP_DRV_LOG(ERR, "tcam_rm_db alloc error %s\n",
108 tcam_db = cparms.mem_va;
109 for (i = 0; i < TF_DIR_MAX; i++)
110 tcam_db->tcam_db[i] = NULL;
111 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db);
113 db_cfg.module = TF_MODULE_TYPE_TCAM;
114 db_cfg.num_elements = parms->num_elements;
115 db_cfg.cfg = parms->cfg;
117 for (d = 0; d < TF_DIR_MAX; d++) {
119 db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt;
120 db_cfg.rm_db = (void *)&tcam_db->tcam_db[d];
121 rc = tf_rm_create_db(tfp, &db_cfg);
124 "%s: TCAM DB creation failed\n",
130 /* check if reserved resource for WC is multiple of num_slices */
131 for (d = 0; d < TF_DIR_MAX; d++) {
132 memset(&info, 0, sizeof(info));
133 ainfo.rm_db = tcam_db->tcam_db[d];
134 ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM;
136 rc = tf_rm_get_info(&ainfo);
140 if (info.entry.start % num_slices != 0 ||
141 info.entry.stride % num_slices != 0) {
143 "%s: TCAM reserved resource is not multiple of %d\n",
150 /* Initialize the TCAM manager. */
151 if (parms->shadow_copy) {
152 for (d = 0; d < TF_DIR_MAX; d++) {
153 memset(&shadow_cfg, 0, sizeof(shadow_cfg));
154 memset(&shadow_cdb, 0, sizeof(shadow_cdb));
155 /* Get the base addresses of the tcams for tcam mgr */
156 for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
157 memset(&info, 0, sizeof(info));
159 if (!parms->resources->tcam_cnt[d].cnt[i])
161 ainfo.rm_db = tcam_db->tcam_db[d];
164 rc = tf_rm_get_info(&ainfo);
168 shadow_cfg.base_addr[i] = info.entry.start;
171 /* Create the shadow db */
172 shadow_cfg.alloc_cnt =
173 parms->resources->tcam_cnt[d].cnt;
174 shadow_cfg.num_entries = parms->num_elements;
176 shadow_cdb.shadow_db = &shadow_tcam_db[d];
177 shadow_cdb.cfg = &shadow_cfg;
178 rc = tf_shadow_tcam_create_db(&shadow_cdb);
181 "TCAM MGR DB creation failed "
192 "TCAM - initialized\n");
196 for (i = 0; i < TF_DIR_MAX; i++) {
197 memset(&fparms, 0, sizeof(fparms));
199 fparms.rm_db = tcam_db->tcam_db[i];
200 /* Ignoring return here since we are in the error case */
201 (void)tf_rm_free_db(tfp, &fparms);
203 if (parms->shadow_copy) {
204 fshadow.shadow_db = shadow_tcam_db[i];
205 tf_shadow_tcam_free_db(&fshadow);
206 shadow_tcam_db[i] = NULL;
209 tcam_db->tcam_db[i] = NULL;
210 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL);
220 tf_tcam_unbind(struct tf *tfp)
224 struct tf_rm_free_db_parms fparms;
225 struct tcam_rm_db *tcam_db;
226 void *tcam_db_ptr = NULL;
227 struct tf_shadow_tcam_free_db_parms fshadow;
228 TF_CHECK_PARMS1(tfp);
230 /* Bail if nothing has been initialized */
233 "No TCAM DBs created\n");
237 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
240 "Failed to get em_ext_db from session, rc:%s\n",
244 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
246 for (i = 0; i < TF_DIR_MAX; i++) {
247 memset(&fparms, 0, sizeof(fparms));
249 fparms.rm_db = tcam_db->tcam_db[i];
250 rc = tf_rm_free_db(tfp, &fparms);
254 tcam_db->tcam_db[i] = NULL;
257 memset(&fshadow, 0, sizeof(fshadow));
259 fshadow.shadow_db = shadow_tcam_db[i];
260 tf_shadow_tcam_free_db(&fshadow);
261 shadow_tcam_db[i] = NULL;
272 tf_tcam_alloc(struct tf *tfp,
273 struct tf_tcam_alloc_parms *parms)
276 struct tf_session *tfs;
277 struct tf_dev_info *dev;
278 struct tf_rm_allocate_parms aparms;
279 uint16_t num_slices = 1;
281 struct tcam_rm_db *tcam_db;
282 void *tcam_db_ptr = NULL;
284 TF_CHECK_PARMS2(tfp, parms);
288 "%s: No TCAM DBs created\n",
289 tf_dir_2_str(parms->dir));
293 /* Retrieve the session information */
294 rc = tf_session_get_session_internal(tfp, &tfs);
298 /* Retrieve the device information */
299 rc = tf_session_get_device(tfs, &dev);
303 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
306 "%s: Operation not supported, rc:%s\n",
307 tf_dir_2_str(parms->dir),
312 /* Need to retrieve number of slices based on the key_size */
313 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
320 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
323 "Failed to get em_ext_db from session, rc:%s\n",
327 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
330 * For WC TCAM, number of slices could be 4, 2, 1 based on
331 * the key_size. For other TCAM, it is always 1
333 for (i = 0; i < num_slices; i++) {
334 memset(&aparms, 0, sizeof(aparms));
335 aparms.rm_db = tcam_db->tcam_db[parms->dir];
336 aparms.subtype = parms->type;
337 aparms.priority = parms->priority;
338 aparms.index = &index;
339 rc = tf_rm_allocate(&aparms);
342 "%s: Failed tcam, type:%d\n",
343 tf_dir_2_str(parms->dir),
348 /* return the start index of each row */
357 tf_tcam_free(struct tf *tfp,
358 struct tf_tcam_free_parms *parms)
361 struct tf_session *tfs;
362 struct tf_dev_info *dev;
363 struct tf_rm_is_allocated_parms aparms;
364 struct tf_rm_free_parms fparms;
365 struct tf_rm_get_hcapi_parms hparms;
366 uint16_t num_slices = 1;
368 struct tf_shadow_tcam_remove_parms shparms;
370 struct tcam_rm_db *tcam_db;
371 void *tcam_db_ptr = NULL;
373 TF_CHECK_PARMS2(tfp, parms);
377 "%s: No TCAM DBs created\n",
378 tf_dir_2_str(parms->dir));
382 /* Retrieve the session information */
383 rc = tf_session_get_session_internal(tfp, &tfs);
387 /* Retrieve the device information */
388 rc = tf_session_get_device(tfs, &dev);
392 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
395 "%s: Operation not supported, rc:%s\n",
396 tf_dir_2_str(parms->dir),
401 /* Need to retrieve row size etc */
402 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
409 if (parms->idx % num_slices) {
411 "%s: TCAM reserved resource is not multiple of %d\n",
412 tf_dir_2_str(parms->dir),
417 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
420 "Failed to get em_ext_db from session, rc:%s\n",
424 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
426 /* Check if element is in use */
427 memset(&aparms, 0, sizeof(aparms));
428 aparms.rm_db = tcam_db->tcam_db[parms->dir];
429 aparms.subtype = parms->type;
430 aparms.index = parms->idx;
431 aparms.allocated = &allocated;
432 rc = tf_rm_is_allocated(&aparms);
436 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
438 "%s: Entry already free, type:%d, index:%d\n",
439 tf_dir_2_str(parms->dir),
446 * The Shadow mgmt, if enabled, determines if the entry needs
450 shparms.shadow_db = shadow_tcam_db[parms->dir];
451 shparms.fparms = parms;
452 rc = tf_shadow_tcam_remove(&shparms);
455 * Should not get here, log it and let the entry be
458 TFP_DRV_LOG(ERR, "%s: Shadow free fail, "
459 "type:%d index:%d deleting the entry.\n",
460 tf_dir_2_str(parms->dir),
465 * If the entry still has references, just return the
466 * ref count to the caller. No need to remove entry
469 if (parms->ref_cnt >= 1)
474 for (i = 0; i < num_slices; i++) {
475 /* Free requested element */
476 memset(&fparms, 0, sizeof(fparms));
477 fparms.rm_db = tcam_db->tcam_db[parms->dir];
478 fparms.subtype = parms->type;
479 fparms.index = parms->idx + i;
480 rc = tf_rm_free(&fparms);
483 "%s: Free failed, type:%d, index:%d\n",
484 tf_dir_2_str(parms->dir),
491 /* Convert TF type to HCAPI RM type */
492 memset(&hparms, 0, sizeof(hparms));
494 hparms.rm_db = tcam_db->tcam_db[parms->dir];
495 hparms.subtype = parms->type;
496 hparms.hcapi_type = &parms->hcapi_type;
498 rc = tf_rm_get_hcapi_type(&hparms);
502 rc = tf_msg_tcam_entry_free(tfp, dev, parms);
506 "%s: %s: Entry %d free failed, rc:%s\n",
507 tf_dir_2_str(parms->dir),
508 tf_tcam_tbl_2_str(parms->type),
518 tf_tcam_alloc_search(struct tf *tfp,
519 struct tf_tcam_alloc_search_parms *parms)
521 struct tf_shadow_tcam_search_parms sparms;
522 struct tf_shadow_tcam_bind_index_parms bparms;
523 struct tf_tcam_free_parms fparms;
524 struct tf_tcam_alloc_parms aparms;
525 uint16_t num_slice_per_row = 1;
526 struct tf_session *tfs;
527 struct tf_dev_info *dev;
530 TF_CHECK_PARMS2(tfp, parms);
534 "%s: No TCAM DBs created\n",
535 tf_dir_2_str(parms->dir));
539 if (!shadow_init || !shadow_tcam_db[parms->dir]) {
540 TFP_DRV_LOG(ERR, "%s: TCAM Shadow not initialized for %s\n",
541 tf_dir_2_str(parms->dir),
542 tf_tcam_tbl_2_str(parms->type));
546 /* Retrieve the session information */
547 rc = tf_session_get_session_internal(tfp, &tfs);
551 /* Retrieve the device information */
552 rc = tf_session_get_device(tfs, &dev);
556 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
559 "%s: Operation not supported, rc:%s\n",
560 tf_dir_2_str(parms->dir),
565 /* Need to retrieve row size etc */
566 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
574 * Prep the shadow search, reusing the parms from original search
575 * instead of copying them. Shadow will update output in there.
577 memset(&sparms, 0, sizeof(sparms));
578 sparms.sparms = parms;
579 sparms.shadow_db = shadow_tcam_db[parms->dir];
581 rc = tf_shadow_tcam_search(&sparms);
586 * The app didn't request us to alloc the entry, so return now.
587 * The hit should have been updated in the original search parm.
589 if (!parms->alloc || parms->search_status != MISS)
592 /* Caller desires an allocate on miss */
593 if (dev->ops->tf_dev_alloc_tcam == NULL) {
596 "%s: Operation not supported, rc:%s\n",
597 tf_dir_2_str(parms->dir),
601 memset(&aparms, 0, sizeof(aparms));
602 aparms.dir = parms->dir;
603 aparms.type = parms->type;
604 aparms.key_size = parms->key_size;
605 aparms.priority = parms->priority;
606 rc = dev->ops->tf_dev_alloc_tcam(tfp, &aparms);
610 /* Successful allocation, attempt to add it to the shadow */
611 memset(&bparms, 0, sizeof(bparms));
612 bparms.dir = parms->dir;
613 bparms.shadow_db = shadow_tcam_db[parms->dir];
614 bparms.type = parms->type;
615 bparms.key = parms->key;
616 bparms.mask = parms->mask;
617 bparms.key_size = parms->key_size;
618 bparms.idx = aparms.idx;
619 bparms.hb_handle = sparms.hb_handle;
620 rc = tf_shadow_tcam_bind_index(&bparms);
622 /* Error binding entry, need to free the allocated idx */
623 if (dev->ops->tf_dev_free_tcam == NULL) {
626 "%s: Operation not supported, rc:%s\n",
627 tf_dir_2_str(parms->dir),
632 fparms.dir = parms->dir;
633 fparms.type = parms->type;
634 fparms.idx = aparms.idx;
635 rc = dev->ops->tf_dev_free_tcam(tfp, &fparms);
640 /* Add the allocated index to output and done */
641 parms->idx = aparms.idx;
647 tf_tcam_set(struct tf *tfp __rte_unused,
648 struct tf_tcam_set_parms *parms __rte_unused)
651 struct tf_session *tfs;
652 struct tf_dev_info *dev;
653 struct tf_rm_is_allocated_parms aparms;
654 struct tf_rm_get_hcapi_parms hparms;
655 struct tf_shadow_tcam_insert_parms iparms;
656 uint16_t num_slice_per_row = 1;
658 struct tcam_rm_db *tcam_db;
659 void *tcam_db_ptr = NULL;
661 TF_CHECK_PARMS2(tfp, parms);
665 "%s: No TCAM DBs created\n",
666 tf_dir_2_str(parms->dir));
670 /* Retrieve the session information */
671 rc = tf_session_get_session_internal(tfp, &tfs);
675 /* Retrieve the device information */
676 rc = tf_session_get_device(tfs, &dev);
680 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
683 "%s: Operation not supported, rc:%s\n",
684 tf_dir_2_str(parms->dir),
689 /* Need to retrieve row size etc */
690 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
697 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
700 "Failed to get em_ext_db from session, rc:%s\n",
704 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
706 /* Check if element is in use */
707 memset(&aparms, 0, sizeof(aparms));
709 aparms.rm_db = tcam_db->tcam_db[parms->dir];
710 aparms.subtype = parms->type;
711 aparms.index = parms->idx;
712 aparms.allocated = &allocated;
713 rc = tf_rm_is_allocated(&aparms);
717 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
719 "%s: Entry is not allocated, type:%d, index:%d\n",
720 tf_dir_2_str(parms->dir),
726 /* Convert TF type to HCAPI RM type */
727 memset(&hparms, 0, sizeof(hparms));
729 hparms.rm_db = tcam_db->tcam_db[parms->dir];
730 hparms.subtype = parms->type;
731 hparms.hcapi_type = &parms->hcapi_type;
733 rc = tf_rm_get_hcapi_type(&hparms);
737 rc = tf_msg_tcam_entry_set(tfp, dev, parms);
741 "%s: %s: Entry %d set failed, rc:%s",
742 tf_dir_2_str(parms->dir),
743 tf_tcam_tbl_2_str(parms->type),
749 /* Successfully added to hw, now for shadow if enabled. */
750 if (!shadow_init || !shadow_tcam_db[parms->dir])
753 iparms.shadow_db = shadow_tcam_db[parms->dir];
754 iparms.sparms = parms;
755 rc = tf_shadow_tcam_insert(&iparms);
758 "%s: %s: Entry %d set failed, rc:%s",
759 tf_dir_2_str(parms->dir),
760 tf_tcam_tbl_2_str(parms->type),
770 tf_tcam_get(struct tf *tfp __rte_unused,
771 struct tf_tcam_get_parms *parms)
774 struct tf_session *tfs;
775 struct tf_dev_info *dev;
776 struct tf_rm_is_allocated_parms aparms;
777 struct tf_rm_get_hcapi_parms hparms;
779 struct tcam_rm_db *tcam_db;
780 void *tcam_db_ptr = NULL;
782 TF_CHECK_PARMS2(tfp, parms);
786 "%s: No TCAM DBs created\n",
787 tf_dir_2_str(parms->dir));
791 /* Retrieve the session information */
792 rc = tf_session_get_session_internal(tfp, &tfs);
796 /* Retrieve the device information */
797 rc = tf_session_get_device(tfs, &dev);
801 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr);
804 "Failed to get em_ext_db from session, rc:%s\n",
808 tcam_db = (struct tcam_rm_db *)tcam_db_ptr;
810 /* Check if element is in use */
811 memset(&aparms, 0, sizeof(aparms));
813 aparms.rm_db = tcam_db->tcam_db[parms->dir];
814 aparms.subtype = parms->type;
815 aparms.index = parms->idx;
816 aparms.allocated = &allocated;
817 rc = tf_rm_is_allocated(&aparms);
821 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
823 "%s: Entry is not allocated, type:%d, index:%d\n",
824 tf_dir_2_str(parms->dir),
830 /* Convert TF type to HCAPI RM type */
831 memset(&hparms, 0, sizeof(hparms));
833 hparms.rm_db = tcam_db->tcam_db[parms->dir];
834 hparms.subtype = parms->type;
835 hparms.hcapi_type = &parms->hcapi_type;
837 rc = tf_rm_get_hcapi_type(&hparms);
841 rc = tf_msg_tcam_entry_get(tfp, dev, parms);
845 "%s: %s: Entry %d set failed, rc:%s",
846 tf_dir_2_str(parms->dir),
847 tf_tcam_tbl_2_str(parms->type),