latency_monitor.c (82896B)
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 */ 8 9 #include <shared/bsl.h> 10 #include <sal/appl/sal.h> 11 #include <sal/core/time.h> 12 #include <appl/diag/system.h> 13 #include <appl/diag/parse.h> 14 #include <soc/mem.h> 15 #include <soc/register.h> 16 #include <soc/debug.h> 17 #include <soc/dma.h> 18 #include <soc/schanmsg_internal.h> 19 #include <soc/sbusdma_internal.h> 20 21 #include <bcm/error.h> 22 #include <bcm_int/esw/latency_monitor.h> 23 #include <soc/drv.h> 24 #include <bcm_int/esw/flex_ctr.h> 25 #include <bcm_int/common/debug.h> 26 #include <include/soc/tomahawk3.h> 27 28 #ifdef BCM_WARM_BOOT_SUPPORT 29 #include <bcm_int/esw/switch.h> 30 #endif /* BCM_WARM_BOOT_SUPPORT */ 31 32 extern int inside_bcm_shutdown[BCM_MAX_NUM_UNITS]; 33 34 static latency_monitor_driver_data_t latency_monitor_driver_data; 35 static latency_monitor_mem_t latency_monitor_mem[BCM_MAX_NUM_UNITS][LATENCY_MONITOR_MAX_COUNT]; 36 int bcm_tomahawk3_latency_monitor_enable(int unit, uint8 monitor_id, uint8 enable); 37 38 #ifdef BCM_WARM_BOOT_SUPPORT 39 #ifdef BCM_TOMAHAWK3_SUPPORT 40 STATIC int _bcm_th3_latency_monitor_scache_alloc(int unit, int create); 41 STATIC int _bcm_th3_latency_monitor_wb_recover(int unit); 42 #endif /* BCM_TOMAHAWK3_SUPPORT */ 43 #endif /* BCM_WARM_BOOT_SUPPORT */ 44 45 uint8 wb_post_init; 46 47 /** 48 * Initialize the linked list (fifo) to empty value. 49 * @param desc_handle_list 50 */ 51 void 52 _sbusdma_desc_handle_list_init(_sbusdma_desc_handle_list_t * desc_handle_list) 53 { 54 desc_handle_list->head = desc_handle_list->tail = NULL; 55 } 56 57 /** 58 * Push an entry to the end of the linked list 59 * 60 * @param desc_handle_list -linked list on which entry is added 61 * @param handle entry - to get pushed. 62 * 63 * @return int BCM_E_MEMORY if memory allocation fails, 64 * BCM_E_NONE otherwise. 65 */ 66 int 67 _sbusdma_desc_handle_list_push(_sbusdma_desc_handle_list_t *desc_handle_list, const _sbusdma_desc_handle_data_t *data) 68 { 69 _sbusdma_desc_handle_node_t *new_node = sal_alloc(sizeof(_sbusdma_desc_handle_node_t), "sbus dma fifo"); 70 if (new_node == NULL) { 71 return BCM_E_MEMORY; 72 } 73 new_node->next = NULL; 74 new_node->data = (_sbusdma_desc_handle_data_t *)data; 75 if (desc_handle_list->head != NULL) { 76 desc_handle_list->tail->next = new_node; 77 desc_handle_list->tail = new_node; 78 } else { 79 desc_handle_list->head = desc_handle_list->tail = new_node; 80 } 81 return BCM_E_NONE; 82 } 83 84 85 /** 86 * Pop an event from the front of the linked list (fifo) 87 * 88 * @param desc_handle_list - linked list where event is pushed. 89 * @param handle - event is set here. 90 * 91 * @return int BCM_E_EMPTY if linked list is empty, BCM_E_NONE 92 * otherwise. 93 */ 94 int 95 _sbusdma_desc_handle_list_pop(_sbusdma_desc_handle_list_t *desc_handle_list, _sbusdma_desc_handle_data_t **data) 96 { 97 if (desc_handle_list->head) { 98 _sbusdma_desc_handle_node_t *temp_head = desc_handle_list->head; 99 *data = desc_handle_list->head->data; 100 if (desc_handle_list->head == desc_handle_list->tail) { 101 desc_handle_list->head = desc_handle_list->tail = NULL; 102 } else { 103 desc_handle_list->head = desc_handle_list->head->next; 104 } 105 sal_free(temp_head); 106 return BCM_E_NONE; 107 } else { 108 return BCM_E_EMPTY; 109 } 110 } 111 112 113 int 114 _sbusdma_desc_handle_list_is_empty(_sbusdma_desc_handle_list_t *desc_handle_list) 115 { 116 if (!desc_handle_list->head) { 117 return TRUE; 118 } 119 120 return FALSE; 121 } 122 123 124 #ifdef BCM_TOMAHAWK3_SUPPORT 125 static int 126 latency_monitor_driver_data_init(int unit) 127 { 128 int i; 129 130 if (!latency_monitor_driver_data.init_done) { 131 latency_monitor_driver_data.desc_mode = 1; 132 latency_monitor_driver_data.dma_wr_en = TRUE; 133 latency_monitor_driver_data.dma_rd_en = TRUE; 134 latency_monitor_driver_data.num_mem = 1; 135 latency_monitor_driver_data.init_done = TRUE; 136 137 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 138 SOC_LATENCY_MONITOR_INFO(unit, i).time_step = -1; 139 SOC_LATENCY_MONITOR_INFO(unit, i).flex_pool_number = -1; 140 BCM_PBMP_CLEAR(SOC_LATENCY_MONITOR_INFO(unit, i).src_pbmp); 141 BCM_PBMP_CLEAR(SOC_LATENCY_MONITOR_INFO(unit, i).dest_pbmp); 142 } 143 } 144 145 return BCM_E_NONE; 146 } 147 #endif /* BCM_TOMAHAWK3_SUPPORT */ 148 149 static void 150 latency_monitor_sbusdma_cb(int unit, int status, sbusdma_desc_handle_t handle, 151 void *data) 152 { 153 int rv; 154 int monitor_id; 155 cb_data_t *p_cb_data; 156 uint32 *entbuf; 157 uint8 frag_count; 158 _sbusdma_desc_handle_data_t *list_data; 159 160 if (status != BCM_E_NONE) { 161 LOG_ERROR(BSL_LS_BCM_LATENCY_MONITOR, 162 (BSL_META_U(unit, "SBUS DMA failed: type %d\n"), 163 PTR_TO_INT(data))); 164 if (status == BCM_E_TIMEOUT) 165 (void)soc_sbusdma_desc_delete(unit, handle); 166 } 167 168 if (data == NULL) { 169 return; 170 } 171 172 p_cb_data = (cb_data_t *)data; 173 monitor_id = p_cb_data->monitor_id; 174 175 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 176 (BSL_META_U(unit, "latency_monitor_sbusdma_cb:: monitor_id:%d \n"), 177 monitor_id)); 178 179 if (p_cb_data->write_op) { 180 BCM_EXIT; 181 } 182 183 frag_count = latency_monitor_mem[unit][monitor_id].frag_count; 184 entbuf = sal_alloc(WORDS2BYTES(latency_monitor_mem[unit][monitor_id].bufwords/frag_count), "CB dma fifo"); 185 if (entbuf) { 186 /* Since the DMA able memory is scarce, copy and free it at the earliest possible. */ 187 sal_memcpy(entbuf, p_cb_data->data, WORDS2BYTES((latency_monitor_mem[unit][monitor_id].bufwords)/frag_count)); 188 if (p_cb_data->data) { 189 soc_cm_sfree(unit, p_cb_data->data); 190 } 191 } else { 192 latency_monitor_driver_data.run[monitor_id] = FALSE; 193 BCM_EXIT; 194 } 195 196 list_data = sal_alloc(sizeof(_sbusdma_desc_handle_data_t), "DMA handler list data"); 197 if (list_data) { 198 list_data->dbuf = entbuf; 199 list_data->pipe = p_cb_data->pipe_num; 200 } 201 202 if (latency_monitor_driver_data.run[monitor_id] == TRUE) { 203 sal_sem_take(latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock, sal_sem_FOREVER); 204 _sbusdma_desc_handle_list_push(&latency_monitor_mem[unit][monitor_id].handle_list, list_data); 205 sal_sem_give(latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem); 206 sal_sem_give(latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock); 207 } else { 208 sal_free(entbuf); 209 sal_free(list_data); 210 } 211 212 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 213 (BSL_META_U(unit,"Call back completed for handle:%d Monitor:%d data:%p\n"), 214 handle, monitor_id, p_cb_data->data)); 215 exit: 216 rv = soc_sbusdma_desc_delete(unit, handle); 217 if (rv != BCM_E_NONE) { 218 LOG_ERROR(BSL_LS_BCM_LATENCY_MONITOR, 219 (BSL_META_U(unit, 220 "Failed to delete sbusdma descriptor Monitor:%d\n"), 221 monitor_id)); 222 } else { 223 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 224 (BSL_META_U(unit, 225 "Deleting handle %d Monitor:%d\n"), 226 handle, monitor_id)); 227 } 228 229 if (latency_monitor_driver_data.sbusdma_run_lock) { 230 sal_sem_give(latency_monitor_driver_data.sbusdma_run_lock); 231 } 232 sal_free(p_cb_data); 233 /* coverity[leaked_storage : FALSE] */ 234 } 235 236 237 static int 238 latency_monitor_sbusdma_setup(int unit, int monitor_id, int pipe, uint32 *entbuf, int index_min, 239 int index_max, int frag, int write, sbusdma_desc_handle_t *handle_to_run) 240 { 241 /* for soc_sbusdma_desc_create and soc_sbusdma_desc_run */ 242 soc_sbusdma_desc_ctrl_t ctrl; 243 soc_sbusdma_desc_cfg_t cfg; 244 soc_sbusdma_desc_cfg_t *cfg_array; 245 int rv = BCM_E_NONE; 246 int i; 247 uint8 at; 248 cb_data_t *p_cb_data; 249 250 if (latency_monitor_driver_data.desc_mode > 0) { 251 /* descriptor based sbus dma mode through sdk api */ 252 sal_memset(&ctrl, 0, sizeof(soc_sbusdma_desc_ctrl_t)); 253 sal_memset(&cfg, 0, sizeof(soc_sbusdma_desc_cfg_t)); 254 cfg_array = soc_cm_salloc(unit, sizeof(soc_sbusdma_desc_cfg_t) * 255 latency_monitor_driver_data.desc_mode, "sbusdma_desc_cfg"); 256 ctrl.cfg_count = latency_monitor_driver_data.desc_mode; 257 ctrl.cb = latency_monitor_sbusdma_cb; 258 p_cb_data = sal_alloc(sizeof(cb_data_t), "CB Data"); 259 if (p_cb_data == NULL) { 260 return BCM_E_MEMORY; 261 } 262 p_cb_data->monitor_id = monitor_id; 263 p_cb_data->data = entbuf; 264 if (write == 0) { 265 ctrl.flags = SOC_SBUSDMA_MEMORY_CMD_MSG; 266 } else { 267 ctrl.flags = SOC_SBUSDMA_WRITE_CMD_MSG | SOC_SBUSDMA_MEMORY_CMD_MSG; 268 } 269 p_cb_data->write_op = write; 270 p_cb_data->pipe_num = pipe; 271 ctrl.data = p_cb_data; 272 273 cfg.acc_type = SOC_MEM_ACC_TYPE(unit, latency_monitor_mem[unit][monitor_id].mem+pipe); 274 cfg.blk = SOC_BLOCK2SCH(unit, latency_monitor_mem[unit][monitor_id].copyno); 275 cfg.addr = soc_mem_addr_get(unit, latency_monitor_mem[unit][monitor_id].mem+pipe, 0, 276 latency_monitor_mem[unit][monitor_id].copyno, index_min, &at); 277 cfg.width = latency_monitor_mem[unit][monitor_id].entwords; 278 cfg.count = index_max - index_min + 1; 279 cfg.buff = entbuf; 280 cfg.addr_shift = 0; 281 for (i = 0; i < latency_monitor_driver_data.desc_mode; i++) { 282 sal_memcpy(cfg_array + i, &cfg, sizeof(soc_sbusdma_desc_cfg_t)); 283 } 284 285 if (SOC_FAILURE((rv = (soc_sbusdma_desc_create(unit, &ctrl, cfg_array, 286 handle_to_run))))) { 287 _SHR_ERROR_TRACE(rv); 288 } 289 290 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 291 (BSL_META_U(unit,"Create handle %d Monitor:%d\n"), 292 *handle_to_run, monitor_id)); 293 294 soc_cm_sfree(unit, cfg_array); 295 } 296 297 return rv; 298 } 299 300 void 301 counter_accrue_thread(void* up) 302 { 303 int unit = PTR_TO_INT(up) & 0xff; 304 int monitor_id; 305 uint32 packet_count=0; 306 uint64 byte_count; 307 soc_memacc_t memacc_pkt_x; 308 soc_memacc_t memacc_byte_x; 309 egr_flex_ctr_counter_table_0_entry_t *data_ptr; 310 uint64 (*arr_pkt_cnt)[LATENCY_MONITOR_BUCKET_COUNT]; 311 uint64 (*arr_byte_cnt)[LATENCY_MONITOR_BUCKET_COUNT]; 312 int l, j, k; 313 int data_buffer_idx = 0; 314 uint32 *dbuf = NULL; 315 int frag_count; 316 uint64 *sw_buff = NULL; 317 uint32 sw_buf_idx = 0; 318 _sbusdma_desc_handle_data_t *list_data; 319 int pipe = 0; 320 int pipe_lower = -1; 321 uint64 byte_count_tmp; 322 uint32 packet_count_tmp; 323 uint8 pkt_ctr_f_width; 324 uint64 tmp64; 325 uint64 mask64; 326 327 monitor_id = PTR_TO_INT(up) >> 8; 328 if (((soc_memacc_init(unit, latency_monitor_mem[unit][monitor_id].mem, PACKET_COUNTERf, &memacc_pkt_x))) || 329 ((soc_memacc_init(unit, latency_monitor_mem[unit][monitor_id].mem, BYTE_COUNTERf, &memacc_byte_x)))) { 330 return; 331 } 332 333 frag_count = latency_monitor_mem[unit][monitor_id].frag_count; 334 pkt_ctr_f_width = soc_mem_field_length(unit,latency_monitor_mem[unit][monitor_id].mem, PACKET_COUNTERf); 335 336 while (TRUE) { 337 if (sal_sem_take(latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem, sal_sem_FOREVER) == 0) { 338 if ((latency_monitor_driver_data.run[monitor_id] == FALSE) && 339 (_sbusdma_desc_handle_list_is_empty(&latency_monitor_mem[unit][monitor_id].handle_list))) { 340 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 341 (BSL_META_U(unit, "Exiting the counter_accrue_thread monitor_id:%d \n"), monitor_id)); 342 BCM_EXIT; 343 } 344 sal_sem_take(latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock, sal_sem_FOREVER); 345 _sbusdma_desc_handle_list_pop(&latency_monitor_mem[unit][monitor_id].handle_list, &list_data); 346 sal_sem_give(latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock); 347 348 if (list_data) { 349 dbuf = list_data->dbuf; 350 pipe = list_data->pipe; 351 sal_free(list_data); 352 } else { 353 BCM_EXIT; 354 } 355 356 if (latency_monitor_mem[unit][monitor_id].pipe_map_temp == 0) { 357 latency_monitor_mem[unit][monitor_id].pipe_map_temp = latency_monitor_mem[unit][monitor_id].dest_pbmp_pipe_map; 358 pipe_lower = pipe; 359 } else { 360 pipe_lower = -1; 361 } 362 363 latency_monitor_mem[unit][monitor_id].pipe_map_temp &= ~(1 << pipe); 364 365 if (dbuf) { 366 arr_pkt_cnt = (uint64 (*)[LATENCY_MONITOR_BUCKET_COUNT])latency_monitor_mem[unit][monitor_id].histogram_packet64_counter; 367 arr_byte_cnt = (uint64 (*)[LATENCY_MONITOR_BUCKET_COUNT])latency_monitor_mem[unit][monitor_id].histogram_byte64_counter; 368 data_ptr = (egr_flex_ctr_counter_table_0_entry_t *)dbuf; 369 data_buffer_idx = 0; 370 for (l=0; l<(TIME_STEP_SET_COUNT/frag_count); l++) { 371 if (latency_monitor_mem[unit][monitor_id].monitor_mode == bcmLatencyMonitorTimeSeriesMode) { 372 sw_buff = (uint64 *)latency_monitor_mem[unit][monitor_id].sw_buf_addr; 373 } 374 for (j=0; j<LATENCY_MONITOR_QUEUE_COUNT; j++) { 375 for (k=0; k<LATENCY_MONITOR_BUCKET_COUNT; k++) { 376 soc_memacc_field64_get(&memacc_byte_x, 377 (uint64 *)&data_ptr[data_buffer_idx], &byte_count); 378 packet_count = soc_memacc_field32_get(&memacc_pkt_x, 379 (uint32 *)&data_ptr[data_buffer_idx]); 380 COMPILER_64_ADD_32(arr_pkt_cnt[j][k], packet_count); 381 COMPILER_64_ADD_64(arr_byte_cnt[j][k], byte_count); 382 data_buffer_idx++; 383 if (latency_monitor_mem[unit][monitor_id].monitor_mode == bcmLatencyMonitorTimeSeriesMode) { 384 sw_buf_idx = latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx; 385 386 packet_count_tmp = 0; 387 COMPILER_64_ZERO(byte_count_tmp); 388 if (pipe_lower != -1) { 389 /* Overwrite counter for the the pipe corresponding to first port in dbmp */ 390 COMPILER_64_COPY(sw_buff[sw_buf_idx], byte_count); 391 } else { 392 COMPILER_64_COPY(tmp64, sw_buff[sw_buf_idx]); 393 COMPILER_64_SHR(tmp64, pkt_ctr_f_width); 394 COMPILER_64_COPY(byte_count_tmp, tmp64); 395 COMPILER_64_COPY(tmp64, sw_buff[sw_buf_idx]); 396 COMPILER_64_SET(mask64, 0, (uint32)((1 << pkt_ctr_f_width) - 1)); 397 COMPILER_64_AND(tmp64, mask64); 398 packet_count_tmp = COMPILER_64_LO(tmp64); 399 /* Accumulate counter for the remaining pipe corresponding to port in dbmp */ 400 COMPILER_64_ADD_64(byte_count_tmp, byte_count); 401 COMPILER_64_COPY(sw_buff[sw_buf_idx], byte_count_tmp); 402 } 403 packet_count_tmp += packet_count; 404 COMPILER_64_SHL(sw_buff[sw_buf_idx], pkt_ctr_f_width); 405 COMPILER_64_ADD_32(sw_buff[sw_buf_idx], packet_count_tmp); 406 407 latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx++; 408 latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx %= latency_monitor_mem[unit][monitor_id].sw_buf_size; 409 } 410 } 411 } 412 } 413 414 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 415 (BSL_META_U(unit, "Freed buffer for dbuf:%p Monitor:%d\n"), dbuf, monitor_id)); 416 sal_free(dbuf); 417 418 /* Call the callback handler after accumilation for all the pipes */ 419 if ((latency_monitor_mem[unit][monitor_id].monitor_mode == bcmLatencyMonitorTimeSeriesMode) && 420 (latency_monitor_mem[unit][monitor_id].pipe_map_temp == 0) && 421 (latency_monitor_mem[unit][monitor_id].cb)) { 422 latency_monitor_mem[unit][monitor_id].cb(unit, monitor_id, latency_monitor_mem[unit][monitor_id].status, 423 (void *)sw_buff, latency_monitor_mem[unit][monitor_id].sw_buf_size, sw_buf_idx); 424 } 425 426 /* Counter accumilation pending for other pipes. Back track the sw_buf_wr_idx index in S/W Ring buffer */ 427 if ((latency_monitor_mem[unit][monitor_id].monitor_mode == bcmLatencyMonitorTimeSeriesMode) && 428 (latency_monitor_mem[unit][monitor_id].pipe_map_temp != 0)) { 429 if (latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx == 0) { 430 latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx = latency_monitor_mem[unit][monitor_id].sw_buf_size; 431 } 432 433 if (latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx) { 434 latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx -= 435 (LATENCY_MONITOR_QUEUE_COUNT * LATENCY_MONITOR_BUCKET_COUNT)*(TIME_STEP_SET_COUNT/frag_count); 436 } 437 } 438 } 439 } 440 } 441 442 exit: 443 if (latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem) { 444 sal_sem_destroy(latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem); 445 latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem = NULL; 446 } 447 448 if (latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock) { 449 sal_sem_destroy(latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock); 450 latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock = NULL; 451 } 452 latency_monitor_mem[unit][monitor_id].init_done = FALSE; 453 454 if (latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_RUNNING) { 455 latency_monitor_mem[unit][monitor_id].status = LATENCY_MONITOR_STATE_IDLE; 456 } 457 458 sal_thread_exit(0); 459 460 return; 461 } 462 463 static int 464 _get_curr_histogram_set(int unit, int monitor_id) 465 { 466 soc_reg_t histogram_set_reg; 467 uint32 reg_value; 468 int rv = SOC_E_NONE; 469 int histogram_set; 470 471 switch (monitor_id) { 472 case MONITOR_ID_0: 473 histogram_set_reg = EGR_HISTO_MON_0_HISTOGRAM_SETr; 474 break; 475 case MONITOR_ID_1: 476 histogram_set_reg = EGR_HISTO_MON_1_HISTOGRAM_SETr; 477 break; 478 case MONITOR_ID_2: 479 histogram_set_reg = EGR_HISTO_MON_2_HISTOGRAM_SETr; 480 break; 481 case MONITOR_ID_3: 482 histogram_set_reg = EGR_HISTO_MON_3_HISTOGRAM_SETr; 483 break; 484 default: 485 return SOC_E_PARAM; 486 } 487 488 rv = soc_reg32_get(unit, histogram_set_reg, REG_PORT_ANY, 0, ®_value); 489 SOC_IF_ERROR_RETURN(rv); 490 histogram_set = soc_reg_field_get(unit,histogram_set_reg,reg_value, HISTOGRAM_SETf); 491 492 return histogram_set; 493 } 494 495 static int 496 _check_for_wraparound_condition(int unit, int monitor_id, int frag) 497 { 498 soc_reg_t histogram_set_reg; 499 soc_reg_t flex_ctr_wrap_ctr_reg; 500 int histogram_set; 501 uint32 flex_ctr_wrap_ctr_old; 502 uint32 flex_ctr_wrap_ctr_new; 503 uint32 reg_value; 504 int rv = SOC_E_NONE; 505 int frag_count; 506 uint8 frag_set_idx; 507 508 switch (monitor_id) { 509 case MONITOR_ID_0: 510 histogram_set_reg = EGR_HISTO_MON_0_HISTOGRAM_SETr; 511 flex_ctr_wrap_ctr_reg = EGR_HISTO_MON_0_FLEX_COUNTER_WRAP_COUNTERr; 512 break; 513 case MONITOR_ID_1: 514 histogram_set_reg = EGR_HISTO_MON_1_HISTOGRAM_SETr; 515 flex_ctr_wrap_ctr_reg = EGR_HISTO_MON_1_FLEX_COUNTER_WRAP_COUNTERr; 516 break; 517 case MONITOR_ID_2: 518 histogram_set_reg = EGR_HISTO_MON_2_HISTOGRAM_SETr; 519 flex_ctr_wrap_ctr_reg = EGR_HISTO_MON_2_FLEX_COUNTER_WRAP_COUNTERr; 520 break; 521 case MONITOR_ID_3: 522 histogram_set_reg = EGR_HISTO_MON_3_HISTOGRAM_SETr; 523 flex_ctr_wrap_ctr_reg = EGR_HISTO_MON_3_FLEX_COUNTER_WRAP_COUNTERr; 524 break; 525 default: 526 return BCM_E_PARAM; 527 } 528 529 frag_count = latency_monitor_mem[unit][monitor_id].frag_count; 530 531 while (latency_monitor_driver_data.run[monitor_id]) { 532 rv = soc_reg32_get(unit, histogram_set_reg, REG_PORT_ANY, 0, ®_value); 533 SOC_IF_ERROR_RETURN(rv); 534 histogram_set = soc_reg_field_get(unit,histogram_set_reg,reg_value, HISTOGRAM_SETf); 535 536 rv = soc_reg32_get(unit, flex_ctr_wrap_ctr_reg, REG_PORT_ANY, 0, ®_value); 537 SOC_IF_ERROR_RETURN(rv); 538 flex_ctr_wrap_ctr_new = soc_reg_field_get(unit,flex_ctr_wrap_ctr_reg,reg_value, FLEX_COUNTER_WRAP_COUNTf); 539 540 flex_ctr_wrap_ctr_old = latency_monitor_mem[unit][monitor_id].flex_ctr_wrap_ctr; 541 /* On The H/W reg field FLEX_COUNTER_WRAP_COUNT wrap, reset the counters */ 542 if ((flex_ctr_wrap_ctr_old == 0xFFFFFFFF) && (flex_ctr_wrap_ctr_new == 0)) { 543 flex_ctr_wrap_ctr_old = 0; 544 } 545 latency_monitor_mem[unit][monitor_id].flex_ctr_wrap_ctr = flex_ctr_wrap_ctr_new; 546 547 if ((flex_ctr_wrap_ctr_new - flex_ctr_wrap_ctr_old) > 1 ) { 548 /* Error: Data Overwrite Occurred */ 549 return BCM_E_FAIL; 550 } 551 if (frag == 0) { /* Check for 1st Fragment */ 552 /* Checking to schedule DMA for 1st Half of the flex counter block */ 553 if (histogram_set >= (TIME_STEP_SET_COUNT/frag_count)) { 554 /*i.e the hardware is upgrading the 2nd half of the allocated flex pool */ 555 if ((flex_ctr_wrap_ctr_new - flex_ctr_wrap_ctr_old) > 0) { 556 /* Error: Data Overwrite Occurred */ 557 return BCM_E_FAIL; 558 } else { 559 frag_set_idx = histogram_set - (TIME_STEP_SET_COUNT/frag_count); 560 latency_monitor_mem[unit][monitor_id].dma_schedule_period = 561 ((TIME_STEP_SET_COUNT/frag_count) - frag_set_idx) * latency_monitor_mem[unit][monitor_id].time_step; 562 /* We are good */ 563 return BCM_E_NONE; 564 } 565 } else { 566 if (latency_monitor_driver_data.run[monitor_id] == FALSE) { 567 return BCM_E_NONE; 568 } 569 } 570 } else if (frag == 1) { /* Check for 2nd Fragment */ 571 /* Checking to schedule DMA for 2nd Half of the flex counter block */ 572 if (histogram_set < (TIME_STEP_SET_COUNT/frag_count)) { 573 /*i.e the hardware is upgrading the 1st half of the allocated flex pool */ 574 if ((flex_ctr_wrap_ctr_new - flex_ctr_wrap_ctr_old) > 1) { 575 /* Error: Data Overwrite Occurred */ 576 return BCM_E_FAIL; 577 } else { 578 latency_monitor_mem[unit][monitor_id].dma_schedule_period = 579 ((TIME_STEP_SET_COUNT/frag_count) - histogram_set) * latency_monitor_mem[unit][monitor_id].time_step; 580 /* We are good */ 581 return BCM_E_NONE; 582 } 583 } else { 584 if (latency_monitor_driver_data.run[monitor_id] == FALSE) { 585 return BCM_E_NONE; 586 } 587 } 588 } else { 589 /* We never enter here. Error condition. */ 590 return BCM_E_FAIL; 591 } 592 }; 593 594 return BCM_E_NONE; 595 } 596 597 static int 598 sbusdma_handler_run (int unit, sbusdma_desc_handle_t handle) 599 { 600 soc_timeout_t to; 601 sal_usecs_t dma_timeout = 1000000; 602 int ret; 603 604 soc_timeout_init(&to, 2 * dma_timeout, 0); 605 do { 606 ret = soc_sbusdma_desc_run(unit, handle); 607 if ((ret == BCM_E_BUSY) || (ret == BCM_E_INIT)) { 608 if (ret == BCM_E_INIT) { 609 break; 610 } 611 if (soc_timeout_check(&to)) { 612 LOG_WARN(BSL_LS_BCM_LATENCY_MONITOR, 613 (BSL_META_U(unit, 614 "sbusdma desc run operation timeout\n"))); 615 return BCM_E_TIMEOUT; 616 } 617 sal_usleep(10); 618 } 619 } while ((ret == BCM_E_BUSY) || (ret == BCM_E_INIT)); 620 621 return BCM_E_NONE; 622 } 623 624 static void 625 sbusdma_read(void* up) 626 { 627 int unit = PTR_TO_INT(up) & 0xff; 628 uint32 *entbuf; 629 uint32 *cleanup_buf; 630 int frag; 631 int index_min, index_max; 632 char *access_type; 633 int cnt; 634 int monitor_id; 635 sal_usecs_t dma_timeout = 1000000; 636 sbusdma_desc_handle_t handle_to_run = 0; 637 uint64 rval, val; 638 int frag_count; 639 uint8 frag_set_idx; 640 uint8 histogram_set; 641 uint8 pipe; 642 int rv = BCM_E_NONE; 643 644 if (latency_monitor_driver_data.dma_rd_en) { 645 access_type = sal_strdup("SBUS DMA"); 646 } else { 647 access_type = sal_strdup("SBUS "); 648 } 649 650 monitor_id = PTR_TO_INT(up) >> 8; 651 frag_count = latency_monitor_mem[unit][monitor_id].frag_count; 652 653 latency_monitor_mem[unit][monitor_id].sbusdma_read_thread_pid = sal_thread_id_get(); 654 655 while (latency_monitor_driver_data.run[monitor_id] == FALSE) { 656 sal_usleep(10); 657 } 658 659 cnt = WORDS2BYTES((latency_monitor_mem[unit][monitor_id].bufwords)/frag_count); 660 cleanup_buf = soc_cm_salloc(unit, cnt, "latency monitor cleanup buffer"); 661 if (!cleanup_buf) { 662 BCM_EXIT; 663 } 664 sal_memset(cleanup_buf, 0x0, cnt); 665 666 histogram_set = _get_curr_histogram_set(unit, monitor_id); 667 if (histogram_set >= (TIME_STEP_SET_COUNT/frag_count)) { 668 frag = 1; /* Start from second Half of the flex counter pool block */ 669 frag_set_idx = histogram_set - (TIME_STEP_SET_COUNT/frag_count); 670 latency_monitor_mem[unit][monitor_id].dma_schedule_period = ((TIME_STEP_SET_COUNT/frag_count) - frag_set_idx) * 671 latency_monitor_mem[unit][monitor_id].time_step; 672 } else { 673 frag = 0; /* Start from first Half of the flex counter pool block */ 674 latency_monitor_mem[unit][monitor_id].dma_schedule_period = ((TIME_STEP_SET_COUNT/frag_count) - histogram_set) * 675 latency_monitor_mem[unit][monitor_id].time_step; 676 } 677 678 while (latency_monitor_driver_data.run[monitor_id]) { 679 frag %= latency_monitor_mem[unit][monitor_id].frag_count; 680 for (; frag < latency_monitor_mem[unit][monitor_id].frag_count; frag++) { 681 index_min = latency_monitor_mem[unit][monitor_id].frag_index_min[frag]; 682 index_max = latency_monitor_mem[unit][monitor_id].frag_index_max[frag]; 683 684 /* 685 * The Binary Semaphore time out here is used for periodic scheduling of SBUS DMA. 686 * The semaphore is also used to signal that the monitor is disabled and quick termination of the thread. 687 */ 688 sal_sem_take(latency_monitor_mem[unit][monitor_id].latency_monitor_thread_trigger, 689 latency_monitor_mem[unit][monitor_id].dma_schedule_period); 690 if (latency_monitor_driver_data.run[monitor_id] == FALSE) { 691 BCM_EXIT; 692 } 693 if (_check_for_wraparound_condition(unit, monitor_id, frag) != SOC_E_NONE) { 694 /* Disable Monitor */ 695 bcm_tomahawk3_latency_monitor_enable(unit, monitor_id, 0); 696 latency_monitor_mem[unit][monitor_id].status = LATENCY_MONITOR_STATE_ERROR; 697 if (latency_monitor_mem[unit][monitor_id].cb) { 698 latency_monitor_mem[unit][monitor_id].cb(unit, monitor_id, LATENCY_MONITOR_STATE_ERROR, NULL,0,0); 699 } 700 BCM_EXIT; 701 } 702 703 entbuf = soc_cm_salloc(unit, cnt, 704 "latency_monitor_driver_data source"); 705 if (!entbuf) { 706 latency_monitor_driver_data.run[monitor_id] = FALSE; 707 BCM_EXIT; 708 } 709 sal_memset(entbuf, 0x0, cnt); 710 711 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 712 (BSL_META_U(unit, "Allocated %d bytes addr:%p Monitor:%d\n"), 713 cnt, entbuf, monitor_id)); 714 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 715 (BSL_META_U(unit, "New DMA Satrted index_min:%d index_max;%d Monitor:%d\n"), 716 index_min, index_max, monitor_id)); 717 718 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 719 (BSL_META_U(unit, "%s reading from %s[%0d..%0d] to address 0x%08x\n"), 720 access_type, SOC_MEM_NAME(unit, latency_monitor_mem[unit][monitor_id].mem), 721 index_max,index_min, PTR_TO_INT(entbuf))); 722 723 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 724 if (!(latency_monitor_mem[unit][monitor_id].dest_pbmp_pipe_map & (1 << pipe))) { 725 continue; 726 } 727 sal_sem_take(latency_monitor_driver_data.sbusdma_run_lock, sal_sem_FOREVER); 728 729 if (latency_monitor_driver_data.dma_rd_en) { 730 /* Setup DMA handler for read operation */ 731 latency_monitor_sbusdma_setup(unit, monitor_id, pipe, entbuf, index_min, 732 index_max, frag, 0, &handle_to_run); 733 } 734 735 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 736 (BSL_META_U(unit, "handle:%d Monitor:%d \n"), handle_to_run, monitor_id)); 737 738 if (latency_monitor_driver_data.dma_rd_en && latency_monitor_driver_data.desc_mode > 0) { 739 soc_timeout_t to; 740 soc_timeout_init(&to, 2 * dma_timeout, 0); 741 /* Execute SBUS DMA command to read the flex pool block */ 742 sbusdma_handler_run(unit, handle_to_run); 743 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 744 (BSL_META_U(unit, "DMA RUN completed Monitor:%d\n"), monitor_id)); 745 } 746 747 } 748 } 749 } 750 751 exit: 752 if (latency_monitor_driver_data.monitors_in_use_count) { 753 latency_monitor_driver_data.monitors_in_use_count--; 754 if (latency_monitor_driver_data.monitors_in_use_count == 0) { 755 if (latency_monitor_driver_data.sbusdma_run_lock) { 756 /* Wait for other thread to release the semaphore before deleting it */ 757 sal_sem_take(latency_monitor_driver_data.sbusdma_run_lock, sal_sem_FOREVER); 758 sal_sem_destroy(latency_monitor_driver_data.sbusdma_run_lock); 759 latency_monitor_driver_data.sbusdma_run_lock = NULL; 760 } 761 latency_monitor_driver_data.init_done = FALSE; 762 if (cleanup_buf) { 763 soc_cm_sfree(unit, cleanup_buf); 764 } 765 /* Since none of the monitors are in use, clear the hist_1us_enable bit */ 766 rv = soc_reg_get(unit, AUX_ARB_CONTROLr, REG_PORT_ANY, 0, &rval); 767 if (rv == BCM_E_NONE) { 768 COMPILER_64_SET(val, 0, 0); 769 soc_reg64_field_set(unit, AUX_ARB_CONTROLr, &rval, HIST_1US_ENABLEf, val); 770 /* coverity[check_return : FALSE] */ 771 soc_reg_set(unit, AUX_ARB_CONTROLr, REG_PORT_ANY, 0, rval); 772 } 773 } 774 } 775 776 latency_monitor_driver_data.run[monitor_id] = FALSE; 777 sal_free(access_type); 778 779 latency_monitor_mem[unit][monitor_id].sbusdma_read_thread_pid = 0; 780 sal_thread_exit(0); 781 } 782 783 int 784 latency_monitor_read(int unit, int monitor_id) 785 { 786 sal_thread_t pid; 787 788 /* sbus dma read */ 789 latency_monitor_driver_data.mem_done[monitor_id] = FALSE; 790 791 if (latency_monitor_mem[unit][monitor_id].sbusdma_read_thread_pid) { 792 return BCM_E_NONE; 793 } 794 795 pid = sal_thread_create("bcm_latency_monitor_sbusdma_read", 796 SAL_THREAD_STKSZ, 797 200, 798 sbusdma_read, 799 INT_TO_PTR(monitor_id << 8 | unit)); 800 801 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 802 (BSL_META_U(unit, "\npid_sbusdma[%0d] = %p"), monitor_id, pid)); 803 804 if (pid == SAL_THREAD_ERROR) { 805 LOG_ERROR(BSL_LS_BCM_LATENCY_MONITOR, 806 (BSL_META_U(unit, "Failed to create sbusdma_read thread for monitor ID:%d \n"), 807 monitor_id)); 808 return BCM_E_FAIL; 809 } 810 811 pid = sal_thread_create("bcm_latency_monitor_counter_accrue", 812 SAL_THREAD_STKSZ, 813 200, 814 counter_accrue_thread, 815 INT_TO_PTR(monitor_id << 8 | unit)); 816 817 if (pid == SAL_THREAD_ERROR) { 818 LOG_ERROR(BSL_LS_BCM_LATENCY_MONITOR, 819 (BSL_META_U(unit, "Failed to create counter_accrue_thread, for monitor ID:%d \n"), 820 monitor_id)); 821 return BCM_E_FAIL; 822 } else { 823 LOG_DEBUG(BSL_LS_BCM_LATENCY_MONITOR, 824 (BSL_META_U(unit, "created counter_accrue_thread for monitor%d \n"), monitor_id)); 825 } 826 827 return BCM_E_NONE; 828 } 829 830 int 831 latency_monitor_init(int unit, int monitor_id) 832 { 833 int index_min, index_max; 834 int frag, delta; 835 836 if (!latency_monitor_mem[unit][monitor_id].init_done) { 837 latency_monitor_driver_data.monitors_in_use_count++; 838 latency_monitor_mem[unit][monitor_id].frag_count = LATENCY_MONITOR_DEFAULT_FRAG_COUNT; 839 latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem = 840 sal_sem_create("DMA Handler Count Semaphore", sal_sem_COUNTING, 0); 841 latency_monitor_mem[unit][monitor_id].dma_handle_queue_lock = 842 sal_sem_create("DMA Handler Queue Lock", sal_sem_BINARY, 1); 843 _sbusdma_desc_handle_list_init(&latency_monitor_mem[unit][monitor_id].handle_list); 844 latency_monitor_mem[unit][monitor_id].latency_monitor_thread_trigger = 845 sal_sem_create("Latency Monitor Thread Sempahore", sal_sem_BINARY, 0); 846 latency_monitor_mem[unit][monitor_id].init_done = TRUE; 847 latency_monitor_driver_data.run[monitor_id] = FALSE; 848 latency_monitor_driver_data.mem_done[monitor_id] = TRUE; 849 } 850 851 if (latency_monitor_driver_data.sbusdma_run_lock == NULL) { 852 latency_monitor_driver_data.sbusdma_run_lock = 853 sal_sem_create("SBUS DMA RUN Lock", sal_sem_BINARY, 1); 854 } 855 856 latency_monitor_mem[unit][monitor_id].copyno = SOC_MEM_BLOCK_ANY(unit, latency_monitor_mem[unit][monitor_id].mem); 857 if (!SOC_MEM_BLOCK_VALID(unit, latency_monitor_mem[unit][monitor_id].mem, latency_monitor_mem[unit][monitor_id].copyno)) { 858 LOG_ERROR(BSL_LS_BCM_LATENCY_MONITOR, 859 (BSL_META_U(unit, 860 "Invalid copyno %d specified in %s\n"), 861 latency_monitor_mem[unit][monitor_id].copyno, 862 SOC_MEM_NAME(unit, latency_monitor_mem[unit][monitor_id].mem))); 863 return BCM_E_FAIL; 864 } 865 866 index_min = soc_mem_index_min(unit, latency_monitor_mem[unit][monitor_id].mem); 867 index_max = soc_mem_index_max(unit, latency_monitor_mem[unit][monitor_id].mem); 868 869 if (latency_monitor_mem[unit][monitor_id].index_min <= index_min) { 870 latency_monitor_mem[unit][monitor_id].index_min = index_min; 871 } 872 if (latency_monitor_mem[unit][monitor_id].index_min > index_max) { 873 latency_monitor_mem[unit][monitor_id].index_min = index_min; 874 } 875 876 if (latency_monitor_mem[unit][monitor_id].count <= 0) { 877 /* 878 * do not use soc_mem_index_count, index_max may have been, 879 * index_max may have been modified above 880 */ 881 latency_monitor_mem[unit][monitor_id].count = index_max - index_min + 1; 882 } 883 884 if (latency_monitor_mem[unit][monitor_id].index_min + latency_monitor_mem[unit][monitor_id].count - 1 > index_max) { 885 latency_monitor_mem[unit][monitor_id].count = index_max - latency_monitor_mem[unit][monitor_id].index_min + 1; 886 } 887 888 latency_monitor_mem[unit][monitor_id].index_max = latency_monitor_mem[unit][monitor_id].index_min + 889 latency_monitor_mem[unit][monitor_id].count - 1; 890 891 if (latency_monitor_mem[unit][monitor_id].frag_count <= latency_monitor_driver_data.num_mem) { 892 latency_monitor_mem[unit][monitor_id].frag_count = latency_monitor_driver_data.num_mem; 893 latency_monitor_mem[unit][monitor_id].frag_index_min[0] = latency_monitor_mem[unit][monitor_id].index_min; 894 latency_monitor_mem[unit][monitor_id].frag_index_max[0] = latency_monitor_mem[unit][monitor_id].index_max; 895 } else { 896 if (latency_monitor_mem[unit][monitor_id].frag_count > latency_monitor_mem[unit][monitor_id].count) { 897 latency_monitor_mem[unit][monitor_id].frag_count = latency_monitor_mem[unit][monitor_id].count; 898 } 899 900 delta = (latency_monitor_mem[unit][monitor_id].index_max - latency_monitor_mem[unit][monitor_id].index_min + 1) / 901 latency_monitor_mem[unit][monitor_id].frag_count; 902 for (frag = 0; frag < latency_monitor_mem[unit][monitor_id].frag_count; frag++) { 903 latency_monitor_mem[unit][monitor_id].frag_index_min[frag] = latency_monitor_mem[unit][monitor_id].index_min + 904 frag * delta; 905 latency_monitor_mem[unit][monitor_id].frag_index_max[frag] = latency_monitor_mem[unit][monitor_id].index_min + 906 (frag + 1) * delta - 1; 907 } 908 latency_monitor_mem[unit][monitor_id].frag_index_max[latency_monitor_mem[unit][monitor_id].frag_count - 1] = 909 latency_monitor_mem[unit][monitor_id].index_max; 910 } 911 912 return BCM_E_NONE; 913 } 914 915 916 /* Set monitor with a given configuration. */ 917 int 918 bcm_tomahawk3_latency_monitor_config_set( 919 int unit, 920 uint8 monitor_id, 921 bcm_latency_monitor_config_t *config) 922 { 923 #ifdef BCM_TOMAHAWK3_SUPPORT 924 pbmp_t src_pbm; 925 pbmp_t dest_pbm; 926 soc_field_t field_ids[5]; 927 uint32 field_values[5]; 928 int port_idx; 929 bcm_stat_object_t stat_obj; 930 uint32 stat_counter_id = 0; 931 uint32 num_entries; 932 bcm_stat_group_mode_t group; 933 bcm_stat_object_t object; 934 uint32 mode; 935 uint32 pool_number; 936 uint32 base_idx; 937 soc_reg_t flex_bank_sel_reg; 938 soc_field_t pbmp_field; 939 uint32 sw_buf_size; 940 uint16 time_step_incr; 941 uint32 time_step_set; 942 soc_info_t *si; 943 int rv = BCM_E_NONE; 944 uint8 count_mode; 945 946 947 if (monitor_id > MONITOR_ID_3) { 948 return BCM_E_PARAM; 949 } 950 951 if (!config) { 952 return BCM_E_PARAM; 953 } 954 955 if ((!wb_post_init) && 956 (latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_RUNNING)) { 957 if (config->mode == bcmLatencyMonitorTimeSeriesMode) { 958 latency_monitor_mem[unit][monitor_id].cb = config->cb; 959 } 960 return BCM_E_BUSY; 961 } 962 963 if ((config->mode != bcmLatencyMonitorAccrueMode) && 964 (config->mode != bcmLatencyMonitorTimeSeriesMode)) { 965 return BCM_E_PARAM; 966 } 967 968 if ((config->count_mode < bcmLatencyMonitorCutThrough) || 969 (config->count_mode > bcmLatencyMonitorCountAll)) { 970 return _SHR_E_PARAM; 971 } 972 973 if ((latency_monitor_mem[unit][monitor_id].status != LATENCY_MONITOR_STATE_CLEANUP) && 974 (config->time_step < LATENCY_MONITOR_MIN_TIME_STEP)) { 975 return BCM_E_PARAM; 976 } 977 978 latency_monitor_mem[unit][monitor_id].monitor_mode = config->mode; 979 latency_monitor_mem[unit][monitor_id].sw_buf_size = 0; 980 if (config->mode == bcmLatencyMonitorTimeSeriesMode) { 981 if (config->histogram_set_count < TIME_STEP_SET_COUNT) { 982 return BCM_E_PARAM; 983 } 984 985 if (latency_monitor_mem[unit][monitor_id].sw_buf_addr) { 986 sal_free(latency_monitor_mem[unit][monitor_id].sw_buf_addr); 987 } 988 989 sw_buf_size = (config->histogram_set_count) * COUNTERS_PER_STEP_SET * LATENCY_MONITOR_SW_BUF_WIDTH; 990 latency_monitor_mem[unit][monitor_id].sw_buf_addr = 991 sal_alloc(sw_buf_size, "sw ring buffer"); 992 if (latency_monitor_mem[unit][monitor_id].sw_buf_addr == NULL) { 993 return BCM_E_MEMORY; 994 } 995 996 latency_monitor_mem[unit][monitor_id].cb = config->cb; 997 /* Save the sw ring buffer size in terms of 64 bit word count */ 998 latency_monitor_mem[unit][monitor_id].sw_buf_size = config->histogram_set_count * COUNTERS_PER_STEP_SET; 999 } 1000 1001 if ((latency_monitor_mem[unit][monitor_id].status != LATENCY_MONITOR_STATE_CLEANUP) && 1002 (!latency_monitor_driver_data.init_done)) { 1003 latency_monitor_driver_data_init(unit); 1004 } 1005 1006 SOC_LATENCY_MONITOR_INFO(unit, monitor_id).time_step = config->time_step; 1007 SOC_LATENCY_MONITOR_INFO(unit, monitor_id).flex_pool_number = -1; 1008 BCM_PBMP_ASSIGN(SOC_LATENCY_MONITOR_INFO(unit, monitor_id).src_pbmp, config->src_pbmp); 1009 BCM_PBMP_ASSIGN(SOC_LATENCY_MONITOR_INFO(unit, monitor_id).dest_pbmp, config->dest_pbmp); 1010 1011 /* Convert from zero indexed enum value to one indexed value. Register field value '0' is reserved in HW */ 1012 count_mode = config->count_mode + 1; 1013 1014 switch (monitor_id) { 1015 case MONITOR_ID_0: 1016 field_ids[0] = TIME_SERIES_STEPf; 1017 field_values[0] = config->time_step; 1018 BCM_IF_ERROR_RETURN 1019 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_0_FLEX_BANK_SEL_0r, REG_PORT_ANY, 1, 1020 field_ids, field_values)); 1021 1022 field_ids[0] = MON_CUT_THROUGHf; 1023 field_values[0] = count_mode; 1024 BCM_IF_ERROR_RETURN 1025 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_0_CONFIGr, REG_PORT_ANY, 1, 1026 field_ids, field_values)); 1027 pbmp_field = MONITOR_0f; 1028 stat_obj = bcmIntStatObjectEgrLatencyMonitor0; 1029 flex_bank_sel_reg = EGR_HISTO_MON_0_FLEX_BANK_SEL_1r; 1030 break; 1031 case MONITOR_ID_1: 1032 field_ids[0] = TIME_SERIES_STEPf; 1033 field_values[0] = config->time_step; 1034 BCM_IF_ERROR_RETURN 1035 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_1_FLEX_BANK_SEL_0r, REG_PORT_ANY, 1, 1036 field_ids, field_values)); 1037 1038 field_ids[0] = MON_CUT_THROUGHf; 1039 field_values[0] = count_mode; 1040 BCM_IF_ERROR_RETURN 1041 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_1_CONFIGr, REG_PORT_ANY, 1, 1042 field_ids, field_values)); 1043 pbmp_field = MONITOR_1f; 1044 stat_obj = bcmIntStatObjectEgrLatencyMonitor1; 1045 flex_bank_sel_reg = EGR_HISTO_MON_1_FLEX_BANK_SEL_1r; 1046 break; 1047 case MONITOR_ID_2: 1048 field_ids[0] = TIME_SERIES_STEPf; 1049 field_values[0] = config->time_step; 1050 BCM_IF_ERROR_RETURN 1051 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_2_FLEX_BANK_SEL_0r, REG_PORT_ANY, 1, 1052 field_ids, field_values)); 1053 1054 field_ids[0] = MON_CUT_THROUGHf; 1055 field_values[0] = count_mode; 1056 BCM_IF_ERROR_RETURN 1057 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_2_CONFIGr, REG_PORT_ANY, 1, 1058 field_ids, field_values)); 1059 pbmp_field = MONITOR_2f; 1060 stat_obj = bcmIntStatObjectEgrLatencyMonitor2; 1061 flex_bank_sel_reg = EGR_HISTO_MON_2_FLEX_BANK_SEL_1r; 1062 break; 1063 case MONITOR_ID_3: 1064 field_ids[0] = TIME_SERIES_STEPf; 1065 field_values[0] = config->time_step; 1066 BCM_IF_ERROR_RETURN 1067 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_3_FLEX_BANK_SEL_0r, REG_PORT_ANY, 1, 1068 field_ids, field_values)); 1069 1070 field_ids[0] = MON_CUT_THROUGHf; 1071 field_values[0] = count_mode; 1072 BCM_IF_ERROR_RETURN 1073 (soc_reg_fields32_modify(unit, EGR_HISTO_MON_3_CONFIGr, REG_PORT_ANY, 1, 1074 field_ids, field_values)); 1075 pbmp_field = MONITOR_3f; 1076 stat_obj = bcmIntStatObjectEgrLatencyMonitor3; 1077 flex_bank_sel_reg = EGR_HISTO_MON_3_FLEX_BANK_SEL_1r; 1078 break; 1079 default: 1080 return BCM_E_PARAM; 1081 } 1082 1083 src_pbm = PBMP_PORT_ALL(unit); 1084 dest_pbm = PBMP_PORT_ALL(unit); 1085 if (latency_monitor_mem[unit][monitor_id].status != LATENCY_MONITOR_STATE_CLEANUP) { 1086 field_values[0] = 1; 1087 BCM_PBMP_AND(src_pbm, config->src_pbmp); 1088 BCM_PBMP_AND(dest_pbm, config->dest_pbmp); 1089 } else { 1090 field_values[0] = 0; 1091 } 1092 1093 field_ids[0] = pbmp_field; 1094 BCM_PBMP_ITER(src_pbm, port_idx) { 1095 BCM_IF_ERROR_RETURN 1096 (soc_reg_fields32_modify(unit, EGR_HISTO_SRC_PORT_MAPr, port_idx, 1, 1097 field_ids, field_values)); 1098 } 1099 1100 latency_monitor_mem[unit][monitor_id].dest_pbmp_pipe_map = 0; 1101 si = &SOC_INFO(unit); 1102 field_ids[0] = pbmp_field; 1103 BCM_PBMP_ITER(dest_pbm, port_idx) { 1104 latency_monitor_mem[unit][monitor_id].dest_pbmp_pipe_map |= 1 << si->port_pipe[port_idx]; 1105 BCM_IF_ERROR_RETURN 1106 (soc_reg_fields32_modify(unit, EGR_HISTO_DST_PORT_MAPr, port_idx, 1, 1107 field_ids, field_values)); 1108 } 1109 1110 latency_monitor_mem[unit][monitor_id].time_step = config->time_step; 1111 latency_monitor_mem[unit][monitor_id].wrap_around_time = 1112 config->time_step * TIME_STEP_SET_COUNT; 1113 1114 if (latency_monitor_mem[unit][monitor_id].status != LATENCY_MONITOR_STATE_CLEANUP) { 1115 if (latency_monitor_mem[unit][monitor_id].stat_counter_id != 0) { 1116 rv = _bcm_esw_stat_group_destroy(unit, 1117 latency_monitor_mem[unit][monitor_id].stat_counter_id); 1118 1119 /* Return error if the stat group exists and on failure to delete it */ 1120 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 1121 BCM_IF_ERROR_RETURN(rv); 1122 } 1123 } 1124 1125 BCM_IF_ERROR_RETURN(_bcm_esw_stat_group_create(unit, stat_obj, 1126 bcmIntStatGroupModeLatencyMonitor, 1127 &stat_counter_id, &num_entries)); 1128 1129 _bcm_esw_stat_get_counter_id_info(unit, stat_counter_id, &group, &object, 1130 &mode, &pool_number, &base_idx); 1131 1132 time_step_incr = TIME_STEP_COUNTER_INCR; 1133 time_step_set = (TIME_STEP_SET_COUNT - 1); 1134 } else { 1135 latency_monitor_mem[unit][monitor_id].cb = NULL; 1136 latency_monitor_mem[unit][monitor_id].sw_buf_size = 0; 1137 pool_number = 0; 1138 base_idx = 0; 1139 time_step_incr = 0; 1140 time_step_set = 0; 1141 } 1142 1143 /* If the base index is zero, skip the first two reserved entries and select the next power of 2 entry */ 1144 if (base_idx == 0) 1145 latency_monitor_mem[unit][monitor_id].index_min = base_idx + 4; 1146 else 1147 latency_monitor_mem[unit][monitor_id].index_min = base_idx; 1148 1149 field_ids[0] = FLEX_CTR_POOL_NUMBERf; 1150 field_values[0] = pool_number; 1151 field_ids[1] = HISTOGRAM_OFFSETf; 1152 field_values[1] = latency_monitor_mem[unit][monitor_id].index_min; 1153 field_ids[2] = TIME_STEP_COUNTER_INCRf; 1154 field_values[2] = time_step_incr; 1155 field_ids[3] = FLEX_CTR_OFFSET_MODEf; 1156 field_values[3] = 0; 1157 field_ids[4] = MAX_TIME_STEP_SETSf; 1158 field_values[4] = time_step_set; 1159 1160 BCM_IF_ERROR_RETURN 1161 (soc_reg_fields32_modify(unit, flex_bank_sel_reg, REG_PORT_ANY, 5, 1162 field_ids, field_values)); 1163 1164 latency_monitor_mem[unit][monitor_id].stat_counter_id = stat_counter_id; 1165 latency_monitor_mem[unit][monitor_id].status = LATENCY_MONITOR_STATE_IDLE; 1166 1167 latency_monitor_mem[unit][monitor_id].count = COUNTERS_PER_STEP_SET * TIME_STEP_SET_COUNT; 1168 latency_monitor_mem[unit][monitor_id].index_max = latency_monitor_mem[unit][monitor_id].index_min + latency_monitor_mem[unit][monitor_id].count; 1169 switch (pool_number) { 1170 case 0: 1171 latency_monitor_mem[unit][monitor_id].mem = EGR_FLEX_CTR_COUNTER_TABLE_0_PIPE0m; 1172 break; 1173 case 1: 1174 latency_monitor_mem[unit][monitor_id].mem = EGR_FLEX_CTR_COUNTER_TABLE_1_PIPE0m; 1175 break; 1176 case 2: 1177 latency_monitor_mem[unit][monitor_id].mem = EGR_FLEX_CTR_COUNTER_TABLE_2_PIPE0m; 1178 break; 1179 case 3: 1180 latency_monitor_mem[unit][monitor_id].mem = EGR_FLEX_CTR_COUNTER_TABLE_3_PIPE0m; 1181 break; 1182 default: 1183 return BCM_E_BADID; 1184 } 1185 1186 latency_monitor_mem[unit][monitor_id].entwords = soc_mem_entry_words(unit, latency_monitor_mem[unit][monitor_id].mem); 1187 latency_monitor_mem[unit][monitor_id].bufwords = latency_monitor_mem[unit][monitor_id].entwords * latency_monitor_mem[unit][monitor_id].count; 1188 1189 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1190 1191 return BCM_E_NONE; 1192 } 1193 1194 /* Get configuration for a given monitor. */ 1195 int 1196 bcm_tomahawk3_latency_monitor_config_get( 1197 int unit, 1198 uint8 monitor_id, 1199 bcm_latency_monitor_config_t *config) 1200 { 1201 #ifdef BCM_TOMAHAWK3_SUPPORT 1202 uint32 reg_value; 1203 int rv, port_idx; 1204 soc_field_t pbmp_field; 1205 soc_reg_t mon_count_mode_reg; 1206 1207 if (config == NULL) 1208 return BCM_E_PARAM; 1209 1210 switch (monitor_id) { 1211 case MONITOR_ID_0: 1212 rv = soc_reg32_get(unit, EGR_HISTO_MON_0_FLEX_BANK_SEL_0r, REG_PORT_ANY,0, 1213 ®_value); 1214 SOC_IF_ERROR_RETURN(rv); 1215 config->time_step = soc_reg_field_get(unit,EGR_HISTO_MON_0_FLEX_BANK_SEL_0r,reg_value, 1216 TIME_SERIES_STEPf); 1217 pbmp_field = MONITOR_0f; 1218 mon_count_mode_reg = EGR_HISTO_MON_0_CONFIGr; 1219 break; 1220 case MONITOR_ID_1: 1221 rv = soc_reg32_get(unit, EGR_HISTO_MON_1_FLEX_BANK_SEL_0r, REG_PORT_ANY,0, 1222 ®_value); 1223 SOC_IF_ERROR_RETURN(rv); 1224 config->time_step = soc_reg_field_get(unit,EGR_HISTO_MON_1_FLEX_BANK_SEL_0r,reg_value, 1225 TIME_SERIES_STEPf); 1226 pbmp_field = MONITOR_1f; 1227 mon_count_mode_reg = EGR_HISTO_MON_1_CONFIGr; 1228 break; 1229 case MONITOR_ID_2: 1230 rv = soc_reg32_get(unit, EGR_HISTO_MON_2_FLEX_BANK_SEL_0r, REG_PORT_ANY,0, 1231 ®_value); 1232 SOC_IF_ERROR_RETURN(rv); 1233 config->time_step = soc_reg_field_get(unit,EGR_HISTO_MON_2_FLEX_BANK_SEL_0r,reg_value, 1234 TIME_SERIES_STEPf); 1235 pbmp_field = MONITOR_2f; 1236 mon_count_mode_reg = EGR_HISTO_MON_2_CONFIGr; 1237 break; 1238 case MONITOR_ID_3: 1239 rv = soc_reg32_get(unit, EGR_HISTO_MON_3_FLEX_BANK_SEL_0r, REG_PORT_ANY,0, 1240 ®_value); 1241 SOC_IF_ERROR_RETURN(rv); 1242 config->time_step = soc_reg_field_get(unit,EGR_HISTO_MON_3_FLEX_BANK_SEL_0r,reg_value, 1243 TIME_SERIES_STEPf); 1244 pbmp_field = MONITOR_3f; 1245 mon_count_mode_reg = EGR_HISTO_MON_3_CONFIGr; 1246 break; 1247 default: 1248 return BCM_E_PARAM; 1249 } 1250 1251 config->mode = latency_monitor_mem[unit][monitor_id].monitor_mode; 1252 if (config->mode == bcmLatencyMonitorTimeSeriesMode) { 1253 config->histogram_set_count = (latency_monitor_mem[unit][monitor_id].sw_buf_size)/COUNTERS_PER_STEP_SET; 1254 config->cb = latency_monitor_mem[unit][monitor_id].cb; 1255 } 1256 1257 rv = soc_reg32_get(unit, mon_count_mode_reg, REG_PORT_ANY, 0, ®_value); 1258 SOC_IF_ERROR_RETURN(rv); 1259 config->count_mode = soc_reg_field_get(unit, EGR_HISTO_MON_0_CONFIGr, reg_value, 1260 MON_CUT_THROUGHf); 1261 1262 /* Convert from '1' indexed register field value to '0' indexed enum type */ 1263 config->count_mode -= 1; 1264 1265 BCM_PBMP_CLEAR(config->src_pbmp); 1266 BCM_PBMP_ITER(PBMP_PORT_ALL(unit), port_idx) { 1267 rv = soc_reg32_get(unit, EGR_HISTO_SRC_PORT_MAPr, port_idx, 0, 1268 ®_value); 1269 SOC_IF_ERROR_RETURN(rv); 1270 if (soc_reg_field_get(unit,EGR_HISTO_SRC_PORT_MAPr,reg_value, 1271 pbmp_field)) 1272 BCM_PBMP_PORT_ADD(config->src_pbmp, port_idx); 1273 } 1274 1275 BCM_PBMP_CLEAR(config->dest_pbmp); 1276 BCM_PBMP_ITER(PBMP_PORT_ALL(unit), port_idx) { 1277 rv = soc_reg32_get(unit, EGR_HISTO_DST_PORT_MAPr, port_idx, 0, 1278 ®_value); 1279 SOC_IF_ERROR_RETURN(rv); 1280 if (soc_reg_field_get(unit,EGR_HISTO_DST_PORT_MAPr,reg_value, 1281 pbmp_field)) 1282 BCM_PBMP_PORT_ADD(config->dest_pbmp, port_idx); 1283 } 1284 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1285 return BCM_E_NONE; 1286 } 1287 1288 /* 1289 * Configures the LATENCY_LIMIT device table, which has 32 entries max 1290 * and each entry is specified in terms of 64 nSec quanta. 1291 */ 1292 int 1293 bcm_tomahawk3_latency_monitor_latency_limit_table_set( 1294 int unit, 1295 uint8 table_size, 1296 uint32 *latency_limit_table) 1297 { 1298 #ifdef BCM_TOMAHAWK3_SUPPORT 1299 int i; 1300 uint32 value; 1301 1302 if (table_size > LATENCY_LIMIT_TABLE_SIZE) 1303 return BCM_E_PARAM; 1304 1305 if (latency_limit_table == NULL) 1306 return BCM_E_PARAM; 1307 1308 for (i=0; i<table_size; i++) { 1309 if (latency_limit_table[i] < LATENCY_LIMIT_QUANTA) 1310 value = 1; /* Min is 64 nS */ 1311 else 1312 value = latency_limit_table[i]/LATENCY_LIMIT_QUANTA; 1313 1314 BCM_IF_ERROR_RETURN 1315 (soc_mem_field32_modify(unit, EGR_HISTO_LATENCY_LIMITm, i, LATENCY_LIMITf, 1316 value)); 1317 } 1318 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1319 return BCM_E_NONE; 1320 } 1321 1322 /* 1323 * Output is the table size and configured values of LATENCY_LIMIT device 1324 * table. 1325 */ 1326 1327 int 1328 bcm_tomahawk3_latency_monitor_latency_limit_table_get( 1329 int unit, 1330 uint8 table_size, 1331 uint32 *latency_limit_table) 1332 { 1333 #ifdef BCM_TOMAHAWK3_SUPPORT 1334 int i, rv; 1335 uint32 value; 1336 1337 if (table_size > LATENCY_LIMIT_TABLE_SIZE) 1338 table_size = LATENCY_LIMIT_TABLE_SIZE; 1339 1340 if (latency_limit_table == NULL) 1341 return BCM_E_PARAM; 1342 1343 for (i=0; i<table_size; i++) { 1344 rv = soc_mem_read(unit, EGR_HISTO_LATENCY_LIMITm, MEM_BLOCK_ANY, 1345 i, &value); 1346 if (SOC_FAILURE(rv)) { 1347 return (rv); 1348 } 1349 1350 latency_limit_table[i] = soc_mem_field32_get(unit, 1351 EGR_HISTO_LATENCY_LIMITm, 1352 &value, LATENCY_LIMITf); 1353 latency_limit_table[i] *= LATENCY_LIMIT_QUANTA; 1354 } 1355 #endif 1356 return BCM_E_NONE; 1357 } 1358 1359 1360 /* 1361 * Configure the bucket size and upper latency limit of each bucket, for a 1362 * given cos queue and monitor id. 1363 */ 1364 int 1365 bcm_tomahawk3_latency_monitor_cosq_config_set( 1366 int unit, 1367 uint8 monitor_id, 1368 uint8 cosq, 1369 bcm_latency_monitor_cosq_info_t cosq_info) 1370 { 1371 #ifdef BCM_TOMAHAWK3_SUPPORT 1372 int i, j, index; 1373 soc_mem_t mem; 1374 uint8 cosq_first; 1375 uint8 cosq_last; 1376 1377 if ((cosq >= LATENCY_MONITOR_QUEUE_COUNT) && ((int8)cosq != -1)) 1378 return BCM_E_PARAM; 1379 1380 if (cosq_info.bucket_count > LATENCY_HISTOGRAM_BUCKET_COUNT) 1381 return BCM_E_PARAM; 1382 1383 switch (monitor_id) { 1384 case MONITOR_ID_0: 1385 mem = EGR_HISTO_MON_0_Q_LATENCY_LIMIT_SELm; 1386 break; 1387 case MONITOR_ID_1: 1388 mem = EGR_HISTO_MON_1_Q_LATENCY_LIMIT_SELm; 1389 break; 1390 case MONITOR_ID_2: 1391 mem = EGR_HISTO_MON_2_Q_LATENCY_LIMIT_SELm; 1392 break; 1393 case MONITOR_ID_3: 1394 mem = EGR_HISTO_MON_3_Q_LATENCY_LIMIT_SELm; 1395 break; 1396 default: 1397 return BCM_E_PARAM; 1398 } 1399 1400 cosq_first = cosq; 1401 cosq_last = cosq; 1402 if ((int8)cosq == -1) { 1403 cosq_first = 0; 1404 cosq_last = (LATENCY_MONITOR_QUEUE_COUNT - 1); 1405 } 1406 1407 for (i=cosq_first; i<=cosq_last; i++) { 1408 latency_monitor_mem[unit][monitor_id].cosq_info[i].bucket_count = cosq_info.bucket_count; 1409 for (j=0; j<(cosq_info.bucket_count - 1); j++) { 1410 if (cosq_info.latency_index_array[j] >= LATENCY_LIMIT_TABLE_SIZE) 1411 return BCM_E_PARAM; 1412 1413 index = (i * (LATENCY_HISTOGRAM_BUCKET_COUNT - 1)) + j; 1414 BCM_IF_ERROR_RETURN 1415 (soc_mem_field32_modify(unit, mem, index, Q_LATENCY_LIMIT_SELf, 1416 cosq_info.latency_index_array[j])); 1417 1418 } 1419 } 1420 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1421 1422 return BCM_E_NONE; 1423 } 1424 1425 /* 1426 * Output is the bucket size and upper latency limit of each bucket for a 1427 * given cos queue and monitor. 1428 */ 1429 int 1430 bcm_tomahawk3_latency_monitor_cosq_config_get( 1431 int unit, 1432 uint8 monitor_id, 1433 uint8 cosq, 1434 bcm_latency_monitor_cosq_info_t *cosq_info) 1435 { 1436 #ifdef BCM_TOMAHAWK3_SUPPORT 1437 int i, index, rv; 1438 uint32 value; 1439 soc_mem_t mem; 1440 1441 if (cosq_info == NULL) 1442 return BCM_E_PARAM; 1443 1444 if (cosq >= LATENCY_MONITOR_QUEUE_COUNT) 1445 return BCM_E_PARAM; 1446 1447 switch (monitor_id) { 1448 case MONITOR_ID_0: 1449 mem = EGR_HISTO_MON_0_Q_LATENCY_LIMIT_SELm; 1450 break; 1451 case MONITOR_ID_1: 1452 mem = EGR_HISTO_MON_1_Q_LATENCY_LIMIT_SELm; 1453 break; 1454 case MONITOR_ID_2: 1455 mem = EGR_HISTO_MON_2_Q_LATENCY_LIMIT_SELm; 1456 break; 1457 case MONITOR_ID_3: 1458 mem = EGR_HISTO_MON_3_Q_LATENCY_LIMIT_SELm; 1459 break; 1460 default: 1461 return BCM_E_PARAM; 1462 } 1463 1464 cosq_info->bucket_count = latency_monitor_mem[unit][monitor_id].cosq_info[cosq].bucket_count; 1465 1466 for (i=0; i<(cosq_info->bucket_count - 1); i++) { 1467 index = (cosq * (LATENCY_HISTOGRAM_BUCKET_COUNT - 1)) + i; 1468 1469 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &value); 1470 if (SOC_FAILURE(rv)) { 1471 return (rv); 1472 } 1473 1474 cosq_info->latency_index_array[i] = soc_mem_field32_get(unit, 1475 mem, &value, Q_LATENCY_LIMIT_SELf); 1476 } 1477 1478 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1479 1480 return BCM_E_NONE; 1481 } 1482 1483 #ifdef BCM_TOMAHAWK3_SUPPORT 1484 static int 1485 _clear_debug_registers(int unit, uint8 monitor_id) 1486 { 1487 if (SOC_IS_TOMAHAWK3(unit)) { 1488 switch (monitor_id) { 1489 case MONITOR_ID_0: 1490 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_0_LAST_COUNTER_INDEXr, REG_PORT_ANY, 0, 0)); 1491 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_0_HISTOGRAM_SETr, REG_PORT_ANY, 0, 0)); 1492 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_0_FLEX_COUNTER_WRAP_COUNTERr, REG_PORT_ANY, 0, 0)); 1493 break; 1494 case MONITOR_ID_1: 1495 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_1_LAST_COUNTER_INDEXr, REG_PORT_ANY, 0, 0)); 1496 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_1_HISTOGRAM_SETr, REG_PORT_ANY, 0, 0)); 1497 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_1_FLEX_COUNTER_WRAP_COUNTERr, REG_PORT_ANY, 0, 0)); 1498 break; 1499 case MONITOR_ID_2: 1500 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_2_LAST_COUNTER_INDEXr, REG_PORT_ANY, 0, 0)); 1501 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_2_HISTOGRAM_SETr, REG_PORT_ANY, 0, 0)); 1502 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_2_FLEX_COUNTER_WRAP_COUNTERr, REG_PORT_ANY, 0, 0)); 1503 break; 1504 case MONITOR_ID_3: 1505 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_3_LAST_COUNTER_INDEXr, REG_PORT_ANY, 0, 0)); 1506 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_3_HISTOGRAM_SETr, REG_PORT_ANY, 0, 0)); 1507 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EGR_HISTO_MON_3_FLEX_COUNTER_WRAP_COUNTERr, REG_PORT_ANY, 0, 0)); 1508 break; 1509 default: 1510 return BCM_E_PARAM; 1511 } 1512 } 1513 1514 return BCM_E_NONE; 1515 } 1516 #endif 1517 1518 /* Enable or Disable a given monitor */ 1519 int 1520 bcm_tomahawk3_latency_monitor_enable( 1521 int unit, 1522 uint8 monitor_id, 1523 uint8 enable) 1524 { 1525 #ifdef BCM_TOMAHAWK3_SUPPORT 1526 soc_field_t field_ids[1]; 1527 uint32 field_values[1]; 1528 soc_reg_t mon_config_reg; 1529 int rv = BCM_E_NONE; 1530 uint32 hist_1us_enable; 1531 uint32 rval; 1532 1533 if (monitor_id > MONITOR_ID_3) { 1534 return BCM_E_PARAM; 1535 } 1536 1537 if (!wb_post_init) { 1538 /* If monitor is in cleanup/error state, return failure. */ 1539 if ((latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_CLEANUP) || 1540 (latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_ERROR)) { 1541 return BCM_E_FAIL; 1542 } 1543 1544 /* If monitor is already enabled and running. */ 1545 if ((enable) &&(latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_RUNNING)) { 1546 return BCM_E_NONE; 1547 } 1548 1549 /* If monitor is already disabled and idle. */ 1550 if ((!enable) && (latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_IDLE)) { 1551 return BCM_E_NONE; 1552 } 1553 } 1554 1555 if (enable) 1556 latency_monitor_init(unit, monitor_id); 1557 1558 switch (monitor_id) { 1559 case MONITOR_ID_0: 1560 mon_config_reg = EGR_HISTO_MON_0_CONFIGr; 1561 break; 1562 case MONITOR_ID_1: 1563 mon_config_reg = EGR_HISTO_MON_1_CONFIGr; 1564 break; 1565 case MONITOR_ID_2: 1566 mon_config_reg = EGR_HISTO_MON_2_CONFIGr; 1567 break; 1568 case MONITOR_ID_3: 1569 mon_config_reg = EGR_HISTO_MON_3_CONFIGr; 1570 break; 1571 default: 1572 return BCM_E_PARAM; 1573 } 1574 1575 field_ids[0] = MONITOR_ENf; 1576 field_values[0] = enable; 1577 BCM_IF_ERROR_RETURN 1578 (soc_reg_fields32_modify(unit, mon_config_reg, REG_PORT_ANY, 1, 1579 field_ids, field_values)); 1580 1581 if (enable) { 1582 sal_memset(latency_monitor_mem[unit][monitor_id].histogram_packet64_counter, 0, 1583 sizeof(latency_monitor_mem[unit][monitor_id].histogram_packet64_counter)); 1584 sal_memset(latency_monitor_mem[unit][monitor_id].histogram_byte64_counter, 0, 1585 sizeof(latency_monitor_mem[unit][monitor_id].histogram_byte64_counter)); 1586 1587 if (latency_monitor_mem[unit][monitor_id].monitor_mode == bcmLatencyMonitorTimeSeriesMode) { 1588 if (latency_monitor_mem[unit][monitor_id].sw_buf_addr) { 1589 sal_memset(latency_monitor_mem[unit][monitor_id].sw_buf_addr, 0, 1590 latency_monitor_mem[unit][monitor_id].sw_buf_size); 1591 } 1592 latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx = 0; 1593 } 1594 1595 /* Clear below debug registers for the monitor */ 1596 SOC_IF_ERROR_RETURN(_clear_debug_registers(unit, monitor_id)); 1597 1598 latency_monitor_mem[unit][monitor_id].flex_ctr_wrap_ctr = 0; 1599 1600 latency_monitor_mem[unit][monitor_id].status = LATENCY_MONITOR_STATE_RUNNING; 1601 1602 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, AUX_ARB_CONTROLr, REG_PORT_ANY, 0, &rval)); 1603 hist_1us_enable = soc_reg_field_get(unit, AUX_ARB_CONTROLr, rval, HIST_1US_ENABLEf); 1604 if (!hist_1us_enable) { 1605 soc_reg_field_set(unit, AUX_ARB_CONTROLr, &rval, HIST_1US_ENABLEf, 1); 1606 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, AUX_ARB_CONTROLr, REG_PORT_ANY, 0, rval)); 1607 } 1608 1609 rv = latency_monitor_read(unit, monitor_id); 1610 if (rv == BCM_E_NONE) 1611 latency_monitor_driver_data.run[monitor_id] = TRUE; 1612 else 1613 return rv; 1614 } else { 1615 latency_monitor_mem[unit][monitor_id].pipe_map_temp = 0; 1616 latency_monitor_driver_data.run[monitor_id] = FALSE; 1617 /* Signal the sbusdma_read thread for termination */ 1618 sal_sem_give(latency_monitor_mem[unit][monitor_id].latency_monitor_thread_trigger); 1619 /* Signal the counter_accrue_thread for termination */ 1620 sal_sem_give(latency_monitor_mem[unit][monitor_id].dma_handle_counter_sem); 1621 } 1622 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1623 1624 return BCM_E_NONE; 1625 } 1626 1627 /* 1628 * Returns the accrued histogram counter values for a given monitor ID 1629 * and cosq (Valid in Accrue mode only) 1630 */ 1631 int 1632 bcm_tomahawk3_latency_monitor_histogram_get( 1633 int unit, 1634 uint8 monitor_id, 1635 uint8 cosq, 1636 uint8 byte_counter_flag, 1637 bcm_latency_monitor_histogram_t *histogram) 1638 { 1639 #ifdef BCM_TOMAHAWK3_SUPPORT 1640 int i; 1641 uint64 (*arr_pkt_cnt)[LATENCY_MONITOR_BUCKET_COUNT]; 1642 uint64 (*arr_byte_cnt)[LATENCY_MONITOR_BUCKET_COUNT]; 1643 1644 if (histogram == NULL) 1645 return BCM_E_PARAM; 1646 1647 if (monitor_id >= LATENCY_MONITOR_MAX_COUNT) 1648 return BCM_E_PARAM; 1649 1650 if (latency_monitor_mem[unit][monitor_id].monitor_mode != bcmLatencyMonitorAccrueMode) 1651 return BCM_E_UNAVAIL; 1652 1653 if (cosq >= LATENCY_MONITOR_QUEUE_COUNT) 1654 return BCM_E_PARAM; 1655 1656 if (histogram->histogram_size > LATENCY_MONITOR_BUCKET_COUNT) 1657 histogram->histogram_size = LATENCY_MONITOR_BUCKET_COUNT; 1658 1659 arr_pkt_cnt = (uint64 (*)[LATENCY_MONITOR_BUCKET_COUNT])latency_monitor_mem[unit][monitor_id].histogram_packet64_counter; 1660 arr_byte_cnt = (uint64 (*)[LATENCY_MONITOR_BUCKET_COUNT])latency_monitor_mem[unit][monitor_id].histogram_byte64_counter; 1661 1662 for (i=0; i<histogram->histogram_size; i++) { 1663 if (byte_counter_flag) 1664 histogram->histogram[i] = arr_byte_cnt[cosq][i]; 1665 else 1666 histogram->histogram[i] = arr_pkt_cnt[cosq][i]; 1667 } 1668 #endif 1669 1670 return BCM_E_NONE; 1671 } 1672 1673 int 1674 bcm_tomahawk3_latency_monitor_info_get( 1675 int unit, 1676 uint8 monitor_id, 1677 bcm_latency_monitor_info_t *monitor_info) 1678 { 1679 #ifdef BCM_TOMAHAWK3_SUPPORT 1680 if (monitor_info == NULL) 1681 return BCM_E_PARAM; 1682 1683 if (monitor_id >= LATENCY_MONITOR_MAX_COUNT) 1684 return BCM_E_PARAM; 1685 1686 switch (latency_monitor_mem[unit][monitor_id].status) { 1687 case LATENCY_MONITOR_STATE_RUNNING: 1688 monitor_info->monitor_status = bcmLatencyMonitorStatusRunning; 1689 break; 1690 case LATENCY_MONITOR_STATE_IDLE: 1691 monitor_info->monitor_status = bcmLatencyMonitorStatusIdle; 1692 break; 1693 case LATENCY_MONITOR_STATE_ERROR: 1694 monitor_info->monitor_status = bcmLatencyMonitorStatusError; 1695 break; 1696 default: 1697 monitor_info->monitor_status = bcmLatencyMonitorStatusUninit; 1698 break; 1699 } 1700 1701 monitor_info->sw_buf_addr = latency_monitor_mem[unit][monitor_id].sw_buf_addr; 1702 monitor_info->sw_buf_size = latency_monitor_mem[unit][monitor_id].sw_buf_size; 1703 monitor_info->sw_buf_wr_idx = (latency_monitor_mem[unit][monitor_id].sw_buf_wr_idx - 1); 1704 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1705 1706 return BCM_E_NONE; 1707 } 1708 1709 /* Release all the resource allocated for a given monitor. */ 1710 int 1711 bcm_tomahawk3_latency_monitor_destroy( 1712 int unit, 1713 uint8 monitor_id) 1714 { 1715 #ifdef BCM_TOMAHAWK3_SUPPORT 1716 bcm_latency_monitor_config_t monitor_cfg; 1717 bcm_latency_monitor_cosq_info_t cosq_cfg; 1718 1719 if (monitor_id >= LATENCY_MONITOR_MAX_COUNT) 1720 return BCM_E_PARAM; 1721 1722 if (latency_monitor_mem[unit][monitor_id].status == LATENCY_MONITOR_STATE_RUNNING) 1723 return BCM_E_BUSY; 1724 1725 _bcm_esw_stat_group_destroy(unit, latency_monitor_mem[unit][monitor_id].stat_counter_id); 1726 latency_monitor_mem[unit][monitor_id].stat_counter_id = 0; 1727 1728 latency_monitor_mem[unit][monitor_id].status = LATENCY_MONITOR_STATE_CLEANUP; 1729 bcm_latency_monitor_config_t_init(&monitor_cfg); 1730 SOC_PBMP_ASSIGN(monitor_cfg.src_pbmp, SOC_LATENCY_MONITOR_INFO(unit, monitor_id).src_pbmp); 1731 SOC_PBMP_ASSIGN(monitor_cfg.dest_pbmp, SOC_LATENCY_MONITOR_INFO(unit, monitor_id).dest_pbmp); 1732 BCM_IF_ERROR_RETURN(bcm_tomahawk3_latency_monitor_config_set(unit, monitor_id, &monitor_cfg)); 1733 bcm_latency_monitor_cosq_info_t_init(&cosq_cfg); 1734 BCM_IF_ERROR_RETURN(bcm_tomahawk3_latency_monitor_cosq_config_set(unit, monitor_id, -1, cosq_cfg)); 1735 1736 latency_monitor_mem[unit][monitor_id].status = 0; 1737 latency_monitor_mem[unit][monitor_id].init_done = FALSE; 1738 1739 SOC_LATENCY_MONITOR_INFO(unit, monitor_id).time_step = -1; 1740 SOC_LATENCY_MONITOR_INFO(unit, monitor_id).flex_pool_number = -1; 1741 BCM_PBMP_CLEAR(SOC_LATENCY_MONITOR_INFO(unit, monitor_id).src_pbmp); 1742 BCM_PBMP_CLEAR(SOC_LATENCY_MONITOR_INFO(unit, monitor_id).dest_pbmp); 1743 1744 sal_memset(latency_monitor_mem[unit][monitor_id].histogram_packet64_counter, 0, 1745 sizeof(latency_monitor_mem[unit][monitor_id].histogram_packet64_counter)); 1746 sal_memset(latency_monitor_mem[unit][monitor_id].histogram_byte64_counter, 0, 1747 sizeof(latency_monitor_mem[unit][monitor_id].histogram_byte64_counter)); 1748 1749 if (latency_monitor_mem[unit][monitor_id].monitor_mode == bcmLatencyMonitorTimeSeriesMode) { 1750 if (latency_monitor_mem[unit][monitor_id].sw_buf_addr) { 1751 sal_free(latency_monitor_mem[unit][monitor_id].sw_buf_addr); 1752 latency_monitor_mem[unit][monitor_id].sw_buf_addr = NULL; 1753 } 1754 } 1755 1756 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1757 1758 return BCM_E_NONE; 1759 } 1760 1761 int 1762 bcm_tomahawk3_latency_monitor_detach (int unit) 1763 { 1764 #ifdef BCM_TOMAHAWK3_SUPPORT 1765 int monitor_id; 1766 1767 if (soc_feature(unit, soc_feature_latency_monitor)) { 1768 for (monitor_id = 0; monitor_id < LATENCY_MONITOR_MAX_COUNT; monitor_id++) { 1769 if (latency_monitor_mem[unit][monitor_id].status == 1770 LATENCY_MONITOR_STATE_RUNNING) { 1771 latency_monitor_driver_data.run[monitor_id] = FALSE; 1772 bcm_tomahawk3_latency_monitor_enable(unit, monitor_id, 0); 1773 while (latency_monitor_mem[unit][monitor_id].status == 1774 LATENCY_MONITOR_STATE_RUNNING) { 1775 sal_usleep(5); 1776 } 1777 } 1778 bcm_tomahawk3_latency_monitor_destroy(unit, monitor_id); 1779 } 1780 1781 latency_monitor_driver_data.init_done = 0; 1782 } 1783 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1784 1785 return BCM_E_NONE; 1786 } 1787 1788 int 1789 bcm_tomahawk3_latency_monitor_init (int unit) 1790 { 1791 #ifdef BCM_TOMAHAWK3_SUPPORT 1792 int monitor_id; 1793 int rv; 1794 1795 if (soc_feature(unit, soc_feature_latency_monitor)) { 1796 for (monitor_id = 0; monitor_id < LATENCY_MONITOR_MAX_COUNT; monitor_id++) { 1797 if (latency_monitor_mem[unit][monitor_id].status == 1798 LATENCY_MONITOR_STATE_RUNNING) { 1799 latency_monitor_driver_data.run[monitor_id] = FALSE; 1800 rv = bcm_tomahawk3_latency_monitor_enable(unit, monitor_id, 0); 1801 BCM_IF_ERROR_RETURN(rv); 1802 } 1803 rv = bcm_tomahawk3_latency_monitor_destroy(unit, monitor_id); 1804 BCM_IF_ERROR_RETURN(rv); 1805 } 1806 1807 if (!latency_monitor_driver_data.init_done) 1808 latency_monitor_driver_data_init(unit); 1809 1810 #ifdef BCM_WARM_BOOT_SUPPORT 1811 if (SOC_WARM_BOOT(unit)) { 1812 rv = _bcm_th3_latency_monitor_wb_recover(unit); 1813 } else { 1814 rv = _bcm_th3_latency_monitor_scache_alloc(unit, 1); 1815 } 1816 1817 if (rv == BCM_E_NOT_FOUND) { 1818 /* Continue with initialization if scache not found */ 1819 rv = BCM_E_NONE; 1820 } 1821 1822 if (BCM_FAILURE(rv)) { 1823 return (rv); 1824 } 1825 #endif /* BCM_WARM_BOOT_SUPPORT */ 1826 } 1827 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1828 1829 return BCM_E_NONE; 1830 } 1831 1832 #ifdef BCM_WARM_BOOT_SUPPORT 1833 #ifdef BCM_TOMAHAWK3_SUPPORT 1834 1835 #define BCM_WB_LATENCY_MONITOR_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 1836 #define BCM_WB_LATENCY_MONITOR_DEFAULT_VERSION BCM_WB_LATENCY_MONITOR_VERSION_1_0 1837 1838 #define LATENCY_MONITOR_SCACHE_WRITE(_scache, _val, _type) \ 1839 do { \ 1840 _type _tmp = (_type) (_val); \ 1841 sal_memcpy((_scache), &(_tmp), sizeof(_type)); \ 1842 (_scache) += sizeof(_type); \ 1843 } while(0) 1844 1845 #define LATENCY_MONITOR_SCACHE_READ(_scache, _var, _type) \ 1846 do { \ 1847 _type _tmp; \ 1848 sal_memcpy(&(_tmp), (_scache), sizeof(_type)); \ 1849 (_scache) += sizeof(_type); \ 1850 (_var) = (_tmp); \ 1851 } while(0) 1852 1853 /* 1854 * Function: 1855 * _bcm_th3_latency_monitor_scache_v0_global_size_get 1856 * Purpose: 1857 * Get the size required to sync Latency Monitor global data to scache v0 1858 * Parameters: 1859 * unit - (IN) Device unit number 1860 * Returns: 1861 * Required size 1862 */ 1863 STATIC uint32 1864 _bcm_th3_latency_monitor_scache_v0_global_size_get(int unit) 1865 { 1866 uint32 size = 0; 1867 1868 /* Reserved bits */ 1869 size += sizeof(uint32); 1870 1871 /* Monitor status */ 1872 size += sizeof(uint8) * LATENCY_MONITOR_MAX_COUNT; 1873 1874 /*Monitor Mode */ 1875 size += sizeof(uint8) * LATENCY_MONITOR_MAX_COUNT; 1876 1877 /* SW Ring Buffer size (Timeseries mode only) */ 1878 size += sizeof(uint32) * LATENCY_MONITOR_MAX_COUNT; 1879 1880 /* Store configured bucket count for each Queue */ 1881 size += sizeof(uint8) * LATENCY_MONITOR_QUEUE_COUNT * LATENCY_MONITOR_MAX_COUNT; 1882 1883 return size; 1884 } 1885 1886 1887 /* 1888 * Function: 1889 * _bcm_th3_latency_monitor_scache_v0_size_get 1890 * Purpose: 1891 * Get Latency monitor scache v0 size 1892 * Parameters: 1893 * unit - (IN) Device unit number 1894 * Returns: 1895 * Size required 1896 */ 1897 STATIC uint32 1898 _bcm_th3_latency_monitor_scache_v0_size_get(int unit) 1899 { 1900 uint32 size = 0; 1901 1902 /* Get global data size */ 1903 size += _bcm_th3_latency_monitor_scache_v0_global_size_get(unit); 1904 1905 return size; 1906 } 1907 1908 int 1909 _bcm_th3_latency_monitor_wb_post_init(int unit) 1910 { 1911 int i=0; 1912 bcm_latency_monitor_config_t cfg; 1913 int monitor_status; 1914 1915 wb_post_init = 1; 1916 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 1917 if (latency_monitor_mem[unit][i].status) { 1918 monitor_status = latency_monitor_mem[unit][i].status; 1919 bcm_tomahawk3_latency_monitor_config_get(unit, i, &cfg); 1920 bcm_tomahawk3_latency_monitor_config_set(unit, i, &cfg); 1921 if (monitor_status == LATENCY_MONITOR_STATE_RUNNING) { 1922 bcm_tomahawk3_latency_monitor_enable(unit, i, 1); 1923 } 1924 } 1925 } 1926 wb_post_init = 0; 1927 return BCM_E_NONE; 1928 } 1929 1930 /* 1931 * Function: 1932 * _bcm_th3_latency_monitor_scache_v0_global_recover 1933 * Purpose: 1934 * Recover Latency monitor global data from scache v0 1935 * Parameters: 1936 * unit - (IN) Device unit number 1937 * scache - (IN) Pointer to current scache location 1938 * Returns: 1939 * BCM_E_XXX 1940 */ 1941 STATIC int 1942 _bcm_th3_latency_monitor_scache_v0_global_recover(int unit, uint8 **scache) 1943 { 1944 int i=0; 1945 int j=0; 1946 1947 /* Reserved bits */ 1948 *scache += sizeof(uint32); 1949 1950 /* Restore Monitor state info */ 1951 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 1952 LATENCY_MONITOR_SCACHE_READ(*scache, latency_monitor_mem[unit][i].status, uint8); 1953 } 1954 1955 /* Restore Monitor Mode */ 1956 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 1957 LATENCY_MONITOR_SCACHE_READ(*scache, latency_monitor_mem[unit][i].monitor_mode, uint8); 1958 } 1959 1960 /* Restore Histogram set count in SW Ring buffer used for Timeseries mode */ 1961 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 1962 LATENCY_MONITOR_SCACHE_READ(*scache, latency_monitor_mem[unit][i].sw_buf_size, uint32); 1963 } 1964 1965 /* Restore bucket count for each queues */ 1966 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 1967 for (j=0; j<LATENCY_MONITOR_QUEUE_COUNT; j++) { 1968 LATENCY_MONITOR_SCACHE_READ(*scache, 1969 latency_monitor_mem[unit][i].cosq_info[j].bucket_count, uint8); 1970 } 1971 } 1972 1973 return BCM_E_NONE; 1974 } 1975 1976 1977 /* 1978 * Function: 1979 * _bcm_th3_latency_monitor_scache_v0_recover 1980 * Purpose: 1981 * Recover Latency Monitor scache v0 data 1982 * Parameters: 1983 * unit - (IN) Device unit number 1984 * scache - (IN) Pointer to current scache location 1985 * Returns: 1986 * BCM_E_XXX 1987 */ 1988 STATIC int 1989 _bcm_th3_latency_monitor_scache_v0_recover(int unit, uint8 **scache) 1990 { 1991 /* Recover global data */ 1992 BCM_IF_ERROR_RETURN(_bcm_th3_latency_monitor_scache_v0_global_recover(unit, scache)); 1993 1994 return BCM_E_NONE; 1995 } 1996 1997 /* 1998 * Function: 1999 * _bcm_th3_latency_monitor_scache_alloc 2000 * Purpose: 2001 * Latency Monitor WB scache alloc 2002 * Parameters: 2003 * unit - (IN) Unit number. 2004 * create - (IN) 1 - Create, 0 - Realloc 2005 * Returns: 2006 * BCM_E_XXX 2007 * Notes: 2008 */ 2009 STATIC int _bcm_th3_latency_monitor_scache_alloc(int unit, int create) 2010 { 2011 uint32 cur_size = 0; 2012 uint32 rqd_size = 0; 2013 int rv = BCM_E_NONE; 2014 soc_scache_handle_t scache_handle; 2015 uint8 *scache = NULL; 2016 2017 rqd_size += _bcm_th3_latency_monitor_scache_v0_size_get(unit); 2018 2019 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_LATENCY_MONITOR, 0); 2020 2021 if (create) { 2022 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1, rqd_size, 2023 &scache, BCM_WB_LATENCY_MONITOR_DEFAULT_VERSION, NULL); 2024 BCM_IF_ERROR_RETURN(rv); 2025 } else { 2026 /* Get current size */ 2027 rv = soc_scache_ptr_get(unit, scache_handle, &scache, &cur_size); 2028 SOC_IF_ERROR_RETURN(rv); 2029 2030 if (rqd_size > cur_size) { 2031 /* Request the extra size */ 2032 rv = soc_scache_realloc(unit, scache_handle, rqd_size - cur_size); 2033 SOC_IF_ERROR_RETURN(rv); 2034 } 2035 } 2036 2037 return BCM_E_NONE; 2038 } 2039 2040 /* 2041 * Function: 2042 * _BCM_th3_latency_monitor_wb_recover 2043 * Purpose: 2044 * Latency Monitor WB recovery 2045 * Parameters: 2046 * unit - (IN) Unit number. 2047 * Returns: 2048 * BCM_E_XXX 2049 * Notes: 2050 */ 2051 STATIC int _bcm_th3_latency_monitor_wb_recover(int unit) 2052 { 2053 int stable_size; /* Secondary storage size. */ 2054 uint8 *scache = NULL; 2055 soc_scache_handle_t scache_handle; 2056 int rv = BCM_E_NONE; 2057 uint16 recovered_ver = 0; 2058 2059 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2060 2061 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 2062 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_LATENCY_MONITOR, 0); 2063 2064 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 2065 &scache, BCM_WB_LATENCY_MONITOR_DEFAULT_VERSION, 2066 &recovered_ver); 2067 if (BCM_E_NOT_FOUND == rv) { 2068 /* Upgrading from SDK release that does not have warmboot state */ 2069 rv = _bcm_th3_latency_monitor_scache_alloc(unit, 1); 2070 return rv; 2071 } else if (BCM_FAILURE(rv)) { 2072 return rv; 2073 } 2074 2075 if (NULL == scache) { 2076 return BCM_E_NOT_FOUND; 2077 } 2078 } else { 2079 return BCM_E_NONE; 2080 } 2081 2082 /* Scache recovery */ 2083 BCM_IF_ERROR_RETURN(_bcm_th3_latency_monitor_scache_v0_recover(unit, &scache)); 2084 2085 /* Realloc any extra scache that may be needed */ 2086 BCM_IF_ERROR_RETURN(_bcm_th3_latency_monitor_scache_alloc(unit, 0)); 2087 2088 return rv; 2089 } 2090 2091 /* 2092 * Function: 2093 * _bcm_th3_latency_monitor_scache_v0_global_sync 2094 * Purpose: 2095 * Sync Latency Monitor global data to scache v0 2096 * Parameters: 2097 * unit - (IN) Device unit number 2098 * scache - (IN) Pointer to current scache location 2099 * Returns: 2100 * BCM_E_XXX 2101 */ 2102 STATIC void 2103 _bcm_th3_latency_monitor_scache_v0_global_sync(int unit, uint8 **scache) 2104 { 2105 int i; 2106 int j; 2107 uint8 tmp = 0; 2108 2109 /* Reserve first 32 bits */ 2110 LATENCY_MONITOR_SCACHE_WRITE(*scache, 0, uint32); 2111 2112 /* Store Monitor state info */ 2113 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 2114 LATENCY_MONITOR_SCACHE_WRITE(*scache, latency_monitor_mem[unit][i].status, uint8); 2115 } 2116 2117 /* Store Monitor Mode */ 2118 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 2119 if (latency_monitor_mem[unit][i].monitor_mode == bcmLatencyMonitorTimeSeriesMode) { 2120 tmp = 1; 2121 } else { 2122 tmp = 0; 2123 } 2124 LATENCY_MONITOR_SCACHE_WRITE(*scache, tmp, uint8); 2125 } 2126 2127 /* Store SW ring buffer size (used in Timeseries mode */ 2128 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 2129 LATENCY_MONITOR_SCACHE_WRITE(*scache, latency_monitor_mem[unit][i].sw_buf_size, uint32); 2130 } 2131 2132 /* Store bucket count for each queues */ 2133 for (i=0; i<LATENCY_MONITOR_MAX_COUNT; i++) { 2134 for (j=0; j<LATENCY_MONITOR_QUEUE_COUNT; j++) { 2135 LATENCY_MONITOR_SCACHE_WRITE(*scache, 2136 latency_monitor_mem[unit][i].cosq_info[j].bucket_count, uint8); 2137 } 2138 } 2139 2140 2141 } 2142 2143 /* 2144 * Function: 2145 * _bcm_th3_latency_monitor_scache_v0_sync 2146 * Purpose: 2147 * Sync Latency Monitor scache v0 2148 * Parameters: 2149 * unit - (IN) Device unit number 2150 * scache - (IN) Pointer to current scache location 2151 * Returns: 2152 * None 2153 */ 2154 STATIC void 2155 _bcm_th3_latency_monitor_scache_v0_sync(int unit, uint8 **scache) 2156 { 2157 /* Sync global data */ 2158 _bcm_th3_latency_monitor_scache_v0_global_sync(unit, scache); 2159 } 2160 2161 /* 2162 * Function: 2163 * _bcm_th3_latency_monitor_sync 2164 * Purpose: 2165 * Warmboot scache sync 2166 * Parameters: 2167 * unit - (IN) Unit number. 2168 * Returns: 2169 * BCM_E_XXX 2170 * Notes: 2171 */ 2172 int _bcm_th3_latency_monitor_sync(int unit) 2173 { 2174 int stable_size; 2175 soc_scache_handle_t scache_handle; 2176 uint8 *scache = NULL; 2177 2178 /* Get FT module storage size. */ 2179 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 2180 2181 /* If level 2 store is not configured return from here. */ 2182 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 2183 return BCM_E_NONE; 2184 } 2185 2186 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_LATENCY_MONITOR, 0); 2187 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 2188 &scache, 0, NULL)); 2189 if (NULL == scache) { 2190 return BCM_E_INTERNAL; 2191 } 2192 2193 /* Sync FT scache v0 */ 2194 _bcm_th3_latency_monitor_scache_v0_sync(unit, &scache); 2195 2196 return BCM_E_NONE; 2197 } 2198 2199 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2200 #endif /* BCM_WARM_BOOT_SUPPORT */ 2201