1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2019-2021 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <string.h> 7 8 #include <rte_common.h> 9 #include <rte_debug.h> 10 11 #include <cfa_resource_types.h> 12 13 #include "tf_rm.h" 14 #include "tf_common.h" 15 #include "tf_util.h" 16 #include "tf_session.h" 17 #include "tf_device.h" 18 #include "tfp.h" 19 #include "tf_msg.h" 20 21 /* Logging defines */ 22 #define TF_RM_DEBUG 0 23 24 /** 25 * Generic RM Element data type that an RM DB is build upon. 26 */ 27 struct tf_rm_element { 28 /** 29 * RM Element configuration type. If Private then the 30 * hcapi_type can be ignored. If Null then the element is not 31 * valid for the device. 32 */ 33 enum tf_rm_elem_cfg_type cfg_type; 34 35 /** 36 * HCAPI RM Type for the element. 37 */ 38 uint16_t hcapi_type; 39 40 /** 41 * Resource slices. How many slices will fit in the 42 * resource pool chunk size. 43 */ 44 uint8_t slices; 45 46 /** 47 * HCAPI RM allocated range information for the element. 48 */ 49 struct tf_rm_alloc_info alloc; 50 51 /** 52 * If cfg_type == HCAPI_BA_CHILD, this field indicates 53 * the parent module subtype for look up into the parent pool. 54 * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a 55 * module subtype of TF_MODULE_TYPE_TABLE. 56 */ 57 uint16_t parent_subtype; 58 59 /** 60 * Bit allocator pool for the element. Pool size is controlled 61 * by the struct tf_session_resources at time of session creation. 62 * Null indicates that the pool is not used for the element. 63 */ 64 struct bitalloc *pool; 65 }; 66 67 /** 68 * TF RM DB definition 69 */ 70 struct tf_rm_new_db { 71 /** 72 * Number of elements in the DB 73 */ 74 uint16_t num_entries; 75 76 /** 77 * Direction this DB controls. 78 */ 79 enum tf_dir dir; 80 81 /** 82 * Module type, used for logging purposes. 83 */ 84 enum tf_module_type module; 85 86 /** 87 * The DB consists of an array of elements 88 */ 89 struct tf_rm_element *db; 90 }; 91 92 /** 93 * Adjust an index according to the allocation information. 94 * 95 * All resources are controlled in a 0 based pool. Some resources, by 96 * design, are not 0 based, i.e. Full Action Records (SRAM) thus they 97 * need to be adjusted before they are handed out. 98 * 99 * [in] cfg 100 * Pointer to the DB configuration 101 * 102 * [in] reservations 103 * Pointer to the allocation values associated with the module 104 * 105 * [in] count 106 * Number of DB configuration elements 107 * 108 * [out] valid_count 109 * Number of HCAPI entries with a reservation value greater than 0 110 * 111 * Returns: 112 * 0 - Success 113 * - EOPNOTSUPP - Operation not supported 114 */ 115 static void 116 tf_rm_count_hcapi_reservations(enum tf_dir dir, 117 enum tf_module_type module, 118 struct tf_rm_element_cfg *cfg, 119 uint16_t *reservations, 120 uint16_t count, 121 uint16_t *valid_count) 122 { 123 int i; 124 uint16_t cnt = 0; 125 126 for (i = 0; i < count; i++) { 127 if (cfg[i].cfg_type != TF_RM_ELEM_CFG_NULL && 128 reservations[i] > 0) 129 cnt++; 130 131 /* Only log msg if a type is attempted reserved and 132 * not supported. We ignore EM module as its using a 133 * split configuration array thus it would fail for 134 * this type of check. 135 */ 136 if (module != TF_MODULE_TYPE_EM && 137 cfg[i].cfg_type == TF_RM_ELEM_CFG_NULL && 138 reservations[i] > 0) { 139 TFP_DRV_LOG(ERR, 140 "%s, %s, %s allocation of %d not supported\n", 141 tf_module_2_str(module), 142 tf_dir_2_str(dir), 143 tf_module_subtype_2_str(module, i), 144 reservations[i]); 145 } 146 } 147 148 *valid_count = cnt; 149 } 150 151 /** 152 * Resource Manager Adjust of base index definitions. 153 */ 154 enum tf_rm_adjust_type { 155 TF_RM_ADJUST_ADD_BASE, /**< Adds base to the index */ 156 TF_RM_ADJUST_RM_BASE /**< Removes base from the index */ 157 }; 158 159 /** 160 * Adjust an index according to the allocation information. 161 * 162 * All resources are controlled in a 0 based pool. Some resources, by 163 * design, are not 0 based, i.e. Full Action Records (SRAM) thus they 164 * need to be adjusted before they are handed out. 165 * 166 * [in] db 167 * Pointer to the db, used for the lookup 168 * 169 * [in] action 170 * Adjust action 171 * 172 * [in] subtype 173 * TF module subtype used as an index into the database. 174 * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a 175 * module subtype of TF_MODULE_TYPE_TABLE. 176 * 177 * [in] index 178 * Index to convert 179 * 180 * [out] adj_index 181 * Adjusted index 182 * 183 * Returns: 184 * 0 - Success 185 * - EOPNOTSUPP - Operation not supported 186 */ 187 static int 188 tf_rm_adjust_index(struct tf_rm_element *db, 189 enum tf_rm_adjust_type action, 190 uint32_t subtype, 191 uint32_t index, 192 uint32_t *adj_index) 193 { 194 int rc = 0; 195 uint32_t base_index; 196 197 base_index = db[subtype].alloc.entry.start; 198 199 switch (action) { 200 case TF_RM_ADJUST_RM_BASE: 201 *adj_index = index - base_index; 202 break; 203 case TF_RM_ADJUST_ADD_BASE: 204 *adj_index = index + base_index; 205 break; 206 default: 207 return -EOPNOTSUPP; 208 } 209 210 return rc; 211 } 212 213 /** 214 * Logs an array of found residual entries to the console. 215 * 216 * [in] dir 217 * Receive or transmit direction 218 * 219 * [in] module 220 * Type of Device Module 221 * 222 * [in] count 223 * Number of entries in the residual array 224 * 225 * [in] residuals 226 * Pointer to an array of residual entries. Array is index same as 227 * the DB in which this function is used. Each entry holds residual 228 * value for that entry. 229 */ 230 #if (TF_RM_DEBUG == 1) 231 static void 232 tf_rm_log_residuals(enum tf_dir dir, 233 enum tf_module_type module, 234 uint16_t count, 235 uint16_t *residuals) 236 { 237 int i; 238 239 /* Walk the residual array and log the types that wasn't 240 * cleaned up to the console. 241 */ 242 for (i = 0; i < count; i++) { 243 if (residuals[i] != 0) 244 TFP_DRV_LOG(INFO, 245 "%s, %s was not cleaned up, %d outstanding\n", 246 tf_dir_2_str(dir), 247 tf_module_subtype_2_str(module, i), 248 residuals[i]); 249 } 250 } 251 #endif /* TF_RM_DEBUG == 1 */ 252 /** 253 * Performs a check of the passed in DB for any lingering elements. If 254 * a resource type was found to not have been cleaned up by the caller 255 * then its residual values are recorded, logged and passed back in an 256 * allocate reservation array that the caller can pass to the FW for 257 * cleanup. 258 * 259 * [in] db 260 * Pointer to the db, used for the lookup 261 * 262 * [out] resv_size 263 * Pointer to the reservation size of the generated reservation 264 * array. 265 * 266 * [in/out] resv 267 * Pointer Pointer to a reservation array. The reservation array is 268 * allocated after the residual scan and holds any found residual 269 * entries. Thus it can be smaller than the DB that the check was 270 * performed on. Array must be freed by the caller. 271 * 272 * [out] residuals_present 273 * Pointer to a bool flag indicating if residual was present in the 274 * DB 275 * 276 * Returns: 277 * 0 - Success 278 * - EOPNOTSUPP - Operation not supported 279 */ 280 static int 281 tf_rm_check_residuals(struct tf_rm_new_db *rm_db, 282 uint16_t *resv_size, 283 struct tf_rm_resc_entry **resv, 284 bool *residuals_present) 285 { 286 int rc; 287 int i; 288 int f; 289 uint16_t count; 290 uint16_t found; 291 uint16_t *residuals = NULL; 292 uint16_t hcapi_type; 293 struct tf_rm_get_inuse_count_parms iparms; 294 struct tf_rm_get_alloc_info_parms aparms; 295 struct tf_rm_get_hcapi_parms hparms; 296 struct tf_rm_alloc_info info; 297 struct tfp_calloc_parms cparms; 298 struct tf_rm_resc_entry *local_resv = NULL; 299 300 /* Create array to hold the entries that have residuals */ 301 cparms.nitems = rm_db->num_entries; 302 cparms.size = sizeof(uint16_t); 303 cparms.alignment = 0; 304 rc = tfp_calloc(&cparms); 305 if (rc) 306 return rc; 307 308 residuals = (uint16_t *)cparms.mem_va; 309 310 /* Traverse the DB and collect any residual elements */ 311 iparms.rm_db = rm_db; 312 iparms.count = &count; 313 for (i = 0, found = 0; i < rm_db->num_entries; i++) { 314 iparms.subtype = i; 315 rc = tf_rm_get_inuse_count(&iparms); 316 /* Not a device supported entry, just skip */ 317 if (rc == -ENOTSUP) 318 continue; 319 if (rc) 320 goto cleanup_residuals; 321 322 if (count) { 323 found++; 324 residuals[i] = count; 325 *residuals_present = true; 326 } 327 } 328 329 if (*residuals_present) { 330 /* Populate a reduced resv array with only the entries 331 * that have residuals. 332 */ 333 cparms.nitems = found; 334 cparms.size = sizeof(struct tf_rm_resc_entry); 335 cparms.alignment = 0; 336 rc = tfp_calloc(&cparms); 337 if (rc) 338 return rc; 339 340 local_resv = (struct tf_rm_resc_entry *)cparms.mem_va; 341 342 aparms.rm_db = rm_db; 343 hparms.rm_db = rm_db; 344 hparms.hcapi_type = &hcapi_type; 345 for (i = 0, f = 0; i < rm_db->num_entries; i++) { 346 if (residuals[i] == 0) 347 continue; 348 aparms.subtype = i; 349 aparms.info = &info; 350 rc = tf_rm_get_info(&aparms); 351 if (rc) 352 goto cleanup_all; 353 354 hparms.subtype = i; 355 rc = tf_rm_get_hcapi_type(&hparms); 356 if (rc) 357 goto cleanup_all; 358 359 local_resv[f].type = hcapi_type; 360 local_resv[f].start = info.entry.start; 361 local_resv[f].stride = info.entry.stride; 362 f++; 363 } 364 *resv_size = found; 365 } 366 367 #if (TF_RM_DEBUG == 1) 368 tf_rm_log_residuals(rm_db->dir, 369 rm_db->module, 370 rm_db->num_entries, 371 residuals); 372 #endif 373 tfp_free((void *)residuals); 374 *resv = local_resv; 375 376 return 0; 377 378 cleanup_all: 379 tfp_free((void *)local_resv); 380 *resv = NULL; 381 cleanup_residuals: 382 tfp_free((void *)residuals); 383 384 return rc; 385 } 386 387 /** 388 * Some resources do not have a 1:1 mapping between the Truflow type and the cfa 389 * resource type (HCAPI RM). These resources have multiple Truflow types which 390 * map to a single HCAPI RM type. In order to support this, one Truflow type 391 * sharing the HCAPI resources is designated the parent. All other Truflow 392 * types associated with that HCAPI RM type are designated the children. 393 * 394 * This function updates the resource counts of any HCAPI_BA_PARENT with the 395 * counts of the HCAPI_BA_CHILDREN. These are read from the alloc_cnt and 396 * written back to the req_cnt. 397 * 398 * [in] cfg 399 * Pointer to an array of module specific Truflow type indexed RM cfg items 400 * 401 * [in] alloc_cnt 402 * Pointer to the tf_open_session() configured array of module specific 403 * Truflow type indexed requested counts. 404 * 405 * [in/out] req_cnt 406 * Pointer to the location to put the updated resource counts. 407 * 408 * Returns: 409 * 0 - Success 410 * - - Failure if negative 411 */ 412 static int 413 tf_rm_update_parent_reservations(struct tf *tfp, 414 struct tf_dev_info *dev, 415 struct tf_rm_element_cfg *cfg, 416 uint16_t *alloc_cnt, 417 uint16_t num_elements, 418 uint16_t *req_cnt, 419 bool shared_session) 420 { 421 int parent, child; 422 const char *type_str; 423 424 /* Search through all the elements */ 425 for (parent = 0; parent < num_elements; parent++) { 426 uint16_t combined_cnt = 0; 427 428 /* If I am a parent */ 429 if (cfg[parent].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { 430 uint8_t p_slices = 1; 431 432 /* Shared session doesn't support slices */ 433 if (!shared_session) 434 p_slices = cfg[parent].slices; 435 436 RTE_ASSERT(p_slices); 437 438 combined_cnt = alloc_cnt[parent] / p_slices; 439 440 if (alloc_cnt[parent] % p_slices) 441 combined_cnt++; 442 443 if (alloc_cnt[parent]) { 444 dev->ops->tf_dev_get_resource_str(tfp, 445 cfg[parent].hcapi_type, 446 &type_str); 447 #if (TF_RM_DEBUG == 1) 448 printf("%s:%s cnt(%d) slices(%d)\n", 449 type_str, tf_tbl_type_2_str(parent), 450 alloc_cnt[parent], p_slices); 451 #endif /* (TF_RM_DEBUG == 1) */ 452 } 453 454 /* Search again through all the elements */ 455 for (child = 0; child < num_elements; child++) { 456 /* If this is one of my children */ 457 if (cfg[child].cfg_type == 458 TF_RM_ELEM_CFG_HCAPI_BA_CHILD && 459 cfg[child].parent_subtype == parent && 460 alloc_cnt[child]) { 461 uint8_t c_slices = 1; 462 uint16_t cnt = 0; 463 464 if (!shared_session) 465 c_slices = cfg[child].slices; 466 467 RTE_ASSERT(c_slices); 468 469 dev->ops->tf_dev_get_resource_str(tfp, 470 cfg[child].hcapi_type, 471 &type_str); 472 #if (TF_RM_DEBUG == 1) 473 printf("%s:%s cnt(%d) slices(%d)\n", 474 type_str, 475 tf_tbl_type_2_str(child), 476 alloc_cnt[child], 477 c_slices); 478 #endif /* (TF_RM_DEBUG == 1) */ 479 /* Increment the parents combined count 480 * with each child's count adjusted for 481 * number of slices per RM alloc item. 482 */ 483 cnt = alloc_cnt[child] / c_slices; 484 485 if (alloc_cnt[child] % c_slices) 486 cnt++; 487 488 combined_cnt += cnt; 489 /* Clear the requested child count */ 490 req_cnt[child] = 0; 491 } 492 } 493 /* Save the parent count to be requested */ 494 req_cnt[parent] = combined_cnt; 495 #if (TF_RM_DEBUG == 1) 496 printf("%s calculated total:%d\n\n", 497 type_str, req_cnt[parent]); 498 #endif /* (TF_RM_DEBUG == 1) */ 499 } 500 } 501 return 0; 502 } 503 504 int 505 tf_rm_create_db(struct tf *tfp, 506 struct tf_rm_create_db_parms *parms) 507 { 508 int rc; 509 struct tf_session *tfs; 510 struct tf_dev_info *dev; 511 int i, j; 512 uint16_t max_types, hcapi_items, *req_cnt; 513 struct tfp_calloc_parms cparms; 514 struct tf_rm_resc_req_entry *query; 515 enum tf_rm_resc_resv_strategy resv_strategy; 516 struct tf_rm_resc_req_entry *req; 517 struct tf_rm_resc_entry *resv; 518 struct tf_rm_new_db *rm_db; 519 struct tf_rm_element *db; 520 uint32_t pool_size; 521 bool shared_session = 0; 522 523 TF_CHECK_PARMS2(tfp, parms); 524 525 /* Retrieve the session information */ 526 rc = tf_session_get_session_internal(tfp, &tfs); 527 if (rc) 528 return rc; 529 530 /* Retrieve device information */ 531 rc = tf_session_get_device(tfs, &dev); 532 if (rc) 533 return rc; 534 535 /* Need device max number of elements for the RM QCAPS */ 536 rc = dev->ops->tf_dev_get_max_types(tfp, &max_types); 537 538 /* Allocate memory for RM QCAPS request */ 539 cparms.nitems = max_types; 540 cparms.size = sizeof(struct tf_rm_resc_req_entry); 541 cparms.alignment = 0; 542 rc = tfp_calloc(&cparms); 543 if (rc) 544 return rc; 545 546 query = (struct tf_rm_resc_req_entry *)cparms.mem_va; 547 548 /* Get Firmware Capabilities */ 549 rc = tf_msg_session_resc_qcaps(tfp, 550 dev, 551 parms->dir, 552 max_types, 553 query, 554 &resv_strategy, 555 NULL); 556 if (rc) 557 return rc; 558 559 /* Copy requested counts (alloc_cnt) from tf_open_session() to local 560 * copy (req_cnt) so that it can be updated if required. 561 */ 562 563 cparms.nitems = parms->num_elements; 564 cparms.size = sizeof(uint16_t); 565 rc = tfp_calloc(&cparms); 566 if (rc) 567 return rc; 568 569 req_cnt = (uint16_t *)cparms.mem_va; 570 571 tfp_memcpy(req_cnt, parms->alloc_cnt, 572 parms->num_elements * sizeof(uint16_t)); 573 574 shared_session = tf_session_is_shared_session(tfs); 575 576 /* Update the req_cnt based upon the element configuration 577 */ 578 tf_rm_update_parent_reservations(tfp, dev, parms->cfg, 579 parms->alloc_cnt, 580 parms->num_elements, 581 req_cnt, 582 shared_session); 583 584 /* Process capabilities against DB requirements. However, as a 585 * DB can hold elements that are not HCAPI we can reduce the 586 * req msg content by removing those out of the request yet 587 * the DB holds them all as to give a fast lookup. We can also 588 * remove entries where there are no request for elements. 589 */ 590 tf_rm_count_hcapi_reservations(parms->dir, 591 parms->module, 592 parms->cfg, 593 req_cnt, 594 parms->num_elements, 595 &hcapi_items); 596 597 if (hcapi_items == 0) { 598 #if (TF_RM_DEBUG == 1) 599 TFP_DRV_LOG(INFO, 600 "%s: module: %s Empty RM DB create request\n", 601 tf_dir_2_str(parms->dir), 602 tf_module_2_str(parms->module)); 603 #endif 604 parms->rm_db = NULL; 605 return -ENOMEM; 606 } 607 608 /* Alloc request, alignment already set */ 609 cparms.nitems = (size_t)hcapi_items; 610 cparms.size = sizeof(struct tf_rm_resc_req_entry); 611 rc = tfp_calloc(&cparms); 612 if (rc) 613 return rc; 614 req = (struct tf_rm_resc_req_entry *)cparms.mem_va; 615 616 /* Alloc reservation, alignment and nitems already set */ 617 cparms.size = sizeof(struct tf_rm_resc_entry); 618 rc = tfp_calloc(&cparms); 619 if (rc) 620 return rc; 621 resv = (struct tf_rm_resc_entry *)cparms.mem_va; 622 623 /* Build the request */ 624 for (i = 0, j = 0; i < parms->num_elements; i++) { 625 struct tf_rm_element_cfg *cfg = &parms->cfg[i]; 626 uint16_t hcapi_type = cfg->hcapi_type; 627 628 /* Only perform reservation for requested entries 629 */ 630 if (req_cnt[i] == 0) 631 continue; 632 633 /* Skip any children in the request */ 634 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI || 635 cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || 636 cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { 637 638 /* Verify that we can get the full amount per qcaps. 639 */ 640 if (req_cnt[i] <= query[hcapi_type].max) { 641 req[j].type = hcapi_type; 642 req[j].min = req_cnt[i]; 643 req[j].max = req_cnt[i]; 644 j++; 645 } else { 646 const char *type_str; 647 648 dev->ops->tf_dev_get_resource_str(tfp, 649 hcapi_type, 650 &type_str); 651 TFP_DRV_LOG(ERR, 652 "Failure, %s:%d:%s req:%d avail:%d\n", 653 tf_dir_2_str(parms->dir), 654 hcapi_type, type_str, 655 req_cnt[i], 656 query[hcapi_type].max); 657 return -EINVAL; 658 } 659 } 660 } 661 662 /* Allocate all resources for the module type 663 */ 664 rc = tf_msg_session_resc_alloc(tfp, 665 dev, 666 parms->dir, 667 hcapi_items, 668 req, 669 resv); 670 if (rc) 671 return rc; 672 673 /* Build the RM DB per the request */ 674 cparms.nitems = 1; 675 cparms.size = sizeof(struct tf_rm_new_db); 676 rc = tfp_calloc(&cparms); 677 if (rc) 678 return rc; 679 rm_db = (void *)cparms.mem_va; 680 681 /* Build the DB within RM DB */ 682 cparms.nitems = parms->num_elements; 683 cparms.size = sizeof(struct tf_rm_element); 684 rc = tfp_calloc(&cparms); 685 if (rc) 686 return rc; 687 rm_db->db = (struct tf_rm_element *)cparms.mem_va; 688 689 db = rm_db->db; 690 for (i = 0, j = 0; i < parms->num_elements; i++) { 691 struct tf_rm_element_cfg *cfg = &parms->cfg[i]; 692 const char *type_str; 693 694 dev->ops->tf_dev_get_resource_str(tfp, 695 cfg->hcapi_type, 696 &type_str); 697 698 db[i].cfg_type = cfg->cfg_type; 699 db[i].hcapi_type = cfg->hcapi_type; 700 db[i].slices = cfg->slices; 701 702 /* Save the parent subtype for later use to find the pool 703 */ 704 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 705 db[i].parent_subtype = cfg->parent_subtype; 706 707 /* If the element didn't request an allocation no need 708 * to create a pool nor verify if we got a reservation. 709 */ 710 if (req_cnt[i] == 0) 711 continue; 712 713 /* Skip any children or invalid 714 */ 715 if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI && 716 cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 717 cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT) 718 continue; 719 720 /* If the element had requested an allocation and that 721 * allocation was a success (full amount) then 722 * allocate the pool. 723 */ 724 if (req_cnt[i] == resv[j].stride) { 725 db[i].alloc.entry.start = resv[j].start; 726 db[i].alloc.entry.stride = resv[j].stride; 727 728 /* Only allocate BA pool if a BA type not a child */ 729 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || 730 cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { 731 /* Create pool */ 732 pool_size = (BITALLOC_SIZEOF(resv[j].stride) / 733 sizeof(struct bitalloc)); 734 /* Alloc request, alignment already set */ 735 cparms.nitems = pool_size; 736 cparms.size = sizeof(struct bitalloc); 737 rc = tfp_calloc(&cparms); 738 if (rc) { 739 TFP_DRV_LOG(ERR, 740 "%s: Pool alloc failed, type:%d:%s\n", 741 tf_dir_2_str(parms->dir), 742 cfg->hcapi_type, type_str); 743 goto fail; 744 } 745 db[i].pool = (struct bitalloc *)cparms.mem_va; 746 747 rc = ba_init(db[i].pool, 748 resv[j].stride, 749 !tf_session_is_shared_session(tfs)); 750 if (rc) { 751 TFP_DRV_LOG(ERR, 752 "%s: Pool init failed, type:%d:%s\n", 753 tf_dir_2_str(parms->dir), 754 cfg->hcapi_type, type_str); 755 goto fail; 756 } 757 } 758 j++; 759 } else { 760 /* Bail out as we want what we requested for 761 * all elements, not any less. 762 */ 763 TFP_DRV_LOG(ERR, 764 "%s: Alloc failed %d:%s req:%d, alloc:%d\n", 765 tf_dir_2_str(parms->dir), cfg->hcapi_type, 766 type_str, req_cnt[i], resv[j].stride); 767 goto fail; 768 } 769 } 770 771 rm_db->num_entries = parms->num_elements; 772 rm_db->dir = parms->dir; 773 rm_db->module = parms->module; 774 *parms->rm_db = (void *)rm_db; 775 776 #if (TF_RM_DEBUG == 1) 777 778 printf("%s: module:%s\n", 779 tf_dir_2_str(parms->dir), 780 tf_module_2_str(parms->module)); 781 #endif /* (TF_RM_DEBUG == 1) */ 782 783 tfp_free((void *)req); 784 tfp_free((void *)resv); 785 tfp_free((void *)req_cnt); 786 return 0; 787 788 fail: 789 tfp_free((void *)req); 790 tfp_free((void *)resv); 791 tfp_free((void *)db->pool); 792 tfp_free((void *)db); 793 tfp_free((void *)rm_db); 794 tfp_free((void *)req_cnt); 795 parms->rm_db = NULL; 796 797 return -EINVAL; 798 } 799 800 int 801 tf_rm_create_db_no_reservation(struct tf *tfp, 802 struct tf_rm_create_db_parms *parms) 803 { 804 int rc; 805 struct tf_session *tfs; 806 struct tf_dev_info *dev; 807 int i, j; 808 uint16_t hcapi_items, *req_cnt; 809 struct tfp_calloc_parms cparms; 810 struct tf_rm_resc_req_entry *req; 811 struct tf_rm_resc_entry *resv; 812 struct tf_rm_new_db *rm_db; 813 struct tf_rm_element *db; 814 uint32_t pool_size; 815 816 TF_CHECK_PARMS2(tfp, parms); 817 818 /* Retrieve the session information */ 819 rc = tf_session_get_session_internal(tfp, &tfs); 820 if (rc) 821 return rc; 822 823 /* Retrieve device information */ 824 rc = tf_session_get_device(tfs, &dev); 825 if (rc) 826 return rc; 827 828 /* Copy requested counts (alloc_cnt) from tf_open_session() to local 829 * copy (req_cnt) so that it can be updated if required. 830 */ 831 832 cparms.nitems = parms->num_elements; 833 cparms.size = sizeof(uint16_t); 834 cparms.alignment = 0; 835 rc = tfp_calloc(&cparms); 836 if (rc) 837 return rc; 838 839 req_cnt = (uint16_t *)cparms.mem_va; 840 841 tfp_memcpy(req_cnt, parms->alloc_cnt, 842 parms->num_elements * sizeof(uint16_t)); 843 844 /* Process capabilities against DB requirements. However, as a 845 * DB can hold elements that are not HCAPI we can reduce the 846 * req msg content by removing those out of the request yet 847 * the DB holds them all as to give a fast lookup. We can also 848 * remove entries where there are no request for elements. 849 */ 850 tf_rm_count_hcapi_reservations(parms->dir, 851 parms->module, 852 parms->cfg, 853 req_cnt, 854 parms->num_elements, 855 &hcapi_items); 856 857 if (hcapi_items == 0) { 858 TFP_DRV_LOG(ERR, 859 "%s: module:%s Empty RM DB create request\n", 860 tf_dir_2_str(parms->dir), 861 tf_module_2_str(parms->module)); 862 863 parms->rm_db = NULL; 864 return -ENOMEM; 865 } 866 867 /* Alloc request, alignment already set */ 868 cparms.nitems = (size_t)hcapi_items; 869 cparms.size = sizeof(struct tf_rm_resc_req_entry); 870 rc = tfp_calloc(&cparms); 871 if (rc) 872 return rc; 873 req = (struct tf_rm_resc_req_entry *)cparms.mem_va; 874 875 /* Alloc reservation, alignment and nitems already set */ 876 cparms.size = sizeof(struct tf_rm_resc_entry); 877 rc = tfp_calloc(&cparms); 878 if (rc) 879 return rc; 880 resv = (struct tf_rm_resc_entry *)cparms.mem_va; 881 882 /* Build the request */ 883 for (i = 0, j = 0; i < parms->num_elements; i++) { 884 struct tf_rm_element_cfg *cfg = &parms->cfg[i]; 885 uint16_t hcapi_type = cfg->hcapi_type; 886 887 /* Only perform reservation for requested entries 888 */ 889 if (req_cnt[i] == 0) 890 continue; 891 892 /* Skip any children in the request */ 893 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI || 894 cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || 895 cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { 896 req[j].type = hcapi_type; 897 req[j].min = req_cnt[i]; 898 req[j].max = req_cnt[i]; 899 j++; 900 } 901 } 902 903 /* Get all resources info for the module type 904 */ 905 rc = tf_msg_session_resc_info(tfp, 906 dev, 907 parms->dir, 908 hcapi_items, 909 req, 910 resv); 911 if (rc) 912 return rc; 913 914 /* Build the RM DB per the request */ 915 cparms.nitems = 1; 916 cparms.size = sizeof(struct tf_rm_new_db); 917 rc = tfp_calloc(&cparms); 918 if (rc) 919 return rc; 920 rm_db = (void *)cparms.mem_va; 921 922 /* Build the DB within RM DB */ 923 cparms.nitems = parms->num_elements; 924 cparms.size = sizeof(struct tf_rm_element); 925 rc = tfp_calloc(&cparms); 926 if (rc) 927 return rc; 928 rm_db->db = (struct tf_rm_element *)cparms.mem_va; 929 930 db = rm_db->db; 931 for (i = 0, j = 0; i < parms->num_elements; i++) { 932 struct tf_rm_element_cfg *cfg = &parms->cfg[i]; 933 const char *type_str; 934 935 dev->ops->tf_dev_get_resource_str(tfp, 936 cfg->hcapi_type, 937 &type_str); 938 939 db[i].cfg_type = cfg->cfg_type; 940 db[i].hcapi_type = cfg->hcapi_type; 941 942 /* Save the parent subtype for later use to find the pool 943 */ 944 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 945 db[i].parent_subtype = cfg->parent_subtype; 946 947 /* If the element didn't request an allocation no need 948 * to create a pool nor verify if we got a reservation. 949 */ 950 if (req_cnt[i] == 0) 951 continue; 952 953 /* Skip any children or invalid 954 */ 955 if (cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI && 956 cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 957 cfg->cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT) 958 continue; 959 960 /* If the element had requested an allocation and that 961 * allocation was a success (full amount) then 962 * allocate the pool. 963 */ 964 if (req_cnt[i] == resv[j].stride) { 965 db[i].alloc.entry.start = resv[j].start; 966 db[i].alloc.entry.stride = resv[j].stride; 967 968 /* Only allocate BA pool if a BA type not a child */ 969 if (cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA || 970 cfg->cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_PARENT) { 971 /* Create pool */ 972 pool_size = (BITALLOC_SIZEOF(resv[j].stride) / 973 sizeof(struct bitalloc)); 974 /* Alloc request, alignment already set */ 975 cparms.nitems = pool_size; 976 cparms.size = sizeof(struct bitalloc); 977 rc = tfp_calloc(&cparms); 978 if (rc) { 979 TFP_DRV_LOG(ERR, 980 "%s: Pool alloc failed, type:%d:%s\n", 981 tf_dir_2_str(parms->dir), 982 cfg->hcapi_type, type_str); 983 goto fail; 984 } 985 db[i].pool = (struct bitalloc *)cparms.mem_va; 986 987 rc = ba_init(db[i].pool, 988 resv[j].stride, 989 !tf_session_is_shared_session(tfs)); 990 if (rc) { 991 TFP_DRV_LOG(ERR, 992 "%s: Pool init failed, type:%d:%s\n", 993 tf_dir_2_str(parms->dir), 994 cfg->hcapi_type, type_str); 995 goto fail; 996 } 997 } 998 j++; 999 } else { 1000 /* Bail out as we want what we requested for 1001 * all elements, not any less. 1002 */ 1003 TFP_DRV_LOG(ERR, 1004 "%s: Alloc failed %d:%s req:%d, alloc:%d\n", 1005 tf_dir_2_str(parms->dir), cfg->hcapi_type, 1006 type_str, req_cnt[i], resv[j].stride); 1007 goto fail; 1008 } 1009 } 1010 1011 rm_db->num_entries = parms->num_elements; 1012 rm_db->dir = parms->dir; 1013 rm_db->module = parms->module; 1014 *parms->rm_db = (void *)rm_db; 1015 1016 #if (TF_RM_DEBUG == 1) 1017 1018 printf("%s: module:%s\n", 1019 tf_dir_2_str(parms->dir), 1020 tf_module_2_str(parms->module)); 1021 #endif /* (TF_RM_DEBUG == 1) */ 1022 1023 tfp_free((void *)req); 1024 tfp_free((void *)resv); 1025 tfp_free((void *)req_cnt); 1026 return 0; 1027 1028 fail: 1029 tfp_free((void *)req); 1030 tfp_free((void *)resv); 1031 tfp_free((void *)db->pool); 1032 tfp_free((void *)db); 1033 tfp_free((void *)rm_db); 1034 tfp_free((void *)req_cnt); 1035 parms->rm_db = NULL; 1036 1037 return -EINVAL; 1038 } 1039 int 1040 tf_rm_free_db(struct tf *tfp, 1041 struct tf_rm_free_db_parms *parms) 1042 { 1043 int rc; 1044 int i; 1045 uint16_t resv_size = 0; 1046 struct tf_rm_new_db *rm_db; 1047 struct tf_rm_resc_entry *resv; 1048 bool residuals_found = false; 1049 1050 TF_CHECK_PARMS2(parms, parms->rm_db); 1051 1052 /* Device unbind happens when the TF Session is closed and the 1053 * session ref count is 0. Device unbind will cleanup each of 1054 * its support modules, i.e. Identifier, thus we're ending up 1055 * here to close the DB. 1056 * 1057 * On TF Session close it is assumed that the session has already 1058 * cleaned up all its resources, individually, while 1059 * destroying its flows. 1060 * 1061 * To assist in the 'cleanup checking' the DB is checked for any 1062 * remaining elements and logged if found to be the case. 1063 * 1064 * Any such elements will need to be 'cleared' ahead of 1065 * returning the resources to the HCAPI RM. 1066 * 1067 * RM will signal FW to flush the DB resources. FW will 1068 * perform the invalidation. TF Session close will return the 1069 * previous allocated elements to the RM and then close the 1070 * HCAPI RM registration. That then saves several 'free' msgs 1071 * from being required. 1072 */ 1073 1074 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1075 1076 /* Check for residuals that the client didn't clean up */ 1077 rc = tf_rm_check_residuals(rm_db, 1078 &resv_size, 1079 &resv, 1080 &residuals_found); 1081 if (rc) 1082 return rc; 1083 1084 /* Invalidate any residuals followed by a DB traversal for 1085 * pool cleanup. 1086 */ 1087 if (residuals_found) { 1088 rc = tf_msg_session_resc_flush(tfp, 1089 parms->dir, 1090 resv_size, 1091 resv); 1092 tfp_free((void *)resv); 1093 /* On failure we still have to cleanup so we can only 1094 * log that FW failed. 1095 */ 1096 if (rc) 1097 TFP_DRV_LOG(ERR, 1098 "%s: Internal Flush error, module:%s\n", 1099 tf_dir_2_str(parms->dir), 1100 tf_module_2_str(rm_db->module)); 1101 } 1102 1103 /* No need to check for configuration type, even if we do not 1104 * have a BA pool we just delete on a null ptr, no harm 1105 */ 1106 for (i = 0; i < rm_db->num_entries; i++) 1107 tfp_free((void *)rm_db->db[i].pool); 1108 1109 tfp_free((void *)parms->rm_db); 1110 1111 return rc; 1112 } 1113 /** 1114 * Get the bit allocator pool associated with the subtype and the db 1115 * 1116 * [in] rm_db 1117 * Pointer to the DB 1118 * 1119 * [in] subtype 1120 * Module subtype used to index into the module specific database. 1121 * An example subtype is TF_TBL_TYPE_FULL_ACT_RECORD which is a 1122 * module subtype of TF_MODULE_TYPE_TABLE. 1123 * 1124 * [in/out] pool 1125 * Pointer to the bit allocator pool used 1126 * 1127 * [in/out] new_subtype 1128 * Pointer to the subtype of the actual pool used 1129 * Returns: 1130 * 0 - Success 1131 * - ENOTSUP - Operation not supported 1132 */ 1133 static int 1134 tf_rm_get_pool(struct tf_rm_new_db *rm_db, 1135 uint16_t subtype, 1136 struct bitalloc **pool, 1137 uint16_t *new_subtype) 1138 { 1139 int rc = 0; 1140 uint16_t tmp_subtype = subtype; 1141 1142 /* If we are a child, get the parent table index */ 1143 if (rm_db->db[subtype].cfg_type == TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 1144 tmp_subtype = rm_db->db[subtype].parent_subtype; 1145 1146 *pool = rm_db->db[tmp_subtype].pool; 1147 1148 /* Bail out if the pool is not valid, should never happen */ 1149 if (rm_db->db[tmp_subtype].pool == NULL) { 1150 rc = -ENOTSUP; 1151 TFP_DRV_LOG(ERR, 1152 "%s: Invalid pool for this type:%d, rc:%s\n", 1153 tf_dir_2_str(rm_db->dir), 1154 tmp_subtype, 1155 strerror(-rc)); 1156 return rc; 1157 } 1158 *new_subtype = tmp_subtype; 1159 return rc; 1160 } 1161 1162 int 1163 tf_rm_allocate(struct tf_rm_allocate_parms *parms) 1164 { 1165 int rc; 1166 int id; 1167 uint32_t index; 1168 struct tf_rm_new_db *rm_db; 1169 enum tf_rm_elem_cfg_type cfg_type; 1170 struct bitalloc *pool; 1171 uint16_t subtype; 1172 1173 TF_CHECK_PARMS2(parms, parms->rm_db); 1174 1175 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1176 TF_CHECK_PARMS1(rm_db->db); 1177 1178 cfg_type = rm_db->db[parms->subtype].cfg_type; 1179 1180 /* Bail out if not controlled by RM */ 1181 if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 1182 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && 1183 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 1184 return -ENOTSUP; 1185 1186 rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); 1187 if (rc) 1188 return rc; 1189 /* 1190 * priority 0: allocate from top of the tcam i.e. high 1191 * priority !0: allocate index from bottom i.e lowest 1192 */ 1193 if (parms->priority) 1194 id = ba_alloc_reverse(pool); 1195 else 1196 id = ba_alloc(pool); 1197 if (id == BA_FAIL) { 1198 rc = -ENOMEM; 1199 TFP_DRV_LOG(ERR, 1200 "%s: Allocation failed, rc:%s\n", 1201 tf_dir_2_str(rm_db->dir), 1202 strerror(-rc)); 1203 return rc; 1204 } 1205 1206 /* Adjust for any non zero start value */ 1207 rc = tf_rm_adjust_index(rm_db->db, 1208 TF_RM_ADJUST_ADD_BASE, 1209 subtype, 1210 id, 1211 &index); 1212 if (rc) { 1213 TFP_DRV_LOG(ERR, 1214 "%s: Alloc adjust of base index failed, rc:%s\n", 1215 tf_dir_2_str(rm_db->dir), 1216 strerror(-rc)); 1217 return -EINVAL; 1218 } 1219 1220 *parms->index = index; 1221 if (parms->base_index) 1222 *parms->base_index = id; 1223 1224 return rc; 1225 } 1226 1227 int 1228 tf_rm_free(struct tf_rm_free_parms *parms) 1229 { 1230 int rc; 1231 uint32_t adj_index; 1232 struct tf_rm_new_db *rm_db; 1233 enum tf_rm_elem_cfg_type cfg_type; 1234 struct bitalloc *pool; 1235 uint16_t subtype; 1236 1237 TF_CHECK_PARMS2(parms, parms->rm_db); 1238 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1239 TF_CHECK_PARMS1(rm_db->db); 1240 1241 cfg_type = rm_db->db[parms->subtype].cfg_type; 1242 1243 /* Bail out if not controlled by RM */ 1244 if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 1245 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && 1246 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 1247 return -ENOTSUP; 1248 1249 rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); 1250 if (rc) 1251 return rc; 1252 1253 /* Adjust for any non zero start value */ 1254 rc = tf_rm_adjust_index(rm_db->db, 1255 TF_RM_ADJUST_RM_BASE, 1256 subtype, 1257 parms->index, 1258 &adj_index); 1259 if (rc) 1260 return rc; 1261 1262 rc = ba_free(pool, adj_index); 1263 /* No logging direction matters and that is not available here */ 1264 if (rc) 1265 return rc; 1266 1267 return rc; 1268 } 1269 1270 int 1271 tf_rm_is_allocated(struct tf_rm_is_allocated_parms *parms) 1272 { 1273 int rc; 1274 uint32_t adj_index; 1275 struct tf_rm_new_db *rm_db; 1276 enum tf_rm_elem_cfg_type cfg_type; 1277 struct bitalloc *pool; 1278 uint16_t subtype; 1279 1280 TF_CHECK_PARMS2(parms, parms->rm_db); 1281 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1282 TF_CHECK_PARMS1(rm_db->db); 1283 1284 cfg_type = rm_db->db[parms->subtype].cfg_type; 1285 1286 /* Bail out if not controlled by RM */ 1287 if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 1288 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && 1289 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 1290 return -ENOTSUP; 1291 1292 rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); 1293 if (rc) 1294 return rc; 1295 1296 /* Adjust for any non zero start value */ 1297 rc = tf_rm_adjust_index(rm_db->db, 1298 TF_RM_ADJUST_RM_BASE, 1299 subtype, 1300 parms->index, 1301 &adj_index); 1302 if (rc) 1303 return rc; 1304 1305 if (parms->base_index) 1306 *parms->base_index = adj_index; 1307 *parms->allocated = ba_inuse(pool, adj_index); 1308 1309 return rc; 1310 } 1311 1312 int 1313 tf_rm_get_info(struct tf_rm_get_alloc_info_parms *parms) 1314 { 1315 struct tf_rm_new_db *rm_db; 1316 enum tf_rm_elem_cfg_type cfg_type; 1317 1318 TF_CHECK_PARMS2(parms, parms->rm_db); 1319 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1320 TF_CHECK_PARMS1(rm_db->db); 1321 1322 cfg_type = rm_db->db[parms->subtype].cfg_type; 1323 1324 /* Bail out if not controlled by HCAPI */ 1325 if (cfg_type == TF_RM_ELEM_CFG_NULL) 1326 return -ENOTSUP; 1327 1328 memcpy(parms->info, 1329 &rm_db->db[parms->subtype].alloc, 1330 sizeof(struct tf_rm_alloc_info)); 1331 1332 return 0; 1333 } 1334 1335 int 1336 tf_rm_get_all_info(struct tf_rm_get_alloc_info_parms *parms, int size) 1337 { 1338 struct tf_rm_new_db *rm_db; 1339 enum tf_rm_elem_cfg_type cfg_type; 1340 struct tf_rm_alloc_info *info = parms->info; 1341 int i; 1342 1343 TF_CHECK_PARMS1(parms); 1344 1345 /* No rm info available for this module type 1346 */ 1347 if (!parms->rm_db) 1348 return -ENOMEM; 1349 1350 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1351 TF_CHECK_PARMS1(rm_db->db); 1352 1353 for (i = 0; i < size; i++) { 1354 cfg_type = rm_db->db[i].cfg_type; 1355 1356 /* Bail out if not controlled by HCAPI */ 1357 if (cfg_type == TF_RM_ELEM_CFG_NULL) { 1358 info++; 1359 continue; 1360 } 1361 1362 memcpy(info, 1363 &rm_db->db[i].alloc, 1364 sizeof(struct tf_rm_alloc_info)); 1365 info++; 1366 } 1367 1368 return 0; 1369 } 1370 1371 int 1372 tf_rm_get_hcapi_type(struct tf_rm_get_hcapi_parms *parms) 1373 { 1374 struct tf_rm_new_db *rm_db; 1375 enum tf_rm_elem_cfg_type cfg_type; 1376 1377 TF_CHECK_PARMS2(parms, parms->rm_db); 1378 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1379 TF_CHECK_PARMS1(rm_db->db); 1380 1381 cfg_type = rm_db->db[parms->subtype].cfg_type; 1382 1383 /* Bail out if not controlled by HCAPI */ 1384 if (cfg_type == TF_RM_ELEM_CFG_NULL) 1385 return -ENOTSUP; 1386 1387 *parms->hcapi_type = rm_db->db[parms->subtype].hcapi_type; 1388 1389 return 0; 1390 } 1391 int 1392 tf_rm_get_slices(struct tf_rm_get_slices_parms *parms) 1393 { 1394 struct tf_rm_new_db *rm_db; 1395 enum tf_rm_elem_cfg_type cfg_type; 1396 1397 TF_CHECK_PARMS2(parms, parms->rm_db); 1398 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1399 TF_CHECK_PARMS1(rm_db->db); 1400 1401 cfg_type = rm_db->db[parms->subtype].cfg_type; 1402 1403 /* Bail out if not controlled by HCAPI */ 1404 if (cfg_type == TF_RM_ELEM_CFG_NULL) 1405 return -ENOTSUP; 1406 1407 *parms->slices = rm_db->db[parms->subtype].slices; 1408 1409 return 0; 1410 } 1411 1412 int 1413 tf_rm_get_inuse_count(struct tf_rm_get_inuse_count_parms *parms) 1414 { 1415 int rc = 0; 1416 struct tf_rm_new_db *rm_db; 1417 enum tf_rm_elem_cfg_type cfg_type; 1418 1419 TF_CHECK_PARMS2(parms, parms->rm_db); 1420 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1421 TF_CHECK_PARMS1(rm_db->db); 1422 1423 cfg_type = rm_db->db[parms->subtype].cfg_type; 1424 1425 /* Bail out if not a BA pool */ 1426 if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 1427 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && 1428 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 1429 return -ENOTSUP; 1430 1431 /* Bail silently (no logging), if the pool is not valid there 1432 * was no elements allocated for it. 1433 */ 1434 if (rm_db->db[parms->subtype].pool == NULL) { 1435 *parms->count = 0; 1436 return 0; 1437 } 1438 1439 *parms->count = ba_inuse_count(rm_db->db[parms->subtype].pool); 1440 1441 return rc; 1442 } 1443 /* Only used for table bulk get at this time 1444 */ 1445 int 1446 tf_rm_check_indexes_in_range(struct tf_rm_check_indexes_in_range_parms *parms) 1447 { 1448 struct tf_rm_new_db *rm_db; 1449 enum tf_rm_elem_cfg_type cfg_type; 1450 uint32_t base_index; 1451 uint32_t stride; 1452 int rc = 0; 1453 struct bitalloc *pool; 1454 uint16_t subtype; 1455 1456 TF_CHECK_PARMS2(parms, parms->rm_db); 1457 rm_db = (struct tf_rm_new_db *)parms->rm_db; 1458 TF_CHECK_PARMS1(rm_db->db); 1459 1460 cfg_type = rm_db->db[parms->subtype].cfg_type; 1461 1462 /* Bail out if not a BA pool */ 1463 if (cfg_type != TF_RM_ELEM_CFG_HCAPI_BA && 1464 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_PARENT && 1465 cfg_type != TF_RM_ELEM_CFG_HCAPI_BA_CHILD) 1466 return -ENOTSUP; 1467 1468 rc = tf_rm_get_pool(rm_db, parms->subtype, &pool, &subtype); 1469 if (rc) 1470 return rc; 1471 1472 base_index = rm_db->db[subtype].alloc.entry.start; 1473 stride = rm_db->db[subtype].alloc.entry.stride; 1474 1475 if (parms->starting_index < base_index || 1476 parms->starting_index + parms->num_entries > base_index + stride) 1477 return -EINVAL; 1478 1479 return rc; 1480 } 1481