openbcm

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

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