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