openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 */