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 db_cfg.cfg = parms->cfg; 62 63 for (d = 0; d < TF_DIR_MAX; d++) { 64 db_cfg.dir = d; 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 311 /* Do not check meter drop counter because it is not allocated 312 * resources 313 */ 314 if (parms->type != TF_TBL_TYPE_METER_DROP_CNT) { 315 /* Verify that the entry has been previously allocated */ 316 aparms.rm_db = tbl_db->tbl_db[parms->dir]; 317 aparms.subtype = parms->type; 318 aparms.allocated = &allocated; 319 aparms.index = parms->idx; 320 rc = tf_rm_is_allocated(&aparms); 321 if (rc) 322 return rc; 323 324 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 325 TFP_DRV_LOG(ERR, 326 "%s, Invalid or not allocated, type:%s, idx:%d\n", 327 tf_dir_2_str(parms->dir), 328 tf_tbl_type_2_str(parms->type), 329 parms->idx); 330 return -EINVAL; 331 } 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 /* Do not check meter drop counter because it is not allocated 402 * resources. 403 */ 404 if (parms->type != TF_TBL_TYPE_METER_DROP_CNT) { 405 /* Verify that the entry has been previously allocated */ 406 aparms.rm_db = tbl_db->tbl_db[parms->dir]; 407 aparms.subtype = parms->type; 408 aparms.index = parms->idx; 409 aparms.allocated = &allocated; 410 rc = tf_rm_is_allocated(&aparms); 411 if (rc) 412 return rc; 413 414 if (allocated != TF_RM_ALLOCATED_ENTRY_IN_USE) { 415 TFP_DRV_LOG(ERR, 416 "%s, Invalid or not allocated index, type:%s, idx:%d\n", 417 tf_dir_2_str(parms->dir), 418 tf_tbl_type_2_str(parms->type), 419 parms->idx); 420 return -EINVAL; 421 } 422 } 423 424 /* Set the entry */ 425 hparms.rm_db = tbl_db->tbl_db[parms->dir]; 426 hparms.subtype = parms->type; 427 hparms.hcapi_type = &hcapi_type; 428 rc = tf_rm_get_hcapi_type(&hparms); 429 if (rc) { 430 TFP_DRV_LOG(ERR, 431 "%s, Failed type lookup, type:%s, rc:%s\n", 432 tf_dir_2_str(parms->dir), 433 tf_tbl_type_2_str(parms->type), 434 strerror(-rc)); 435 return rc; 436 } 437 438 /* Get the entry */ 439 rc = tf_msg_get_tbl_entry(tfp, 440 parms->dir, 441 hcapi_type, 442 parms->data_sz_in_bytes, 443 parms->data, 444 parms->idx); 445 if (rc) { 446 TFP_DRV_LOG(ERR, 447 "%s, Get failed, type:%s, rc:%s\n", 448 tf_dir_2_str(parms->dir), 449 tf_tbl_type_2_str(parms->type), 450 strerror(-rc)); 451 return rc; 452 } 453 454 return 0; 455 } 456 457 int 458 tf_tbl_bulk_get(struct tf *tfp, 459 struct tf_tbl_get_bulk_parms *parms) 460 { 461 int rc; 462 uint16_t hcapi_type; 463 struct tf_rm_get_hcapi_parms hparms = { 0 }; 464 struct tf_rm_check_indexes_in_range_parms cparms = { 0 }; 465 struct tf_session *tfs; 466 struct tf_dev_info *dev; 467 struct tbl_rm_db *tbl_db; 468 void *tbl_db_ptr = NULL; 469 470 TF_CHECK_PARMS2(tfp, parms); 471 472 /* Retrieve the session information */ 473 rc = tf_session_get_session_internal(tfp, &tfs); 474 if (rc) 475 return rc; 476 477 /* Retrieve the device information */ 478 rc = tf_session_get_device(tfs, &dev); 479 if (rc) 480 return rc; 481 482 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 483 if (rc) { 484 TFP_DRV_LOG(ERR, 485 "Failed to get em_ext_db from session, rc:%s\n", 486 strerror(-rc)); 487 return rc; 488 } 489 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 490 491 /* Verify that the entries are in the range of reserved resources. */ 492 cparms.rm_db = tbl_db->tbl_db[parms->dir]; 493 cparms.subtype = parms->type; 494 cparms.num_entries = parms->num_entries; 495 cparms.starting_index = parms->starting_idx; 496 497 rc = tf_rm_check_indexes_in_range(&cparms); 498 if (rc) { 499 TFP_DRV_LOG(ERR, 500 "%s, Invalid or %d index starting from %d" 501 " not in range, type:%s", 502 tf_dir_2_str(parms->dir), 503 parms->starting_idx, 504 parms->num_entries, 505 tf_tbl_type_2_str(parms->type)); 506 return rc; 507 } 508 509 hparms.rm_db = tbl_db->tbl_db[parms->dir]; 510 hparms.subtype = parms->type; 511 hparms.hcapi_type = &hcapi_type; 512 rc = tf_rm_get_hcapi_type(&hparms); 513 if (rc) { 514 TFP_DRV_LOG(ERR, 515 "%s, Failed type lookup, type:%s, rc:%s\n", 516 tf_dir_2_str(parms->dir), 517 tf_tbl_type_2_str(parms->type), 518 strerror(-rc)); 519 return rc; 520 } 521 522 /* Get the entries */ 523 rc = tf_msg_bulk_get_tbl_entry(tfp, 524 parms->dir, 525 hcapi_type, 526 parms->starting_idx, 527 parms->num_entries, 528 parms->entry_sz_in_bytes, 529 parms->physical_mem_addr); 530 if (rc) { 531 TFP_DRV_LOG(ERR, 532 "%s, Bulk get failed, type:%s, rc:%s\n", 533 tf_dir_2_str(parms->dir), 534 tf_tbl_type_2_str(parms->type), 535 strerror(-rc)); 536 } 537 538 return rc; 539 } 540 541 int 542 tf_tbl_get_resc_info(struct tf *tfp, 543 struct tf_tbl_resource_info *tbl) 544 { 545 int rc; 546 int d, i; 547 struct tf_resource_info *dinfo; 548 struct tf_rm_get_alloc_info_parms ainfo; 549 void *tbl_db_ptr = NULL; 550 struct tbl_rm_db *tbl_db; 551 struct tf_dev_info *dev; 552 struct tf_session *tfs; 553 uint16_t base = 0, shift = 0; 554 555 TF_CHECK_PARMS2(tfp, tbl); 556 557 /* Retrieve the session information */ 558 rc = tf_session_get_session_internal(tfp, &tfs); 559 if (rc) 560 return rc; 561 562 /* Retrieve the device information */ 563 rc = tf_session_get_device(tfs, &dev); 564 if (rc) 565 return rc; 566 567 rc = tf_session_get_db(tfp, TF_MODULE_TYPE_TABLE, &tbl_db_ptr); 568 if (rc == -ENOMEM) 569 return 0; /* db doesn't exist */ 570 else if (rc) 571 return rc; /* error getting db */ 572 573 tbl_db = (struct tbl_rm_db *)tbl_db_ptr; 574 575 for (d = 0; d < TF_DIR_MAX; d++) { 576 ainfo.rm_db = tbl_db->tbl_db[d]; 577 dinfo = tbl[d].info; 578 579 if (!ainfo.rm_db) 580 continue; 581 582 ainfo.info = (struct tf_rm_alloc_info *)dinfo; 583 ainfo.subtype = 0; 584 rc = tf_rm_get_all_info(&ainfo, TF_TBL_TYPE_MAX); 585 if (rc) 586 return rc; 587 588 if (dev->ops->tf_dev_get_tbl_info) { 589 /* Adjust all */ 590 for (i = 0; i < TF_TBL_TYPE_MAX; i++) { 591 /* Only get table info if required for the device */ 592 rc = dev->ops->tf_dev_get_tbl_info(tfp, 593 tbl_db->tbl_db[d], 594 i, 595 &base, 596 &shift); 597 if (rc) { 598 TFP_DRV_LOG(ERR, 599 "%s: Failed to get table info:%d\n", 600 tf_dir_2_str(d), 601 i); 602 return rc; 603 } 604 if (dinfo[i].stride) 605 TF_TBL_RM_TO_PTR(&dinfo[i].start, 606 dinfo[i].start, 607 base, 608 shift); 609 } 610 } 611 } 612 613 return 0; 614 } 615