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