rcpu.c (55937B)
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 * Remote CPU module for XGS devices. 8 */ 9 10 /* We need to call top-level APIs on other units */ 11 #ifdef BCM_HIDE_DISPATCHABLE 12 #undef BCM_HIDE_DISPATCHABLE 13 #endif 14 15 #include <shared/bsl.h> 16 17 #include <shared/alloc.h> 18 #include <sal/core/libc.h> 19 #include <sal/core/sync.h> 20 #include <shared/bsl.h> 21 #include <soc/drv.h> 22 #include <soc/debug.h> 23 #include <soc/error.h> 24 #include <soc/mem.h> 25 #include <soc/pbsmh.h> 26 #include <soc/higig.h> 27 28 #include <bcm/pkt.h> 29 #include <bcm/rx.h> 30 #include <bcm/tx.h> 31 32 #include <bcm_int/control.h> 33 #include <bcm_int/esw/rcpu.h> 34 #include <bcm_int/esw/rx.h> 35 #include <bcm_int/esw/trunk.h> 36 #include <bcm_int/esw/tx.h> 37 #include <bcm_int/esw/stack.h> 38 #include <bcm_int/api_xlate_port.h> 39 #include <bcm_int/esw_dispatch.h> 40 41 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_XGS3_SWITCH_SUPPORT) 42 43 #include <bcm_int/esw/port.h> 44 45 #ifdef BCM_TRX_SUPPORT 46 #include <bcm_int/esw/trx.h> 47 #endif /* BCM_TRX_SUPPORT */ 48 49 #if defined(BCM_OOB_RCPU_SUPPORT) 50 #include <drv/eth/eth_drv.h> 51 #endif /* BCM_OOB_RCPU_SUPPORT */ 52 53 /* Number of module header bytes inserted after CMIC header for FromCPU packet */ 54 #define FROM_CPU_DCB_SIZE (32) 55 56 /* Number of packet retransmission for S-channel oprations */ 57 #define MAX_RETRY_ATTEMPTS (3) 58 59 /* 60 * Define this if you want to know the time take to prcess RCPU s-channel request. 61 */ 62 #define BCM_RCPU_BENCHMARK (1) 63 64 #define RCPU_HDR_F_SOBMH 0x01 65 #define RCPU_HDR_F_HIGIG 0x02 66 67 #define RCPU_COPY_HDR(b, s, l, inc_buf_ptr) \ 68 sal_memcpy((uint8*)(b), (s), (l)); \ 69 if ((inc_buf_ptr)) { \ 70 (b) += (l); \ 71 } 72 73 #define RCPU_CLR_HDR(b, l, inc_buf_ptr) \ 74 sal_memset((uint8*)(b), 0, (l)); \ 75 if ((inc_buf_ptr)) { \ 76 (b) += (l); \ 77 } 78 79 STATIC int _bcm_rcpu_data_alloc(int unit, int size, void **pkt_buf); 80 STATIC int _bcm_rcpu_data_free(int unit, void *pkt_buf); 81 STATIC int _bcm_rcpu_rx_register(int unit, rcpu_rx_cb_f rx, void *cookie); 82 STATIC int _bcm_rcpu_rx_unregister(int unit, rcpu_rx_cb_f rx); 83 STATIC int _bcm_rcpu_tp_tx(int unit, uint8 *pkt_buf, int len, void *cookie); 84 STATIC void _rcpu_tx_callback(int unit, bcm_pkt_t *rcpu_pkt, void *cookie); 85 STATIC bcm_rx_t _bcm_rcpu_pkt_rx(int unit, bcm_pkt_t * rx_pkt, void * cookie); 86 #if defined(BCM_OOB_RCPU_SUPPORT) 87 STATIC int _bcm_rcpu_oob_tp_tx(int unit, uint8 *pkt_buf, int len, void *cookie); 88 #endif /* BCM_OOB_RCPU_SUPPORT */ 89 90 /********** global variables ****************/ 91 92 _bcm_rcpu_control_t *_bcm_rcpu_control[BCM_RCPU_MAX_UNITS]; 93 94 /* Standard BCM transport pointer structure */ 95 rcpu_trans_ptr_t rcpu_trans_ptr = { 96 _bcm_rcpu_rx_register, 97 _bcm_rcpu_rx_unregister, 98 _bcm_rcpu_tp_tx, 99 _bcm_rcpu_data_alloc, 100 _bcm_rcpu_data_free, 101 0, /* Default unit */ 102 0 103 }; 104 105 #if defined(BCM_OOB_RCPU_SUPPORT) 106 /* Standard OOB transport pointer structure */ 107 rcpu_trans_ptr_t rcpu_oob_trans_ptr = { 108 eth_drv_register, 109 eth_drv_unregister, 110 _bcm_rcpu_oob_tp_tx, 111 _bcm_rcpu_data_alloc, 112 _bcm_rcpu_data_free, 113 0, /* Default unit */ 114 0 115 }; 116 #endif /* BCM_OOB_RCPU_SUPPORT */ 117 118 /************** local functions *****************************/ 119 120 #define RCPU_TRANS_PTR_SET(unit) _rcpu_trans_ptr = CMVEC(unit).rcpu_tp; 121 122 STATIC int 123 _bcm_rcpu_data_alloc(int unit, int size, void **pkt_buf) 124 { 125 COMPILER_REFERENCE(unit); 126 *pkt_buf = (void *)sal_dma_alloc(size, "RCPU"); 127 return (*pkt_buf == NULL)? BCM_E_MEMORY:BCM_E_NONE; 128 } 129 130 STATIC int 131 _bcm_rcpu_data_free(int unit, void *pkt_buf) 132 { 133 COMPILER_REFERENCE(unit); 134 if (pkt_buf) { 135 sal_dma_free(pkt_buf); 136 } 137 return BCM_E_NONE; 138 } 139 140 typedef struct rcpu_rx_callback_s { 141 void *rcb_cookie; /* Cookie for callback */ 142 rcpu_rx_cb_f rcb_function; /* Callback function */ 143 } rcpu_rx_callback_t; 144 145 STATIC rcpu_rx_callback_t rcpu_cb[BCM_RCPU_MAX_UNITS]; 146 147 STATIC int 148 _bcm_rcpu_rx_register(int unit, rcpu_rx_cb_f rx, void *cookie) 149 { 150 int rv; 151 bcm_rx_cfg_t rx_cfg; 152 uint32 flags = BCM_RCO_F_ALL_COS; 153 #ifdef BCM_RX_REFILL_FROM_INTR 154 /* 155 * Define BCM_RX_REFILL_FROM_INTR to allocate common rx pool for ToCPU packets 156 * in interrupt context. 157 */ 158 flags |= BCM_RCO_F_INTR; 159 #endif 160 BCM_IF_ERROR_RETURN(bcm_esw_rx_register(unit, 161 "RCPU RX", _bcm_rcpu_pkt_rx, 162 BCM_RCPU_RX_PRIO, NULL, flags)); 163 bcm_esw_rx_cfg_get(unit, &rx_cfg); 164 rv = bcm_esw_rx_start(unit, &rx_cfg); 165 if (rv == BCM_E_BUSY) { 166 rv = BCM_E_NONE; 167 } 168 169 rcpu_cb[unit].rcb_function = rx; 170 rcpu_cb[unit].rcb_cookie = cookie; 171 172 return rv; 173 } 174 175 STATIC int 176 _bcm_rcpu_rx_unregister(int unit, rcpu_rx_cb_f rx) 177 { 178 rcpu_cb[unit].rcb_function = NULL; 179 return bcm_esw_rx_unregister(unit, _bcm_rcpu_pkt_rx, BCM_RCPU_RX_PRIO); 180 } 181 182 STATIC int 183 _bcm_rcpu_tp_tx(int unit, uint8 *pkt_buf, int len, void *cookie) 184 { 185 int rv; 186 bcm_pkt_t *pkt = (bcm_pkt_t *)cookie; 187 bcm_pkt_t *new_pkt = NULL; 188 189 new_pkt = sal_alloc(sizeof(bcm_pkt_t), "_bcm_rcpu_tp_tx"); 190 if (!new_pkt) { 191 return BCM_E_MEMORY; 192 } 193 sal_memset(new_pkt, 0, sizeof(bcm_pkt_t)); 194 new_pkt->unit = unit; 195 new_pkt->pkt_data = &new_pkt->_pkt_data; 196 new_pkt->blk_count = 1; 197 new_pkt->pkt_data[0].data = pkt_buf; 198 new_pkt->pkt_data[0].len = len; 199 200 /* Use plain ether mode */ 201 new_pkt->flags = BCM_TX_ETHER | BCM_TX_CRC_REGEN; 202 203 if (pkt) { 204 new_pkt->cookie = pkt->_dv; 205 } else { 206 new_pkt->flags |= BCM_TX_CRC_ALLOC; 207 } 208 209 /* Use asynchronous tx */ 210 new_pkt->call_back = _rcpu_tx_callback; 211 212 if (pkt && pkt->call_back != NULL) { 213 /* coverity[overrun-buffer-val : FALSE] */ 214 rv = bcm_esw_tx(unit, new_pkt, pkt); 215 } else { 216 /* coverity[overrun-buffer-val : FALSE] */ 217 rv = bcm_esw_tx(unit, new_pkt, NULL); 218 } 219 220 /* Handle error case */ 221 222 return rv; 223 } 224 225 #if defined(BCM_OOB_RCPU_SUPPORT) 226 STATIC int 227 _bcm_rcpu_oob_tp_tx(int unit, uint8 *pkt_buf, int len, void *cookie) 228 { 229 int rv; 230 231 rv = eth_drv_tx(unit, pkt_buf, len, cookie); 232 233 sal_dma_free(pkt_buf); 234 235 return rv; 236 } 237 #endif /* BCM_OOB_RCPU_SUPPORT */ 238 239 STATIC uint8 240 _bcm_rcpu_ctoi(const char *s) 241 { 242 uint32 n = 0, base = 16; 243 244 if (*s == '0') { 245 s++; 246 } 247 248 for (n = 0; ((*s >= 'a' && *s <= 'z') || 249 (*s >= 'A' && *s <= 'Z') || 250 (*s >= '0' && *s <= '9')); s++) { 251 n = n * base + 252 (*s >= 'a' ? *s - 'a' + 10 : 253 *s >= 'A' ? *s - 'A' + 10 : 254 *s - '0'); 255 } 256 return (uint8)n; 257 } 258 259 STATIC int 260 _bcm_rcpu_parse_macaddr(char *s, bcm_mac_t mac) 261 { 262 char *p = s; 263 int i; 264 265 if (NULL == s) { 266 return -1; 267 } 268 269 /* Must be of the form 00:01:02:03:AA:BB */ 270 if (17 != sal_strlen(s)) { 271 return -1; 272 } 273 274 for (i = 0; i < 6; i++) { 275 mac[i] = _bcm_rcpu_ctoi(p); 276 p += 3; 277 } 278 return 0; 279 } 280 281 STATIC int 282 _bcm_rcpu_get_config(int unit) 283 { 284 soc_pbmp_t pbmp; 285 char *mac_str; 286 287 /* Get MAC address of slave unit */ 288 mac_str = soc_property_get_str(unit, spn_RCPU_LMAC); 289 if (mac_str != NULL) { 290 if (_bcm_rcpu_parse_macaddr(mac_str, BCM_RCPU_CFG_LMAC(unit)) < 0 ) { 291 return BCM_E_INTERNAL; 292 } 293 }else{ 294 mac_str = DEFAULT_RCPU_DST_MAC; 295 if (_bcm_rcpu_parse_macaddr(mac_str, BCM_RCPU_CFG_LMAC(unit)) < 0 ) { 296 return BCM_E_INTERNAL; 297 } 298 BCM_RCPU_CFG(unit)->rcpu_cfg.dst_mac[5] = unit; 299 300 } 301 302 303 /* Get MAC address used by master unit */ 304 mac_str = soc_property_get_str(unit, spn_RCPU_SRC_MAC); 305 if (mac_str == NULL) { 306 mac_str = DEFAULT_RCPU_SRC_MAC; 307 } 308 309 if (_bcm_rcpu_parse_macaddr(mac_str, BCM_RCPU_CFG_SRC_MAC(unit)) < 0 ) { 310 return BCM_E_INTERNAL; 311 } 312 313 /* Get the default VLAN and TPID */ 314 BCM_RCPU_CFG(unit)->rcpu_cfg.vlan = soc_property_get(unit, spn_RCPU_VLAN, 315 BCM_VLAN_DEFAULT); 316 BCM_RCPU_CFG(unit)->rcpu_cfg.tpid = DEFAULT_RCPU_TPID; 317 318 /* 319 * Get the valid PBM for remote MAC. Valid PBM is the ports 320 * on which the RCPU packets can be received by the remote CMIC. 321 */ 322 pbmp = soc_property_get_pbmp(unit, spn_RCPU_RX_PBMP, 0); 323 if (SOC_PBMP_IS_NULL(pbmp)) { 324 pbmp = PBMP_PORT_ALL(unit); 325 } 326 SOC_PBMP_ASSIGN(BCM_RCPU_CFG(unit)->pbmp, pbmp); 327 328 /* Get the Signature and Ethertype to be used for remote CMIC packets. */ 329 BCM_RCPU_CFG(unit)->rcpu_cfg.signature = DEFAULT_RCPU_SIGNATURE; 330 BCM_RCPU_CFG(unit)->rcpu_cfg.ether_type = DEFAULT_RCPU_ETHER_TYPE; 331 332 /* Get the various RCPU packet priorities */ 333 if (soc_feature(unit, soc_feature_rcpu_priority)) { 334 BCM_RCPU_CFG(unit)->dot1pri[0] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS0, 0); 335 BCM_RCPU_CFG(unit)->mh_tc[0] = soc_property_get(unit, spn_RCPU_MH_TC_COS0, 0); 336 BCM_RCPU_CFG(unit)->cpu_tc[0] = soc_property_get(unit, spn_RCPU_CPU_TC_COS0, 0); 337 BCM_RCPU_CFG(unit)->dot1pri[1] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS1, 0); 338 BCM_RCPU_CFG(unit)->mh_tc[1] = soc_property_get(unit, spn_RCPU_MH_TC_COS1, 0); 339 BCM_RCPU_CFG(unit)->cpu_tc[1] = soc_property_get(unit, spn_RCPU_CPU_TC_COS1, 0); 340 BCM_RCPU_CFG(unit)->dot1pri[2] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS2, 0); 341 BCM_RCPU_CFG(unit)->mh_tc[2] = soc_property_get(unit, spn_RCPU_MH_TC_COS2, 0); 342 BCM_RCPU_CFG(unit)->cpu_tc[2] = soc_property_get(unit, spn_RCPU_CPU_TC_COS2, 0); 343 BCM_RCPU_CFG(unit)->dot1pri[3] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS3, 0); 344 BCM_RCPU_CFG(unit)->mh_tc[3] = soc_property_get(unit, spn_RCPU_MH_TC_COS3, 0); 345 BCM_RCPU_CFG(unit)->cpu_tc[3] = soc_property_get(unit, spn_RCPU_CPU_TC_COS3, 0); 346 BCM_RCPU_CFG(unit)->dot1pri[4] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS4, 0); 347 BCM_RCPU_CFG(unit)->mh_tc[4] = soc_property_get(unit, spn_RCPU_MH_TC_COS4, 0); 348 BCM_RCPU_CFG(unit)->cpu_tc[4] = soc_property_get(unit, spn_RCPU_CPU_TC_COS4, 0); 349 BCM_RCPU_CFG(unit)->dot1pri[5] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS5, 0); 350 BCM_RCPU_CFG(unit)->mh_tc[5] = soc_property_get(unit, spn_RCPU_MH_TC_COS5, 0); 351 BCM_RCPU_CFG(unit)->cpu_tc[5] = soc_property_get(unit, spn_RCPU_CPU_TC_COS5, 0); 352 BCM_RCPU_CFG(unit)->dot1pri[6] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS6, 0); 353 BCM_RCPU_CFG(unit)->mh_tc[6] = soc_property_get(unit, spn_RCPU_MH_TC_COS6, 0); 354 BCM_RCPU_CFG(unit)->cpu_tc[6] = soc_property_get(unit, spn_RCPU_CPU_TC_COS6, 0); 355 BCM_RCPU_CFG(unit)->dot1pri[7] = soc_property_get(unit, spn_RCPU_DOT1PRI_COS7, 0); 356 BCM_RCPU_CFG(unit)->mh_tc[7] = soc_property_get(unit, spn_RCPU_MH_TC_COS7, 0); 357 BCM_RCPU_CFG(unit)->cpu_tc[7] = soc_property_get(unit, spn_RCPU_CPU_TC_COS7, 0); 358 } 359 return BCM_E_NONE; 360 } 361 362 STATIC void 363 _rcpu_tx_callback(int unit, bcm_pkt_t *rcpu_pkt, void *cookie) 364 { 365 bcm_pkt_t *pkt; 366 367 if (cookie) { 368 pkt = (bcm_pkt_t *) cookie; 369 if (pkt->unit != unit && pkt->call_back) { 370 pkt->call_back(pkt->unit, pkt, rcpu_pkt->cookie); 371 } 372 } 373 sal_dma_free(rcpu_pkt->pkt_data[0].data); 374 sal_free(rcpu_pkt); 375 } 376 377 /* tx_list callback data */ 378 typedef struct _rcpu_tx_list_callback_data_s { 379 bcm_pkt_cb_f call_back; /* Packet callback function */ 380 bcm_pkt_cb_f all_done; /* List callback function */ 381 void *cookie; /* Original pkt->cookie */ 382 bcm_pkt_t *pkt_list; /* head of packte list */ 383 } _rcpu_tx_list_callback_data_t; 384 385 STATIC void 386 _rcpu_tx_list_callback(int unit, bcm_pkt_t *pkt, void *cookie) 387 { 388 _rcpu_tx_list_callback_data_t *data = 389 (_rcpu_tx_list_callback_data_t *)pkt->cookie; 390 391 /* Restore pkt data that was used */ 392 pkt->cookie = data->cookie; 393 pkt->call_back = data->call_back; 394 395 /* Packet callback, if any */ 396 if (pkt->call_back) { 397 pkt->call_back(unit, pkt, cookie); 398 } 399 400 /* There's should always be a list callback, otherwise this 401 function would not have been called */ 402 data->all_done(unit, data->pkt_list, cookie); 403 404 sal_free(data); 405 406 } 407 408 STATIC INLINE void 409 _rcpu_get_mac_vlan_ptrs(bcm_pkt_t *pkt, uint8 **src_mac, 410 uint8 **vlan_ptr, int *block_offset, int *byte_offset) 411 { 412 /* Assume everything is in block 0 */ 413 *src_mac = &pkt->pkt_data[0].data[sizeof(bcm_mac_t)]; 414 *block_offset = 0; 415 416 if (BCM_PKT_NO_VLAN_TAG(pkt)) { 417 /* Get VLAN from _vtag pkt member */ 418 *byte_offset = 2 * sizeof(bcm_mac_t); 419 *vlan_ptr = pkt->_vtag; 420 421 if ((uint32)pkt->pkt_data[0].len < 2 * sizeof(bcm_mac_t)) { 422 if (pkt->blk_count > 1) { 423 /* Src MAC in block 1 */ 424 *src_mac = pkt->pkt_data[1].data; 425 *block_offset = 1; 426 *byte_offset = sizeof(bcm_mac_t); 427 } else { 428 /* This else case is added in conjunction with the 429 * pkt->blk_count check above to fix coverity warning 430 * regarding out-of-bounds access. This is needed to convey 431 * an error condition to the caller. The caller enforces 432 * a check on block_offset to be <= pkt->blk_count. 433 */ 434 *block_offset = pkt->blk_count + 1; 435 } 436 } 437 } else { /* Packet has VLAN tag */ 438 *byte_offset = 2 * sizeof(bcm_mac_t) + sizeof(uint32); 439 *vlan_ptr = &pkt->pkt_data[0].data[2 * sizeof(bcm_mac_t)]; 440 441 if ((uint32)pkt->pkt_data[0].len < 2 * sizeof(bcm_mac_t)) { 442 if (pkt->blk_count > 1) { 443 /* Src MAC in block 1; assume VLAN there too at first */ 444 *src_mac = pkt->pkt_data[1].data; 445 *vlan_ptr = &pkt->pkt_data[1].data[sizeof(bcm_mac_t)]; 446 *block_offset = 1; 447 *byte_offset = sizeof(bcm_mac_t) + sizeof(uint32); 448 if ((uint32)pkt->pkt_data[1].len < sizeof(bcm_mac_t) + sizeof(uint32)) { 449 /* Oops, VLAN in block 2 */ 450 if (pkt->blk_count > 2) { 451 *vlan_ptr = pkt->pkt_data[2].data; 452 *block_offset = 2; 453 *byte_offset = sizeof(uint32); 454 } else { 455 /* This else case is added in conjunction with the 456 * pkt->blk_count check above to fix coverity warning 457 * regarding out-of-bounds access. This is needed to convey 458 * an error condition to the caller. The caller enforces 459 * a check on block_offset to be <= pkt->blk_count. 460 */ 461 *block_offset = pkt->blk_count + 1; 462 } 463 } 464 } else { 465 /* This else case is added in conjunction with the 466 * pkt->blk_count check above to fix coverity warning 467 * regarding out-of-bounds access. This is needed to convey 468 * an error condition to the caller. The caller enforces 469 * a check on block_offset to be <= pkt->blk_count. 470 */ 471 *block_offset = pkt->blk_count + 1; 472 } 473 } else if ((uint32)pkt->pkt_data[0].len < 474 2 * sizeof(bcm_mac_t) + sizeof(uint32)) { 475 if (pkt->blk_count > 1) { 476 /* VLAN in block 1 */ 477 *block_offset = 1; 478 *byte_offset = sizeof(uint32); 479 *vlan_ptr = pkt->pkt_data[1].data; 480 } else { 481 /* This else case is added in conjunction with the 482 * pkt->blk_count check above to fix coverity warning 483 * regarding out-of-bounds access. This is needed to convey 484 * an error condition to the caller. The caller enforces 485 * a check on block_offset to be <= pkt->blk_count. 486 */ 487 *block_offset = pkt->blk_count + 1; 488 } 489 } 490 } 491 } 492 493 STATIC int 494 _tx_rcpu_higig_hdr_setup(int unit, bcm_pkt_t *pkt, uint8 *hdr_buf, 495 int *hdr_size, int *blk_ofst, int *byte_ofst) 496 { 497 int i, byte_offset = 0; 498 uint8 *src_mac, *vlan_ptr, *buf_start = hdr_buf; 499 int block_offset = 0; 500 soc_pbsmh_hdr_t *pbh = NULL; 501 502 if ((uint32)pkt->pkt_data[0].len < sizeof(bcm_mac_t)) { 503 return BCM_E_PARAM; 504 } 505 506 /* Get pointers to srcmac and vlan; check if bad block count */ 507 _rcpu_get_mac_vlan_ptrs(pkt, &src_mac, &vlan_ptr, &block_offset, 508 &byte_offset); 509 510 if (block_offset >= pkt->blk_count) { 511 return BCM_E_PARAM; 512 } 513 514 if (byte_offset >= pkt->pkt_data[block_offset].len) { 515 byte_offset = 0; 516 block_offset++; 517 } 518 519 if (!BCM_PKT_TX_ETHER(pkt)) { 520 /* Raw packet steered mode (PB header in descriptor) */ 521 pbh = (soc_pbsmh_hdr_t *)pkt->_pb_hdr; 522 523 /* copy PBH to header buffer */ 524 RCPU_COPY_HDR(hdr_buf, pbh, sizeof(soc_pbsmh_hdr_t), TRUE); 525 RCPU_CLR_HDR(hdr_buf, FROM_CPU_DCB_SIZE - sizeof(soc_pbsmh_hdr_t), TRUE); 526 527 /* 528 * BCM_PKT_F_HGHDR flag indicates higig header is part of 529 * packet data stream. 530 */ 531 if (BCM_PKT_HAS_HGHDR(pkt)) { 532 uint8 *tmp_pkt_hg_hdr = BCM_PKT_HG_HDR(pkt); 533 int hg_hdr_len = SOC_HIGIG_HDR_SIZE; 534 /* 535 * XGS3: Raw Higig packet steered mode. 536 * Make higig header part of packet stream and PB 537 * header part of descriptor 538 */ 539 #ifdef BCM_HIGIG2_SUPPORT 540 if (tmp_pkt_hg_hdr[0] == SOC_HIGIG2_START) { 541 hg_hdr_len = SOC_HIGIG2_HDR_SIZE; 542 } 543 #endif /* BCM_HIGIG2_SUPPORT */ 544 /* copy HiGig header to buffer */ 545 RCPU_COPY_HDR(hdr_buf, tmp_pkt_hg_hdr, hg_hdr_len, TRUE); 546 } 547 } else { 548 /* Non-SOBMH HiGig hdr */ 549 if (BCM_PKT_TX_HG_READY(pkt)) { 550 uint8 *tmp_pkt_hg_hdr = BCM_PKT_HG_HDR(pkt); 551 uint8 pad[FROM_CPU_DCB_SIZE]; 552 int hg_hdr_len = SOC_HIGIG_HDR_SIZE; 553 #ifdef BCM_HIGIG2_SUPPORT 554 if (tmp_pkt_hg_hdr[0] == SOC_HIGIG2_START) { 555 hg_hdr_len = SOC_HIGIG2_HDR_SIZE; 556 } 557 #endif /* BCM_HIGIG2_SUPPORT */ 558 for (i = 0; i < (FROM_CPU_DCB_SIZE - hg_hdr_len); i++) { 559 pad[i] = 0; 560 } 561 /* copy HiGig header to buffer */ 562 RCPU_COPY_HDR(hdr_buf, tmp_pkt_hg_hdr, hg_hdr_len, TRUE); 563 RCPU_COPY_HDR(hdr_buf, pad, (FROM_CPU_DCB_SIZE - hg_hdr_len), TRUE); 564 } 565 } 566 567 /* Dest mac */ 568 RCPU_COPY_HDR(hdr_buf, pkt->pkt_data[0].data, sizeof(bcm_mac_t), TRUE); 569 570 /* Source mac */ 571 RCPU_COPY_HDR(hdr_buf, src_mac, sizeof(bcm_mac_t), TRUE); 572 573 /* VLAN tag */ 574 /* No VLAN tag for Fabric mapped Higig TX as well */ 575 if (!BCM_PKT_HAS_HGHDR(pkt) && 576 !(pkt->flags & BCM_PKT_F_TX_UNTAG) && 577 !BCM_PKT_TX_FABRIC_MAPPED(pkt)) { /* No HG Hdr, so add VLAN tag */ 578 RCPU_COPY_HDR(hdr_buf, vlan_ptr, sizeof(uint32), TRUE); 579 } 580 581 /* SL TAG */ 582 if (pkt->flags & BCM_PKT_F_SLTAG) { 583 RCPU_COPY_HDR(hdr_buf, pkt->_sltag, sizeof(uint32), TRUE); 584 } 585 586 *blk_ofst = block_offset; 587 *byte_ofst = byte_offset; 588 *hdr_size = hdr_buf - buf_start; 589 590 LOG_INFO(BSL_LS_BCM_TX, 591 (BSL_META_U(unit, 592 "_tx_rcpu_higig_hdr_setup: flags 0x%08x\n"), pkt->flags)); 593 594 return BCM_E_NONE; 595 } 596 597 598 extern void 599 rx_higig_info_decode(int unit, bcm_pkt_t *pkt); 600 601 STATIC bcm_pkt_t * 602 _bcm_rcpu_rx_process_dcb(int unit, dcb_t *dcb, bcm_pkt_t *pkt) 603 { 604 pkt->rx_untagged = SOC_DCB_RX_UNTAGGED_GET(unit, dcb); 605 pkt->rx_port = SOC_DCB_RX_INGPORT_GET(unit, dcb); 606 607 pkt->rx_reason = SOC_DCB_RX_REASON_GET(unit, dcb); 608 SOC_DCB_RX_REASONS_GET(unit, dcb, &pkt->rx_reasons); 609 610 if (SOC_IS_XGS_SWITCH(unit)) { /* Get XGS HiGig info from DMA desc */ 611 int src_port_tgid; 612 pkt->opcode = SOC_DCB_RX_OPCODE_GET(unit, dcb); 613 pkt->dest_mod = SOC_DCB_RX_DESTMOD_GET(unit, dcb); 614 pkt->dest_port = SOC_DCB_RX_DESTPORT_GET(unit, dcb); 615 pkt->src_mod = SOC_DCB_RX_SRCMOD_GET(unit, dcb); 616 src_port_tgid = SOC_DCB_RX_SRCPORT_GET(unit, dcb); 617 if (!soc_feature(unit, soc_feature_trunk_group_overlay) && 618 (src_port_tgid & BCM_TGID_TRUNK_INDICATOR(unit))) { 619 pkt->src_trunk = src_port_tgid & BCM_TGID_PORT_TRUNK_MASK(unit); 620 pkt->flags |= BCM_PKT_F_TRUNK; 621 pkt->src_port = -1; 622 } else { 623 pkt->src_port = src_port_tgid; 624 pkt->src_trunk = -1; 625 if (soc_feature(unit, soc_feature_trunk_extended)) { 626 int rv = BCM_E_NONE; 627 bcm_trunk_t tid; 628 629 tid = -1; 630 rv = _bcm_esw_trunk_port_property_get(unit, pkt->src_mod, 631 src_port_tgid, &tid); 632 if (BCM_SUCCESS(rv) && (tid != -1)) { 633 pkt->src_trunk = tid; 634 pkt->flags |= BCM_PKT_F_TRUNK; 635 } 636 } 637 } 638 pkt->src_gport = BCM_GPORT_INVALID; 639 pkt->dst_gport = BCM_GPORT_INVALID; 640 pkt->cos = SOC_DCB_RX_COS_GET(unit, dcb); 641 642 pkt->prio_int = BCM_PKT_VLAN_PRI(pkt); 643 pkt->vlan = BCM_PKT_VLAN_ID(pkt); 644 645 if (SOC_IS_XGS3_SWITCH(unit)) { 646 bcm_vlan_t outer_vid; 647 int hg_hdr_size; 648 int rv = BCM_E_NONE; 649 _bcm_gport_dest_t dest; 650 651 if (SOC_DCB_RX_MIRROR_GET(unit, dcb)) { 652 pkt->flags |= BCM_RX_MIRRORED; 653 } 654 pkt->rx_classification_tag = SOC_DCB_RX_CLASSTAG_GET(unit, dcb); 655 outer_vid = SOC_DCB_RX_OUTER_VID_GET(unit, dcb); 656 if (outer_vid) { 657 /* Don't overwrite if we don't have info */ 658 pkt->vlan = outer_vid; 659 } 660 pkt->vlan_pri = SOC_DCB_RX_OUTER_PRI_GET(unit, dcb); 661 pkt->vlan_cfi = SOC_DCB_RX_OUTER_CFI_GET(unit, dcb); 662 pkt->inner_vlan = SOC_DCB_RX_INNER_VID_GET(unit, dcb); 663 pkt->inner_vlan_pri = SOC_DCB_RX_INNER_PRI_GET(unit, dcb); 664 pkt->inner_vlan_cfi = SOC_DCB_RX_INNER_CFI_GET(unit, dcb); 665 #ifdef BCM_TRX_SUPPORT 666 pkt->rx_outer_tag_action = 667 _BCM_TRX_TAG_ACTION_DECODE(SOC_DCB_RX_OUTER_TAG_ACTION_GET(unit, dcb)); 668 pkt->rx_inner_tag_action = 669 _BCM_TRX_TAG_ACTION_DECODE(SOC_DCB_RX_INNER_TAG_ACTION_GET(unit, dcb)); 670 #endif /* BCM_TRX_SUPPORT */ 671 672 #ifdef BCM_HIGIG2_SUPPORT 673 if (soc_feature(unit, soc_feature_higig2)) { 674 hg_hdr_size = sizeof(soc_higig2_hdr_t); 675 } else 676 #endif /* BCM_HIGIG2_SUPPORT */ 677 { 678 hg_hdr_size = sizeof(soc_higig_hdr_t); 679 } 680 /* Put XGS hdr into pkt->_higig */ 681 sal_memcpy(pkt->_higig, SOC_DCB_MHP_GET(unit, dcb), 682 hg_hdr_size); 683 #ifdef LE_HOST 684 { 685 /* Higig field accessors expect network byte ordering, 686 * so we must reverse the bytes on LE hosts */ 687 int word; 688 uint32 *hg_data = (uint32 *) pkt->_higig; 689 for (word = 0; word < BYTES2WORDS(hg_hdr_size); word++) { 690 hg_data[word] = _shr_swap32(hg_data[word]); 691 } 692 } 693 #endif /* LE_HOST */ 694 rx_higig_info_decode(unit, pkt); 695 696 if (BCM_GPORT_INVALID == pkt->src_gport) { 697 /* Not set by the Higig2 logic */ 698 _bcm_gport_dest_t_init(&dest); 699 if (-1 != pkt->src_trunk) { 700 dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 701 dest.tgid = pkt->src_trunk; 702 } else { 703 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 704 dest.modid = pkt->src_mod; 705 dest.port = pkt->src_port; 706 } 707 rv = _bcm_esw_gport_construct(unit, &dest, &(pkt->src_gport)); 708 if (BCM_FAILURE(rv)) { 709 pkt->src_gport = BCM_GPORT_INVALID; 710 } 711 } 712 713 if (BCM_GPORT_INVALID == pkt->dst_gport) { 714 /* Not set by the Higig2 logic */ 715 _bcm_gport_dest_t_init(&dest); 716 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 717 dest.modid = pkt->dest_mod; 718 dest.port = pkt->dest_port; 719 rv = _bcm_esw_gport_construct(unit, &dest, 720 &(pkt->dst_gport)); 721 if (BCM_FAILURE(rv)) { 722 pkt->dst_gport = BCM_GPORT_INVALID; 723 } 724 } 725 } 726 pkt->rx_matched = SOC_DCB_RX_MATCHRULE_GET(unit, dcb); 727 728 if (soc_feature(unit, soc_feature_rx_timestamp)) { 729 /* Get time stamp value for TS protocol packets or OAM DM */ 730 pkt->rx_timestamp = SOC_DCB_RX_TIMESTAMP_GET(unit, dcb); 731 } 732 733 if (soc_feature(unit, soc_feature_rx_timestamp_upper)) { 734 /* Get upper 32-bit of time stamp value for OAM DM */ 735 pkt->rx_timestamp_upper = SOC_DCB_RX_TIMESTAMP_UPPER_GET(unit, dcb); 736 } 737 } 738 return 0; 739 } 740 741 /* Enable VLAN translation for the vlan on given unit and port. */ 742 STATIC int 743 rcpu_vlan_translate(int unit, int vlan, int port) 744 { 745 BCM_IF_ERROR_RETURN 746 (bcm_vlan_translate_add(unit, port, vlan, vlan, -1)); 747 BCM_IF_ERROR_RETURN 748 (bcm_vlan_translate_egress_add(unit, port, vlan, vlan, -1)); 749 BCM_IF_ERROR_RETURN 750 (bcm_vlan_control_port_set(unit, port, 751 bcmVlanTranslateIngressEnable, TRUE)); 752 BCM_IF_ERROR_RETURN 753 (bcm_vlan_control_port_set(unit, port, 754 bcmVlanTranslateEgressEnable, TRUE)); 755 BCM_IF_ERROR_RETURN 756 (bcm_vlan_control_port_set(unit, port, 757 bcmVlanTranslateEgressMissUntag, FALSE)); 758 return BCM_E_NONE; 759 } 760 761 STATIC int 762 _bcm_rcpu_init(int unit) 763 { 764 uint32 rval, MacOui, MacNonOui; 765 uint8 *mac; 766 bcm_l2_addr_t l2addr; 767 bcm_pbmp_t pbm; 768 bcm_pbmp_t upbm; 769 bcm_pbmp_t pbmcpu; 770 int masterunit; 771 bcm_module_t mymodid; 772 int rcpu_vlan; 773 int rcpu_encap; 774 int rcpu_port, port; 775 776 masterunit = soc_property_get(unit, spn_RCPU_MASTER_UNIT, -1); 777 if (masterunit == unit) { 778 return BCM_E_CONFIG; 779 } 780 781 rcpu_vlan = BCM_RCPU_CFG(unit)->rcpu_cfg.vlan & 0xfff; 782 rcpu_port = soc_property_get(unit, spn_RCPU_PORT, 3); 783 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, rcpu_port, &rcpu_encap)); 784 785 rval = 0; 786 SOC_PBMP_ITER(BCM_RCPU_CFG(unit)->pbmp, port) { 787 BCM_IF_ERROR_RETURN( 788 bcm_esw_port_control_set(unit, port, 789 bcmPortControlRemoteCpuEnable, 1)); 790 } 791 792 /* enable all COS */ 793 BCM_IF_ERROR_RETURN( 794 bcm_esw_switch_control_set(unit, 795 bcmSwitchRemoteCpuToCpuDestPortAllReasons, 0)); 796 BCM_IF_ERROR_RETURN( 797 bcm_esw_switch_control_set(unit, 798 bcmSwitchRemoteCpuToCpuDestMacAllReasons, 1)); 799 800 rval = 0; 801 #ifdef BCM_CMICM_SUPPORT 802 if (soc_feature(unit, soc_feature_cmicm)){ 803 soc_reg_field_set(unit, CMIC_PKT_REASON_MINI_0_TYPEr, &rval, REASONSf, 0); 804 /* coverity[result_independent_of_operands] */ 805 SOC_IF_ERROR_RETURN(WRITE_CMIC_PKT_REASON_MINI_0_TYPEr(unit, rval)); 806 }else 807 #endif 808 { 809 soc_reg_field_set(unit, CMIC_PKT_REASON_MINIr, &rval, REASONSf, 0); 810 /* coverity[result_independent_of_operands] */ 811 SOC_IF_ERROR_RETURN(WRITE_CMIC_PKT_REASON_MINIr(unit, rval)); 812 } 813 814 /* enable all COS */ 815 BCM_IF_ERROR_RETURN( 816 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuForceScheduling, 1)); 817 818 /* Set dest mac address */ 819 mac = BCM_RCPU_CFG_SRC_MAC(unit); 820 MacOui = (((uint32)mac[0]) << 16 | ((uint32)mac[1]) << 8 | ((uint32)mac[2])); 821 MacNonOui = (((uint32)mac[3]) << 16 | ((uint32)mac[4]) << 8 | ((uint32)mac[5])); 822 BCM_IF_ERROR_RETURN( 823 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuDestMacOui, 824 MacOui)); 825 BCM_IF_ERROR_RETURN( 826 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuDestMacNonOui, 827 MacNonOui)); 828 829 /* Set local mac address */ 830 mac = BCM_RCPU_CFG_LMAC(unit); 831 MacOui = (((uint32)mac[0]) << 16 | ((uint32)mac[1]) << 8 | ((uint32)mac[2])); 832 MacNonOui = (((uint32)mac[3]) << 16 | ((uint32)mac[4]) << 8 | ((uint32)mac[5])); 833 BCM_IF_ERROR_RETURN( 834 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuLocalMacOui, 835 MacOui)); 836 BCM_IF_ERROR_RETURN( 837 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuLocalMacNonOui, 838 MacNonOui)); 839 /* set CMIC EtherType and Signature */ 840 BCM_IF_ERROR_RETURN( 841 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuEthertype, 842 BCM_RCPU_CFG(unit)->rcpu_cfg.ether_type)); 843 BCM_IF_ERROR_RETURN( 844 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuSignature, 845 BCM_RCPU_CFG(unit)->rcpu_cfg.signature)); 846 847 /* Set the vlan and tpid values */ 848 BCM_IF_ERROR_RETURN( 849 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuTpid, 850 BCM_RCPU_CFG(unit)->rcpu_cfg.tpid)); 851 BCM_IF_ERROR_RETURN( 852 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuVlan, 853 BCM_RCPU_CFG(unit)->rcpu_cfg.vlan)); 854 855 /* Enable vlan/lmac1 checking and Schan op */ 856 BCM_IF_ERROR_RETURN( 857 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuSchanEnable, 1)); 858 BCM_IF_ERROR_RETURN( 859 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuMatchLocalMac, 1)); 860 BCM_IF_ERROR_RETURN( 861 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuMatchVlan, 1)); 862 BCM_IF_ERROR_RETURN( 863 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuToCpuEnable, 1)); 864 BCM_IF_ERROR_RETURN( 865 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuFromCpuEnable, 1)); 866 867 #ifdef BCM_CMICM_SUPPORT 868 if (soc_feature(unit, soc_feature_cmicm)) { 869 BCM_IF_ERROR_RETURN( 870 bcm_esw_switch_control_set(unit, bcmSwitchRemoteCpuCmicEnable, 1)); 871 } 872 #endif /* BCM_CMICM_SUPPORT */ 873 874 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 875 if (soc_feature(unit, soc_feature_rcpu_priority)) { 876 uint8 property; 877 /* coverity[result_independent_of_operands] */ 878 SOC_IF_ERROR_RETURN(READ_CMIC_PKT_CTRLr(unit, &rval)); 879 property = soc_property_get(unit, spn_RCPU_MH_SRC_PID_ENABLE, 0); 880 soc_reg_field_set(unit, CMIC_PKT_CTRLr, &rval, MH_SRC_PID_ENABLEf, property); 881 property = soc_property_get(unit, spn_RCPU_MH_CPU_COS_ENABLE, 0); 882 soc_reg_field_set(unit, CMIC_PKT_CTRLr, &rval, CPU_TC_ENABLEf, property); 883 property = soc_property_get(unit, spn_RCPU_MH_TC_MAP_ENABLE, 0); 884 soc_reg_field_set(unit, CMIC_PKT_CTRLr, &rval, MH_TC_MAP_ENABLEf, property); 885 property = soc_property_get(unit, spn_RCPU_DOT1PRI_MAP_ENABLE, 0); 886 soc_reg_field_set(unit, CMIC_PKT_CTRLr, &rval, IEEE_802_1_PRI_MAP_ENABLEf, property); 887 /* coverity[result_independent_of_operands] */ 888 SOC_IF_ERROR_RETURN(WRITE_CMIC_PKT_CTRLr(unit, rval)); 889 } 890 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */ 891 892 /* 893 * Insert L2 entry on remote unit and local unit. 894 */ 895 bcm_l2_addr_t_init(&l2addr, 896 BCM_RCPU_CFG_LMAC(unit), 897 rcpu_vlan); 898 l2addr.flags |= BCM_L2_STATIC | BCM_L2_COPY_TO_CPU; 899 BCM_IF_ERROR_RETURN( 900 bcm_esw_stk_my_modid_get(unit, &mymodid)); 901 l2addr.modid = soc_property_get(unit, spn_RCPU_SLAVE_MODID, mymodid); 902 bcm_esw_l2_addr_add(unit, &l2addr); 903 904 if ( masterunit >= 0 ) { 905 l2addr.flags &= ~(BCM_L2_COPY_TO_CPU); 906 BCM_IF_ERROR_RETURN( 907 bcm_esw_stk_my_modid_get(masterunit, &mymodid)); 908 if ( rcpu_encap != BCM_PORT_ENCAP_IEEE ) { 909 l2addr.modid = soc_property_get(unit, spn_RCPU_SLAVE_MODID, mymodid); 910 l2addr.port = CMIC_PORT(unit); 911 } else { 912 l2addr.modid = soc_property_get(masterunit, spn_RCPU_MASTER_MODID, mymodid); 913 l2addr.port = rcpu_port; 914 } 915 bcm_esw_l2_addr_add(masterunit, &l2addr); 916 } 917 918 bcm_l2_addr_t_init(&l2addr, 919 BCM_RCPU_CFG_SRC_MAC(unit), 920 rcpu_vlan); 921 922 l2addr.flags = BCM_L2_STATIC; 923 if ( masterunit >= 0 ) { 924 BCM_IF_ERROR_RETURN( 925 bcm_esw_stk_my_modid_get(masterunit, &mymodid)); 926 l2addr.modid = soc_property_get(masterunit, spn_RCPU_MASTER_MODID, mymodid); 927 bcm_esw_l2_addr_add(masterunit, &l2addr); 928 } 929 930 BCM_IF_ERROR_RETURN( 931 bcm_esw_stk_my_modid_get(unit, &mymodid)); 932 933 if ( rcpu_encap != BCM_PORT_ENCAP_IEEE ) { 934 /* for higig, we want to do it on the higig port */ 935 l2addr.modid = soc_property_get(masterunit, spn_RCPU_MASTER_MODID, mymodid); 936 l2addr.port = CMIC_PORT(masterunit); /* destination should be CMIC port */ 937 } else { 938 l2addr.modid = soc_property_get(unit, spn_RCPU_SLAVE_MODID, mymodid); 939 l2addr.port = rcpu_port; 940 } 941 bcm_esw_l2_addr_add(unit, &l2addr); 942 943 BCM_PBMP_CLEAR(pbm); 944 BCM_PBMP_CLEAR(upbm); 945 BCM_PBMP_CLEAR(pbmcpu); 946 BCM_PBMP_PORT_SET(pbm, l2addr.port); 947 BCM_PBMP_PORT_SET(pbmcpu, l2addr.port); 948 BCM_PBMP_PORT_ADD(pbmcpu, CMIC_PORT(unit)); 949 950 951 /* If the RCPU vlan is not the default, create the vlan */ 952 if (BCM_SUCCESS(bcm_esw_vlan_create(unit, rcpu_vlan))) { 953 if (rcpu_vlan != BCM_VLAN_DEFAULT && 954 rcpu_encap == BCM_PORT_ENCAP_IEEE) { 955 /* 956 * Remove RCPU port from VLAN 1 if RCPU VLAN is not 1, 957 * and the RCPU port encapsulation is IEEE 958 */ 959 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_remove(unit, 1, pbm)); 960 961 /* 962 * Prepare VLAN translation on the RCPU port and CPU port if 963 * double tagging mode gets enabled. This forces the service 964 * vlan to always be the RCPU vlan for RCPU protocol packets. 965 */ 966 967 if (soc_feature(unit, soc_feature_vlan_translation) && 968 !soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 969 BCM_IF_ERROR_RETURN(rcpu_vlan_translate(unit, rcpu_vlan, 970 l2addr.port)); 971 BCM_IF_ERROR_RETURN(rcpu_vlan_translate(unit, rcpu_vlan, 972 CMIC_PORT(unit))); 973 } 974 } 975 } 976 977 BCM_IF_ERROR_RETURN 978 (bcm_esw_vlan_port_remove(unit, rcpu_vlan, pbmcpu)); 979 980 BCM_IF_ERROR_RETURN 981 (bcm_esw_vlan_port_add(unit, rcpu_vlan, pbmcpu, upbm)); 982 983 if ( masterunit >= 0 ) { 984 /* Error code here is ignored in purpose */ 985 (void)bcm_esw_vlan_create(masterunit, rcpu_vlan); 986 987 BCM_IF_ERROR_RETURN 988 (bcm_esw_vlan_port_remove(masterunit, rcpu_vlan, pbmcpu)); 989 BCM_IF_ERROR_RETURN 990 (bcm_esw_vlan_port_add(masterunit, rcpu_vlan, pbmcpu, upbm)); 991 if (rcpu_vlan != BCM_VLAN_DEFAULT && 992 rcpu_encap == BCM_PORT_ENCAP_IEEE) { 993 BCM_IF_ERROR_RETURN 994 (bcm_esw_vlan_port_remove(masterunit, 1, pbm)); 995 996 /* 997 * Prepare VLAN translation on the RCPU port and CPU port 998 * if double tagging mode gets enabled for the master 999 * unit. This forces the service vlan to always be the 1000 * RCPU vlan for RCPU protocol packets. 1001 */ 1002 1003 if (soc_feature(unit, soc_feature_vlan_translation)) { 1004 BCM_IF_ERROR_RETURN(rcpu_vlan_translate(masterunit, rcpu_vlan, 1005 l2addr.port)); 1006 BCM_IF_ERROR_RETURN(rcpu_vlan_translate(masterunit, rcpu_vlan, 1007 CMIC_PORT(masterunit))); 1008 } 1009 } 1010 } 1011 1012 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1013 /* Set the various packet priorities */ 1014 if (soc_feature(unit, soc_feature_rcpu_priority)) { 1015 int i; 1016 1017 for (i = 0; i < NUM_COS(unit); i++) { 1018 uint32 flags = 0; 1019 int val = 0; 1020 1021 if (BCM_RCPU_CFG(unit)->dot1pri[i]) { 1022 flags |= BCM_SWITCH_REMOTE_CPU_ENCAP_IEEE; 1023 val = BCM_RCPU_CFG(unit)->dot1pri[i]; 1024 } else if (BCM_RCPU_CFG(unit)->mh_tc[i]) { 1025 flags |= BCM_SWITCH_REMOTE_CPU_ENCAP_HIGIG2; 1026 val = BCM_RCPU_CFG(unit)->mh_tc[i]; 1027 } 1028 BCM_IF_ERROR_RETURN( 1029 bcm_esw_switch_rcpu_encap_priority_map_set(unit, flags, i, val)); 1030 } 1031 } 1032 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */ 1033 1034 #if defined(BCM_TRX_SUPPORT) 1035 1036 #define BCM_TRX_CPU_QUEUE_MAX 31 1037 1038 /* Set the traffic class to CPU queue mapping */ 1039 if (soc_feature(unit, soc_feature_rcpu_tc_mapping)) { 1040 int queue, tc, tc_total = soc_mem_index_count(unit, CPU_TS_MAPm); 1041 cpu_ts_map_entry_t tc_map; 1042 1043 for (tc = 0; tc < tc_total; tc++) { 1044 sal_memset(&tc_map, 0, sizeof(tc_map)); 1045 queue = soc_property_suffix_num_get(unit, tc, spn_RCPU_CPU_QUEUE, 1046 "tc", 0); 1047 if (queue > BCM_TRX_CPU_QUEUE_MAX) { 1048 queue = BCM_TRX_CPU_QUEUE_MAX; 1049 } 1050 soc_mem_field32_set(unit, CPU_TS_MAPm, &tc_map, 1051 CPU_QUEUE_IDf, queue); 1052 SOC_IF_ERROR_RETURN 1053 (WRITE_CPU_TS_MAPm(unit, MEM_BLOCK_ALL, tc, &tc_map)); 1054 } 1055 } 1056 #endif /* BCM_TRX_SUPPORT */ 1057 return BCM_E_NONE; 1058 } 1059 1060 int 1061 _bcm_rcpu_tx(int unit, bcm_pkt_t *pkt, void * cookie) 1062 { 1063 int rcpu_pkt_len = 0, pkt_len; 1064 #ifdef BCM_HIGIG2_SUPPORT 1065 uint8 *tmp_pkt_hg_hdr = BCM_PKT_HG_HDR(pkt); 1066 #endif /* BCM_HIGIG2_SUPPORT */ 1067 int hg_hdr_len = SOC_HIGIG_HDR_SIZE; 1068 int i, hdr_size = 0, blk_ofst = 0, byte_ofst= 0, rv = BCM_E_NONE; 1069 uint32 mh_flags = 0, tmp_len, payload_len; 1070 uint8 *tx_buf, *buf_ptr; 1071 rcpu_encap_info_t info; 1072 rcpu_trans_ptr_t *_rcpu_trans_ptr; 1073 1074 if (!SOC_IS_RCPU_UNIT(unit)) { 1075 return BCM_E_UNIT; 1076 } 1077 1078 pkt->unit = unit; 1079 1080 BCM_PKT_BLK_BYTES_CALC(pkt, pkt_len); 1081 if (pkt_len <= 0) { 1082 return BCM_E_PARAM; 1083 } 1084 1085 /* 1086 * Allocate pkt/buffer big enough to accommodate the packet 1087 * after all the header manipulation is done. 1088 */ 1089 rcpu_pkt_len = pkt_len + sizeof(rcpu1_cmic_pkt_hdr_t); 1090 if (!BCM_PKT_TX_ETHER(pkt)) { 1091 /* SOBMH header needs to be appended to the packet. */ 1092 rcpu_pkt_len += FROM_CPU_DCB_SIZE; 1093 if (BCM_PKT_HAS_HGHDR(pkt)) { 1094 #ifdef BCM_HIGIG2_SUPPORT 1095 if (tmp_pkt_hg_hdr[0] == SOC_HIGIG2_START) { 1096 hg_hdr_len = SOC_HIGIG2_HDR_SIZE; 1097 } 1098 #endif /* BCM_HIGIG2_SUPPORT */ 1099 rcpu_pkt_len += hg_hdr_len ; 1100 } 1101 mh_flags = 1; 1102 } else { 1103 /* Non-SOBMH HiGig hdr */ 1104 if (BCM_PKT_TX_HG_READY(pkt)) { 1105 rcpu_pkt_len += FROM_CPU_DCB_SIZE; 1106 mh_flags = 1; 1107 } 1108 } 1109 1110 if (!BCM_PKT_NO_VLAN_TAG(pkt)) { 1111 if (BCM_PKT_HAS_HGHDR(pkt) || 1112 (pkt->flags & BCM_PKT_F_TX_UNTAG)|| 1113 BCM_PKT_TX_FABRIC_MAPPED(pkt)) { 1114 /* No VLAN tag */ 1115 rcpu_pkt_len -= sizeof(uint32); 1116 } 1117 } 1118 1119 if (pkt->flags & BCM_PKT_F_SLTAG) { 1120 /* SL TAG */ 1121 rcpu_pkt_len += sizeof(uint32); 1122 } 1123 1124 if ((BCM_PKT_NO_VLAN_TAG(pkt) && rcpu_pkt_len < 60) || 1125 (!BCM_PKT_NO_VLAN_TAG(pkt) && BCM_PKT_HAS_HGHDR(pkt) && 1126 BCM_PKT_TX_FABRIC_MAPPED(pkt) && rcpu_pkt_len < 60) || 1127 (!BCM_PKT_NO_VLAN_TAG(pkt) && !BCM_PKT_HAS_HGHDR(pkt) && 1128 !BCM_PKT_TX_FABRIC_MAPPED(pkt) && rcpu_pkt_len < 64)) { 1129 LOG_ERROR(BSL_LS_BCM_RCPU, 1130 (BSL_META_U(unit, 1131 "_bcm_rcpu_tx: Discarding %s runt packet %s higig header %d\n"), 1132 BCM_PKT_NO_VLAN_TAG(pkt) ? "untagged" : "tagged", 1133 BCM_PKT_HAS_HGHDR(pkt) ? "with" : "without", rcpu_pkt_len)); 1134 return BCM_E_PARAM; 1135 } 1136 1137 if (pkt->flags & BCM_TX_CRC_ALLOC) { 1138 rcpu_pkt_len += ENET_FCS_SIZE; 1139 } 1140 1141 RCPU_TRANS_PTR_SET(unit); 1142 _rcpu_trans_ptr->rcpu_tp_data_alloc(_rcpu_trans_ptr->tp_unit, 1143 rcpu_pkt_len, 1144 (void*)&buf_ptr); 1145 if (NULL == buf_ptr) { 1146 return BCM_E_MEMORY; 1147 } 1148 1149 tx_buf = buf_ptr; 1150 1151 _tx_rcpu_higig_hdr_setup(unit, pkt, 1152 buf_ptr + sizeof(rcpu1_cmic_pkt_hdr_t), 1153 &hdr_size, &blk_ofst, &byte_ofst); 1154 1155 payload_len = hdr_size; 1156 buf_ptr = tx_buf + sizeof(rcpu1_cmic_pkt_hdr_t) + hdr_size; 1157 for (i = blk_ofst; i < pkt->blk_count; i++) { 1158 tmp_len = pkt->pkt_data[i].len - byte_ofst; 1159 sal_memcpy(buf_ptr, 1160 &pkt->pkt_data[i].data[byte_ofst], 1161 tmp_len); 1162 buf_ptr += tmp_len; 1163 payload_len += tmp_len; 1164 byte_ofst = 0; 1165 } 1166 1167 if (pkt->flags & BCM_TX_CRC_ALLOC) { 1168 payload_len += ENET_FCS_SIZE; 1169 } 1170 1171 /* Now construct the CMIC header */ 1172 info.datalen = (uint16)payload_len; 1173 info.flags = (mh_flags == 1)? SOC_RCPU_FLAG_MODHDR : 0; 1174 info.operation = SOC_RCPU_OP_FROMCPU_PKT; 1175 info.transid = 0; 1176 info.replen = 0; 1177 soc_rcpu_encap(unit, tx_buf, &info); 1178 1179 /* This is for in-band driver tx */ 1180 pkt->_dv = cookie; 1181 1182 if (bsl_check(bslLayerSoc, bslSourceTx, bslSeverityNormal, unit)) { 1183 int j; 1184 LOG_INFO(BSL_LS_BCM_TX, 1185 (BSL_META_U(unit, 1186 "_bcm_rcpu_tx: packet: "))); 1187 for (j = 0; j < payload_len + sizeof(rcpu1_cmic_pkt_hdr_t); j++) { 1188 LOG_INFO(BSL_LS_BCM_TX, 1189 (BSL_META_U(unit, 1190 "%.2x"), tx_buf[j])); 1191 } 1192 LOG_INFO(BSL_LS_BCM_TX, 1193 (BSL_META_U(unit, 1194 "\n"))); 1195 } 1196 1197 rv = _rcpu_trans_ptr->rcpu_tp_tx(_rcpu_trans_ptr->tp_unit, 1198 (void*)tx_buf, 1199 payload_len + sizeof(rcpu1_cmic_pkt_hdr_t), 1200 (void *)pkt); 1201 return rv; 1202 } 1203 1204 extern int rcpu_rx_pkt_enqueue(int unit, bcm_pkt_t *ptk); 1205 1206 /* 1207 * Function: 1208 * _bcm_rcpu_tx_list 1209 * Purpose: 1210 * Transmit a linked list of packets via RCPU mechanism 1211 * Parameters: 1212 * unit - transmission unit 1213 * pkt - Pointer to linked list of packets 1214 * all_done_cb - callback when complete 1215 * cookie - Callback cookie. 1216 * Returns: 1217 * BCM_E_XXX 1218 * Notes: 1219 * This mimics the behavior of the XGS implementation of 1220 * of bcm_tx_list(). 1221 */ 1222 int 1223 _bcm_rcpu_tx_list(int unit, bcm_pkt_t *pkt, bcm_pkt_cb_f all_done_cb, void *cookie) 1224 { 1225 bcm_pkt_t *cur_pkt, *next_pkt; 1226 1227 for (cur_pkt = pkt; cur_pkt; cur_pkt = next_pkt) { 1228 next_pkt = cur_pkt->next; 1229 if (!cur_pkt->next && all_done_cb) { 1230 _rcpu_tx_list_callback_data_t *data; 1231 1232 /* If this is the last packet and there's a completion 1233 callback, then chain _rcpu_tx_list_callback to this 1234 packet's callback. */ 1235 data = sal_alloc(sizeof(_rcpu_tx_list_callback_data_t), 1236 "_bcm_rcpu_tx_list"); 1237 if (!data) { 1238 return BCM_E_MEMORY; 1239 } 1240 1241 data->call_back = cur_pkt->call_back; 1242 data->cookie = cur_pkt->cookie; 1243 data->all_done = all_done_cb; 1244 data->pkt_list = pkt; 1245 cur_pkt->call_back = _rcpu_tx_list_callback; 1246 cur_pkt->cookie = (void *)data; 1247 } 1248 1249 BCM_IF_ERROR_RETURN( 1250 _bcm_rcpu_tx(unit, cur_pkt, cookie)); 1251 } 1252 1253 return BCM_E_NONE; 1254 } 1255 1256 /* 1257 * Function: 1258 * _bcm_rcpu_tx_array 1259 * Purpose: 1260 * Transmit am array of packets via RCPU mechanism 1261 * Parameters: 1262 * unit - transmission unit 1263 * pkt - Pointer to an array of packets 1264 * count - number of packets in the array 1265 * all_done_cb - callback when complete 1266 * cookie - Callback cookie. 1267 * Returns: 1268 * BCM_E_XXX 1269 * Notes: 1270 * This mimics the behavior of the XGS implementation of 1271 * of bcm_tx_array(). 1272 */ 1273 int 1274 _bcm_rcpu_tx_array(int unit, bcm_pkt_t **pkt, int count, 1275 bcm_pkt_cb_f all_done_cb, void *cookie) 1276 { 1277 int i; 1278 1279 for (i = 0; i < count; i++) { 1280 if ((i == count - 1) && all_done_cb) { 1281 _rcpu_tx_list_callback_data_t *data; 1282 1283 /* If this is the last packet and there's a completion 1284 callback, then chain _rcpu_tx_list_callback to this 1285 packet's callback. */ 1286 data = sal_alloc(sizeof(_rcpu_tx_list_callback_data_t), 1287 "_bcm_rcpu_tx_list"); 1288 if (!data) { 1289 return BCM_E_MEMORY; 1290 } 1291 1292 data->call_back = pkt[i]->call_back; 1293 data->cookie = pkt[i]->cookie; 1294 data->all_done = all_done_cb; 1295 data->pkt_list = pkt[0]; 1296 pkt[i]->call_back = _rcpu_tx_list_callback; 1297 pkt[i]->cookie = (void *)data; 1298 } 1299 1300 BCM_IF_ERROR_RETURN( 1301 _bcm_rcpu_tx(unit, pkt[i], cookie)); 1302 } 1303 1304 return BCM_E_NONE; 1305 } 1306 1307 int 1308 _bcm_esw_rcpu_tocpu_rx(int unit, uint8 *pkt, int pkt_len, rcpu_encap_info_t *info) 1309 { 1310 int len, rv; 1311 bcm_pkt_t *rx_pkt = NULL; 1312 dcb_t *dcb; 1313 1314 /* 1315 * CMIC header is followed by dcb information. 1316 */ 1317 len = pkt_len - info->cmic_hdr_size - info->dcb_size; 1318 /* Allocate pkt. */ 1319 rv = bcm_rx_remote_pkt_alloc(len, &rx_pkt); 1320 if (BCM_FAILURE(rv)) { 1321 return rv; 1322 } 1323 sal_memcpy(rx_pkt->pkt_data[0].data, pkt + info->cmic_hdr_size + info->dcb_size , len); 1324 rx_pkt->pkt_len = len; 1325 rx_pkt->unit = unit; 1326 /* 1327 * The dcb in ToCPU packets starts with module header, so make it aligned 1328 * with dcb structure. 1329 */ 1330 dcb = (dcb_t *) (pkt + info->cmic_hdr_size - 8); 1331 _bcm_rcpu_rx_process_dcb(unit, dcb, rx_pkt); 1332 1333 rv = rcpu_rx_pkt_enqueue(unit, rx_pkt); 1334 if (BCM_FAILURE(rv)) { 1335 bcm_rx_remote_pkt_free(rx_pkt); 1336 } 1337 1338 return rv; 1339 } 1340 1341 1342 int rx_rcpu_base_info_parse(bcm_pkt_t *rx_pkt) 1343 { 1344 int unit, len, pkt_len; 1345 dcb_t *dcb; 1346 uint8 *pkt, *pkt_start_p, *pkt_data_p; 1347 rcpu_encap_info_t info; 1348 1349 pkt = pkt_start_p = rx_pkt->pkt_data[0].data; 1350 pkt_len = rx_pkt->pkt_len; 1351 1352 unit = rx_pkt->unit; 1353 SOC_IF_ERROR_RETURN(soc_rcpu_decap(pkt, &unit, &info)); 1354 1355 /* Accept only ToCPU packets */ 1356 if (SOC_RCPU_OP_TOCPU_PKT != info.operation) { 1357 return BCM_E_PARAM; 1358 } 1359 1360 1361 len = pkt_len - info.cmic_hdr_size - info.dcb_size; 1362 dcb = (dcb_t *) ((uint8*) pkt + info.cmic_hdr_size - 8); 1363 /* Move the data to the head of the packet */ 1364 pkt_data_p = pkt + info.cmic_hdr_size + info.dcb_size; 1365 1366 sal_memcpy(pkt_start_p, pkt_data_p, len); 1367 1368 rx_pkt->pkt_data[0].len = len; 1369 rx_pkt->pkt_len = len; 1370 rx_pkt->tot_len = len; 1371 rx_pkt->blk_count = 1; 1372 rx_pkt->alloc_ptr = rx_pkt->_pkt_data.data; 1373 1374 rx_pkt->rx_unit = unit; 1375 rx_pkt->_dcb = (void *)dcb; 1376 return BCM_E_NONE; 1377 } 1378 1379 int rx_rcpu_intr_process_packet(bcm_pkt_t *rx_pkt, int *runit) 1380 { 1381 int unit; 1382 dcb_t *dcb; 1383 bcm_port_t src_port_tgid; 1384 1385 if (rx_pkt->rx_unit > 0) { 1386 /*base info has been parsed*/ 1387 } else { 1388 SOC_IF_ERROR_RETURN(rx_rcpu_base_info_parse(rx_pkt)); 1389 } 1390 1391 *runit = unit = rx_pkt->rx_unit; 1392 dcb = (dcb_t *)(rx_pkt->_dcb); 1393 1394 rx_pkt->opcode = SOC_DCB_RX_OPCODE_GET(unit, dcb); 1395 rx_pkt->dest_mod = SOC_DCB_RX_DESTMOD_GET(unit, dcb); 1396 rx_pkt->dest_port = SOC_DCB_RX_DESTPORT_GET(unit, dcb); 1397 rx_pkt->src_mod = SOC_DCB_RX_SRCMOD_GET(unit, dcb); 1398 src_port_tgid = SOC_DCB_RX_SRCPORT_GET(unit, dcb); 1399 if (!soc_feature(unit, soc_feature_trunk_group_overlay) && 1400 (src_port_tgid & BCM_TGID_TRUNK_INDICATOR(unit))) { 1401 rx_pkt->src_trunk = src_port_tgid & BCM_TGID_PORT_TRUNK_MASK(unit); 1402 rx_pkt->flags |= BCM_PKT_F_TRUNK; 1403 rx_pkt->src_port = -1; 1404 } else { 1405 rx_pkt->src_port = src_port_tgid; 1406 rx_pkt->src_trunk = -1; 1407 } 1408 rx_pkt->cos = SOC_DCB_RX_COS_GET(unit, dcb); 1409 rx_pkt->prio_int = BCM_PKT_VLAN_PRI(rx_pkt); 1410 rx_pkt->vlan = BCM_PKT_VLAN_ID(rx_pkt); 1411 rx_pkt->rx_untagged = SOC_DCB_RX_UNTAGGED_GET(unit, dcb); 1412 1413 if (SOC_DCB_RX_MIRROR_GET(unit, dcb)) { 1414 rx_pkt->flags |= BCM_RX_MIRRORED; 1415 } 1416 rx_pkt->rx_classification_tag = SOC_DCB_RX_CLASSTAG_GET(unit, dcb); 1417 rx_pkt->rx_matched = SOC_DCB_RX_MATCHRULE_GET(unit, dcb); 1418 1419 if (soc_feature(unit, soc_feature_rx_timestamp)) { 1420 /* Get time stamp value for TS protocol packets */ 1421 rx_pkt->rx_timestamp = SOC_DCB_RX_TIMESTAMP_GET(unit, dcb); 1422 } 1423 1424 rx_pkt->rx_reason = SOC_DCB_RX_REASON_GET(unit, dcb); 1425 SOC_DCB_RX_REASONS_GET(unit, dcb, &rx_pkt->rx_reasons); 1426 1427 rx_pkt->rx_decap_tunnel = 1428 (bcm_rx_decap_tunnel_t)SOC_DCB_RX_DECAP_TUNNEL_GET(unit, dcb); 1429 1430 return BCM_E_NONE; 1431 } 1432 1433 STATIC bcm_rx_t 1434 _bcm_rcpu_pkt_rx(int unit, bcm_pkt_t * rx_pkt, void * cookie) 1435 { 1436 int rv; 1437 1438 if (rx_pkt->blk_count == 1) { 1439 if (rcpu_cb[unit].rcb_function) { 1440 rv = (*rcpu_cb[unit].rcb_function)(unit, rx_pkt->pkt_data[0].data, 1441 rx_pkt->pkt_len, 1442 rcpu_cb[unit].rcb_cookie); 1443 if (rv == BCM_E_NONE) { 1444 return BCM_RX_HANDLED; 1445 } 1446 } 1447 } 1448 1449 return BCM_RX_NOT_HANDLED; 1450 } 1451 1452 STATIC void 1453 _rcpu_modid_chg_cb(int unit, soc_switch_event_t event, uint32 arg1, 1454 uint32 arg2, uint32 arg3, void* userdata) 1455 { 1456 switch (event) { 1457 case SOC_SWITCH_EVENT_MODID_CHANGE: 1458 _bcm_rcpu_init(unit); 1459 break; 1460 default: 1461 break; 1462 } 1463 1464 return; 1465 } 1466 /* 1467 * Function: 1468 * _bcm_esw_rcpu_init 1469 * Purpose: 1470 * Initialize RCPU configuration for below configurations: 1471 * (1)Dual-Rapotr/Raven 1472 * (2)Stand alone unit ready to be accessed by RCPU 1473 * Parameters: 1474 * unit - (IN) BCM device number 1475 * Returns: 1476 * BCM_E_XXX 1477 * Notes: 1478 */ 1479 int 1480 _bcm_esw_rcpu_init(int unit) 1481 { 1482 int rv = BCM_E_NONE; 1483 soc_pbmp_t pbmp; 1484 1485 if (!SOC_UNIT_VALID(unit)) { 1486 return BCM_E_UNIT; 1487 } 1488 1489 if (!soc_feature(unit, soc_feature_rcpu_1) || SOC_IS_RCPU_ONLY(unit)) { 1490 /* Do not need this if this is RCPU master unit. */ 1491 return BCM_E_NONE; 1492 } 1493 1494 if (!SOC_IS_RCPU_UNIT(unit)) { 1495 /* 1496 * Use rcpu_rx_pbmp to indicate this is stand alone unit and needs to 1497 * be accessed by RCPU. 1498 */ 1499 pbmp = soc_property_get_pbmp(unit, spn_RCPU_RX_PBMP, 0); 1500 if (SOC_PBMP_IS_NULL(pbmp)) { 1501 return BCM_E_NONE; 1502 } 1503 } 1504 1505 if (BCM_RCPU_CONTROL(unit) && 1506 (BCM_RCPU_CONTROL(unit)->flags & BCM_RCPU_F_INITED)) { 1507 return BCM_E_NONE; 1508 } 1509 1510 if (BCM_RCPU_CONTROL(unit) == NULL) { 1511 BCM_RCPU_CONTROL(unit) = sal_alloc(sizeof(_bcm_rcpu_control_t), 1512 "rcpu_control"); 1513 if (BCM_RCPU_CONTROL(unit) == NULL) { 1514 return BCM_E_MEMORY; 1515 } 1516 sal_memset(BCM_RCPU_CONTROL(unit), 0, sizeof(_bcm_rcpu_control_t)); 1517 1518 BCM_RCPU_CONTROL(unit)->lock = sal_mutex_create("rcpu_unit_mutex"); 1519 if (BCM_RCPU_CONTROL(unit)->lock == NULL) { 1520 return BCM_E_MEMORY; 1521 } 1522 } 1523 1524 /* 1525 * Get the config for the device. 1526 */ 1527 rv = _bcm_rcpu_get_config(unit); 1528 1529 if (BCM_FAILURE(rv)) { 1530 LOG_ERROR(BSL_LS_BCM_RCPU, 1531 (BSL_META_U(unit, 1532 "_bcm_esw_rcpu_init: Failed to get default config.\n"))); 1533 goto err_cfg; 1534 } 1535 1536 rv = _bcm_rcpu_init(unit); 1537 1538 if (BCM_FAILURE(rv)) { 1539 LOG_ERROR(BSL_LS_BCM_RCPU, 1540 (BSL_META_U(unit, 1541 "_bcm_esw_rcpu_init: Failed to init.\n"))); 1542 goto err_cfg; 1543 } 1544 1545 if (SOC_IS_RCPU_UNIT(unit)) { 1546 /* 1547 * Assign soc_rcpu_cfg_t and transport vectors to make it compatible to 1548 * RCPU_ONLY devices. 1549 */ 1550 soc_cm_set_rcpu_cfg(unit, &BCM_RCPU_CFG(unit)->rcpu_cfg); 1551 #if defined(BCM_OOB_RCPU_SUPPORT) 1552 if (soc_property_get(unit, spn_RCPU_USE_OOB, 0)) { 1553 soc_cm_set_rcpu_trans_tpr(unit, &rcpu_oob_trans_ptr); 1554 } else 1555 #endif /* BCM_OOB_RCPU_SUPPORT */ 1556 { 1557 soc_cm_set_rcpu_trans_tpr(unit, &rcpu_trans_ptr); 1558 } 1559 1560 /* Use the same routine of RCPU_ONLY device to receive ToCPU packets. */ 1561 rv = soc_rcpu_init(unit); 1562 } 1563 1564 /* Register a call back function to be notified upon modid changes */ 1565 BCM_IF_ERROR_RETURN(soc_event_register(unit, _rcpu_modid_chg_cb, NULL)); 1566 1567 BCM_RCPU_CONTROL(unit)->flags |= BCM_RCPU_F_INITED; 1568 1569 return rv; 1570 1571 err_cfg: 1572 1573 if (BCM_RCPU_CONTROL(unit)) { 1574 sal_free(BCM_RCPU_CONTROL(unit)); 1575 BCM_RCPU_CONTROL(unit) = NULL; 1576 } 1577 1578 return rv; 1579 } 1580 1581 int 1582 _bcm_esw_rcpu_deinit(int unit) 1583 { 1584 if ((!SOC_UNIT_VALID(unit))){ 1585 return BCM_E_UNIT; 1586 } 1587 1588 if (!soc_feature(unit, soc_feature_rcpu_1) || SOC_IS_RCPU_ONLY(unit)) { 1589 /* Do not need this if this is RCPU master unit. */ 1590 return BCM_E_NONE; 1591 } 1592 1593 if (BCM_RCPU_CONTROL(unit)) { 1594 1595 if (BCM_RCPU_CONTROL(unit)->lock) { 1596 sal_mutex_destroy(BCM_RCPU_CONTROL(unit)->lock); 1597 } 1598 1599 sal_free(BCM_RCPU_CONTROL(unit)); 1600 BCM_RCPU_CONTROL(unit) = NULL; 1601 1602 soc_rcpu_deinit(unit); 1603 } 1604 1605 (void)soc_event_unregister(unit, _rcpu_modid_chg_cb, NULL); 1606 1607 return BCM_E_NONE; 1608 } 1609 #else 1610 int 1611 _bcm_esw_rcpu_init(int unit) 1612 { 1613 COMPILER_REFERENCE(unit); 1614 return BCM_E_UNAVAIL; 1615 } 1616 1617 int 1618 _bcm_esw_rcpu_deinit(int unit) 1619 { 1620 COMPILER_REFERENCE(unit); 1621 return BCM_E_UNAVAIL; 1622 } 1623 1624 int 1625 _bcm_rcpu_tx(int unit, bcm_pkt_t *pkt, void *cookie) 1626 { 1627 COMPILER_REFERENCE(unit); 1628 COMPILER_REFERENCE(pkt); 1629 COMPILER_REFERENCE(cookie); 1630 return BCM_E_UNAVAIL; 1631 } 1632 1633 int 1634 _bcm_rcpu_tx_list(int unit, bcm_pkt_t *pkt, bcm_pkt_cb_f all_done_cb, void *cookie) 1635 { 1636 COMPILER_REFERENCE(unit); 1637 COMPILER_REFERENCE(pkt); 1638 COMPILER_REFERENCE(all_done_cb); 1639 COMPILER_REFERENCE(cookie); 1640 return BCM_E_UNAVAIL; 1641 } 1642 1643 int 1644 _bcm_rcpu_tx_array(int unit, bcm_pkt_t **pkt, int count, 1645 bcm_pkt_cb_f all_done_cb, void *cookie) 1646 { 1647 COMPILER_REFERENCE(unit); 1648 COMPILER_REFERENCE(pkt); 1649 COMPILER_REFERENCE(count); 1650 COMPILER_REFERENCE(all_done_cb); 1651 COMPILER_REFERENCE(cookie); 1652 return BCM_E_UNAVAIL; 1653 } 1654 1655 int rx_rcpu_intr_process_packet(bcm_pkt_t *rx_pkt, int *runit) 1656 { 1657 COMPILER_REFERENCE(rx_pkt); 1658 COMPILER_REFERENCE(runit); 1659 return BCM_E_UNAVAIL; 1660 } 1661 1662 #endif /* BCM_RCPU_SUPPORT && BCM_XGS3_SWITCH_SUPPORT */