txbeacon.c (17200B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * This program is the proprietary software of Broadcom Corporation 9 * and/or its licensors, and may only be used, duplicated, modified 10 * or distributed pursuant to the terms and conditions of a separate, 11 * written license agreement executed between you and Broadcom 12 * (an "Authorized License"). Except as set forth in an Authorized 13 * License, Broadcom grants no license (express or implied), right 14 * to use, or waiver of any kind with respect to the Software, and 15 * Broadcom expressly reserves all rights in and to the Software and 16 * all intellectual property rights therein. IF YOU HAVE NO AUTHORIZED 17 * LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, 18 * AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE ALL USE 19 * OF THE SOFTWARE. 20 * 21 * Except as expressly set forth in the Authorized License, 22 * 23 * 1. This program, including its structure, sequence and organization, 24 * constitutes the valuable trade secrets of Broadcom, and you shall use 25 * all reasonable efforts to protect the confidentiality thereof, and 26 * to use this information only in connection with your use of Broadcom 27 * integrated circuit products. 28 * 29 * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED 30 * "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, 31 * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, 32 * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY 33 * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, 34 * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, 35 * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING 37 * OUT OF USE OR PERFORMANCE OF THE SOFTWARE. 38 * 39 * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM 40 * OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, 41 * INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY 42 * RELATING TO YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF 43 * BROADCOM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR (ii) 44 * ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE 45 * ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE LIMITATIONS SHALL 46 * APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED 47 * REMEDY. 48 */ 49 50 #include <soc/cm.h> 51 #include <soc/debug.h> 52 #include <soc/drv.h> 53 #include <soc/uc_msg.h> 54 #include <soc/shared/mos_msg_common.h> 55 #include <shared/bsl.h> 56 #include <bcm_int/control.h> 57 #include <bcm/error.h> 58 59 #include <bcm/txbeacon.h> 60 61 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 62 63 /* Version of the SDK-side app code */ 64 #define TXBEACON_SDK_VERSION 0x01000000 65 #define TXBEACON_UK_MIN_VERSION 0x01000000 66 67 68 /* 69 * Function: 70 * _bcm_esw_txbeacon_hton 71 * Purpose: 72 * Internal routine to convert txbeacon area endianness 73 * Parameters: 74 * host - pointer to host struct 75 * net - pointer to net (uC) struct 76 * Returns: 77 * nothing 78 * Notes: 79 */ 80 81 void 82 _bcm_esw_txbeacon_hton(bcm_txbeacon_t *host, bcm_txbeacon_t *net) 83 { 84 net->flags = soc_htonl(host->flags); 85 net->len = soc_htons(host->len); 86 net->maxlen = soc_htons(host->maxlen); 87 net->pkt_id = soc_htonl(host->pkt_id); 88 net->port = soc_htons(host->port); 89 net->interval = soc_htons(host->interval); 90 net->count = soc_htons(host->count); 91 } 92 93 /* 94 * Function: 95 * _bcm_esw_txbeacon_ntoh 96 * Purpose: 97 * Internal routine to convert txbeacon area endianness 98 * Parameters: 99 * host - pointer to host struct 100 * net - pointer to net (uC) struct 101 * Returns: 102 * nothing 103 * Notes: 104 */ 105 106 void 107 _bcm_esw_txbeacon_ntoh(bcm_txbeacon_t *net, bcm_txbeacon_t *host) 108 { 109 host->flags = soc_ntohl(net->flags); 110 host->len = soc_ntohs(net->len); 111 host->maxlen = soc_ntohs(net->maxlen); 112 host->pkt_id = soc_ntohl(net->pkt_id); 113 host->port = soc_ntohs(net->port); 114 host->interval = soc_ntohs(net->interval); 115 host->count = soc_ntohs(net->count); 116 } 117 #endif 118 119 /* 120 * Function: 121 * bcm_esw_txbeacon_init 122 * Purpose: 123 * Init routine for TX beacon 124 * Parameters: 125 * unit - for what unit is this being set up 126 * uC - Microcontroller to handle TX beacons 127 * Returns: 128 * BCM_E_XXX 129 * Notes: 130 */ 131 132 int 133 bcm_esw_txbeacon_init(int unit, int uC) 134 { 135 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 136 soc_control_t *soc = SOC_CONTROL(unit); 137 138 if ( (!soc_feature(unit, soc_feature_cmicm)) && 139 (!soc_feature(unit, soc_feature_cmicx)) ) { 140 return (BCM_E_UNAVAIL); 141 } 142 143 soc->txbeacon_msg_timeout = 144 soc_property_get(unit, spn_UC_MSG_TX_BEACON_TIMEOUT, 200000000); 145 146 /* Send the init msg to the uC and wait for an "APPL ready" 147 message */ 148 if (soc_cmic_uc_appl_init(unit, uC, MOS_MSG_CLASS_PKT_BCN, 149 soc->txbeacon_msg_timeout, 150 TXBEACON_SDK_VERSION, 151 TXBEACON_UK_MIN_VERSION, 152 NULL, NULL) != SOC_E_NONE) { 153 return (BCM_E_UNAVAIL); 154 } 155 156 soc->txbeacon_uC = uC; 157 soc->txbeacon_init = 1; 158 159 LOG_CLI((BSL_META_U(unit, 160 "txbeacon ready\n"))); 161 162 return (BCM_E_NONE); 163 164 #else 165 return (BCM_E_UNAVAIL); 166 167 #endif 168 } 169 170 /* 171 * Function: 172 * bcm_esw_txbeacon_pkt_setup 173 * Purpose: 174 * Add a packet for TX beacon 175 * Parameters: 176 * unit - for what unit is this being set up 177 * txbeacon - pkt beacon info 178 * Returns: 179 * BCM_E_XXX 180 * Notes: 181 */ 182 183 int 184 bcm_esw_txbeacon_pkt_setup( 185 int unit, 186 bcm_txbeacon_t *txbeacon) 187 { 188 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 189 190 soc_control_t *soc = SOC_CONTROL(unit); 191 soc_info_t *si = &SOC_INFO(unit); 192 mos_msg_data_t send, rcv; 193 int rc = BCM_E_NONE; 194 char *dma_mem; 195 196 if ( (!soc_feature(unit, soc_feature_cmicm)) && 197 (!soc_feature(unit, soc_feature_cmicx)) ) { 198 return (BCM_E_UNAVAIL); 199 } 200 201 if (soc->txbeacon_init == 0) { 202 return (BCM_E_INIT); 203 } 204 205 if (txbeacon->port >= SOC_MAX_NUM_PORTS) { 206 return (BCM_E_PARAM); 207 } 208 209 /* Make a dma-able copy */ 210 dma_mem = soc_cm_salloc(unit, 211 MOS_MSG_DMA_LEN(sizeof(bcm_txbeacon_t) + 212 txbeacon->len), 213 "txbeacon copy"); 214 if (dma_mem == NULL) { 215 return (BCM_E_MEMORY); 216 } 217 _bcm_esw_txbeacon_hton(txbeacon, (bcm_txbeacon_t *) dma_mem); 218 sal_memcpy(dma_mem + sizeof(bcm_txbeacon_t), txbeacon->pkt_data, txbeacon->len); 219 soc_cm_sflush(unit, dma_mem, sizeof(bcm_txbeacon_t) + txbeacon->len); 220 221 send.s.mclass = MOS_MSG_CLASS_PKT_BCN; 222 send.s.subclass = MOS_MSG_SUBCLASS_PKT_BCN_CONFIG; 223 /* Cheat and use the len for the queue num */ 224 send.s.len = soc_htons(si->port_cosq_base[txbeacon->port]); 225 send.s.data = soc_htonl(soc_cm_l2p(unit, dma_mem)); 226 227 rcv.s.mclass = MOS_MSG_CLASS_PKT_BCN; 228 229 if ((soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, 230 &send, &rcv, 231 soc->txbeacon_msg_timeout) != 232 SOC_E_NONE) || 233 (rcv.s.data != 0)) { 234 rc = BCM_E_FAIL; 235 } 236 237 soc_cm_sfree(unit, dma_mem); 238 239 return(rc); 240 241 #else 242 return (BCM_E_UNAVAIL); 243 244 #endif 245 } 246 247 /* 248 * Function: 249 * bcm_esw_txbeacon_destroy 250 * Purpose: 251 * Remove this packet from the list 252 * Parameters: 253 * unit - for what unit is this being set up 254 * pkt_id - ID of packet to destroy 255 * Returns: 256 * BCM_E_XXX 257 * Notes: 258 */ 259 260 int bcm_esw_txbeacon_destroy( 261 int unit, 262 bcm_txbeacon_pkt_id_t pkt_id) { 263 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 264 265 soc_control_t *soc = SOC_CONTROL(unit); 266 mos_msg_data_t send, rcv; 267 268 if ( (!soc_feature(unit, soc_feature_cmicm)) && 269 (!soc_feature(unit, soc_feature_cmicx)) ) { 270 return (BCM_E_UNAVAIL); 271 } 272 273 if (soc->txbeacon_init == 0) { 274 return (BCM_E_INIT); 275 } 276 277 send.s.mclass = MOS_MSG_CLASS_PKT_BCN; 278 send.s.subclass = MOS_MSG_SUBCLASS_PKT_BCN_DESTROY; 279 send.s.len = soc_htons(4); 280 send.s.data = soc_htonl(pkt_id); 281 282 if ((soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, &send, &rcv, 283 soc->txbeacon_msg_timeout) != SOC_E_NONE) || 284 (rcv.s.data != 0)) { 285 return(BCM_E_FAIL); 286 } 287 288 return(BCM_E_NONE); 289 290 #else 291 return (BCM_E_UNAVAIL); 292 293 #endif 294 } 295 296 /* 297 * Function: 298 * bcm_esw_txbeacon_pkt_get 299 * Purpose: 300 * Lookup packet beacon info structure 301 * Parameters: 302 * unit - for what unit is this being set up 303 * txbeacon - pkt beacon info. Should have the pkt_id, pkt_ptr, 304 * and maxlen fields set. 305 * Returns: 306 * BCM_E_XXX 307 * Notes: 308 * Find the packet with the minimum packt ID which is greater 309 * than or equal to the pkt_id in the txbeacon into. This can 310 * be used in a loop to recover all of the packets by starting 311 * with zero and then incrementing the returned pkt_id until a 312 * zero pkt_id is returned. 313 * 314 * The txbeacon info must be filled in with the pkt_id, and a 315 * pkt_pointer. Up to maxlen bytes are copied into the 316 * pkt_pointer. 317 */ 318 319 int bcm_esw_txbeacon_pkt_get( 320 int unit, 321 bcm_txbeacon_t *txbeacon) { 322 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 323 324 uint8 *dma_mem = NULL; 325 soc_control_t *soc = SOC_CONTROL(unit); 326 mos_msg_data_t send, rcv; 327 uint8 * pkt_data = txbeacon->pkt_data; 328 329 int rc = BCM_E_NONE; 330 int maxlen = txbeacon->maxlen; 331 int size = 0; 332 333 if ( (!soc_feature(unit, soc_feature_cmicm)) && 334 (!soc_feature(unit, soc_feature_cmicx)) ) { 335 return (BCM_E_UNAVAIL); 336 } 337 338 if (soc->txbeacon_init == 0) { 339 return (BCM_E_INIT); 340 } 341 342 /* Get a dma-able region and copy the pkt data in*/ 343 size = MOS_MSG_DMA_LEN(sizeof(bcm_txbeacon_t) + maxlen); 344 dma_mem = soc_cm_salloc(unit, size, "dma"); 345 if (dma_mem == NULL) { 346 return (BCM_E_MEMORY); 347 } 348 349 _bcm_esw_txbeacon_hton(txbeacon, (bcm_txbeacon_t *) dma_mem); 350 soc_cm_sflush(unit, dma_mem, sizeof(bcm_txbeacon_t)); 351 soc_cm_sinval(unit, dma_mem, size); 352 353 send.s.mclass = MOS_MSG_CLASS_PKT_BCN; 354 send.s.subclass = MOS_MSG_SUBCLASS_PKT_BCN_GET; 355 send.s.len = soc_htons(sizeof(bcm_txbeacon_t)); 356 send.s.data = soc_htonl(soc_cm_l2p(unit, dma_mem)); 357 358 rcv.s.mclass = MOS_MSG_CLASS_PKT_BCN; 359 360 rc = soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, &send, &rcv, 361 soc->txbeacon_msg_timeout); 362 if (rc == SOC_E_NONE) { 363 /* Copy the data back out to the user area */ 364 _bcm_esw_txbeacon_ntoh((bcm_txbeacon_t *) dma_mem, txbeacon); 365 txbeacon->pkt_data = pkt_data; /* Restore data ptr */ 366 sal_memcpy(pkt_data, dma_mem + sizeof(bcm_txbeacon_t), 367 (maxlen > txbeacon->len) ? txbeacon->len : maxlen); 368 } 369 370 soc_cm_sfree(unit, dma_mem); 371 372 return(rc); 373 374 #else 375 return (BCM_E_UNAVAIL); 376 377 #endif 378 } 379 380 /* 381 * Function: 382 * bcm_esw_txbeacon_start 383 * Purpose: 384 * Start beacon for this packet or all 385 * Parameters: 386 * unit - for what unit is this being set up 387 * pkt_id - ID of packet to start or zero for all 388 * Returns: 389 * BCM_E_XXX 390 * Notes: 391 */ 392 393 int bcm_esw_txbeacon_start( 394 int unit, 395 bcm_txbeacon_pkt_id_t pkt_id) { 396 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 397 398 mos_msg_data_t send, rcv; 399 400 soc_control_t *soc = SOC_CONTROL(unit); 401 402 if ( (!soc_feature(unit, soc_feature_cmicm)) && 403 (!soc_feature(unit, soc_feature_cmicx)) ) { 404 return (BCM_E_UNAVAIL); 405 } 406 407 if (soc->txbeacon_init == 0) { 408 return BCM_E_INIT; 409 } 410 411 send.s.mclass = MOS_MSG_CLASS_PKT_BCN; 412 send.s.subclass = MOS_MSG_SUBCLASS_PKT_BCN_START; 413 send.s.len = soc_htons(4); 414 send.s.data = soc_htonl(pkt_id); 415 416 rcv.s.mclass = MOS_MSG_CLASS_PKT_BCN; 417 418 if ((soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, &send, &rcv, 419 soc->txbeacon_msg_timeout) != SOC_E_NONE) || 420 (rcv.s.data != 0)) { 421 return(BCM_E_FAIL); 422 } 423 424 return(BCM_E_NONE); 425 426 #else 427 return (BCM_E_UNAVAIL); 428 429 #endif 430 } 431 432 /* 433 * Function: 434 * bcm_esw_txbeacon_stop 435 * Purpose: 436 * Stop the packet beacon 437 * Parameters: 438 * unit - for what unit is this being set up 439 * pkt_id - ID of packet to stop or zero for all 440 * Returns: 441 * BCM_E_XXX 442 * Notes: 443 */ 444 445 int bcm_esw_txbeacon_stop( 446 int unit, 447 bcm_txbeacon_pkt_id_t pkt_id) { 448 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 449 450 mos_msg_data_t send, rcv; 451 452 soc_control_t *soc = SOC_CONTROL(unit); 453 454 if ( (!soc_feature(unit, soc_feature_cmicm)) && 455 (!soc_feature(unit, soc_feature_cmicx)) ) { 456 return (BCM_E_UNAVAIL); 457 } 458 459 if (soc->txbeacon_init == 0) { 460 return BCM_E_INIT; 461 } 462 463 send.s.mclass = MOS_MSG_CLASS_PKT_BCN; 464 send.s.subclass = MOS_MSG_SUBCLASS_PKT_BCN_STOP; 465 send.s.len = soc_htons(4); 466 send.s.data = soc_htonl(pkt_id); 467 468 rcv.s.mclass = MOS_MSG_CLASS_PKT_BCN; 469 470 if ((soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, &send, &rcv, 471 soc->txbeacon_msg_timeout) != SOC_E_NONE) || 472 (rcv.s.data != 0)) { 473 return(BCM_E_FAIL); 474 } 475 476 return(BCM_E_NONE); 477 478 #else 479 return (BCM_E_UNAVAIL); 480 481 #endif 482 } 483 484 /* 485 * Function: 486 * bcm_esw_txbeacon_traverse 487 * Purpose: 488 * Traverse the tx beacon packets 489 * Parameters: 490 * unit - for what unit is this being set up 491 * txbeacon_traverse_cb 492 * Returns: 493 * BCM_E_XXX 494 * Notes: 495 */ 496 497 int 498 bcm_esw_txbeacon_traverse( 499 int unit, 500 bcm_txbeacon_traverse_cb_t trav_fn, 501 void *user_data) 502 { 503 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT) 504 505 soc_control_t *soc = SOC_CONTROL(unit); 506 mos_msg_data_t send, rcv; 507 bcm_txbeacon_pkt_id_t pkt_id = 0; 508 int rc = BCM_E_NONE; 509 bcm_txbeacon_t *txb; 510 int size; 511 bcm_txbeacon_t *pkt; 512 513 if ( (!soc_feature(unit, soc_feature_cmicm)) && 514 (!soc_feature(unit, soc_feature_cmicx)) ) { 515 return (BCM_E_UNAVAIL); 516 } 517 518 if (soc->txbeacon_init == 0) { 519 return (BCM_E_INIT); 520 } 521 522 /* Allocate a dma-able area just big enough for the beacon info */ 523 txb = soc_cm_salloc(unit, MOS_MSG_DMA_LEN(sizeof(bcm_txbeacon_t)), 524 "traverse info"); 525 if (txb == NULL) { 526 return(BCM_E_MEMORY); 527 } 528 529 while (1) { 530 531 /* Set up the info-only area */ 532 txb->pkt_id = soc_htonl(pkt_id); 533 txb->maxlen = 0; 534 txb->pkt_data = NULL; 535 soc_cm_sflush(unit, txb, sizeof(bcm_txbeacon_t)); 536 soc_cm_sinval(unit, txb, sizeof(bcm_txbeacon_t)); 537 538 send.s.mclass = MOS_MSG_CLASS_PKT_BCN; 539 send.s.subclass = MOS_MSG_SUBCLASS_PKT_BCN_GET; 540 send.s.len = soc_htons(sizeof(bcm_txbeacon_t)); 541 send.s.data = soc_htonl(soc_cm_l2p(unit, txb)); 542 543 if ((soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, &send, &rcv, 544 soc->txbeacon_msg_timeout) != SOC_E_NONE) || 545 (rcv.s.data != 0)) { 546 break; 547 } 548 549 /* Copy actual packet ID out */ 550 pkt_id = soc_htonl(txb->pkt_id); 551 552 /* Allocate an area big enough for everything */ 553 size = MOS_MSG_DMA_LEN(sizeof(bcm_txbeacon_t) + soc_htons(txb->maxlen)); 554 pkt = soc_cm_salloc(unit, size, "traverse packet"); 555 if (pkt == NULL) { 556 rc = BCM_E_MEMORY; 557 break; 558 } 559 560 561 pkt->pkt_id = soc_htonl(pkt_id); 562 pkt->maxlen = soc_htons(txb->maxlen); 563 pkt->pkt_data = INT_TO_PTR(soc_cm_l2p(unit, ((char *) pkt) + sizeof(bcm_txbeacon_t))); 564 soc_cm_sflush(unit, pkt, size); 565 soc_cm_sinval(unit, pkt, size); 566 567 568 /* Resend the request - this time with the len big enough for 569 the whole packet */ 570 send.s.len = soc_htons(sizeof(bcm_txbeacon_t)); 571 send.s.data = soc_htonl(soc_cm_l2p(unit, pkt)); 572 573 if ((soc_cmic_uc_msg_send_receive(unit, soc->txbeacon_uC, &send, &rcv, 574 soc->txbeacon_msg_timeout) != SOC_E_NONE) || 575 (rcv.s.data != 0)) { 576 rc = BCM_E_FAIL; 577 soc_cm_sfree(unit, pkt); 578 break; 579 } 580 581 /* Set the packet point to the virtual addr and call the loopback function */ 582 _bcm_esw_txbeacon_ntoh(pkt, pkt); 583 pkt->pkt_data = (((uint8 *) pkt) + sizeof(bcm_txbeacon_t)); 584 585 trav_fn(unit, pkt, user_data); 586 587 soc_cm_sfree(unit, pkt); /* Free the big one */ 588 589 pkt_id++; 590 } 591 592 soc_cm_sfree(unit, txb); 593 594 return rc; 595 596 #else 597 return (BCM_E_UNAVAIL); 598 599 #endif 600 } 601