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

wb_engine.c (90554B)


      1 /*
      2 
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 #include <shared/bsl.h>
      9 
     10 #include <soc/types.h>
     11 #include <soc/error.h>
     12 #include <soc/scache.h>
     13 #include <soc/drv.h>
     14 #include <soc/wb_engine.h>
     15 #include <sal/appl/io.h>
     16 #include <shared/alloc.h>
     17 
     18 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
     19 #include <soc/dnxc/swstate/auto_generated/access/wb_engine_access.h>
     20 #endif
     21 
     22 #include <soc/dnxc/multithread_analyzer.h>
     23 
     24 #ifdef CRASH_RECOVERY_SUPPORT
     25 #include <soc/dcmn/dcmn_crash_recovery.h>
     26 #ifdef BCM_PETRA_SUPPORT
     27 #include <shared/swstate/access/sw_state_access.h>
     28 #endif /* BCM_PETRA_SUPPORT */
     29 extern soc_dcmn_cr_t *dcmn_cr_info[SOC_MAX_NUM_DEVICES];
     30 #endif
     31 
     32 
     33 
     34 #ifdef _ERR_MSG_MODULE_NAME 
     35     #error "_ERR_MSG_MODULE_NAME redefined" 
     36 #endif
     37 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_INIT
     38 
     39 #ifdef CRASH_RECOVERY_SUPPORT
     40 #define CRASH_RECOVERY_INVALIDATE(unit) \
     41     soc_dcmn_cr_suppress(unit, dcmn_cr_no_support_legacy_wb)
     42 #else
     43 #define CRASH_RECOVERY_INVALIDATE(unit)
     44 #endif
     45 
     46 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
     47 #define WB_ENGINE_EXIT_IF_DNX(unit)\
     48     if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {\
     49         return SOC_E_NONE;\
     50     }
     51 #define WB_ENGINE_ERROR_IF_DNX(unit)\
     52     if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {\
     53         return SOC_E_INTERNAL;\
     54     }
     55 #else
     56 #define WB_ENGINE_EXIT_IF_DNX(unit)
     57 #define WB_ENGINE_ERROR_IF_DNX(unit)
     58 #endif
     59 
     60 #define SOC_WB_ENGINE_VARS_INFO(unit, engine_id)                  (soc_wb_engine_var_info[unit][engine_id])
     61 #define SOC_WB_ENGINE_BUFFERS_INFO(unit, engine_id)               (soc_wb_engine_buffer_info[unit][engine_id])
     62 #define SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, buffer_id)    &(soc_wb_engine_buffer_info[unit][engine_id][buffer_id])
     63 #define SOC_WB_ENGINE_VAR_INFO(unit, engine_id, var_id)          &(soc_wb_engine_var_info[unit][engine_id][var_id])
     64 
     65 static soc_wb_engine_var_info_t *soc_wb_engine_var_info[SOC_MAX_NUM_DEVICES][SOC_WB_ENGINE_NOF];
     66 
     67 /* buffers and variable tables*/
     68 static soc_wb_engine_buffer_info_t *soc_wb_engine_buffer_info[SOC_MAX_NUM_DEVICES][SOC_WB_ENGINE_NOF];
     69 
     70 
     71 static uint32 soc_wb_engine_nof_buffers[SOC_MAX_NUM_DEVICES][SOC_WB_ENGINE_NOF];
     72 static uint32 soc_wb_engine_nof_vars[SOC_MAX_NUM_DEVICES][SOC_WB_ENGINE_NOF];
     73 
     74 #ifdef BCM_WARM_BOOT_SUPPORT
     75 #define SOC_WB_ENGINE_SCACHE_HANDLE_SET(_wb_handle, _unit, _engine_id, _buffer_name)\
     76     SOC_SCACHE_HANDLE_SET(_wb_handle, _unit, SOC_MODULE_WB_ENGINE_BASE + _engine_id, _buffer_name)
     77 #else
     78 #define SOC_WB_ENGINE_SCACHE_HANDLE_SET(_wb_handle, _unit, _engine_id, _buffer_name)
     79 #endif /*BCM_WARM_BOOT_SUPPORT*/
     80 
     81 #ifdef BCM_WARM_BOOT_SUPPORT
     82 #define SOC_WB_ENGINE_UNIT_DIRTY_BIT_SET(unit)                   \
     83                      SOC_CONTROL_LOCK(unit);                     \
     84                      SOC_CONTROL(unit)->scache_dirty = 1;        \
     85                      SOC_CONTROL_UNLOCK(unit);
     86 
     87 #define SOC_WB_ENGINE_UNIT_DIRTY_BIT_UNSET(unit)                 \
     88                      SOC_CONTROL_LOCK(unit);                     \
     89                      SOC_CONTROL(unit)->scache_dirty = 0;        \
     90                      SOC_CONTROL_UNLOCK(unit);
     91 
     92 #define SOC_WB_ENGINE_IS_AUTOSYNC(unit)                          \
     93                      (SOC_CONTROL(unit)->autosync)
     94 
     95 static int soc_wb_engine_update(int unit, int engine_id, uint32 var_id, uint32 outer_ndx, uint32 inner_ndx, int update_length);
     96 #else /* BCM_WARM_BOOT_SUPPORT */
     97 #define SOC_WB_ENGINE_UNIT_DIRTY_BIT_SET(unit)
     98 #define SOC_WB_ENGINE_UNIT_DIRTY_BIT_UNSET(unit)
     99 #define SOC_WB_ENGINE_IS_AUTOSYNC(unit) (0x0)
    100 #endif /* BCM_WARM_BOOT_SUPPORT */
    101 
    102 #ifdef VALGRIND_DEBUG
    103 /* This is used to force the generation of code (machine instructions) for assignments to this variable. */
    104 /* Specifically we want to avoid the situation where the compiler decides to optimize out the assignment. */
    105 static int _wb_engine_valgrind_init_check_var = 0;
    106 
    107 /* May be used for debugging VALGRIND errors. */
    108 /* When enabled this code "uses" all the contents of var. */
    109 /* "Uses" in this context means doing a branch depending on the contents of var. */
    110 /* This is done to allow Valgrind to throw an error when uninitialized memory is written */
    111 /* into a warmboot variable. */
    112 /* If you have a Valgrind error here, then you are probably writing uninitialized memory to a warmboot array/variable. */
    113 STATIC void _wb_engine_valgrind_check_array_is_initialized_in_set(const void *arr, uint32 len)
    114 {
    115   int i;
    116   const uint8 *src = arr;
    117 
    118   for (i = 0; i < len; i++) {
    119     int byte = src[i];
    120     if (byte) {
    121       _wb_engine_valgrind_init_check_var = byte;
    122     } else {
    123       _wb_engine_valgrind_init_check_var = byte - 1;
    124     }
    125   }
    126 }
    127 #else /* VALGRIND_DEBUG */
    128 #define _wb_engine_valgrind_check_array_is_initialized_in_set(arr, len) ((void)0)
    129 #endif /* VALGRIND_DEBUG */
    130 
    131 typedef struct wb_engine_var_info_chunk_s {
    132     char   name[128];
    133     uint32  nof_items_in_array;
    134     uint32  data_size;
    135 } wb_engine_var_info_chunk_t;
    136 
    137 typedef struct wb_engine_vars_info_header_s {
    138     uint32 nof_vars;
    139     char  buffer_name[128];
    140 } wb_engine_vars_info_header_t;
    141 
    142 STATIC int
    143 _wb_engine_var_index_search(int unit, int engine_id, int buffer_id, int *var_ndx);
    144 
    145 int
    146 soc_wb_engine_add_buff(int unit, int engine_id, int buff_idx, soc_wb_engine_buffer_info_t buffer)
    147 {
    148     if(!soc_wb_engine_buffer_info[unit][engine_id]) 
    149     {
    150         LOG_ERROR(BSL_LS_SOC_COMMON,
    151                   (BSL_META_U(unit,
    152                               "engine_id:%d wb engine buffer table is not initialized\n"),
    153                    engine_id));
    154         return SOC_E_RESOURCE;
    155     }
    156     soc_wb_engine_buffer_info[unit][engine_id][buff_idx] = buffer;
    157     return SOC_E_NONE;
    158 }
    159 
    160 
    161 int
    162 soc_wb_engine_add_var(int unit, int engine_id, int var_idx, soc_wb_engine_var_info_t var)
    163 {
    164     soc_wb_engine_var_info_t *variables;
    165     soc_wb_engine_buffer_info_t *buffer;
    166     uint32 data_size;
    167     uint32 outer_arr_length;
    168     uint32 inner_arr_length;
    169 
    170     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
    171     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id,var.buffer);
    172 
    173     /* mixing of dynamic and non-dynamic componnents is not allowed,
    174        dynamic buffers should be used to hold dynamic vars */
    175     if ((var.is_dynamic && !buffer->is_dynamic) ||
    176         (!var.is_dynamic && buffer->is_dynamic)) {
    177         LOG_ERROR(BSL_LS_SOC_COMMON,
    178                   (BSL_META_U(unit,
    179                               "var and buffer dont have same is_dynamic value (buffer %d var %d - %s)\n"),
    180                    var.buffer, var_idx, var.var_string));
    181         return SOC_E_INTERNAL;
    182     }
    183 
    184     if(!soc_wb_engine_var_info[unit][engine_id]) 
    185     {
    186         LOG_ERROR(BSL_LS_SOC_COMMON,
    187                   (BSL_META_U(unit,
    188                               "engine_id:%d wb engine variable table is not initialized\n"),
    189                    engine_id));
    190         return SOC_E_RESOURCE;
    191     }
    192 
    193     /* if values were dynamically comitted (e.g during init) dont override them*/
    194     if (variables[var_idx].init_done == SOC_WB_ENGINE_VAR_DYNAMIC_SIZE_UPDATED) {
    195         data_size        = variables[var_idx].data_size;
    196         outer_arr_length = variables[var_idx].outer_arr_length;
    197         inner_arr_length = variables[var_idx].inner_arr_length;
    198     }
    199     else {
    200         data_size        = var.data_size;
    201         outer_arr_length = var.outer_arr_length;
    202         inner_arr_length = var.inner_arr_length;
    203     }
    204 
    205     if (data_size == 0 && !var.is_dynamic) {
    206         /*size was supposed to be comitted dinamically but wasnt recieved*/
    207         LOG_ERROR(BSL_LS_SOC_COMMON,
    208                   (BSL_META_U(unit,
    209                               "engine id:%d wb variable %d - %s have size 0\n"),
    210                    engine_id, var_idx, var.var_string));
    211         return SOC_E_PARAM;
    212     }
    213 
    214     if (buffer->is_only_copy && var.data_orig!=NULL) {
    215         /*size was supposed to be comitted dinamically but wasnt recieved*/
    216         LOG_ERROR(BSL_LS_SOC_COMMON,
    217                   (BSL_META_U(unit,
    218                               "engine id:%d wb variable %d - %s: buffer %d is marked as the only original data and thus expect NULL pointer to external original data\n"),
    219                    engine_id, var_idx, var.var_string, var.buffer));
    220         return SOC_E_PARAM;
    221     }
    222 
    223     if (var.data_orig==NULL && !buffer->is_dynamic && !buffer->is_only_copy) {
    224         LOG_ERROR(BSL_LS_SOC_COMMON,
    225                   (BSL_META_U(unit,
    226                               "unit %d engine_id %d: data_orig is NULL while buffer is not dynamic and not holds the original data var #%d %s buffer %d\n"),
    227                    unit, engine_id, var_idx, var.var_string, var.buffer));
    228         return SOC_E_PARAM;
    229     } 
    230 
    231 
    232     variables[var_idx] = var;
    233     variables[var_idx].data_size = data_size;
    234     variables[var_idx].outer_arr_length = outer_arr_length;
    235     variables[var_idx].inner_arr_length = inner_arr_length;
    236     buffer->variable_num++;
    237 
    238     return SOC_E_NONE;
    239 }
    240 
    241 
    242 
    243 int
    244 soc_wb_engine_enable_dynamic_var(int unit, int engine_id, int var_idx, soc_wb_engine_dynamic_var_info_t var, uint8 *data_orig)
    245 {
    246     int rv = SOC_E_NONE;
    247     soc_wb_engine_var_info_t *variables;
    248 #ifdef BCM_WARM_BOOT_SUPPORT
    249     int var_ndx;
    250     int buff_id;
    251     soc_wb_engine_buffer_info_t *buffer;
    252     int is_dynamic_count = 0;
    253     int enabled_var_location = 0;
    254     wb_engine_vars_info_header_t *vars_info_header;
    255     soc_wb_engine_dynamic_var_info_t *dynamic_vars_header;
    256     soc_wb_engine_dynamic_var_info_t *dynamic_vars_header_copy;
    257     int header_size;
    258     int dynamic_vars_header_offset = 0;
    259 #endif
    260 
    261 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT)
    262     CRASH_RECOVERY_INVALIDATE(unit);
    263 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */
    264 
    265     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
    266 
    267 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    268     if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {
    269         LOG_ERROR(BSL_LS_SOC_COMMON,
    270                     (BSL_META_U(unit,
    271                               "wb_engine dynamic vars are not supported for dnx/dnxf devices")));
    272         return SOC_E_INTERNAL;
    273     }
    274 #endif
    275 
    276     if(!soc_wb_engine_var_info[unit][engine_id]) 
    277     {
    278         LOG_ERROR(BSL_LS_SOC_COMMON,
    279                   (BSL_META_U(unit,
    280                               "engine_id:%d wb engine variable table is not initialized\n"),
    281                    engine_id));
    282         return SOC_E_RESOURCE;
    283     }
    284 
    285     /* update relevant info */
    286     variables[var_idx].flags             = var.flags;
    287     variables[var_idx].data_size         = var.data_size;
    288     variables[var_idx].outer_arr_length  = var.outer_arr_length;
    289     variables[var_idx].inner_arr_length  = var.inner_arr_length;
    290     variables[var_idx].outer_arr_jump    = var.outer_arr_jump;
    291     variables[var_idx].inner_arr_jump    = var.inner_arr_jump;
    292     variables[var_idx].offset            = var.offset;
    293     variables[var_idx].is_enabled        = var.is_enabled;
    294 
    295     variables[var_idx].data_orig         = data_orig;
    296 
    297 #ifdef BCM_WARM_BOOT_SUPPORT
    298     buff_id = variables[var_idx].buffer;
    299     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, buff_id);
    300     vars_info_header = (wb_engine_vars_info_header_t *) buffer->scache_ptr;
    301     dynamic_vars_header_offset = sizeof(wb_engine_vars_info_header_t) + (sizeof(wb_engine_var_info_chunk_t)*vars_info_header->nof_vars);
    302 
    303     /* add enabled dynamic vars info at the beginnig of the buffer */
    304     for (var_ndx = 0; var_ndx < soc_wb_engine_nof_vars[unit][engine_id]; var_ndx++) {
    305         if (variables[var_ndx].buffer == buff_id && variables[var_ndx].is_dynamic == 1) {
    306             if (var_ndx == var_idx) {
    307                 /*the enabled var location in the buffer header */
    308                 enabled_var_location = is_dynamic_count;
    309             }
    310             is_dynamic_count++;
    311         }
    312     }
    313 
    314     header_size = sizeof(soc_wb_engine_dynamic_var_info_t) * is_dynamic_count;
    315     dynamic_vars_header_copy = sal_alloc(header_size,"warmboot - dynamic buffer header");
    316 
    317     /* copy the header from the buffer before dismising it in init_buffer */
    318     sal_memcpy(dynamic_vars_header_copy, buffer->scache_ptr + dynamic_vars_header_offset, header_size);
    319 
    320     rv = soc_wb_engine_init_buffer(unit, engine_id, buff_id, TRUE);
    321     if (SOC_FAILURE(rv)) {
    322         LOG_ERROR(BSL_LS_SOC_COMMON,
    323                   (BSL_META_U(unit,
    324                               "%s\n"), soc_errmsg(rv)));
    325         goto exit;
    326     }
    327 
    328     /* copy the header back to the new buffer and add newly enabled variable */
    329     dynamic_vars_header_copy[enabled_var_location] = var;
    330     sal_memcpy(buffer->scache_ptr + dynamic_vars_header_offset, dynamic_vars_header_copy, header_size);
    331 
    332     /*update the offsets in the header from new offsets in the table*/
    333     is_dynamic_count = 0;
    334     dynamic_vars_header = (soc_wb_engine_dynamic_var_info_t *) (buffer->scache_ptr + dynamic_vars_header_offset);
    335     for (var_ndx = 0; var_ndx < soc_wb_engine_nof_vars[unit][engine_id]; var_ndx++) {
    336         if (variables[var_ndx].buffer == buff_id && variables[var_ndx].is_dynamic == 1) {
    337             dynamic_vars_header[is_dynamic_count].offset = variables[var_ndx].offset;
    338             is_dynamic_count++;
    339         }
    340     }
    341 
    342     /*if in autosync mode flush the new buffer to file*/
    343     if (SOC_WB_ENGINE_IS_AUTOSYNC(unit)) {
    344         rv = soc_scache_commit(unit);
    345         if (SOC_FAILURE(rv)) {
    346             LOG_ERROR(BSL_LS_SOC_COMMON,
    347                       (BSL_META_U(unit,
    348                                   "%s\n"), soc_errmsg(rv)));
    349             goto exit;
    350         }
    351     }
    352 
    353 exit:
    354     sal_free(dynamic_vars_header_copy);
    355 #endif /*BCM_WARM_BOOT_SUPPORT*/
    356 
    357     return rv;
    358 }
    359 
    360 int
    361 soc_wb_engine_disable_dynamic_var(int unit, int engine_id, int var_idx)
    362 {
    363     soc_wb_engine_dynamic_var_info_t zeroed_var;
    364 
    365 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT)
    366     CRASH_RECOVERY_INVALIDATE(unit);
    367 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */
    368 
    369 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    370     if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {
    371         LOG_ERROR(BSL_LS_SOC_COMMON,
    372                     (BSL_META_U(unit,
    373                               "wb_engine dynamic vars are not supported for dnx/dnxf devices")));
    374         return SOC_E_INTERNAL;
    375     }
    376 #endif
    377 
    378     sal_memset(&zeroed_var, 0x0, sizeof(soc_wb_engine_dynamic_var_info_t));
    379 
    380     /* change the buffer accordingly */
    381     return soc_wb_engine_enable_dynamic_var(unit, engine_id, var_idx, zeroed_var, NULL);
    382 }
    383 
    384 
    385 
    386 
    387 /* set/get function to be used to read/write warmbootable data */
    388 int
    389 soc_wb_engine_array_set(int unit, int engine_id, int var_ndx, uint8 value)
    390 {
    391     soc_wb_engine_var_info_t    *variables;
    392     uint8                       *dst;
    393     soc_wb_engine_buffer_info_t *buffer;
    394 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    395     int                          rc = SOC_E_NONE;  
    396 #endif
    397 
    398 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT)
    399     CRASH_RECOVERY_INVALIDATE(unit);
    400 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */
    401 
    402     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
    403     if(variables == NULL) {
    404         LOG_ERROR(BSL_LS_SOC_COMMON,
    405                   (BSL_META_U(unit,
    406                               "engine_id:%d wb engine variable table is not initialized\n"),
    407                    engine_id));
    408         return SOC_E_RESOURCE;
    409     }
    410 
    411     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id,variables[var_ndx].buffer);
    412 
    413     if (!(variables[var_ndx].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
    414         LOG_ERROR(BSL_LS_SOC_COMMON,
    415                   (BSL_META_U(unit,
    416                               "engine_id:%d wb engine variable %d - is not initialized\n"),
    417                    engine_id, var_ndx));
    418         return SOC_E_INTERNAL;
    419     }
    420 
    421     if(var_ndx < 0 || var_ndx >= soc_wb_engine_nof_vars[unit][engine_id]) {
    422         LOG_ERROR(BSL_LS_SOC_COMMON,
    423                   (BSL_META_U(unit,
    424                               "engine_id:%d var_ndx %d is out of bound\n"),
    425                    engine_id, var_ndx));
    426         return SOC_E_PARAM;
    427     }
    428 
    429     /* verifiying it is an array */
    430     if (variables[var_ndx].inner_arr_length <= 1) {
    431         LOG_ERROR(BSL_LS_SOC_COMMON,
    432                   (BSL_META_U(unit,
    433                               "engine_id:%d function:soc_wb_engine_array_set wb engine variable %d - %s - has length <= 1\n"),
    434                    engine_id, var_ndx, variables[var_ndx].var_string));
    435         return SOC_E_INTERNAL;
    436     }
    437 
    438     /* verifiying it is an array */
    439     if (variables[var_ndx].outer_arr_length != 1) {
    440         LOG_ERROR(BSL_LS_SOC_COMMON,
    441                   (BSL_META_U(unit,
    442                               "engine_id:%d function:soc_wb_engine_array_set wb engine variable %d - %s - is not a valid 1d array\n"),
    443                    engine_id, var_ndx, variables[var_ndx].var_string));
    444         return SOC_E_INTERNAL;
    445     }
    446 
    447     /* check that the array is continuous (without any spaces) */
    448     if (variables[var_ndx].inner_arr_jump != variables[var_ndx].data_size) {
    449         LOG_ERROR(BSL_LS_SOC_COMMON,
    450                   (BSL_META_U(unit,
    451                               "engine_id:%d wb engine variable %d - %s - is expected to be a continous array\n"),
    452                    engine_id, var_ndx, variables[var_ndx].var_string));
    453         return SOC_E_INTERNAL;
    454     }
    455 
    456 
    457 
    458     /* if data_orig is NULL, data is stored only on scache */
    459     if (variables[var_ndx].data_orig) {
    460         dst = variables[var_ndx].data_orig;
    461     }
    462     else {
    463         dst = buffer->scache_ptr + variables[var_ndx].offset;
    464     }
    465 
    466     if (!SOC_IS_DNX(unit) && !SOC_IS_DNXF(unit)) {
    467         sal_memset(dst, value, variables[var_ndx].data_size * variables[var_ndx].inner_arr_length);
    468     }
    469 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    470     else {
    471         rc = sw_state_wb_engine.buffer.instance.memset(unit, engine_id, variables[var_ndx].buffer, variables[var_ndx].offset,
    472                                                         variables[var_ndx].data_size * variables[var_ndx].inner_arr_length, value);
    473         if (SOC_FAILURE(rc)) {
    474             LOG_ERROR(BSL_LS_SOC_COMMON,
    475                       (BSL_META_U(unit,
    476                                   "%s failed to memset wb engine var in sw state\n"), soc_errmsg(rc)));
    477             return rc;
    478         }
    479     }
    480 #endif
    481 
    482 #ifdef BCM_WARM_BOOT_SUPPORT
    483     return soc_wb_engine_update(unit, engine_id, var_ndx, 0, 0, variables[var_ndx].inner_arr_length);
    484 #else
    485     return SOC_E_NONE;
    486 #endif /* BCM_WARM_BOOT_SUPPORT */
    487 }
    488 
    489 
    490 /* set/get function to be used to read/write warmbootable data.
    491    set_get = 1 - Set
    492    set_get = 0 - Get
    493    */
    494 int
    495 soc_wb_engine_array_range_set_or_get(int unit, int engine_id, int var_ndx, uint32 arr_ndx, uint32 range_length, uint8 set_get, uint8 *external_arr)
    496 {
    497     soc_wb_engine_var_info_t *variables;
    498     uint8 *wb_arr;
    499     uint8 *dst;
    500     uint8 *src;
    501     soc_wb_engine_buffer_info_t *buffer;
    502 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    503     int rc = SOC_E_NONE;
    504 #endif
    505 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT)
    506     CRASH_RECOVERY_INVALIDATE(unit);
    507 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */
    508 
    509     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
    510         
    511     if(variables == NULL) {
    512         LOG_ERROR(BSL_LS_SOC_COMMON,
    513                   (BSL_META_U(unit,
    514                               "engine_id:%d wb engine variable table is not initialized\n"),
    515                    engine_id));
    516         return SOC_E_RESOURCE;
    517     }
    518 
    519     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id,variables[var_ndx].buffer);
    520 
    521     if (!(variables[var_ndx].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
    522         LOG_ERROR(BSL_LS_SOC_COMMON,
    523                   (BSL_META_U(unit,
    524                               "engine_id:%d wb engine variable %d is not initialized\n"),
    525                    engine_id, var_ndx));
    526         return SOC_E_INTERNAL;
    527     }
    528 
    529     if(var_ndx < 0 || var_ndx >= soc_wb_engine_nof_vars[unit][engine_id]) {
    530         LOG_ERROR(BSL_LS_SOC_COMMON,
    531                   (BSL_META_U(unit,
    532                               "engine_id:%d var_ndx %d is out of bound\n"),
    533                    engine_id, var_ndx));
    534         return SOC_E_PARAM;
    535     }
    536 
    537     /* verifiying it is an array */
    538     if (variables[var_ndx].inner_arr_length <= 1) {
    539         LOG_ERROR(BSL_LS_SOC_COMMON,
    540                   (BSL_META_U(unit,
    541                               "engine_id:%d wb engine variable %d - %s - has invalid array length (inner_arr_length <= 1)\n"),
    542                    engine_id, var_ndx, variables[var_ndx].var_string));
    543         return SOC_E_INTERNAL;
    544     }
    545 
    546     /* verifiying it is an array */
    547     if (variables[var_ndx].outer_arr_length != 1) {
    548         LOG_ERROR(BSL_LS_SOC_COMMON,
    549                   (BSL_META_U(unit,
    550                               "engine_id:%d wb engine variable %d - %s - has is not a valid 1d array\n"),
    551                    engine_id, var_ndx, variables[var_ndx].var_string));
    552         return SOC_E_INTERNAL;
    553     }
    554 
    555     /* check that the array is continuous (without any spaces) */
    556     if (variables[var_ndx].inner_arr_jump != variables[var_ndx].data_size) {
    557         LOG_ERROR(BSL_LS_SOC_COMMON,
    558                   (BSL_META_U(unit,
    559                               "engine_id:%d wb engine variable %d - %s - is expected to be a continous array\n"),
    560                    engine_id, var_ndx, variables[var_ndx].var_string));
    561         return SOC_E_INTERNAL;
    562     }
    563 
    564     /* prevent copying outisde of array limit */
    565     if (arr_ndx + range_length > variables[var_ndx].inner_arr_length) {
    566         LOG_ERROR(BSL_LS_SOC_COMMON,
    567                   (BSL_META_U(unit,
    568                               "engine_id:%d wb engine variable %d - %s - is trying to read outisde of array limit \n"),
    569                    engine_id, var_ndx, variables[var_ndx].var_string));
    570         return SOC_E_INTERNAL;
    571     }
    572 
    573     /* if data_orig is NULL, data is stored only on scache */
    574     if (variables[var_ndx].data_orig) {
    575         wb_arr = variables[var_ndx].data_orig + (arr_ndx * variables[var_ndx].data_size);
    576     }
    577     else {
    578         wb_arr = buffer->scache_ptr + variables[var_ndx].offset + (arr_ndx * variables[var_ndx].data_size);
    579     }
    580     
    581     src = (set_get) ? external_arr: wb_arr;
    582     dst = (set_get) ? wb_arr: external_arr;
    583 
    584     sal_memcpy(dst, src, variables[var_ndx].data_size * range_length);
    585 
    586     if (!SOC_IS_DNX(unit) && !SOC_IS_DNXF(unit)) {
    587         sal_memcpy(dst, src, variables[var_ndx].data_size * range_length);
    588     }
    589 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    590     else {
    591         if (set_get) {
    592             rc = sw_state_wb_engine.buffer.instance.memwrite(unit, engine_id, variables[var_ndx].buffer,
    593                                                              external_arr, /*src*/
    594                                                              variables[var_ndx].offset + (arr_ndx * variables[var_ndx].data_size) /*offset*/,
    595                                                              variables[var_ndx].data_size * range_length /*length*/);
    596         }
    597         else {
    598             rc = sw_state_wb_engine.buffer.instance.memread(unit, engine_id, variables[var_ndx].buffer,
    599                                                             external_arr, /*dst*/
    600                                                             variables[var_ndx].offset + (arr_ndx * variables[var_ndx].data_size) /*offset*/,
    601                                                             variables[var_ndx].data_size * range_length /*length*/);
    602         }
    603         if (SOC_FAILURE(rc)) {
    604             LOG_ERROR(BSL_LS_SOC_COMMON,
    605                       (BSL_META_U(unit,
    606                                   "%s failed to read or write wb engine array range in sw state\n"), soc_errmsg(rc)));
    607             return rc;
    608         }
    609     }
    610 #endif
    611 
    612     /* If calling get functionality, we're done. */
    613     if (!set_get) {
    614         return SOC_E_NONE;
    615     }
    616 
    617     /* Uninitialized data check for valgrind. */
    618     _wb_engine_valgrind_check_array_is_initialized_in_set(src, variables[var_ndx].data_size);
    619 
    620 #ifdef BCM_WARM_BOOT_SUPPORT
    621     return soc_wb_engine_update(unit, engine_id, var_ndx, 0, arr_ndx, range_length);
    622 #else
    623     return SOC_E_NONE;
    624 #endif /* BCM_WARM_BOOT_SUPPORT */
    625 }
    626 
    627 
    628 
    629 
    630 
    631 /* set/get function to be used to read/write warmbootable data */
    632 int
    633 soc_wb_engine_var_set(int unit, int engine_id, int var_ndx, uint32 outer_arr_ndx, uint32 inner_arr_ndx, CONST uint8 *var)
    634 {
    635     soc_wb_engine_var_info_t *variables;
    636     uint8 *dst;
    637     CONST uint8 *src;
    638     soc_wb_engine_buffer_info_t *buffer;
    639     uint32 offset;
    640 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    641     int rc = SOC_E_NONE;
    642 #endif
    643     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_WB_ENGINE, var_ndx, TRUE));
    644 
    645     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
    646 
    647 #if defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT)
    648     CRASH_RECOVERY_INVALIDATE(unit);
    649 #endif /* defined(BCM_PETRA_SUPPORT) || defined (BCM_DFE_SUPPORT) */
    650 
    651     if(variables == NULL) {
    652         LOG_ERROR(BSL_LS_SOC_COMMON,
    653                   (BSL_META_U(unit,
    654                               "wb engine variable table is not initialized\n")));
    655         /* using assert as legacy code may not check return value */
    656         assert(0);
    657         return SOC_E_RESOURCE;
    658     }
    659 
    660     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id,variables[var_ndx].buffer);
    661 
    662     if(var_ndx < 0 || var_ndx >= soc_wb_engine_nof_vars[unit][engine_id]) {
    663         LOG_ERROR(BSL_LS_SOC_COMMON,
    664                   (BSL_META_U(unit,
    665                               "engine_id:%d var_ndx %d is out of bound\n"),
    666                    engine_id, var_ndx));
    667         /* using assert as legacy code may not check return value */
    668         assert(0);
    669         return SOC_E_PARAM;
    670     }
    671 
    672     if (!(variables[var_ndx].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
    673         LOG_ERROR(BSL_LS_SOC_COMMON,
    674                   (BSL_META_U(unit,
    675                               "wb engine variable %d was not initialized\n"),
    676                    var_ndx));
    677         /* using assert as legacy code may not check return value */
    678         assert(0);
    679         return SOC_E_INTERNAL;
    680     }
    681 
    682     /* if variable is a dynamic variable but was not enabled */
    683     if (variables[var_ndx].is_dynamic && (!variables[var_ndx].is_enabled)) {
    684         LOG_ERROR(BSL_LS_SOC_COMMON,
    685                   (BSL_META_U(unit,
    686                               "wb engine variable %d (%s) is a dynamic variable that wasn't initialized\n"),
    687                    var_ndx, variables[var_ndx].var_string));
    688         /* using assert as legacy code may not check return value */
    689         assert(0);
    690         return SOC_E_INTERNAL;
    691     }
    692 
    693     if ((variables[var_ndx].inner_arr_length <= inner_arr_ndx) || (variables[var_ndx].outer_arr_length <= outer_arr_ndx)) {
    694         LOG_ERROR(BSL_LS_SOC_COMMON,
    695                   (BSL_META_U(unit,
    696                               "trying to set wb variable %d (%s) with index out of bounds (inner %d, outer %d\n)"),
    697                    var_ndx, variables[var_ndx].var_string, inner_arr_ndx, outer_arr_ndx));
    698         /* using assert as legacy code may not check return value */
    699         assert(0);
    700         return SOC_E_PARAM;
    701     }
    702 
    703     offset = variables[var_ndx].offset + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
    704     src = var;
    705     /* if data_orig is NULL, data is stored only on scache */
    706     if (variables[var_ndx].data_orig) {
    707         dst = variables[var_ndx].data_orig + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
    708     }
    709     else {
    710         dst = buffer->scache_ptr + offset;
    711     }
    712 
    713     /* if src == dst, only need to soc_wb_engine_update, skip memcpy*/
    714     if (src != dst) {
    715         if (!SOC_IS_DNX(unit) && !SOC_IS_DNXF(unit)) {
    716             sal_memcpy(dst,src,variables[var_ndx].data_size);
    717         }
    718 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    719         else {
    720             rc = sw_state_wb_engine.buffer.instance.memwrite(unit, engine_id, variables[var_ndx].buffer,
    721                                                              src,
    722                                                              offset,
    723                                                              variables[var_ndx].data_size);
    724 
    725             if (SOC_FAILURE(rc)) {
    726                 LOG_ERROR(BSL_LS_SOC_COMMON,
    727                           (BSL_META_U(unit,
    728                                       "%s failed to write wb engine var in sw state\n"), soc_errmsg(rc)));
    729                 return rc;
    730             }
    731         }
    732 #endif
    733     }
    734     
    735 #ifdef BCM_WARM_BOOT_SUPPORT
    736     return soc_wb_engine_update(unit, engine_id, var_ndx, outer_arr_ndx, inner_arr_ndx, 1);
    737 #else
    738     return SOC_E_NONE;
    739 #endif /* BCM_WARM_BOOT_SUPPORT */
    740 }
    741 
    742 int
    743 soc_wb_engine_var_get(int unit, int engine_id, int var_ndx, uint32 outer_arr_ndx, uint32 inner_arr_ndx, uint8 *var)
    744 {
    745     soc_wb_engine_var_info_t *variables;
    746     soc_wb_engine_buffer_info_t *buffer;
    747     uint8 *dst;
    748     uint8 *src;
    749     uint32 offset = 0;
    750 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    751     int rc = SOC_E_NONE;  
    752 #endif
    753     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_WB_ENGINE, var_ndx, FALSE));
    754 
    755     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
    756     if(variables == NULL) {
    757         LOG_ERROR(BSL_LS_SOC_COMMON,
    758                   (BSL_META_U(unit,
    759                               "engine_id:%d wb engine variable table is not initialized\n"),
    760                    engine_id));
    761         /* using assert as legacy code may not check return value */
    762         assert(0);
    763         return SOC_E_RESOURCE;
    764     }
    765 
    766     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, variables[var_ndx].buffer);
    767 
    768     if(var_ndx < 0 || var_ndx >= soc_wb_engine_nof_vars[unit][engine_id]) {
    769         LOG_ERROR(BSL_LS_SOC_COMMON,
    770                   (BSL_META_U(unit,
    771                               "engine_id:%d var_ndx %d is out of bound\n"),
    772                    engine_id, var_ndx));
    773         /* using assert as legacy code may not check return value */
    774         assert(0);
    775         return SOC_E_PARAM;
    776     }
    777 
    778     if (!(variables[var_ndx].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
    779         LOG_ERROR(BSL_LS_SOC_COMMON,
    780                   (BSL_META_U(unit,
    781                               "engine_id:%d wb engine variable %d wasn't initialized\n"),
    782                    engine_id, var_ndx));
    783         /* using assert as legacy code may not check return value */
    784         assert(0);
    785         return SOC_E_INTERNAL;
    786     }
    787 
    788     /* if variable is a dynamic variable but was not enabled */
    789     if (variables[var_ndx].is_dynamic && (!variables[var_ndx].is_enabled)) {
    790         LOG_ERROR(BSL_LS_SOC_COMMON,
    791                   (BSL_META_U(unit,
    792                               "engine_id:%d wb engine variable %d (%s) is a dynamic variable that wasn't enabled\n"),
    793                    engine_id, var_ndx, variables[var_ndx].var_string));
    794         /* using assert as legacy code may not check return value */
    795         assert(0);
    796         return SOC_E_INTERNAL;
    797     }
    798 
    799     if (inner_arr_ndx >= variables[var_ndx].inner_arr_length) {
    800         LOG_ERROR(BSL_LS_SOC_COMMON,
    801                   (BSL_META_U(unit,
    802                               "engine_id:%d wb variable %d (%s) idex out of bounds (inner index = %d)\n"),
    803                    engine_id, var_ndx, variables[var_ndx].var_string, inner_arr_ndx));
    804         /* using assert as legacy code may not check return value */
    805         assert(0);
    806         return SOC_E_PARAM;
    807     }
    808 
    809     if (outer_arr_ndx >= variables[var_ndx].outer_arr_length) {
    810         LOG_ERROR(BSL_LS_SOC_COMMON,
    811                   (BSL_META_U(unit,
    812                               "engine_id:%d wb variable %d (%s) idex out of bounds (outer index = %d)\n"),
    813                    engine_id, var_ndx, variables[var_ndx].var_string, outer_arr_ndx));
    814         /* using assert as legacy code may not check return value */
    815         assert(0);
    816         return SOC_E_PARAM;
    817     }
    818 
    819     offset = variables[var_ndx].offset + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
    820     dst = var;
    821     if (buffer->is_only_copy) {
    822         src = buffer->scache_ptr + offset;
    823     }
    824     else{
    825         src = variables[var_ndx].data_orig + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
    826     }
    827 
    828     if (!SOC_IS_DNX(unit) && !SOC_IS_DNXF(unit)) {
    829         sal_memcpy(dst,src,variables[var_ndx].data_size);;
    830     }
    831 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    832     else {
    833         rc = sw_state_wb_engine.buffer.instance.memread(unit, engine_id, variables[var_ndx].buffer,
    834                                                          dst,
    835                                                          offset,
    836                                                          variables[var_ndx].data_size);
    837 
    838         if (SOC_FAILURE(rc)) {
    839             LOG_ERROR(BSL_LS_SOC_COMMON,
    840                       (BSL_META_U(unit,
    841                                   "%s failed to read wb engine var in sw state\n"), soc_errmsg(rc)));
    842             return rc;
    843         }
    844     }
    845 #endif
    846     
    847 
    848     return SOC_E_NONE;
    849 }
    850 
    851 
    852 int
    853 soc_wb_engine_init_tables(int unit, int engine_id, int nof_buffers, int nof_vars)
    854 {
    855 
    856 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    857     int rc = SOC_E_NONE;
    858 #endif
    859 
    860     if (soc_wb_engine_buffer_info[unit][engine_id] || soc_wb_engine_var_info[unit][engine_id]) {
    861         LOG_ERROR(BSL_LS_SOC_COMMON,
    862                   (BSL_META_U(unit,
    863                               "engine_id:%d wb variable tables are already allocated (trying to realloc)\n"),
    864                    engine_id));
    865         return SOC_E_RESOURCE;
    866     }
    867     soc_wb_engine_nof_buffers[unit][engine_id] = nof_buffers;
    868     soc_wb_engine_nof_vars[unit][engine_id]    = nof_vars;
    869 
    870     soc_wb_engine_buffer_info[unit][engine_id] = sal_alloc(nof_buffers * sizeof(soc_wb_engine_buffer_info_t), "soc_wb_engine_buffer_info_t");
    871     if ( soc_wb_engine_buffer_info[unit][engine_id] == NULL) {
    872         return SOC_E_MEMORY;
    873     }
    874     sal_memset(soc_wb_engine_buffer_info[unit][engine_id], 0x0, nof_buffers*sizeof(soc_wb_engine_buffer_info_t));
    875 
    876 
    877 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
    878     if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {
    879         if (!SOC_WARM_BOOT(unit)) {
    880             rc = sw_state_wb_engine.buffer.alloc(unit, engine_id, nof_buffers);
    881 
    882             if (SOC_FAILURE(rc)) {
    883                 LOG_ERROR(BSL_LS_SOC_COMMON,
    884                           (BSL_META_U(unit,
    885                                       "%s failed to alloc wb_engine buffers in sw state\n"), soc_errmsg(rc)));
    886                 return rc;
    887             }
    888         }
    889     }
    890 #endif
    891 
    892     soc_wb_engine_var_info[unit][engine_id] = sal_alloc(nof_vars * sizeof(soc_wb_engine_var_info_t), "soc_wb_engine_var_info_t");
    893     if (soc_wb_engine_var_info[unit][engine_id] == NULL) {
    894         return SOC_E_MEMORY;
    895     }
    896     sal_memset(soc_wb_engine_var_info[unit][engine_id], 0x0, nof_vars*sizeof(soc_wb_engine_var_info_t));
    897 
    898     return SOC_E_NONE;
    899 }
    900 
    901 
    902 
    903 int
    904 soc_wb_engine_deinit_tables(int unit,int engine_id)
    905 {
    906 #ifndef BCM_WARM_BOOT_SUPPORT
    907     int i;
    908     soc_wb_engine_buffer_info_t *buffers;
    909     buffers = SOC_WB_ENGINE_BUFFERS_INFO(unit, engine_id);
    910 #endif
    911 
    912     if (!soc_wb_engine_buffer_info[unit][engine_id] || !soc_wb_engine_var_info[unit][engine_id]) {
    913         LOG_WARN(BSL_LS_SOC_COMMON,
    914                   (BSL_META_U(unit,
    915                               "engine_id:%d wb variable tables weren't allocated\n"),
    916                    engine_id));
    917         return SOC_E_NONE;
    918     }
    919 
    920 #ifndef BCM_WARM_BOOT_SUPPORT
    921     if (!SOC_IS_DNX(unit) && !SOC_IS_DNXF(unit)) {
    922         /*if buffer is allocated at engine instead of at scache.c*/
    923         for (i=0; i<soc_wb_engine_nof_buffers[unit][engine_id]; i++) {
    924             if (buffers[i].init_done) {
    925                 sal_free(buffers[i].scache_ptr);
    926             }
    927         }
    928     }
    929 #endif
    930 
    931     soc_wb_engine_nof_buffers[unit][engine_id] = 0;
    932     soc_wb_engine_nof_vars[unit][engine_id] = 0;
    933 
    934     sal_free(soc_wb_engine_buffer_info[unit][engine_id]);
    935     sal_free(soc_wb_engine_var_info[unit][engine_id]);
    936 
    937     soc_wb_engine_buffer_info[unit][engine_id] = NULL;
    938     soc_wb_engine_var_info[unit][engine_id] = NULL;
    939 
    940     return SOC_E_NONE;
    941 }
    942 
    943 /* 
    944  * this function does the interaction with scache module,
    945  * fetching\creating\modifying an scache buffer and return a pointer to it
    946  */
    947 int
    948 soc_wb_engine_scache_ptr_get(int unit, int engine_id, soc_scache_handle_t handle, soc_wb_engine_scache_oper_t oper,
    949                              int flags, uint32 *size, uint8 **scache_ptr,
    950                              uint16 version, uint16 *recovered_ver, int *already_exists)
    951 {
    952     int        rc = SOC_E_NONE;  
    953     uint32     allocated_size;
    954     int        alloc_size;
    955 #ifdef BCM_WARM_BOOT_SUPPORT
    956     int        incr_size;
    957     uint16     storage_version = version;
    958 #endif
    959 
    960     /* scache buffer is allocated by sw state when dnx */
    961     WB_ENGINE_ERROR_IF_DNX(unit);
    962     
    963     if (scache_ptr == NULL) {
    964         return(SOC_E_PARAM);
    965     }
    966 
    967     if (oper == socWbEngineScacheCreate) {
    968         if (size == NULL) {
    969             return(SOC_E_PARAM);
    970         }
    971         if (already_exists == NULL) {
    972             return(SOC_E_PARAM);
    973         }
    974 
    975         SOC_WB_ENGINE_ALIGN_SIZE(*size);
    976 
    977         alloc_size = (*size) + SOC_WB_SCACHE_CONTROL_SIZE;
    978 
    979 #if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT)) && !defined(__KERNEL__) && (defined(LINUX) || defined(UNIX))
    980         /* make sure that the alloc_size is multiplication of 8 */
    981         alloc_size = ((alloc_size + 7) >> 3) << 3;
    982 #endif
    983 
    984 #ifdef BCM_WARM_BOOT_SUPPORT
    985         rc = soc_scache_ptr_get(unit, handle, scache_ptr, &allocated_size);
    986         if ((rc != SOC_E_NONE) && (rc != SOC_E_NOT_FOUND) ) {
    987             return(rc);
    988         }
    989 
    990         if (rc == SOC_E_NONE) { /* already exists */
    991             (*already_exists) = TRUE;
    992             if (flags & SOC_WB_ENGINE_SCACHE_EXISTS_ERROR) {
    993                 return(SOC_E_PARAM);
    994             }
    995 
    996         }
    997         else { /* need to create */
    998             (*already_exists) = FALSE;
    999             rc = soc_scache_alloc(unit, handle, alloc_size);
   1000             if (rc != SOC_E_NONE) {
   1001                 return(rc);
   1002             }
   1003 
   1004             rc = soc_scache_ptr_get(unit, handle, scache_ptr, &allocated_size);
   1005             if (rc != SOC_E_NONE) {
   1006                 return(rc);
   1007             }
   1008             if ((*scache_ptr) == NULL) {
   1009                 return(SOC_E_MEMORY);
   1010             }
   1011         }
   1012 
   1013         if (alloc_size != allocated_size) {
   1014             return(SOC_E_INTERNAL);
   1015         }
   1016         if ((*already_exists) == FALSE) {
   1017             sal_memcpy(*scache_ptr, &version, sizeof(uint16));
   1018         }
   1019         else {
   1020             sal_memcpy(&storage_version, *scache_ptr, sizeof(uint16));
   1021             if (storage_version != version) {
   1022                 return(SOC_E_INTERNAL);
   1023             }
   1024         }
   1025 
   1026         if (recovered_ver != NULL) {
   1027             (*recovered_ver) = version;
   1028         }
   1029 #else /*BCM_WARM_BOOT_SUPPORT*/
   1030         /* alloc buffer here instead of in scache */
   1031         /*   (for buffers that store their original data on the buffer itself)*/
   1032         *scache_ptr = sal_alloc(alloc_size, "scache buffer replacement");
   1033         if ( *scache_ptr == NULL) {
   1034             return SOC_E_MEMORY;
   1035         }
   1036         allocated_size = alloc_size;
   1037 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1038     }
   1039 
   1040 #ifdef BCM_WARM_BOOT_SUPPORT
   1041     else if (oper == socWbEngineScacheRetreive) {
   1042         if (size == NULL) {
   1043             return(SOC_E_PARAM);
   1044         }
   1045         if (recovered_ver == NULL) {
   1046             return(SOC_E_PARAM);
   1047         }
   1048 
   1049         rc = soc_scache_ptr_get(unit, handle, scache_ptr, &allocated_size);
   1050         if (rc != SOC_E_NONE) {
   1051             return(rc);
   1052         }
   1053         (*size) = allocated_size;
   1054 
   1055         sal_memcpy(&storage_version, *scache_ptr, sizeof(uint16));
   1056         (*recovered_ver) = storage_version;
   1057 
   1058         if (already_exists != NULL) {
   1059             (*already_exists) = TRUE;
   1060         }
   1061 
   1062         if (storage_version < *recovered_ver) {
   1063             LOG_ERROR(BSL_LS_SOC_COMMON,
   1064                       (BSL_META_U(unit,
   1065                                   "Downgrade detected. Current version=%d.%d  found %d.%d\n"),
   1066                        SOC_SCACHE_VERSION_MAJOR(version),
   1067                        SOC_SCACHE_VERSION_MINOR(version),
   1068                        SOC_SCACHE_VERSION_MAJOR(storage_version),
   1069                        SOC_SCACHE_VERSION_MINOR(storage_version)));
   1070 
   1071                 /* Notify the application with an event                  */
   1072                 /* The application will then need to reconcile the       */
   1073                 /* version differences using the documented behavioral   */
   1074                 /* differences on per module (handle) basis              */
   1075                 SOC_IF_ERROR_RETURN
   1076                     (soc_event_generate(unit,
   1077                                         SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE,
   1078                                         handle, storage_version, version));
   1079 
   1080 
   1081             if (flags & SOC_WB_ENGINE_SCACHE_DOWNGRADE_INVALID) {
   1082                 return(SOC_E_INTERNAL);
   1083             }
   1084         }
   1085         else if (storage_version > *recovered_ver) {
   1086 
   1087             /* Individual BCM module implementations are version-aware. The       */
   1088             /* default_ver is the latest version that the module is aware of.     */
   1089             /* Each module should be able to understand versions <= default_ver.  */
   1090             /* The actual recovered_ver is returned to the calling module during  */
   1091             /* warm boot initialization. The individual module needs to parse its */
   1092             /* scache based on the recovered_ver.                                 */
   1093 
   1094             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1095                         (BSL_META_U(unit,
   1096                                     "Upgrade scenario supported. Current version=%d.%d  found %d.%d\n"),
   1097                          SOC_SCACHE_VERSION_MAJOR(version),
   1098                          SOC_SCACHE_VERSION_MINOR(version),
   1099                          SOC_SCACHE_VERSION_MAJOR(storage_version),
   1100                          SOC_SCACHE_VERSION_MINOR(storage_version)));
   1101         }
   1102     }
   1103 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1104 
   1105     else if (oper == socWbEngineScacheRealloc) {
   1106         if (size == NULL) {
   1107             return(SOC_E_PARAM);
   1108         }
   1109 
   1110 #ifdef BCM_WARM_BOOT_SUPPORT
   1111         /* get current size */
   1112         rc = soc_scache_ptr_get(unit, handle, scache_ptr, &allocated_size);
   1113         if (rc != SOC_E_NONE) {
   1114             return(rc);
   1115         }
   1116 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1117 
   1118         /* allocate new size */
   1119         SOC_WB_ENGINE_ALIGN_SIZE(*size);
   1120         alloc_size = (*size) + SOC_WB_SCACHE_CONTROL_SIZE;
   1121 #ifdef BCM_WARM_BOOT_SUPPORT
   1122         incr_size = alloc_size - allocated_size;
   1123 
   1124         rc = soc_scache_realloc(unit, handle, incr_size);
   1125         if (rc != SOC_E_NONE) {
   1126             return(rc);
   1127         }
   1128 
   1129         /* update version */
   1130         rc = soc_scache_ptr_get(unit, handle, scache_ptr, &allocated_size);
   1131         if (rc != SOC_E_NONE) {
   1132             return(rc);
   1133         }
   1134         sal_memcpy(&storage_version, *scache_ptr, sizeof(uint16));
   1135         sal_memcpy(*scache_ptr, &version, sizeof(uint16));
   1136 
   1137         if (recovered_ver != NULL) {
   1138             (*recovered_ver) = storage_version; 
   1139         }
   1140         if (already_exists != NULL) {
   1141             (*already_exists) = TRUE;
   1142         }
   1143 #else /*BCM_WARM_BOOT_SUPPORT*/
   1144         /* alloc buffer here instead of in scache */
   1145         /*   (for buffers that store their original data on the buffer itself)*/
   1146         *scache_ptr = sal_alloc(alloc_size, "soc_wb_engine_buffer_info_t");
   1147         if (*scache_ptr == NULL) {
   1148             return SOC_E_MEMORY;
   1149         }
   1150         allocated_size = alloc_size;
   1151 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1152     }
   1153     else if (oper == socWbEngineScacheFreeCreate) {
   1154         return(SOC_E_PARAM); /* only re-alloc supported */
   1155     }
   1156     else {
   1157         return(SOC_E_PARAM);
   1158     }
   1159 
   1160     /* Advance over scache control info */
   1161     (*scache_ptr) += SOC_WB_SCACHE_CONTROL_SIZE;
   1162     (*size) = (allocated_size - SOC_WB_SCACHE_CONTROL_SIZE); /* update size */
   1163 
   1164     return(rc);  
   1165 }
   1166 
   1167 #ifdef BCM_WARM_BOOT_SUPPORT 
   1168 static int
   1169 soc_wb_engine_update(int unit, int engine_id, uint32 var_id, uint32 outer_ndx, uint32 inner_ndx, int update_length)
   1170 {
   1171     int                                     rc = SOC_E_NONE;
   1172     uint32                                  data_size;
   1173     uint8                                  *data;
   1174     uint8                                  *dst;
   1175     uint8                                  *src;
   1176     int                                     offset;
   1177     soc_scache_handle_t                     wb_handle;
   1178     soc_wb_engine_buffer_info_t            *buffer;
   1179     soc_wb_engine_var_info_t               *variable;
   1180 
   1181     /* dnx devices does not support autosync */
   1182     WB_ENGINE_EXIT_IF_DNX(unit);
   1183 
   1184     variable = SOC_WB_ENGINE_VAR_INFO(unit, engine_id, var_id);
   1185     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, variable->buffer);
   1186 
   1187     /* handle corner case of being invoked before the wb module is initialized      */
   1188     /* (e.g. from module's init().                                                  */
   1189     /* default configuration either does not have to be saved or has to be handled  */
   1190     /* in a special manner.                                                         */
   1191     if (!buffer->init_done) {
   1192         return rc;
   1193     }
   1194 
   1195     /* if immediate sync not enabled -> mark buffer as dirty and exit */
   1196     if (!SOC_CONTROL(unit)->autosync) {
   1197         /* mark dirty state. Currently no other processing done           */
   1198         /* if required framework cache could be updated without updating  */
   1199         /* the persistent storage                                         */
   1200         buffer->dirty = TRUE;
   1201         return rc;
   1202     }
   1203 
   1204     SOC_WB_ENGINE_SCACHE_HANDLE_SET(wb_handle, unit, engine_id, buffer->buffer_name);
   1205 
   1206     data_size = variable->data_size;
   1207     /* pointer to the offset of the variable's space in his buffer */
   1208     data = buffer->scache_ptr + variable->offset;
   1209     dst = data + (outer_ndx * variable->inner_arr_length * variable->data_size) + (inner_ndx * variable->data_size);
   1210     if (buffer->is_only_copy) {
   1211         src = 0;
   1212     }
   1213     else {
   1214         src = variable->data_orig + (outer_ndx * variable->outer_arr_jump) + (inner_ndx * variable->inner_arr_jump);
   1215         sal_memcpy(dst, src, variable->data_size * update_length);
   1216     }
   1217 
   1218 
   1219     /* buffer's header is already calculated in variables' offsets */
   1220     offset = (uint32)(dst - buffer->scache_ptr);
   1221     /* data to be commited is the data we updated in dst*/
   1222     data = dst;
   1223 
   1224     rc = soc_scache_commit_specific_data(unit, wb_handle, data_size *update_length, data, offset);
   1225     if (SOC_FAILURE(rc)) {
   1226         LOG_ERROR(BSL_LS_SOC_COMMON,
   1227                   (BSL_META_U(unit,
   1228                               "%s\n"), soc_errmsg(rc)));
   1229     }
   1230 
   1231     return rc;
   1232 }
   1233 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1234 
   1235 /* 
   1236  * to be called by functions who create variables with dynamic sizes. 
   1237  * these variables should be entered to wb_engine with size=0 (when added with soc_wb_engine_add_var) 
   1238  * and update the var info once the var is alloced
   1239  */
   1240 int
   1241 soc_wb_engine_update_var_info(int unit, int engine_id, int var_idx, uint32 data_size, uint32 outer_arr_length, uint32 inner_arr_length)
   1242 {
   1243     soc_wb_engine_var_info_t               *variable;
   1244 
   1245     variable = SOC_WB_ENGINE_VAR_INFO(unit, engine_id, var_idx);
   1246 
   1247     if(!soc_wb_engine_var_info[unit][engine_id]) 
   1248     {
   1249         LOG_ERROR(BSL_LS_SOC_COMMON,
   1250                   (BSL_META_U(unit,
   1251                               "engine_id:%d wb engine variable table is not initialized\n"),
   1252                    engine_id));
   1253         return SOC_E_RESOURCE;
   1254     }
   1255 
   1256     variable->data_size = data_size;
   1257     variable->outer_arr_length = outer_arr_length;
   1258     variable->inner_arr_length = inner_arr_length;
   1259     variable->init_done = SOC_WB_ENGINE_VAR_DYNAMIC_SIZE_UPDATED;
   1260 
   1261     return SOC_E_NONE;
   1262 }
   1263 
   1264 
   1265 /* 
   1266  * consider  implement a function that check the data in the tables 
   1267  */ 
   1268 int
   1269 soc_wb_engine_verify_tables(int unit, int engine_id)
   1270 {
   1271     return SOC_E_NONE;
   1272 }
   1273 
   1274 /* 
   1275  * consider implement a function that return a layout of 
   1276  *       a specific version to be used by upgrade functions
   1277  */ 
   1278 int
   1279 soc_wb_engine_version_offsets_get(int unit, int engine_id, uint32 buffer_id, uint16 version, soc_wb_engine_var_info_t *vars_arr)
   1280 {
   1281     return SOC_E_NONE;
   1282 }
   1283 
   1284 static int
   1285 soc_wb_engine_calculate_offsets(int unit, int engine_id, uint32 buffer_id, uint16 version, int *var_ndx)
   1286 {
   1287     soc_wb_engine_buffer_info_t *buffer;
   1288     soc_wb_engine_var_info_t *variables;
   1289     uint32 nof_entries;
   1290     uint32 nof_vars = 0;
   1291     uint32 offset = 0;
   1292     int is_dynamic_count = 0;
   1293     int i;
   1294 
   1295     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, buffer_id);
   1296     variables = SOC_WB_ENGINE_VARS_INFO(unit, engine_id);
   1297 
   1298     /* allocate space for a header that represent the structure of the buffer */
   1299     for (i = 0; i < buffer->variable_num; i++) {
   1300         if (variables[var_ndx[i]].buffer == buffer_id &&
   1301             variables[var_ndx[i]].version_added <= version &&
   1302             variables[var_ndx[i]].version_removed > version) {
   1303             nof_vars++;
   1304         }
   1305     }
   1306     offset += sizeof(wb_engine_vars_info_header_t);
   1307     offset += (nof_vars * sizeof(wb_engine_var_info_chunk_t));
   1308 
   1309 
   1310     if (buffer->is_dynamic == 1) {
   1311         /* count the buffer's dynamic variables */
   1312         for (i = 0; i < buffer->variable_num; i++) {
   1313             /* count only if var is dynamic, belong to this buffer, and exist in this version*/
   1314             if (variables[var_ndx[i]].buffer == buffer_id && variables[var_ndx[i]].is_dynamic == 1
   1315                 && variables[var_ndx[i]].version_added <= version && variables[var_ndx[i]].version_removed > version) {
   1316                 is_dynamic_count++;
   1317             }
   1318         }
   1319 
   1320         /* allocate space for the dynamic variables info at the beginning of the buffer */
   1321         offset = offset + (sizeof(soc_wb_engine_dynamic_var_info_t) * is_dynamic_count);
   1322         offset = (offset + 4) & ~(0x3); /* next offset at a word boundary */
   1323     }
   1324     
   1325     /* consider the buffer's header when calculating the offsets,
   1326      *  that means save/restore/update dont need to consider the header if using these offsets
   1327      */
   1328     for (i = 0; i < buffer->variable_num; i++) {
   1329         nof_entries = 0;
   1330         if (variables[var_ndx[i]].buffer != buffer_id) {
   1331             /*only consider variables of current buffer*/
   1332             continue;
   1333         }
   1334         if (variables[var_ndx[i]].version_removed <= version) {
   1335             /*skip if was removed before current version*/
   1336             continue;
   1337         }
   1338         if (variables[var_ndx[i]].version_added > version) {
   1339             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1340                         (BSL_META_U(unit,
   1341                                     "engine_id:%d wb engine variable %d (%s) version:%d is larger than its buffer version:%d (meanning ISSU is detected)\n"),
   1342                          engine_id, var_ndx[i], variables[var_ndx[i]].var_string, variables[var_ndx[i]].version_added, version));
   1343             /* skip if was only added in a later version */
   1344             continue;
   1345         }
   1346         if (variables[var_ndx[i]].is_dynamic == 1 && variables[var_ndx[i]].is_enabled == 0) {
   1347             /* if var is dynamic but was never enabled - ignore it*/
   1348             continue;
   1349         }
   1350 
   1351         variables[var_ndx[i]].offset = offset;
   1352         nof_entries = variables[var_ndx[i]].outer_arr_length * variables[var_ndx[i]].inner_arr_length;
   1353         offset = offset + (variables[var_ndx[i]].data_size * nof_entries);
   1354         offset = (offset + 4) & ~(0x3); /* next offset at a word boundary */
   1355     }
   1356     buffer->size = offset;
   1357 
   1358     return SOC_E_NONE;
   1359 }
   1360 
   1361 #ifdef BCM_WARM_BOOT_SUPPORT
   1362 int
   1363 soc_wb_engine_sync(int unit, int engine_id)
   1364 {
   1365     soc_wb_engine_buffer_info_t *buffers;
   1366     soc_wb_engine_var_info_t *variables;
   1367     uint32 var_ndx;
   1368     uint32 outer_arr_ndx;
   1369     uint32 inner_arr_ndx;
   1370     int    buff_id;
   1371     uint8 *data;
   1372     uint8 *dst;
   1373     uint8 *src;
   1374 
   1375     /* should use sw_state sync when dnx */
   1376     WB_ENGINE_EXIT_IF_DNX(unit);
   1377 
   1378     buffers = SOC_WB_ENGINE_BUFFERS_INFO(unit, engine_id);
   1379     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
   1380 
   1381     for (var_ndx = 0; var_ndx < soc_wb_engine_nof_vars[unit][engine_id]; var_ndx++) {
   1382 
   1383         buff_id = variables[var_ndx].buffer;
   1384 
   1385         /* skip non existing vars */
   1386         if (!(variables[var_ndx].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
   1387             continue;
   1388         }
   1389         /*skip if was removed before current version*/
   1390         if (variables[var_ndx].version_removed <= buffers[variables[var_ndx].buffer].version) {
   1391             continue;
   1392         }
   1393         /* if variable is a dynamic variable but was not enabled skip it */
   1394         if (variables[var_ndx].is_dynamic && (!variables[var_ndx].is_enabled)) {
   1395             continue;
   1396         }
   1397         /* check dirty bit - check if there was any state change or a part of init sequence */
   1398         if ( !(buffers[buff_id].dirty) && (buffers[buff_id].init_done == TRUE)) {
   1399             continue;
   1400         }
   1401         /* no need to sync vars that are stored only ob scache buffer */
   1402         if (!variables[var_ndx].data_orig) {
   1403             continue;
   1404         }
   1405         /* no need to sync vars that are stored only ob scache buffer */
   1406         if (!variables[var_ndx].data_orig) {
   1407             continue;
   1408         }
   1409 
   1410         /* pointer to the offset of the variable's space in his buffer */
   1411         data = buffers[buff_id].scache_ptr + variables[var_ndx].offset;
   1412 
   1413         for (outer_arr_ndx = 0; outer_arr_ndx < variables[var_ndx].outer_arr_length; outer_arr_ndx++) {
   1414             for(inner_arr_ndx = 0; inner_arr_ndx < variables[var_ndx].inner_arr_length; inner_arr_ndx++) {
   1415                 dst = data + (outer_arr_ndx * variables[var_ndx].inner_arr_length * variables[var_ndx].data_size) + (inner_arr_ndx * variables[var_ndx].data_size);
   1416                 src = variables[var_ndx].data_orig + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
   1417                 /* check for buffer overflow */
   1418                 if ((dst - buffers[buff_id].scache_ptr)+variables[var_ndx].data_size >= buffers[buff_id].size) {
   1419                     return SOC_E_RESOURCE;
   1420                 }
   1421                 if (!buffers[buff_id].is_only_copy) {
   1422                     sal_memcpy(dst,src,variables[var_ndx].data_size);
   1423                 }
   1424             }
   1425         }
   1426     }
   1427 
   1428     return SOC_E_NONE;
   1429 }
   1430 
   1431 
   1432 int
   1433 soc_wb_engine_restore(int unit, int engine_id, uint32 buffer_id, uint16 recovered_ver, int *var_ndx)
   1434 {
   1435     soc_wb_engine_buffer_info_t *buffer;
   1436     soc_wb_engine_var_info_t *variables;
   1437     wb_engine_vars_info_header_t *vars_info_header;
   1438     uint32 outer_arr_ndx;
   1439     uint32 inner_arr_ndx;
   1440     uint8 *data;
   1441     uint8 *dst;
   1442     uint8 *src;
   1443     int rc;
   1444     int i;
   1445 
   1446     int is_dynamic_count = 0;
   1447     soc_wb_engine_dynamic_var_info_t *dynamic_vars_header;
   1448 
   1449     /* restored by sw_state when dnx */
   1450     WB_ENGINE_ERROR_IF_DNX(unit);
   1451 
   1452     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id,buffer_id);
   1453     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
   1454 
   1455     /*if it's a dynamic buffer - update the data in the variables table from data in the buffer's header*/
   1456     is_dynamic_count = 0;
   1457     vars_info_header = (wb_engine_vars_info_header_t *) buffer->scache_ptr;
   1458     dynamic_vars_header = (soc_wb_engine_dynamic_var_info_t *) (buffer->scache_ptr + sizeof(wb_engine_vars_info_header_t) + (sizeof(wb_engine_var_info_chunk_t)*vars_info_header->nof_vars));
   1459     if (buffer->is_dynamic) {
   1460         for (i = 0; i < buffer->variable_num; i++) {
   1461             if (variables[var_ndx[i]].buffer == buffer_id && variables[var_ndx[i]].is_dynamic == 1) {
   1462                 variables[var_ndx[i]].offset = dynamic_vars_header[is_dynamic_count].offset;
   1463                 variables[var_ndx[i]].flags = dynamic_vars_header[is_dynamic_count].flags;
   1464                 variables[var_ndx[i]].data_size = dynamic_vars_header[is_dynamic_count].data_size;
   1465                 variables[var_ndx[i]].outer_arr_length = dynamic_vars_header[is_dynamic_count].outer_arr_length;
   1466                 variables[var_ndx[i]].inner_arr_length = dynamic_vars_header[is_dynamic_count].inner_arr_length;
   1467                 variables[var_ndx[i]].outer_arr_jump = dynamic_vars_header[is_dynamic_count].outer_arr_jump;
   1468                 variables[var_ndx[i]].inner_arr_jump = dynamic_vars_header[is_dynamic_count].inner_arr_jump;
   1469                 variables[var_ndx[i]].is_enabled = dynamic_vars_header[is_dynamic_count].is_enabled;
   1470                 is_dynamic_count++;
   1471             }
   1472         }
   1473         /*given new info regarding enabled vars, recalculate offset and buffer size*/
   1474         rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, recovered_ver, var_ndx);
   1475         if (rc != SOC_E_NONE) {
   1476             return rc;
   1477         }
   1478     }
   1479 
   1480     if (buffer->version < recovered_ver) {
   1481         /* downgrade scenario is not supported */
   1482         return SOC_E_UNAVAIL;
   1483     }
   1484 
   1485     for (i = 0; i < buffer->variable_num; i++) {
   1486         /* check if variable belongs to this buffer */
   1487         if (variables[var_ndx[i]].buffer != buffer_id) {
   1488             continue;
   1489         }
   1490 
   1491         /* if variable was no ititialized skipping it  */
   1492         if (!(variables[var_ndx[i]].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
   1493             continue;
   1494         }
   1495 
   1496         /* if variable is a dynamic variable but was not enabled skip it */
   1497         if (variables[var_ndx[i]].is_dynamic && (!variables[var_ndx[i]].is_enabled)) {
   1498             continue;
   1499         }
   1500 
   1501         /* no need to restore vars that are stored only ob scache buffer */
   1502         if (!variables[var_ndx[i]].data_orig) {
   1503             continue;
   1504         }
   1505 
   1506         /* if this variable didnt exist in the version we are recovering, initialize it with given default value*/
   1507         if (variables[var_ndx[i]].version_added > recovered_ver) {
   1508             /* init with default value */
   1509             if (variables[var_ndx[i]].default_value != NULL) {
   1510                 for (outer_arr_ndx = 0; outer_arr_ndx < variables[var_ndx[i]].outer_arr_length; outer_arr_ndx++) {
   1511                     for(inner_arr_ndx = 0; inner_arr_ndx < variables[var_ndx[i]].inner_arr_length; inner_arr_ndx++) {
   1512                         src = variables[var_ndx[i]].default_value;
   1513                         dst = variables[var_ndx[i]].data_orig + (outer_arr_ndx * variables[var_ndx[i]].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx[i]].inner_arr_jump);
   1514                         sal_memcpy(dst,src,variables[var_ndx[i]].data_size);
   1515                     }
   1516                 }
   1517 
   1518             }
   1519             continue;
   1520         }
   1521 
   1522         /* if this variable was removed, skip it*/
   1523         if (variables[var_ndx[i]].version_removed <= buffer->version) {
   1524             continue;
   1525         }
   1526 
   1527         /* 
   1528          * restore all vars that werent removed or added (common case) according to current version layout
   1529          * if need to make any fixes (e.g fill data of newly added vars from old removed vars)
   1530          * address them in the buffer's upgrade function that will be called after all vars are recovered
   1531          */
   1532         /* pointer to the offset of the variable's space in his buffer */
   1533         data = buffer->scache_ptr + variables[var_ndx[i]].offset;
   1534         if (!buffer->is_only_copy) {
   1535             for (outer_arr_ndx = 0; outer_arr_ndx < variables[var_ndx[i]].outer_arr_length; outer_arr_ndx++) {
   1536                 for(inner_arr_ndx = 0; inner_arr_ndx < variables[var_ndx[i]].inner_arr_length; inner_arr_ndx++) {
   1537                     src = data + (outer_arr_ndx * variables[var_ndx[i]].inner_arr_length * variables[var_ndx[i]].data_size) + (inner_arr_ndx * variables[var_ndx[i]].data_size);
   1538                     dst = variables[var_ndx[i]].data_orig + (outer_arr_ndx * variables[var_ndx[i]].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx[i]].inner_arr_jump);
   1539                     sal_memcpy(dst,src,variables[var_ndx[i]].data_size);
   1540                 }
   1541             }
   1542         }
   1543     }
   1544 
   1545     /* here we handle non-add\remove changes using buffer's destined callback.
   1546        callback takes only unit but can be tailored to do any manipulation on the old buffer's data currently stored at
   1547        SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id,buffer_id)->scache_ptr (the old buffer's offsets are still stored at variable location in
   1548        SOC_WB_ENGINE_VARS_INFO(unit,engine_id)). typical use is to extract some data from old version's vars, modify it to suit size and content of some
   1549        new var and store it directly into new version's vars locations.
   1550        --------------------
   1551        doing these kind of manipulations require some knowlege of how data is stored inside wb_engine. it's a little complicated and should
   1552        generally be avoided and be used as a last resort
   1553        --------------------
   1554        later in the sequence SOC_WB_ENGINE_VARS_INFO(unit,engine_id) will be updated with current version's offsets */
   1555 
   1556     if (buffer->version > recovered_ver) {
   1557         /* call upgrade function (if NULL, no upgrade should be done)*/
   1558         if (buffer->upgrade_func != NULL) {
   1559             (*(buffer->upgrade_func))(unit, buffer->upgrade_func_arg, recovered_ver, buffer->version);
   1560         }
   1561     }
   1562 
   1563     return SOC_E_NONE;
   1564 }
   1565 
   1566 #ifndef NO_SAL_APPL
   1567 void
   1568 soc_wb_engine_mem_print(FILE *output_file, uint8 *mem, int size)
   1569 {
   1570 #ifndef __KERNEL__
   1571     int i;
   1572     for (i=0; i<size; i++) {
   1573         sal_fprintf(output_file, "%02X", mem[i]);
   1574     }
   1575 #else
   1576     return;
   1577 #endif
   1578 }
   1579 #endif /*NO_SAL_APPL*/
   1580 
   1581 int
   1582 soc_wb_engine_dump(int unit, int engine_id, int flags, uint32 var_id, uint32 buffer_id, int print_orig_data, char *file_name, char *mode)
   1583 {
   1584     int                                rc = SOC_E_NONE;
   1585 #if (!defined(__KERNEL__)  && !defined(NO_SAL_APPL))
   1586     uint32                             buff_ndx;
   1587     uint32                             var_ndx;
   1588     soc_wb_engine_buffer_info_t       *buffers;
   1589     soc_wb_engine_var_info_t          *variables;
   1590     uint32                             outer_arr_ndx;
   1591     uint32                             inner_arr_ndx;
   1592     uint8                             *data;
   1593     uint8                             *src;
   1594     uint8                             *dst;
   1595     int                                curr_buff;
   1596     FILE                              *output_file;
   1597 
   1598     WB_ENGINE_EXIT_IF_DNX(unit);
   1599 
   1600     if ((output_file = sal_fopen(file_name, mode)) == 0) {
   1601         cli_out("Error opening sw dump file %s\n", file_name);
   1602         return SOC_E_MEMORY;
   1603     }
   1604 
   1605     sal_fprintf(output_file, "\n######################################################################################\n");
   1606     sal_fprintf(output_file, "# you are dumping a view of the data stored using wb_engine module.                  #\n");
   1607     sal_fprintf(output_file, "# for each buffer, youll see some of the buffer attributes followed by details on    #\n");
   1608     sal_fprintf(output_file, "# all of the buffer's variables, including their \"real\" value and their value in     #\n");
   1609     sal_fprintf(output_file, "# the scache buffer that is written to the external storage.                         #\n");
   1610     sal_fprintf(output_file, "# the variables printed value is not aware of the variable's type and is printed as  #\n");
   1611     sal_fprintf(output_file, "# a hex buffer                                                                       #\n");
   1612     sal_fprintf(output_file, "######################################################################################\n\n");
   1613 
   1614     buffers = SOC_WB_ENGINE_BUFFERS_INFO(unit, engine_id);
   1615     variables = SOC_WB_ENGINE_VARS_INFO(unit,engine_id);
   1616 
   1617     for (buff_ndx = 0; buff_ndx < soc_wb_engine_nof_buffers[unit][engine_id]; buff_ndx++) {
   1618         /* skip non existing buffers */
   1619         if (!(buffers[buff_ndx].init_done)) {
   1620             continue;
   1621         }
   1622         else if (buffer_id != -1 && buffer_id != buff_ndx) {
   1623             continue;
   1624         }
   1625         else
   1626         {
   1627             sal_fprintf(output_file, "buffer #%d (%s buffer):\n", buff_ndx, (buffers[buff_ndx].is_dynamic ? "dynamic" : "static"));
   1628             sal_fprintf(output_file, "buffer's name - %s,\t", buffers[buff_ndx].buff_string);
   1629             sal_fprintf(output_file, "buffer's version - %d,\t", buffers[buff_ndx].version);
   1630             sal_fprintf(output_file, "buffer's size - %d,\t", buffers[buff_ndx].size);
   1631             sal_fprintf(output_file, "is dirty - %s\n", (buffers[buff_ndx].dirty ? "yes" : "no"));
   1632             if (buffers[buff_ndx].is_only_copy) {
   1633                 sal_fprintf(output_file, "data is stored exclusively on buffer (buffer does not contai copies of global variables)\n");
   1634             }
   1635             sal_fprintf(output_file, "----------------------------------------\n");
   1636         }
   1637 
   1638         for (var_ndx = 0; var_ndx < soc_wb_engine_nof_vars[unit][engine_id]; var_ndx++) {
   1639 
   1640             curr_buff = variables[var_ndx].buffer;
   1641 
   1642             /*only consider variables of current buffer*/
   1643             if (curr_buff != buff_ndx) {
   1644                 continue;
   1645             }
   1646 
   1647             /* skip non existing vars */
   1648             if (!(variables[var_ndx].init_done == SOC_WB_ENGINE_VAR_INITIALIZED)) {
   1649                 continue;
   1650             }
   1651 
   1652             /* skip non existing vars */
   1653             if (var_id != -1 && var_id != var_ndx) {
   1654                 continue;
   1655             }
   1656 
   1657             /* if variable is a dynamic variable but was not enabled*/
   1658             if (variables[var_ndx].is_dynamic && (!variables[var_ndx].is_enabled)) {
   1659                 sal_fprintf(output_file, "variable #%d (%s) - is a dynamic variable that was not yet created\n", var_ndx, variables[var_ndx].var_string);
   1660                 sal_fprintf(output_file, "---\n");
   1661             }
   1662 
   1663             sal_fprintf(output_file, "variable #%d (%s) - ", var_ndx, variables[var_ndx].var_string);
   1664             sal_fprintf(output_file, "%s%s%s, ", (variables[var_ndx].is_dynamic ? "dynamic" : "static"), (variables[var_ndx].outer_arr_length > 1 ? " 2D" : ""), (variables[var_ndx].inner_arr_length > 1 ? " array" : " variable"));
   1665             sal_fprintf(output_file, "offset in scache buffer = %d, size of one data unit = %d, added in version %d\n", variables[var_ndx].offset, variables[var_ndx].data_size, variables[var_ndx].version_added);
   1666             if (variables[var_ndx].version_removed != 0xff) {
   1667                 sal_fprintf(output_file, "removed in version %d\n", variables[var_ndx].version_removed);
   1668             }
   1669 
   1670             /* pointer to the offset of the variable's space in his buffer */
   1671             data = buffers[curr_buff].scache_ptr + variables[var_ndx].offset;
   1672 
   1673             for (outer_arr_ndx = 0; outer_arr_ndx < variables[var_ndx].outer_arr_length; outer_arr_ndx++) {
   1674                 for(inner_arr_ndx = 0; inner_arr_ndx < variables[var_ndx].inner_arr_length; inner_arr_ndx++) {
   1675                     dst = data + (outer_arr_ndx * variables[var_ndx].inner_arr_length * variables[var_ndx].data_size) + (inner_arr_ndx * variables[var_ndx].data_size);
   1676                     if (buffers[buff_ndx].is_only_copy) {
   1677                         src = buffers[buff_ndx].scache_ptr + variables[var_ndx].offset + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
   1678                     }
   1679                     else {
   1680                         src = variables[var_ndx].data_orig + (outer_arr_ndx * variables[var_ndx].outer_arr_jump) + (inner_arr_ndx * variables[var_ndx].inner_arr_jump);
   1681                     }
   1682                     /* check for buffer overflow */
   1683                     if ((dst - buffers[curr_buff].scache_ptr)+variables[var_ndx].data_size >= buffers[curr_buff].size) {
   1684                         LOG_ERROR(BSL_LS_SOC_COMMON,
   1685                                   (BSL_META_U(unit,
   1686                                               "%s\n"), soc_errmsg(rc)));
   1687                         sal_fclose(output_file);
   1688                         return SOC_E_RESOURCE;
   1689                     }
   1690 
   1691                     sal_fprintf(output_file, "%s - var_%d", variables[var_ndx].var_string,var_ndx);
   1692                     if (variables[var_ndx].outer_arr_length>1) {
   1693                         sal_fprintf(output_file, "[%d]", outer_arr_ndx);
   1694                     }
   1695                     if (variables[var_ndx].inner_arr_length>1) {
   1696                         sal_fprintf(output_file, "[%d]", inner_arr_ndx);
   1697                     }
   1698 
   1699                     if (!buffers[buff_ndx].is_only_copy && print_orig_data) {
   1700                         sal_fprintf(output_file, "variable's warmboot data at [%d][%d] - 0x", outer_arr_ndx, inner_arr_ndx);
   1701                         soc_wb_engine_mem_print(output_file, dst, variables[var_ndx].data_size);
   1702                         sal_fprintf(output_file, "\n");
   1703                         sal_fprintf(output_file, "variable's original data at [%d][%d] - 0x", outer_arr_ndx, inner_arr_ndx);
   1704                         soc_wb_engine_mem_print(output_file, src, variables[var_ndx].data_size);
   1705                         sal_fprintf(output_file, "\n");
   1706                     }
   1707                     else{
   1708                         sal_fprintf(output_file, " - 0x");
   1709                         soc_wb_engine_mem_print(output_file, src, variables[var_ndx].data_size);
   1710                         sal_fprintf(output_file, "\n");
   1711                     }
   1712                 }
   1713             }
   1714 
   1715             sal_fprintf(output_file, "-------\n");
   1716         }
   1717 
   1718         sal_fprintf(output_file, "\n\n*******************************************************************************\n");
   1719     }
   1720 
   1721     sal_fclose(output_file);
   1722 #endif /*(!defined(__KERNEL__)  && !defined(NO_SAL_APPL))*/
   1723     return rc;
   1724 }
   1725 
   1726 int
   1727 soc_wb_engine_buffer_dynamic_vars_state_get(int unit, int engine_id, int buffer_idx, soc_wb_engine_dynamic_var_info_t **var)
   1728 {
   1729     int                                rc = SOC_E_NONE;
   1730     soc_scache_handle_t                wb_handle;
   1731     int                                flags=0;
   1732     int                                already_exists;
   1733     uint32                             size;
   1734     uint16                             version;
   1735     uint16                             recovered_ver;
   1736     uint8                             *scache_ptr;
   1737     soc_wb_engine_buffer_info_t       *buffer;
   1738     wb_engine_vars_info_header_t      *vars_info_header;
   1739 
   1740     WB_ENGINE_EXIT_IF_DNX(unit);
   1741 
   1742     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, buffer_idx);
   1743     version = buffer->version;
   1744     
   1745     SOC_WB_ENGINE_SCACHE_HANDLE_SET(wb_handle, unit, engine_id, buffer->buffer_name);
   1746 
   1747     rc = soc_wb_engine_scache_ptr_get(unit, engine_id, wb_handle, socWbEngineScacheRetreive, flags,
   1748                                     &size, &scache_ptr, version, &recovered_ver, &already_exists);
   1749 
   1750     vars_info_header = (wb_engine_vars_info_header_t *) scache_ptr;
   1751 
   1752     *var = (soc_wb_engine_dynamic_var_info_t *) (scache_ptr + sizeof(wb_engine_vars_info_header_t) + (vars_info_header->nof_vars * sizeof(wb_engine_var_info_chunk_t)));
   1753 
   1754     if (rc == SOC_E_NOT_FOUND) {
   1755         
   1756         LOG_ERROR(BSL_LS_SOC_COMMON,
   1757                   (BSL_META_U(unit,
   1758                               "%s\n"), soc_errmsg(rc)));
   1759     }
   1760 
   1761     return rc;
   1762 }
   1763 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1764 
   1765 
   1766 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
   1767 int soc_wb_engine_dnx_init_buffer(int unit, int engine_id, int buffer_id, uint8 is_reinit)
   1768 {
   1769     int                                rc = SOC_E_NONE;
   1770     uint32                             size;
   1771     soc_wb_engine_buffer_info_t       *buffer;
   1772     int                               *var_ndx;
   1773 
   1774     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, buffer_id);
   1775 
   1776     var_ndx = sal_alloc(sizeof(int)*buffer->variable_num, "tmp variables index copy of the buffer");
   1777     if (var_ndx == NULL) {
   1778         return SOC_E_MEMORY;
   1779     }
   1780     sal_memset(var_ndx, 0x0, sizeof(int)*buffer->variable_num);
   1781 
   1782     rc = _wb_engine_var_index_search(unit, engine_id, buffer_id, var_ndx);
   1783     if (rc != SOC_E_NONE) {
   1784         sal_free(var_ndx);
   1785         return rc;
   1786     }
   1787 
   1788     /* calculate offsets corresponding to current version */
   1789     rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, buffer->version, var_ndx);
   1790     if (SOC_FAILURE(rc)) {
   1791         LOG_ERROR(BSL_LS_SOC_COMMON,
   1792                   (BSL_META_U(unit,
   1793                               "%s - failed to calculate offsets (dnx)\n"), soc_errmsg(rc)));
   1794         sal_free(var_ndx);
   1795         return rc;
   1796     }
   1797 
   1798     if (SOC_WARM_BOOT(unit)) {
   1799         buffer->init_done = TRUE;
   1800         sal_free(var_ndx);
   1801         return rc;
   1802     }
   1803     size = buffer->size;
   1804 
   1805     /* don't allow reinit in dnx(f) */
   1806     assert (!is_reinit);
   1807 
   1808     if (!SOC_WARM_BOOT(unit)) {
   1809         rc = sw_state_wb_engine.buffer.instance.alloc(unit, engine_id, buffer_id, size);
   1810     }
   1811 
   1812     if (SOC_FAILURE(rc)) {
   1813         LOG_ERROR(BSL_LS_SOC_COMMON,
   1814                   (BSL_META_U(unit,
   1815                               "%s failed to alloc buffer in sw state\n"), soc_errmsg(rc)));
   1816         sal_free(var_ndx);
   1817         return rc;
   1818     }
   1819 
   1820     buffer->init_done = TRUE;
   1821 
   1822     sal_free(var_ndx);
   1823     return rc;
   1824 }
   1825 #endif /* defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) */
   1826 
   1827 int soc_wb_engine_init_buffer(int unit, int engine_id, int buffer_id, uint8 is_reinit)
   1828 {
   1829     int                                rc = SOC_E_NONE;
   1830     soc_scache_handle_t                wb_handle = 0;
   1831     int                                flags=0;
   1832     int                                already_exists;
   1833     uint32                             size;
   1834     uint16                             version;
   1835     uint16                             recovered_ver;
   1836     uint8                             *scache_ptr;
   1837     soc_wb_engine_buffer_info_t       *buffer;
   1838     soc_wb_engine_var_info_t          *variables;
   1839     int                                *var_ndx;
   1840     uint32                             nof_vars = 0;
   1841     wb_engine_vars_info_header_t      *vars_info_header;
   1842     wb_engine_var_info_chunk_t        *var_info_arr;
   1843     int                                var_str_len = 129;
   1844     int                                buff_str_len = 129;
   1845 #ifdef BCM_WARM_BOOT_SUPPORT
   1846     uint8                             *tmp_scache_copy = NULL;
   1847     uint8                              is_only_copy_workaround = 0;
   1848     uint32                             tmp_scache_size = 0;
   1849     uint32                             tmp_scache_first_offset = -1;
   1850 #endif
   1851     int i;
   1852 
   1853 #if defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT)
   1854     if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) {
   1855         return soc_wb_engine_dnx_init_buffer(unit, engine_id, buffer_id, is_reinit);
   1856     }
   1857 #endif
   1858 
   1859     variables = SOC_WB_ENGINE_VARS_INFO(unit, engine_id);
   1860     buffer = SOC_WB_ENGINE_BUFFER_INFO(unit, engine_id, buffer_id);
   1861     version = buffer->version;
   1862    
   1863     SOC_WB_ENGINE_SCACHE_HANDLE_SET(wb_handle, unit, engine_id, buffer->buffer_name);
   1864 
   1865     var_ndx = sal_alloc(sizeof(int)*buffer->variable_num, "tmp variables index copy of the buffer");
   1866     if (var_ndx == NULL) {
   1867         return SOC_E_MEMORY;
   1868     }
   1869     sal_memset(var_ndx, 0x0, sizeof(int)*buffer->variable_num);
   1870 
   1871     rc = _wb_engine_var_index_search(unit, engine_id, buffer_id, var_ndx);
   1872     if (rc != SOC_E_NONE) {
   1873         sal_free(var_ndx);
   1874         return rc;
   1875     }
   1876 
   1877 #ifdef BCM_WARM_BOOT_SUPPORT
   1878     if (SOC_WARM_BOOT(unit)) {
   1879          size = 0;
   1880          rc = soc_wb_engine_scache_ptr_get(unit, engine_id, wb_handle, socWbEngineScacheRetreive, flags,
   1881                                      &size, &scache_ptr, version, &recovered_ver, &already_exists);
   1882     }
   1883     if (SOC_WARM_BOOT(unit) &&
   1884         (!SOC_FAILURE(rc) || (buffer->is_added_after_relase == SOC_WB_ENGINE_PRE_RELEASE))) {
   1885         /* warmboot */
   1886         /* buffers that were added after the release (i.e not on development branch) need to be added with
   1887          * WB_ENGINE_POST_RELEASE, these buffer will perform cold-boot when ISSUing from a version where they
   1888          * did not exist.
   1889          * NOTE!! - still need to adress the issue that the module init itself runs under warmboot flag and might 
   1890          * not initialize some or all of it components. 
   1891          * in order to solve it, the mdule can read the old version number from a destined register on the device and act 
   1892          * according to it (e.g coldboot the module even if in WB in case it didnt exist in previous version)
   1893          */
   1894 
   1895         if (SOC_FAILURE(rc)) {
   1896             LOG_ERROR(BSL_LS_SOC_COMMON,
   1897                       (BSL_META_U(unit,
   1898                                   "%s\n"), soc_errmsg(rc)));
   1899             sal_free(var_ndx);
   1900             return rc;
   1901         }
   1902 
   1903         buffer->scache_ptr = scache_ptr;
   1904 
   1905         /* calculate offsets corresponding to buffer's version in scache */
   1906         rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, recovered_ver, var_ndx);
   1907         if (SOC_FAILURE(rc)) {
   1908             LOG_ERROR(BSL_LS_SOC_COMMON,
   1909                       (BSL_META_U(unit,
   1910                                   "%s\n"), soc_errmsg(rc)));
   1911             sal_free(var_ndx);
   1912             return rc;
   1913         }
   1914 
   1915         /* compare the buffer info's header to the current variable layout to detect missing ISSU implementation */
   1916         vars_info_header = (wb_engine_vars_info_header_t *) buffer->scache_ptr;
   1917         var_info_arr = (wb_engine_var_info_chunk_t *) (buffer->scache_ptr + sizeof(wb_engine_vars_info_header_t));
   1918 
   1919         /* if version is the same as the saved version, layout should be identical */
   1920         if (version == recovered_ver) {
   1921                 if (sal_strcmp(vars_info_header->buffer_name, buffer->buff_string)){
   1922                     LOG_ERROR(BSL_LS_SOC_COMMON,
   1923                               (BSL_META_U(unit,
   1924                                           "engine_id:%d wb engine buffer %d - buffer name has changed after warm reboot! (%s --> %s)\n"), 
   1925                                engine_id, buffer_id, vars_info_header->buffer_name, buffer->buff_string));
   1926                     sal_free(var_ndx);
   1927                     return SOC_E_INTERNAL;
   1928                 }
   1929 
   1930                 for (i = 0; i < buffer->variable_num; i++) {
   1931                     if (variables[var_ndx[i]].buffer == buffer_id &&
   1932                         variables[var_ndx[i]].version_added <= version &&
   1933                         variables[var_ndx[i]].version_removed > version)
   1934                     {
   1935                         if (sal_strcmp(var_info_arr[nof_vars].name, variables[var_ndx[i]].var_string)) {
   1936                             LOG_ERROR(BSL_LS_SOC_COMMON,
   1937                                       (BSL_META_U(unit,
   1938                                                   "engine_id:%d wb engine buffer %d var %d - variable name has changed after warm reboot! (%s --> %s)\n"), 
   1939                                        engine_id, buffer_id, var_ndx[i], var_info_arr[nof_vars].name, variables[var_ndx[i]].var_string));
   1940                             sal_free(var_ndx);
   1941                             return SOC_E_INTERNAL;
   1942                         }
   1943 
   1944                         if ((var_info_arr[nof_vars].data_size != variables[var_ndx[i]].data_size) && !buffer->is_dynamic) {
   1945                             LOG_ERROR(BSL_LS_SOC_COMMON,
   1946                                       (BSL_META_U(unit,
   1947                                                   "engine_id:%d wb engine buffer %d var %d (%s)- variable size has changed after warm reboot! (%d --> %d)\n"), 
   1948                                        engine_id, buffer_id, var_ndx[i], var_info_arr[nof_vars].name, var_info_arr[nof_vars].data_size, variables[var_ndx[i]].data_size));
   1949                             sal_free(var_ndx);
   1950                             return SOC_E_INTERNAL;
   1951                         }
   1952 
   1953                         if ((var_info_arr[nof_vars].nof_items_in_array != (variables[var_ndx[i]].inner_arr_length * variables[var_ndx[i]].outer_arr_length)) && !buffer->is_dynamic) {
   1954                             LOG_ERROR(BSL_LS_SOC_COMMON,
   1955                                       (BSL_META_U(unit,
   1956                                                   "engine_id:%d wb engine buffer %d var %d (%s)- array length has changed after warm reboot! (%d --> %d)\n"), 
   1957                                        engine_id, buffer_id, var_ndx[i], var_info_arr[nof_vars].name,
   1958                                        var_info_arr[nof_vars].nof_items_in_array, (variables[var_ndx[i]].inner_arr_length * variables[var_ndx[i]].outer_arr_length)));
   1959                             sal_free(var_ndx);
   1960                             return SOC_E_INTERNAL;
   1961                         }
   1962 
   1963                         nof_vars++;
   1964                     }
   1965                 }
   1966         }
   1967 
   1968         /*ISSU is_only_copy workaround - change the orig_data to point to a temporary buffer*/
   1969         is_only_copy_workaround = buffer->is_only_copy;
   1970         if (version != recovered_ver && is_only_copy_workaround) {
   1971             /* calculate offsets according to current buffer's version (only need to know the size)*/
   1972             rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, buffer->version, var_ndx);
   1973             if (SOC_FAILURE(rc)) {
   1974                 LOG_ERROR(BSL_LS_SOC_COMMON,
   1975                           (BSL_META_U(unit,
   1976                                       "%s\n"), soc_errmsg(rc)));
   1977                 sal_free(var_ndx);
   1978                 return rc;
   1979             }
   1980 
   1981             /* alloc a temporary buffer with the offsets layed out as the new version */
   1982             tmp_scache_size = buffer->size;
   1983             tmp_scache_copy = sal_alloc(tmp_scache_size, "tmp scache buffer copy");
   1984             if (tmp_scache_copy == NULL) {
   1985                 sal_free(var_ndx);
   1986                 return SOC_E_MEMORY;
   1987             }
   1988 
   1989             /* change the orig_data to point to the temporary buffer */
   1990             for (i = 0; i < buffer->variable_num; i++) {
   1991                 if (variables[var_ndx[i]].buffer != buffer_id) {
   1992                     /*only consider variables of current buffer*/
   1993                     continue;
   1994                 }
   1995                 if (tmp_scache_first_offset == -1) {
   1996                     tmp_scache_first_offset = variables[var_ndx[i]].offset;
   1997                 }
   1998                 variables[var_ndx[i]].data_orig = tmp_scache_copy + variables[var_ndx[i]].offset;
   1999             }
   2000 
   2001             /* also temporarily mark this buffer as not only copy (and revert it later) */
   2002             buffer->is_only_copy = 0x0;
   2003 
   2004             /* calculate offsets corresponding to buffer's version in scache */
   2005             rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, recovered_ver, var_ndx);
   2006             if (SOC_FAILURE(rc)) {
   2007                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2008                           (BSL_META_U(unit,
   2009                                       "%s\n"), soc_errmsg(rc)));
   2010                 sal_free(var_ndx);
   2011                 sal_free(tmp_scache_copy);
   2012                 return rc;
   2013             }
   2014         }
   2015 
   2016 
   2017         /* restore state (ISSU is handled here)*/
   2018         rc = soc_wb_engine_restore(unit, engine_id, buffer_id, recovered_ver, var_ndx);
   2019         if (SOC_FAILURE(rc)) {
   2020             LOG_ERROR(BSL_LS_SOC_COMMON,
   2021                       (BSL_META_U(unit,
   2022                                   "%s\n"), soc_errmsg(rc)));
   2023             sal_free(var_ndx);
   2024             sal_free(tmp_scache_copy);
   2025             return rc;
   2026         }
   2027 
   2028         /* if version difference save current (upgraded) state */
   2029         if (version != recovered_ver) {
   2030 
   2031             /* recalculate offsets according to current buffer's version*/
   2032             rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, buffer->version, var_ndx);
   2033             if (SOC_FAILURE(rc)) {
   2034                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2035                           (BSL_META_U(unit,
   2036                                       "%s\n"), soc_errmsg(rc)));
   2037                 sal_free(var_ndx);
   2038                 sal_free(tmp_scache_copy);
   2039                 return rc;
   2040             }
   2041 
   2042             size = buffer->size;
   2043             rc = soc_wb_engine_scache_ptr_get(unit, engine_id, wb_handle, socWbEngineScacheRealloc, flags,
   2044                                 &size, &scache_ptr, version, &recovered_ver, &already_exists);
   2045             if (SOC_FAILURE(rc)) {
   2046                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2047                       (BSL_META_U(unit,
   2048                                   "%s\n"), soc_errmsg(rc)));
   2049                 sal_free(var_ndx);
   2050                 sal_free(tmp_scache_copy);
   2051                 return rc;
   2052             }
   2053             buffer->scache_ptr = scache_ptr;
   2054 
   2055             /*ISSU is_only_copy workaround cntd. - copy data from temporary buffer*/
   2056             if (is_only_copy_workaround) {
   2057                 sal_memcpy(scache_ptr + tmp_scache_first_offset,
   2058                            tmp_scache_copy + tmp_scache_first_offset,
   2059                            tmp_scache_size - tmp_scache_first_offset);
   2060                 sal_free(tmp_scache_copy);
   2061 
   2062                 /* change the is_only_copy marker to be TRUE again */
   2063                 buffer->is_only_copy = 1;
   2064 
   2065                 /* change the orig_data to point be null again */
   2066                 for (i = 0; i < buffer->variable_num; i++) {
   2067                     if (variables[var_ndx[i]].buffer != buffer_id) {
   2068                         /*only consider variables of current buffer*/
   2069                         continue;
   2070                     }
   2071                     variables[var_ndx[i]].data_orig = NULL;
   2072                 }
   2073             }
   2074 
   2075             /* mark buffer state as dirty */
   2076             buffer->dirty = TRUE;
   2077 
   2078             /* turn on dirty bit for the unit (data will be commited upon global sync request) */
   2079             SOC_WB_ENGINE_UNIT_DIRTY_BIT_SET(unit);
   2080         }
   2081     }
   2082     else
   2083 #endif /*BCM_WARM_BOOT_SUPPORT*/
   2084      {
   2085         /* coldboot */
   2086 
   2087         /* calculate offsets corresponding to current version */
   2088         rc = soc_wb_engine_calculate_offsets(unit, engine_id, buffer_id, buffer->version, var_ndx);
   2089         if (SOC_FAILURE(rc)) {
   2090             LOG_ERROR(BSL_LS_SOC_COMMON,
   2091                       (BSL_META_U(unit,
   2092                                   "%s\n"), soc_errmsg(rc)));
   2093             sal_free(var_ndx);
   2094             return rc;
   2095         }
   2096         size = buffer->size;
   2097 
   2098         if (is_reinit) {
   2099             /* special case - is used when enabling dynamic variable in a dynamic buffer - need to resize buffer */
   2100 #ifndef BCM_WARM_BOOT_SUPPORT
   2101             /*If buffer is not in not handled by scache.c (not compiled with wb) free it here*/
   2102             sal_free(buffer->scache_ptr);
   2103 #endif
   2104             rc = soc_wb_engine_scache_ptr_get(unit, engine_id, wb_handle, socWbEngineScacheRealloc, flags,
   2105                                     &size, &scache_ptr, version, &recovered_ver, &already_exists);
   2106         }
   2107         else {
   2108             /* regular case - allocate new buffer */
   2109             rc = soc_wb_engine_scache_ptr_get(unit, engine_id, wb_handle, socWbEngineScacheCreate, flags,
   2110                                     &size, &scache_ptr, version, &recovered_ver, &already_exists);
   2111         }
   2112 
   2113         if (SOC_FAILURE(rc)) {
   2114             LOG_ERROR(BSL_LS_SOC_COMMON,
   2115                       (BSL_META_U(unit,
   2116                                   "%s\n"), soc_errmsg(rc)));
   2117             sal_free(var_ndx);
   2118             return rc;
   2119         }
   2120 
   2121         buffer->scache_ptr = scache_ptr;
   2122 
   2123         /*init the buffer to be all zeros*/
   2124         sal_memset(scache_ptr, 0x0, size);
   2125 
   2126         /* create a header describing the content of the buffer */
   2127         buffer->scache_ptr = scache_ptr;
   2128         vars_info_header = (wb_engine_vars_info_header_t *) buffer->scache_ptr;
   2129         var_info_arr = (wb_engine_var_info_chunk_t *) (buffer->scache_ptr + sizeof(wb_engine_vars_info_header_t));
   2130         for (i = 0; i < buffer->variable_num; i++) {
   2131             if (variables[var_ndx[i]].buffer == buffer_id &&
   2132                 variables[var_ndx[i]].version_added <= version &&
   2133                 variables[var_ndx[i]].version_removed > version)
   2134             {
   2135                 var_info_arr[nof_vars].data_size = variables[var_ndx[i]].data_size;
   2136                 var_info_arr[nof_vars].nof_items_in_array = variables[var_ndx[i]].inner_arr_length * variables[var_ndx[i]].outer_arr_length;
   2137                 var_str_len = sal_strlen(variables[var_ndx[i]].var_string);
   2138                 if (var_str_len < 128) {
   2139                     /* coverity[secure_coding] */
   2140                     sal_strcpy(var_info_arr[nof_vars].name, variables[var_ndx[i]].var_string);
   2141                 }
   2142                 else
   2143                 {
   2144                     LOG_ERROR(BSL_LS_SOC_COMMON,
   2145                               (BSL_META_U(unit,
   2146                                           "engine_id:%d wb engine variable %d - variable name (string) is longer than 128 chars\n"),
   2147                                engine_id, var_ndx[i]));
   2148                     sal_free(var_ndx);
   2149                     return SOC_E_PARAM;
   2150                 }
   2151                 nof_vars++;
   2152             }
   2153         }
   2154         buff_str_len = sal_strlen(buffer->buff_string);
   2155         if (buff_str_len < 128) {
   2156             /* coverity[secure_coding] */
   2157             sal_strcpy(vars_info_header->buffer_name, buffer->buff_string);
   2158         }
   2159         else
   2160         {
   2161             LOG_ERROR(BSL_LS_SOC_COMMON,
   2162                       (BSL_META_U(unit,
   2163                                   "engine_id:%d wb engine buffer %d - buffer name (string) is longer than 128 chars\n"),
   2164                        engine_id, buffer_id));
   2165             sal_free(var_ndx);
   2166             return SOC_E_PARAM;
   2167         }
   2168         vars_info_header->nof_vars = nof_vars;
   2169 
   2170         /* state should have been removed by Host. Stale State */
   2171         /* mark buffer state as dirty */
   2172         buffer->dirty = TRUE;
   2173 
   2174         /* writing to persistent storage initiated by bcm_init() */
   2175         SOC_WB_ENGINE_UNIT_DIRTY_BIT_SET(unit);
   2176     }
   2177 
   2178     buffer->init_done = TRUE;
   2179     sal_free(var_ndx);
   2180     return rc;
   2181 }
   2182 
   2183 STATIC int
   2184 _wb_engine_var_index_search(int unit, int engine_id, int buffer_id, int *var_ndx)
   2185 {
   2186     soc_wb_engine_var_info_t     *variables;
   2187     int i, index = 0;
   2188 
   2189     variables = SOC_WB_ENGINE_VARS_INFO(unit, engine_id);
   2190     if(variables == NULL) {
   2191         LOG_ERROR(BSL_LS_SOC_COMMON,
   2192                   (BSL_META_U(unit,
   2193                               "engine_id:%d wb engine variable table is not initialized\n"),
   2194                    engine_id));
   2195         return SOC_E_RESOURCE;
   2196     }
   2197 
   2198     for (i = 0; i < soc_wb_engine_nof_vars[unit][engine_id]; i++) {
   2199         /* The buffer_id 0 is used by valid variable. The buffer_id
   2200            of invalid variable is also 0. 'variables[i].version_added' is used
   2201            to skip invalid variable.
   2202          */
   2203         if ((variables[i].buffer != buffer_id) || (variables[i].version_added == 0)) {
   2204             /*only consider variables of current buffer*/
   2205             continue;
   2206         }
   2207         var_ndx[index++] = i;
   2208     }
   2209 
   2210     return SOC_E_NONE;
   2211 }
   2212