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