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

subport.c (357907B)


      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  * File:    subport.c
      8  * Purpose: Katana2 SUBPORT functions
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #include <sal/core/libc.h>
     15 #if defined(BCM_KATANA2_SUPPORT)
     16 
     17 #include <soc/drv.h>
     18 #include <soc/mem.h>
     19 #include <soc/util.h>
     20 #include <soc/katana2.h>
     21 #include <bcm/error.h>
     22 #include <bcm/port.h>
     23 #include <bcm/subport.h>
     24 #include <bcm_int/esw/katana2.h>
     25 #include <bcm_int/esw/subport.h>
     26 #include <bcm_int/esw_dispatch.h>
     27 #include <bcm_int/esw/triumph.h>
     28 #include <bcm_int/esw/triumph2.h>
     29 #include <bcm_int/esw/stack.h>
     30 
     31 #if defined(BCM_SABER2_SUPPORT)
     32 #include <soc/saber2.h>
     33 #endif
     34 
     35 #if defined(BCM_METROLITE_SUPPORT)
     36 #include <soc/metrolite.h>
     37 #endif
     38 /*****************************************
     39 * Subport common section - start
     40  */
     41 
     42 /*
     43  * Function Vector
     44  */
     45 static bcm_esw_subport_drv_t bcmi_kt2_subport_drv = {
     46 
     47 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
     48     /* subport_init                */ bcm_tr2_subport_init,
     49     /* subport_group_create        */ bcm_tr2_subport_group_create,
     50     /* subport_group_get           */ bcm_tr2_subport_group_get,
     51     /* subport_group_traverse      */ NULL,
     52     /* subport_group_destroy       */ bcm_tr2_subport_group_destroy,
     53     /* subport_linkphy_config_set  */ NULL,
     54     /* subport_linkphy_config_get  */ NULL,
     55     /* subport_port_add            */ bcm_tr2_subport_port_add,
     56     /* subport_port_get            */ bcm_tr2_subport_port_get,
     57     /* subport_port_traverse       */ bcm_tr2_subport_port_traverse,
     58     /* subport_port_stat_set       */ NULL,
     59     /* subport_port_stat_get       */ NULL,
     60     /* subport_port_delete         */ bcm_tr2_subport_port_delete,
     61     /* subport_cleanup             */ bcm_tr2_subport_cleanup,
     62 #else 
     63     NULL, NULL, NULL, NULL, NULL,
     64     NULL, NULL, NULL, NULL, NULL,
     65     NULL, NULL, NULL, NULL,
     66 #endif
     67 
     68     /* coe_init                */ bcm_kt2_subport_init,
     69     /* coe_group_create        */ bcm_kt2_subport_group_create,
     70     /* coe_group_get           */ bcm_kt2_subport_group_get,
     71     /* coe_group_traverse      */ bcm_kt2_subport_group_traverse,
     72     /* coe_group_destroy       */ bcm_kt2_subport_group_destroy,
     73     /* coe_linkphy_config_set  */ bcm_kt2_subport_group_linkphy_config_set,
     74     /* coe_linkphy_config_get  */ bcm_kt2_subport_group_linkphy_config_get,
     75     /* coe_port_add            */ bcm_kt2_subport_port_add,
     76     /* coe_port_get            */ bcm_kt2_subport_port_get,
     77     /* coe_port_traverse       */ bcm_kt2_subport_port_traverse,
     78     /* coe_port_stat_set       */ bcm_kt2_subport_port_stat_set,
     79     /* coe_port_stat_get       */ bcm_kt2_subport_port_stat_get,
     80     /* coe_port_delete         */ bcm_kt2_subport_port_delete,
     81     /* coe_cleanup             */ bcm_kt2_subport_cleanup,
     82     /* subport_linkphy_rx_error_register */ bcm_kt2_subport_linkphy_rx_error_register,
     83     /* subport_linkphy_rx_error_unregister */ bcm_kt2_subport_linkphy_rx_error_unregister,
     84     /* subport_gport_modport_get */ bcmi_kt2_subport_gport_modport_get
     85 };
     86 
     87 /*****************************************
     88 * Subport common section - start
     89  */
     90 
     91 /* Bitmap to manage PP_PORT indices for subport port addition*/
     92 STATIC SHR_BITDCL *_bcm_subport_pp_port_bitmap[BCM_MAX_NUM_UNITS] = { 0 };
     93 STATIC int _bcm_subport_pp_port_count[BCM_MAX_NUM_UNITS] = { 0 };
     94 
     95 /*********************************
     96 * Subport common  section - end
     97  */
     98 
     99 
    100 /*********************************
    101 * LinkPHY subport section -start
    102  */
    103 
    104 /* Bitmap of LinkPHY subport group id */
    105 STATIC SHR_BITDCL *_bcm_linkphy_group_bitmap[BCM_MAX_NUM_UNITS] = { 0 };
    106 
    107 /* Count of all LinkPHY subport groups created */
    108 STATIC int _bcm_linkphy_subport_group_count[BCM_MAX_NUM_UNITS] = { 0 };
    109 
    110 /*
    111 * Bitmap of device internal stream id usage.usage for Katana2
    112 * Katana has 2 blocks and each block has 128 streams.
    113 * External stream id is mapped to 256 device internal stream ids.
    114 * Block 0 internal stream id base = 0
    115 * Block 1 internal stream id base = 128
    116 * device internal stream id = internal stream id + internal stream id base
    117 */
    118 STATIC SHR_BITDCL *_bcm_dev_int_stream_id_bitmap[BCM_MAX_NUM_UNITS] = { 0 };
    119 
    120 /* Set the LinkPHY subport group gport */
    121 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_SET(_subport_group, \
    122                                            _port, _gid) \
    123             _BCM_COE_LINKPHY_SUBPORT_GROUP_SET(_subport_group, \
    124                                            _port, _gid)
    125 
    126 
    127 #define _BCM_KT2_PORT_SUPPORTS_LINKPHY(_unit_, _port_) \
    128     (SOC_REG_PORT_VALID(_unit_, RXLP_PORT_ENABLEr, _port_))
    129 
    130 /*
    131  * LinkPHY subport group usage bitmap operations
    132  */
    133 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(_u_, _group_) \
    134         SHR_BITGET(_bcm_linkphy_group_bitmap[_u_], (_group_))
    135 
    136 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_SET(_u_, _group_) \
    137         SHR_BITSET(_bcm_linkphy_group_bitmap[_u_], (_group_))
    138 
    139 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_CLR(_u_, _group_) \
    140         SHR_BITCLR(_bcm_linkphy_group_bitmap[_u_], (_group_))
    141 
    142 
    143 /* Katana2 LinkPHY device internal stream id usage bitmap */
    144 #define _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(_u_, _stream_id_) \
    145         SHR_BITGET(_bcm_dev_int_stream_id_bitmap[_u_], (_stream_id_))
    146 
    147 #define _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(_u_, _stream_id_) \
    148         SHR_BITSET(_bcm_dev_int_stream_id_bitmap[_u_], (_stream_id_))
    149 
    150 #define _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_CLR(_u_, _stream_id_) \
    151         SHR_BITCLR(_bcm_dev_int_stream_id_bitmap[_u_], (_stream_id_))
    152 
    153 /* LinkPHY subport port info structure */
    154 typedef struct {
    155     bcm_gport_t group;       /* Subport group gort*/
    156     int         valid;
    157     int         num_streams; /* Number of sreams */
    158     uint16      ext_stream_idx[BCM_SUBPORT_CONFIG_MAX_STREAMS];
    159 } _bcm_linkphy_subport_port_info_t;
    160 
    161 /* LinkPHY subport port array */
    162 _bcm_linkphy_subport_port_info_t
    163            *(_bcm_linkphy_subport_port_info[BCM_MAX_NUM_UNITS]) = { 0 };
    164 
    165 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port) \
    166     (_bcm_linkphy_subport_port_info[unit][pp_port].valid)
    167 
    168 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port) \
    169     (_bcm_linkphy_subport_port_info[unit][pp_port].group)
    170 
    171 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, pp_port) \
    172     (_bcm_linkphy_subport_port_info[unit][pp_port].num_streams)
    173 
    174 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(unit, pp_port, \
    175     sp_stream_array_id) \
    176     (_bcm_linkphy_subport_port_info[unit] \
    177     [pp_port].ext_stream_idx[sp_stream_array_id])
    178 
    179 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, \
    180     pp_port, sp_group, sp_num_streams, is_valid) \
    181 { \
    182     _bcm_linkphy_subport_port_info[unit][pp_port].group = sp_group; \
    183      _bcm_linkphy_subport_port_info[unit][pp_port].num_streams \
    184                                    = sp_num_streams; \
    185     _bcm_linkphy_subport_port_info[unit][pp_port].valid = is_valid; \
    186 }
    187 
    188 #if defined(BCM_SABER2_SUPPORT)
    189 /* SB2 Linkphy internal stream id allocation related structures 
    190  * There are only 32 internal stream ids possible for SB2 (0 to 31).
    191  * This has to be divided to four ports as 8 stream ids per linkphy port.
    192  *
    193  * Note that this cannot be directly calculated from external stream id
    194  * since external stream ids range from N to N+31 (where N is external stream
    195  * id base) for that port. And these 32 external stream IDs have a 
    196  * limited pool range of 8 internal stream IDs. Hence we need an allocation 
    197  * procedure. 
    198  *
    199  * Hence Internal stream id pool allocation is as follows. 
    200  * 
    201  * Port 1 - Pool contains Ids from 0 to 7
    202  * Port 2 - Pool contains Ids from 8 to 15
    203  * Port 3 - Pool contains Ids from 16 to 23
    204  * Port 4 - Pool contains Ids from 24 to 31.
    205  */
    206 shr_idxres_list_handle_t _bcm_sb2_int_stream_id_pool[BCM_MAX_NUM_UNITS][SOC_SB2_MAX_LINKPHY_PORTS];
    207 #endif
    208 
    209 #if defined(BCM_METROLITE_SUPPORT)
    210 /* Metrolite Linkphy internal stream id allocation related structures
    211  * There are only 24 internal stream ids possible for Metrolite (0 to 23).
    212  * This has to be divided to four ports as 6 stream ids per linkphy port.
    213  *
    214  * Note that this cannot be directly calculated from external stream id
    215  * since external stream ids range from N to N+23 (where N is external stream
    216  * id base) for that port. And these 24 external stream IDs have a
    217  * limited pool range of 6 internal stream IDs. Hence we need an allocation
    218  * procedure.
    219  *
    220  * Hence Internal stream id pool allocation is as follows.
    221  *
    222  * Port 1 - Pool contains Ids from 0 to 5
    223  * Port 2 - Pool contains Ids from 6 to 11
    224  * Port 3 - Pool contains Ids from 12 to 17
    225  * Port 4 - Pool contains Ids from 18 to 23.
    226  */
    227 shr_idxres_list_handle_t _bcm_ml_int_stream_id_pool[BCM_MAX_NUM_UNITS][_BCM_ML_MAX_LINKPHY_PORTS];
    228 #endif
    229 
    230 /* 
    231 * KT2 - Pool of LinkPhy block per port internal stream Ids.
    232 * Each LinkPhy block port has internal streams ids in the range of
    233 * 0 to 127. Each LinkPhy block supports upto maximum 4 LinkPhy
    234 * ports and the internal stream id allocation is done per port in LP block.
    235 * Block 0 has LP ports 27,32,33,34 and Block 1 has LP ports 28,29,30,31.
    236 */
    237 shr_idxres_list_handle_t
    238 _bcm_kt2_blk_int_stream_id_pool[BCM_MAX_NUM_UNITS][SOC_KT2_LINKPHY_BLOCK_MAX]
    239                                [SOC_KT2_LINKPHY_BLOCK_PORT_IDX_MAX];
    240 /* LinkPHY counter related defines */
    241 
    242 #define _BCM_KT2_LINKPHY_DIRECTION_MAX 2
    243 #define _BCM_KT2_LINKPHY_DIRECTION_RX  0
    244 #define _BCM_KT2_LINKPHY_DIRECTION_TX  1
    245 #define _BCM_KT2_LINKPHY_BLOCK_MAX     2
    246 #define _BCM_KT2_LINKPHY_POOL_MAX      4
    247 #define _BCM_KT2_LINKPHY_POOL_FRAG_BYTE  0
    248 #define _BCM_KT2_LINKPHY_POOL_FRAG       1
    249 #define _BCM_KT2_LINKPHY_POOL_FRAME_BYTE 2
    250 #define _BCM_KT2_LINKPHY_POOL_FRAME      3
    251 #define _BCM_KT2_LINKPHY_COUNTER_MIN(unit)   \
    252                 (soc_mem_index_min(unit, RXLP_DEBUG_COUNTER8m))
    253 #define _BCM_KT2_LINKPHY_COUNTER_MAX(unit)   \
    254                 (soc_mem_index_max(unit, RXLP_DEBUG_COUNTER8m) + 1)
    255 
    256 #define _BCM_ML_LINKPHY_BLOCK_MAX      1 /* Only one RXLP/TXLP block */
    257 
    258 static sal_mutex_t linkphy_ctr_mutex[BCM_UNITS_MAX] = {NULL};
    259 
    260 
    261 static rxlp_debug_counter7_entry_t *linkphy_temp_ctr
    262                [BCM_UNITS_MAX] = {NULL};
    263 
    264 static uint64 *linkphy_frag_byte_ctr
    265                [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX]
    266                [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}};
    267 static uint64 *linkphy_frag_ctr
    268                [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX]
    269                [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}};
    270 static uint64 *linkphy_frame_byte_ctr
    271                [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX]
    272                [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}};
    273 static uint64 *linkphy_frame_ctr
    274                [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX]
    275                [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}};
    276 
    277 
    278 #define BCM_LINKPHY_COUNTER_LOCK(unit) \
    279         sal_mutex_take(linkphy_ctr_mutex[unit], sal_mutex_FOREVER);
    280 #define BCM_LINKPHY_COUNTER_UNLOCK(unit) \
    281         sal_mutex_give(linkphy_ctr_mutex[unit]);
    282 
    283 static soc_mem_t linkphy_counter_table
    284          [_BCM_KT2_LINKPHY_DIRECTION_MAX][_BCM_KT2_LINKPHY_POOL_MAX] = {
    285              {RXLP_DEBUG_COUNTER8m,
    286               RXLP_DEBUG_COUNTER9m,
    287               RXLP_DEBUG_COUNTER10m,
    288               RXLP_DEBUG_COUNTER11m},
    289              {TXLP_DEBUG_COUNTER8m,
    290               TXLP_DEBUG_COUNTER9m,
    291               TXLP_DEBUG_COUNTER10m,
    292               TXLP_DEBUG_COUNTER11m}
    293              };
    294 
    295 typedef struct _bcm_subport_linkphy_rx_error_cb_info_s{
    296     bcm_subport_linkphy_rx_error_reg_info_t reg_info;
    297     void *user_data;
    298 }_bcm_subport_linkphy_rx_error_cb_info_t;
    299 
    300 _bcm_subport_linkphy_rx_error_cb_info_t _bcm_linkphy_rx_error_cb_info[bcmSubportLinkphyRxErrorCount] = {{{NULL, 0},NULL}};
    301 
    302 
    303 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_reg_field_map[bcmSubportLinkphyRxErrorCount] = {
    304     MAX_FRAME_SIZE_ERROR_INT_ENABLEf,
    305     RUNT_FRAME_INT_ENABLEf,
    306     DFC_LENGTH_ERROR_INT_ENABLEf,
    307     DFC_DROP_DUE_TO_PORT_PURGE_INT_ENABLEf,
    308     DFC_TIME_ERROR_INT_ENABLEf,
    309     DFC_OPCODE_ERROR_INT_ENABLEf,
    310     LENGTH_ZERO_INT_ENABLEf,
    311     LENGTH_LT_PAYLOAD_INT_ENABLEf,
    312     LENGTH_GT_PAYLOAD_INT_ENABLEf,
    313     FRAMING_ERROR_INT_ENABLEf,
    314     FRAME_CRC_ERROR_INT_ENABLEf,
    315     STREAM_ID_UNEXPECTED_INT_ENABLEf,
    316     MACSA_ERROR_INT_ENABLEf,
    317     MACDA_ERROR_INT_ENABLEf,
    318     ETHERTYPE_ERROR_INT_ENABLEf,
    319 };
    320 
    321 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_st_reg_field_map[bcmSubportLinkphyRxErrorCount] = {
    322     MAX_FRAME_SIZE_ERROR_INT_STATUSf,
    323     RUNT_FRAME_INT_STATUSf,
    324     DFC_LENGTH_ERROR_INT_STATUSf,
    325     DFC_DROP_DUE_TO_PORT_PURGE_INT_STATUSf,
    326     DFC_TIME_ERROR_INT_STATUSf,
    327     DFC_OPCODE_ERROR_INT_STATUSf,
    328     LENGTH_ZERO_INT_STATUSf,
    329     LENGTH_LT_PAYLOAD_INT_STATUSf,
    330     LENGTH_GT_PAYLOAD_INT_STATUSf,
    331     FRAMING_ERROR_INT_STATUSf,
    332     FRAME_CRC_ERROR_INT_STATUSf,
    333     STREAM_ID_UNEXPECTED_INT_STATUSf,
    334     MACSA_ERROR_INT_STATUSf,
    335     MACDA_ERROR_INT_STATUSf,
    336     ETHERTYPE_ERROR_INT_STATUSf,
    337 };
    338 
    339 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_dl_reg_field_map[bcmSubportLinkphyRxErrorCount] = {
    340     MAX_FRAME_SIZE_ERROR_LOG_ENABLEf,
    341     RUNT_FRAME_LOG_ENABLEf,
    342     DFC_LENGTH_ERROR_LOG_ENABLEf,
    343     DFC_DROP_DUE_TO_PORT_PURGE_LOG_ENABLEf,
    344     DFC_TIME_ERROR_LOG_ENABLEf,
    345     DFC_OPCODE_ERROR_LOG_ENABLEf,
    346     LENGTH_ZERO_LOG_ENABLEf,
    347     LENGTH_LT_PAYLOAD_LOG_ENABLEf,
    348     LENGTH_GT_PAYLOAD_LOG_ENABLEf,
    349     FRAMING_ERROR_LOG_ENABLEf,
    350     INVALIDf,
    351     STREAM_ID_UNEXPECTED_LOG_ENABLEf,
    352     MACSA_ERROR_LOG_ENABLEf,
    353     MACDA_ERROR_LOG_ENABLEf,
    354     ETHERTYPE_ERROR_LOG_ENABLEf,
    355 };
    356 
    357 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_dl_val_reg_field_map[bcmSubportLinkphyRxErrorCount] = {
    358     MAX_FRAME_SIZE_ERROR_LOG_VALIDf,
    359     RUNT_FRAME_INT_LOG_VALIDf,
    360     DFC_LENGTH_ERROR_INT_LOG_VALIDf,
    361     DFC_DROP_DUE_TO_PORT_PURGE_INT_LOG_VALIDf,
    362     DFC_TIME_ERROR_INT_LOG_VALIDf,
    363     DFC_OPCODE_ERROR_INT_LOG_VALIDf,
    364     LENGTH_ZERO_INT_LOG_VALIDf,
    365     LENGTH_LT_PAYLOAD_INT_LOG_VALIDf,
    366     LENGTH_GT_PAYLOAD_INT_LOG_VALIDf,
    367     FRAMING_ERROR_INT_LOG_VALIDf,
    368     INVALIDf,
    369     STREAM_ID_UNEXPECTED_INT_LOG_VALIDf,
    370     MACSA_ERROR_INT_LOG_VALIDf,
    371     MACDA_ERROR_INT_LOG_VALIDf,
    372     ETHERTYPE_ERROR_INT_LOG_VALIDf,
    373 };
    374 
    375 
    376 #define _BCM_KT2_SUBPORT_LINKPHY_RX_ERROR_VALID(lp_rx_error) ((lp_rx_error >= bcmSubportLinkphyRxErrorMaxFrameSize) &&\
    377                                                               (lp_rx_error < bcmSubportLinkphyRxErrorCount))
    378 
    379 int _bcm_linkphy_port_int_stream_id_base_get(int unit,
    380                                          bcm_port_t port,
    381                                          uint16 *int_stream_id_base);
    382 int _bcm_linkphy_port_ext_stream_id_base_get(int unit,
    383                                          bcm_port_t port,
    384                                          uint16 *ext_stream_id_base);
    385 STATIC int
    386 _bcm_linkphy_port_rx_int_stream_map_port_get(int unit,
    387                                              int port,
    388                                              uint16 ext_stream_id,
    389                                              uint16 *int_stream_id);
    390 
    391 int
    392 soc_linkphy_port_blk_idx_get(int unit, int port, int *block, int *index);
    393 
    394 int _bcm_kt2_subport_linkphy_rx_error_handler(
    395                 int unit, bcm_port_t port, uint32 rval);
    396 /*********************************
    397 * LinkPHY subport section -end
    398  */
    399 
    400 
    401 
    402 /*********************************
    403 * Subport common  section - start
    404  */
    405 
    406 
    407 /* Get port number/trunk id associated with subport_group gport*/
    408 #define _BCM_KT2_SUBPORT_GROUP_PORT_GET(_subport_group) \
    409             _BCM_SUBPORT_COE_GROUP_PORT_GET(_subport_group)
    410 
    411 /* Get group id associated with subport_group gport*/
    412 #define _BCM_KT2_SUBPORT_GROUP_ID_GET(_subport_group) \
    413             _BCM_SUBPORT_COE_GROUP_ID_GET(_subport_group)
    414 
    415 #define _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(_subport_group) \
    416             _BCM_SUBPORT_COE_GROUP_TYPE_CASCADED_SET(_subport_group)
    417                          
    418 #define _BCM_KT2_SUBPORT_LOCK(unit) \
    419              _BCM_SUBPORT_COE_LOCK(unit);
    420 
    421 #define _BCM_KT2_SUBPORT_UNLOCK(unit) \
    422              _BCM_SUBPORT_COE_UNLOCK(unit);
    423 
    424 #define _BCM_KT2_SUBPORT_CHECK_INIT(_unit_) \
    425              _BCM_SUBPORT_COE_CHECK_INIT(_unit_);
    426 
    427 /*
    428  * Subport group usage bitmap operations
    429  */
    430 #define _BCM_KT2_SUBPORT_GROUP_USED_GET(_u_, _group_) \
    431                 _BCM_SUBPORT_COE_GROUP_USED_GET(_u_, _group_)
    432 
    433 #define _BCM_KT2_SUBPORT_GROUP_USED_SET(_u_, _group_) \
    434                 _BCM_SUBPORT_COE_GROUP_USED_SET(_u_, _group_)
    435 
    436 #define _BCM_KT2_SUBPORT_GROUP_USED_CLR(_u_, _group_) \
    437                 _BCM_SUBPORT_COE_GROUP_USED_CLR(_u_, _group_)
    438 
    439 #define _BCM_KT2_SUBPORT_PP_PORT_USED_GET(_u_, _pp_port_) \
    440                 SHR_BITGET(_bcm_subport_pp_port_bitmap[_u_], (_pp_port_))
    441 
    442 #define _BCM_KT2_SUBPORT_PP_PORT_USED_SET(_u_, _pp_port_) \
    443                 SHR_BITSET(_bcm_subport_pp_port_bitmap[_u_], (_pp_port_))
    444 
    445 #define _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(_u_, _pp_port_) \
    446                 SHR_BITCLR(_bcm_subport_pp_port_bitmap[_u_], (_pp_port_))
    447 
    448 
    449 /*********************************
    450 * Subport common  section - end
    451  */
    452 
    453 /*********************************
    454 * General subport section - start
    455  */
    456 
    457 /* Set the general subport group gport */
    458 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_SET(_subport_group, \
    459                                            _port, _gid) \
    460     _BCM_GENERAL_SUBPORT_GROUP_SET(_subport_group, \
    461                                    _port, _gid)
    462 
    463 /* General subport group usage bitmap operations */
    464 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(_u_, _group_) \
    465     _BCM_GENERAL_SUBPORT_GROUP_USED_GET(_u_, _group_)
    466 
    467 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_SET(_u_, _group_) \
    468     _BCM_GENERAL_SUBPORT_GROUP_USED_SET(_u_, _group_)
    469 
    470 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_CLR(_u_, _group_) \
    471     _BCM_GENERAL_SUBPORT_GROUP_USED_CLR(_u_, _group_)
    472 
    473 #define _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port) \
    474     (_bcm_general_subport_port_info[unit][pp_port].valid)
    475 
    476 #define _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port) \
    477     (_bcm_general_subport_port_info[unit][pp_port].group)
    478 
    479 #define _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_SET(unit, pp_port,\
    480                                                sp_group, is_valid) \
    481 { \
    482     _bcm_general_subport_port_info[unit][pp_port].group = sp_group; \
    483     _bcm_general_subport_port_info[unit][pp_port].valid = is_valid; \
    484 }
    485 
    486 /*********************************
    487 * General subport section - end
    488  */
    489 
    490 /*********************************
    491 * SubTag subport section - start
    492  */
    493 
    494 /* Set the SubTag subport group gport */
    495 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_SET(_subport_group, \
    496                                           _port, _gid) \
    497              _BCM_SUBPORT_COE_SUBTAG_GROUP_SET(_subport_group, \
    498                                           _port, _gid)
    499 
    500 /*
    501  * SubTag subport group usage bitmap operations
    502  */
    503 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(_u_, _group_) \
    504              _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_GET(_u_, _group_)
    505 
    506 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_SET(_u_, _group_) \
    507              _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_SET(_u_, _group_)
    508 
    509 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_CLR(_u_, _group_) \
    510              _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_CLR(_u_, _group_)
    511 
    512 /* Katana2 SubTag VLAN id usage bitmap for given port*/
    513 #define _BCM_KT2_SUBTAG_VLAN_ID_USED_GET(_u_, _p, _vlan_id_) \
    514              _BCM_COE_SUBTAG_VLAN_ID_USED_GET(_u_, _p, _vlan_id_)
    515 
    516 #define _BCM_KT2_SUBTAG_VLAN_ID_USED_SET(_u_, _p, _vlan_id_) \
    517              _BCM_COE_SUBTAG_VLAN_ID_USED_SET(_u_, _p, _vlan_id_)
    518 
    519 #define _BCM_KT2_SUBTAG_VLAN_ID_USED_CLR(_u_, _p, _vlan_id_) \
    520              _BCM_COE_SUBTAG_VLAN_ID_USED_CLR(_u_, _p, _vlan_id_)
    521 
    522 
    523 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port) \
    524     (_bcm_subtag_subport_port_info[unit][pp_port].valid)
    525 
    526 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port) \
    527     (_bcm_subtag_subport_port_info[unit][pp_port].group)
    528 
    529 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port) \
    530     (_bcm_subtag_subport_port_info[unit][pp_port].vlan)
    531 
    532 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, pp_port) \
    533     (_bcm_subtag_subport_port_info[unit][pp_port].subtag_tcam_hw_idx)
    534 
    535 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port,\
    536         sp_group, vlan_id, tcam_hw_id, is_valid) \
    537 { \
    538     _bcm_subtag_subport_port_info[unit][pp_port].group = sp_group; \
    539     _bcm_subtag_subport_port_info[unit][pp_port].vlan = vlan_id; \
    540     _bcm_subtag_subport_port_info[unit] \
    541                                  [pp_port].subtag_tcam_hw_idx = tcam_hw_id; \
    542     _bcm_subtag_subport_port_info[unit][pp_port].valid = is_valid; \
    543 }
    544 
    545 
    546 /*********************************
    547 * SubTag subport section - end
    548  */
    549 
    550 /* prototypes - start */
    551 STATIC int
    552 _bcm_linkphy_subport_port_get(int unit,
    553                              bcm_gport_t subport_port_gport,
    554                              bcm_subport_config_t *config);
    555 
    556 STATIC int
    557 _bcm_linkphy_subport_port_delete(int unit,
    558                                 bcm_gport_t subport_port_gport);
    559 
    560 STATIC int
    561 _bcm_subtag_subport_port_get(int unit,
    562                              bcm_gport_t subport_port_gport,
    563                              bcm_subport_config_t *config);
    564 
    565 STATIC int
    566 _bcm_subtag_subport_port_delete(int unit,
    567                                 bcm_gport_t subport_port_gport);
    568 
    569 STATIC int
    570 _bcm_general_subport_port_get(int unit,
    571                               bcm_gport_t subport_port_gport,
    572                               bcm_subport_config_t *config);
    573 
    574 STATIC int
    575 _bcm_general_subport_port_delete(int unit,
    576                                  bcm_gport_t subport_port_gport);
    577 
    578 #ifdef BCM_WARM_BOOT_SUPPORT
    579 
    580 #define SCACHE_ALLOC_SIZE_INIT(_var_)                                          \
    581     do {                                                                       \
    582         (_var_) = 0; (_scache_ofst_) = 0;                                      \
    583         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                        \
    584             (BSL_META_U(unit,                                                  \
    585                         "WarmBoot: Scache offset initialized to 0\n")));       \
    586     } while (0);
    587 
    588 #define SCACHE_ALLOC_SIZE_INCR(_var_, _count_)                                 \
    589     do {                                                                       \
    590         (_var_) += (_count_); (_scache_ofst_) += (_count_);                    \
    591         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                        \
    592                     (BSL_META_U(unit,                                          \
    593                                 "WarmBoot: Scache offset incr by %d to %d\n"), \
    594                                 (int)(_count_),  (_scache_ofst_)              \
    595                                ));                                            \
    596     } while (0);
    597 
    598 #define SCACHE_BYTE_INIT(_scache_ptr_)                                         \
    599     do {                                                                       \
    600         _scache_ofst_ = 0;                                                     \
    601         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                        \
    602                     (BSL_META_U(unit,                                          \
    603                                 "WarmBoot: Scache offset initialized to 0\n")  \
    604                                ));                                            \
    605     } while (0);
    606 
    607 #define SCACHE_BYTE_COPY(_scache_ptr_, _local_var_, _size_)                   \
    608     do {                                                                      \
    609         sal_memcpy(_scache_ptr_, _local_var_, _size_);                        \
    610         _scache_ptr_ += (_size_);                                             \
    611         (_scache_ofst_) += (_size_);                                          \
    612         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                       \
    613                     (BSL_META_U(unit,                                         \
    614                                 "WarmBoot: Scache offset incr by %d to %d\n"),\
    615                                 (int)(_size_),  (_scache_ofst_)              \
    616                                ));                                           \
    617     } while (0);
    618 
    619 #define SCACHE_BYTE_RESTORE(_scache_ptr_, _local_var_, _size_)                \
    620     do {                                                                      \
    621         sal_memcpy(_local_var_, _scache_ptr_, _size_);                        \
    622         _scache_ptr_ += (_size_);                                             \
    623         (_scache_ofst_) += (_size_);                                          \
    624         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,                                       \
    625                     (BSL_META_U(unit,                                         \
    626                                 "WarmBoot: Scache offset incr by %d to %d\n"),\
    627                                 (int)(_size_),  (_scache_ofst_)              \
    628                                ));                                           \
    629     } while (0);
    630 
    631 int
    632 bcm_kt2_subport_wb_scache_alloc(int unit, uint16 version, int *alloc_sz)
    633 {
    634     int subport_group_max = SOC_INFO(unit).subport_group_max;
    635     int pp_port_index_max = SOC_INFO(unit).pp_port_index_max;
    636     uint32 _scache_ofst_ = 0;
    637 
    638     SCACHE_ALLOC_SIZE_INIT(*alloc_sz);
    639 
    640     /* Num subport groups */
    641     SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int));
    642 
    643     /* Num pp ports */
    644     SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int));
    645 
    646     /* Subport-group bitmap */
    647     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    648         SHR_BITALLOCSIZE(subport_group_max));
    649 
    650     /* Subport pp_port bitmap */
    651     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    652         SHR_BITALLOCSIZE(pp_port_index_max + 1));
    653 
    654     /* Num subtag groups */
    655     SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int));
    656 
    657     /* Subtag group bitmap */
    658     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    659         SHR_BITALLOCSIZE(subport_group_max));
    660 
    661     /* pp_port to subport group info */
    662     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    663         (sizeof(bcm_gport_t) * SOC_MAX_NUM_PP_PORTS));
    664 
    665     /* Num linkphy group  */
    666     SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int));
    667 
    668     /* linkphy group bitmap */
    669     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    670         SHR_BITALLOCSIZE(subport_group_max));
    671 
    672     /* linkphy subports info */
    673     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    674         (sizeof(bcm_gport_t) * SOC_MAX_NUM_PP_PORTS)); /* group */
    675     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    676         (sizeof(uint16) * SOC_MAX_NUM_PP_PORTS));      /* valid */
    677     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    678         (sizeof(uint16) * SOC_MAX_NUM_PP_PORTS));      /* num_streams */
    679     SCACHE_ALLOC_SIZE_INCR(*alloc_sz,
    680         (2 * sizeof(uint16) * SOC_MAX_NUM_PP_PORTS));  /* streams */
    681 
    682     if (version >= BCM_SUBPORT_WB_VERSION_1_1) {
    683         /* Enabled_subtag pbm */
    684         SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(pbmp_t));
    685         /* Enabled_linkphy pbm */
    686         SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(pbmp_t));
    687     }
    688 
    689 
    690     return BCM_E_NONE;
    691 }
    692 
    693 int
    694 bcm_kt2_subport_wb_sync(int unit, uint16 version, uint8 **scache_ptr)
    695 {
    696     int index, value;
    697     uint16 value16;
    698     int subport_group_max = SOC_INFO(unit).subport_group_max;
    699     int pp_port_index_max = SOC_INFO(unit).pp_port_index_max;
    700     uint32 _scache_ofst_ = 0;
    701 
    702     SCACHE_BYTE_INIT(*scache_ptr);
    703 
    704     /* Num subport groups */
    705     value = _bcm_subport_group_count[unit];
    706     SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int));
    707 
    708     /* Num pp ports */
    709     value = _bcm_subport_pp_port_count[unit];
    710     SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int));
    711 
    712     /* Subport-group bitmap */
    713     SCACHE_BYTE_COPY(*scache_ptr, _bcm_subport_group_bitmap[unit],
    714                       SHR_BITALLOCSIZE(subport_group_max));
    715 
    716     /* Subport pp_port bitmap */
    717     SCACHE_BYTE_COPY(*scache_ptr, _bcm_subport_pp_port_bitmap[unit],
    718                       SHR_BITALLOCSIZE(pp_port_index_max + 1));
    719 
    720     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) {
    721         /* Num subtag groups */
    722         value = _bcm_subtag_subport_group_count[unit];
    723         SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int));
    724 
    725         /* Subtag group bitmap */
    726         SCACHE_BYTE_COPY(*scache_ptr, _bcm_subtag_group_bitmap[unit],
    727                           SHR_BITALLOCSIZE(subport_group_max));
    728 
    729         /* pp_port to subport group info */
    730         for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) {
    731             SCACHE_BYTE_COPY(*scache_ptr,
    732                            &(_bcm_subtag_subport_port_info[unit][index].group),
    733                               sizeof(bcm_gport_t));
    734         }
    735     }
    736 
    737     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).linkphy_allowed_pbm)) {
    738         /* Num linkphy group  */
    739         value = _bcm_linkphy_subport_group_count[unit];
    740         SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int));
    741 
    742         /* linkphy group bitmap */
    743         SCACHE_BYTE_COPY(*scache_ptr, _bcm_linkphy_group_bitmap[unit],
    744                           SHR_BITALLOCSIZE(subport_group_max));
    745 
    746         /* linkphy subports info */
    747         for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) {
    748             value = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, index);
    749             SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(bcm_gport_t));
    750 
    751             value16 = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, index);
    752             SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16));
    753 
    754             value16 =
    755                 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, index);
    756             SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16));
    757 
    758             value16 = 
    759                 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(unit,
    760                                                                      index, 0);
    761             SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16));
    762 
    763             value16 =
    764                 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(unit,
    765                                                                      index, 1);
    766             SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16));
    767 
    768         }
    769     }
    770 
    771     if (version >= BCM_SUBPORT_WB_VERSION_1_1) {
    772         SCACHE_BYTE_COPY(*scache_ptr, &(SOC_INFO(unit).enabled_subtag_pp_port_pbm),
    773                 sizeof(pbmp_t));
    774         SCACHE_BYTE_COPY(*scache_ptr, &(SOC_INFO(unit).enabled_linkphy_pp_port_pbm),
    775                 sizeof(pbmp_t));
    776     }
    777 
    778     return BCM_E_NONE;
    779 }
    780 
    781  /* Function:
    782  *      bcm_kt2_port_control_subtag_linkphy_pbm_recover
    783  * Description:
    784  *      Retrieve the subtag_pbm from hw to SOC_INFO->subtag_pbm
    785  * Parameters:
    786  *      unit  - (IN) Device number
    787  * Return Value:
    788  *      BCM_E_XXX
    789  */
    790 
    791 int bcm_kt2_port_control_subtag_linkphy_pbm_recover(int unit)
    792 {
    793     int rv = BCM_E_NONE;
    794     soc_mem_t mem;
    795     soc_info_t *si = &SOC_INFO(unit);
    796     ing_physical_port_table_entry_t ing_physical_port_entry;
    797     bcm_port_t port;
    798 
    799     if (!soc_feature(unit, soc_feature_subtag_coe)) {
    800         return rv;
    801     }
    802 
    803     mem = ING_PHYSICAL_PORT_TABLEm;
    804 
    805     _BCM_KT2_SUBPORT_LOCK(unit);
    806 
    807     BCM_PBMP_ITER(PBMP_ALL(unit), port) {
    808 
    809         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
    810                 &ing_physical_port_entry);
    811         if (SOC_FAILURE(rv)) {
    812             LOG_ERROR(BSL_LS_BCM_SUBPORT,
    813                   (BSL_META_U(unit,
    814                           "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n")));
    815             _BCM_KT2_SUBPORT_UNLOCK(unit);
    816             return rv;
    817         }
    818         if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
    819                 PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED) {
    820             if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
    821                         CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) {
    822                 BCM_PBMP_PORT_ADD(si->subtag_pbm, port);
    823                 BCM_PBMP_PORT_ADD(si->subtag.bitmap, port);
    824             } else if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
    825                         CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY) {
    826                 BCM_PBMP_PORT_ADD(si->linkphy_pbm, port);
    827                 BCM_PBMP_PORT_ADD(si->lp.bitmap, port);
    828             }
    829         }
    830     }
    831 
    832     _BCM_KT2_SUBPORT_UNLOCK(unit);
    833 
    834     return rv;
    835 }
    836 
    837 
    838 
    839 
    840 int
    841 bcm_kt2_subport_wb_recover(int unit, uint16 version, uint8 **scache_ptr)
    842 {
    843     bcm_gport_t group;
    844     int length, pp_port, index, rv = BCM_E_NONE;
    845     int subport_group_max = SOC_INFO(unit).subport_group_max;
    846     int pp_port_index_max = SOC_INFO(unit).pp_port_index_max;
    847     uint32 _scache_ofst_ = 0;
    848     soc_info_t *si = &SOC_INFO(unit);
    849 
    850     SCACHE_BYTE_INIT(*scache_ptr);
    851 
    852     /* Recover subtag_pbm from hw */
    853     rv = bcm_kt2_port_control_subtag_linkphy_pbm_recover(unit);
    854     SOC_IF_ERROR_RETURN(rv);
    855 
    856     /* Num subport groups */
    857     SCACHE_BYTE_RESTORE(*scache_ptr,
    858                          &_bcm_subport_group_count[unit], sizeof(int));
    859 
    860     /* Num pp ports */
    861     SCACHE_BYTE_RESTORE(*scache_ptr,
    862                          &_bcm_subport_pp_port_count[unit], sizeof(int));
    863 
    864     /* Subport group bitmap */
    865     SCACHE_BYTE_RESTORE(*scache_ptr,
    866                         _bcm_subport_group_bitmap[unit],
    867                         SHR_BITALLOCSIZE(subport_group_max));
    868 
    869 
    870     /* Subport pp_port bitmap */
    871     SCACHE_BYTE_RESTORE(*scache_ptr,
    872                         _bcm_subport_pp_port_bitmap[unit],
    873                         SHR_BITALLOCSIZE(pp_port_index_max + 1));
    874 
    875 
    876     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) {
    877         soc_mem_t mem;
    878         int start, end;
    879         subport_tag_to_pp_port_map_entry_t entry;
    880 
    881         /* Num subtag groups */
    882         SCACHE_BYTE_RESTORE(*scache_ptr,
    883                            &_bcm_subtag_subport_group_count[unit], sizeof(int));
    884 
    885         /* Subtag group bitmap */
    886         SCACHE_BYTE_RESTORE(*scache_ptr,
    887                              _bcm_subtag_group_bitmap[unit],
    888                              SHR_BITALLOCSIZE(subport_group_max));
    889 
    890         mem = SUBPORT_TAG_TO_PP_PORT_MAPm;
    891         start = soc_mem_index_min(unit, mem);
    892         end = soc_mem_index_max(unit, mem);
    893 
    894         length = sizeof(bcm_gport_t);
    895         for (index = start; index <= end; index++) {
    896 
    897             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry);
    898             SOC_IF_ERROR_RETURN(rv);
    899 
    900             if (soc_mem_field32_get(unit, mem, &entry, VALIDf)) {
    901 
    902                 pp_port = soc_mem_field32_get(unit, mem, &entry, PP_PORTf);
    903                 sal_memcpy(&group, (*scache_ptr + (pp_port * length)), length);
    904 
    905                 _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port);
    906                 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port, group,
    907                     soc_mem_field32_get(unit, mem, &entry, SUBPORT_TAGf),
    908                     index, TRUE);
    909 
    910                 _BCM_KT2_SUBTAG_VLAN_ID_USED_SET(unit,
    911                     soc_mem_field32_get(unit, mem, &entry, PHYSICAL_PORTf),
    912                     _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port));
    913 
    914                 _bcm_subport_group_subport_port_count[unit]
    915                     [_BCM_KT2_SUBPORT_GROUP_ID_GET(group)] += 1;
    916             }
    917         }
    918         *scache_ptr += (length * SOC_MAX_NUM_PP_PORTS);
    919     }
    920 
    921     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).linkphy_allowed_pbm)) {
    922         uint16 valid = 0, num_streams = 0;
    923         uint16 stream_id_1 = 0, stream_id_2 = 0;
    924 
    925         /* Num linkphy groups */
    926         SCACHE_BYTE_RESTORE(*scache_ptr,
    927                          &_bcm_linkphy_subport_group_count[unit], sizeof(int));
    928 
    929         /* linkphy group bitmap */
    930         SCACHE_BYTE_RESTORE(*scache_ptr,
    931                              _bcm_linkphy_group_bitmap[unit],
    932                              SHR_BITALLOCSIZE(subport_group_max));
    933 
    934 
    935         /* linkphy subport info */
    936         for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) {
    937             SCACHE_BYTE_RESTORE(*scache_ptr,
    938                                  &group, sizeof(bcm_gport_t));
    939 
    940             SCACHE_BYTE_RESTORE(*scache_ptr,
    941                                  &valid, sizeof(uint16));
    942 
    943             SCACHE_BYTE_RESTORE(*scache_ptr,
    944                                  &num_streams, sizeof(uint16));
    945 
    946             SCACHE_BYTE_RESTORE(*scache_ptr,
    947                                  &stream_id_1, sizeof(uint16));
    948 
    949             SCACHE_BYTE_RESTORE(*scache_ptr,
    950                                  &stream_id_2, sizeof(uint16));
    951 
    952 
    953             _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, index, group,
    954                                                    num_streams, valid);
    955             _bcm_linkphy_subport_port_info[unit][index].ext_stream_idx[0] = 
    956                                                         stream_id_1;
    957             if (num_streams > 1) {
    958                 _bcm_linkphy_subport_port_info[unit][index].ext_stream_idx[1] =
    959                     stream_id_2;
    960             }
    961 
    962             if (valid) {
    963                 int rv;
    964                 bcm_port_t port;
    965                 uint16 dev_int_stream_id_1 = 0, dev_int_stream_id_2 = 0;
    966                 uint16 int_stream_id_base = 0, ext_stream_id_base = 0;
    967                 uint16 port_e_stream_id_base_adj_1 = 0;
    968                 uint16 port_e_stream_id_base_adj_2 = 0;
    969                 uint16 blk_i_stream_id_1 = 0;
    970                 uint16 blk_i_stream_id_2 = 0;
    971                 uint16 blk_port_idx_i_stream_id_1 = 0;
    972                 uint16 blk_port_idx_i_stream_id_2 = 0;
    973                 uint16 dev_int_stream_id_base = 0;
    974                 port = ((group >> _BCM_KT2_SUBPORT_GROUP_PORT_SHIFT) &
    975                         _BCM_KT2_SUBPORT_GROUP_PORT_MASK);
    976 
    977                 rv = _bcm_linkphy_port_int_stream_id_base_get(unit, port, 
    978                                                          &int_stream_id_base);
    979                 BCM_IF_ERROR_RETURN(rv);
    980 
    981                 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 
    982                                                          &ext_stream_id_base);
    983                 BCM_IF_ERROR_RETURN(rv);
    984 
    985                 port_e_stream_id_base_adj_1 = stream_id_1 - ext_stream_id_base;
    986 
    987                 if (num_streams > 1) {
    988                     port_e_stream_id_base_adj_2 = stream_id_2 - ext_stream_id_base;
    989                 }
    990 
    991                 BCM_IF_ERROR_RETURN(
    992                     _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port,
    993                                                   port_e_stream_id_base_adj_1,
    994                                                   &blk_i_stream_id_1));
    995                 if (num_streams > 1) {
    996                     BCM_IF_ERROR_RETURN(
    997                             _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port,
    998                                 port_e_stream_id_base_adj_2,
    999                                 &blk_i_stream_id_2));
   1000                 }
   1001 
   1002 #if defined(BCM_METROLITE_SUPPORT)
   1003                 if (SOC_IS_METROLITE(unit)) {
   1004                     /* Index for _bcm_ml_int_stream_id_pool runs from 0 to 3,
   1005                      * whereas port runs from 1 to 4. Hence doing port -1
   1006                      * to index the pool
   1007                      */
   1008                     /* Reserve those internal streams in that port's pool. */
   1009                     BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(
   1010                                 _bcm_ml_int_stream_id_pool[unit][port-1],
   1011                                 blk_i_stream_id_1, blk_i_stream_id_1));
   1012                     if (num_streams > 1) {
   1013                         BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(
   1014                                     _bcm_ml_int_stream_id_pool[unit][port-1],
   1015                                     blk_i_stream_id_2, blk_i_stream_id_2));
   1016                     }
   1017                 } else
   1018 #endif
   1019 #if defined(BCM_SABER2_SUPPORT)
   1020                 if (SOC_IS_SABER2(unit)) {
   1021                     /* Index for _bcm_sb2_int_stream_id_pool runs from 0 to 3,
   1022                      * whereas port runs from 1 to 4. Hence doing port -1
   1023                      * to index the pool
   1024                      */
   1025                     /* Reserve those internal streams in that port's pool. */
   1026                     BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(
   1027                                   _bcm_sb2_int_stream_id_pool[unit][port-1],
   1028                                   blk_i_stream_id_1, blk_i_stream_id_1));
   1029                     if (num_streams > 1) {
   1030                         BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(
   1031                                    _bcm_sb2_int_stream_id_pool[unit][port-1],
   1032                                    blk_i_stream_id_2, blk_i_stream_id_2));
   1033                     }
   1034                 } else
   1035 #endif
   1036                 {
   1037                     int lp_block, lp_index;
   1038                     /* get the block and index for the LinkPHY memory */
   1039                     rv = soc_linkphy_port_blk_idx_get(unit, port, 
   1040                                                       &lp_block, &lp_index);
   1041                     if (BCM_FAILURE(rv)) {
   1042                         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1043                                  (BSL_META_U(unit,
   1044                                  "ERROR: LinkPHY block, index get failed "
   1045                                  "for port %d\n"), port));
   1046                         return rv;
   1047                     }
   1048                     dev_int_stream_id_base = (lp_block)? 128: 0;
   1049                     blk_port_idx_i_stream_id_1 = blk_i_stream_id_1 -
   1050                                                  (si->port_linkphy_s1_base[port]
   1051                                                  - dev_int_stream_id_base);
   1052                     BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(
   1053                                _bcm_kt2_blk_int_stream_id_pool[unit][lp_block]
   1054                                                               [lp_index],
   1055                                blk_port_idx_i_stream_id_1, blk_port_idx_i_stream_id_1));
   1056                     if (num_streams > 1) {
   1057                         blk_port_idx_i_stream_id_2 = blk_i_stream_id_2 -
   1058                                                  (si->port_linkphy_s1_base[port]
   1059                                                  - dev_int_stream_id_base);
   1060                         BCM_IF_ERROR_RETURN(shr_idxres_list_reserve(
   1061                                _bcm_kt2_blk_int_stream_id_pool[unit][lp_block]
   1062                                                               [lp_index],
   1063                                blk_port_idx_i_stream_id_2,
   1064                                blk_port_idx_i_stream_id_2));
   1065                     }
   1066                 }
   1067 
   1068                 dev_int_stream_id_1 = blk_i_stream_id_1 + int_stream_id_base;
   1069                 if (num_streams > 1) {
   1070                     dev_int_stream_id_2 = blk_i_stream_id_2 +
   1071                                           int_stream_id_base;
   1072                 }
   1073 
   1074                 _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(unit, 
   1075                                                            dev_int_stream_id_1);
   1076                 if (num_streams > 1) {
   1077                     _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(unit,
   1078                                                            dev_int_stream_id_2);
   1079                 }
   1080 
   1081                 _bcm_subport_group_subport_port_count[unit]
   1082                     [_BCM_KT2_SUBPORT_GROUP_ID_GET(group)] += 1;
   1083             }
   1084         }
   1085     }
   1086 
   1087     if (version >= BCM_SUBPORT_WB_VERSION_1_1) {
   1088         SCACHE_BYTE_RESTORE(*scache_ptr,
   1089                 &(si->enabled_subtag_pp_port_pbm), sizeof(pbmp_t));
   1090         SCACHE_BYTE_RESTORE(*scache_ptr,
   1091                 &(si->enabled_linkphy_pp_port_pbm), sizeof(pbmp_t));
   1092     }
   1093     return BCM_E_NONE;
   1094 }
   1095 
   1096 
   1097 #endif /* BCM_WARM_BOOT_SUPPORT */
   1098 
   1099 /* prototypes - end */
   1100 
   1101 
   1102 /***********************************
   1103 * LinkPHY helper functions - start *
   1104  */
   1105 
   1106 STATIC int
   1107 _bcm_linkphy_reg_mac_addr_set(int unit, bcm_port_t port,
   1108                         soc_reg_t reg, soc_field_t field,
   1109                         bcm_mac_t mac) 
   1110 {
   1111     uint64 val, tmp, regval;
   1112     int i;
   1113 
   1114     COMPILER_64_ZERO(val);
   1115     COMPILER_64_ZERO(tmp);
   1116     COMPILER_64_ZERO(regval);
   1117 
   1118     for (i = 0; i < 6; i++) {
   1119         COMPILER_64_SET(tmp, 0, mac[i]);
   1120         COMPILER_64_SHL(val, 8);
   1121         COMPILER_64_OR(val, tmp);
   1122     }
   1123     BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &regval));
   1124     soc_reg64_field_set(unit, reg, &regval, field, val);
   1125     return soc_reg_set(unit, reg, port, 0, regval);
   1126 }
   1127 
   1128 STATIC int
   1129 _bcm_linkphy_reg_mac_addr_get(int unit, bcm_port_t port,
   1130                         soc_reg_t reg, soc_field_t field,
   1131                         bcm_mac_t mac)
   1132 {
   1133     uint64 regval, data;
   1134     uint32 msw;
   1135     uint32 lsw;
   1136 
   1137     COMPILER_64_ZERO(data);
   1138     COMPILER_64_ZERO(regval);
   1139 
   1140     BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &regval));
   1141     data = soc_reg64_field_get(unit, reg, regval, field);
   1142     COMPILER_64_TO_32_HI(msw, data);
   1143     COMPILER_64_TO_32_LO(lsw, data);
   1144 
   1145     mac[0] = (uint8) ( ( msw & 0x0000ff00 ) >> 8 );
   1146     mac[1] = (uint8) ( msw & 0x000000ff );
   1147 
   1148     mac[2] = (uint8)  ( ( lsw & 0xff000000) >> 24 );
   1149     mac[3] = (uint8)  ( ( lsw & 0x00ff0000) >> 16 );
   1150     mac[4] = (uint8)  ( ( lsw & 0x0000ff00) >> 8 );
   1151     mac[5] = (uint8)  ( lsw & 0x000000ff );
   1152 
   1153     return BCM_E_NONE;
   1154 }
   1155 
   1156 int
   1157 _bcm_linkphy_port_ext_stream_id_base_get(int unit,
   1158                                          bcm_port_t port,
   1159                                          uint16 *ext_stream_id_base)
   1160 {
   1161     uint32 regval = 0;
   1162     soc_reg_t reg = RXLP_PORT_STREAM_ID_BASEr;
   1163     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   1164         SOC_IF_ERROR_RETURN(
   1165             READ_RXLP_PORT_STREAM_ID_BASEr(unit, port, &regval));
   1166         *ext_stream_id_base = soc_reg_field_get(unit, reg, regval, BASEf);
   1167     }
   1168     return BCM_E_NONE;
   1169 }
   1170 
   1171 int
   1172 _bcm_linkphy_port_int_stream_id_base_get(int unit,
   1173                                          bcm_port_t port,
   1174                                          uint16 *int_stream_id_base)
   1175 {
   1176     uint32 regval = 0;
   1177     soc_reg_t reg = RXLP_INT_STREAM_ID_BASEr;
   1178     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   1179         SOC_IF_ERROR_RETURN(READ_RXLP_INT_STREAM_ID_BASEr(unit, port, &regval));
   1180         *int_stream_id_base = soc_reg_field_get(unit, reg, regval, BASEf);
   1181     }
   1182     return BCM_E_NONE;
   1183 }
   1184 
   1185 int soc_linkphy_port_blk_idx_get(
   1186             int unit, int port, int *block, int *index) {
   1187 #if defined(BCM_METROLITE_SUPPORT)
   1188     if (SOC_IS_METROLITE(unit)) {
   1189         SOC_IF_ERROR_RETURN(
   1190             soc_ml_linkphy_port_blk_idx_get(unit, port, block, index));
   1191     } else
   1192 #endif
   1193 #if defined(BCM_SABER2_SUPPORT)
   1194    if(SOC_IS_SABER2(unit)) {
   1195       SOC_IF_ERROR_RETURN(
   1196                 soc_sb2_linkphy_port_blk_idx_get(unit, port, block, index));
   1197     } else
   1198 #endif
   1199  if (SOC_IS_KATANA2(unit)) {
   1200      SOC_IF_ERROR_RETURN(
   1201                 soc_kt2_linkphy_port_blk_idx_get(unit, port, block, index));
   1202   }
   1203   return SOC_E_NONE;
   1204 }
   1205 
   1206 /*
   1207 * Set or clear the valid streams on a sub-port of a port-interface
   1208 * in a bitmap format.
   1209 * Each bit set indicates that SID being part of that port.
   1210 * Note that same stream cannot be enabled on more than one sub-port.
   1211 * When the port is in LP-mode, then Stream-ID for that sub-port is 
   1212 * in Range [0-127] only.
   1213 * Sub-ports cannot be dyncamically changed to LP->NonLP and vice-versa
   1214 * without resetting the entire block.
   1215 * However in LP-mode, streams could get added dynamically to a port.
   1216 */
   1217 
   1218 STATIC int
   1219 _bcm_linkphy_port_tx_active_stream_set(int unit,
   1220                                        bcm_port_t port,
   1221                                        uint16 int_stream_id,
   1222                                        int enable)
   1223 {
   1224     soc_mem_t mem;
   1225     int rv = BCM_E_NONE, lp_index = 0, lp_block = 0, copyno = 0;
   1226     int field_word = 0, bit_pos = 0;
   1227     uint32 fldbuf[4] = { 0 };
   1228     txlp_port_stream_bitmap_table_entry_t txlp_port_stream_bitmap;
   1229 
   1230     /* Set Active Stream ID
   1231     *  Use TXLP_PORT_STREAM_BITMAP_TABLE
   1232     *  This is a per-LP block, per-LP port memory.
   1233     *  KT2 has 2 LP block and 4 LP ports per LP block
   1234     */
   1235 
   1236     mem = TXLP_PORT_STREAM_BITMAP_TABLEm;
   1237     if (SOC_MEM_FIELD_VALID(unit, mem, STREAM_BITMAPf)) {
   1238         /* get the block and index for the LinkPHY memory */
   1239         rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index);
   1240         if (SOC_FAILURE(rv)) {
   1241             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1242                       (BSL_META_U(unit,
   1243                                   
   1244                                    "ERROR: LinkPHY block, index get failed for port %d\n"), port));
   1245             return rv;
   1246         }
   1247 
   1248         copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block;
   1249         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, lp_index,
   1250             &txlp_port_stream_bitmap));
   1251         soc_mem_field_get(unit, mem, (uint32 *)&txlp_port_stream_bitmap,
   1252                  STREAM_BITMAPf, fldbuf);
   1253 
   1254         field_word = int_stream_id / 32;
   1255         bit_pos  = int_stream_id % 32;
   1256         if (enable) {
   1257              fldbuf[field_word] |= (1 << bit_pos);
   1258         } else {
   1259              fldbuf[field_word] &= ~(1 << bit_pos);
   1260         }
   1261         soc_mem_field_set(unit, mem, (uint32 *)&txlp_port_stream_bitmap,
   1262                         STREAM_BITMAPf, fldbuf);
   1263         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno,
   1264                     lp_index, &txlp_port_stream_bitmap));
   1265     }
   1266 
   1267     return rv;
   1268 }
   1269 
   1270 /* Map the Internal-SID(7b) to External-SID(10b) */
   1271 STATIC int
   1272 _bcm_linkphy_port_tx_int_to_ext_stream_map_set(int unit,
   1273                                                int port,
   1274                                                uint16 ext_stream_id,
   1275                                                uint16 int_stream_id,
   1276                                                int enable)
   1277 {
   1278     int rv = BCM_E_NONE;
   1279     soc_mem_t mem;
   1280     int copyno = 0, lp_block = 0, lp_index = 0;
   1281     txlp_int2ext_stream_map_table_entry_t txlp_int2ext_stream_map;
   1282 
   1283     /* Map Internal Stream ID to External Stream ID 
   1284     *  Use TXLP_INT2EXT_STREAM_MAP_TABLE  table
   1285     *  This is a per-LP block memory
   1286     */
   1287     mem = TXLP_INT2EXT_STREAM_MAP_TABLEm;
   1288     if (SOC_MEM_FIELD_VALID(unit, mem, EXTERNAL_SIDf)) {
   1289         /* get the block and index for the LinkPHY memory */
   1290         rv = soc_linkphy_port_blk_idx_get(unit,port,
   1291                                          &lp_block, &lp_index);
   1292         if (SOC_FAILURE(rv)) {
   1293             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1294                       (BSL_META_U(unit,
   1295                                   
   1296                                    "ERROR: LinkPHY block, index get failed for port %d\n"), port));
   1297             return rv;
   1298         }
   1299         sal_memset(&txlp_int2ext_stream_map, 0, 
   1300             sizeof(txlp_int2ext_stream_map_table_entry_t));
   1301 
   1302         copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block;
   1303         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, int_stream_id,
   1304             &txlp_int2ext_stream_map));
   1305         soc_mem_field32_set(unit, mem, (uint32 *)&txlp_int2ext_stream_map,
   1306                  VALIDf, (enable) ? 1 : 0);
   1307         soc_mem_field32_set(unit, mem, (uint32 *)&txlp_int2ext_stream_map,
   1308                     EXTERNAL_SIDf, (enable) ? (uint32)ext_stream_id : 0);
   1309         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno, int_stream_id,
   1310             &txlp_int2ext_stream_map));
   1311     }
   1312 
   1313     return rv;
   1314 }
   1315 
   1316 STATIC int
   1317 _bcm_linkphy_subport_index_to_phyport_get(int unit,
   1318                                           bcm_port_t port,
   1319                                           uint32 subport_index,
   1320                                           uint32 *phy_port)
   1321 {
   1322     uint8 block;
   1323 
   1324     /* Input Param Check */
   1325     if (phy_port == NULL) {
   1326         return BCM_E_INTERNAL;
   1327     }
   1328 
   1329     /* Retreive physical port from subport index provided */
   1330 #if defined(BCM_METROLITE_SUPPORT)
   1331     if (SOC_IS_METROLITE(unit)) {
   1332         BCM_IF_ERROR_RETURN(soc_metrolite_get_port_block(unit, port, &block));
   1333         if (ml_block_ports[unit] == NULL) {
   1334             return BCM_E_INTERNAL;
   1335         }
   1336         *phy_port = (*ml_block_ports[unit])[block][subport_index];
   1337     } else
   1338 #endif
   1339 #if defined(BCM_SABER2_SUPPORT)
   1340     if (SOC_IS_SABER2(unit)) {
   1341         BCM_IF_ERROR_RETURN(soc_saber2_get_port_block(unit, port, &block));
   1342         if (sb2_block_ports[unit] == NULL) {
   1343             return BCM_E_INTERNAL;
   1344         }
   1345         *phy_port =(*sb2_block_ports[unit])[block][subport_index];
   1346     } else
   1347 #endif
   1348     {
   1349         BCM_IF_ERROR_RETURN(soc_katana2_get_port_mxqblock(unit, port, &block));
   1350         if (kt2_mxqblock_ports[unit] == NULL) {
   1351             return BCM_E_INTERNAL;
   1352         }
   1353         *phy_port = (*kt2_mxqblock_ports[unit])[block][subport_index];
   1354     }
   1355 
   1356     return BCM_E_NONE;
   1357 }
   1358 
   1359 STATIC int
   1360 _bcm_linkphy_port_tx_int_to_ext_stream_map_get(int unit,
   1361                                                int port,
   1362                                                uint16 int_stream_id,
   1363                                                uint16 *ext_stream_id)
   1364 {
   1365     int rv = BCM_E_NONE;
   1366     soc_mem_t mem;
   1367     int copyno = 0, lp_block = 0, lp_index = 0;
   1368     txlp_int2ext_stream_map_table_entry_t txlp_int2ext_stream_map;
   1369     int valid = 0;
   1370 
   1371     /* Map Internal Stream ID to External Stream ID 
   1372     *  Use TXLP_INT2EXT_STREAM_MAP_TABLE  table
   1373     *  This is a per-LP block memory
   1374     */
   1375     mem = TXLP_INT2EXT_STREAM_MAP_TABLEm;
   1376     if (SOC_MEM_FIELD_VALID(unit, mem, EXTERNAL_SIDf)) {
   1377         /* get the block and index for the LinkPHY memory */
   1378         rv = soc_linkphy_port_blk_idx_get(unit,port,
   1379                                          &lp_block, &lp_index);
   1380         if (SOC_FAILURE(rv)) {
   1381             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1382                       (BSL_META_U(unit,
   1383                                    "ERROR: LinkPHY block, index get failed for port %d rv %d\n"), port, rv));
   1384             return rv;
   1385         }
   1386         sal_memset(&txlp_int2ext_stream_map, 0, 
   1387             sizeof(txlp_int2ext_stream_map_table_entry_t));
   1388 
   1389         copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block;
   1390         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, int_stream_id,
   1391             &txlp_int2ext_stream_map));
   1392         valid = soc_mem_field32_get(unit, mem, &txlp_int2ext_stream_map,
   1393                 VALIDf);
   1394         if (valid) {
   1395             *ext_stream_id = soc_mem_field32_get(unit, mem,
   1396                     &txlp_int2ext_stream_map,
   1397                     EXTERNAL_SIDf);
   1398         } else {
   1399             return BCM_E_NOT_FOUND;
   1400         }
   1401     }
   1402 
   1403     return rv;
   1404 }
   1405 /* 
   1406 * Function for buffer allocation for the streams of LP-ENABLED ports.
   1407 *
   1408 * End address Range = [11-3423].
   1409 * Starting address Range = [0-3420].
   1410 * Note that [END-START+1] must be an integral multiple of "4".
   1411 *
   1412 * 856-cell worth of storage is available in the TXL-DATA-BUFFER. 
   1413 * 856 cells have to be distributed across:
   1414 * 1. All the streams of LP-ENABLED ports,
   1415 * 2. Non-LP ports.
   1416 *
   1417 * A cell=384B(4-lines of 96B). Hence Depth = 856 * 4 = 3424 lines.
   1418 * Following are the rules of how to configure space for each STREAM::
   1419 * 1.  Each active STREAM on an LP-PORT can be allocated utmost "N" cells, 
   1420 * 2.  "N" is an integer and [2* <= N <= 64] 
   1421 * 3.  Each STREAM is provided with a [start,end] pointer pairs. 
   1422 * 4.  Space for each STREAM = [end-start+1] lines of buffer.
   1423 * 5.  As each cell-occupies "4" lines in buffer, 
   1424 *     [end-start+1] must be a integral multiple of "4".
   1425 * 6.  The addresses must be configured linearly from "0" till "3423". 
   1426 * 7.  Wrap-around not supported.
   1427 * 8.  END must be always greater than START.
   1428 * 9.  If a stream is INACTIVE start=end=0.
   1429 * 10. This configuration has to be done before "enabling" the STREAM.
   1430 * NOTE: There has to be a minimum of "2" cell allocation 
   1431 * for a stream to function. If we allocate only "1" cell,
   1432 * there is potential that stream will be stuck.
   1433 *
   1434 * Following are the guidelines to configure number of cells/STREAM::
   1435 * The Line-rate is gaurenteed when below guidelines are adhered to.
   1436 *
   1437 * In LP-Mode:
   1438 * ===========
   1439 * Stream-Speed(Gbps) |  Min Num.Cells
   1440 *    < 1G            |     3
   1441 *      1G            |     6
   1442 *      10G           |     50 
   1443 *  
   1444 * In Non-LP-Mode:
   1445 * ===============
   1446 * DONOT PROGRAM.
   1447 */
   1448 
   1449 STATIC int
   1450 _bcm_linkphy_port_tx_stream_addr_map_set(int unit,
   1451                                          int port,
   1452                                          uint16 int_stream_id,
   1453                                          uint32 start_addr,
   1454                                          uint32 end_addr,
   1455                                          int enable)
   1456 {
   1457     int rv = BCM_E_NONE;
   1458     int copyno = 0, lp_block = 0, lp_index = 0;
   1459     soc_mem_t mem;
   1460     txlp_stream_addr_map_table_entry_t txlp_stream_addr_map;
   1461     uint32 max_start_addr = SOC_INFO(unit).lp_tx_databuf_start_addr_max;
   1462     uint32 min_end_addr   = SOC_INFO(unit).lp_tx_databuf_end_addr_min;
   1463     uint32 max_end_addr   = SOC_INFO(unit).lp_tx_databuf_end_addr_max;
   1464 
   1465     mem = TXLP_STREAM_ADDR_MAP_TABLEm;
   1466 
   1467     if (SOC_MEM_FIELD_VALID(unit, mem, START_ADDRf)) {
   1468         if (enable) {
   1469             if ((start_addr > max_start_addr) ||
   1470                 (end_addr < min_end_addr) ||
   1471                 (end_addr > max_end_addr)) {
   1472                 return BCM_E_PARAM;
   1473             }
   1474 
   1475             if ((end_addr - start_addr + 1) % 4) {
   1476                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1477                           (BSL_META_U(unit,
   1478                                       "ERROR:for TX data buffer allocation [END-START+1] "
   1479                                       "should be multiple of 4. \n(start =%d, end = %d)"
   1480                                       "for port = %d, int_stream_id = %d\n"),
   1481                            start_addr, end_addr,
   1482                            port, int_stream_id));
   1483                 return BCM_E_PARAM;
   1484             }
   1485         } else {
   1486             start_addr = 0;
   1487             end_addr = 0;
   1488         }
   1489 
   1490         /* get the block and index for the LinkPHY memory */
   1491         rv = soc_linkphy_port_blk_idx_get(unit,port,
   1492                                          &lp_block, &lp_index);
   1493         if (SOC_FAILURE(rv)) {
   1494             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1495                      (BSL_META_U(unit,
   1496                      "ERROR: LinkPHY block, index get failed for port %d\n"),
   1497                       port));
   1498             return rv;
   1499         }
   1500 
   1501         sal_memset(&txlp_stream_addr_map, 0,
   1502             sizeof(txlp_stream_addr_map_table_entry_t));
   1503 
   1504         copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block;
   1505         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, int_stream_id,
   1506             &txlp_stream_addr_map));
   1507 
   1508         soc_mem_field32_set(unit, mem, (uint32 *)&txlp_stream_addr_map,
   1509                  START_ADDRf, enable ? start_addr : 0);
   1510 
   1511         soc_mem_field32_set(unit, mem, (uint32 *)&txlp_stream_addr_map,
   1512                  END_ADDRf, enable ? end_addr : 0);
   1513 
   1514         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno, int_stream_id,
   1515             &txlp_stream_addr_map));
   1516     }
   1517 
   1518     return rv;
   1519 }
   1520 
   1521 STATIC int
   1522 _bcm_linkphy_port_rx_flow_control_set(int unit,
   1523                                       int port,
   1524                                       uint16 int_stream_id,
   1525                                       int enable)
   1526 {
   1527     soc_reg_t reg;
   1528     int rv = BCM_E_NONE, reg_hi = 0, stream_bit = 0;
   1529     uint64 rval64, data, bit_pos;
   1530 
   1531     COMPILER_64_ZERO(rval64);
   1532     COMPILER_64_ZERO(data);
   1533     COMPILER_64_ZERO(bit_pos);
   1534 
   1535     reg_hi = int_stream_id / 64;
   1536     stream_bit = int_stream_id % 64;
   1537 
   1538     reg = (reg_hi) ? RXLP_DFC_STATUS_CPU_UPDATE_ENABLE_HIr :
   1539                      RXLP_DFC_STATUS_CPU_UPDATE_ENABLE_LOr;
   1540 
   1541     if (SOC_REG_IS_VALID(unit, reg)) {
   1542         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   1543 
   1544         data = soc_reg64_field_get(unit, reg, rval64, DFC_STATUS_CPU_WRITE_ENf);
   1545         if (!enable) {
   1546             if (!COMPILER_64_BITTEST(data, stream_bit)) {
   1547                 COMPILER_64_SET(bit_pos, 0, 1);
   1548                 COMPILER_64_SHL(bit_pos, stream_bit);
   1549                 COMPILER_64_OR(data, bit_pos);
   1550             }
   1551         } else {
   1552             if (COMPILER_64_BITTEST(data, stream_bit)) {
   1553                 COMPILER_64_SET(bit_pos, 0, 1);
   1554                 COMPILER_64_SHL(bit_pos, stream_bit);
   1555                 COMPILER_64_NOT(bit_pos);
   1556                 COMPILER_64_AND(data,bit_pos);
   1557             }
   1558         }
   1559         soc_reg64_field_set(unit, reg, &rval64, DFC_STATUS_CPU_WRITE_ENf, data);
   1560         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   1561     }
   1562     WRITE_RXLP_DFC_CPU_UPDATE_REFRESHr(unit, port, 1);
   1563     reg = (reg_hi) ? RXLP_DFC_STATUS_HIr : RXLP_DFC_STATUS_LOr;
   1564 
   1565     if (SOC_REG_IS_VALID(unit, reg)) {
   1566         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   1567 
   1568         data = soc_reg64_field_get(unit, reg, rval64, DFC_STATUSf);
   1569 
   1570         if (enable) {
   1571             if (!COMPILER_64_BITTEST(data, stream_bit)) {
   1572                 COMPILER_64_SET(bit_pos, 0, 1);
   1573                 COMPILER_64_SHL(bit_pos, stream_bit);
   1574                 COMPILER_64_OR(data, bit_pos);
   1575 
   1576                 soc_reg64_field_set(unit, reg, &rval64, DFC_STATUSf, data);
   1577                 SOC_IF_ERROR_RETURN(
   1578                     soc_reg_set(unit, reg, port, 0, rval64));
   1579             }
   1580         } else {
   1581             if (COMPILER_64_BITTEST(data, stream_bit)) {
   1582                 COMPILER_64_SET(bit_pos, 0, 1);
   1583                 COMPILER_64_SHL(bit_pos, stream_bit);
   1584                 COMPILER_64_NOT(bit_pos);
   1585                 COMPILER_64_AND(data,bit_pos);
   1586 
   1587                 soc_reg64_field_set(unit, reg, &rval64, DFC_STATUSf, data);
   1588                 SOC_IF_ERROR_RETURN(
   1589                     soc_reg_set(unit, reg, port, 0, rval64));
   1590             }
   1591         }
   1592     }
   1593 
   1594     return rv;
   1595 }
   1596 
   1597 /* Set and clear Bitmap(LSBs/MSBs) of active internal stream IDs 
   1598 * associated with a port.
   1599 * The same internal stream ID should not be active on more than one ports
   1600 */
   1601 STATIC int
   1602 _bcm_linkphy_port_rx_active_stream_bitmap_set(int unit,
   1603                                               int port,
   1604                                               uint16 int_stream_id,
   1605                                               int enable)
   1606 {
   1607     soc_reg_t reg;
   1608     int rv = BCM_E_NONE, reg_hi = 0, stream_bit = 0;
   1609     uint64 rval64, data, bit_pos;
   1610 
   1611     COMPILER_64_ZERO(rval64);
   1612     COMPILER_64_ZERO(data);
   1613     COMPILER_64_ZERO(bit_pos);
   1614 
   1615     reg_hi = int_stream_id / 64;
   1616     stream_bit = int_stream_id % 64;
   1617 
   1618     reg = (reg_hi) ? RXLP_PORT_ACTIVE_STREAM_BITMAP_HIr :
   1619                      RXLP_PORT_ACTIVE_STREAM_BITMAP_LOr;
   1620     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   1621 
   1622         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   1623 
   1624         data = soc_reg64_field_get(unit, reg, rval64,ACTIVE_STREAM_BITMAPf);
   1625 
   1626         if (enable) {
   1627             if (!COMPILER_64_BITTEST(data, stream_bit)) {
   1628                 COMPILER_64_SET(bit_pos, 0, 1);
   1629                 COMPILER_64_SHL(bit_pos, stream_bit);
   1630                 COMPILER_64_OR(data, bit_pos);
   1631 
   1632                 soc_reg64_field_set(unit, reg, &rval64,
   1633                     ACTIVE_STREAM_BITMAPf, data);
   1634                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   1635             }
   1636         } else {
   1637             if (COMPILER_64_BITTEST(data, stream_bit)) {
   1638                 COMPILER_64_SET(bit_pos, 0, 1);
   1639                 COMPILER_64_SHL(bit_pos, stream_bit);
   1640                 COMPILER_64_NOT(bit_pos);
   1641                 COMPILER_64_AND(data, bit_pos);
   1642 
   1643                 soc_reg64_field_set(unit, reg, &rval64,
   1644                     ACTIVE_STREAM_BITMAPf, data);
   1645                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   1646             }
   1647         }
   1648     }
   1649 
   1650     return rv;
   1651 }
   1652 
   1653 /* Given the external stream id,
   1654  * which is the (original external stream id - external stream id base),
   1655  * This function will return the internal stream id mapped to it.
   1656  *
   1657  * 
   1658  * NOTE:
   1659  * This internal stream id got can be added to internal stream id base
   1660  * to get the device level internal stream id.
   1661  */
   1662 STATIC int
   1663 _bcm_linkphy_port_rx_int_stream_map_port_get(int unit,
   1664                                              int port,
   1665                                              uint16 ext_stream_id,
   1666                                              uint16 *int_stream_id)
   1667 {
   1668     soc_mem_t mem;
   1669     int rv = BCM_E_NONE, copyno = 0, lp_index = 0, lp_block = 0;
   1670     rxlp_internal_stream_map_port_0_entry_t rxlp_int_stream_map_port;
   1671     int rxlp_int_stream_map_port_idx = -1;
   1672     int valid = 0;
   1673 
   1674     mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m;
   1675     if (SOC_MEM_FIELD_VALID(unit, mem, INTERNAL_STREAM_IDf)) {
   1676         /* get the block and index for the LinkPHY memory */
   1677         rv = soc_linkphy_port_blk_idx_get(unit,port,
   1678                                          &lp_block, &lp_index);
   1679         if (SOC_FAILURE(rv)) {
   1680             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1681                       (BSL_META_U(unit,
   1682                        "ERROR: LinkPHY block, index get failed for port %d\n"),
   1683                        port));
   1684             return rv;
   1685         }
   1686         sal_memset(&rxlp_int_stream_map_port, 0, 
   1687             sizeof(rxlp_internal_stream_map_port_0_entry_t));
   1688 
   1689         /*
   1690         * Internal stream id = 
   1691         * RXLP_INTERNAL_STREAM_MAP_PORTn.rxlp0/1 [Internal Stream ID];
   1692         */
   1693         switch (lp_index) {
   1694             case 0:
   1695                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m;
   1696                 break;
   1697             case 1:
   1698                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_1m;
   1699                 break;
   1700             case 2:
   1701                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_2m;
   1702                 break;
   1703             case 3:
   1704                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_3m;
   1705                 break;
   1706             default:
   1707                 return SOC_E_PORT;
   1708         };
   1709         copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block;
   1710         /* The index into the rxlp_internal_stream_map_port table is
   1711          * stream_id_array_value - external_stream_id_base which is 
   1712          * given by the passed ext_stream_id. 
   1713          */
   1714         rxlp_int_stream_map_port_idx = ext_stream_id; 
   1715 
   1716 
   1717         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno,
   1718                                          rxlp_int_stream_map_port_idx,
   1719                                          &rxlp_int_stream_map_port));
   1720         valid = soc_mem_field32_get(unit, mem,
   1721                     (uint32 *)&rxlp_int_stream_map_port, VALIDf);
   1722         if (valid) {
   1723             *int_stream_id = soc_mem_field32_get(unit, mem,
   1724                     (uint32 *)&rxlp_int_stream_map_port, INTERNAL_STREAM_IDf);
   1725         }
   1726         else {
   1727             return BCM_E_BADID;
   1728         }
   1729         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   1730                    (BSL_META_U(unit,
   1731                     "rxlp_internal_stream_map_port index[%d] for port[%d] "
   1732                     "block_internal_stream_id[%d]\n"),
   1733                      rxlp_int_stream_map_port_idx, port, *int_stream_id));
   1734     }
   1735 
   1736     return rv;
   1737 }
   1738 
   1739 
   1740 /* Map (External Stream ID - RXLP_PORT_STREAM_ID_BASE) 
   1741 * to internal stream ID in the range 0-127.
   1742 * There is one copy of this table for each port.
   1743 * The internal stream IDs configured in this table 
   1744 * should be unique across the four ports associated with the RXLP slice.
   1745 */
   1746 STATIC int
   1747 _bcm_linkphy_port_rx_int_stream_map_port_set(int unit,
   1748                                              int port,
   1749                                              uint16 ext_stream_id,
   1750                                              uint16 int_stream_id,
   1751                                              int enable)
   1752 {
   1753     soc_mem_t mem;
   1754     int rv = BCM_E_NONE, copyno = 0, lp_index = 0, lp_block = 0;
   1755     rxlp_internal_stream_map_port_0_entry_t rxlp_int_stream_map_port;
   1756     int rxlp_int_stream_map_port_idx = -1;
   1757 
   1758     mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m;
   1759     if (SOC_MEM_FIELD_VALID(unit, mem, INTERNAL_STREAM_IDf)) {
   1760         /* get the block and index for the LinkPHY memory */
   1761         rv = soc_linkphy_port_blk_idx_get(unit,port,
   1762                                          &lp_block, &lp_index);
   1763         if (SOC_FAILURE(rv)) {
   1764             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1765                       (BSL_META_U(unit,
   1766                                   
   1767                                    "ERROR: LinkPHY block, index get failed for port %d\n"), port));
   1768             return rv;
   1769         }
   1770         sal_memset(&rxlp_int_stream_map_port, 0, 
   1771             sizeof(rxlp_internal_stream_map_port_0_entry_t));
   1772 
   1773         /*
   1774         * Internal stream id = 
   1775         * RXLP_INTERNAL_STREAM_MAP_PORTn.rxlp0/1 [Internal Stream ID];
   1776         */
   1777         switch (lp_index) {
   1778             case 0:
   1779                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m;
   1780                 break;
   1781             case 1:
   1782                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_1m;
   1783                 break;
   1784             case 2:
   1785                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_2m;
   1786                 break;
   1787             case 3:
   1788                 mem = RXLP_INTERNAL_STREAM_MAP_PORT_3m;
   1789                 break;
   1790             default:
   1791                 return SOC_E_PORT;
   1792         };
   1793         copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block;
   1794 
   1795            /* The index into the rxlp_internal_stream_map_port table is
   1796             * stream_id_array_value - external_stream_id_base which is 
   1797             * given by the passed ext_stream_id. 
   1798             */
   1799         rxlp_int_stream_map_port_idx = ext_stream_id;
   1800 
   1801         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   1802                    (BSL_META_U(unit,
   1803                     "rxlp_internal_stream_map_port index[%d] for port[%d] "
   1804                     "block_internal_stream_id[%d]\n"),
   1805                      rxlp_int_stream_map_port_idx, port, int_stream_id));
   1806 
   1807         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno,
   1808                                          rxlp_int_stream_map_port_idx,
   1809                                          &rxlp_int_stream_map_port));
   1810         soc_mem_field32_set(unit, mem,
   1811                     (uint32 *)&rxlp_int_stream_map_port, VALIDf,
   1812                     (enable) ? 1 : 0);
   1813         soc_mem_field32_set(unit, mem,
   1814                     (uint32 *)&rxlp_int_stream_map_port, INTERNAL_STREAM_IDf,
   1815                     (enable) ? int_stream_id : 0);
   1816         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno,
   1817                                           rxlp_int_stream_map_port_idx,
   1818                                           &rxlp_int_stream_map_port));
   1819     }
   1820 
   1821     return rv;
   1822 }
   1823 
   1824 /*
   1825  * Function:
   1826  *      _bcmi_linkphy_subport_ext_stream_id_in_use
   1827  * Description:
   1828  *      Check if an external stream id is in use on
   1829  *      a subport group.
   1830  * Parameters:
   1831  *      unit   - (IN) Device Number
   1832  *      config - (IN) Subport config information
   1833  *      ext_stream_d - (IN) External stream id
   1834  * Returns:
   1835  *      BCM_E_XXX
   1836  */
   1837 STATIC int
   1838 _bcmi_linkphy_subport_ext_stream_id_in_use(int unit,
   1839                                           bcm_subport_config_t *config,
   1840                                           int ext_stream_id)
   1841 {
   1842     int rv = BCM_E_NONE, group_id = 0, i;
   1843     int pp_port = 0, subport_port;
   1844     int linkphy_subport_count = 0;
   1845     bcm_subport_config_t sp_config;
   1846 
   1847     group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group);
   1848 
   1849     if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   1850         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1851                   (BSL_META_U(unit,
   1852                               "ERROR: LinkPHY subport group 0x%x not found.\n"),
   1853                               config->group));
   1854         return BCM_E_NOT_FOUND;
   1855     }
   1856 
   1857     linkphy_subport_count =
   1858         *(_bcm_subport_group_subport_port_count[unit] + group_id);
   1859 
   1860     /*
   1861      * Iterate through all the linkphy ports in the subport group
   1862      * to check if external stream id is already in use.
   1863      */
   1864     BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port) {
   1865 
   1866         if (linkphy_subport_count == 0) {
   1867             break;
   1868         }
   1869 
   1870         if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   1871             continue;
   1872         }
   1873 
   1874         if (config->group !=
   1875             _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   1876             continue;
   1877         }
   1878 
   1879         _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port);
   1880 
   1881         _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   1882                                        _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   1883 
   1884         rv = _bcm_linkphy_subport_port_get(unit, subport_port, &sp_config);
   1885         if (SOC_FAILURE(rv)) {
   1886             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   1887                      (BSL_META_U(unit,
   1888                      "ERROR: LinkPHY subport group 0x%x \n"
   1889                      "to get subport port (group id %d, pp_port id %d)\n"),
   1890                      config->group, group_id, pp_port));
   1891             return rv;
   1892         }
   1893 
   1894         for (i = 0; i < sp_config.num_streams; i++) {
   1895             if (ext_stream_id == sp_config.stream_id_array[i]) {
   1896                 LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   1897                        (BSL_META_U(unit,
   1898                         "*ERROR: External stream_id %d is in use!! port %d\n"),
   1899                         config->stream_id_array[i],
   1900                         _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group)));
   1901                 return BCM_E_EXISTS;
   1902             }
   1903         }
   1904 
   1905         linkphy_subport_count--;
   1906     }
   1907     return BCM_E_NONE;
   1908 }
   1909 
   1910 STATIC void
   1911 _bcm_linkphy_subport_stat_callback(int unit)
   1912 {
   1913     int pool_id = 0, direction = 0, index = 0, block_id = 0, copyno = 0;
   1914     int width = 0;
   1915     soc_mem_t mem;
   1916     uint32 ctr_new = 0, ctr_prev = 0, ctr_diff = 0;
   1917     volatile uint64 *vptr;
   1918     int linkphy_counter_max = _BCM_KT2_LINKPHY_COUNTER_MAX(unit);
   1919     int linkphy_block_max   = SOC_INFO(unit).lp_block_max;
   1920 
   1921     BCM_LINKPHY_COUNTER_LOCK(unit);
   1922     if (linkphy_temp_ctr[unit] == NULL){
   1923         LOG_WARN(BSL_LS_BCM_SUBPORT,
   1924                  (BSL_META_U(unit,
   1925                              "Not Initilized or attached\n")));
   1926     }
   1927 
   1928     for (direction = 0;
   1929         direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) {
   1930         for (block_id = 0; block_id < linkphy_block_max; block_id++) {
   1931             for (pool_id = 0; pool_id < _BCM_KT2_LINKPHY_POOL_MAX; pool_id++) {
   1932 
   1933                 mem = linkphy_counter_table[direction][pool_id];
   1934                 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block_id;
   1935                 width = soc_mem_field_length(unit, mem, COUNTf);
   1936                 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
   1937                      continue;
   1938                 }
   1939 
   1940                 if (soc_mem_read_range(unit, mem, copyno, 0,
   1941                         (linkphy_counter_max - 1),
   1942                         linkphy_temp_ctr[unit]) != BCM_E_NONE) {
   1943                     BCM_LINKPHY_COUNTER_UNLOCK(unit);
   1944                     return;
   1945                 }
   1946                 for (index = 0; index <= (linkphy_counter_max - 1);
   1947                     index++) {
   1948                     switch (pool_id) {
   1949                         case 0:
   1950                             vptr = &linkphy_frag_byte_ctr[unit][direction]
   1951                                                          [block_id][index];
   1952                             break;
   1953                         case 1:
   1954                             vptr = &linkphy_frag_ctr[unit][direction]
   1955                                                     [block_id][index];
   1956                             break;
   1957                         case 2:
   1958                             vptr = &linkphy_frame_byte_ctr[unit][direction]
   1959                                                           [block_id][index];
   1960                             break;
   1961                         case 3:
   1962                         default:
   1963                             vptr = &linkphy_frame_ctr[unit][direction]
   1964                                                      [block_id][index];
   1965                             break;
   1966                     }
   1967                     LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   1968                                 (BSL_META_U(unit,
   1969                                             "%s_DEBUG_COUNTER%d.lp%d index:%d "
   1970                                             "%s : old count:0x%08x%08x \n"),
   1971                                  direction ? "TXLP" : "RXLP", 
   1972                                  ((pool_id == 3) ? 11 :
   1973                                   ((pool_id == 2) ? 10 :
   1974                                    ((pool_id == 1) ? 9 : 8))),
   1975                                  block_id, index,
   1976                                  ((pool_id == 3) ? "Frame    " : 
   1977                                   ((pool_id == 2) ? "FrameByte" :
   1978                                    ((pool_id == 1) ? "Frag     " : "FragByte "))),
   1979                                  COMPILER_64_HI(*vptr),
   1980                                  COMPILER_64_LO(*vptr)));
   1981 
   1982                     ctr_prev = COMPILER_64_LO(*vptr);
   1983 
   1984                     if (width < 32) {
   1985                         ctr_prev &= ((1UL << width) - 1);
   1986                     }
   1987 
   1988                     soc_mem_field_get(unit, mem,
   1989                         (uint32 *)&linkphy_temp_ctr[unit][index],
   1990                         COUNTf, &ctr_new);
   1991 
   1992                     if (ctr_new == ctr_prev) {
   1993                         continue;
   1994                     }
   1995 
   1996                     ctr_diff = ctr_new;
   1997 
   1998                     if (ctr_diff < ctr_prev) {
   1999                         /* Counter has wrapped around. */
   2000                         if (width < 32) {
   2001                             ctr_diff += (1UL << width);
   2002                         }
   2003                     }
   2004 
   2005                     ctr_diff -= ctr_prev;
   2006 
   2007                     COMPILER_64_ADD_32(*vptr, ctr_diff);
   2008 
   2009                     LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   2010                                 (BSL_META_U(unit,
   2011                                             "%s_DEBUG_COUNTER%d.lp%d index:%d "
   2012                                             "%s : new_count:0x%08x%08x\n"),
   2013                                  direction ? "TXLP" : "RXLP",
   2014                                  ((pool_id == 3) ? 11 :
   2015                                   ((pool_id == 2) ? 10 :
   2016                                    ((pool_id == 1) ? 9 : 8))),
   2017                                  block_id, index, 
   2018                                  ((pool_id == 3) ? "Frame    " :
   2019                                   ((pool_id == 2) ? "FrameByte" :
   2020                                    ((pool_id == 1) ? "Frag     " : "FragByte "))),
   2021                          COMPILER_64_HI(*vptr),
   2022                          COMPILER_64_LO(*vptr)));
   2023                 } /*end index */
   2024             }/* end pool */
   2025         } /* end block */
   2026     } /* end direction */
   2027     BCM_LINKPHY_COUNTER_UNLOCK(unit);
   2028     return;
   2029 }
   2030 
   2031 STATIC int
   2032 _bcm_linkphy_subport_counter_cleanup(int unit)
   2033 {
   2034     int direction = 0, block_id = 0;
   2035     int linkphy_block_max = SOC_INFO(unit).lp_block_max;
   2036 
   2037     if (linkphy_ctr_mutex[unit] != NULL) {
   2038         BCM_LINKPHY_COUNTER_LOCK(unit);
   2039         soc_counter_extra_unregister(unit, _bcm_linkphy_subport_stat_callback);
   2040         BCM_LINKPHY_COUNTER_UNLOCK(unit);
   2041         sal_mutex_destroy(linkphy_ctr_mutex[unit]);
   2042         linkphy_ctr_mutex[unit] = NULL;
   2043     }
   2044 
   2045     if (linkphy_temp_ctr[unit] != NULL){
   2046         soc_cm_sfree(unit,linkphy_temp_ctr[unit]);
   2047         linkphy_temp_ctr[unit] = NULL;
   2048     }
   2049 
   2050     for (direction = 0;
   2051         direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) {
   2052         for (block_id = 0; block_id < linkphy_block_max; block_id++) {
   2053             if (linkphy_frag_byte_ctr[unit][direction][block_id] != NULL) {
   2054                  soc_cm_sfree(unit,
   2055                     linkphy_frag_byte_ctr[unit][direction][block_id]);
   2056                 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL;
   2057             }
   2058             if (linkphy_frag_ctr[unit][direction][block_id] != NULL) {
   2059                 soc_cm_sfree(unit,
   2060                     linkphy_frag_ctr[unit][direction][block_id]);
   2061                 linkphy_frag_ctr[unit][direction][block_id] = NULL;
   2062             }
   2063             if (linkphy_frame_byte_ctr[unit][direction][block_id] != NULL) {
   2064                 soc_cm_sfree(unit,
   2065                     linkphy_frame_byte_ctr[unit][direction][block_id]);
   2066                 linkphy_frame_byte_ctr[unit][direction][block_id] = NULL;
   2067             }
   2068             if (linkphy_frame_ctr[unit][direction][block_id] != NULL) {
   2069                 soc_cm_sfree(unit,
   2070                     linkphy_frame_ctr[unit][direction][block_id]);
   2071                 linkphy_frame_ctr[unit][direction][block_id] = NULL;
   2072             }
   2073         }
   2074     }
   2075     return BCM_E_NONE;
   2076 }
   2077 
   2078 STATIC int
   2079 _bcm_linkphy_subport_counter_init(int unit)
   2080 {
   2081     int direction = 0, block_id = 0, pool_id = 0, copyno = 0, index = 0;
   2082     uint32 temp_alloc_size = 0, block_alloc_size = 0;
   2083     soc_mem_t mem;
   2084     int linkphy_counter_max = _BCM_KT2_LINKPHY_COUNTER_MAX(unit);
   2085     int linkphy_block_max = SOC_INFO(unit).lp_block_max;
   2086 
   2087     _bcm_linkphy_subport_counter_cleanup(unit);
   2088 
   2089     if (linkphy_ctr_mutex[unit] == NULL) {
   2090         linkphy_ctr_mutex[unit] = sal_mutex_create("subport counter mutex");
   2091         if (linkphy_ctr_mutex[unit] == NULL) {
   2092             return BCM_E_MEMORY;
   2093         }
   2094     }
   2095 
   2096     if (linkphy_temp_ctr[unit] != NULL){
   2097         LOG_WARN(BSL_LS_BCM_SUBPORT,
   2098                  (BSL_META_U(unit,
   2099                              "WARN:Freeing linkphy_temp_ctr\n")));
   2100         soc_cm_sfree(unit,linkphy_temp_ctr[unit]);
   2101         linkphy_temp_ctr[unit] = NULL;
   2102     }
   2103 
   2104     temp_alloc_size =
   2105         sizeof(rxlp_debug_counter7_entry_t) * linkphy_counter_max;
   2106     linkphy_temp_ctr[unit] = soc_cm_salloc(unit,
   2107                       temp_alloc_size, "linkphy temp counter");
   2108 
   2109     if (linkphy_temp_ctr[unit] == NULL) {
   2110         LOG_WARN(BSL_LS_BCM_SUBPORT,
   2111                  (BSL_META_U(unit,
   2112                              "linkphy temp allocation for unit:%d failed\n"),
   2113                   unit));
   2114         _bcm_linkphy_subport_counter_cleanup(unit);
   2115         return BCM_E_MEMORY;
   2116     }
   2117     sal_memset(linkphy_temp_ctr[unit], 0, temp_alloc_size);
   2118     LOG_DEBUG(BSL_LS_BCM_SUBPORT,
   2119               (BSL_META_U(unit,
   2120                           "linkphy temp counter size:%d \n"),
   2121                temp_alloc_size));
   2122 
   2123 
   2124     for (direction = 0;
   2125         direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) {
   2126         for (block_id = 0; block_id < linkphy_block_max; block_id++) {
   2127             for (pool_id = 0; pool_id < _BCM_KT2_LINKPHY_POOL_MAX; pool_id++) {
   2128 
   2129                 mem = linkphy_counter_table[direction][pool_id];
   2130                 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block_id;
   2131                 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
   2132                      continue;
   2133                 }
   2134                 if (soc_mem_write_range(unit, mem, copyno,
   2135                     0,
   2136                     (linkphy_counter_max - 1),
   2137                     linkphy_temp_ctr[unit])) {
   2138                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2139                               (BSL_META_U(unit,
   2140                                           "ERROR: zeroing LinkPHY counter failed\n")));
   2141                     soc_cm_sfree(unit,linkphy_temp_ctr[unit]);
   2142                     linkphy_temp_ctr[unit] = NULL;
   2143                 }
   2144             }
   2145         }
   2146     }
   2147 
   2148     block_alloc_size = sizeof(uint64) * linkphy_counter_max;
   2149 
   2150     for (direction=0; direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) {
   2151         for (block_id = 0; block_id < linkphy_block_max; block_id++) {
   2152             /* fragment byte */
   2153             if (linkphy_frag_byte_ctr[unit][direction][block_id] != NULL) {
   2154                 LOG_WARN(BSL_LS_BCM_SUBPORT,
   2155                          (BSL_META_U(unit,
   2156                                      "WARN:Freeing linkphy_frag_byte_ctr\n")));
   2157                 soc_cm_sfree(unit,
   2158                     linkphy_frag_byte_ctr[unit][direction][block_id]);
   2159                 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL;
   2160             }
   2161 
   2162             linkphy_frag_byte_ctr[unit][direction][block_id] = 
   2163                  soc_cm_salloc(unit, block_alloc_size,
   2164                                "linkphy_fragment_byte counter");
   2165             if (linkphy_frag_byte_ctr[unit][direction][block_id] == NULL) {
   2166                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2167                           (BSL_META_U(unit,
   2168                                       "linkphy_frag_byte_ctr failed for "
   2169                                        " unit:%d,dir:%d, block:%d \n"), unit, direction, block_id));
   2170                 _bcm_linkphy_subport_counter_cleanup(unit);
   2171                 return BCM_E_MEMORY;
   2172             }
   2173             sal_memset(linkphy_frag_byte_ctr[unit][direction][block_id],
   2174                 0, block_alloc_size);
   2175 
   2176             /* fragment */
   2177             if (linkphy_frag_ctr[unit][direction][block_id] != NULL) {
   2178                 LOG_WARN(BSL_LS_BCM_SUBPORT,
   2179                          (BSL_META_U(unit,
   2180                                      "WARN:Freeing linkphy_frag_ctr\n")));
   2181                 soc_cm_sfree(unit,
   2182                     linkphy_frag_ctr[unit][direction][block_id]);
   2183                 linkphy_frag_ctr[unit][direction][block_id] = NULL;
   2184             }
   2185 
   2186             linkphy_frag_ctr[unit][direction][block_id] = 
   2187                  soc_cm_salloc(unit, block_alloc_size,
   2188                      "linkphy_fragment counter");
   2189             if (linkphy_frag_ctr[unit][direction][block_id] == NULL) {
   2190                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2191                           (BSL_META_U(unit,
   2192                                       "linkphy_frag_ctr failed for "
   2193                                        " unit:%d,dir:%d, block:%d \n"), unit, direction, block_id));
   2194                 soc_cm_sfree(unit,
   2195                     linkphy_frag_byte_ctr[unit][direction][block_id]);
   2196                 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL;
   2197                 _bcm_linkphy_subport_counter_cleanup(unit);
   2198                 return BCM_E_MEMORY;
   2199             }
   2200             sal_memset(
   2201               linkphy_frag_ctr[unit][direction][block_id], 0, block_alloc_size);
   2202 
   2203             /* frame byte */
   2204             if (linkphy_frame_byte_ctr[unit][direction][block_id] != NULL) {
   2205                 LOG_WARN(BSL_LS_BCM_SUBPORT,
   2206                          (BSL_META_U(unit,
   2207                                      "WARN:Freeing linkphy_frame_byte_ctr\n")));
   2208                 soc_cm_sfree(unit,
   2209                     linkphy_frame_byte_ctr[unit][direction][block_id]);
   2210             }
   2211             linkphy_frame_byte_ctr[unit][direction][block_id] = 
   2212                  soc_cm_salloc(unit, block_alloc_size,
   2213                      "linkphy_frame_byte counter");
   2214             if (linkphy_frame_byte_ctr[unit][direction][block_id] == NULL) {
   2215                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2216                           (BSL_META_U(unit,
   2217                                       "linkphy_frame_byte_ctr failed for "
   2218                                        "unit:%d,dir:%d, block:%d \n"), unit, direction, block_id));
   2219                 soc_cm_sfree(unit,
   2220                     linkphy_frag_byte_ctr[unit][direction][block_id]);
   2221                 soc_cm_sfree(unit,
   2222                     linkphy_frag_ctr[unit][direction][block_id]);
   2223                 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL;
   2224                 linkphy_frag_ctr[unit][direction][block_id] = NULL;
   2225                 linkphy_frame_byte_ctr[unit][direction][block_id] = NULL;
   2226                 _bcm_linkphy_subport_counter_cleanup(unit);
   2227                 return BCM_E_MEMORY;
   2228             }
   2229             sal_memset(linkphy_frame_byte_ctr[unit][direction][block_id],
   2230                 0, block_alloc_size);
   2231 
   2232             /* frame */
   2233             if (linkphy_frame_ctr[unit][direction][block_id] != NULL) {
   2234                 LOG_WARN(BSL_LS_BCM_SUBPORT,
   2235                          (BSL_META_U(unit,
   2236                                      "WARN:Freeing linkphy_frame_ctr\n")));
   2237                 soc_cm_sfree(unit,
   2238                     linkphy_frame_ctr[unit][direction][block_id]);
   2239             }
   2240             linkphy_frame_ctr[unit][direction][block_id] = 
   2241                  soc_cm_salloc(unit, block_alloc_size, "linkphy_frame counter");
   2242             if (linkphy_frame_ctr[unit][direction][block_id] == NULL) {
   2243                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2244                           (BSL_META_U(unit,
   2245                                       "linkphy_frame_ctr failed for "
   2246                                        "unit:%d,dir:%d block:%d\n"), unit, direction, block_id));
   2247                 soc_cm_sfree(unit,
   2248                     linkphy_frag_byte_ctr[unit][direction][block_id]);
   2249                 soc_cm_sfree(unit,
   2250                     linkphy_frag_ctr[unit][direction][block_id]);
   2251                 soc_cm_sfree(unit,
   2252                     linkphy_frame_byte_ctr[unit][direction][block_id]);
   2253                 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL;
   2254                 linkphy_frag_ctr[unit][direction][block_id] = NULL;
   2255                 linkphy_frame_byte_ctr[unit][direction][block_id] = NULL;
   2256                 _bcm_linkphy_subport_counter_cleanup(unit);
   2257                 return BCM_E_MEMORY;
   2258             }
   2259             sal_memset(linkphy_frame_ctr[unit][direction][block_id],
   2260                 0, block_alloc_size);
   2261 
   2262             for (index = 0; index < linkphy_counter_max; index++) {
   2263                 COMPILER_64_ZERO (
   2264                     linkphy_frag_ctr[unit][direction][block_id][index]);
   2265                 COMPILER_64_ZERO (
   2266                     linkphy_frag_byte_ctr[unit][direction][block_id][index]);
   2267                 COMPILER_64_ZERO (
   2268                     linkphy_frame_ctr[unit][direction][block_id][index]);
   2269                 COMPILER_64_ZERO (
   2270                     linkphy_frame_byte_ctr[unit][direction][block_id][index]);
   2271             }
   2272         }
   2273     }
   2274 
   2275     BCM_IF_ERROR_RETURN
   2276      (soc_counter_extra_register(unit, _bcm_linkphy_subport_stat_callback));
   2277     return BCM_E_NONE;
   2278 }
   2279 
   2280 /*
   2281  * Function:
   2282  *      _bcm_linkphy_subport_port_stat_set
   2283  * Purpose:
   2284  *      Set the statistics value for LinkPHY subport port and statistics type
   2285  * Parameters:
   2286  *      unit      - (IN) Device Number
   2287  *      subport   - (IN) subport port
   2288  *      stream_id - (IN) stream ID array index
   2289  *      stat_type - (IN) statistics type
   2290  *      val       - (IN) value
   2291  * Returns:
   2292  *      BCM_E_XXX
   2293  */
   2294 STATIC int
   2295 _bcm_linkphy_subport_port_stat_set(
   2296     int unit,
   2297     bcm_gport_t subport,
   2298     int stream_id,
   2299     bcm_subport_stat_t stat_type,
   2300     uint64 val)
   2301 {
   2302     int direction = 0, block = 0, pool = 0, copyno = 0;
   2303     int rv = BCM_E_NONE;
   2304     uint16 counter_id = 0;
   2305     uint16 port_e_stream_id_base_adj = 0;
   2306     uint16 blk_i_stream_id = 0;
   2307     int i = 0;
   2308     uint16 ext_stream_id_base = 0;
   2309     uint32 val32 = 0, count_mask = 0;
   2310     bcm_port_t port;
   2311     bcm_subport_config_t config;
   2312     soc_mem_t mem;
   2313     rxlp_debug_counter7_entry_t temp_counter;
   2314 
   2315     /* get port from subport */
   2316     bcm_subport_config_t_init(&config);
   2317     rv = _bcm_linkphy_subport_port_get(unit, subport, &config);
   2318     if (BCM_FAILURE(rv)) {
   2319         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2320                   (BSL_META_U(unit,
   2321                               "ERROR: _bcm_linkphy_subport_port_get failed \n"
   2322                                "for subport 0x%x\n"), subport));
   2323         return rv;
   2324     }
   2325 
   2326     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config.group);
   2327     rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port,
   2328             &ext_stream_id_base);
   2329     if (BCM_FAILURE(rv)) {
   2330         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2331                   (BSL_META_U(unit,
   2332                               "ERROR: Linkphy port %d external "
   2333                                "stream id base get failed\n"), port));
   2334         return rv;
   2335     }
   2336 
   2337     if ((stream_id != -1) && (stream_id >= config.num_streams)) {
   2338         return BCM_E_PARAM;
   2339     }
   2340 
   2341     switch (stat_type) {
   2342         case bcmSubportLinkPhyStatRxFragmentBytes:
   2343             direction = _BCM_KT2_LINKPHY_DIRECTION_RX;
   2344             pool = _BCM_KT2_LINKPHY_POOL_FRAG_BYTE;
   2345             break;
   2346         case bcmSubportLinkPhyStatRxFragments:
   2347             direction = _BCM_KT2_LINKPHY_DIRECTION_RX;
   2348             pool = _BCM_KT2_LINKPHY_POOL_FRAG;
   2349             break;
   2350         case bcmSubportLinkPhyStatRxFrameBytes:
   2351             direction = _BCM_KT2_LINKPHY_DIRECTION_RX;
   2352             pool = _BCM_KT2_LINKPHY_POOL_FRAME_BYTE;
   2353             break;
   2354         case bcmSubportLinkPhyStatRxFrames:
   2355             direction = _BCM_KT2_LINKPHY_DIRECTION_RX;
   2356             pool = _BCM_KT2_LINKPHY_POOL_FRAME;
   2357             break;
   2358         case bcmSubportLinkPhyStatTxFragmentBytes:
   2359             direction = _BCM_KT2_LINKPHY_DIRECTION_TX;
   2360             pool = _BCM_KT2_LINKPHY_POOL_FRAG_BYTE;
   2361             break;
   2362         case bcmSubportLinkPhyStatTxFragments:
   2363             direction = _BCM_KT2_LINKPHY_DIRECTION_TX;
   2364             pool = _BCM_KT2_LINKPHY_POOL_FRAG;
   2365             break;
   2366         case bcmSubportLinkPhyStatTxFrameBytes:
   2367             direction = _BCM_KT2_LINKPHY_DIRECTION_TX;
   2368             pool = _BCM_KT2_LINKPHY_POOL_FRAME_BYTE;
   2369             break;
   2370         case bcmSubportLinkPhyStatTxFrames:
   2371             direction = _BCM_KT2_LINKPHY_DIRECTION_TX;
   2372             pool = _BCM_KT2_LINKPHY_POOL_FRAME;
   2373             break;
   2374         default:
   2375             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2376                         (BSL_META_U(unit,
   2377                                     "LinkPHY Statistic not supported: %d\n"), stat_type));
   2378             return BCM_E_PARAM;
   2379             break;
   2380     }
   2381 
   2382     rv = soc_linkphy_port_blk_idx_get(unit, port, &block, NULL);
   2383     if (SOC_FAILURE(rv)) {
   2384         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2385                   (BSL_META_U(unit,
   2386                               
   2387                                "ERROR: LinkPHY block, index get failed for port %d\n"), port));
   2388         return rv;
   2389     }
   2390 
   2391     BCM_LINKPHY_COUNTER_LOCK(unit);
   2392     mem = linkphy_counter_table[direction][pool];
   2393     copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block;
   2394 
   2395     for (i =0; i < config.num_streams; i++) {
   2396         if (stream_id != i) {
   2397             /* if stream_id == -1 then set the stats for all
   2398             * streams associated with the LinkPHY subport */
   2399             if (stream_id != -1) {
   2400                 continue;
   2401             }
   2402         }
   2403 
   2404         /*
   2405          * Port external stream Id after adjusting the
   2406          * port external stream id base.
   2407          * Range from 0 - 127.
   2408          */
   2409         port_e_stream_id_base_adj = config.stream_id_array[i] -
   2410                                       ext_stream_id_base;
   2411 
   2412         /*
   2413          * get the rxlp block internal stream id(0 - 127) for the
   2414          * external stream id.
   2415          */
   2416         BCM_IF_ERROR_RETURN(_bcm_linkphy_port_rx_int_stream_map_port_get(unit,
   2417                                         port, port_e_stream_id_base_adj,
   2418                                         &blk_i_stream_id));
   2419 
   2420         /* counter index is same as rxlp block internal stream id */
   2421         counter_id = blk_i_stream_id;
   2422 
   2423 
   2424         /* Read Hard copy */
   2425         if (soc_mem_read(unit, mem, copyno, counter_id,
   2426                          &temp_counter) != BCM_E_NONE) {
   2427             BCM_LINKPHY_COUNTER_UNLOCK(unit);
   2428             return BCM_E_INTERNAL;
   2429         }
   2430 
   2431         /* Update soft copy */
   2432         if ((stat_type == bcmSubportLinkPhyStatRxFragmentBytes) ||
   2433             (stat_type ==  bcmSubportLinkPhyStatTxFragmentBytes)) {
   2434             COMPILER_64_SET (linkphy_frag_byte_ctr[unit][direction]
   2435                                [block][counter_id],
   2436                                COMPILER_64_HI(val),
   2437                                COMPILER_64_LO(val));
   2438         } else if ((stat_type == bcmSubportLinkPhyStatRxFragments) ||
   2439                    (stat_type == bcmSubportLinkPhyStatTxFragments)) {
   2440             COMPILER_64_SET (linkphy_frag_ctr[unit][direction]
   2441                                [block][counter_id],
   2442                                COMPILER_64_HI(val),
   2443                                COMPILER_64_LO(val));
   2444         } else if ((stat_type == bcmSubportLinkPhyStatRxFrameBytes) ||
   2445                    (stat_type == bcmSubportLinkPhyStatTxFrameBytes)) {
   2446             COMPILER_64_SET (linkphy_frame_byte_ctr[unit][direction]
   2447                                [block][counter_id],
   2448                                COMPILER_64_HI(val),
   2449                                COMPILER_64_LO(val));
   2450         } else {
   2451             /* if ((stat_type == bcmSubportLinkPhyStatRxFrames) ||
   2452                   (stat_type == bcmSubportLinkPhyStatTxFrames))  */
   2453             COMPILER_64_SET (linkphy_frame_ctr[unit][direction]
   2454                                [block][counter_id],
   2455                                COMPILER_64_HI(val),
   2456                                COMPILER_64_LO(val));
   2457         }
   2458 
   2459         /* Modify Hard copy */
   2460         count_mask = (1 << soc_mem_field_length(unit, mem, COUNTf)) - 1;
   2461         val32 = COMPILER_64_LO(val) & count_mask;
   2462        
   2463         soc_mem_field_set(unit, mem, (uint32 *)&temp_counter, COUNTf, &val32);
   2464         /* Update Hard Copy */
   2465         if (soc_mem_write(unit, mem, copyno, counter_id,
   2466                           &temp_counter) != BCM_E_NONE){
   2467             BCM_LINKPHY_COUNTER_UNLOCK(unit);
   2468             return BCM_E_INTERNAL;
   2469         }
   2470     }
   2471 
   2472     BCM_LINKPHY_COUNTER_UNLOCK(unit);
   2473     return BCM_E_NONE;
   2474 }
   2475 
   2476 /* TXLP module is not aware of the Fragment FCS added by the MAC/PORT logic.
   2477  * Hence the TXLP Fragment byte counters do not count the additional
   2478  * 4 bytes added as FCS per fragment. Hence we need to add it in SW,
   2479  * when those counters are retrieved by user.
   2480  */
   2481 STATIC void
   2482 _bcm_kt2_linkphy_add_FCS_bytes_count_to_frag_byte_ctr(uint64 *val,
   2483                                              uint64 num_fragments)
   2484 {
   2485     /* Add the current frag byte counter with
   2486      * 4 bytes of FCS per fragment * num of fragments
   2487      */
   2488     COMPILER_64_UMUL_32(num_fragments,  4);
   2489     COMPILER_64_ADD_64(*val, num_fragments);
   2490 }
   2491 
   2492 /*
   2493  * Function:
   2494  *      _bcm_linkphy_subport_port_stat_get
   2495  * Purpose:
   2496  *      Get the statistics value for LinkPHY subport port and statistics type
   2497  * Parameters:
   2498  *      unit      - (IN) Device Number
   2499  *      subport   - (IN) subport port
   2500  *      stream_id - (IN) stream ID array index
   2501  *      stat_type - (IN) statistics type
   2502  *      val       - (OUT) value
   2503  * Returns:
   2504  *      BCM_E_XXX
   2505  */
   2506 STATIC int
   2507 _bcm_linkphy_subport_port_stat_get(
   2508     int unit,
   2509     bcm_gport_t subport,
   2510     int stream_id,
   2511     bcm_subport_stat_t stat_type,
   2512     uint64 *val)
   2513 {
   2514     int direction = 0, block = 0;
   2515     int rv = BCM_E_NONE, i = 0;
   2516     uint16 counter_id = 0;
   2517     uint16 ext_stream_id_base = 0;
   2518     uint16 port_e_stream_id_base_adj = 0;
   2519     uint16 blk_i_stream_id = 0;
   2520     bcm_port_t port;
   2521     bcm_subport_config_t config;
   2522 
   2523     /* get port from subport */
   2524     bcm_subport_config_t_init(&config);
   2525     rv = _bcm_linkphy_subport_port_get(unit, subport, &config);
   2526     if (BCM_FAILURE(rv)) {
   2527         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2528                   (BSL_META_U(unit,
   2529                               "ERROR: _bcm_linkphy_subport_port_get failed \n"
   2530                                "for subport 0x%x\n"), subport));
   2531         return rv;
   2532     }
   2533 
   2534     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config.group);
   2535 
   2536     rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port,
   2537             &ext_stream_id_base);
   2538     if (BCM_FAILURE(rv)) {
   2539         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2540                   (BSL_META_U(unit,
   2541                               "ERROR: Linkphy port %d external "
   2542                                "stream id base get failed\n"), port));
   2543         return rv;
   2544     }
   2545 
   2546     if ((stream_id != -1) && (stream_id >= config.num_streams)) {
   2547         return BCM_E_PARAM;
   2548     }
   2549 
   2550     rv = soc_linkphy_port_blk_idx_get(unit, port, &block, NULL);
   2551     if (SOC_FAILURE(rv)) {
   2552         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2553                   (BSL_META_U(unit,
   2554                               
   2555                                "ERROR: LinkPHY block, index get failed for port %d\n"), port));
   2556         return rv;
   2557     }
   2558 
   2559     switch (stat_type) {
   2560         case bcmSubportLinkPhyStatRxFragmentBytes:
   2561         case bcmSubportLinkPhyStatRxFragments:
   2562         case bcmSubportLinkPhyStatRxFrameBytes:
   2563         case bcmSubportLinkPhyStatRxFrames:
   2564             direction = _BCM_KT2_LINKPHY_DIRECTION_RX;
   2565             break;
   2566         case bcmSubportLinkPhyStatTxFragmentBytes:
   2567         case bcmSubportLinkPhyStatTxFragments:
   2568         case bcmSubportLinkPhyStatTxFrameBytes:
   2569         case bcmSubportLinkPhyStatTxFrames:
   2570             direction = _BCM_KT2_LINKPHY_DIRECTION_TX;
   2571             break;
   2572         default:
   2573             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2574                         (BSL_META_U(unit,
   2575                                     "LinkPHY Statistic not supported: %d\n"), stat_type));
   2576             return BCM_E_PARAM;
   2577             break;
   2578     }
   2579 
   2580     BCM_LINKPHY_COUNTER_LOCK(unit);
   2581 
   2582     COMPILER_64_ZERO(*val);
   2583 
   2584     for (i =0; i < config.num_streams; i++) {
   2585         if (stream_id != i) {
   2586             /* if stream_id == -1 then get the stats for all
   2587             * streams associated with the LinkPHY subport and add them*/
   2588             if (stream_id != -1) {
   2589                 continue;
   2590             }
   2591         }
   2592 
   2593         /*
   2594          * Port external stream Id after adjusting the 
   2595          * port external stream id base.
   2596          * Range from 0 - 127.
   2597          */
   2598         port_e_stream_id_base_adj = config.stream_id_array[i] -
   2599                                       ext_stream_id_base;
   2600 
   2601         /* 
   2602          * get the rxlp block internal stream id(0 - 127) for the
   2603          * external stream id.
   2604          */ 
   2605         BCM_IF_ERROR_RETURN(_bcm_linkphy_port_rx_int_stream_map_port_get(unit,
   2606                                         port, port_e_stream_id_base_adj, 
   2607                                         &blk_i_stream_id));
   2608 
   2609         /* counter index is same as rxlp block internal stream id */
   2610         counter_id = blk_i_stream_id;
   2611 
   2612 
   2613         if ((stat_type == bcmSubportLinkPhyStatRxFragmentBytes) ||
   2614             (stat_type ==  bcmSubportLinkPhyStatTxFragmentBytes)) {
   2615             COMPILER_64_ADD_64(*val, linkphy_frag_byte_ctr[unit][direction]
   2616                                                          [block][counter_id]);
   2617             /* On both RXLP and TXLP, fragment bytes counter does not
   2618              * include FCS bytes. Hence we add it when we provide stats
   2619              * to user.
   2620              */
   2621             _bcm_kt2_linkphy_add_FCS_bytes_count_to_frag_byte_ctr(val,
   2622                     linkphy_frag_ctr[unit][direction]
   2623                     [block][counter_id]);
   2624         } else if ((stat_type == bcmSubportLinkPhyStatRxFragments) ||
   2625                    (stat_type == bcmSubportLinkPhyStatTxFragments)) {
   2626             COMPILER_64_ADD_64(*val, linkphy_frag_ctr[unit][direction]
   2627                                                     [block][counter_id]);
   2628         } else if ((stat_type == bcmSubportLinkPhyStatRxFrameBytes) ||
   2629                   (stat_type == bcmSubportLinkPhyStatTxFrameBytes)) {
   2630             COMPILER_64_ADD_64(*val, linkphy_frame_byte_ctr[unit][direction]
   2631                                                           [block][counter_id]);
   2632         } else {
   2633             /* if ((stat_type == bcmSubportLinkPhyStatRxFrames) ||
   2634                   (stat_type == bcmSubportLinkPhyStatTxFrames)) */
   2635             COMPILER_64_ADD_64(*val, linkphy_frame_ctr[unit][direction]
   2636                                                      [block][counter_id]);
   2637         }
   2638     }
   2639     BCM_LINKPHY_COUNTER_UNLOCK(unit);
   2640     return BCM_E_NONE;
   2641 }
   2642 
   2643 
   2644 /*
   2645  * Function:
   2646  *      _bcm_linkphy_subport_init
   2647  * Purpose:
   2648  *      Initialize LinkPHY subport module.
   2649  * Parameters:
   2650  *      unit      - Device Number
   2651  * Returns:
   2652  *      BCM_E_XXX
   2653  */
   2654 STATIC int
   2655 _bcm_linkphy_subport_init(int unit)
   2656 {
   2657     int  dev_int_stream_max = 0;
   2658     bcm_port_t port;
   2659     soc_info_t *si = &SOC_INFO(unit);
   2660     int subport_port_max = si->subport_port_max;
   2661     int subport_group_max = si->subport_group_max;
   2662     int index = 0;
   2663     int block = 0;
   2664     int linkphy_enable = 0;
   2665     int rv = BCM_E_NONE;
   2666     int start_index, end_index;
   2667 
   2668     /* Clear TXLP_PORT_STREAM_BITMAP_TABLEm table */
   2669     BCM_IF_ERROR_RETURN
   2670        (soc_mem_clear(unit, TXLP_PORT_STREAM_BITMAP_TABLEm, COPYNO_ALL, TRUE));
   2671 
   2672     /*
   2673      * Check if pbmp_linkphy members are valid for supporting LinkPHY.
   2674      * For Katana2(BCM56450) port 27 to 34 only support LinkPHY 
   2675      */
   2676     BCM_PBMP_ITER(si->linkphy_allowed_pbm, port) {
   2677         if (!_BCM_KT2_PORT_SUPPORTS_LINKPHY(unit, port)) {
   2678             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2679                       (BSL_META_U(unit,
   2680                        "ERROR: config variable pbmp_linkphy "
   2681                        "member port %d is invalid for LinkPHY support\n"), 
   2682                         port));
   2683             return BCM_E_PORT;
   2684         }
   2685     }
   2686 
   2687     /*
   2688      * If config variable linkphy_enable is enabled
   2689      * initialize and setup the linkphy on ports
   2690      * enabled in the config variable "pbmp_linkphy".
   2691      * The config variable "linkphy_enable" is set
   2692      * by default, meaning linkphy is enabled during
   2693      * initialization.
   2694      */
   2695 
   2696     linkphy_enable = soc_property_get(unit, spn_LINKPHY_ENABLE, 1); 
   2697     if (linkphy_enable) {
   2698         port = 0;
   2699         BCM_PBMP_ITER(si->linkphy_allowed_pbm, port) {
   2700             if (BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) {
   2701                 /* Disable the port before enabling LinkPhy */
   2702                 BCM_IF_ERROR_RETURN (bcm_esw_port_enable_set(unit, port, 0));
   2703                 rv = bcm_kt2_port_control_linkphy_status_set(unit, 
   2704                                                             port, 
   2705                                                             linkphy_enable);
   2706                 /* Enable the port */
   2707                 BCM_IF_ERROR_RETURN (bcm_esw_port_enable_set(unit, port, 1));
   2708 
   2709                 if (BCM_FAILURE(rv)) {
   2710                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2711                              (BSL_META_U(unit,
   2712                               "ERROR:Enabling LinkPhy on Port(%d) "
   2713                               "failed - %s\n"),
   2714                                port, bcm_errmsg(rv)));
   2715                     return rv;
   2716                 }
   2717             } /* BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), port) */
   2718         } /* BCM_PBMP_ITER */
   2719     } /* linkphy_enable */
   2720 
   2721     /* LinkPHY group bitmap to keep track of used LinkPHY groups */
   2722     if (_bcm_linkphy_group_bitmap[unit] == NULL) {
   2723 
   2724         _bcm_linkphy_group_bitmap[unit] = 
   2725             sal_alloc(SHR_BITALLOCSIZE(subport_group_max),
   2726             "linkphy_subport_group_bitmap");
   2727 
   2728         if (_bcm_linkphy_group_bitmap[unit] == NULL) {
   2729             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2730                       (BSL_META_U(unit,
   2731                                   "ERROR:subport_init: group bitmap alloc failed\n")));
   2732 
   2733             return BCM_E_MEMORY;
   2734         }
   2735     }
   2736 
   2737     sal_memset(_bcm_linkphy_group_bitmap[unit], 0,
   2738         SHR_BITALLOCSIZE(subport_group_max));
   2739 
   2740    /* LinkPHY device internal stream ID bitmap to keep track of the device
   2741    * internal stream ID used. A device internal stream id can be active on
   2742    * one port at a time.
   2743    */
   2744     dev_int_stream_max = 2 * subport_port_max;
   2745     if (_bcm_dev_int_stream_id_bitmap[unit] == NULL) {
   2746 
   2747         _bcm_dev_int_stream_id_bitmap[unit] =
   2748             sal_alloc(SHR_BITALLOCSIZE(dev_int_stream_max),
   2749                 "dev_int_stream_id_bitmap");
   2750 
   2751         if (_bcm_dev_int_stream_id_bitmap[unit] == NULL) {
   2752             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2753                       (BSL_META_U(unit,
   2754                                   "ERROR:subport_init: dev_int_stream_id_bitmap "
   2755                                    " alloc failed\n")));
   2756 
   2757             return BCM_E_MEMORY;
   2758         }
   2759     }
   2760     sal_memset(_bcm_dev_int_stream_id_bitmap[unit], 0,
   2761         SHR_BITALLOCSIZE(dev_int_stream_max));
   2762 
   2763     /* LinkPHY subport port info per pp_port */
   2764     if (_bcm_linkphy_subport_port_info[unit] == NULL) {
   2765         _bcm_linkphy_subport_port_info[unit] =
   2766             sal_alloc((SOC_MAX_NUM_PP_PORTS *
   2767                        sizeof(_bcm_linkphy_subport_port_info_t)),
   2768                        "linkphy_subport_port_info");
   2769         if (_bcm_linkphy_subport_port_info[unit] == NULL) {
   2770             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2771                       (BSL_META_U(unit,
   2772                                   "ERROR: "
   2773                                    " linkphy_subport_port_info alloc failed\n")));
   2774 
   2775                 return BCM_E_MEMORY;
   2776         }
   2777     }
   2778 
   2779     sal_memset(_bcm_linkphy_subport_port_info[unit], 0,
   2780         (SOC_MAX_NUM_PP_PORTS * sizeof(_bcm_linkphy_subport_port_info_t)));
   2781 
   2782     for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) {
   2783         _bcm_linkphy_subport_port_info[unit][index].group = -1;
   2784         _bcm_linkphy_subport_port_info[unit][index].num_streams = -1;
   2785     }
   2786 
   2787 #if defined(BCM_METROLITE_SUPPORT)
   2788     if (SOC_IS_METROLITE(unit)) {
   2789         /* Allocate for _BCM_ML_MAX_LINKPHY_PORTS */
   2790         for (index = 0; index < _BCM_ML_MAX_LINKPHY_PORTS; index++) {
   2791             start_index = si->port_subport_base[index+1];
   2792             end_index   = si->port_subport_base[index+1] + si->port_num_subport[index+1] - 1;
   2793             rv = shr_idxres_list_create(&(_bcm_ml_int_stream_id_pool[unit][index]),
   2794                     start_index, end_index,
   2795                     start_index, end_index,
   2796                     "ml_int_stream_id_pool");
   2797         }
   2798     } else
   2799 #endif
   2800 #if defined(BCM_SABER2_SUPPORT)
   2801     if (SOC_IS_SABER2(unit)) {
   2802         /* Allocate for _BCM_SB2_MAX_LINKPHY_PORTS */
   2803         for (index = 0; index < SOC_INFO(unit).lp_ports_max; index++) {
   2804             start_index = si->port_linkphy_s1_base[index+1];
   2805             end_index   = start_index + (si->port_num_subport[index+1] * 2)- 1;
   2806             rv = shr_idxres_list_create(&(_bcm_sb2_int_stream_id_pool[unit][index]),
   2807                                         start_index, end_index,
   2808                                         start_index, end_index,
   2809                                         "sb2_int_stream_id_pool");
   2810         }
   2811     } else
   2812 #endif
   2813     {
   2814         for (block = 0; block < SOC_INFO(unit).lp_block_max; block++) {
   2815              for (index =0; index < SOC_KT2_LINKPHY_BLOCK_PORT_IDX_MAX;
   2816                   index++) {
   2817                   start_index = 0;
   2818                   end_index = _BCM_KT2_LINKPHY_PER_BLK_STREAMS_MAX - 1;
   2819                   rv = shr_idxres_list_create(
   2820                          &(_bcm_kt2_blk_int_stream_id_pool[unit][block][index]),
   2821                            start_index, end_index,
   2822                            start_index, end_index,
   2823                            "kt2_blk_int_stream_id_pool");
   2824              }
   2825         }
   2826     }
   2827 
   2828     /* Set the STP state of subports */
   2829     BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, port) {
   2830         bcm_esw_port_learn_set(unit, port,
   2831                 BCM_PORT_LEARN_ARL | BCM_PORT_LEARN_FWD);
   2832         bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD);
   2833     }
   2834 
   2835     /* Register for RXLP interrupts */
   2836     soc_kt2_linkphy_handler_register(unit, &_bcm_kt2_subport_linkphy_rx_error_handler);
   2837     return BCM_E_NONE;
   2838 }
   2839 
   2840 /*
   2841  * Function:
   2842  *      _bcm_linkphy_subport_group_create
   2843  * Purpose:
   2844  *      Create a LinkPHY subport group
   2845  * Parameters:
   2846  *      unit   - (IN) Device Number
   2847  *      config - (IN) Subport group config information
   2848  *      group  - (OUT) GPORT (generic port) identifier
   2849  * Returns:
   2850  *      BCM_E_XXX
   2851  */
   2852 STATIC int
   2853 _bcm_linkphy_subport_group_create(int unit,
   2854                                   int is_trunk, bcm_port_t port,
   2855                                   int group_id, bcm_gport_t *group)
   2856 {
   2857     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   2858 
   2859     _BCM_KT2_LINKPHY_SUBPORT_GROUP_SET(*group, port, group_id);
   2860     _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(*group);
   2861 
   2862     _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_SET(unit, group_id);
   2863     _bcm_linkphy_subport_group_count[unit]++;
   2864 
   2865     return BCM_E_NONE;
   2866 }
   2867 
   2868 /*
   2869  * Function:
   2870  *      _bcm_linkphy_subport_group_destroy
   2871  * Purpose:
   2872  *      Destroy the LinkPHY subport group and all subport ports attached to it.
   2873  * Parameters:
   2874  *      unit   - (IN) Device Number
   2875  *      group  - (IN) GPORT (generic port) identifier for subport group
   2876  * Returns:
   2877  *      BCM_E_XXX
   2878  */
   2879 STATIC int 
   2880 _bcm_linkphy_subport_group_destroy(int unit,
   2881                                    bcm_gport_t group)
   2882 {
   2883     int group_id = -1;
   2884     int pp_port = 0, rv = BCM_E_NONE;
   2885     int linkphy_subport_count = 0;
   2886     bcm_gport_t subport_port_gport;
   2887 
   2888     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   2889 
   2890     if (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) {
   2891 
   2892         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   2893 
   2894         if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   2895             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2896                       (BSL_META_U(unit,
   2897                                   "ERROR: LinkPHY subport group 0x%x not found.\n"),
   2898                        group));
   2899             return BCM_E_NOT_FOUND;
   2900         }
   2901 
   2902         linkphy_subport_count =
   2903             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   2904 
   2905         /* delete all subport ports attached to the subport group */
   2906         BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port) {
   2907             if (linkphy_subport_count == 0) {
   2908                 break;
   2909             }
   2910 
   2911             if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   2912                 continue;
   2913             }
   2914 
   2915             if (group !=
   2916                 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   2917                 continue;
   2918             }
   2919 
   2920             _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port_gport, pp_port);
   2921 
   2922             _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port_gport,
   2923                                            _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   2924 
   2925             rv = _bcm_linkphy_subport_port_delete(unit, subport_port_gport);
   2926             if (SOC_FAILURE(rv)) {
   2927                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2928                           (BSL_META_U(unit,
   2929                                       "ERROR: LinkPHY subport group 0x%x destroy failed \n"
   2930                                       " to delete subport port (subport group id %d, "
   2931                                       " pp_port id %d)\n"),
   2932                            group, group_id, pp_port));
   2933                 return rv;
   2934             }
   2935             linkphy_subport_count--;
   2936         }
   2937 
   2938         *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0;
   2939         /* delete the subport group */
   2940         _bcm_subport_group_count[unit]--;
   2941         _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id);
   2942         _bcm_linkphy_subport_group_count[unit]--;
   2943         _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_CLR(unit, group_id);
   2944     }
   2945 
   2946     return BCM_E_NONE;
   2947 }
   2948 
   2949 /*
   2950  * Function:
   2951  *      _bcm_linkphy_subport_group_get
   2952  * Purpose:
   2953  *      Get a subport group
   2954  * Parameters:
   2955  *      unit   - (IN) Device Number
   2956  *      group  - (IN) GPORT (generic port) identifier
   2957  *      config - (OUT) Subport group config information
   2958  * Returns:
   2959  *      BCM_E_XXX
   2960  */
   2961 STATIC int
   2962 _bcm_linkphy_subport_group_get(int unit,
   2963                                bcm_gport_t group,
   2964                                bcm_subport_group_config_t *config)
   2965 {
   2966     int group_id = -1;
   2967 
   2968     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   2969 
   2970     if (config == NULL) {
   2971         return BCM_E_PARAM;
   2972     }
   2973 
   2974     if (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) {
   2975         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   2976         if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   2977             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   2978                       (BSL_META_U(unit,
   2979                                   "ERROR: LinkPHY subport group 0x%x not found.\n"),
   2980                        group));
   2981             return BCM_E_NOT_FOUND;;
   2982         }
   2983         config->flags |= BCM_SUBPORT_GROUP_TYPE_LINKPHY;
   2984         config->port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(group);
   2985     } else {
   2986         return BCM_E_PARAM;
   2987     }
   2988 
   2989     return BCM_E_NONE;
   2990 }
   2991 
   2992 /*
   2993  * Function:
   2994  *      _bcm_linkphy_subport_group_traverse
   2995  * Purpose:
   2996  *      Traverse all valid subports for given LinkPHY subport group
   2997  *      and call the user supplied callback routine.
   2998  * Parameters:
   2999  *      unit      - Device Number
   3000  *      group     - Subport group GPORT identifier
   3001  *      cb        - User callback function, called once per subport.
   3002  *      user_data - cookie
   3003  */
   3004 
   3005 STATIC int
   3006 _bcm_linkphy_subport_group_traverse(int unit,
   3007                                     bcm_gport_t group,
   3008                                     bcm_subport_port_traverse_cb cb,
   3009                                     void *user_data)
   3010 {
   3011     int rv = BCM_E_NONE, group_id = 0;
   3012     int pp_port = 0, subport_port;
   3013     int linkphy_subport_count = 0;
   3014     bcm_subport_config_t config;
   3015 
   3016     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   3017 
   3018     bcm_subport_config_t_init(&config);
   3019 
   3020     if (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) {
   3021         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   3022 
   3023         if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   3024             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3025                       (BSL_META_U(unit,
   3026                                   "ERROR: LinkPHY subport group 0x%x not found.\n"),
   3027                        group));
   3028             return BCM_E_NOT_FOUND;
   3029         }
   3030 
   3031         linkphy_subport_count =
   3032             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   3033         
   3034         BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port) {
   3035 
   3036             if (linkphy_subport_count == 0) {
   3037                 break;
   3038             }
   3039 
   3040             if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   3041                 continue;
   3042             }
   3043 
   3044             if (group !=
   3045                 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   3046                 continue;
   3047             }
   3048 
   3049             _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port);
   3050 
   3051             _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   3052                                            _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   3053 
   3054             rv = _bcm_linkphy_subport_port_get(unit, subport_port, &config);
   3055             if (SOC_FAILURE(rv)) {
   3056                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3057                           (BSL_META_U(unit,
   3058                                       "ERROR: LinkPHY subport group 0x%x traverse failed \n"
   3059                                       "to get subport port (group id %d, pp_port id %d)\n"),
   3060                            group, group_id, pp_port));
   3061                 return rv;
   3062             }
   3063 
   3064 #ifdef BCM_CB_ABORT_ON_ERR
   3065             rv = cb(unit, subport_port, &config, user_data);
   3066             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   3067                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3068                           (BSL_META_U(unit,
   3069                                       "ERROR: subport group 0x%x traverse failed \n"
   3070                                        "to callback for subport port (group id %d, "
   3071                                        "subport id %d)\n"), group, group_id, pp_port));
   3072                 return rv;
   3073             }
   3074 #else
   3075             (void)cb(unit, subport_port, &config, user_data);
   3076 #endif
   3077             linkphy_subport_count--;
   3078         }
   3079     } else {
   3080         return BCM_E_PARAM;
   3081     }
   3082     return BCM_E_NONE;
   3083 }
   3084 
   3085 
   3086 /*
   3087  * Function:
   3088  *      _bcm_kt2_allocate_pp_port
   3089  * Purpose:
   3090  *      Allocate a pp_port based on supplied info
   3091  * Parameters:
   3092  *      unit   - (IN) Device Number
   3093  *      config - (IN) Subport config information
   3094  *      pp_port_index  - (OUT) pp_port allocated
   3095  * Returns:
   3096  *      BCM_E_XXX
   3097  */
   3098 STATIC int _bcm_kt2_allocate_pp_port(int unit, bcm_subport_config_t *config,
   3099                                      int *pp_port_index)
   3100 {
   3101     soc_info_t *si = &SOC_INFO(unit);
   3102     int port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group), i = 0;
   3103     int mod_id = 0, port_id = 0;
   3104 #if defined BCM_METROLITE_SUPPORT
   3105     int found_flag = 0;
   3106 #endif
   3107 
   3108     /* If a valid gport is supplied use it, else allocate one */
   3109     if(BCM_GPORT_IS_MODPORT(config->subport_modport)) {
   3110 
   3111         /* The user can use this field to set (mod,port) only if the
   3112            coe-stacking mode is enabled */
   3113         if(!si->coe_stacking_mode) {
   3114             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3115               (BSL_META_U(unit,"ERROR: CoE stacking mode not enabled\n")));
   3116             return BCM_E_PARAM;
   3117         }
   3118 
   3119         mod_id = BCM_GPORT_MODPORT_MODID_GET(config->subport_modport);
   3120         port_id = BCM_GPORT_MODPORT_PORT_GET(config->subport_modport);
   3121         /* Check if the supplied CoE-(mod,port) is valid */
   3122         if(_bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE,
   3123                                       mod_id, port_id) != BCM_E_NONE) {
   3124             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3125                       (BSL_META_U(unit,"ERROR: Supplied (mod,port) (%d,%d) "
   3126                                        "not valid\n"),
   3127                                         mod_id, port_id));
   3128             return BCM_E_PARAM;
   3129         }
   3130 
   3131         /* Also check that the corresponding pp_port is valid on this
   3132            physical port */
   3133         BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit,
   3134                                     mod_id, port_id, pp_port_index));
   3135 
   3136         if((*pp_port_index >= si->port_subport_base[port]) &&
   3137            (*pp_port_index < (si->port_subport_base[port] +
   3138                              (si->port_num_subport[port]) - 1))) {
   3139             /* This pp_port is valid, now check if it is already in use */
   3140             if(_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, *pp_port_index)) {
   3141                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3142                           (BSL_META_U(unit,"ERROR: Supplied (mod,port)"
   3143                                            "(%d,%d) mapped pp_port: %d "
   3144                                            "in use already \n"),
   3145                                             mod_id, port_id, *pp_port_index));
   3146                 return BCM_E_PARAM;
   3147             }
   3148         } else {
   3149             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3150                       (BSL_META_U(unit,"ERROR: Supplied (mod,port)"
   3151                           "(%d,%d) mapped pp_port: %d not valid on "
   3152                           "physical port %d \n"), mod_id, port_id,
   3153                             *pp_port_index, port));
   3154         }
   3155     } else {
   3156 #if defined BCM_METROLITE_SUPPORT
   3157         if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   3158             SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, port), i) {
   3159                 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, i)) {
   3160                     *pp_port_index = i;
   3161                     found_flag = 1;
   3162                     break;
   3163                 }
   3164             }
   3165             if (found_flag == 0) {
   3166                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3167                         (BSL_META_U(unit,
   3168                          "ERROR: All %d subport pp_port already used.\n"),
   3169                          (si->port_num_subport[port])));
   3170                 return BCM_E_FULL;
   3171             }
   3172         } else 
   3173 #endif
   3174         {
   3175             /* Alocate a pp_port for use with this subport */
   3176             for (i = si->port_subport_base[port];
   3177                     i < (si->port_subport_base[port] + si->port_num_subport[port]);
   3178                     i++) {
   3179                 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, i)) {
   3180                     *pp_port_index = i;
   3181                     break;
   3182                 }
   3183             }
   3184 
   3185             if (i == (si->port_subport_base[port] + si->port_num_subport[port])) {
   3186                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3187                         (BSL_META_U(unit,
   3188                                     "ERROR: All %d subport pp_port already used.\n"),
   3189                          (i - si->port_subport_base[port])));
   3190                 return BCM_E_FULL;
   3191             }
   3192         }
   3193 
   3194         /* If the user is running in an enhanced mode, get the mapped
   3195            (module, port) associated with this pp_port and validate
   3196            the same */
   3197         if(si->coe_stacking_mode) {
   3198 
   3199             /* Get the mod-port that corresponds to this pp_port */
   3200             BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(unit,
   3201                                          *pp_port_index, &mod_id, &port_id));
   3202 
   3203             /* Check if the mapped CoE-(mod,port) is valid */
   3204             if(_bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE,
   3205                                           mod_id, port_id) != BCM_E_NONE) {
   3206                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3207                           (BSL_META_U(unit,"ERROR: pp_port (%d) Mapped (mod,port)"
   3208                                            "(%d,%d) not created \n"),
   3209                                             *pp_port_index, mod_id, port_id));
   3210                 return BCM_E_CONFIG;
   3211             }
   3212         }
   3213     }
   3214 
   3215     /* Put together a CoE-MODPORT for subsequent use */
   3216     if(si->coe_stacking_mode) {
   3217         BCM_GPORT_MODPORT_SET(config->subport_modport, mod_id, port_id);
   3218     }
   3219 
   3220     return BCM_E_NONE;
   3221 }
   3222 
   3223 /*
   3224  * Function:
   3225  *      _bcmi_linkphy_subport_stream_int_stream_get
   3226  * Purpose:
   3227  *      Return an internal stream id for a given external
   3228  *      stream id
   3229  * Parameters:
   3230  *      unit   - (IN) Device number.
   3231  *      config  - (IN LInkphy port config info
   3232  *      ext_stream_id   - (IN) External stream id value
   3233  *      blk_int_stream_id   - (OUT) Internal stream id value
   3234  * Returns:
   3235  *      BCM_E_XXX
   3236  */
   3237 STATIC int
   3238 _bcmi_linkphy_subport_stream_int_stream_get(int unit,
   3239                                             bcm_subport_config_t *config,
   3240                                             int ext_stream_id,
   3241                                             uint16 *blk_int_stream_id)
   3242 {
   3243     uint16 ext_stream_id_base = 0;
   3244     int phy_port = 0;
   3245     uint16 port_e_stream_id_base_adj = 0;
   3246     int lp_block, lp_index, rv = BCM_E_NONE;
   3247 
   3248     /* Get the associated physical phy_port */
   3249     phy_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group);
   3250 
   3251     /* Get the stream id base for this physical phy_port */
   3252     rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, phy_port,
   3253                &ext_stream_id_base);
   3254     if (BCM_FAILURE(rv)) {
   3255         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3256                  (BSL_META_U(unit,
   3257                   "ERROR: Linkphy subport group external stream id "
   3258                   "base get failed for phy_port %d.\n"), phy_port));
   3259         return rv;
   3260     }
   3261 
   3262     rv = soc_linkphy_port_blk_idx_get(unit, phy_port, &lp_block, &lp_index);
   3263     if (SOC_FAILURE(rv)) {
   3264         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3265                 (BSL_META_U(unit,
   3266                 "ERROR: LinkPHY block, index get failed for phy_port %d\n"),
   3267                 phy_port));
   3268         return rv;
   3269     }
   3270 
   3271     /* Compute the port stream id base */
   3272     port_e_stream_id_base_adj = ext_stream_id - ext_stream_id_base;
   3273 
   3274     /* Get the associated internal stream id for this ext stream*/
   3275     BCM_IF_ERROR_RETURN(
   3276             _bcm_linkphy_port_rx_int_stream_map_port_get(unit, phy_port,
   3277                 port_e_stream_id_base_adj, blk_int_stream_id));
   3278 
   3279     return BCM_E_NONE;
   3280 }
   3281 
   3282 /*
   3283  * Function:
   3284  *      _bcmi_linkphy_subport_stream_dfc_update
   3285  * Purpose:
   3286  *      Updates the DFC state for a given ext stream id
   3287  * Parameters:
   3288  *      unit   - (IN) Device number.
   3289  *      config  - (IN LInkphy port config info
   3290  *      pp_port_index - (IN) pp_port this external stream is a part of
   3291  *      ext_stream_id   - (IN) External stream id value
   3292  *      enable  - (IN) Port enable/disable status.
   3293  * Returns:
   3294  *      BCM_E_XXX
   3295  */
   3296 extern int
   3297 _bcmi_linkphy_subport_stream_dfc_update(int unit,
   3298                                         bcm_subport_config_t *config,
   3299                                         int pp_port_index,
   3300                                         int ext_stream_id,
   3301                                         int enable)
   3302 {
   3303     uint16 blk_int_stream_id = 0;
   3304     int phy_port = 0;
   3305     int rv = BCM_E_NONE;
   3306 
   3307     /* Get the internal stream associated with this ext stream id */
   3308     BCM_IF_ERROR_RETURN(_bcmi_linkphy_subport_stream_int_stream_get(unit, config,
   3309                                               ext_stream_id, &blk_int_stream_id));
   3310 
   3311     /* Get the associated physical phy_port */
   3312     phy_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group);
   3313 
   3314     /* RXLP */
   3315     /* Update the DFC state for this stream */
   3316     rv = _bcm_linkphy_port_rx_flow_control_set(unit, phy_port,
   3317                                           blk_int_stream_id, enable);
   3318     if (SOC_FAILURE(rv)) {
   3319         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3320                   (BSL_META_U(unit,
   3321                    "ERROR: RX flow control update failed\n"
   3322                    " for, internal ext_stream_id = %d.\n"),
   3323                     blk_int_stream_id));
   3324         return rv;
   3325     }
   3326 
   3327     return rv;
   3328 }
   3329 
   3330 /*
   3331  * Function:
   3332  *      _bcmi_linkphy_subport_stream_flush
   3333  * Purpose:
   3334  *      Performs a flushe for the given ext stream ids
   3335  * Parameters:
   3336  *      unit   - (IN) Device number.
   3337  *      config  - (IN LInkphy port config info
   3338  *      pp_port_index - (IN) pp_port this external stream is a part of
   3339  *      ext_stream_id   - (IN) External stream id value
   3340  * Returns:
   3341  *      BCM_E_XXX
   3342  */
   3343 extern int
   3344 _bcmi_linkphy_subport_stream_flush(int unit,
   3345                                    bcm_subport_config_t *config,
   3346                                    int pp_port_index,
   3347                                    int ext_stream_id)
   3348 {
   3349     uint16 blk_int_stream_id = 0;
   3350     int phy_port = 0, poll_active = 0;
   3351     int rv = BCM_E_NONE;
   3352     uint32 timeoutval = 0, regval = 0;
   3353     soc_timeout_t timeout;
   3354     soc_reg_t reg;
   3355 
   3356     /* Get the internal stream associated with this ext stream id */
   3357     BCM_IF_ERROR_RETURN(_bcmi_linkphy_subport_stream_int_stream_get(unit, config,
   3358                                               ext_stream_id, &blk_int_stream_id));
   3359 
   3360     /* Get the associated physical phy_port */
   3361     phy_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group);
   3362 
   3363     /* Perform an RX flush */
   3364     reg = RXLP_SW_FLUSH_CONTROLr;
   3365     if (SOC_REG_PORT_VALID(unit, reg, phy_port)) {
   3366 
   3367         timeoutval = _BCM_KT2_LINKPHY_STREAM_ID_FLUSH_TIMEOUT;
   3368         soc_timeout_init(&timeout, timeoutval, 0);
   3369 
   3370         /* If warmboot is enabled, HW calls just get written in cache
   3371          * and does not write into HW. So FLUSH timeouts are seen during
   3372          * exit clean which enables warmboot mode. Hence checking for
   3373          * SOC_WARM_BOOT.
   3374          */
   3375         if (!(SAL_BOOT_SIMULATION || SOC_WARM_BOOT(unit))) {
   3376             BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg,
   3377                         phy_port, FLUSH_STREAM_IDf, blk_int_stream_id));
   3378             BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg,
   3379                         phy_port, FLUSH_ACTIVEf, 1));
   3380 
   3381             poll_active = 1;
   3382 
   3383             while (poll_active) {
   3384 
   3385                 if (soc_timeout_check(&timeout)) {
   3386                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3387                               (BSL_META_U(unit,
   3388                                "ERROR: RX stream id %d flush timeout :"
   3389                                "phy_port = %d, pp_port %d\n"),
   3390                                blk_int_stream_id,
   3391                                phy_port, pp_port_index));
   3392                     return BCM_E_TIMEOUT;
   3393                 }
   3394 
   3395                 BCM_IF_ERROR_RETURN(
   3396                     READ_RXLP_SW_FLUSH_CONTROLr(unit, phy_port, &regval));
   3397 
   3398                 poll_active = (soc_reg_field_get(unit, reg, regval,
   3399                                    FLUSH_DONEf)) ? 0 :1;
   3400 
   3401             }
   3402         }
   3403     }
   3404 
   3405     return rv;
   3406 }
   3407 
   3408 /*
   3409  * Function:
   3410      *      _bcm_linkphy_subport_port_add
   3411  * Purpose:
   3412  *      Add a LinkPHY subport to a subport group
   3413  * Parameters:
   3414  *      unit   - (IN) Device Number
   3415  *      config - (IN) Subport config information
   3416  *      port   - (OUT) Subport_port GPORT (generic port) identifier
   3417  * Returns:
   3418  *      BCM_E_XXX
   3419  */
   3420 STATIC int
   3421 _bcm_linkphy_subport_port_add(int unit,
   3422                               bcm_subport_config_t *config,
   3423                               bcm_gport_t *gport)
   3424 {
   3425     int rv = BCM_E_NONE, port = 0, enable = 0, lp_index = 0, lp_block = 0;
   3426     int sp_group_idx = -1, i = 0;
   3427     int start_addr = 0, end_addr = 0;
   3428     uint16 dev_int_stream_id_base = 0, ext_stream_id_base = 0;
   3429     uint32 dev_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3430     uint16 ext_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3431     int pp_port_index = 0;
   3432     soc_mem_t mem;
   3433     soc_info_t *si = &SOC_INFO(unit);
   3434     device_stream_id_to_pp_port_map_entry_t dev_sid_to_pp_entry;
   3435     pp_port_to_physical_port_map_entry_t    pp_to_port_entry;
   3436     uint32 two_s1s_in_s0_config = 0;
   3437     uint32 blk_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3438     int num_max_stream = si->lp_streams_per_subport;
   3439     uint32 blk_port_idx_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3440     soc_pbmp_t pbmp_linkphy_one_stream_per_subport;
   3441 
   3442     /* A. PARAMETER VALIDATION
   3443  */
   3444     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   3445 
   3446     /* Make sure the group exists */
   3447     if (!_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(config->group)) {
   3448         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3449                   (BSL_META_U(unit,
   3450                               "ERROR: subport group 0x%x is not LinkPHY group\n"),
   3451                    config->group));
   3452         return BCM_E_PARAM;
   3453     }
   3454 
   3455     sp_group_idx =
   3456         _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group);
   3457     if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, sp_group_idx)) {
   3458         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3459                   (BSL_META_U(unit,
   3460                               "ERROR: subport group 0x%x does not exist. group id =%d\n"),
   3461                    config->group, sp_group_idx));
   3462         return BCM_E_NOT_FOUND;
   3463     }
   3464 
   3465     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group);
   3466     rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index);
   3467     if (SOC_FAILURE(rv)) {
   3468         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3469                  (BSL_META_U(unit,
   3470                  "ERROR: LinkPHY block, index get failed for port %d\n"),
   3471                  port));
   3472         return rv;
   3473     }
   3474 
   3475     /* Check if port is member of pbmp_linkphy */
   3476     if (!SOC_PBMP_MEMBER(si->linkphy_pbm, port)) {
   3477         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3478                   (BSL_META_U(unit,
   3479                               "ERROR: Port %d is not member of pbmp_linkphy\n"),
   3480                    port));
   3481         return BCM_E_PORT;
   3482     }
   3483 
   3484     if (si->port_num_subport[port] <= 0) {
   3485         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3486                   (BSL_META_U(unit,
   3487                               "ERROR: %d number of subports available for port %d\n"),
   3488                    si->port_num_subport[port], port));
   3489         return BCM_E_CONFIG;
   3490     }
   3491     SOC_PBMP_CLEAR(pbmp_linkphy_one_stream_per_subport);
   3492     if (SOC_IS_SABER2(unit)) {
   3493         pbmp_linkphy_one_stream_per_subport =
   3494         soc_property_get_pbmp(unit, spn_PBMP_LINKPHY_ONE_STREAM_PER_SUBPORT, 0);
   3495     }
   3496     if (SOC_PBMP_MEMBER(pbmp_linkphy_one_stream_per_subport, port)) {
   3497         num_max_stream = 1;
   3498     }
   3499     if (config->num_streams > num_max_stream) {
   3500         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3501                   (BSL_META_U(unit,
   3502                               "ERROR: num_streams %d cannot be greater than %d\n"),
   3503                    config->num_streams, num_max_stream));
   3504         return BCM_E_PARAM;
   3505     }
   3506 
   3507     if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) {
   3508         if ((config->int_pri < 0 || config->int_pri >= (1 << 4)) ||
   3509             ((config->color != bcmColorGreen) &&
   3510              (config->color != bcmColorYellow) &&
   3511              (config->color != bcmColorRed))) {
   3512              LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3513                        (BSL_META_U(unit,
   3514                                    "ERROR: int_pri %d or color %d is invalid\n"),
   3515                         config->int_pri, config->color));
   3516             return BCM_E_PARAM;
   3517         }
   3518     }
   3519 
   3520     if (_bcm_subport_group_subport_port_count[unit][sp_group_idx] > 0) {
   3521         /* This is not the first linkphy subport in the port. Hence 2_s1s_in_s0
   3522          * config would have been already set. Check if it matches with the
   3523          * config->num_streams passed. We cannot allow mix and match of
   3524          * num_streams between different subports of same
   3525          * subport_group(linkphy port).
   3526          */
   3527         two_s1s_in_s0_config = soc_kt2_cosq_two_s1s_in_s0_config_get(unit, port);
   3528         if (((config->num_streams == 1) && (two_s1s_in_s0_config)) ||
   3529             ((config->num_streams == 2) && (!two_s1s_in_s0_config))) {
   3530             return BCM_E_PARAM;
   3531         }
   3532     }
   3533 
   3534     rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port,
   3535             &ext_stream_id_base);
   3536     if (BCM_FAILURE(rv)) {
   3537         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3538                   (BSL_META_U(unit,
   3539                               "ERROR: Linkphy port %d external "
   3540                                "stream id base get failed\n"), port));
   3541         return rv;
   3542     }
   3543 
   3544     dev_int_stream_id_base = (lp_block)? 128: 0;
   3545 
   3546     for (i = 0; i < config->num_streams; i++) {
   3547         /* Check stream_id range for the port */
   3548 
   3549 #if defined(BCM_SABER2_SUPPORT)
   3550         if (SOC_IS_SABER2(unit)) {
   3551                 if (config->stream_id_array[i] >=
   3552                     (ext_stream_id_base +
   3553                     (SOC_INFO(unit).lp_streams_per_slice_max * (lp_block + 1)))) {
   3554                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3555                         (BSL_META_U(unit,
   3556                         "*ERROR: stream_id %d is out of range for port %d\n"),
   3557                          config->stream_id_array[i], port));
   3558                 return BCM_E_PARAM;
   3559             }
   3560         } else
   3561 #endif
   3562         {
   3563             if (config->stream_id_array[i] >=
   3564                     (ext_stream_id_base + si->port_num_subport[port]
   3565                      * _BCM_KT2_LINKPHY_MAX_STREAM_IDS_PER_PORT)) {
   3566                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3567                         (BSL_META_U(unit,
   3568                          "*ERROR: stream_id %d is out of range for port %d\n"),
   3569                          config->stream_id_array[i], port));
   3570                 return BCM_E_PARAM;
   3571             }
   3572         }
   3573 
   3574         /* check if external stream id is in use on the port */
   3575         rv = _bcmi_linkphy_subport_ext_stream_id_in_use(unit, config,
   3576                                                 config->stream_id_array[i]);
   3577         if (BCM_FAILURE(rv)) {
   3578             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3579                      (BSL_META_U(unit,
   3580                       "*ERROR: External stream id %d is in use!! - %s\n"),
   3581                      config->stream_id_array[i], bcm_errmsg(rv)));
   3582             return rv;
   3583         }
   3584 
   3585        /*
   3586         * Check if the device internal stream_id is already active
   3587         * Device Internal stream id can be active only on one port at a time.
   3588         */
   3589         ext_stream_id[i] = config->stream_id_array[i] - ext_stream_id_base;
   3590 
   3591 #if defined(BCM_METROLITE_SUPPORT)
   3592         if (SOC_IS_METROLITE(unit)) {
   3593             /* Allocate a internal stream id for the given external stream id.
   3594              * Index will be 0 to 3 whereas Port numbers would be 1 to 4. Hence
   3595              * using port - 1 as the index.
   3596              * For Metrolite, dev internal stream id and internal stream id are same
   3597              * since dev internal stream id base is 0.
   3598              */
   3599             rv = shr_idxres_list_alloc(_bcm_ml_int_stream_id_pool[unit][port - 1],
   3600                     (shr_idxres_element_t *)(&(blk_int_stream_id[i])));
   3601         
   3602         } else
   3603 #endif
   3604 #if defined(BCM_SABER2_SUPPORT)
   3605         if (SOC_IS_SABER2(unit)) {
   3606             /* Allocate a internal stream id for the given external stream id.
   3607              * Index will be 0 to 3 whereas Port numbers would be 1 to 4. Hence
   3608              * using port - 1 as the index. 
   3609              * For SB2, dev internal stream id and internal stream id are same
   3610              * since dev internal stream id base is 0.
   3611              */
   3612             rv = shr_idxres_list_alloc(_bcm_sb2_int_stream_id_pool[unit][port -1],
   3613                                        (shr_idxres_element_t *)(&(blk_int_stream_id[i])));
   3614         } else
   3615 #endif
   3616         {
   3617             /*
   3618              * Allocate a internal stream id for this linkphy block
   3619              * for the given external stream id.
   3620              * The internal stream id is in the range of 0 to 127
   3621              * per linkphy block.
   3622              */
   3623             rv = shr_idxres_list_alloc(
   3624                     _bcm_kt2_blk_int_stream_id_pool[unit][lp_block][lp_index],
   3625                     (shr_idxres_element_t *)(&(blk_port_idx_int_stream_id[i])));
   3626         }
   3627 
   3628         if (BCM_FAILURE(rv)) {
   3629             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3630                      (BSL_META_U(unit,
   3631                      "*ERROR: Internal stream id alloc failed for "
   3632                      "External stream_id %d - %s\n"),
   3633                      config->stream_id_array[i], bcm_errmsg(rv)));
   3634             return rv;
   3635         }
   3636 
   3637         if(!SOC_IS_SABER2(unit) && !SOC_IS_METROLITE(unit)) {
   3638            blk_int_stream_id[i] = (si->port_linkphy_s1_base[port]
   3639                                   - dev_int_stream_id_base)
   3640                                   + blk_port_idx_int_stream_id[i];
   3641         }
   3642         /*
   3643          * Device Internal stream Id is in the range 0 to 255.
   3644          * (Internal stream id of block) + (block stream id base)
   3645          */
   3646         dev_int_stream_id[i] = blk_int_stream_id[i] + dev_int_stream_id_base;
   3647 
   3648         if (dev_int_stream_id[i] > soc_mem_index_max(unit,
   3649                                     DEVICE_STREAM_ID_TO_PP_PORT_MAPm)) {
   3650             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3651                       (BSL_META_U(unit,
   3652                       "ERROR: device internal stream_id %d is out of "
   3653                       "range for \nport %d. internal stream id base %d, "
   3654                       "internal stream id %d\n"),
   3655                       dev_int_stream_id[i], port,
   3656                       dev_int_stream_id_base, blk_int_stream_id[i]));
   3657 
   3658             return BCM_E_PARAM;
   3659         }
   3660 
   3661         if (_BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(unit,
   3662                 dev_int_stream_id[i])) {
   3663             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3664                       (BSL_META_U(unit,
   3665                                   "ERROR: Device internal stream_id %d already used.\n"),
   3666                        dev_int_stream_id[i]));
   3667             return BCM_E_EXISTS;
   3668         }
   3669     }
   3670 
   3671     /* B. PP_PORT INDEX RESERVATION
   3672  */
   3673     /* C. PP_PORT INDEX RESERVATION
   3674  */
   3675     /* Reserve PP_PORT index */
   3676     BCM_IF_ERROR_RETURN(_bcm_kt2_allocate_pp_port(unit, config, &pp_port_index));
   3677 
   3678 
   3679     /* C. RXLP/TXLP PROGRAMMING
   3680  */
   3681     for (i = 0; i < config->num_streams; i++) {
   3682 
   3683         mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm;
   3684 
   3685         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, dev_int_stream_id[i],
   3686                 &dev_sid_to_pp_entry);
   3687 
   3688         soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry,
   3689             PP_PORTf, pp_port_index);
   3690 
   3691         /* Set PHB for the subport */
   3692         if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) {
   3693             soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry,
   3694                 PHB_VALIDf, 1);
   3695             soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry,
   3696                 INT_PRIf, config->int_pri);
   3697             soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry,
   3698                 CNGf, config->color);
   3699         }
   3700 
   3701         rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, dev_int_stream_id[i],
   3702                 &dev_sid_to_pp_entry);
   3703 
   3704         if (SOC_FAILURE(rv)) {
   3705             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3706                       (BSL_META_U(unit,
   3707                                   "ERROR: device internal stream id  %d to pp_port %d "
   3708                                    "map failed.\n"), dev_int_stream_id[i], pp_port_index));
   3709 
   3710             return rv;
   3711         }
   3712         SOC_IF_ERROR_RETURN
   3713             (soc_kt2_cosq_lp_repl_map_set(unit, dev_int_stream_id[i], pp_port_index, 1));
   3714 
   3715         /*
   3716         * Steps to Enable New-Stream 
   3717         *  while traffic is flowing on other streams of a Port.:
   3718         * ========================================================
   3719         *    TXLP:
   3720         * 1.First program the active-stream-bitmap-table with this stream.
   3721         * 2.Program the INTERNAL-2-EXTERNAL mapping table for the new-stream.
   3722         * 3.Program the Address-Map-table for that stream.
   3723         * 4.After Step-3, TXLP will send requests to MMU for this stream
   3724         *     and traffic will commence.
   3725         *
   3726         *     RXLP:
   3727         * 1.Reconfigure RXLP_PORT_ACTIVE_STREAM_BITMAP_LO/HI based on
   3728         *      the internal stream ID of the new stream.
   3729         * 2.Configure mapping of external stream ID to internal space in the
   3730         *      table RXLP_INTERNAL_STREAM_MAP_PORT_<0/1/2/3> depending on
   3731         *      the port where the new stream is added.
   3732         * 3.Configure table RXLP_MAX_FRAME_SIZE for the newly added stream ID.
   3733         */
   3734 
   3735         /* TXLP */
   3736 
   3737         enable = 1;
   3738 
   3739         rv = _bcm_linkphy_port_tx_active_stream_set(unit,
   3740                 port, blk_int_stream_id[i], enable);
   3741         if (SOC_FAILURE(rv)) {
   3742             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3743                       (BSL_META_U(unit,
   3744                       "ERROR: TX active stream bitmap enable failed.\n"
   3745                       "port %d, internal stream_id = %d.\n"), 
   3746                       port, blk_int_stream_id[i]));
   3747 
   3748             return rv;
   3749         }
   3750 
   3751         rv = _bcm_linkphy_port_tx_int_to_ext_stream_map_set(unit, 
   3752                                              port, config->stream_id_array[i],
   3753                                              blk_int_stream_id[i], enable);
   3754         if (SOC_FAILURE(rv)) {
   3755             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3756                       (BSL_META_U(unit,
   3757                        "ERROR: TX internal to external stream mapping failed.\n"
   3758                        "port %d, blk internal stream_id = %d, "
   3759                        "external stream id = %d.\n"),
   3760                        port, blk_int_stream_id[i], config->stream_id_array[i]));
   3761 
   3762             return rv;
   3763         }
   3764 
   3765         /*
   3766         * Add start and end address management for TXL Data Buffer.
   3767         * 856 cells have to be distributed across 128 internal streams.
   3768         * Assuming that by default each stream speed is < 1G we will 
   3769         * reserve 6 cells for each stream by default (6 * 128 = 768).
   3770         * Remainig cells can be used when stream speed is
   3771         * set to 10G as per following scheme.
   3772         * Stream-Speed(Gbps) |  Min Num.Cells
   3773         *    < 1G            |     3
   3774         *      1G            |     6
   3775         *      10G           |     50
   3776         */
   3777 
   3778         /*
   3779         * each cell occupies 4 lines of buffer.
   3780         * Assume that by default each stream speed is  1G.
   3781         * so 24 lines of buffer are needed.
   3782         */
   3783 
   3784         start_addr =  SOC_INFO(unit).lp_tx_stream_start_addr_offset + 
   3785             (SOC_INFO(unit).lp_tx_databuf_end_addr_min + 1) *
   3786             blk_int_stream_id[i];
   3787         end_addr = start_addr + SOC_INFO(unit).lp_tx_databuf_end_addr_min;
   3788 
   3789         rv = _bcm_linkphy_port_tx_stream_addr_map_set(unit,
   3790                 port, blk_int_stream_id[i], start_addr, end_addr, enable);
   3791         if (SOC_FAILURE(rv)) {
   3792             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3793                       (BSL_META_U(unit,
   3794                       "ERROR: TX data buffer address set failed.\n"
   3795                       "port %d, internal stream_id = %d, start_addr = %d "
   3796                       "end_addr = %d.\n"), port, blk_int_stream_id[i],
   3797                       start_addr, end_addr));
   3798             return rv;
   3799         }
   3800 
   3801         /* RXLP */
   3802 
   3803         rv = _bcm_linkphy_port_rx_active_stream_bitmap_set(unit,
   3804                 port, blk_int_stream_id[i], enable);
   3805         if (SOC_FAILURE(rv)) {
   3806             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3807                      (BSL_META_U(unit,
   3808                      "ERROR: RX active stream enable failed\n"
   3809                      " port %d, internal stream_id = %d.\n"), port,
   3810                      blk_int_stream_id[i]));
   3811             return rv;
   3812         }
   3813 
   3814         rv = _bcm_linkphy_port_rx_int_stream_map_port_set(unit,
   3815                 port, ext_stream_id[i], blk_int_stream_id[i], enable);
   3816         if (SOC_FAILURE(rv)) {
   3817             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3818                       (BSL_META_U(unit,
   3819                       "ERROR: RX stream map for port enable failed.\n"
   3820                       "port %d, external stream_id = %d, "
   3821                       "internal stream_id = %d.\n"), 
   3822                       port, ext_stream_id[i], blk_int_stream_id[i]));
   3823 
   3824             return rv;
   3825         }
   3826 
   3827         _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(unit, dev_int_stream_id[i]);
   3828 
   3829         _bcm_linkphy_subport_port_info[unit]
   3830             [pp_port_index].ext_stream_idx[i] = config->stream_id_array[i];
   3831     }
   3832 
   3833     rv = soc_kt2_cosq_two_s1s_in_s0_config_set(unit, port,
   3834                             (config->num_streams > 1)?1:0);
   3835     if (SOC_FAILURE(rv)) {
   3836         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3837                   (BSL_META_U(unit,
   3838                               "ERROR: 2 s1s in s0 config failed %s for port %d"
   3839                                "\n"), bcm_errmsg(rv), port));
   3840         return rv;
   3841     }
   3842 
   3843     /*
   3844     * Map PP_PORT to Physical port mapping (IP/ EP):
   3845     * Use the PP_PORT_TO_PHYSICAL_PORT_MAP
   3846     */
   3847     mem = PP_PORT_TO_PHYSICAL_PORT_MAPm;
   3848     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port_index,
   3849             &pp_to_port_entry);
   3850     
   3851     soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry,
   3852         DESTINATIONf, port);
   3853     soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry,
   3854         ISTRUNKf, 0);
   3855 
   3856     rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, pp_port_index,
   3857             &pp_to_port_entry);
   3858 
   3859     if (SOC_FAILURE(rv)) {
   3860         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3861                   (BSL_META_U(unit,
   3862                               "ERROR: pp_port id %d to physical port %d "
   3863                                "map failed.\n"), pp_port_index, port));
   3864         for (i = 0; i < config->num_streams; i++) {
   3865             _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_CLR(unit,
   3866                                                 dev_int_stream_id[i]);
   3867         }
   3868         return rv;
   3869     }
   3870 
   3871     _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, pp_port_index,
   3872         config->group, config->num_streams, TRUE);
   3873 
   3874     _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port_index);
   3875 
   3876     /* Reset the  subport_modport */
   3877     config->subport_modport = 0;
   3878 
   3879     _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   3880 
   3881     *(_bcm_subport_group_subport_port_count[unit]+ sp_group_idx) += 1;
   3882 
   3883     _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port_index);
   3884     _bcm_subport_pp_port_count[unit]++;
   3885 
   3886     /* Add to enabled_linkphy_pbm */
   3887     BCM_PBMP_PORT_ADD(si->enabled_linkphy_pp_port_pbm, pp_port_index);
   3888 
   3889 #ifdef BCM_WARM_BOOT_SUPPORT
   3890     SOC_CONTROL_LOCK(unit);
   3891     SOC_CONTROL(unit)->scache_dirty = 1;
   3892     SOC_CONTROL_UNLOCK(unit);
   3893 #endif
   3894 
   3895     return rv;
   3896 }
   3897 
   3898 /*
   3899  * Function:
   3900  *      _bcm_linkphy_subport_port_delete
   3901  * Purpose:
   3902  *      Delete a LinkPHY subport_port
   3903  * Parameters:
   3904  *      unit   - (IN) Device Number
   3905  *      port   - (IN) Subport_port GPORT (generic port) identifier
   3906  * Returns:
   3907  *      BCM_E_XXX
   3908  */
   3909 STATIC int
   3910 _bcm_linkphy_subport_port_delete(int unit,
   3911                                  bcm_gport_t subport_port_gport)
   3912 {
   3913     int rv = BCM_E_NONE, group_id = 0;
   3914     int port = 0, subport_group = -1, disable = 0, poll_active = 0;
   3915     int dev_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3916     int num_streams = 0, i = 0;
   3917     uint16 dev_int_stream_id_base = 0, ext_stream_id_base = 0;
   3918     uint16 port_e_stream_id_base_adj[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0};
   3919     uint16 pp_port_index = 0;
   3920     uint32 timeoutval = 0, regval = 0;
   3921     soc_timeout_t timeout;
   3922     soc_reg_t reg;
   3923     soc_mem_t mem;
   3924     int lp_block = 0, lp_index = 0;    
   3925     uint16 blk_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3926     uint16 blk_port_idx_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0};
   3927     soc_info_t *si = &SOC_INFO(unit);
   3928 
   3929     if (!_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) {
   3930         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3931                   (BSL_META_U(unit,
   3932                    "ERROR: gport 0x%x is not LinkPHY subport port type.\n"),
   3933                    subport_port_gport));
   3934         return BCM_E_PARAM;
   3935     }
   3936 
   3937     pp_port_index = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport);
   3938 
   3939     if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_index)) {
   3940         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3941                   (BSL_META_U(unit,
   3942                    "ERROR: LinkPHY subport port gport 0x%x is invalid\n"),
   3943                    subport_port_gport));
   3944         return BCM_E_NOT_FOUND;
   3945     }
   3946 
   3947     num_streams = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit,
   3948                       pp_port_index);
   3949     if (num_streams == -1) {
   3950         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3951                   (BSL_META_U(unit,
   3952                    "ERROR: Subport port 0x%x does not have any streams.\n"),
   3953                    subport_port_gport));
   3954         return BCM_E_NOT_FOUND;
   3955     }
   3956 
   3957     subport_group =
   3958         _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_index);
   3959 
   3960     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group);
   3961 
   3962     rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port,
   3963             &ext_stream_id_base);
   3964     if (BCM_FAILURE(rv)) {
   3965         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3966                   (BSL_META_U(unit,
   3967                    "ERROR: Linkphy subport group external stream id "
   3968                    "base get failed for port %d.\n"), port));
   3969         return rv;
   3970     }
   3971 
   3972     rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index);
   3973     if (SOC_FAILURE(rv)) {
   3974         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   3975                 (BSL_META_U(unit,
   3976                  "ERROR: LinkPHY block, index get failed for port %d\n"),
   3977                  port));
   3978         return rv;
   3979     }
   3980     dev_int_stream_id_base = (lp_block)? 128: 0;
   3981 
   3982     /*Disable a Stream while traffic is flowing on other streams of a Port:
   3983     *      RXLP:
   3984     * 1.Set the bit corresponding to the internal stream ID in the register
   3985     *   RXLP_DFC_STATUS_LO/HI to XON.
   3986     *   This is to enable flushing of the data egressing to that stream
   3987     *   from the TXLP.
   3988     * 2.Ensure that the stream being disabled in not sending in data anymore
   3989     * 3.Flush the left over data (partial cell, if any) for the stream
   3990     *   in the RXLP by writing to the register RXLP_SW_FLUSH_CONTROL.
   3991     * 4.Poll the FLUSH_DONE bit in the register RXLP_SW_FLUSH_CONTROL.
   3992     *   Once this bit is read as 1, proceed to the next step.
   3993     * 5.Write 0 to the bit corresponding to the internal stream ID 
   3994     *   in the register RXLP_PORT_ACTIVE_STREAM_BITMAP_LO/HI.
   3995     * 6.Clear the configuration corresponding to the stream in
   3996     *   the table RXLP_INTERNAL_STREAM_MAP_PORT_<0/1/2/3> depending
   3997     *   on the port where the stream being disabled resides.
   3998     *
   3999     *       TXLP:
   4000     * 1. Disabling a stream MUST be done after all the packets 
   4001     *    for that stream have been drained from {MMU-TXLP} sub-system.
   4002     *    This is like Stream/Queue-flush initiated by MMU.
   4003     * 2.Once it has been ascertained that {MMU, TXLP} have been drained,
   4004     *   only then can s/w disable the stream by removing the stream
   4005     *   from ACTIVE-STREAM-BITMAP for that port.
   4006     * 3.ADDR-MAP for this stream should be programmed to ZEROS.
   4007     *   This will also RESET the outstanding MMU-Credit for that SID.
   4008     *   (The same must also be done in MMU).
   4009     */
   4010 
   4011     for (i = 0; i < num_streams; i++) {
   4012 
   4013         port_e_stream_id_base_adj[i] = 
   4014                     _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(
   4015                               unit, pp_port_index, i) - ext_stream_id_base;
   4016 
   4017         BCM_IF_ERROR_RETURN(
   4018               _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port,
   4019                     port_e_stream_id_base_adj[i], &(blk_int_stream_id[i])));
   4020 
   4021         dev_int_stream_id[i] = blk_int_stream_id[i] + dev_int_stream_id_base;
   4022 
   4023         mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm;
   4024         if (dev_int_stream_id[i] > soc_mem_index_max(unit,mem)) {
   4025             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4026                       (BSL_META_U(unit,
   4027                        "ERROR: device internal stream_id %d is out of range \n"
   4028                        "port %d, internal stream id base %d, "
   4029                        "internal stream id %d "
   4030                        "pp_port %d\n"), dev_int_stream_id[i], port,
   4031                        dev_int_stream_id_base, port_e_stream_id_base_adj[i],
   4032                        pp_port_index));
   4033             return BCM_E_PARAM;
   4034         }
   4035 
   4036         if (!_BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(unit,
   4037                 dev_int_stream_id[i])) {
   4038             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4039                       (BSL_META_U(unit,
   4040                        "ERROR: LinkPHY subport port gport 0x%x is not found.\n"
   4041                        "Device internal stream_id = %d "
   4042                        "is not set for port %d\n"),
   4043                        subport_port_gport, dev_int_stream_id[i], port));
   4044             return BCM_E_NOT_FOUND;
   4045         }
   4046 
   4047         /* RXLP */
   4048         disable = 0;
   4049         rv = _bcm_linkphy_port_rx_flow_control_set(unit, port,
   4050                                               blk_int_stream_id[i], disable);
   4051         if (SOC_FAILURE(rv)) {
   4052             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4053                       (BSL_META_U(unit,
   4054                        "ERROR: RX flow control disable failed\n"
   4055                        " for, internal stream_id = %d.\n"),
   4056                         blk_int_stream_id[i]));
   4057             return rv;
   4058         }
   4059 
   4060         reg = RXLP_SW_FLUSH_CONTROLr;
   4061         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   4062 
   4063             timeoutval = _BCM_KT2_LINKPHY_STREAM_ID_FLUSH_TIMEOUT;
   4064             soc_timeout_init(&timeout, timeoutval, 0);
   4065 
   4066             /* If warmboot is enabled, HW calls just get written in cache
   4067              * and does not write into HW. So FLUSH timeouts are seen during
   4068              * exit clean which enables warmboot mode. Hence checking for
   4069              * SOC_WARM_BOOT.
   4070              */
   4071             if (!(SAL_BOOT_SIMULATION || SOC_WARM_BOOT(unit))) {
   4072                 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg,
   4073                             port, FLUSH_STREAM_IDf, blk_int_stream_id[i]));
   4074                 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg,
   4075                             port, FLUSH_ACTIVEf, 1));
   4076 
   4077                 poll_active = 1;
   4078 
   4079                 while (poll_active) {
   4080 
   4081                     if (soc_timeout_check(&timeout)) {
   4082                         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4083                                   (BSL_META_U(unit,
   4084                                    "ERROR: RX stream id %d flush timeout :"
   4085                                    "subport_port gport 0x%x, port = %d, "
   4086                                    "pp_port %d\n"),
   4087                                    blk_int_stream_id[i], subport_port_gport,
   4088                                    port, pp_port_index));
   4089                         return BCM_E_TIMEOUT;
   4090                     }
   4091 
   4092                     BCM_IF_ERROR_RETURN(
   4093                         READ_RXLP_SW_FLUSH_CONTROLr(unit, port, &regval));
   4094 
   4095                     poll_active = (soc_reg_field_get(unit, reg, regval,
   4096                                        FLUSH_DONEf)) ? 0 :1;
   4097 
   4098                 }
   4099             }
   4100         }
   4101 
   4102         rv = _bcm_linkphy_port_rx_active_stream_bitmap_set(unit,
   4103                                         port, blk_int_stream_id[i], disable);
   4104         if (SOC_FAILURE(rv)) {
   4105             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4106                       (BSL_META_U(unit,
   4107                        "ERROR: RX active stream disable failed\n"
   4108                        " port %d, internal stream_id = %d.\n"),
   4109                        port, blk_int_stream_id[i]));
   4110             return rv;
   4111         }
   4112 
   4113         rv = _bcm_linkphy_port_rx_int_stream_map_port_set(unit, port,
   4114                                                port_e_stream_id_base_adj[i],
   4115                                                blk_int_stream_id[i], disable);
   4116         if (SOC_FAILURE(rv)) {
   4117             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4118                       (BSL_META_U(unit,
   4119                        "ERROR: RX stream map for port clear failed.\n"
   4120                        "port %d, internal stream_id = %d.\n"),
   4121                        port, port_e_stream_id_base_adj[i]));
   4122             return rv;
   4123         }
   4124 
   4125         /* TXLP */
   4126 
   4127         
   4128         rv = _bcm_linkphy_port_tx_active_stream_set(unit, port,
   4129                                                     blk_int_stream_id[i],
   4130                                                     disable);
   4131         if (SOC_FAILURE(rv)) {
   4132             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4133                       (BSL_META_U(unit,
   4134                       "ERROR: TX active stream bitmap disable failed.\n"
   4135                       "port %d, internal stream_id = %d.\n"),
   4136                       port, blk_int_stream_id[i]));
   4137             return rv;
   4138         }
   4139 
   4140         rv = _bcm_linkphy_port_tx_int_to_ext_stream_map_set(unit, port, 0,
   4141                                                           blk_int_stream_id[i],
   4142                                                           disable);
   4143         if (SOC_FAILURE(rv)) {
   4144             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4145                       (BSL_META_U(unit,
   4146                        "ERROR: TX int to ext stream map clear failed.\n"
   4147                        "port %d, int stream_id = %d, ext stream id = %d.\n"),
   4148                        port, blk_int_stream_id[i], 0));
   4149             return rv;
   4150         }
   4151 
   4152         rv = _bcm_linkphy_port_tx_stream_addr_map_set(unit, port,
   4153                                                       blk_int_stream_id[i],
   4154                                                       0, 0, disable);
   4155         if (SOC_FAILURE(rv)) {
   4156             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4157                       (BSL_META_U(unit,
   4158                        "ERROR: TX data buffer address clear failed.\n"
   4159                        "port %d, internal stream_id = %d, start_addr = %d "
   4160                        "end_addr = %d.\n"), port, blk_int_stream_id[i], 0, 0));
   4161             return rv;
   4162         }
   4163 
   4164         /* 
   4165          * Clean Device Internal Stream ID to pp_port mapping
   4166          */
   4167         mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm;
   4168         rv = soc_mem_field32_modify(unit, mem, dev_int_stream_id[i], PP_PORTf, 0);
   4169         if (SOC_FAILURE(rv)) {
   4170             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4171                       (BSL_META_U(unit,
   4172                       "ERROR: cleaning device internal stream id  %d "
   4173                       "to pp_port map failed.\n"),
   4174                        dev_int_stream_id[i]));
   4175             return rv;
   4176         }
   4177         /* Clean PHB for the subport */
   4178         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   4179             unit, mem, dev_int_stream_id[i], PHB_VALIDf, 0));
   4180         BCM_IF_ERROR_RETURN(
   4181             soc_mem_field32_modify(unit, mem, dev_int_stream_id[i],
   4182                                    INT_PRIf, 0));
   4183         BCM_IF_ERROR_RETURN(
   4184             soc_mem_field32_modify(unit, mem, dev_int_stream_id[i], CNGf, 0));
   4185         SOC_IF_ERROR_RETURN
   4186             (soc_kt2_cosq_lp_repl_map_set(unit, dev_int_stream_id[i], 0, 0));
   4187 
   4188 #if defined(BCM_METROLITE_SUPPORT)
   4189         if (SOC_IS_METROLITE(unit)) {
   4190             /* Remove the internal stream id from the port's pool */
   4191             BCM_IF_ERROR_RETURN(shr_idxres_list_free(
   4192                         _bcm_ml_int_stream_id_pool[unit][port-1],
   4193                         blk_int_stream_id[i]));
   4194         } else
   4195 #endif
   4196 #if defined(BCM_SABER2_SUPPORT)
   4197         if (SOC_IS_SABER2(unit)) {
   4198             /* Remove the internal stream id from the port's pool */
   4199             BCM_IF_ERROR_RETURN(shr_idxres_list_free(
   4200                         _bcm_sb2_int_stream_id_pool[unit][port-1],
   4201                         blk_int_stream_id[i]));
   4202         } else
   4203 #endif
   4204         {
   4205             blk_port_idx_int_stream_id[i] = blk_int_stream_id[i]
   4206                                             - (si->port_linkphy_s1_base[port]
   4207                                             - dev_int_stream_id_base);
   4208             /* Remove the internal stream id from the port's pool */
   4209             BCM_IF_ERROR_RETURN(shr_idxres_list_free(
   4210                   _bcm_kt2_blk_int_stream_id_pool[unit][lp_block][lp_index],
   4211                   blk_port_idx_int_stream_id[i]));
   4212         }
   4213 
   4214         _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_CLR(unit, dev_int_stream_id[i]);
   4215 
   4216         _bcm_linkphy_subport_port_info[unit]
   4217             [pp_port_index].ext_stream_idx[i] = 0;
   4218     }
   4219 
   4220     /*
   4221      * clean PP_PORT to Physical port mapping
   4222      */
   4223     mem = PP_PORT_TO_PHYSICAL_PORT_MAPm;
   4224     rv = soc_mem_field32_modify(unit,mem ,pp_port_index, DESTINATIONf, 0);
   4225     if (SOC_FAILURE(rv)) {
   4226         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4227                   (BSL_META_U(unit,
   4228                               "ERROR: Cleaning pp_port id %d to physical port "
   4229                                "map failed.\n"), pp_port_index));
   4230         return rv;
   4231     }
   4232 
   4233 
   4234     _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(unit, pp_port_index);
   4235     _bcm_subport_pp_port_count[unit]--;
   4236 
   4237     group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group);
   4238     *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1;
   4239 
   4240     _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, pp_port_index,
   4241                                            BCM_GPORT_INVALID, -1, FALSE);
   4242 
   4243     if (_bcm_subport_group_subport_port_count[unit][group_id] == 0) {
   4244         /* This is the last subport deleted in this group. So reset the
   4245          * 2_s1s_in_s0_config to 1 which is the default for the
   4246          * linkphy port
   4247          */
   4248         rv = soc_kt2_cosq_two_s1s_in_s0_config_set(unit, port, 1);
   4249         if (SOC_FAILURE(rv)) {
   4250             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4251                     (BSL_META_U(unit,
   4252                      "ERROR: 2 s1s in s0 config failed %s for port %d\n"),
   4253                      bcm_errmsg(rv), port));
   4254             return rv;
   4255         }
   4256     }
   4257 
   4258     /* Remove from enabled_linkphy_pbm */
   4259     BCM_PBMP_PORT_REMOVE(si->enabled_linkphy_pp_port_pbm, pp_port_index);
   4260 
   4261 #ifdef BCM_WARM_BOOT_SUPPORT
   4262     SOC_CONTROL_LOCK(unit);
   4263     SOC_CONTROL(unit)->scache_dirty = 1;
   4264     SOC_CONTROL_UNLOCK(unit);
   4265 #endif
   4266 
   4267     return rv;
   4268 }
   4269 
   4270 /*
   4271  * Function:
   4272  *      _bcm_subport_physical_port_get
   4273  * Purpose:
   4274  *      Get the local_port given subport pp_port
   4275  * Parameters:
   4276  *      unit   - (IN) Device Number
   4277  *      pp_port - (IN) Subport pp_port number
   4278  *      local_port - (OUT) Physical port number
   4279  * Returns:
   4280  *      BCM_E_XXX
   4281  */
   4282 int
   4283 _bcm_subport_physical_port_get(int unit, int pp_port,
   4284                               int *local_port)
   4285 {
   4286         bcm_gport_t subport_group;
   4287         if (local_port == NULL) {
   4288             return BCM_E_PARAM;
   4289         }
   4290         
   4291         if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
   4292             subport_group = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port);
   4293             if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) {
   4294                 return BCM_E_PARAM;
   4295             } 
   4296         } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
   4297             subport_group = _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port);
   4298             if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) {
   4299                 return BCM_E_PARAM;
   4300             }
   4301         } else {
   4302             return BCM_E_PARAM;
   4303         }
   4304         *local_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group);
   4305         return BCM_E_NONE;
   4306 }
   4307 
   4308 /*
   4309  * Function:
   4310  *      _bcm_linkphy_subport_port_get
   4311  * Purpose:
   4312  *      Get the LinkPHY subport_port config (subport group gport and stream_id)
   4313  * Parameters:
   4314  *      unit   - (IN) Device Number
   4315  *      port   - (IN) Subport_port GPORT (generic port) identifier
   4316  *      config - (OUT) Subport port config
   4317  * Returns:
   4318  *      BCM_E_XXX
   4319  */
   4320 STATIC int
   4321 _bcm_linkphy_subport_port_get(int unit,
   4322                               bcm_gport_t subport_port_gport,
   4323                               bcm_subport_config_t *config)
   4324 {
   4325     int i = 0, port = 0, pp_port = 0;
   4326     int rv = BCM_E_NONE;
   4327     bcm_gport_t subport_group;
   4328     uint16 dev_int_stream_id_base = 0, dev_int_stream_id = 0;
   4329     uint16 port_e_stream_id_base_adj = 0;
   4330     uint16 blk_int_stream_id = 0;
   4331     uint16 ext_stream_id_base = 0;
   4332     device_stream_id_to_pp_port_map_entry_t dev_sid_to_pp_entry;
   4333     soc_mem_t mem;
   4334     int lp_block = 0, lp_index = 0;    
   4335 
   4336     if (config == NULL) {
   4337         return BCM_E_PARAM;
   4338     }
   4339 
   4340     pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport);
   4341 
   4342     subport_group =
   4343         _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port);
   4344 
   4345     if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) {
   4346         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4347                   (BSL_META_U(unit,
   4348                    "ERROR:Invalid LinkPHY subport port gport 0x%x\n"),
   4349                    subport_port_gport));
   4350         return BCM_E_PARAM;
   4351     }
   4352 
   4353     if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   4354         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4355                   (BSL_META_U(unit,
   4356                    "ERROR: LinkPHY subport port gport 0x%x is invalid\n"),
   4357                    subport_port_gport));
   4358         return BCM_E_NOT_FOUND;
   4359     }
   4360 
   4361     config->group = subport_group;
   4362 
   4363     config->num_streams =
   4364         _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, pp_port);
   4365 
   4366     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group);
   4367 
   4368     rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port,
   4369                &ext_stream_id_base);
   4370     if (BCM_FAILURE(rv)) {
   4371         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4372                  (BSL_META_U(unit,
   4373                   "ERROR: Linkphy subport group external stream id "
   4374                   "base get failed for port %d.\n"), port));
   4375         return rv;
   4376     }
   4377 
   4378     rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index);
   4379     if (SOC_FAILURE(rv)) {
   4380         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4381                 (BSL_META_U(unit,
   4382                 "ERROR: LinkPHY block, index get failed for port %d\n"),
   4383                 port));
   4384         return rv;
   4385     }
   4386 
   4387     dev_int_stream_id_base = (lp_block)? 128: 0;
   4388 
   4389     for (i = 0; i < config->num_streams; i++) {
   4390         port_e_stream_id_base_adj =
   4391             _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(
   4392                     unit, pp_port, i) - ext_stream_id_base;
   4393 
   4394         BCM_IF_ERROR_RETURN(
   4395                 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port,
   4396                     port_e_stream_id_base_adj, &(blk_int_stream_id)));
   4397 
   4398         dev_int_stream_id = blk_int_stream_id + dev_int_stream_id_base;
   4399         if (dev_int_stream_id > soc_mem_index_max(unit,
   4400                                     DEVICE_STREAM_ID_TO_PP_PORT_MAPm)) {
   4401             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4402                      (BSL_META_U(unit,
   4403                      "ERROR: device internal stream_id %d is out of range \n"
   4404                      "port %d, internal stream id base %d\n"),
   4405                      dev_int_stream_id, port, dev_int_stream_id_base));
   4406             return BCM_E_PARAM;
   4407         }
   4408 
   4409         if (!_BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(unit,
   4410                 dev_int_stream_id)) {
   4411             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4412                      (BSL_META_U(unit,
   4413                      "ERROR: LinkPHY subport port gport 0x%x is not found.\n"
   4414                      "Device internal stream_id = %d(%d) is not set "
   4415                      "for port %d\n"),
   4416                      subport_port_gport, dev_int_stream_id,
   4417                      blk_int_stream_id, port));
   4418             return BCM_E_NOT_FOUND;
   4419         }
   4420 
   4421         config->stream_id_array[i] =
   4422             _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(
   4423                 unit, pp_port, i);
   4424     }
   4425 
   4426     mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm;
   4427     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, dev_int_stream_id,
   4428             &dev_sid_to_pp_entry);
   4429     if (SOC_FAILURE(rv)) {
   4430         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4431                   (BSL_META_U(unit,
   4432                               "ERROR: DEVICE_STREAM_ID_TO_PP_PORT_MAPm read "
   4433                                "failed.for index %d\n"), dev_int_stream_id));
   4434         return rv;
   4435     }
   4436 
   4437     if (soc_mem_field32_get(unit, mem,
   4438             (uint32 *)&dev_sid_to_pp_entry, PHB_VALIDf)) {
   4439         config->prop_flags |= BCM_SUBPORT_PROPERTY_PHB;
   4440         config->int_pri = soc_mem_field32_get(unit, mem,
   4441             (uint32 *)&dev_sid_to_pp_entry, INT_PRIf);
   4442         config->color = soc_mem_field32_get(unit, mem,
   4443             (uint32 *)&dev_sid_to_pp_entry, CNGf);
   4444     } else {
   4445         config->prop_flags &= ~BCM_SUBPORT_PROPERTY_PHB;
   4446         config->int_pri = 0;
   4447         config->color = 0;
   4448     }
   4449 
   4450     return BCM_E_NONE;
   4451 }
   4452 
   4453 /*
   4454  * Function:
   4455  *      _bcm_linkphy_subport_port_traverse
   4456  * Purpose:
   4457  *      Add all valid LinkPHY subports under all valid LinkPHY subport groups
   4458  * Parameters:
   4459  *      unit      - Device Number
   4460  *      cb        - User callback function, called once per subport.
   4461  *      user_data - cookie
   4462  * Returns:
   4463  *      BCM_E_XXX
   4464  */
   4465 STATIC int
   4466 _bcm_linkphy_subport_port_traverse(int unit,
   4467                                    bcm_subport_port_traverse_cb cb,
   4468                                    void *user_data)
   4469 {
   4470     int rv = BCM_E_NONE;
   4471     int pp_port_id = 0;
   4472     bcm_subport_config_t config;
   4473     bcm_gport_t linkphy_subport_port;
   4474 
   4475     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   4476 
   4477     BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port_id) {
   4478 
   4479         if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_id)) {
   4480             continue;
   4481         }
   4482 
   4483         bcm_subport_config_t_init(&config);
   4484 
   4485         _BCM_KT2_SUBPORT_PORT_ID_SET(linkphy_subport_port, pp_port_id);
   4486 
   4487         _BCM_KT2_SUBPORT_PORT_TYPE_SET(linkphy_subport_port,
   4488                                    _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   4489 
   4490         rv = _bcm_linkphy_subport_port_get(unit, linkphy_subport_port, &config);
   4491         if (BCM_FAILURE(rv)) {
   4492             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4493                       (BSL_META_U(unit,
   4494                                   "ERROR: subport port traverse failed \n"
   4495                                    "to get LinkPHY subport id %d\n"), pp_port_id));
   4496             return rv;
   4497         }
   4498 
   4499         rv = cb(unit, linkphy_subport_port, &config, user_data);
   4500         COMPILER_REFERENCE(rv);
   4501 #ifdef BCM_CB_ABORT_ON_ERR
   4502         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4503             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4504                       (BSL_META_U(unit,
   4505                                   "ERROR: subport port traverse failed \n"
   4506                                    "to callback for subport port (pp_port id %d)\n"), pp_port_id));
   4507             return rv;
   4508         }
   4509 #endif
   4510     }
   4511 
   4512     return BCM_E_NONE;
   4513 }
   4514 
   4515 /*
   4516  * Function:
   4517  *      _bcm_linkphy_subport_cleanup
   4518  * Purpose:
   4519  *      Delate all valid LinkPHY subport ports and
   4520  *      all valid LinkPHY subport groups.
   4521  * Parameters:
   4522  *      unit      - Device Number
   4523  * Returns:
   4524  *      BCM_E_XXX
   4525  */
   4526 STATIC int
   4527 _bcm_linkphy_subport_cleanup(int unit)
   4528 {
   4529     int group_id = 0, rv = BCM_E_NONE, pp_port_id = 0;
   4530     bcm_gport_t subport_group;
   4531     bcm_gport_t subport_port;
   4532     bcm_port_t port;
   4533     soc_mem_t mem;
   4534     int index;
   4535     int block;
   4536 
   4537     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   4538 
   4539     /* delete all LinkPHY subport ports */
   4540     BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port_id) {
   4541         
   4542         if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, pp_port_id)) {
   4543             continue;
   4544         }
   4545 
   4546         _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port_id);
   4547 
   4548         _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   4549                                    _BCM_KT2_SUBPORT_TYPE_LINKPHY);
   4550 
   4551         subport_group =
   4552             _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_id);
   4553         
   4554         rv = _bcm_linkphy_subport_port_delete(unit, subport_port);
   4555         if (SOC_FAILURE(rv)) {
   4556             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4557                       (BSL_META_U(unit,
   4558                       "ERROR: LinkPHY subport port delete "
   4559                       "failed (subport id %d)\n"),
   4560                        pp_port_id));
   4561             return rv;
   4562         }
   4563 
   4564         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group);
   4565 
   4566         if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) {
   4567              /* delete the subport group */
   4568             _bcm_subport_group_count[unit]--;
   4569             _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id);
   4570             _bcm_linkphy_subport_group_count[unit]--;
   4571             _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_CLR(unit, group_id);
   4572         }
   4573     }
   4574 
   4575     /* Cleanup SubTag VLAN id bit map */
   4576     BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pbm, port) {
   4577         mem = ING_PHYSICAL_PORT_TABLEm;
   4578         if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   4579             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   4580                 unit, mem, port, CASCADED_PORT_TYPEf, 0));
   4581         }
   4582         if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   4583             BCM_IF_ERROR_RETURN(soc_mem_field32_modify
   4584                 (unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET));
   4585         }
   4586         mem = EGR_PHYSICAL_PORTm;
   4587         if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   4588             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   4589                 unit, mem, port, CASCADED_PORT_TYPEf, 0));
   4590         }
   4591         if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   4592             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   4593                 unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET));
   4594         }
   4595     }
   4596 
   4597     BCM_PBMP_ITER(SOC_INFO(unit).linkphy_allowed_pbm, port) {
   4598         /* check to fix coverity static overrun error */
   4599         if (port < SOC_MAX_NUM_PORTS) {
   4600             sal_free(_bcm_subtag_vlan_id_bitmap[unit][port]);
   4601             _bcm_subtag_vlan_id_bitmap[unit][port] = NULL;
   4602         }
   4603     }
   4604 
   4605 #if defined(BCM_METROLITE_SUPPORT)
   4606     if (SOC_IS_METROLITE(unit)) {
   4607         for (index = 0; index < _BCM_ML_MAX_LINKPHY_PORTS; index++) {
   4608             shr_idxres_list_destroy(_bcm_ml_int_stream_id_pool[unit][index]);
   4609         }
   4610     } else
   4611 #endif
   4612 #if defined(BCM_SABER2_SUPPORT)
   4613     if (SOC_IS_SABER2(unit)) {
   4614        for (index = 0; index < SOC_INFO(unit).lp_ports_max; index++) {
   4615             shr_idxres_list_destroy(_bcm_sb2_int_stream_id_pool[unit][index]);
   4616         }
   4617     } else
   4618 #endif
   4619     {
   4620         for (block = 0; block < SOC_INFO(unit).lp_block_max; block++) {
   4621              for (index = 0; index < SOC_KT2_LINKPHY_BLOCK_PORT_IDX_MAX;
   4622                   index++) {
   4623                   shr_idxres_list_destroy(
   4624                      _bcm_kt2_blk_int_stream_id_pool[unit][block][index]);
   4625              }
   4626         }
   4627     }
   4628 
   4629     return BCM_E_NONE;
   4630 }
   4631 
   4632 
   4633 /*********************************
   4634  * LinkPHY helper functions -end *
   4635  */
   4636 
   4637 
   4638 /**********************************
   4639  * SubTag helper functions -start *
   4640  */
   4641 
   4642 /*
   4643  * Function:
   4644  *      _bcm_subtag_subport_free_entry_find
   4645  * Purpose:
   4646  *      Search for unused entry in the SUBPORT_TAG_TO_PP_PORT_MAP table
   4647  * Parameters:
   4648  *      unit - Device unit number
   4649  *      index - (OUT) index where found
   4650  * Returns:
   4651  *      BOC_E_NONE      - free entry found
   4652  *      BOC_E_FULL      - no free entries found
   4653  */
   4654 STATIC int 
   4655 _bcm_subtag_subport_free_entry_find(int unit, int *free_index)
   4656 {
   4657     subport_tag_to_pp_port_map_entry_t entry;
   4658     int index, rv, start, end;
   4659     soc_mem_t mem = SUBPORT_TAG_TO_PP_PORT_MAPm;
   4660 
   4661     start = soc_mem_index_min(unit, mem);
   4662     end = soc_mem_index_max(unit, mem) + 1;
   4663 
   4664     for (index = start; index != end; index++) {
   4665         rv = READ_SUBPORT_TAG_TO_PP_PORT_MAPm(unit,
   4666                  MEM_BLOCK_ANY, index, &entry);
   4667         if (SOC_SUCCESS(rv)) {
   4668             if (!soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_get(unit,
   4669                                                  (uint32 *)&entry, VALIDf)) {
   4670                 *free_index = index;
   4671                 return BCM_E_NONE;
   4672             }
   4673         }
   4674     }
   4675 
   4676     return BCM_E_FULL;
   4677 }
   4678 
   4679 /*
   4680  * Function:
   4681  *  _bcm_general_subport_init
   4682  * Purpose:
   4683  *  Initialize general subport module.
   4684  * Parameters:
   4685  *  unit      - Device Number
   4686  * Returns:
   4687  *  BCM_E_XXX
   4688  */
   4689 STATIC int
   4690 _bcm_general_subport_init(int unit)
   4691 {
   4692     int subport_group_max = SOC_INFO(unit).subport_group_max;
   4693     int index = 0;
   4694 
   4695     /* General subport group bitmap to keep track of used General groups */
   4696     if (_bcm_general_subport_group_bitmap[unit] == NULL) {
   4697 
   4698         _bcm_general_subport_group_bitmap[unit] =
   4699             sal_alloc(SHR_BITALLOCSIZE(subport_group_max),
   4700                     "general_subport_group_bitmap");
   4701 
   4702         if (_bcm_general_subport_group_bitmap[unit] == NULL) {
   4703             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4704                     (BSL_META_U(unit,
   4705                                 "ERROR:general group bitmap alloc failed\n")));
   4706 
   4707             return BCM_E_MEMORY;
   4708         }
   4709     }
   4710 
   4711     sal_memset(_bcm_general_subport_group_bitmap[unit], 0,
   4712                         SHR_BITALLOCSIZE(subport_group_max));
   4713 
   4714     _bcm_general_subport_group_count[unit] = 0;
   4715 
   4716     /* general subport port info per subport group per subport port */
   4717     if (_bcm_general_subport_port_info[unit] == NULL) {
   4718         _bcm_general_subport_port_info[unit] =
   4719             sal_alloc((SOC_MAX_NUM_PP_PORTS *
   4720                         sizeof(_bcm_general_subport_port_info_t)),
   4721                     "general_subport_port_info");
   4722         if (_bcm_general_subport_port_info[unit] == NULL) {
   4723             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4724                     (BSL_META_U(unit,
   4725                     "ERROR: "
   4726                     " general_subport_port_info alloc failed\n")));
   4727             return BCM_E_MEMORY;
   4728         }
   4729     }
   4730 
   4731     sal_memset(_bcm_general_subport_port_info[unit], 0,
   4732                     (SOC_MAX_NUM_PP_PORTS * sizeof(_bcm_general_subport_port_info_t)));
   4733 
   4734     for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) {
   4735         _bcm_general_subport_port_info[unit][index].group = BCM_GPORT_INVALID;
   4736     }
   4737 
   4738     return BCM_E_NONE;
   4739 }
   4740 
   4741 /*
   4742  * Function:
   4743  *      _bcm_subtag_subport_init
   4744  * Purpose:
   4745  *      Initialize SubTag subport module.
   4746  * Parameters:
   4747  *      unit      - Device Number
   4748  * Returns:
   4749  *      BCM_E_XXX
   4750  */
   4751 STATIC int
   4752 _bcm_subtag_subport_init(int unit)
   4753 {
   4754     bcm_port_t port;
   4755     int num_vlan = 0, index = 0;
   4756     soc_info_t *si = &SOC_INFO(unit);
   4757     int subport_group_max = SOC_INFO(unit).subport_group_max;
   4758 
   4759     /* Clear SUBPORT_TAG_TO_PP_PORT_MAP table */
   4760     BCM_IF_ERROR_RETURN
   4761         (soc_mem_clear(unit, SUBPORT_TAG_TO_PP_PORT_MAPm, COPYNO_ALL, TRUE));
   4762 
   4763     num_vlan = soc_mem_index_count(unit, VLAN_TABm);
   4764 
   4765     BCM_PBMP_ITER(si->subtag_allowed_pbm, port) {
   4766 
   4767         /* check to fix coverity static overrun error */
   4768         if (port < SOC_MAX_NUM_PORTS) {
   4769 
   4770             /* SubTag VLAN ID bitmap to keep track of the VLAN ID used per 
   4771              * SubTag enabled port.
   4772              */
   4773             if (_bcm_subtag_vlan_id_bitmap[unit][port] == NULL) {
   4774 
   4775                 _bcm_subtag_vlan_id_bitmap[unit][port] =
   4776                     sal_alloc(SHR_BITALLOCSIZE(num_vlan),
   4777                             "_bcm_subtag_vlan_id_bitmap");
   4778 
   4779                 if (_bcm_subtag_vlan_id_bitmap[unit][port] == NULL) {
   4780                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4781                               (BSL_META_U(unit,
   4782                                           "ERROR:_bcm_subtag_vlan_id_bitmap "
   4783                                            " alloc failed\n")));
   4784 
   4785                     return BCM_E_MEMORY;
   4786                 }
   4787             }
   4788             sal_memset(_bcm_subtag_vlan_id_bitmap[unit][port], 0,
   4789                     SHR_BITALLOCSIZE(num_vlan));
   4790         }
   4791     }
   4792 
   4793 
   4794     /* SubTag subport group bitmap to keep track of used SubTag groups */
   4795     if (_bcm_subtag_group_bitmap[unit] == NULL) {
   4796 
   4797         _bcm_subtag_group_bitmap[unit] = 
   4798              sal_alloc(SHR_BITALLOCSIZE(subport_group_max),
   4799              "subtag_subport_group_bitmap");
   4800 
   4801         if (_bcm_subtag_group_bitmap[unit] == NULL) {
   4802             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4803                       (BSL_META_U(unit,
   4804                                   "ERROR:subtag group bitmap alloc failed\n")));
   4805 
   4806              return BCM_E_MEMORY;
   4807         }
   4808     }
   4809 
   4810     sal_memset(_bcm_subtag_group_bitmap[unit], 0,
   4811         SHR_BITALLOCSIZE(subport_group_max));
   4812 
   4813     _bcm_subtag_subport_group_count[unit] = 0;
   4814 
   4815     /* SubTag subport port info per subport group per subport port */
   4816     if (_bcm_subtag_subport_port_info[unit] == NULL) {
   4817         _bcm_subtag_subport_port_info[unit] =
   4818             sal_alloc((SOC_MAX_NUM_PP_PORTS *
   4819                        sizeof(_bcm_subtag_subport_port_info_t)),
   4820                        "subtag_subport_port_info");
   4821         if (_bcm_subtag_subport_port_info[unit] == NULL) {
   4822             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4823                       (BSL_META_U(unit,
   4824                                   "ERROR: "
   4825                                    " subtag_subport_port_info alloc failed\n")));
   4826 
   4827             return BCM_E_MEMORY;
   4828         }
   4829     }
   4830 
   4831     sal_memset(_bcm_subtag_subport_port_info[unit], 0,
   4832         (SOC_MAX_NUM_PP_PORTS * sizeof(_bcm_subtag_subport_port_info_t)));
   4833 
   4834     for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) {
   4835         _bcm_subtag_subport_port_info[unit][index].group = BCM_GPORT_INVALID;
   4836         _bcm_subtag_subport_port_info[unit][index].vlan = BCM_VLAN_INVALID;
   4837         _bcm_subtag_subport_port_info[unit][index].subtag_tcam_hw_idx = -1;
   4838     }
   4839 
   4840     /* Set the STP state of subports */
   4841     BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, port) {
   4842         bcm_esw_port_learn_set(unit, port,
   4843                 BCM_PORT_LEARN_ARL | BCM_PORT_LEARN_FWD);
   4844         bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD);
   4845     }
   4846 
   4847     return BCM_E_NONE;
   4848 }
   4849 
   4850 
   4851 /*
   4852  * Function:
   4853  *      _bcm_subtag_subport_group_create
   4854  * Purpose:
   4855  *      Create a SubTag subport group
   4856  * Parameters:
   4857  *      unit   - (IN) Device Number
   4858  *      config - (IN) Subport group config information
   4859  *      group  - (OUT) GPORT (generic port) identifier
   4860  * Returns:
   4861  *      BCM_E_XXX
   4862  */
   4863 STATIC int
   4864 _bcm_subtag_subport_group_create(int unit,
   4865                                  int is_trunk, bcm_port_t port,
   4866                                  int group_id, bcm_gport_t *group)
   4867 {
   4868     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   4869 
   4870     _BCM_KT2_SUBTAG_SUBPORT_GROUP_SET(*group, port, group_id);
   4871     _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(*group);
   4872 
   4873     _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_SET(unit, group_id);
   4874     _bcm_subtag_subport_group_count[unit]++;
   4875 
   4876     return BCM_E_NONE;
   4877 }
   4878 
   4879 /*
   4880  * Function:
   4881  *  _bcm_general_subport_group_create
   4882  * Purpose:
   4883  *  Create a general subport group
   4884  * Parameters:
   4885  *  unit       - (IN) Device Number
   4886  *  is_trunk   - (IN) Is a trunk port
   4887  *  port       - (IN) Physical port identifier
   4888  *  group_id   - (IN) Group id
   4889  *  group      - (OUT) GPORT (generic port) identifier
   4890  * Returns:
   4891  *  BCM_E_XXX
   4892  */
   4893 STATIC int
   4894 _bcm_general_subport_group_create(int unit,
   4895                                   int is_trunk, bcm_port_t port,
   4896                                   int group_id, bcm_gport_t *group)
   4897 {
   4898     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   4899 
   4900     /* Create general group based on subport property flags */
   4901     _BCM_KT2_GENERAL_SUBPORT_GROUP_SET(*group, port, group_id);
   4902     _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(*group);
   4903 
   4904     _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_SET(unit, group_id);
   4905     _bcm_general_subport_group_count[unit]++;
   4906 
   4907     return BCM_E_NONE;
   4908 }
   4909 
   4910 
   4911 /*
   4912  * Function:
   4913  *      _bcm_subtag_subport_group_destroy
   4914  * Purpose:
   4915  *      Destroy the SubTag subport group and all subport ports attached to it.
   4916  * Parameters:
   4917  *      unit   - (IN) Device Number
   4918  *      group  - (IN) GPORT (generic port) identifier for subport group
   4919  * Returns:
   4920  *      BCM_E_XXX
   4921  */
   4922 STATIC int 
   4923 _bcm_subtag_subport_group_destroy(int unit,
   4924                                   bcm_gport_t group)
   4925 {
   4926     int group_id = -1;
   4927     int pp_port = 0, rv = BCM_E_NONE;
   4928     int subtag_subport_count = 0;
   4929     bcm_gport_t subport_port_gport;
   4930 
   4931     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   4932 
   4933     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   4934 
   4935         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   4936 
   4937         if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   4938             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4939                       (BSL_META_U(unit,
   4940                                   "ERROR: SubTag subport group 0x%x not found.\n"),
   4941                        group));
   4942             return BCM_E_NOT_FOUND;
   4943         }
   4944 
   4945         subtag_subport_count =
   4946             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   4947 
   4948         /* delete all subport ports attached to the subport group */
   4949         BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port) {
   4950             if (subtag_subport_count == 0) {
   4951                 break;
   4952             }
   4953 
   4954             if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   4955                 continue;
   4956             }
   4957 
   4958             if (group !=
   4959                 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   4960                 continue;
   4961             }
   4962 
   4963             _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port_gport, pp_port);
   4964 
   4965             _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port_gport,
   4966                                    _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   4967 
   4968             rv = _bcm_subtag_subport_port_delete(unit,subport_port_gport);
   4969             if (SOC_FAILURE(rv)) {
   4970                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   4971                           (BSL_META_U(unit,
   4972                                       "ERROR: SubTag subport group 0x%x destroy failed \n"
   4973                                       " to delete subport port (subport group id %d, "
   4974                                       " subport id %d)\n"),
   4975                            group, group_id, pp_port));
   4976                 return rv;
   4977             }
   4978             subtag_subport_count--;
   4979         }
   4980 
   4981         *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0;
   4982         /* delete the subport group */
   4983         _bcm_subport_group_count[unit]--;
   4984         _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id);
   4985         _bcm_subtag_subport_group_count[unit]--;
   4986         _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_CLR(unit, group_id);
   4987     }
   4988 
   4989     return BCM_E_NONE;
   4990 }
   4991 
   4992 /*
   4993  * Function:
   4994  *  _bcm_general_subport_group_destroy
   4995  * Purpose:
   4996  *  Destroy the general subport group and all subport ports attached to it.
   4997  * Parameters:
   4998  *  unit   - (IN) Device Number
   4999  *  group  - (IN) GPORT (generic port) identifier for subport group
   5000  * Returns:
   5001  *  BCM_E_XXX
   5002  */
   5003 STATIC int
   5004 _bcm_general_subport_group_destroy(int unit,
   5005                                    bcm_gport_t group)
   5006 {
   5007     int group_id = -1;
   5008     int pp_port = 0, rv = BCM_E_NONE;
   5009     int general_subport_count = 0;
   5010     bcm_gport_t subport_port_gport;
   5011 
   5012     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5013 
   5014     if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) {
   5015 
   5016         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   5017 
   5018         if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   5019             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5020                     (BSL_META_U(unit,
   5021                     "ERROR: General subport group 0x%x not found.\n"),
   5022                      group));
   5023             return BCM_E_NOT_FOUND;
   5024         }
   5025 
   5026         general_subport_count =
   5027                     *(_bcm_subport_group_subport_port_count[unit] + group_id);
   5028 
   5029         /* Delete all subport added in group */
   5030         BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port) {
   5031             if (general_subport_count == 0) {
   5032                 break;
   5033             }
   5034 
   5035             if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   5036                 continue;
   5037             }
   5038 
   5039             if (group !=
   5040                     _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   5041                 continue;
   5042             }
   5043 
   5044             _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port_gport, pp_port);
   5045 
   5046             _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port_gport,
   5047                                            _BCM_KT2_SUBPORT_TYPE_GENERAL);
   5048 
   5049             rv = _bcm_general_subport_port_delete(unit,subport_port_gport);
   5050             if (SOC_FAILURE(rv)) {
   5051                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5052                         (BSL_META_U(unit,
   5053                         "ERROR: General subport group 0x%x destroy failed \n"
   5054                         " to delete subport port (subport group id %d, "
   5055                         " subport id %d)\n"),
   5056                          group, group_id, pp_port));
   5057                 return rv;
   5058             }
   5059             general_subport_count--;
   5060         }
   5061 
   5062         *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0;
   5063 
   5064         /* Delete the subport group */
   5065         _bcm_subport_group_count[unit]--;
   5066         _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id);
   5067         _bcm_general_subport_group_count[unit]--;
   5068         _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_CLR(unit, group_id);
   5069     }
   5070     
   5071     return BCM_E_NONE;
   5072 }
   5073 
   5074 /*
   5075  * Function:
   5076  *      _bcm_subtag_subport_group_get
   5077  * Purpose:
   5078  *      Get a subport group
   5079  * Parameters:
   5080  *      unit   - (IN) Device Number
   5081  *      group  - (IN) GPORT (generic port) identifier
   5082  *      config - (OUT) Subport group config information
   5083  * Returns:
   5084  *      BCM_E_XXX
   5085  */
   5086 STATIC int
   5087 _bcm_subtag_subport_group_get(int unit,
   5088                               bcm_gport_t group,
   5089                               bcm_subport_group_config_t *config)
   5090 {
   5091     int group_id = -1;
   5092 
   5093     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5094 
   5095     if (config == NULL) {
   5096         return BCM_E_PARAM;
   5097     }
   5098 
   5099     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   5100         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   5101         if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   5102             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5103                       (BSL_META_U(unit,
   5104                                   "ERROR: SubTag subport group 0x%x not found.\n"),
   5105                        group));
   5106             return BCM_E_NOT_FOUND;;
   5107         }
   5108         config->flags |= BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG;
   5109         config->port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(group);
   5110     } else {
   5111         return BCM_E_PARAM;
   5112     }
   5113 
   5114     return BCM_E_NONE;
   5115 }
   5116 
   5117 /*
   5118  * Function:
   5119  *  _bcm_general_subport_group_get
   5120  * Purpose:
   5121  *  Get a subport group
   5122  * Parameters:
   5123  *  unit   - (IN) Device Number
   5124  *  group  - (IN) GPORT (generic port) identifier
   5125  *  config - (OUT) Subport group config information
   5126  * Returns:
   5127  *  BCM_E_XXX
   5128  */
   5129 STATIC int
   5130 _bcm_general_subport_group_get(int unit,
   5131                                bcm_gport_t group,
   5132                                bcm_subport_group_config_t *config)
   5133 {
   5134     int group_id = -1;
   5135 
   5136     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5137 
   5138     if (config == NULL) {
   5139         return BCM_E_PARAM;
   5140     }
   5141 
   5142     if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) {
   5143         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   5144         if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   5145             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5146                     (BSL_META_U(unit,
   5147                     "ERROR: General subport group 0x%x not found.\n"),
   5148                      group));
   5149             return BCM_E_NOT_FOUND;;
   5150         }
   5151         config->flags |= BCM_SUBPORT_GROUP_TYPE_GENERAL;
   5152         config->port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(group);
   5153     } else {
   5154         return BCM_E_PARAM;
   5155     }
   5156 
   5157     return BCM_E_NONE;
   5158 }
   5159 
   5160 /*
   5161  * Function:
   5162  *      _bcm_subtag_subport_group_traverse
   5163  * Purpose:
   5164  *      Traverse all valid subports for given SubTag subport group
   5165  *      and call the user supplied callback routine.
   5166  * Parameters:
   5167  *      unit      - Device Number
   5168  *      group     - Subport group GPORT identifier
   5169  *      cb        - User callback function, called once per subport.
   5170  *      user_data - cookie
   5171  */
   5172 
   5173 STATIC int
   5174 _bcm_subtag_subport_group_traverse(int unit,
   5175                                    bcm_gport_t group,
   5176                                    bcm_subport_port_traverse_cb cb,
   5177                                    void *user_data)
   5178 {
   5179     int rv = BCM_E_NONE, group_id = 0;
   5180     int pp_port = 0, subport_port;
   5181     int subtag_subport_count = 0;
   5182     bcm_subport_config_t config;
   5183 
   5184     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5185 
   5186     bcm_subport_config_t_init(&config);
   5187 
   5188     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   5189         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   5190 
   5191         if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   5192             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5193                       (BSL_META_U(unit,
   5194                                   "ERROR: SubTag subport group 0x%x not found.\n"),
   5195                        group));
   5196             return BCM_E_NOT_FOUND;
   5197         }
   5198 
   5199         subtag_subport_count =
   5200             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   5201 
   5202         
   5203         BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port) {
   5204 
   5205             if (subtag_subport_count == 0) {
   5206                break;
   5207             }
   5208 
   5209             if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   5210                continue;
   5211             }
   5212 
   5213             if (group !=
   5214                _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   5215                continue;
   5216             }
   5217 
   5218             _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port);
   5219 
   5220             _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   5221                                    _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   5222 
   5223             rv = _bcm_subtag_subport_port_get(unit, subport_port, &config);
   5224             if (SOC_FAILURE(rv)) {
   5225                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5226                           (BSL_META_U(unit,
   5227                                       "ERROR: SubTag subport group 0x%x traverse failed \n"
   5228                                       "to get subport port (group id %d, subport id %d)\n"),
   5229                            group, group_id, pp_port));
   5230                 return rv;
   5231             }
   5232 
   5233 #ifdef BCM_CB_ABORT_ON_ERR
   5234             rv = cb(unit, subport_port, &config, user_data);
   5235             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5236                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5237                           (BSL_META_U(unit,
   5238                                       "ERROR: subport group 0x%x traverse failed \n"
   5239                                        "to callback for subport port (group id %d, "
   5240                                        "subport id %d)\n"), group, group_id, pp_port));
   5241                 return rv;
   5242             }
   5243 #else
   5244             (void)cb(unit, subport_port, &config, user_data);
   5245 #endif
   5246             subtag_subport_count--;
   5247         }
   5248     } else {
   5249         return BCM_E_PARAM;
   5250     }
   5251     return BCM_E_NONE;
   5252 }
   5253 
   5254 /*
   5255  * Function:
   5256  *  _bcm_general_subport_group_traverse
   5257  * Purpose:
   5258  *  Traverse all valid subports for given general subport group
   5259  *  and call the user supplied callback routine.
   5260  * Parameters:
   5261  *  unit      - Device Number
   5262  *  group     - Subport group GPORT identifier
   5263  *  cb        - User callback function, called once per subport.
   5264  *  user_data - cookie
   5265  */
   5266 STATIC int
   5267 _bcm_general_subport_group_traverse(int unit,
   5268                                     bcm_gport_t group,
   5269                                     bcm_subport_port_traverse_cb cb,
   5270                                     void *user_data)
   5271 {
   5272     int rv = BCM_E_NONE, group_id = 0;
   5273     int pp_port = 0, subport_port;
   5274     int general_subport_count = 0;
   5275     bcm_subport_config_t config;
   5276 
   5277     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5278 
   5279     bcm_subport_config_t_init(&config);
   5280 
   5281     if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) {
   5282         
   5283         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group);
   5284 
   5285         if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   5286             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5287                     (BSL_META_U(unit,
   5288                     "ERROR: General subport group 0x%x not found.\n"),
   5289                      group));
   5290             return BCM_E_NOT_FOUND;
   5291         }
   5292 
   5293         general_subport_count =
   5294             *(_bcm_subport_group_subport_port_count[unit] + group_id);
   5295 
   5296 
   5297         BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port) {
   5298 
   5299             if (general_subport_count == 0) {
   5300                 break;
   5301             }
   5302 
   5303             if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   5304                 continue;
   5305             }
   5306 
   5307             if (group !=
   5308                     _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) {
   5309                 continue;
   5310             }
   5311             _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port);
   5312 
   5313             _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   5314                                            _BCM_KT2_SUBPORT_TYPE_GENERAL);
   5315 
   5316             rv = _bcm_general_subport_port_get(unit, subport_port, &config);
   5317             if (SOC_FAILURE(rv)) {
   5318                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5319                         (BSL_META_U(unit,
   5320                         "ERROR: general subport group 0x%x traverse failed \n"
   5321                         "to get subport port (group id %d, subport id %d)\n"),
   5322                          group, group_id, pp_port));
   5323                 return rv;
   5324             }
   5325 
   5326 #ifdef BCM_CB_ABORT_ON_ERR
   5327             rv = cb(unit, subport_port, &config, user_data);
   5328             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5329                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5330                         (BSL_META_U(unit,
   5331                                     "ERROR: subport group 0x%x traverse failed \n"
   5332                                     "to callback for subport port (group id %d, "
   5333                                     "subport id %d)\n"), group, group_id, pp_port));
   5334                 return rv;
   5335             }
   5336 #else
   5337             (void)cb(unit, subport_port, &config, user_data);
   5338 #endif
   5339             general_subport_count--;
   5340         }
   5341     } else {
   5342         return BCM_E_PARAM;
   5343     }
   5344     
   5345     return BCM_E_NONE;
   5346 }
   5347 
   5348 /*
   5349  * Function:
   5350  *      _bcm_subtag_subport_port_add
   5351  * Purpose:
   5352  *      Add a SubTag subport to a subport group
   5353  * Parameters:
   5354  *      unit   - (IN) Device Number
   5355  *      config - (IN) Subport config information
   5356  *      port   - (OUT) Subport_port GPORT (generic port) identifier
   5357  * Returns:
   5358  *      BCM_E_XXX
   5359  */
   5360 STATIC int
   5361 _bcm_subtag_subport_port_add(int unit,
   5362                              bcm_subport_config_t *config,
   5363                              bcm_gport_t *gport)
   5364 {
   5365     int rv = BCM_E_NONE, port = -1;
   5366     int subtag_index = -1;
   5367     int sp_group_idx = -1;
   5368     uint16 vlan_id = 0;
   5369     int pp_port_index = 0;
   5370     soc_mem_t mem;
   5371     soc_info_t *si = &SOC_INFO(unit);
   5372     subport_tag_to_pp_port_map_entry_t    subtag_to_pp_entry;
   5373     pp_port_to_physical_port_map_entry_t  pp_to_port_entry;
   5374 
   5375     /* A. PARAMETER VALIDATION
   5376  */
   5377     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5378 
   5379     if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) {
   5380         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5381                   (BSL_META_U(unit,
   5382                               "ERROR: group 0x%x is not subport group gport\n"),
   5383                    config->group));
   5384         return BCM_E_PARAM;
   5385     }
   5386 
   5387     /* Make sure the group exists */
   5388     if (!_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(config->group)) {
   5389         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5390                   (BSL_META_U(unit,
   5391                               "ERROR: subport group 0x%x is not SubTag group\n"),
   5392                    config->group));
   5393         return BCM_E_PARAM;
   5394     }
   5395 
   5396     sp_group_idx = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group);
   5397 
   5398     if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, sp_group_idx)) {
   5399         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5400                   (BSL_META_U(unit,
   5401                               "ERROR: group 0x%x does not exist. group id =%d\n"),
   5402                    config->group, sp_group_idx));
   5403         return BCM_E_NOT_FOUND;
   5404     }
   5405 
   5406     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group);
   5407 
   5408     /* Check if port is member of pbmp_subtag  */
   5409     if (!SOC_PBMP_MEMBER(si->subtag_pbm, port)) {
   5410         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5411                   (BSL_META_U(unit,
   5412                               "ERROR: Port %d is not member of pbmp_subport\n"),
   5413                    port));
   5414         return BCM_E_PORT;
   5415     }
   5416 
   5417     if (si->port_num_subport[port] <= 0) {
   5418         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5419                   (BSL_META_U(unit,
   5420                               "ERROR: %d number of subports available for port %d\n"),
   5421                    si->port_num_subport[port], port));
   5422         return BCM_E_CONFIG;
   5423     }
   5424 
   5425     if ((config->pkt_vlan & 0xFFF) <= BCM_VLAN_NONE) {
   5426         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5427                   (BSL_META_U(unit,
   5428                               "ERROR: (config->pkt_vlan & 0xFFF) %d is invalid\n"),
   5429                    (config->pkt_vlan & 0xFFF)));
   5430         return BCM_E_PARAM;
   5431     }
   5432 
   5433     if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) {
   5434         if (config->int_pri < 0 || config->int_pri > 15) {
   5435             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5436                       (BSL_META_U(unit,
   5437                                   "ERROR: int_pri %d is invalid\n"),
   5438                        config->int_pri));
   5439             return BCM_E_PARAM;
   5440         }
   5441         if ((config->color != bcmColorGreen) &&
   5442              (config->color != bcmColorYellow) &&
   5443              (config->color != bcmColorRed)) {
   5444              LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5445                        (BSL_META_U(unit,
   5446                                    "ERROR: color %d is invalid\n"),
   5447                         config->color));
   5448             return BCM_E_PARAM;
   5449         }
   5450     }
   5451 
   5452     /* Check if VLAN id is alredy used for the port */
   5453     vlan_id = config->pkt_vlan & 0xFFF; 
   5454 
   5455     if (_BCM_KT2_SUBTAG_VLAN_ID_USED_GET(unit, port, vlan_id)) {
   5456         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5457                   (BSL_META_U(unit,
   5458                               "ERROR: VLAN id %d already used for port %d\n"),
   5459                    vlan_id, port));
   5460         return BCM_E_EXISTS;
   5461     }
   5462 
   5463     /* B. find free entry in subtag to pp_port Mapping table
   5464  */
   5465 
   5466     mem = SUBPORT_TAG_TO_PP_PORT_MAPm;
   5467 
   5468     rv = _bcm_subtag_subport_free_entry_find(unit, &subtag_index);
   5469     if (SOC_FAILURE(rv)) {
   5470         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5471                   (BSL_META_U(unit,
   5472                               "ERROR: Free entry not found in "
   5473                                " subtag to pp_port map table\n")));
   5474         return rv;
   5475     }
   5476 
   5477     /* C. PP_PORT INDEX RESERVATION
   5478  */
   5479     /* Reserve PP_PORT index */
   5480     BCM_IF_ERROR_RETURN(_bcm_kt2_allocate_pp_port(unit, config, &pp_port_index));
   5481 
   5482     /* D. Map VLAN ID, port to pp_port_index
   5483  */
   5484     /* Use the SUBPORT_TAG_TO_PP_PORT_MAPm table */
   5485 
   5486     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_index,
   5487             &subtag_to_pp_entry);
   5488     if (BCM_FAILURE(rv)) {
   5489         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5490                   (BSL_META_U(unit,
   5491                               "SUBPORT_TAG_TO_PP_PORT_MAPm read failed at index %d\n"),
   5492                    subtag_index));
   5493 
   5494         return rv;
   5495     }
   5496 
   5497     /* Set the SUBPORT_TAG, PHYSICAL_PORT and VALID fields */
   5498     soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5499             (uint32 *)&subtag_to_pp_entry, SUBPORT_TAGf, config->pkt_vlan);
   5500     soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5501             (uint32 *)&subtag_to_pp_entry, PHYSICAL_PORTf, port);
   5502 
   5503 #if defined(BCM_METROLITE_SUPPORT)
   5504     if (SOC_IS_METROLITE(unit)) {
   5505         soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5506                 (uint32 *)&subtag_to_pp_entry, VALIDf, 0x1);
   5507     } else
   5508 #endif
   5509 #if defined(BCM_SABER2_SUPPORT)
   5510     if (SOC_IS_SABER2(unit)) {
   5511         soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5512                 (uint32 *)&subtag_to_pp_entry, VALIDf, 0x3);
   5513     } else 
   5514 #endif
   5515     {
   5516         soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5517                (uint32 *)&subtag_to_pp_entry, VALIDf, 0x1);
   5518     }
   5519 
   5520     soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5521         (uint32 *)&subtag_to_pp_entry, SUBPORT_TAG_MASKf, 0xFFF);
   5522     soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5523         (uint32 *)&subtag_to_pp_entry, PHYSICAL_PORT_MASKf,
   5524         ((1 << soc_mem_field_length(unit, mem, PHYSICAL_PORT_MASKf)) - 1));
   5525 
   5526     /* Set the PP_PORT field */
   5527     soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit,
   5528         (uint32 *)&subtag_to_pp_entry, PP_PORTf, pp_port_index);
   5529 
   5530     /* Set PHB for the subport */
   5531     if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) {
   5532         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_pp_entry,
   5533             PHB_VALIDf, 1);
   5534         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_pp_entry,
   5535             INT_PRIf, config->int_pri);
   5536         soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_pp_entry,
   5537             CNGf, config->color);
   5538     }
   5539 
   5540     rv = WRITE_SUBPORT_TAG_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ANY, subtag_index,
   5541             &subtag_to_pp_entry);
   5542 
   5543     if (SOC_FAILURE(rv)) {
   5544         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5545                   (BSL_META_U(unit,
   5546                               "ERROR: (VLAN id %d, port %d) to pp_port %d "
   5547                                "map failed.\n"), vlan_id, port, pp_port_index));
   5548 
   5549         return rv;
   5550     }
   5551 
   5552     /* E. Map PP_PORT to Physical port mapping (IP/ EP):
   5553  */
   5554     /* Use the PP_PORT_TO_PHYSICAL_PORT_MAP */
   5555     mem = PP_PORT_TO_PHYSICAL_PORT_MAPm;
   5556     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port_index,
   5557             &pp_to_port_entry);
   5558 
   5559     soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry,
   5560         DESTINATIONf, port);
   5561     soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry,
   5562         ISTRUNKf, 0);
   5563 
   5564     rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, pp_port_index,
   5565             &pp_to_port_entry);
   5566 
   5567     if (SOC_FAILURE(rv)) {
   5568         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5569                   (BSL_META_U(unit,
   5570                               "ERROR: pp_port id %d to physical port %d "
   5571                                "map failed.\n"), pp_port_index, port));
   5572 
   5573         /* free/invalidate the SUBTAG_TO_PP_PORT_MAP table entry */
   5574        BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   5575                    SUBPORT_TAG_TO_PP_PORT_MAPm, subtag_index, VALIDf, 0));
   5576         return rv;
   5577     }
   5578 
   5579     _BCM_KT2_SUBTAG_VLAN_ID_USED_SET(unit, port, vlan_id);
   5580 
   5581     _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port_index,
   5582         config->group, config->pkt_vlan, subtag_index, TRUE);
   5583 
   5584     _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port_index);
   5585     
   5586     /* Reset the  subport_modport */
   5587     config->subport_modport = 0;
   5588 
   5589     _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   5590 
   5591     *(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) += 1;
   5592 
   5593     _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port_index);
   5594     _bcm_subport_pp_port_count[unit]++;
   5595 
   5596     /* Add to enabled_subtag_pbm */
   5597     BCM_PBMP_PORT_ADD(si->enabled_subtag_pp_port_pbm, pp_port_index);
   5598 
   5599     /*LOG_FATAL(BSL_LS_BCM_SUBPORT,
   5600               (BSL_META_U(unit,
   5601                           "Raghu: pp_port_id %d mod: %d port %d "
   5602                            "\n"), pp_port_index, mod_id, port_id));
   5603     */
   5604 #ifdef BCM_WARM_BOOT_SUPPORT
   5605     SOC_CONTROL_LOCK(unit);
   5606     SOC_CONTROL(unit)->scache_dirty = 1;
   5607     SOC_CONTROL_UNLOCK(unit);
   5608 #endif
   5609     return rv;
   5610 }
   5611 
   5612 /*
   5613  * Function:
   5614  *  _bcm_general_subport_port_add
   5615  * Purpose:
   5616  *  Add a subport to a general subport group
   5617  * Parameters:
   5618  *  unit   - (IN) Device Number
   5619  *  config - (IN) Subport config information
   5620  *  gport   - (OUT) Subport_port GPORT (generic port) identifier
   5621  * Returns:
   5622  *  BCM_E_XXX
   5623  */
   5624 STATIC int
   5625 _bcm_general_subport_port_add(int unit,
   5626                               bcm_subport_config_t *config,
   5627                               bcm_gport_t *gport)
   5628 {
   5629     int sp_group_idx = -1;
   5630     soc_port_t pp_port;
   5631     soc_info_t *si = &SOC_INFO(unit);
   5632 
   5633     /* A. PARAMETER VALIDATION
   5634  */
   5635     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   5636 
   5637     if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) {
   5638         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5639                 (BSL_META_U(unit,
   5640                 "ERROR: group 0x%x is not subport group gport\n"),
   5641                  config->group));
   5642         return BCM_E_PARAM;
   5643     }
   5644 
   5645     /* Make sure the group exists */
   5646     if (!_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(config->group)) {
   5647         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5648                 (BSL_META_U(unit,
   5649                 "ERROR: subport group 0x%x is not general group\n"),
   5650                  config->group));
   5651         return BCM_E_PARAM;
   5652     }
   5653 
   5654     sp_group_idx = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group);
   5655 
   5656     if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, sp_group_idx)) {
   5657         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5658                 (BSL_META_U(unit,
   5659                 "ERROR: group 0x%x does not exist. group id =%d\n"),
   5660                  config->group, sp_group_idx));
   5661         return BCM_E_NOT_FOUND;
   5662     }
   5663 
   5664     /* B. Allocate pp port */
   5665     SOC_PBMP_ITER(si->general_pp_port_pbm, pp_port) {
   5666         if (SOC_PBMP_MEMBER(si->enabled_general_pp_port_pbm, pp_port)) {
   5667             continue;
   5668         }
   5669         break;
   5670     }
   5671 
   5672     _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_SET(unit, pp_port,
   5673                                            config->group, TRUE);
   5674     
   5675     _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port);
   5676 
   5677     _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, _BCM_KT2_SUBPORT_TYPE_GENERAL);
   5678 
   5679     *(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) += 1;
   5680 
   5681     _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port);
   5682     
   5683     _bcm_subport_pp_port_count[unit]++;
   5684 
   5685     SOC_PBMP_PORT_ADD(si->enabled_general_pp_port_pbm, pp_port);
   5686 
   5687 #ifdef BCM_WARM_BOOT_SUPPORT
   5688     SOC_CONTROL_LOCK(unit);
   5689     SOC_CONTROL(unit)->scache_dirty = 1;
   5690     SOC_CONTROL_UNLOCK(unit);
   5691 #endif
   5692 
   5693     return BCM_E_NONE;
   5694 }
   5695 
   5696 /*
   5697  * Function:
   5698  *      _bcm_subtag_subport_port_delete
   5699  * Purpose:
   5700  *      Delete a SubTag subport_port
   5701  * Parameters:
   5702  *      unit   - (IN) Device Number
   5703  *      port   - (IN) Subport_port GPORT (generic port) identifier
   5704  * Returns:
   5705  *      BCM_E_XXX
   5706  */
   5707 STATIC int
   5708 _bcm_subtag_subport_port_delete(int unit,
   5709                                 bcm_gport_t subport_port_gport)
   5710 {
   5711     int rv = BCM_E_NONE, group_id = 0;
   5712     int port = 0, subport_group = -1;
   5713     int subtag_to_pp_port_tab_idx = -1;
   5714     uint16 pp_port_index = 0;
   5715     bcm_vlan_t vlan_id;
   5716     soc_mem_t mem;
   5717     soc_info_t *si = &SOC_INFO(unit);
   5718     subport_tag_to_pp_port_map_entry_t subport_tag_to_pp_port_map_entry;
   5719 
   5720     if (!_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) {
   5721         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5722                   (BSL_META_U(unit,
   5723                               "ERROR: gport 0x%x is not SubTag subport port type.\n"),
   5724                    subport_port_gport));
   5725         return BCM_E_PARAM;
   5726     }
   5727 
   5728     pp_port_index =
   5729         _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport);
   5730 
   5731     if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_index)) {
   5732         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5733                   (BSL_META_U(unit,
   5734                               "ERROR: SubTag subport port gport 0x%x is invalid\n"),
   5735                    subport_port_gport));
   5736         return BCM_E_NOT_FOUND;
   5737     }
   5738 
   5739     subport_group =
   5740         _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_index);
   5741 
   5742     port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group);
   5743 
   5744     subtag_to_pp_port_tab_idx =
   5745         _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, pp_port_index);
   5746 
   5747     mem = SUBPORT_TAG_TO_PP_PORT_MAPm;
   5748     if (subtag_to_pp_port_tab_idx < 0 ||
   5749         subtag_to_pp_port_tab_idx > soc_mem_index_max(unit,mem)) {
   5750         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5751                   (BSL_META_U(unit,
   5752                               "ERROR: SubTag subport port gport 0x%x is not found.\n"
   5753                                "subtag_to_pp_port  tcam idx = %d\n"), subport_port_gport,
   5754                    subtag_to_pp_port_tab_idx));
   5755         return BCM_E_NOT_FOUND;
   5756     }
   5757 
   5758     vlan_id = _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port_index) &
   5759               0xFFF;
   5760 
   5761     if (!_BCM_KT2_SUBTAG_VLAN_ID_USED_GET(unit, port, vlan_id)) {
   5762         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5763                   (BSL_META_U(unit,
   5764                               "ERROR: SubTag subport port gport 0x%x is not found.\n"
   5765                               "VLAN id = %d is not set for port %d\n"),
   5766                    subport_port_gport, vlan_id, port));
   5767         return BCM_E_NOT_FOUND;
   5768     }
   5769 
   5770     
   5771 
   5772     /* 
   5773     * Clean port, VLAN ID to pp_port mapping
   5774     */
   5775     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_to_pp_port_tab_idx,
   5776              &subport_tag_to_pp_port_map_entry);
   5777     soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry,
   5778         SUBPORT_TAGf, 0);
   5779     soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry,
   5780         PP_PORTf, 0);
   5781     soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry,
   5782         VALIDf, 0);
   5783     /* Clean PHB for the subport */
   5784     soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry,
   5785         PHB_VALIDf, 0);
   5786     soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry,
   5787         INT_PRIf, 0);
   5788     soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry,
   5789         CNGf, 0);
   5790     rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, subtag_to_pp_port_tab_idx,
   5791             &subport_tag_to_pp_port_map_entry);
   5792     if (SOC_FAILURE(rv)) {
   5793         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5794                   (BSL_META_U(unit,
   5795                               "ERROR: subport_tag %d to pp_port %d "
   5796                                "map failed.\n"), vlan_id, pp_port_index));
   5797         return rv;
   5798     }
   5799 
   5800     /*
   5801      * clean PP_PORT to Physical port mapping
   5802      */
   5803     mem = PP_PORT_TO_PHYSICAL_PORT_MAPm;
   5804     rv = soc_mem_field32_modify(unit,mem ,pp_port_index, DESTINATIONf, 0);
   5805     if (SOC_FAILURE(rv)) {
   5806         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5807                   (BSL_META_U(unit,
   5808                               "ERROR: Cleaning pp_port id %d to physical port "
   5809                                "map failed.\n"), pp_port_index));
   5810         return rv;
   5811     }
   5812 
   5813     _BCM_KT2_SUBTAG_VLAN_ID_USED_CLR(unit, port, vlan_id);
   5814 
   5815     _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(unit, pp_port_index);
   5816     _bcm_subport_pp_port_count[unit]--;
   5817 
   5818     group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group);
   5819     *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1;
   5820 
   5821     _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port_index,
   5822                               BCM_GPORT_INVALID, BCM_VLAN_INVALID, -1, FALSE);
   5823 
   5824     /* remove from enabled_subtag_pbm */
   5825     BCM_PBMP_PORT_REMOVE(si->enabled_subtag_pp_port_pbm, pp_port_index);
   5826 
   5827 #ifdef BCM_WARM_BOOT_SUPPORT
   5828     SOC_CONTROL_LOCK(unit);
   5829     SOC_CONTROL(unit)->scache_dirty = 1;
   5830     SOC_CONTROL_UNLOCK(unit);
   5831 #endif
   5832 
   5833     return rv;
   5834 }
   5835 
   5836 /*
   5837  * Function:
   5838  *  _bcm_general_subport_port_delete
   5839  * Purpose:
   5840  *  Delete a general subport_port
   5841  * Parameters:
   5842  *  unit   - (IN) Device Number
   5843  *  port   - (IN) Subport_port GPORT (generic port) identifier
   5844  * Returns:
   5845  *  BCM_E_XXX
   5846  */
   5847 STATIC int
   5848 _bcm_general_subport_port_delete(int unit,
   5849                                  bcm_gport_t subport_port_gport)
   5850 {
   5851     int subport_group = -1;
   5852     uint16 pp_port_index = 0;
   5853     soc_info_t *si = &SOC_INFO(unit);
   5854     int group_id = 0;
   5855 
   5856     if (!_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) {
   5857         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5858                 (BSL_META_U(unit,
   5859                 "ERROR: gport 0x%x is not general subport port type.\n"),
   5860                  subport_port_gport));
   5861         return BCM_E_PARAM;
   5862     }
   5863 
   5864     pp_port_index =
   5865             _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport);
   5866 
   5867     if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_index)) {
   5868         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5869                 (BSL_META_U(unit,
   5870                 "ERROR: general subport port gport 0x%x is invalid\n"),
   5871                  subport_port_gport));
   5872         return BCM_E_NOT_FOUND;
   5873     }
   5874 
   5875     subport_group =
   5876             _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_index);
   5877 
   5878     _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(unit, pp_port_index);
   5879     
   5880     _bcm_subport_pp_port_count[unit]--;
   5881 
   5882     group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group);
   5883    
   5884     *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1;
   5885 
   5886     _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_SET(unit, pp_port_index,
   5887                                            BCM_GPORT_INVALID, FALSE);
   5888 
   5889     /* remove from enabled_general_pp_port_pbm */
   5890     BCM_PBMP_PORT_REMOVE(si->enabled_general_pp_port_pbm, pp_port_index);
   5891 
   5892 #ifdef BCM_WARM_BOOT_SUPPORT
   5893     SOC_CONTROL_LOCK(unit);
   5894     SOC_CONTROL(unit)->scache_dirty = 1;
   5895     SOC_CONTROL_UNLOCK(unit);
   5896 #endif
   5897     
   5898     return BCM_E_NONE;
   5899 }
   5900 
   5901 /*
   5902  * Function:
   5903  *      _bcm_subtag_subport_port_get
   5904  * Purpose:
   5905  *      Get the SubTag subport_port config (subport group gport and stream_id)
   5906  * Parameters:
   5907  *      unit   - (IN) Device Number
   5908  *      port   - (IN) Subport_port GPORT (generic port) identifier
   5909  *      config - (OUT) Subport port config
   5910  * Returns:
   5911  *      BCM_E_XXX
   5912  */
   5913 STATIC int
   5914 _bcm_subtag_subport_port_get(int unit,
   5915                              bcm_gport_t subport_port_gport,
   5916                              bcm_subport_config_t *config)
   5917 {
   5918     int pp_port = 0;
   5919     int rv = BCM_E_NONE;
   5920     bcm_gport_t subport_group;
   5921     int subtag_to_pp_hw_id = -1;
   5922     subport_tag_to_pp_port_map_entry_t subtag_pp_entry;
   5923     soc_mem_t mem;
   5924 
   5925     if (config == NULL) {
   5926         return BCM_E_PARAM;
   5927     }
   5928 
   5929     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) {
   5930 
   5931         pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport);
   5932 
   5933         subport_group =
   5934             _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port);
   5935 
   5936         if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) {
   5937             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   5938                         (BSL_META_U(unit,
   5939                                     "ERROR:Invalid SubTag subport port gport 0x%x\n"),
   5940                          subport_port_gport));
   5941             return BCM_E_PARAM;
   5942         }
   5943 
   5944         if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   5945             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   5946                         (BSL_META_U(unit,
   5947                                     "ERROR: SubTag subport port gport 0x%x not found\n"),
   5948                          subport_port_gport));
   5949             return BCM_E_NOT_FOUND;
   5950         }
   5951 
   5952         config->group = subport_group;
   5953 
   5954         config->pkt_vlan =
   5955             _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port);
   5956 
   5957         subtag_to_pp_hw_id =
   5958             _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, pp_port);
   5959 
   5960         mem = SUBPORT_TAG_TO_PP_PORT_MAPm;
   5961         if ((subtag_to_pp_hw_id < 0) ||
   5962             (subtag_to_pp_hw_id > soc_mem_index_max(unit, mem))) {
   5963             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5964                       (BSL_META_U(unit,
   5965                                   "ERROR: SubTag subport port gport 0x%x is not found.\n"
   5966                                    "subtag_to_pp_port_tab idx = %d\n"), subport_port_gport,
   5967                        subtag_to_pp_hw_id));
   5968             return BCM_E_NOT_FOUND;
   5969         }
   5970 
   5971         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_to_pp_hw_id,
   5972                 &subtag_pp_entry);
   5973         if (SOC_FAILURE(rv)) {
   5974             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   5975                       (BSL_META_U(unit,
   5976                                   "ERROR: DEVICE_STREAM_ID_TO_PP_PORT_MAPm read "
   5977                                    "failed.for index %d\n"), subtag_to_pp_hw_id));
   5978             return rv;
   5979         }
   5980 
   5981         if (soc_mem_field32_get(unit, mem,
   5982                 (uint32 *)&subtag_pp_entry, PHB_VALIDf)) {
   5983             config->prop_flags |= BCM_SUBPORT_PROPERTY_PHB;
   5984             config->int_pri = soc_mem_field32_get(unit, mem,
   5985                 (uint32 *)&subtag_pp_entry, INT_PRIf);
   5986             config->color = soc_mem_field32_get(unit, mem,
   5987                 (uint32 *)&subtag_pp_entry, CNGf);
   5988         } else {
   5989             config->prop_flags &= ~BCM_SUBPORT_PROPERTY_PHB;
   5990             config->int_pri = 0;
   5991             config->color = 0;
   5992         }
   5993     } else {
   5994         return BCM_E_PARAM;
   5995     }
   5996 
   5997     return BCM_E_NONE;
   5998 }
   5999 
   6000 /*
   6001  * Function:
   6002  *  _bcm_general_subport_port_get
   6003  * Purpose:
   6004  *  Get the General subport_port config
   6005  * Parameters:
   6006  *  unit   - (IN) Device Number
   6007  *  port   - (IN) Subport_port GPORT (generic port) identifier
   6008  *  config - (OUT) Subport port config
   6009  * Returns:
   6010  *  BCM_E_XXX
   6011  */
   6012 STATIC int
   6013 _bcm_general_subport_port_get(int unit,
   6014                               bcm_gport_t subport_port_gport,
   6015                               bcm_subport_config_t *config)
   6016 {
   6017     int pp_port = 0;
   6018     bcm_gport_t subport_group;
   6019 
   6020     if (config == NULL) {
   6021         return BCM_E_PARAM;
   6022     }
   6023 
   6024     if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) {
   6025 
   6026         pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport);
   6027 
   6028         subport_group =
   6029             _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port);
   6030 
   6031         if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) {
   6032             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   6033                     (BSL_META_U(unit,
   6034                     "ERROR:Invalid General subport port gport 0x%x\n"),
   6035                      subport_port_gport));
   6036             return BCM_E_PARAM;
   6037         }
   6038 
   6039         if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   6040             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   6041                     (BSL_META_U(unit,
   6042                     "ERROR: General subport port gport 0x%x not found\n"),
   6043                      subport_port_gport));
   6044             return BCM_E_NOT_FOUND;
   6045         }
   6046         
   6047         config->group = subport_group;
   6048 
   6049     } else {
   6050         return BCM_E_PARAM;
   6051     }
   6052 
   6053     return BCM_E_NONE;
   6054 }
   6055 
   6056 /*
   6057  * Function:
   6058  *      _bcm_subtag_subport_port_traverse
   6059  * Purpose:
   6060  *      Add all valid SubTag subports under all valid SubTag subport groups
   6061  * Parameters:
   6062  *      unit      - Device Number
   6063  *      cb        - User callback function, called once per subport.
   6064  *      user_data - cookie
   6065  * Returns:
   6066  *      BCM_E_XXX
   6067  */
   6068 STATIC int
   6069 _bcm_subtag_subport_port_traverse(int unit,
   6070                                   bcm_subport_port_traverse_cb cb,
   6071                                   void *user_data)
   6072 {
   6073     int rv = BCM_E_NONE;
   6074     int pp_port_id = 0;
   6075     bcm_subport_config_t config;
   6076     bcm_gport_t subtag_subport_port;
   6077 
   6078     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6079 
   6080     BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port_id) {
   6081 
   6082         if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_id)) {
   6083             continue;
   6084         }
   6085 
   6086         bcm_subport_config_t_init(&config);
   6087 
   6088         _BCM_KT2_SUBPORT_PORT_ID_SET(subtag_subport_port, pp_port_id);
   6089         
   6090         _BCM_KT2_SUBPORT_PORT_TYPE_SET(subtag_subport_port,
   6091                                           _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   6092 
   6093         rv = _bcm_subtag_subport_port_get(unit, subtag_subport_port, &config);
   6094         if (BCM_FAILURE(rv)) {
   6095             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6096                       (BSL_META_U(unit,
   6097                                   "ERROR: subport port traverse failed \n"
   6098                                    "to get SubTag subport id %d\n"), pp_port_id));
   6099             return rv;
   6100         }
   6101 
   6102         rv = cb(unit, subtag_subport_port, &config, user_data);
   6103         COMPILER_REFERENCE(rv);
   6104 #ifdef BCM_CB_ABORT_ON_ERR
   6105         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   6106             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6107                       (BSL_META_U(unit,
   6108                                   "ERROR: subport port traverse failed \n"
   6109                                    "to callback for subport port (subport_port id %d)\n"),
   6110                        pp_port_id));
   6111             return rv;
   6112         }
   6113 #endif
   6114     }
   6115     return BCM_E_NONE;
   6116 }
   6117 
   6118 /*
   6119  * Function:
   6120  *  _bcm_general_subport_port_traverse
   6121  * Purpose:
   6122  *  Traverse all valid general subports under all valid general subport groups
   6123  * Parameters:
   6124  *  unit      - Device Number
   6125  *  cb        - User callback function, called once per subport.
   6126  *  user_data - cookie
   6127  * Returns:
   6128  *  BCM_E_XXX
   6129  */
   6130 STATIC int
   6131 _bcm_general_subport_port_traverse(int unit,
   6132                                    bcm_subport_port_traverse_cb cb,
   6133                                    void *user_data)
   6134 {
   6135     int rv = BCM_E_NONE;
   6136     int pp_port_id = 0;
   6137     bcm_subport_config_t config;
   6138     bcm_gport_t general_subport_port;
   6139 
   6140     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6141 
   6142     BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port_id) {
   6143 
   6144         if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_id)) {
   6145             continue;
   6146         }
   6147 
   6148         bcm_subport_config_t_init(&config);
   6149 
   6150         _BCM_KT2_SUBPORT_PORT_ID_SET(general_subport_port, pp_port_id);
   6151 
   6152         _BCM_KT2_SUBPORT_PORT_TYPE_SET(general_subport_port,
   6153                                        _BCM_KT2_SUBPORT_TYPE_GENERAL);
   6154 
   6155         rv = _bcm_general_subport_port_get(unit, general_subport_port, &config);
   6156         if (BCM_FAILURE(rv)) {
   6157             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6158                     (BSL_META_U(unit,
   6159                                 "ERROR: subport port traverse failed \n"
   6160                                 "to get general subport id %d\n"), pp_port_id));
   6161             return rv;
   6162         }
   6163 
   6164         rv = cb(unit, general_subport_port, &config, user_data);
   6165         COMPILER_REFERENCE(rv);
   6166 
   6167 #ifdef BCM_CB_ABORT_ON_ERR
   6168         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   6169             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6170                     (BSL_META_U(unit,
   6171                      "ERROR: subport port traverse failed \n"
   6172                      "to callback for subport port (subport_port id %d)\n"),
   6173                      pp_port_id));
   6174             return rv;
   6175         }
   6176 #endif
   6177     }
   6178     
   6179     return BCM_E_NONE;
   6180 }
   6181 
   6182 /*
   6183  * Function:
   6184  *      _bcm_subtag_subport_cleanup
   6185  * Purpose:
   6186  *      Delate all valid SubTag subport ports and
   6187  *      all valid SubTag subport groups.
   6188  * Parameters:
   6189  *      unit      - Device Number
   6190  * Returns:
   6191  *      BCM_E_XXX
   6192  */
   6193 STATIC int
   6194 _bcm_subtag_subport_cleanup(int unit)
   6195 {
   6196     int group_id = 0, rv = BCM_E_NONE, pp_port_id = 0;
   6197     bcm_port_t port;
   6198     bcm_gport_t subport_group;
   6199     bcm_gport_t subport_port;
   6200     soc_mem_t mem;
   6201 
   6202     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6203 
   6204    /* delete all SubTag subport ports */
   6205     BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port_id) {
   6206         
   6207         if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, pp_port_id)) {
   6208             continue;
   6209         }
   6210 
   6211         _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port_id);
   6212 
   6213         _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   6214                                           _BCM_KT2_SUBPORT_TYPE_SUBTAG);
   6215 
   6216         subport_group =
   6217             _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_id);
   6218 
   6219         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group);
   6220 
   6221         rv = _bcm_subtag_subport_port_delete(unit, subport_port);
   6222         if (SOC_FAILURE(rv)) {
   6223             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6224                       (BSL_META_U(unit,
   6225                                   "ERROR: SubTag subport port delete failed (subport id %d)\n"),
   6226                        pp_port_id));
   6227             return rv;
   6228         }
   6229 
   6230         if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) {
   6231              /* delete the subport group */
   6232             _bcm_subport_group_count[unit]--;
   6233             _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id);
   6234             _bcm_linkphy_subport_group_count[unit]--;
   6235             _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_CLR(unit, group_id);
   6236         }
   6237     }
   6238 
   6239     /* Cleanup SubTag VLAN id bit map */
   6240     BCM_PBMP_ITER(SOC_INFO(unit).subtag_pbm, port) {
   6241         mem = ING_PHYSICAL_PORT_TABLEm;
   6242         if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   6243             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   6244                 unit, mem, port, CASCADED_PORT_TYPEf, 0));
   6245         }
   6246         if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   6247             BCM_IF_ERROR_RETURN(soc_mem_field32_modify
   6248                 (unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET));
   6249         }
   6250         mem = EGR_PHYSICAL_PORTm;
   6251         if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   6252             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   6253                 unit, mem, port, CASCADED_PORT_TYPEf, 0));
   6254         }
   6255         if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   6256             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   6257                 unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET));
   6258         }
   6259     }
   6260 
   6261     return BCM_E_NONE;
   6262 
   6263 }
   6264 
   6265 /*
   6266  * Function:
   6267  *  _bcm_general_subport_cleanup
   6268  * Purpose:
   6269  *  Delete all valid general purpose subport ports and
   6270  *  all valid general subport groups.
   6271  * Parameters:
   6272  *  unit      - Device Number
   6273  * Returns:
   6274  *  BCM_E_XXX
   6275  */
   6276 STATIC int
   6277 _bcm_general_subport_cleanup(int unit)
   6278 {
   6279 
   6280     int group_id = 0, rv = BCM_E_NONE, pp_port_id = 0;
   6281     bcm_gport_t subport_group;
   6282     bcm_gport_t subport_port;
   6283 
   6284     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6285 
   6286     /* delete all general subport ports */
   6287     BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port_id) {
   6288 
   6289         if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, pp_port_id)) {
   6290             continue;
   6291         }
   6292 
   6293         _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port_id);
   6294 
   6295         _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port,
   6296                 _BCM_KT2_SUBPORT_TYPE_GENERAL);
   6297 
   6298         subport_group =
   6299             _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_id);
   6300 
   6301         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group);
   6302 
   6303         rv = _bcm_general_subport_port_delete(unit, subport_port);
   6304         if (SOC_FAILURE(rv)) {
   6305             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6306                     (BSL_META_U(unit,
   6307                     "ERROR: General subport port delete failed (subport id %d)\n"),
   6308                      pp_port_id));
   6309             return rv;
   6310         }
   6311 
   6312         /* delete the subport group */
   6313         if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) {
   6314             _bcm_subport_group_count[unit]--;
   6315             _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id);
   6316             _bcm_general_subport_group_count[unit]--;
   6317             _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_CLR(unit, group_id);
   6318         }
   6319     }
   6320 
   6321     return BCM_E_NONE;
   6322 }
   6323 
   6324 /*********************************
   6325  * SubTag helper functions -end *
   6326  */
   6327 
   6328 
   6329 STATIC void
   6330 bcm_kt2_subport_free_resource(int unit)
   6331 {
   6332     if(_bcm_subport_group_bitmap[unit] != NULL) {
   6333         sal_free(_bcm_subport_group_bitmap[unit]);
   6334         _bcm_subport_group_bitmap[unit] = NULL;
   6335     }
   6336 
   6337     if(_bcm_subport_pp_port_bitmap[unit] != NULL) {
   6338         sal_free(_bcm_subport_pp_port_bitmap[unit]);
   6339         _bcm_subport_pp_port_bitmap[unit] = NULL;
   6340     }
   6341 
   6342     if (soc_feature(unit, soc_feature_linkphy_coe)) {
   6343 
   6344         if(_bcm_linkphy_group_bitmap[unit] != NULL) {
   6345             sal_free(_bcm_linkphy_group_bitmap[unit]);
   6346             _bcm_linkphy_group_bitmap[unit] = NULL;
   6347         }
   6348 
   6349         if (_bcm_linkphy_subport_port_info[unit] != NULL) {
   6350             sal_free(_bcm_linkphy_subport_port_info[unit]);
   6351             _bcm_linkphy_subport_port_info[unit] = NULL;
   6352         }
   6353 
   6354     } /* end of  soc_feature_linkphy_coe */
   6355 
   6356     if (soc_feature(unit, soc_feature_subtag_coe)) {
   6357 
   6358         if(_bcm_subtag_group_bitmap[unit] != NULL) {
   6359             sal_free(_bcm_subtag_group_bitmap[unit]);
   6360             _bcm_subtag_group_bitmap[unit] = NULL;
   6361         }
   6362 
   6363         if (_bcm_subtag_subport_port_info[unit] != NULL) {
   6364             sal_free(_bcm_subtag_subport_port_info[unit]);
   6365             _bcm_subtag_subport_port_info[unit] = NULL;
   6366         }
   6367 
   6368     } /* end of  soc_feature_subtag_coe */
   6369 
   6370     if (soc_feature(unit, soc_feature_general_cascade)) {
   6371 
   6372         if(_bcm_general_subport_group_bitmap[unit] != NULL) {
   6373             sal_free(_bcm_general_subport_group_bitmap[unit]);
   6374             _bcm_general_subport_group_bitmap[unit] = NULL;
   6375         }
   6376 
   6377         if (_bcm_general_subport_port_info[unit] != NULL) {
   6378             sal_free(_bcm_general_subport_port_info[unit]);
   6379             _bcm_general_subport_port_info[unit] = NULL;
   6380         }
   6381 
   6382     } /* end of soc_feature_general_cascade */
   6383 
   6384     if (_bcm_subport_group_subport_port_count[unit] != NULL) {
   6385         sal_free(_bcm_subport_group_subport_port_count[unit]);
   6386         _bcm_subport_group_subport_port_count[unit] = NULL;
   6387     }
   6388 
   6389     if (_bcm_subport_mutex[unit] != NULL) {
   6390         sal_mutex_destroy(_bcm_subport_mutex[unit]);
   6391         _bcm_subport_mutex[unit] = NULL;
   6392     }
   6393 
   6394 }
   6395 
   6396 /*
   6397  * Function:
   6398  *      bcm_kt2_nhi_group_tc_profile_init
   6399  * Purpose:
   6400  *      Initialize kt2 NHI_GROUP_TC_PROFILE table. KT2 provides a TC PROFILE table with 256
   6401  *      items which are used to store the NHI_OFFSET.  The index of TC PROFILE derives from 
   6402  *      concatenating the TC PROFILE INDEX and internal priority of the packet.
   6403  * Parameters:
   6404  *      unit      - Device Number
   6405  * Returns:
   6406  *      BCM_E_XXX
   6407  */
   6408 STATIC int 
   6409 bcm_kt2_nhi_group_tc_profile_init(int unit)
   6410 {
   6411     int rv = BCM_E_NONE;
   6412     int nhi_group, int_pri;
   6413     nhi_group_tc_profile_entry_t nhi_entry;
   6414     
   6415     if (SOC_MEM_IS_VALID(unit, NHI_GROUP_TC_PROFILEm)) {
   6416         for (nhi_group = 0; nhi_group <= 0xf; nhi_group++) {
   6417             for (int_pri = 0; int_pri <= 0xf; int_pri++) {
   6418                 sal_memset(&nhi_entry, 0, sizeof(nhi_group_tc_profile_entry_t));  
   6419                 soc_mem_field32_set(unit, NHI_GROUP_TC_PROFILEm, &nhi_entry, 
   6420                                 NHI_OFFSETf, int_pri);
   6421                 rv = soc_mem_write(unit, NHI_GROUP_TC_PROFILEm,
   6422                         MEM_BLOCK_ALL, (nhi_group<<4)|int_pri, &nhi_entry);
   6423                 if (SOC_FAILURE(rv)) {
   6424                     LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6425                               (BSL_META_U(unit,
   6426                                           "ERROR: NHI_GROUP_TC_PROFIE init failed\n")));
   6427                     return rv;
   6428                 }
   6429             }
   6430         }
   6431     }
   6432 
   6433     return rv;  
   6434 }
   6435 
   6436 
   6437 /*
   6438  * Function:
   6439  *      bcm_kt2_subport_init
   6440  * Purpose:
   6441  *      Initialize the SUBPORT software module
   6442  * Parameters:
   6443  *      unit - Device Number
   6444  * Returns:
   6445  *      BCM_E_XXX
   6446  */
   6447 int
   6448 bcm_kt2_subport_init(int unit)
   6449 {
   6450     int rv = BCM_E_NONE;
   6451     soc_info_t *si = &SOC_INFO(unit);
   6452     int pp_port_index_max = si->pp_port_index_max;
   6453     int subport_group_max = si->subport_group_max;
   6454 
   6455     /* Subport group bitmap to keep track of used subport groups */
   6456     if (_bcm_subport_group_bitmap[unit] == NULL) {
   6457 
   6458         _bcm_subport_group_bitmap[unit] = 
   6459             sal_alloc(SHR_BITALLOCSIZE(subport_group_max),
   6460             "subport_group_bitmap");
   6461 
   6462         if (_bcm_subport_group_bitmap[unit] == NULL) {
   6463             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6464                       (BSL_META_U(unit,
   6465                                   "ERROR:subport_init: group bitmap alloc failed\n")));
   6466 
   6467             bcm_kt2_subport_free_resource(unit);
   6468 
   6469             return BCM_E_MEMORY;
   6470         }
   6471     }
   6472 
   6473     sal_memset(_bcm_subport_group_bitmap[unit], 0,
   6474         SHR_BITALLOCSIZE(subport_group_max));
   6475 
   6476     _bcm_subport_group_count[unit] = 0;
   6477 
   6478     /* Keep Count of subport port created per subport group */
   6479     if (_bcm_subport_group_subport_port_count[unit] == NULL) {
   6480         _bcm_subport_group_subport_port_count[unit] =
   6481             sal_alloc((subport_group_max * sizeof(int)),
   6482                         "subport_group_subport_port_count");
   6483         if (_bcm_subport_group_subport_port_count[unit] == NULL) {
   6484             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6485                       (BSL_META_U(unit,
   6486                                   "ERROR: "
   6487                                    "subport_group_subport_port_count alloc failed\n")));
   6488 
   6489             return BCM_E_MEMORY;
   6490         }
   6491     }
   6492 
   6493     sal_memset(_bcm_subport_group_subport_port_count[unit], 0,
   6494         (subport_group_max * sizeof(int)));
   6495 
   6496     /* Create subport mutex */
   6497     if (NULL == _bcm_subport_mutex[unit]) {
   6498         _bcm_subport_mutex[unit] =
   6499             sal_mutex_create("linkphy_subtag subport mutex");
   6500 
   6501         if (_bcm_subport_mutex[unit] == NULL) {
   6502             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6503                       (BSL_META_U(unit,
   6504                                   "ERROR:linkphy_subtag subport mutex create failed\n")));
   6505 
   6506             return BCM_E_MEMORY;
   6507         }
   6508     }
   6509 
   6510     /* LinkPHY subport initialization */
   6511     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   6512         BCM_PBMP_NOT_NULL(si->linkphy_allowed_pbm)) {
   6513         rv = _bcm_linkphy_subport_init(unit);
   6514         if (SOC_FAILURE(rv)) {
   6515             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6516                       (BSL_META_U(unit,
   6517                                   "ERROR: LinkPHY init failed.\n")));
   6518 
   6519             bcm_kt2_subport_free_resource(unit);
   6520             return rv;
   6521         }
   6522     }
   6523 
   6524     /* Subtag CoE subport initialization */
   6525     if (soc_feature(unit, soc_feature_subtag_coe) &&
   6526         BCM_PBMP_NOT_NULL(si->subtag_allowed_pbm)) {
   6527         rv = _bcm_subtag_subport_init(unit);
   6528         if (SOC_FAILURE(rv)) {
   6529             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6530                       (BSL_META_U(unit,
   6531                                   "ERROR: SubTag init failed.\n")));
   6532 
   6533             bcm_kt2_subport_free_resource(unit);
   6534             return rv;
   6535         }
   6536     }
   6537 
   6538     /* General subport initialization */
   6539     if (soc_feature(unit, soc_feature_general_cascade)) { 
   6540         rv = _bcm_general_subport_init(unit);
   6541         if (SOC_FAILURE(rv)) {
   6542             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6543                     (BSL_META_U(unit,
   6544                      "ERROR: General subport init failed.\n")));
   6545             bcm_kt2_subport_free_resource(unit);
   6546             return rv;
   6547         }
   6548     }
   6549 
   6550     if (soc_feature(unit, soc_feature_lltag)) {
   6551         rv = bcm_kt2_nhi_group_tc_profile_init(unit);
   6552         if (SOC_FAILURE(rv)) {
   6553             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6554                       (BSL_META_U(unit,
   6555                                   "ERROR: tc profile init failed.\n")));
   6556 
   6557             bcm_kt2_subport_free_resource(unit);
   6558             return rv;
   6559         }
   6560     }
   6561 
   6562     if (_bcm_subport_pp_port_bitmap[unit] == NULL) {
   6563 
   6564         _bcm_subport_pp_port_bitmap[unit] =
   6565         sal_alloc(SHR_BITALLOCSIZE(pp_port_index_max + 1),
   6566             "subport_group_bitmap");
   6567 
   6568         if (_bcm_subport_pp_port_bitmap[unit] == NULL) {
   6569             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6570                       (BSL_META_U(unit,
   6571                                   "ERROR:subport_init: pp_port bitmap alloc failed\n")));
   6572 
   6573             bcm_kt2_subport_free_resource(unit);
   6574 
   6575             return BCM_E_MEMORY;
   6576         }
   6577     }
   6578 
   6579     sal_memset(_bcm_subport_pp_port_bitmap[unit], 0,
   6580         SHR_BITALLOCSIZE(pp_port_index_max + 1));
   6581 
   6582     _bcm_subport_pp_port_count[unit] = 0;
   6583 
   6584 
   6585     /* Initialize common SUBPORT module */
   6586 
   6587     /* If the subport-feature is disabled, unset the relevant
   6588        handlers in the vector, these would have been setup by
   6589        default for all KT2 devices, the feature being disabled
   6590        is an exception */
   6591     if(!soc_feature(unit, soc_feature_subport_enhanced)) {
   6592         bcmi_kt2_subport_drv.subport_init = NULL;
   6593         bcmi_kt2_subport_drv.subport_group_create = NULL;      
   6594         bcmi_kt2_subport_drv.subport_group_get = NULL;      
   6595         bcmi_kt2_subport_drv.subport_group_traverse = NULL;    
   6596         bcmi_kt2_subport_drv.subport_group_destroy = NULL;    
   6597         bcmi_kt2_subport_drv.subport_linkphy_config_set = NULL;
   6598         bcmi_kt2_subport_drv.subport_linkphy_config_get = NULL;
   6599         bcmi_kt2_subport_drv.subport_port_add = NULL;
   6600         bcmi_kt2_subport_drv.subport_port_get = NULL;          
   6601         bcmi_kt2_subport_drv.subport_port_traverse = NULL;
   6602         bcmi_kt2_subport_drv.subport_port_stat_set = NULL;
   6603         bcmi_kt2_subport_drv.subport_port_stat_get = NULL;
   6604         bcmi_kt2_subport_drv.subport_port_delete = NULL;   
   6605         bcmi_kt2_subport_drv.subport_cleanup = NULL; 
   6606     }
   6607 
   6608     BCM_IF_ERROR_RETURN
   6609         (bcmi_subport_common_init(unit, &bcmi_kt2_subport_drv));
   6610 
   6611     return rv;
   6612 }
   6613 
   6614 /*
   6615  * Function:
   6616  *      bcm_kt2_subport_group_create
   6617  * Purpose:
   6618  *      Create a subport group
   6619  * Parameters:
   6620  *      unit   - (IN) Device Number
   6621  *      config - (IN) Subport group config information
   6622  *      group  - (OUT) GPORT (generic port) identifier
   6623  * Returns:
   6624  *      BCM_E_XXX
   6625  */
   6626 int
   6627 bcm_kt2_subport_group_create(int unit, 
   6628                              bcm_subport_group_config_t *config,
   6629                              bcm_gport_t *group)
   6630 {
   6631     int rv = BCM_E_NONE, group_id = -1, i = 0, is_trunk = 0;
   6632     bcm_port_t port = 0;
   6633     soc_info_t *si = &SOC_INFO(unit);
   6634     int subport_group_max = si->subport_group_max;
   6635 
   6636     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6637 
   6638     if ((config == NULL) || (group == NULL)) {
   6639         return BCM_E_PARAM;
   6640     }
   6641 
   6642     if ((config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY) &&
   6643         (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) {
   6644         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6645                   (BSL_META_U(unit,
   6646                   "ERROR:Either LinkPHY or SubTag group can "
   6647                   "be created at a time\n")));
   6648         return BCM_E_PARAM;
   6649     }
   6650 
   6651     if (!(config->flags & BCM_SUBPORT_GROUP_TYPE_GENERAL)) {
   6652         rv = _bcm_esw_port_gport_validate(unit, config->port, &port);
   6653         if (SOC_FAILURE(rv)) {
   6654             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6655                     (BSL_META_U(unit,
   6656                     "ERROR: Invalid gport 0x%x for subport group create.\n"),
   6657                      config->port));
   6658             return BCM_E_PORT;
   6659         }
   6660     }
   6661 
   6662     if ((config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY) &&
   6663         !BCM_PBMP_MEMBER(si->linkphy_pbm, port)) {
   6664         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6665                   (BSL_META_U(unit,
   6666                               "ERROR: port %d is not member of pbmp_linkphy\n"),
   6667                    port));
   6668         return BCM_E_PORT;
   6669     }
   6670 
   6671     if ((config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG) &&
   6672         !BCM_PBMP_MEMBER(si->subtag_pbm, port)) {
   6673         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6674                   (BSL_META_U(unit,
   6675                               "ERROR: SubportTag/CoE should be enabled"
   6676                                " for port %d\n"), port));
   6677         return BCM_E_PORT;
   6678     }
   6679 
   6680     if (config->flags & BCM_SUBPORT_GROUP_TYPE_GENERAL) {
   6681         if ((config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY) ||
   6682             (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) {
   6683             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6684                      (BSL_META_U(unit,
   6685                      "ERROR: General subport group not supported "
   6686                      "with Linkphy/Coe applications.\n")));
   6687             return BCM_E_CONFIG;
   6688         }
   6689     }
   6690 
   6691     if (_bcm_subport_group_count[unit] == subport_group_max) {
   6692         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6693                   (BSL_META_U(unit,
   6694                             "ERROR: All %d subport groups already used.\n"),
   6695                             subport_group_max));
   6696         return BCM_E_FULL;
   6697     }
   6698 
   6699     if (config->flags & BCM_SUBPORT_GROUP_WITH_ID) {
   6700         group_id = BCM_GPORT_SUBPORT_GROUP_GET(*group);
   6701         /* Group id should be within 0 to 128.
   6702         * BCM_GPORT_SUBPORT_GROUP_MASK is 0xffffff (for all chips)
   6703         * but subtag/linkphy group id is only first 9 bits (8-0). 
   6704         * Check that only subtag/linkphy group id bits (8-0) are configured*/
   6705         if ((group_id >> _BCM_KT2_SUBPORT_GROUP_PORT_SHIFT)
   6706                 & _SHR_GPORT_SUBPORT_GROUP_MASK) {
   6707             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6708                       (BSL_META_U(unit,
   6709                           "ERROR: subport group id = %d should be within 0 to"
   6710                            " %d\n"), group_id, SOC_INFO(unit).subport_group_max-1));
   6711             return BCM_E_PARAM;
   6712         }
   6713         if (_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   6714             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6715                       (BSL_META_U(unit,
   6716                                   "ERROR: subport group id = %d is already used\n"),
   6717                        group_id));
   6718             return BCM_E_EXISTS;
   6719         }
   6720     } else {
   6721         for (i =0; i < subport_group_max; i++) {
   6722             if (!_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, i)) {
   6723                 group_id = i;
   6724                 break;
   6725             }
   6726         }
   6727 
   6728         if (i == subport_group_max) {
   6729             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6730                       (BSL_META_U(unit,
   6731                                   "ERROR: All %d subport groups already used.\n"),
   6732                        i));
   6733             return BCM_E_FULL;
   6734         }
   6735     }
   6736 
   6737     _BCM_KT2_SUBPORT_LOCK(unit);
   6738 
   6739     if (soc_feature(unit, soc_feature_linkphy_coe) && 
   6740         (config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY)) {
   6741 
   6742         rv  =_bcm_linkphy_subport_group_create(unit,
   6743                 is_trunk, port, group_id, group);
   6744         if (SOC_FAILURE(rv)) {
   6745             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6746                       (BSL_META_U(unit,
   6747                                   "ERROR: LinkPHY subport group create failed"
   6748                                    " for port %d. rv = %d(%s)\n"),
   6749                        config->port, rv, soc_errmsg(rv)));
   6750             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6751             return rv;
   6752         }
   6753     } else if (soc_feature(unit, soc_feature_subtag_coe) && 
   6754         (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) {
   6755         rv  =_bcm_subtag_subport_group_create(unit,
   6756                 is_trunk, port, group_id, group);
   6757         if (SOC_FAILURE(rv)) {
   6758             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6759                       (BSL_META_U(unit,
   6760                                   "ERROR: SubTag subport group create failed"
   6761                                    " for port %d. rv = %d(%s)\n"),
   6762                        config->port, rv, soc_errmsg(rv)));
   6763             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6764             return rv;
   6765         }
   6766     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   6767               (config->flags & BCM_SUBPORT_GROUP_TYPE_GENERAL)) {
   6768         rv  =_bcm_general_subport_group_create(unit,
   6769                                                is_trunk, port,
   6770                                                group_id, group);
   6771         if (SOC_FAILURE(rv)) {
   6772             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6773                     (BSL_META_U(unit,
   6774                                 "ERROR: General subport group create failed"
   6775                                 " for port %d. rv = %d(%s)\n"),
   6776                      config->port, rv, soc_errmsg(rv)));
   6777             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6778             return rv;
   6779         }
   6780     }
   6781 
   6782     /* defensive check for static analyzers */
   6783     if (group_id == -1) {
   6784         _BCM_KT2_SUBPORT_UNLOCK(unit);
   6785         return BCM_E_INTERNAL;
   6786     }
   6787     _BCM_KT2_SUBPORT_GROUP_USED_SET(unit, group_id);
   6788     _bcm_subport_group_count[unit]++;
   6789 
   6790     _BCM_KT2_SUBPORT_UNLOCK(unit);
   6791 
   6792 #ifdef BCM_WARM_BOOT_SUPPORT
   6793     SOC_CONTROL_LOCK(unit);
   6794     SOC_CONTROL(unit)->scache_dirty = 1;
   6795     SOC_CONTROL_UNLOCK(unit);
   6796 #endif
   6797 
   6798     return BCM_E_NONE;
   6799 
   6800 }
   6801 
   6802 
   6803 /*
   6804  * Function:
   6805  *      bcm_kt2_subport_group_destroy
   6806  * Purpose:
   6807  *      Destroy a subport group and all subport ports attached to it.
   6808  * Parameters:
   6809  *      unit   - (IN) Device Number
   6810  *      group  - (IN) GPORT (generic port) identifier for subport group
   6811  * Returns:
   6812  *      BCM_E_XXX
   6813  */
   6814 int 
   6815 bcm_kt2_subport_group_destroy(int unit,
   6816                               bcm_gport_t group)
   6817 {
   6818     int rv = BCM_E_NONE;
   6819     soc_info_t *si = &SOC_INFO(unit);
   6820 
   6821     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6822 
   6823     if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) {
   6824         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6825                   (BSL_META_U(unit,
   6826                               "ERROR: group 0x%x is not subport group gport\n"),
   6827                    group));
   6828         return BCM_E_PARAM;
   6829     }
   6830 
   6831     _BCM_KT2_SUBPORT_LOCK(unit);
   6832 
   6833     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   6834         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) {
   6835         if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) {
   6836             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6837                       (BSL_META_U(unit,
   6838                                   "ERROR: LinkPHY ports not configured\n")));
   6839             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6840             return BCM_E_PARAM;
   6841         }
   6842         rv = _bcm_linkphy_subport_group_destroy(unit, group);
   6843     } else if (soc_feature(unit, soc_feature_subtag_coe) &&
   6844         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   6845         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   6846             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6847                       (BSL_META_U(unit,
   6848                                   "ERROR: SubTag ports not configured\n")));
   6849             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6850             return BCM_E_PARAM;
   6851         }
   6852         rv = _bcm_subtag_subport_group_destroy(unit, group);
   6853     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   6854             _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) {
   6855         rv = _bcm_general_subport_group_destroy(unit, group);
   6856     }
   6857 
   6858     if (SOC_FAILURE(rv)) {
   6859         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6860                   (BSL_META_U(unit,
   6861                               "ERROR: subport group 0x%x destroy failed. rv= %d(%s)\n"),
   6862                    group, rv, soc_errmsg(rv)));
   6863         _BCM_KT2_SUBPORT_UNLOCK(unit);
   6864         return rv;
   6865     }
   6866 
   6867     _BCM_KT2_SUBPORT_UNLOCK(unit);
   6868 
   6869 #ifdef BCM_WARM_BOOT_SUPPORT
   6870     SOC_CONTROL_LOCK(unit);
   6871     SOC_CONTROL(unit)->scache_dirty = 1;
   6872     SOC_CONTROL_UNLOCK(unit);
   6873 #endif
   6874 
   6875     return BCM_E_NONE;
   6876 }
   6877 
   6878 /*
   6879  * Function:
   6880  *      bcm_kt2_subport_group_get
   6881  * Purpose:
   6882  *      Get a subport group
   6883  * Parameters:
   6884  *      unit   - (IN) Device Number
   6885  *      group  - (IN) GPORT (generic port) identifier
   6886  *      config - (OUT) Subport group config information
   6887  * Returns:
   6888  *      BCM_E_XXX
   6889  */
   6890 int
   6891 bcm_kt2_subport_group_get(int unit,
   6892                           bcm_gport_t group,
   6893                           bcm_subport_group_config_t *config)
   6894 {
   6895     int rv = BCM_E_NONE;
   6896     soc_info_t *si = &SOC_INFO(unit);
   6897 
   6898     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6899 
   6900     if (config == NULL) {
   6901         return BCM_E_PARAM;
   6902     }
   6903 
   6904     if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) {
   6905         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6906                   (BSL_META_U(unit,
   6907                               "ERROR: group 0x%x is not subport group gport\n"),
   6908                    group));
   6909         return BCM_E_PARAM;
   6910     }
   6911 
   6912     _BCM_KT2_SUBPORT_LOCK(unit);
   6913 
   6914     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   6915         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) {
   6916         if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) {
   6917             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6918                       (BSL_META_U(unit,
   6919                                   "ERROR: LinkPHY ports not configured\n")));
   6920             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6921             return BCM_E_PARAM;
   6922         }
   6923         rv = _bcm_linkphy_subport_group_get(unit, group, config);
   6924     } else if (soc_feature(unit, soc_feature_subtag_coe) &&
   6925         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   6926         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   6927             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6928                       (BSL_META_U(unit,
   6929                                   "ERROR: SubTag ports not configured\n")));
   6930             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6931             return BCM_E_PARAM;
   6932         }
   6933         rv = _bcm_subtag_subport_group_get(unit, group, config);
   6934     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   6935         _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) {
   6936         rv = _bcm_general_subport_group_get(unit, group, config);
   6937     }
   6938 
   6939     if (SOC_FAILURE(rv)) {
   6940         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6941                   (BSL_META_U(unit,
   6942                               "ERROR: subport group get failed for 0x%x, rv = %d(%s)\n"),
   6943                    group, rv, soc_errmsg(rv)));
   6944         _BCM_KT2_SUBPORT_UNLOCK(unit);
   6945         return rv;
   6946     }
   6947 
   6948     _BCM_KT2_SUBPORT_UNLOCK(unit);
   6949 
   6950     return BCM_E_NONE;
   6951 }
   6952 
   6953 /*
   6954  * Function:
   6955  *      bcm_kt2_subport_group_traverse
   6956  * Purpose:
   6957  *      Traverse all valid subports for given subport group and call the user
   6958  *      supplied callback routine.
   6959  * Parameters:
   6960  *      unit      - Device Number
   6961  *      group     - Subport group GPORT identifier
   6962  *      cb        - User callback function, called once per subport.
   6963  *      user_data - cookie
   6964  */
   6965 
   6966 int
   6967 bcm_kt2_subport_group_traverse(int unit,
   6968                                bcm_gport_t group,
   6969                                bcm_subport_port_traverse_cb cb,
   6970                                void *user_data)
   6971 {
   6972     int rv = BCM_E_NONE;
   6973     soc_info_t *si = &SOC_INFO(unit);
   6974 
   6975     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   6976 
   6977     if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) {
   6978         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6979                   (BSL_META_U(unit,
   6980                               "ERROR: group 0x%x is not subport group gport\n"),
   6981                    group));
   6982         return BCM_E_PARAM;
   6983     }
   6984 
   6985     _BCM_KT2_SUBPORT_LOCK(unit);
   6986 
   6987     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   6988         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) {
   6989         if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) {
   6990             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   6991                       (BSL_META_U(unit,
   6992                                   "ERROR: LinkPHY ports not configured\n")));
   6993             _BCM_KT2_SUBPORT_UNLOCK(unit);
   6994             return BCM_E_PARAM;
   6995         }
   6996         rv =_bcm_linkphy_subport_group_traverse(unit, group, cb, user_data);
   6997     } else if (soc_feature(unit, soc_feature_subtag_coe) &&
   6998         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) {
   6999         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   7000             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7001                       (BSL_META_U(unit,
   7002                                   "ERROR: SubTag ports not configured\n")));
   7003             _BCM_KT2_SUBPORT_UNLOCK(unit);
   7004             return BCM_E_PARAM;
   7005         }
   7006         rv =_bcm_subtag_subport_group_traverse(unit, group, cb, user_data);
   7007     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   7008             _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) {
   7009         rv =_bcm_general_subport_group_traverse(unit, group, cb, user_data);
   7010     }
   7011 
   7012     if (SOC_FAILURE(rv)) {
   7013         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7014                   (BSL_META_U(unit,
   7015                               "ERROR: subport group traverse failed for 0x%x, rv = %d(%s)\n"),
   7016                    group, rv, soc_errmsg(rv)));
   7017         _BCM_KT2_SUBPORT_UNLOCK(unit);
   7018         return rv;
   7019     }
   7020 
   7021     _BCM_KT2_SUBPORT_UNLOCK(unit);
   7022 
   7023     return BCM_E_NONE;
   7024 }
   7025 
   7026 /*
   7027  * Function:
   7028  *      bcm_kt2_subport_group_resolve
   7029  * Purpose:
   7030  *      resolve physical port associated with the LinkPHy subport group
   7031  */
   7032 int
   7033 bcm_kt2_subport_group_resolve(int unit,
   7034                               bcm_gport_t subport_group_gport,
   7035                               bcm_module_t *modid, bcm_port_t *port,
   7036                               bcm_trunk_t *trunk_id, int *id)
   7037 
   7038 {
   7039     bcm_module_t my_modid;
   7040     uint16 group_id;
   7041 
   7042     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7043 
   7044     *modid = -1;
   7045     *port = -1;
   7046     *id = -1;
   7047     *trunk_id = BCM_TRUNK_INVALID;
   7048 
   7049     if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group_gport)) {
   7050         LOG_WARN(BSL_LS_BCM_SUBPORT,
   7051                  (BSL_META_U(unit,
   7052                              "gport 0x%x is not subport gport\n"),
   7053                   subport_group_gport));
   7054         return BCM_E_NONE;
   7055     }
   7056 
   7057     if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   7058         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(subport_group_gport)) ||
   7059         (soc_feature(unit, soc_feature_subtag_coe) &&
   7060         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(subport_group_gport)) || 
   7061         (soc_feature(unit, soc_feature_general_cascade) &&
   7062         _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(subport_group_gport))) {
   7063         group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group_gport);
   7064         if(!_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   7065             LOG_WARN(BSL_LS_BCM_SUBPORT,
   7066                      (BSL_META_U(unit,
   7067                                  "subport gport 0x%x is not used\n"),
   7068                       subport_group_gport));
   7069             return BCM_E_NONE;
   7070         }
   7071 
   7072         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   7073         *modid = my_modid;
   7074         *port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group_gport);
   7075     } else if (soc_feature(unit, soc_feature_subport_enhanced)) {
   7076 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
   7077         return _bcm_tr2_subport_group_resolve(unit, subport_group_gport,
   7078                                             modid, port, trunk_id,id);
   7079 #endif
   7080     } else if (soc_feature(unit, soc_feature_subport)) {
   7081 #if defined (BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
   7082         return _bcm_tr_subport_group_resolve(unit, subport_group_gport,
   7083                                              modid, port, trunk_id, id);
   7084 #endif
   7085     }
   7086 
   7087     return BCM_E_NONE;
   7088 
   7089 }
   7090 
   7091 /*
   7092  * Function:
   7093  *      bcm_kt2_subport_port_add
   7094  * Purpose:
   7095  *      Add a subport to a subport group
   7096  * Parameters:
   7097  *      unit   - (IN) Device Number
   7098  *      config - (IN) Subport config information
   7099  *      port   - (OUT) Subport_port GPORT (generic port) identifier
   7100  * Returns:
   7101  *      BCM_E_XXX
   7102  */
   7103 int
   7104 bcm_kt2_subport_port_add(int unit,
   7105                          bcm_subport_config_t *config,
   7106                          bcm_gport_t *gport)
   7107 {
   7108     int rv = BCM_E_NONE;
   7109     uint16 group_id;
   7110     soc_info_t *si = &SOC_INFO(unit);
   7111     int subport_port_max = si->subport_port_max;
   7112 
   7113     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7114     
   7115     if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) {
   7116         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7117                   (BSL_META_U(unit,
   7118                   "ERROR: config->group 0x%x is not subport group gport\n"),
   7119                    config->group));
   7120         return BCM_E_PARAM;
   7121     }
   7122 
   7123     group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group);
   7124     if(!_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, group_id)) {
   7125         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7126                  (BSL_META_U(unit,
   7127                  "ERROR:config->group 0x%x is not found\n"),
   7128                    config->group));
   7129         return BCM_E_NOT_FOUND;
   7130     }
   7131 
   7132     if (_bcm_subport_pp_port_count[unit] == subport_port_max) {
   7133         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7134                   (BSL_META_U(unit,
   7135                               "ERROR:All %d subport pp_port used\n"),
   7136                    subport_port_max));
   7137         return BCM_E_FULL;
   7138     }
   7139 
   7140     _BCM_KT2_SUBPORT_LOCK(unit);
   7141 
   7142     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   7143         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(config->group)) {
   7144         if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) {
   7145             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7146                       (BSL_META_U(unit,
   7147                                   "ERROR: LinkPHY ports not configured\n")));
   7148             _BCM_KT2_SUBPORT_UNLOCK(unit);
   7149             return BCM_E_PARAM;
   7150         }
   7151         rv = _bcm_linkphy_subport_port_add(unit, config, gport);
   7152     } else if (soc_feature(unit, soc_feature_subtag_coe) &&
   7153         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(config->group)) {
   7154         if (BCM_PBMP_IS_NULL(si->subtag_pbm)) {
   7155             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7156                       (BSL_META_U(unit,
   7157                                   "ERROR: SubTag ports not configured\n")));
   7158             _BCM_KT2_SUBPORT_UNLOCK(unit);
   7159             return BCM_E_PARAM;
   7160         }
   7161         rv = _bcm_subtag_subport_port_add(unit, config, gport);
   7162     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   7163             _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(config->group)) {
   7164         rv = _bcm_general_subport_port_add(unit, config, gport);
   7165     }
   7166 
   7167     if (SOC_FAILURE(rv)) {
   7168         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7169                   (BSL_META_U(unit,
   7170                               "ERROR: Subport port add failed. rv = %d(%s)\n"),
   7171                    rv, soc_errmsg(rv)));
   7172         _BCM_KT2_SUBPORT_UNLOCK(unit);
   7173         return rv;
   7174     }
   7175 
   7176     _BCM_KT2_SUBPORT_UNLOCK(unit);
   7177 
   7178 #ifdef BCM_WARM_BOOT_SUPPORT
   7179     SOC_CONTROL_LOCK(unit);
   7180     SOC_CONTROL(unit)->scache_dirty = 1;
   7181     SOC_CONTROL_UNLOCK(unit);
   7182 #endif
   7183 
   7184     return rv;
   7185 }
   7186 
   7187 /*
   7188  * Function:
   7189  *      bcm_kt2_subport_port_delete
   7190  * Purpose:
   7191  *      Delete a subport_port
   7192  * Parameters:
   7193  *      unit   - (IN) Device Number
   7194  *      port   - (IN) Subport_port GPORT (generic port) identifier
   7195  * Returns:
   7196  *      BCM_E_XXX
   7197  */
   7198 int
   7199 bcm_kt2_subport_port_delete(int unit,
   7200                             bcm_gport_t subport_port_gport)
   7201 {
   7202     int rv = BCM_E_NONE;
   7203 
   7204     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7205 
   7206     if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) {
   7207         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7208                   (BSL_META_U(unit,
   7209                               "ERROR: gport 0x%x is not subport port gport\n"),
   7210                    subport_port_gport));
   7211         return BCM_E_PARAM;
   7212     }
   7213 
   7214     _BCM_KT2_SUBPORT_LOCK(unit);
   7215 
   7216     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   7217         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) {
   7218         rv = _bcm_linkphy_subport_port_delete(unit, subport_port_gport);
   7219     } else if (soc_feature(unit, soc_feature_subtag_coe) &&
   7220         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) {
   7221         rv = _bcm_subtag_subport_port_delete(unit, subport_port_gport);
   7222     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   7223         _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) {
   7224         rv = _bcm_general_subport_port_delete(unit, subport_port_gport);
   7225     }
   7226 
   7227     if (SOC_FAILURE(rv)) {
   7228         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7229                   (BSL_META_U(unit,
   7230                               "ERROR: Subport port 0x%x delete failed. rv = %d(%s)\n"),
   7231                    subport_port_gport, rv, soc_errmsg(rv)));
   7232         _BCM_KT2_SUBPORT_UNLOCK(unit);
   7233         return rv;
   7234     }
   7235 
   7236     _BCM_KT2_SUBPORT_UNLOCK(unit);
   7237 
   7238 #ifdef BCM_WARM_BOOT_SUPPORT
   7239     SOC_CONTROL_LOCK(unit);
   7240     SOC_CONTROL(unit)->scache_dirty = 1;
   7241     SOC_CONTROL_UNLOCK(unit);
   7242 #endif
   7243 
   7244     return rv;
   7245 }
   7246 
   7247 /*
   7248  * Function:
   7249  *      bcm_kt2_subport_port_get
   7250  * Purpose:
   7251  *      Get the subport_port config
   7252  * Parameters:
   7253  *      unit   - (IN) Device Number
   7254  *      port   - (IN) Subport_port GPORT (generic port) identifier
   7255  *      config - (OUT) Subport port config
   7256  * Returns:
   7257  *      BCM_E_XXX
   7258  */
   7259 int 
   7260 bcm_kt2_subport_port_get(int unit,
   7261                          bcm_gport_t subport_port_gport,
   7262                          bcm_subport_config_t *config)
   7263 {
   7264     int rv = BCM_E_NONE;
   7265 
   7266     if (config == NULL) {
   7267         return BCM_E_PARAM;
   7268     }
   7269 
   7270     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7271 
   7272     if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) {
   7273         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7274                   (BSL_META_U(unit,
   7275                               "ERROR: gport 0x%x is not subport port gport\n"),
   7276                    subport_port_gport));
   7277         return BCM_E_PARAM;
   7278     }
   7279 
   7280     _BCM_KT2_SUBPORT_LOCK(unit);
   7281 
   7282     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   7283         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) {
   7284         rv = _bcm_linkphy_subport_port_get(unit, subport_port_gport, config);
   7285     } else if (soc_feature(unit, soc_feature_subtag_coe) &&
   7286         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) {
   7287         rv = _bcm_subtag_subport_port_get(unit, subport_port_gport, config);
   7288     } else if (soc_feature(unit, soc_feature_general_cascade) &&
   7289         _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) {
   7290         rv = _bcm_general_subport_port_get(unit, subport_port_gport, config);
   7291     }
   7292 
   7293     if (SOC_FAILURE(rv)) {
   7294         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   7295                     (BSL_META_U(unit,
   7296                                 "ERROR: Subport port 0x%x get failed. rv=%d(%s)\n"),
   7297                      subport_port_gport, rv, soc_errmsg(rv)));
   7298         _BCM_KT2_SUBPORT_UNLOCK(unit);
   7299         return rv;
   7300     }
   7301 
   7302     _BCM_KT2_SUBPORT_UNLOCK(unit);
   7303 
   7304     return BCM_E_NONE;
   7305 }
   7306 
   7307 /*
   7308  * Function:
   7309  *      bcm_kt2_subport_port_traverse
   7310  * Purpose:
   7311  *      Add all valid subports under all valid subport groups
   7312  * Parameters:
   7313  *      unit      - Device Number
   7314  *      cb        - User callback function, called once per subport.
   7315  *      user_data - cookie
   7316  * Returns:
   7317  *      BCM_E_XXX
   7318  */
   7319 
   7320 int
   7321 bcm_kt2_subport_port_traverse(int unit,
   7322                               bcm_subport_port_traverse_cb cb,
   7323                               void *user_data)
   7324 {
   7325     int rv = BCM_E_NONE;
   7326     soc_info_t *si = &SOC_INFO(unit);
   7327 
   7328     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7329 
   7330     _BCM_KT2_SUBPORT_LOCK(unit);
   7331 
   7332     if(soc_feature(unit, soc_feature_linkphy_coe) &&
   7333         BCM_PBMP_NOT_NULL(si->linkphy_pbm)) {
   7334         rv = _bcm_linkphy_subport_port_traverse(unit, cb, user_data);
   7335     }
   7336     if (soc_feature(unit, soc_feature_subtag_coe) &&
   7337         BCM_PBMP_NOT_NULL(si->subtag_pbm)) {
   7338         rv = _bcm_subtag_subport_port_traverse(unit, cb, user_data);
   7339     }
   7340     if (soc_feature(unit, soc_feature_general_cascade)) {
   7341         rv = _bcm_general_subport_port_traverse(unit, cb, user_data);
   7342     }
   7343 
   7344     if (SOC_FAILURE(rv)) {
   7345         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7346                   (BSL_META_U(unit,
   7347                               "ERROR:Subport port traverse failed. rv = %d(%s)\n"),
   7348                    rv,soc_errmsg(rv)));
   7349         _BCM_KT2_SUBPORT_UNLOCK(unit);
   7350         return rv;
   7351     }
   7352 
   7353     _BCM_KT2_SUBPORT_UNLOCK(unit);
   7354 
   7355     return BCM_E_NONE;
   7356 }
   7357 
   7358 /*
   7359  * Function:
   7360  *      bcm_kt2_subport_port_resolve
   7361  * Purpose:
   7362  *      resolve pp_port associated with the LinkPHy subport port 
   7363  */
   7364 int
   7365 bcm_kt2_subport_port_resolve(int unit,
   7366                               bcm_gport_t subport_port_gport,
   7367                               bcm_module_t *modid, bcm_port_t *port,
   7368                               bcm_trunk_t *trunk_id, int *id)
   7369 {
   7370     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7371 
   7372     *modid = -1;
   7373     *port = -1;
   7374     *id = -1;
   7375     *trunk_id = BCM_TRUNK_INVALID;
   7376 
   7377     if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) {
   7378         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7379                   (BSL_META_U(unit,
   7380                               "ERROR: gport 0x%x is not subport gport\n"),
   7381                    subport_port_gport));
   7382         return BCM_E_PARAM;
   7383     }
   7384 
   7385     if ((soc_feature(unit, soc_feature_linkphy_coe) &&
   7386         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) ||
   7387         (soc_feature(unit, soc_feature_subtag_coe) &&
   7388         _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) ||
   7389         (soc_feature(unit, soc_feature_general_cascade) &&
   7390         _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport))) {
   7391         BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(
   7392                                 unit, subport_port_gport, modid, port));
   7393     } else if (soc_feature(unit, soc_feature_subport_enhanced)) {
   7394 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3)
   7395         return _bcm_tr2_subport_port_resolve(unit,subport_port_gport,
   7396                                              modid, port, trunk_id, id);
   7397 #endif /* defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) */
   7398     } else if (soc_feature(unit, soc_feature_subport)) {
   7399 #if defined (BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
   7400         return _bcm_tr_subport_port_resolve(unit, subport_port_gport,
   7401                                             modid, port, trunk_id, id);
   7402 #endif
   7403     }
   7404     return BCM_E_NONE;
   7405 }
   7406 
   7407 int bcm_kt2_subport_pp_port_s1_index_get(int unit,
   7408                                          bcm_port_t pp_port,
   7409                                          int *s1_index)
   7410 {
   7411     int rv = BCM_E_NONE;
   7412 #if defined BCM_METROLITE_SUPPORT
   7413     soc_info_t *si = &SOC_INFO(unit);
   7414     soc_port_t port;
   7415     int i = 0, index = 0, found = 0;
   7416 
   7417     /* Retreive s1 index from provided pp port */
   7418     for (port = 0 ; port < ML_MAX_LOGICAL_PORTS; port ++) {
   7419         index = 0;
   7420         SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, port), i) {
   7421             index++;
   7422             if (pp_port == i) {
   7423                 found = 1;
   7424                 break;
   7425             }
   7426         }
   7427         if (found) {
   7428             break;
   7429         }
   7430     }
   7431 
   7432     if (found) {
   7433         *s1_index = si->port_subport_base[port] + (index -1);
   7434         return rv;
   7435     } else {
   7436         rv = BCM_E_NOT_FOUND; 
   7437     }
   7438 #endif
   7439 
   7440     *s1_index = -1;
   7441     return rv;
   7442 }
   7443 
   7444 /*
   7445  * Function:
   7446  *      bcm_kt2_subport_pp_port_subport_info_get
   7447  * Purpose:
   7448  *      Get physical port number and port_type (LinkPHY/SubTag/General), SubTag/Device internal
   7449  *      stream IDs for given pp_port.
   7450  *      If subport_port and group are not configured for the pp_port the port number
   7451  *      and type are returned as -1.
   7452  * Returns
   7453  *      BCM_E_XXX
   7454  */
   7455 
   7456 int bcm_kt2_subport_pp_port_subport_info_get(int unit,
   7457                               bcm_port_t pp_port,
   7458                               _bcm_kt2_subport_info_t *subport_info)
   7459 {
   7460     bcm_gport_t subport_port;
   7461     int rv = BCM_E_NONE, i = 0;
   7462     uint16 dev_int_stream_id_base = 0, ext_stream_id_base = 0, int_stream_id = 0;
   7463     bcm_subport_config_t subport_port_config;
   7464     int pp_port_index_min = SOC_INFO(unit).pp_port_index_min;
   7465     int pp_port_index_max = SOC_INFO(unit).pp_port_index_max;
   7466     int lp_block = 0, lp_index = 0;    
   7467     uint16 port_e_stream_id_base_adj = 0;
   7468     uint16 blk_int_stream_id = 0;
   7469 
   7470     if (subport_info == NULL) {
   7471         return BCM_E_MEMORY;
   7472     }
   7473 
   7474     sal_memset(subport_info, 0, sizeof(_bcm_kt2_subport_info_t));
   7475 
   7476     if ((pp_port < pp_port_index_min) ||
   7477         (pp_port > pp_port_index_max)) {
   7478         if (SOC_PORT_VALID(unit, pp_port)) {
   7479             subport_info->port = pp_port;
   7480             return BCM_E_NONE;
   7481         } else {
   7482             return BCM_E_PORT;
   7483         }
   7484     }
   7485 
   7486     if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) {
   7487         subport_info->port_type = _BCM_KT2_SUBPORT_TYPE_LINKPHY;
   7488     } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) {
   7489         subport_info->port_type = _BCM_KT2_SUBPORT_TYPE_SUBTAG;
   7490     } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, pp_port)) {
   7491         subport_info->port_type = _BCM_KT2_SUBPORT_TYPE_GENERAL;
   7492     } else {
   7493         return BCM_E_PORT;
   7494     }
   7495 
   7496     _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port);
   7497     _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, subport_info->port_type);
   7498 
   7499     rv = bcm_kt2_subport_port_get(unit, subport_port, &subport_port_config);
   7500     if (BCM_FAILURE(rv)) {
   7501         return rv;
   7502     }
   7503 
   7504     subport_info->port =
   7505         _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_port_config.group);
   7506 
   7507 
   7508 
   7509     if (subport_info->port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) {
   7510         subport_info->subtag = subport_port_config.pkt_vlan & 0xFFF;
   7511     } else if (subport_info->port_type == _BCM_KT2_SUBPORT_TYPE_GENERAL) {
   7512         /* Nothing to fill for general subport type */
   7513     } else {
   7514         rv = soc_linkphy_port_blk_idx_get(unit, subport_info->port,
   7515                                           &lp_block, &lp_index);
   7516         if (SOC_FAILURE(rv)) {
   7517             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7518                     (BSL_META_U(unit,
   7519                      "ERROR: LinkPHY block, index get failed for port %d\n"),
   7520                      subport_info->port));
   7521             return rv;
   7522         }
   7523         dev_int_stream_id_base = (lp_block)? 128: 0;
   7524 
   7525         subport_info->num_streams = subport_port_config.num_streams;
   7526 
   7527         rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, subport_info->port,
   7528                        &ext_stream_id_base);
   7529 
   7530         if (BCM_FAILURE(rv)) {
   7531             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7532                      (BSL_META_U(unit,
   7533                      "ERROR: Linkphy subport group external stream id "
   7534                      "base get failed for port %d - %d.\n"), 
   7535                      subport_info->port, ext_stream_id_base));
   7536             return rv;
   7537         }
   7538 
   7539         for (i = 0; i < subport_port_config.num_streams; i++) {
   7540             port_e_stream_id_base_adj =
   7541                 subport_port_config.stream_id_array[i] - ext_stream_id_base;
   7542     
   7543                 BCM_IF_ERROR_RETURN(
   7544                             _bcm_linkphy_port_rx_int_stream_map_port_get(unit,
   7545                                                  subport_info->port,
   7546                                                  port_e_stream_id_base_adj,
   7547                                                  &blk_int_stream_id));
   7548 
   7549             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   7550                      (BSL_META_U(unit,
   7551                      "Linkphy subport group external stream id "
   7552                      "base get failed for port %d - %d - int_stream_id(%d).\n"),
   7553                      subport_info->port, ext_stream_id_base, int_stream_id));
   7554 
   7555             subport_info->dev_int_stream_id[i] =
   7556                 blk_int_stream_id + dev_int_stream_id_base;
   7557         }
   7558     }
   7559 
   7560     return BCM_E_NONE;
   7561 
   7562 }
   7563 
   7564 /*
   7565  * Function:
   7566  *      bcm_kt2_subport_cleanup
   7567  * Purpose:
   7568  *      Delate all valid subport ports and all valid subport groups.
   7569         Also clean up software resources.
   7570  * Parameters:
   7571  *      unit      - Device Number
   7572  * Returns:
   7573  *      BCM_E_XXX
   7574  */
   7575 int
   7576 bcm_kt2_subport_cleanup(int unit)
   7577 {
   7578     int rv = BCM_E_NONE;
   7579     soc_info_t *si = &SOC_INFO(unit);
   7580 
   7581     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   7582 
   7583     if (soc_feature(unit, soc_feature_linkphy_coe)) {
   7584         if (BCM_PBMP_NOT_NULL(si->linkphy_pbm)) {
   7585             rv = _bcm_linkphy_subport_cleanup(unit);
   7586             if (SOC_FAILURE(rv)) {
   7587                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7588                          (BSL_META_U(unit,
   7589                          "ERROR: LinkPHY cleanup failed\n")));
   7590                 return rv;
   7591             }
   7592         }
   7593     }
   7594     if (soc_feature(unit, soc_feature_subtag_coe)) {
   7595         if (BCM_PBMP_NOT_NULL(si->subtag_allowed_pbm)) {
   7596             rv = _bcm_subtag_subport_cleanup(unit);
   7597             if (SOC_FAILURE(rv)) {
   7598                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7599                           (BSL_META_U(unit,
   7600                           "ERROR: SubTag cleanup failed\n")));
   7601                 return rv;
   7602             }
   7603         }
   7604     }
   7605     if (soc_feature(unit, soc_feature_general_cascade)) {
   7606         rv = _bcm_general_subport_cleanup(unit);
   7607         if (SOC_FAILURE(rv)) {
   7608             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7609                     (BSL_META_U(unit,
   7610                     "ERROR: General subport cleanup failed\n")));
   7611             return rv;
   7612         }
   7613     }
   7614 
   7615     bcm_kt2_subport_free_resource(unit);
   7616 
   7617     return BCM_E_NONE;
   7618 }
   7619 
   7620 /**
   7621  * Function:
   7622  *      bcm_kt2_subport_group_linkphy_config_get
   7623  * Purpose:
   7624  *      Get ALL or selective LinkPHY configuration attributes 
   7625  *      on a given port GPORT.
   7626  * Parameters:
   7627  * Parameters:
   7628  *      uint (IN) BCM device number
   7629  *      port (IN) port GPORT
   7630  *      linkphy_cfg (OUT) LinkPHY configuration 
   7631  * Returns:
   7632  *      BCM_E_xxx
   7633  * Notes:
   7634  *     When retrieving, if an error is returned then the entire contents of the 
   7635  *        linkphy_config structure are undefined.
   7636  */
   7637 
   7638 int 
   7639 bcm_kt2_subport_group_linkphy_config_get(int unit, 
   7640                              bcm_gport_t port, 
   7641                              bcm_subport_group_linkphy_config_t *linkphy_config)
   7642 {
   7643     int rv = BCM_E_NONE;
   7644     uint32 regval = 0;
   7645     uint32 header_mode = 0;
   7646     uint32 mac_addr[2] = {0, 0};
   7647     uint64 rval64, data;
   7648     uint16 base_stream_id = 0;
   7649     soc_reg_t reg;
   7650     int base_stream_id_max = 0;
   7651     int ne_mac_check = 0, fe_mac_check = 0, dfc_destmac_check = 0;
   7652     int dfc_opcode_check = 0, dfc_time_check = 0;
   7653     soc_info_t *si = &SOC_INFO(unit);
   7654     int max_streams = si->lp_streams_per_slice_max;
   7655 
   7656     if (!soc_feature(unit, soc_feature_linkphy_coe)) {
   7657         return BCM_E_UNAVAIL;
   7658     }
   7659 
   7660     if (linkphy_config == NULL) {
   7661         return BCM_E_PARAM;
   7662     }
   7663 
   7664     if (!BCM_PBMP_MEMBER(si->linkphy_pbm, port)) {
   7665         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7666                   (BSL_META_U(unit,
   7667                               "ERROR: Invalid port %d for LinkPHY config get\n"),
   7668                    port));
   7669         return BCM_E_PORT;
   7670     }
   7671 
   7672     sal_memset(linkphy_config, 0, sizeof(bcm_subport_group_linkphy_config_t));
   7673 
   7674     reg = RXLP_PORT_STREAM_ID_BASEr;
   7675     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7676         base_stream_id_max = _BCM_KT2_LINKPHY_STREAMS_MAX -
   7677                             max_streams;
   7678 
   7679         BCM_IF_ERROR_RETURN(
   7680             READ_RXLP_PORT_STREAM_ID_BASEr(unit, port, &regval));
   7681         base_stream_id = soc_reg_field_get(unit, reg, regval, BASEf);
   7682         if ((base_stream_id % 8) || (base_stream_id > base_stream_id_max)) {
   7683             linkphy_config->action_mask &= ~BCM_SUBPORT_LINKPHY_BASE_STREAM_ID;
   7684         } else {
   7685             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_BASE_STREAM_ID;
   7686             linkphy_config->base_stream_id = base_stream_id;
   7687         }
   7688     }
   7689 
   7690     reg = RXLP_PORT_LP_MODE_CONTROLr;
   7691     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7692         BCM_IF_ERROR_RETURN(
   7693             READ_RXLP_PORT_LP_MODE_CONTROLr(unit, port, &regval));
   7694         header_mode = soc_reg_field_get(unit, reg, regval, HEADER_MODEf);
   7695         if ((header_mode == bcmSubportLinkphyHeaderModeEthAdapt) ||
   7696             (header_mode == bcmSubportLinkphyHeaderModeTciLength)) {
   7697             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_HEADER_MODE;
   7698             linkphy_config->header_mode = header_mode;
   7699         }
   7700     }
   7701 
   7702     COMPILER_64_ZERO(rval64);
   7703     COMPILER_64_ZERO(data);
   7704     reg = RXLP_PORT_NEAR_END_MAC_ADDRr;
   7705     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7706         BCM_IF_ERROR_RETURN(
   7707             READ_RXLP_PORT_NEAR_END_MAC_ADDRr(unit, port, &rval64));
   7708         data = soc_reg64_field_get(unit, reg, rval64, CHECK_ENABLEf);
   7709         COMPILER_64_TO_32_LO(regval, data);
   7710         if ((ne_mac_check = (regval & 0x1))) {
   7711             linkphy_config->rx_check_flags |=
   7712                 BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC_CHECK;
   7713         }
   7714     }
   7715 
   7716     COMPILER_64_ZERO(rval64);
   7717     COMPILER_64_ZERO(data);
   7718     reg = RXLP_PORT_FAR_END_MAC_ADDRr;
   7719     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7720         BCM_IF_ERROR_RETURN(
   7721             READ_RXLP_PORT_FAR_END_MAC_ADDRr(unit, port, &rval64));
   7722         data = soc_reg64_field_get(unit, reg, rval64, CHECK_ENABLEf);
   7723         COMPILER_64_TO_32_LO(regval, data);
   7724         if ((fe_mac_check = (regval & 0x1))) {
   7725             linkphy_config->rx_check_flags |=
   7726                 BCM_SUBPORT_LINKPHY_RX_FAREND_MAC_CHECK;
   7727         }
   7728     }
   7729 
   7730     COMPILER_64_ZERO(rval64);
   7731     COMPILER_64_ZERO(data);
   7732     reg = RXLP_PORT_DFC_DESTINATION_MAC_ADDRr;
   7733     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7734         BCM_IF_ERROR_RETURN(
   7735             READ_RXLP_PORT_DFC_DESTINATION_MAC_ADDRr(unit, port, &rval64));
   7736         data = soc_reg64_field_get(unit, reg, rval64, CHECK_ENABLEf);
   7737         COMPILER_64_TO_32_LO(regval, data);
   7738         if ((dfc_destmac_check = (regval & 0x1))) {
   7739             linkphy_config->rx_check_flags |=
   7740                 BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC_CHECK;
   7741         }
   7742     }
   7743 
   7744     reg = RXLP_PORT_DFC_OPCODEr;
   7745     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7746         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_OPCODEr(unit, port, &regval));
   7747         if ((dfc_opcode_check =
   7748             soc_reg_field_get(unit, reg, regval, CHECK_ENABLEf))) {
   7749             linkphy_config->rx_check_flags |=
   7750                 BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE_CHECK;
   7751         }
   7752     }
   7753 
   7754     reg = RXLP_PORT_DFC_TIMEr;
   7755     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7756         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, &regval));
   7757         if ((dfc_time_check =
   7758             soc_reg_field_get(unit, reg, regval, CHECK_ENABLEf))) {
   7759             linkphy_config->rx_check_flags |=
   7760                 BCM_SUBPORT_LINKPHY_RX_DFC_TIME_CHECK;
   7761         }
   7762     }
   7763 
   7764     if (ne_mac_check || fe_mac_check || dfc_destmac_check ||
   7765         dfc_opcode_check || dfc_time_check) {
   7766         linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_CHECK_FLAGS;
   7767     }
   7768 
   7769     reg = RXLP_PORT_VLAN_TPIDr;
   7770     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7771         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_VLAN_TPIDr(unit, port, &regval));
   7772         if ((linkphy_config->rx_vlan_tpid = 
   7773                 soc_reg_field_get(unit, reg, regval, VLAN_TPIDf))) {
   7774             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_VLAN_TPID;
   7775         }
   7776     }
   7777 
   7778     reg = RXLP_PORT_NEAR_END_MAC_ADDRr;
   7779     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7780         BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port,
   7781             RXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf,
   7782             linkphy_config->rx_nearend_mac));
   7783         SAL_MAC_ADDR_TO_UINT32(linkphy_config->rx_nearend_mac, mac_addr);
   7784         if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) {
   7785             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC;
   7786         }
   7787     }
   7788 
   7789     reg = RXLP_PORT_FAR_END_MAC_ADDRr;
   7790     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7791         BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port,
   7792             RXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf,
   7793             linkphy_config->rx_farend_mac));
   7794         SAL_MAC_ADDR_TO_UINT32(linkphy_config->rx_farend_mac, mac_addr);
   7795         if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) {
   7796             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_FAREND_MAC;
   7797         }
   7798     }
   7799 
   7800     reg = RXLP_PORT_DFC_DESTINATION_MAC_ADDRr;
   7801     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7802         BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port,
   7803             RXLP_PORT_DFC_DESTINATION_MAC_ADDRr, MAC_ADDRf,
   7804             linkphy_config->rx_dfc_dest_mac));
   7805         SAL_MAC_ADDR_TO_UINT32(linkphy_config->rx_dfc_dest_mac, mac_addr);
   7806         if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) {
   7807             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC;
   7808         }
   7809     }
   7810 
   7811     reg = RXLP_PORT_DFC_OPCODEr;
   7812     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7813         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_OPCODEr(unit, port, &regval));
   7814         if ((linkphy_config->rx_dfc_opcode = 
   7815                 soc_reg_field_get(unit, reg, regval, OPCODEf))) {
   7816             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE;
   7817         }
   7818     }
   7819 
   7820     reg = RXLP_PORT_DFC_TIMEr;
   7821     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7822         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, &regval));
   7823         if ((linkphy_config->rx_dfc_time = 
   7824                 soc_reg_field_get(unit, reg, regval, DFC_TIMEf))) {
   7825             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_TIME;
   7826         }
   7827     }
   7828 
   7829     reg = RXLP_PORT_DFC_MAC_TYPEr;
   7830     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7831         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_MAC_TYPEr(unit, port, &regval));
   7832         if ((linkphy_config->rx_dfc_mac_type =
   7833                 soc_reg_field_get(unit, reg, regval, MAC_TYPEf))) {
   7834             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_MAC_TYPE;
   7835         }
   7836     }
   7837 
   7838     reg = TXLP_PORT_VLAN_TPIDr;
   7839     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7840         BCM_IF_ERROR_RETURN(READ_TXLP_PORT_VLAN_TPIDr(unit, port, &regval));
   7841         if ((linkphy_config->tx_vlan_tpid = 
   7842                 soc_reg_field_get(unit, reg, regval, VLAN_TPIDf))) {
   7843             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_TX_VLAN_TPID;
   7844         }
   7845     }
   7846 
   7847     reg = TXLP_PORT_NEAR_END_MAC_ADDRr;
   7848     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7849         BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port,
   7850             TXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf,
   7851             linkphy_config->tx_nearend_mac));
   7852         SAL_MAC_ADDR_TO_UINT32(linkphy_config->tx_nearend_mac, mac_addr);
   7853         if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) {
   7854             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_TX_NEAREND_MAC;
   7855         }
   7856     }
   7857 
   7858     reg = TXLP_PORT_FAR_END_MAC_ADDRr;
   7859     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7860         BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port,
   7861             TXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf,
   7862             linkphy_config->tx_farend_mac));
   7863         SAL_MAC_ADDR_TO_UINT32(linkphy_config->tx_farend_mac, mac_addr);
   7864         if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) {
   7865             linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_TX_FAREND_MAC;
   7866         }
   7867     }
   7868 
   7869 
   7870     reg = TXLP_PORT_LP_MODE_CONTROLr;
   7871     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7872         BCM_IF_ERROR_RETURN(
   7873             READ_TXLP_PORT_LP_MODE_CONTROLr(unit, port, &regval));
   7874         if (soc_reg_field_get(unit, reg, regval, PENULTIMATE_MODEf)) {
   7875             linkphy_config->action_mask |= 
   7876                 BCM_SUBPORT_LINKPHY_TX_PENULTIMATE_MODE;
   7877         }
   7878     }
   7879 
   7880     return rv;
   7881 }
   7882 
   7883 /**
   7884  * Function:
   7885  *      bcm_kt2_subport_group_linkphy_config_set
   7886  * Purpose:
   7887  *      Set ALL or selective LinkPHY configuration attributes 
   7888  *      on a given port GPORT.
   7889  * Parameters:
   7890  *      uint (IN) BCM device number
   7891  *      port (IN) port GPORT
   7892  *      linkphy_cfg (IN) LinkPHY configuration 
   7893  * Returns:
   7894  *      BCM_E_xxx
   7895  * Notes:
   7896  *      The 'linkphy_config.action_mask' field is used to indicate if ALL or 
   7897  *              selective attributes will be set or get.
   7898  *      While setting or restoring LinkPHY port configuration, if the call
   7899  *              returns an error then the port state is undefined.
   7900  *      Each field in linkphy_config structure has a corresponding mask bit
   7901  *              to set that value during the execution of this functions.
   7902  *              The OR of all BCM_SUBPORT_LINKPHY_xxx masks
   7903  *              should be stored in the linkphy_config.action_mask field.
   7904  *      The 'linkphy_config.base_stream_id' member should be a multiple
   7905  *              of 8 and <=896 for bcm5645x device.
   7906  *              LinkPHY fragment headers with stream ID range 
   7907  *              {base_stream_id, base_stream_id+127} are valid for the gport.
   7908  *              Fragments with stream id outside this range will be dropped.
   7909  *              It is recommended to configure the 'base_stream_id' first
   7910  *              on a given port before adding LinkPHY subports to the port
   7911  *              using bcm_subport_port_add() API.
   7912  *      The 'linkphy_config.rx_check_flags' member is used to enable LinkPHY 
   7913  *              fragment header parameter checks on received fragments.
   7914  */
   7915 
   7916 int
   7917 bcm_kt2_subport_group_linkphy_config_set(int unit,
   7918                              bcm_gport_t port,
   7919                              bcm_subport_group_linkphy_config_t *linkphy_config)
   7920 {
   7921     int rv = BCM_E_NONE;
   7922     uint32 mask = 0, regval = 0, rx_check_flags = 0;
   7923     uint64 rval64, data;
   7924     uint16 base_stream_id = 0;
   7925     soc_reg_t reg;
   7926     int base_stream_id_max = 0;
   7927     soc_info_t *si = &SOC_INFO(unit);
   7928     int max_streams = si->lp_streams_per_slice_max;
   7929 
   7930     COMPILER_64_ZERO(rval64);
   7931     COMPILER_64_ZERO(data);
   7932 
   7933     if (!soc_feature(unit, soc_feature_linkphy_coe)) {
   7934         return BCM_E_UNAVAIL;
   7935     }
   7936 
   7937     if (!BCM_PBMP_MEMBER(si->linkphy_pbm, port)) {
   7938         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7939                   (BSL_META_U(unit,
   7940                               "ERROR: Invalid port %d for LinkPHY config set\n"),
   7941                    port));
   7942         return BCM_E_PORT;
   7943     }
   7944 
   7945     mask = linkphy_config->action_mask;
   7946 
   7947     if (mask & BCM_SUBPORT_LINKPHY_BASE_STREAM_ID) {
   7948         base_stream_id = linkphy_config->base_stream_id;
   7949 
   7950         base_stream_id_max = _BCM_KT2_LINKPHY_STREAMS_MAX -
   7951                             max_streams;
   7952 
   7953         if ((base_stream_id % 8) || (base_stream_id > base_stream_id_max)) {
   7954             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7955                       (BSL_META_U(unit,
   7956                                   "ERROR:base stream id should be "
   7957                                    "multiple of 8 and <= %d\n"), base_stream_id_max));
   7958             return BCM_E_PARAM;
   7959         }
   7960 
   7961         reg = RXLP_PORT_STREAM_ID_BASEr;
   7962         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7963             regval = 0;
   7964             BCM_IF_ERROR_RETURN(
   7965                 READ_RXLP_PORT_STREAM_ID_BASEr(unit, port, &regval));
   7966             soc_reg_field_set(unit, reg, &regval, BASEf, base_stream_id);
   7967             BCM_IF_ERROR_RETURN(
   7968                 WRITE_RXLP_PORT_STREAM_ID_BASEr(unit, port, regval));
   7969         }
   7970 
   7971         /* Write DFC MSG START OFFSET based on external stream ID base */
   7972         reg = RXLP_DFC_MSG_START_BYTE_OFFSETr;
   7973         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   7974             regval = 0;
   7975             BCM_IF_ERROR_RETURN(
   7976                 READ_RXLP_DFC_MSG_START_BYTE_OFFSETr(unit, port, &regval));
   7977             /* Byte offset. For example, if external stream id base is say 40,
   7978                40th bit should be the offset. Since it is provided in bytes,
   7979                40/8 will be equal to 5 bytes. */
   7980             soc_reg_field_set(unit, reg, &regval, OFFSETf, (base_stream_id/8));
   7981             BCM_IF_ERROR_RETURN(
   7982                 WRITE_RXLP_DFC_MSG_START_BYTE_OFFSETr(unit, port, regval));
   7983         }
   7984     }
   7985 
   7986     if (mask & BCM_SUBPORT_LINKPHY_HEADER_MODE) {
   7987         if ((linkphy_config->header_mode !=
   7988                 bcmSubportLinkphyHeaderModeEthAdapt) &&
   7989             (linkphy_config->header_mode !=
   7990                 bcmSubportLinkphyHeaderModeTciLength)){
   7991             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   7992                       (BSL_META_U(unit,
   7993                                   "ERROR: invalid LinkPHY header mode %d\n"),
   7994                        linkphy_config->header_mode));
   7995             return BCM_E_PARAM;
   7996         }
   7997 #ifdef BCM_KATANA2_SUPPORT
   7998         if (SOC_IS_KATANA2(unit) &&
   7999             (linkphy_config->header_mode ==
   8000                 bcmSubportLinkphyHeaderModeTciLength)){
   8001             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8002                       (BSL_META_U(unit,
   8003                                   "ERROR: LinkPHY TCI+Length header mode is not supported.\n")));
   8004             return BCM_E_PARAM;
   8005         }
   8006 #endif
   8007 
   8008         reg = RXLP_PORT_LP_MODE_CONTROLr;
   8009         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8010             regval = 0;
   8011             BCM_IF_ERROR_RETURN(
   8012                 READ_RXLP_PORT_LP_MODE_CONTROLr(unit, port, &regval));
   8013             soc_reg_field_set(unit, reg, &regval,
   8014                 HEADER_MODEf, linkphy_config->header_mode);
   8015             BCM_IF_ERROR_RETURN(
   8016                 WRITE_RXLP_PORT_LP_MODE_CONTROLr(unit, port, regval));
   8017         }
   8018     }
   8019 
   8020     if (mask & BCM_SUBPORT_LINKPHY_RX_CHECK_FLAGS) {
   8021         rx_check_flags = linkphy_config->rx_check_flags;
   8022 
   8023         reg = RXLP_PORT_NEAR_END_MAC_ADDRr;
   8024         COMPILER_64_ZERO(rval64);
   8025         BCM_IF_ERROR_RETURN(
   8026             READ_RXLP_PORT_NEAR_END_MAC_ADDRr(unit, port, &rval64));
   8027         COMPILER_64_ZERO(data);
   8028         COMPILER_64_SET(data, 0,
   8029           ((rx_check_flags & BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC_CHECK) ? 1: 0));
   8030         soc_reg64_field_set(unit, reg, &rval64, CHECK_ENABLEf, data);
   8031         BCM_IF_ERROR_RETURN(
   8032             WRITE_RXLP_PORT_NEAR_END_MAC_ADDRr(unit, port, rval64));
   8033 
   8034         reg = RXLP_PORT_FAR_END_MAC_ADDRr;
   8035         COMPILER_64_ZERO(rval64);
   8036         BCM_IF_ERROR_RETURN(
   8037             READ_RXLP_PORT_FAR_END_MAC_ADDRr(unit, port, &rval64));
   8038         COMPILER_64_ZERO(data);
   8039         COMPILER_64_SET(data, 0,
   8040           ((rx_check_flags & BCM_SUBPORT_LINKPHY_RX_FAREND_MAC_CHECK) ? 1: 0));
   8041         soc_reg64_field_set(unit, reg, &rval64, CHECK_ENABLEf, data);
   8042         BCM_IF_ERROR_RETURN(
   8043             WRITE_RXLP_PORT_FAR_END_MAC_ADDRr(unit, port, rval64));
   8044 
   8045         reg = RXLP_PORT_DFC_DESTINATION_MAC_ADDRr;
   8046         COMPILER_64_ZERO(rval64);
   8047         BCM_IF_ERROR_RETURN(
   8048             READ_RXLP_PORT_DFC_DESTINATION_MAC_ADDRr(unit, port, &rval64));
   8049         COMPILER_64_ZERO(data);
   8050         COMPILER_64_SET(data, 0, ((rx_check_flags &
   8051                         BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC_CHECK) ? 1: 0));
   8052         soc_reg64_field_set(unit, reg, &rval64, CHECK_ENABLEf, data);
   8053         BCM_IF_ERROR_RETURN(
   8054             WRITE_RXLP_PORT_DFC_DESTINATION_MAC_ADDRr(unit, port, rval64));
   8055 
   8056         reg = RXLP_PORT_DFC_OPCODEr;
   8057         regval = 0;
   8058         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_OPCODEr(unit, port, &regval));
   8059         soc_reg_field_set(unit, reg, &regval, CHECK_ENABLEf,
   8060             (rx_check_flags & BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE_CHECK) ? 1 : 0);
   8061         BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_DFC_OPCODEr(unit, port, regval));
   8062 
   8063         reg = RXLP_PORT_DFC_TIMEr;
   8064         regval = 0;
   8065         BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, &regval));
   8066         soc_reg_field_set(unit, reg, &regval, CHECK_ENABLEf,
   8067             (rx_check_flags & BCM_SUBPORT_LINKPHY_RX_DFC_TIME_CHECK) ? 1 : 0);
   8068         BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_DFC_TIMEr(unit, port, regval));
   8069     }
   8070 
   8071     if (mask & BCM_SUBPORT_LINKPHY_RX_VLAN_TPID) {
   8072         reg = RXLP_PORT_VLAN_TPIDr;
   8073         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8074             regval = 0;
   8075             BCM_IF_ERROR_RETURN(READ_RXLP_PORT_VLAN_TPIDr(unit, port, &regval));
   8076             soc_reg_field_set(unit, reg, &regval, VLAN_TPIDf,
   8077                               linkphy_config->rx_vlan_tpid);
   8078             BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_VLAN_TPIDr(unit, port, regval));
   8079         }
   8080     }
   8081 
   8082     if (mask & BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC) {
   8083         rv = _bcm_linkphy_reg_mac_addr_set(unit, port,
   8084                 RXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf,
   8085                 linkphy_config->rx_nearend_mac);
   8086         if (BCM_FAILURE(rv)) {
   8087             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8088                       (BSL_META_U(unit,
   8089                                   "ERROR: LinkPHY RX nearend MAC set failed\n")));
   8090             return rv;
   8091         }
   8092     }
   8093 
   8094     if (mask & BCM_SUBPORT_LINKPHY_RX_FAREND_MAC) {
   8095         rv = _bcm_linkphy_reg_mac_addr_set(unit, port,
   8096                 RXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf,
   8097                 linkphy_config->rx_farend_mac);
   8098         if (BCM_FAILURE(rv)) {
   8099             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8100                       (BSL_META_U(unit,
   8101                                   "ERROR: LinkPHY RX farend MAC set failed\n")));
   8102             return rv;
   8103         }
   8104     }
   8105 
   8106     if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC) {
   8107         rv = _bcm_linkphy_reg_mac_addr_set(unit, port,
   8108                 RXLP_PORT_DFC_DESTINATION_MAC_ADDRr, MAC_ADDRf,
   8109                 linkphy_config->rx_dfc_dest_mac);
   8110         if (BCM_FAILURE(rv)) {
   8111             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8112                       (BSL_META_U(unit,
   8113                                   "ERROR: LinkPHY RX DFC dest MAC set failed\n")));
   8114             return rv;
   8115         }
   8116     }
   8117 
   8118     if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE) {
   8119         reg = RXLP_PORT_DFC_OPCODEr;
   8120         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8121             regval = 0;
   8122             BCM_IF_ERROR_RETURN(
   8123                 READ_RXLP_PORT_DFC_OPCODEr(unit, port, &regval));
   8124             soc_reg_field_set(unit, reg, &regval, OPCODEf,
   8125                               linkphy_config->rx_dfc_opcode);
   8126             BCM_IF_ERROR_RETURN(
   8127                 WRITE_RXLP_PORT_DFC_OPCODEr(unit, port, regval));
   8128         }
   8129     }
   8130 
   8131     if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_TIME) {
   8132         reg = RXLP_PORT_DFC_TIMEr;
   8133         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8134             regval = 0;
   8135             BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, &regval));
   8136             soc_reg_field_set(unit, reg, &regval, DFC_TIMEf,
   8137                               linkphy_config->rx_dfc_time);
   8138             BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_DFC_TIMEr(unit, port, regval));
   8139         }
   8140     }
   8141 
   8142     if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_MAC_TYPE) {
   8143         reg = RXLP_PORT_DFC_MAC_TYPEr;
   8144         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8145             regval = 0;
   8146             BCM_IF_ERROR_RETURN(
   8147                 READ_RXLP_PORT_DFC_MAC_TYPEr(unit, port, &regval));
   8148             soc_reg_field_set(unit, reg, &regval, MAC_TYPEf,
   8149                               linkphy_config->rx_dfc_mac_type);
   8150             BCM_IF_ERROR_RETURN(
   8151                 WRITE_RXLP_PORT_DFC_MAC_TYPEr(unit, port, regval));
   8152         }
   8153     }
   8154 
   8155     if (mask & BCM_SUBPORT_LINKPHY_TX_VLAN_TPID) {
   8156         reg = TXLP_PORT_VLAN_TPIDr;
   8157         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8158             regval = 0;
   8159             BCM_IF_ERROR_RETURN(
   8160                 READ_TXLP_PORT_VLAN_TPIDr(unit, port, &regval));
   8161             soc_reg_field_set(unit, reg, &regval, VLAN_TPIDf,
   8162                               linkphy_config->tx_vlan_tpid);
   8163             BCM_IF_ERROR_RETURN(
   8164                 WRITE_TXLP_PORT_VLAN_TPIDr(unit, port, regval));
   8165         }
   8166     }
   8167 
   8168     if (mask & BCM_SUBPORT_LINKPHY_TX_NEAREND_MAC) {
   8169         rv = _bcm_linkphy_reg_mac_addr_set(unit, port,
   8170                 TXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf,
   8171                 linkphy_config->tx_nearend_mac);
   8172         if (BCM_FAILURE(rv)) {
   8173             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8174                       (BSL_META_U(unit,
   8175                                   "ERROR: LinkPHY TX nearend MAC set failed\n")));
   8176             return rv;
   8177         }
   8178     }
   8179 
   8180     if (mask & BCM_SUBPORT_LINKPHY_TX_FAREND_MAC) {
   8181         rv = _bcm_linkphy_reg_mac_addr_set(unit, port,
   8182                 TXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf,
   8183                 linkphy_config->tx_farend_mac);
   8184         if (BCM_FAILURE(rv)) {
   8185             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8186                       (BSL_META_U(unit,
   8187                                   "ERROR: LinkPHY TX farend MAC set failed\n")));
   8188             return rv;
   8189         }
   8190     }
   8191 
   8192     reg = TXLP_PORT_LP_MODE_CONTROLr;
   8193     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8194         regval = 0;
   8195         BCM_IF_ERROR_RETURN(
   8196             READ_TXLP_PORT_LP_MODE_CONTROLr(unit, port, &regval));
   8197         soc_reg_field_set(unit, reg, &regval, PENULTIMATE_MODEf,
   8198             (mask & BCM_SUBPORT_LINKPHY_TX_PENULTIMATE_MODE) ? 1 : 0);
   8199         BCM_IF_ERROR_RETURN(
   8200             WRITE_TXLP_PORT_LP_MODE_CONTROLr(unit, port, regval));
   8201     }
   8202 
   8203     /*
   8204      * If DFC dest mac is 0x0180c2000001 and DFC Mac Type is 0x8808
   8205      * the enable RX_PASS_PAUSE in XMAC_PAUSE_CTR to enable
   8206      * DFC frames to bypass the MAC.
   8207      * On Saber2 enable PASS_PAUSE_FRAME in XPORT_CONFIG to enable
   8208      * DFC frames to bypass the MAC.
   8209      */
   8210     if ((mask & BCM_SUBPORT_LINKPHY_RX_DFC_MAC_TYPE) &&
   8211         (mask & BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC)) {
   8212         if ((linkphy_config->rx_dfc_mac_type == 0x8808) &&
   8213             (sal_strncmp((char *)linkphy_config->rx_dfc_dest_mac,
   8214                         "01:80:c2:00:00:01",
   8215                         sal_strlen((char *)linkphy_config->rx_dfc_dest_mac)))) {
   8216 #if defined(BCM_SABER2_SUPPORT)
   8217             if (SOC_IS_SABER2(unit)) {
   8218                 reg = XPORT_CONFIGr;
   8219                     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8220                         uint32 rval;
   8221 
   8222                         SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &rval));
   8223                         soc_reg_field_set(unit, reg, &rval, PASS_PAUSE_FRAMEf, 1);
   8224                         SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval));
   8225                     }
   8226 
   8227             } else
   8228 #endif 
   8229             {
   8230                 reg = XMAC_PAUSE_CTRLr;
   8231                 if (SOC_REG_PORT_VALID(unit, reg, port)) {
   8232                     uint64 rval;
   8233 
   8234                     SOC_IF_ERROR_RETURN(READ_XMAC_PAUSE_CTRLr(unit, port, &rval));
   8235                     soc_reg64_field32_set(unit, reg, &rval, RX_PASS_PAUSEf, 1);
   8236                     SOC_IF_ERROR_RETURN(WRITE_XMAC_PAUSE_CTRLr(unit, port, rval));
   8237                 }
   8238             }
   8239         }
   8240     }
   8241 
   8242     return rv;
   8243 }
   8244 
   8245 /*
   8246  * Function:
   8247  *      bcm_kt2_subport_counter_init
   8248  * Purpose:
   8249  *      Initialize the subport counters
   8250  * Parameters:
   8251  *      unit - Device Number
   8252  * Returns:
   8253  *      BCM_E_XXX
   8254  */
   8255 int
   8256 bcm_kt2_subport_counter_init(int unit)
   8257 {
   8258     int rv = BCM_E_NONE;
   8259     if (soc_feature(unit, soc_feature_linkphy_coe)) {
   8260         rv = _bcm_linkphy_subport_counter_init(unit);
   8261         if (SOC_FAILURE(rv)) {
   8262             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8263                       (BSL_META_U(unit,
   8264                                   "ERROR: subport counter init failed\n")));
   8265             return rv;
   8266         }
   8267     }
   8268     if (soc_feature(unit, soc_feature_subtag_coe)) {
   8269         
   8270     }
   8271     return rv;
   8272 }
   8273 
   8274 /*
   8275  * Function:
   8276  *      bcm_kt2_subport_counter_cleanup
   8277  * Purpose:
   8278  *      cleanup the subport counters
   8279  * Parameters:
   8280  *      unit      - Device Number
   8281  * Returns:
   8282  *      BCM_E_XXX
   8283  */
   8284 int
   8285 bcm_kt2_subport_counter_cleanup(int unit)
   8286 {
   8287     int rv = BCM_E_NONE;
   8288     if (soc_feature(unit, soc_feature_linkphy_coe)) {
   8289         rv = _bcm_linkphy_subport_counter_cleanup(unit);
   8290         if (SOC_FAILURE(rv)) {
   8291             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8292                       (BSL_META_U(unit,
   8293                                   "ERROR: subport counter cleanup failed\n")));
   8294             return rv;
   8295         }
   8296     }
   8297     if (soc_feature(unit, soc_feature_subtag_coe)) {
   8298         
   8299     }
   8300     return rv;
   8301 }
   8302 
   8303 /*
   8304  * Function:
   8305  *      bcm_kt2_subport_port_stat_set
   8306  * Purpose:
   8307  *      Set the statistics value for a given subport port and statistics type
   8308  * Parameters:
   8309  *      unit      - (IN) Device Number
   8310  *      port      - (IN) subport port
   8311  *      stream_id - (IN) stream ID array index (if LinkPHY subport)
   8312  *      stat_type - (IN) statistics type
   8313  *      val       - (IN) value
   8314  * Returns:
   8315  *      BCM_E_XXX
   8316  */
   8317 int
   8318 bcm_kt2_subport_port_stat_set(
   8319     int unit,
   8320     bcm_gport_t port,
   8321     int stream_id,
   8322     bcm_subport_stat_t stat_type,
   8323     uint64 val)
   8324 {
   8325     int rv = BCM_E_NONE;
   8326 
   8327     /* Parameter validation */
   8328     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   8329 
   8330     if (!BCM_GPORT_IS_SUBPORT_PORT(port)) {
   8331         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8332                   (BSL_META_U(unit,
   8333                               "ERROR: gport 0x%x is not subport port gport\n"),
   8334                    port));
   8335         return BCM_E_PARAM;
   8336     }
   8337 
   8338     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   8339         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, port)) {
   8340         _BCM_KT2_SUBPORT_LOCK(unit);
   8341         rv = _bcm_linkphy_subport_port_stat_set(unit,
   8342                 port, stream_id, stat_type, val);
   8343         if (SOC_FAILURE(rv)) {
   8344             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8345                       (BSL_META_U(unit,
   8346                                   "ERROR: Subport 0x%x stat set failed. rv = %d(%s)\n"),
   8347                        port, rv, soc_errmsg(rv)));
   8348             _BCM_KT2_SUBPORT_UNLOCK(unit);
   8349             return rv;
   8350         }
   8351         _BCM_KT2_SUBPORT_UNLOCK(unit);
   8352     } else {
   8353         rv = BCM_E_UNAVAIL;
   8354     }
   8355 
   8356     return rv;
   8357 
   8358 }
   8359 
   8360 /*
   8361  * Function:
   8362  *      bcm_kt2_subport_port_stat_get
   8363  * Purpose:
   8364  *      Get the statistics value for a given subport port and statistics type
   8365  * Parameters:
   8366  *      unit      - (IN) Device Number
   8367  *      port      - (IN) subport port
   8368  *      stream_id - (IN) stream ID array index (if LinkPHY subport)
   8369  *      stat_type - (IN) statistics type
   8370  *      val       - (OUT) value
   8371  * Returns:
   8372  *      BCM_E_XXX
   8373  */
   8374 int
   8375 bcm_kt2_subport_port_stat_get(
   8376     int unit,
   8377     bcm_gport_t port,
   8378     int stream_id,
   8379     bcm_subport_stat_t stat_type,
   8380     uint64 *val)
   8381 {
   8382     int rv = BCM_E_NONE;
   8383 
   8384     /* Parameter validation */
   8385     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   8386 
   8387     if (!BCM_GPORT_IS_SUBPORT_PORT(port)) {
   8388         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8389                   (BSL_META_U(unit,
   8390                               "ERROR: gport 0x%x is not subport port gport\n"),
   8391                    port));
   8392         return BCM_E_PARAM;
   8393     }
   8394 
   8395     if (soc_feature(unit, soc_feature_linkphy_coe) &&
   8396         _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, port)) {
   8397 
   8398         _BCM_KT2_SUBPORT_LOCK(unit);
   8399 
   8400         rv = _bcm_linkphy_subport_port_stat_get(unit,
   8401                 port, stream_id, stat_type, val);
   8402         if (SOC_FAILURE(rv)) {
   8403             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8404                       (BSL_META_U(unit,
   8405                                   "ERROR: Subport 0x%x stat get failed. rv = %d(%s)\n"),
   8406                        port, rv, soc_errmsg(rv)));
   8407             _BCM_KT2_SUBPORT_UNLOCK(unit);
   8408             return rv;
   8409         }
   8410         _BCM_KT2_SUBPORT_UNLOCK(unit);
   8411     } else {
   8412         rv = BCM_E_UNAVAIL;
   8413     }
   8414 
   8415     return rv;
   8416 
   8417 }
   8418 
   8419 /*
   8420  * Function:
   8421  *      bcm_kt2_subport_egr_subtag_dot1p_map_add
   8422  * Purpose:
   8423  *      Map the egress SubTag CoE packet's PHB (internal priority and color) 
   8424  *      to subport tag's Priority Code Point(PCP) and Drop Eligible(DE).
   8425  * Parameters:
   8426  *      unit      - (IN) Device Number
   8427  *      map       - (IN) qos map
   8428  * Returns:
   8429  *      BCM_E_XXX
   8430  */
   8431 int
   8432 bcm_kt2_subport_egr_subtag_dot1p_map_add(int unit,
   8433                                          bcm_qos_map_t *map)
   8434 {
   8435     soc_mem_t mem;
   8436     int index;
   8437     egr_subport_tag_dot1p_map_entry_t egr_subtag_dot1p_map;
   8438 
   8439     mem = EGR_SUBPORT_TAG_DOT1P_MAPm;
   8440 
   8441     if (!soc_feature(unit, soc_feature_subtag_coe)) {
   8442         return BCM_E_UNAVAIL;
   8443     }
   8444 
   8445     if (map->etag_pcp > 7 ||
   8446         map->etag_de > 1 ||
   8447         map->int_pri < 0 || map->int_pri > 15 ||
   8448         ((map->color != bcmColorGreen) && 
   8449         (map->color != bcmColorYellow) && 
   8450         (map->color != bcmColorRed))) {
   8451         return BCM_E_PARAM;
   8452     }
   8453 
   8454     /* EGR_SUBPORT_TAG_DOT1P_MAPm table is indexed with
   8455      * internal priority - 4 bits [5:2] and color - 2 bits[1:0]
   8456      */
   8457     index = ((map->int_pri << 2) | map->color) & soc_mem_index_max(unit, mem);
   8458 
   8459     sal_memset(&egr_subtag_dot1p_map, 0, sizeof(egr_subtag_dot1p_map));
   8460     soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_PCPf,
   8461                         map->etag_pcp);
   8462     soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_DEf,
   8463                         map->etag_de);
   8464     SOC_IF_ERROR_RETURN(WRITE_EGR_SUBPORT_TAG_DOT1P_MAPm(unit,
   8465                             MEM_BLOCK_ALL, index, &egr_subtag_dot1p_map));
   8466     return BCM_E_NONE;
   8467 }
   8468 
   8469 /*
   8470  * Function:
   8471  *      bcm_kt2_subport_egr_subtag_dot1p_map_delete
   8472  * Purpose:
   8473  *      Delete the map the egress SubTag CoE packet's
   8474  *      PHB (internal priority and color) 
   8475  *      to subport tag's Priority Code Point(PCP) and Drop Eligible(DE).
   8476  * Parameters:
   8477  *      unit      - (IN) Device Number
   8478  *      map       - (IN) qos map
   8479  * Returns:
   8480  *      BCM_E_XXX
   8481  */
   8482 int
   8483 bcm_kt2_subport_egr_subtag_dot1p_map_delete(int unit,
   8484                                             bcm_qos_map_t *map)
   8485 {
   8486     soc_mem_t mem;
   8487     int index;
   8488     egr_subport_tag_dot1p_map_entry_t egr_subtag_dot1p_map;
   8489 
   8490     mem = EGR_SUBPORT_TAG_DOT1P_MAPm;
   8491 
   8492     if (!soc_feature(unit, soc_feature_subtag_coe)) {
   8493         return BCM_E_UNAVAIL;
   8494     }
   8495 
   8496     if (map->etag_pcp > 7 ||
   8497         map->etag_de > 1 ||
   8498         map->int_pri < 0 || map->int_pri > 15 ||
   8499         ((map->color != bcmColorGreen) && 
   8500         (map->color != bcmColorYellow) && 
   8501         (map->color != bcmColorRed))) {
   8502         return BCM_E_PARAM;
   8503     }
   8504 
   8505     /* EGR_SUBPORT_TAG_DOT1P_MAPm table is indexed with
   8506      * internal priority - 4 bits [5:2] and color - 2 bits[1:0]
   8507      */
   8508     index = ((map->int_pri << 2) | map->color) & soc_mem_index_max(unit, mem);
   8509 
   8510     sal_memset(&egr_subtag_dot1p_map, 0, sizeof(egr_subtag_dot1p_map));
   8511     soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_PCPf, 0);
   8512     soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_DEf, 0);
   8513     SOC_IF_ERROR_RETURN(WRITE_EGR_SUBPORT_TAG_DOT1P_MAPm(unit,
   8514                             MEM_BLOCK_ALL, index, &egr_subtag_dot1p_map));
   8515     return BCM_E_NONE;
   8516 }
   8517 
   8518 /*
   8519  * Function:
   8520  *      bcm_kt2_subport_subtag_port_tpid_set
   8521  * Description:
   8522  *      Set the default Tag Protocol ID for a SubTag port.
   8523  * Parameters:
   8524  *      unit  - (IN) Device number
   8525  *      gport - (IN) SubTag group gport
   8526  *      tpid  - (IN) Tag Protocol ID
   8527  * Return Value:
   8528  *      BCM_E_XXX
   8529  */
   8530 
   8531 int 
   8532 bcm_kt2_subport_subtag_port_tpid_set(int unit,
   8533                                      bcm_gport_t gport,
   8534                                      uint16 tpid)
   8535 {
   8536     int rv = BCM_E_UNAVAIL;
   8537     bcm_port_t port;
   8538     soc_mem_t mem;
   8539     ing_physical_port_table_entry_t ing_physical_port_entry;
   8540     egr_physical_port_entry_t       egr_physical_port_entry;
   8541 
   8542     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(gport)) {
   8543         port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(gport);
   8544 
   8545         mem = ING_PHYSICAL_PORT_TABLEm;
   8546         if (port > soc_mem_index_max(unit, mem)) {
   8547             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8548                       (BSL_META_U(unit,
   8549                                   "ERROR: Invalid port %d in subport group 0x%x\n"),
   8550                        port, gport));
   8551         }
   8552         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   8553             &ing_physical_port_entry);
   8554         if (SOC_FAILURE(rv)) {
   8555             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8556                       (BSL_META_U(unit,
   8557                                   "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n")));
   8558             return rv;
   8559         }
   8560         if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   8561             CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) {
   8562             rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf,
   8563                 tpid);
   8564             if (SOC_FAILURE(rv)) {
   8565                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8566                           (BSL_META_U(unit,
   8567                                       "ERROR: SubTag TPID setting failed for port %d\n"),
   8568                            port));
   8569                 return rv;
   8570             }
   8571         } else {
   8572             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8573                       (BSL_META_U(unit,
   8574                                   "ERROR: Port %d is not SubTag Cascaded\n"),
   8575                        port));
   8576             return BCM_E_PORT;
   8577         }
   8578         mem = EGR_PHYSICAL_PORTm;
   8579         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   8580             &egr_physical_port_entry);
   8581         if (SOC_FAILURE(rv)) {
   8582             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8583                       (BSL_META_U(unit,
   8584                                   "ERROR:EGR_PHYSICAL_PORTm read failed\n")));
   8585             return rv;
   8586         }
   8587         rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, tpid);
   8588         if (SOC_FAILURE(rv)) {
   8589             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8590                       (BSL_META_U(unit,
   8591                                   "ERROR: SubTag TPID setting failed for egr_port %d\n"),
   8592                        port));
   8593             return rv;
   8594         }
   8595     } else {
   8596         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8597                   (BSL_META_U(unit,
   8598                               "ERROR: Invalid gport 0x%x for SubTag TPID set\n"),
   8599                    gport));
   8600         return BCM_E_PARAM;
   8601     }
   8602     return BCM_E_NONE;
   8603 }
   8604 
   8605 /*
   8606  * Function:
   8607  *      bcm_kt2_subport_subtag_port_tpid_get
   8608  * Description:
   8609  *      Retrieve the default Tag Protocol ID for a SubTag port.
   8610  * Parameters:
   8611  *      unit  - (IN) Device number
   8612  *      gport - (IN)SubTag group gport
   8613  *      tpid  - (OUT) Tag Protocol ID
   8614  * Return Value:
   8615  *      BCM_E_XXX
   8616  */
   8617 
   8618 int
   8619 bcm_kt2_subport_subtag_port_tpid_get(int unit,
   8620                                      bcm_gport_t gport,
   8621                                      uint16 *tpid)
   8622 {
   8623     int rv = BCM_E_UNAVAIL;
   8624     bcm_port_t port;
   8625     soc_mem_t mem;
   8626     ing_physical_port_table_entry_t ing_physical_port_entry;
   8627 
   8628     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(gport)) {
   8629         port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(gport);
   8630 
   8631         mem = ING_PHYSICAL_PORT_TABLEm;
   8632         if (port > soc_mem_index_max(unit, mem)) {
   8633             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8634                       (BSL_META_U(unit,
   8635                                   "ERROR: Invalid port %d in subport group 0x%x\n"),
   8636                        port, gport));
   8637         }
   8638         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   8639             &ing_physical_port_entry);
   8640         if (SOC_FAILURE(rv)) {
   8641             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8642                       (BSL_META_U(unit,
   8643                                   "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n")));
   8644             return rv;
   8645         }
   8646         if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   8647             CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) {
   8648             *tpid = soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   8649                         SUBPORT_TAG_TPIDf);
   8650         } else {
   8651             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8652                       (BSL_META_U(unit,
   8653                                   "ERROR: Port %d is not SubTag Cascaded\n"),
   8654                        port));
   8655             return BCM_E_PORT;
   8656         }
   8657     } else {
   8658         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8659                   (BSL_META_U(unit,
   8660                               "ERROR: Invalid gport 0x%x for SubTag TPID set\n"),
   8661                    gport));
   8662         return BCM_E_PARAM;
   8663     }
   8664     return BCM_E_NONE;
   8665 }
   8666 
   8667 
   8668 /*
   8669  * Function:
   8670  *      bcm_kt2_subport_subtag_port_tpid_delete
   8671  * Description:
   8672  *      Delete allowed TPID for a SubTag port.
   8673  * Parameters:
   8674  *      unit  - (IN) Device number
   8675  *      gport - (IN) SubTag group gport
   8676  *      tpid  - (IN) Tag Protocol ID
   8677  * Return Value:
   8678  *      BCM_E_XXX
   8679  */
   8680 
   8681 int
   8682 bcm_kt2_subport_subtag_port_tpid_delete(int unit,
   8683                                         bcm_gport_t gport,
   8684                                         uint16 tpid)
   8685 {
   8686     int rv = BCM_E_UNAVAIL;
   8687     bcm_port_t port;
   8688     soc_mem_t mem;
   8689     ing_physical_port_table_entry_t ing_physical_port_entry;
   8690     egr_physical_port_entry_t       egr_physical_port_entry;
   8691 
   8692     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(gport)) {
   8693         port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(gport);
   8694 
   8695         mem = ING_PHYSICAL_PORT_TABLEm;
   8696         if (port > soc_mem_index_max(unit, mem)) {
   8697             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8698                       (BSL_META_U(unit,
   8699                                   "ERROR: Invalid port %d in subport group 0x%x\n"),
   8700                        port, gport));
   8701         }
   8702         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   8703             &ing_physical_port_entry);
   8704         if (SOC_FAILURE(rv)) {
   8705             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8706                       (BSL_META_U(unit,
   8707                                   "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n")));
   8708             return rv;
   8709         }
   8710         if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   8711             CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) {
   8712             rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, 0);
   8713             if (SOC_FAILURE(rv)) {
   8714                 LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8715                           (BSL_META_U(unit,
   8716                                       "ERROR: SubTag TPID delete failed for port %d\n"),
   8717                            port));
   8718                 return rv;
   8719             }
   8720         } else {
   8721             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8722                       (BSL_META_U(unit,
   8723                                   "ERROR: Port %d is not SubTag Cascaded\n"),
   8724                        port));
   8725             return BCM_E_PORT;
   8726         }
   8727         mem = EGR_PHYSICAL_PORTm;
   8728         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   8729             &egr_physical_port_entry);
   8730         if (SOC_FAILURE(rv)) {
   8731             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8732                       (BSL_META_U(unit,
   8733                                   "ERROR:EGR_PHYSICAL_PORTm read failed\n")));
   8734             return rv;
   8735         }
   8736         rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, 0);
   8737         if (SOC_FAILURE(rv)) {
   8738             LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8739                       (BSL_META_U(unit,
   8740                                   "ERROR: SubTag TPID delete failed for egr_port %d\n"),
   8741                        port));
   8742             return rv;
   8743         }
   8744     } else {
   8745         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   8746                   (BSL_META_U(unit,
   8747                               "ERROR: Invalid gport 0x%x for SubTag TPID set\n"),
   8748                    gport));
   8749         return BCM_E_PARAM;
   8750     }
   8751     return BCM_E_NONE;
   8752 }
   8753 
   8754 STATIC int
   8755     _bcm_linkphy_subport_cb(int unit,
   8756     bcm_gport_t subport_gport, 
   8757     bcm_subport_config_t *linkphy_config, 
   8758     void *user_data)
   8759 {
   8760     int stream_idx = 0;
   8761     int rv = 0, stat = 0;
   8762     uint64 val;
   8763     int subport_group = -1, port = 0, done = 0;
   8764 
   8765     char *stat_name[]=
   8766         {"RxFragByte ","RxFrag     ","RxFrameByte",
   8767          "RxFrame    ","TxFragByte ","TxFrag     ",
   8768          "TxFrameByte","TxFrame    "};
   8769     bcm_subport_stat_t stat_type[]={
   8770         bcmSubportLinkPhyStatRxFragmentBytes,
   8771         bcmSubportLinkPhyStatRxFragments, 
   8772         bcmSubportLinkPhyStatRxFrameBytes,
   8773         bcmSubportLinkPhyStatRxFrames,
   8774         bcmSubportLinkPhyStatTxFragmentBytes,
   8775         bcmSubportLinkPhyStatTxFragments,
   8776         bcmSubportLinkPhyStatTxFrameBytes,
   8777         bcmSubportLinkPhyStatTxFrames
   8778     };
   8779 
   8780     if (linkphy_config->num_streams > 0) {
   8781         for(stream_idx = 0;
   8782             stream_idx < linkphy_config->num_streams; stream_idx++) {
   8783             done = 0;
   8784             for(stat = 0; stat <= 7; stat++) {
   8785                 COMPILER_64_ZERO(val);
   8786                 rv = bcm_kt2_subport_port_stat_get(unit, subport_gport,
   8787                          stream_idx, stat_type[stat], &val);
   8788                 if (rv < 0) {
   8789                     LOG_CLI((BSL_META_U(unit,
   8790                                         "Subport(0x%x) stat get failed\n"),
   8791                              subport_gport));
   8792                 } else {
   8793                     if (!COMPILER_64_IS_ZERO(val)) {
   8794                         if (!done) {
   8795                             subport_group = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit,
   8796                                     BCM_GPORT_SUBPORT_PORT_GET(subport_gport));
   8797                             port  = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group);
   8798                             LOG_CLI((BSL_META_U(unit,
   8799                                     "\nSubport = 0x%x PP_Port = %02d "
   8800                                     "ExtStreamId = %d Port = %s(%d)\n\n"),
   8801                                      subport_gport,
   8802                                      BCM_GPORT_SUBPORT_PORT_GET(subport_gport),
   8803                                      linkphy_config->stream_id_array[stream_idx],
   8804                                      SOC_PORT_NAME(unit, port), port));
   8805                             done = 1;
   8806                         }
   8807                         if (COMPILER_64_HI(val) == 0) {
   8808                             LOG_CLI((BSL_META_U(unit,
   8809                                     "\t%s  %08u\n"),
   8810                                      stat_name[stat],
   8811                                      COMPILER_64_LO(val)));
   8812                         } else {
   8813                             LOG_CLI((BSL_META_U(unit,
   8814                                     "\t%s 0x%08x%08x\n"),
   8815                                      stat_name[stat],
   8816                                      COMPILER_64_HI(val),
   8817                                      COMPILER_64_LO(val)));
   8818                         }
   8819                     }
   8820                 }
   8821             }
   8822         }
   8823     }
   8824     return BCM_E_NONE;
   8825 }
   8826 
   8827 STATIC void
   8828 _bcm_linkphy_ext_stream_id_port_get(int unit,
   8829     int block_id, int index, int *ext_stream_id, int *port)
   8830 {
   8831     int copyno = 0, idx = 0, pp_port = 0;
   8832     soc_mem_t  mem = INVALIDm;
   8833     txlp_int2ext_stream_map_table_entry_t txlp_int2ext_stream_map;
   8834     device_stream_id_to_pp_port_map_entry_t dev_sid_to_pp_entry;
   8835     pp_port_to_physical_port_map_entry_t    pp_to_port_entry;
   8836     int valid = 0;
   8837 
   8838 
   8839     mem = TXLP_INT2EXT_STREAM_MAP_TABLEm;
   8840     /* get the block and index for the LinkPHY memory */
   8841     sal_memset(&txlp_int2ext_stream_map, 0,
   8842             sizeof(txlp_int2ext_stream_map_table_entry_t));
   8843     copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block_id;
   8844     (void) soc_mem_read(unit, mem, copyno, index,
   8845             &txlp_int2ext_stream_map);
   8846     valid = soc_mem_field32_get(unit, mem,
   8847             (uint32 *)&txlp_int2ext_stream_map,
   8848             VALIDf);
   8849     if (!valid) {
   8850         /* If not a valid internal stream id, do not 
   8851          * fill external stream id and port.
   8852          */
   8853         return;
   8854     }
   8855     *ext_stream_id = soc_mem_field32_get(unit, mem,
   8856             (uint32 *)&txlp_int2ext_stream_map,
   8857             EXTERNAL_SIDf);
   8858 
   8859     /* get the pp_port from dev stream id */
   8860     mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm;
   8861     idx = ((block_id) ? (_BCM_KT2_LINKPHY_COUNTER_MAX(unit) + index) : index);
   8862     sal_memset(&dev_sid_to_pp_entry, 0,
   8863             sizeof(dev_sid_to_pp_entry));
   8864     copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   8865     (void) soc_mem_read(unit, mem, copyno, idx,
   8866             &dev_sid_to_pp_entry);
   8867     pp_port = soc_mem_field32_get(unit, mem,
   8868             (uint32 *)&dev_sid_to_pp_entry,
   8869             PP_PORTf);
   8870 
   8871     /* get the port id from pp_port */
   8872     mem = PP_PORT_TO_PHYSICAL_PORT_MAPm;
   8873     sal_memset(&pp_to_port_entry, 0,
   8874             sizeof(pp_to_port_entry));
   8875     copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   8876     (void) soc_mem_read(unit, mem, copyno, pp_port,
   8877             &pp_to_port_entry);
   8878     *port = soc_mem_field32_get(unit, mem,
   8879             (uint32 *)&pp_to_port_entry,
   8880             DESTINATIONf);
   8881     return;
   8882 }
   8883 
   8884 STATIC void
   8885 _bcm_kt2_linkphy_counter_show(int unit,
   8886     int block_id, int index)
   8887 {
   8888     char *stat[] = {"RxFragByte ","RxFrag     ","RxFrameByte", "RxFrame    ",
   8889                     "TxFragByte ","TxFrag     ","TxFrameByte", "TxFrame    "};
   8890     int stat_type_id = 0;
   8891     int direction = 0, pool_id = 0;
   8892     volatile uint64 *vptr;
   8893     int ext_stream_id = -1, port = -1, done = 0;
   8894 
   8895     _bcm_linkphy_ext_stream_id_port_get(unit, block_id, index,
   8896             &ext_stream_id, &port);
   8897     if (ext_stream_id == -1 || port == -1) {
   8898         /* Not a valid internal stream id. Return */
   8899         return;
   8900     }
   8901 
   8902     BCM_LINKPHY_COUNTER_LOCK(unit);
   8903         for (direction = 0; direction < _BCM_KT2_LINKPHY_DIRECTION_MAX;
   8904             direction++) {
   8905             for (pool_id = 0; pool_id < _BCM_KT2_LINKPHY_POOL_MAX; pool_id++) {
   8906                 switch (pool_id) {
   8907                     case 0:
   8908                         vptr = &linkphy_frag_byte_ctr[unit]
   8909                                 [direction][block_id][index];
   8910                         break;
   8911                     case 1:
   8912                         vptr = &linkphy_frag_ctr[unit]
   8913                                 [direction][block_id][index];
   8914                         break;
   8915                     case 2:
   8916                         vptr = &linkphy_frame_byte_ctr[unit]
   8917                                 [direction][block_id][index];
   8918                         break;
   8919                     case 3:
   8920                     default:
   8921                         vptr = &linkphy_frame_ctr[unit]
   8922                                 [direction][block_id][index];
   8923                         break;
   8924                 }
   8925                 stat_type_id =
   8926                     (direction*_BCM_KT2_LINKPHY_POOL_MAX) + pool_id;
   8927                 if (!(COMPILER_64_IS_ZERO(*vptr))) {
   8928                     if (!done) {
   8929                         LOG_CLI((BSL_META_U(unit,
   8930                                 "\nDevStreamID = %d "
   8931                                 "ExtStreamID = %d "
   8932                                 "Port = %s(%d) \n\n"),
   8933                                 ((block_id) ? (_BCM_KT2_LINKPHY_COUNTER_MAX(unit) +
   8934                                               index) : index),
   8935                                  ext_stream_id,
   8936                                  SOC_PORT_NAME(unit,port),
   8937                                  port));
   8938                         done = 1;
   8939                     }
   8940                     if (COMPILER_64_HI(*vptr) == 0) {
   8941                         LOG_CLI((BSL_META_U(unit,
   8942                                 "\t%s  %08u\n"),
   8943                                  stat[stat_type_id],
   8944                                  COMPILER_64_LO(*vptr)));
   8945                     } else {
   8946                         LOG_CLI((BSL_META_U(unit,
   8947                                 "\t%s 0x%08x%08x\n"),
   8948                                  stat[stat_type_id],
   8949                                  COMPILER_64_HI(*vptr),
   8950                                  COMPILER_64_LO(*vptr)));
   8951                     }
   8952                 }
   8953             }
   8954         }
   8955         BCM_LINKPHY_COUNTER_UNLOCK(unit);
   8956     return;
   8957 }
   8958 
   8959 int
   8960 bcm_kt2_subport_port_stat_show(int unit, uint32 flag, int sid)
   8961 {
   8962     int block_id = 0, index = 0;
   8963     int max_streams = SOC_INFO(unit).lp_streams_per_slice_max;
   8964     int linkphy_block_max = SOC_INFO(unit).lp_block_max; 
   8965 
   8966     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   8967 
   8968     if(soc_feature(unit, soc_feature_linkphy_coe) &&
   8969         SOC_INFO(unit).linkphy_enabled) {
   8970         if (flag == 0) {
   8971             _bcm_linkphy_subport_port_traverse(unit,
   8972                 _bcm_linkphy_subport_cb, NULL);
   8973         } else { /* flag == 1*/
   8974             if (sid != -1) {
   8975                 if (sid >= max_streams) {
   8976                     LOG_CLI((BSL_META_U(unit,
   8977                                         "invalid stream ID\n")));
   8978                     return BCM_E_PARAM;
   8979                 } else {
   8980                     for (block_id = 0;
   8981                         block_id < linkphy_block_max; block_id++) {
   8982                         _bcm_kt2_linkphy_counter_show(unit, block_id, sid);
   8983                     }
   8984                 }
   8985             } else {
   8986                 for (index = 0;
   8987                     index < _BCM_KT2_LINKPHY_COUNTER_MAX(unit); index++) {
   8988                     for (block_id = 0;
   8989                         block_id < linkphy_block_max; block_id++) {
   8990                         _bcm_kt2_linkphy_counter_show(unit, block_id, index);
   8991                     }
   8992                 }
   8993             }
   8994         }
   8995     }
   8996     return BCM_E_NONE;
   8997 }
   8998 
   8999 /*
   9000  * Function:
   9001  *      bcm_kt2_port_control_subtag_status_set
   9002  * Description:
   9003  *      Set the SubTag status for a given port.
   9004  * Parameters:
   9005  *      unit  - (IN) Device number
   9006  *      port  - (IN) port
   9007  *      value - (IN) Enable/Disable status
   9008  * Return Value:
   9009  *      BCM_E_XXX
   9010  * Note: The application need to delete all subport groups/ports, if any,
   9011  *       before disabling the SubTag CoE for given port.
   9012  */
   9013 
   9014 int bcm_kt2_port_control_subtag_status_set(int unit,
   9015                                  bcm_port_t port, int value)
   9016 {
   9017     int rv = BCM_E_NONE;
   9018     int  start = 0, end = 0;
   9019     uint32 port_type, cascaded_port_type;
   9020     soc_mem_t mem;
   9021     soc_info_t *si = &SOC_INFO(unit);
   9022     int min_subport_index = si->pp_port_index_min;
   9023     ing_physical_port_table_entry_t ing_physical_port_entry;
   9024     egr_physical_port_entry_t       egr_physical_port_entry;
   9025 
   9026     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   9027 
   9028     if (!soc_feature(unit, soc_feature_subtag_coe)) {
   9029         return BCM_E_UNAVAIL;
   9030     }
   9031     if (!BCM_PBMP_MEMBER(si->subtag_allowed_pbm, port)) {
   9032         return BCM_E_PORT;
   9033     }
   9034 
   9035     port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED :
   9036                         _BCM_KT2_PORT_TYPE_ETHERNET;
   9037     cascaded_port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG : 0;
   9038 
   9039     _BCM_KT2_SUBPORT_LOCK(unit);
   9040     mem = ING_PHYSICAL_PORT_TABLEm;
   9041     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   9042         rv = soc_mem_field32_modify( unit, mem, port, PORT_TYPEf, port_type);
   9043         if (SOC_FAILURE(rv)) {
   9044             _BCM_KT2_SUBPORT_UNLOCK(unit);
   9045             return rv;
   9046         }
   9047     }
   9048     if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   9049         rv = soc_mem_field32_modify(unit, mem, port,
   9050                  CASCADED_PORT_TYPEf, cascaded_port_type);
   9051         if (SOC_FAILURE(rv)) {
   9052             _BCM_KT2_SUBPORT_UNLOCK(unit);
   9053             return rv;
   9054         }
   9055     }
   9056 
   9057     /* Add default TPID for the created cascaded port */
   9058     if (value) {
   9059         if (SOC_MEM_FIELD_VALID(unit, mem, SUBPORT_TAG_TPIDf)) {
   9060 
   9061             /* Lets not modify the field, if default tpid is already set */
   9062             if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   9063                     SUBPORT_TAG_TPIDf) != BCM_SUBPORT_COE_DEFAULT_ETHERTYPE) {
   9064                 rv = soc_mem_field32_modify(unit, mem, port,
   9065                         SUBPORT_TAG_TPIDf, BCM_SUBPORT_COE_DEFAULT_ETHERTYPE);
   9066                 if (SOC_FAILURE(rv)) {
   9067                     _BCM_KT2_SUBPORT_UNLOCK(unit);
   9068                     return rv;
   9069                 }
   9070             }
   9071         }
   9072     }
   9073 
   9074     mem = EGR_PHYSICAL_PORTm;
   9075     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   9076         rv = soc_mem_field32_modify(unit, mem, port, PORT_TYPEf, port_type);
   9077         if (SOC_FAILURE(rv)) {
   9078             _BCM_KT2_SUBPORT_UNLOCK(unit);
   9079             return rv;
   9080         }
   9081     }
   9082     if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   9083         rv = soc_mem_field32_modify(unit, mem, port,
   9084                  CASCADED_PORT_TYPEf, cascaded_port_type);
   9085         if (SOC_FAILURE(rv)) {
   9086             _BCM_KT2_SUBPORT_UNLOCK(unit);
   9087             return rv;
   9088         }
   9089     }
   9090 
   9091     /* Update tpid in EGR_PHYSICAL_PORT if default tpid is not set */
   9092     if (value) {
   9093         if (SOC_MEM_FIELD_VALID(unit, mem, SUBPORT_TAG_TPIDf)) {
   9094             if (soc_mem_field32_get(unit, mem, &egr_physical_port_entry,
   9095                     SUBPORT_TAG_TPIDf) != BCM_SUBPORT_COE_DEFAULT_ETHERTYPE) {
   9096                 rv = soc_mem_field32_modify(unit, mem, port,
   9097                         SUBPORT_TAG_TPIDf, BCM_SUBPORT_COE_DEFAULT_ETHERTYPE);
   9098                 if (SOC_FAILURE(rv)) {
   9099                     _BCM_KT2_SUBPORT_UNLOCK(unit);
   9100                     return rv;
   9101                 }
   9102             }
   9103         }
   9104     }
   9105 
   9106     start = si->port_subport_base[port] - min_subport_index;
   9107     end = start + si->port_num_subport[port] - 1;
   9108     if (value) {
   9109         BCM_PBMP_PORT_ADD(si->subtag_pbm, port);
   9110         BCM_PBMP_PORT_ADD(si->subtag.bitmap, port);
   9111         SOC_IF_ERROR_RETURN
   9112             (soc_kt2_cosq_s1_range_set(unit, port, start, end, 0));
   9113         SOC_IF_ERROR_RETURN
   9114             (soc_kt2_cosq_repl_map_set(unit, port, start, end, 1));
   9115         SOC_IF_ERROR_RETURN
   9116             (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1));
   9117     } else {
   9118         if (BCM_PBMP_MEMBER(si->subtag_pbm, port)) {
   9119             BCM_PBMP_PORT_REMOVE(si->subtag_pbm, port);
   9120             BCM_PBMP_PORT_REMOVE(si->subtag.bitmap, port);
   9121             SOC_IF_ERROR_RETURN
   9122                 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 0));
   9123             SOC_IF_ERROR_RETURN
   9124                 (soc_kt2_cosq_s1_range_set(unit, port, 0, 0, 0));
   9125             SOC_IF_ERROR_RETURN
   9126                 (soc_kt2_cosq_repl_map_set(unit, port, start, end, 0));
   9127         }
   9128     }
   9129     _BCM_KT2_SUBPORT_UNLOCK(unit);
   9130     return rv;
   9131 }
   9132 /*
   9133  * Function:
   9134  *      bcm_kt2_port_control_subtag_status_get
   9135  * Description:
   9136  *      Get the SubTag status for a given port.
   9137  * Parameters:
   9138  *      unit  - (IN) Device number
   9139  *      port  - (IN) port
   9140  *      value - (OUT) Enable/Disable status
   9141  * Return Value:
   9142  *      BCM_E_XXX
   9143  */
   9144 
   9145 int bcm_kt2_port_control_subtag_status_get(int unit,
   9146                                  bcm_port_t port, int *value)
   9147 {
   9148     int rv = BCM_E_NONE;
   9149     soc_mem_t mem;
   9150     soc_info_t *si = &SOC_INFO(unit);
   9151     ing_physical_port_table_entry_t ing_physical_port_entry;
   9152 
   9153     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   9154 
   9155     if (!soc_feature(unit, soc_feature_subtag_coe)) {
   9156         return BCM_E_UNAVAIL;
   9157     }
   9158     if (!BCM_PBMP_MEMBER(si->subtag_allowed_pbm, port)) {
   9159         return BCM_E_PORT;
   9160     }
   9161 
   9162     _BCM_KT2_SUBPORT_LOCK(unit);
   9163 
   9164     *value = 0;
   9165     mem = ING_PHYSICAL_PORT_TABLEm;
   9166     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   9167             &ing_physical_port_entry);
   9168     if (SOC_FAILURE(rv)) {
   9169         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   9170                   (BSL_META_U(unit,
   9171                               "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n")));
   9172         _BCM_KT2_SUBPORT_UNLOCK(unit);
   9173         return rv;
   9174     }
   9175     if ((soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   9176             CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) &&
   9177         (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   9178             PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED)) {
   9179         *value = 1;
   9180     }
   9181 
   9182     _BCM_KT2_SUBPORT_UNLOCK(unit);
   9183 
   9184     return rv;
   9185 }
   9186 
   9187 /*
   9188  * Function:
   9189  *      bcm_kt2_port_control_linkphy_status_set
   9190  * Description:
   9191  *      Set the LinkPHY status for a given port.
   9192  * Parameters:
   9193  *      unit  - (IN) Device number
   9194  *      port  - (IN) port
   9195  *      value - (IN) Enable/Disable status
   9196  * Return Value:
   9197  *      BCM_E_XXX
   9198  * Note: The application need to delete all subport groups/ports, if any,
   9199  *       before disabling the LinkPHY CoE for given port.
   9200  */
   9201 
   9202 int bcm_kt2_port_control_linkphy_status_set(int unit,
   9203                                  bcm_port_t port, int value)
   9204 {
   9205     int rv = BCM_E_NONE;
   9206     int  start = 0, end = 0, index = 0, lp_block = 0, lp_index = 0;
   9207     uint32 lp_enable, port_enable;
   9208     uint32 port_type, cascaded_port_type;
   9209     uint32 regval = 0;
   9210     uint64 tx_ctrl, rx_ctrl;
   9211     soc_reg_t reg;
   9212     soc_mem_t mem;
   9213     soc_info_t *si = &SOC_INFO(unit);
   9214     int num_max_stream = si->lp_streams_per_subport;
   9215     soc_pbmp_t pbmp_linkphy_one_stream_per_subport;
   9216 
   9217     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   9218 
   9219     if (!soc_feature(unit, soc_feature_linkphy_coe)) {
   9220         return BCM_E_UNAVAIL;
   9221     }
   9222     if (!BCM_PBMP_MEMBER(si->linkphy_allowed_pbm, port)) {
   9223         return BCM_E_PORT;
   9224     }
   9225     port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED :
   9226                         _BCM_KT2_PORT_TYPE_ETHERNET;
   9227     cascaded_port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY : 0;
   9228 
   9229     _BCM_KT2_SUBPORT_LOCK(unit);
   9230 
   9231     /* Configures XMAC_TX_CTRL register to append CRC to the data */
   9232     if (SOC_REG_PORT_VALID(unit, XMAC_TX_CTRLr, port)) {
   9233         SOC_IF_ERROR_RETURN(READ_XMAC_TX_CTRLr(unit, port, &tx_ctrl));
   9234         soc_reg64_field32_set(unit, XMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 0x0);
   9235         SOC_IF_ERROR_RETURN(WRITE_XMAC_TX_CTRLr(unit, port, tx_ctrl));
   9236     } else if (SOC_REG_PORT_VALID(unit, XLMAC_TX_CTRLr, port)) { 
   9237         /* For saber2 it is XLMAC */
   9238         SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctrl));
   9239         soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 0x0);
   9240         SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctrl));
   9241     }
   9242 
   9243     if (SOC_REG_PORT_VALID(unit, XMAC_RX_CTRLr, port)) {
   9244         SOC_IF_ERROR_RETURN(READ_XMAC_RX_CTRLr(unit, port, &rx_ctrl));
   9245         soc_reg64_field32_set(unit, XMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 1);
   9246         SOC_IF_ERROR_RETURN(WRITE_XMAC_RX_CTRLr(unit, port, rx_ctrl));
   9247     } else if (SOC_REG_PORT_VALID(unit, XLMAC_RX_CTRLr, port)) { 
   9248         /* For saber2 it is XLMAC */
   9249         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_CTRLr(unit, port, &rx_ctrl));
   9250         soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 1);
   9251         SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_CTRLr(unit, port, rx_ctrl));
   9252     }
   9253 
   9254     /*
   9255     * Set the RXLP/TXLP internal stream id base to 128 for
   9256     * RXLP/TXLP block number 1. This is needed to support
   9257     * 256 streams
   9258     */
   9259 
   9260     rv = soc_linkphy_port_blk_idx_get(unit,port,
   9261                                          &lp_block, &lp_index);
   9262     if (SOC_FAILURE(rv)) {
   9263         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   9264                (BSL_META_U(unit,
   9265                "ERROR: LinkPHY block, index get failed for port %d\n"), port));
   9266         return rv;
   9267     }
   9268 
   9269     reg = RXLP_INT_STREAM_ID_BASEr;
   9270     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   9271         soc_reg_field_set(unit, reg, &regval, BASEf, lp_block ? 128 : 0);
   9272         BCM_IF_ERROR_RETURN(
   9273             WRITE_RXLP_INT_STREAM_ID_BASEr(unit, port, regval));
   9274     }
   9275     reg = TXLP_INT_STREAM_ID_BASEr;
   9276     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   9277         soc_reg_field_set(unit, reg, &regval, BASEf, lp_block ? 128 : 0);
   9278         BCM_IF_ERROR_RETURN(
   9279             WRITE_TXLP_INT_STREAM_ID_BASEr(unit, port, regval));
   9280     }
   9281 
   9282     SOC_PBMP_CLEAR(pbmp_linkphy_one_stream_per_subport);
   9283     if (SOC_IS_SABER2(unit)) {
   9284         pbmp_linkphy_one_stream_per_subport =
   9285         soc_property_get_pbmp(unit, spn_PBMP_LINKPHY_ONE_STREAM_PER_SUBPORT, 0);
   9286     }
   9287     if (value) {
   9288         BCM_PBMP_PORT_ADD(si->linkphy_pbm, port);
   9289         BCM_PBMP_PORT_ADD(si->lp.bitmap, port);
   9290         start = si->port_linkphy_s1_base[port];
   9291         end = start +
   9292             si->port_num_subport[port] *
   9293             (SOC_PBMP_MEMBER(pbmp_linkphy_one_stream_per_subport, port) ?
   9294              1 : num_max_stream) - 1;
   9295 
   9296         SOC_IF_ERROR_RETURN
   9297             (soc_kt2_cosq_s1_range_set(unit, port, start, end, value));
   9298         SOC_IF_ERROR_RETURN
   9299             (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1));
   9300     } else {
   9301         if (BCM_PBMP_MEMBER(si->linkphy_pbm, port)) {
   9302             BCM_PBMP_PORT_REMOVE(si->linkphy_pbm, port);
   9303             BCM_PBMP_PORT_REMOVE(si->lp.bitmap, port);
   9304             SOC_IF_ERROR_RETURN
   9305                 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 0));
   9306             SOC_IF_ERROR_RETURN
   9307                 (soc_kt2_cosq_s1_range_set(unit, port, 0, 0, 0));
   9308         }
   9309     }
   9310 
   9311     port_type = _BCM_KT2_PORT_TYPE_CASCADED;
   9312     cascaded_port_type = _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY;
   9313 
   9314     mem = ING_PHYSICAL_PORT_TABLEm;
   9315     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   9316         BCM_IF_ERROR_RETURN(soc_mem_field32_modify
   9317             (unit, mem, port, PORT_TYPEf, port_type));
   9318         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   9319             unit, mem, port, CASCADED_PORT_TYPEf, cascaded_port_type));
   9320     }
   9321 
   9322     mem = EGR_PHYSICAL_PORTm;
   9323     if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) {
   9324         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   9325             unit, mem, port, PORT_TYPEf, port_type));
   9326     }
   9327     if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) {
   9328         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(
   9329             unit, mem, port, CASCADED_PORT_TYPEf, cascaded_port_type));
   9330     }
   9331 
   9332     reg = RXLP_PORT_ENABLEr;
   9333     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   9334         BCM_IF_ERROR_RETURN(
   9335             READ_RXLP_PORT_ENABLEr(unit, port, &regval));
   9336         lp_enable = soc_reg_field_get(unit, reg, regval, LP_ENABLEf);
   9337 
   9338         if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port,
   9339             SOC_BLK_RXLP, NULL, &index) == SOC_E_NONE) {
   9340             lp_enable |= ((1 << index) & 0xF);
   9341         }
   9342 
   9343         regval = 0;
   9344         soc_reg_field_set(unit, reg, &regval, LP_ENABLEf, lp_enable);
   9345         BCM_IF_ERROR_RETURN( WRITE_RXLP_PORT_ENABLEr(unit,port,regval));
   9346     }
   9347 
   9348     reg = TXLP_PORT_ENABLEr;
   9349     if (SOC_REG_PORT_VALID(unit, reg, port)) {
   9350         BCM_IF_ERROR_RETURN(
   9351             READ_TXLP_PORT_ENABLEr(unit, port, &regval));
   9352         lp_enable = soc_reg_field_get(unit, reg, regval, LP_ENABLEf);
   9353         port_enable = soc_reg_field_get(unit, reg, regval,PORT_ENABLEf);
   9354 
   9355         if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port,
   9356             SOC_BLK_TXLP, NULL, &index) == SOC_E_NONE) {
   9357             lp_enable |= ((1 << index) & 0xF);
   9358             port_enable |= ((1 << index) & 0xF);
   9359         }
   9360 
   9361         regval = 0;
   9362         soc_reg_field_set(unit, reg, &regval, LP_ENABLEf, lp_enable);
   9363         soc_reg_field_set(unit, reg, &regval, PORT_ENABLEf,port_enable);
   9364         BCM_IF_ERROR_RETURN(WRITE_TXLP_PORT_ENABLEr(unit, port,regval));
   9365     }
   9366 
   9367     _BCM_KT2_SUBPORT_UNLOCK(unit);
   9368     return rv;
   9369 }
   9370 /*
   9371  * Function:
   9372  *      bcm_kt2_port_control_linkphy_status_get
   9373  * Description:
   9374  *      Get the LinkPHY status for a given port.
   9375  * Parameters:
   9376  *      unit  - (IN) Device number
   9377  *      port  - (IN) port
   9378  *      value - (OUT) Enable/Disable status
   9379  * Return Value:
   9380  *      BCM_E_XXX
   9381  */
   9382 
   9383 int bcm_kt2_port_control_linkphy_status_get(int unit,
   9384                                  bcm_port_t port, int *value)
   9385 {
   9386     int rv = BCM_E_NONE;
   9387     soc_mem_t mem;
   9388     soc_info_t *si = &SOC_INFO(unit);
   9389     ing_physical_port_table_entry_t ing_physical_port_entry;
   9390 
   9391     _BCM_KT2_SUBPORT_CHECK_INIT(unit);
   9392 
   9393     if (!soc_feature(unit, soc_feature_linkphy_coe)) {
   9394         return BCM_E_UNAVAIL;
   9395     }
   9396     if (!BCM_PBMP_MEMBER(si->linkphy_allowed_pbm, port)) {
   9397         return BCM_E_PORT;
   9398     }
   9399 
   9400     _BCM_KT2_SUBPORT_LOCK(unit);
   9401 
   9402     *value = 0;
   9403     mem = ING_PHYSICAL_PORT_TABLEm;
   9404     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port,
   9405             &ing_physical_port_entry);
   9406     if (SOC_FAILURE(rv)) {
   9407         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   9408                   (BSL_META_U(unit,
   9409                               "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n")));
   9410         _BCM_KT2_SUBPORT_UNLOCK(unit);
   9411         return rv;
   9412     }
   9413     if ((soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   9414             CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY) &&
   9415         (soc_mem_field32_get(unit, mem, &ing_physical_port_entry,
   9416             PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED)) {
   9417         *value = 1;
   9418     }
   9419 
   9420     _BCM_KT2_SUBPORT_UNLOCK(unit);
   9421 
   9422     return rv;
   9423 }
   9424 
   9425 int
   9426 _bcm_kt2_modport_is_local_coe_subport(int unit, int mod, bcm_port_t port,
   9427                                       int *is_local_subport)
   9428 {
   9429     int pp_port = 0;
   9430     int pp_port_index_min = SOC_INFO(unit).pp_port_index_min;
   9431     int pp_port_index_max = SOC_INFO(unit).pp_port_index_max;
   9432 
   9433     *is_local_subport = 0;
   9434 
   9435     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   9436         soc_feature(unit, soc_feature_subtag_coe)) {
   9437         /* For LinkPHY/SubportPktTag pp_ports, check if the mod is a valid one */
   9438         if (_bcm_kt2_mod_is_coe_mod_check(unit, mod) == BCM_E_NONE) {
   9439             BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit,
   9440                                     mod, port, &pp_port));
   9441 #if defined BCM_METROLITE_SUPPORT
   9442             if (soc_feature(unit, soc_feature_discontinuous_pp_port)) {
   9443                 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) {
   9444                     *is_local_subport = 1; 
   9445                 }
   9446             } else
   9447 #endif
   9448             {
   9449                 /* For KT2, pp_port 42 to 169 are used for LinkPHY/CoE subport.*/
   9450                 if ((pp_port >= pp_port_index_min) &&
   9451                     (pp_port <= pp_port_index_max)) {
   9452                     *is_local_subport = 1;
   9453                 }
   9454             }
   9455         }
   9456     }
   9457     return BCM_E_NONE;
   9458 }
   9459 
   9460 
   9461 int _bcm_kt2_subport_linkphy_rx_error_hw_set(int unit,
   9462                     bcm_subport_linkphy_rx_error_t error,
   9463                     soc_reg_t reg,
   9464                     uint32 value)
   9465 {
   9466     soc_field_t field = INVALIDf;
   9467     soc_info_t *si = &SOC_INFO(unit);
   9468     bcm_port_t port;
   9469 
   9470 
   9471     /* Validate the error parameter */
   9472     if (!_BCM_KT2_SUBPORT_LINKPHY_RX_ERROR_VALID(error)) {
   9473         return BCM_E_PARAM;
   9474     }
   9475 
   9476     /* Validate value parameter */
   9477     if (value > 1) {
   9478         /* It is expected to be 0 or 1 only implying
   9479          * enable/disable.
   9480          */
   9481         return BCM_E_PARAM;
   9482     }
   9483     
   9484     switch (reg) {
   9485         case RXLP_INTERRUPT_ENABLEr:
   9486             /* Map the error to field in the register */
   9487             field = _bcm_kt2_subport_linkphy_rx_error_to_reg_field_map[error];
   9488             break;
   9489         case RXLP_INTERRUPT_STATUSr:
   9490             /* Map the error to field in the register */
   9491             field = _bcm_kt2_subport_linkphy_rx_error_to_st_reg_field_map[error];
   9492             break;
   9493         case RXLP_INTERRUPT_DATA_LOG_ENABLEr:
   9494             field = _bcm_kt2_subport_linkphy_rx_error_to_dl_reg_field_map[error];
   9495             break;
   9496         case RXLP_INTERRUPT_DATA_LOG_VALIDr:
   9497             field = _bcm_kt2_subport_linkphy_rx_error_to_dl_val_reg_field_map[error];
   9498             break;
   9499         default:
   9500             return BCM_E_PARAM;
   9501             break;
   9502     }
   9503 
   9504     /* Enable/Disable the register's field. */
   9505     SOC_PBMP_ITER(si->linkphy_pbm, port) {
   9506         if (SOC_REG_PORT_VALID(unit, reg, port)) {
   9507             if (soc_reg_field_valid(unit, reg, field)) {
   9508                 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, port, field, value));
   9509             } 
   9510         }
   9511     }
   9512 
   9513     return BCM_E_NONE;
   9514 }
   9515 
   9516 
   9517 int bcm_kt2_subport_linkphy_rx_error_register (
   9518         int unit,
   9519         bcm_subport_linkphy_rx_errors_t errors,
   9520         bcm_subport_linkphy_rx_error_reg_info_t *reg_info,
   9521         void *user_data)
   9522 {
   9523     bcm_subport_linkphy_rx_error_t error;
   9524 
   9525     /* Loop for the errors in the errors bitmap. */
   9526     for (error = 0; error < bcmSubportLinkphyRxErrorCount; error++) {
   9527         /* For every error set in the bitmap */
   9528         if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error)) {
   9529             /* Enable the interrupt */
   9530             BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set
   9531                     (unit, error, RXLP_INTERRUPT_ENABLEr, 1));
   9532             /* Assign the callback function to the handler for the error */
   9533             _bcm_linkphy_rx_error_cb_info[error].reg_info.cb = reg_info->cb; 
   9534             /* If Data log enable/disable, enable/disable data log in the register */
   9535             BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set
   9536                     (unit, error, RXLP_INTERRUPT_DATA_LOG_ENABLEr, reg_info->data_log_enable));
   9537             /* Update the data log information for the error */
   9538             _bcm_linkphy_rx_error_cb_info[error].reg_info.data_log_enable = reg_info->data_log_enable;
   9539             _bcm_linkphy_rx_error_cb_info[error].user_data = user_data;
   9540         }
   9541     }
   9542 
   9543     return BCM_E_NONE;
   9544 }
   9545 
   9546 int bcm_kt2_subport_linkphy_rx_error_unregister (
   9547         int unit,
   9548         bcm_subport_linkphy_rx_errors_t errors)
   9549 {
   9550     bcm_subport_linkphy_rx_error_t error;
   9551 
   9552     /* Loop for errors in the errors bitmap */
   9553     for (error = 0; error < bcmSubportLinkphyRxErrorCount; error++) {
   9554         /* For every error set in the bitmap */
   9555         if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error)) {
   9556             /* Disable the interrupt */
   9557             BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set
   9558                     (unit, error, RXLP_INTERRUPT_ENABLEr, 0));
   9559             /* Assign the callback function to NULL for the error */
   9560             _bcm_linkphy_rx_error_cb_info[error].reg_info.cb = NULL; 
   9561             /* Disable data log in the register */
   9562             BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set
   9563                     (unit, error, RXLP_INTERRUPT_DATA_LOG_ENABLEr, 0));
   9564             /* Set data log info to 0 (disabled) for the error */
   9565             _bcm_linkphy_rx_error_cb_info[error].reg_info.data_log_enable = 0;
   9566             _bcm_linkphy_rx_error_cb_info[error].user_data = NULL;
   9567         }
   9568     }
   9569 
   9570     return BCM_E_NONE;
   9571 }
   9572 
   9573 void _bcm_kt2_subport_linkphy_rx_error_get_from_interrupt_status(int unit, uint32 rval,
   9574                                     bcm_subport_linkphy_rx_errors_t *errors)
   9575 {
   9576     bcm_subport_linkphy_rx_error_t error_type;
   9577     soc_field_t field = INVALIDf;
   9578 
   9579     BCM_SUBPORT_LINKPHY_RX_ERROR_CLEAR_ALL(*errors);
   9580 
   9581     for (error_type = bcmSubportLinkphyRxErrorMaxFrameSize;
   9582          error_type < bcmSubportLinkphyRxErrorCount;
   9583          error_type++) {
   9584         field = _bcm_kt2_subport_linkphy_rx_error_to_st_reg_field_map[error_type];
   9585         if (soc_reg_field_get(unit, RXLP_INTERRUPT_STATUSr, rval, field)) {
   9586             BCM_SUBPORT_LINKPHY_RX_ERROR_SET(*errors, error_type);
   9587         }
   9588     }
   9589 }
   9590 
   9591 int _bcm_kt2_subport_linkphy_rx_error_handler(
   9592                 int unit, bcm_port_t port, uint32 rval)
   9593 {
   9594     uint32 rval1 = 0;
   9595     uint32 rxlp_subport_index = 0, phy_port = 0, blk_int_stream_id = 0;
   9596     uint8 intr_data_mem[BCM_SUBPORT_LINKPHY_MAX_FRAGMENT_SIZE] = {0};
   9597     int i, j;
   9598     int rv = BCM_E_NONE;
   9599     uint32 flags = 0;
   9600     int data_log_valid = 0, data_log_enabled = 0;
   9601     void *user_data = NULL;
   9602     bcm_subport_linkphy_rx_error_t error_type = -1;
   9603     bcm_subport_linkphy_rx_errors_t errors;
   9604     bcm_subport_linkphy_rx_error_data_t error_data;
   9605     uint32 *user_pkt_data = NULL;
   9606     uint32 *user_frag_data = NULL;
   9607     int entry_dw = 0;
   9608 
   9609     BCM_SUBPORT_LINKPHY_RX_ERROR_CLEAR_ALL(errors);
   9610     _bcm_kt2_subport_linkphy_rx_error_get_from_interrupt_status(unit, rval, &errors);
   9611 
   9612     entry_dw = soc_mem_entry_words(unit, RXLP_INTR_DATA_MEMm);
   9613 
   9614     rv = READ_RXLP_INTERRUPT_DATA_LOG_VALIDr(unit, port, &rval1);
   9615     if (rv < BCM_E_NONE) {
   9616         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9617                 (BSL_META_U(unit,
   9618                             "Linkphy error handler data log valid read failed "
   9619                             "%s\n"),
   9620                  bcm_errmsg(rv)));
   9621     }
   9622     if (rval1) {
   9623         rval1 = 0;
   9624         data_log_valid = 1;
   9625         rv = READ_RXLP_INTERRUPT_DATA_SOURCEr(unit, port, &rval1);
   9626         if (rv < BCM_E_NONE) {
   9627             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9628                     (BSL_META_U(unit,
   9629                                 "Linkphy error handler data source read failed "
   9630                                 "%s\n"),
   9631                      bcm_errmsg(rv)));
   9632         }
   9633         rxlp_subport_index = soc_reg_field_get(unit, RXLP_INTERRUPT_DATA_SOURCEr, rval1, PORT_NUMBERf);
   9634         blk_int_stream_id = soc_reg_field_get(unit, RXLP_INTERRUPT_DATA_SOURCEr, rval1, STREAM_IDf);
   9635         j = 0;
   9636         for (i = 0; i < 192; i=i+16) {
   9637             rv = READ_RXLP_INTR_DATA_MEMm(unit, MEM_BLOCK_ANY, j, &(intr_data_mem[i]));
   9638             if (rv < BCM_E_NONE) {
   9639                 LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9640                         (BSL_META_U(unit,
   9641                                     "Linkphy error handler intr data mem read failed "
   9642                                     "%s\n"),
   9643                          bcm_errmsg(rv)));
   9644             }
   9645             j++;
   9646         }
   9647     }
   9648     for (error_type = bcmSubportLinkphyRxErrorMaxFrameSize;
   9649             error_type < bcmSubportLinkphyRxErrorCount;
   9650             error_type++) {
   9651         if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error_type)) { 
   9652             flags = 0;
   9653             sal_memset(&error_data, 0, sizeof(error_data));
   9654             data_log_enabled = _bcm_linkphy_rx_error_cb_info[error_type].reg_info.data_log_enable;
   9655             if (data_log_valid && data_log_enabled) {
   9656                 flags |= BCM_SUBPORT_LINKPHY_RX_ERROR_CB_DATA_VALID;
   9657 
   9658                 /* Retreive physical port from subport index returned by hardware */
   9659                 rv = _bcm_linkphy_subport_index_to_phyport_get(unit, port, rxlp_subport_index, &phy_port);
   9660                 if (rv < BCM_E_NONE) {
   9661                     LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9662                             (BSL_META_U(unit,
   9663                                         "Linkphy error getting physical port failed "
   9664                                         "%s\n"),
   9665                              bcm_errmsg(rv)));
   9666                 }
   9667                 error_data.port = phy_port;
   9668 
   9669                 /* Retreive ext stream id from int steam id returned by hardware */
   9670                 rv = _bcm_linkphy_port_tx_int_to_ext_stream_map_get(unit, port, blk_int_stream_id, &(error_data.ext_stream_id));
   9671                 if (rv < BCM_E_NONE) {
   9672                     LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9673                             (BSL_META_U(unit,
   9674                                         "Linkphy error handler stream mapping failed "
   9675                                         "%s\n"),
   9676                              bcm_errmsg(rv)));
   9677                 }
   9678 
   9679                 /* Copy fragment data to user */
   9680                 user_frag_data = (uint32 *)error_data.fragment_data;
   9681                 for (i = 0; i<12; i++) {
   9682                     user_pkt_data = (uint32 *)intr_data_mem + (((i+1)*entry_dw) - 1);
   9683                     for (j=0; j<entry_dw; j++) {
   9684                         *user_pkt_data = bcm_htonl(*user_pkt_data);
   9685                         sal_memcpy(user_frag_data, user_pkt_data, sizeof(uint32));
   9686                         user_pkt_data--;
   9687                         user_frag_data++;
   9688                     }
   9689                 }
   9690             }
   9691 
   9692             /* Call the user registered handler */
   9693             user_data = _bcm_linkphy_rx_error_cb_info[error_type].user_data;
   9694             if (_bcm_linkphy_rx_error_cb_info[error_type].reg_info.cb) {
   9695                 rv = _bcm_linkphy_rx_error_cb_info[error_type].reg_info.cb(unit, error_type, flags, &error_data, user_data);
   9696                 if (rv < BCM_E_NONE) {
   9697                     LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9698                             (BSL_META_U(unit,
   9699                                         "Linkphy error handler callback failed "
   9700                                         "%s\n"),
   9701                              bcm_errmsg(rv)));
   9702                 }
   9703             }
   9704         }
   9705     }
   9706     
   9707     /* Clear the interrupt data source register */
   9708     rv = WRITE_RXLP_INTERRUPT_DATA_SOURCEr(unit, port, 0);
   9709     if (rv < BCM_E_NONE) {
   9710         LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9711                 (BSL_META_U(unit,
   9712                             "Linkphy error handler data source write failed "
   9713                             "%s\n"),
   9714                  bcm_errmsg(rv)));
   9715     }
   9716     for (error_type = bcmSubportLinkphyRxErrorMaxFrameSize;
   9717             error_type < bcmSubportLinkphyRxErrorCount;
   9718             error_type++) {
   9719         if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error_type)) { 
   9720             /* Clear the interrupt enable for that error_type */
   9721             _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_ENABLEr, 0);
   9722             /* Clear the interrupt data log valid register for the given error type */
   9723             _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_DATA_LOG_VALIDr, 0);
   9724             /* Clear the interrupt status register for the given error type */
   9725             _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_STATUSr, 0);
   9726             /* Enable the interrupt enable for that error_type */
   9727             _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_ENABLEr, 1);
   9728         }
   9729     }
   9730     
   9731     return BCM_E_NONE;
   9732 }
   9733 
   9734 /*
   9735  * Function:
   9736  *      bcmi_kt2_subport_gport_modport_get
   9737  * Purpose:
   9738  *      Given a subport-gport, return teh corresponding mod-port 
   9739  * Parameters:
   9740  *      unit   - (IN) Device Number
   9741  *      subport_gport  - (IN) GPORT (generic port) identifier
   9742  *      module  - (OUT) Module associated with the subport
   9743  *      port  - (OUT) Port associated with the subport  
   9744  * Returns:
   9745  *      BCM_E_XXX
   9746  */
   9747 
   9748 int bcmi_kt2_subport_gport_modport_get(int unit,
   9749             bcm_gport_t subport_gport, bcm_module_t *module, bcm_port_t *port)
   9750 {
   9751     int pp_port = 0;
   9752 
   9753     if (!BCM_GPORT_IS_SUBPORT_PORT(subport_gport)) {
   9754         LOG_ERROR(BSL_LS_BCM_SUBPORT,
   9755                   (BSL_META_U(unit,
   9756                               "ERROR: gport 0x%x is not subport port gport\n"),
   9757                    subport_gport));
   9758         return BCM_E_PARAM;
   9759     }
   9760 
   9761     /* Extract the pp_port from the encoded gport and make sure it is valid */
   9762     pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_gport);
   9763 
   9764     if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_gport)) {
   9765         if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   9766             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9767                     (BSL_META_U(unit,
   9768                     "ERROR: SubTag subport port gport 0x%x not found\n"),
   9769                      subport_gport));
   9770             return BCM_E_NOT_FOUND;
   9771         }
   9772     } else if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_gport)) {
   9773         if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) {
   9774             LOG_VERBOSE(BSL_LS_BCM_SUBPORT,
   9775                     (BSL_META_U(unit,
   9776                     "ERROR: General subport port gport 0x%x not found\n"),
   9777                      subport_gport));
   9778             return BCM_E_NOT_FOUND;
   9779         }
   9780     }
   9781 
   9782     /* Get the mod-port that corresponds to this pp_port */
   9783     BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(unit,
   9784                           pp_port, module, port));
   9785 
   9786     return BCM_E_NONE;
   9787 }
   9788 
   9789 
   9790 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   9791 /*
   9792  * Function:
   9793  *      _bcm_kt2_subport_sw_dump
   9794  * Purpose:
   9795  *      Print Subport module s/w state
   9796  * Returns: 
   9797  *      void
   9798  */
   9799 void
   9800 _bcm_kt2_subport_sw_dump(int unit)
   9801 {
   9802     int idx;
   9803     int subport_group_max = SOC_INFO(unit).subport_group_max;
   9804 
   9805     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) {
   9806         LOG_CLI((BSL_META_U(unit,
   9807                            "Subtag Subport Groups: total (%d)\n"),
   9808                            _bcm_subtag_subport_group_count[unit]));
   9809 
   9810         for(idx = 0; idx < subport_group_max; idx++) {
   9811             if(_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, idx)) {
   9812                 LOG_CLI((BSL_META_U(unit, "%d "), idx));
   9813             }
   9814         }
   9815         LOG_CLI((BSL_META_U(unit, "\n")));
   9816         LOG_CLI((BSL_META_U(unit, "\n----\n")));
   9817     
   9818         LOG_CLI((BSL_META_U(unit,
   9819                             "Subtag Subport ids and pp_port used:\n")));
   9820         for (idx = 0; idx < SOC_MAX_NUM_PP_PORTS; idx++) {
   9821             if (_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, idx)) {
   9822                 LOG_CLI((BSL_META_U(unit,
   9823                      "group_gport = 0x%x, vlan = %d tcam_idx = %d\n"), 
   9824                      _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, idx),
   9825                      _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, idx),
   9826                      _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, idx)
   9827                     ));
   9828             }
   9829         }
   9830     } else {
   9831         LOG_CLI((BSL_META_U(unit,
   9832                             "Subtag Subports not enabled!!\n")));
   9833     }
   9834 
   9835     LOG_CLI((BSL_META_U(unit,
   9836                         "\n--**--\n")));
   9837 
   9838 
   9839     if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).linkphy_allowed_pbm)) {
   9840         LOG_CLI((BSL_META_U(unit,
   9841                             "Linkphy Subport Groups: total (%d)\n"),
   9842                             _bcm_linkphy_subport_group_count[unit]));
   9843         for(idx = 0; idx < SOC_INFO(unit).subport_group_max; idx++) {
   9844             if(_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, idx)) {
   9845                 LOG_CLI((BSL_META_U(unit, "%d "), idx));
   9846             }
   9847         }
   9848         LOG_CLI((BSL_META_U(unit, "\n")));
   9849         LOG_CLI((BSL_META_U(unit, "\n----\n")));
   9850     
   9851         LOG_CLI((BSL_META_U(unit,
   9852                             "Linkphy Subport ids and pp_port used:\n")));
   9853         for (idx = 0; idx < SOC_MAX_NUM_PP_PORTS; idx++) {
   9854             if (_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, idx)) {
   9855                 LOG_CLI((BSL_META_U(unit,
   9856                     "group_gport = 0x%x, streams(%d) = {%d, %d}\n"), 
   9857                     _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, idx),
   9858                     _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, idx),
   9859                     _bcm_linkphy_subport_port_info[unit][idx].ext_stream_idx[0],
   9860                     _bcm_linkphy_subport_port_info[unit][idx].ext_stream_idx[1]
   9861                     ));
   9862             }
   9863         }
   9864     } else {
   9865         LOG_CLI((BSL_META_U(unit,
   9866                             "Linkphy Subports not enabled!!\n")));
   9867     }
   9868 
   9869     return; 
   9870 }
   9871 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   9872 
   9873 #else  /* BCM_KATANA2_SUPPORT */
   9874 int bcm_esw_kt2_subport_not_empty;
   9875 #endif /* BCM_KATANA2_SUPPORT */
   9876 
   9877