1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <string.h> 7 #include <rte_common.h> 8 9 #include "tf_tcam.h" 10 #include "tf_common.h" 11 #include "tf_util.h" 12 #include "tf_rm.h" 13 #include "tf_device.h" 14 #include "tfp.h" 15 #include "tf_session.h" 16 #include "tf_msg.h" 17 #include "tf_shadow_tcam.h" 18 19 struct tf; 20 21 /** 22 * TCAM Shadow DBs 23 */ 24 static void *shadow_tcam_db[TF_DIR_MAX]; 25 26 /** 27 * Shadow init flag, set on bind and cleared on unbind 28 */ 29 static uint8_t shadow_init; 30 31 int 32 tf_tcam_bind(struct tf *tfp, 33 struct tf_tcam_cfg_parms *parms) 34 { 35 int rc; 36 int db_rc[TF_DIR_MAX] = { 0 }; 37 int i, d; 38 struct tf_rm_alloc_info info; 39 struct tf_rm_free_db_parms fparms; 40 struct tf_rm_create_db_parms db_cfg; 41 struct tf_tcam_resources *tcam_cnt; 42 struct tf_rm_get_alloc_info_parms ainfo; 43 struct tf_shadow_tcam_free_db_parms fshadow; 44 struct tf_shadow_tcam_cfg_parms shadow_cfg; 45 struct tf_shadow_tcam_create_db_parms shadow_cdb; 46 uint16_t num_slices = 1; 47 struct tf_session *tfs; 48 struct tf_dev_info *dev; 49 struct tcam_rm_db *tcam_db; 50 struct tfp_calloc_parms cparms; 51 52 TF_CHECK_PARMS2(tfp, parms); 53 54 /* Retrieve the session information */ 55 rc = tf_session_get_session_internal(tfp, &tfs); 56 if (rc) 57 return rc; 58 59 /* Retrieve the device information */ 60 rc = tf_session_get_device(tfs, &dev); 61 if (rc) 62 return rc; 63 64 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 65 rc = -EOPNOTSUPP; 66 TFP_DRV_LOG(ERR, 67 "Operation not supported, rc:%s\n", 68 strerror(-rc)); 69 return rc; 70 } 71 72 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 73 TF_TCAM_TBL_TYPE_WC_TCAM, 74 0, 75 &num_slices); 76 if (rc) 77 return rc; 78 79 tcam_cnt = parms->resources->tcam_cnt; 80 if ((tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices) || 81 (tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] % num_slices)) { 82 TFP_DRV_LOG(ERR, 83 "Requested num of WC TCAM entries has to be multiple %d\n", 84 num_slices); 85 return -EINVAL; 86 } 87 88 memset(&db_cfg, 0, sizeof(db_cfg)); 89 cparms.nitems = 1; 90 cparms.size = sizeof(struct tcam_rm_db); 91 cparms.alignment = 0; 92 if (tfp_calloc(&cparms) != 0) { 93 TFP_DRV_LOG(ERR, "tcam_rm_db alloc error %s\n", 94 strerror(ENOMEM)); 95 return -ENOMEM; 96 } 97 98 tcam_db = cparms.mem_va; 99 for (i = 0; i < TF_DIR_MAX; i++) 100 tcam_db->tcam_db[i] = NULL; 101 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, tcam_db); 102 103 db_cfg.module = TF_MODULE_TYPE_TCAM; 104 db_cfg.num_elements = parms->num_elements; 105 db_cfg.cfg = parms->cfg; 106 107 for (d = 0; d < TF_DIR_MAX; d++) { 108 db_cfg.dir = d; 109 db_cfg.alloc_cnt = parms->resources->tcam_cnt[d].cnt; 110 db_cfg.rm_db = (void *)&tcam_db->tcam_db[d]; 111 if (tf_session_is_shared_session(tfs) && 112 (!tf_session_is_shared_session_creator(tfs))) 113 db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg); 114 else 115 db_rc[d] = tf_rm_create_db(tfp, &db_cfg); 116 } 117 118 /* No db created */ 119 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) { 120 TFP_DRV_LOG(ERR, "No TCAM DB created\n"); 121 return db_rc[TF_DIR_RX]; 122 } 123 124 /* check if reserved resource for WC is multiple of num_slices */ 125 for (d = 0; d < TF_DIR_MAX; d++) { 126 if (!tcam_db->tcam_db[d]) 127 continue; 128 129 memset(&info, 0, sizeof(info)); 130 ainfo.rm_db = tcam_db->tcam_db[d]; 131 ainfo.subtype = TF_TCAM_TBL_TYPE_WC_TCAM; 132 ainfo.info = &info; 133 rc = tf_rm_get_info(&ainfo); 134 if (rc) 135 goto error; 136 137 if (info.entry.start % num_slices != 0 || 138 info.entry.stride % num_slices != 0) { 139 TFP_DRV_LOG(ERR, 140 "%s: TCAM reserved resource is not multiple of %d\n", 141 tf_dir_2_str(d), 142 num_slices); 143 rc = -EINVAL; 144 goto error; 145 } 146 } 147 148 /* Initialize the TCAM manager. */ 149 if (parms->shadow_copy) { 150 for (d = 0; d < TF_DIR_MAX; d++) { 151 memset(&shadow_cfg, 0, sizeof(shadow_cfg)); 152 memset(&shadow_cdb, 0, sizeof(shadow_cdb)); 153 /* Get the base addresses of the tcams for tcam mgr */ 154 for (i = 0; i < TF_TCAM_TBL_TYPE_MAX; i++) { 155 memset(&info, 0, sizeof(info)); 156 157 if (!parms->resources->tcam_cnt[d].cnt[i]) 158 continue; 159 ainfo.rm_db = tcam_db->tcam_db[d]; 160 ainfo.subtype = i; 161 ainfo.info = &info; 162 rc = tf_rm_get_info(&ainfo); 163 if (rc) 164 goto error; 165 166 shadow_cfg.base_addr[i] = info.entry.start; 167 } 168 169 /* Create the shadow db */ 170 shadow_cfg.alloc_cnt = 171 parms->resources->tcam_cnt[d].cnt; 172 shadow_cfg.num_entries = parms->num_elements; 173 174 shadow_cdb.shadow_db = &shadow_tcam_db[d]; 175 shadow_cdb.cfg = &shadow_cfg; 176 rc = tf_shadow_tcam_create_db(&shadow_cdb); 177 if (rc) { 178 TFP_DRV_LOG(ERR, 179 "TCAM MGR DB creation failed " 180 "rc=%d\n", rc); 181 goto error; 182 } 183 } 184 shadow_init = 1; 185 } 186 187 TFP_DRV_LOG(INFO, 188 "TCAM - initialized\n"); 189 190 return 0; 191 error: 192 for (i = 0; i < TF_DIR_MAX; i++) { 193 memset(&fparms, 0, sizeof(fparms)); 194 fparms.dir = i; 195 fparms.rm_db = tcam_db->tcam_db[i]; 196 /* Ignoring return here since we are in the error case */ 197 (void)tf_rm_free_db(tfp, &fparms); 198 199 if (parms->shadow_copy) { 200 fshadow.shadow_db = shadow_tcam_db[i]; 201 tf_shadow_tcam_free_db(&fshadow); 202 shadow_tcam_db[i] = NULL; 203 } 204 205 tcam_db->tcam_db[i] = NULL; 206 tf_session_set_db(tfp, TF_MODULE_TYPE_TCAM, NULL); 207 } 208 209 shadow_init = 0; 210 211 return rc; 212 } 213 214 int 215 tf_tcam_unbind(struct tf *tfp) 216 { 217 int rc; 218 int i; 219 struct tf_rm_free_db_parms fparms; 220 struct tcam_rm_db *tcam_db; 221 void *tcam_db_ptr = NULL; 222 struct tf_shadow_tcam_free_db_parms fshadow; 223 TF_CHECK_PARMS1(tfp); 224 225 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 226 if (rc) { 227 return 0; 228 } 229 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 230 231 for (i = 0; i < TF_DIR_MAX; i++) { 232 if (tcam_db->tcam_db[i] == NULL) 233 continue; 234 memset(&fparms, 0, sizeof(fparms)); 235 fparms.dir = i; 236 fparms.rm_db = tcam_db->tcam_db[i]; 237 rc = tf_rm_free_db(tfp, &fparms); 238 if (rc) 239 return rc; 240 241 tcam_db->tcam_db[i] = NULL; 242 243 if (shadow_init) { 244 memset(&fshadow, 0, sizeof(fshadow)); 245 246 fshadow.shadow_db = shadow_tcam_db[i]; 247 tf_shadow_tcam_free_db(&fshadow); 248 shadow_tcam_db[i] = NULL; 249 } 250 } 251 252 shadow_init = 0; 253 254 return 0; 255 } 256 257 int 258 tf_tcam_alloc(struct tf *tfp, 259 struct tf_tcam_alloc_parms *parms) 260 { 261 int rc, i; 262 struct tf_session *tfs; 263 struct tf_dev_info *dev; 264 struct tf_rm_allocate_parms aparms; 265 uint16_t num_slices = 1; 266 uint32_t index; 267 struct tcam_rm_db *tcam_db; 268 void *tcam_db_ptr = NULL; 269 270 TF_CHECK_PARMS2(tfp, parms); 271 272 /* Retrieve the session information */ 273 rc = tf_session_get_session_internal(tfp, &tfs); 274 if (rc) 275 return rc; 276 277 /* Retrieve the device information */ 278 rc = tf_session_get_device(tfs, &dev); 279 if (rc) 280 return rc; 281 282 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 283 rc = -EOPNOTSUPP; 284 TFP_DRV_LOG(ERR, 285 "%s: Operation not supported, rc:%s\n", 286 tf_dir_2_str(parms->dir), 287 strerror(-rc)); 288 return rc; 289 } 290 291 /* Need to retrieve number of slices based on the key_size */ 292 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 293 parms->type, 294 parms->key_size, 295 &num_slices); 296 if (rc) 297 return rc; 298 299 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 300 if (rc) { 301 TFP_DRV_LOG(ERR, 302 "Failed to get tcam_db from session, rc:%s\n", 303 strerror(-rc)); 304 return rc; 305 } 306 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 307 308 /* 309 * For WC TCAM, number of slices could be 4, 2, 1 based on 310 * the key_size. For other TCAM, it is always 1 311 */ 312 for (i = 0; i < num_slices; i++) { 313 memset(&aparms, 0, sizeof(aparms)); 314 aparms.rm_db = tcam_db->tcam_db[parms->dir]; 315 aparms.subtype = parms->type; 316 aparms.priority = parms->priority; 317 aparms.index = &index; 318 rc = tf_rm_allocate(&aparms); 319 if (rc) { 320 TFP_DRV_LOG(ERR, 321 "%s: Failed tcam, type:%d\n", 322 tf_dir_2_str(parms->dir), 323 parms->type); 324 return rc; 325 } 326 327 /* return the start index of each row */ 328 if (i == 0) 329 parms->idx = index; 330 } 331 332 return 0; 333 } 334 335 int 336 tf_tcam_free(struct tf *tfp, 337 struct tf_tcam_free_parms *parms) 338 { 339 int rc; 340 struct tf_session *tfs; 341 struct tf_dev_info *dev; 342 struct tf_rm_is_allocated_parms aparms; 343 struct tf_rm_free_parms fparms; 344 struct tf_rm_get_hcapi_parms hparms; 345 uint16_t num_slices = 1; 346 int allocated = 0; 347 struct tf_shadow_tcam_remove_parms shparms; 348 int i; 349 struct tcam_rm_db *tcam_db; 350 void *tcam_db_ptr = NULL; 351 352 TF_CHECK_PARMS2(tfp, parms); 353 354 /* Retrieve the session information */ 355 rc = tf_session_get_session_internal(tfp, &tfs); 356 if (rc) 357 return rc; 358 359 /* Retrieve the device information */ 360 rc = tf_session_get_device(tfs, &dev); 361 if (rc) 362 return rc; 363 364 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 365 rc = -EOPNOTSUPP; 366 TFP_DRV_LOG(ERR, 367 "%s: Operation not supported, rc:%s\n", 368 tf_dir_2_str(parms->dir), 369 strerror(-rc)); 370 return rc; 371 } 372 373 /* Need to retrieve row size etc */ 374 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 375 parms->type, 376 0, 377 &num_slices); 378 if (rc) 379 return rc; 380 381 if (parms->idx % num_slices) { 382 TFP_DRV_LOG(ERR, 383 "%s: TCAM reserved resource is not multiple of %d\n", 384 tf_dir_2_str(parms->dir), 385 num_slices); 386 return -EINVAL; 387 } 388 389 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 390 if (rc) { 391 TFP_DRV_LOG(ERR, 392 "Failed to get em_ext_db from session, rc:%s\n", 393 strerror(-rc)); 394 return rc; 395 } 396 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 397 398 /* Check if element is in use */ 399 memset(&aparms, 0, sizeof(aparms)); 400 aparms.rm_db = tcam_db->tcam_db[parms->dir]; 401 aparms.subtype = parms->type; 402 aparms.index = parms->idx; 403 aparms.allocated = &allocated; 404 rc = tf_rm_is_allocated(&aparms); 405 if (rc) 406 return rc; 407 408 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 409 TFP_DRV_LOG(ERR, 410 "%s: Entry already free, type:%d, index:%d\n", 411 tf_dir_2_str(parms->dir), 412 parms->type, 413 parms->idx); 414 return -EINVAL; 415 } 416 417 /* 418 * The Shadow mgmt, if enabled, determines if the entry needs 419 * to be deleted. 420 */ 421 if (shadow_init) { 422 shparms.shadow_db = shadow_tcam_db[parms->dir]; 423 shparms.fparms = parms; 424 rc = tf_shadow_tcam_remove(&shparms); 425 if (rc) { 426 /* 427 * Should not get here, log it and let the entry be 428 * deleted. 429 */ 430 TFP_DRV_LOG(ERR, "%s: Shadow free fail, " 431 "type:%d index:%d deleting the entry.\n", 432 tf_dir_2_str(parms->dir), 433 parms->type, 434 parms->idx); 435 } else { 436 /* 437 * If the entry still has references, just return the 438 * ref count to the caller. No need to remove entry 439 * from rm or hw 440 */ 441 if (parms->ref_cnt >= 1) 442 return rc; 443 } 444 } 445 446 for (i = 0; i < num_slices; i++) { 447 /* Free requested element */ 448 memset(&fparms, 0, sizeof(fparms)); 449 fparms.rm_db = tcam_db->tcam_db[parms->dir]; 450 fparms.subtype = parms->type; 451 fparms.index = parms->idx + i; 452 rc = tf_rm_free(&fparms); 453 if (rc) { 454 TFP_DRV_LOG(ERR, 455 "%s: Free failed, type:%d, index:%d\n", 456 tf_dir_2_str(parms->dir), 457 parms->type, 458 parms->idx); 459 return rc; 460 } 461 } 462 463 /* Convert TF type to HCAPI RM type */ 464 memset(&hparms, 0, sizeof(hparms)); 465 466 hparms.rm_db = tcam_db->tcam_db[parms->dir]; 467 hparms.subtype = parms->type; 468 hparms.hcapi_type = &parms->hcapi_type; 469 470 rc = tf_rm_get_hcapi_type(&hparms); 471 if (rc) 472 return rc; 473 474 rc = tf_msg_tcam_entry_free(tfp, dev, parms); 475 if (rc) { 476 /* Log error */ 477 TFP_DRV_LOG(ERR, 478 "%s: %s: Entry %d free failed, rc:%s\n", 479 tf_dir_2_str(parms->dir), 480 tf_tcam_tbl_2_str(parms->type), 481 parms->idx, 482 strerror(-rc)); 483 return rc; 484 } 485 486 return 0; 487 } 488 489 int 490 tf_tcam_alloc_search(struct tf *tfp, 491 struct tf_tcam_alloc_search_parms *parms) 492 { 493 struct tf_shadow_tcam_search_parms sparms; 494 struct tf_shadow_tcam_bind_index_parms bparms; 495 struct tf_tcam_free_parms fparms; 496 struct tf_tcam_alloc_parms aparms; 497 uint16_t num_slice_per_row = 1; 498 struct tf_session *tfs; 499 struct tf_dev_info *dev; 500 int rc; 501 502 TF_CHECK_PARMS2(tfp, parms); 503 504 if (!shadow_init || !shadow_tcam_db[parms->dir]) { 505 TFP_DRV_LOG(ERR, "%s: TCAM Shadow not initialized for %s\n", 506 tf_dir_2_str(parms->dir), 507 tf_tcam_tbl_2_str(parms->type)); 508 return -EINVAL; 509 } 510 511 /* Retrieve the session information */ 512 rc = tf_session_get_session_internal(tfp, &tfs); 513 if (rc) 514 return rc; 515 516 /* Retrieve the device information */ 517 rc = tf_session_get_device(tfs, &dev); 518 if (rc) 519 return rc; 520 521 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 522 rc = -EOPNOTSUPP; 523 TFP_DRV_LOG(ERR, 524 "%s: Operation not supported, rc:%s\n", 525 tf_dir_2_str(parms->dir), 526 strerror(-rc)); 527 return rc; 528 } 529 530 /* Need to retrieve row size etc */ 531 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 532 parms->type, 533 parms->key_size, 534 &num_slice_per_row); 535 if (rc) 536 return rc; 537 538 /* 539 * Prep the shadow search, reusing the parms from original search 540 * instead of copying them. Shadow will update output in there. 541 */ 542 memset(&sparms, 0, sizeof(sparms)); 543 sparms.sparms = parms; 544 sparms.shadow_db = shadow_tcam_db[parms->dir]; 545 546 rc = tf_shadow_tcam_search(&sparms); 547 if (rc) 548 return rc; 549 550 /* 551 * The app didn't request us to alloc the entry, so return now. 552 * The hit should have been updated in the original search parm. 553 */ 554 if (!parms->alloc || parms->search_status != MISS) 555 return rc; 556 557 /* Caller desires an allocate on miss */ 558 if (dev->ops->tf_dev_alloc_tcam == NULL) { 559 rc = -EOPNOTSUPP; 560 TFP_DRV_LOG(ERR, 561 "%s: Operation not supported, rc:%s\n", 562 tf_dir_2_str(parms->dir), 563 strerror(-rc)); 564 return rc; 565 } 566 memset(&aparms, 0, sizeof(aparms)); 567 aparms.dir = parms->dir; 568 aparms.type = parms->type; 569 aparms.key_size = parms->key_size; 570 aparms.priority = parms->priority; 571 rc = dev->ops->tf_dev_alloc_tcam(tfp, &aparms); 572 if (rc) 573 return rc; 574 575 /* Successful allocation, attempt to add it to the shadow */ 576 memset(&bparms, 0, sizeof(bparms)); 577 bparms.dir = parms->dir; 578 bparms.shadow_db = shadow_tcam_db[parms->dir]; 579 bparms.type = parms->type; 580 bparms.key = parms->key; 581 bparms.mask = parms->mask; 582 bparms.key_size = parms->key_size; 583 bparms.idx = aparms.idx; 584 bparms.hb_handle = sparms.hb_handle; 585 rc = tf_shadow_tcam_bind_index(&bparms); 586 if (rc) { 587 /* Error binding entry, need to free the allocated idx */ 588 if (dev->ops->tf_dev_free_tcam == NULL) { 589 rc = -EOPNOTSUPP; 590 TFP_DRV_LOG(ERR, 591 "%s: Operation not supported, rc:%s\n", 592 tf_dir_2_str(parms->dir), 593 strerror(-rc)); 594 return rc; 595 } 596 597 fparms.dir = parms->dir; 598 fparms.type = parms->type; 599 fparms.idx = aparms.idx; 600 rc = dev->ops->tf_dev_free_tcam(tfp, &fparms); 601 if (rc) 602 return rc; 603 } 604 605 /* Add the allocated index to output and done */ 606 parms->idx = aparms.idx; 607 608 return 0; 609 } 610 611 int 612 tf_tcam_set(struct tf *tfp __rte_unused, 613 struct tf_tcam_set_parms *parms __rte_unused) 614 { 615 int rc; 616 struct tf_session *tfs; 617 struct tf_dev_info *dev; 618 struct tf_rm_is_allocated_parms aparms; 619 struct tf_rm_get_hcapi_parms hparms; 620 struct tf_shadow_tcam_insert_parms iparms; 621 uint16_t num_slice_per_row = 1; 622 int allocated = 0; 623 struct tcam_rm_db *tcam_db; 624 void *tcam_db_ptr = NULL; 625 626 TF_CHECK_PARMS2(tfp, parms); 627 628 /* Retrieve the session information */ 629 rc = tf_session_get_session_internal(tfp, &tfs); 630 if (rc) 631 return rc; 632 633 /* Retrieve the device information */ 634 rc = tf_session_get_device(tfs, &dev); 635 if (rc) 636 return rc; 637 638 if (dev->ops->tf_dev_get_tcam_slice_info == NULL) { 639 rc = -EOPNOTSUPP; 640 TFP_DRV_LOG(ERR, 641 "%s: Operation not supported, rc:%s\n", 642 tf_dir_2_str(parms->dir), 643 strerror(-rc)); 644 return rc; 645 } 646 647 /* Need to retrieve row size etc */ 648 rc = dev->ops->tf_dev_get_tcam_slice_info(tfp, 649 parms->type, 650 parms->key_size, 651 &num_slice_per_row); 652 if (rc) 653 return rc; 654 655 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 656 if (rc) { 657 TFP_DRV_LOG(ERR, 658 "Failed to get em_ext_db from session, rc:%s\n", 659 strerror(-rc)); 660 return rc; 661 } 662 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 663 664 /* Check if element is in use */ 665 memset(&aparms, 0, sizeof(aparms)); 666 667 aparms.rm_db = tcam_db->tcam_db[parms->dir]; 668 aparms.subtype = parms->type; 669 aparms.index = parms->idx; 670 aparms.allocated = &allocated; 671 rc = tf_rm_is_allocated(&aparms); 672 if (rc) 673 return rc; 674 675 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 676 TFP_DRV_LOG(ERR, 677 "%s: Entry is not allocated, type:%d, index:%d\n", 678 tf_dir_2_str(parms->dir), 679 parms->type, 680 parms->idx); 681 return -EINVAL; 682 } 683 684 /* Convert TF type to HCAPI RM type */ 685 memset(&hparms, 0, sizeof(hparms)); 686 687 hparms.rm_db = tcam_db->tcam_db[parms->dir]; 688 hparms.subtype = parms->type; 689 hparms.hcapi_type = &parms->hcapi_type; 690 691 rc = tf_rm_get_hcapi_type(&hparms); 692 if (rc) 693 return rc; 694 695 rc = tf_msg_tcam_entry_set(tfp, dev, parms); 696 if (rc) { 697 /* Log error */ 698 TFP_DRV_LOG(ERR, 699 "%s: %s: Entry %d set failed, rc:%s", 700 tf_dir_2_str(parms->dir), 701 tf_tcam_tbl_2_str(parms->type), 702 parms->idx, 703 strerror(-rc)); 704 return rc; 705 } 706 707 /* Successfully added to hw, now for shadow if enabled. */ 708 if (!shadow_init || !shadow_tcam_db[parms->dir]) 709 return 0; 710 711 iparms.shadow_db = shadow_tcam_db[parms->dir]; 712 iparms.sparms = parms; 713 rc = tf_shadow_tcam_insert(&iparms); 714 if (rc) { 715 TFP_DRV_LOG(ERR, 716 "%s: %s: Entry %d set failed, rc:%s", 717 tf_dir_2_str(parms->dir), 718 tf_tcam_tbl_2_str(parms->type), 719 parms->idx, 720 strerror(-rc)); 721 return rc; 722 } 723 724 return 0; 725 } 726 727 int 728 tf_tcam_get(struct tf *tfp __rte_unused, 729 struct tf_tcam_get_parms *parms) 730 { 731 int rc; 732 struct tf_session *tfs; 733 struct tf_dev_info *dev; 734 struct tf_rm_is_allocated_parms aparms; 735 struct tf_rm_get_hcapi_parms hparms; 736 int allocated = 0; 737 struct tcam_rm_db *tcam_db; 738 void *tcam_db_ptr = NULL; 739 740 TF_CHECK_PARMS2(tfp, parms); 741 742 /* Retrieve the session information */ 743 rc = tf_session_get_session_internal(tfp, &tfs); 744 if (rc) 745 return rc; 746 747 /* Retrieve the device information */ 748 rc = tf_session_get_device(tfs, &dev); 749 if (rc) 750 return rc; 751 752 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 753 if (rc) { 754 TFP_DRV_LOG(ERR, 755 "Failed to get em_ext_db from session, rc:%s\n", 756 strerror(-rc)); 757 return rc; 758 } 759 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 760 761 /* Check if element is in use */ 762 memset(&aparms, 0, sizeof(aparms)); 763 764 aparms.rm_db = tcam_db->tcam_db[parms->dir]; 765 aparms.subtype = parms->type; 766 aparms.index = parms->idx; 767 aparms.allocated = &allocated; 768 rc = tf_rm_is_allocated(&aparms); 769 if (rc) 770 return rc; 771 772 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 773 TFP_DRV_LOG(ERR, 774 "%s: Entry is not allocated, type:%d, index:%d\n", 775 tf_dir_2_str(parms->dir), 776 parms->type, 777 parms->idx); 778 return -EINVAL; 779 } 780 781 /* Convert TF type to HCAPI RM type */ 782 memset(&hparms, 0, sizeof(hparms)); 783 784 hparms.rm_db = tcam_db->tcam_db[parms->dir]; 785 hparms.subtype = parms->type; 786 hparms.hcapi_type = &parms->hcapi_type; 787 788 rc = tf_rm_get_hcapi_type(&hparms); 789 if (rc) 790 return rc; 791 792 rc = tf_msg_tcam_entry_get(tfp, dev, parms); 793 if (rc) { 794 /* Log error */ 795 TFP_DRV_LOG(ERR, 796 "%s: %s: Entry %d set failed, rc:%s", 797 tf_dir_2_str(parms->dir), 798 tf_tcam_tbl_2_str(parms->type), 799 parms->idx, 800 strerror(-rc)); 801 return rc; 802 } 803 804 return 0; 805 } 806 807 int 808 tf_tcam_get_resc_info(struct tf *tfp, 809 struct tf_tcam_resource_info *tcam) 810 { 811 int rc; 812 int d; 813 struct tf_resource_info *dinfo; 814 struct tf_rm_get_alloc_info_parms ainfo; 815 void *tcam_db_ptr = NULL; 816 struct tcam_rm_db *tcam_db; 817 818 TF_CHECK_PARMS2(tfp, tcam); 819 820 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TCAM, &tcam_db_ptr); 821 if (rc == -ENOMEM) 822 return 0; /* db doesn't exist */ 823 else if (rc) 824 return rc; /* error getting db */ 825 826 tcam_db = (struct tcam_rm_db *)tcam_db_ptr; 827 828 /* check if reserved resource for WC is multiple of num_slices */ 829 for (d = 0; d < TF_DIR_MAX; d++) { 830 ainfo.rm_db = tcam_db->tcam_db[d]; 831 832 if (!ainfo.rm_db) 833 continue; 834 835 dinfo = tcam[d].info; 836 837 ainfo.info = (struct tf_rm_alloc_info *)dinfo; 838 ainfo.subtype = 0; 839 rc = tf_rm_get_all_info(&ainfo, TF_TCAM_TBL_TYPE_MAX); 840 if (rc && rc != -ENOTSUP) 841 return rc; 842 } 843 844 return 0; 845 } 846