openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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