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

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