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