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

hw_log.c (52716B)


      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  * This file contains structure and routine declarations for the
      8  * Hw Log journal for Crash Recovery LOG Mechanism.
      9  */
     10 
     11 #include <appl/diag/parse.h>
     12 #include <soc/dcmn/error.h>
     13 #include <soc/drv.h>
     14 #include <soc/error.h>
     15 #include <shared/bsl.h>
     16 #include <soc/sbusdma.h>
     17 #include <soc/dpp/SAND/Utils/sand_os_interface.h>
     18 #include <soc/dpp/JER/jer_sbusdma_desc.h>
     19 
     20 #ifdef CRASH_RECOVERY_SUPPORT
     21 #include <soc/hwstate/hw_log.h>
     22 #include <soc/dcmn/dcmn_crash_recovery_utils.h>
     23 #ifdef BCM_ARAD_SUPPORT
     24 #include <soc/dpp/ARAD/arad_chip_regs.h>
     25 #endif
     26 
     27 #if !defined(__KERNEL__) && defined (LINUX)
     28 #ifdef BCM_WARM_BOOT_SUPPORT
     29 #include <soc/ha.h>
     30 #define HW_LOG_VERSION_1_0 1
     31 #define HW_LOG_STRUCT_SIG 0
     32 typedef enum {
     33     HA_HW_LOG_SUB_ID_0 = 0
     34 } HA_sub_id_tl;
     35 #endif
     36 #endif
     37 
     38 /* ERROr Module Name */
     39 #ifdef _ERR_MSG_MODULE_NAME
     40   #error "_ERR_MSG_MODULE_NAME redefined"
     41 #endif
     42 #define _ERR_MSG_MODULE_NAME BSL_LS_SHARED_SWSTATE
     43 
     44 #define HWLOG_MARGIN sizeof(HwLogEntry_t)
     45 
     46 
     47 /* change this flag to 1 to get debug prints */
     48 #define HW_LOG_DEBUG_ENABLE 0
     49 #if HW_LOG_DEBUG_ENABLE
     50 #define HW_LOG_DEBUG(op) op
     51 #else
     52 #define HW_LOG_DEBUG(op)
     53 #endif
     54 
     55 
     56 /* ------------------------------EXTERNAL FUNCTION DECLARATION-----------------------*/
     57 int reg_test(int unit, args_t *a, void *pa);
     58 
     59 /* ------------------------------INTERNAL FUNCTION DECLARATION-----------------------*/
     60 STATIC int _soc_hw_log_insert_entry_to_log(int unit, LogEntry_t *data);
     61 STATIC int _soc_hw_log_write_memory_to_log(int unit, soc_mem_t mem, unsigned array_index, int copyno, int index, void *entry_data);
     62 STATIC int _soc_hw_log_read_memory_entry_from_log(int unit, soc_mem_t mem, unsigned array_index, int copyno, int index, void *entry_data);
     63 STATIC int _soc_hw_log_write_register32_to_log(int unit, soc_reg_t reg, int port, int index, uint32 entry_data);
     64 STATIC int _soc_hw_log_read_register32_entry_from_log(int unit, soc_reg_t reg, int port, int index, uint32 *entry_data);
     65 STATIC int _soc_hw_log_write_register64_to_log(int unit, soc_reg_t reg, int port, int index, uint64 entry_data);
     66 STATIC int _soc_hw_log_read_register64_entry_from_log(int unit, soc_reg_t reg, int port, int index, uint64 *entry_data);
     67 STATIC int _soc_hw_log_write_reg_above64_to_log(int unit, soc_reg_t reg, int port, int index, soc_reg_above_64_val_t entry_data);
     68 STATIC int _soc_hw_log_read_reg_above64_entry_from_log(int unit, soc_reg_t reg, int port, int index, soc_reg_above_64_val_t entry_data);
     69 STATIC int _soc_hw_log_polling(int unit, sal_usecs_t time_out, int32 min_polls, soc_reg_t reg, int32 port, int32 index, soc_field_t field, uint32 expected_value);
     70 STATIC int _soc_hw_log_direct_reg_set(int unit, int cmic_block, uint32 addr, uint32 dwc_write, uint32 *data);
     71 STATIC int _soc_hw_log_fast_reg_set(int unit, soc_reg_t reg, int acc_type, int addr, int block, soc_reg_above_64_val_t data);
     72 STATIC int _soc_hw_log_fast_reg_get(int unit, soc_reg_t reg, int acc_type, int addr, int block, soc_reg_above_64_val_t data);
     73 STATIC int _soc_hw_log_soc_reg_set(int unit, soc_reg_t reg, int port, int index, uint64 data);
     74 STATIC int _soc_hw_log_soc_reg_get(int unit, soc_reg_t reg, int port, int index, uint64 *data);
     75 STATIC int _soc_hw_log_reg_set_nocache(int unit, soc_reg_t reg, int port, int index, uint64 data);
     76 STATIC int _soc_hw_log_is_suppressed(int unit);
     77 STATIC int _soc_hw_is_immediate_hw_access_enabled(int unit);
     78 STATIC uint32 _soc_hw_log_commit_counter_get(int unit);
     79 STATIC int _soc_hw_log_commit_counter_set(int unit, uint32 count);
     80 STATIC int _soc_hw_log_commit_counter_reset(int unit);
     81 STATIC int _soc_hw_log_mem_sbusdma_write(int unit, int flags, soc_mem_t mem,
     82                              unsigned array_index_start,
     83                              unsigned array_index_end, int copyno,
     84                              int index_begin, int index_end,
     85                              void *buffer, uint8 mem_clear,
     86                              int clear_buf_ent, int vchan);
     87 STATIC int _soc_hw_log_mem_sbusdma_read(int unit, soc_mem_t mem, unsigned array_index,
     88                             int copyno, int index_min, int index_max,
     89                             uint32 ser_flags, void *buffer, int vchan);
     90 STATIC int _soc_hw_log_sbusdma_entry_commit(int unit, LogEntry_t *data);
     91 STATIC int _soc_hw_log_mem_sbusdma_get_size(int unit, soc_mem_t mem, int index_begin, int index_end, uint8 mem_clear);
     92 STATIC void *_soc_hw_log_sbusdma_buffer_allocate(int unit, uint32 size);
     93 STATIC int _soc_hw_log_sbusdma_buffers_free(int unit);
     94 
     95 STATIC int _soc_hw_log_descdma_write(int unit, soc_mem_t mem, unsigned array_index, int copyno, int index, void *entry_data);
     96 
     97 
     98 /* ------------------------------Global Variables------------------------------------*/
     99 
    100 soc_hw_log_access_t crash_rec_access =
    101 {
    102         _soc_hw_log_read_register32_entry_from_log,
    103         _soc_hw_log_read_register64_entry_from_log,
    104         _soc_hw_log_read_reg_above64_entry_from_log,
    105         _soc_hw_log_write_register32_to_log,
    106         _soc_hw_log_write_register64_to_log,
    107         _soc_hw_log_write_reg_above64_to_log,
    108         _soc_hw_log_read_memory_entry_from_log,
    109         _soc_hw_log_write_memory_to_log,
    110         _soc_hw_log_polling,
    111         _soc_hw_log_direct_reg_set,
    112         _soc_hw_log_fast_reg_set,
    113         _soc_hw_log_fast_reg_get,
    114         _soc_hw_log_soc_reg_set,
    115         _soc_hw_log_soc_reg_get,
    116         _soc_hw_log_reg_set_nocache,
    117         _soc_hw_log_mem_sbusdma_write,
    118         _soc_hw_log_mem_sbusdma_read,
    119         _soc_hw_log_descdma_write
    120 };
    121 
    122 LogList_t Hw_Log_List[SOC_MAX_NUM_DEVICES];
    123 
    124 
    125 /* ------------------------------FUNCTION IMPLEMENTATION-----------------------------*/
    126 
    127 STATIC uint32
    128 _soc_hw_log_dma_get_buff_idx(int index_begin, int index_end, int entry_idx)
    129 {
    130     uint32 buff_idx;
    131 
    132     if(index_begin <= index_end) {
    133         buff_idx = (entry_idx - index_begin);
    134     } else { /* reverse direction */
    135         buff_idx = (index_begin - entry_idx);
    136     }
    137 
    138     return buff_idx;
    139 }
    140 
    141 STATIC void
    142 _soc_hw_log_brcd_blocks_list_init(int unit)
    143 {
    144     int blk;
    145 
    146     soc_info_t *si = &SOC_INFO(unit);
    147 
    148     for(blk = 0; blk < SOC_MAX_NUM_BLKS; blk++) {
    149         Hw_Log_List[unit].brcd_blocks[blk] = (NULL == si->broadcast_blocks[blk]) ? 0 : 1;
    150     }
    151 }
    152 
    153 
    154 STATIC int
    155 _soc_hw_log_log_list_is_empty(int unit)
    156 {
    157     return !(Hw_Log_List[unit].header->nof_elements > 0);
    158 }
    159 
    160 int
    161 soc_hw_log_is_initialized(int unit)
    162 {
    163     return Hw_Log_List[unit].init;
    164 }
    165 
    166 int
    167 soc_hw_set_immediate_hw_access(int unit)
    168 {
    169     SOC_INIT_FUNC_DEFS;
    170 
    171     /* make sure that we are currently in a middle of a transaction */
    172     if (!soc_dcmn_cr_utils_is_logging(unit)) SOC_EXIT;
    173 
    174     /* exit if not the journaling thread */
    175     DCMN_CR_EXIT_IF_NOT_JOURNALING_THREAD(unit);
    176 
    177     /* increment the counter and set the immediate access to TRUE*/
    178     Hw_Log_List[unit].access_ct++;
    179     Hw_Log_List[unit].ImmediateAccess = TRUE;
    180 
    181     SOC_EXIT;
    182 
    183 exit:
    184     SOC_FUNC_RETURN;
    185 
    186 }
    187 
    188 int
    189 soc_hw_restore_immediate_hw_access(int unit)
    190 {
    191     SOC_INIT_FUNC_DEFS;
    192 
    193     /* exit if not the journaling thread */
    194     DCMN_CR_EXIT_IF_NOT_JOURNALING_THREAD(unit);
    195 
    196     if (Hw_Log_List[unit].access_ct <= 0) {
    197         SOC_EXIT;
    198     }
    199     
    200     /* decrease the immediate access counter */
    201     Hw_Log_List[unit].access_ct--;
    202 
    203     /* if there are no more nested levels of immediate access, then resume journaling */
    204     Hw_Log_List[unit].ImmediateAccess =  (Hw_Log_List[unit].access_ct > 0);
    205     SOC_EXIT;
    206 
    207 exit:
    208     SOC_FUNC_RETURN;
    209 
    210 }
    211 
    212 int
    213 soc_hw_reset_immediate_hw_access_counter(int unit)
    214 {
    215     SOC_INIT_FUNC_DEFS;
    216 
    217     if (!SOC_UNIT_VALID(unit))
    218         return SOC_E_UNIT;
    219 
    220     /* exit if not the journaling thread */
    221     DCMN_CR_EXIT_IF_NOT_JOURNALING_THREAD(unit);
    222 
    223     Hw_Log_List[unit].access_ct = 0;
    224 
    225     SOC_EXIT;
    226 
    227 exit:
    228     SOC_FUNC_RETURN;
    229 }
    230 
    231 STATIC int
    232 _soc_hw_is_immediate_hw_access_enabled(int unit)
    233 {
    234     return (Hw_Log_List[unit].ImmediateAccess);
    235 }
    236 
    237 int
    238 soc_hw_ensure_immediate_hw_access_disabled(int unit)
    239 {
    240     SOC_INIT_FUNC_DEFS;
    241     
    242     if(_soc_hw_is_immediate_hw_access_enabled(unit)) {
    243         return SOC_E_FAIL;
    244     }
    245 
    246     SOC_EXIT;
    247 
    248 exit:
    249     SOC_FUNC_RETURN;
    250 }
    251 
    252 int
    253 soc_hw_log_do_hwlog_read_write(int unit)
    254 {
    255     return (SOC_CR_ENABALED(unit)                        && /* don't jounal while crash recovery is disabled */
    256            soc_hw_log_is_initialized(unit)               && /* HW LOG is enabled and initialized */
    257            soc_dcmn_cr_utils_is_journaling_thread(unit)  && /* Allow journaling only from the journaling thread */
    258            !_soc_hw_is_immediate_hw_access_enabled(unit) && /* check if immediate hw access is enabled */
    259            !_soc_hw_log_is_suppressed(unit)              && /* check if log is suppressed */
    260            soc_dcmn_cr_utils_is_logging(unit));
    261 }
    262 
    263 int
    264 soc_hw_log_init(int unit, uint32 size)
    265 {
    266     uint8  *mem_ptr = NULL;
    267 
    268     SOC_INIT_FUNC_DEFS;
    269 
    270     /* allocation hw log in Shared memory
    271        (cold boot - create; warm boot - retrieve) */
    272     if (ha_mem_alloc(unit, HA_HW_LOG_Mem_Pool, HA_HW_LOG_SUB_ID_0, &size, (void**)&mem_ptr) != SOC_E_NONE) {
    273         return SOC_E_INTERNAL;
    274     }
    275     if (!mem_ptr)
    276     {
    277         LOG_ERROR(BSL_LS_SOC_HWLOG,
    278                        (BSL_META_U(unit, "HW LOG Allocation failed for unit %d. LogSize %d\n"), unit, size));
    279         return SOC_E_MEMORY;
    280     }
    281 
    282     /* set the static data (warm and cold boot) */
    283     Hw_Log_List[unit].Access_cb = crash_rec_access;
    284     Hw_Log_List[unit].ImmediateAccess = FALSE;
    285     Hw_Log_List[unit].access_ct = 0;
    286     Hw_Log_List[unit].is_suppressed = FALSE;
    287     Hw_Log_List[unit].header = (hw_log_header_t *) mem_ptr;
    288     Hw_Log_List[unit].journal = (HwLogEntry_t *) (mem_ptr + sizeof(hw_log_header_t));
    289     Hw_Log_List[unit].size = size;
    290     _soc_hw_log_brcd_blocks_list_init(unit);
    291 
    292     /* Reset the journal (only in Cold boot */
    293     if (!SOC_WARM_BOOT(unit)) {
    294         memset(mem_ptr, 0, size);
    295 
    296         Hw_Log_List[unit].header->max_elements = 
    297             (size - HW_LOG_DMA_BUFFER_SIZE - sizeof(hw_log_header_t) - HWLOG_MARGIN) / sizeof(HwLogEntry_t);
    298         Hw_Log_List[unit].header->nof_elements = 0;
    299         _soc_hw_log_commit_counter_reset(unit);
    300     }
    301 
    302     /* mark as initialized */
    303     Hw_Log_List[unit].init = TRUE;
    304 
    305     LOG_VERBOSE(BSL_LS_SOC_HWLOG,
    306             (BSL_META_U(unit, "HW LOG Enabled for unit %d. LogSize %d Bytes\n"), unit, size));
    307 
    308     SOC_EXIT;
    309 
    310 exit:
    311     SOC_FUNC_RETURN;
    312 }
    313 
    314 int
    315 soc_hw_log_deinit(int unit)
    316 {
    317     Hw_Log_List[unit].ImmediateAccess = TRUE;
    318     Hw_Log_List[unit].init = FALSE;
    319 
    320     return SOC_E_NONE;
    321 }
    322 
    323 void
    324 _soc_hw_log_print_list_memory_entry(int unit, LogEntry_Data_t *Data)
    325 {
    326     uint32 entry_bytes = soc_mem_entry_bytes(unit, Data->MemData.Mem);
    327     uint32 entry_words = soc_mem_entry_words(unit, Data->MemData.Mem);
    328 
    329     int i;
    330     /* Memory entry print */
    331     LOG_ERROR(BSL_LS_SOC_HWLOG,
    332             (BSL_META_U(unit, "Unit %d mem %d (%s) Array %d blk %d index %d  bytesInEntry %d wordsInEntry %d data 0x%X\n"), unit, Data->MemData.Mem,
    333                     SOC_MEM_NAME( unit, Data->MemData.Mem), Data->MemData.ArrayIndex, Data->MemData.Blk, /*Use COPYNO_ALL for all*/
    334             Data->MemData.Index, entry_bytes, entry_words, Data->MemData.EntryData[0]));
    335 
    336     for (i = 1; i < entry_words ; i++) /* Print the data */
    337     {
    338         LOG_ERROR(BSL_LS_SOC_HWLOG,
    339                 (BSL_META_U(unit, "[%d]%X\n"), i, Data->MemData.EntryData[i]));
    340     }
    341 /*    LOG_ERROR(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "\n")));*/
    342 }
    343 
    344 void
    345 _soc_hw_log_print_list_register_entry(int unit, LogEntry_Data_t *Data)
    346 {
    347     /* Register entry print */
    348     LOG_ERROR(BSL_LS_SOC_HWLOG,
    349             (BSL_META_U(unit, "Unit %d Reg %d (%s) Port 0x%X Index %d Data 0x%X\n"), unit, Data->RegData.Reg,
    350                     SOC_REG_NAME( unit, Data->RegData.Reg), Data->RegData.Port,
    351                     Data->RegData.Index, Data->RegData.EntryData[0]));
    352 }
    353 
    354 void
    355 _soc_hw_log_print_list_polling_entry(int unit, LogEntry_Data_t *Data)
    356 {
    357     /* Polling entry print */
    358     LOG_ERROR(BSL_LS_SOC_HWLOG,
    359             (BSL_META_U(unit, "Unit %d Polling: Reg %d (%s) Timeout %d MinPolls %d Port 0x%X Index %d ExpectedValue 0x%X\n"),
    360                     unit,
    361                     Data->PollingData.Reg,
    362                     SOC_REG_NAME( unit, Data->PollingData.Reg),
    363                     Data->PollingData.TimeOut,
    364                     Data->PollingData.MinPolls,
    365                     Data->PollingData.Port,
    366                     Data->PollingData.Index,
    367                     Data->PollingData.ExpectedValue));
    368 }
    369 
    370 void
    371 _soc_hw_log_print_list_direct_reg_entry(int unit, LogEntry_Data_t *Data)
    372 {
    373     /* Direct Regs entry print */
    374     LOG_ERROR(BSL_LS_SOC_HWLOG,
    375             (BSL_META_U(unit, "Unit %d DirectRegSet: CmicBlock 0x%X Addr 0x%X DwcWrite 0x%X Data 0x%X\n"),
    376                     unit,
    377                     Data->DirectRegData.CmicBlock,
    378                     Data->DirectRegData.Addr,
    379                     Data->DirectRegData.DwcWrite,
    380                     Data->DirectRegData.EntryData));
    381 }
    382 
    383 void
    384 _soc_hw_log_print_list_fast_reg_entry(int unit, LogEntry_Data_t *Data)
    385 {
    386     /* Direct Regs entry print */
    387     LOG_ERROR(BSL_LS_SOC_HWLOG,
    388             (BSL_META_U(unit, "Unit %d FastRegSet: Reg %d (%s) AccType %d Addr 0x%X Block 0x%X Data 0x%X\n"),
    389                     unit,
    390                     Data->FastRegData.Reg,
    391                     SOC_REG_NAME( unit, Data->FastRegData.Reg),
    392                     Data->FastRegData.AccType,
    393                     Data->FastRegData.Addr,
    394                     Data->FastRegData.Block,
    395                     Data->FastRegData.EntryData[0]));
    396 }
    397 void
    398 _soc_hw_log_print_list_soc_reg_entry(int unit, LogEntry_Data_t *Data)
    399 {
    400     _soc_hw_log_print_list_register_entry(unit, Data);
    401 }
    402 
    403 void
    404 soc_hw_log_print_single_entry(int unit, HwLogEntry_t *entry)
    405 {
    406 	if (!entry)
    407 		return;
    408 
    409     if (entry->Entry.Type == LOG_ENTRY_TYPE_Memory)
    410     {
    411         _soc_hw_log_print_list_memory_entry(unit, &entry->Entry.Data);
    412     }
    413     else if ((entry->Entry.Type == LOG_ENTRY_TYPE_Register32) || (entry->Entry.Type == LOG_ENTRY_TYPE_Register64) || (entry->Entry.Type == LOG_ENTRY_TYPE_Register_Above64))
    414     {
    415         _soc_hw_log_print_list_register_entry(unit, &entry->Entry.Data);
    416     }
    417     else if (entry->Entry.Type == LOG_ENTRY_TYPE_Polling)
    418     {
    419         _soc_hw_log_print_list_polling_entry(unit, &entry->Entry.Data);
    420     }
    421     else if (entry->Entry.Type == LOG_ENTRY_TYPE_DirectRegWrite)
    422     {
    423         _soc_hw_log_print_list_direct_reg_entry(unit, &entry->Entry.Data);
    424     }
    425     else if  (entry->Entry.Type == LOG_ENTRY_TYPE_FastRegData)
    426     {
    427         _soc_hw_log_print_list_fast_reg_entry(unit, &entry->Entry.Data);
    428     }
    429     else if ((entry->Entry.Type == LOG_ENTRY_TYPE_SocRegData) || (entry->Entry.Type == LOG_ENTRY_TYPE_SocRegNoCacheData))
    430     {
    431         _soc_hw_log_print_list_soc_reg_entry(unit, &entry->Entry.Data);
    432     }
    433 }
    434 
    435 int
    436 soc_hw_log_print_list(int unit)
    437 {
    438     uint32 i;
    439 
    440     SOC_INIT_FUNC_DEFS;
    441 
    442     if (_soc_hw_log_log_list_is_empty(unit))
    443         return SOC_E_NONE;
    444 
    445     for (i=0 ; i < Hw_Log_List[unit].header->nof_elements; i++) {
    446         soc_hw_log_print_single_entry(unit, &(Hw_Log_List[unit].journal[i]));
    447     }
    448 
    449     SOC_EXIT;
    450 
    451 exit:
    452     SOC_FUNC_RETURN;
    453 }
    454 
    455 int
    456 soc_hw_log_purge(int unit)
    457 {
    458     SOC_INIT_FUNC_DEFS;
    459 
    460     Hw_Log_List[unit].header->nof_elements = 0;
    461     _soc_hw_log_commit_counter_reset(unit);
    462     _soc_hw_log_sbusdma_buffers_free(unit);
    463     SOC_EXIT;
    464 
    465 exit:
    466     SOC_FUNC_RETURN;
    467 }
    468 
    469 STATIC int _soc_hw_log_sbusdma_entry_commit(int unit, LogEntry_t *entry)
    470 {
    471     void *buffer;
    472     soc_error_t res;
    473     int alloc_size = _soc_hw_log_mem_sbusdma_get_size(unit, entry->Data.SbusDMA.mem, entry->Data.SbusDMA.index_begin, entry->Data.SbusDMA.index_end, entry->Data.SbusDMA.mem_clear);
    474 
    475     /* create a dmaable buffer and copy the contents of the existing buffer to it */
    476     buffer = soc_cm_salloc(unit, alloc_size, "dma_commit phase");
    477 
    478     sal_memcpy(buffer,entry->Data.SbusDMA.buffer,alloc_size);
    479 
    480     /* perform the actual dma operationg */
    481     res =   _soc_mem_array_sbusdma_write(unit,
    482             entry->Data.SbusDMA.flags,
    483             entry->Data.SbusDMA.mem,
    484             entry->Data.SbusDMA.array_index_start,
    485             entry->Data.SbusDMA.array_index_end,
    486             entry->Data.SbusDMA.copyno,
    487             entry->Data.SbusDMA.index_begin,
    488             entry->Data.SbusDMA.index_end,
    489             buffer, /* use the dmaable buffer */
    490             entry->Data.SbusDMA.mem_clear,
    491             entry->Data.SbusDMA.clear_buf_ent,
    492             entry->Data.SbusDMA.vchan);
    493 
    494     /* release the dma buffer and the stored buffer */
    495     soc_cm_sfree(unit, buffer);
    496 
    497     /* no need to free the hw log buffer, dma buffers are purged at the end of the commit of the current transactions */
    498 
    499     return res;
    500 }
    501 
    502 int
    503 soc_hw_log_commit(int unit)
    504 {
    505     HwLogEntry_t   *entry;
    506     uint32          i;
    507     soc_error_t     res             = SOC_E_NONE,
    508                     func_res        = SOC_E_NONE;
    509     uint8           suspend_commit_counter = 0;
    510 
    511     SOC_INIT_FUNC_DEFS;
    512 
    513     /* If Log is empty --> nothing to commit */
    514     if (_soc_hw_log_log_list_is_empty(unit)) SOC_EXIT;
    515 
    516     LOG_VERBOSE(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "----------   COMMIT START   ----------: \n")));
    517 
    518     Hw_Log_List[unit].ImmediateAccess = TRUE;
    519 
    520     /* if a crash has occured continue committing log where we left off */
    521     i = _soc_hw_log_commit_counter_get(unit);
    522 
    523     for (; i < Hw_Log_List[unit].header->nof_elements; i++) {
    524 
    525         entry = &(Hw_Log_List[unit].journal[i]);
    526 
    527         if (entry->Entry.Type == LOG_ENTRY_TYPE_Memory)
    528         {
    529             if(entry->Entry.Data.MemData.DescDMA) {
    530                 res = jer_sbusdma_desc_add_mem(unit, entry->Entry.Data.MemData.Mem, entry->Entry.Data.MemData.ArrayIndex, entry->Entry.Data.MemData.Blk, entry->Entry.Data.MemData.Index, entry->Entry.Data.MemData.EntryData);
    531                 /* Suspend the automatic commit counter increase if there are entries in the descriptor chain. There is always at least one entry in the descriptor chain after desc add so we need to suspend to commit counter */
    532                 suspend_commit_counter = TRUE;
    533             } else {
    534                 res = soc_mem_array_write(unit, entry->Entry.Data.MemData.Mem, entry->Entry.Data.MemData.ArrayIndex, entry->Entry.Data.MemData.Blk, entry->Entry.Data.MemData.Index, entry->Entry.Data.MemData.EntryData);
    535             }
    536         }
    537         else if (entry->Entry.Type == LOG_ENTRY_TYPE_Register32)
    538         {
    539         	res = soc_reg32_set(unit, entry->Entry.Data.RegData.Reg, entry->Entry.Data.RegData.Port, entry->Entry.Data.RegData.Index, entry->Entry.Data.RegData.EntryData[0]);
    540         }
    541         else if (entry->Entry.Type == LOG_ENTRY_TYPE_Register64)
    542         {
    543         	res = soc_reg64_set(unit, entry->Entry.Data.RegData.Reg, entry->Entry.Data.RegData.Port, entry->Entry.Data.RegData.Index, *(uint64 *)(entry->Entry.Data.RegData.EntryData));
    544         }
    545         else if (entry->Entry.Type == LOG_ENTRY_TYPE_Register_Above64)
    546         {
    547         	res = soc_reg_above_64_set(unit, entry->Entry.Data.RegData.Reg, entry->Entry.Data.RegData.Port, entry->Entry.Data.RegData.Index, entry->Entry.Data.RegData.EntryData);
    548         }
    549         else if (entry->Entry.Type == LOG_ENTRY_TYPE_Polling)
    550         {
    551 /*            _soc_hw_log_print_list_polling_entry(unit, &entry->Entry.Data);*/
    552 #ifdef BCM_ARAD_SUPPORT
    553             res = arad_polling(unit,  entry->Entry.Data.PollingData.TimeOut, entry->Entry.Data.PollingData.MinPolls, entry->Entry.Data.PollingData.Reg, entry->Entry.Data.PollingData.Port, entry->Entry.Data.PollingData.Index,   entry->Entry.Data.PollingData.Field, entry->Entry.Data.PollingData.ExpectedValue);
    554 #endif
    555         }
    556         else if (entry->Entry.Type == LOG_ENTRY_TYPE_DirectRegWrite)
    557         {
    558             _soc_hw_log_print_list_direct_reg_entry(unit, &entry->Entry.Data);
    559 #ifdef BCM_ARAD_SUPPORT
    560             res = soc_direct_reg_set(unit, entry->Entry.Data.DirectRegData.CmicBlock, entry->Entry.Data.DirectRegData.Addr, entry->Entry.Data.DirectRegData.DwcWrite, &entry->Entry.Data.DirectRegData.EntryData);
    561 #endif
    562         }
    563         else if (entry->Entry.Type == LOG_ENTRY_TYPE_FastRegData)
    564         {
    565 /*			_soc_hw_log_print_list_fast_reg_entry(unit, &entry->Entry.Data);*/
    566 #ifdef BCM_ARAD_SUPPORT
    567             res = arad_fast_reg_set(unit, entry->Entry.Data.FastRegData.Reg, entry->Entry.Data.FastRegData.AccType, entry->Entry.Data.FastRegData.Addr, entry->Entry.Data.FastRegData.Block, entry->Entry.Data.FastRegData.EntryData);
    568 #endif
    569         }
    570         else if (entry->Entry.Type == LOG_ENTRY_TYPE_SocRegData)
    571         {
    572 /*            _soc_hw_log_print_list_soc_reg_entry(unit, &entry->Entry.Data);*/
    573         	res = soc_reg_set(unit, entry->Entry.Data.RegData.Reg, entry->Entry.Data.RegData.Port, entry->Entry.Data.RegData.Index, *(uint64 *)(entry->Entry.Data.RegData.EntryData));
    574         }
    575         else if (entry->Entry.Type == LOG_ENTRY_TYPE_SocRegNoCacheData)
    576         {
    577 /*            _soc_hw_log_print_list_soc_reg_entry(unit, &entry->Entry.Data);*/
    578         	res = soc_reg_set_nocache(unit, entry->Entry.Data.RegData.Reg, entry->Entry.Data.RegData.Port, entry->Entry.Data.RegData.Index, *(uint64 *)(entry->Entry.Data.RegData.EntryData));
    579         }
    580         else if (entry->Entry.Type == LOG_ENTRY_TYPE_SbusDMA)
    581         {
    582             _soc_hw_log_sbusdma_entry_commit(unit, &entry->Entry);
    583         }
    584         else
    585         {
    586             LOG_ERROR(BSL_LS_SOC_HWLOG,
    587                 (BSL_META_U(unit, "Unit %d: Unknown Entry Type %d FAILED TO COMMIT!!!!.\n"), unit, entry->Entry.Type));
    588         }
    589 
    590 
    591         if (SOC_FAILURE(res))
    592         {
    593             LOG_ERROR(BSL_LS_SOC_HWLOG,
    594                             (BSL_META_U(unit, "Unit %d: FAILED TO COMMIT Entry Type %d!!!.\n"), unit, entry->Entry.Type));
    595 
    596             soc_hw_log_print_single_entry(unit, entry);	/* Print the problematic entry */
    597 
    598             /* continue execution but remember the error */
    599         	func_res |= res;	/* Remember error result*/
    600         }
    601         /* set the index of the next element to be comitted, if commit counter is not suspended */
    602         if(!suspend_commit_counter) {
    603             _soc_hw_log_commit_counter_set(unit,i+1);
    604         }
    605     }
    606     
    607     /* NOTE: clearing the list is the caller responssibility */
    608 
    609     /* start logging again */
    610     Hw_Log_List[unit].ImmediateAccess = FALSE;
    611 
    612     /* reset counter after the commit is done */
    613     _soc_hw_log_commit_counter_reset(unit);
    614 
    615     /* flush the descriptor dma chain */
    616     jer_sbusdma_desc_wait_done(unit);
    617 
    618     /* free the dma buffers */
    619     _soc_hw_log_sbusdma_buffers_free(unit);
    620 
    621     LOG_VERBOSE(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "---------- END COMMIT ---------- : \n")));
    622 
    623     /* check for the error summarry for all entries */
    624     _SOC_IF_ERR_EXIT(func_res);
    625 
    626     SOC_EXIT;
    627 
    628 exit:
    629     SOC_FUNC_RETURN;
    630 
    631 }
    632 
    633 
    634 
    635 STATIC int _soc_hw_log_insert_entry_to_log(int unit, LogEntry_t *data)
    636 {
    637     HwLogEntry_t *entry = NULL;
    638 
    639     SOC_INIT_FUNC_DEFS;
    640 
    641     if (!soc_hw_log_is_initialized(unit))
    642     {
    643         /* The List is not initialized */
    644         _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL,
    645                    (BSL_META_U(unit,
    646                       "unit:%d The Hw Log List is not initialized, failed to insert.\n"), unit));
    647     }
    648 
    649     /* Check if The list is full */
    650     if (Hw_Log_List[unit].header->max_elements == Hw_Log_List[unit].header->nof_elements) {
    651         /* The journal is full */
    652         _SOC_EXIT_WITH_ERR(SOC_E_FULL,
    653                    (BSL_META_U(unit,
    654                       "unit:%d The Hw Log List is FULL.\n"), unit));
    655     }
    656 
    657     /* prepare ptr to the next free entry */
    658     entry = &(Hw_Log_List[unit].journal[Hw_Log_List[unit].header->nof_elements]);
    659     Hw_Log_List[unit].header->nof_elements++;
    660 
    661     /* Save the new content in the log list */
    662     sal_memcpy(&(entry->Entry), data, sizeof(LogEntry_t)/*data->data_size*/);
    663 
    664 	LOG_DEBUG(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "---   Entry Added to the HW LOG !!!   ---: \n")));
    665 
    666     SOC_EXIT;
    667 
    668 exit:
    669     SOC_FUNC_RETURN;
    670 
    671 }
    672 
    673 
    674 STATIC int _soc_hw_log_write_memory_to_log(int unit, soc_mem_t mem,
    675         unsigned array_index, int copyno, int index, void *entry_data)
    676 {
    677     LogEntry_t entry;
    678     uint32 entry_words;
    679 
    680     sal_memset(entry.Data.MemData.EntryData, 0, sizeof(entry.Data.MemData.EntryData));
    681 
    682     entry_words                   = soc_mem_entry_words(unit, mem);
    683     /* Init the Log entry */
    684     entry.Data.MemData.Mem        = mem;
    685     entry.Data.MemData.ArrayIndex = array_index;
    686     entry.Data.MemData.Blk        = copyno;
    687     entry.Data.MemData.Index      = index;
    688     entry.Data.MemData.IsCoreAll  = Hw_Log_List[unit].brcd_blocks[copyno];
    689 	entry.Data.MemData.DescDMA    = FALSE;
    690 
    691     entry.Type                    = LOG_ENTRY_TYPE_Memory;
    692 
    693     sal_memcpy(entry.Data.MemData.EntryData, ((char*) entry_data),  entry_words*sizeof(int));
    694 
    695     /*Insert the log entry*/
    696     return _soc_hw_log_insert_entry_to_log(unit, &entry);
    697 }
    698 
    699 STATIC int
    700 _soc_hw_log_mem_sbusdma_get_size(int unit, soc_mem_t mem, int index_begin, int index_end, uint8 mem_clear)
    701 {
    702     uint32     entry_dw;
    703     int        count;
    704 
    705     entry_dw = soc_mem_entry_words(unit, mem);
    706 
    707     if(mem_clear) { /* SLAM DMA */
    708         count = 1; /* only one entry in the buffer */
    709     } else {
    710         if (index_begin > index_end) {
    711             count = index_begin - index_end + 1;
    712         } else {
    713             count = index_end - index_begin + 1;
    714         }
    715     }
    716 
    717     return (count * entry_dw * sizeof(uint32));
    718 }
    719 
    720 STATIC int
    721 _soc_hw_log_mem_sbusdma_read(int unit, soc_mem_t mem, unsigned array_index,
    722                             int copyno, int index_begin, int index_end,
    723                             uint32 ser_flags, void *buffer, int vchan)
    724 {
    725     HwLogEntry_t    *entry;
    726     uint32          entry_words;
    727     int             found   = FALSE;
    728     soc_mem_t       saved_in_hw_log_mem;
    729     uint32          i;
    730     uint32          buff_idx;
    731     char            *buff_entry;
    732     int interval_A_start, interval_A_end, interval_B_start, interval_B_end; /* used to calculate overlapping dma intervals */
    733 
    734     /* Get the alias memory. Note: updates 'mem' value. */
    735     SOC_MEM_ALIAS_TO_ORIG(unit, mem);
    736 
    737     if (!soc_hw_log_is_initialized(unit) || _soc_hw_log_log_list_is_empty(unit))
    738     {
    739         /* The List is not initialized or empty */
    740         goto not_found;
    741     }
    742 
    743     /* calculate the lowest and the highest indexes */
    744     interval_A_start = HWLOG_MIN(index_begin,index_end);
    745     interval_A_end = HWLOG_MAX(index_begin,index_end);
    746 
    747     for (i=0 ; i < Hw_Log_List[unit].header->nof_elements; i++) {
    748 
    749         entry = &(Hw_Log_List[unit].journal[i]);
    750 
    751         if (entry->Entry.Type == LOG_ENTRY_TYPE_Memory)
    752         {
    753             saved_in_hw_log_mem = entry->Entry.Data.MemData.Mem;
    754             /* Get the alias memory for saved mem value. Note: updates 'saved_mem' value. */
    755             SOC_MEM_ALIAS_TO_ORIG(unit, saved_in_hw_log_mem);
    756 
    757             if (   (mem             == saved_in_hw_log_mem)
    758                 && (array_index     == entry->Entry.Data.MemData.ArrayIndex)
    759                 && ((copyno         == entry->Entry.Data.MemData.Blk) || (entry->Entry.Data.MemData.Blk == MEM_BLOCK_ANY) || (entry->Entry.Data.MemData.IsCoreAll))
    760                 && ((interval_A_start <= entry->Entry.Data.MemData.Index) && (entry->Entry.Data.MemData.Index <= interval_A_end)))
    761             {
    762                 entry_words             = soc_mem_entry_words(unit, mem);
    763 
    764                 buff_idx = _soc_hw_log_dma_get_buff_idx(index_begin, index_end,entry->Entry.Data.MemData.Index);  
    765 
    766                 buff_entry = (char *)buffer + buff_idx*entry_words*sizeof(int);
    767 
    768 
    769                 sal_memcpy(((char *) buff_entry), entry->Entry.Data.MemData.EntryData , entry_words*sizeof(int));
    770 
    771                 found = TRUE;
    772                 LOG_DEBUG( BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "MEM FOUND in LOG!!! .\n")) );
    773                 HW_LOG_DEBUG(_soc_hw_log_print_list_memory_entry(unit, entry));
    774             }
    775         } else if (entry->Entry.Type == LOG_ENTRY_TYPE_SbusDMA) {
    776             saved_in_hw_log_mem = entry->Entry.Data.SbusDMA.mem;
    777             SOC_MEM_ALIAS_TO_ORIG(unit, saved_in_hw_log_mem);
    778 
    779             /* calculate the lowest and highest indexes for stored DMA entry*/
    780             interval_B_start = HWLOG_MIN(entry->Entry.Data.SbusDMA.index_begin,entry->Entry.Data.SbusDMA.index_end);
    781             interval_B_end = HWLOG_MAX(entry->Entry.Data.SbusDMA.index_begin,entry->Entry.Data.SbusDMA.index_end);
    782 
    783             if ((mem == saved_in_hw_log_mem) &&
    784                 ((array_index >= entry->Entry.Data.SbusDMA.array_index_start) &&
    785                  (array_index <= entry->Entry.Data.SbusDMA.array_index_end)) &&
    786                 ((copyno == entry->Entry.Data.SbusDMA.copyno) || (entry->Entry.Data.SbusDMA.copyno == MEM_BLOCK_ANY) || (entry->Entry.Data.SbusDMA.IsCoreAll)) &&
    787                 (HWLOG_MAX(interval_A_start,interval_B_start) <= HWLOG_MIN(interval_A_end,interval_B_end))) /* check if the two intervals are overlapping */ {
    788                     LOG_ERROR(BSL_LS_SOC_HWLOG,
    789                         (BSL_META_U(unit, "Unit %d: DMA reads cannot retrieve updated values from journaled DMA entries !!!.\n"),unit));
    790                     return SOC_E_FAIL;
    791             }
    792         }
    793     }
    794 
    795 not_found:
    796     return found;
    797 
    798 }
    799 
    800 STATIC int
    801 _soc_hw_log_mem_sbusdma_write(int unit, int flags, soc_mem_t mem,
    802                              unsigned array_index_start,
    803                              unsigned array_index_end, int copyno,
    804                              int index_begin, int index_end,
    805                              void *buffer, uint8 mem_clear,
    806                              int clear_buf_ent, int vchan)
    807 {
    808     LogEntry_t entry;
    809     void       *hwlog_buffer;
    810 
    811     int alloc_size = _soc_hw_log_mem_sbusdma_get_size(unit, mem, index_begin, index_end, mem_clear);
    812 
    813     hwlog_buffer = _soc_hw_log_sbusdma_buffer_allocate(unit, alloc_size);
    814     if(NULL == hwlog_buffer) {
    815         return SOC_E_MEMORY;
    816     }
    817 
    818     sal_memcpy(hwlog_buffer, buffer, alloc_size);
    819 
    820     entry.Data.SbusDMA.flags                = flags;
    821     entry.Data.SbusDMA.mem                  = mem;
    822     entry.Data.SbusDMA.array_index_start    = array_index_start;
    823     entry.Data.SbusDMA.array_index_end      = array_index_end;
    824     entry.Data.SbusDMA.copyno               = copyno;
    825     entry.Data.SbusDMA.index_begin          = index_begin;
    826     entry.Data.SbusDMA.index_end            = index_end;
    827     entry.Data.SbusDMA.buffer               = hwlog_buffer; /* non-volatile buffer */
    828     entry.Data.SbusDMA.mem_clear            = mem_clear;
    829     entry.Data.SbusDMA.clear_buf_ent        = clear_buf_ent;
    830     entry.Data.SbusDMA.vchan                = vchan;
    831     entry.Data.SbusDMA.IsCoreAll            = Hw_Log_List[unit].brcd_blocks[copyno];
    832 
    833 
    834     entry.Type                              = LOG_ENTRY_TYPE_SbusDMA;
    835 
    836     return _soc_hw_log_insert_entry_to_log(unit, &entry);
    837 }
    838 
    839 STATIC int _soc_hw_log_read_memory_entry_from_log(int unit, soc_mem_t mem,
    840         unsigned array_index, int copyno, int index, void *entry_data)
    841 {
    842     HwLogEntry_t    *entry;
    843     uint32          entry_words;
    844     int             found   = FALSE;
    845     soc_mem_t       saved_in_hw_log_mem;
    846     uint32          i;
    847     uint32          buff_idx;
    848     char            *buff_entry;
    849     uint8           table_dma;
    850     int interval_A_start,interval_A_end; /* used for dma min and max dma entries indexes */
    851 
    852 
    853     /* Get the alias memory. Note: updates 'mem' value. */
    854     SOC_MEM_ALIAS_TO_ORIG(unit, mem);
    855 
    856     if (!soc_hw_log_is_initialized(unit) || _soc_hw_log_log_list_is_empty(unit)) 
    857     {
    858         /* The List is not initialized or empty */
    859         goto not_found;
    860     }
    861 
    862     for (i=0 ; i < Hw_Log_List[unit].header->nof_elements; i++) {
    863 
    864         entry = &(Hw_Log_List[unit].journal[i]);
    865 
    866         if (entry->Entry.Type == LOG_ENTRY_TYPE_Memory)
    867         {
    868             saved_in_hw_log_mem = entry->Entry.Data.MemData.Mem;
    869             /* Get the alias memory for saved mem value. Note: updates 'saved_mem' value. */
    870             SOC_MEM_ALIAS_TO_ORIG(unit, saved_in_hw_log_mem);
    871 
    872             if (    (mem                == saved_in_hw_log_mem)
    873                     && (array_index     == entry->Entry.Data.MemData.ArrayIndex)
    874                     && ((copyno         == entry->Entry.Data.MemData.Blk) || (entry->Entry.Data.MemData.Blk == MEM_BLOCK_ANY) || (entry->Entry.Data.MemData.IsCoreAll))
    875                     && (index           == entry->Entry.Data.MemData.Index))
    876             {
    877                 entry_words             = soc_mem_entry_words(unit, mem);
    878 
    879                 sal_memcpy(((char *) entry_data), entry->Entry.Data.MemData.EntryData , entry_words*sizeof(int));
    880 
    881                 found = TRUE;
    882                 LOG_DEBUG( BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "MEM FOUND in LOG!!! .\n")) );
    883                 HW_LOG_DEBUG(_soc_hw_log_print_list_memory_entry(unit, entry));
    884             }
    885         } else if (entry->Entry.Type == LOG_ENTRY_TYPE_SbusDMA) {
    886             saved_in_hw_log_mem = entry->Entry.Data.SbusDMA.mem;
    887             SOC_MEM_ALIAS_TO_ORIG(unit, saved_in_hw_log_mem);
    888 
    889             interval_A_start = HWLOG_MIN(entry->Entry.Data.SbusDMA.index_begin,entry->Entry.Data.SbusDMA.index_end);
    890             interval_A_end = HWLOG_MAX(entry->Entry.Data.SbusDMA.index_begin,entry->Entry.Data.SbusDMA.index_end);
    891 
    892 
    893             if ((mem == saved_in_hw_log_mem) &&
    894 
    895                 ((array_index >= entry->Entry.Data.SbusDMA.array_index_start) && (array_index <= entry->Entry.Data.SbusDMA.array_index_end)) &&
    896                 ((copyno == entry->Entry.Data.SbusDMA.copyno) || (entry->Entry.Data.SbusDMA.copyno == MEM_BLOCK_ANY) || (entry->Entry.Data.SbusDMA.IsCoreAll)) &&
    897                 ((interval_A_start <= index) && (index <= interval_A_end))) {
    898                 entry_words = soc_mem_entry_words(unit, mem);
    899 
    900                 table_dma = (entry->Entry.Data.SbusDMA.mem_clear) ? 0 : 1;
    901 
    902                 /* distinguish between Table and SLAM dma */
    903                 if(table_dma) {
    904                     buff_idx = _soc_hw_log_dma_get_buff_idx(entry->Entry.Data.SbusDMA.index_begin, entry->Entry.Data.SbusDMA.index_end, index);
    905                 } else {
    906                     buff_idx = 0;
    907                 }
    908 
    909                 buff_entry = (char *)entry->Entry.Data.SbusDMA.buffer + buff_idx*entry_words*sizeof(int); /* buff_entry = buffer for slam dma */
    910                 sal_memcpy(((char *) entry_data), buff_entry, entry_words*sizeof(int));
    911 
    912                 found = TRUE;
    913             }
    914         }
    915     }
    916 
    917 not_found:
    918     return found;
    919 }
    920 
    921 
    922 STATIC int
    923 _soc_hw_log_write_register_to_log(int unit, soc_reg_t reg, int port, int index, LogEntry_Type_t type, void * entry_data)
    924 {
    925     LogEntry_t entry;
    926     int size = (type == LOG_ENTRY_TYPE_Register32 ? sizeof(uint32) : (((type == LOG_ENTRY_TYPE_Register64) || (type == LOG_ENTRY_TYPE_SocRegData) || (type == LOG_ENTRY_TYPE_SocRegNoCacheData)) ? sizeof(uint64) : sizeof(soc_reg_above_64_val_t)));
    927 
    928     sal_memset(entry.Data.RegData.EntryData, 0, sizeof(soc_reg_above_64_val_t));
    929 
    930     /* Init the Log entry */
    931     entry.Data.RegData.Reg        = reg;
    932     entry.Data.RegData.Port       = port;
    933     entry.Data.RegData.Index      = index;
    934     entry.Type                    = type;
    935 
    936     sal_memcpy(entry.Data.RegData.EntryData, (int *) entry_data, size);
    937 
    938     /*Insert the log entry*/
    939     return _soc_hw_log_insert_entry_to_log(unit, &entry);
    940 }
    941 
    942 STATIC int
    943 _soc_hw_log_get_size_by_type(LogEntry_Type_t type)
    944 {
    945     int size;
    946 
    947     switch(type) {
    948         case LOG_ENTRY_TYPE_Register32:
    949             size = sizeof(uint32); 
    950             break;
    951         case LOG_ENTRY_TYPE_Register64:
    952             size = sizeof(uint64);
    953             break;
    954         case LOG_ENTRY_TYPE_SocRegData:
    955             size = sizeof(uint64);
    956             break;
    957         case LOG_ENTRY_TYPE_SocRegNoCacheData:
    958             size = sizeof(uint64);
    959             break;
    960         default: 
    961             size = sizeof(soc_reg_above_64_val_t);
    962     }
    963 
    964     return size;
    965 }
    966 
    967 /* check if the arch is little endian */
    968 STATIC int 
    969 _soc_hw_log_is_little_endian(void) {
    970     int i = 1;
    971     char *p = (char *)&i;
    972 
    973     if (p[0] == 1)
    974         return 1;
    975     else
    976         return 0;
    977 }
    978 
    979 /* Type-independent hwlog register entry copy mechanism. Allows all register entry read mechanisms to be able to retrieve data from all hwlog register entry types */
    980 STATIC int
    981 _soc_hw_log_copy_register_entry_generic(int unit, soc_reg_t reg, LogEntry_Type_t type, void* entry_data, HwLogEntry_t *entry) 
    982 {
    983     int              source_size, destination_size, actual_size, added_destionation_size, register_size;
    984     SOC_INIT_FUNC_DEFS;
    985 
    986 
    987                 /* Calculate source size, destination size and actual size
    988                  * 1. Destination size - size of the type of the structure to be copied to
    989                  * 2. Source size - size of type of the entry in the hwlog
    990                  * 3. Actual size = number of bytes to be copied from source to destination */
    991                 destination_size = _soc_hw_log_get_size_by_type(type);
    992                 source_size      = _soc_hw_log_get_size_by_type(entry->Entry.Type);
    993                 actual_size      = (destination_size < source_size) ? destination_size : source_size;
    994 
    995                 /* if the size of the source and destination types is different, we need to consider the size of the register itself */
    996                 if(source_size != destination_size) {
    997                     /* get the register size */
    998                     register_size    = (SOC_REG_IS_ABOVE_64(unit,reg) ? sizeof(soc_reg_above_64_val_t) : (SOC_REG_IS_64(unit, reg) ? sizeof(uint64) : sizeof(uint32)));
    999                     /* if the register size is smaller than the actual size, than use the register size instead.
   1000                      * This is a problem, when above 64 reg read mechanism is trying to retrieve the value of 64 bit entry that contains the value of 32 bit register.
   1001                     */
   1002                     if(register_size < actual_size) {
   1003                         actual_size = register_size;
   1004                     }
   1005                 }
   1006 
   1007                 /* the write in above 64 register starts always from the lowest location. This is a problem in big-endian */
   1008                 added_destionation_size = (type == LOG_ENTRY_TYPE_Register_Above64) ? 0 : (destination_size - actual_size);
   1009 
   1010                 /* depending on the endianness, use an appropriate mem copy mechanism */
   1011                 if (_soc_hw_log_is_little_endian()) {
   1012                     sal_memcpy((uint8*)entry_data, (uint8*)entry->Entry.Data.RegData.EntryData, actual_size);
   1013                 } else {
   1014                     sal_memcpy((uint8*)entry_data + added_destionation_size, (uint8*)entry->Entry.Data.RegData.EntryData + source_size - actual_size, actual_size);
   1015                 }
   1016 
   1017     SOC_EXIT;
   1018 
   1019 exit:
   1020     SOC_FUNC_RETURN;
   1021 }
   1022 
   1023 STATIC int
   1024 _soc_hw_log_read_register_entry_from_log(int unit, soc_reg_t reg, int port, int index, LogEntry_Type_t type, void* entry_data)
   1025 {
   1026     HwLogEntry_t    *entry;
   1027     uint32           i;
   1028     int              found   = FALSE;
   1029     soc_error_t      res     = SOC_E_NONE;
   1030 
   1031     if (!soc_hw_log_is_initialized(unit) || _soc_hw_log_log_list_is_empty(unit)) 
   1032     {
   1033         /* The List is not initialized or empty */
   1034         goto not_found;
   1035     }
   1036 
   1037     for (i=0 ; i < Hw_Log_List[unit].header->nof_elements; i++) {
   1038 
   1039         entry = &(Hw_Log_List[unit].journal[i]);
   1040 
   1041         if ((entry->Entry.Type == LOG_ENTRY_TYPE_Register32) 
   1042             || (entry->Entry.Type == LOG_ENTRY_TYPE_Register64) 
   1043             || (entry->Entry.Type == LOG_ENTRY_TYPE_Register_Above64)
   1044             || (entry->Entry.Type == LOG_ENTRY_TYPE_SocRegData)
   1045             || (entry->Entry.Type == LOG_ENTRY_TYPE_SocRegNoCacheData))
   1046         {
   1047             if ((reg == entry->Entry.Data.RegData.Reg)
   1048                     && ((port == entry->Entry.Data.RegData.Port) /* Exact match for lookup*/
   1049                             || (entry->Entry.Data.RegData.Port == REG_PORT_ANY)
   1050                             || (entry->Entry.Data.RegData.Port == SOC_CORE_ALL) /* Stored data is for all cores*/
   1051                             || (port                           == REG_PORT_ANY)
   1052                             || (port                           == SOC_CORE_ALL))    /*requested data is for all cores - we can return data from any port/core*/
   1053                     && (index == entry->Entry.Data.RegData.Index))
   1054             {
   1055 
   1056                 _soc_hw_log_copy_register_entry_generic(unit, reg, type, entry_data, entry); 
   1057                 
   1058                 found = TRUE;
   1059 
   1060                 LOG_DEBUG(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "REG FOUND in LOG!!! .\n")));
   1061                 HW_LOG_DEBUG(_soc_hw_log_print_list_register_entry(unit, entry->Entry.Data));
   1062             }
   1063         }
   1064     }
   1065 
   1066 not_found:
   1067     if (!found)
   1068     {
   1069         Hw_Log_List[unit].ImmediateAccess = TRUE;
   1070         switch (type)
   1071         {
   1072         case LOG_ENTRY_TYPE_Register32:
   1073         	res = soc_reg32_get(unit, reg, port, index, entry_data);
   1074             break;
   1075         case LOG_ENTRY_TYPE_Register64:
   1076         	res = soc_reg64_get(unit, reg, port, index, entry_data);
   1077             break;
   1078         case LOG_ENTRY_TYPE_Register_Above64:
   1079         	res = soc_reg_above_64_get(unit, reg, port, index, entry_data);
   1080             break;
   1081         case LOG_ENTRY_TYPE_SocRegData:
   1082             res = soc_reg_get(unit, reg, port, index, entry_data);
   1083             break;
   1084         default:
   1085             LOG_DEBUG(BSL_LS_SOC_HWLOG, 
   1086                 (BSL_META_U(unit, "!! Got into _soc_hw_log_read_register_entry_from_log with type %d, reg %d!! .\n"), type, reg));
   1087         }
   1088         Hw_Log_List[unit].ImmediateAccess = FALSE;
   1089 
   1090         if (SOC_FAILURE(res))
   1091         {
   1092             LOG_ERROR(BSL_LS_SOC_HWLOG,
   1093                             (BSL_META_U(unit, "Unit %d: FAILED to READ reg %d(%s) port %d index %d !!!.\n"), 
   1094                              unit, reg, SOC_REG_NAME( unit, reg), port, index));
   1095         }
   1096     }
   1097 
   1098     return res;
   1099 }
   1100 
   1101 STATIC int
   1102 _soc_hw_log_write_register32_to_log(int unit, soc_reg_t reg, int port, int index, uint32 entry_data)
   1103 {
   1104     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1105             (BSL_META_U(unit, "_soc_hw_log_write_register32_to_log!.\n")));
   1106 
   1107     _soc_hw_log_write_register_to_log(unit, reg, port, index, LOG_ENTRY_TYPE_Register32, &entry_data);
   1108     return SOC_E_NONE;
   1109 }
   1110 
   1111 STATIC int
   1112 _soc_hw_log_read_register32_entry_from_log(int unit, soc_reg_t reg, int port, int index, uint32 *entry_data)
   1113 {
   1114     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1115             (BSL_META_U(unit, "_soc_hw_log_read_register32_entry_from_log!.\n")));
   1116 
   1117     _soc_hw_log_read_register_entry_from_log( unit, reg, port, index, LOG_ENTRY_TYPE_Register32, entry_data);
   1118     return SOC_E_NONE;
   1119 
   1120 }
   1121 
   1122 STATIC int
   1123 _soc_hw_log_write_register64_to_log(int unit, soc_reg_t reg, int port, int index, uint64 entry_data)
   1124 {
   1125     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1126                 (BSL_META_U(unit, "_soc_hw_log_write_register64_to_log!.\n")));
   1127 
   1128     _soc_hw_log_write_register_to_log(unit, reg, port, index, LOG_ENTRY_TYPE_Register64, &entry_data);
   1129     return SOC_E_NONE;
   1130 }
   1131 
   1132 STATIC int
   1133 _soc_hw_log_read_register64_entry_from_log(int unit, soc_reg_t reg, int port, int index,
   1134         uint64 *entry_data)
   1135 {
   1136     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1137             (BSL_META_U(unit, "_soc_hw_log_read_register64_entry_from_log!.\n")));
   1138 
   1139     _soc_hw_log_read_register_entry_from_log( unit, reg, port, index, LOG_ENTRY_TYPE_Register64, entry_data);
   1140 
   1141     return SOC_E_NONE;
   1142 }
   1143 
   1144 STATIC int
   1145 _soc_hw_log_write_reg_above64_to_log(int unit, soc_reg_t reg, int port, int index,
   1146         soc_reg_above_64_val_t entry_data)
   1147 {
   1148     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1149             (BSL_META_U(unit, "_soc_hw_log_write_reg_above64_to_log!.\n")));
   1150 
   1151     _soc_hw_log_write_register_to_log(unit, reg, port, index, LOG_ENTRY_TYPE_Register_Above64, entry_data);
   1152     return SOC_E_NONE;
   1153 }
   1154 
   1155 STATIC int
   1156 _soc_hw_log_read_reg_above64_entry_from_log(int unit, soc_reg_t reg, int port, int index,
   1157         soc_reg_above_64_val_t entry_data)
   1158 {
   1159     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1160             (BSL_META_U(unit, "_soc_hw_log_read_reg_above64_entry_from_log!.\n")));
   1161 
   1162     _soc_hw_log_read_register_entry_from_log( unit, reg, port, index, LOG_ENTRY_TYPE_Register_Above64, entry_data);
   1163 
   1164     return SOC_E_NONE;
   1165 }
   1166 
   1167 
   1168 
   1169 STATIC int
   1170 _soc_hw_log_polling(int unit, sal_usecs_t time_out, int32 min_polls, soc_reg_t reg, int32 port, int32 index,
   1171         soc_field_t field, uint32 expected_value)
   1172 {
   1173     LogEntry_t entry;
   1174 
   1175     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1176        (BSL_META_U(unit, "_soc_hw_log_polling!.\n")));
   1177 
   1178 
   1179     /* Init the Log entry */
   1180     entry.Data.PollingData.TimeOut      = time_out;
   1181     entry.Data.PollingData.MinPolls     = min_polls;
   1182     entry.Data.PollingData.Reg          = reg;
   1183     entry.Data.PollingData.Port         = port;
   1184     entry.Data.PollingData.Index        = index;
   1185     entry.Data.PollingData.Field        = field;
   1186     entry.Data.PollingData.ExpectedValue= expected_value;
   1187     entry.Type                          = LOG_ENTRY_TYPE_Polling;
   1188 
   1189     /*Insert the log entry*/
   1190     return _soc_hw_log_insert_entry_to_log(unit, &entry);
   1191 }
   1192 
   1193 STATIC int
   1194 _soc_hw_log_direct_reg_set(int unit, int cmic_block, uint32 addr, uint32 dwc_write, uint32 *data)
   1195 {
   1196     LogEntry_t entry;
   1197 
   1198     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1199         (BSL_META_U(unit, "_soc_hw_log_direct_reg_set!.\n")));
   1200 
   1201     entry.Data.DirectRegData.CmicBlock  = cmic_block;
   1202     entry.Data.DirectRegData.Addr       = addr;
   1203     entry.Data.DirectRegData.DwcWrite   = dwc_write;
   1204     entry.Data.DirectRegData.EntryData  = *data;
   1205 
   1206     entry.Type                          = LOG_ENTRY_TYPE_DirectRegWrite;
   1207 
   1208     /*Insert the log entry*/
   1209     return _soc_hw_log_insert_entry_to_log(unit, &entry);
   1210 }
   1211 STATIC int
   1212 _soc_hw_log_fast_reg_set(int unit, soc_reg_t reg, int acc_type, int addr, int block,
   1213         soc_reg_above_64_val_t data)
   1214 {
   1215     LogEntry_t entry;
   1216 
   1217     LOG_DEBUG(BSL_LS_SOC_HWLOG,
   1218             (BSL_META_U(unit, "_soc_hw_log_direct_reg_set!.\n")));
   1219 
   1220     entry.Data.FastRegData.Reg        = reg;
   1221     entry.Data.FastRegData.AccType    = acc_type;
   1222     entry.Data.FastRegData.Addr       = addr;
   1223     entry.Data.FastRegData.Block      = block;
   1224     sal_memcpy(entry.Data.FastRegData.EntryData, data, sizeof(soc_reg_above_64_val_t));
   1225 
   1226     entry.Type                          = LOG_ENTRY_TYPE_FastRegData;
   1227 
   1228     /*Insert the log entry*/
   1229     return _soc_hw_log_insert_entry_to_log(unit, &entry);
   1230 }
   1231 
   1232 STATIC int
   1233 _soc_hw_log_fast_reg_get(int unit, soc_reg_t reg, int acc_type, int addr, int block, soc_reg_above_64_val_t data)
   1234 {
   1235     HwLogEntry_t    *entry          = NULL;
   1236     int             found           = FALSE;
   1237     soc_error_t     res             = SOC_E_NONE;
   1238     uint32          i;
   1239 
   1240     if (!soc_hw_log_is_initialized(unit) || _soc_hw_log_log_list_is_empty(unit)) 
   1241     {
   1242         /* The List is not initialized or empty */
   1243         goto not_found;
   1244     }
   1245 
   1246     for (i=0 ; i < Hw_Log_List[unit].header->nof_elements; i++) {
   1247 
   1248         entry = &(Hw_Log_List[unit].journal[i]);
   1249 
   1250         if (entry->Entry.Type == LOG_ENTRY_TYPE_FastRegData)
   1251         {
   1252             if (       (reg         == entry->Entry.Data.FastRegData.Reg)
   1253                     && (acc_type    == entry->Entry.Data.FastRegData.AccType)
   1254                     && (addr        == entry->Entry.Data.FastRegData.Addr)
   1255                     && (block       == entry->Entry.Data.FastRegData.Block ))
   1256             {
   1257                 sal_memcpy(data, entry->Entry.Data.FastRegData.EntryData, sizeof(soc_reg_above_64_val_t));
   1258 
   1259                 found = TRUE;
   1260                 LOG_DEBUG( BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "MEM FOUND in LOG!!! .\n")) );
   1261                 HW_LOG_DEBUG(_soc_hw_log_print_list_memory_entry(unit, entry->Entry.Data));
   1262             }
   1263         }
   1264     }
   1265 
   1266 not_found:
   1267     if (!found)
   1268     {
   1269         Hw_Log_List[unit].ImmediateAccess = TRUE;
   1270 #ifdef BCM_ARAD_SUPPORT
   1271         res = arad_fast_reg_get(unit, reg,  acc_type, addr, block, data);
   1272 #endif /*BCM_ARAD_SUPPORT*/
   1273 
   1274         Hw_Log_List[unit].ImmediateAccess = FALSE;
   1275 
   1276         if (SOC_FAILURE(res))
   1277         {
   1278             LOG_ERROR(BSL_LS_SOC_HWLOG,
   1279                             (BSL_META_U(unit, "Unit %d: FAILED to FAST READ reg %d(%s)!\n"),
   1280                              unit, reg, SOC_REG_NAME( unit, reg)));
   1281         }
   1282     }
   1283 
   1284     return res;
   1285 
   1286 }
   1287 STATIC int
   1288 _soc_hw_log_soc_reg_set(int unit, soc_reg_t reg, int port, int index, uint64 entry_data)
   1289 {
   1290     return _soc_hw_log_write_register_to_log(unit, reg, port, index, LOG_ENTRY_TYPE_SocRegData, &entry_data);
   1291 }
   1292 
   1293 STATIC int
   1294 _soc_hw_log_soc_reg_get(int unit, soc_reg_t reg, int port, int index, uint64 *data)
   1295 {
   1296    
   1297     return  _soc_hw_log_read_register_entry_from_log(unit, reg, port, index, LOG_ENTRY_TYPE_SocRegData, data);
   1298 }
   1299 
   1300 STATIC int
   1301 _soc_hw_log_reg_set_nocache(int unit, soc_reg_t reg, int port, int index, uint64 entry_data)
   1302 {
   1303     return _soc_hw_log_write_register_to_log(unit, reg, port, index, LOG_ENTRY_TYPE_SocRegNoCacheData, &entry_data);
   1304 }
   1305 
   1306 int
   1307 soc_hw_log_suppress(int unit)
   1308 {
   1309     if (!SOC_UNIT_VALID(unit))
   1310         return SOC_E_UNIT;
   1311 
   1312     if (soc_dcmn_cr_utils_is_journaling_thread(unit)) {
   1313         /* Indicate that we have reached an unsupported feature */
   1314         Hw_Log_List[unit].is_suppressed = TRUE;
   1315         LOG_DEBUG(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "--- HW LOG SUPPRESSED !!! --- : \n")));
   1316     }
   1317 
   1318     return SOC_E_NONE;
   1319 }
   1320 
   1321 int
   1322 soc_hw_log_unsuppress(int unit)
   1323 {
   1324 
   1325     if (!SOC_UNIT_VALID(unit))
   1326         return SOC_E_UNIT;
   1327 
   1328     if (soc_dcmn_cr_utils_is_journaling_thread(unit)) {
   1329         Hw_Log_List[unit].is_suppressed = FALSE;
   1330         LOG_DEBUG(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "--- HW LOG UNSUPPRESSED !!! --- : \n")));
   1331     }
   1332 
   1333     return SOC_E_NONE;
   1334 }
   1335 
   1336 STATIC int
   1337 _soc_hw_log_is_suppressed(int unit)
   1338 {
   1339     return (Hw_Log_List[unit].is_suppressed);
   1340 }
   1341 
   1342 int
   1343 soc_hw_log_ensure_not_suppressed(int unit) 
   1344 {
   1345     SOC_INIT_FUNC_DEFS;
   1346     
   1347     if (_soc_hw_log_is_suppressed(unit)) {
   1348         LOG_VERBOSE(BSL_LS_SOC_HWLOG, (BSL_META_U(unit, "!!! ERROR: HW LOG SUPPRESSED WHEN IT SHOULD NOT BE !!! \n")));
   1349         return SOC_E_FAIL;
   1350     }
   1351 
   1352     SOC_EXIT;
   1353 
   1354 exit:
   1355     SOC_FUNC_RETURN;
   1356 
   1357 }
   1358 
   1359 STATIC uint32
   1360 _soc_hw_log_commit_counter_get(int unit)
   1361 {
   1362     return Hw_Log_List[unit].header->hw_log_commit_index;
   1363 }
   1364 
   1365 STATIC int
   1366 _soc_hw_log_commit_counter_set(int unit, uint32 counter)
   1367 {
   1368     SOC_INIT_FUNC_DEFS;
   1369 
   1370     Hw_Log_List[unit].header->hw_log_commit_index = counter;
   1371 
   1372     SOC_EXIT;
   1373 
   1374 exit:
   1375     SOC_FUNC_RETURN;
   1376 }
   1377 
   1378 STATIC int
   1379 _soc_hw_log_commit_counter_reset(int unit)
   1380 {
   1381     SOC_INIT_FUNC_DEFS;
   1382 
   1383     _soc_hw_log_commit_counter_set(unit, 0);
   1384 
   1385     SOC_EXIT;
   1386 
   1387 exit:
   1388     SOC_FUNC_RETURN;
   1389 }
   1390 
   1391 STATIC void *
   1392 _soc_hw_log_sbusdma_buffer_allocate(int unit, uint32 size)
   1393 {
   1394     char *pt = (char *)Hw_Log_List[unit].header;
   1395 
   1396     /* check if we have sufficient space left to allocate the new dma buffer */
   1397     if(Hw_Log_List[unit].header->dma_allocated_size + size > HW_LOG_DMA_BUFFER_SIZE) {
   1398         return NULL;
   1399     }
   1400 
   1401     /* increase the allocated dma buffer size */
   1402     Hw_Log_List[unit].header->dma_allocated_size += size;
   1403 
   1404     /* return a pointer to the newly allocated buffer */
   1405     pt +=  (Hw_Log_List[unit].size - HW_LOG_DMA_BUFFER_SIZE + Hw_Log_List[unit].header->dma_allocated_size);
   1406 
   1407     return (void *)pt;
   1408 }
   1409 
   1410 STATIC int
   1411 _soc_hw_log_sbusdma_buffers_free(int unit)
   1412 {
   1413     SOC_INIT_FUNC_DEFS;
   1414 
   1415     Hw_Log_List[unit].header->dma_allocated_size = 0;
   1416 
   1417     SOC_EXIT;
   1418 
   1419 exit:
   1420     SOC_FUNC_RETURN;
   1421 }
   1422 
   1423 STATIC int _soc_hw_log_descdma_write(int unit, soc_mem_t mem, unsigned array_index, int copyno, int index, void *entry_data)
   1424 {
   1425     LogEntry_t entry;
   1426     uint32 entry_words;
   1427 
   1428     sal_memset(entry.Data.MemData.EntryData, 0, sizeof(entry.Data.MemData.EntryData));
   1429 
   1430     entry_words                   = soc_mem_entry_words(unit, mem);
   1431     /* Init the Log entry */
   1432     entry.Data.MemData.Mem        = mem;
   1433     entry.Data.MemData.ArrayIndex = array_index;
   1434     entry.Data.MemData.Blk        = copyno;
   1435     entry.Data.MemData.Index      = index;
   1436     entry.Data.MemData.DescDMA    = TRUE;
   1437 
   1438     entry.Type                    = LOG_ENTRY_TYPE_Memory;
   1439 
   1440     sal_memcpy(entry.Data.MemData.EntryData, ((char*) entry_data),  entry_words*sizeof(int));
   1441 
   1442     /*Insert the log entry*/
   1443     return _soc_hw_log_insert_entry_to_log(unit, &entry);
   1444 }
   1445 
   1446 
   1447 /********************************************************************************/
   1448 /***********************Diag & Tests*********************************************/
   1449 /********************************************************************************/
   1450 int
   1451 soc_hw_log_mem_test(int unit, soc_mem_t mem, void* data)
   1452 {
   1453     if (!SOC_UNIT_VALID(unit))
   1454         return SOC_E_NONE;
   1455 
   1456     soc_mem_single_test(unit, mem);
   1457 
   1458     return SOC_E_NONE;
   1459 }
   1460 
   1461 int
   1462 soc_hw_log_reg_test(int unit)
   1463 {
   1464     if (!SOC_UNIT_VALID(unit))
   1465         return SOC_E_NONE;
   1466 
   1467     reg_test(unit, NULL, NULL); /* TR 3 */
   1468     return SOC_E_NONE;
   1469 }
   1470 
   1471 #endif /* CRASH_RECOVERY_SUPPORT */