1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 /* Truflow Table APIs and supporting code */ 7 8 #include <rte_common.h> 9 10 #include "tf_tbl.h" 11 #include "tf_common.h" 12 #include "tf_rm.h" 13 #include "tf_util.h" 14 #include "tf_msg.h" 15 #include "tfp.h" 16 #include "tf_session.h" 17 #include "tf_device.h" 18 19 struct tf; 20 21 #define TF_TBL_RM_TO_PTR(new_idx, idx, base, shift) { \ 22 *(new_idx) = (((idx) + (base)) << (shift)); \ 23 } 24 25 int 26 tf_tbl_bind(struct tf *tfp, 27 struct tf_tbl_cfg_parms *parms) 28 { 29 int rc, d, i; 30 int db_rc[TF_DIR_MAX] = { 0 }; 31 struct tf_rm_create_db_parms db_cfg = { 0 }; 32 struct tbl_rm_db *tbl_db; 33 struct tfp_calloc_parms cparms; 34 struct tf_session *tfs; 35 36 TF_CHECK_PARMS2(tfp, parms); 37 38 /* Retrieve the session information */ 39 rc = tf_session_get_session_internal(tfp, &tfs); 40 if (rc) 41 return rc; 42 43 memset(&db_cfg, 0, sizeof(db_cfg)); 44 cparms.nitems = 1; 45 cparms.size = sizeof(struct tbl_rm_db); 46 cparms.alignment = 0; 47 if (tfp_calloc(&cparms) != 0) { 48 TFP_DRV_LOG(ERR, "tbl_rm_db alloc error %s\n", 49 strerror(ENOMEM)); 50 return -ENOMEM; 51 } 52 53 tbl_db = cparms.mem_va; 54 for (i = 0; i < TF_DIR_MAX; i++) 55 tbl_db->tbl_db[i] = NULL; 56 tf_session_set_db(tfp, TF_MODULE_TYPE_TABLE, tbl_db); 57 58 db_cfg.num_elements = parms->num_elements; 59 db_cfg.module = TF_MODULE_TYPE_TABLE; 60 db_cfg.num_elements = parms->num_elements; 61 62 for (d = 0; d < TF_DIR_MAX; d++) { 63 db_cfg.dir = d; 64 db_cfg.cfg = &parms->cfg[d ? TF_TBL_TYPE_MAX : 0]; 65 db_cfg.alloc_cnt = parms->resources->tbl_cnt[d].cnt; 66 db_cfg.rm_db = (void *)&tbl_db->tbl_db[d]; 67 if (tf_session_is_shared_session(tfs) && 68 (!tf_session_is_shared_session_creator(tfs))) 69 db_rc[d] = tf_rm_create_db_no_reservation(tfp, &db_cfg); 70 else 71 db_rc[d] = tf_rm_create_db(tfp, &db_cfg); 72 } 73 74 /* No db created */ 75 if (db_rc[TF_DIR_RX] && db_rc[TF_DIR_TX]) { 76 TFP_DRV_LOG(ERR, 77 "%s: No Table DB created\n", 78 tf_dir_2_str(d)); 79 return db_rc[TF_DIR_RX]; 80 } 81 82 TFP_DRV_LOG(INFO, 83 "Table Type - initialized\n"); 84 85 return 0; 86 } 87 88 int 89 tf_tbl_unbind(struct tf *tfp) 90 { 91 int rc; 92 int i; 93 struct tf_rm_free_db_parms fparms = { 0 }; 94 struct tbl_rm_db *tbl_db; 95 void *tbl_db_ptr = NULL; 96 TF_CHECK_PARMS1(tfp); 97 98 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 99 if (rc) 100 return 0; 101 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 102 103 for (i = 0; i < TF_DIR_MAX; i++) { 104 if (tbl_db->tbl_db[i] == NULL) 105 continue; 106 fparms.dir = i; 107 fparms.rm_db = tbl_db->tbl_db[i]; 108 rc = tf_rm_free_db(tfp, &fparms); 109 if (rc) 110 return rc; 111 112 tbl_db->tbl_db[i] = NULL; 113 } 114 115 return 0; 116 } 117 118 int 119 tf_tbl_alloc(struct tf *tfp __rte_unused, 120 struct tf_tbl_alloc_parms *parms) 121 { 122 int rc; 123 uint32_t idx; 124 struct tf_rm_allocate_parms aparms = { 0 }; 125 struct tf_session *tfs; 126 struct tf_dev_info *dev; 127 struct tbl_rm_db *tbl_db; 128 void *tbl_db_ptr = NULL; 129 130 TF_CHECK_PARMS2(tfp, parms); 131 132 /* Retrieve the session information */ 133 rc = tf_session_get_session_internal(tfp, &tfs); 134 if (rc) 135 return rc; 136 137 /* Retrieve the device information */ 138 rc = tf_session_get_device(tfs, &dev); 139 if (rc) 140 return rc; 141 142 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 143 if (rc) { 144 TFP_DRV_LOG(ERR, 145 "Failed to get tbl_db from session, rc:%s\n", 146 strerror(-rc)); 147 return rc; 148 } 149 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 150 151 /* Allocate requested element */ 152 aparms.rm_db = tbl_db->tbl_db[parms->dir]; 153 aparms.subtype = parms->type; 154 aparms.index = &idx; 155 rc = tf_rm_allocate(&aparms); 156 if (rc) { 157 TFP_DRV_LOG(ERR, 158 "%s: Failed allocate, type:%s\n", 159 tf_dir_2_str(parms->dir), 160 tf_tbl_type_2_str(parms->type)); 161 return rc; 162 } 163 164 *parms->idx = idx; 165 166 return 0; 167 } 168 169 int 170 tf_tbl_free(struct tf *tfp __rte_unused, 171 struct tf_tbl_free_parms *parms) 172 { 173 int rc; 174 struct tf_rm_is_allocated_parms aparms = { 0 }; 175 struct tf_rm_free_parms fparms = { 0 }; 176 int allocated = 0; 177 struct tf_session *tfs; 178 struct tf_dev_info *dev; 179 struct tbl_rm_db *tbl_db; 180 void *tbl_db_ptr = NULL; 181 182 TF_CHECK_PARMS2(tfp, parms); 183 184 /* Retrieve the session information */ 185 rc = tf_session_get_session_internal(tfp, &tfs); 186 if (rc) 187 return rc; 188 189 /* Retrieve the device information */ 190 rc = tf_session_get_device(tfs, &dev); 191 if (rc) 192 return rc; 193 194 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 195 if (rc) { 196 TFP_DRV_LOG(ERR, 197 "Failed to get em_ext_db from session, rc:%s\n", 198 strerror(-rc)); 199 return rc; 200 } 201 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 202 203 /* Check if element is in use */ 204 aparms.rm_db = tbl_db->tbl_db[parms->dir]; 205 aparms.subtype = parms->type; 206 aparms.index = parms->idx; 207 aparms.allocated = &allocated; 208 rc = tf_rm_is_allocated(&aparms); 209 if (rc) 210 return rc; 211 212 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 213 TFP_DRV_LOG(ERR, 214 "%s: Entry already free, type:%s, index:%d\n", 215 tf_dir_2_str(parms->dir), 216 tf_tbl_type_2_str(parms->type), 217 parms->idx); 218 return -EINVAL; 219 } 220 221 /* If this is counter table, clear the entry on free */ 222 if (parms->type == TF_TBL_TYPE_ACT_STATS_64) { 223 uint8_t data[8] = { 0 }; 224 uint16_t hcapi_type = 0; 225 struct tf_rm_get_hcapi_parms hparms = { 0 }; 226 227 /* Get the hcapi type */ 228 hparms.rm_db = tbl_db->tbl_db[parms->dir]; 229 hparms.subtype = parms->type; 230 hparms.hcapi_type = &hcapi_type; 231 rc = tf_rm_get_hcapi_type(&hparms); 232 if (rc) { 233 TFP_DRV_LOG(ERR, 234 "%s, Failed type lookup, type:%s, rc:%s\n", 235 tf_dir_2_str(parms->dir), 236 tf_tbl_type_2_str(parms->type), 237 strerror(-rc)); 238 return rc; 239 } 240 /* Clear the counter 241 */ 242 rc = tf_msg_set_tbl_entry(tfp, 243 parms->dir, 244 hcapi_type, 245 sizeof(data), 246 data, 247 parms->idx); 248 if (rc) { 249 TFP_DRV_LOG(ERR, 250 "%s, Set failed, type:%s, rc:%s\n", 251 tf_dir_2_str(parms->dir), 252 tf_tbl_type_2_str(parms->type), 253 strerror(-rc)); 254 return rc; 255 } 256 } 257 258 /* Free requested element */ 259 fparms.rm_db = tbl_db->tbl_db[parms->dir]; 260 fparms.subtype = parms->type; 261 fparms.index = parms->idx; 262 rc = tf_rm_free(&fparms); 263 if (rc) { 264 TFP_DRV_LOG(ERR, 265 "%s: Free failed, type:%s, index:%d\n", 266 tf_dir_2_str(parms->dir), 267 tf_tbl_type_2_str(parms->type), 268 parms->idx); 269 return rc; 270 } 271 272 return 0; 273 } 274 275 int 276 tf_tbl_set(struct tf *tfp, 277 struct tf_tbl_set_parms *parms) 278 { 279 int rc; 280 int allocated = 0; 281 uint16_t hcapi_type; 282 struct tf_rm_is_allocated_parms aparms = { 0 }; 283 struct tf_rm_get_hcapi_parms hparms = { 0 }; 284 struct tf_session *tfs; 285 struct tf_dev_info *dev; 286 struct tbl_rm_db *tbl_db; 287 void *tbl_db_ptr = NULL; 288 289 TF_CHECK_PARMS3(tfp, parms, parms->data); 290 291 /* Retrieve the session information */ 292 rc = tf_session_get_session_internal(tfp, &tfs); 293 if (rc) 294 return rc; 295 296 /* Retrieve the device information */ 297 rc = tf_session_get_device(tfs, &dev); 298 if (rc) 299 return rc; 300 301 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 302 if (rc) { 303 TFP_DRV_LOG(ERR, 304 "Failed to get em_ext_db from session, rc:%s\n", 305 strerror(-rc)); 306 return rc; 307 } 308 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 309 310 /* Verify that the entry has been previously allocated. 311 * for meter drop counter, check the corresponding meter 312 * entry 313 */ 314 aparms.rm_db = tbl_db->tbl_db[parms->dir]; 315 if (parms->type != TF_TBL_TYPE_METER_DROP_CNT) 316 aparms.subtype = parms->type; 317 else 318 aparms.subtype = TF_TBL_TYPE_METER_INST; 319 aparms.allocated = &allocated; 320 aparms.index = parms->idx; 321 rc = tf_rm_is_allocated(&aparms); 322 if (rc) 323 return rc; 324 325 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 326 TFP_DRV_LOG(ERR, 327 "%s, Invalid or not allocated, type:%s, idx:%d\n", 328 tf_dir_2_str(parms->dir), 329 tf_tbl_type_2_str(parms->type), 330 parms->idx); 331 return -EINVAL; 332 } 333 334 /* Set the entry */ 335 hparms.rm_db = tbl_db->tbl_db[parms->dir]; 336 hparms.subtype = parms->type; 337 hparms.hcapi_type = &hcapi_type; 338 rc = tf_rm_get_hcapi_type(&hparms); 339 if (rc) { 340 TFP_DRV_LOG(ERR, 341 "%s, Failed type lookup, type:%s, rc:%s\n", 342 tf_dir_2_str(parms->dir), 343 tf_tbl_type_2_str(parms->type), 344 strerror(-rc)); 345 return rc; 346 } 347 348 rc = tf_msg_set_tbl_entry(tfp, 349 parms->dir, 350 hcapi_type, 351 parms->data_sz_in_bytes, 352 parms->data, 353 parms->idx); 354 if (rc) { 355 TFP_DRV_LOG(ERR, 356 "%s, Set failed, type:%s, rc:%s\n", 357 tf_dir_2_str(parms->dir), 358 tf_tbl_type_2_str(parms->type), 359 strerror(-rc)); 360 return rc; 361 } 362 363 return 0; 364 } 365 366 int 367 tf_tbl_get(struct tf *tfp, 368 struct tf_tbl_get_parms *parms) 369 { 370 int rc; 371 uint16_t hcapi_type; 372 int allocated = 0; 373 struct tf_rm_is_allocated_parms aparms = { 0 }; 374 struct tf_rm_get_hcapi_parms hparms = { 0 }; 375 struct tf_session *tfs; 376 struct tf_dev_info *dev; 377 struct tbl_rm_db *tbl_db; 378 void *tbl_db_ptr = NULL; 379 380 TF_CHECK_PARMS3(tfp, parms, parms->data); 381 382 /* Retrieve the session information */ 383 rc = tf_session_get_session_internal(tfp, &tfs); 384 if (rc) 385 return rc; 386 387 /* Retrieve the device information */ 388 rc = tf_session_get_device(tfs, &dev); 389 if (rc) 390 return rc; 391 392 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 393 if (rc) { 394 TFP_DRV_LOG(ERR, 395 "Failed to get em_ext_db from session, rc:%s\n", 396 strerror(-rc)); 397 return rc; 398 } 399 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 400 401 /* Verify that the entry has been previously allocated. 402 * for meter drop counter, check the corresponding meter 403 * entry 404 */ 405 aparms.rm_db = tbl_db->tbl_db[parms->dir]; 406 if (parms->type != TF_TBL_TYPE_METER_DROP_CNT) 407 aparms.subtype = parms->type; 408 else 409 aparms.subtype = TF_TBL_TYPE_METER_INST; 410 aparms.index = parms->idx; 411 aparms.allocated = &allocated; 412 rc = tf_rm_is_allocated(&aparms); 413 if (rc) 414 return rc; 415 416 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 417 TFP_DRV_LOG(ERR, 418 "%s, Invalid or not allocated index, type:%s, idx:%d\n", 419 tf_dir_2_str(parms->dir), 420 tf_tbl_type_2_str(parms->type), 421 parms->idx); 422 return -EINVAL; 423 } 424 425 /* Set the entry */ 426 hparms.rm_db = tbl_db->tbl_db[parms->dir]; 427 hparms.subtype = parms->type; 428 hparms.hcapi_type = &hcapi_type; 429 rc = tf_rm_get_hcapi_type(&hparms); 430 if (rc) { 431 TFP_DRV_LOG(ERR, 432 "%s, Failed type lookup, type:%s, rc:%s\n", 433 tf_dir_2_str(parms->dir), 434 tf_tbl_type_2_str(parms->type), 435 strerror(-rc)); 436 return rc; 437 } 438 439 /* Get the entry */ 440 rc = tf_msg_get_tbl_entry(tfp, 441 parms->dir, 442 hcapi_type, 443 parms->data_sz_in_bytes, 444 parms->data, 445 parms->idx, 446 false); 447 if (rc) { 448 TFP_DRV_LOG(ERR, 449 "%s, Get failed, type:%s, rc:%s\n", 450 tf_dir_2_str(parms->dir), 451 tf_tbl_type_2_str(parms->type), 452 strerror(-rc)); 453 return rc; 454 } 455 456 return 0; 457 } 458 459 int 460 tf_tbl_bulk_get(struct tf *tfp, 461 struct tf_tbl_get_bulk_parms *parms) 462 { 463 int rc; 464 uint16_t hcapi_type; 465 struct tf_rm_get_hcapi_parms hparms = { 0 }; 466 struct tf_rm_check_indexes_in_range_parms cparms = { 0 }; 467 struct tf_session *tfs; 468 struct tf_dev_info *dev; 469 struct tbl_rm_db *tbl_db; 470 void *tbl_db_ptr = NULL; 471 472 TF_CHECK_PARMS2(tfp, parms); 473 474 /* Retrieve the session information */ 475 rc = tf_session_get_session_internal(tfp, &tfs); 476 if (rc) 477 return rc; 478 479 /* Retrieve the device information */ 480 rc = tf_session_get_device(tfs, &dev); 481 if (rc) 482 return rc; 483 484 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 485 if (rc) { 486 TFP_DRV_LOG(ERR, 487 "Failed to get em_ext_db from session, rc:%s\n", 488 strerror(-rc)); 489 return rc; 490 } 491 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 492 493 /* Verify that the entries are in the range of reserved resources. */ 494 cparms.rm_db = tbl_db->tbl_db[parms->dir]; 495 cparms.subtype = parms->type; 496 cparms.num_entries = parms->num_entries; 497 cparms.starting_index = parms->starting_idx; 498 499 rc = tf_rm_check_indexes_in_range(&cparms); 500 if (rc) { 501 TFP_DRV_LOG(ERR, 502 "%s, Invalid or %d index starting from %d" 503 " not in range, type:%s", 504 tf_dir_2_str(parms->dir), 505 parms->starting_idx, 506 parms->num_entries, 507 tf_tbl_type_2_str(parms->type)); 508 return rc; 509 } 510 511 hparms.rm_db = tbl_db->tbl_db[parms->dir]; 512 hparms.subtype = parms->type; 513 hparms.hcapi_type = &hcapi_type; 514 rc = tf_rm_get_hcapi_type(&hparms); 515 if (rc) { 516 TFP_DRV_LOG(ERR, 517 "%s, Failed type lookup, type:%s, rc:%s\n", 518 tf_dir_2_str(parms->dir), 519 tf_tbl_type_2_str(parms->type), 520 strerror(-rc)); 521 return rc; 522 } 523 524 /* Get the entries */ 525 rc = tf_msg_bulk_get_tbl_entry(tfp, 526 parms->dir, 527 hcapi_type, 528 parms->starting_idx, 529 parms->num_entries, 530 parms->entry_sz_in_bytes, 531 parms->physical_mem_addr, 532 false); 533 if (rc) { 534 TFP_DRV_LOG(ERR, 535 "%s, Bulk get failed, type:%s, rc:%s\n", 536 tf_dir_2_str(parms->dir), 537 tf_tbl_type_2_str(parms->type), 538 strerror(-rc)); 539 } 540 541 return rc; 542 } 543 544 int 545 tf_tbl_get_resc_info(struct tf *tfp, 546 struct tf_tbl_resource_info *tbl) 547 { 548 int rc; 549 int d, i; 550 struct tf_resource_info *dinfo; 551 struct tf_rm_get_alloc_info_parms ainfo; 552 void *tbl_db_ptr = NULL; 553 struct tbl_rm_db *tbl_db; 554 struct tf_dev_info *dev; 555 struct tf_session *tfs; 556 uint16_t base = 0, shift = 0; 557 558 TF_CHECK_PARMS2(tfp, tbl); 559 560 /* Retrieve the session information */ 561 rc = tf_session_get_session_internal(tfp, &tfs); 562 if (rc) 563 return rc; 564 565 /* Retrieve the device information */ 566 rc = tf_session_get_device(tfs, &dev); 567 if (rc) 568 return rc; 569 570 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 571 if (rc == -ENOMEM) 572 return 0; /* db doesn't exist */ 573 else if (rc) 574 return rc; /* error getting db */ 575 576 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 577 578 for (d = 0; d < TF_DIR_MAX; d++) { 579 ainfo.rm_db = tbl_db->tbl_db[d]; 580 dinfo = tbl[d].info; 581 582 if (!ainfo.rm_db) 583 continue; 584 585 ainfo.info = (struct tf_rm_alloc_info *)dinfo; 586 ainfo.subtype = 0; 587 rc = tf_rm_get_all_info(&ainfo, TF_TBL_TYPE_MAX); 588 if (rc) 589 return rc; 590 591 if (dev->ops->tf_dev_get_tbl_info) { 592 /* Adjust all */ 593 for (i = 0; i < TF_TBL_TYPE_MAX; i++) { 594 /* Only get table info if required for the device */ 595 rc = dev->ops->tf_dev_get_tbl_info(tfp, 596 tbl_db->tbl_db[d], 597 i, 598 &base, 599 &shift); 600 if (rc) { 601 TFP_DRV_LOG(ERR, 602 "%s: Failed to get table info:%d\n", 603 tf_dir_2_str(d), 604 i); 605 return rc; 606 } 607 if (dinfo[i].stride) 608 TF_TBL_RM_TO_PTR(&dinfo[i].start, 609 dinfo[i].start, 610 base, 611 shift); 612 } 613 } 614 } 615 616 return 0; 617 } 618