1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019-2021 Broadcom
6 /* Truflow Table APIs and supporting code */
8 #include <rte_common.h>
11 #include "tf_common.h"
16 #include "tf_session.h"
17 #include "tf_device.h"
19 #define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) { \
20 *(new_idx) = (((idx) + (base)) << (shift)); \
23 #define TF_TBL_PTR_TO_RM(new_idx, idx, base, shift) { \
24 *(new_idx) = (((idx) >> (shift)) - (base)); \
30 * Shadow init flag, set on bind and cleared on unbind
32 static uint8_t shadow_init;
35 tf_tbl_bind(struct tf *tfp,
36 struct tf_tbl_cfg_parms *parms)
39 int db_rc[TF_DIR_MAX] = { 0 };
40 struct tf_rm_create_db_parms db_cfg = { 0 };
41 struct tbl_rm_db *tbl_db;
42 struct tfp_calloc_parms cparms;
43 struct tf_session *tfs;
45 TF_CHECK_PARMS2(tfp, parms);
47 /* Retrieve the session information */
48 rc = tf_session_get_session_internal(tfp, &tfs);
52 memset(&db_cfg, 0, sizeof(db_cfg));
54 cparms.size = sizeof(struct tbl_rm_db);
56 if (tfp_calloc(&cparms) != 0) {
57 TFP_DRV_LOG(ERR, "tbl_rm_db alloc error %s\n",
62 tbl_db = cparms.mem_va;
63 for (i = 0; i < TF_DIR_MAX; i++)
64 tbl_db->tbl_db[i] = NULL;
65 tf_session_set_db(tfp, TF_MODULE_TYPE_TABLE, tbl_db);
67 db_cfg.num_elements = parms->num_elements;
68 db_cfg.module = TF_MODULE_TYPE_TABLE;
69 db_cfg.num_elements = parms->num_elements;
70 db_cfg.cfg = parms->cfg;
72 for (d = 0; d < TF_DIR_MAX; d++) {
74 db_cfg.alloc_cnt = parms->resources->tbl_cnt[d].cnt;
75 db_cfg.rm_db = (void *)&tbl_db->tbl_db[d];
76 if (tf_session_is_shared_session(tfs) &&
77 (!tf_session_is_shared_session_creator(tfs)))
78 db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg);
80 db_rc[d] = tf_rm_create_db(tfp, &db_cfg);
84 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) {
86 "%s: No Table DB created\n",
88 return db_rc[TF_DIR_RX];
92 "Table Type - initialized\n");
98 tf_tbl_unbind(struct tf *tfp)
102 struct tf_rm_free_db_parms fparms = { 0 };
103 struct tbl_rm_db *tbl_db;
104 void *tbl_db_ptr = NULL;
105 TF_CHECK_PARMS1(tfp);
107 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
110 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
112 for (i = 0; i < TF_DIR_MAX; i++) {
113 if (tbl_db->tbl_db[i] == NULL)
116 fparms.rm_db = tbl_db->tbl_db[i];
117 rc = tf_rm_free_db(tfp, &fparms);
121 tbl_db->tbl_db[i] = NULL;
130 tf_tbl_alloc(struct tf *tfp __rte_unused,
131 struct tf_tbl_alloc_parms *parms)
135 struct tf_rm_allocate_parms aparms = { 0 };
136 struct tf_session *tfs;
137 struct tf_dev_info *dev;
138 uint16_t base = 0, shift = 0;
139 struct tbl_rm_db *tbl_db;
140 void *tbl_db_ptr = NULL;
142 TF_CHECK_PARMS2(tfp, parms);
144 /* Retrieve the session information */
145 rc = tf_session_get_session_internal(tfp, &tfs);
149 /* Retrieve the device information */
150 rc = tf_session_get_device(tfs, &dev);
154 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
157 "Failed to get em_ext_db from session, rc:%s\n",
161 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
163 /* Only get table info if required for the device */
164 if (dev->ops->tf_dev_get_tbl_info) {
165 rc = dev->ops->tf_dev_get_tbl_info(tfp,
166 tbl_db->tbl_db[parms->dir],
172 "%s: Failed to get table info:%d\n",
173 tf_dir_2_str(parms->dir),
179 /* Allocate requested element */
180 aparms.rm_db = tbl_db->tbl_db[parms->dir];
181 aparms.subtype = parms->type;
183 rc = tf_rm_allocate(&aparms);
186 "%s: Failed allocate, type:%d\n",
187 tf_dir_2_str(parms->dir),
192 TF_TBL_RM_TO_PTR(&idx, idx, base, shift);
199 tf_tbl_free(struct tf *tfp __rte_unused,
200 struct tf_tbl_free_parms *parms)
203 struct tf_rm_is_allocated_parms aparms = { 0 };
204 struct tf_rm_free_parms fparms = { 0 };
206 struct tf_session *tfs;
207 struct tf_dev_info *dev;
208 uint16_t base = 0, shift = 0;
209 struct tbl_rm_db *tbl_db;
210 void *tbl_db_ptr = NULL;
212 TF_CHECK_PARMS2(tfp, parms);
214 /* Retrieve the session information */
215 rc = tf_session_get_session_internal(tfp, &tfs);
219 /* Retrieve the device information */
220 rc = tf_session_get_device(tfs, &dev);
224 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
227 "Failed to get em_ext_db from session, rc:%s\n",
231 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
233 /* Only get table info if required for the device */
234 if (dev->ops->tf_dev_get_tbl_info) {
235 rc = dev->ops->tf_dev_get_tbl_info(tfp,
236 tbl_db->tbl_db[parms->dir],
242 "%s: Failed to get table info:%d\n",
243 tf_dir_2_str(parms->dir),
249 /* Check if element is in use */
250 aparms.rm_db = tbl_db->tbl_db[parms->dir];
251 aparms.subtype = parms->type;
253 TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
255 aparms.allocated = &allocated;
256 rc = tf_rm_is_allocated(&aparms);
260 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
262 "%s: Entry already free, type:%d, index:%d\n",
263 tf_dir_2_str(parms->dir),
269 /* If this is counter table, clear the entry on free */
270 if (parms->type == TF_TBL_TYPE_ACT_STATS_64) {
271 uint8_t data[8] = { 0 };
272 uint16_t hcapi_type = 0;
273 struct tf_rm_get_hcapi_parms hparms = { 0 };
275 /* Get the hcapi type */
276 hparms.rm_db = tbl_db->tbl_db[parms->dir];
277 hparms.subtype = parms->type;
278 hparms.hcapi_type = &hcapi_type;
279 rc = tf_rm_get_hcapi_type(&hparms);
282 "%s, Failed type lookup, type:%d, rc:%s\n",
283 tf_dir_2_str(parms->dir),
290 rc = tf_msg_set_tbl_entry(tfp,
298 "%s, Set failed, type:%d, rc:%s\n",
299 tf_dir_2_str(parms->dir),
306 /* Free requested element */
307 fparms.rm_db = tbl_db->tbl_db[parms->dir];
308 fparms.subtype = parms->type;
310 TF_TBL_PTR_TO_RM(&fparms.index, parms->idx, base, shift);
312 rc = tf_rm_free(&fparms);
315 "%s: Free failed, type:%d, index:%d\n",
316 tf_dir_2_str(parms->dir),
326 tf_tbl_set(struct tf *tfp,
327 struct tf_tbl_set_parms *parms)
332 struct tf_rm_is_allocated_parms aparms = { 0 };
333 struct tf_rm_get_hcapi_parms hparms = { 0 };
334 struct tf_session *tfs;
335 struct tf_dev_info *dev;
336 uint16_t base = 0, shift = 0;
337 struct tbl_rm_db *tbl_db;
338 void *tbl_db_ptr = NULL;
340 TF_CHECK_PARMS3(tfp, parms, parms->data);
342 /* Retrieve the session information */
343 rc = tf_session_get_session_internal(tfp, &tfs);
347 /* Retrieve the device information */
348 rc = tf_session_get_device(tfs, &dev);
352 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
355 "Failed to get em_ext_db from session, rc:%s\n",
359 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
361 /* Only get table info if required for the device */
362 if (dev->ops->tf_dev_get_tbl_info) {
363 rc = dev->ops->tf_dev_get_tbl_info(tfp,
364 tbl_db->tbl_db[parms->dir],
370 "%s: Failed to get table info:%d\n",
371 tf_dir_2_str(parms->dir),
377 /* Do not check meter drop counter because it is not allocated
380 if (parms->type != TF_TBL_TYPE_METER_DROP_CNT) {
381 /* Verify that the entry has been previously allocated */
382 aparms.rm_db = tbl_db->tbl_db[parms->dir];
383 aparms.subtype = parms->type;
384 TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
386 aparms.allocated = &allocated;
387 rc = tf_rm_is_allocated(&aparms);
391 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
393 "%s, Invalid or not allocated index, type:%d, idx:%d\n",
394 tf_dir_2_str(parms->dir),
402 hparms.rm_db = tbl_db->tbl_db[parms->dir];
403 hparms.subtype = parms->type;
404 hparms.hcapi_type = &hcapi_type;
405 rc = tf_rm_get_hcapi_type(&hparms);
408 "%s, Failed type lookup, type:%d, rc:%s\n",
409 tf_dir_2_str(parms->dir),
415 rc = tf_msg_set_tbl_entry(tfp,
418 parms->data_sz_in_bytes,
423 "%s, Set failed, type:%d, rc:%s\n",
424 tf_dir_2_str(parms->dir),
434 tf_tbl_get(struct tf *tfp,
435 struct tf_tbl_get_parms *parms)
440 struct tf_rm_is_allocated_parms aparms = { 0 };
441 struct tf_rm_get_hcapi_parms hparms = { 0 };
442 struct tf_session *tfs;
443 struct tf_dev_info *dev;
444 uint16_t base = 0, shift = 0;
445 struct tbl_rm_db *tbl_db;
446 void *tbl_db_ptr = NULL;
448 TF_CHECK_PARMS3(tfp, parms, parms->data);
450 /* Retrieve the session information */
451 rc = tf_session_get_session_internal(tfp, &tfs);
455 /* Retrieve the device information */
456 rc = tf_session_get_device(tfs, &dev);
460 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
463 "Failed to get em_ext_db from session, rc:%s\n",
467 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
469 /* Only get table info if required for the device */
470 if (dev->ops->tf_dev_get_tbl_info) {
471 rc = dev->ops->tf_dev_get_tbl_info(tfp,
472 tbl_db->tbl_db[parms->dir],
478 "%s: Failed to get table info:%d\n",
479 tf_dir_2_str(parms->dir),
485 /* Do not check meter drop counter because it is not allocated
488 if (parms->type != TF_TBL_TYPE_METER_DROP_CNT) {
489 /* Verify that the entry has been previously allocated */
490 aparms.rm_db = tbl_db->tbl_db[parms->dir];
491 aparms.subtype = parms->type;
492 TF_TBL_PTR_TO_RM(&aparms.index, parms->idx, base, shift);
494 aparms.allocated = &allocated;
495 rc = tf_rm_is_allocated(&aparms);
499 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) {
501 "%s, Invalid or not allocated index, type:%d, idx:%d\n",
502 tf_dir_2_str(parms->dir),
510 hparms.rm_db = tbl_db->tbl_db[parms->dir];
511 hparms.subtype = parms->type;
512 hparms.hcapi_type = &hcapi_type;
513 rc = tf_rm_get_hcapi_type(&hparms);
516 "%s, Failed type lookup, type:%d, rc:%s\n",
517 tf_dir_2_str(parms->dir),
524 rc = tf_msg_get_tbl_entry(tfp,
527 parms->data_sz_in_bytes,
532 "%s, Get failed, type:%d, rc:%s\n",
533 tf_dir_2_str(parms->dir),
543 tf_tbl_bulk_get(struct tf *tfp,
544 struct tf_tbl_get_bulk_parms *parms)
548 struct tf_rm_get_hcapi_parms hparms = { 0 };
549 struct tf_rm_check_indexes_in_range_parms cparms = { 0 };
550 struct tf_session *tfs;
551 struct tf_dev_info *dev;
552 uint16_t base = 0, shift = 0;
553 struct tbl_rm_db *tbl_db;
554 void *tbl_db_ptr = NULL;
556 TF_CHECK_PARMS2(tfp, parms);
558 /* Retrieve the session information */
559 rc = tf_session_get_session_internal(tfp, &tfs);
563 /* Retrieve the device information */
564 rc = tf_session_get_device(tfs, &dev);
568 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
571 "Failed to get em_ext_db from session, rc:%s\n",
575 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
577 /* Only get table info if required for the device */
578 if (dev->ops->tf_dev_get_tbl_info) {
579 rc = dev->ops->tf_dev_get_tbl_info(tfp,
580 tbl_db->tbl_db[parms->dir],
586 "%s: Failed to get table info:%d\n",
587 tf_dir_2_str(parms->dir),
593 /* Verify that the entries are in the range of reserved resources. */
594 cparms.rm_db = tbl_db->tbl_db[parms->dir];
595 cparms.subtype = parms->type;
597 TF_TBL_PTR_TO_RM(&cparms.starting_index, parms->starting_idx,
600 cparms.num_entries = parms->num_entries;
602 rc = tf_rm_check_indexes_in_range(&cparms);
605 "%s, Invalid or %d index starting from %d"
606 " not in range, type:%d",
607 tf_dir_2_str(parms->dir),
614 hparms.rm_db = tbl_db->tbl_db[parms->dir];
615 hparms.subtype = parms->type;
616 hparms.hcapi_type = &hcapi_type;
617 rc = tf_rm_get_hcapi_type(&hparms);
620 "%s, Failed type lookup, type:%d, rc:%s\n",
621 tf_dir_2_str(parms->dir),
627 /* Get the entries */
628 rc = tf_msg_bulk_get_tbl_entry(tfp,
633 parms->entry_sz_in_bytes,
634 parms->physical_mem_addr);
637 "%s, Bulk get failed, type:%d, rc:%s\n",
638 tf_dir_2_str(parms->dir),
647 tf_tbl_get_resc_info(struct tf *tfp,
648 struct tf_tbl_resource_info *tbl)
652 struct tf_resource_info *dinfo;
653 struct tf_rm_get_alloc_info_parms ainfo;
654 void *tbl_db_ptr = NULL;
655 struct tbl_rm_db *tbl_db;
656 uint16_t base = 0, shift = 0;
657 struct tf_dev_info *dev;
658 struct tf_session *tfs;
660 TF_CHECK_PARMS2(tfp, tbl);
662 /* Retrieve the session information */
663 rc = tf_session_get_session_internal(tfp, &tfs);
667 /* Retrieve the device information */
668 rc = tf_session_get_device(tfs, &dev);
672 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr);
674 return 0; /* db doesn't exist */
676 return rc; /* error getting db */
678 tbl_db = (struct tbl_rm_db *)tbl_db_ptr;
680 /* check if reserved resource for WC is multiple of num_slices */
681 for (d = 0; d < TF_DIR_MAX; d++) {
682 ainfo.rm_db = tbl_db->tbl_db[d];
688 ainfo.info = (struct tf_rm_alloc_info *)dinfo;
690 rc = tf_rm_get_all_info(&ainfo, TF_TBL_TYPE_MAX);
694 if (dev->ops->tf_dev_get_tbl_info) {
696 for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
697 /* Only get table info if required for the device */
698 rc = dev->ops->tf_dev_get_tbl_info(tfp,
705 "%s: Failed to get table info:%d\n",
711 TF_TBL_RM_TO_PTR(&dinfo[i].start,