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

iproc_mbox.c (19024B)


      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  * Purpose: Host <-> M0SSQ communcation protocol
      8  */
      9 #include <sal/core/boot.h>
     10 #include <sal/core/libc.h>
     11 #include <sal/core/sync.h>
     12 #include <shared/alloc.h>
     13 #include <shared/bsl.h>
     14 
     15 #if defined(BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
     16 #include <soc/drv.h>
     17 #include <soc/cm.h>
     18 #include <soc/cmic.h>
     19 #ifdef BCM_CMICX_SUPPORT
     20 #include <shared/cmicfw/iproc_mbox.h>
     21 #include <shared/cmicfw/iproc_fwconfig.h>
     22 
     23 #define soc_iproc_mbox_write(unit, offset, val)    soc_m0ssq_sram_write32(unit, offset, val)
     24 #define soc_iproc_mbox_read(unit, offset)          soc_m0ssq_sram_read32(unit, offset)
     25 
     26 int soc_iproc_mbox_size_get(int unit, int ucnum)  {
     27     return M0SSQ_SHMEM_MBOX_SIZE;
     28 }
     29 
     30 int soc_iproc_mbox_base_get(int unit, int ucnum)  {
     31     if (SOC_IS_HELIX5(unit)) {
     32         return IPROC_M0SSQ_SRAM_BASE_HX5 + M0SSQ_SRAM_FWREG_SIZE + (ucnum * soc_iproc_mbox_size_get(unit, ucnum));
     33     } else {
     34         return IPROC_M0SSQ_SRAM_BASE + M0SSQ_SRAM_FWREG_SIZE + (ucnum * soc_iproc_mbox_size_get(unit, ucnum));
     35     }
     36 }
     37 
     38 void _soc_iproc_fw_config(int unit)
     39 {
     40     SOC_CONTROL(unit)->iproc_mbox_config.max_ucores = MAX_UCORES;
     41     SOC_CONTROL(unit)->iproc_mbox_config.nucores_enabled = MAX_UCORES_ENABLED;
     42 
     43     SOC_CONTROL(unit)->iproc_mbox_config.max_mboxs[0] = U0_MAX_MBOXS;
     44     SOC_CONTROL(unit)->iproc_mbox_config.max_mboxs[1] = U1_MAX_MBOXS;
     45     SOC_CONTROL(unit)->iproc_mbox_config.max_mboxs[2] = U2_MAX_MBOXS;
     46     SOC_CONTROL(unit)->iproc_mbox_config.max_mboxs[3] = U3_MAX_MBOXS;
     47 }
     48 
     49 int _soc_iproc_num_mbox_get(int unit, int ucnum)
     50 {
     51     return SOC_CONTROL(unit)->iproc_mbox_config.max_mboxs[ucnum];
     52 }
     53 
     54 int _soc_iproc_num_ucore_get(int unit)
     55 {
     56     return SOC_CONTROL(unit)->iproc_mbox_config.nucores_enabled;
     57 }
     58 
     59 /*
     60  * Function:
     61  *      soc_iproc_msgintr_handler
     62  * Purpose:
     63  *      Checks the mail box for messages ans call the registered handler.
     64  * Parameters:
     65  *      param - Parameter registered at the time of initialization.
     66  * Returns:
     67  *      SOC_E_NONE on success
     68  * NOTE:
     69  *      soc_iproc_msgintr_handler is added as a timer event handler when NVIC support is not enabled.
     70  */
     71 int soc_iproc_msgintr_handler(int unit, void *param)
     72 {
     73     int id, num_ids = 0, start_id = 0, end_id = 0;
     74     soc_iproc_mbox_info_t *chan;
     75     soc_iproc_mbox_ptr_t *mbox;
     76     soc_control_t   *soc = SOC_CONTROL(unit);
     77     uint32 max_ucores, ucnum;
     78 
     79     max_ucores = _soc_iproc_num_ucore_get(unit);
     80 
     81     for (ucnum = 0; ucnum < max_ucores; ucnum++) {
     82         num_ids = _soc_iproc_num_mbox_get(unit, ucnum);
     83         end_id = start_id + num_ids;
     84         for (id = start_id; id < end_id; id++) {
     85             if (soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].inuse == 0)
     86                 continue;
     87 
     88             chan = &soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX];
     89             mbox = IPROC_MBOX_PTR(chan);
     90 
     91             if (IPROC_MBOX_EMPTY(chan, mbox))
     92                 continue;
     93 
     94             LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "Received iproc mbox %d message\n"),id));
     95             soc->stat.m0_intr++;
     96 
     97             if (soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler != NULL)
     98                 soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler(soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler_param);
     99         }
    100         start_id = end_id;
    101     }
    102 
    103     return SOC_E_NONE;
    104 }
    105 
    106 
    107 /*
    108  * Function:
    109  *      soc_iproc_mbox_exit
    110  * Purpose:
    111  *      Initialize the mail box data structure.
    112  * Parameters:
    113  *      unit - unit number.
    114  * Returns:
    115  *      SOC_E_NONE on success
    116  */
    117 int soc_iproc_mbox_exit(int unit)
    118 {
    119     int id, num_ids = 0, start_id = 0, end_id = 0;
    120     soc_control_t   *soc = SOC_CONTROL(unit);
    121     int ucnum, type;
    122     uint32 max_ucores;
    123 
    124     max_ucores = _soc_iproc_num_ucore_get(unit);
    125 
    126     for (ucnum = 0; ucnum < max_ucores; ucnum++) {
    127         num_ids = _soc_iproc_num_mbox_get(unit, ucnum);
    128         end_id = start_id + num_ids;
    129         for (id = start_id; id < end_id; id++) {
    130             for (type = 0; type < MAX_IPROC_MBOX_TYPES; type++) {
    131                 if (soc->iproc_mbox_info[id][type].lock) {
    132                     sal_mutex_destroy(soc->iproc_mbox_info[id][type].lock);
    133                     soc->iproc_mbox_info[id][type].lock = NULL;
    134                 }
    135                 soc->iproc_mbox_info[id][type].msg_handler = NULL;
    136                 soc->iproc_mbox_info[id][type].msg_handler_param = 0;
    137             }
    138         }
    139         start_id = end_id;
    140     }
    141 
    142     SOC_CONTROL(unit)->iproc_mbox_init_done = 0;
    143 
    144     return SOC_E_NONE;
    145 }
    146 
    147 /*
    148  * Function:
    149  *      soc_iproc_mbox_init
    150  * Purpose:
    151  *      Initialize the mail box data structure.
    152  * Parameters:
    153  *      unit - unit number.
    154  * Returns:
    155  *      SOC_E_NONE on success
    156  */
    157 int soc_iproc_mbox_init(int unit)
    158 {
    159     int id, num_ids = 0, start_id = 0, end_id = 0;
    160     int ucnum, type;
    161     uint32 mbox_base;
    162     uint32 mbox_size, max_mboxs, max_ucores;
    163     char mutex_name[30];
    164     soc_control_t   *soc = SOC_CONTROL(unit);
    165 
    166     if (SOC_CONTROL(unit)->iproc_mbox_init_done) {
    167         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "mbox init already done..skipping it\n")));
    168         return SOC_E_NONE;
    169     }
    170 
    171     max_ucores = _soc_iproc_num_ucore_get(unit);
    172 
    173     for (ucnum = 0; ucnum < max_ucores; ucnum++) {
    174         max_mboxs = _soc_iproc_num_mbox_get(unit, ucnum);
    175         mbox_base = soc_iproc_mbox_base_get(unit, ucnum);
    176         mbox_size = soc_iproc_mbox_size_get(unit, ucnum) / max_mboxs;
    177 
    178         num_ids = max_mboxs;
    179         end_id = start_id + num_ids;
    180         for (id = start_id; id < end_id; id++) {
    181             for (type = 0; type < MAX_IPROC_MBOX_TYPES; type++) {
    182                 soc->iproc_mbox_info[id][type].base = mbox_base;
    183                 soc->iproc_mbox_info[id][type].limit = mbox_base + mbox_size;
    184                 soc->iproc_mbox_info[id][type].unit = unit;
    185                 soc->iproc_mbox_info[id][type].mbox = id;
    186                 soc->iproc_mbox_info[id][type].maxent = mbox_size / 4;
    187                 sal_snprintf(mutex_name, sizeof(mutex_name), "Iproc_Mbox%d-%d-%d", unit, id, type);
    188                 soc->iproc_mbox_info[id][type].lock = sal_mutex_create(mutex_name);
    189                 soc->iproc_mbox_info[id][type].ptr = (soc_iproc_mbox_ptr_t *) (long int)mbox_base;
    190                 soc_iproc_setreg(unit, (uint32)(long int)&soc->iproc_mbox_info[id][type].ptr->head, IPROC_MBOX_START_IDX);
    191                 soc_iproc_setreg(unit, (uint32)(long int)&soc->iproc_mbox_info[id][type].ptr->tail, IPROC_MBOX_START_IDX);
    192 
    193                 soc->iproc_mbox_info[id][type].msg_handler = NULL;
    194                 soc->iproc_mbox_info[id][type].msg_handler_param = 0;
    195                 mbox_base += mbox_size;
    196                 LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "id %d type %s mbox_base 0x%x \n"),
    197                                 id, (type ? "TX" : "RX"), soc->iproc_mbox_info[id][type].base));
    198                 LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "id %d type %s mbox_limit 0x%x \n"),
    199                                 id, (type ? "TX" : "RX"), soc->iproc_mbox_info[id][type].limit));
    200             }
    201         }
    202         start_id = end_id;
    203     }
    204 
    205     max_mboxs = 0;
    206     /* Write the mailbox base and size into SRAM */
    207     for (ucnum = 0; ucnum < max_ucores; ucnum++) {
    208         max_mboxs |= _soc_iproc_num_mbox_get(unit, ucnum) << (ucnum * MAX_IPROC_MBOX_SHIFT);
    209         soc_m0ssq_tcam_write32(unit, ucnum, CPU_ID_OFFSET, ucnum);
    210 
    211         /* To fill device id to enable HELIX5 M0 FW. */
    212         if (SOC_IS_HELIX5(unit)) {
    213             soc_m0ssq_tcam_write32(unit, ucnum, DEVID_ID_OFFSET, CMDEV(unit).dev.dev_id);
    214         }
    215         soc_m0ssq_sram_write32(unit, (U0_MBOX_BASE_OFFSET + (ucnum * 8)), soc_iproc_mbox_base_get(unit, ucnum));
    216         soc_m0ssq_sram_write32(unit, (U0_MBOX_SIZE_OFFSET + (ucnum * 8)), soc_iproc_mbox_size_get(unit, ucnum));
    217     }
    218 
    219     soc_m0ssq_sram_write32(unit, MAX_IPROC_MBOX_PER_CORE_OFFSET, max_mboxs);
    220     soc_m0ssq_sram_write32(unit, MBOX_INTERRUPT_MODE_OFFSET, MBOX_INTERRUPT_ENABLE);
    221 
    222     SOC_CONTROL(unit)->iproc_mbox_init_done = 1;
    223 
    224     return SOC_E_NONE;
    225 }
    226 
    227 /*
    228  * Function:
    229  *      soc_iproc_mbox_alloc
    230  * Purpose:
    231  *      Allocate mail box id.
    232  * Parameters:
    233  *      unit - unit number.
    234  *      app_id - Application identifier
    235  * Returns:
    236  *      SOC_E_NONE on success
    237  *      IPROC_MBOX_ERR_xxx on Error
    238  */
    239 int soc_iproc_mbox_alloc(int unit, int app_id)
    240 {
    241     int type, ucnum, id;
    242     soc_control_t   *soc = SOC_CONTROL(unit);
    243 
    244     ucnum = UC_APPID_TO_UCNUM(app_id);
    245     id = UC_APPID_TO_MBOX(app_id);
    246 
    247     if ((ucnum >= MAX_UCORES) || (id >= NUM_MBOX_PER_UCORE)){
    248         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "App id 0x%x Error\n"), app_id));
    249         return IPROC_MBOX_ERR_INVPARAM;
    250     }
    251 
    252     id = id + (ucnum * NUM_MBOX_PER_UCORE);
    253 
    254     LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "iproc mbox id %d\n"), id));
    255 
    256     for (type = 0; type < MAX_IPROC_MBOX_TYPES; type++) {
    257         if (soc->iproc_mbox_info[id][type].inuse) {
    258             LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "mbox %d inuse\n"),id));
    259             return IPROC_MBOX_ERR_ALLOC;
    260         }
    261     }
    262 
    263     for (type = 0; type < MAX_IPROC_MBOX_TYPES; type++) {
    264         soc->iproc_mbox_info[id][type].inuse = 1;
    265     }
    266 
    267     return id;
    268 }
    269 
    270 /*
    271  * Function:
    272  *      soc_iproc_mbox_free
    273  * Purpose:
    274  *      Free mail box id.
    275  * Parameters:
    276  *      unit - unit number.
    277  *      mbox_id - mail box identifier
    278  * Returns:
    279  *      SOC_E_NONE on success
    280  *      IPROC_MBOX_ERR_xxx on Error
    281  */
    282 int soc_iproc_mbox_free(int unit, int mbox_id)
    283 {
    284     int type;
    285     soc_control_t   *soc = SOC_CONTROL(unit);
    286 
    287     LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "iproc mbox id %d\n"), mbox_id));
    288 
    289     if (mbox_id >= MAX_IPROC_MBOXS) {
    290         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Mbox id 0x%x Error\n"), mbox_id));
    291         return IPROC_MBOX_ERR_INVPARAM;
    292     }
    293 
    294     for (type = 0; type < MAX_IPROC_MBOX_TYPES; type++) {
    295         soc->iproc_mbox_info[mbox_id][type].inuse = 0;
    296     }
    297 
    298     return SOC_E_NONE;
    299 }
    300 
    301 /*
    302  * Function:
    303  *      soc_iproc_mbox_handler_register
    304  * Purpose:
    305  *      Register callback function to handle RX messages.
    306  * Parameters:
    307  *      unit - unit number.
    308  *      id - mailbox identifier
    309  *      hndlr - callback function to be called
    310  *      param - parameter to be passed to the callback function
    311  * Returns:
    312  *      SOC_E_NONE on success
    313  *      IPROC_MBOX_ERR_xxx on Error
    314  */
    315 int soc_iproc_mbox_handler_register(int unit, int id, soc_iproc_msg_hndlr_t hndlr, void *param)
    316 {
    317     soc_control_t   *soc = SOC_CONTROL(unit);
    318 
    319     if (id < MAX_IPROC_MBOXS) {
    320         soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler = hndlr;
    321         soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler_param = param;
    322     } else {
    323         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Invalid Mbox id 0x%x \n"),id));
    324         return IPROC_MBOX_ERR_INVPARAM;
    325     }
    326 
    327     return SOC_E_NONE;
    328 }
    329 
    330 /*
    331  * Function:
    332  *      soc_iproc_mbox_handler_unregister
    333  * Purpose:
    334  *      Unregister Rx mailbox callback function.
    335  * Parameters:
    336  *      unit - unit number.
    337  *      id - mailbox identifier
    338  * Returns:
    339  *      SOC_E_NONE on success
    340  *      IPROC_MBOX_ERR_xxx on Error
    341  */
    342 int soc_iproc_mbox_handler_unregister(int unit, int id)
    343 {
    344     soc_control_t   *soc = SOC_CONTROL(unit);
    345 
    346     if (id < MAX_IPROC_MBOXS) {
    347         soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler = NULL;
    348         soc->iproc_mbox_info[id][IPROC_MBOX_TYPE_RX].msg_handler_param = 0;
    349     } else {
    350         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Invalid Mbox id %d \n"),id));
    351         return IPROC_MBOX_ERR_INVPARAM;
    352     }
    353 
    354     return SOC_E_NONE;
    355 }
    356 
    357 /*
    358  * Function:
    359  *      soc_iproc_data_send_nowait
    360  * Purpose:
    361  *      Send message using iproc mailbox.
    362  * Parameters:
    363  *      chan - pointer to tx mailbox
    364  *      msg - pointer to the message to be sent
    365  * Returns:
    366  *      SOC_E_NONE on success
    367  *      IPROC_MBOX_ERR_xxx on Error
    368  */
    369 int soc_iproc_data_send_nowait(soc_iproc_mbox_info_t *chan, soc_iproc_mbox_msg_t *msg)
    370 {
    371     soc_iproc_mbox_ptr_t *mboxptr;
    372     uint32 *src, *dst;
    373     int retval, unit;
    374     uint32 sidx, didx, nentries;
    375     soc_control_t   *soc;
    376 
    377     if (chan == NULL) {
    378         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META("Mbox info pointer is NULL \n")));
    379         return IPROC_MBOX_ERR_INVPARAM;
    380     }
    381 
    382     unit = chan->unit;
    383     soc = SOC_CONTROL(unit);
    384     mboxptr = IPROC_MBOX_PTR(chan);
    385     LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "Base: 0x%x, Head: %d, Tail: %d Sz: %d Id: %d\n"),
    386          IPROC_MBOX_BASE(chan), IPROC_MBOX_HEAD(chan, mboxptr), IPROC_MBOX_TAIL(chan, mboxptr),
    387          msg->size, msg->id));
    388 
    389     RESOURCE_LOCK(chan->lock, LOCK_FOREVER);
    390     if (IPROC_MBOX_FULL(chan, mboxptr, IPROC_MSG_SIZE(msg))) {
    391         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Mbox 0x%x FULL \n"), IPROC_MBOX_BASE(chan)));
    392         retval = IPROC_MBOX_ERR_FULL;
    393         goto errexit;
    394     }
    395 
    396     nentries = msg->size + IPROC_MSG_HDRSZ;
    397     src = (uint32 *)msg;
    398     dst = (uint32 *)mboxptr;
    399     sidx = 0;
    400     didx = IPROC_MBOX_TAIL(chan, mboxptr);
    401     while (sidx < nentries) {
    402         soc_iproc_mbox_write(unit, ((unsigned long)&dst[didx] - soc_iproc_sram_membase_get(unit)), src[sidx]);
    403         didx++;
    404         sidx++;
    405         if (didx == IPROC_MBOX_MAX_ENT(chan)) {
    406             didx = IPROC_MBOX_START_IDX;
    407         }
    408     }
    409 
    410     soc->stat.m0_msg++;
    411 
    412     MOVE_IPROC_MBOX_TAIL(chan, mboxptr, nentries);
    413     RESOURCE_UNLOCK(chan->lock);
    414     return IPROC_MSG_SUCCESS;
    415 
    416 errexit:
    417     RESOURCE_UNLOCK(chan->lock);
    418     return retval;
    419 }
    420 
    421 /*
    422  * Function:
    423  *      soc_iproc_data_recv
    424  * Purpose:
    425  *      Receive message using iproc mailbox.
    426  * Parameters:
    427  *      chan - pointer to rx mailbox
    428  *      msg - pointer to the message received
    429  * Returns:
    430  *      0 on success
    431  *      IPROC_MBOX_ERR_xxx on Error
    432  */
    433 int soc_iproc_data_recv(soc_iproc_mbox_info_t *chan, soc_iproc_mbox_msg_t **msg)
    434 {
    435     soc_iproc_mbox_ptr_t *mboxptr;
    436     soc_iproc_mbox_msg_t hdr;
    437     uint32 *src, *dst;
    438     int retval, unit;
    439     uint32 sidx, didx, nentries, cmdhead;
    440     soc_control_t   *soc;
    441 
    442     if (chan == NULL) {
    443         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META("Mbox info pointer is NULL \n")));
    444         return IPROC_MBOX_ERR_INVPARAM;
    445     }
    446 
    447     unit = chan->unit;
    448     soc = SOC_CONTROL(unit);
    449     mboxptr = IPROC_MBOX_PTR(chan);
    450 
    451     RESOURCE_LOCK(chan->lock, LOCK_FOREVER);
    452     /* Check mbox is empty */
    453     if (IPROC_MBOX_EMPTY(chan, mboxptr)) {
    454         LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "Mbox %d EMPTY \n"),chan->mbox));
    455         retval = IPROC_MBOX_ERR_EMPTY;
    456         goto errexit;
    457     }
    458 
    459     src = (uint32 *)mboxptr;
    460     dst = (uint32 *)&hdr;
    461     /* Copy message Header */
    462     nentries = IPROC_MSG_HDRSZ;
    463     cmdhead = sidx = IPROC_MBOX_HEAD(chan, mboxptr);
    464     didx = 0;
    465     while (didx < nentries) {
    466         dst[didx] = soc_iproc_mbox_read(unit, ((unsigned long)&src[sidx] - soc_iproc_sram_membase_get(unit)));
    467         didx++;
    468         sidx++;
    469         if (sidx == IPROC_MBOX_MAX_ENT(chan)) {
    470             sidx = IPROC_MBOX_START_IDX;
    471         }
    472     }
    473     *msg = soc_iproc_alloc((hdr.size + IPROC_MSG_HDRSZ) * sizeof(uint32));
    474     if (*msg == NULL) {
    475         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Mbox %d message alloc failed \n"),chan->mbox));
    476         retval = IPROC_MBOX_ERR_INTERNAL;
    477         goto errexit;
    478     }
    479     soc_iproc_memcpy(*msg, &hdr, (IPROC_MSG_HDRSZ * sizeof(uint32)));
    480 
    481     dst = (uint32 *) (*msg);
    482     didx = IPROC_MSG_HDRSZ;
    483     /* Copy message payload */
    484     nentries += hdr.size;
    485     while (didx < nentries) {
    486         dst[didx] = soc_iproc_mbox_read(unit, ((unsigned long)&src[sidx]- soc_iproc_sram_membase_get(unit)));
    487         didx++;
    488         sidx++;
    489         if (sidx == IPROC_MBOX_MAX_ENT(chan)) {
    490             sidx = IPROC_MBOX_START_IDX;
    491         }
    492     }
    493 
    494     soc->stat.m0_resp++;
    495 
    496     MOVE_IPROC_MBOX_HEAD(chan, mboxptr, nentries);
    497     RESOURCE_UNLOCK(chan->lock);
    498     return cmdhead;
    499 
    500 errexit:
    501     RESOURCE_UNLOCK(chan->lock);
    502     return retval;
    503 }
    504 
    505 /*
    506  * Function:
    507  *      soc_iproc_data_send_wait
    508  * Purpose:
    509  *      Send message using iproc mailbox and wait for the response from M0.
    510  * Parameters:
    511  *      chan - pointer to tx mailbox
    512  *      msg - pointer to the message to be sent
    513  *      resp - pointer to the response to be received
    514  * Returns:
    515  *      0 on success
    516  *      IPROC_MBOX_ERR_xxx on Error
    517  */
    518 int soc_iproc_data_send_wait(soc_iproc_mbox_info_t *chan, soc_iproc_mbox_msg_t *cmd, soc_iproc_mbox_msg_t *resp)
    519 {
    520     soc_iproc_mbox_ptr_t *mboxptr;
    521     uint32 *src, *dst;
    522     int retval, unit;
    523     uint32 nentries, sidx, didx, cmdidx;
    524     int count = IPROC_MBOX_READ_RETRY_COUNT;
    525     soc_control_t   *soc;
    526 
    527     if (chan == NULL) {
    528         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META("Mbox info pointer is NULL \n")));
    529         return IPROC_MBOX_ERR_INVPARAM;
    530     }
    531 
    532     unit = chan->unit;
    533     soc = SOC_CONTROL(unit);
    534     mboxptr = IPROC_MBOX_PTR(chan);
    535     RESOURCE_LOCK(chan->lock, LOCK_FOREVER);
    536     LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "Base: 0x%x, Head: %d, Tail: %d Sz: %d Id: %d\n"),
    537          IPROC_MBOX_BASE(chan), IPROC_MBOX_HEAD(chan, mboxptr), IPROC_MBOX_TAIL(chan, mboxptr),
    538          cmd->size, cmd->id));
    539 
    540     if (IPROC_MBOX_FULL(chan, mboxptr, IPROC_MSG_SIZE(cmd))) {
    541         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Mbox 0x%x FULL \n"), IPROC_MBOX_BASE(chan)));
    542         retval = IPROC_MBOX_ERR_FULL;
    543         goto errexit;
    544     }
    545 
    546     nentries = cmd->size + IPROC_MSG_HDRSZ;
    547     src = (uint32 *)cmd;
    548     dst = (uint32 *)mboxptr;
    549     sidx = 0;
    550     didx = cmdidx = IPROC_MBOX_TAIL(chan, mboxptr);
    551 
    552     while (sidx < nentries) {
    553         soc_iproc_mbox_write(unit, ((unsigned long)&dst[didx] - soc_iproc_sram_membase_get(unit)), src[sidx]);
    554         didx++;
    555         sidx++;
    556         if (didx == IPROC_MBOX_MAX_ENT(chan)) {
    557             didx = IPROC_MBOX_START_IDX;
    558         }
    559     }
    560 
    561     soc->stat.m0_msg++;
    562     MOVE_IPROC_MBOX_TAIL(chan, mboxptr, nentries);
    563 
    564     /* poll for response */
    565     src = (uint32 *)mboxptr;
    566     dst = (uint32 *)resp;
    567     while (count) {
    568         if ((soc_iproc_mbox_read(unit, (unsigned long)&src[cmdidx] - soc_iproc_sram_membase_get(unit)) & IPROC_RESP_READY) != 0) {
    569             break;
    570         }
    571         sal_usleep(IPROC_MBOX_SLEEP_DELAY);
    572         count--;
    573     }
    574 
    575     if (!count) {
    576         LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "No response for msg %d\n"), cmd->id));
    577         retval = IPROC_MBOX_ERR_INTERNAL;
    578         goto errexit;
    579     }
    580     sidx = cmdidx;
    581     didx = 0;
    582     while (didx < nentries) {
    583         dst[didx] = soc_iproc_mbox_read(unit, (unsigned long)&src[sidx] - soc_iproc_sram_membase_get(unit));
    584         didx++;
    585         sidx++;
    586         if (sidx == IPROC_MBOX_MAX_ENT(chan)) {
    587             sidx = IPROC_MBOX_START_IDX;
    588         }
    589     }
    590 
    591     soc->stat.m0_resp++;
    592 
    593     RESOURCE_UNLOCK(chan->lock);
    594     return IPROC_MSG_SUCCESS;
    595 
    596 errexit:
    597     RESOURCE_UNLOCK(chan->lock);
    598     return retval;
    599 }
    600 #endif /* BCM_CMICX_SUPPORT */
    601 #endif /* BCM_ESW_SUPPORT */