sramscan.c (21912B)
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 * SRAM Memory Error Scan 7 * 8 * This is an optional module that can be used to detect and correct 9 * parity or ECC errors in certain static hardware memories (SRAM memories). 10 * For SRAM memory, scan or scrub is not very critical. But performing SRAM 11 * scan has following benefit: ensuring that entries are proactively corrected 12 * prior to an actual hardware/packet lookup. 13 * Additional CPU time is required to do the scanning. Table DMA is 14 * used to reduce this overhead. The application may choose the overall 15 * scan rate in entries/sec. 16 * 17 * similar to TCAM scan variables, the following configure variables will 18 * be added to support SRAM scan. 19 * 20 * ? sram_scan_chunk_size 21 * To specify the number of table entries to be retrieved at a time during 22 * SRAM memory scanning. 23 24 * ? sram_scan_enable 25 * To control to automatically run background SRAM memory scan. 26 * 27 * ? sram_scan_interval 28 * To specify the SRAM scan repeat interval. 29 * 30 * ? sram_scan_rate 31 * To specify the SRAM scan rate in terms of entries per pass. 32 * 33 * ? sram_scan_thread_pri 34 * To specify the priority of the SRAM scanning and error correction thread. 35 * 36 37 * File: sramscan.c 38 * Purpose: scan sram memories to detect parity error in the chip. 39 * Requires: sal/soc/shared layer 40 */ 41 42 #include <shared/bsl.h> 43 #include <sal/core/libc.h> 44 #include <soc/mem.h> 45 #include <soc/debug.h> 46 #include <soc/cmic.h> 47 #include <soc/error.h> 48 #include <soc/drv.h> 49 #include <soc/l2x.h> 50 51 #ifdef BCM_SRAM_SCAN_SUPPORT 52 53 #if defined(BCM_TRIDENT2_SUPPORT) 54 #include <soc/trident2.h> 55 #endif /* BCM_TRIDENT2_SUPPORT */ 56 #if defined(BCM_TOMAHAWK_SUPPORT) 57 #include <soc/tomahawk.h> 58 #endif /* BCM_TOMAHAWK_SUPPORT */ 59 #if defined(BCM_APACHE_SUPPORT) 60 #include <soc/apache.h> 61 #endif /* BCM_APACHE_SUPPORT */ 62 #if defined(BCM_MONTEREY_SUPPORT) 63 #include <soc/monterey.h> 64 #endif /* BCM_MONTEREY_SUPPORT */ 65 #if defined(BCM_TRIDENT3_SUPPORT) 66 #include <soc/trident3.h> 67 #endif 68 #if defined(BCM_TOMAHAWK3_SUPPORT) 69 #include <soc/tomahawk3.h> 70 #endif /* BCM_TOMAHAWK3_SUPPORT */ 71 72 #if defined(ALPM_ENABLE) 73 #include <soc/l3x.h> 74 #define _ALPM_LOCK(unit) \ 75 L3_LOCK(unit); \ 76 _alpm_lock = 1 77 #define _ALPM_UNLOCK(unit) \ 78 if (_alpm_lock) { \ 79 L3_UNLOCK(unit); \ 80 } 81 #else 82 #define _ALPM_LOCK(unit) 83 #define _ALPM_UNLOCK(unit) 84 #endif /* ALPM_ENABLE */ 85 86 87 STATIC void _soc_sram_scan_thread(void *unit_vp); 88 89 /* 90 * Function: 91 * soc_sram_scan_running 92 * Purpose: 93 * Boolean to indicate if the sram scan thread is running 94 * Parameters: 95 * unit - unit number. 96 * rate - (OUT) if non-NULL, number of entries scanned per interval 97 * interval - (OUT) if non-NULL, receives current wake-up interval. 98 */ 99 100 int 101 soc_sram_scan_running(int unit, int *rate, sal_usecs_t *interval) 102 { 103 soc_control_t *soc = SOC_CONTROL(unit); 104 105 if (soc->sram_scan_pid != SAL_THREAD_ERROR) { 106 if (rate != NULL) { 107 *rate = soc->sram_scan_rate; 108 } 109 if (interval != NULL) { 110 *interval = soc->sram_scan_interval; 111 } 112 } 113 114 return (soc->sram_scan_pid != SAL_THREAD_ERROR); 115 } 116 117 /* 118 * Function: 119 * soc_sram_scan_start 120 * Purpose: 121 * Start sram scan thread 122 * Parameters: 123 * unit - unit number. 124 * rate - maximum number of entries to scan each time thread runs 125 * interval - how often the thread should run (microseconds). 126 * Returns: 127 * SOC_E_MEMORY if can't create thread. 128 */ 129 130 int 131 soc_sram_scan_start(int unit, int rate, sal_usecs_t interval) 132 { 133 soc_control_t *soc = SOC_CONTROL(unit); 134 int pri; 135 136 if (rate <= 0) { 137 return (SOC_E_PARAM); 138 } 139 140 if (soc->sram_scan_pid != SAL_THREAD_ERROR) { 141 SOC_IF_ERROR_RETURN(soc_sram_scan_stop(unit)); 142 } 143 sal_snprintf(soc->sram_scan_name, sizeof (soc->sram_scan_name), 144 "bcmSRAM_SCAN.%d", unit); 145 soc->sram_scan_rate = rate; 146 soc->sram_scan_interval = interval; 147 if (interval == 0) { 148 return SOC_E_NONE; 149 } 150 if (soc->sram_scan_pid == SAL_THREAD_ERROR) { 151 pri = soc_property_get(unit, spn_SRAM_SCAN_THREAD_PRI, 50); 152 soc->sram_scan_pid = sal_thread_create(soc->sram_scan_name, 153 SAL_THREAD_STKSZ, 154 pri, 155 _soc_sram_scan_thread, 156 INT_TO_PTR(unit)); 157 if (soc->sram_scan_pid == SAL_THREAD_ERROR) { 158 LOG_ERROR(BSL_LS_SOC_COMMON, 159 (BSL_META_U(unit, 160 "soc_sram_scan_start: Could not start sram_scan thread\n"))); 161 return SOC_E_MEMORY; 162 } 163 } 164 return SOC_E_NONE; 165 } 166 167 /* 168 * Function: 169 * soc_sram_scan_stop 170 * Purpose: 171 * Stop sram scan thread 172 * Parameters: 173 * unit - unit number. 174 * Returns: 175 * SOC_E_XXX 176 */ 177 178 int 179 soc_sram_scan_stop(int unit) 180 { 181 soc_control_t *soc = SOC_CONTROL(unit); 182 int rv = SOC_E_NONE; 183 soc_timeout_t to; 184 int tosec; 185 186 soc->sram_scan_interval = 0; /* Request exit */ 187 if (soc->sram_scan_pid != SAL_THREAD_ERROR) { 188 sal_sem_give(soc->sram_scan_notify); 189 190 tosec = 5; 191 #ifdef PLISIM 192 if (SAL_BOOT_PLISIM) { 193 tosec = 15; 194 } 195 #endif 196 soc_timeout_init(&to, tosec * 1000000, 0); 197 while (soc->sram_scan_pid != SAL_THREAD_ERROR) { 198 if (soc_timeout_check(&to)) { 199 LOG_ERROR(BSL_LS_SOC_COMMON, 200 (BSL_META_U(unit, 201 "soc_sram_scan_stop: thread will not exit\n"))); 202 rv = SOC_E_INTERNAL; 203 break; 204 } 205 } 206 } 207 return rv; 208 } 209 210 STATIC void 211 _soc_sram_scan_info_get (int unit, soc_mem_t mem, int blk, int *num_pipe, int *ser_flags) 212 { 213 soc_acc_type_t mem_acc_type; 214 215 if (NUM_PIPE(unit) == 2) { 216 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_IPIPE || 217 SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_EPIPE) { 218 mem_acc_type = SOC_MEM_ACC_TYPE(unit, mem); 219 switch (mem_acc_type) { 220 case _SOC_ACC_TYPE_PIPE_Y: 221 *num_pipe = 1; 222 ser_flags[0] = _SOC_SER_FLAG_MULTI_PIPE | 223 _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 224 if (!soc_mem_dmaable(unit, mem, blk)) { 225 ser_flags[0] |= _SOC_SER_FLAG_NO_DMA; 226 } 227 break; 228 case _SOC_ACC_TYPE_PIPE_X: 229 *num_pipe = 1; 230 ser_flags[0] = _SOC_SER_FLAG_MULTI_PIPE | 231 _SOC_MEM_ADDR_ACC_TYPE_PIPE_X; 232 if (!soc_mem_dmaable(unit, mem, blk)) { 233 ser_flags[0] |= _SOC_SER_FLAG_NO_DMA; 234 } 235 break; 236 default: 237 *num_pipe = 2; 238 ser_flags[0] = _SOC_SER_FLAG_MULTI_PIPE | 239 _SOC_MEM_ADDR_ACC_TYPE_PIPE_X; 240 ser_flags[1] = _SOC_SER_FLAG_MULTI_PIPE | 241 _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 242 if (!soc_mem_dmaable(unit, mem, blk)) { 243 ser_flags[0] |= _SOC_SER_FLAG_NO_DMA; 244 ser_flags[1] |= _SOC_SER_FLAG_NO_DMA; 245 } 246 break; 247 } 248 } else { 249 *num_pipe = 1; 250 ser_flags[0] = 0; 251 if (!soc_mem_dmaable(unit, mem, blk)) { 252 ser_flags[0] |= _SOC_SER_FLAG_NO_DMA; 253 } 254 } 255 #if defined(BCM_TRIDENT_SUPPORT) 256 if ((SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) && 257 (mem == EGR_VLANm)) { 258 *num_pipe = 1; 259 ser_flags[0] = _SOC_SER_FLAG_NO_DMA; 260 } 261 #endif 262 } else { 263 *num_pipe = 1; 264 if (SOC_IS_APACHE(unit) && (mem == EGR_VLANm)) { 265 ser_flags[0] = _SOC_SER_FLAG_NO_DMA; 266 } else { 267 ser_flags[0] = 0; 268 } 269 if (!soc_mem_dmaable(unit, mem, blk)) { 270 ser_flags[0] |= _SOC_SER_FLAG_NO_DMA; 271 } 272 } 273 } 274 275 STATIC int 276 _soc_mem_is_eligible_for_sramscan (int unit, soc_mem_t mem) 277 { 278 if (!SOC_MEM_IS_VALID(unit, mem)) { 279 return FALSE; 280 } 281 if (soc_mem_index_count(unit, mem) == 0) { 282 return FALSE; 283 } 284 if (soc_feature(unit, soc_feature_ser_parity)) { 285 if ((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_SER_ENGINE)) { 286 #if defined(BCM_ESW_SUPPORT) 287 LOG_VERBOSE(BSL_LS_SOC_SER, 288 (BSL_META_U(unit, 289 "sram_scrub: skipping mem %s (SOC_MEM_FLAG_SER_ENGINE is set)\n"), 290 SOC_MEM_NAME(unit, mem))); 291 #endif 292 return FALSE; 293 } 294 } 295 #ifdef BCM_ESW_SUPPORT 296 if(TRUE == soc_mem_is_mapped_mem(unit, mem)) { 297 LOG_VERBOSE(BSL_LS_SOC_SER, 298 (BSL_META_U(unit, 299 "sram_scrub: skipping mem %s (soc_mem_is_mapped_mem)\n"), 300 SOC_MEM_NAME(unit, mem))); 301 return FALSE; 302 } 303 #endif 304 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT 305 if(TRUE == soc_mem_is_cache_only(unit, mem)) { 306 LOG_VERBOSE(BSL_LS_SOC_SER, 307 (BSL_META_U(unit, 308 "sram_scrub: skipping mem %s (soc_mem_is_cache_only)\n"), 309 SOC_MEM_NAME(unit, mem))); 310 return FALSE; 311 } 312 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */ 313 314 if (SOC_MEM_SER_CORRECTION_TYPE(unit, mem) == 0) { 315 #if defined(BCM_ESW_SUPPORT) 316 LOG_VERBOSE(BSL_LS_SOC_SER, 317 (BSL_META_U(unit, 318 "sram_scrub: skipping mem %s (ERR_CORRECTION = 0)\n"), 319 SOC_MEM_NAME(unit, mem))); 320 #endif 321 return FALSE; 322 } 323 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_SER_ENTRY_CLEAR) { 324 #if defined(BCM_ESW_SUPPORT) 325 LOG_VERBOSE(BSL_LS_SOC_SER, 326 (BSL_META_U(unit, 327 "sram_scrub: skipping mem %s (SER_RESPONSE = SER_ENTRY_CLEAR)\n"), 328 SOC_MEM_NAME(unit, mem))); 329 #endif 330 return FALSE; 331 } 332 if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_SER_PARITY_ENABLE_SKIP) { 333 #if defined(BCM_ESW_SUPPORT) 334 LOG_VERBOSE(BSL_LS_SOC_SER, 335 (BSL_META_U(unit, 336 "sram_scrub: skipping mem %s (SOC_MEM_FLAG_SER_PARITY_ENABLE_SKIP is set)\n"), 337 SOC_MEM_NAME(unit, mem))); 338 #endif 339 return FALSE; 340 } 341 #if defined(BCM_TOMAHAWK_SUPPORT) 342 if (SOC_IS_TOMAHAWKX(unit) && soc_th_check_scrub_skip(unit, mem, 0)) { 343 return FALSE; 344 } 345 #endif 346 #if defined(BCM_TOMAHAWK3_SUPPORT) 347 /* In TH3, the flag SOC_MEM_FLAG_SER_ENGINE isn't set due to we use 348 HW tcam scan engine. Hence using SOC_MEM_FLAG_CAM to check if 349 the memory is tcam */ 350 if (SOC_IS_TOMAHAWK3(unit) && soc_mem_is_cam(unit, mem)) { 351 return FALSE; 352 } 353 #endif 354 #if defined(BCM_TRIDENT3_SUPPORT) 355 if (SOC_IS_TRIDENT3X(unit) && soc_td3_check_scrub_skip(unit, mem, 0)) { 356 return FALSE; 357 } 358 #endif 359 #if defined(BCM_TRIDENT2_SUPPORT) 360 if (SOC_IS_TD2P_TT2P(unit) && 361 soc_trident2_ser_test_skip_check(unit, mem, _SOC_ACC_TYPE_PIPE_ANY)) { 362 return FALSE; 363 } 364 #endif 365 #if defined(BCM_MONTEREY_SUPPORT) 366 if (SOC_IS_MONTEREY(unit) && 367 soc_monterey_ser_test_skip_check(unit, mem)) { 368 return FALSE; 369 } 370 #endif 371 #if defined(BCM_APACHE_SUPPORT) 372 if (SOC_IS_APACHE(unit) && 373 soc_apache_ser_test_skip_check(unit, mem)) { 374 return FALSE; 375 } 376 #endif 377 if (!soc_mem_cache_get(unit, mem, MEM_BLOCK_ALL)) { 378 /* By default, we don't want to scan the memories which are not cacheable. 379 * Exceptions to this rule are specified by chip-specific functions below. 380 */ 381 #if defined(BCM_TOMAHAWK_SUPPORT) 382 if (SOC_IS_TOMAHAWKX(unit)) { 383 if (soc_th_mem_is_eligible_for_scan(unit, mem)) { 384 return TRUE; 385 } 386 } 387 #endif /* BCM_TOMAHAWK_SUPPORT */ 388 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 389 if (SOC_IS_TD2P_TT2P(unit)) { 390 if (soc_trident2p_mem_is_eligible_for_scan(unit, mem)) { 391 return TRUE; 392 } 393 } 394 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 395 #if defined(BCM_MONTEREY_SUPPORT) 396 if (SOC_IS_MONTEREY(unit)) { 397 if (soc_monterey_mem_is_eligible_for_scan(unit, mem)) { 398 return TRUE; 399 } 400 } 401 #endif 402 #if defined(BCM_APACHE_SUPPORT) 403 if (SOC_IS_APACHE(unit)) { 404 if (soc_apache_mem_is_eligible_for_scan(unit, mem)) { 405 return TRUE; 406 } 407 } 408 #endif /* BCM_APACHE_SUPPORT */ 409 #if defined(BCM_ESW_SUPPORT) 410 LOG_VERBOSE(BSL_LS_SOC_SER, 411 (BSL_META_U(unit, 412 "sram_scrub: skipping mem %s (NOT_CACHEABLE)\n"), 413 SOC_MEM_NAME(unit, mem))); 414 #endif /* BCM_ESW_SUPPORT */ 415 return FALSE; 416 } 417 return TRUE; 418 } 419 420 /* 421 * Function: 422 * _soc_sram_scan_thread (internal) 423 * Purpose: 424 * Thread for scrubing SRAM parity error 425 * Parameters: 426 * unit_vp - StrataSwitch unit # (as a void *). 427 * Returns: 428 * Nothing 429 * Notes: 430 * Exits when sram_scan_interval is set to zero and semaphore is given. 431 */ 432 433 STATIC void 434 _soc_sram_scan_thread(void *unit_vp) 435 { 436 int unit = PTR_TO_INT(unit_vp); 437 soc_control_t *soc = SOC_CONTROL(unit); 438 int rv; 439 int interval; 440 int chunk_size; 441 int entries_interval; 442 uint32 *read_buf = NULL; 443 soc_mem_t mem; 444 int blk; 445 int idx, idx_count; 446 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 447 sal_thread_t thread; 448 int pipe, num_pipe; 449 int ser_flags[SOC_MAX_NUM_PIPES]; 450 #if defined(ALPM_ENABLE) 451 uint8 _alpm_lock = 0; 452 #endif /* ALPM_ENABLE */ 453 454 chunk_size = soc_property_get(unit, spn_SRAM_SCAN_CHUNK_SIZE, 256); 455 456 read_buf = soc_cm_salloc(unit, chunk_size * SOC_MAX_MEM_WORDS * 4, 457 "sram_scan_new"); 458 459 if (read_buf == NULL) { 460 LOG_ERROR(BSL_LS_SOC_COMMON, 461 (BSL_META_U(unit, 462 "soc_sram_scan_thread: not enough memory, exiting\n"))); 463 soc_event_generate(unit, SOC_SWITCH_EVENT_THREAD_ERROR, 464 SOC_SWITCH_EVENT_THREAD_SRAMSCAN, __LINE__, 465 SOC_E_MEMORY); 466 goto cleanup_exit; 467 } 468 469 /* 470 * Implement the sleep using a semaphore timeout so if the task is 471 * requested to exit, it can do so immediately. 472 */ 473 474 sal_memset(&ser_flags, 0, sizeof(ser_flags)); 475 entries_interval = 0; 476 thread = sal_thread_self(); 477 thread_name[0] = 0; 478 sal_thread_name(thread, thread_name, sizeof (thread_name)); 479 while ((interval = soc->sram_scan_interval) != 0) { 480 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 481 if (soc->sram_scan_interval == 0) { 482 break; 483 } 484 if (!_soc_mem_is_eligible_for_sramscan(unit, mem)) { 485 continue; 486 } 487 #ifdef BCM_ESW_SUPPORT 488 LOG_VERBOSE(BSL_LS_SOC_SER, 489 (BSL_META_U(unit, 490 "sram_scrub: now scrubbing mem %s\n"), 491 SOC_MEM_NAME(unit, mem))); 492 #endif 493 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 494 if (soc->sram_scan_interval == 0) { 495 break; 496 } 497 num_pipe = 0; /* re-init num_pipe for every mem */ 498 #if defined(BCM_TOMAHAWK_SUPPORT) 499 if (SOC_IS_TOMAHAWKX(unit)) { 500 soc_th_mem_scan_info_get(unit, mem, blk, &num_pipe, ser_flags); 501 } else 502 #endif /* BCM_TOMAHAWK_SUPPORT */ 503 #if defined(BCM_TRIDENT3_SUPPORT) 504 if (SOC_IS_TRIDENT3X(unit)) { 505 soc_td3_mem_scan_info_get(unit, mem, blk, &num_pipe, ser_flags); 506 } else 507 #endif 508 { 509 _soc_sram_scan_info_get(unit, mem, blk, &num_pipe, ser_flags); 510 } 511 for (idx = soc_mem_index_min(unit, mem); 512 idx <= soc_mem_index_max(unit, mem); 513 idx += idx_count) { 514 if (soc->sram_scan_interval == 0) { 515 break; 516 } 517 idx_count = soc_mem_index_count(unit, mem) - idx; 518 if (idx_count > chunk_size) { 519 idx_count = chunk_size; 520 } 521 if (entries_interval + idx_count > soc->sram_scan_rate) { 522 idx_count = soc->sram_scan_rate - entries_interval; 523 } 524 525 if (mem == L2_ENTRY_ONLYm || 526 mem == L2_ENTRY_ONLY_ECCm) { 527 SOC_L2X_MEM_LOCK(unit); 528 } else if (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 529 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 530 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_PAIR_128m || 531 mem == L3_DEFIP_ALPM_RAWm || mem == L3_DEFIP_ALPM_ECCm || 532 mem == L3_DEFIPm || mem == L3_DEFIP_AUX_TABLEm) { 533 _ALPM_LOCK(unit); 534 } else { 535 MEM_LOCK(unit, mem); 536 } 537 538 for (pipe = 0; pipe < num_pipe; pipe++) { 539 #if defined(BCM_ESW_SUPPORT) 540 LOG_VERBOSE(BSL_LS_SOC_SER, 541 (BSL_META_U(unit, 542 "sram_scan: will now scrub mem %s, pipe %d, range %0d - %0d, ser_flags 0x%x\n"), 543 SOC_MEM_NAME(unit, mem), pipe, 544 idx, idx + idx_count - 1, 545 ser_flags[pipe])); 546 547 if (TRUE == soc_mem_is_shared_mem(unit, mem)) { 548 LOG_VERBOSE(BSL_LS_SOC_SER, 549 (BSL_META_U(unit, 550 "sram_scrub: skipping mem %s (soc_mem_is_shared_mem)\n"), 551 SOC_MEM_NAME(unit, mem))); 552 continue; 553 } 554 #endif 555 #ifdef BCM_TOMAHAWK3_SUPPORT 556 if (SOC_IS_TOMAHAWK3(unit) && 557 soc_th3_ser_pipe_skip(unit, pipe)) { 558 continue; 559 } 560 #endif 561 rv = soc_mem_ser_read_range(unit, mem, blk, idx, idx + idx_count - 1, 562 ser_flags[pipe], read_buf); 563 if (rv < 0) { 564 LOG_ERROR(BSL_LS_SOC_COMMON, 565 (BSL_META_U(unit, 566 "AbnormalThreadExit:%s, read failed: %s\n"), 567 thread_name, 568 soc_errmsg(rv))); 569 570 soc_event_generate(unit, 571 SOC_SWITCH_EVENT_THREAD_ERROR, 572 SOC_SWITCH_EVENT_THREAD_SRAMSCAN, 573 __LINE__, rv); 574 if (mem == L2_ENTRY_ONLYm || 575 mem == L2_ENTRY_ONLY_ECCm) { 576 SOC_L2X_MEM_UNLOCK(unit); 577 } else if (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 578 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 579 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_PAIR_128m || 580 mem == L3_DEFIP_ALPM_RAWm || mem == L3_DEFIP_ALPM_ECCm || 581 mem == L3_DEFIPm || mem == L3_DEFIP_AUX_TABLEm) { 582 _ALPM_UNLOCK(unit); 583 } else 584 { 585 MEM_UNLOCK(unit, mem); 586 } 587 goto cleanup_exit; 588 } 589 } 590 if (mem == L2_ENTRY_ONLYm || 591 mem == L2_ENTRY_ONLY_ECCm) { 592 SOC_L2X_MEM_UNLOCK(unit); 593 } else if (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 594 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 595 mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_PAIR_128m || 596 mem == L3_DEFIP_ALPM_RAWm || mem == L3_DEFIP_ALPM_ECCm || 597 mem == L3_DEFIPm || mem == L3_DEFIP_AUX_TABLEm) { 598 _ALPM_UNLOCK(unit); 599 } else 600 { 601 MEM_UNLOCK(unit, mem); 602 } 603 604 entries_interval += num_pipe * idx_count; 605 606 if (entries_interval >= soc->sram_scan_rate) { 607 sal_sem_take(soc->sram_scan_notify, interval); 608 entries_interval = 0; 609 } 610 } 611 } 612 } 613 614 if (soc->sram_scan_interval != 0) { 615 /* Extra sleep in main loop, in case no caches are enabled. */ 616 sal_sem_take(soc->sram_scan_notify, interval); 617 entries_interval = 0; 618 } 619 } 620 cleanup_exit: 621 if (read_buf != NULL) { 622 soc_cm_sfree(unit, read_buf); 623 } 624 soc->sram_scan_pid = SAL_THREAD_ERROR; 625 sal_thread_exit(0); 626 } 627 628 #endif /* BCM_SRAM_SCAN_SUPPORT */