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

internal_stack.c (10968B)


      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  * File:    internal_stack.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      _bcm_kt_ptp_hw_init
     13  *      _bcm_ptp_internal_stack_create
     14  */
     15 
     16 #if defined(INCLUDE_PTP)
     17 
     18 #include <soc/defs.h>
     19 #include <soc/drv.h>
     20 
     21 #include <sal/core/dpc.h>
     22 #include <shared/bsl.h>
     23 #include <bcm_int/common/rx.h>
     24 #include <bcm/ptp.h>
     25 #include <bcm_int/common/ptp.h>
     26 #include <bcm/error.h>
     27 #include <bcm_int/common/PTP_feature.h>
     28 
     29 /* Global variables */
     30 /* PTP FW version for feature compatibility check */
     31 uint32 ptp_firmware_version = PTP_UC_MIN_VERSION;
     32 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
     33 
     34 #include <soc/uc_msg.h>
     35 #include <soc/uc_dbg.h>
     36 
     37 
     38 /*
     39  * Function:
     40  *      bcm_kt_ptp_hw_init
     41  * Purpose:
     42  *      Initialize the HW for PTP packet processing.
     43  *      Configure:
     44  *      - FP rules to copy L2, IPv4, and IPv6 PTP traffic to CPU
     45  *      - Assign RX DMA channel to PTP CPU COS Queue
     46  *      - Map RX PTP packets to PTP CPU COS Queue
     47  * Parameters:
     48  *      unit - (IN) Unit number.
     49  * Returns:
     50  *      BCM_E_XXX
     51  * Notes:
     52  */
     53 STATIC int
     54 _bcm_kt_ptp_hw_init(int unit, int uc_num)
     55 {
     56     int rv = BCM_E_NONE;
     57     bcm_rx_chan_t chan_id;
     58     int num_cosq = 0;
     59     int min_cosq, max_cosq, ptp_cosq;
     60     int i;
     61     int rx_channel = 1;  /* For now, PTP is always on uC by itself, so always use Rx channel 1 */
     62 
     63     /*
     64      * PTP COS Queue
     65      *
     66      * - The default PTP COS queue.  This is set to the highest queue
     67      *   available within the queue range assigned to the uC where
     68      *   the PTP application is running.
     69      */
     70     
     71 
     72     /* Get valid range of COS queues for uC where PTP is loaded */
     73     min_cosq = 0;
     74     for (i = 0; i < SOC_CMCS_NUM(unit); i++) {
     75         num_cosq = NUM_CPU_ARM_COSQ(unit, i);
     76         if (i == uc_num + 1) {
     77             break;
     78         }
     79         min_cosq += num_cosq;
     80     }
     81 
     82     max_cosq = min_cosq + num_cosq - 1;
     83 
     84     /* Check that there is at least one COS queue assigned to the CMC */
     85     if (max_cosq < min_cosq) {
     86         LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
     87                      "PTP unable to assign COSQ, none are assigned to FW core.\n")));
     88         return BCM_E_CONFIG;
     89     }
     90 
     91     /* Get PTP COSq soc property */
     92     ptp_cosq = soc_property_get(unit, spn_PTP_COSQ, max_cosq);
     93 
     94     /*
     95      * Assign RX DMA channel to PTP CPU COS Queue
     96      * (This is the RX channel to listen on for PTP packets).
     97      *
     98      * DMA channels (12) are assigned 4 per processor:
     99      * (see /src/bcm/common/rx.c)
    100      *   channels 0..3  --> PCI host
    101      *   channels 4..7  --> uController 0
    102      *   chnanels 8..11 --> uController 1
    103      *
    104      * The uControllers designate the 4 local DMA channels as follows:
    105      *   local channel  0     --> TX
    106      *   local channel  1..3  --> RX
    107      *
    108      * Each uController application needs to use a different
    109      * RX DMA channel to listen on.
    110      */
    111     chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, uc_num))) + rx_channel;
    112 
    113     if (ptp_cosq != max_cosq) 
    114     {
    115        if ((ptp_cosq < min_cosq) || (ptp_cosq > max_cosq)) {
    116         LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    117                  "PTP COSQ %d is out of bounds for FW core [%d - %d].\n"),
    118                  ptp_cosq, min_cosq, max_cosq));
    119 
    120           return BCM_E_RESOURCE;    /* Could not find an available COSQ */
    121        }
    122 
    123        rv = _bcm_common_rx_queue_channel_set(unit, ptp_cosq, chan_id);
    124 
    125        if (!BCM_SUCCESS(rv)) {
    126            LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    127                  "PTP unable to assign COSQ %d.\n"),
    128                  ptp_cosq));
    129 
    130            return rv;
    131        }
    132     }
    133     else
    134     {
    135        for (i = max_cosq; i >= min_cosq; i--) {
    136           rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id);
    137           if (BCM_SUCCESS(rv)) {
    138              break;
    139           }
    140        }
    141 
    142        if (i < min_cosq) {
    143            LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    144                  "PTP unable to assign COSQ from range %d - %d.\n"),
    145                  min_cosq, max_cosq));
    146 
    147            return BCM_E_RESOURCE;    /* Could not find an available COSQ */
    148        }
    149 
    150        ptp_cosq = i;
    151     }
    152 
    153     LOG_VERBOSE(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    154         "1588 COSQ for unit %d is %d chan_id: %d\n"), unit, ptp_cosq, chan_id));
    155 
    156     return rv;
    157 }
    158 
    159 
    160 /*
    161  * Function:
    162  *      _bcm_ptp_internal_stack_create
    163  * Purpose:
    164  *      Create a PTP stack instance
    165  * Parameters:
    166  *      unit - (IN) Unit number.
    167  *      ptp_info - (IN/OUT) Pointer to an PTP Stack Info structure
    168  * Returns:
    169  *      BCM_E_xxx
    170  * Notes:
    171  */
    172 int 
    173 _bcm_ptp_internal_stack_create(
    174     int unit, 
    175     bcm_ptp_stack_info_t *info,
    176     bcm_ptp_stack_id_t ptp_id)
    177 {
    178     _bcm_ptp_info_t *ptp_info_p;
    179     _bcm_ptp_stack_info_t *stack_p;
    180     mos_msg_data_t start_msg; 
    181     int timeout_usec = 1900000;
    182     int result;
    183     int c;
    184     int i;
    185     int rv;
    186 
    187     /* log storage size is the size of the structure without the placeholder */
    188     /* space for debug->buf, plus the real space for it                      */
    189     int log_storage_size = sizeof(_bcm_ptp_internal_stack_log_t) -
    190         sizeof(stack_p->int_state.log->buf) + BCM_PTP_MAX_LOG;
    191 
    192     SET_PTP_INFO;
    193     if (!SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    194         return BCM_E_UNAVAIL;
    195     }
    196 
    197     stack_p = &ptp_info_p->stack_info[ptp_id];
    198 
    199     /* Set up dispatch for internal transport */
    200     stack_p->transport_init = _bcm_ptp_internal_transport_init;
    201     stack_p->tx = _bcm_ptp_internal_tx;
    202     stack_p->tx_completion = _bcm_ptp_internal_tx_completion;
    203     stack_p->rx_free = _bcm_ptp_internal_rx_response_free;
    204     stack_p->transport_terminate = _bcm_ptp_internal_transport_terminate;
    205 
    206     /* allocate space for mboxes */
    207     stack_p->int_state.mboxes = soc_cm_salloc(unit, sizeof(_bcm_ptp_internal_stack_mboxes_t), "ptp msg");
    208 
    209     if (!stack_p->int_state.mboxes) {
    210         return BCM_E_MEMORY;
    211     }
    212 
    213     /* clear state of message mboxes */
    214     stack_p->int_state.mboxes->num_mboxes = soc_htonl(BCM_PTP_MAX_BUFFERS);
    215     stack_p->int_state.mboxes->mbox_size = soc_htonl(sizeof(_bcm_ptp_internal_stack_mbox_t));
    216     stack_p->int_state.mboxes->mbox_offset = soc_htonl((uint8 *)&stack_p->int_state.mboxes->mbox[0] - (uint8 *)stack_p->int_state.mboxes);
    217     stack_p->int_state.mboxes->rfu = soc_htonl(0);
    218 
    219     for (i = 0; i < BCM_PTP_MAX_BUFFERS; ++i) {
    220         stack_p->int_state.mboxes->mbox[i].status = soc_htonl(MBOX_STATUS_EMPTY);
    221         stack_p->int_state.mboxes->mbox[i].clock_num = soc_htonl(0);
    222         stack_p->int_state.mboxes->mbox[i].data_len = soc_htonl(0);
    223         stack_p->int_state.mboxes->mbox[i].rfu_mbox = soc_htonl(0);
    224     }
    225 
    226     /* allocate space for debug log */
    227     stack_p->int_state.log = soc_cm_salloc(unit, log_storage_size, "ptp log");
    228     if (!stack_p->int_state.log) {
    229         soc_cm_sfree(unit, stack_p->int_state.mboxes);
    230         LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    231                      "PTP Failed to allocate shared memory\n")));
    232         return BCM_E_MEMORY;
    233     }
    234 
    235     /* initialize debug */
    236     stack_p->int_state.log->size = soc_htonl(BCM_PTP_MAX_LOG);
    237     stack_p->int_state.log->head = soc_htonl(0);
    238     stack_p->int_state.log_tail = 0;
    239 
    240     /* set up the network-byte-order pointers so that CMICm can access the shared memory */
    241     stack_p->int_state.mbox_ptr = soc_htonl(soc_cm_l2p(unit, (void*)stack_p->int_state.mboxes));
    242     stack_p->int_state.log_ptr = soc_htonl(soc_cm_l2p(unit, (void*)stack_p->int_state.log));
    243 
    244     /* LOG_CLI((BSL_META_U(unit,
    245                            "DEBUG SPACE: %p\n"), (void *)stack_p->int_state.log->buf)); */
    246 
    247     /* flush memory on platforms that need it */
    248     soc_cm_sflush(unit, stack_p, sizeof(_bcm_ptp_stack_info_t));
    249     soc_cm_sflush(unit, stack_p->int_state.mboxes, sizeof(_bcm_ptp_internal_stack_mboxes_t));
    250     soc_cm_sflush(unit, stack_p->int_state.log, log_storage_size);
    251 
    252     rv = BCM_E_UNAVAIL;
    253     for (c = (SOC_INFO(unit).num_ucs - 1); c >= 0; c--) {
    254         LOG_VERBOSE(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    255             "Trying PTP on core %d\n"), c));
    256         SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp,
    257             "Trying PTP on core %d\n", c));
    258         result = soc_cmic_uc_appl_init(unit, c,
    259                                        MOS_MSG_CLASS_1588,
    260                                        timeout_usec,
    261                                        PTP_SDK_VERSION, PTP_UC_MIN_VERSION,
    262                                        &_bcm_ptp_stack_deinit_callback, INT_TO_PTR(ptp_id));
    263         if (SOC_E_NONE == result){
    264             /* uKernel communications started successfully */
    265             SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp,
    266                 "PTP -> uKernel communications started successfully\n"));
    267             soc_cmic_ucdebug_core_communication_status(unit,
    268                 CMIC_UC_DBG_PTP_CORE_COMM_SUCCESS);
    269 
    270             start_msg.s.mclass = MOS_MSG_CLASS_1588;
    271             start_msg.s.subclass = MOS_MSG_SUBCLASS_MBOX_CONFIG;
    272             start_msg.s.len = 0;
    273             start_msg.s.data = bcm_htonl(soc_cm_l2p(unit, (void*)&stack_p->int_state));
    274 
    275             if (BCM_FAILURE(rv = soc_cmic_uc_msg_send(unit, c, &start_msg, timeout_usec))) {
    276                 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp,
    277                     "Error in Initializing PTP application\n"));
    278                 PTP_ERROR_FUNC("soc_cmic_uc_msg_send()");
    279             }
    280             stack_p->int_state.core_num = c;
    281             break;
    282         }
    283         LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
    284                             "No response on core %d\n"), c));
    285         SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtp,
    286                             "No response on core %d\n", c));
    287     }
    288 
    289     if (BCM_FAILURE(rv)) {
    290         return rv;
    291     }
    292 
    293     soc_cmic_ucdebug_core_communication_status(unit,
    294         CMIC_UC_DBG_PTP_STACK_INIT_SUCCESS);
    295 
    296     rv = _bcm_kt_ptp_hw_init(unit, stack_p->int_state.core_num);
    297     if (BCM_FAILURE(rv)) {
    298         return rv;
    299     }
    300 
    301     return rv;
    302 }
    303 
    304 /*
    305  * Function:
    306  *      _bcm_ptp_internal_stack_cleanup
    307  * Purpose:
    308  *      Cleans up internal allocations of an internal stack
    309  * Parameters:
    310  *      unit - (IN) Unit number.
    311  *      ptp_id - (IN) Stack ID
    312  * Returns:
    313  *      BCM_E_xxx
    314  * Notes:
    315  */
    316 int
    317 _bcm_ptp_internal_stack_cleanup(
    318     int unit,
    319     bcm_ptp_stack_id_t ptp_id)
    320 {
    321     _bcm_ptp_stack_info_t *stack_p;
    322 
    323     if (!SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) {
    324         return BCM_E_UNAVAIL;
    325     }
    326 
    327     if (_bcm_common_ptp_info[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
    328         return BCM_E_UNAVAIL;
    329     }
    330 
    331     stack_p = &_bcm_common_ptp_info[unit].stack_info[ptp_id];
    332 
    333     soc_cm_sfree(unit, stack_p->int_state.log);
    334     stack_p->int_state.log = NULL;
    335 
    336     soc_cm_sfree(unit, stack_p->int_state.mboxes);
    337     stack_p->int_state.mboxes = NULL;
    338 
    339     return BCM_E_NONE;
    340 }
    341 
    342 
    343 #endif /* defined(BCM_PTP_INTERNAL_STACK_SUPPORT) */
    344 #endif /* defined(INCLUDE_PTP) */