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