shr_resmgr.c (193175B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Global resource allocator 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/sync.h> 13 #include <sal/core/alloc.h> 14 #include <shared/error.h> 15 #include <shared/shr_resmgr.h> 16 17 18 #include <soc/cm.h> 19 20 /*****************************************************************************/ 21 /* 22 * Internal implementation 23 */ 24 25 /* 26 * This structure is global, and points to the information about all units. 27 * 28 * For each unit, it's just a pointer here, since this reduces the overall 29 * memory footprint for the case of units that do not use this mechanism, plus 30 * it allows each unit to use only as much memory as needed to describe its 31 * resources and pools and how they map. 32 */ 33 _shr_res_unit_desc_t *_g_unitResDesc[BCM_LOCAL_UNITS_MAX] = { NULL }; 34 35 /* 36 * Various function prototypes per method for the alloc managers. 37 */ 38 typedef int (*_shr_res_alloc_create)(_shr_res_pool_desc_t **desc, 39 int low_id, 40 int count, 41 const void *extras, 42 const char *name); 43 typedef int (*_shr_res_alloc_destroy)(_shr_res_pool_desc_t *desc); 44 typedef int (*_shr_res_alloc_alloc)(_shr_res_pool_desc_t *desc, 45 uint32 flags, 46 int count, 47 int *elem); 48 typedef int (*_shr_res_alloc_tag)(_shr_res_pool_desc_t *desc, 49 uint32 flags, 50 const void* tag, 51 int count, 52 int *elem); 53 typedef int (*_shr_res_alloc_align)(_shr_res_pool_desc_t *desc, 54 uint32 flags, 55 int align, 56 int offset, 57 int count, 58 int *elem); 59 typedef int (*_shr_res_alloc_align_sparse)(_shr_res_pool_desc_t *desc, 60 uint32 flags, 61 int align, 62 int offs, 63 uint32 pattern, 64 int length, 65 int repeats, 66 int *elem); 67 typedef int (*_shr_res_alloc_align_tag)(_shr_res_pool_desc_t *desc, 68 uint32 flags, 69 int align, 70 int offset, 71 const void* tag, 72 int count, 73 int *elem); 74 typedef int (*_shr_res_alloc_free)(_shr_res_pool_desc_t *desc, 75 int count, 76 int elem); 77 typedef int (*_shr_res_alloc_free_sparse)(_shr_res_pool_desc_t *desc, 78 uint32 pattern, 79 int length, 80 int repeats, 81 int elem); 82 typedef int (*_shr_res_alloc_check)(_shr_res_pool_desc_t *desc, 83 int count, 84 int elem); 85 typedef int (*_shr_res_alloc_check_all)(_shr_res_pool_desc_t *desc, 86 int count, 87 int elem); 88 typedef int (*_shr_res_alloc_check_all_sparse)(_shr_res_pool_desc_t *desc, 89 uint32 pattern, 90 int length, 91 int repeats, 92 int elem); 93 typedef int (*_shr_res_alloc_check_all_tag)(_shr_res_pool_desc_t *desc, 94 const void *tag, 95 int count, 96 int elem); 97 98 /* 99 * This structure describes a single allocator mechanism, specifically by 100 * providing a set pointers to functions that are used to manipulate it. 101 * 102 * Many functions are mandatory. Those that are optional are, in fact, 103 * mandatory in groups (all or none of the 'align' group must be provded; all 104 * or none of the 'tag' group must be provided; all or nothing of 'align_tag' 105 * must be provided, and if all is provided, all of 'align' and all of 'tag' 106 * must also be provided). 107 */ 108 typedef struct _shr_res_alloc_mgr_s { 109 _shr_res_alloc_create create; /* mandatory */ 110 _shr_res_alloc_destroy destroy; /* mandatory */ 111 _shr_res_alloc_alloc alloc; /* mandatory */ 112 _shr_res_alloc_tag tag; /* optional */ 113 _shr_res_alloc_align align; /* optional */ 114 _shr_res_alloc_align_sparse align_sparse; /* optional */ 115 _shr_res_alloc_align_tag tag_align; /* optional */ 116 _shr_res_alloc_free free; /* mandatory */ 117 _shr_res_alloc_free_sparse free_sparse; /* iff have align_sparse */ 118 _shr_res_alloc_check check; /* mandatory */ 119 _shr_res_alloc_check_all check_all; /* mandatory */ 120 _shr_res_alloc_check_all_sparse c_a_sparse; /* iff have align_sparse */ 121 _shr_res_alloc_check_all_tag check_all_tag; /* iff have tag or tag_align */ 122 char *name; 123 } _shr_res_alloc_mgr_t; 124 125 /* 126 * These prototypes are for the global const structure below that points to 127 * all of the various implementations. 128 */ 129 static int _shr_res_bitmap_create(_shr_res_pool_desc_t **desc, 130 int low_id, 131 int count, 132 const void* extras, 133 const char* name); 134 static int _shr_res_bitmap_destroy(_shr_res_pool_desc_t *desc); 135 static int _shr_res_bitmap_alloc(_shr_res_pool_desc_t *desc, 136 uint32 flags, 137 int count, 138 int *elem); 139 static int _shr_res_bitmap_alloc_align(_shr_res_pool_desc_t *desc, 140 uint32 flags, 141 int align, 142 int offs, 143 int count, 144 int *elem); 145 static int _shr_res_bitmap_alloc_align_sparse(_shr_res_pool_desc_t *desc, 146 uint32 flags, 147 int align, 148 int offs, 149 uint32 pattern, 150 int length, 151 int repeats, 152 int *elem); 153 static int _shr_res_bitmap_free(_shr_res_pool_desc_t *desc, 154 int count, 155 int elem); 156 static int _shr_res_bitmap_free_sparse(_shr_res_pool_desc_t *desc, 157 uint32 pattern, 158 int length, 159 int repeats, 160 int elem); 161 static int _shr_res_bitmap_check(_shr_res_pool_desc_t *desc, 162 int count, 163 int elem); 164 static int _shr_res_bitmap_check_all_desc(_shr_res_pool_desc_t *desc, 165 int count, 166 int elem); 167 static int _shr_res_bitmap_check_all_sparse(_shr_res_pool_desc_t *desc, 168 uint32 pattern, 169 int length, 170 int repeats, 171 int elem); 172 static int _shr_res_tag_bitmap_create(_shr_res_pool_desc_t **desc, 173 int low_id, 174 int count, 175 const void* extras, 176 const char* name); 177 static int _shr_res_tag_bitmap_destroy(_shr_res_pool_desc_t *desc); 178 static int _shr_res_tag_bitmap_alloc(_shr_res_pool_desc_t *desc, 179 uint32 flags, 180 int count, 181 int *elem); 182 static int _shr_res_tag_bitmap_alloc_tag(_shr_res_pool_desc_t *desc, 183 uint32 flags, 184 const void *tag, 185 int count, 186 int *elem); 187 static int _shr_res_tag_bitmap_alloc_align(_shr_res_pool_desc_t *desc, 188 uint32 flags, 189 int align, 190 int offs, 191 int count, 192 int *elem); 193 static int _shr_res_tag_bitmap_alloc_align_tag(_shr_res_pool_desc_t *desc, 194 uint32 flags, 195 int align, 196 int offs, 197 const void *tag, 198 int count, 199 int *elem); 200 static int _shr_res_tag_bitmap_free(_shr_res_pool_desc_t *desc, 201 int count, 202 int elem); 203 static int _shr_res_tag_bitmap_check(_shr_res_pool_desc_t *desc, 204 int count, 205 int elem); 206 static int _shr_res_tag_bitmap_check_all(_shr_res_pool_desc_t *desc, 207 int count, 208 int elem); 209 static int _shr_res_tag_bitmap_check_all_tag(_shr_res_pool_desc_t *desc, 210 const void *tag, 211 int count, 212 int elem); 213 static int _shr_res_idxres_create(_shr_res_pool_desc_t **desc, 214 int low_id, 215 int count, 216 const void* extras, 217 const char* name); 218 static int _shr_res_idxres_destroy(_shr_res_pool_desc_t *desc); 219 static int _shr_res_idxres_alloc(_shr_res_pool_desc_t *desc, 220 uint32 flags, 221 int count, 222 int *elem); 223 static int _shr_res_idxres_free(_shr_res_pool_desc_t *desc, 224 int count, 225 int elem); 226 static int _shr_res_idxres_check(_shr_res_pool_desc_t *desc, 227 int count, 228 int elem); 229 static int _shr_res_idxres_check_all(_shr_res_pool_desc_t *desc, 230 int count, 231 int elem); 232 static int _shr_res_aidxres_create(_shr_res_pool_desc_t **desc, 233 int low_id, 234 int count, 235 const void* extras, 236 const char* name); 237 static int _shr_res_aidxres_destroy(_shr_res_pool_desc_t *desc); 238 static int _shr_res_aidxres_alloc(_shr_res_pool_desc_t *desc, 239 uint32 flags, 240 int count, 241 int *elem); 242 static int _shr_res_aidxres_free(_shr_res_pool_desc_t *desc, 243 int count, 244 int elem); 245 static int _shr_res_aidxres_check(_shr_res_pool_desc_t *desc, 246 int count, 247 int elem); 248 static int _shr_res_aidxres_check_all(_shr_res_pool_desc_t *desc, 249 int count, 250 int elem); 251 static int _shr_res_mdb_create(_shr_res_pool_desc_t **desc, 252 int low_id, 253 int count, 254 const void* extras, 255 const char* name); 256 static int _shr_res_mdb_destroy(_shr_res_pool_desc_t *desc); 257 static int _shr_res_mdb_alloc(_shr_res_pool_desc_t *desc, 258 uint32 flags, 259 int count, 260 int *elem); 261 static int _shr_res_mdb_free(_shr_res_pool_desc_t *desc, 262 int count, 263 int elem); 264 static int _shr_res_mdb_check(_shr_res_pool_desc_t *desc, 265 int count, 266 int elem); 267 static int _shr_res_mdb_check_all(_shr_res_pool_desc_t *desc, 268 int count, 269 int elem); 270 271 /* 272 * Global const structure describing the various allocator mechanisms. 273 */ 274 static const _shr_res_alloc_mgr_t _shr_res_alloc_mgrs[SHR_RES_ALLOCATOR_COUNT] = 275 { 276 { 277 _shr_res_bitmap_create, 278 _shr_res_bitmap_destroy, 279 _shr_res_bitmap_alloc, 280 NULL, 281 _shr_res_bitmap_alloc_align, 282 _shr_res_bitmap_alloc_align_sparse, 283 NULL, 284 _shr_res_bitmap_free, 285 _shr_res_bitmap_free_sparse, 286 _shr_res_bitmap_check, 287 _shr_res_bitmap_check_all_desc, 288 _shr_res_bitmap_check_all_sparse, 289 NULL, 290 "SHR_RES_ALLOCATOR_BITMAP" 291 } /* bitmap */, 292 { 293 _shr_res_tag_bitmap_create, 294 _shr_res_tag_bitmap_destroy, 295 _shr_res_tag_bitmap_alloc, 296 _shr_res_tag_bitmap_alloc_tag, 297 _shr_res_tag_bitmap_alloc_align, 298 NULL, 299 _shr_res_tag_bitmap_alloc_align_tag, 300 _shr_res_tag_bitmap_free, 301 NULL, 302 _shr_res_tag_bitmap_check, 303 _shr_res_tag_bitmap_check_all, 304 NULL, 305 _shr_res_tag_bitmap_check_all_tag, 306 "SHR_RES_ALLOCATOR_TAGGED_BITMAP" 307 } /* tagged bitmap */, 308 { 309 _shr_res_idxres_create, 310 _shr_res_idxres_destroy, 311 _shr_res_idxres_alloc, 312 NULL, 313 NULL, 314 NULL, 315 NULL, 316 _shr_res_idxres_free, 317 NULL, 318 _shr_res_idxres_check, 319 _shr_res_idxres_check_all, 320 NULL, 321 NULL, 322 "SHR_RES_ALLOCATOR_IDXRES" 323 } /* idxres */, 324 { 325 _shr_res_aidxres_create, 326 _shr_res_aidxres_destroy, 327 _shr_res_aidxres_alloc, 328 NULL, 329 NULL, 330 NULL, 331 NULL, 332 _shr_res_aidxres_free, 333 NULL, 334 _shr_res_aidxres_check, 335 _shr_res_aidxres_check_all, 336 NULL, 337 NULL, 338 "SHR_RES_ALLOCATOR_AIDXRES" 339 } /* aidxres */, 340 { 341 _shr_res_mdb_create, 342 _shr_res_mdb_destroy, 343 _shr_res_mdb_alloc, 344 NULL, 345 NULL, 346 NULL, 347 NULL, 348 _shr_res_mdb_free, 349 NULL, 350 _shr_res_mdb_check, 351 _shr_res_mdb_check_all, 352 NULL, 353 NULL, 354 "SHR_RES_ALLOCATOR_MDB" 355 } /* mdb */ 356 }; 357 358 /* 359 * Basic checks performed for many functions 360 */ 361 #define RES_UNIT_CHECK(_unit, _unitInfo) \ 362 if ((0 > (_unit)) || (BCM_LOCAL_UNITS_MAX <= (_unit))) { \ 363 LOG_ERROR(BSL_LS_SOC_COMMON, \ 364 (BSL_META("invalid unit number %d\n"), \ 365 _unit)); \ 366 return _SHR_E_PARAM; \ 367 } \ 368 if (!(_g_unitResDesc[_unit])) { \ 369 LOG_ERROR(BSL_LS_SOC_COMMON, \ 370 (BSL_META("unit %d is not initialised\n"), \ 371 _unit)); \ 372 return _SHR_E_INIT; \ 373 } \ 374 (_unitInfo) = _g_unitResDesc[_unit] 375 #define RES_HANDLE_VALID_CHECK(_handle) \ 376 if (!(_handle)) { \ 377 LOG_ERROR(BSL_LS_SOC_COMMON, \ 378 (BSL_META("NULL handle is not valid\n"))); \ 379 return _SHR_E_PARAM; \ 380 } 381 #define RES_POOL_VALID_CHECK(_handle, _pool) \ 382 if ((0 > (_pool)) || ((_handle)->resPoolCount <= (_pool))) { \ 383 LOG_ERROR(BSL_LS_SOC_COMMON, \ 384 (BSL_META("%p pool %d does not exist\n"), \ 385 ((void*)(_handle)), _pool)); \ 386 return _SHR_E_PARAM; \ 387 } 388 #define RES_POOL_EXIST_CHECK(_handle, _pool) \ 389 if (!((_handle)->pool[_pool])) { \ 390 LOG_ERROR(BSL_LS_SOC_COMMON, \ 391 (BSL_META("%p pool %d is not configured\n"), \ 392 ((void*)(_handle)), _pool)); \ 393 return _SHR_E_CONFIG; \ 394 } 395 #define RES_TYPE_VALID_CHECK(_handle, _type) \ 396 if ((0 > (_type)) || ((_handle)->resTypeCount <= (_type))) { \ 397 LOG_ERROR(BSL_LS_SOC_COMMON, \ 398 (BSL_META("%p resource %d does not exist\n"), \ 399 ((void*)(_handle)), _type)); \ 400 return _SHR_E_PARAM; \ 401 } 402 #define RES_TYPE_EXIST_CHECK(_handle, _type) \ 403 if (!((_handle)->res[_type])) { \ 404 LOG_ERROR(BSL_LS_SOC_COMMON, \ 405 (BSL_META("%p resource %d is not configured\n"), \ 406 ((void*)(_handle)), _type)); \ 407 return _SHR_E_CONFIG; \ 408 } 409 410 /* 411 * Destroys all of the resources and then pools for a unit. 412 */ 413 static int 414 _shr_mres_destroy_data(_shr_res_unit_desc_t *unitData) 415 { 416 int i; 417 int result = _SHR_E_NONE; 418 _shr_res_type_desc_t *type; 419 _shr_res_pool_desc_t *pool; 420 421 /* destroy resources */ 422 for (i = 0; i < unitData->resTypeCount; i++) { 423 if (unitData->res[i]) { 424 425 type = unitData->res[i]; 426 unitData->res[i] = NULL; 427 if (type->refCount) { 428 LOG_WARN(BSL_LS_SOC_COMMON, 429 (BSL_META("%p type %d (%s): still in use (%d)\n"), 430 (void*)unitData, 431 i, 432 &(type->name[0]), 433 type->refCount)); 434 } 435 unitData->pool[type->resPoolId]->refCount--; 436 sal_free(type); 437 } 438 } /* for (all resources this unit) */ 439 440 /* destroy pools */ 441 for (i = 0; 442 (i < unitData->resPoolCount) && (_SHR_E_NONE == result); 443 i++) { 444 if (unitData->pool[i]) { 445 446 pool = unitData->pool[i]; 447 unitData->pool[i] = NULL; 448 if (pool->refCount) { 449 LOG_WARN(BSL_LS_SOC_COMMON, 450 (BSL_META("%p pool %d (%s): unexpectedly still" 451 " in use (%d) - invalid condition???\n"), 452 (void*)unitData, 453 i, 454 &(pool->name[0]), 455 pool->refCount)); 456 } 457 result = _shr_res_alloc_mgrs[pool->resManagerType].destroy(pool); 458 if (_SHR_E_NONE != result) { 459 LOG_ERROR(BSL_LS_SOC_COMMON, 460 (BSL_META("%p pool %d (%s): unable to destroy:" 461 " %d (%s)\n"), 462 (void*)unitData, 463 i, 464 &(pool->name[0]), 465 result, 466 _SHR_ERRMSG(result))); 467 unitData->pool[i] = pool; 468 } /* if (_SHR_E_NONE != result) */ 469 } /* if (unitData->pool[i]) */ 470 } /* for (all pools as long as no errors) */ 471 return result; 472 } 473 474 /*****************************************************************************/ 475 /* 476 * Exposed API implementation (handle based) 477 */ 478 479 /* 480 * Initialise unit 481 */ 482 int 483 shr_mres_create(shr_mres_handle_t *handle, 484 int num_res_types, 485 int num_res_pools) 486 { 487 _shr_res_unit_desc_t *tempHandle; 488 int result = _SHR_E_NONE; 489 490 LOG_DEBUG(BSL_LS_SOC_COMMON, 491 (BSL_META("(%p, %d, %d) enter\n"), 492 (void*)handle, 493 num_res_types, 494 num_res_pools)); 495 496 /* a little parameter checking */ 497 if (!handle) { 498 LOG_ERROR(BSL_LS_SOC_COMMON, 499 (BSL_META("obligatory OUT argument must not be NULL\n"))); 500 result = _SHR_E_PARAM; 501 } 502 if (1 > num_res_pools) { 503 LOG_ERROR(BSL_LS_SOC_COMMON, 504 (BSL_META("resource pools %d; must be > 0\n"), 505 num_res_pools)); 506 result = _SHR_E_PARAM; 507 } 508 if (1 > num_res_types) { 509 LOG_ERROR(BSL_LS_SOC_COMMON, 510 (BSL_META("resource types %d; must be > 0\n"), 511 num_res_types)); 512 result = _SHR_E_PARAM; 513 } 514 if (_SHR_E_NONE != result) { 515 /* displayed diagnostics above */ 516 return result; 517 } 518 /* set things up */ 519 tempHandle = sal_alloc(sizeof(_shr_res_unit_desc_t) + 520 (sizeof(_shr_res_pool_desc_t) * num_res_pools) + 521 (sizeof(_shr_res_type_desc_t) * num_res_types), 522 "resource descriptor"); 523 if (!tempHandle) { 524 /* alloc failed */ 525 LOG_ERROR(BSL_LS_SOC_COMMON, 526 (BSL_META("unable to allocate %u bytes for info\n"), 527 (unsigned int)(sizeof(_shr_res_unit_desc_t) + 528 (sizeof(_shr_res_pool_desc_t) * num_res_pools) + 529 (sizeof(_shr_res_type_desc_t) * num_res_types)))); 530 result = _SHR_E_MEMORY; 531 } else { /* if (!tempUnit) */ 532 /* got the unit information heap cell, set it up */ 533 sal_memset(tempHandle, 534 0x00, 535 sizeof(_shr_res_unit_desc_t) + 536 (sizeof(_shr_res_pool_desc_t*) * num_res_pools) + 537 (sizeof(_shr_res_type_desc_t*) * num_res_types)); 538 tempHandle->pool = (_shr_res_pool_desc_t**)(&(tempHandle[1])); 539 tempHandle->res = (_shr_res_type_desc_t**)(&(tempHandle->pool[num_res_pools])); 540 tempHandle->resTypeCount = num_res_types; 541 tempHandle->resPoolCount = num_res_pools; 542 *handle = tempHandle; 543 } /* if (!tempUnit) */ 544 545 LOG_DEBUG(BSL_LS_SOC_COMMON, 546 (BSL_META("(&(%p), %d, %d) return %d (%s)\n"), 547 (void*)(*handle), 548 num_res_types, 549 num_res_pools, 550 result, 551 _SHR_ERRMSG(result))); 552 return result; 553 } 554 555 /* 556 * Get unit resource information (top level) 557 */ 558 int 559 shr_mres_get(shr_mres_handle_t handle, 560 int *num_res_types, 561 int *num_res_pools) 562 { 563 LOG_DEBUG(BSL_LS_SOC_COMMON, 564 (BSL_META("(%p, %p, %p) enter\n"), 565 (void*)handle, 566 (void*)num_res_types, 567 (void*)num_res_pools)); 568 569 /* a little parameter checking */ 570 RES_HANDLE_VALID_CHECK(handle); 571 /* return the requested information */ 572 if (num_res_pools) { 573 *num_res_pools = handle->resPoolCount; 574 } 575 if (num_res_types) { 576 *num_res_types = handle->resTypeCount; 577 } 578 579 LOG_DEBUG(BSL_LS_SOC_COMMON, 580 (BSL_META("(%p, &(%d), &(%d)) return %d (%s)\n"), 581 (void*)handle, 582 num_res_types?*num_res_types:-1, 583 num_res_pools?*num_res_pools:-1, 584 _SHR_E_NONE, 585 _SHR_ERRMSG(_SHR_E_NONE))); 586 return _SHR_E_NONE; 587 } 588 589 /* 590 * Deinitialise unit 591 */ 592 int 593 shr_mres_destroy(shr_mres_handle_t handle) 594 { 595 int result = _SHR_E_NONE; 596 597 LOG_DEBUG(BSL_LS_SOC_COMMON, 598 (BSL_META("(%p) enter\n"), 599 (void*)handle)); 600 601 /* a little parameter checking */ 602 RES_HANDLE_VALID_CHECK(handle); 603 /* tear things down */ 604 result = _shr_mres_destroy_data(handle); 605 if (_SHR_E_NONE == result) { 606 sal_free(handle); 607 } 608 609 LOG_DEBUG(BSL_LS_SOC_COMMON, 610 (BSL_META("(%p) return %d (%s)\n"), 611 (void*)handle, 612 result, 613 _SHR_ERRMSG(result))); 614 return result; 615 } 616 617 /* 618 * Configure a resource pool on a unit 619 */ 620 int 621 shr_mres_pool_set(shr_mres_handle_t handle, 622 int pool_id, 623 shr_res_allocator_t manager, 624 int low_id, 625 int count, 626 const void *extras, 627 const char *name) 628 { 629 _shr_res_pool_desc_t *tempPool; 630 _shr_res_pool_desc_t *oldPool; 631 int result = _SHR_E_NONE; 632 int xresult; 633 const char *noname = "???"; 634 635 LOG_DEBUG(BSL_LS_SOC_COMMON, 636 (BSL_META("(%p, %d, %s, %d, %d, %p, \"%s\") enter\n"), 637 (void*)handle, 638 pool_id, 639 ((0 <= manager) && (SHR_RES_ALLOCATOR_COUNT > manager))?_shr_res_alloc_mgrs[manager].name:"INVALID", 640 low_id, 641 count, 642 (void*)extras, 643 name?name:noname)); 644 645 /* a little parameter checking */ 646 RES_HANDLE_VALID_CHECK(handle); 647 RES_POOL_VALID_CHECK(handle, pool_id); 648 if ((0 > manager) || (SHR_RES_ALLOCATOR_COUNT <= manager)) { 649 LOG_ERROR(BSL_LS_SOC_COMMON, 650 (BSL_META("allocation manager type %d not supported\n"), 651 manager)); 652 return _SHR_E_PARAM; 653 } 654 if (0 > count) { 655 LOG_ERROR(BSL_LS_SOC_COMMON, 656 (BSL_META("negative counts are not permitted\n"))); 657 return _SHR_E_PARAM; 658 } 659 if ((handle->pool[pool_id]) && (handle->pool[pool_id]->refCount)) { 660 LOG_ERROR(BSL_LS_SOC_COMMON, 661 (BSL_META("%p pool %d (%s) can not be changed because it" 662 " has %d types that use it\n"), 663 (void*)handle, 664 pool_id, 665 handle->pool[pool_id]->name, 666 handle->pool[pool_id]->refCount)); 667 return _SHR_E_CONFIG; 668 } 669 670 oldPool = handle->pool[pool_id]; 671 handle->pool[pool_id] = NULL; 672 /* create the new pool */ 673 result = _shr_res_alloc_mgrs[manager].create(&tempPool, 674 low_id, 675 count, 676 extras, 677 name?name:noname); 678 if (_SHR_E_NONE == result) { 679 /* new one created successfully */ 680 tempPool->resManagerType = manager; 681 tempPool->refCount = 0; 682 if (oldPool) { 683 /* old one exists; get rid of it */ 684 result = _shr_res_alloc_mgrs[oldPool->resManagerType].destroy(oldPool); 685 if (_SHR_E_NONE != result) { 686 handle->pool[pool_id] = oldPool; 687 LOG_ERROR(BSL_LS_SOC_COMMON, 688 (BSL_META("unable to destroy %p old pool %d (%s):" 689 " %d (%s)\n"), 690 (void*)handle, 691 pool_id, 692 oldPool->name, 693 result, 694 _SHR_ERRMSG(result))); 695 xresult = _shr_res_alloc_mgrs[tempPool->resManagerType].destroy(tempPool); 696 if (_SHR_E_NONE != xresult) { 697 LOG_ERROR(BSL_LS_SOC_COMMON, 698 (BSL_META("unable to destroy new pool for %p pool" 699 " %d after replace error: %d (%s)\n"), 700 (void*)handle, 701 pool_id, 702 xresult, 703 _SHR_ERRMSG(xresult))); 704 } 705 } /* if (_SHR_E_NONE != result) */ 706 } /* if (oldPool) */ 707 } /* if (_SHR_E_NONE == result) */ 708 if (_SHR_E_NONE == result) { 709 handle->pool[pool_id] = tempPool; 710 } 711 712 LOG_DEBUG(BSL_LS_SOC_COMMON, 713 (BSL_META("(%p, %d, %s, %d, %d, %p, \"%s\") return %d (%s)\n"), 714 (void*)handle, 715 pool_id, 716 _shr_res_alloc_mgrs[manager].name, 717 low_id, 718 count, 719 (void*)extras, 720 name?name:noname, 721 result, 722 _SHR_ERRMSG(result))); 723 return result; 724 } 725 726 /* 727 * Destroy a resource pool on a unit 728 */ 729 int 730 shr_mres_pool_unset(shr_mres_handle_t handle, 731 int pool_id) 732 { 733 _shr_res_pool_desc_t *oldPool; 734 int result = _SHR_E_NONE; 735 736 LOG_DEBUG(BSL_LS_SOC_COMMON, 737 (BSL_META("(%p, %d) enter\n"), 738 (void*)handle, pool_id)); 739 740 /* a little parameter checking */ 741 RES_HANDLE_VALID_CHECK(handle); 742 RES_POOL_VALID_CHECK(handle, pool_id); 743 744 oldPool = handle->pool[pool_id]; 745 handle->pool[pool_id] = NULL; 746 if (oldPool) { 747 if (oldPool->refCount) { 748 LOG_ERROR(BSL_LS_SOC_COMMON, 749 (BSL_META("%p pool %d (%s) can not be destroyed because" 750 " it has %d types that use it\n"), 751 (void*)handle, 752 pool_id, 753 oldPool->name, 754 oldPool->refCount)); 755 result = _SHR_E_CONFIG; 756 } else { /* if (oldPool->refCount) */ 757 result = _shr_res_alloc_mgrs[oldPool->resManagerType].destroy(oldPool); 758 if (_SHR_E_NONE != result) { 759 LOG_ERROR(BSL_LS_SOC_COMMON, 760 (BSL_META("unable to destroy %p old pool %d (%s):" 761 " %d (%s)\n"), 762 (void*)handle, 763 pool_id, 764 oldPool->name, 765 result, 766 _SHR_ERRMSG(result))); 767 } /* if (_SHR_E_NONE != result) */ 768 } /* if (oldPool->refCount) */ 769 } /* if (oldPool) */ 770 if (_SHR_E_NONE != result) { 771 handle->pool[pool_id] = oldPool; 772 } 773 774 LOG_DEBUG(BSL_LS_SOC_COMMON, 775 (BSL_META("(%p, %d) return %d (%s)\n"), 776 (void*)handle, 777 pool_id, 778 result, 779 _SHR_ERRMSG(result))); 780 return result; 781 } 782 783 /* 784 * Get information about a resource pool on a unit 785 */ 786 int 787 shr_mres_pool_get(shr_mres_handle_t handle, 788 int pool_id, 789 shr_res_allocator_t *manager, 790 int *low_id, 791 int *count, 792 const void **extras, 793 const char **name) 794 { 795 _shr_res_pool_desc_t *thisPool; 796 797 LOG_DEBUG(BSL_LS_SOC_COMMON, 798 (BSL_META("(%p, %d, %p, %p, %p, %p, %p) enter\n"), 799 (void*)handle, 800 pool_id, 801 (void*)manager, 802 (void*)low_id, 803 (void*)count, 804 (void*)extras, 805 (void*)name)); 806 807 /* a little parameter checking */ 808 RES_HANDLE_VALID_CHECK(handle); 809 RES_POOL_VALID_CHECK(handle, pool_id); 810 RES_POOL_EXIST_CHECK(handle, pool_id); 811 /* fill in the caller's request */ 812 thisPool = handle->pool[pool_id]; 813 if (manager) { 814 *manager = thisPool->resManagerType; 815 } 816 if (low_id) { 817 *low_id = thisPool->low; 818 } 819 if (count) { 820 *count = thisPool->count; 821 } 822 if (extras) { 823 *extras = thisPool->extras; 824 } 825 if (name) { 826 *name = thisPool->name; 827 } 828 829 LOG_DEBUG(BSL_LS_SOC_COMMON, 830 (BSL_META("(%p, %d, &(%s), &(%d), &(%d), &(%p), &(\"%s\")) return %d (%s)\n"), 831 (void*)handle, 832 pool_id, 833 manager?_shr_res_alloc_mgrs[*manager].name:"NULL", 834 low_id?*low_id:0, 835 count?*count:0, 836 extras?(void*)(*extras):NULL, 837 name?*name:"NULL", 838 _SHR_E_NONE, 839 _SHR_ERRMSG(_SHR_E_NONE))); 840 return _SHR_E_NONE; 841 } 842 843 /* 844 * Get certain details about a pool on a unit 845 */ 846 int 847 shr_mres_pool_info_get(shr_mres_handle_t handle, 848 int pool_id, 849 shr_res_pool_info_t *info) 850 { 851 _shr_res_pool_desc_t *thisPool; 852 853 LOG_DEBUG(BSL_LS_SOC_COMMON, 854 (BSL_META("(%p, %d, %p) enter\n"), 855 (void*)handle, 856 pool_id, 857 (void*)info)); 858 859 /* a little parameter checking */ 860 RES_HANDLE_VALID_CHECK(handle); 861 RES_POOL_VALID_CHECK(handle, pool_id); 862 RES_POOL_EXIST_CHECK(handle, pool_id); 863 /* fill in the caller's request */ 864 thisPool = handle->pool[pool_id]; 865 if (info) { 866 info->free = thisPool->count - thisPool->inuse; 867 info->used = thisPool->inuse; 868 } 869 870 LOG_DEBUG(BSL_LS_SOC_COMMON, 871 (BSL_META("(%p, %d, %p) return %d (%s)\n"), 872 (void*)handle, 873 pool_id, 874 (void*)info, 875 _SHR_E_NONE, 876 _SHR_ERRMSG(_SHR_E_NONE))); 877 return _SHR_E_NONE; 878 } 879 880 /* 881 * Configure a resource type on a unit 882 */ 883 int 884 shr_mres_type_set(shr_mres_handle_t handle, 885 int res_id, 886 int pool_id, 887 int elem_size, 888 const char *name) 889 { 890 _shr_res_type_desc_t *tempType; 891 _shr_res_type_desc_t *oldType; 892 int result = _SHR_E_NONE; 893 const char *noname = "???"; 894 int len_name = 0; 895 896 LOG_DEBUG(BSL_LS_SOC_COMMON, 897 (BSL_META("(%p, %d, %d, %d, \"%s\") enter\n"), 898 (void*)handle, 899 res_id, 900 pool_id, 901 elem_size, 902 name?name:noname)); 903 904 /* a little parameter checking */ 905 RES_HANDLE_VALID_CHECK(handle); 906 RES_POOL_VALID_CHECK(handle, pool_id); 907 RES_POOL_EXIST_CHECK(handle, pool_id); 908 RES_TYPE_VALID_CHECK(handle, res_id); 909 if (1 > elem_size) { 910 LOG_ERROR(BSL_LS_SOC_COMMON, 911 (BSL_META("element size %d too small; must be >= 1\n"), 912 elem_size)); 913 return _SHR_E_PARAM; 914 } 915 if ((handle->res[res_id]) && (handle->res[res_id]->refCount)) { 916 LOG_ERROR(BSL_LS_SOC_COMMON, 917 (BSL_META("%p resource %d (%s) can not be changed" 918 " because it has %d elements in use\n"), 919 (void*)handle, 920 res_id, 921 handle->res[res_id]->name, 922 handle->res[res_id]->refCount)); 923 return _SHR_E_CONFIG; 924 } 925 if (!name) { 926 /* force a non-NULL name pointer */ 927 name = noname; 928 } 929 930 len_name = sal_strlen(name); 931 932 oldType = handle->res[res_id]; 933 handle->res[res_id] = NULL; 934 /* allocate new type descriptor */ 935 /* note base type includes one character, so don't need to add NUL here */ 936 tempType = sal_alloc(sizeof(*tempType) + len_name, 937 "resource type descriptor"); 938 if (tempType) { 939 /* got the needed memory; set it up */ 940 sal_memset(tempType, 941 0x00, 942 sizeof(*tempType) + len_name); 943 tempType->resElemSize = elem_size; 944 tempType->resPoolId = pool_id; 945 sal_strncpy(&(tempType->name[0]), name, len_name); 946 if (len_name) 947 *((char*)&(tempType->name[0])+len_name) = '\0'; 948 949 if (oldType) { 950 /* there was an old one; get rid of it and adjust references */ 951 handle->pool[oldType->resPoolId]->refCount--; 952 sal_free(oldType); 953 } 954 /* adjust references and put this type in place */ 955 handle->pool[pool_id]->refCount++; 956 handle->res[res_id] = tempType; 957 } else { 958 LOG_ERROR(BSL_LS_SOC_COMMON, 959 (BSL_META("unable to allocate %u bytes for %p resource" 960 " type %d\n"), 961 (unsigned int)(sizeof(*tempType) + sal_strlen(name)), 962 (void*)handle, 963 res_id)); 964 result = _SHR_E_MEMORY; 965 /* restore the old type */ 966 handle->res[res_id] = oldType; 967 } 968 969 LOG_DEBUG(BSL_LS_SOC_COMMON, 970 (BSL_META("(%p, %d, %d, %d, \"%s\") return %d (%s)\n"), 971 (void*)handle, 972 res_id, 973 pool_id, 974 elem_size, 975 name?name:noname, 976 result, 977 _SHR_ERRMSG(result))); 978 return result; 979 } 980 981 /* 982 * Destroy a resource type on a unit 983 */ 984 int 985 shr_mres_type_unset(shr_mres_handle_t handle, 986 int res_id) 987 { 988 _shr_res_type_desc_t *oldType; 989 int result = _SHR_E_NONE; 990 991 LOG_DEBUG(BSL_LS_SOC_COMMON, 992 (BSL_META("(%p, %d) enter\n"), 993 (void*)handle, res_id)); 994 995 /* a little parameter checking */ 996 RES_HANDLE_VALID_CHECK(handle); 997 RES_TYPE_VALID_CHECK(handle, res_id); 998 999 oldType = handle->res[res_id]; 1000 handle->res[res_id] = NULL; 1001 if (oldType) { 1002 if (oldType->refCount) { 1003 LOG_ERROR(BSL_LS_SOC_COMMON, 1004 (BSL_META("%p resource %d (%s) can not be destroyed" 1005 " because it has %d elements in use\n"), 1006 (void*)handle, 1007 res_id, 1008 oldType->name, 1009 oldType->refCount)); 1010 result = _SHR_E_CONFIG; 1011 } else { 1012 handle->pool[oldType->resPoolId]->refCount--; 1013 sal_free(oldType); 1014 } 1015 } /* if (oldType) */ 1016 if (_SHR_E_NONE != result) { 1017 handle->res[res_id] = oldType; 1018 } 1019 1020 LOG_DEBUG(BSL_LS_SOC_COMMON, 1021 (BSL_META("(%p, %d) return %d (%s)\n"), 1022 (void*)handle, 1023 res_id, 1024 result, 1025 _SHR_ERRMSG(result))); 1026 return result; 1027 } 1028 1029 /* 1030 * Get information about a resource type 1031 */ 1032 int 1033 shr_mres_type_get(shr_mres_handle_t handle, 1034 int res_id, 1035 int *pool_id, 1036 int *elem_size, 1037 const char **name) 1038 { 1039 _shr_res_type_desc_t *thisType; 1040 1041 LOG_DEBUG(BSL_LS_SOC_COMMON, 1042 (BSL_META("(%p, %d, %p, %p, %p) enter\n"), 1043 (void*)handle, 1044 res_id, 1045 (void*)pool_id, 1046 (void*)elem_size, 1047 (void*)name)); 1048 1049 /* a little parameter checking */ 1050 RES_HANDLE_VALID_CHECK(handle); 1051 RES_TYPE_VALID_CHECK(handle, res_id); 1052 RES_TYPE_EXIST_CHECK(handle, res_id); 1053 /* fill in the caller's request */ 1054 thisType = handle->res[res_id]; 1055 if (pool_id) { 1056 *pool_id = thisType->resPoolId; 1057 } 1058 if (elem_size) { 1059 *elem_size = thisType->resElemSize; 1060 } 1061 if (name) { 1062 *name = thisType->name; 1063 } 1064 1065 LOG_DEBUG(BSL_LS_SOC_COMMON, 1066 (BSL_META("(%p, %d, &(%d), &(%d), &(\"%s\")) return %d (%s)\n"), 1067 (void*)handle, 1068 res_id, 1069 pool_id?*pool_id:0, 1070 elem_size?*elem_size:0, 1071 name?*name:"NULL", 1072 _SHR_E_NONE, 1073 _SHR_ERRMSG(_SHR_E_NONE))); 1074 return _SHR_E_NONE; 1075 } 1076 1077 /* 1078 * Get information about a resource type 1079 */ 1080 int 1081 shr_mres_type_info_get(shr_mres_handle_t handle, 1082 int res_id, 1083 shr_res_type_info_t *info) 1084 { 1085 _shr_res_type_desc_t *thisType; 1086 1087 LOG_DEBUG(BSL_LS_SOC_COMMON, 1088 (BSL_META("(%p, %d, %p) enter\n"), 1089 (void*)handle, 1090 res_id, 1091 (void*)info)); 1092 1093 /* a little parameter checking */ 1094 RES_HANDLE_VALID_CHECK(handle); 1095 RES_TYPE_VALID_CHECK(handle, res_id); 1096 RES_TYPE_EXIST_CHECK(handle, res_id); 1097 /* fill in the caller's request */ 1098 thisType = handle->res[res_id]; 1099 if (info) { 1100 info->used = thisType->refCount; 1101 } 1102 1103 LOG_DEBUG(BSL_LS_SOC_COMMON, 1104 (BSL_META("(%p, %d, %p) return %d (%s)\n"), 1105 (void*)handle, 1106 res_id, 1107 (void*)info, 1108 _SHR_E_NONE, 1109 _SHR_ERRMSG(_SHR_E_NONE))); 1110 return _SHR_E_NONE; 1111 } 1112 1113 /* 1114 * Allocate elements of a resource type 1115 */ 1116 int 1117 shr_mres_alloc(shr_mres_handle_t handle, 1118 int res_id, 1119 uint32 flags, 1120 int count, 1121 int *elem) 1122 { 1123 _shr_res_pool_desc_t *thisPool; 1124 int result = _SHR_E_NONE; 1125 int scaled; 1126 1127 LOG_DEBUG(BSL_LS_SOC_COMMON, 1128 (BSL_META("(%p, %d, %08X, %d, %p) enter\n"), 1129 (void*)handle, 1130 res_id, 1131 flags, 1132 count, 1133 (void*)elem)); 1134 1135 /* a little parameter checking */ 1136 RES_HANDLE_VALID_CHECK(handle); 1137 RES_TYPE_VALID_CHECK(handle, res_id); 1138 RES_TYPE_EXIST_CHECK(handle, res_id); 1139 if (0 >= count) { 1140 LOG_ERROR(BSL_LS_SOC_COMMON, 1141 (BSL_META("element count %d must be > 0\n"), 1142 count)); 1143 return _SHR_E_PARAM; 1144 } 1145 if (flags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 1146 LOG_ERROR(BSL_LS_SOC_COMMON, 1147 (BSL_META("invalid flags %08X\n"), 1148 flags & (~SHR_RES_ALLOC_SINGLE_FLAGS))); 1149 return _SHR_E_PARAM; 1150 } 1151 if (!elem) { 1152 LOG_ERROR(BSL_LS_SOC_COMMON, 1153 (BSL_META("obligatory argument is NULL\n"))); 1154 return _SHR_E_PARAM; 1155 } 1156 /* adjust element count per scaling factor */ 1157 scaled = count * handle->res[res_id]->resElemSize; 1158 1159 /* get the pool information */ 1160 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 1161 /* make the call */ 1162 result = _shr_res_alloc_mgrs[thisPool->resManagerType].alloc(thisPool, 1163 flags, 1164 scaled, 1165 elem); 1166 if (_SHR_E_NONE == result) { 1167 /* account for successful allocation */ 1168 if (0 == (flags & SHR_RES_ALLOC_REPLACE)) { 1169 /* only account for alloc if new allocation */ 1170 handle->res[res_id]->refCount += count; 1171 thisPool->inuse += scaled; 1172 } 1173 } 1174 1175 LOG_DEBUG(BSL_LS_SOC_COMMON, 1176 (BSL_META("(%p, %d, %08X, %d, &(%d)) return %d (%s)\n"), 1177 (void*)handle, 1178 res_id, 1179 flags, 1180 count, 1181 *elem, 1182 result, 1183 _SHR_ERRMSG(result))); 1184 return result; 1185 } 1186 1187 /* 1188 * Allocate a bunch of elements or blocks of a resource type 1189 */ 1190 int 1191 shr_mres_alloc_group(shr_mres_handle_t handle, 1192 int res_id, 1193 uint32 grp_flags, 1194 int grp_size, 1195 int *grp_done, 1196 const uint32 *flags, 1197 const int *count, 1198 int *elem) 1199 { 1200 _shr_res_pool_desc_t *thisPool; 1201 _shr_res_type_desc_t *thisRes; 1202 int result = _SHR_E_NONE; 1203 int xresult; 1204 int scaled = 0; 1205 int index; 1206 uint32 blkFlags; 1207 1208 LOG_DEBUG(BSL_LS_SOC_COMMON, 1209 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p) enter\n"), 1210 (void*)handle, 1211 res_id, 1212 grp_flags, 1213 grp_size, 1214 (void*)grp_done, 1215 (void*)flags, 1216 (void*)count, 1217 (void*)elem)); 1218 1219 /* a little parameter checking */ 1220 RES_HANDLE_VALID_CHECK(handle); 1221 RES_TYPE_VALID_CHECK(handle, res_id); 1222 RES_TYPE_EXIST_CHECK(handle, res_id); 1223 if (!grp_done) { 1224 LOG_ERROR(BSL_LS_SOC_COMMON, 1225 (BSL_META("obligatory out argument grp_done is NULL\n"))); 1226 return _SHR_E_PARAM; 1227 } 1228 *grp_done = 0; 1229 if (0 > grp_size) { 1230 LOG_ERROR(BSL_LS_SOC_COMMON, 1231 (BSL_META("group member count %d must be >= 0\n"), 1232 grp_size)); 1233 return _SHR_E_PARAM; 1234 } 1235 if ((0 < grp_size) && (!flags || !count || !elem)) { 1236 LOG_ERROR(BSL_LS_SOC_COMMON, 1237 (BSL_META("an obligatory array pointer is NULL\n"))); 1238 return _SHR_E_PARAM; 1239 } 1240 if (grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | SHR_RES_ALLOC_GROUP_FLAGS))) { 1241 LOG_ERROR(BSL_LS_SOC_COMMON, 1242 (BSL_META("invalid group flags %08X\n"), 1243 grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | 1244 SHR_RES_ALLOC_GROUP_FLAGS)))); 1245 return _SHR_E_PARAM; 1246 } 1247 /* get the resource information */ 1248 thisRes = handle->res[res_id]; 1249 /* get the pool information */ 1250 thisPool = handle->pool[thisRes->resPoolId]; 1251 /* try to collect the requested blocks */ 1252 for (index = 0; 1253 (_SHR_E_NONE == result) && (index < grp_size); 1254 index++) { 1255 /* check parameters for this block */ 1256 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 1257 if (blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 1258 LOG_ERROR(BSL_LS_SOC_COMMON, 1259 (BSL_META("invalid flags %08X for block %d\n"), 1260 blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS), 1261 index)); 1262 result = _SHR_E_PARAM; 1263 } 1264 if (0 >= count[index]) { 1265 LOG_ERROR(BSL_LS_SOC_COMMON, 1266 (BSL_META("element count %d must be > 0\n"), 1267 count[index])); 1268 result = _SHR_E_PARAM; 1269 } 1270 if (_SHR_E_NONE == result) { 1271 /* adjust element count per scaling factor */ 1272 scaled = count[index] * thisRes->resElemSize; 1273 1274 /* make the call */ 1275 result = _shr_res_alloc_mgrs[thisPool->resManagerType].alloc(thisPool, 1276 blkFlags, 1277 scaled, 1278 &(elem[index])); 1279 } 1280 if (_SHR_E_NONE == result) { 1281 /* account for successful allocation */ 1282 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 1283 /* only account for alloc if new allocation */ 1284 handle->res[res_id]->refCount += count[index]; 1285 thisPool->inuse += scaled; 1286 } 1287 } else { 1288 /* we'll hope the allocation manager displayed an error */ 1289 /* don't want postincrement if an error occurred */ 1290 break; 1291 } 1292 } /* for (all blocks in the caller's group) */ 1293 if ((_SHR_E_NONE != result) && (grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 1294 /* atomic mode and it failed; back out everything that we have */ 1295 /* index is at the first failure */ 1296 while (index > 0) { 1297 /* look at previous index (must have been successful) */ 1298 index--; 1299 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 1300 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 1301 /* free only blocks that were not trying to be replaced */ 1302 /* adjust element count per scaling factor */ 1303 scaled = count[index] * thisRes->resElemSize; 1304 /* free this element or block */ 1305 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].free(thisPool, 1306 scaled, 1307 elem[index]); 1308 if (_SHR_E_NONE != xresult) { 1309 LOG_ERROR(BSL_LS_SOC_COMMON, 1310 (BSL_META("unable to back out %p resource %d" 1311 " index %d base %d count %d: %d (%s)\n"), 1312 (void*)handle, 1313 res_id, 1314 index, 1315 elem[index], 1316 count[index], 1317 result, 1318 _SHR_ERRMSG(result))); 1319 } else { 1320 thisRes->refCount -= count[index]; 1321 thisPool->inuse -= scaled; 1322 } 1323 } /* if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) */ 1324 } /* while (index > 0) */ 1325 } /* if (error && SHR_RES_ALLOC_GROUP_ATOMIC was set) */ 1326 /* update number of allocations that succeeded */ 1327 *grp_done = index; 1328 1329 /* return the result */ 1330 LOG_DEBUG(BSL_LS_SOC_COMMON, 1331 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p) enter\n"), 1332 (void*)handle, 1333 res_id, 1334 grp_flags, 1335 grp_size, 1336 *grp_done, 1337 (void*)flags, 1338 (void*)count, 1339 (void*)elem)); 1340 for (index = 0; index < grp_size; index++) { 1341 LOG_DEBUG(BSL_LS_SOC_COMMON, 1342 (BSL_META(" block %12d: %08X %12d %12d\n"), 1343 index, 1344 flags[index], 1345 count[index], 1346 elem[index])); 1347 } 1348 return result; 1349 } 1350 1351 /* 1352 * Allocate elements of a resource type (tagged) 1353 */ 1354 int 1355 shr_mres_alloc_tag(shr_mres_handle_t handle, 1356 int res_id, 1357 uint32 flags, 1358 const void *tag, 1359 int count, 1360 int *elem) 1361 { 1362 _shr_res_pool_desc_t *thisPool; 1363 int result = _SHR_E_NONE; 1364 int scaled; 1365 1366 LOG_DEBUG(BSL_LS_SOC_COMMON, 1367 (BSL_META("(%p, %d, %08X, %p, %d, %p) enter\n"), 1368 (void*)handle, 1369 res_id, 1370 flags, 1371 (void*)tag, 1372 count, 1373 (void*)elem)); 1374 1375 /* a little parameter checking */ 1376 RES_HANDLE_VALID_CHECK(handle); 1377 RES_TYPE_VALID_CHECK(handle, res_id); 1378 RES_TYPE_EXIST_CHECK(handle, res_id); 1379 if (0 >= count) { 1380 LOG_ERROR(BSL_LS_SOC_COMMON, 1381 (BSL_META("element count %d must be > 0\n"), 1382 count)); 1383 return _SHR_E_PARAM; 1384 } 1385 if (flags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 1386 LOG_ERROR(BSL_LS_SOC_COMMON, 1387 (BSL_META("invalid flags %08X\n"), 1388 flags & (~SHR_RES_ALLOC_SINGLE_FLAGS))); 1389 return _SHR_E_PARAM; 1390 } 1391 if (!elem) { 1392 LOG_ERROR(BSL_LS_SOC_COMMON, 1393 (BSL_META("obligatory argument is NULL\n"))); 1394 return _SHR_E_PARAM; 1395 } 1396 /* adjust element count per scaling factor */ 1397 scaled = count * handle->res[res_id]->resElemSize; 1398 1399 /* get the pool information */ 1400 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 1401 /* make the call */ 1402 if (_shr_res_alloc_mgrs[thisPool->resManagerType].tag) { 1403 /* allocator supports it; make the call */ 1404 result = _shr_res_alloc_mgrs[thisPool->resManagerType].tag(thisPool, 1405 flags, 1406 tag, 1407 scaled, 1408 elem); 1409 } else { 1410 /* not supported by this allocator */ 1411 LOG_ERROR(BSL_LS_SOC_COMMON, 1412 (BSL_META("allocator type %s does not support tagged alloc\n"), 1413 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 1414 result = _SHR_E_UNAVAIL; 1415 } 1416 if (_SHR_E_NONE == result) { 1417 /* account for successful allocation */ 1418 if (0 == (flags & SHR_RES_ALLOC_REPLACE)) { 1419 /* only account for alloc if new allocation */ 1420 handle->res[res_id]->refCount += count; 1421 thisPool->inuse += scaled; 1422 } 1423 } 1424 1425 LOG_DEBUG(BSL_LS_SOC_COMMON, 1426 (BSL_META("(%p, %d, %08X, %p, %d, &(%d)) return %d (%s)\n"), 1427 (void*)handle, 1428 res_id, 1429 flags, 1430 (void*)tag, 1431 count, 1432 *elem, 1433 result, 1434 _SHR_ERRMSG(result))); 1435 return result; 1436 } 1437 1438 /* 1439 * Allocate a bunch of elements or blocks of a resource type (tagged) 1440 */ 1441 int 1442 shr_mres_alloc_tag_group(shr_mres_handle_t handle, 1443 int res_id, 1444 uint32 grp_flags, 1445 int grp_size, 1446 int *grp_done, 1447 const uint32 *flags, 1448 const void **tag, 1449 const int *count, 1450 int *elem) 1451 { 1452 _shr_res_pool_desc_t *thisPool; 1453 _shr_res_type_desc_t *thisRes; 1454 int result = _SHR_E_NONE; 1455 int xresult; 1456 int scaled = 0; 1457 int index; 1458 uint32 blkFlags; 1459 1460 LOG_DEBUG(BSL_LS_SOC_COMMON, 1461 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p, %p) enter\n"), 1462 (void*)handle, 1463 res_id, 1464 grp_flags, 1465 grp_size, 1466 (void*)grp_done, 1467 (void*)flags, 1468 (void*)tag, 1469 (void*)count, 1470 (void*)elem)); 1471 1472 /* a little parameter checking */ 1473 RES_HANDLE_VALID_CHECK(handle); 1474 RES_TYPE_VALID_CHECK(handle, res_id); 1475 RES_TYPE_EXIST_CHECK(handle, res_id); 1476 if (!grp_done) { 1477 LOG_ERROR(BSL_LS_SOC_COMMON, 1478 (BSL_META("obligatory out argument grp_done is NULL\n"))); 1479 return _SHR_E_PARAM; 1480 } 1481 *grp_done = 0; 1482 if (0 > grp_size) { 1483 LOG_ERROR(BSL_LS_SOC_COMMON, 1484 (BSL_META("group member count %d must be >= 0\n"), 1485 grp_size)); 1486 return _SHR_E_PARAM; 1487 } 1488 if ((0 < grp_size) && (!flags || !count || !elem)) { 1489 LOG_ERROR(BSL_LS_SOC_COMMON, 1490 (BSL_META("an obligatory array pointer is NULL\n"))); 1491 return _SHR_E_PARAM; 1492 } 1493 if (grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | SHR_RES_ALLOC_GROUP_FLAGS))) { 1494 LOG_ERROR(BSL_LS_SOC_COMMON, 1495 (BSL_META("invalid group flags %08X\n"), 1496 grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | 1497 SHR_RES_ALLOC_GROUP_FLAGS)))); 1498 return _SHR_E_PARAM; 1499 } 1500 /* get the resource information */ 1501 thisRes = handle->res[res_id]; 1502 /* get the pool information */ 1503 thisPool = handle->pool[thisRes->resPoolId]; 1504 /* try to collect the requested blocks */ 1505 if (!_shr_res_alloc_mgrs[thisPool->resManagerType].tag) { 1506 /* not supported by this allocator */ 1507 LOG_ERROR(BSL_LS_SOC_COMMON, 1508 (BSL_META("allocator type %s does not support tagged alloc\n"), 1509 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 1510 return _SHR_E_UNAVAIL; 1511 } 1512 for (index = 0; 1513 (_SHR_E_NONE == result) && (index < grp_size); 1514 index++) { 1515 /* check parameters for this block */ 1516 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 1517 if (blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 1518 LOG_ERROR(BSL_LS_SOC_COMMON, 1519 (BSL_META("invalid flags %08X for block %d\n"), 1520 blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS), 1521 index)); 1522 result = _SHR_E_PARAM; 1523 } 1524 if (0 >= count[index]) { 1525 LOG_ERROR(BSL_LS_SOC_COMMON, 1526 (BSL_META("element count %d must be > 0\n"), 1527 count[index])); 1528 result = _SHR_E_PARAM; 1529 } 1530 if (_SHR_E_NONE == result) { 1531 /* adjust element count per scaling factor */ 1532 scaled = count[index] * thisRes->resElemSize; 1533 1534 /* make the call */ 1535 result = _shr_res_alloc_mgrs[thisPool->resManagerType].tag(thisPool, 1536 blkFlags, 1537 tag[index], 1538 scaled, 1539 &(elem[index])); 1540 } 1541 if (_SHR_E_NONE == result) { 1542 /* account for successful allocation */ 1543 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 1544 /* only account for alloc if new allocation */ 1545 handle->res[res_id]->refCount += count[index]; 1546 thisPool->inuse += scaled; 1547 } 1548 } else { 1549 /* we'll hope the allocation manager displayed an error */ 1550 /* don't want postincrement if an error occurred */ 1551 break; 1552 } 1553 } /* for (all blocks in the caller's group) */ 1554 if ((_SHR_E_NONE != result) && (grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 1555 /* atomic mode and it failed; back out everything that we have */ 1556 /* index is at the first failure */ 1557 while (index > 0) { 1558 /* look at previous index (must have been successful) */ 1559 index--; 1560 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 1561 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 1562 /* only free blocks that were not trying to be replaced */ 1563 /* adjust element count per scaling factor */ 1564 scaled = count[index] * thisRes->resElemSize; 1565 /* free this element or block */ 1566 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].free(thisPool, 1567 scaled, 1568 elem[index]); 1569 if (_SHR_E_NONE != xresult) { 1570 LOG_ERROR(BSL_LS_SOC_COMMON, 1571 (BSL_META("unable to back out %p resource %d" 1572 " index %d base %d count %d: %d (%s)\n"), 1573 (void*)handle, 1574 res_id, 1575 index, 1576 elem[index], 1577 count[index], 1578 result, 1579 _SHR_ERRMSG(result))); 1580 } else { 1581 thisRes->refCount -= count[index]; 1582 thisPool->inuse -= scaled; 1583 } 1584 } /* if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) */ 1585 } /* while (index > 0) */ 1586 } /* if (error && SHR_RES_ALLOC_GROUP_ATOMIC was set) */ 1587 /* update number of allocations that succeeded */ 1588 *grp_done = index; 1589 1590 /* return the result */ 1591 LOG_DEBUG(BSL_LS_SOC_COMMON, 1592 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p, %p) enter\n"), 1593 (void*)handle, 1594 res_id, 1595 grp_flags, 1596 grp_size, 1597 *grp_done, 1598 (void*)flags, 1599 (void*)tag, 1600 (void*)count, 1601 (void*)elem)); 1602 for (index = 0; index < grp_size; index++) { 1603 LOG_DEBUG(BSL_LS_SOC_COMMON, 1604 (BSL_META(" block %12d: %08X %12d %12d\n"), 1605 index, 1606 flags[index], 1607 count[index], 1608 elem[index])); 1609 } 1610 return result; 1611 } 1612 1613 /* 1614 * Allocate a block of elements with the requested alignment and offset. 1615 */ 1616 int 1617 shr_mres_alloc_align(shr_mres_handle_t handle, 1618 int res_id, 1619 uint32 flags, 1620 int align, 1621 int offset, 1622 int count, 1623 int *elem) 1624 { 1625 _shr_res_pool_desc_t *thisPool; 1626 _shr_res_type_desc_t *thisType; 1627 int result = _SHR_E_NONE; 1628 int base; 1629 int scaled; 1630 int scaledAlign; 1631 int scaledOffset; 1632 1633 LOG_DEBUG(BSL_LS_SOC_COMMON, 1634 (BSL_META("(%p, %d, %08X, %d, %d, %d, %p) enter\n"), 1635 (void*)handle, 1636 res_id, 1637 flags, 1638 align, 1639 offset, 1640 count, 1641 (void*)elem)); 1642 1643 /* a little parameter checking */ 1644 RES_HANDLE_VALID_CHECK(handle); 1645 RES_TYPE_VALID_CHECK(handle, res_id); 1646 RES_TYPE_EXIST_CHECK(handle, res_id); 1647 if (0 >= count) { 1648 LOG_ERROR(BSL_LS_SOC_COMMON, 1649 (BSL_META("element count %d must be > 0\n"), 1650 count)); 1651 return _SHR_E_PARAM; 1652 } 1653 if (1 > align) { 1654 LOG_WARN(BSL_LS_SOC_COMMON, 1655 (BSL_META("align <= 0 invalid, using align = 1 instead\n"))); 1656 align = 1; 1657 } 1658 if ((offset >= align) || (0 > offset)) { 1659 LOG_ERROR(BSL_LS_SOC_COMMON, 1660 (BSL_META("offset %d must be >= 0 and < align %d\n"), 1661 offset, 1662 align)); 1663 return _SHR_E_PARAM; 1664 } 1665 if (flags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 1666 LOG_ERROR(BSL_LS_SOC_COMMON, 1667 (BSL_META("invalid flags %08X\n"), 1668 flags & (~SHR_RES_ALLOC_SINGLE_FLAGS))); 1669 return _SHR_E_PARAM; 1670 } 1671 if (!elem) { 1672 LOG_ERROR(BSL_LS_SOC_COMMON, 1673 (BSL_META("obligatory argument is NULL\n"))); 1674 return _SHR_E_PARAM; 1675 } 1676 /* get the pool information */ 1677 thisType = handle->res[res_id]; 1678 thisPool = handle->pool[thisType->resPoolId]; 1679 /* adjust element count per scaling factor */ 1680 scaled = count * thisType->resElemSize; 1681 scaledAlign = align * thisType->resElemSize; 1682 scaledOffset = offset * thisType->resElemSize; 1683 1684 /* check alignment for WITH_ID case */ 1685 if (flags & SHR_RES_ALLOC_WITH_ID) { 1686 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 1687 base = *elem; 1688 } else { 1689 base = *elem - thisPool->low; 1690 } 1691 if (((((base) / scaledAlign) * scaledAlign) + scaledOffset) != base) { 1692 LOG_ERROR(BSL_LS_SOC_COMMON, 1693 (BSL_META("WITH_ID requested element %d does not comply" 1694 " with alignment specifications\n"), 1695 *elem)); 1696 return _SHR_E_PARAM; 1697 } 1698 } 1699 if (_shr_res_alloc_mgrs[thisPool->resManagerType].align) { 1700 /* allocator supports it; make the call */ 1701 result = _shr_res_alloc_mgrs[thisPool->resManagerType].align(thisPool, 1702 flags, 1703 scaledAlign, 1704 scaledOffset, 1705 scaled, 1706 elem); 1707 } else { 1708 /* not supported by this allocator */ 1709 LOG_ERROR(BSL_LS_SOC_COMMON, 1710 (BSL_META("allocator type %s does not support aligned alloc\n"), 1711 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 1712 result = _SHR_E_UNAVAIL; 1713 } 1714 if (_SHR_E_NONE == result) { 1715 /* account for successful allocation */ 1716 if (0 == (flags & SHR_RES_ALLOC_REPLACE)) { 1717 /* only account for alloc if new allocation */ 1718 handle->res[res_id]->refCount += count; 1719 thisPool->inuse += scaled; 1720 } 1721 } 1722 1723 LOG_DEBUG(BSL_LS_SOC_COMMON, 1724 (BSL_META("(%p, %d, %08X, %d, %d, %d, &(%d)) return %d (%s)\n"), 1725 (void*)handle, 1726 res_id, 1727 flags, 1728 align, 1729 offset, 1730 count, 1731 *elem, 1732 result, 1733 _SHR_ERRMSG(result))); 1734 return result; 1735 } 1736 1737 /* 1738 * Allocate a bunch of aligned elements or blocks of a resource type 1739 */ 1740 int 1741 shr_mres_alloc_align_group(shr_mres_handle_t handle, 1742 int res_id, 1743 uint32 grp_flags, 1744 int grp_size, 1745 int *grp_done, 1746 const uint32 *flags, 1747 const int *align, 1748 const int *offset, 1749 const int *count, 1750 int *elem) 1751 { 1752 _shr_res_pool_desc_t *thisPool; 1753 _shr_res_type_desc_t *thisRes; 1754 int result = _SHR_E_NONE; 1755 int xresult; 1756 int scaled = 0; 1757 int scaledAlign; 1758 int scaledOffset; 1759 int index; 1760 int xalign; 1761 int base; 1762 uint32 blkFlags; 1763 1764 LOG_DEBUG(BSL_LS_SOC_COMMON, 1765 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p, %p, %p) enter\n"), 1766 (void*)handle, 1767 res_id, 1768 grp_flags, 1769 grp_size, 1770 (void*)grp_done, 1771 (void*)flags, 1772 (void*)align, 1773 (void*)offset, 1774 (void*)count, 1775 (void*)elem)); 1776 1777 /* a little parameter checking */ 1778 RES_HANDLE_VALID_CHECK(handle); 1779 RES_TYPE_VALID_CHECK(handle, res_id); 1780 RES_TYPE_EXIST_CHECK(handle, res_id); 1781 if (!grp_done) { 1782 LOG_ERROR(BSL_LS_SOC_COMMON, 1783 (BSL_META("obligatory out argument grp_done is NULL\n"))); 1784 return _SHR_E_PARAM; 1785 } 1786 *grp_done = 0; 1787 if (0 > grp_size) { 1788 LOG_ERROR(BSL_LS_SOC_COMMON, 1789 (BSL_META("group member count %d must be >= 0\n"), 1790 grp_size)); 1791 return _SHR_E_PARAM; 1792 } 1793 if ((0 < grp_size) && (!flags || !count || !elem || !align || !offset)) { 1794 LOG_ERROR(BSL_LS_SOC_COMMON, 1795 (BSL_META("an obligatory array pointer is NULL\n"))); 1796 return _SHR_E_PARAM; 1797 } 1798 if (grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | SHR_RES_ALLOC_GROUP_FLAGS))) { 1799 LOG_ERROR(BSL_LS_SOC_COMMON, 1800 (BSL_META("invalid group flags %08X\n"), 1801 grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | 1802 SHR_RES_ALLOC_GROUP_FLAGS)))); 1803 return _SHR_E_PARAM; 1804 } 1805 /* get the resource information */ 1806 thisRes = handle->res[res_id]; 1807 /* get the pool information */ 1808 thisPool = handle->pool[thisRes->resPoolId]; 1809 /* try to collect the requested blocks */ 1810 if (_shr_res_alloc_mgrs[thisPool->resManagerType].align) { 1811 /* allocator does not support this feature */ 1812 LOG_ERROR(BSL_LS_SOC_COMMON, 1813 (BSL_META("allocator type %s does not support aligned alloc\n"), 1814 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 1815 result = _SHR_E_UNAVAIL; 1816 } 1817 for (index = 0; 1818 (_SHR_E_NONE == result) && (index < grp_size); 1819 index++) { 1820 /* check parameters for this block */ 1821 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 1822 if (blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 1823 LOG_ERROR(BSL_LS_SOC_COMMON, 1824 (BSL_META("invalid flags %08X for block %d\n"), 1825 blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS), 1826 index)); 1827 result = _SHR_E_PARAM; 1828 } 1829 if (0 >= count[index]) { 1830 LOG_ERROR(BSL_LS_SOC_COMMON, 1831 (BSL_META("element count %d must be > 0\n"), 1832 count[index])); 1833 result = _SHR_E_PARAM; 1834 } 1835 if (1 > align[index]) { 1836 LOG_WARN(BSL_LS_SOC_COMMON, 1837 (BSL_META("align <= 0 invalid, using align = 1 instead\n"))); 1838 xalign = 1; 1839 } else { 1840 xalign = align[index]; 1841 } 1842 if ((offset[index] >= xalign) || (0 > offset[index])) { 1843 LOG_ERROR(BSL_LS_SOC_COMMON, 1844 (BSL_META("offset %d must be >= 0 and < align %d\n"), 1845 offset[index], 1846 xalign)); 1847 result = _SHR_E_PARAM; 1848 } 1849 if (_SHR_E_NONE == result) { 1850 /* adjust element count per scaling factor */ 1851 scaled = count[index] * thisRes->resElemSize; 1852 scaledAlign = xalign * thisRes->resElemSize; 1853 scaledOffset = offset[index] * thisRes->resElemSize; 1854 1855 /* check alignment for WITH_ID case */ 1856 if (blkFlags & SHR_RES_ALLOC_WITH_ID) { 1857 if (blkFlags & SHR_RES_ALLOC_ALIGN_ZERO) { 1858 base = elem[index]; 1859 } else { 1860 base = elem[index] - thisPool->low; 1861 } 1862 if (((((base) / scaledAlign) * scaledAlign) + scaledOffset) != base) { 1863 LOG_ERROR(BSL_LS_SOC_COMMON, 1864 (BSL_META("WITH_ID requested element %d does not" 1865 " comply with alignment specifications\n"), 1866 elem[index])); 1867 result = _SHR_E_PARAM; 1868 } 1869 } 1870 if (_SHR_E_NONE == result) { 1871 result = _shr_res_alloc_mgrs[thisPool->resManagerType].align(thisPool, 1872 blkFlags, 1873 scaledAlign, 1874 scaledOffset, 1875 scaled, 1876 &(elem[index])); 1877 } 1878 } 1879 if (_SHR_E_NONE == result) { 1880 /* account for successful allocation */ 1881 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 1882 /* only account for alloc if new allocation */ 1883 handle->res[res_id]->refCount += count[index]; 1884 thisPool->inuse += scaled; 1885 } 1886 } else { 1887 /* we'll hope the allocation manager displayed an error */ 1888 /* don't want postincrement if an error occurred */ 1889 break; 1890 } 1891 } /* for (all blocks in the caller's group) */ 1892 if ((_SHR_E_NONE != result) && (grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 1893 /* atomic mode and it failed; back out everything that we have */ 1894 /* index is at the first failure */ 1895 while (index > 0) { 1896 /* look at previous index (must have been successful) */ 1897 index--; 1898 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 1899 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 1900 /* only free blocks that were not trying to be replaced */ 1901 /* adjust element count per scaling factor */ 1902 scaled = count[index] * thisRes->resElemSize; 1903 /* free this element or block */ 1904 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].free(thisPool, 1905 scaled, 1906 elem[index]); 1907 if (_SHR_E_NONE != xresult) { 1908 LOG_ERROR(BSL_LS_SOC_COMMON, 1909 (BSL_META("unable to back out %p resource %d" 1910 " index %d base %d count %d: %d (%s)\n"), 1911 (void*)handle, 1912 res_id, 1913 index, 1914 elem[index], 1915 count[index], 1916 result, 1917 _SHR_ERRMSG(result))); 1918 } else { 1919 thisRes->refCount -= count[index]; 1920 thisPool->inuse -= scaled; 1921 } 1922 } /* if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) */ 1923 } /* while (index > 0) */ 1924 } /* if (error && SHR_RES_ALLOC_GROUP_ATOMIC was set) */ 1925 /* update number of allocations that succeeded */ 1926 *grp_done = index; 1927 1928 /* return the result */ 1929 LOG_DEBUG(BSL_LS_SOC_COMMON, 1930 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p, %p, %p)" 1931 " return %d (%s)\n"), 1932 (void*)handle, 1933 res_id, 1934 grp_flags, 1935 grp_size, 1936 *grp_done, 1937 (void*)flags, 1938 (void*)align, 1939 (void*)offset, 1940 (void*)count, 1941 (void*)elem, 1942 result, 1943 _SHR_ERRMSG(result))); 1944 for (index = 0; index < grp_size; index++) { 1945 LOG_DEBUG(BSL_LS_SOC_COMMON, 1946 (BSL_META(" block %12d: %08X %12d %12d %12d %12d\n"), 1947 index, 1948 flags[index], 1949 align[index], 1950 offset[index], 1951 count[index], 1952 elem[index])); 1953 } 1954 return result; 1955 } 1956 1957 /* 1958 * Allocate a block of elements with the requested alignment and offset. 1959 */ 1960 int 1961 shr_mres_alloc_align_sparse(shr_mres_handle_t handle, 1962 int res_id, 1963 uint32 flags, 1964 int align, 1965 int offset, 1966 uint32 pattern, 1967 int length, 1968 int repeats, 1969 int *elem) 1970 { 1971 _shr_res_pool_desc_t *thisPool; 1972 _shr_res_type_desc_t *thisType; 1973 int result = _SHR_E_NONE; 1974 int count; 1975 int index; 1976 int base; 1977 1978 LOG_DEBUG(BSL_LS_SOC_COMMON, 1979 (BSL_META("(%p, %d, %08X, %d, %d, %08X, %d, %d, %p) enter\n"), 1980 (void*)handle, 1981 res_id, 1982 flags, 1983 align, 1984 offset, 1985 pattern, 1986 length, 1987 repeats, 1988 (void*)elem)); 1989 1990 /* a little parameter checking */ 1991 RES_HANDLE_VALID_CHECK(handle); 1992 RES_TYPE_VALID_CHECK(handle, res_id); 1993 RES_TYPE_EXIST_CHECK(handle, res_id); 1994 if (0 >= length) { 1995 LOG_ERROR(BSL_LS_SOC_COMMON, 1996 (BSL_META("pattern length must be greater than zero\n"))); 1997 return _SHR_E_PARAM; 1998 } 1999 if (32 < length) { 2000 LOG_ERROR(BSL_LS_SOC_COMMON, 2001 (BSL_META("pattern length must be 32 or less\n"))); 2002 return _SHR_E_PARAM; 2003 } 2004 if (0 >= repeats) { 2005 LOG_ERROR(BSL_LS_SOC_COMMON, 2006 (BSL_META("repeat count must be greater than zero\n"))); 2007 return _SHR_E_PARAM; 2008 } 2009 if (1 > align) { 2010 LOG_WARN(BSL_LS_SOC_COMMON, 2011 (BSL_META("align <= 0 invalid, using align = 1 instead\n"))); 2012 align = 1; 2013 } 2014 if ((offset >= align) || (0 > offset)) { 2015 LOG_ERROR(BSL_LS_SOC_COMMON, 2016 (BSL_META("offset %d must be >= 0 and < align %d\n"), 2017 offset, 2018 align)); 2019 return _SHR_E_PARAM; 2020 } 2021 if (flags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 2022 LOG_ERROR(BSL_LS_SOC_COMMON, 2023 (BSL_META("invalid flags %08X\n"), 2024 flags & (~SHR_RES_ALLOC_SINGLE_FLAGS))); 2025 return _SHR_E_PARAM; 2026 } 2027 if (!elem) { 2028 LOG_ERROR(BSL_LS_SOC_COMMON, 2029 (BSL_META("obligatory argument is NULL\n"))); 2030 return _SHR_E_PARAM; 2031 } 2032 /* get the pool information */ 2033 thisType = handle->res[res_id]; 2034 thisPool = handle->pool[thisType->resPoolId]; 2035 if (1 != thisType->resElemSize) { 2036 LOG_ERROR(BSL_LS_SOC_COMMON, 2037 (BSL_META("not compatible with scaled resources\n"))); 2038 return _SHR_E_CONFIG; 2039 } 2040 /* check alignment for WITH_ID case */ 2041 if (flags & SHR_RES_ALLOC_WITH_ID) { 2042 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 2043 base = *elem; 2044 } else { 2045 base = *elem - thisPool->low; 2046 } 2047 if (((((base) / align) * align) + offset) != base) { 2048 LOG_ERROR(BSL_LS_SOC_COMMON, 2049 (BSL_META("WITH_ID requested element %d does not comply" 2050 " with alignment specifications\n"), 2051 *elem)); 2052 return _SHR_E_PARAM; 2053 } 2054 } 2055 if (_shr_res_alloc_mgrs[thisPool->resManagerType].align_sparse) { 2056 /* allocator supports it; make the call */ 2057 result = _shr_res_alloc_mgrs[thisPool->resManagerType].align_sparse(thisPool, 2058 flags, 2059 align, 2060 offset, 2061 pattern, 2062 length, 2063 repeats, 2064 elem); 2065 } else { 2066 /* not supported by this allocator */ 2067 LOG_ERROR(BSL_LS_SOC_COMMON, 2068 (BSL_META("allocator type %s does not support aligned" 2069 " sparse alloc\n"), 2070 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 2071 result = _SHR_E_UNAVAIL; 2072 } 2073 if (_SHR_E_NONE == result) { 2074 /* account for successful allocation */ 2075 if (0 == (flags & SHR_RES_ALLOC_REPLACE)) { 2076 /* only account for alloc if new allocation */ 2077 for (index = 0, count = 0; index < length; index++) { 2078 if (pattern & (1 << index)) { 2079 count++; 2080 } 2081 } 2082 count *= repeats; 2083 handle->res[res_id]->refCount += count; 2084 thisPool->inuse += count; 2085 } 2086 } 2087 2088 LOG_DEBUG(BSL_LS_SOC_COMMON, 2089 (BSL_META("(%p, %d, %08X, %d, %d, %08X, %d, %d, &(%d))" 2090 " return %d (%s)\n"), 2091 (void*)handle, 2092 res_id, 2093 flags, 2094 align, 2095 offset, 2096 pattern, 2097 length, 2098 repeats, 2099 *elem, 2100 result, 2101 _SHR_ERRMSG(result))); 2102 return result; 2103 } 2104 2105 /* 2106 * Alloc a tagged block of elements with the requested alignment and offset. 2107 */ 2108 int 2109 shr_mres_alloc_align_tag(shr_mres_handle_t handle, 2110 int res_id, 2111 uint32 flags, 2112 int align, 2113 int offset, 2114 const void *tag, 2115 int count, 2116 int *elem) 2117 { 2118 _shr_res_pool_desc_t *thisPool; 2119 _shr_res_type_desc_t *thisType; 2120 int result = _SHR_E_NONE; 2121 int base; 2122 int scaled; 2123 int scaledAlign; 2124 int scaledOffset; 2125 2126 LOG_DEBUG(BSL_LS_SOC_COMMON, 2127 (BSL_META("(%p, %d, %08X, %d, %d, %p, %d, %p) enter\n"), 2128 (void*)handle, 2129 res_id, 2130 flags, 2131 align, 2132 offset, 2133 (void*)tag, 2134 count, 2135 (void*)elem)); 2136 2137 /* a little parameter checking */ 2138 RES_HANDLE_VALID_CHECK(handle); 2139 RES_TYPE_VALID_CHECK(handle, res_id); 2140 RES_TYPE_EXIST_CHECK(handle, res_id); 2141 if (0 >= count) { 2142 LOG_ERROR(BSL_LS_SOC_COMMON, 2143 (BSL_META("element count %d must be > 0\n"), 2144 count)); 2145 return _SHR_E_PARAM; 2146 } 2147 if (1 > align) { 2148 LOG_WARN(BSL_LS_SOC_COMMON, 2149 (BSL_META("align <= 0 invalid, using align = 1 instead\n"))); 2150 align = 1; 2151 } 2152 if ((offset >= align) || (0 > offset)) { 2153 LOG_ERROR(BSL_LS_SOC_COMMON, 2154 (BSL_META("offset %d must be >= 0 and < align %d\n"), 2155 offset, 2156 align)); 2157 return _SHR_E_PARAM; 2158 } 2159 if (flags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 2160 LOG_ERROR(BSL_LS_SOC_COMMON, 2161 (BSL_META("invalid flags %08X\n"), 2162 flags & (~SHR_RES_ALLOC_SINGLE_FLAGS))); 2163 return _SHR_E_PARAM; 2164 } 2165 if (!elem) { 2166 LOG_ERROR(BSL_LS_SOC_COMMON, 2167 (BSL_META("obligatory argument is NULL\n"))); 2168 return _SHR_E_PARAM; 2169 } 2170 /* get the pool information */ 2171 thisType = handle->res[res_id]; 2172 thisPool = handle->pool[thisType->resPoolId]; 2173 /* adjust element count per scaling factor */ 2174 scaled = count * thisType->resElemSize; 2175 scaledAlign = align * thisType->resElemSize; 2176 scaledOffset = offset * thisType->resElemSize; 2177 2178 /* check alignment for WITH_ID case */ 2179 if (flags & SHR_RES_ALLOC_WITH_ID) { 2180 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 2181 base = *elem; 2182 } else { 2183 base = *elem - thisPool->low; 2184 } 2185 if (((((base) / scaledAlign) * scaledAlign) + scaledOffset) != base) { 2186 LOG_ERROR(BSL_LS_SOC_COMMON, 2187 (BSL_META("WITH_ID requested element %d does not comply" 2188 " with alignment specifications\n"), 2189 *elem)); 2190 return _SHR_E_PARAM; 2191 } 2192 } 2193 if (_shr_res_alloc_mgrs[thisPool->resManagerType].tag_align) { 2194 /* allocator supports it; make the call */ 2195 result = _shr_res_alloc_mgrs[thisPool->resManagerType].tag_align(thisPool, 2196 flags, 2197 scaledAlign, 2198 scaledOffset, 2199 tag, 2200 scaled, 2201 elem); 2202 } else { 2203 /* not supported by this allocator */ 2204 LOG_ERROR(BSL_LS_SOC_COMMON, 2205 (BSL_META("allocator type %s does not support tagged aligned" 2206 " alloc\n"), 2207 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 2208 result = _SHR_E_UNAVAIL; 2209 } 2210 if (_SHR_E_NONE == result) { 2211 /* account for successful allocation */ 2212 if (0 == (flags & SHR_RES_ALLOC_REPLACE)) { 2213 /* only account for alloc if new allocation */ 2214 handle->res[res_id]->refCount += count; 2215 thisPool->inuse += scaled; 2216 } 2217 } 2218 2219 LOG_DEBUG(BSL_LS_SOC_COMMON, 2220 (BSL_META("(%p, %d, %08X, %d, %d, %p, %d, &(%d)) return" 2221 " %d (%s)\n"), 2222 (void*)handle, 2223 res_id, 2224 flags, 2225 align, 2226 offset, 2227 (void*)tag, 2228 count, 2229 *elem, 2230 result, 2231 _SHR_ERRMSG(result))); 2232 return result; 2233 } 2234 2235 /* 2236 * Allocate a bunch of aligned elements or blocks of a resource type 2237 */ 2238 int 2239 shr_mres_alloc_align_tag_group(shr_mres_handle_t handle, 2240 int res_id, 2241 uint32 grp_flags, 2242 int grp_size, 2243 int *grp_done, 2244 const uint32 *flags, 2245 const int *align, 2246 const int *offset, 2247 const void **tag, 2248 const int *count, 2249 int *elem) 2250 { 2251 _shr_res_pool_desc_t *thisPool; 2252 _shr_res_type_desc_t *thisRes; 2253 int result = _SHR_E_NONE; 2254 int xresult; 2255 int scaled = 0; 2256 int scaledAlign; 2257 int scaledOffset; 2258 int index; 2259 int xalign; 2260 int base; 2261 uint32 blkFlags; 2262 2263 LOG_DEBUG(BSL_LS_SOC_COMMON, 2264 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p, %p, %p, %p)" 2265 " enter\n"), 2266 (void*)handle, 2267 res_id, 2268 grp_flags, 2269 grp_size, 2270 (void*)grp_done, 2271 (void*)flags, 2272 (void*)align, 2273 (void*)offset, 2274 (void*)tag, 2275 (void*)count, 2276 (void*)elem)); 2277 2278 /* a little parameter checking */ 2279 RES_HANDLE_VALID_CHECK(handle); 2280 RES_TYPE_VALID_CHECK(handle, res_id); 2281 RES_TYPE_EXIST_CHECK(handle, res_id); 2282 if (!grp_done) { 2283 LOG_ERROR(BSL_LS_SOC_COMMON, 2284 (BSL_META("obligatory out argument grp_done is NULL\n"))); 2285 return _SHR_E_PARAM; 2286 } 2287 *grp_done = 0; 2288 if (0 > grp_size) { 2289 LOG_ERROR(BSL_LS_SOC_COMMON, 2290 (BSL_META("group member count %d must be >= 0\n"), 2291 grp_size)); 2292 return _SHR_E_PARAM; 2293 } 2294 if ((0 < grp_size) && (!flags || !count || !elem || !align || !offset)) { 2295 LOG_ERROR(BSL_LS_SOC_COMMON, 2296 (BSL_META("an obligatory array pointer is NULL\n"))); 2297 return _SHR_E_PARAM; 2298 } 2299 if (grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | SHR_RES_ALLOC_GROUP_FLAGS))) { 2300 LOG_ERROR(BSL_LS_SOC_COMMON, 2301 (BSL_META("invalid group flags %08X\n"), 2302 grp_flags & (~(SHR_RES_ALLOC_SINGLE_FLAGS | 2303 SHR_RES_ALLOC_GROUP_FLAGS)))); 2304 return _SHR_E_PARAM; 2305 } 2306 /* get the resource information */ 2307 thisRes = handle->res[res_id]; 2308 /* get the pool information */ 2309 thisPool = handle->pool[thisRes->resPoolId]; 2310 /* try to collect the requested blocks */ 2311 if (_shr_res_alloc_mgrs[thisPool->resManagerType].tag_align) { 2312 /* allocator does not support this feature */ 2313 LOG_ERROR(BSL_LS_SOC_COMMON, 2314 (BSL_META("allocator type %s does not support tagged aligned" 2315 " alloc\n"), 2316 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 2317 result = _SHR_E_UNAVAIL; 2318 } 2319 for (index = 0; 2320 (_SHR_E_NONE == result) && (index < grp_size); 2321 index++) { 2322 /* check parameters for this block */ 2323 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 2324 if (blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS)) { 2325 LOG_ERROR(BSL_LS_SOC_COMMON, 2326 (BSL_META("invalid flags %08X for block %d\n"), 2327 blkFlags & (~SHR_RES_ALLOC_SINGLE_FLAGS), 2328 index)); 2329 result = _SHR_E_PARAM; 2330 } 2331 if (0 >= count[index]) { 2332 LOG_ERROR(BSL_LS_SOC_COMMON, 2333 (BSL_META("element count %d must be > 0\n"), 2334 count[index])); 2335 result = _SHR_E_PARAM; 2336 } 2337 if (1 > align[index]) { 2338 LOG_WARN(BSL_LS_SOC_COMMON, 2339 (BSL_META("align <= 0 invalid, using align = 1 instead\n"))); 2340 xalign = 1; 2341 } else { 2342 xalign = align[index]; 2343 } 2344 if ((offset[index] >= xalign) || (0 > offset[index])) { 2345 LOG_ERROR(BSL_LS_SOC_COMMON, 2346 (BSL_META("offset %d must be >= 0 and < align %d\n"), 2347 offset[index], 2348 xalign)); 2349 result = _SHR_E_PARAM; 2350 } 2351 if (_SHR_E_NONE == result) { 2352 /* adjust element count per scaling factor */ 2353 scaled = count[index] * thisRes->resElemSize; 2354 scaledAlign = xalign * thisRes->resElemSize; 2355 scaledOffset = offset[index] * thisRes->resElemSize; 2356 2357 /* check alignment for WITH_ID case */ 2358 if (blkFlags & SHR_RES_ALLOC_WITH_ID) { 2359 if (blkFlags & SHR_RES_ALLOC_ALIGN_ZERO) { 2360 base = elem[index]; 2361 } else { 2362 base = elem[index] - thisPool->low; 2363 } 2364 if (((((base) / scaledAlign) * scaledAlign) + scaledOffset) != base) { 2365 LOG_ERROR(BSL_LS_SOC_COMMON, 2366 (BSL_META("WITH_ID requested element %d does not" 2367 " comply with alignment specifications\n"), 2368 elem[index])); 2369 result = _SHR_E_PARAM; 2370 } 2371 } 2372 if (_SHR_E_NONE == result) { 2373 result = _shr_res_alloc_mgrs[thisPool->resManagerType].tag_align(thisPool, 2374 blkFlags, 2375 scaledAlign, 2376 scaledOffset, 2377 tag[index], 2378 scaled, 2379 &(elem[index])); 2380 } 2381 } 2382 if (_SHR_E_NONE == result) { 2383 /* account for successful allocation */ 2384 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 2385 /* only account for alloc if new allocation */ 2386 handle->res[res_id]->refCount += count[index]; 2387 thisPool->inuse += scaled; 2388 } 2389 } else { 2390 /* we'll hope the allocation manager displayed an error */ 2391 /* don't want postincrement if an error occurred */ 2392 break; 2393 } 2394 } /* for (all blocks in the caller's group) */ 2395 if ((_SHR_E_NONE != result) && (grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 2396 /* atomic mode and it failed; back out everything that we have */ 2397 /* index is at the first failure */ 2398 while (index > 0) { 2399 /* look at previous index (must have been successful) */ 2400 index--; 2401 blkFlags = flags[index] | (grp_flags & SHR_RES_ALLOC_SINGLE_FLAGS); 2402 if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) { 2403 /* only free blocks that were not trying to be replaced */ 2404 /* adjust element count per scaling factor */ 2405 scaled = count[index] * thisRes->resElemSize; 2406 /* free this element or block */ 2407 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].free(thisPool, 2408 scaled, 2409 elem[index]); 2410 if (_SHR_E_NONE != xresult) { 2411 LOG_ERROR(BSL_LS_SOC_COMMON, 2412 (BSL_META("unable to back out %p resource %d" 2413 " index %d base %d count %d: %d (%s)\n"), 2414 (void*)handle, 2415 res_id, 2416 index, 2417 elem[index], 2418 count[index], 2419 result, 2420 _SHR_ERRMSG(result))); 2421 } else { 2422 thisRes->refCount -= count[index]; 2423 thisPool->inuse -= scaled; 2424 } 2425 } /* if (0 == (blkFlags & SHR_RES_ALLOC_REPLACE)) */ 2426 } /* while (index > 0) */ 2427 } /* if (error && SHR_RES_ALLOC_GROUP_ATOMIC was set) */ 2428 /* update number of allocations that succeeded */ 2429 *grp_done = index; 2430 2431 /* return the result */ 2432 LOG_DEBUG(BSL_LS_SOC_COMMON, 2433 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p, %p, %p, %p)" 2434 " return %d (%s)\n"), 2435 (void*)handle, 2436 res_id, 2437 grp_flags, 2438 grp_size, 2439 *grp_done, 2440 (void*)flags, 2441 (void*)align, 2442 (void*)offset, 2443 (void*)tag, 2444 (void*)count, 2445 (void*)elem, 2446 result, 2447 _SHR_ERRMSG(result))); 2448 for (index = 0; index < grp_size; index++) { 2449 LOG_DEBUG(BSL_LS_SOC_COMMON, 2450 (BSL_META(" block %12d: %08X %12d %12d %12d %12d\n"), 2451 index, 2452 flags[index], 2453 align[index], 2454 offset[index], 2455 count[index], 2456 elem[index])); 2457 } 2458 return result; 2459 } 2460 2461 /* 2462 * Free elements of a resource type then get status flags 2463 */ 2464 int 2465 shr_mres_free_and_status(shr_mres_handle_t handle, 2466 int res_id, 2467 int count, 2468 int elem, 2469 uint32 *status) 2470 { 2471 _shr_res_pool_desc_t *thisPool; 2472 int result = _SHR_E_NONE; 2473 int scaled; 2474 2475 LOG_DEBUG(BSL_LS_SOC_COMMON, 2476 (BSL_META("(%p, %d, %d, %d, %p) enter\n"), 2477 (void*)handle, 2478 res_id, 2479 count, 2480 elem, 2481 (void*)status)); 2482 2483 /* a little parameter checking */ 2484 RES_HANDLE_VALID_CHECK(handle); 2485 RES_TYPE_VALID_CHECK(handle, res_id); 2486 RES_TYPE_EXIST_CHECK(handle, res_id); 2487 if (0 >= count) { 2488 LOG_ERROR(BSL_LS_SOC_COMMON, 2489 (BSL_META("element count %d must be > 0\n"), 2490 count)); 2491 return _SHR_E_PARAM; 2492 } 2493 /* adjust element count per scaling factor */ 2494 scaled = count * handle->res[res_id]->resElemSize; 2495 2496 /* get the pool information */ 2497 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 2498 /* make the call */ 2499 result = _shr_res_alloc_mgrs[thisPool->resManagerType].free(thisPool, 2500 scaled, 2501 elem); 2502 if (_SHR_E_NONE == result) { 2503 /* account for successful deallocation */ 2504 handle->res[res_id]->refCount -= count; 2505 thisPool->inuse -= scaled; 2506 if (status) { 2507 *status = 0; 2508 if (!(handle->res[res_id]->refCount)) { 2509 (*status) |= SHR_RES_FREED_TYPE_LAST_ELEM; 2510 } 2511 if (!(thisPool->inuse)) { 2512 (*status) |= SHR_RES_FREED_POOL_LAST_ELEM; 2513 } 2514 } /* if (flags) */ 2515 } /* if (_SHR_E_NONE == result) */ 2516 2517 LOG_DEBUG(BSL_LS_SOC_COMMON, 2518 (BSL_META("(%p, %d, %d, %d, &(%08X)) return %d (%s)\n"), 2519 (void*)handle, 2520 res_id, 2521 count, 2522 elem, 2523 status?(*status):0, 2524 result, 2525 _SHR_ERRMSG(result))); 2526 return result; 2527 } 2528 2529 /* 2530 * Free elements of a resource type 2531 */ 2532 int 2533 shr_mres_free(shr_mres_handle_t handle, 2534 int res_id, 2535 int count, 2536 int elem) 2537 { 2538 return shr_mres_free_and_status(handle, res_id, count, elem, NULL); 2539 } 2540 2541 /* 2542 * Free a bunch of elements/blocks of a resource type then get status flags 2543 */ 2544 int 2545 shr_mres_free_group_and_status(shr_mres_handle_t handle, 2546 int res_id, 2547 uint32 grp_flags, 2548 int grp_size, 2549 int *grp_done, 2550 const int *count, 2551 const int *elem, 2552 uint32 *status) 2553 { 2554 _shr_res_pool_desc_t *thisPool; 2555 _shr_res_type_desc_t *thisRes; 2556 int result = _SHR_E_NONE; 2557 int index; 2558 int scaled; 2559 2560 LOG_DEBUG(BSL_LS_SOC_COMMON, 2561 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p) enter\n"), 2562 (void*)handle, 2563 res_id, 2564 grp_flags, 2565 grp_size, 2566 (void*)grp_done, 2567 (void*)count, 2568 (void*)elem, 2569 (void*)status)); 2570 2571 /* a little parameter checking */ 2572 RES_HANDLE_VALID_CHECK(handle); 2573 RES_TYPE_VALID_CHECK(handle, res_id); 2574 RES_TYPE_EXIST_CHECK(handle, res_id); 2575 if (!grp_done) { 2576 LOG_ERROR(BSL_LS_SOC_COMMON, 2577 (BSL_META("obligatory out argument grp_done is NULL\n"))); 2578 return _SHR_E_PARAM; 2579 } 2580 *grp_done = 0; 2581 if (0 > grp_size) { 2582 LOG_ERROR(BSL_LS_SOC_COMMON, 2583 (BSL_META("group member count %d must be >= 0\n"), 2584 grp_size)); 2585 return _SHR_E_PARAM; 2586 } 2587 if ((0 < grp_size) && (!count || !elem)) { 2588 LOG_ERROR(BSL_LS_SOC_COMMON, 2589 (BSL_META("an obligatory array pointer is NULL\n"))); 2590 return _SHR_E_PARAM; 2591 } 2592 if (grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS)) { 2593 LOG_ERROR(BSL_LS_SOC_COMMON, 2594 (BSL_META("invalid group flags %08X\n"), 2595 grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS))); 2596 return _SHR_E_PARAM; 2597 } 2598 /* get the resource information */ 2599 thisRes = handle->res[res_id]; 2600 /* get the pool information */ 2601 thisPool = handle->pool[thisRes->resPoolId]; 2602 /* try to release the requested blocks */ 2603 for (index = 0; 2604 (_SHR_E_NONE == result) && (index < grp_size); 2605 index++) { 2606 /* adjust element count per scaling factor */ 2607 scaled = count[index] * thisRes->resElemSize; 2608 /* free this element or block */ 2609 result = _shr_res_alloc_mgrs[thisPool->resManagerType].free(thisPool, 2610 scaled, 2611 elem[index]); 2612 if (_SHR_E_NONE == result) { 2613 /* account for successful deallocation */ 2614 handle->res[res_id]->refCount -= count[index]; 2615 thisPool->inuse -= scaled; 2616 } else { 2617 /* we'll hope the allocation manager displayed an error */ 2618 /* don't want postincrement if an error occurred */ 2619 break; 2620 } 2621 } /* for (all elements/blocks as long as no errors) */ 2622 /* update number of frees that succeeded */ 2623 *grp_done = index; 2624 if (status) { 2625 *status = 0; 2626 if (!(handle->res[res_id]->refCount)) { 2627 (*status) |= SHR_RES_FREED_TYPE_LAST_ELEM; 2628 } 2629 if (!(thisPool->inuse)) { 2630 (*status) |= SHR_RES_FREED_POOL_LAST_ELEM; 2631 } 2632 } /* if (flags) */ 2633 2634 /* return the result */ 2635 LOG_DEBUG(BSL_LS_SOC_COMMON, 2636 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, &(%08X)) return %d (%s)\n"), 2637 (void*)handle, 2638 res_id, 2639 grp_flags, 2640 grp_size, 2641 *grp_done, 2642 (void*)count, 2643 (void*)elem, 2644 status?(*status):0, 2645 result, 2646 _SHR_ERRMSG(result))); 2647 for (index = 0; index < grp_size; index++) { 2648 LOG_DEBUG(BSL_LS_SOC_COMMON, 2649 (BSL_META(" block %12d: %12d, %12d\n"), 2650 index, 2651 count[index], 2652 elem[index])); 2653 } 2654 return result; 2655 } 2656 2657 /* 2658 * Free a bunch of elements/blocks of a resource type 2659 */ 2660 int 2661 shr_mres_free_group(shr_mres_handle_t handle, 2662 int res_id, 2663 uint32 grp_flags, 2664 int grp_size, 2665 int *grp_done, 2666 const int *count, 2667 const int *elem) 2668 { 2669 return shr_mres_free_group_and_status(handle, 2670 res_id, 2671 grp_flags, 2672 grp_size, 2673 grp_done, 2674 count, 2675 elem, 2676 NULL); 2677 } 2678 2679 /* 2680 * Free elements of a resource type then get status flags 2681 */ 2682 int 2683 shr_mres_free_sparse_and_status(shr_mres_handle_t handle, 2684 int res_id, 2685 uint32 pattern, 2686 int length, 2687 int repeats, 2688 int elem, 2689 uint32 *status) 2690 { 2691 _shr_res_pool_desc_t *thisPool; 2692 int result = _SHR_E_NONE; 2693 int count; 2694 int index; 2695 2696 LOG_DEBUG(BSL_LS_SOC_COMMON, 2697 (BSL_META("(%p, %d, %08X, %d, %d, %d, %p) enter\n"), 2698 (void*)handle, 2699 res_id, 2700 pattern, 2701 length, 2702 repeats, 2703 elem, 2704 (void*)status)); 2705 2706 /* a little parameter checking */ 2707 RES_HANDLE_VALID_CHECK(handle); 2708 RES_TYPE_VALID_CHECK(handle, res_id); 2709 RES_TYPE_EXIST_CHECK(handle, res_id); 2710 if (0 >= length) { 2711 LOG_ERROR(BSL_LS_SOC_COMMON, 2712 (BSL_META("pattern length must be greater than zero\n"))); 2713 return _SHR_E_PARAM; 2714 } 2715 if (32 < length) { 2716 LOG_ERROR(BSL_LS_SOC_COMMON, 2717 (BSL_META("pattern length must be 32 or less\n"))); 2718 return _SHR_E_PARAM; 2719 } 2720 if (0 >= repeats) { 2721 LOG_ERROR(BSL_LS_SOC_COMMON, 2722 (BSL_META("repeat count must be greater than zero\n"))); 2723 return _SHR_E_PARAM; 2724 } 2725 if (1 != handle->res[res_id]->resElemSize) { 2726 LOG_ERROR(BSL_LS_SOC_COMMON, 2727 (BSL_META("not compatible with scaled resources\n"))); 2728 return _SHR_E_CONFIG; 2729 } 2730 /* get the pool information */ 2731 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 2732 if (_shr_res_alloc_mgrs[thisPool->resManagerType].free_sparse) { 2733 /* make the call */ 2734 result = _shr_res_alloc_mgrs[thisPool->resManagerType].free_sparse(thisPool, 2735 pattern, 2736 length, 2737 repeats, 2738 elem); 2739 if (_SHR_E_NONE == result) { 2740 /* account for successful deallocation */ 2741 for (index = 0, count = 0; index < length; index++) { 2742 if (pattern & (1 << index)) { 2743 count++; 2744 } 2745 } 2746 count *= repeats; 2747 handle->res[res_id]->refCount -= count; 2748 thisPool->inuse -= count; 2749 if (status) { 2750 *status = 0; 2751 if (!(handle->res[res_id]->refCount)) { 2752 (*status) |= SHR_RES_FREED_TYPE_LAST_ELEM; 2753 } 2754 if (!(thisPool->inuse)) { 2755 (*status) |= SHR_RES_FREED_POOL_LAST_ELEM; 2756 } 2757 } /* if (status) */ 2758 } /* if (_SHR_E_NONE == result) */ 2759 } else { 2760 LOG_ERROR(BSL_LS_SOC_COMMON, 2761 (BSL_META("allocator does not support sparse free\n"))); 2762 return _SHR_E_UNAVAIL; 2763 } 2764 2765 LOG_DEBUG(BSL_LS_SOC_COMMON, 2766 (BSL_META("(%p, %d, %08X, %d, %d, %d, &(%08X)) return %d (%s)\n"), 2767 (void*)handle, 2768 res_id, 2769 pattern, 2770 length, 2771 repeats, 2772 elem, 2773 status?(*status):0, 2774 result, 2775 _SHR_ERRMSG(result))); 2776 return result; 2777 } 2778 2779 /* 2780 * Free elements of a resource type 2781 */ 2782 int 2783 shr_mres_free_sparse(shr_mres_handle_t handle, 2784 int res_id, 2785 uint32 pattern, 2786 int length, 2787 int repeats, 2788 int elem) 2789 { 2790 return shr_mres_free_sparse_and_status(handle, 2791 res_id, 2792 pattern, 2793 length, 2794 repeats, 2795 elem, 2796 NULL); 2797 } 2798 2799 /* 2800 * Check whether there are in-use elements in a block 2801 */ 2802 int 2803 shr_mres_check(shr_mres_handle_t handle, 2804 int res_id, 2805 int count, 2806 int elem) 2807 { 2808 _shr_res_pool_desc_t *thisPool; 2809 int scaled; 2810 int result; 2811 2812 LOG_DEBUG(BSL_LS_SOC_COMMON, 2813 (BSL_META("(%p, %d, %d, %d) enter\n"), 2814 (void*)handle, 2815 res_id, 2816 count, 2817 elem)); 2818 2819 /* a little parameter checking */ 2820 RES_HANDLE_VALID_CHECK(handle); 2821 RES_TYPE_VALID_CHECK(handle, res_id); 2822 RES_TYPE_EXIST_CHECK(handle, res_id); 2823 if (1 > count) { 2824 LOG_ERROR(BSL_LS_SOC_COMMON, 2825 (BSL_META("element count %d must be > 0\n"), 2826 count)); 2827 return _SHR_E_PARAM; 2828 } 2829 /* adjust element count per scaling factor */ 2830 scaled = count * handle->res[res_id]->resElemSize; 2831 2832 /* get the pool information */ 2833 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 2834 /* make the call */ 2835 result = _shr_res_alloc_mgrs[thisPool->resManagerType].check(thisPool, 2836 scaled, 2837 elem); 2838 2839 LOG_DEBUG(BSL_LS_SOC_COMMON, 2840 (BSL_META("(%p, %d, %d, %d) return %d (%s)\n"), 2841 (void*)handle, 2842 res_id, 2843 count, 2844 elem, 2845 result, 2846 _SHR_ERRMSG(result))); 2847 return result; 2848 } 2849 2850 /* 2851 * Check a bunch of elements/blocks of a resource type 2852 */ 2853 int 2854 shr_mres_check_group(shr_mres_handle_t handle, 2855 int res_id, 2856 uint32 grp_flags, 2857 int grp_size, 2858 int *grp_done, 2859 const int *count, 2860 const int *elem, 2861 int *status) 2862 { 2863 _shr_res_pool_desc_t *thisPool; 2864 _shr_res_type_desc_t *thisRes; 2865 int result = _SHR_E_NONE; 2866 int xresult; 2867 int index; 2868 int scaled; 2869 2870 LOG_DEBUG(BSL_LS_SOC_COMMON, 2871 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p) enter\n"), 2872 (void*)handle, 2873 res_id, 2874 grp_flags, 2875 grp_size, 2876 (void*)grp_done, 2877 (void*)count, 2878 (void*)elem, 2879 (void*)status)); 2880 2881 /* a little parameter checking */ 2882 RES_HANDLE_VALID_CHECK(handle); 2883 RES_TYPE_VALID_CHECK(handle, res_id); 2884 RES_TYPE_EXIST_CHECK(handle, res_id); 2885 if (!grp_done) { 2886 LOG_ERROR(BSL_LS_SOC_COMMON, 2887 (BSL_META("obligatory out argument grp_done is NULL\n"))); 2888 return _SHR_E_PARAM; 2889 } 2890 *grp_done = 0; 2891 if (0 > grp_size) { 2892 LOG_ERROR(BSL_LS_SOC_COMMON, 2893 (BSL_META("group member count %d must be >= 0\n"), 2894 grp_size)); 2895 return _SHR_E_PARAM; 2896 } 2897 if ((0 < grp_size) && (!count || !elem || !status)) { 2898 LOG_ERROR(BSL_LS_SOC_COMMON, 2899 (BSL_META("an obligatory array pointer is NULL\n"))); 2900 return _SHR_E_PARAM; 2901 } 2902 if (grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS)) { 2903 LOG_ERROR(BSL_LS_SOC_COMMON, 2904 (BSL_META("invalid group flags %08X\n"), 2905 grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS))); 2906 return _SHR_E_PARAM; 2907 } 2908 /* get the resource information */ 2909 thisRes = handle->res[res_id]; 2910 /* get the pool information */ 2911 thisPool = handle->pool[thisRes->resPoolId]; 2912 /* try to check the requested blocks */ 2913 for (index = 0; 2914 (_SHR_E_NONE == result) && (index < grp_size); 2915 index++) { 2916 /* adjust element count per scaling factor */ 2917 scaled = count[index] * thisRes->resElemSize; 2918 /* check this element or block */ 2919 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].check(thisPool, 2920 scaled, 2921 elem[index]); 2922 status[index] = xresult; 2923 if ((_SHR_E_NOT_FOUND != xresult) && 2924 (_SHR_E_EXISTS != xresult)) { 2925 LOG_ERROR(BSL_LS_SOC_COMMON, 2926 (BSL_META("unexpected result checking %p resource %d" 2927 " index %d elem %d count %d: %d (%s)\n"), 2928 (void*)handle, 2929 res_id, 2930 index, 2931 elem[index], 2932 count[index], 2933 result, 2934 _SHR_ERRMSG(result))); 2935 if (!(grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 2936 /* if not atomic mode, abort on first unexpected result */ 2937 result = _SHR_E_FAIL; 2938 break; 2939 } 2940 } /* if (result is neither NOT_FOUND nor EXISTS) */ 2941 } /* for (all elements/blocks as long as no errors) */ 2942 /* update number of frees that succeeded */ 2943 *grp_done = index; 2944 2945 /* return the result */ 2946 LOG_DEBUG(BSL_LS_SOC_COMMON, 2947 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p) return %d (%s)\n"), 2948 (void*)handle, 2949 res_id, 2950 grp_flags, 2951 grp_size, 2952 *grp_done, 2953 (void*)count, 2954 (void*)elem, 2955 (void*)status, 2956 result, 2957 _SHR_ERRMSG(result))); 2958 for (index = 0; index < grp_size; index++) { 2959 LOG_DEBUG(BSL_LS_SOC_COMMON, 2960 (BSL_META(" block %12d: %d, %d, %d (%s)\n"), 2961 index, 2962 count[index], 2963 elem[index], 2964 status[index], 2965 _SHR_ERRMSG(status[index]))); 2966 } 2967 return result; 2968 } 2969 2970 /* 2971 * Check whether all elements are free, all elements are used, mixed free and 2972 * in-use, or block size is appropriate, for a block of elements. The block 2973 * size check assumes the intent is to 'reallocate' the specified block for a 2974 * paritcular purpose, and failing it does not indicate corruption or fault. 2975 */ 2976 int 2977 shr_mres_check_all(shr_mres_handle_t handle, 2978 int res_id, 2979 int count, 2980 int elem) 2981 { 2982 _shr_res_pool_desc_t *thisPool; 2983 int scaled; 2984 int result; 2985 2986 LOG_DEBUG(BSL_LS_SOC_COMMON, 2987 (BSL_META("(%p, %d, %d, %d) enter\n"), 2988 (void*)handle, 2989 res_id, 2990 count, 2991 elem)); 2992 2993 /* a little parameter checking */ 2994 RES_HANDLE_VALID_CHECK(handle); 2995 RES_TYPE_VALID_CHECK(handle, res_id); 2996 RES_TYPE_EXIST_CHECK(handle, res_id); 2997 if (1 > count) { 2998 LOG_ERROR(BSL_LS_SOC_COMMON, 2999 (BSL_META("element count %d must be > 0\n"), 3000 count)); 3001 return _SHR_E_PARAM; 3002 } 3003 /* adjust element count per scaling factor */ 3004 scaled = count * handle->res[res_id]->resElemSize; 3005 3006 /* get the pool information */ 3007 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 3008 /* make the call */ 3009 result = _shr_res_alloc_mgrs[thisPool->resManagerType].check_all(thisPool, 3010 scaled, 3011 elem); 3012 3013 LOG_DEBUG(BSL_LS_SOC_COMMON, 3014 (BSL_META("(%p, %d, %d, %d) return %d (%s)\n"), 3015 (void*)handle, 3016 res_id, 3017 count, 3018 elem, 3019 result, 3020 _SHR_ERRMSG(result))); 3021 return result; 3022 } 3023 3024 /* 3025 * Check_all for a bunch of elements/blocks of a resource type 3026 */ 3027 int 3028 shr_mres_check_all_group(shr_mres_handle_t handle, 3029 int res_id, 3030 uint32 grp_flags, 3031 int grp_size, 3032 int *grp_done, 3033 const int *count, 3034 const int *elem, 3035 int *status) 3036 { 3037 _shr_res_pool_desc_t *thisPool; 3038 _shr_res_type_desc_t *thisRes; 3039 int result = _SHR_E_NONE; 3040 int xresult; 3041 int index; 3042 int scaled; 3043 3044 LOG_DEBUG(BSL_LS_SOC_COMMON, 3045 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p) enter\n"), 3046 (void*)handle, 3047 res_id, 3048 grp_flags, 3049 grp_size, 3050 (void*)grp_done, 3051 (void*)count, 3052 (void*)elem, 3053 (void*)status)); 3054 3055 /* a little parameter checking */ 3056 RES_HANDLE_VALID_CHECK(handle); 3057 RES_TYPE_VALID_CHECK(handle, res_id); 3058 RES_TYPE_EXIST_CHECK(handle, res_id); 3059 if (!grp_done) { 3060 LOG_ERROR(BSL_LS_SOC_COMMON, 3061 (BSL_META("obligatory out argument grp_done is NULL\n"))); 3062 return _SHR_E_PARAM; 3063 } 3064 *grp_done = 0; 3065 if (0 > grp_size) { 3066 LOG_ERROR(BSL_LS_SOC_COMMON, 3067 (BSL_META("group member count %d must be >= 0\n"), 3068 grp_size)); 3069 return _SHR_E_PARAM; 3070 } 3071 if ((0 < grp_size) && (!count || !elem || !status)) { 3072 LOG_ERROR(BSL_LS_SOC_COMMON, 3073 (BSL_META("an obligatory array pointer is NULL\n"))); 3074 return _SHR_E_PARAM; 3075 } 3076 if (grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS)) { 3077 LOG_ERROR(BSL_LS_SOC_COMMON, 3078 (BSL_META("invalid group flags %08X\n"), 3079 grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS))); 3080 return _SHR_E_PARAM; 3081 } 3082 /* get the resource information */ 3083 thisRes = handle->res[res_id]; 3084 /* get the pool information */ 3085 thisPool = handle->pool[thisRes->resPoolId]; 3086 /* try to check the requested blocks */ 3087 for (index = 0; 3088 (_SHR_E_NONE == result) && (index < grp_size); 3089 index++) { 3090 /* adjust element count per scaling factor */ 3091 scaled = count[index] * thisRes->resElemSize; 3092 /* check this element or block */ 3093 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].check_all(thisPool, 3094 scaled, 3095 elem[index]); 3096 status[index] = xresult; 3097 if ((_SHR_E_NOT_FOUND != xresult) && 3098 (_SHR_E_EXISTS != xresult)) { 3099 LOG_ERROR(BSL_LS_SOC_COMMON, 3100 (BSL_META("unexpected result checking %p resource %d" 3101 " index %d elem %d count %d: %d (%s)\n"), 3102 (void*)handle, 3103 res_id, 3104 index, 3105 elem[index], 3106 count[index], 3107 result, 3108 _SHR_ERRMSG(result))); 3109 if (!(grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 3110 /* if not atomic mode, abort on first unexpected result */ 3111 result = _SHR_E_FAIL; 3112 break; 3113 } 3114 } /* if (result is neither NOT_FOUND nor EXISTS) */ 3115 } /* for (all elements/blocks as long as no errors) */ 3116 /* update number of frees that succeeded */ 3117 *grp_done = index; 3118 3119 /* return the result */ 3120 LOG_DEBUG(BSL_LS_SOC_COMMON, 3121 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p) return %d (%s)\n"), 3122 (void*)handle, 3123 res_id, 3124 grp_flags, 3125 grp_size, 3126 *grp_done, 3127 (void*)count, 3128 (void*)elem, 3129 (void*)status, 3130 result, 3131 _SHR_ERRMSG(result))); 3132 for (index = 0; index < grp_size; index++) { 3133 LOG_DEBUG(BSL_LS_SOC_COMMON, 3134 (BSL_META(" block %12d: %d, %d, %d (%s)\n"), 3135 index, 3136 count[index], 3137 elem[index], 3138 status[index], 3139 _SHR_ERRMSG(status[index]))); 3140 } 3141 return result; 3142 } 3143 3144 /* 3145 * Check whether all elements are free, all elements are used, mixed free and 3146 * in-use, or block size is appropriate, for a sparse block of elements. The 3147 * block size check assumes the intent is to 'reallocate' the specified block 3148 * for a paritcular purpose, and failing it does not indicate corruption or 3149 * fault. 3150 */ 3151 int 3152 shr_mres_check_all_sparse(shr_mres_handle_t handle, 3153 int res_id, 3154 uint32 pattern, 3155 int length, 3156 int repeats, 3157 int elem) 3158 { 3159 _shr_res_pool_desc_t *thisPool; 3160 int result; 3161 3162 LOG_DEBUG(BSL_LS_SOC_COMMON, 3163 (BSL_META("(%p, %d, %08X, %d, %d, %d) enter\n"), 3164 (void*)handle, 3165 res_id, 3166 pattern, 3167 length, 3168 repeats, 3169 elem)); 3170 3171 /* a little parameter checking */ 3172 RES_HANDLE_VALID_CHECK(handle); 3173 RES_TYPE_VALID_CHECK(handle, res_id); 3174 RES_TYPE_EXIST_CHECK(handle, res_id); 3175 if (0 >= length) { 3176 LOG_ERROR(BSL_LS_SOC_COMMON, 3177 (BSL_META("pattern length must be greater than zero\n"))); 3178 return _SHR_E_PARAM; 3179 } 3180 if (32 < length) { 3181 LOG_ERROR(BSL_LS_SOC_COMMON, 3182 (BSL_META("pattern length must be 32 or less\n"))); 3183 return _SHR_E_PARAM; 3184 } 3185 if (0 >= repeats) { 3186 LOG_ERROR(BSL_LS_SOC_COMMON, 3187 (BSL_META("repeat count must be greater than zero\n"))); 3188 return _SHR_E_PARAM; 3189 } 3190 if (1 != handle->res[res_id]->resElemSize) { 3191 LOG_ERROR(BSL_LS_SOC_COMMON, 3192 (BSL_META("not compatible with scaled resources\n"))); 3193 return _SHR_E_CONFIG; 3194 } 3195 /* get the pool information */ 3196 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 3197 if (_shr_res_alloc_mgrs[thisPool->resManagerType].c_a_sparse) { 3198 /* make the call */ 3199 result = _shr_res_alloc_mgrs[thisPool->resManagerType].c_a_sparse(thisPool, 3200 pattern, 3201 length, 3202 repeats, 3203 elem); 3204 } else { 3205 LOG_ERROR(BSL_LS_SOC_COMMON, 3206 (BSL_META("allocator does not support sparse check all\n"))); 3207 return _SHR_E_UNAVAIL; 3208 } 3209 3210 LOG_DEBUG(BSL_LS_SOC_COMMON, 3211 (BSL_META("(%p, %d, %08X, %d, %d, %d) return %d (%s)\n"), 3212 (void*)handle, 3213 res_id, 3214 pattern, 3215 length, 3216 repeats, 3217 elem, 3218 result, 3219 _SHR_ERRMSG(result))); 3220 return result; 3221 } 3222 3223 /* 3224 * Check whether all elements are free, all elements are used, mixed free and 3225 * in-use, or block size is appropriate, for a block of elements. The block 3226 * size check assumes the intent is to 'reallocate' the specified block for a 3227 * paritcular purpose, and failing it does not indicate corruption or fault. 3228 */ 3229 int 3230 shr_mres_check_all_tag(shr_mres_handle_t handle, 3231 int res_id, 3232 const void *tag, 3233 int count, 3234 int elem) 3235 { 3236 _shr_res_pool_desc_t *thisPool; 3237 int scaled; 3238 int result; 3239 3240 LOG_DEBUG(BSL_LS_SOC_COMMON, 3241 (BSL_META("(%p, %d, %p, %d, %d) enter\n"), 3242 (void*)handle, 3243 res_id, 3244 (void*)tag, 3245 count, 3246 elem)); 3247 3248 /* a little parameter checking */ 3249 RES_HANDLE_VALID_CHECK(handle); 3250 RES_TYPE_VALID_CHECK(handle, res_id); 3251 RES_TYPE_EXIST_CHECK(handle, res_id); 3252 if (1 > count) { 3253 LOG_ERROR(BSL_LS_SOC_COMMON, 3254 (BSL_META("element count %d must be > 0\n"), 3255 count)); 3256 return _SHR_E_PARAM; 3257 } 3258 /* adjust element count per scaling factor */ 3259 scaled = count * handle->res[res_id]->resElemSize; 3260 3261 /* get the pool information */ 3262 thisPool = handle->pool[handle->res[res_id]->resPoolId]; 3263 /* make the call */ 3264 result = _shr_res_alloc_mgrs[thisPool->resManagerType].check_all_tag(thisPool, 3265 tag, 3266 scaled, 3267 elem); 3268 3269 LOG_DEBUG(BSL_LS_SOC_COMMON, 3270 (BSL_META("(%p, %d, %p, %d, %d) return %d (%s)\n"), 3271 (void*)handle, 3272 res_id, 3273 (void*)tag, 3274 count, 3275 elem, 3276 result, 3277 _SHR_ERRMSG(result))); 3278 return result; 3279 } 3280 3281 /* 3282 * Check_all for a bunch of elements/blocks of a resource type 3283 */ 3284 int 3285 shr_mres_check_all_tag_group(shr_mres_handle_t handle, 3286 int res_id, 3287 uint32 grp_flags, 3288 int grp_size, 3289 int *grp_done, 3290 const void **tag, 3291 const int *count, 3292 const int *elem, 3293 int *status) 3294 { 3295 _shr_res_pool_desc_t *thisPool; 3296 _shr_res_type_desc_t *thisRes; 3297 int result = _SHR_E_NONE; 3298 int xresult; 3299 int index; 3300 int scaled; 3301 3302 LOG_DEBUG(BSL_LS_SOC_COMMON, 3303 (BSL_META("(%p, %d, %08X, %d, %p, %p, %p, %p, %p) enter\n"), 3304 (void*)handle, 3305 res_id, 3306 grp_flags, 3307 grp_size, 3308 (void*)grp_done, 3309 (void*)tag, 3310 (void*)count, 3311 (void*)elem, 3312 (void*)status)); 3313 3314 /* a little parameter checking */ 3315 RES_HANDLE_VALID_CHECK(handle); 3316 RES_TYPE_VALID_CHECK(handle, res_id); 3317 RES_TYPE_EXIST_CHECK(handle, res_id); 3318 if (!grp_done) { 3319 LOG_ERROR(BSL_LS_SOC_COMMON, 3320 (BSL_META("obligatory out argument grp_done is NULL\n"))); 3321 return _SHR_E_PARAM; 3322 } 3323 *grp_done = 0; 3324 if (0 > grp_size) { 3325 LOG_ERROR(BSL_LS_SOC_COMMON, 3326 (BSL_META("group member count %d must be >= 0\n"), 3327 grp_size)); 3328 return _SHR_E_PARAM; 3329 } 3330 if ((0 < grp_size) && (!count || !elem || !status)) { 3331 LOG_ERROR(BSL_LS_SOC_COMMON, 3332 (BSL_META("an obligatory array pointer is NULL\n"))); 3333 return _SHR_E_PARAM; 3334 } 3335 if (grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS)) { 3336 LOG_ERROR(BSL_LS_SOC_COMMON, 3337 (BSL_META("invalid group flags %08X\n"), 3338 grp_flags & (~SHR_RES_ALLOC_GROUP_FLAGS))); 3339 return _SHR_E_PARAM; 3340 } 3341 /* get the resource information */ 3342 thisRes = handle->res[res_id]; 3343 /* get the pool information */ 3344 thisPool = handle->pool[thisRes->resPoolId]; 3345 /* try to check the requested blocks */ 3346 for (index = 0; 3347 (_SHR_E_NONE == result) && (index < grp_size); 3348 index++) { 3349 /* adjust element count per scaling factor */ 3350 scaled = count[index] * thisRes->resElemSize; 3351 /* check this element or block */ 3352 xresult = _shr_res_alloc_mgrs[thisPool->resManagerType].check_all_tag(thisPool, 3353 tag[index], 3354 scaled, 3355 elem[index]); 3356 status[index] = xresult; 3357 if ((_SHR_E_NOT_FOUND != xresult) && 3358 (_SHR_E_EXISTS != xresult)) { 3359 LOG_ERROR(BSL_LS_SOC_COMMON, 3360 (BSL_META("unexpected result checking %p resource %d" 3361 " index %d elem %d count %d: %d (%s)\n"), 3362 (void*)handle, 3363 res_id, 3364 index, 3365 elem[index], 3366 count[index], 3367 result, 3368 _SHR_ERRMSG(result))); 3369 if (!(grp_flags & SHR_RES_ALLOC_GROUP_ATOMIC)) { 3370 /* if not atomic mode, abort on first unexpected result */ 3371 result = _SHR_E_FAIL; 3372 break; 3373 } 3374 } /* if (result is neither NOT_FOUND nor EXISTS) */ 3375 } /* for (all elements/blocks as long as no errors) */ 3376 /* update number of frees that succeeded */ 3377 *grp_done = index; 3378 3379 /* return the result */ 3380 LOG_DEBUG(BSL_LS_SOC_COMMON, 3381 (BSL_META("(%p, %d, %08X, %d, &(%d), %p, %p, %p, %p) return %d (%s)\n"), 3382 (void*)handle, 3383 res_id, 3384 grp_flags, 3385 grp_size, 3386 *grp_done, 3387 (void*)tag, 3388 (void*)count, 3389 (void*)elem, 3390 (void*)status, 3391 result, 3392 _SHR_ERRMSG(result))); 3393 for (index = 0; index < grp_size; index++) { 3394 LOG_DEBUG(BSL_LS_SOC_COMMON, 3395 (BSL_META(" block %12d: %p, %d, %d, %d (%s)\n"), 3396 index, 3397 (void*)(tag[index]), 3398 count[index], 3399 elem[index], 3400 status[index], 3401 _SHR_ERRMSG(status[index]))); 3402 } 3403 return result; 3404 } 3405 3406 /* 3407 * Diagnostic dump 3408 */ 3409 int 3410 shr_mres_dump(shr_mres_handle_t handle) 3411 { 3412 _shr_res_pool_desc_t *thisPool; 3413 _shr_res_type_desc_t *thisRes; 3414 int index; 3415 int result = _SHR_E_NONE; 3416 3417 /* a little parameter checking */ 3418 RES_HANDLE_VALID_CHECK(handle); 3419 3420 /* dump information about the handle */ 3421 LOG_CLI((BSL_META("%p resource allocation manager\n"), (void*)handle)); 3422 LOG_CLI((BSL_META(" resource type count = %d\n"), handle->resTypeCount)); 3423 LOG_CLI((BSL_META(" resource pool count = %d\n"), handle->resPoolCount)); 3424 for (index = 0; index < handle->resPoolCount; index++) { 3425 thisPool = handle->pool[index]; 3426 if (thisPool) { 3427 LOG_CLI((BSL_META(" resource pool %d (%s):\n"), 3428 index, 3429 &(thisPool->name[0]))); 3430 LOG_CLI((BSL_META(" method = %d (%s)\n"), 3431 thisPool->resManagerType, 3432 _shr_res_alloc_mgrs[thisPool->resManagerType].name)); 3433 LOG_CLI((BSL_META(" handle = %p\n"), (void*)thisPool->resHandle)); 3434 LOG_CLI((BSL_META(" range = %d..%d\n"), 3435 thisPool->low, 3436 thisPool->low + thisPool->count - 1)); 3437 LOG_CLI((BSL_META(" elems = %d (%d in use)\n"), 3438 thisPool->count, 3439 thisPool->inuse)); 3440 LOG_CLI((BSL_META(" refcnt = %d\n"), thisPool->refCount)); 3441 } else { 3442 LOG_CLI((BSL_META(" resource pool %d is not in use\n"), index)); 3443 } 3444 } 3445 for (index = 0; index < handle->resTypeCount; index++) { 3446 thisRes = handle->res[index]; 3447 if (thisRes) { 3448 thisPool = handle->pool[thisRes->resPoolId]; 3449 LOG_CLI((BSL_META(" resource type %d (%s):\n"), 3450 index, 3451 &(thisRes->name[0]))); 3452 LOG_CLI((BSL_META(" resource pool = %d (%s)\n"), 3453 thisRes->resPoolId, 3454 &(thisPool->name[0]))); 3455 LOG_CLI((BSL_META(" pool elem each = %d\n"), 3456 thisRes->resElemSize)); 3457 LOG_CLI((BSL_META(" active elements = %d\n"), 3458 thisRes->refCount)); 3459 } else { 3460 LOG_CLI((BSL_META(" resource type %d is not in use\n"), index)); 3461 } 3462 } 3463 return result; 3464 } 3465 3466 /*****************************************************************************/ 3467 /* 3468 * Exposed API implementation (unit based, local handle cache) 3469 */ 3470 3471 /* 3472 * Initialise unit 3473 */ 3474 int 3475 shr_res_init(int unit, 3476 int num_res_types, 3477 int num_res_pools) 3478 { 3479 _shr_res_unit_desc_t *tempUnit; 3480 int result = _SHR_E_NONE; 3481 3482 LOG_DEBUG(BSL_LS_SOC_COMMON, 3483 (BSL_META_U(unit, 3484 "(%d, %d, %d) enter\n"), 3485 unit, 3486 num_res_types, 3487 num_res_pools)); 3488 3489 /* a little parameter checking */ 3490 if ((0 > unit) || (BCM_LOCAL_UNITS_MAX <= unit)) { 3491 LOG_ERROR(BSL_LS_SOC_COMMON, 3492 (BSL_META_U(unit, 3493 "invalid unit number %d\n"), 3494 unit)); 3495 return _SHR_E_PARAM; 3496 } 3497 3498 /* get this unit's current information, mark it as destroyed */ 3499 3500 tempUnit = _g_unitResDesc[unit]; 3501 _g_unitResDesc[unit] = NULL; 3502 if (tempUnit) { 3503 /* this unit has already been initialised; tear it down */ 3504 result = _shr_mres_destroy_data(tempUnit); 3505 if (_SHR_E_NONE != result) { 3506 /* something went wrong with the teardown, put what's left back */ 3507 _g_unitResDesc[unit] = tempUnit; 3508 } 3509 tempUnit = NULL; 3510 } 3511 3512 if (_SHR_E_NONE == result) { 3513 result = shr_mres_create(&tempUnit, 3514 num_res_types, 3515 num_res_pools); 3516 if (_SHR_E_NONE == result) { 3517 _g_unitResDesc[unit] = tempUnit; 3518 } 3519 } /* if (_SHR_E_NONE == result) */ 3520 3521 /* return the result */ 3522 LOG_DEBUG(BSL_LS_SOC_COMMON, 3523 (BSL_META_U(unit, 3524 "(%d, %d, %d) return %d (%s)\n"), 3525 unit, 3526 num_res_types, 3527 num_res_pools, 3528 result, 3529 _SHR_ERRMSG(result))); 3530 return result; 3531 } 3532 3533 /* 3534 * Get unit resource information (top level) 3535 */ 3536 int 3537 shr_res_get(int unit, 3538 int *num_res_types, 3539 int *num_res_pools) 3540 { 3541 _shr_res_unit_desc_t *thisUnit; 3542 3543 /* a little parameter checking */ 3544 RES_UNIT_CHECK(unit, thisUnit); 3545 3546 /* perform the fetch */ 3547 return shr_mres_get(thisUnit, num_res_types, num_res_pools); 3548 } 3549 3550 /* 3551 * Deinitialise unit 3552 */ 3553 int 3554 shr_res_detach(int unit) 3555 { 3556 _shr_res_unit_desc_t *tempUnit; 3557 int result = _SHR_E_NONE; 3558 3559 LOG_DEBUG(BSL_LS_SOC_COMMON, 3560 (BSL_META_U(unit, 3561 "(%d) enter\n"), 3562 unit)); 3563 3564 /* get this unit's current information, mark it as destroyed */ 3565 3566 tempUnit = _g_unitResDesc[unit]; 3567 _g_unitResDesc[unit] = NULL; 3568 if (tempUnit) { 3569 /* this unit has already been initialised; tear it down */ 3570 result = _shr_mres_destroy_data(tempUnit); 3571 if (_SHR_E_NONE != result) { 3572 /* something went wrong with the teardown, put what's left back */ 3573 _g_unitResDesc[unit] = tempUnit; 3574 } else { 3575 sal_free(tempUnit); 3576 } 3577 tempUnit = NULL; 3578 } /* if (tempUnit) */ 3579 /* else would be not inited, again, easy to detach in that case - NOP */ 3580 3581 /* return the result */ 3582 LOG_DEBUG(BSL_LS_SOC_COMMON, 3583 (BSL_META_U(unit, 3584 "(%d) return %d (%s)\n"), 3585 unit, 3586 result, 3587 _SHR_ERRMSG(result))); 3588 return result; 3589 } 3590 3591 /* 3592 * Configure a resource pool on a unit 3593 */ 3594 int 3595 shr_res_pool_set(int unit, 3596 int pool_id, 3597 shr_res_allocator_t manager, 3598 int low_id, 3599 int count, 3600 const void *extras, 3601 const char *name) 3602 { 3603 _shr_res_unit_desc_t *thisUnit; 3604 3605 /* a little parameter checking */ 3606 RES_UNIT_CHECK(unit, thisUnit); 3607 3608 /* perform the action */ 3609 return shr_mres_pool_set(thisUnit, 3610 pool_id, 3611 manager, 3612 low_id, 3613 count, 3614 extras, 3615 name); 3616 } 3617 3618 /* 3619 * Destroy a resource pool on a unit 3620 */ 3621 int 3622 shr_res_pool_unset(int unit, 3623 int pool_id) 3624 { 3625 _shr_res_unit_desc_t *thisUnit; 3626 3627 /* a little parameter checking */ 3628 RES_UNIT_CHECK(unit, thisUnit); 3629 3630 /* perform the action */ 3631 return shr_mres_pool_unset(thisUnit, pool_id); 3632 } 3633 3634 /* 3635 * Get information about a resource pool on a unit 3636 */ 3637 int 3638 shr_res_pool_get(int unit, 3639 int pool_id, 3640 shr_res_allocator_t *manager, 3641 int *low_id, 3642 int *count, 3643 const void **extras, 3644 const char **name) 3645 { 3646 _shr_res_unit_desc_t *thisUnit; 3647 3648 /* a little parameter checking */ 3649 RES_UNIT_CHECK(unit, thisUnit); 3650 3651 /* perform the action */ 3652 return shr_mres_pool_get(thisUnit, 3653 pool_id, 3654 manager, 3655 low_id, 3656 count, 3657 extras, 3658 name); 3659 } 3660 3661 /* 3662 * Get information about a resource pool on a unit 3663 */ 3664 int 3665 shr_res_pool_info_get(int unit, 3666 int pool_id, 3667 shr_res_pool_info_t *info) 3668 { 3669 _shr_res_unit_desc_t *thisUnit; 3670 3671 /* a little parameter checking */ 3672 RES_UNIT_CHECK(unit, thisUnit); 3673 3674 /* perform the action */ 3675 return shr_mres_pool_info_get(thisUnit, 3676 pool_id, 3677 info); 3678 } 3679 3680 /* 3681 * Configure a resource type on a unit 3682 */ 3683 int 3684 shr_res_type_set(int unit, 3685 int res_id, 3686 int pool_id, 3687 int elem_size, 3688 const char *name) 3689 { 3690 _shr_res_unit_desc_t *thisUnit; 3691 3692 /* a little parameter checking */ 3693 RES_UNIT_CHECK(unit, thisUnit); 3694 3695 /* perform the action */ 3696 return shr_mres_type_set(thisUnit, res_id, pool_id, elem_size, name); 3697 } 3698 3699 /* 3700 * Destroy a resource type on a unit 3701 */ 3702 int 3703 shr_res_type_unset(int unit, 3704 int res_id) 3705 { 3706 _shr_res_unit_desc_t *thisUnit; 3707 3708 /* a little parameter checking */ 3709 RES_UNIT_CHECK(unit, thisUnit); 3710 3711 /* perform the action */ 3712 return shr_mres_type_unset(thisUnit, res_id); 3713 } 3714 3715 /* 3716 * Get information about a resource type 3717 */ 3718 int 3719 shr_res_type_get(int unit, 3720 int res_id, 3721 int *pool_id, 3722 int *elem_size, 3723 const char **name) 3724 { 3725 _shr_res_unit_desc_t *thisUnit; 3726 3727 /* a little parameter checking */ 3728 RES_UNIT_CHECK(unit, thisUnit); 3729 3730 /* perform the action */ 3731 return shr_mres_type_get(thisUnit, res_id, pool_id, elem_size, name); 3732 } 3733 3734 /* 3735 * Get information about a resource type 3736 */ 3737 int 3738 shr_res_type_info_get(int unit, 3739 int res_id, 3740 shr_res_type_info_t *info) 3741 { 3742 _shr_res_unit_desc_t *thisUnit; 3743 3744 /* a little parameter checking */ 3745 RES_UNIT_CHECK(unit, thisUnit); 3746 3747 /* perform the action */ 3748 return shr_mres_type_info_get(thisUnit, res_id, info); 3749 } 3750 3751 /* 3752 * Allocate elements of a resource type 3753 */ 3754 int 3755 shr_res_alloc(int unit, 3756 int res_id, 3757 uint32 flags, 3758 int count, 3759 int *elem) 3760 { 3761 _shr_res_unit_desc_t *thisUnit; 3762 3763 /* a little parameter checking */ 3764 RES_UNIT_CHECK(unit, thisUnit); 3765 3766 /* perform the action */ 3767 return shr_mres_alloc(thisUnit, res_id, flags, count, elem); 3768 } 3769 3770 /* 3771 * Allocate a bunch of elements or blocks of a resource type 3772 */ 3773 int 3774 shr_res_alloc_group(int unit, 3775 int res_id, 3776 uint32 grp_flags, 3777 int grp_size, 3778 int *grp_done, 3779 const uint32 *flags, 3780 const int *count, 3781 int *elem) 3782 { 3783 _shr_res_unit_desc_t *thisUnit; 3784 3785 /* a little parameter checking */ 3786 RES_UNIT_CHECK(unit, thisUnit); 3787 3788 /* perform the action */ 3789 return shr_mres_alloc_group(thisUnit, 3790 res_id, 3791 grp_flags, 3792 grp_size, 3793 grp_done, 3794 flags, 3795 count, 3796 elem); 3797 } 3798 3799 /* 3800 * Allocate elements of a resource type 3801 */ 3802 int 3803 shr_res_alloc_tag(int unit, 3804 int res_id, 3805 uint32 flags, 3806 const void *tag, 3807 int count, 3808 int *elem) 3809 { 3810 _shr_res_unit_desc_t *thisUnit; 3811 3812 /* a little parameter checking */ 3813 RES_UNIT_CHECK(unit, thisUnit); 3814 3815 /* perform the action */ 3816 return shr_mres_alloc_tag(thisUnit, res_id, flags, tag, count, elem); 3817 } 3818 3819 /* 3820 * Allocate a bunch of elements or blocks of a resource type 3821 */ 3822 int 3823 shr_res_alloc_tag_group(int unit, 3824 int res_id, 3825 uint32 grp_flags, 3826 int grp_size, 3827 int *grp_done, 3828 const uint32 *flags, 3829 const void **tag, 3830 const int *count, 3831 int *elem) 3832 { 3833 _shr_res_unit_desc_t *thisUnit; 3834 3835 /* a little parameter checking */ 3836 RES_UNIT_CHECK(unit, thisUnit); 3837 3838 /* perform the action */ 3839 return shr_mres_alloc_tag_group(thisUnit, 3840 res_id, 3841 grp_flags, 3842 grp_size, 3843 grp_done, 3844 flags, 3845 tag, 3846 count, 3847 elem); 3848 } 3849 3850 /* 3851 * Allocate a block of elements with the requested alignment and offset. 3852 */ 3853 int 3854 shr_res_alloc_align(int unit, 3855 int res_id, 3856 uint32 flags, 3857 int align, 3858 int offset, 3859 int count, 3860 int *elem) 3861 { 3862 _shr_res_unit_desc_t *thisUnit; 3863 3864 /* a little parameter checking */ 3865 RES_UNIT_CHECK(unit, thisUnit); 3866 3867 /* perform the action */ 3868 return shr_mres_alloc_align(thisUnit, 3869 res_id, 3870 flags, 3871 align, 3872 offset, 3873 count, 3874 elem); 3875 } 3876 3877 /* 3878 * Allocate a sparse block of elements with the requested alignment and 3879 * offset. 3880 */ 3881 int 3882 shr_res_alloc_align_sparse(int unit, 3883 int res_id, 3884 uint32 flags, 3885 int align, 3886 int offset, 3887 uint32 pattern, 3888 int length, 3889 int repeats, 3890 int *elem) 3891 { 3892 _shr_res_unit_desc_t *thisUnit; 3893 3894 /* a little parameter checking */ 3895 RES_UNIT_CHECK(unit, thisUnit); 3896 3897 /* perform the action */ 3898 return shr_mres_alloc_align_sparse(thisUnit, 3899 res_id, 3900 flags, 3901 align, 3902 offset, 3903 pattern, 3904 length, 3905 repeats, 3906 elem); 3907 } 3908 3909 /* 3910 * Allocate a bunch of aligned elements or blocks of a resource type 3911 */ 3912 int 3913 shr_res_alloc_align_group(int unit, 3914 int res_id, 3915 uint32 grp_flags, 3916 int grp_size, 3917 int *grp_done, 3918 const uint32 *flags, 3919 const int *align, 3920 const int *offset, 3921 const int *count, 3922 int *elem) 3923 { 3924 _shr_res_unit_desc_t *thisUnit; 3925 3926 /* a little parameter checking */ 3927 RES_UNIT_CHECK(unit, thisUnit); 3928 3929 /* perform the action */ 3930 return shr_mres_alloc_align_group(thisUnit, 3931 res_id, 3932 grp_flags, 3933 grp_size, 3934 grp_done, 3935 flags, 3936 align, 3937 offset, 3938 count, 3939 elem); 3940 } 3941 3942 /* 3943 * Allocate a block of elements with the requested alignment and offset. 3944 */ 3945 int 3946 shr_res_alloc_align_tag(int unit, 3947 int res_id, 3948 uint32 flags, 3949 int align, 3950 int offset, 3951 const void *tag, 3952 int count, 3953 int *elem) 3954 { 3955 _shr_res_unit_desc_t *thisUnit; 3956 3957 /* a little parameter checking */ 3958 RES_UNIT_CHECK(unit, thisUnit); 3959 3960 /* perform the action */ 3961 return shr_mres_alloc_align_tag(thisUnit, 3962 res_id, 3963 flags, 3964 align, 3965 offset, 3966 tag, 3967 count, 3968 elem); 3969 } 3970 3971 /* 3972 * Allocate a bunch of aligned elements or blocks of a resource type 3973 */ 3974 int 3975 shr_res_alloc_align_tag_group(int unit, 3976 int res_id, 3977 uint32 grp_flags, 3978 int grp_size, 3979 int *grp_done, 3980 const uint32 *flags, 3981 const int *align, 3982 const int *offset, 3983 const void **tag, 3984 const int *count, 3985 int *elem) 3986 { 3987 _shr_res_unit_desc_t *thisUnit; 3988 3989 /* a little parameter checking */ 3990 RES_UNIT_CHECK(unit, thisUnit); 3991 3992 /* perform the action */ 3993 return shr_mres_alloc_align_tag_group(thisUnit, 3994 res_id, 3995 grp_flags, 3996 grp_size, 3997 grp_done, 3998 flags, 3999 align, 4000 offset, 4001 tag, 4002 count, 4003 elem); 4004 } 4005 4006 /* 4007 * Free elements of a resource type 4008 */ 4009 int 4010 shr_res_free(int unit, 4011 int res_id, 4012 int count, 4013 int elem) 4014 { 4015 _shr_res_unit_desc_t *thisUnit; 4016 4017 /* a little parameter checking */ 4018 RES_UNIT_CHECK(unit, thisUnit); 4019 4020 /* perform the action */ 4021 return shr_mres_free_and_status(thisUnit, res_id, count, elem, NULL); 4022 } 4023 4024 /* 4025 * Free elements of a resource type, get status flags 4026 */ 4027 int 4028 shr_res_free_and_status(int unit, 4029 int res_id, 4030 int count, 4031 int elem, 4032 uint32 *flags) 4033 { 4034 _shr_res_unit_desc_t *thisUnit; 4035 4036 /* a little parameter checking */ 4037 RES_UNIT_CHECK(unit, thisUnit); 4038 4039 /* perform the action */ 4040 return shr_mres_free_and_status(thisUnit, res_id, count, elem, flags); 4041 } 4042 4043 /* 4044 * Free sparse block of elements of a resource type 4045 */ 4046 int 4047 shr_res_free_sparse(int unit, 4048 int res_id, 4049 uint32 pattern, 4050 int length, 4051 int repeats, 4052 int elem) 4053 { 4054 _shr_res_unit_desc_t *thisUnit; 4055 4056 /* a little parameter checking */ 4057 RES_UNIT_CHECK(unit, thisUnit); 4058 4059 /* perform the action */ 4060 return shr_mres_free_sparse_and_status(thisUnit, 4061 res_id, 4062 pattern, 4063 length, 4064 repeats, 4065 elem, 4066 NULL); 4067 } 4068 4069 /* 4070 * Free sparse block of elements of a resource type, get status flags 4071 */ 4072 int 4073 shr_res_free_sparse_and_status(int unit, 4074 int res_id, 4075 uint32 pattern, 4076 int length, 4077 int repeats, 4078 int elem, 4079 uint32 *flags) 4080 { 4081 _shr_res_unit_desc_t *thisUnit; 4082 4083 /* a little parameter checking */ 4084 RES_UNIT_CHECK(unit, thisUnit); 4085 4086 /* perform the action */ 4087 return shr_mres_free_sparse_and_status(thisUnit, 4088 res_id, 4089 pattern, 4090 length, 4091 repeats, 4092 elem, 4093 flags); 4094 } 4095 4096 /* 4097 * Free a bunch of elements/blocks of a resource type 4098 */ 4099 int 4100 shr_res_free_group(int unit, 4101 int res_id, 4102 uint32 grp_flags, 4103 int grp_size, 4104 int *grp_done, 4105 const int *count, 4106 const int *elem) 4107 { 4108 _shr_res_unit_desc_t *thisUnit; 4109 4110 /* a little parameter checking */ 4111 RES_UNIT_CHECK(unit, thisUnit); 4112 4113 /* perform the action */ 4114 return shr_mres_free_group_and_status(thisUnit, 4115 res_id, 4116 grp_flags, 4117 grp_size, 4118 grp_done, 4119 count, 4120 elem, 4121 NULL); 4122 } 4123 4124 4125 /* 4126 * Free a bunch of elements/blocks of a resource type, get status flags 4127 */ 4128 int 4129 shr_res_free_group_and_status(int unit, 4130 int res_id, 4131 uint32 grp_flags, 4132 int grp_size, 4133 int *grp_done, 4134 const int *count, 4135 const int *elem, 4136 uint32 *status) 4137 { 4138 _shr_res_unit_desc_t *thisUnit; 4139 4140 /* a little parameter checking */ 4141 RES_UNIT_CHECK(unit, thisUnit); 4142 4143 /* perform the action */ 4144 return shr_mres_free_group_and_status(thisUnit, 4145 res_id, 4146 grp_flags, 4147 grp_size, 4148 grp_done, 4149 count, 4150 elem, 4151 status); 4152 } 4153 4154 /* 4155 * Check whether elements are free or not 4156 */ 4157 int 4158 shr_res_check(int unit, 4159 int res_id, 4160 int count, 4161 int elem) 4162 { 4163 _shr_res_unit_desc_t *thisUnit; 4164 4165 /* a little parameter checking */ 4166 RES_UNIT_CHECK(unit, thisUnit); 4167 4168 /* perform the action */ 4169 return shr_mres_check(thisUnit, res_id, count, elem); 4170 } 4171 4172 /* 4173 * Check a bunch of elements/blocks of a resource type 4174 */ 4175 int 4176 shr_res_check_group(int unit, 4177 int res_id, 4178 uint32 grp_flags, 4179 int grp_size, 4180 int *grp_done, 4181 const int *count, 4182 const int *elem, 4183 int *status) 4184 { 4185 _shr_res_unit_desc_t *thisUnit; 4186 4187 /* a little parameter checking */ 4188 RES_UNIT_CHECK(unit, thisUnit); 4189 4190 /* perform the action */ 4191 return shr_mres_check_group(thisUnit, 4192 res_id, 4193 grp_flags, 4194 grp_size, 4195 grp_done, 4196 count, 4197 elem, 4198 status); 4199 } 4200 4201 /* 4202 * Check whether elements are free or not 4203 */ 4204 int 4205 shr_res_check_all(int unit, 4206 int res_id, 4207 int count, 4208 int elem) 4209 { 4210 _shr_res_unit_desc_t *thisUnit; 4211 4212 /* a little parameter checking */ 4213 RES_UNIT_CHECK(unit, thisUnit); 4214 4215 /* perform the action */ 4216 return shr_mres_check_all(thisUnit, res_id, count, elem); 4217 } 4218 4219 /* 4220 * Check whether elements in a sparse block are free or not 4221 */ 4222 int 4223 shr_res_check_all_sparse(int unit, 4224 int res_id, 4225 uint32 pattern, 4226 int length, 4227 int repeats, 4228 int elem) 4229 { 4230 _shr_res_unit_desc_t *thisUnit; 4231 4232 /* a little parameter checking */ 4233 RES_UNIT_CHECK(unit, thisUnit); 4234 4235 /* perform the action */ 4236 return shr_mres_check_all_sparse(thisUnit, 4237 res_id, 4238 pattern, 4239 length, 4240 repeats, 4241 elem); 4242 } 4243 4244 /* 4245 * Check a bunch of elements/blocks of a resource type 4246 */ 4247 int 4248 shr_res_check_all_group(int unit, 4249 int res_id, 4250 uint32 grp_flags, 4251 int grp_size, 4252 int *grp_done, 4253 const int *count, 4254 const int *elem, 4255 int *status) 4256 { 4257 _shr_res_unit_desc_t *thisUnit; 4258 4259 /* a little parameter checking */ 4260 RES_UNIT_CHECK(unit, thisUnit); 4261 4262 /* perform the action */ 4263 return shr_mres_check_all_group(thisUnit, 4264 res_id, 4265 grp_flags, 4266 grp_size, 4267 grp_done, 4268 count, 4269 elem, 4270 status); 4271 } 4272 4273 /* 4274 * Check whether elements are free or not 4275 */ 4276 int 4277 shr_res_check_all_tag(int unit, 4278 int res_id, 4279 const void *tag, 4280 int count, 4281 int elem) 4282 { 4283 _shr_res_unit_desc_t *thisUnit; 4284 4285 /* a little parameter checking */ 4286 RES_UNIT_CHECK(unit, thisUnit); 4287 4288 /* perform the action */ 4289 return shr_mres_check_all_tag(thisUnit, res_id, tag, count, elem); 4290 } 4291 4292 /* 4293 * Check a bunch of elements/blocks of a resource type 4294 */ 4295 int 4296 shr_res_check_all_tag_group(int unit, 4297 int res_id, 4298 uint32 grp_flags, 4299 int grp_size, 4300 int *grp_done, 4301 const void **tag, 4302 const int *count, 4303 const int *elem, 4304 int *status) 4305 { 4306 _shr_res_unit_desc_t *thisUnit; 4307 4308 /* a little parameter checking */ 4309 RES_UNIT_CHECK(unit, thisUnit); 4310 4311 /* perform the action */ 4312 return shr_mres_check_all_tag_group(thisUnit, 4313 res_id, 4314 grp_flags, 4315 grp_size, 4316 grp_done, 4317 tag, 4318 count, 4319 elem, 4320 status); 4321 } 4322 4323 /* 4324 * Diagnostic dump 4325 */ 4326 int 4327 shr_res_dump(int unit) 4328 { 4329 _shr_res_unit_desc_t *thisUnit; 4330 4331 /* a little parameter checking */ 4332 RES_UNIT_CHECK(unit, thisUnit); 4333 4334 /* perform the action */ 4335 return shr_mres_dump(thisUnit); 4336 } 4337 4338 /*****************************************************************************/ 4339 /* 4340 * Interface to shr_res_bitmap (external implementation) 4341 */ 4342 4343 /* 4344 * shr_res_bitmap is a fairly simple bitmap allocator that supports a number 4345 * of features, but isn't terribly optimised. It allows alignment and offset, 4346 * blocks of multiple elements (arbitrary size). It has a few other minor 4347 * upgrades versus simple bitmap, including keeping track of the next place 4348 * where it wants to search for free elements and the last place where it 4349 * freed elements, to improve performance under simple conditions, and which 4350 * are designed to not have significant negative impact even when they fail to 4351 * provide improvements to performance. 4352 */ 4353 static int 4354 _shr_res_bitmap_create(_shr_res_pool_desc_t **desc, 4355 int low_id, 4356 int count, 4357 const void* extras, 4358 const char* name) 4359 { 4360 shr_res_bitmap_handle_t handle; 4361 int result; 4362 int len_name = sal_strlen(name); 4363 4364 /* need the base descriptor */ 4365 *desc = sal_alloc(sizeof(_shr_res_pool_desc_t) + len_name, 4366 "bitmap resource descriptor"); 4367 if (!(*desc)) { 4368 /* alloc failed */ 4369 LOG_ERROR(BSL_LS_SOC_COMMON, 4370 (BSL_META("unable to allocate %u bytes for descriptor\n"), 4371 (unsigned int)(sizeof(_shr_res_pool_desc_t) + 4372 sal_strlen(name)))); 4373 return _SHR_E_MEMORY; 4374 } 4375 sal_memset(*desc, 0x00, sizeof(_shr_res_pool_desc_t) + sal_strlen(name)); 4376 (*desc)->count = count; 4377 (*desc)->low = low_id; 4378 (*desc)->extras = NULL; /* don't need this here */ 4379 sal_strncpy(&((*desc)->name[0]), name, len_name); 4380 if (len_name) 4381 *((char*)&((*desc)->name[0])+len_name) = '\0'; 4382 4383 /* create the bitmap allocator */ 4384 result = shr_res_bitmap_create(&handle, low_id, count); 4385 if (_SHR_E_NONE == result) { 4386 (*desc)->resHandle = handle; 4387 } else { 4388 LOG_ERROR(BSL_LS_SOC_COMMON, 4389 (BSL_META("unable to create bitmap allocator, low_id = %d," 4390 " count = %d\n"), 4391 low_id, 4392 count)); 4393 sal_free(*desc); 4394 *desc = NULL; 4395 } 4396 return result; 4397 } 4398 4399 static int 4400 _shr_res_bitmap_destroy(_shr_res_pool_desc_t *desc) 4401 { 4402 shr_res_bitmap_handle_t handle = desc->resHandle; 4403 int result; 4404 4405 /* destroy the list */ 4406 result = shr_res_bitmap_destroy(handle); 4407 if(desc->extras) { 4408 sal_free(desc->extras); 4409 } 4410 if (_SHR_E_NONE == result) { 4411 /* free the descriptor */ 4412 sal_free(desc); 4413 /* that usually crashes if something is wrong */ 4414 } 4415 return result; 4416 } 4417 4418 static int 4419 _shr_res_bitmap_alloc(_shr_res_pool_desc_t *desc, 4420 uint32 flags, 4421 int count, 4422 int *elem) 4423 { 4424 shr_res_bitmap_handle_t handle = desc->resHandle; 4425 uint32 iflags = 0; 4426 4427 if (flags & SHR_RES_ALLOC_WITH_ID) { 4428 iflags |= SHR_RES_BITMAP_ALLOC_WITH_ID; 4429 } 4430 if (flags & SHR_RES_ALLOC_REPLACE) { 4431 iflags |= SHR_RES_BITMAP_ALLOC_REPLACE; 4432 } 4433 return shr_res_bitmap_alloc(handle, iflags, count, elem); 4434 } 4435 4436 static int 4437 _shr_res_bitmap_alloc_align(_shr_res_pool_desc_t *desc, 4438 uint32 flags, 4439 int align, 4440 int offs, 4441 int count, 4442 int *elem) 4443 { 4444 shr_res_bitmap_handle_t handle = desc->resHandle; 4445 uint32 iflags = 0; 4446 4447 if (flags & SHR_RES_ALLOC_WITH_ID) { 4448 iflags |= SHR_RES_BITMAP_ALLOC_WITH_ID; 4449 } 4450 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 4451 iflags |= SHR_RES_BITMAP_ALLOC_ALIGN_ZERO; 4452 } 4453 if (flags & SHR_RES_ALLOC_REPLACE) { 4454 iflags |= SHR_RES_BITMAP_ALLOC_REPLACE; 4455 } 4456 return shr_res_bitmap_alloc_align(handle, 4457 iflags, 4458 align, 4459 offs, 4460 count, 4461 elem); 4462 } 4463 4464 static int 4465 _shr_res_bitmap_alloc_align_sparse(_shr_res_pool_desc_t *desc, 4466 uint32 flags, 4467 int align, 4468 int offs, 4469 uint32 pattern, 4470 int length, 4471 int repeats, 4472 int *elem) 4473 { 4474 shr_res_bitmap_handle_t handle = desc->resHandle; 4475 uint32 iflags = 0; 4476 4477 if (flags & SHR_RES_ALLOC_WITH_ID) { 4478 iflags |= SHR_RES_BITMAP_ALLOC_WITH_ID; 4479 } 4480 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 4481 iflags |= SHR_RES_BITMAP_ALLOC_ALIGN_ZERO; 4482 } 4483 if (flags & SHR_RES_ALLOC_REPLACE) { 4484 iflags |= SHR_RES_BITMAP_ALLOC_REPLACE; 4485 } 4486 return shr_res_bitmap_alloc_align_sparse(handle, 4487 flags, 4488 align, 4489 offs, 4490 pattern, 4491 length, 4492 repeats, 4493 elem); 4494 } 4495 4496 static int 4497 _shr_res_bitmap_free(_shr_res_pool_desc_t *desc, 4498 int count, 4499 int elem) 4500 { 4501 shr_res_bitmap_handle_t handle = desc->resHandle; 4502 4503 return shr_res_bitmap_free(handle, count, elem); 4504 } 4505 4506 static int 4507 _shr_res_bitmap_free_sparse(_shr_res_pool_desc_t *desc, 4508 uint32 pattern, 4509 int length, 4510 int repeats, 4511 int elem) 4512 { 4513 shr_res_bitmap_handle_t handle = desc->resHandle; 4514 4515 return shr_res_bitmap_free_sparse(handle, pattern, length, repeats, elem); 4516 } 4517 4518 static int 4519 _shr_res_bitmap_check(_shr_res_pool_desc_t *desc, 4520 int count, 4521 int elem) 4522 { 4523 shr_res_bitmap_handle_t handle = desc->resHandle; 4524 4525 return shr_res_bitmap_check(handle, count, elem); 4526 } 4527 4528 static int 4529 _shr_res_bitmap_check_all_desc(_shr_res_pool_desc_t *desc, 4530 int count, 4531 int elem) 4532 { 4533 shr_res_bitmap_handle_t handle = desc->resHandle; 4534 4535 return shr_res_bitmap_check_all(handle, count, elem); 4536 } 4537 4538 static int 4539 _shr_res_bitmap_check_all_sparse(_shr_res_pool_desc_t *desc, 4540 uint32 pattern, 4541 int length, 4542 int repeats, 4543 int elem) 4544 { 4545 shr_res_bitmap_handle_t handle = desc->resHandle; 4546 4547 return shr_res_bitmap_check_all_sparse(handle, 4548 pattern, 4549 length, 4550 repeats, 4551 elem); 4552 } 4553 4554 /*****************************************************************************/ 4555 /* 4556 * Interface to shr_res_tag_bitmap (external implementation) 4557 */ 4558 4559 /* 4560 * shr_res_tag_bitmap is a fairly simple bitmap allocator that supports a 4561 * number of features, but isn't terribly optimised. It allows alignment and 4562 * offset, blocks of multiple elements (arbitrary size). It also optionally 4563 * tracks tags (an arbitrary number of bytes assigned to each grain, where a 4564 * grain is one or more elements -- a grain can only be shared between blocks 4565 * if the blocks have same tag). Disabling tagging renders it roughly 4566 * equivalent to the shr_res_bitmap implementation, but perhaps a little bit 4567 * less optimal. 4568 */ 4569 static int 4570 _shr_res_tag_bitmap_create(_shr_res_pool_desc_t **desc, 4571 int low_id, 4572 int count, 4573 const void* extras, 4574 const char* name) 4575 { 4576 shr_res_tag_bitmap_handle_t handle; 4577 shr_res_tagged_bitmap_extras_t *extra; 4578 int result; 4579 int len_name = sal_strlen(name); 4580 4581 /* need the base descriptor */ 4582 *desc = sal_alloc(sizeof(_shr_res_pool_desc_t) + 4583 sizeof(shr_res_tagged_bitmap_extras_t) + 4584 len_name, 4585 "tagged bitmap resource descriptor"); 4586 if (!(*desc)) { 4587 /* alloc failed */ 4588 LOG_ERROR(BSL_LS_SOC_COMMON, 4589 (BSL_META("unable to allocate %u bytes for descriptor\n"), 4590 (unsigned int)(sizeof(_shr_res_pool_desc_t) + 4591 sal_strlen(name)))); 4592 return _SHR_E_MEMORY; 4593 } 4594 sal_memset(*desc, 0x00, sizeof(_shr_res_pool_desc_t) + sal_strlen(name)); 4595 (*desc)->count = count; 4596 (*desc)->low = low_id; 4597 (*desc)->extras = sal_alloc(sizeof(*extra), "tagged bitmap extras"); 4598 if (!((*desc)->extras)) { 4599 LOG_ERROR(BSL_LS_SOC_COMMON, 4600 (BSL_META("unable to allocate %u bytes for extras\n"), 4601 (unsigned int)(sizeof(*extra)))); 4602 result = _SHR_E_MEMORY; 4603 } else { 4604 sal_strncpy(&((*desc)->name[0]), name, len_name); 4605 if (len_name) 4606 *((char*)&((*desc)->name[0])+len_name) = '\0'; 4607 4608 extra = (*desc)->extras; 4609 if (extras) { 4610 sal_memcpy((*desc)->extras, extras, sizeof(*extra)); 4611 } else { 4612 LOG_WARN(BSL_LS_SOC_COMMON, 4613 (BSL_META("assuming zero tag length and one element" 4614 " per grain, since no extras provided\n"))); 4615 extra->grain_size = 1; 4616 extra->tag_length = 0; 4617 } 4618 /* create the bitmap allocator */ 4619 result = shr_res_tag_bitmap_create(&handle, 4620 low_id, 4621 count, 4622 extra->grain_size, 4623 extra->tag_length); 4624 if (_SHR_E_NONE != result) { 4625 LOG_ERROR(BSL_LS_SOC_COMMON, 4626 (BSL_META("unable to create tagged bitmap allocator:" 4627 " %d (%s)\n"), 4628 result, 4629 _SHR_ERRMSG(result))); 4630 } 4631 } 4632 if (_SHR_E_NONE == result) { 4633 (*desc)->resHandle = handle; 4634 } else { 4635 if ((*desc)->extras) { 4636 sal_free((*desc)->extras); 4637 } 4638 sal_free(*desc); 4639 *desc = NULL; 4640 } 4641 return result; 4642 } 4643 4644 static int 4645 _shr_res_tag_bitmap_destroy(_shr_res_pool_desc_t *desc) 4646 { 4647 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4648 int result; 4649 4650 /* destroy the list */ 4651 result = shr_res_tag_bitmap_destroy(handle); 4652 if (_SHR_E_NONE == result) { 4653 sal_free(desc->extras); 4654 /* free the descriptor */ 4655 sal_free(desc); 4656 /* that usually crashes if something is wrong */ 4657 } 4658 return result; 4659 } 4660 4661 static int 4662 _shr_res_tag_bitmap_alloc(_shr_res_pool_desc_t *desc, 4663 uint32 flags, 4664 int count, 4665 int *elem) 4666 { 4667 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4668 uint32 iflags = 0; 4669 4670 if (flags & SHR_RES_ALLOC_WITH_ID) { 4671 iflags |= SHR_RES_TAG_BITMAP_ALLOC_WITH_ID; 4672 } 4673 if (flags & SHR_RES_ALLOC_REPLACE) { 4674 iflags |= SHR_RES_TAG_BITMAP_ALLOC_REPLACE; 4675 } 4676 return shr_res_tag_bitmap_alloc(handle, iflags, count, elem); 4677 } 4678 4679 static int 4680 _shr_res_tag_bitmap_alloc_tag(_shr_res_pool_desc_t *desc, 4681 uint32 flags, 4682 const void* tag, 4683 int count, 4684 int *elem) 4685 { 4686 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4687 uint32 iflags = 0; 4688 4689 if (flags & SHR_RES_ALLOC_WITH_ID) { 4690 iflags |= SHR_RES_TAG_BITMAP_ALLOC_WITH_ID; 4691 } 4692 if (flags & SHR_RES_ALLOC_REPLACE) { 4693 iflags |= SHR_RES_TAG_BITMAP_ALLOC_REPLACE; 4694 } 4695 return shr_res_tag_bitmap_alloc_tag(handle, iflags, tag, count, elem); 4696 } 4697 4698 static int 4699 _shr_res_tag_bitmap_alloc_align(_shr_res_pool_desc_t *desc, 4700 uint32 flags, 4701 int align, 4702 int offs, 4703 int count, 4704 int *elem) 4705 { 4706 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4707 uint32 iflags = 0; 4708 4709 if (flags & SHR_RES_ALLOC_WITH_ID) { 4710 iflags |= SHR_RES_TAG_BITMAP_ALLOC_WITH_ID; 4711 } 4712 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 4713 iflags |= SHR_RES_TAG_BITMAP_ALLOC_ALIGN_ZERO; 4714 } 4715 if (flags & SHR_RES_ALLOC_REPLACE) { 4716 iflags |= SHR_RES_TAG_BITMAP_ALLOC_REPLACE; 4717 } 4718 return shr_res_tag_bitmap_alloc_align(handle, 4719 iflags, 4720 align, 4721 offs, 4722 count, 4723 elem); 4724 } 4725 4726 static int 4727 _shr_res_tag_bitmap_alloc_align_tag(_shr_res_pool_desc_t *desc, 4728 uint32 flags, 4729 int align, 4730 int offs, 4731 const void *tag, 4732 int count, 4733 int *elem) 4734 { 4735 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4736 uint32 iflags = 0; 4737 4738 if (flags & SHR_RES_ALLOC_WITH_ID) { 4739 iflags |= SHR_RES_TAG_BITMAP_ALLOC_WITH_ID; 4740 } 4741 if (flags & SHR_RES_ALLOC_ALIGN_ZERO) { 4742 iflags |= SHR_RES_TAG_BITMAP_ALLOC_ALIGN_ZERO; 4743 } 4744 if (flags & SHR_RES_ALLOC_REPLACE) { 4745 iflags |= SHR_RES_TAG_BITMAP_ALLOC_REPLACE; 4746 } 4747 return shr_res_tag_bitmap_alloc_align_tag(handle, 4748 iflags, 4749 align, 4750 offs, 4751 tag, 4752 count, 4753 elem); 4754 } 4755 4756 static int 4757 _shr_res_tag_bitmap_free(_shr_res_pool_desc_t *desc, 4758 int count, 4759 int elem) 4760 { 4761 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4762 4763 return shr_res_tag_bitmap_free(handle, count, elem); 4764 } 4765 4766 static int 4767 _shr_res_tag_bitmap_check(_shr_res_pool_desc_t *desc, 4768 int count, 4769 int elem) 4770 { 4771 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4772 4773 return shr_res_tag_bitmap_check(handle, count, elem); 4774 } 4775 4776 static int 4777 _shr_res_tag_bitmap_check_all(_shr_res_pool_desc_t *desc, 4778 int count, 4779 int elem) 4780 { 4781 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4782 4783 return shr_res_tag_bitmap_check_all(handle, count, elem); 4784 } 4785 4786 static int 4787 _shr_res_tag_bitmap_check_all_tag(_shr_res_pool_desc_t *desc, 4788 const void *tag, 4789 int count, 4790 int elem) 4791 { 4792 shr_res_tag_bitmap_handle_t handle = desc->resHandle; 4793 4794 return shr_res_tag_bitmap_check_all_tag(handle, tag, count, elem); 4795 } 4796 4797 /*****************************************************************************/ 4798 /* 4799 * Interface to idxres (external implementation) 4800 */ 4801 4802 /* 4803 * idxres_fl is a folded freelist implementation that has roughly O(1) alloc, 4804 * free, and check times, at the cost of about 8.1 bits per element. It does 4805 * not deal well with blocks of elements (unless everything works by a 4806 * specific number of elements, and so can scale the list), though, and should 4807 * not be asked to allocate blocks except WITH_ID, which unhappily has more 4808 * like O(log128(n)) operation time where n is elements in the list. 4809 * 4810 * When WITH_ID is provided, we can use the reserve function to specify the 4811 * block requested, but in other cases, count must equal the scale else we 4812 * will return _SHR_E_PARAM. 4813 * 4814 * Since idxres checks arguments, fewer explicit argument checks are performed 4815 * by these function than, for example, by the bitmap implementation above. 4816 */ 4817 4818 static int 4819 _shr_res_idxres_create(_shr_res_pool_desc_t **desc, 4820 int low_id, 4821 int count, 4822 const void* extras, 4823 const char* name) 4824 { 4825 int result; 4826 int len_name = (sal_strlen(name)); 4827 const shr_res_idxres_extras_t *info = extras; 4828 int namesize = ((len_name + 3) & (~3)); /* align to quadbyte */ 4829 int nodesize = namesize + sizeof(**desc) + sizeof(*info); 4830 4831 /* need the base descriptor */ 4832 *desc = sal_alloc(nodesize, "idxres resource descriptor"); 4833 if (!(*desc)) { 4834 /* alloc failed */ 4835 LOG_ERROR(BSL_LS_SOC_COMMON, 4836 (BSL_META("unable to allocate %d bytes for descriptor\n"), 4837 nodesize)); 4838 return _SHR_E_MEMORY; 4839 } 4840 sal_memset(*desc, 0x00, nodesize); 4841 (*desc)->count = count; 4842 (*desc)->low = low_id; 4843 (*desc)->extras = &((*desc)->name[namesize]); 4844 sal_strncpy(&((*desc)->name[0]), name, len_name); 4845 if (len_name) 4846 *((char*)&((*desc)->name[0])+len_name) = '\0'; 4847 4848 if (info) { 4849 if ((1 > info->scaling_factor)) { 4850 /* negative or zero scaling factors are ignored */ 4851 LOG_WARN(BSL_LS_SOC_COMMON, 4852 (BSL_META("invalid scaling factor %d; using 1 instead\n"), 4853 info->scaling_factor)); 4854 ((shr_res_idxres_extras_t*)((*desc)->extras))->scaling_factor = 1; 4855 } else { 4856 ((shr_res_idxres_extras_t*)((*desc)->extras))->scaling_factor = info->scaling_factor; 4857 } 4858 } else { 4859 /* no scaling factor provided */ 4860 LOG_WARN(BSL_LS_SOC_COMMON, 4861 (BSL_META("missing scaling factor; using 1\n"))); 4862 ((shr_res_idxres_extras_t*)((*desc)->extras))->scaling_factor = 1; 4863 } 4864 if (1 == ((shr_res_idxres_extras_t*)((*desc)->extras))->scaling_factor) { 4865 result = shr_idxres_list_create((shr_idxres_list_handle_t*)&((*desc)->resHandle), 4866 low_id, 4867 low_id + count - 1, 4868 low_id, 4869 low_id + count - 1, 4870 "managed idxres"); 4871 } else { 4872 result = shr_idxres_list_create_scaled((shr_idxres_list_handle_t*)&((*desc)->resHandle), 4873 low_id, 4874 low_id + count - 1, 4875 low_id, 4876 low_id + count - 1, 4877 ((shr_res_idxres_extras_t*)((*desc)->extras))->scaling_factor, 4878 "managed idxres (scaled)"); 4879 } 4880 if (_SHR_E_NONE != result) { 4881 /* creation failed */ 4882 LOG_ERROR(BSL_LS_SOC_COMMON, 4883 (BSL_META("unable to create idxres(%d,%d,%d,%d,%d): %d (%s)\n"), 4884 low_id, 4885 low_id + count - 1, 4886 low_id, 4887 low_id + count - 1, 4888 ((shr_res_idxres_extras_t*)((*desc)->extras))->scaling_factor, 4889 result, 4890 _SHR_ERRMSG(result))); 4891 sal_free(*desc); 4892 *desc = NULL; 4893 } 4894 /* return the result */ 4895 return result; 4896 } 4897 4898 static int 4899 _shr_res_idxres_destroy(_shr_res_pool_desc_t *desc) 4900 { 4901 int result; 4902 4903 result = shr_idxres_list_destroy((shr_idxres_list_handle_t)(desc->resHandle)); 4904 if (_SHR_E_NONE == result) { 4905 sal_free(desc); 4906 } 4907 return result; 4908 } 4909 4910 static int 4911 _shr_res_idxres_alloc(_shr_res_pool_desc_t *desc, 4912 uint32 flags, 4913 int count, 4914 int *elem) 4915 { 4916 int result; 4917 const shr_res_idxres_extras_t *info = desc->extras; 4918 shr_idxres_list_handle_t handle = desc->resHandle; 4919 shr_idxres_element_t item; 4920 4921 if (SHR_RES_ALLOC_REPLACE & flags) { 4922 LOG_ERROR(BSL_LS_SOC_COMMON, 4923 (BSL_META("REPLACE not yet supported on idxres\n"))); 4924 } 4925 4926 if (SHR_RES_ALLOC_WITH_ID & flags) { 4927 /* allocate WITH_ID */ 4928 result = shr_idxres_list_reserve(handle, 4929 *elem, 4930 (*elem) + count - 1); 4931 } else { 4932 /* allocate next available */ 4933 if (count > info->scaling_factor) { 4934 LOG_ERROR(BSL_LS_SOC_COMMON, 4935 (BSL_META("tried to allocate %d elements from idxres list" 4936 " of scaling_factor %d\n"), 4937 count, 4938 info->scaling_factor)); 4939 return _SHR_E_PARAM; 4940 } 4941 result = shr_idxres_list_alloc(handle, &item); 4942 if (_SHR_E_NONE == result) { 4943 *elem = item; 4944 } 4945 } 4946 return result; 4947 } 4948 4949 static int 4950 _shr_res_idxres_free(_shr_res_pool_desc_t *desc, 4951 int count, 4952 int elem) 4953 { 4954 int result = _SHR_E_NONE; 4955 const shr_res_idxres_extras_t *info = desc->extras; 4956 shr_idxres_list_handle_t handle = desc->resHandle; 4957 4958 while ((_SHR_E_NONE == result) && (count > 0)) { 4959 result = shr_idxres_list_free(handle, elem); 4960 elem += info->scaling_factor; 4961 count -= info->scaling_factor; 4962 } 4963 if (_SHR_E_RESOURCE == result) { 4964 /* return NOT_FOUND instead */ 4965 result = _SHR_E_NOT_FOUND; 4966 } 4967 return result; 4968 } 4969 4970 static int 4971 _shr_res_idxres_check(_shr_res_pool_desc_t *desc, 4972 int count, 4973 int elem) 4974 { 4975 int result = _SHR_E_NOT_FOUND; 4976 shr_idxres_list_handle_t handle = desc->resHandle; 4977 4978 while ((_SHR_E_NOT_FOUND == result) && (0 < count)) { 4979 result = shr_idxres_list_elem_state(handle, elem); 4980 elem++; 4981 count--; 4982 } 4983 return result; 4984 } 4985 4986 static int 4987 _shr_res_idxres_check_all(_shr_res_pool_desc_t *desc, 4988 int count, 4989 int elem) 4990 { 4991 int freed = 0; 4992 int inuse = 0; 4993 int index; 4994 int result; 4995 shr_idxres_list_handle_t handle = desc->resHandle; 4996 4997 for (index = 0; index < count; index++) { 4998 result = shr_idxres_list_elem_state(handle, elem + index); 4999 if (_SHR_E_NOT_FOUND == result) { 5000 freed++; 5001 } else if (_SHR_E_EXISTS == result) { 5002 inuse++; 5003 } else { 5004 /* unexpected result */ 5005 return result; 5006 } 5007 } 5008 if (freed == count) { 5009 return _SHR_E_EMPTY; 5010 } else if (inuse == count) { 5011 return _SHR_E_FULL; 5012 } else { 5013 return _SHR_E_EXISTS; 5014 } 5015 } 5016 5017 /*****************************************************************************/ 5018 /* 5019 * Interface to aidxres (external implementation) 5020 */ 5021 5022 /* 5023 * aidxres_fl is a folded freelist implementation that has roughly O(1) alloc, 5024 * free, and check times, at the cost of about 16.2 bits per element. It 5025 * deals reasonably well with blocks of elements but ends up aligning them to 5026 * the next higher power of two (unless they are exactly a power of two 5027 * already, then that size is also the alignment). It suffers similar issues 5028 * to idxres when used WITH_ID, but not quite at such a performance loss. 5029 * Blocks will be aligned unless they are allocated WITH_ID, then it places 5030 * the block as requested. 5031 * 5032 * Note that the blocking factor has some effect on the performance; larger 5033 * blocking factor means also larger memory footprint (more sublists). 5034 * Despite these limitations, the default blocking factor is 7 if it is not 5035 * provided by the caller, as this is the largest value supported in all of 5036 * the normal operation modes (4b is *not* normal operation), and provides the 5037 * ability to manage blocks up to 128 elements in size. 5038 * 5039 * Since aidxres checks arguments, fewer argument checks are performed by 5040 * these function than, for example, by the bitmap implementation above. 5041 */ 5042 5043 static int 5044 _shr_res_aidxres_create(_shr_res_pool_desc_t **desc, 5045 int low_id, 5046 int count, 5047 const void* extras, 5048 const char* name) 5049 { 5050 int result; 5051 int len_name = sal_strlen(name); 5052 const shr_res_aidxres_extras_t *info = extras; 5053 int namesize = ((len_name + 3) & (~3)); /* align to quadbyte */ 5054 int nodesize = namesize + sizeof(**desc) + sizeof(*info); 5055 5056 /* need the base descriptor */ 5057 *desc = sal_alloc(nodesize, "aidxres resource descriptor"); 5058 if (!(*desc)) { 5059 /* alloc failed */ 5060 LOG_ERROR(BSL_LS_SOC_COMMON, 5061 (BSL_META("unable to allocate %d bytes for descriptor\n"), 5062 nodesize)); 5063 return _SHR_E_MEMORY; 5064 } 5065 sal_memset(*desc, 0x00, nodesize); 5066 (*desc)->count = count; 5067 (*desc)->low = low_id; 5068 (*desc)->extras = &((*desc)->name[namesize]); 5069 sal_strncpy(&((*desc)->name[0]), name, len_name); 5070 if (len_name) 5071 *((char*)&((*desc)->name[0])+len_name) = '\0'; 5072 5073 if (info) { 5074 if ((1 >= info->blocking_factor)) { 5075 /* negative or zero scaling factors are ignored */ 5076 LOG_WARN(BSL_LS_SOC_COMMON, 5077 (BSL_META("invalid blocking factor %d; using 7 instead\n"), 5078 info->blocking_factor)); 5079 ((shr_res_aidxres_extras_t*)((*desc)->extras))->blocking_factor = 7; 5080 } else { 5081 ((shr_res_aidxres_extras_t*)((*desc)->extras))->blocking_factor = info->blocking_factor; 5082 } 5083 } else { 5084 /* no scaling factor provided */ 5085 LOG_WARN(BSL_LS_SOC_COMMON, 5086 (BSL_META("missing blocking factor; using 7\n"))); 5087 ((shr_res_aidxres_extras_t*)((*desc)->extras))->blocking_factor = 7; 5088 } 5089 result = shr_aidxres_list_create((shr_aidxres_list_handle_t*)&((*desc)->resHandle), 5090 low_id, 5091 low_id + count - 1, 5092 low_id, 5093 low_id + count - 1, 5094 ((shr_res_aidxres_extras_t*)((*desc)->extras))->blocking_factor, 5095 "managed aidxres"); 5096 if (_SHR_E_NONE != result) { 5097 /* creation failed */ 5098 LOG_ERROR(BSL_LS_SOC_COMMON, 5099 (BSL_META("unable to create aidxres(%d,%d,%d,%d,%d): %d (%s)\n"), 5100 low_id, 5101 low_id + count - 1, 5102 low_id, 5103 low_id + count - 1, 5104 ((shr_res_aidxres_extras_t*)((*desc)->extras))->blocking_factor, 5105 result, 5106 _SHR_ERRMSG(result))); 5107 sal_free(*desc); 5108 *desc = NULL; 5109 } 5110 /* return the result */ 5111 return result; 5112 } 5113 5114 static int 5115 _shr_res_aidxres_destroy(_shr_res_pool_desc_t *desc) 5116 { 5117 int result; 5118 5119 result = shr_aidxres_list_destroy((shr_aidxres_list_handle_t)(desc->resHandle)); 5120 if (_SHR_E_NONE == result) { 5121 sal_free(desc); 5122 } 5123 return result; 5124 } 5125 5126 static int 5127 _shr_res_aidxres_alloc(_shr_res_pool_desc_t *desc, 5128 uint32 flags, 5129 int count, 5130 int *elem) 5131 { 5132 int result; 5133 const shr_res_aidxres_extras_t *info = desc->extras; 5134 shr_aidxres_list_handle_t handle = desc->resHandle; 5135 shr_aidxres_element_t item; 5136 5137 if (SHR_RES_ALLOC_REPLACE & flags) { 5138 LOG_ERROR(BSL_LS_SOC_COMMON, 5139 (BSL_META("REPLACE not yet supported on aidxres\n"))); 5140 } 5141 5142 if (SHR_RES_ALLOC_WITH_ID & flags) { 5143 /* allocate WITH_ID */ 5144 result = shr_aidxres_list_reserve(handle, 5145 *elem, 5146 (*elem) + count - 1); 5147 } else { 5148 /* allocate next available */ 5149 if (count > (2 << info->blocking_factor)) { 5150 LOG_ERROR(BSL_LS_SOC_COMMON, 5151 (BSL_META("tried to allocate %d elements from idxres list" 5152 " with blocking_factor %d\n"), 5153 count, 5154 info->blocking_factor)); 5155 return _SHR_E_PARAM; 5156 } 5157 if (count > 1) { 5158 result = shr_aidxres_list_alloc_block(handle, count, &item); 5159 } else { 5160 result = shr_aidxres_list_alloc(handle, &item); 5161 } 5162 if (_SHR_E_NONE == result) { 5163 *elem = item; 5164 } 5165 } 5166 return result; 5167 } 5168 5169 static int 5170 _shr_res_aidxres_free(_shr_res_pool_desc_t *desc, 5171 int count, 5172 int elem) 5173 { 5174 int result = _SHR_E_NONE; 5175 int xresult; 5176 shr_aidxres_list_handle_t handle = desc->resHandle; 5177 5178 result = shr_aidxres_list_free(handle, elem); 5179 /* 5180 * If it was a single block that was allocated, then it is all free, but 5181 * if it was more than one block, or if it was marked by 'reserve' (so 5182 * WITH_ID), then we need to traverse it. Since we're freeing blocks as 5183 * we come to them, any members of those blocks will already be free after 5184 * the first element, but there isn't a way to know how many elements were 5185 * in the block. Basically, we need to skip any elements after the first 5186 * that are marked NOT_FOUND (not in use) as if nothing was wrong. 5187 */ 5188 if (_SHR_E_NONE == result) { 5189 count--; 5190 elem++; 5191 xresult = _SHR_E_NONE; 5192 while (((_SHR_E_NONE == xresult) || (_SHR_E_RESOURCE == xresult)) && 5193 (count > 0)) { 5194 xresult = shr_aidxres_list_free(handle, elem); 5195 if ((_SHR_E_NONE != xresult) && (_SHR_E_RESOURCE != xresult)) { 5196 LOG_ERROR(BSL_LS_SOC_COMMON, 5197 (BSL_META("element %d unable to free: %d (%s)\n"), 5198 elem, 5199 xresult, 5200 _SHR_ERRMSG(xresult))); 5201 result = xresult; 5202 } 5203 elem++; 5204 count--; 5205 } 5206 } 5207 if (_SHR_E_RESOURCE == result) { 5208 /* return NOT_FOUND instead */ 5209 result = _SHR_E_NOT_FOUND; 5210 } 5211 return result; 5212 } 5213 5214 static int 5215 _shr_res_aidxres_check(_shr_res_pool_desc_t *desc, 5216 int count, 5217 int elem) 5218 { 5219 int result = _SHR_E_NOT_FOUND; 5220 shr_aidxres_list_handle_t handle = desc->resHandle; 5221 5222 while ((_SHR_E_NOT_FOUND == result) && (0 < count)) { 5223 result = shr_aidxres_list_elem_state(handle, elem); 5224 elem++; 5225 count--; 5226 } 5227 return result; 5228 } 5229 5230 static int 5231 _shr_res_aidxres_check_all(_shr_res_pool_desc_t *desc, 5232 int count, 5233 int elem) 5234 { 5235 shr_aidxres_list_handle_t handle = desc->resHandle; 5236 5237 return shr_aidxres_list_block_state(handle, elem, count); 5238 } 5239 5240 /*****************************************************************************/ 5241 /* 5242 * Interface to mdb (external implementation) 5243 */ 5244 5245 /* 5246 * MDB has a lot of features that are not exposed through this interface, but 5247 * it does improve upon aidxres for allowing greater versatility in terms of 5248 * not requiring alignment of multiple element blocks, and it can track 5249 * variable (non-power-of-two) size free block lists, in order to optimise 5250 * allocation of certain sizes of blocks. Its performance will be slightly 5251 * worse than aidxres because mdb likes to combine neighbouring free blocks 5252 * when allocating and freeing, and this causes roughly O(logm(b)) where m is 5253 * the number of free lists additional overhead after the primary one and b is 5254 * the size of the banks. Note that poor choice of free list sizes (such as 5255 * only using the mandatory single-element free list) will significantly 5256 * imparir performance, degrading it as far as O(c*b) where c is the number of 5257 * elements in a block. 5258 * 5259 * The overhead for mdb is fairly close to 32.5 bits per element. This may 5260 * sound like rather a lot, but if you consider it against a traditional 5261 * linked list, which requires an alloc cell per block (so 16 bytes of memory 5262 * per block) and can't do query in O(1) time or best-fit as described above, 5263 * it's still worthwhile in case where there are large resources to manage. 5264 * 5265 * The mdb interface here also offers a lot more sanity checking than most of 5266 * the other mechanisms. This is because mdb allows information to be 5267 * retrieved about a block of elements, and so free() and check() call 5268 * parameters can be validated very specifically. 5269 * 5270 * In order to take advantage of the other features of mdb, such as user 5271 * lists, live adjustments to allocation mechanism, and so on, the mdb code 5272 * should be used directly. 5273 */ 5274 5275 static int 5276 _shr_res_mdb_create(_shr_res_pool_desc_t **desc, 5277 int low_id, 5278 int count, 5279 const void* extras, 5280 const char* name) 5281 { 5282 int result = _SHR_E_NONE; 5283 int len_name = sal_strlen(name); 5284 const shr_res_mdb_extras_t *info = extras; 5285 shr_res_mdb_extras_t *intInfo; 5286 int namesize = ((len_name + 3) & (~3)); /* align to quadbyte */ 5287 int nodesize = namesize + sizeof(**desc) + sizeof(*info); 5288 int index; 5289 5290 /* need the base descriptor */ 5291 *desc = sal_alloc(nodesize, "mdb resource descriptor"); 5292 if (!(*desc)) { 5293 /* alloc failed */ 5294 LOG_ERROR(BSL_LS_SOC_COMMON, 5295 (BSL_META("unable to allocate %d bytes for descriptor\n"), 5296 nodesize)); 5297 return _SHR_E_MEMORY; 5298 } 5299 sal_memset(*desc, 0x00, nodesize); 5300 (*desc)->count = count; 5301 (*desc)->low = low_id; 5302 (*desc)->extras = &((*desc)->name[namesize]); 5303 intInfo = (shr_res_mdb_extras_t*)((*desc)->extras); 5304 sal_strncpy(&((*desc)->name[0]), name, len_name); 5305 if (len_name) 5306 *((char*)&((*desc)->name[0])+len_name) = '\0'; 5307 if (info) { 5308 /* Just copy the settings; the mdb manager will check things */ 5309 intInfo->bank_size = info->bank_size; 5310 intInfo->free_lists = info->free_lists; 5311 for (index = 0; index < info->free_lists; index++) { 5312 intInfo->free_counts[index] = info->free_counts[index]; 5313 } 5314 } else { 5315 /* no settings provided; pick a reasonable(?) default set */ 5316 LOG_WARN(BSL_LS_SOC_COMMON, 5317 (BSL_META("missing extra information; using defaults\n"))); 5318 intInfo->bank_size = 4096; 5319 intInfo->free_lists = 12; 5320 intInfo->free_counts[0] = 2; 5321 intInfo->free_counts[1] = 4; 5322 intInfo->free_counts[2] = 8; 5323 intInfo->free_counts[3] = 16; 5324 intInfo->free_counts[4] = 32; 5325 intInfo->free_counts[5] = 64; 5326 intInfo->free_counts[6] = 128; 5327 intInfo->free_counts[7] = 256; 5328 intInfo->free_counts[8] = 512; 5329 intInfo->free_counts[9] = 1024; 5330 intInfo->free_counts[10] = 2048; 5331 intInfo->free_counts[11] = 4096; 5332 } 5333 result = shr_mdb_create((shr_mdb_list_handle_t*)&((*desc)->resHandle), 5334 intInfo->bank_size, 5335 intInfo->free_lists, 5336 &(intInfo->free_counts[0]), 5337 0 /* user lists */, 5338 low_id, 5339 low_id + count - 1, 5340 FALSE /* no implied locking */); 5341 if (_SHR_E_NONE != result) { 5342 /* creation failed */ 5343 LOG_ERROR(BSL_LS_SOC_COMMON, 5344 (BSL_META("unable to create mdb(%d,%d,%d,%d,...): %d (%s)\n"), 5345 low_id, 5346 low_id + count - 1, 5347 intInfo->bank_size, 5348 intInfo->free_lists, 5349 result, 5350 _SHR_ERRMSG(result))); 5351 sal_free(*desc); 5352 *desc = NULL; 5353 } else { 5354 /* set the thing to use a reasonable alloc mode */ 5355 result = shr_mdb_allocmode_set((shr_mdb_list_handle_t)((*desc)->resHandle), 5356 shr_mdb_alloc_bank_first | 5357 shr_mdb_alloc_block_low | 5358 shr_mdb_free_block_low | 5359 shr_mdb_join_alloc_and_free | 5360 shr_mdb_join_high_and_low); 5361 } 5362 /* return the result */ 5363 return result; 5364 } 5365 5366 static int 5367 _shr_res_mdb_destroy(_shr_res_pool_desc_t *desc) 5368 { 5369 int result; 5370 5371 result = shr_mdb_destroy((shr_mdb_list_handle_t)(desc->resHandle)); 5372 if (_SHR_E_NONE == result) { 5373 sal_free(desc); 5374 } 5375 return result; 5376 } 5377 5378 static int 5379 _shr_res_mdb_alloc(_shr_res_pool_desc_t *desc, 5380 uint32 flags, 5381 int count, 5382 int *elem) 5383 { 5384 shr_mdb_list_handle_t handle = desc->resHandle; 5385 shr_mdb_elem_index_t item; 5386 int result; 5387 5388 if (SHR_RES_ALLOC_WITH_ID & flags) { 5389 /* allocate WITH_ID */ 5390 /* 5391 * More complicated than idxres, aidxress. For starters, mdb honours 5392 * BCM tendency to declare _SHR_E_NOT_FOUND when it would be more 5393 * helpful for _SHR_E_PARAM -- trying to go beyond the end of a list. 5394 * Therefore we need to check and provide the results documented for 5395 * this API. 5396 */ 5397 if (((*elem) < desc->low) || ((*elem) + count > desc->low + desc->count)) { 5398 return _SHR_E_PARAM; 5399 } 5400 if (SHR_RES_ALLOC_REPLACE & flags) { 5401 /* replacing, see if it is already there */ 5402 result = shr_mdb_block_check_all(handle, *elem, count); 5403 switch (result) { 5404 case _SHR_E_FULL: 5405 /* matches existing block, consider it allocated (again) */ 5406 result = _SHR_E_NONE; 5407 break; 5408 case _SHR_E_EMPTY: 5409 /* nothing here to reallocate */ 5410 result = _SHR_E_NOT_FOUND; 5411 break; 5412 case _SHR_E_CONFIG: 5413 case _SHR_E_EXISTS: 5414 /* not all free or specified range includes >1 one block */ 5415 result = _SHR_E_RESOURCE; 5416 break; 5417 default: 5418 /* should never see this */ 5419 result = _SHR_E_INTERNAL; 5420 } 5421 } else { 5422 /* not replacing */ 5423 result = shr_mdb_alloc_id(handle, *elem, count); 5424 } 5425 } else { 5426 if (SHR_RES_ALLOC_REPLACE & flags) { 5427 /* replace is not supported except WITH_ID */ 5428 return _SHR_E_PARAM; 5429 } 5430 /* allocate next available */ 5431 result = shr_mdb_alloc(handle, &item, count); 5432 if (_SHR_E_NONE == result) { 5433 *elem = item; 5434 } 5435 } 5436 return result; 5437 } 5438 5439 static int 5440 _shr_res_mdb_free(_shr_res_pool_desc_t *desc, 5441 int count, 5442 int elem) 5443 { 5444 int result; 5445 shr_mdb_list_handle_t handle = desc->resHandle; 5446 shr_mdb_block_info_t info; 5447 5448 /* Coverity :: 21913 */ 5449 memset(&info, 0, sizeof(info)); 5450 5451 /* 5452 * More complicated than idxres, aidxress. For starters, mdb honours BCM 5453 * tendency to declare _SHR_E_NOT_FOUND when it would be more helpful for 5454 * _SHR_E_PARAM -- trying to go beyond the end of a list. Therefore we 5455 * need to check and provide the results documented for this API. 5456 */ 5457 if ((elem < desc->low) || (elem + count > desc->low + desc->count)) { 5458 return _SHR_E_PARAM; 5459 } 5460 /* 5461 * Life gets interesting now. In idxres and aidxres and even bitmap 5462 * models, we had no way of getting the block size back from the starting 5463 * element. Here we do have that ability. Ensure the block is the 5464 * claimed size before freeing it. 5465 */ 5466 result = shr_mdb_block_info(handle, elem, &info); 5467 if (_SHR_E_NONE == result) { 5468 if (info.size != count) { 5469 LOG_ERROR(BSL_LS_SOC_COMMON, 5470 (BSL_META("freeing block size %d but claimed %d\n"), 5471 info.size, 5472 count)); 5473 result = _SHR_E_FAIL; 5474 } 5475 if (info.head != (uint32)elem) { 5476 LOG_ERROR(BSL_LS_SOC_COMMON, 5477 (BSL_META("freeing block with head %d by non-head" 5478 " element %d\n"), 5479 info.head, 5480 elem)); 5481 result = _SHR_E_FAIL; 5482 } 5483 if (_SHR_E_NONE == result) { 5484 result = shr_mdb_free(handle, elem); 5485 } 5486 } 5487 return result; 5488 } 5489 5490 static int 5491 _shr_res_mdb_check(_shr_res_pool_desc_t *desc, 5492 int count, 5493 int elem) 5494 { 5495 int result = _SHR_E_NOT_FOUND; 5496 shr_mdb_list_handle_t handle = desc->resHandle; 5497 shr_mdb_block_info_t info; 5498 5499 /* Coverity :: 21912 */ 5500 memset(&info, 0, sizeof(info)); 5501 5502 /* 5503 * More complicated than idxres, aidxres. For starters, mdb honours BCM 5504 * tendency to declare _SHR_E_NOT_FOUND when it would be more helpful for 5505 * _SHR_E_PARAM -- trying to go beyond the end of a list. Therefore we 5506 * need to check and provide the results documented for this API. 5507 */ 5508 if ((elem < desc->low) || (elem + count > desc->low + desc->count)) { 5509 return _SHR_E_PARAM; 5510 } 5511 /* 5512 * Since this is meant to be a probe for elements in use, we don't want to 5513 * simply bail out if the caller requests a block that is different in 5514 * size than one that already exists, or if the caller's block is a member 5515 * of an existing block that started elsewhere. Just scan for elements 5516 * that are in use and bail for those, otherwise keep going. 5517 */ 5518 while ((count > 0) && (_SHR_E_NOT_FOUND == result)) { 5519 result = shr_mdb_block_info(handle, elem, &info); 5520 count--; 5521 elem++; 5522 } 5523 if (_SHR_E_NONE == result) { 5524 /* shr_mdb_block_info returns _SHR_E_NONE if it finds a block */ 5525 result = _SHR_E_EXISTS; 5526 } 5527 return result; 5528 } 5529 5530 static int 5531 _shr_res_mdb_check_all(_shr_res_pool_desc_t *desc, 5532 int count, 5533 int elem) 5534 { 5535 shr_mdb_list_handle_t handle = desc->resHandle; 5536 5537 return shr_mdb_block_check_all(handle, count, elem); 5538 } 5539 5540