int.c (31634B)
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 * INT - In-band Telemetry Turnaround Embedded Application APP interface 8 * Purpose: API to configure In-band Telemetry Turnaround embedded app interface. 9 */ 10 11 #if defined(INCLUDE_INT) && defined(BCM_TOMAHAWK3_SUPPORT) 12 13 #include <shared/bsl.h> 14 #include <shared/alloc.h> 15 #include <shared/bslenum.h> 16 #include <shared/idxres_fl.h> 17 18 #include <soc/defs.h> 19 #include <soc/drv.h> 20 #include <soc/uc.h> 21 22 #include <bcm/types.h> 23 #include <bcm/error.h> 24 #include <bcm/int.h> 25 26 #include <bcm_int/common/int_feature.h> 27 #include <bcm_int/common/int.h> 28 #include <bcm_int/common/rx.h> 29 #include <bcm_int/tomahawk3_dispatch.h> 30 31 #include <soc/shared/int.h> 32 #include <soc/shared/int_msg.h> 33 #include <soc/shared/int_pack.h> 34 #include <soc/shared/shr_pkt.h> 35 36 /*Global to hold the INT Turnaround firmware version for feature compatibility check */ 37 uint32 int_firmware_version = 0; 38 39 /* INT Turnaround global information */ 40 _bcm_int_turnaround_info_t *int_global_info[BCM_MAX_NUM_UNITS] = {0}; 41 static sal_mutex_t mutex[BCM_MAX_NUM_UNITS]; 42 43 /* List of INT Turnaround configuration information */ 44 bcm_int_turnaround_config_t int_turnaround_config[BCM_MAX_NUM_UNITS]; 45 46 /* 47 * Function: 48 * _bcm_int_convert_uc_error 49 * Purpose: 50 * Converts uController error code to corresponding BCM error code. 51 * Parameters: 52 * uc_rv - (IN) uController error code to convert. 53 * Returns: 54 * BCM_E_XXX - BCM error code. 55 * Notes: 56 */ 57 STATIC int 58 _bcm_int_convert_uc_error(uint32 uc_rv) 59 { 60 int rv = BCM_E_NONE; 61 62 switch(uc_rv) { 63 case SHR_INT_UC_E_NONE: 64 rv = BCM_E_NONE; 65 break; 66 case SHR_INT_UC_E_INTERNAL: 67 rv = BCM_E_INTERNAL; 68 break; 69 case SHR_INT_UC_E_MEMORY: 70 rv = BCM_E_MEMORY; 71 break; 72 case SHR_INT_UC_E_UNIT: 73 rv = BCM_E_UNIT; 74 break; 75 case SHR_INT_UC_E_PARAM: 76 rv = BCM_E_PARAM; 77 break; 78 case SHR_INT_UC_E_EMPTY: 79 rv = BCM_E_EMPTY; 80 break; 81 case SHR_INT_UC_E_FULL: 82 rv = BCM_E_FULL; 83 break; 84 case SHR_INT_UC_E_NOT_FOUND: 85 rv = BCM_E_NOT_FOUND; 86 break; 87 case SHR_INT_UC_E_EXISTS: 88 rv = BCM_E_EXISTS; 89 break; 90 case SHR_INT_UC_E_TIMEOUT: 91 rv = BCM_E_TIMEOUT; 92 break; 93 case SHR_INT_UC_E_BUSY: 94 rv = BCM_E_BUSY; 95 break; 96 case SHR_INT_UC_E_FAIL: 97 rv = BCM_E_FAIL; 98 break; 99 case SHR_INT_UC_E_DISABLED: 100 rv = BCM_E_DISABLED; 101 break; 102 case SHR_INT_UC_E_BADID: 103 rv = BCM_E_BADID; 104 break; 105 case SHR_INT_UC_E_RESOURCE: 106 rv = BCM_E_RESOURCE; 107 break; 108 case SHR_INT_UC_E_CONFIG: 109 rv = BCM_E_CONFIG; 110 break; 111 case SHR_INT_UC_E_UNAVAIL: 112 rv = BCM_E_UNAVAIL; 113 break; 114 case SHR_INT_UC_E_INIT: 115 rv = BCM_E_INIT; 116 break; 117 case SHR_INT_UC_E_PORT: 118 rv = BCM_E_PORT; 119 break; 120 default: 121 rv = BCM_E_INTERNAL; 122 break; 123 } 124 125 return rv; 126 } 127 128 STATIC int 129 _bcm_int_lb_header_get( 130 shr_lb_header_t *lb) 131 { 132 /* LB Header below fields fixed in case of INT Turnaround eapps */ 133 sal_memset(lb, 0, sizeof(*lb)); 134 lb->start = 0xFB; 135 lb->common_hdr0 = 1; 136 lb->common_hdr1 = 1; 137 lb->source_type = 1; 138 139 /* LB header other fields are update by R5 */ 140 return BCM_E_NONE; 141 } 142 143 144 /* 145 * Function: 146 * _bcm_int_eapp_lb_encap_build_pack 147 * Purpose: 148 * Builds and packs the INT LB Header 149 * Parameters: 150 * config_info - (IN) Pointer to config info structure. 151 * config_info_msg - (OUT) Message which contains the int header encapsulation. 152 * Returns: 153 * BCM_E_XXX 154 * Notes: 155 * The returning encapsulation includes only INT headers 156 */ 157 STATIC int 158 _bcm_int_eapp_lb_encap_build_pack(int unit, 159 bcm_int_turnaround_config_t *config_info, 160 shr_int_turnaround_msg_ctrl_config_t *config_info_msg) 161 { 162 uint8 *buffer = config_info_msg->lb_encap; 163 uint8 *cur_ptr; 164 shr_lb_header_t lb; 165 166 sal_memset(&lb, 0, sizeof(lb)); 167 BCM_IF_ERROR_RETURN 168 (_bcm_int_lb_header_get(&lb)); 169 170 /* 171 * Pack header into given buffer (network packet format). 172 */ 173 cur_ptr = buffer; 174 175 /* LoopBack Header is always present */ 176 cur_ptr = shr_lb_header_pack(cur_ptr, &lb); 177 178 /* Set INT export pkt encapsulation length */ 179 config_info_msg->lb_encap_length = cur_ptr - buffer; 180 181 if (config_info_msg->lb_encap_length != SHR_LB_HEADER_LENGTH) { 182 LOG_DEBUG(BSL_LS_BCM_INT, (BSL_META_U(unit, 183 "INT(unit %d) Info: update LB header"), unit)); 184 return (BCM_E_INTERNAL); 185 } 186 187 return BCM_E_NONE; 188 } 189 190 STATIC int 191 _bcm_int_msg_send_receive(int unit, uint8 s_subclass, 192 uint16 s_len, uint32 s_data, 193 uint8 r_subclass, uint16 *r_len, 194 sal_usecs_t timeout) 195 { 196 int rv; 197 mos_msg_data_t send, reply; 198 uint32 uc_rv; 199 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 200 uint8 *dma_buffer; 201 int dma_buffer_len; 202 203 204 dma_buffer = int_turnaround_info->dma_buffer; 205 dma_buffer_len = int_turnaround_info->dma_buffer_len; 206 207 sal_memset(&send, 0, sizeof(send)); 208 sal_memset(&reply, 0, sizeof(reply)); 209 send.s.mclass = MOS_MSG_CLASS_INT; 210 send.s.subclass = s_subclass; 211 send.s.len = bcm_htons(s_len); 212 213 /* 214 * Set 'data' to DMA buffer address if a DMA operation is 215 * required for send or receive. 216 */ 217 if (MOS_MSG_DMA_MSG(s_subclass) || 218 MOS_MSG_DMA_MSG(r_subclass)) { 219 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 220 } else { 221 send.s.data = bcm_htonl(s_data); 222 } 223 224 /* Flush DMA memory */ 225 if (MOS_MSG_DMA_MSG(s_subclass)) { 226 soc_cm_sflush(unit, dma_buffer, s_len); 227 } 228 229 /* Invalidate DMA memory to read */ 230 if (MOS_MSG_DMA_MSG(r_subclass)) { 231 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 232 } 233 234 rv = soc_cmic_uc_msg_send_receive(unit, int_turnaround_info->uc_num, 235 &send, &reply, 236 timeout); 237 if (rv != SOC_E_NONE){ 238 return BCM_E_INTERNAL; 239 } 240 241 /* Convert INT Turnaround uController error code to BCM */ 242 uc_rv = bcm_ntohl(reply.s.data); 243 rv = _bcm_int_convert_uc_error(uc_rv); 244 245 *r_len = bcm_ntohs(reply.s.len); 246 247 /*Check reply class and subclass*/ 248 if((rv == SOC_E_NONE) && ((reply.s.mclass != MOS_MSG_CLASS_INT) || 249 (reply.s.subclass != r_subclass))) 250 { 251 return BCM_E_INTERNAL; 252 } 253 return rv; 254 } 255 256 STATIC int 257 _bcm_int_eapp_send_ctrl_init_msg (int unit) 258 { 259 shr_int_turnaround_msg_ctrl_init_t ctrl_init_msg; 260 uint8 *buffer_req = NULL, *buffer_ptr = NULL; 261 uint16 buffer_len = 0, reply_len = 0; 262 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 263 264 sal_memset(&ctrl_init_msg, 0, sizeof(ctrl_init_msg)); 265 ctrl_init_msg.rx_channel = BCM_INT_EAPP_RX_CHANNEL; 266 ctrl_init_msg.tx_channel = BCM_INT_EAPP_TX_CHANNEL; 267 268 buffer_req = int_turnaround_info->dma_buffer; 269 buffer_ptr = shr_int_turnaround_msg_ctrl_init_pack(buffer_req, &ctrl_init_msg); 270 buffer_len = buffer_ptr - buffer_req; 271 272 BCM_IF_ERROR_RETURN(_bcm_int_msg_send_receive(unit, MOS_MSG_SUBCLASS_INT_INIT, 273 buffer_len, 0, 274 MOS_MSG_SUBCLASS_INT_INIT_REPLY, &reply_len, 275 SHR_INT_MAX_UC_MSG_TIMEOUT)); 276 return BCM_E_NONE; 277 } 278 279 /******************************************************* 280 * * 281 * INT TURNAROUND EMBEDDED APP APIs * 282 */ 283 284 STATIC int 285 bcm_int_eapp_detach(int unit) 286 { 287 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 288 int rv = BCM_E_NONE; 289 int status = 0; 290 uint16 reply_len = 0; 291 292 if (!SOC_WARM_BOOT(unit)) { 293 /* Un Init the app */ 294 SOC_IF_ERROR_RETURN(soc_uc_status(unit, int_turnaround_info->uc_num, &status)); 295 if (status) { 296 rv = _bcm_int_msg_send_receive(unit, 297 MOS_MSG_SUBCLASS_INT_SHUTDOWN, 298 0, 0, 299 MOS_MSG_SUBCLASS_INT_SHUTDOWN_REPLY, 300 &reply_len, 301 SHR_INT_MAX_UC_MSG_TIMEOUT); 302 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 303 return BCM_E_INTERNAL; 304 } 305 } 306 } 307 308 /* 309 * Free DMA buffer 310 */ 311 if (int_turnaround_info->dma_buffer != NULL) { 312 soc_cm_sfree(unit, int_turnaround_info->dma_buffer); 313 int_turnaround_info->dma_buffer = NULL; 314 } 315 316 return BCM_E_NONE; 317 } 318 319 STATIC int 320 bcm_int_turnaround_eapp_config_get_msg(int unit, 321 bcm_int_turnaround_config_t *config_info) 322 { 323 shr_int_turnaround_msg_ctrl_config_t config_info_msg; 324 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 325 uint8 *buffer_req = NULL, *buffer_ptr = NULL; 326 uint16 buffer_len = 0, reply_len = 0; 327 328 if (config_info == NULL) { 329 return BCM_E_PARAM; 330 } 331 332 sal_memset(config_info, 0, sizeof(bcm_int_turnaround_config_t)); 333 sal_memset(&config_info_msg, 0, sizeof(config_info_msg)); 334 335 BCM_IF_ERROR_RETURN(_bcm_int_msg_send_receive(unit, MOS_MSG_SUBCLASS_INT_CONFIG_GET, 336 buffer_len, 0, 337 MOS_MSG_SUBCLASS_INT_CONFIG_GET_REPLY, &reply_len, 338 SHR_INT_MAX_UC_MSG_TIMEOUT)); 339 buffer_req = int_turnaround_info->dma_buffer; 340 buffer_ptr = shr_int_turnaround_msg_ctrl_config_unpack(buffer_req, &config_info_msg); 341 buffer_len = buffer_ptr - buffer_req; 342 343 if (reply_len != buffer_len) { 344 return BCM_E_INTERNAL; 345 } 346 347 sal_memcpy(config_info->src_mac, config_info_msg.src_mac, SHR_MAC_ADDR_LENGTH); 348 349 return BCM_E_NONE; 350 } 351 352 STATIC int 353 bcm_int_eapp_init(int unit) 354 { 355 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 356 int rv = BCM_E_NONE; 357 int uc = 0; 358 int status; 359 bcm_int_turnaround_config_t *config_info = (&(int_turnaround_config[unit])); 360 361 /* Init the app */ 362 /* 363 * Start INT Turnaround application in BTE (Broadcom Task Engine) uController, 364 * if not already running (warm boot). 365 * Determine which uController is running INT Turnaround by choosing the first 366 * uC that returns successfully. 367 */ 368 for (uc = 0; uc < CMICM_NUM_UCS; uc++) { 369 rv = soc_uc_status(unit, uc, &status); 370 if ((rv == SOC_E_NONE) && (status != 0)) { 371 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_INT, 372 SHR_INT_MAX_UC_MSG_TIMEOUT, 373 INT_SDK_VERSION, 374 INT_UC_MIN_VERSION, 375 NULL, NULL); 376 if (SOC_E_NONE == rv) { 377 /* INT Turnaround started successfully */ 378 break; 379 } 380 } 381 } 382 383 if (uc >= CMICM_NUM_UCS) { 384 /* Could not find or start INT Turnaround appl */ 385 LOG_WARN(BSL_LS_BCM_INT, 386 (BSL_META_U(unit, 387 "uKernel INT Turnaround application not available\n"))); 388 return BCM_E_NONE; 389 } 390 int_turnaround_info->uc_num = uc; 391 int_turnaround_info->cosq_turnaround_index = -1; 392 int_turnaround_info->cosq_hoplimit_index = -1; 393 394 /* Detach if already initialized */ 395 if (!soc_feature(unit, soc_feature_uc_int_turnaround)) { 396 BCM_IF_ERROR_RETURN(bcm_int_eapp_detach(unit)); 397 return BCM_E_INIT; 398 } 399 400 if (!SOC_WARM_BOOT(unit)) { 401 /* Send the init config to UKERNEL */ 402 rv = _bcm_int_eapp_send_ctrl_init_msg(unit); 403 if (BCM_FAILURE(rv)) { 404 BCM_IF_ERROR_RETURN(bcm_int_eapp_detach(unit)); 405 return rv; 406 } 407 sal_memset(config_info, 0, sizeof(bcm_int_turnaround_config_t)); 408 } else { 409 /* Get the Config info */ 410 rv = bcm_int_turnaround_eapp_config_get_msg(unit, config_info); 411 if (BCM_FAILURE(rv)) { 412 return rv; 413 } 414 } 415 416 return BCM_E_NONE; 417 } 418 419 STATIC int 420 bcm_int_turnaround_eapp_config_msg(int unit, 421 bcm_int_turnaround_config_t *config_info) 422 { 423 shr_int_turnaround_msg_ctrl_config_t config_info_msg; 424 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 425 uint8 *buffer_req = NULL, *buffer_ptr = NULL; 426 uint16 buffer_len = 0, reply_len = 0; 427 int rv = BCM_E_NONE; 428 429 sal_memset(&config_info_msg, 0, sizeof(config_info_msg)); 430 431 sal_memcpy(config_info_msg.src_mac, config_info->src_mac, SHR_MAC_ADDR_LENGTH); 432 rv = _bcm_int_eapp_lb_encap_build_pack(unit, 433 config_info, &config_info_msg); 434 if (BCM_FAILURE(rv)) { 435 return rv; 436 } 437 438 buffer_req = int_turnaround_info->dma_buffer; 439 buffer_ptr = shr_int_turnaround_msg_ctrl_config_pack(buffer_req, &config_info_msg); 440 buffer_len = buffer_ptr - buffer_req; 441 442 BCM_IF_ERROR_RETURN(_bcm_int_msg_send_receive(unit, MOS_MSG_SUBCLASS_INT_CONFIG_SET, 443 buffer_len, 0, 444 MOS_MSG_SUBCLASS_INT_CONFIG_SET_REPLY, &reply_len, 445 SHR_INT_MAX_UC_MSG_TIMEOUT)); 446 return BCM_E_NONE; 447 } 448 449 STATIC int 450 bcm_int_tunraround_eapp_stat_get_msg(int unit, 451 bcm_int_turnaround_stat_t *stat_data) 452 { 453 shr_int_turnaround_msg_ctrl_stat_t stat_data_msg; 454 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 455 uint8 *buffer_req = NULL, *buffer_ptr = NULL; 456 uint16 buffer_len = 0, reply_len = 0; 457 458 sal_memset(stat_data, 0, sizeof(bcm_int_turnaround_stat_t)); 459 sal_memset(&stat_data_msg, 0, sizeof(stat_data_msg)); 460 461 BCM_IF_ERROR_RETURN(_bcm_int_msg_send_receive(unit, MOS_MSG_SUBCLASS_INT_STAT_GET, 462 buffer_len, 0, 463 MOS_MSG_SUBCLASS_INT_STAT_GET_REPLY, &reply_len, 464 SHR_INT_MAX_UC_MSG_TIMEOUT)); 465 buffer_req = int_turnaround_info->dma_buffer; 466 buffer_ptr = shr_int_turnaround_msg_ctrl_stat_unpack(buffer_req, &stat_data_msg); 467 buffer_len = buffer_ptr - buffer_req; 468 469 if (reply_len != buffer_len) { 470 return BCM_E_INTERNAL; 471 } 472 473 COMPILER_64_SET(stat_data->rx_pkt_cnt, stat_data_msg.rx_pkt_cnt_hi, 474 stat_data_msg.rx_pkt_cnt_lo); 475 COMPILER_64_SET(stat_data->tx_pkt_cnt, stat_data_msg.tx_pkt_cnt_hi, 476 stat_data_msg.tx_pkt_cnt_lo); 477 COMPILER_64_SET(stat_data->drop_pkt_cnt, stat_data_msg.drop_pkt_cnt_hi, 478 stat_data_msg.drop_pkt_cnt_lo); 479 COMPILER_64_SET(stat_data->int_init_config_drop, stat_data_msg.int_init_config_drop_hi, 480 stat_data_msg.int_init_config_drop_lo); 481 COMPILER_64_SET(stat_data->int_hop_cnt_invalid_drop, stat_data_msg.int_hop_cnt_invalid_drop_hi, 482 stat_data_msg.int_hop_cnt_invalid_drop_lo); 483 COMPILER_64_SET(stat_data->int_hdr_len_invalid_drop, stat_data_msg.int_hdr_len_invalid_drop_hi, 484 stat_data_msg.int_hdr_len_invalid_drop_lo); 485 COMPILER_64_SET(stat_data->int_pkt_size_invalid_drop, stat_data_msg.int_pkt_size_invalid_drop_hi, 486 stat_data_msg.int_pkt_size_invalid_drop_lo); 487 488 return BCM_E_NONE; 489 } 490 491 /* Shut down the INT TURNAROUND app. */ 492 STATIC int 493 _bcm_th3_int_detach(int unit) 494 { 495 /* De-init the embedded app */ 496 int rv = BCM_E_NONE; 497 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 498 499 if (int_turnaround_info == NULL) { 500 return BCM_E_NONE; 501 } 502 503 rv = bcm_int_eapp_detach(unit); 504 if (BCM_FAILURE(rv)) { 505 LOG_ERROR(BSL_LS_BCM_INT, (BSL_META_U(unit, 506 "INT TURNAROUND: Failed to Detach"))); 507 return rv; 508 } 509 510 /* Delete CPU COS queue mapping entries for INT TURNAROUND packets */ 511 if (int_turnaround_info->cosq_turnaround_index >= 0) { 512 (void) bcm_esw_rx_cosq_mapping_delete(unit, 513 int_turnaround_info->cosq_turnaround_index); 514 int_turnaround_info->cosq_turnaround_index = -1; 515 } 516 if (int_turnaround_info->cosq_hoplimit_index >= 0) { 517 (void) bcm_esw_rx_cosq_mapping_delete(unit, 518 int_turnaround_info->cosq_hoplimit_index); 519 int_turnaround_info->cosq_hoplimit_index = -1; 520 } 521 522 sal_free(int_turnaround_info); 523 int_turnaround_info = NULL; 524 int_global_info[unit] = NULL; 525 526 return rv; 527 } 528 529 /* 530 * Function: 531 * bcm_int_turnaround_hw_init 532 * Purpose: 533 * Initialize the HW for INT Turnaround packet processing. 534 * Configure: 535 * - Copy to CPU INT Turnaround error packets 536 * - Assign RX DMA channel to CPU COS Queue 537 * Parameters: 538 * unit - (IN) Unit number. 539 * Returns: 540 * BCM_E_XXX 541 * Notes: 542 */ 543 STATIC int 544 bcm_int_turnaround_hw_init(int unit) 545 { 546 int rv = BCM_E_NONE; 547 int index, turnaround_index, hoplimit_index; 548 int cosq_map_size; 549 bcm_rx_reasons_t reasons, reasons_mask, reasons_all; 550 uint8 int_prio, int_prio_mask; 551 uint32 packet_type, packet_type_mask; 552 bcm_cos_queue_t cosq, cpu_cosq; 553 bcm_rx_chan_t chan_id; 554 int num_cosq = 0; 555 int min_cosq, max_cosq; 556 int i; 557 uint32 max_rx_channels = 0; 558 uint32 num_of_cpu_queues = 0; 559 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 560 561 /* 562 * INT Turnaround COS Queue 563 * 564 * INT Turnaround COSQ will be set to one of the following: 565 * - User configured INT Turnaround COSq, if provided 566 * - The default INT Turnaround COS queue. This is set to the highest queue 567 * available within the queue range assigned to the uC where 568 * the INT Turnaround application is running. 569 */ 570 571 /* Get valid range of COS queues for uC where INT Turnaround is loaded */ 572 min_cosq = 0; 573 num_of_cpu_queues = SOC_CMCS_NUM(unit); 574 575 for (i = 0; i < num_of_cpu_queues; i++) { 576 num_cosq = NUM_CPU_ARM_COSQ(unit, i); 577 if (i == int_turnaround_info->uc_num + 1) { 578 break; 579 } 580 min_cosq += num_cosq; 581 } 582 max_cosq = min_cosq + num_cosq - 1; 583 584 /* Check that there is at least one COS queue assigned to the CMC */ 585 if (max_cosq < min_cosq) { 586 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 587 "ERROR: No INT Turnaround COS Queue available from uC%d\n"), 588 int_turnaround_info->uc_num)); 589 return BCM_E_CONFIG; 590 } 591 592 /* 593 * Assign RX DMA channel to INT Turnaround CPU COS Queue 594 * (This is the RX channel to listen on for INT Turnaround packets). 595 */ 596 #ifdef BCM_CMICX_SUPPORT 597 if (soc_feature(unit, soc_feature_cmicx)) { 598 max_rx_channels = BCM_CMICX_RX_CHANNELS; 599 } 600 #endif /* BCM_CMICX_SUPPORT */ 601 602 chan_id = (max_rx_channels * (SOC_ARM_CMC(unit, int_turnaround_info->uc_num))) + 603 BCM_INT_EAPP_RX_CHANNEL; 604 for (i = max_cosq; i >= min_cosq; i--) { 605 rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id); 606 if (BCM_SUCCESS(rv)) { 607 cpu_cosq = i; /* COSQ found */ 608 break; 609 } 610 } 611 612 if (i < min_cosq) { 613 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 614 "ERROR: INT Turnaround COS Queue minimum uC%d\n"), 615 int_turnaround_info->uc_num)); 616 return BCM_E_RESOURCE; /* Could not find an available COSQ */ 617 } 618 619 /* 620 * Direct INT Turnaround packets to designated RX CPU COS Queue 621 * Reasons: 622 * - bcmRxReasonIntTurnAround 623 * INT TurnAround 624 * - bcmRxReasonIntHopLimit 625 * INT Hop Limit 626 */ 627 628 /* Find available entries in CPU COS queue map table */ 629 turnaround_index = -1; /* COSQ map index for TurnAround */ 630 hoplimit_index = -1; /* COSQ map index for Hop Limit */ 631 BCM_IF_ERROR_RETURN 632 (bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size)); 633 634 for (index = 0; index < cosq_map_size; index++) { 635 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 636 &reasons, &reasons_mask, 637 &int_prio, &int_prio_mask, 638 &packet_type, &packet_type_mask, 639 &cosq); 640 if (rv == BCM_E_NOT_FOUND) { 641 /* Find available indexes for INT Turnaround reason codes */ 642 rv = BCM_E_NONE; 643 if (turnaround_index == -1) { 644 turnaround_index = index; 645 } else { 646 hoplimit_index = index; 647 break; 648 } 649 } 650 if (BCM_FAILURE(rv)) { 651 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 652 "ERROR: INT Turnaround COS mapping uC%d\n"), 653 int_turnaround_info->uc_num)); 654 return rv; 655 } 656 } 657 if ((turnaround_index == -1) || (hoplimit_index == -1)) { 658 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 659 "ERROR: INT Turnaround Index uC%d\n"), 660 int_turnaround_info->uc_num)); 661 return BCM_E_RESOURCE; 662 } 663 664 /* 665 * Map RX reason code to RX CPU COS Queue 666 */ 667 BCM_IF_ERROR_RETURN 668 (bcm_esw_rx_cosq_mapping_reasons_get(unit, &reasons_all)); 669 670 /* INT TurnAround hit */ 671 BCM_RX_REASON_CLEAR_ALL(reasons); 672 BCM_RX_REASON_SET(reasons, bcmRxReasonIntTurnAround); 673 rv = bcm_esw_rx_cosq_mapping_set(unit, turnaround_index, 674 reasons, reasons, 675 0, 0, /* Any priority */ 676 0, 0, /* Any packet type */ 677 cpu_cosq); 678 if (BCM_FAILURE(rv)) { 679 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 680 "ERROR: INT Turnaround index mapping uC%d\n"), 681 int_turnaround_info->uc_num)); 682 return rv; 683 } 684 int_turnaround_info->cosq_turnaround_index = turnaround_index; 685 686 /* INT Hop Limit */ 687 BCM_RX_REASON_CLEAR_ALL(reasons); 688 BCM_RX_REASON_SET(reasons, bcmRxReasonIntHopLimit); 689 rv = bcm_esw_rx_cosq_mapping_set(unit, hoplimit_index, 690 reasons, reasons, 691 0, 0, /* Any priority */ 692 0, 0, /* Any packet type */ 693 cpu_cosq); 694 if (BCM_FAILURE(rv)) { 695 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit, 696 "ERROR: INT Turnaround Hop limit mapping uC%d\n"), 697 int_turnaround_info->uc_num)); 698 return rv; 699 } 700 int_turnaround_info->cosq_hoplimit_index = hoplimit_index; 701 return rv; 702 } 703 704 705 /* Initialize the INT Turnaround app. */ 706 STATIC int 707 _bcm_th3_int_init(int unit) 708 { 709 /* Init the embedded app */ 710 int rv = BCM_E_NONE; 711 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 712 713 int int_turnaround_enable = 0; 714 int_turnaround_enable = soc_property_get(unit, spn_INT_TURNAROUND_ENABLE, 0); 715 716 if (!int_turnaround_enable) { 717 /* Silently return since INT Turnaround is not enabled */ 718 return BCM_E_NONE; 719 } 720 721 if (int_turnaround_info != NULL) { 722 BCM_IF_ERROR_RETURN(_bcm_th3_int_detach(unit)); 723 int_turnaround_info = NULL; 724 } 725 726 _BCM_INT_ALLOC(int_turnaround_info, _bcm_int_turnaround_info_t, 727 sizeof(_bcm_int_turnaround_info_t), "INT TURNAROUND INFO"); 728 if (int_turnaround_info == NULL) { 729 LOG_ERROR(BSL_LS_BCM_INT, (BSL_META_U(unit, 730 "INT TURNAROUND: Failed to allocate memory"))); 731 return BCM_E_MEMORY; 732 } 733 int_global_info[unit] = int_turnaround_info; 734 int_turnaround_info->uc_num = -1; 735 736 /* 737 * Allocate DMA buffer 738 * 739 * DMA buffer will be used to send and receive 'long' messages 740 * between SDK Host and uController (BTE). 741 */ 742 int_turnaround_info->dma_buffer_len = sizeof(shr_int_turnaround_msg_ctrl_init_t); 743 int_turnaround_info->dma_buffer = soc_cm_salloc(unit, int_turnaround_info->dma_buffer_len, 744 "INT Turnaround DMA buffer allocate"); 745 if (!int_turnaround_info->dma_buffer) { 746 BCM_IF_ERROR_RETURN(bcm_int_eapp_detach(unit)); 747 return BCM_E_MEMORY; 748 } 749 sal_memset(int_turnaround_info->dma_buffer, 0, int_turnaround_info->dma_buffer_len); 750 751 rv = bcm_int_eapp_init(unit); 752 if (BCM_FAILURE(rv)) { 753 LOG_ERROR(BSL_LS_BCM_INT, (BSL_META_U(unit, 754 "INT TURNAROUND App Config set uc message communication failed \n"))); 755 return rv; 756 } 757 758 if (int_turnaround_info->uc_num == -1) { 759 /* Could not start INT Turnaround appl */ 760 soc_cm_sfree(unit, int_turnaround_info->dma_buffer); 761 int_turnaround_info->dma_buffer = NULL; 762 763 sal_free(int_turnaround_info); 764 int_turnaround_info = NULL; 765 int_global_info[unit] = NULL; 766 return BCM_E_NONE; 767 } else { 768 rv = bcm_int_turnaround_hw_init(unit); 769 if (BCM_FAILURE(rv)) { 770 LOG_ERROR(BSL_LS_BCM_INT, (BSL_META_U(unit, 771 "INT TURNAROUND App hardware issue failed \n"))); 772 return rv; 773 } 774 } 775 776 return BCM_E_NONE; 777 } 778 779 /* 780 * Function: 781 * _bcm_th3_int_turnaround_config_set 782 * Purpose: 783 * Create a INT Turnaround Configuration informatio 784 * Parameters: 785 * unit - (IN) BCM device number 786 * config_info - (IN) Configuration information 787 * Returns: 788 * BCM_E_XXX - BCM error code. 789 */ 790 STATIC int 791 _bcm_th3_int_turnaround_config_set(int unit, 792 bcm_int_turnaround_config_t *config_info) 793 { 794 int rv = BCM_E_NONE; 795 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 796 797 if (int_turnaround_info == NULL) { 798 return BCM_E_INIT; 799 } 800 801 bcm_int_turnaround_config_t *config_info_node = (&(int_turnaround_config[unit])); 802 sal_memcpy(config_info_node, config_info, 803 sizeof(bcm_int_turnaround_config_t)); 804 805 /* Inform INT TURNAROUND EAPP of the change/addition in/of configuration information */ 806 rv = bcm_int_turnaround_eapp_config_msg(unit, config_info); 807 808 if (BCM_FAILURE(rv)) { 809 LOG_ERROR(BSL_LS_BCM_INT, (BSL_META_U(unit, 810 "INT TURNAROUND App Config set uc message communication failed \n"))); 811 return rv; 812 } 813 814 return BCM_E_NONE; 815 } 816 817 /* 818 * Function: 819 * _bcm_th3_int_turnaround_config_get 820 * Purpose: 821 * Get INT Turnaround configuration information 822 * Parameters: 823 * unit - (IN) BCM device number 824 * config_info - (OUT) Configuration information info 825 * Returns: 826 * BCM_E_XXX - BCM error code. 827 */ 828 STATIC int 829 _bcm_th3_int_turnaround_config_get(int unit, 830 bcm_int_turnaround_config_t *config_info) 831 { 832 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 833 bcm_int_turnaround_config_t *config_info_data = NULL; 834 835 if (int_turnaround_info == NULL) { 836 return BCM_E_INIT; 837 } 838 config_info_data = (bcm_int_turnaround_config_t *)(&(int_turnaround_config[unit])); 839 840 /* Ensure configuration_info is not NULL */ 841 if (config_info == NULL) { 842 return BCM_E_PARAM; 843 } 844 845 /* Get the configuration info */ 846 sal_memcpy(config_info, config_info_data, 847 sizeof(bcm_int_turnaround_config_t)); 848 return (BCM_E_NONE); 849 } 850 851 /* 852 * Function: 853 * _bcm_th3_int_turnaround_stat_get 854 * Purpose: 855 * Get INT Turnaround statistics information data 856 * Parameters: 857 * unit - (IN) BCM device number 858 * stat_data - (OUT) Statistics information data 859 * Returns: 860 * BCM_E_XXX - BCM error code. 861 */ 862 STATIC int 863 _bcm_th3_int_turnaround_stat_get(int unit, 864 bcm_int_turnaround_stat_t *stat_data) 865 { 866 int rv = BCM_E_NONE; 867 _bcm_int_turnaround_info_t *int_turnaround_info = INT_TURNAROUND_INFO_GET(unit); 868 869 if (int_turnaround_info == NULL) { 870 return BCM_E_NONE; 871 } 872 873 /* Ensure stat_data is not NULL */ 874 if (stat_data == NULL) { 875 return BCM_E_PARAM; 876 } 877 878 /* Get the Stat info */ 879 rv = bcm_int_tunraround_eapp_stat_get_msg(unit, stat_data); 880 return rv; 881 } 882 883 int bcm_tomahawk3_int_lock(int unit) 884 { 885 if (mutex[unit] == NULL) { 886 return BCM_E_INIT; 887 } 888 889 sal_mutex_take(mutex[unit], sal_mutex_FOREVER); 890 return BCM_E_NONE; 891 } 892 893 int bcm_tomahawk3_int_unlock(int unit) 894 { 895 if (mutex[unit] == NULL) { 896 return BCM_E_INIT; 897 } 898 899 if (sal_mutex_give(mutex[unit]) != 0) { 900 return BCM_E_INTERNAL; 901 } 902 return BCM_E_NONE; 903 } 904 905 /* Initialize the INT Turnaround app. */ 906 int bcm_tomahawk3_int_init(int unit) 907 { 908 int result = BCM_E_UNAVAIL; 909 /* Create mutex */ 910 if (mutex[unit] == NULL) { 911 mutex[unit] = sal_mutex_create("int.mutex"); 912 if (mutex[unit] == NULL) { 913 return BCM_E_MEMORY; 914 } 915 } 916 917 if (soc_feature(unit, soc_feature_uc_int_turnaround)) { 918 result = _bcm_th3_int_init(unit); 919 } 920 921 /* If init itself fails, there is no point in having the mutex. 922 * Destroy it. 923 */ 924 if (BCM_FAILURE(result)) { 925 sal_mutex_destroy(mutex[unit]); 926 mutex[unit] = NULL; 927 } 928 return result; 929 } 930 931 /* Shut down the INT Turnaround app. */ 932 int bcm_tomahawk3_int_detach(int unit) 933 { 934 int result = BCM_E_UNAVAIL; 935 /* Take lock */ 936 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_lock(unit)); 937 938 if (soc_feature(unit, soc_feature_uc_int_turnaround)) { 939 result = _bcm_th3_int_detach(unit); 940 } 941 942 /* Release lock */ 943 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_unlock(unit)); 944 return result; 945 } 946 947 int bcm_tomahawk3_int_turnaround_config_set(int unit, 948 bcm_int_turnaround_config_t *config_data) 949 { 950 int result = BCM_E_UNAVAIL; 951 /* Take lock */ 952 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_lock(unit)); 953 954 /* INT Turnaround app APIs. */ 955 if (soc_feature(unit, soc_feature_uc_int_turnaround)) { 956 result = _bcm_th3_int_turnaround_config_set(unit, 957 config_data); 958 } 959 960 /* Release lock */ 961 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_unlock(unit)); 962 return result; 963 } 964 965 int bcm_tomahawk3_int_turnaround_config_get(int unit, 966 bcm_int_turnaround_config_t *config_data) 967 { 968 int result = BCM_E_UNAVAIL; 969 /* Take lock */ 970 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_lock(unit)); 971 972 /* INT Turnaround app APIs. */ 973 if (soc_feature(unit, soc_feature_uc_int_turnaround)) { 974 result = _bcm_th3_int_turnaround_config_get(unit, 975 config_data); 976 } 977 978 /* Release lock */ 979 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_unlock(unit)); 980 return result; 981 } 982 983 /* 984 * Function: 985 * bcm_tomahawk3_int_turnaround_stat_get 986 * Purpose: 987 * Get INT Turnaround statistics information data 988 * Parameters: 989 * unit - (IN) BCM device number 990 * stat_data - (OUT) Statistics information data 991 * Returns: 992 * BCM_E_XXX - BCM error code. 993 */ 994 int bcm_tomahawk3_int_turnaround_stat_get(int unit, 995 bcm_int_turnaround_stat_t *stat_data) 996 { 997 int result = BCM_E_UNAVAIL; 998 /* Take lock */ 999 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_lock(unit)); 1000 1001 /* INT Turnaround app APIs. */ 1002 if (soc_feature(unit, soc_feature_uc_int_turnaround)) { 1003 result = _bcm_th3_int_turnaround_stat_get(unit, 1004 stat_data); 1005 } 1006 1007 /* Release lock */ 1008 BCM_IF_ERROR_RETURN(bcm_tomahawk3_int_unlock(unit)); 1009 return result; 1010 } 1011 #else /* INCLUDE_INT and BCM_TOMAHAWK3_SUPPORT */ 1012 int _tomahawk3_int_turnaround_not_empty; 1013 #endif /* INCLUDE_INT and BCM_TOMAHAWK3_SUPPORT*/