1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2020 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 *tcam_db[TF_DIR_MAX];
29 static void *shadow_tcam_db[TF_DIR_MAX];
32 * Init flag, set on bind and cleared on unbind
37 * Shadow init flag, set on bind and cleared on unbind
39 static uint8_t shadow_init;
42 tf_tcam_bind(struct tf *tfp,
43 struct tf_tcam_cfg_parms *parms)
47 struct tf_rm_alloc_info info;
48 struct tf_rm_free_db_parms fparms;
49 struct tf_rm_create_db_parms db_cfg;
50 struct tf_tcam_resources *tcam_cnt;
51 struct tf_shadow_tcam_free_db_parms fshadow;
52 struct tf_rm_get_alloc_info_parms ainfo;
53 struct tf_shadow_tcam_cfg_parms shadow_cfg;
54 struct tf_shadow_tcam_create_db_parms shadow_cdb;
56 TF_CHECK_PARMS2(tfp, parms);
60 "TCAM DB already initialized\n");
64 tcam_cnt = parms->resources->tcam_cnt;
65 if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % 2) ||
66 (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % 2)) {
68 "Number of WC TCAM entries cannot be odd num\n");
72 memset(&db_cfg, 0, sizeof(db_cfg));
74 db_cfg.type = TF_DEVICE_MODULE_TYPE_TCAM;
75 db_cfg.num_elements = parms->num_elements;
76 db_cfg.cfg = parms->cfg;
78 for (d = 0; d < TF_DIR_MAX; d++) {
80 db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt;
81 db_cfg.rm_db = &tcam_db[d];
82 rc = tf_rm_create_db(tfp, &db_cfg);
85 "%s: TCAM DB creation failed\n",
91 /* Initialize the TCAM manager. */
92 if (parms->shadow_copy) {
93 for (d = 0; d < TF_DIR_MAX; d++) {
94 memset(&shadow_cfg, 0, sizeof(shadow_cfg));
95 memset(&shadow_cdb, 0, sizeof(shadow_cdb));
96 /* Get the base addresses of the tcams for tcam mgr */
97 for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) {
98 memset(&info, 0, sizeof(info));
100 if (!parms->resources->tcam_cnt[d].cnt[i])
102 ainfo.rm_db = tcam_db[d];
105 rc = tf_rm_get_info(&ainfo);
109 shadow_cfg.base_addr[i] = info.entry.start;
112 /* Create the shadow db */
113 shadow_cfg.alloc_cnt =
114 parms->resources->tcam_cnt[d].cnt;
115 shadow_cfg.num_entries = parms->num_elements;
117 shadow_cdb.shadow_db = &shadow_tcam_db[d];
118 shadow_cdb.cfg = &shadow_cfg;
119 rc = tf_shadow_tcam_create_db(&shadow_cdb);
122 "TCAM MGR DB creation failed "
133 "TCAM - initialized\n");
137 for (i = 0; i < TF_DIR_MAX; i++) {
138 memset(&fparms, 0, sizeof(fparms));
140 fparms.rm_db = tcam_db[i];
141 /* Ignoring return here since we are in the error case */
142 (void)tf_rm_free_db(tfp, &fparms);
144 if (parms->shadow_copy) {
145 fshadow.shadow_db = shadow_tcam_db[i];
146 tf_shadow_tcam_free_db(&fshadow);
147 shadow_tcam_db[i] = NULL;
160 tf_tcam_unbind(struct tf *tfp)
164 struct tf_rm_free_db_parms fparms;
165 struct tf_shadow_tcam_free_db_parms fshadow;
167 TF_CHECK_PARMS1(tfp);
169 /* Bail if nothing has been initialized */
172 "No TCAM DBs created\n");
176 for (i = 0; i < TF_DIR_MAX; i++) {
177 memset(&fparms, 0, sizeof(fparms));
179 fparms.rm_db = tcam_db[i];
180 rc = tf_rm_free_db(tfp, &fparms);
187 memset(&fshadow, 0, sizeof(fshadow));
189 fshadow.shadow_db = shadow_tcam_db[i];
190 tf_shadow_tcam_free_db(&fshadow);
191 shadow_tcam_db[i] = NULL;
202 tf_tcam_alloc(struct tf *tfp,
203 struct tf_tcam_alloc_parms *parms)
206 struct tf_session *tfs;
207 struct tf_dev_info *dev;
208 struct tf_rm_allocate_parms aparms;
209 uint16_t num_slice_per_row = 1;
211 TF_CHECK_PARMS2(tfp, parms);
215 "%s: No TCAM DBs created\n",
216 tf_dir_2_str(parms->dir));
220 /* Retrieve the session information */
221 rc = tf_session_get_session_internal(tfp, &tfs);
225 /* Retrieve the device information */
226 rc = tf_session_get_device(tfs, &dev);
230 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
233 "%s: Operation not supported, rc:%s\n",
234 tf_dir_2_str(parms->dir),
239 /* Need to retrieve row size etc */
240 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
247 /* Allocate requested element */
248 memset(&aparms, 0, sizeof(aparms));
250 aparms.rm_db = tcam_db[parms->dir];
251 aparms.db_index = parms->type;
252 aparms.priority = parms->priority;
253 aparms.index = (uint32_t *)&parms->idx;
254 rc = tf_rm_allocate(&aparms);
257 "%s: Failed tcam, type:%d\n",
258 tf_dir_2_str(parms->dir),
263 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM &&
264 (parms->idx % 2) != 0) {
265 rc = tf_rm_allocate(&aparms);
268 "%s: Failed tcam, type:%d\n",
269 tf_dir_2_str(parms->dir),
275 parms->idx *= num_slice_per_row;
281 tf_tcam_free(struct tf *tfp,
282 struct tf_tcam_free_parms *parms)
285 struct tf_session *tfs;
286 struct tf_dev_info *dev;
287 struct tf_rm_is_allocated_parms aparms;
288 struct tf_rm_free_parms fparms;
289 struct tf_rm_get_hcapi_parms hparms;
290 uint16_t num_slice_per_row = 1;
292 struct tf_shadow_tcam_remove_parms shparms;
294 TF_CHECK_PARMS2(tfp, parms);
298 "%s: No TCAM DBs created\n",
299 tf_dir_2_str(parms->dir));
303 /* Retrieve the session information */
304 rc = tf_session_get_session_internal(tfp, &tfs);
308 /* Retrieve the device information */
309 rc = tf_session_get_device(tfs, &dev);
313 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
316 "%s: Operation not supported, rc:%s\n",
317 tf_dir_2_str(parms->dir),
322 /* Need to retrieve row size etc */
323 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
330 /* Check if element is in use */
331 memset(&aparms, 0, sizeof(aparms));
333 aparms.rm_db = tcam_db[parms->dir];
334 aparms.db_index = parms->type;
335 aparms.index = parms->idx / num_slice_per_row;
336 aparms.allocated = &allocated;
337 rc = tf_rm_is_allocated(&aparms);
341 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
343 "%s: Entry already free, type:%d, index:%d\n",
344 tf_dir_2_str(parms->dir),
351 * The Shadow mgmt, if enabled, determines if the entry needs
355 shparms.shadow_db = shadow_tcam_db[parms->dir];
356 shparms.fparms = parms;
357 rc = tf_shadow_tcam_remove(&shparms);
360 * Should not get here, log it and let the entry be
363 TFP_DRV_LOG(ERR, "%s: Shadow free fail, "
364 "type:%d index:%d deleting the entry.\n",
365 tf_dir_2_str(parms->dir),
370 * If the entry still has references, just return the
371 * ref count to the caller. No need to remove entry
374 if (parms->ref_cnt >= 1)
379 /* Free requested element */
380 memset(&fparms, 0, sizeof(fparms));
381 fparms.rm_db = tcam_db[parms->dir];
382 fparms.db_index = parms->type;
383 fparms.index = parms->idx / num_slice_per_row;
384 rc = tf_rm_free(&fparms);
387 "%s: Free failed, type:%d, index:%d\n",
388 tf_dir_2_str(parms->dir),
394 if (parms->type == TF_TCAM_TBL_TYPE_WC_TCAM) {
397 for (i = -1; i < 3; i += 3) {
399 rc = tf_rm_is_allocated(&aparms);
403 if (allocated == TF_RM_ALLOCATED_ENTRY_IN_USE) {
404 /* Free requested element */
405 fparms.index = aparms.index;
406 rc = tf_rm_free(&fparms);
409 "%s: Free failed, type:%d, "
411 tf_dir_2_str(parms->dir),
420 /* Convert TF type to HCAPI RM type */
421 memset(&hparms, 0, sizeof(hparms));
423 hparms.rm_db = tcam_db[parms->dir];
424 hparms.db_index = parms->type;
425 hparms.hcapi_type = &parms->hcapi_type;
427 rc = tf_rm_get_hcapi_type(&hparms);
431 rc = tf_msg_tcam_entry_free(tfp, parms);
435 "%s: %s: Entry %d free failed, rc:%s\n",
436 tf_dir_2_str(parms->dir),
437 tf_tcam_tbl_2_str(parms->type),
447 tf_tcam_alloc_search(struct tf *tfp,
448 struct tf_tcam_alloc_search_parms *parms)
450 struct tf_shadow_tcam_search_parms sparms;
451 struct tf_shadow_tcam_bind_index_parms bparms;
452 struct tf_tcam_alloc_parms aparms;
453 struct tf_tcam_free_parms fparms;
454 uint16_t num_slice_per_row = 1;
455 struct tf_session *tfs;
456 struct tf_dev_info *dev;
459 TF_CHECK_PARMS2(tfp, parms);
463 "%s: No TCAM DBs created\n",
464 tf_dir_2_str(parms->dir));
468 if (!shadow_init || !shadow_tcam_db[parms->dir]) {
469 TFP_DRV_LOG(ERR, "%s: TCAM Shadow not initialized for %s\n",
470 tf_dir_2_str(parms->dir),
471 tf_tcam_tbl_2_str(parms->type));
475 /* Retrieve the session information */
476 rc = tf_session_get_session_internal(tfp, &tfs);
480 /* Retrieve the device information */
481 rc = tf_session_get_device(tfs, &dev);
485 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
488 "%s: Operation not supported, rc:%s\n",
489 tf_dir_2_str(parms->dir),
494 /* Need to retrieve row size etc */
495 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
503 * Prep the shadow search, reusing the parms from original search
504 * instead of copying them. Shadow will update output in there.
506 memset(&sparms, 0, sizeof(sparms));
507 sparms.sparms = parms;
508 sparms.shadow_db = shadow_tcam_db[parms->dir];
510 rc = tf_shadow_tcam_search(&sparms);
515 * The app didn't request us to alloc the entry, so return now.
516 * The hit should have been updated in the original search parm.
518 if (!parms->alloc || parms->search_status != MISS)
521 /* Caller desires an allocate on miss */
522 if (dev->ops->tf_dev_alloc_tcam == NULL) {
525 "%s: Operation not supported, rc:%s\n",
526 tf_dir_2_str(parms->dir),
530 memset(&aparms, 0, sizeof(aparms));
531 aparms.dir = parms->dir;
532 aparms.type = parms->type;
533 aparms.key_size = parms->key_size;
534 aparms.priority = parms->priority;
535 rc = dev->ops->tf_dev_alloc_tcam(tfp, &aparms);
539 /* Successful allocation, attempt to add it to the shadow */
540 memset(&bparms, 0, sizeof(bparms));
541 bparms.dir = parms->dir;
542 bparms.shadow_db = shadow_tcam_db[parms->dir];
543 bparms.type = parms->type;
544 bparms.key = parms->key;
545 bparms.mask = parms->mask;
546 bparms.key_size = parms->key_size;
547 bparms.idx = aparms.idx;
548 bparms.hb_handle = sparms.hb_handle;
549 rc = tf_shadow_tcam_bind_index(&bparms);
551 /* Error binding entry, need to free the allocated idx */
552 if (dev->ops->tf_dev_free_tcam == NULL) {
555 "%s: Operation not supported, rc:%s\n",
556 tf_dir_2_str(parms->dir),
561 fparms.dir = parms->dir;
562 fparms.type = parms->type;
563 fparms.idx = aparms.idx;
564 rc = dev->ops->tf_dev_free_tcam(tfp, &fparms);
569 /* Add the allocated index to output and done */
570 parms->idx = aparms.idx;
576 tf_tcam_set(struct tf *tfp __rte_unused,
577 struct tf_tcam_set_parms *parms __rte_unused)
580 struct tf_session *tfs;
581 struct tf_dev_info *dev;
582 struct tf_rm_is_allocated_parms aparms;
583 struct tf_rm_get_hcapi_parms hparms;
584 struct tf_shadow_tcam_insert_parms iparms;
585 uint16_t num_slice_per_row = 1;
588 TF_CHECK_PARMS2(tfp, parms);
592 "%s: No TCAM DBs created\n",
593 tf_dir_2_str(parms->dir));
597 /* Retrieve the session information */
598 rc = tf_session_get_session_internal(tfp, &tfs);
602 /* Retrieve the device information */
603 rc = tf_session_get_device(tfs, &dev);
607 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) {
610 "%s: Operation not supported, rc:%s\n",
611 tf_dir_2_str(parms->dir),
616 /* Need to retrieve row size etc */
617 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp,
624 /* Check if element is in use */
625 memset(&aparms, 0, sizeof(aparms));
627 aparms.rm_db = tcam_db[parms->dir];
628 aparms.db_index = parms->type;
629 aparms.index = parms->idx / num_slice_per_row;
630 aparms.allocated = &allocated;
631 rc = tf_rm_is_allocated(&aparms);
635 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
637 "%s: Entry is not allocated, type:%d, index:%d\n",
638 tf_dir_2_str(parms->dir),
644 /* Convert TF type to HCAPI RM type */
645 memset(&hparms, 0, sizeof(hparms));
647 hparms.rm_db = tcam_db[parms->dir];
648 hparms.db_index = parms->type;
649 hparms.hcapi_type = &parms->hcapi_type;
651 rc = tf_rm_get_hcapi_type(&hparms);
655 rc = tf_msg_tcam_entry_set(tfp, parms);
659 "%s: %s: Entry %d set failed, rc:%s",
660 tf_dir_2_str(parms->dir),
661 tf_tcam_tbl_2_str(parms->type),
667 /* Successfully added to hw, now for shadow if enabled. */
668 if (!shadow_init || !shadow_tcam_db[parms->dir])
671 iparms.shadow_db = shadow_tcam_db[parms->dir];
672 iparms.sparms = parms;
673 rc = tf_shadow_tcam_insert(&iparms);
676 "%s: %s: Entry %d set failed, rc:%s",
677 tf_dir_2_str(parms->dir),
678 tf_tcam_tbl_2_str(parms->type),
688 tf_tcam_get(struct tf *tfp __rte_unused,
689 struct tf_tcam_get_parms *parms __rte_unused)