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

scache.c (54824B)


      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  * Purpose: Level 2 Warm Boot cache management    
      8  */
      9 
     10 /* upgrade:  should separate out from scache/stable */
     11 #include <shared/bsl.h>
     12 
     13 #include <shared/switch.h> /* for _SHR_SWITCH_STABLE_*  */
     14 
     15 #ifdef BCM_ESW_SUPPORT
     16 /* upgrade: remove for phase1*/
     17 #include <soc/mem.h> /* soc_mem_entry_bytes */
     18 #endif
     19 
     20 #include <shared/alloc.h>
     21 
     22 #include <soc/scache.h>
     23 #include <soc/drv.h>
     24 #include <soc/error.h>
     25 #include <soc/cm.h>
     26 #include <soc/types.h>
     27 #include <shared/util.h>
     28 
     29 #if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) && !defined(__KERNEL__)  && (defined(LINUX) || defined(UNIX))
     30 #define SCACHE_SHMEM_SUPPORT
     31 #endif
     32 
     33 #if defined(SCACHE_SHMEM_SUPPORT)
     34 #include <soc/ha.h>
     35 #define SCACHE_IS_SHMEM(unit) (SOC_STABLE(unit)->location == _SHR_SWITCH_STABLE_SHARED_MEM)
     36 #endif
     37 
     38 #ifdef BCM_WARM_BOOT_SUPPORT
     39 int scache_max_partitions[SOC_MAX_NUM_DEVICES][SOC_SCACHE_MAX_MODULES];
     40 #endif /* BCM_WARM_BOOT_SUPPORT */
     41 
     42 /* Next phase work:  (search for upgrade)
     43  *  1. remove knowledge of specific stable types/locations from scache.
     44  *  1.1. remove stable.location, index_min, index_max
     45  *  1.2. move stable into scache state entirely
     46  *  1.3. remove shared/switch.h include..
     47  *  1.4. remove SHR_SWITCH_STABLE_APPLICATION, SHR_SWITCH_STABLE_*?
     48  *  1.5. move SOC_STABLE_BASIC, SOC_STABLE_* to specific impls
     49  *  2. enable dirty bit support
     50  */
     51 
     52 #ifdef BCM_WARM_BOOT_SUPPORT
     53 
     54 typedef struct soc_stable_s {
     55     VOL uint32  location;    /* Storage location (Level 2 WB) */
     56     VOL uint32  size;        /* Storage size (Level 2 WB)     */
     57     VOL uint32  used;        /* Storage usage (Level 2 WB)    */
     58     VOL uint32  index_min;   /* Min index if using chip memory (Level 2 WB) */
     59     VOL uint32  index_max;   /* Max index if using chip memory (Level 2 WB) */
     60     VOL uint32  flags;       /* Flags for storage attributes (Level 2 WB) */
     61     soc_read_func_t rf;      /* Read function (Level 2 WB)    */
     62     soc_write_func_t wf;     /* Write function (Level 2 WB)   */
     63     soc_alloc_func_t alloc_f;/* To allocate per scache handle,
     64                               * buffer must be persistent for life
     65                               * of process */
     66     soc_free_func_t  free_f; /* To free per scache handle     */
     67 } soc_stable_t;
     68 
     69 
     70 /* soc_stable: per-unit storage table structure for level 2 warm boot */
     71 /* not externally visible state; use accessors */
     72 /* upgrade:  move into scache state */
     73 static soc_stable_t    soc_stable[SOC_MAX_NUM_DEVICES];
     74 
     75 #define SOC_STABLE(unit)                (&soc_stable[unit])
     76 
     77 #define SOC_SCACHE_COMMIT_ALL           (0x2)
     78 
     79 /* Read/Write stable accessors must be configured for scache to function */
     80 #define STABLE_CONFIGURED(stable_) \
     81   (!(((stable_)->rf == NULL) || ((stable_)->wf == NULL)))
     82 
     83 #if defined(SCACHE_SHMEM_SUPPORT)
     84 #define RETURN_IF_STABLE_NOT_CONFIGURED(unit_) \
     85 if (SCACHE_IS_SHMEM(unit)) {\
     86     return SOC_E_NONE;\
     87 }\
     88 else {\
     89     if (!STABLE_CONFIGURED(SOC_STABLE(unit_))) { return SOC_E_CONFIG; }\
     90 }
     91 #else
     92 #define RETURN_IF_STABLE_NOT_CONFIGURED(unit_) \
     93   if (!STABLE_CONFIGURED(SOC_STABLE(unit_))) { return SOC_E_CONFIG; }
     94 #endif
     95 
     96 /*
     97  *  In the persistent storage, the data will be stored in the following format:
     98  *  Each entry will be preceded by an scache_descriptor, the last discriptor 
     99  *  will contain null information.
    100  *   --------------------------------------------------------------------------
    101  *  |  Cache guard  1 (32 bit) <--- Starting offset zero                       |
    102  *  |  Cache handle 1 (32 bit)                                                 |
    103  *  |  Cache size   1 (32 bit)                                                 |
    104  *  |  Module data  1 (size = Cache size 1)                                    |
    105  *  |  CRC          1 (32 bit) (OPTIONAL. If compilaed with SCACHE_CRC_CHECK   |
    106  *  |  Cache guard  2 (32 bit) <--- Starting offset = sum(cache sizes + 2 * 32)|
    107  *  |  Cache handle 2 (32 bit)                                                 |
    108  *  |  Cache size   2 (32 bit)                                                 |
    109  *  |  Module data  2 (size = Cache size 2)                                    |
    110  *  |  CRC          2 (32 bit) (OPTIONAL. If compilaed with SCACHE_CRC_CHECK   |
    111  *  |  .                                                                       |
    112  *  |  .                                                                       |
    113  *  |  Cache guard  N (32 bit) <--- Starting offset = sum(cache sizes + 2 * 32)|
    114  *  |  Cache handle N (32 bit)                                                 |
    115  *  |  Cache size   N (32 bit)                                                 |
    116  *  |  CRC          N (32 bit) (OPTIONAL. If compilaed with SCACHE_CRC_CHECK   |
    117  *  |  Module data  N (size = Cache size)                                      |
    118  *  |  Cache guard  N+1                                                        |
    119  *  |  Cache handle N+1 ~0    - End of list                                    |
    120  *  |  Cache size   N+1 0     - End of list                                    |
    121  *  |  Module data  N+1 Empty - end of list                                    |
    122  *   --------------------------------------------------------------------------
    123  *  The format for each individual module data is module-specific.
    124  *  The functions here are oblivious of the module-specific formats.
    125  *  The size of the cache equals the size of the stable, which must be selected
    126  *  before using the functions below.
    127  *  On Warm Boot initialization, the entire blob will be DMA'ed.
    128  */
    129 typedef struct scache_descriptor_s {
    130     uint32  guard;
    131     uint32  handle;
    132     uint32  size;
    133 } scache_descriptor_t;
    134 
    135 #define DESCR_GUARD  0xba5eba11
    136 #define DESCRIPTOR_IS_VALID(sd_)   ((sd_)->guard == DESCR_GUARD)
    137 #define DESCRIPTOR_IS_NULL(sd_)    ((sd_)->size == 0)
    138 
    139 #ifdef SCACHE_CRC_CHECK
    140 typedef uint32 scache_crc_t;
    141 
    142 /* compute the size to allocated from stable/persistent storage */
    143 #define SCACHE_HANDLE_ALLOC_SIZE(sz)  ((sz) + sizeof(scache_descriptor_t) + sizeof(scache_crc_t))
    144 
    145 /* Compute the size requested by the caller from the size in
    146  * stable/persistent storage */
    147 #define SCACHE_HANDLE_CALLER_SIZE(sz) ((sz) - sizeof(scache_descriptor_t) - sizeof(scache_crc_t))
    148 
    149 #else /*SCACHE_CRC_CHECK*/
    150 #define SCACHE_HANDLE_ALLOC_SIZE(sz)  ((sz) + sizeof(scache_descriptor_t))
    151 
    152 /* Compute the size requested by the caller from the size in
    153  * stable/persistent storage */
    154 #define SCACHE_HANDLE_CALLER_SIZE(sz) ((sz) - sizeof(scache_descriptor_t))
    155 #endif /*SCACHE_CRC_CHECK*/
    156 
    157 
    158 /* Compute pointer to the caller data from the start of an scache entry */
    159 #define SCACHE_HANDLE_BUF_DATA_OFFSET sizeof(scache_descriptor_t)
    160 #define SCACHE_HANDLE_CALLER_PTR(ptr) ((uint8 *)(ptr) + SCACHE_HANDLE_BUF_DATA_OFFSET)
    161 
    162 #ifdef SCACHE_CRC_CHECK
    163 /* Compute pointer to store the CRC. Will be placed after the descriptor and data. */
    164 #define SCACHE_HANDLE_CRC_PTR(hs_) \
    165           ((uint32*)(SCACHE_HANDLE_CALLER_PTR(hs_->buf) + ((scache_descriptor_t*)(hs_->buf))->size))
    166 
    167 /* Compute the size we want to calcule the CRC on. sd_ is a pointer to a descriptor. */
    168 #define SCACHE_CRC_DATA_SIZE(sd_) (sizeof(scache_descriptor_t) + (sd_)->size)
    169 
    170 #define SCACHE_CRC_INVALID 0xbabababa
    171 
    172 #define SCACHE_CRC_INVALIDATE(hs_) *(SCACHE_HANDLE_CRC_PTR(hs_)) = SCACHE_CRC_INVALID
    173 #define SCACHE_CRC_IS_VALID(hs_)   (*(SCACHE_HANDLE_CRC_PTR(hs_)) != SCACHE_CRC_INVALID)
    174 
    175 #endif
    176 
    177 
    178 static void
    179 scache_descriptor_t_init(scache_descriptor_t *sd, uint32 size, uint32 handle) 
    180 {
    181     sal_memset(sd, 0, sizeof(*sd));
    182     sd->guard  = DESCR_GUARD;
    183     sd->handle = handle;
    184     sd->size   = size;
    185 }
    186 
    187 #define SCACHE_HANDLE_ID_INVALID      ~0
    188 #define SCACHE_HANDLE_STATE_DIRTY      0x1
    189 
    190 typedef struct scache_handle_state_s {
    191     soc_scache_handle_t handle; /* BCM API module, e.g., BCM_MODULE_VLAN */
    192     sal_mutex_t         lock;   /* lock access to buffer */
    193     void   *buf;                 /* Starting pointer for this cache's desc */
    194     uint32 size;                /* Total cache handle size =
    195                                  *  (descriptor_size + requested_size) */
    196     uint32 used;                /* Current used storage                */
    197     uint32 flags;
    198     uint32 offset;              /* Position of this handle in persistent
    199                                  * storage */
    200     struct scache_handle_state_s *next; /* Next pointer */
    201 } scache_handle_state_t;
    202 
    203 typedef struct scache_state_s {
    204     scache_handle_state_t *head;
    205     scache_descriptor_t    null_descriptor;
    206     uint32                 flags;
    207     uint32                 last_offset;
    208 } scache_state_t;
    209 
    210 static scache_state_t scache_state[SOC_MAX_NUM_DEVICES];
    211 
    212 
    213 static int
    214 scache_handle_state_find(scache_handle_state_t *head, 
    215                          soc_scache_handle_t handle,
    216                          scache_handle_state_t **hs);
    217 
    218 /* clean up scache_handle_state resources */
    219 /* unit agnostic */
    220 static void
    221 scache_handle_state_destroy(scache_handle_state_t *hs,
    222                             soc_stable_t *stable)
    223 {
    224     if (hs->lock) {
    225         sal_mutex_destroy(hs->lock);
    226     }
    227     if (stable && hs->buf) {
    228         stable->free_f(hs->buf);
    229     }
    230 }
    231 
    232 #ifdef SCACHE_CRC_CHECK
    233 /* Calculate CRC on the buffer of a handle, and writes the result after the data section
    234    on the buffer */
    235 STATIC void
    236 _scache_hsbuf_crc32_append(scache_handle_state_t *hs)
    237 {
    238     /* Calculate CRC on descriptor and data, without the CRC at the end */
    239     scache_crc_t crc=0;
    240     scache_crc_t *crc_ptr;
    241     scache_descriptor_t *descriptor  = (scache_descriptor_t*)hs->buf;
    242 
    243     crc = _shr_crc32(~0, (unsigned char*)descriptor, SCACHE_CRC_DATA_SIZE(descriptor));
    244     crc_ptr = SCACHE_HANDLE_CRC_PTR(hs);
    245 
    246     LOG_DEBUG(BSL_LS_SOC_COMMON,
    247               (BSL_META("_scache_hsbuf_crc32_append: desc=%p, handle=0x%x, size=%d, crc_offset=%p, crc=0x%x\n"),
    248                descriptor, hs->handle, hs->size, crc_ptr, crc));
    249 
    250     *crc_ptr = soc_htonl(crc);
    251 }
    252 
    253 int
    254 soc_scache_hsbuf_crc32_append(int unit, soc_scache_handle_t handle_id)
    255 {
    256     int rv;
    257     scache_handle_state_t *hs = NULL;
    258 
    259     rv = scache_handle_state_find(scache_state[unit].head, handle_id, &hs);    
    260     SOC_IF_ERROR_RETURN(rv);
    261 
    262     _scache_hsbuf_crc32_append(hs);
    263 
    264     return SOC_E_NONE;
    265 }
    266 
    267 /* Checks that the CRC appended after the data is correct */
    268 STATIC uint8
    269 _scache_hsbuf_crc32_check(scache_handle_state_t *hs)
    270 {
    271     /* To check, _shr_crc32 expects the CRC value to be a part of the data  */
    272     scache_crc_t crc;
    273     scache_descriptor_t *descriptor  = (scache_descriptor_t*)hs->buf;
    274 
    275 #ifdef BROADCOM_DEBUG
    276     scache_crc_t re_crc = _shr_crc32(~0, (unsigned char*)descriptor, (SCACHE_CRC_DATA_SIZE(descriptor)));
    277     scache_crc_t *read_crc_ptr = (SCACHE_HANDLE_CRC_PTR(hs));
    278 #endif
    279     crc = _shr_crc32(~0, (unsigned char*)descriptor, (SCACHE_CRC_DATA_SIZE(descriptor) + sizeof(scache_crc_t)));
    280 
    281 #ifdef BROADCOM_DEBUG
    282     LOG_DEBUG(BSL_LS_SOC_COMMON,
    283               (BSL_META("_scache_hsbuf_crc32_check: desc=%p, handle=0x%x, size=%d, crc=0x%x, re_crc=0x%x, read_crc=0x%x, read_crc_ptr=%p\n"),
    284                descriptor, hs->handle, hs->size, crc, re_crc, *read_crc_ptr, read_crc_ptr));
    285 #endif
    286 
    287     return (crc == 0); 
    288 }
    289 #endif /* SCACHE_CRC_CHECK */
    290 
    291 /* scache_handle_state factory.  
    292  * Allocates associated stable buffer, if available and initializes state */
    293 /* unit agnostic */
    294 static int
    295 scache_handle_state_create(soc_stable_t *stable,
    296                            soc_scache_handle_t handle_id,
    297                            uint32 alloc_size,
    298                            scache_handle_state_t **handle_state)
    299 {
    300     scache_handle_state_t *hs;
    301     scache_descriptor_t *descriptor;
    302 
    303     hs = sal_alloc(sizeof(*hs), "WB cache info");
    304 #if (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT))
    305     /**
    306      * Offset accocation counters, scache memory should not be taken into account
    307      */
    308     sal_set_alloc_counters_offset(sizeof(*hs), 0);
    309     sal_set_alloc_counters_offset_main_thr(sizeof(*hs), 0);
    310 #endif
    311 
    312     if (hs == NULL) {
    313         return SOC_E_MEMORY;
    314     }
    315 
    316     sal_memset(hs, 0, sizeof(*hs));
    317     hs->lock = sal_mutex_create("wb handle lock");
    318 
    319     if (stable) {
    320         hs->buf = stable->alloc_f(alloc_size);
    321         if (hs->buf) {
    322             sal_memset(hs->buf,0x0,alloc_size);
    323         }
    324     } else {
    325         hs->buf = NULL;
    326     }
    327 
    328     if (hs->lock == NULL || (stable && (hs->buf == NULL))) {
    329         scache_handle_state_destroy(hs, stable);
    330         sal_free(hs);
    331         return SOC_E_MEMORY;
    332     }
    333 
    334     hs->flags  = 0;
    335     hs->offset = 0;
    336     hs->size   = alloc_size;
    337     hs->handle = handle_id;
    338 
    339     /* initalize the descriptor in scache */
    340     if (hs->buf) {
    341         descriptor = (scache_descriptor_t*)hs->buf;
    342         scache_descriptor_t_init(descriptor, 
    343                                  SCACHE_HANDLE_CALLER_SIZE(alloc_size), 
    344                                  handle_id);
    345     }
    346 
    347     if (handle_state) {
    348         *handle_state = hs;
    349     }
    350 
    351     /*    coverity[leaked_storage : FALSE]    */
    352     return SOC_E_NONE;
    353 }
    354 
    355 /* Find an scache_handle_state object with the given handle */
    356 /* unit agnostic */
    357 static int
    358 scache_handle_state_find(scache_handle_state_t *head, 
    359                          soc_scache_handle_t handle,
    360                          scache_handle_state_t **hs)
    361 {
    362     while (head && (head->handle != handle)) {
    363         head = head->next;
    364     }
    365     
    366     if (head == NULL) {
    367         return SOC_E_NOT_FOUND;
    368     }
    369     if (hs) { *hs = head; }
    370 
    371     return SOC_E_NONE;
    372 }
    373 
    374 
    375 
    376 /* recursively dump the scache info list from any given node */
    377 static void 
    378 soc_scache_dump_handle_state(int idx, scache_handle_state_t *sc)
    379 {
    380     scache_descriptor_t *desc;
    381     if (sc == NULL)   return;
    382     
    383     desc = (scache_descriptor_t*)sc->buf;
    384 
    385     LOG_CLI((BSL_META("%4d 0x%08x 0x%08x 0x%08x 0x%08x %p %p 0x%04x"), 
    386              idx, sc->handle, sc->offset, sc->size, sc->used, sc->buf,
    387              (void *)sc->lock, sc->flags));
    388 
    389     /* validate the soft state matches stored state */
    390     if (desc->handle != sc->handle) {
    391         LOG_CLI((BSL_META("* HANDLE MISMATCH: 0x%08x * "), desc->handle));
    392     }
    393     if (desc->size != SCACHE_HANDLE_CALLER_SIZE(sc->size)) {
    394         LOG_CLI((BSL_META("* SIZE MISMATCH: 0x%08x * "), desc->size));
    395     }
    396 
    397     LOG_CLI((BSL_META("\n")));
    398 
    399     soc_scache_dump_handle_state(idx+1, sc->next);
    400 
    401     return;
    402 }
    403 
    404 void 
    405 soc_scache_dump_state(int unit)
    406 {
    407     if (!SOC_UNIT_NUM_VALID(unit)) {
    408         LOG_CLI((BSL_META_U(unit,
    409                             "invalid unit: %d\n"), unit));
    410         return;
    411     }
    412 
    413     LOG_CLI((BSL_META_U(unit,
    414                         "scache info: flags=0x%04x last_offset=0x%08x\n"),
    415              scache_state[unit].flags, scache_state[unit].last_offset));
    416     LOG_CLI((BSL_META_U(unit,
    417                         "scache handles:\n")));
    418     LOG_CLI((BSL_META_U(unit,
    419                         "%4s %10s %10s %10s %10s %10s %10s %6s\n"),
    420              "idx", "handle", "offset", "size",
    421              "used", "cache", "lock", "flags"));
    422     soc_scache_dump_handle_state(0, scache_state[unit].head);
    423 
    424     return;
    425 }
    426 
    427 /* insert an scache_handle_state into the scache list for this unit */
    428 static int
    429 scache_handle_list_insert(int unit, scache_handle_state_t *hs)
    430 {
    431     hs->offset = scache_state[unit].last_offset;
    432     
    433     /* head insert */
    434     hs->next = scache_state[unit].head;
    435     scache_state[unit].head = hs;
    436 
    437     scache_state[unit].last_offset += hs->size;
    438     return SOC_E_NONE;
    439 }
    440 
    441 
    442 /* Clear the stable info structure for a newly attached unit. */
    443 int
    444 soc_stable_attach(int unit)
    445 {
    446     int stable_size;
    447     soc_stable_t  *stable;
    448 
    449     /* Check for existing scache before clearing the stable 
    450      * info structure. Do not clear if scache already existed */
    451     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    452     if (!stable_size) {
    453         stable = SOC_STABLE(unit);
    454         stable->location = 0;
    455         stable->size = 0;
    456         stable->used = 0;
    457         stable->index_min = 0;
    458         stable->index_max = 0;
    459         stable->flags = 0;
    460     }
    461 
    462     return SOC_E_NONE;
    463 }
    464 
    465 
    466 #ifdef CRASH_RECOVERY_SUPPORT
    467 /* 
    468  * Verify that stable was configured properly for Crash Recovery
    469  */
    470 int
    471 soc_stable_sanity(int unit)
    472 {
    473     soc_stable_t  *stable;
    474     stable = SOC_STABLE(unit);
    475 
    476     if (stable->location != 4) {
    477         LOG_ERROR(BSL_LS_SOC_COMMON,
    478                       (BSL_META_U(unit,
    479                                   "###############\n"
    480                                    "ERROR: Crash Revovery is only allowed with stable_location=4 (shared mem)!!\n "
    481                                   "###############\n")));
    482         return _SHR_E_DISABLED;
    483     }
    484 
    485     return SOC_E_NONE;
    486 }
    487 #endif
    488 
    489 /*set the flag to dirty for all the handles in scache*/
    490 int soc_scache_handle_state_dirty_flag_set(int unit) {
    491 
    492 #ifdef USE_SCACHE_DIRTY_BIT
    493     scache_handle_state_t *current;
    494     int size = 0;
    495     if (!SOC_UNIT_NUM_VALID(unit)) {
    496         return SOC_E_UNIT;
    497     }
    498     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
    499     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &size));
    500     if (size == 0) {
    501         return SOC_E_NONE;
    502     }
    503 
    504     current = scache_state[unit].head;
    505     while (current) {
    506         current->flags |= SCACHE_HANDLE_STATE_DIRTY;
    507         current = current->next;
    508     }
    509 #endif
    510     return SOC_E_NONE;
    511 }
    512 /* Allocate the global block of memory for persistent storage synchronization */
    513 /* This is called by soc_stable_size_set() during cold boot */
    514 int
    515 soc_scache_init(int unit, uint32 size, uint32 flags)
    516 {
    517     if (flags) {
    518         /* flags no longer needed */
    519         return SOC_E_PARAM;
    520     }
    521     if (!SOC_UNIT_NUM_VALID(unit)) {
    522         return SOC_E_UNIT;
    523     }
    524     if (size == 0) {
    525         return SOC_E_NONE;
    526     }
    527 
    528 #if defined(SCACHE_SHMEM_SUPPORT)
    529     if (SCACHE_IS_SHMEM(unit)) {return SOC_E_NONE;};
    530 #endif
    531 
    532     scache_state[unit].head = NULL;
    533     scache_state[unit].flags = flags;
    534     scache_state[unit].last_offset = 0;
    535 
    536     /* The null descriptor determines the end of list in persistent storage.
    537      * Its offset is updated for each handle allocation,
    538      * cleared on init & detach 
    539      * No CRC for the null descriptor. 
    540      */
    541     scache_descriptor_t_init(&scache_state[unit].null_descriptor,
    542                              0, SCACHE_HANDLE_ID_INVALID);
    543 
    544     return SOC_E_NONE;
    545 }
    546 
    547 /* Free the scache and the meta-data */
    548 int
    549 soc_scache_detach(int unit)
    550 {
    551     scache_handle_state_t *current = NULL, *temp = NULL;
    552     soc_stable_t *stable;
    553 #if (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT))
    554     unsigned long alloc_bytes_count;
    555     unsigned long free_bytes_count_before;
    556     unsigned long free_bytes_count_after;
    557 #endif
    558 
    559     if (!SOC_UNIT_NUM_VALID(unit)) {
    560         return SOC_E_UNIT;
    561     }
    562     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
    563 
    564     stable = SOC_STABLE(unit);
    565 
    566     current = scache_state[unit].head;
    567     while (current) {
    568         temp = current;
    569         current = current->next;
    570 
    571         scache_handle_state_destroy(temp, stable);
    572 #if (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT))
    573         sal_get_alloc_counters(&alloc_bytes_count, &free_bytes_count_before);
    574 #endif
    575         sal_free(temp);
    576 #if (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT))
    577         /**
    578           * Offset accocation counters, scache memory should not be taken into account
    579           */
    580         sal_get_alloc_counters(&alloc_bytes_count, &free_bytes_count_after);
    581         sal_set_alloc_counters_offset(0, free_bytes_count_after - free_bytes_count_before);
    582         sal_set_alloc_counters_offset_main_thr(0, free_bytes_count_after - free_bytes_count_before);
    583 #endif
    584     }
    585     scache_state[unit].head = NULL;
    586     scache_state[unit].last_offset = 0;
    587     stable->used = 0;
    588 
    589     scache_descriptor_t_init(&scache_state[unit].null_descriptor,
    590                              0, SCACHE_HANDLE_ID_INVALID);
    591 
    592     return SOC_E_NONE;
    593 }
    594 
    595 /* Carve out a block of memory from the global block */ 
    596 /* This is called by each module that requires persistent storage during 
    597    cold boot */
    598 int
    599 soc_scache_alloc(int unit, soc_scache_handle_t handle_id, uint32 size)
    600 {
    601     int rv;
    602     int stable_size, alloc_size;
    603     scache_handle_state_t *hs;
    604     soc_stable_t *stable;
    605 
    606     /* Don't allow the invalid ID as a handle.  This will be used to
    607      * determine future versioning of the stable format, if needed.
    608      */
    609     if (handle_id == SCACHE_HANDLE_ID_INVALID) {
    610         return SOC_E_PARAM;
    611     }
    612 
    613     if (!SOC_UNIT_NUM_VALID(unit)) {
    614         return SOC_E_UNIT;
    615     }
    616 
    617 #if defined(SCACHE_SHMEM_SUPPORT)
    618     if (SCACHE_IS_SHMEM(unit)) {
    619         uint8* ptr = NULL;
    620         ha_mem_alloc(unit,
    621                     (unsigned char) SOC_SCACHE_HANDLE_MODULE_GET(handle_id), 
    622                     (unsigned char) SOC_SCACHE_HANDLE_SEQUENCE_GET(handle_id),
    623                     &size, (void**)&ptr);
    624         return SOC_E_NONE;
    625     }
    626 #endif
    627 
    628     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
    629 
    630     /* make sure this handle doesn't already exist */
    631     rv = scache_handle_state_find(scache_state[unit].head, handle_id, NULL);
    632     if (SOC_SUCCESS(rv)) {
    633         return SOC_E_EXISTS;
    634     }
    635     if (rv != SOC_E_NOT_FOUND) {
    636         return rv;
    637     }
    638     rv = SOC_E_NONE;
    639 
    640     stable = SOC_STABLE(unit);
    641 
    642     SOC_SCACHE_ALIGN_SIZE(size);
    643 
    644     /* allocate the requested size, plus a descriptor 
    645      * from persistent storage */
    646     alloc_size = SCACHE_HANDLE_ALLOC_SIZE(size);
    647 
    648     /* exclude the null-descriptor from the total available size */
    649     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    650     stable_size -= sizeof(scache_state[unit].null_descriptor);
    651 
    652     if ((alloc_size + scache_state[unit].last_offset) > stable_size) {
    653         soc_scache_dump_state(unit);
    654         LOG_CLI((BSL_META_U(unit,
    655                             "Scache on unit %d exhausted the stable_size of %d\n"), unit, stable_size));        
    656         return SOC_E_RESOURCE;
    657     }
    658 
    659     SOC_IF_ERROR_RETURN(
    660         scache_handle_state_create(stable, handle_id, alloc_size, &hs));
    661 
    662 #ifdef SCACHE_CRC_CHECK
    663     /* Calculate the CRC on the new buffer */
    664     _scache_hsbuf_crc32_append(hs);
    665 #endif
    666     /* Guarantee the scache can be saved at least one time for
    667  * the modules without any warmboot requied data change */
    668 #ifdef USE_SCACHE_DIRTY_BIT
    669     hs->flags |= SCACHE_HANDLE_STATE_DIRTY;
    670 #endif
    671     SOC_IF_ERROR_RETURN(
    672         scache_handle_list_insert(unit, hs));
    673 
    674     
    675     stable->used += alloc_size;
    676 
    677 #ifdef BROADCOM_DEBUG
    678     if (LOG_CHECK(BSL_LS_SOC_COMMON | BSL_DEBUG)) {
    679         LOG_CLI((BSL_META_U(unit,
    680                             "allocated handle=0x%x size=0x%08x\n"), 
    681                  handle_id, size));
    682         soc_scache_dump_state(unit);
    683     }
    684 #endif
    685     return SOC_E_NONE;
    686 }
    687 
    688 /* ReCarve out a block of memory from the global block */ 
    689 /* This is called by each module that requires persistent storage to be increased/decreased during 
    690    warm boot due to scache version change */
    691 int
    692 soc_scache_realloc(int unit, soc_scache_handle_t handle_id, int32 incr_size)
    693 {
    694     int rv;
    695     scache_handle_state_t *hs;
    696 
    697     /* Don't allow the invalid ID as a handle.  This will be used to
    698      * determine future versioning of the stable format, if needed.
    699      */
    700     if (handle_id == SCACHE_HANDLE_ID_INVALID) {
    701         return SOC_E_PARAM;
    702     }
    703 
    704     if (!SOC_UNIT_NUM_VALID(unit)) {
    705         return SOC_E_UNIT;
    706     }
    707     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
    708 
    709     /* make sure this handle already exists */
    710     rv = scache_handle_state_find(scache_state[unit].head, handle_id, &hs);
    711     if (SOC_SUCCESS(rv)) {
    712         soc_stable_t *stable;
    713          /* Realloc*/
    714         stable = SOC_STABLE(unit);
    715  
    716         if (stable != NULL) {
    717             incr_size += hs->size;
    718             SOC_SCACHE_ALIGN_SIZE(incr_size);
    719         
    720             stable->free_f(hs->buf);
    721             hs->buf = stable->alloc_f(incr_size);
    722             sal_memset(hs->buf,0x0,incr_size);
    723 
    724             if (hs->buf == NULL) {
    725                 return SOC_E_MEMORY;
    726             } else {
    727                 scache_handle_state_t *hs_ptr;
    728                 scache_descriptor_t *descriptor;
    729 
    730                 hs_ptr = scache_state[unit].head;
    731 
    732                 stable->used -= hs->size;
    733                 stable->used += incr_size;
    734                 while(hs_ptr) {
    735                     if (hs_ptr->offset > hs->offset) {
    736                         hs_ptr->offset += (incr_size - hs->size);
    737                     }
    738                     hs_ptr = hs_ptr->next;
    739                 }
    740                 scache_state[unit].last_offset += (incr_size - hs->size);
    741                 hs->size = incr_size;
    742                 descriptor = (scache_descriptor_t*)hs->buf;
    743                 scache_descriptor_t_init(descriptor, 
    744                                       SCACHE_HANDLE_CALLER_SIZE(hs->size), 
    745                                       handle_id);
    746 #ifdef SCACHE_CRC_CHECK
    747                 _scache_hsbuf_crc32_append(hs);
    748 #endif
    749             }
    750         }
    751     } else {
    752         return rv;
    753     }
    754 
    755 
    756 #ifdef BROADCOM_DEBUG
    757     if (LOG_CHECK(BSL_LS_SOC_COMMON | BSL_DEBUG)) {
    758         LOG_CLI((BSL_META_U(unit,
    759                             "allocated handle=0x%x incr_size=0x%08x\n"), 
    760                  handle_id, incr_size));
    761         soc_scache_dump_state(unit);
    762     }
    763 #endif
    764     return SOC_E_NONE;
    765 }
    766 
    767 /* Recover the global blob of memory from persistent storage - called by the
    768    SOC layer during warm boot */
    769 int
    770 soc_scache_recover(int unit)
    771 {
    772     int size;
    773     uint32 offset;
    774     soc_stable_t *stable;
    775     scache_handle_state_t *handle_state;
    776     scache_descriptor_t desc;
    777 
    778     if (!SOC_UNIT_NUM_VALID(unit)) {
    779         return SOC_E_UNIT;
    780     }
    781 
    782     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &size));
    783     if (size == 0) {
    784         return SOC_E_NONE;
    785     }
    786 
    787     stable = SOC_STABLE(unit);
    788     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
    789 
    790     /* Remove any latent soft-scache descriptors.  This should only
    791      * happen during a simulated warmboot
    792      */
    793     soc_scache_detach(unit);
    794 
    795     /* Read each handle from persistent storage into scache until 
    796      * the null descriptor is found
    797      */
    798     offset = 0;
    799     SOC_IF_ERROR_RETURN(stable->rf(unit,(uint8*)&desc, offset, sizeof(desc)));
    800     while (!DESCRIPTOR_IS_NULL(&desc)) {
    801 
    802         /* Create a handle_state entry representing this scache handle */
    803         SOC_IF_ERROR_RETURN(
    804             scache_handle_state_create(stable, desc.handle, 
    805                                        SCACHE_HANDLE_ALLOC_SIZE(desc.size),
    806                                        &handle_state));    
    807 
    808         handle_state->flags |= SCACHE_HANDLE_STATE_DIRTY;
    809         SOC_IF_ERROR_RETURN(
    810             scache_handle_list_insert(unit, handle_state));
    811 
    812         /* Read the entire entry into the newly allocated handle */
    813         SOC_IF_ERROR_RETURN(
    814             stable->rf(unit, handle_state->buf, offset, handle_state->size));
    815 
    816 #ifdef SCACHE_CRC_CHECK
    817         /* If CRC hasn't been invalidated, calculate the CRC on the buffer,
    818            and compare with the value read from scache */
    819         if (SCACHE_CRC_IS_VALID(handle_state) &&
    820             !_scache_hsbuf_crc32_check(handle_state)) {
    821 #ifdef BROADCOM_DEBUG
    822             LOG_ERROR(BSL_LS_SOC_COMMON,
    823                       (BSL_META_U(unit,
    824                                   "CRC check failed: handle_id=%d"),
    825                        handle_state->handle));
    826             soc_scache_dump_state(unit);
    827 #endif
    828             return SOC_E_INTERNAL;
    829         }
    830 #endif
    831 
    832         SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit,
    833                                 SOC_SCACHE_HANDLE_MODULE_GET(desc.handle),
    834                                 SOC_SCACHE_HANDLE_SEQUENCE_GET(desc.handle));
    835 
    836         offset += handle_state->size;
    837 
    838         
    839         stable->used += handle_state->size;
    840 
    841         /* get the next descriptor */
    842         SOC_IF_ERROR_RETURN(stable->rf(unit, (uint8*)&desc, offset, sizeof(desc)));
    843     }
    844 
    845 #ifdef BROADCOM_DEBUG
    846     if (LOG_CHECK(BSL_LS_SOC_COMMON | BSL_DEBUG)) {
    847         LOG_CLI((BSL_META_U(unit,
    848                             "Recovered scache:\n")));
    849         soc_scache_dump_state(unit);
    850     }
    851 #endif
    852     return SOC_E_NONE;
    853 }
    854  
    855 /* Get the pointer to the module's area - called by each BCM module during
    856    initialization */
    857 int
    858 soc_scache_ptr_get(int unit, soc_scache_handle_t handle, uint8 **ptr, 
    859                    uint32 *size)
    860 {
    861     scache_handle_state_t *hs;
    862     
    863     if (ptr == NULL) {
    864         return SOC_E_PARAM;
    865     }
    866 
    867 #if defined(SCACHE_SHMEM_SUPPORT)
    868     if (SCACHE_IS_SHMEM(unit)) {
    869         uint8 is_allocated;
    870         SOC_IF_ERROR_RETURN(ha_mem_is_already_alloc(unit, SOC_SCACHE_HANDLE_MODULE_GET(handle), SOC_SCACHE_HANDLE_SEQUENCE_GET(handle), &is_allocated));
    871         if (!is_allocated) {
    872             return SOC_E_NOT_FOUND;
    873         }
    874 
    875         SOC_IF_ERROR_RETURN(ha_mem_alloc(unit, SOC_SCACHE_HANDLE_MODULE_GET(handle), SOC_SCACHE_HANDLE_SEQUENCE_GET(handle), size, (void**)ptr));
    876         return SOC_E_NONE;
    877     }
    878 #endif
    879 
    880     /* Obtain the cache information */
    881     SOC_IF_ERROR_RETURN(
    882         scache_handle_state_find(scache_state[unit].head, handle, &hs));
    883 
    884     *ptr  = SCACHE_HANDLE_CALLER_PTR(hs->buf);
    885     *size = SCACHE_HANDLE_CALLER_SIZE(hs->size);
    886     return SOC_E_NONE;
    887 }
    888 
    889 /*
    890  * Function: soc_scache_info_dump
    891  *
    892  * Purpose:
    893  * Dumps the memory requirements in scache for auxillary modules
    894  *
    895  * Parameters:
    896  * unit - SOC device number
    897  *
    898  * Returns:
    899  * None.
    900  */
    901 void 
    902 soc_scache_info_dump(int unit)
    903 {   
    904     uint32 sum =0;
    905     uint32 size = 0;
    906     uint8 *scache_ptr;
    907     int part_count, i = 0;
    908     soc_scache_handle_t handle;
    909     int rv;
    910     int handle_list[] = { SOC_SCACHE_MEMCACHE_HANDLE, 
    911                           SOC_SCACHE_SOC_DEFIP_HANDLE,
    912                           SOC_SCACHE_FLEXIO_HANDLE, 
    913                           SOC_SCACHE_SWITCH_CONTROL, 
    914                           SOC_SCACHE_TDM_HANDLE,
    915                           SOC_SCACHE_DICTIONARY_HANDLE
    916                          };
    917     char print_modules[][20] = {"Memcache", "Defip", "Flexio", 
    918                                 "Switch control", "TDM", "Dictionary"};
    919 
    920     for (i = 0; i < COUNTOF(handle_list); i++) {
    921         sum = 0;
    922         part_count = 0;
    923         while (0 <= part_count) {
    924             SOC_SCACHE_HANDLE_SET(handle, unit, handle_list[i], part_count);
    925             rv = soc_scache_ptr_get(unit, handle, &scache_ptr, &size);
    926             if (SOC_SUCCESS(rv) && (size > 0)) {
    927                 sum += size;    
    928             }
    929             part_count--;
    930         }
    931 
    932         if (sum > 0) {
    933             LOG_CLI((BSL_META_U(unit,
    934                                 "%s :: %d\n"), print_modules[i], sum));
    935         }
    936     }
    937     return;
    938 }
    939 
    940 int
    941 soc_scache_commit_hs(int unit, soc_stable_t *stable, scache_handle_state_t *hs)
    942 {
    943     int dirty = 0;
    944 
    945     sal_mutex_take(hs->lock, sal_mutex_FOREVER);
    946 /* upgrade: enable */
    947 #ifdef USE_SCACHE_DIRTY_BIT
    948     if (hs->flags & SCACHE_HANDLE_STATE_DIRTY)
    949 #endif
    950     {
    951 #ifdef SCACHE_CRC_CHECK
    952         _scache_hsbuf_crc32_append(hs);
    953 #endif
    954         /* Copy to persistent storage from cache */
    955         stable->wf(unit, (uint8*)hs->buf, 
    956                    (int)hs->offset,
    957                    (int)(hs->size));
    958         hs->flags &= ~SCACHE_HANDLE_STATE_DIRTY;
    959 
    960         dirty = 1;
    961     }
    962     sal_mutex_give(hs->lock);
    963 
    964     return dirty;
    965 }
    966 
    967 /* Write function called by bcmSwitchControlSync when need a specific module to update
    968 *  its scache info. */
    969 int
    970 soc_scache_commit_handle(int unit, soc_scache_handle_t handle, uint32 flags)
    971 {
    972     int size, dirty = 0;
    973     scache_handle_state_t *current;
    974     soc_stable_t *stable;
    975 
    976     if (!SOC_UNIT_NUM_VALID(unit)) {
    977         return SOC_E_UNIT;
    978     }
    979     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
    980     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &size));
    981 
    982     if (size == 0) {
    983         return SOC_E_NONE;
    984     }
    985 
    986     stable = SOC_STABLE(unit);
    987 
    988     current = scache_state[unit].head;
    989     while (current) {
    990         if ((flags & SOC_SCACHE_COMMIT_ALL) || (current->handle == handle)) {
    991             dirty = soc_scache_commit_hs(unit, stable, current);
    992         }
    993 
    994         current = current->next;
    995     }
    996 
    997     if (dirty) {
    998         stable->wf(unit, (uint8*)&scache_state[unit].null_descriptor,
    999                    scache_state[unit].last_offset,
   1000                    sizeof(scache_state[unit].null_descriptor));
   1001     }
   1002 
   1003     return SOC_E_NONE;
   1004 }
   1005 
   1006 
   1007 /* Write function called by bcmSwitchControlSync after all modules update
   1008 *  their scache info. */
   1009 int
   1010 soc_scache_commit(int unit)
   1011 {
   1012     return soc_scache_commit_handle(unit, 0x0, SOC_SCACHE_COMMIT_ALL);
   1013 }
   1014 
   1015 int
   1016 soc_scache_is_config(int unit)
   1017 {
   1018 	RETURN_IF_STABLE_NOT_CONFIGURED(unit);
   1019 	return SOC_E_NONE;
   1020 }
   1021 
   1022 /* function called by apis that want to commit immediately only specific changes they made into scache.  
   1023    this function commits the data in given offset with given size from the supplied handle's scache buffer*/
   1024 int
   1025 soc_scache_commit_specific_data(int unit, soc_scache_handle_t handle, uint32 data_size, uint8 *data, int offset)
   1026 {
   1027     int size;
   1028     soc_stable_t *stable;
   1029     scache_handle_state_t *hs;
   1030 
   1031     if (data == NULL) {
   1032         return SOC_E_PARAM;
   1033     }
   1034     if (!SOC_UNIT_NUM_VALID(unit)) {
   1035         return SOC_E_UNIT;
   1036     }
   1037     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
   1038 
   1039     /* Writing to scache during deinit is a definit bug */
   1040     if (SOC_IS_DETACHING(unit)) {
   1041         
   1042         LOG_DEBUG(BSL_LS_SOC_COMMON,
   1043                   (BSL_META_U(unit,
   1044                               "Writing to scache during de-init is not allowed\n")));
   1045         return SOC_E_NONE;
   1046     }
   1047 
   1048     /* Obtain the cache information */
   1049     SOC_IF_ERROR_RETURN(
   1050         scache_handle_state_find(scache_state[unit].head, handle, &hs));
   1051 
   1052     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &size));
   1053 
   1054     if (size == 0) {
   1055         return SOC_E_NONE;
   1056     }
   1057 
   1058     stable = SOC_STABLE(unit);
   1059     
   1060     sal_mutex_take(hs->lock, sal_mutex_FOREVER);
   1061    
   1062 #ifdef SCACHE_CRC_CHECK
   1063     /* Invalidate the CRC when committing speicifc data, as we do not want to calculate the CRC
   1064        on every entry change */
   1065     SCACHE_CRC_INVALIDATE(hs);
   1066 #endif
   1067 
   1068     /* Copy to persistent storage from cache */
   1069     stable->wf(unit, (uint8*)data, 
   1070                (int)hs->offset + SCACHE_HANDLE_BUF_DATA_OFFSET + SOC_WB_SCACHE_CONTROL_SIZE + offset,
   1071                data_size);   
   1072 
   1073     sal_mutex_give(hs->lock);
   1074 
   1075     stable->wf(unit, (uint8*)&scache_state[unit].null_descriptor,
   1076                scache_state[unit].last_offset,
   1077                sizeof(scache_state[unit].null_descriptor));
   1078 
   1079     return SOC_E_NONE;
   1080 }
   1081 
   1082 
   1083 /* this function perform a partial commit.
   1084    instead of committing all buffers it commit to the extarnal storage only only the changes
   1085    made to the buffer specified by 'handle' between 'offset' to 'offset + length'
   1086    it commits the data from the scache buffer to the external storage as opposed to soc_scache_commit_specific_data
   1087    who commits to the external storage data that is supplied by the caller */
   1088 int
   1089 soc_scache_partial_commit(int unit, soc_scache_handle_t handle, uint32 offset, uint32 length)
   1090 {
   1091     int size;
   1092     soc_stable_t *stable;
   1093     scache_handle_state_t *hs;
   1094 
   1095     if (!SOC_UNIT_NUM_VALID(unit)) {
   1096         return SOC_E_UNIT;
   1097     }
   1098 
   1099     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
   1100 
   1101     if (SOC_IS_DETACHING(unit)) {
   1102         LOG_WARN(BSL_LS_SOC_COMMON,
   1103                   (BSL_META_U(unit,
   1104                               "Writing to scache during de-init\n")));
   1105     }
   1106 
   1107     /* Obtain the cache information */
   1108     SOC_IF_ERROR_RETURN(
   1109         scache_handle_state_find(scache_state[unit].head, handle, &hs));
   1110 
   1111     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &size));
   1112 
   1113     if (size == 0) {
   1114         return SOC_E_INTERNAL;
   1115     }
   1116 
   1117     stable = SOC_STABLE(unit);
   1118     
   1119     sal_mutex_take(hs->lock, sal_mutex_FOREVER);
   1120    
   1121 #ifdef SCACHE_CRC_CHECK
   1122     /* Invalidate the CRC when performing partial commit, as we do not want to calculate the CRC
   1123        on every entry change */
   1124     SCACHE_CRC_INVALIDATE(hs);
   1125 #endif
   1126 
   1127     /* Copy to persistent storage from cache */
   1128     stable->wf(unit, (SCACHE_HANDLE_CALLER_PTR(hs->buf) + offset), 
   1129                (int)hs->offset + SCACHE_HANDLE_BUF_DATA_OFFSET + offset,
   1130                length);   
   1131 
   1132     sal_mutex_give(hs->lock);
   1133 
   1134     stable->wf(unit, (uint8*)&scache_state[unit].null_descriptor,
   1135                scache_state[unit].last_offset,
   1136                sizeof(scache_state[unit].null_descriptor));
   1137 
   1138     return SOC_E_NONE;
   1139 }
   1140 
   1141 
   1142 int
   1143 soc_scache_handle_lock(int unit, soc_scache_handle_t handle)
   1144 {
   1145     scache_handle_state_t *hs;
   1146 
   1147     SOC_IF_ERROR_RETURN(
   1148         scache_handle_state_find(scache_state[unit].head, handle, &hs));
   1149 
   1150     sal_mutex_take(hs->lock, sal_mutex_FOREVER);
   1151     hs->flags |= SCACHE_HANDLE_STATE_DIRTY;
   1152 
   1153     return SOC_E_NONE;
   1154 }
   1155 
   1156 int
   1157 soc_scache_handle_unlock(int unit, soc_scache_handle_t handle)
   1158 {
   1159     scache_handle_state_t *hs;
   1160 
   1161     SOC_IF_ERROR_RETURN(
   1162         scache_handle_state_find(scache_state[unit].head, handle, &hs));
   1163 
   1164     sal_mutex_give(hs->lock);
   1165     return SOC_E_NONE;
   1166 }
   1167 
   1168 int
   1169 soc_scache_module_max_alloc (int unit, uint8 **ptr, int *backup_size) {
   1170 #ifdef USE_SCACHE_DIRTY_BIT
   1171 
   1172     int size = 0;
   1173     scache_handle_state_t *current;
   1174 
   1175     if ((ptr == NULL) || (backup_size == NULL)) {
   1176         return SOC_E_PARAM;
   1177     }
   1178 
   1179     RETURN_IF_STABLE_NOT_CONFIGURED(unit);
   1180 
   1181     current = scache_state[unit].head;
   1182     if (current == NULL) {
   1183         return SOC_E_NOT_FOUND;
   1184     }
   1185     while (current) {
   1186         if (current->size > size) {
   1187             size = current->size;
   1188         }
   1189         current = current->next;
   1190     }
   1191 
   1192     *ptr = (size > 0) ? sal_alloc(size * SOC_SCACHE_MAX_ALLOC_MULTIPLIER, "max scache 0") : NULL;
   1193     if (*ptr == NULL) {
   1194         return SOC_E_MEMORY;
   1195     }
   1196     *backup_size = size * SOC_SCACHE_MAX_ALLOC_MULTIPLIER;
   1197 #endif /* USE_SCACHE_DIRTY_BIT */
   1198     return SOC_E_NONE;
   1199 }
   1200 
   1201 int
   1202 soc_scache_module_dirty_set (int unit, int module, uint8 **ptr,
   1203                                     int min_part, int max_part) {
   1204 
   1205 #ifdef USE_SCACHE_DIRTY_BIT
   1206     soc_scache_handle_t scache_handle;
   1207     scache_handle_state_t *hs;
   1208     uint8* scache_ptr = *ptr;
   1209     int i;
   1210 
   1211     if (scache_ptr == NULL) {
   1212         return SOC_E_PARAM;
   1213     }
   1214 
   1215     for (i = min_part; i <= max_part; i++) {
   1216         SOC_SCACHE_HANDLE_SET(scache_handle, unit, module, i);
   1217         if (scache_handle_state_find(scache_state[unit].head, scache_handle, &hs)
   1218             != SOC_E_NONE) {
   1219             continue;
   1220         }
   1221         if (sal_memcmp(scache_ptr, hs->buf, hs->size) != 0) {
   1222             sal_mutex_take(hs->lock, sal_mutex_FOREVER);
   1223             hs->flags |= SCACHE_HANDLE_STATE_DIRTY;
   1224             sal_mutex_give(hs->lock);
   1225         }
   1226         scache_ptr += hs->size;
   1227     }
   1228 #endif
   1229     return SOC_E_NONE;
   1230 }
   1231 
   1232 int
   1233 soc_scache_module_data_backup (int unit, int module, uint8 **ptr,
   1234                                          int min_part, int max_part,int backup_size) {
   1235 
   1236 #ifdef USE_SCACHE_DIRTY_BIT
   1237     soc_scache_handle_t scache_handle;
   1238     scache_handle_state_t *hs;
   1239     uint8* scache_ptr = *ptr;
   1240     int i;
   1241 
   1242     if (scache_ptr == NULL) {
   1243         return SOC_E_PARAM;
   1244     }
   1245 
   1246     sal_memset(scache_ptr, 0, backup_size);
   1247 
   1248     for (i = min_part; i <= max_part; i++) {
   1249         SOC_SCACHE_HANDLE_SET(scache_handle, unit, module, i);
   1250         if (scache_handle_state_find(scache_state[unit].head, scache_handle, &hs)
   1251             == SOC_E_NONE) {
   1252             sal_memcpy(scache_ptr, hs->buf, hs->size);
   1253             scache_ptr += hs->size;
   1254         }
   1255     }
   1256 #endif
   1257     return SOC_E_NONE;
   1258 }
   1259 
   1260 int
   1261 soc_scache_handle_used_set(int unit, soc_scache_handle_t handle, uint32 arg)
   1262 {
   1263     scache_handle_state_t *hs;
   1264 
   1265     SOC_IF_ERROR_RETURN(
   1266         scache_handle_state_find(scache_state[unit].head, handle, &hs));
   1267 
   1268     hs->used = arg;
   1269     return SOC_E_NONE;
   1270 }
   1271 
   1272 int
   1273 soc_scache_handle_used_get(int unit, soc_scache_handle_t handle, uint32 *arg)
   1274 {
   1275     scache_handle_state_t *hs;
   1276 
   1277     SOC_IF_ERROR_RETURN(
   1278         scache_handle_state_find(scache_state[unit].head, handle, &hs));
   1279 
   1280     *arg = hs->used;
   1281     return SOC_E_NONE;
   1282 }
   1283 
   1284 
   1285 int
   1286 soc_stable_set(int unit, int arg, uint32 flags)
   1287 {
   1288     soc_stable_t    *stable;
   1289 
   1290     if (!SOC_UNIT_NUM_VALID(unit)) {
   1291         return SOC_E_UNIT;
   1292     }
   1293     stable = SOC_STABLE(unit);
   1294 
   1295     if (flags) {
   1296         /* flags are not supported as
   1297            BCM_SWITCH_STABLE_DEVICE_NEXT_HOP is
   1298            not supported starting from SDK-6.5.8
   1299        */
   1300         return SOC_E_PARAM;
   1301     }
   1302     stable->flags = flags;
   1303 
   1304     /* upgrade: move to specific impls */
   1305     switch (arg) {
   1306     case _SHR_SWITCH_STABLE_DEVICE_NEXT_HOP:
   1307         LOG_DEBUG(BSL_LS_SOC_COMMON,
   1308              (BSL_META_U(unit,
   1309                "The stable location BCM_SWITCH_STABLE_DEVICE_NEXT_HOP "
   1310                "is not supported.\r\n")));
   1311         return SOC_E_PARAM;
   1312     case _SHR_SWITCH_STABLE_NONE:
   1313     case _SHR_SWITCH_STABLE_DEVICE_EXT_MEM:
   1314     case _SHR_SWITCH_STABLE_APPLICATION:
   1315     case _SHR_SWITCH_STABLE_SHARED_MEM:
   1316         stable->location = arg;
   1317         break;
   1318     default:
   1319         return SOC_E_PARAM;
   1320     }
   1321     return SOC_E_NONE;
   1322 }
   1323 
   1324 int
   1325 soc_stable_get(int unit, int *arg, uint32 *flags)
   1326 {
   1327     soc_stable_t    *stable;
   1328 
   1329     if (!SOC_UNIT_NUM_VALID(unit)) {
   1330         return SOC_E_UNIT;
   1331     }
   1332     stable = SOC_STABLE(unit);
   1333 
   1334     *arg = stable->location;
   1335     *flags = stable->flags;
   1336     return SOC_E_NONE;
   1337 }
   1338 
   1339 /* 
   1340  * only update the size without re-init of the stable
   1341  */
   1342 int
   1343 soc_stable_size_update(int unit, int arg)
   1344 {
   1345     soc_stable_t    *stable;
   1346 
   1347     if (!SOC_UNIT_NUM_VALID(unit)) {
   1348         return SOC_E_UNIT;
   1349     }
   1350 
   1351     if (arg < 0) {
   1352         return SOC_E_PARAM;
   1353     }
   1354     stable = SOC_STABLE(unit);
   1355 
   1356     stable->size = arg;
   1357 
   1358     return SOC_E_NONE;
   1359 }
   1360     
   1361 
   1362 int
   1363 soc_stable_size_set(int unit, int arg)
   1364 {
   1365         soc_stable_t    *stable;
   1366 
   1367         if (!SOC_UNIT_NUM_VALID(unit)) {
   1368             return SOC_E_UNIT;
   1369         }
   1370 
   1371         if (arg < 0) {
   1372             return SOC_E_PARAM;
   1373         }
   1374         stable = SOC_STABLE(unit);
   1375 
   1376         stable->size = arg;
   1377 
   1378     if (0 == stable->size) {
   1379         /* Deallocate existing stable storage */
   1380         soc_scache_detach(unit);
   1381         return SOC_E_NONE;
   1382     }
   1383 
   1384     if (stable->location == _SHR_SWITCH_STABLE_DEVICE_NEXT_HOP) {
   1385         LOG_DEBUG(BSL_LS_SOC_COMMON,
   1386              (BSL_META_U(unit,
   1387                "The stable location BCM_SWITCH_STABLE_DEVICE_NEXT_HOP "
   1388                "is not supported.\r\n")));
   1389         return SOC_E_PARAM;
   1390     }
   1391 
   1392     SOC_IF_ERROR_RETURN(soc_scache_init(unit, stable->size, 0));
   1393 
   1394     return SOC_E_NONE;
   1395 }
   1396 
   1397 int
   1398 soc_stable_size_get(int unit, int *arg)
   1399 {
   1400     soc_stable_t    *stable;
   1401 
   1402     if (!SOC_UNIT_NUM_VALID(unit)) {
   1403         return SOC_E_UNIT;
   1404     }
   1405     stable = SOC_STABLE(unit);
   1406 
   1407     *arg = stable->size;
   1408 
   1409     return SOC_E_NONE;
   1410 }
   1411 
   1412 int
   1413 soc_stable_used_get(int unit, int *arg)
   1414 {
   1415     soc_stable_t    *stable;
   1416 
   1417     if (!SOC_UNIT_NUM_VALID(unit)) {
   1418         return SOC_E_UNIT;
   1419     }
   1420     stable = SOC_STABLE(unit);
   1421 
   1422     *arg = stable->used;
   1423     return SOC_E_NONE;
   1424 }
   1425 
   1426 
   1427 /* upgrade: temporary  - shd be removed when scache upgrade is complete */
   1428 int
   1429 soc_stable_tmp_access(int unit, soc_stable_field_t field, 
   1430                       uint32 *val, int get)
   1431 {
   1432 #ifdef SCACHE_PHASE1_UPGRADE_COMPLETE
   1433     return SOC_E_UNAVAIL;
   1434 #else
   1435     if (!SOC_UNIT_NUM_VALID(unit)) {
   1436         return SOC_E_UNIT;
   1437     }
   1438 
   1439     switch (field) {
   1440     case sf_index_min:
   1441         if (get) { *val = SOC_STABLE(unit)->index_min; }
   1442         else     { SOC_STABLE(unit)->index_min = *val; }
   1443         break;
   1444     case sf_index_max:
   1445         if (get) { *val = SOC_STABLE(unit)->index_max; }
   1446         else     { SOC_STABLE(unit)->index_max = *val; }
   1447         break;
   1448     default:
   1449         return SOC_E_PARAM;
   1450     }
   1451 #endif /* SCACHE_PHASE1_UPGRADE_COMPLETE */
   1452 
   1453     return SOC_E_NONE;
   1454 }
   1455 
   1456 
   1457 /* upgrade: temporary  - shd be removed when scache upgrade is complete */
   1458 int
   1459 soc_stable_tmp_flags_get(int unit)
   1460 {
   1461     if (!SOC_UNIT_NUM_VALID(unit)) {
   1462         return 0;
   1463     }
   1464     return SOC_STABLE(unit)->flags;
   1465 }
   1466 
   1467 /* default allocator */
   1468 void*
   1469 soc_scache_defl_alloc(uint32 sz)
   1470 {
   1471     return sal_alloc(sz, "wb handle");
   1472 }
   1473 
   1474 void
   1475 soc_scache_defl_free(void *p)
   1476 {
   1477     sal_free(p);
   1478 }
   1479 
   1480 /* default dnx allocator */
   1481 /* those defaults are different in order to exclude changing the allocation and free
   1482  *  counters as a result of scache default alloc and free functions */
   1483 void*
   1484 soc_scache_defl_dnx_alloc(uint32 sz)
   1485 {
   1486     sal_set_alloc_counters_offset(sz, 0);
   1487     sal_set_alloc_counters_offset_main_thr(sz, 0);
   1488     return sal_alloc(sz, "wb handle");
   1489 }
   1490 
   1491 void
   1492 soc_scache_defl_dnx_free(void *p)
   1493 {
   1494     unsigned long alloc_bytes_count;
   1495     unsigned long free_bytes_count_before;
   1496     unsigned long free_bytes_count_after;
   1497 
   1498     sal_get_alloc_counters(&alloc_bytes_count, &free_bytes_count_before);
   1499     sal_free(p);
   1500 
   1501     sal_get_alloc_counters(&alloc_bytes_count, &free_bytes_count_after);
   1502     sal_set_alloc_counters_offset(0, free_bytes_count_after - free_bytes_count_before);
   1503     sal_set_alloc_counters_offset_main_thr(0, free_bytes_count_after - free_bytes_count_before);
   1504 }
   1505 
   1506 
   1507 int 
   1508 soc_switch_stable_register(int unit, soc_read_func_t rf, 
   1509                            soc_write_func_t wf,
   1510                            soc_alloc_func_t alloc_f,
   1511                            soc_free_func_t free_f)
   1512 {
   1513 
   1514     soc_stable_t    *stable;
   1515 
   1516     if (!SOC_UNIT_NUM_VALID(unit)) {
   1517         return SOC_E_UNIT;
   1518     }
   1519 
   1520     if ((NULL == rf) || (NULL == wf)) {
   1521         return SOC_E_PARAM;
   1522     }
   1523 
   1524     stable = SOC_STABLE(unit);
   1525     stable->rf = rf;
   1526     stable->wf = wf;
   1527     stable->alloc_f = alloc_f ? alloc_f : (SOC_IS_DNX(unit)? soc_scache_defl_dnx_alloc : soc_scache_defl_alloc);
   1528     stable->free_f  = free_f ? free_f : (SOC_IS_DNX(unit)? soc_scache_defl_dnx_free : soc_scache_defl_free);
   1529 
   1530     return SOC_E_NONE;
   1531 }
   1532 
   1533 int
   1534 soc_versioned_scache_ptr_get(int unit, soc_scache_handle_t handle, int create,
   1535                              uint32 *size, uint8 **scache_ptr, 
   1536                              uint16 default_ver, uint16 *recovered_ver)
   1537 {
   1538     int stable_size, stable_used, alloc_size, rv, allocated = FALSE;
   1539     uint32 alloc_get = 0;
   1540     uint32 align_size = 0;
   1541     uint16 version = default_ver;
   1542 
   1543     if (NULL == scache_ptr) {
   1544         return SOC_E_PARAM;
   1545     }
   1546 
   1547     align_size = *size;
   1548     SOC_SCACHE_ALIGN_SIZE(align_size);
   1549 
   1550     /* Individual BCM module implementations are version-aware. The 
   1551      * default_ver is the latest version that the module is aware of.
   1552      * Each module should be able to understand versions <= default_ver.
   1553      * The actual recovered_ver is returned to the calling module during
   1554      * warm boot initialization. The individual module needs to parse its
   1555      * scache based on the recovered_ver.
   1556      */
   1557     alloc_size = align_size + SOC_WB_SCACHE_CONTROL_SIZE;
   1558 #if defined(SCACHE_SHMEM_SUPPORT)
   1559     /* make sure that the alloc_size is multiplication of 8 */
   1560     alloc_size = ((alloc_size + 7) >> 3) << 3;
   1561 #endif
   1562 
   1563     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1564     SOC_IF_ERROR_RETURN(soc_stable_used_get(unit, &stable_used));
   1565     rv = soc_scache_ptr_get(unit, handle, scache_ptr,&alloc_get);
   1566 
   1567     /* In warm boot state, a failure means that
   1568      * the warmboot file does not contain this
   1569      * module, or the warmboot state does not exist.
   1570      * in this case, abort
   1571      */
   1572 
   1573     if (SOC_WARM_BOOT(unit) && SOC_FAILURE(rv)) {
   1574         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1575                     (BSL_META_U(unit,
   1576                                 "Failed to obtaine scache pointer for handle %x, unit %d\n"),
   1577                      handle, unit));
   1578 
   1579         return SOC_E_CONFIG;
   1580     }
   1581 
   1582     if (create) {
   1583       if ((stable_size - stable_used) >= (int)(alloc_size - alloc_get)) {
   1584         if (SOC_E_NOT_FOUND == rv) {
   1585             SOC_IF_ERROR_RETURN
   1586                 (soc_scache_alloc(unit, handle, alloc_size));
   1587             rv = soc_scache_ptr_get(unit, handle, scache_ptr,
   1588                                     &alloc_get);
   1589             allocated = TRUE;
   1590 	    LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1591                         (BSL_META_U(unit,
   1592                                     "Allocated raw scache pointer=%p, %d bytes\n"),
   1593                          scache_ptr, alloc_get));
   1594         } else {
   1595             /* If alloc_size differs from alloc_get, then
   1596              * we need to realloc */
   1597             if ((alloc_size - alloc_get) != 0) {
   1598                 SOC_IF_ERROR_RETURN
   1599                     (soc_scache_realloc(unit, handle, (alloc_size - alloc_get)));
   1600                 rv = soc_scache_ptr_get(unit, handle, scache_ptr, &alloc_get);
   1601                 allocated = TRUE;
   1602                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1603                             (BSL_META_U(unit,
   1604                                         "Re-allocated raw scache pointer=%p, %d bytes\n"),
   1605                              scache_ptr, alloc_get));
   1606             }
   1607         }
   1608         if (SOC_FAILURE(rv)) {
   1609             return rv;
   1610         } else if ((0 != align_size) && (alloc_get != alloc_size) &&
   1611                    !SOC_WARM_BOOT(unit)) {
   1612             /* Expected size doesn't match retrieved size */
   1613             return SOC_E_INTERNAL;
   1614         } else if (NULL == *scache_ptr) {
   1615             return SOC_E_MEMORY;
   1616         }
   1617         if (allocated) {
   1618             /* Newly allocated, set up version info */
   1619             sal_memcpy(*scache_ptr, &version, sizeof(uint16));
   1620         }
   1621       } else {
   1622         return SOC_E_NOT_FOUND;
   1623       }
   1624     }
   1625 
   1626     if (SOC_WARM_BOOT(unit)) {
   1627         /* Warm Boot recovery, verify the correct version */
   1628         sal_memcpy(&version, *scache_ptr, sizeof(uint16));
   1629         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1630                     (BSL_META_U(unit,
   1631                                 "Obtained scache pointer=%p, %d bytes, "
   1632                                 "version=%d.%d\n"),
   1633                      scache_ptr, alloc_get,
   1634                      SOC_SCACHE_VERSION_MAJOR(version),
   1635                      SOC_SCACHE_VERSION_MINOR(version)));
   1636         
   1637         if (version > default_ver) {
   1638             LOG_ERROR(BSL_LS_SOC_COMMON,
   1639                       (BSL_META_U(unit,
   1640                                   "Downgrade detected.  "
   1641                                   "Current version=%d.%d  found %d.%d\n"),
   1642                        SOC_SCACHE_VERSION_MAJOR(default_ver),
   1643                        SOC_SCACHE_VERSION_MINOR(default_ver),
   1644                        SOC_SCACHE_VERSION_MAJOR(version),
   1645                        SOC_SCACHE_VERSION_MINOR(version)));
   1646             /* Notify the application with an event */
   1647             /* The application will then need to reconcile the 
   1648                version differences using the documented behavioral
   1649                differences on per module (handle) basis */
   1650             SOC_IF_ERROR_RETURN
   1651                 (soc_event_generate(unit, 
   1652                                     SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 
   1653                                     handle, version, default_ver));
   1654             rv = SOC_E_NONE;
   1655             
   1656         } else if (version < default_ver) {
   1657             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1658                         (BSL_META_U(unit,
   1659                                     "Upgrade scenario supported.  "
   1660                                     "Current version=%d.%d  found %d.%d\n"),
   1661                          SOC_SCACHE_VERSION_MAJOR(default_ver),
   1662                          SOC_SCACHE_VERSION_MINOR(default_ver),
   1663                          SOC_SCACHE_VERSION_MAJOR(version),
   1664                          SOC_SCACHE_VERSION_MINOR(version)));
   1665             rv = SOC_E_NONE;
   1666         } 
   1667         if (recovered_ver) {
   1668             /* Modules that support multiple versions will suppy a pointer
   1669              * to the recovered_ver. Others will not care */
   1670             *recovered_ver = version;
   1671         }
   1672     }    
   1673 
   1674     /* Advance over scache control info */
   1675     *scache_ptr += SOC_WB_SCACHE_CONTROL_SIZE;
   1676     return rv;
   1677 }
   1678 
   1679 int
   1680 soc_extended_scache_ptr_get(int unit,
   1681                             soc_scache_handle_t handle,
   1682                             int create,
   1683                             uint32 size,
   1684                             uint8 **scache_ptr)
   1685 {
   1686     int stable_size, stable_used, alloc_size, rv;
   1687     uint32 alloc_get = 0;
   1688 
   1689     if (NULL == scache_ptr) {
   1690         return SOC_E_PARAM;
   1691     }
   1692 
   1693     alloc_size = size;
   1694 
   1695     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1696     SOC_IF_ERROR_RETURN(soc_stable_used_get(unit, &stable_used));
   1697 
   1698     rv = soc_scache_ptr_get(unit, handle, scache_ptr, &alloc_get);
   1699     if ((SOC_E_NOT_FOUND == rv) &&
   1700         create && (alloc_size > (stable_size - stable_used))) {
   1701         /* scache out of space - requested scache chunk
   1702          * is greater than available scache space  */
   1703         if (stable_size > 0) {
   1704             LOG_ERROR(BSL_LS_SOC_COMMON,
   1705                       (BSL_META_U(unit,
   1706                                   "Scache out of space."
   1707                                    "max=%d bytes, used=%d bytes, alloc_size=%d bytes\n "),
   1708                        stable_size, stable_used, alloc_size ));
   1709             return SOC_E_RESOURCE;
   1710         } else { /* level 1 recovery */
   1711             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1712                         (BSL_META_U(unit,
   1713                                     "Scache not found...Level 1 recovery\n")));
   1714             return SOC_E_NOT_FOUND;
   1715         }
   1716     } else {
   1717         if (create) {
   1718             if (SOC_E_NOT_FOUND == rv) {
   1719                 SOC_IF_ERROR_RETURN
   1720                     (soc_scache_alloc(unit, handle, alloc_size));
   1721             } else if (alloc_size != alloc_get) {
   1722                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1723                             (BSL_META_U(unit,
   1724                                         "Reallocating %d bytes of scache space\n"),
   1725                              (alloc_size - alloc_get)));
   1726                 SOC_IF_ERROR_RETURN
   1727                    (soc_scache_realloc(unit, handle, (alloc_size - alloc_get)));
   1728             }
   1729             rv = soc_scache_ptr_get(unit, handle, scache_ptr, &alloc_get);
   1730             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1731                         (BSL_META_U(unit,
   1732                                     "Allocated raw scache pointer=%p, %d bytes\n"),
   1733                          scache_ptr, alloc_size));
   1734         }
   1735         if (SOC_FAILURE(rv)) {
   1736             return rv;
   1737         } else if ((0 != size) && (alloc_get != alloc_size) &&
   1738                    !SOC_WARM_BOOT(unit) && (!create)) {
   1739             /* Expected size doesn't match retrieved size.
   1740              * This is expected during 'sync' operation
   1741              * during SDK downgrade */
   1742             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1743                         (BSL_META_U(unit,
   1744                                     "Reallocating %d bytes of scache space\n"),
   1745                          (alloc_size - alloc_get)));
   1746             SOC_IF_ERROR_RETURN
   1747                 (soc_scache_realloc(unit, handle, (alloc_size - alloc_get)));
   1748             rv = soc_scache_ptr_get(unit, handle, scache_ptr, &alloc_get);
   1749             if (SOC_FAILURE(rv)) {
   1750                 return rv;
   1751             }
   1752         } else if (NULL == *scache_ptr) {
   1753             return SOC_E_MEMORY;
   1754         }
   1755     }
   1756 
   1757     return SOC_E_NONE;
   1758 }
   1759 
   1760 #if defined(SCACHE_SHMEM_SUPPORT)
   1761 uint8 
   1762 soc_scache_is_shmem(int unit)
   1763 {
   1764     return SCACHE_IS_SHMEM(unit);
   1765 }
   1766 #endif
   1767 
   1768 #else /* BCM_WARM_BOOT_SUPPORT */
   1769 int _scache_not_empty;
   1770 #endif
   1771