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

trunk.c (175189B)


      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  * XGS3 Trunking (Ether and Fabric)
      8  */
      9 
     10 #include <soc/mem.h>
     11 #include <soc/firebolt.h>
     12 #include <shared/bsl.h>
     13 #include <bcm/error.h>
     14 #include <bcm/stack.h>
     15 
     16 #include <bcm_int/esw/l2.h>     /* MAC learn limit interaction */
     17 #include <bcm_int/esw/mbcm.h>
     18 #include <bcm_int/esw/link.h>   /* LAG failover support */
     19 #include <bcm_int/esw/stack.h>
     20 
     21 #include <bcm_int/esw/trunk.h>
     22 #include <bcm_int/esw_dispatch.h>
     23 #if defined(BCM_TRX_SUPPORT)
     24 #include <bcm_int/esw/trx.h>
     25 #endif /* BCM_TRX_SUPPORT */
     26 #if defined(BCM_GREYHOUND2_SUPPORT)
     27 #include <bcm_int/esw/vxlan.h>
     28 #endif /* BCM_GREYHOUND2_SUPPORT */
     29 
     30 #define _BCM_FP_TRUNK_NUM_MAX       128
     31 #define _BCM_FABRIC_TRUNK_NUM_MAX   16
     32 #define _BCM_FABRIC_TRUNK_SWF_TID_OFFSET         200
     33 #define _BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM  16
     34 #define _BCM_TRUNK_FAILOVER_PORT_NUM 8
     35 #define _BCM_HURRICANE2_TRUNK_FAILOVER_PORT_NUM  4
     36 
     37 /*
     38  * Trunk Membership Info
     39  */
     40 
     41 typedef struct {
     42     uint8  num_ports;
     43     uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT];
     44     uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT];
     45 #ifdef BCM_WARM_BOOT_SUPPORT
     46     uint8  recovered_from_scache;
     47 #endif /* BCM_WARM_BOOT_SUPPORT */
     48 } _xgs3_member_info_t;
     49 
     50 typedef struct {
     51     _xgs3_member_info_t member_info[1];
     52 } _xgs3_trunk_member_info_t;
     53 
     54 STATIC _xgs3_trunk_member_info_t *_xgs3_trunk_member_info[BCM_MAX_NUM_UNITS];
     55 
     56 #define MEMBER_INFO(_unit_, _tid_) (_xgs3_trunk_member_info[_unit_]->member_info[_tid_])
     57 
     58 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
     59 /*
     60  * Hardware Trunk Failover:
     61  *
     62  * For the devices which support hardware trunk failover, the failover
     63  * configuration must be retained if it is one of the standard models 
     64  * for the retrieval function to use the same encoding as the set function.
     65  *
     66  * Note: The trunk members stored in _xgs3_tinfo_t's modport array do not 
     67  *       include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set.
     68  */
     69 
     70 typedef struct {
     71     uint8         num_ports;
     72     uint8         psc[BCM_XGS3_TRUNK_MAX_PORTCNT];
     73     uint16        modport[BCM_XGS3_TRUNK_MAX_PORTCNT];
     74     uint32        flags[BCM_XGS3_TRUNK_MAX_PORTCNT];
     75 } _xgs3_hw_tinfo_t;
     76 
     77 typedef struct {
     78     _xgs3_hw_tinfo_t hw_tinfo[_BCM_FP_TRUNK_NUM_MAX + _BCM_FABRIC_TRUNK_NUM_MAX];
     79 } _xgs3_trunk_hwfail_t;
     80 
     81 STATIC _xgs3_trunk_hwfail_t *_xgs3_trunk_hwfail[BCM_MAX_NUM_UNITS];
     82 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
     83 
     84 /*
     85  * Software Trunk Failover:
     86  *
     87  * Even without hardware failover support, given the high speed link
     88  * change notification possible with XGS3 devices, a port that has been
     89  * indicated as link down can cause the trunk_group table to be immediately
     90  * updated with the link down port removed.  This works well for two cases:
     91  * (1) this is a higig trunk, or (2) the local device is the only device
     92  * in the system.
     93  * 
     94  * Note: The trunk members stored in _xgs3_tinfo_t's modport array do not 
     95  *       include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set.
     96  *       If a trunk member port is down, it'll be removed from _xg3_tinfo_t's
     97  *       modport array by _bcm_xgs3_trunk_swfailover_trigger.
     98  */
     99 typedef struct {
    100     uint8         rtag;
    101     uint8         num_ports;
    102     uint16        modport[BCM_XGS3_TRUNK_MAX_PORTCNT];
    103     uint32        member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT];
    104 } _xgs3_tinfo_t;
    105 
    106 typedef struct {
    107     uint8         mymodid;
    108     bcm_trunk_t   trunk[SOC_MAX_NUM_PORTS];       /* 0: unused;
    109                                                    1-129: ether;
    110                                                    200-207: higig */
    111     _xgs3_tinfo_t tinfo[_BCM_FP_TRUNK_NUM_MAX + _BCM_FABRIC_TRUNK_NUM_MAX];
    112 } _xgs3_trunk_swfail_t;
    113 
    114 
    115 STATIC _xgs3_trunk_swfail_t *_xgs3_trunk_swfail[BCM_MAX_NUM_UNITS];
    116 
    117 STATIC int _bcm_xgs3_trunk_swfailover_set(int unit,
    118                                           bcm_trunk_t tid,
    119                                           int rtag,
    120                                           int nports,
    121                                           int mods[BCM_XGS3_TRUNK_MAX_PORTCNT],
    122                                           int ports[BCM_XGS3_TRUNK_MAX_PORTCNT],
    123                                           uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]);
    124 
    125 STATIC int _bcm_xgs3_trunk_swfailover_fabric_set(int unit,
    126                                                  bcm_trunk_t hgtid,
    127                                                  int rtag,
    128                                                  bcm_pbmp_t ports);
    129 
    130 STATIC uint8 *_xgs3_mod_port_to_tid_map[BCM_MAX_NUM_UNITS];
    131 
    132 /* fields from TRUNK_GROUPm */
    133 static soc_field_t      _xgs_portf[8] = {
    134     PORT0f, PORT1f, PORT2f, PORT3f,
    135     PORT4f, PORT5f, PORT6f, PORT7f
    136 };
    137 
    138 static soc_field_t      _xgs_modulef[8] = {
    139     MODULE0f, MODULE1f, MODULE2f, MODULE3f,
    140     MODULE4f, MODULE5f, MODULE6f, MODULE7f
    141 };
    142 
    143 /* fields from FAST_TRUNK_GROUPm */
    144 static soc_field_t      _xgs_fast_portf[8] = {
    145     PORT_NUM_0f, PORT_NUM_1f, PORT_NUM_2f, PORT_NUM_3f,
    146     PORT_NUM_4f, PORT_NUM_5f, PORT_NUM_6f, PORT_NUM_7f
    147 };
    148 
    149 static soc_field_t      _xgs_fast_modulef[8] = {
    150     MODULE_ID_0f, MODULE_ID_1f, MODULE_ID_2f, MODULE_ID_3f,
    151     MODULE_ID_4f, MODULE_ID_5f, MODULE_ID_6f, MODULE_ID_7f
    152 };
    153 
    154 /* fields from HIGIG_TRUNK_GROUPr */
    155 static soc_field_t      _hg_trunk0f[4] = {
    156     HIGIG_TRUNK_ID0_PORT0f, HIGIG_TRUNK_ID0_PORT1f,
    157     HIGIG_TRUNK_ID0_PORT2f, HIGIG_TRUNK_ID0_PORT3f
    158 };
    159 
    160 static soc_field_t      _hg_trunk1f[4] = {
    161     HIGIG_TRUNK_ID1_PORT0f, HIGIG_TRUNK_ID1_PORT1f,
    162     HIGIG_TRUNK_ID1_PORT2f, HIGIG_TRUNK_ID1_PORT3f
    163 };
    164 
    165 /* fields from HIGIG_TRUNK_CONTROLr */
    166 static soc_field_t _hg_cntl0f[4] = {
    167     HIGIG_TRUNK_ID0f, HIGIG_TRUNK_ID1f,
    168     HIGIG_TRUNK_ID2f, HIGIG_TRUNK_ID3f
    169 };
    170 
    171 static soc_field_t _hg_cntl1f[4] = {
    172     HIGIG_TRUNK0f, HIGIG_TRUNK1f,
    173     HIGIG_TRUNK2f, HIGIG_TRUNK3f
    174 };
    175 
    176 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
    177 /* fields from HG_TRUNK_GROUPr */
    178 /* Enduro has only 4 fields. Not 8. They will be checked in the executable code */
    179 static soc_field_t _hg_trunk[8] = {
    180     HIGIG_TRUNK_PORT0f, HIGIG_TRUNK_PORT1f,
    181     HIGIG_TRUNK_PORT2f, HIGIG_TRUNK_PORT3f,
    182     HIGIG_TRUNK_PORT4f, HIGIG_TRUNK_PORT5f,
    183     HIGIG_TRUNK_PORT6f, HIGIG_TRUNK_PORT7f
    184 };
    185 #endif /* BCM_TRX_SUPPORT */
    186 #if defined(BCM_SCORPION_SUPPORT)
    187 /* fields from HG_TRUNK_GROUP_HIr */
    188 static soc_field_t _hg_trunk_hi[8] = {
    189     HIGIG_TRUNK_PORT8f, HIGIG_TRUNK_PORT9f,
    190     HIGIG_TRUNK_PORT10f, HIGIG_TRUNK_PORT11f,
    191     HIGIG_TRUNK_PORT12f, HIGIG_TRUNK_PORT13f,
    192     HIGIG_TRUNK_PORT14f, HIGIG_TRUNK_PORT15f
    193 };
    194 #endif /* BCM_SCORPION_SUPPORT */
    195 
    196 /*
    197  * Function:
    198  *      _bcm_xgs3_trunk_member_init
    199  * Purpose:
    200  *      Initialize trunk member info.
    201  * Parameters:
    202  *      unit - (IN)SOC unit number. 
    203  * Returns:
    204  *      BCM_X_XXX
    205  */
    206 int
    207 _bcm_xgs3_trunk_member_init(int unit)
    208 {
    209     int trunk_num_groups = _BCM_FP_TRUNK_NUM_MAX + _BCM_FABRIC_TRUNK_NUM_MAX;
    210 
    211 #ifdef BCM_TOMAHAWK_SUPPORT
    212     if (soc_feature(unit, soc_feature_fastlag)) {
    213         trunk_num_groups = soc_mem_index_count(unit, FAST_TRUNK_GROUPm) +
    214                            soc_mem_index_count(unit, HG_TRUNK_GROUPm);
    215     }
    216 #endif
    217 
    218     if (_xgs3_trunk_member_info[unit] == NULL) {
    219         _xgs3_trunk_member_info[unit] =
    220             sal_alloc((sizeof(_xgs3_trunk_member_info_t) * trunk_num_groups),
    221                     "_xgs3_trunk_member_info");
    222 
    223         if (_xgs3_trunk_member_info[unit] == NULL) {
    224             return BCM_E_MEMORY;
    225         }
    226     }
    227 
    228     sal_memset(_xgs3_trunk_member_info[unit], 0,
    229                 (sizeof(_xgs3_trunk_member_info_t) * trunk_num_groups));
    230     return BCM_E_NONE;
    231 }
    232 
    233 /*
    234  * Function:
    235  *      _bcm_xgs3_trunk_member_detach
    236  * Purpose:
    237  *      De-allocate trunk member info.
    238  * Parameters:
    239  *      unit - (IN)SOC unit number. 
    240  * Returns:
    241  *      None
    242  */
    243 void
    244 _bcm_xgs3_trunk_member_detach(int unit)
    245 {
    246     if (_xgs3_trunk_member_info[unit] != NULL) {
    247         sal_free(_xgs3_trunk_member_info[unit]);
    248         _xgs3_trunk_member_info[unit] = NULL;
    249     }
    250 }
    251 
    252 /*
    253  * Function:
    254  *      _bcm_xgs3_trunk_mod_port_map_set
    255  * Purpose:
    256  *      Set  (mod, port) to  trunk id map.
    257  *      Map implements a software cache for the SOURCE_TRUNK_MAP_TABLE.
    258  * Parameters:
    259  *      unit     -  (IN) BCM device number. 
    260  *      modid    -  (IN) Member port module id.  
    261  *      port     -  (IN) Member port number.  
    262  *      trunk_id -  (IN) Trunk number or negative value for reset.  
    263  * Returns:
    264  *      BCM_X_XXX
    265  */
    266 STATIC int 
    267 _bcm_xgs3_trunk_mod_port_map_set(int unit, bcm_module_t modid, 
    268                                  bcm_port_t port, bcm_trunk_t trunk_id)  
    269 {
    270 
    271     int   idx;               /* Map array index. */
    272 
    273     if (NULL == _xgs3_mod_port_to_tid_map[unit]) {
    274         return (BCM_E_INIT);
    275     }
    276 
    277     /* Trunk id range check. */
    278     if (trunk_id >= 0xff) {
    279         return (BCM_E_INTERNAL);
    280     }
    281 
    282     idx = modid * SOC_MAX_NUM_PORTS + port;
    283     if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 
    284         return (BCM_E_PARAM);
    285     }
    286 
    287     _xgs3_mod_port_to_tid_map[unit][idx] = (trunk_id < 0) ? 0 : (++trunk_id);
    288 
    289     return (BCM_E_NONE);
    290 }
    291 
    292 /*
    293  * Function:
    294  *      _bcm_xgs3_trunk_mod_port_map_get
    295  * Purpose:
    296  *      Read mapping (mod, port) to trunk id from software cache 
    297  *      for the SOURCE_TRUNK_MAP_TABLE.
    298  * Parameters:
    299  *      unit     -  (IN) BCM device number. 
    300  *      modid    -  (IN) Member port module id.  
    301  *      port     -  (IN) Member port number.  
    302  *      trunk_id -  (OUT) Trunk number or negative value for reset.  
    303  * Returns:
    304  *      BCM_X_XXX
    305  */
    306 STATIC int 
    307 _bcm_xgs3_trunk_mod_port_map_get(int unit, bcm_module_t modid, 
    308                                  bcm_port_t port, bcm_trunk_t *trunk_id)  
    309 {
    310 
    311     int              idx;      /* Map array index.         */
    312     bcm_module_t     mymodid;  /* Local module id.         */
    313     int              isLocal;  /* Local module id flag.    */
    314     int              rv;       /* Operation return status. */
    315 
    316     if (NULL == _xgs3_mod_port_to_tid_map[unit]) {
    317         return (BCM_E_INIT);
    318     }
    319 
    320     rv = _bcm_esw_modid_is_local(unit, modid, &isLocal);
    321     BCM_IF_ERROR_RETURN(rv);
    322 
    323     if (isLocal) {
    324         rv = bcm_esw_stk_my_modid_get(unit, &mymodid);
    325         BCM_IF_ERROR_RETURN(rv);
    326         if (mymodid != modid) {
    327             modid = mymodid;
    328             port += 32;
    329         }
    330     }
    331 
    332     idx = modid * SOC_MAX_NUM_PORTS + port;
    333     if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 
    334         return (BCM_E_PARAM);
    335     }
    336 
    337     *trunk_id = _xgs3_mod_port_to_tid_map[unit][idx] - 1;
    338 
    339     return (_xgs3_mod_port_to_tid_map[unit][idx]) ? BCM_E_NONE : BCM_E_NOT_FOUND;
    340 }
    341 
    342 
    343 /*
    344  * Function:
    345  *      _bcm_xgs3_trunk_mod_port_map_init
    346  * Purpose:
    347  *      Initialize a software cache for the SOURCE_TRUNK_MAP_TABLE.
    348  * Parameters:
    349  *      unit     -  (IN)SOC unit number. 
    350  * Returns:
    351  *      BCM_X_XXX
    352  */
    353 int 
    354 _bcm_xgs3_trunk_mod_port_map_init(int unit) 
    355 {
    356 
    357     int   mem_size;  /* Allocated memory size. */
    358     uint8 *ptr;      /* Allocation pointer.    */
    359 
    360     if (NULL != _xgs3_mod_port_to_tid_map[unit]) {
    361         _bcm_xgs3_trunk_mod_port_map_deinit(unit);
    362     }
    363 
    364     /* Allocated mapping array. */
    365     mem_size =  _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit) * sizeof(uint8);
    366     ptr = sal_alloc(mem_size, "Mod_Port_Trunk");
    367     if (NULL == ptr) {
    368         return (BCM_E_MEMORY);
    369     }
    370     /* Reset allocated buffer. */
    371     sal_memset(ptr, 0, mem_size);
    372 
    373     _xgs3_mod_port_to_tid_map[unit] = ptr;
    374 
    375     return (BCM_E_NONE);
    376 }
    377 
    378 /*
    379  * Function:
    380  *      _bcm_xgs3_trunk_mod_port_map_deinit
    381  * Purpose:
    382  *      Deinitialize a software cache for the SOURCE_TRUNK_MAP_TABLE.
    383  * Parameters:
    384  *      unit     -  (IN)SOC unit number. 
    385  * Returns:
    386  *      BCM_X_XXX
    387  */
    388 int 
    389 _bcm_xgs3_trunk_mod_port_map_deinit(int unit) 
    390 {
    391     void *ptr;
    392 
    393     ptr = (void *)_xgs3_mod_port_to_tid_map[unit];
    394 	
    395     _xgs3_mod_port_to_tid_map[unit] = NULL;
    396 
    397     if (NULL != ptr) {
    398        	sal_free(ptr);
    399     }
    400     return (BCM_E_NONE);
    401 }
    402 
    403 
    404 #if defined (BCM_WARM_BOOT_SUPPORT)
    405 #ifdef BCM_HURRICANE3_SUPPORT
    406 /*
    407  * Function:
    408  *      _bcm_xgs3_trunk_mod_port_map_reinit
    409  * Purpose:
    410  *      Reinitialize the software cache for the SOURCE_TRUNK_MAP_TABLE.
    411  *      Recover trunk members with egress disable flag set.
    412  * Parameters:
    413  *      unit - (IN) SOC unit number. 
    414  *      mod - (IN) Module ID.
    415  *      base_index - (IN) Module ID's base index.
    416  *      num_ports - (IN) Number of ports in the given module.
    417  * Returns:
    418  *      BCM_X_XXX
    419  * Notes:
    420  *      This function is called during stacking module reinit, since
    421  *      the number of ports in a given module is not known until then.
    422  */
    423 int 
    424 _bcm_xgs3_trunk_mod_port_map_reinit(int unit, bcm_module_t mod,
    425         int base_index, int num_ports) 
    426 {
    427     bcm_port_t port;
    428     int	rv = BCM_E_NONE;
    429     source_trunk_map_table_entry_t stm; 
    430     int port_type;
    431     bcm_trunk_t tid;
    432     int array_size;
    433     bcm_module_t *mod_array = NULL;
    434     bcm_port_t *port_array = NULL;
    435     uint32 *flags_array = NULL;
    436     int i, found;
    437 
    438     if (!soc_feature(unit, soc_feature_src_modid_base_index)) {
    439         return BCM_E_UNAVAIL;
    440     }
    441 
    442     /*
    443      * Recover from SOURCE_TRUNK_MAP tables.
    444      */
    445     for (port = 0; port < num_ports; port++) {
    446 
    447         rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
    448                 base_index + port, &stm);
    449         if (BCM_FAILURE(rv)) {
    450             return rv;
    451         }
    452 
    453         port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm,
    454                 PORT_TYPEf);
    455         if (port_type != 1) {
    456             continue;
    457         }
    458 
    459         tid = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, TGIDf);
    460 
    461         /* Recover source trunk map cache */
    462         rv = _bcm_xgs3_trunk_mod_port_map_set(unit, mod, port, tid);  
    463         if (BCM_FAILURE(rv)) {
    464             return rv;
    465         }
    466 
    467         /* Allocate arrays that can accommodate an additional member,
    468          * in case a new member needs to be added to the trunk group.
    469          */
    470         array_size = MEMBER_INFO(unit, tid).num_ports + 1;
    471         mod_array = sal_alloc(sizeof(bcm_module_t) * array_size, "mod_array");
    472         if (mod_array == NULL) {
    473             return BCM_E_MEMORY;
    474         }
    475         sal_memset(mod_array, 0, sizeof(bcm_module_t) * array_size); 
    476 
    477         port_array = sal_alloc(sizeof(bcm_port_t) * array_size, "port_array");
    478         if (port_array == NULL) {
    479             sal_free(mod_array);
    480             return BCM_E_MEMORY;
    481         }
    482         sal_memset(port_array, 0, sizeof(bcm_port_t) * array_size); 
    483 
    484         flags_array = sal_alloc(sizeof(uint32) * array_size, "flags_array");
    485         if (flags_array == NULL) {
    486             sal_free(mod_array);
    487             sal_free(port_array);
    488             return BCM_E_MEMORY;
    489         }
    490         sal_memset(flags_array, 0, sizeof(uint32) * array_size); 
    491 
    492         /* Try to find mod-port in the trunk group */
    493         found = 0; 
    494         for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    495             mod_array[i] = MEMBER_INFO(unit, tid).modport[i] >> 8;
    496             port_array[i] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
    497             flags_array[i] = MEMBER_INFO(unit, tid).member_flags[i];
    498             if (port_array[i] == port && mod_array[i] == mod) {
    499                 found = 1;
    500                 break;
    501             }
    502         }
    503 
    504         /* If the mod-port was not found, then add it with
    505          * EGRESS_DISABLE flag set.
    506          */  
    507         if (!found && !MEMBER_INFO(unit, tid).recovered_from_scache) {
    508             /* Find where to insert */
    509             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    510                 if (port > port_array[i] || mod != mod_array[i]) {
    511                     continue;
    512                 } 
    513                 break;
    514             }
    515 
    516             /* Insert at the required location in sw state */
    517             mod_array[i] = mod;
    518             port_array[i] = port;
    519             flags_array[i] |= BCM_TRUNK_MEMBER_EGRESS_DISABLE;
    520 
    521             /* Copy remaining members as is */
    522             for (; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    523                 mod_array[i+1] = MEMBER_INFO(unit, tid).modport[i] >> 8;
    524                 port_array[i+1] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
    525                 flags_array[i+1] = MEMBER_INFO(unit, tid).member_flags[i];
    526             }
    527 
    528             MEMBER_INFO(unit, tid).num_ports++;
    529 
    530             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    531                 MEMBER_INFO(unit, tid).modport[i] = (mod_array[i] << 8) |
    532                     port_array[i];
    533                 MEMBER_INFO(unit, tid).member_flags[i] = flags_array[i];
    534             }
    535         } 
    536 
    537         sal_free(mod_array);
    538         mod_array = NULL;
    539         sal_free(port_array);
    540         port_array = NULL;
    541         sal_free(flags_array);
    542         flags_array = NULL;
    543     }
    544 
    545     return rv;
    546 }
    547 #endif /* BCM_HURRICANE3_SUPPORT */
    548 
    549 /*
    550  * Function:
    551  *      _xgs3_trunk_mod_port_map_reinit
    552  * Purpose:
    553  *      Reinitialize a software cache for the SOURCE_TRUNK_MAP_TABLE.
    554  * Parameters:
    555  *      unit     -  (IN)SOC unit number. 
    556  * Returns:
    557  *      BCM_X_XXX
    558  */
    559 STATIC int 
    560 _xgs3_trunk_mod_port_map_reinit(int unit) 
    561 {
    562     source_trunk_map_table_entry_t  stm;  /* Hw entry buffer.        */
    563     soc_mem_t        mem;                 /* Hw table memory.        */
    564     int              idx;                 /* Hw table iterator index.*/
    565     int              idx_max;             /* Hw table index max.     */
    566     uint32           valid;               /* Trunk valid indicator.  */
    567     bcm_trunk_t	     tid;                 /* Trunk id.               */
    568     bcm_module_t     modid;               /* Member module id.       */
    569     bcm_port_t       port;                /* Member port id.         */
    570     int	             rv = BCM_E_NONE;     /* Operation return status.*/
    571     bcm_module_t     om[BCM_XGS3_TRUNK_MAX_PORTCNT]; /* new mod list */
    572     bcm_port_t       op[BCM_XGS3_TRUNK_MAX_PORTCNT]; /* new port list */
    573     uint32           of[BCM_XGS3_TRUNK_MAX_PORTCNT]; /* new flag list */
    574     int              i, found;
    575     soc_field_t      tid_fld = TGIDf;
    576 
    577     if (soc_feature(unit, soc_feature_src_tgid_valid)) {
    578         tid_fld = SRC_TGIDf;
    579     }
    580     /* Initialize mod, port to trunk id array. */
    581     BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_mod_port_map_init(unit)); 
    582 
    583     /*
    584      * Iterate over all trunk map entries & populate valid 
    585      * entries into sw mod, port to trunk id map array.
    586      */
    587     mem = SOURCE_TRUNK_MAP_TABLEm;
    588     idx_max = soc_mem_index_max(unit,mem);
    589 
    590     soc_mem_lock(unit, mem);
    591     for (idx = soc_mem_index_min(unit, mem); idx <= idx_max; idx++) {
    592         /* Read  hw entry. */
    593         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &stm);
    594         if (BCM_FAILURE(rv)) {
    595             break;
    596         }
    597 
    598         /* Check if trunk id is valid. */
    599         valid = soc_mem_field32_get(unit, mem, (uint32 *)&stm, PORT_TYPEf);
    600         if (0 == valid) {
    601             continue;
    602         }
    603 
    604         tid = soc_mem_field32_get(unit, mem, (uint32 *)&stm, tid_fld);
    605 
    606         /* Translate index into modid port.  */
    607 #ifdef BCM_TRX_SUPPORT
    608         if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    609             modid = idx / (SOC_PORT_ADDR_MAX(unit) + 1);
    610             port = idx - modid * (SOC_PORT_ADDR_MAX(unit) + 1);
    611         } else
    612 #endif
    613             {
    614                 modid = idx >> SOC_TRUNK_BIT_POS(unit);
    615                 port = idx - (modid << SOC_TRUNK_BIT_POS(unit));
    616             }
    617         rv =  _bcm_xgs3_trunk_mod_port_map_set(unit, modid, port, tid);  
    618         if (BCM_FAILURE(rv)) {
    619             break;
    620         }
    621 
    622         /* Compare values with trunk groups to recreate egress disable flag */        
    623         found = 0; 
    624         for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    625             om[i] = MEMBER_INFO(unit, tid).modport[i] >> 8;
    626             op[i] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
    627             of[i] = MEMBER_INFO(unit, tid).member_flags[i];
    628             if (op[i] == port && om[i] == modid) {
    629                 found = 1;
    630                 break;
    631             }
    632         }
    633 
    634         /* If the mod-port was not found, and if member info was not recovered
    635          * from scache, then add the mod-port to member info
    636          */  
    637         if (!found && !MEMBER_INFO(unit, tid).recovered_from_scache) {
    638             /* Find where to insert */
    639             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    640                 if (port > op[i] || modid != om[i]) {
    641                     continue;
    642                 } 
    643                 break;
    644             }
    645 
    646             /* Insert at the required location in sw state */
    647             om[i] = modid;
    648             op[i] = port;
    649             of[i] = BCM_TRUNK_MEMBER_EGRESS_DISABLE;
    650 
    651             /* Copy remaining values as is */
    652             for (; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    653                 /* sw state */ 
    654                 op[i+1] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
    655                 om[i+1] = MEMBER_INFO(unit, tid).modport[i] >> 8;
    656                 of[i+1] = MEMBER_INFO(unit, tid).member_flags[i];
    657             }
    658 
    659             MEMBER_INFO(unit, tid).num_ports++;
    660             for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
    661                  MEMBER_INFO(unit, tid).modport[i] = (om[i] << 8) | op[i];
    662                  MEMBER_INFO(unit, tid).member_flags[i] = of[i];
    663             }
    664         } 
    665     }
    666 
    667     soc_mem_unlock(unit, mem);
    668 
    669     return rv;
    670 }
    671 #endif /* BCM_WARM_BOOT_SUPPORT */
    672 
    673 /*
    674  * Mark a mod/port pair as being in a particular trunk (or not)
    675  * A negative tid sets the mod/port back to non-trunk status.
    676  */
    677 STATIC int
    678 _bcm_xgs3_trunk_set_port_property(int unit,
    679                                   bcm_module_t mod,
    680                                   bcm_port_t port,
    681                                   int tid)
    682 {
    683     source_trunk_map_table_entry_t  stm;
    684     soc_mem_t        mem;
    685     int              idx, rv, ptype_get, ptype_set, tid_get, tid_set;
    686     soc_field_t      tid_fld = TGIDf;
    687 
    688     if (soc_feature(unit, soc_feature_src_tgid_valid)) {
    689         tid_fld = SRC_TGIDf;
    690     }
    691 
    692     if (tid < 0) {
    693         ptype_set = 0;                /* normal port */
    694         tid_set = 0;
    695     } else {
    696         ptype_set = 1;                /* trunk port */
    697         tid_set = tid;
    698     }
    699 
    700     BCM_IF_ERROR_RETURN
    701         (_bcm_esw_src_mod_port_table_index_get(unit, mod, port, &idx));
    702 
    703     mem = SOURCE_TRUNK_MAP_TABLEm;
    704     soc_mem_lock(unit, mem);
    705     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &stm);
    706     if (BCM_SUCCESS(rv)) {
    707         ptype_get = soc_mem_field32_get(unit, mem, (uint32 *)&stm, PORT_TYPEf);
    708         tid_get = soc_mem_field32_get(unit, mem, (uint32 *)&stm, tid_fld);
    709         if ((ptype_get != ptype_set) || (tid_get != tid_set)) {
    710             soc_mem_field32_set(unit, mem, (uint32 *)&stm,
    711                                 PORT_TYPEf, ptype_set);
    712             soc_mem_field32_set(unit, mem, (uint32 *)&stm,
    713                                 tid_fld, tid_set);
    714             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &stm);
    715         }
    716     }
    717     soc_mem_unlock(unit, mem);
    718 
    719     /* Update SW module, port to tid mapping. */
    720     if (BCM_SUCCESS(rv)) {
    721         rv = _bcm_xgs3_trunk_mod_port_map_set(unit, mod, port, tid);  
    722     }
    723 
    724     return rv;
    725 }
    726 
    727 int
    728 _bcm_xgs3_trunk_get_port_property(int unit,
    729                                   bcm_module_t mod,
    730                                   bcm_port_t port,
    731                                   int *tid)
    732 {
    733     return  _bcm_xgs3_trunk_mod_port_map_get(unit, mod, port, tid);  
    734 }
    735 
    736 /*
    737  * Function:
    738  *      _bcm_xgs3_trunk_fabric_find
    739  * Description:
    740  *      Get fabric trunk id that contains the given Higig port
    741  * Parameters:
    742  *      unit    - Unit number
    743  *      port    - Port number
    744  *      tid     - (OUT) Fabric trunk id
    745  * Returns:
    746  *      BCM_E_xxxx
    747  */
    748 int
    749 _bcm_xgs3_trunk_fabric_find(int unit,
    750                             bcm_port_t port,
    751                             int *tid)
    752 {
    753     bcm_trunk_chip_info_t chip_info;
    754     int                   num_hg_trunk_groups;
    755     int                   hgtid;
    756     pbmp_t                hg_pbmp, pbmp;
    757 
    758     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
    759     if (chip_info.trunk_fabric_id_min == -1) {
    760         return BCM_E_NOT_FOUND;
    761     } else {
    762         num_hg_trunk_groups = chip_info.trunk_fabric_id_max - 
    763                               chip_info.trunk_fabric_id_min + 1;
    764     }
    765 
    766     if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) &&
    767         soc_feature(unit, soc_feature_hg_trunking)) {
    768         uint32      val;
    769         soc_field_t bmapf;
    770 
    771         SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_CONTROLr(unit, &val));
    772         for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) {
    773             switch (hgtid) {
    774                 case 0:
    775                     bmapf = HIGIG_TRUNK_BITMAP0f;
    776                     break;
    777                 case 1:
    778                     bmapf = HIGIG_TRUNK_BITMAP1f;
    779                     break;
    780                 default:
    781                     return BCM_E_INTERNAL;
    782             }
    783 
    784             SOC_PBMP_CLEAR(hg_pbmp);
    785             SOC_PBMP_WORD_SET(hg_pbmp, 0,
    786                               soc_reg_field_get(unit, HIGIG_TRUNK_CONTROLr,
    787                                                 val, bmapf));
    788             SOC_PBMP_CLEAR(pbmp);
    789             if (SOC_IS_RAVEN(unit)) {
    790                 /* For Raven, use the bitmap directly */
    791                 SOC_PBMP_ASSIGN(pbmp, hg_pbmp);
    792             } else {
    793                 /* For other FBX, convert to the physical bitmap */
    794                 SOC_IF_ERROR_RETURN
    795                     (soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp));
    796             } 
    797             if (SOC_PBMP_MEMBER(pbmp, port)) {
    798                 *tid = hgtid + chip_info.trunk_fabric_id_min;
    799                 return BCM_E_NONE;
    800             }
    801         }
    802         return BCM_E_NOT_FOUND;
    803     }
    804 #if defined(BCM_TRIUMPH2_SUPPORT)
    805     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
    806         SOC_IS_VALKYRIE2(unit)) {
    807         uint64        val64;
    808 
    809         for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) {
    810             SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64));
    811             SOC_PBMP_CLEAR(hg_pbmp);
    812             SOC_PBMP_WORD_SET(hg_pbmp, 0,
    813                               soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
    814                                                     val64, HIGIG_TRUNK_BITMAP_LOf));
    815             SOC_PBMP_WORD_SET(hg_pbmp, 1,
    816                               soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
    817                                                     val64, HIGIG_TRUNK_BITMAP_HIf));
    818             if (SOC_PBMP_MEMBER(hg_pbmp, port)) {
    819                 *tid = hgtid + chip_info.trunk_fabric_id_min;
    820                 return BCM_E_NONE;
    821             }
    822         }
    823         return BCM_E_NOT_FOUND;
    824     }
    825 #endif /* BCM_TRIUMPH2_SUPPORT */
    826 #ifdef BCM_GREYHOUND2_SUPPORT
    827     if (soc_feature(unit, soc_feature_high_portcount_register)) {
    828         uint64        val64, hg_trunk_bmap_f;
    829 
    830         for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) {
    831             SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64));
    832             hg_trunk_bmap_f =
    833                 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr,
    834                                     val64, HIGIG_TRUNK_BITMAPf);
    835 
    836             SOC_PBMP_CLEAR(hg_pbmp);
    837             SOC_PBMP_WORD_SET(hg_pbmp, 0, COMPILER_64_LO(hg_trunk_bmap_f));
    838             SOC_PBMP_WORD_SET(hg_pbmp, 1, COMPILER_64_HI(hg_trunk_bmap_f));
    839 
    840             SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64));
    841             hg_trunk_bmap_f =
    842                 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr,
    843                                     val64, HIGIG_TRUNK_BITMAPf);
    844 
    845             SOC_PBMP_WORD_SET(hg_pbmp, 2, COMPILER_64_LO(hg_trunk_bmap_f));
    846 
    847             if (SOC_PBMP_MEMBER(hg_pbmp, port)) {
    848                 *tid = hgtid + chip_info.trunk_fabric_id_min;
    849                 return BCM_E_NONE;
    850             }
    851         }
    852         return BCM_E_NOT_FOUND;
    853     }
    854 #endif /* BCM_GREYHOUND2_SUPPORT */
    855 #if defined(BCM_BRADLEY_SUPPORT)
    856     if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) {
    857         uint32       val;
    858 
    859         for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) {
    860             SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAPr(unit, hgtid, &val));
    861             SOC_PBMP_CLEAR(hg_pbmp);
    862             SOC_PBMP_WORD_SET(hg_pbmp, 0,
    863                               soc_reg_field_get(unit, HG_TRUNK_BITMAPr,
    864                                                 val, HIGIG_TRUNK_BITMAPf));
    865             SOC_PBMP_CLEAR(pbmp);
    866             soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp);
    867             if (SOC_PBMP_MEMBER(pbmp, port)) {
    868                 *tid = hgtid + chip_info.trunk_fabric_id_min;
    869                 return BCM_E_NONE;
    870             }
    871         }
    872         return BCM_E_NOT_FOUND;
    873     }
    874 #endif /* BCM_BRADLEY_SUPPORT */
    875 
    876     return BCM_E_UNAVAIL;
    877 }
    878 
    879 /*
    880  * Update the trunk block mask table.
    881  * Old ports are cleared and new ports are added to each entry.
    882  * Each hash index location entry is owned by a specific unit/modid
    883  * across all units in a stack. Hash index location entry owned by
    884  * local unit/modid is provided by my_modid_bmap. member_count is
    885  * the number of NUC forwarding eligible ports in the trunk group.
    886  * Each eligible entry also has a rolling port that is not masked
    887  * from among the new NUC forwarding eligible ports (nuc_ports).
    888  * This is what spreads non-unicast traffic across multiple ports.
    889  */
    890 STATIC int
    891 _bcm_xgs3_trunk_block_mask(int unit,
    892                            pbmp_t old_ports,
    893                            pbmp_t new_ports,
    894                            pbmp_t nuc_ports,
    895                            uint32 my_modid_bmap,
    896                            uint32 member_count)
    897 {
    898     bcm_port_t        port;
    899     int                localcount, localports[BCM_XGS3_TRUNK_MAX_PORTCNT];
    900     int                index_count, max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT;
    901 
    902     localcount = 0;
    903 #if defined(BCM_SCORPION_SUPPORT)
    904     if (SOC_IS_SC_CQ(unit)) {
    905         max_ports = BCM_XGS3_TRUNK_MAX_PORTCNT;
    906     }
    907 #endif
    908     if (SOC_PBMP_NOT_NULL(nuc_ports)) {
    909         PBMP_ITER(nuc_ports, port) {
    910             localports[localcount++] = port;
    911             if (localcount >= max_ports) {
    912                 break;
    913             }
    914         }
    915     }
    916 
    917 #if defined(BCM_FIREBOLT_SUPPORT)
    918     if (SOC_IS_FBX(unit)) {
    919         int                   i, imax, rv;
    920         soc_mem_t             mem;
    921         nonucast_trunk_block_mask_entry_t mask_entry;
    922         bcm_pbmp_t            pbmp, old_pbmp;
    923 
    924         rv = BCM_E_NONE;
    925         mem = NONUCAST_TRUNK_BLOCK_MASKm;
    926         i = soc_mem_index_min(unit, mem);
    927         imax = soc_mem_index_max(unit, mem);
    928         soc_mem_lock(unit, mem);
    929         index_count = 0;
    930         for (; i <= imax; i++) {
    931             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, &mask_entry);
    932             if (rv < 0) {
    933                 break;
    934             }
    935             soc_mem_pbmp_field_get(unit, mem, &mask_entry, BLOCK_MASKf, &pbmp);
    936             old_pbmp = pbmp;
    937             SOC_PBMP_REMOVE(pbmp, old_ports);
    938             SOC_PBMP_OR(pbmp, new_ports);
    939             if (localcount > 0) {
    940                 if ((i % 16) == 0) {
    941                     /* On Firebolt, NONUCAST_TRUNK_BLOCK_MASK contains 16
    942                      * entries. On Triumph, there are 64 entries, separated
    943                      * into 4 regions: IPMC, L2MC, broadcast, and unknown
    944                      * packets. To make Firebolt interoperate with Triumph,
    945                      * the index_count needs to be reset every 16 entries.
    946                      */
    947                     index_count = 0;
    948                 }
    949                 if (my_modid_bmap & (1 << ((i & 0xf) % member_count)))  {
    950                     SOC_PBMP_PORT_REMOVE(pbmp, localports[index_count % localcount]);
    951                     index_count++;
    952                 }
    953             }
    954             if (SOC_PBMP_EQ(pbmp, old_pbmp)) {
    955                 continue;
    956             }
    957             soc_mem_pbmp_field_set(unit, mem, &mask_entry, BLOCK_MASKf, &pbmp);
    958             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &mask_entry);
    959             if (rv < 0) {
    960                 break;
    961             }
    962         }
    963         soc_mem_unlock(unit, mem);
    964         return rv;
    965     }
    966 #endif /* BCM_FIREBOLT_SUPPORT */
    967 
    968     return BCM_E_NONE;
    969 }
    970 
    971 STATIC int
    972 _bcm_xgs3_trunk_psc_to_rtag(int unit, int psc, int *rtag)
    973 {
    974     switch (psc) {
    975     case BCM_TRUNK_PSC_SRCMAC:
    976     case BCM_TRUNK_PSC_DSTMAC:
    977     case BCM_TRUNK_PSC_SRCDSTMAC:
    978     case BCM_TRUNK_PSC_SRCIP:
    979     case BCM_TRUNK_PSC_DSTIP:
    980     case BCM_TRUNK_PSC_SRCDSTIP:
    981         /* These BCM_TRUNK_PSC_ values match the hardware RTAG values */
    982         *rtag = psc;
    983         break;
    984     case BCM_TRUNK_PSC_PORTINDEX:
    985         if (!soc_feature(unit, soc_feature_port_trunk_index)) {
    986             return BCM_E_PARAM;
    987         }
    988         *rtag = 7;
    989         break;
    990     case BCM_TRUNK_PSC_PORTFLOW:
    991         if (!soc_feature(unit, soc_feature_port_flow_hash)) {
    992             return BCM_E_PARAM;
    993         }
    994         *rtag = 7;
    995         break;
    996     case BCM_TRUNK_PSC_DYNAMIC:
    997     case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED:
    998     case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL:
    999         *rtag = 7;
   1000         if (SOC_IS_ENDURO(unit)) {
   1001            if (!soc_feature(unit, soc_feature_lag_dlb)) {
   1002                return BCM_E_UNAVAIL;
   1003            }
   1004         }
   1005        break;
   1006     default:
   1007         return BCM_E_PARAM;
   1008     }
   1009 
   1010     if ((*rtag == 7) && 
   1011         (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))) {
   1012         /* Hurricanex/Greyhound don't support enhanced hashing */
   1013         return BCM_E_PARAM;
   1014     }
   1015 
   1016     return BCM_E_NONE;
   1017 }
   1018 
   1019 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   1020 int
   1021 _bcm_xgs3_trunk_hwfailover_init(int unit)
   1022 {
   1023     if (_xgs3_trunk_hwfail[unit] == NULL) {
   1024         _xgs3_trunk_hwfail[unit] = sal_alloc(sizeof(_xgs3_trunk_hwfail_t), 
   1025                                              "_xgs3_trunk_hwfail");
   1026         if (_xgs3_trunk_hwfail[unit] == NULL) {
   1027             return BCM_E_MEMORY;
   1028         }
   1029     }
   1030     sal_memset(_xgs3_trunk_hwfail[unit], 0, sizeof(_xgs3_trunk_hwfail_t));
   1031     return BCM_E_NONE;
   1032 }
   1033 
   1034 void
   1035 _bcm_xgs3_trunk_hwfailover_detach(int unit)
   1036 {
   1037     if (_xgs3_trunk_hwfail[unit] != NULL) {
   1038         sal_free(_xgs3_trunk_hwfail[unit]);
   1039         _xgs3_trunk_hwfail[unit] = NULL;
   1040     }
   1041 }
   1042 
   1043 static soc_field_t _hg_trunk_failover_portf[_BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM] = {
   1044     PORT0f, PORT1f, PORT2f, PORT3f,
   1045     PORT4f, PORT5f, PORT6f, PORT7f,
   1046     PORT8f, PORT9f, PORT10f, PORT11f,
   1047     PORT12f, PORT13f, PORT14f, PORT15f
   1048 };
   1049 
   1050 static soc_field_t _trunk_failover_portf[_BCM_TRUNK_FAILOVER_PORT_NUM] = {
   1051     PORT0f, PORT1f, PORT2f, PORT3f,
   1052     PORT4f, PORT5f, PORT6f, PORT7f
   1053 };
   1054 
   1055 static soc_field_t _trunk_failover_modulef[_BCM_TRUNK_FAILOVER_PORT_NUM] = {
   1056     MODULE0f, MODULE1f, MODULE2f, MODULE3f,
   1057     MODULE4f, MODULE5f, MODULE6f, MODULE7f
   1058 };
   1059 
   1060 STATIC int
   1061 _bcm_xgs3_trunk_hwfailover_hg_write(int unit, bcm_port_t failport, int rtag,
   1062                                     int hw_count, bcm_port_t *ftp)
   1063 {
   1064     hg_trunk_failover_set_entry_t  fail_entry;
   1065     uint32        val, oval = 0;
   1066     bcm_pbmp_t    fail_ports, hgp;
   1067     bcm_port_t    hg_failport;
   1068     int           ix, fs_ports;
   1069 #ifdef BCM_GREYHOUND2_SUPPORT
   1070     uint64        val64_hi, oval64_hi;
   1071     uint64        hg_trunk_bmap_f;
   1072 #endif /* BCM_GREYHOUND2_SUPPORT */
   1073 #ifdef BCM_TRIUMPH2_SUPPORT
   1074     uint64        val64, oval64;
   1075     COMPILER_64_ZERO(oval64);
   1076 #endif
   1077 
   1078 #ifdef BCM_GREYHOUND2_SUPPORT
   1079     COMPILER_64_ZERO(oval64_hi);
   1080 #endif /* BCM_GREYHOUND2_SUPPORT */
   1081 
   1082     if(SOC_IS_SC_CQ(unit) && !IS_GX_PORT(unit, failport)) {
   1083         /* We should never hit this case for a fabric trunk */
   1084         return BCM_E_PORT;
   1085     }
   1086 
   1087     sal_memset(&fail_entry, 0, sizeof(fail_entry));
   1088 
   1089     if (hw_count) { /* Enabling HG trunk failover */
   1090         if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1091             SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) ||
   1092             SOC_IS_HURRICANE3(unit) ||
   1093             soc_feature(unit, soc_feature_high_portcount_register)) {
   1094             /* These devices have a 1-1 mapping for HG port number */
   1095             hg_failport = failport;
   1096         } else {
   1097             SOC_IF_ERROR_RETURN
   1098                 (soc_xgs3_port_num_to_higig_port_num(unit, failport,
   1099                                                      &hg_failport));
   1100         }
   1101         if (soc_mem_field_valid(unit, HG_TRUNK_FAILOVER_SETm, 
   1102                                 FAILOVER_SET_SIZEf)) {
   1103             soc_mem_field32_set(unit, HG_TRUNK_FAILOVER_SETm,
   1104                                (uint32 *)&fail_entry,
   1105                                FAILOVER_SET_SIZEf, hw_count - 1);
   1106         }
   1107         soc_mem_field32_set(unit, HG_TRUNK_FAILOVER_SETm,
   1108                             (uint32 *)&fail_entry, RTAGf, rtag);
   1109 
   1110         fs_ports = SOC_IS_SC_CQ(unit) ?
   1111             _BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM :
   1112             (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) ? 
   1113             _BCM_HURRICANE2_TRUNK_FAILOVER_PORT_NUM :
   1114             _BCM_TRUNK_FAILOVER_PORT_NUM;
   1115 
   1116         for (ix = 0; ix < fs_ports; ix++) {
   1117             soc_mem_field32_set(unit, HG_TRUNK_FAILOVER_SETm,
   1118                                 (uint32 *)&fail_entry,
   1119                                 _hg_trunk_failover_portf[ix],
   1120                                 ftp[ix % hw_count]);
   1121         }
   1122         SOC_IF_ERROR_RETURN
   1123             (WRITE_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, hg_failport,
   1124                                           &fail_entry));
   1125     }
   1126 
   1127     /* Update HG trunk mode selection bitmap */
   1128     SOC_PBMP_CLEAR(fail_ports);
   1129 #ifdef BCM_TRIUMPH2_SUPPORT
   1130     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1131         SOC_IS_VALKYRIE2(unit)) {
   1132         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_64r(unit, &val64));
   1133         COMPILER_64_SET(oval64, COMPILER_64_HI(val64),
   1134                         COMPILER_64_LO(val64));
   1135         SOC_PBMP_WORD_SET(fail_ports, 0,
   1136                  soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r,
   1137                                                 val64, BITMAP_LOf));
   1138         SOC_PBMP_WORD_SET(fail_ports, 1,
   1139                  soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r,
   1140                                                 val64, BITMAP_HIf));
   1141     } else
   1142 #endif
   1143 #ifdef BCM_GREYHOUND2_SUPPORT
   1144     if (soc_feature(unit, soc_feature_high_portcount_register)) {
   1145         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_LOr(unit, &val64));
   1146         COMPILER_64_SET(oval64, COMPILER_64_HI(val64),
   1147                         COMPILER_64_LO(val64));
   1148         hg_trunk_bmap_f = soc_reg64_field_get(unit,
   1149             HG_TRUNK_FAILOVER_ENABLE_LOr, val64, BITMAPf);
   1150 
   1151         SOC_PBMP_WORD_SET(fail_ports, 0, COMPILER_64_LO(hg_trunk_bmap_f));
   1152         SOC_PBMP_WORD_SET(fail_ports, 1, COMPILER_64_HI(hg_trunk_bmap_f));
   1153 
   1154         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_HIr(unit, &val64_hi));
   1155         COMPILER_64_SET(oval64_hi, COMPILER_64_HI(val64_hi),
   1156                         COMPILER_64_LO(val64_hi));
   1157         hg_trunk_bmap_f = soc_reg64_field_get(unit,
   1158             HG_TRUNK_FAILOVER_ENABLE_HIr, val64_hi, BITMAPf);
   1159 
   1160         SOC_PBMP_WORD_SET(fail_ports, 2, COMPILER_64_LO(hg_trunk_bmap_f));
   1161 
   1162     } else
   1163 #endif /* BCM_GREYHOUND2_SUPPORT */
   1164     {
   1165         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLEr(unit, &val));
   1166         oval = val;
   1167         SOC_PBMP_CLEAR(hgp);
   1168         SOC_PBMP_WORD_SET(hgp, 0,
   1169                           soc_reg_field_get(unit, HG_TRUNK_FAILOVER_ENABLEr,
   1170                                             val, BITMAPf));
   1171         SOC_IF_ERROR_RETURN
   1172             (soc_xgs3_higig_bitmap_to_bitmap(unit, hgp, &fail_ports));
   1173     }
   1174 
   1175     if (hw_count) {
   1176         SOC_PBMP_PORT_ADD(fail_ports, failport);
   1177     } else {
   1178         SOC_PBMP_PORT_REMOVE(fail_ports, failport);
   1179     }
   1180 
   1181 #ifdef BCM_TRIUMPH2_SUPPORT
   1182     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1183         SOC_IS_VALKYRIE2(unit)) {
   1184         soc_reg64_field32_set(unit, HG_TRUNK_FAILOVER_ENABLE_64r, &val64,
   1185                               BITMAP_LOf, SOC_PBMP_WORD_GET(fail_ports, 0));
   1186         soc_reg64_field32_set(unit, HG_TRUNK_FAILOVER_ENABLE_64r, &val64,
   1187                               BITMAP_HIf, SOC_PBMP_WORD_GET(fail_ports, 1));
   1188         if (COMPILER_64_NE(val64, oval64)) {
   1189             SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLE_64r(unit, val64));
   1190         }
   1191     } else
   1192 #endif
   1193 #ifdef BCM_GREYHOUND2_SUPPORT
   1194     if (soc_feature(unit, soc_feature_high_portcount_register)) {
   1195         COMPILER_64_SET(hg_trunk_bmap_f, SOC_PBMP_WORD_GET(fail_ports, 1),
   1196                         SOC_PBMP_WORD_GET(fail_ports, 0));
   1197         soc_reg64_field_set(unit, HG_TRUNK_FAILOVER_ENABLE_LOr, &val64,
   1198                               BITMAPf, hg_trunk_bmap_f);
   1199         COMPILER_64_SET(hg_trunk_bmap_f, 0,
   1200                         SOC_PBMP_WORD_GET(fail_ports, 2));
   1201         soc_reg64_field_set(unit, HG_TRUNK_FAILOVER_ENABLE_HIr, &val64_hi,
   1202                               BITMAPf, hg_trunk_bmap_f);
   1203         if (COMPILER_64_NE(val64, oval64)) {
   1204             SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLE_LOr(unit, val64));
   1205         }
   1206         if (COMPILER_64_NE(val64_hi, oval64_hi)) {
   1207             SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLE_HIr(unit, val64_hi));
   1208         }
   1209     } else
   1210 #endif /* BCM_GREYHOUND2_SUPPORT */
   1211     {
   1212         SOC_PBMP_CLEAR(hgp);
   1213         SOC_IF_ERROR_RETURN
   1214             (soc_xgs3_bitmap_to_higig_bitmap(unit, fail_ports, &hgp));
   1215         soc_reg_field_set(unit, HG_TRUNK_FAILOVER_ENABLEr, &val, BITMAPf,
   1216                           SOC_PBMP_WORD_GET(hgp, 0));
   1217         if (val != oval) {
   1218             SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLEr(unit, val));
   1219         }
   1220     }
   1221 
   1222     return BCM_E_NONE;
   1223 }
   1224 
   1225 STATIC int
   1226 _bcm_xgs3_trunk_hwfailover_hg_read(int unit, bcm_port_t failport,
   1227                                    int array_size, int *rtag,
   1228                                    bcm_port_t *ftp, bcm_module_t *ftm,
   1229                                    int *array_count)
   1230 {
   1231     hg_trunk_failover_set_entry_t  fail_entry;
   1232     uint32        val;
   1233     bcm_pbmp_t    fail_ports, hgp;
   1234     bcm_port_t    hg_failport;
   1235     int           ix, hw_count = 0;
   1236 #ifdef BCM_TRIUMPH2_SUPPORT
   1237     uint64        val64;
   1238 #endif
   1239 #ifdef BCM_GREYHOUND2_SUPPORT
   1240     uint64        hg_trunk_bmap_f;
   1241 #endif /* BCM_GREYHOUND2_SUPPORT */
   1242 
   1243 #ifdef BCM_TRIUMPH2_SUPPORT
   1244     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1245         SOC_IS_VALKYRIE2(unit)) {
   1246         /* These devices have a 1-1 mapping for HG port number */
   1247         hg_failport = failport;
   1248         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_64r(unit, &val64));
   1249         SOC_PBMP_WORD_SET(fail_ports, 0,
   1250                           soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r,
   1251                                                 val64, BITMAP_LOf));
   1252         SOC_PBMP_WORD_SET(fail_ports, 1,
   1253                           soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r,
   1254                                                 val64, BITMAP_HIf));
   1255     } else
   1256 #endif
   1257 #ifdef BCM_GREYHOUND2_SUPPORT
   1258     if (soc_feature(unit, soc_feature_high_portcount_register)) {
   1259         /* These devices have a 1-1 mapping for HG port number */
   1260         hg_failport = failport;
   1261         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_LOr(unit, &val64));
   1262         hg_trunk_bmap_f = soc_reg64_field_get(unit,
   1263             HG_TRUNK_FAILOVER_ENABLE_LOr, val64, BITMAPf);
   1264 
   1265         SOC_PBMP_WORD_SET(fail_ports, 0, COMPILER_64_LO(hg_trunk_bmap_f));
   1266         SOC_PBMP_WORD_SET(fail_ports, 1, COMPILER_64_HI(hg_trunk_bmap_f));
   1267 
   1268         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_HIr(unit, &val64));
   1269         hg_trunk_bmap_f = soc_reg64_field_get(unit,
   1270             HG_TRUNK_FAILOVER_ENABLE_HIr, val64, BITMAPf);
   1271 
   1272         SOC_PBMP_WORD_SET(fail_ports, 2, COMPILER_64_LO(hg_trunk_bmap_f));
   1273     } else
   1274 #endif /* BCM_GREYHOUND2_SUPPORT */
   1275     {
   1276         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) {
   1277             hg_failport = failport;
   1278         } else {
   1279             SOC_IF_ERROR_RETURN
   1280                 (soc_xgs3_port_num_to_higig_port_num(unit, failport,
   1281                                                      &hg_failport));
   1282         }
   1283         SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLEr(unit, &val));
   1284         SOC_PBMP_CLEAR(hgp);
   1285         SOC_PBMP_WORD_SET(hgp, 0,
   1286                           soc_reg_field_get(unit, HG_TRUNK_FAILOVER_ENABLEr,
   1287                                             val, BITMAPf));
   1288         SOC_PBMP_CLEAR(fail_ports);
   1289         SOC_IF_ERROR_RETURN
   1290             (soc_xgs3_higig_bitmap_to_bitmap(unit, hgp, &fail_ports));
   1291     }
   1292 
   1293     if (SOC_PBMP_MEMBER(fail_ports, failport)) {
   1294         SOC_IF_ERROR_RETURN
   1295             (READ_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, hg_failport,
   1296                                          &fail_entry));
   1297 
   1298         if (soc_mem_field_valid(unit, HG_TRUNK_FAILOVER_SETm, 
   1299                                 FAILOVER_SET_SIZEf)) {
   1300             hw_count = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1301                                            (uint32 *)&fail_entry,
   1302                                            FAILOVER_SET_SIZEf) + 1;
   1303         } else {
   1304             hw_count = SOC_IS_SC_CQ(unit) ?
   1305             _BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM :
   1306             (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) ? 
   1307             _BCM_HURRICANE2_TRUNK_FAILOVER_PORT_NUM :
   1308             _BCM_TRUNK_FAILOVER_PORT_NUM;
   1309         }
   1310 
   1311         if (((NULL != ftp) || (NULL != ftm)) && (hw_count > array_size)) {
   1312             hw_count = array_size;
   1313         }
   1314         for (ix = 0; ix < hw_count; ix++) {
   1315             if (NULL != ftm) {
   1316                 ftm[ix] = 0;
   1317             }
   1318             if (NULL != ftp) {
   1319                 ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1320                         (uint32 *)&fail_entry,
   1321                         _hg_trunk_failover_portf[ix]);
   1322             }
   1323         }
   1324         if (NULL != rtag) {
   1325             *rtag = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm,
   1326                                         (uint32 *)&fail_entry, RTAGf);
   1327         }
   1328         if (NULL != array_count) {
   1329             *array_count = hw_count;
   1330         }
   1331     } else {
   1332         if (NULL != array_count) {
   1333             *array_count = 0;
   1334         }
   1335     }
   1336     return BCM_E_NONE;
   1337 }
   1338 
   1339 STATIC int
   1340 _bcm_xgs3_trunk_hwfailover_write(int unit, bcm_port_t failport, int rtag,
   1341                                  int hw_count,
   1342                                  bcm_port_t *ftp, bcm_module_t *ftm)
   1343 {
   1344     port_lag_failover_set_entry_t  fail_entry;
   1345     uint32 val, oval;
   1346     int    ix, mirror_enable;
   1347 
   1348     if(SOC_IS_SC_CQ(unit) && !IS_GX_PORT(unit, failport)) {
   1349         /* Not supported, but no error due to trunk config implicit use */
   1350         return BCM_E_NONE;
   1351     }
   1352 
   1353     SOC_IF_ERROR_RETURN
   1354         (READ_GXPORT_LAG_FAILOVER_STATUSr(unit, failport, &val));
   1355     if (soc_reg_field_get(unit, GXPORT_LAG_FAILOVER_STATUSr,
   1356                           val, LAG_FAILOVER_LOOPBACKf)) {
   1357         /*
   1358          * Already in failover mode.  Do not change HW settings!
   1359          * This should be dealt with as part of the port link processing.
   1360          */
   1361         if (hw_count == 0) {
   1362             /* Notify linkscan of port removal from trunk */
   1363             BCM_IF_ERROR_RETURN
   1364                 (_bcm_esw_link_failover_set(unit, failport, FALSE));
   1365             return BCM_E_NONE;
   1366         } else {
   1367             return BCM_E_PORT;
   1368         }
   1369     }
   1370 
   1371     if (hw_count) { /* Enabling trunk failover */
   1372         /* We must be in directed mirroring mode to use this feature */
   1373         BCM_IF_ERROR_RETURN
   1374             (bcm_esw_switch_control_get(unit, bcmSwitchDirectedMirroring,
   1375                                         &mirror_enable));
   1376         if (!mirror_enable) {
   1377             return BCM_E_CONFIG;
   1378         }
   1379         
   1380         sal_memset(&fail_entry, 0, sizeof(fail_entry));
   1381         soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1382                             (uint32 *)&fail_entry,
   1383                             FAILOVER_SET_SIZEf, hw_count - 1);
   1384         soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1385                             (uint32 *)&fail_entry, RTAGf, rtag);
   1386 
   1387         for (ix = 0; ix < _BCM_TRUNK_FAILOVER_PORT_NUM; ix++) {
   1388             soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1389                                 (uint32 *)&fail_entry,
   1390                                 _trunk_failover_portf[ix],
   1391                                 ftp[ix % hw_count]);
   1392             soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm,
   1393                                 (uint32 *)&fail_entry,
   1394                                 _trunk_failover_modulef[ix],
   1395                                 ftm[ix % hw_count]);
   1396         }
   1397         SOC_IF_ERROR_RETURN
   1398             (WRITE_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport,
   1399                                           &fail_entry));
   1400     }
   1401 
   1402     SOC_IF_ERROR_RETURN
   1403         (READ_GXPORT_LAG_FAILOVER_CONFIGr(unit, failport, &val));
   1404     oval = val;
   1405     soc_reg_field_set(unit, GXPORT_LAG_FAILOVER_CONFIGr, &val,
   1406                       LAG_FAILOVER_ENf, (hw_count != 0) ? 1 : 0);
   1407     if (val != oval) {
   1408         SOC_IF_ERROR_RETURN
   1409             (WRITE_GXPORT_LAG_FAILOVER_CONFIGr(unit, failport, val));
   1410     }
   1411 
   1412     /* Notify linkscan of failover status */
   1413     BCM_IF_ERROR_RETURN
   1414         (_bcm_esw_link_failover_set(unit, failport, (hw_count != 0)));
   1415 
   1416     return BCM_E_NONE;
   1417 }
   1418 
   1419 STATIC int
   1420 _bcm_xgs3_trunk_hwfailover_read(int unit, bcm_port_t failport,
   1421                                 int array_size, int *rtag,
   1422                                 bcm_port_t *ftp, bcm_module_t *ftm,
   1423                                 int *array_count)
   1424 {
   1425     port_lag_failover_set_entry_t fail_entry;
   1426     uint32 val;
   1427     int    ix, hw_count, enable = FALSE;
   1428 
   1429 
   1430     if(IS_GX_PORT(unit, failport)) {
   1431         SOC_IF_ERROR_RETURN
   1432             (READ_GXPORT_LAG_FAILOVER_CONFIGr(unit, failport, &val));
   1433         enable = soc_reg_field_get(unit, GXPORT_LAG_FAILOVER_CONFIGr, val,
   1434                                    LAG_FAILOVER_ENf);
   1435     }
   1436 
   1437     if (enable) {
   1438         SOC_IF_ERROR_RETURN
   1439             (READ_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport,
   1440                                          &fail_entry));
   1441         hw_count = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   1442                                        (uint32 *)&fail_entry,
   1443                                        FAILOVER_SET_SIZEf) + 1;
   1444         if (((NULL != ftp) || (NULL != ftm)) && (hw_count > array_size)) {
   1445             hw_count = array_size;
   1446         }
   1447         for (ix = 0; ix < hw_count; ix++) {
   1448             if (NULL != ftp) {
   1449                 ftp[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   1450                                               (uint32 *)&fail_entry,
   1451                                               _trunk_failover_portf[ix]);
   1452             }
   1453             if (NULL != ftm) {
   1454                 ftm[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   1455                                               (uint32 *)&fail_entry,
   1456                                               _trunk_failover_modulef[ix]);
   1457             }
   1458         }
   1459         if (NULL != rtag) {
   1460             *rtag = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm,
   1461                                         (uint32 *)&fail_entry, RTAGf);
   1462         }
   1463         if (NULL != array_count) {
   1464             *array_count = hw_count;
   1465         }
   1466     } else {
   1467         if (NULL != array_count) {
   1468             *array_count = 0;
   1469         }
   1470         if (NULL != rtag) {
   1471             *rtag = 0;
   1472         }
   1473     }
   1474 
   1475     return BCM_E_NONE;
   1476 }
   1477 
   1478 int
   1479 _bcm_xgs3_trunk_hwfailover_set(int unit, bcm_trunk_t tid, int hg_trunk,
   1480                                bcm_port_t port, bcm_module_t modid,
   1481                                int psc, uint32 flags, int count, 
   1482                                bcm_port_t *ftp, bcm_module_t *ftm)
   1483 {
   1484     int ix, tix, tid_ix, tports, next, local, mod_is_local, hw_count, rtag;
   1485     uint8 tp_mod;
   1486     uint16 fail_modport;
   1487     bcm_gport_t gport;
   1488     bcm_port_t local_port, port_list[BCM_XGS3_TRUNK_MAX_PORTCNT];
   1489     bcm_module_t modid_list[BCM_XGS3_TRUNK_MAX_PORTCNT];
   1490     _xgs3_hw_tinfo_t           *hwft;
   1491 
   1492     /* Need the HW port number for the table write later */
   1493     if (hg_trunk) {
   1494         fail_modport = local_port = port;
   1495     } else {
   1496         BCM_GPORT_MODPORT_SET(gport, modid, port);
   1497         BCM_IF_ERROR_RETURN
   1498             (bcm_esw_port_local_get(unit, gport, &local_port));
   1499 
   1500         fail_modport = (modid << 8) | port;
   1501     }
   1502 
   1503     BCM_IF_ERROR_RETURN
   1504         (_bcm_xgs3_trunk_psc_to_rtag(unit, psc, &rtag));
   1505 
   1506     tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0);
   1507     hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   1508 
   1509     /* Where is our port in the trunk list? */
   1510     tports = hwft->num_ports;
   1511     for (tix = 0; tix < tports; tix++) {
   1512         if (fail_modport == hwft->modport[tix]) {
   1513             break;
   1514         }
   1515     }
   1516 
   1517     if ((0 != count) && (tix == tports)) {
   1518         /* Port not in trunk! */
   1519         return BCM_E_NOT_FOUND;
   1520     }
   1521 
   1522     if (flags) {
   1523         switch (flags) {
   1524         case BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL:
   1525             next = TRUE;
   1526             local = TRUE;
   1527             break;
   1528         case BCM_TRUNK_FLAG_FAILOVER_NEXT:
   1529             next = TRUE;
   1530             local = FALSE;
   1531             break;
   1532         case BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL:
   1533             next = FALSE;
   1534             local = TRUE;
   1535             break;
   1536         case BCM_TRUNK_FLAG_FAILOVER_ALL:
   1537             next = FALSE;
   1538             local = FALSE;
   1539             break;
   1540         default:
   1541             /* Illegal flags setting */
   1542             return BCM_E_PARAM;
   1543         }
   1544 
   1545         hw_count = 0;
   1546 
   1547         for (ix = ((tix + 1) % tports);  /* Start after fail port */
   1548             ix != tix;                  /* Stop when we get back */
   1549             ix = ((ix + 1) % tports)) { /* Cycle through trunk port list */
   1550             tp_mod = hwft->modport[ix] >> 8;
   1551             if (local && !hg_trunk) {
   1552                 BCM_IF_ERROR_RETURN
   1553                     (_bcm_esw_modid_is_local(unit, tp_mod,
   1554                                              &mod_is_local));
   1555                 if (!mod_is_local) {
   1556                     continue;
   1557                 }
   1558             }
   1559             port_list[hw_count] = hwft->modport[ix] & 0xff;
   1560             modid_list[hw_count] = tp_mod;
   1561             hw_count++;
   1562             if (next) {
   1563                 break;
   1564             }
   1565         }
   1566     } else {
   1567         if (count) {
   1568             for (ix = 0; ix < count; ix++) {
   1569                 port_list[ix] = ftp[ix];
   1570                 modid_list[ix] = ftm[ix];
   1571             }
   1572         }
   1573         hw_count = count;
   1574     }
   1575 
   1576     if (hg_trunk) {
   1577         BCM_IF_ERROR_RETURN
   1578             (_bcm_xgs3_trunk_hwfailover_hg_write(unit, local_port, rtag,
   1579                                         hw_count, port_list));
   1580     } else {
   1581         BCM_IF_ERROR_RETURN
   1582             (_bcm_xgs3_trunk_hwfailover_write(unit, local_port, rtag,
   1583                                         hw_count, port_list, modid_list));
   1584     }
   1585 
   1586     if (tix < hwft->num_ports) {
   1587         hwft->flags[tix] = flags;
   1588         hwft->psc[tix] = psc;
   1589     }
   1590     return BCM_E_NONE;
   1591 }
   1592 
   1593 int
   1594 _bcm_xgs3_trunk_hwfailover_get(int unit, bcm_trunk_t tid, int hg_trunk,
   1595                                bcm_port_t port, bcm_module_t modid,
   1596                                int *psc, uint32 *flags, int array_size,
   1597                                bcm_port_t *ftp, bcm_module_t *ftm, 
   1598                                int *array_count)
   1599 {
   1600     int tix, tid_ix, tports;
   1601     uint16 fail_modport;
   1602     bcm_gport_t gport;
   1603     bcm_port_t local_port;
   1604     _xgs3_hw_tinfo_t           *hwft;
   1605 
   1606     /* Need the HW port number for the table write later */
   1607     if (hg_trunk) {
   1608         fail_modport = local_port = port;
   1609     } else {
   1610         BCM_GPORT_MODPORT_SET(gport, modid, port);
   1611         BCM_IF_ERROR_RETURN
   1612             (bcm_esw_port_local_get(unit, gport, &local_port));
   1613 
   1614         fail_modport = (modid << 8) | port;
   1615     }
   1616 
   1617     tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0);
   1618     hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   1619 
   1620     /* Where is our port in the trunk list? */
   1621     tports = hwft->num_ports;
   1622     for (tix = 0; tix < tports; tix++) {
   1623         if (fail_modport == hwft->modport[tix]) {
   1624             break;
   1625         }
   1626     }
   1627 
   1628     if (tix == tports) {
   1629         /* Port not in trunk! */
   1630         return BCM_E_NOT_FOUND;
   1631     }
   1632 
   1633     *psc = hwft->psc[tix];
   1634 
   1635     if (hwft->flags[tix]) {
   1636         /* Just return the flags value */
   1637         *flags = hwft->flags[tix];
   1638         *array_count = 0;
   1639     } else {
   1640         /* Access the HW to get the list */
   1641         *flags = 0;
   1642         if (hg_trunk) {
   1643             BCM_IF_ERROR_RETURN
   1644                 (_bcm_xgs3_trunk_hwfailover_hg_read(unit, local_port,
   1645                                  array_size, NULL, ftp, ftm, array_count));
   1646         } else {
   1647             BCM_IF_ERROR_RETURN
   1648                 (_bcm_xgs3_trunk_hwfailover_read(unit, local_port,
   1649                                  array_size, NULL, ftp, ftm, array_count));
   1650         }
   1651     }
   1652 
   1653     return BCM_E_NONE;
   1654 }
   1655 
   1656 /*
   1657  *Trunk group set/destroy Trunk Failover config
   1658  */
   1659 STATIC int
   1660 _bcm_xgs3_trunk_failover_set(int unit, bcm_trunk_t tid, int hg_trunk,
   1661                              _esw_trunk_add_info_t *add_info)
   1662 {
   1663     int tix, mod_is_local, tid_ix;
   1664     bcm_port_t tp_port;
   1665     bcm_module_t tp_mod = -1;
   1666     _xgs3_hw_tinfo_t           *hwft;
   1667     int num_hwft_ports;
   1668     bcm_port_t   port_array[BCM_XGS3_TRUNK_MAX_PORTCNT];
   1669     bcm_module_t mod_array[BCM_XGS3_TRUNK_MAX_PORTCNT];
   1670     int failover_flags;
   1671 
   1672     failover_flags = 0;
   1673     if (add_info != NULL) {
   1674         if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT) {
   1675             failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT;
   1676         } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL) {
   1677             failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL;
   1678         } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL) {
   1679             failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL;
   1680         } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL) {
   1681             failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL;
   1682         }
   1683     }
   1684 
   1685     tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0);
   1686     hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   1687 
   1688     if ((NULL == add_info) || (0 != failover_flags)) {
   1689         for (tix = 0; tix < hwft->num_ports; tix++) {
   1690             if (!hg_trunk) {
   1691                 tp_mod = hwft->modport[tix] >> 8;
   1692                 BCM_IF_ERROR_RETURN
   1693                     (_bcm_esw_modid_is_local(unit, tp_mod, &mod_is_local));
   1694                 if (!mod_is_local) {
   1695                     continue;
   1696                 }
   1697             }
   1698             tp_port = hwft->modport[tix] & 0xff;
   1699             BCM_IF_ERROR_RETURN
   1700                 (_bcm_xgs3_trunk_hwfailover_set(unit, tid, hg_trunk,
   1701                                                 tp_port, tp_mod,
   1702                                                 hwft->psc[tix],
   1703                                                 0, 0, NULL, NULL));
   1704         }
   1705     }
   1706     /* Else, updating trunk with add_info->flags == 0,
   1707      * do not change failover configuration */
   1708 
   1709     if (NULL == add_info) {
   1710         /* We're deleting the trunk, flush the info structure */
   1711         hwft->num_ports = 0;
   1712         return BCM_E_NONE;
   1713     }
   1714 
   1715     /* Record trunk data */
   1716     num_hwft_ports = 0;
   1717     for (tix = 0; tix < add_info->num_ports; tix++) {
   1718         if (add_info->member_flags[tix] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   1719             continue;
   1720         }
   1721         hwft->flags[num_hwft_ports] = failover_flags;
   1722         hwft->psc[num_hwft_ports] = add_info->psc;
   1723         hwft->modport[num_hwft_ports] = add_info->tp[tix];
   1724         port_array[num_hwft_ports] = add_info->tp[tix];
   1725         if (!hg_trunk) {
   1726             hwft->modport[num_hwft_ports] |= (add_info->tm[tix] << 8);
   1727             mod_array[num_hwft_ports] = add_info->tm[tix];
   1728         }
   1729         num_hwft_ports++; 
   1730     }
   1731     hwft->num_ports = num_hwft_ports;
   1732 
   1733     /* No flags in trunk_set means no failover changes */
   1734     if (0 != failover_flags) {
   1735         /* Configure new trunk failover info */
   1736         for (tix = 0; tix < hwft->num_ports; tix++) {
   1737             if (!hg_trunk) {
   1738                 BCM_IF_ERROR_RETURN
   1739                     (_bcm_esw_modid_is_local(unit, hwft->modport[tix] >> 8,
   1740                                              &mod_is_local));
   1741                 if (!mod_is_local) { 
   1742                     continue;
   1743                 }
   1744             }
   1745             BCM_IF_ERROR_RETURN
   1746                 (_bcm_xgs3_trunk_hwfailover_set(unit, tid, hg_trunk, 
   1747                            hwft->modport[tix] & 0xff,
   1748                            hwft->modport[tix] >> 8,
   1749                            hwft->psc[tix], hwft->flags[tix], hwft->num_ports,
   1750                            port_array, mod_array));
   1751         }
   1752     }
   1753     return BCM_E_NONE;
   1754 }
   1755 
   1756 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */
   1757 
   1758 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   1759 /*
   1760  * Update port table for fabric trunks.
   1761  * SOC_IS_HBX only.
   1762  */
   1763 STATIC int
   1764 _bcm_xgs3_trunk_fabric_port_set(int unit,
   1765 				bcm_trunk_t hgtid,
   1766 				pbmp_t old_ports,
   1767 				pbmp_t new_ports)
   1768 {
   1769     bcm_port_t		port;
   1770     int			ctid;
   1771 
   1772     PBMP_PORT_ITER(unit, port) {
   1773         if (!(IS_HG_PORT(unit, port) || IS_HL_PORT(unit, port))) {
   1774             continue;
   1775         }
   1776         if (BCM_PBMP_MEMBER(new_ports, port)) {
   1777             ctid = hgtid;
   1778         } else if (BCM_PBMP_MEMBER(old_ports, port)) {
   1779             ctid = -1;
   1780 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   1781             if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   1782                 /* Clear HW failover info for deleted port */
   1783                 BCM_IF_ERROR_RETURN
   1784                     (_bcm_xgs3_trunk_hwfailover_set(unit, hgtid, TRUE,
   1785                                                     port, -1,
   1786                                                     BCM_TRUNK_PSC_DEFAULT,
   1787                                                     0, 0, NULL, NULL));
   1788             }
   1789 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   1790         } else {
   1791             continue;
   1792         }
   1793         BCM_IF_ERROR_RETURN
   1794             (_bcm_esw_port_config_set(unit, port,
   1795                                       _bcmPortHigigTrunkId, ctid));
   1796     }
   1797     return BCM_E_NONE;
   1798 }
   1799 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_BRADLEY_SUPPORT */
   1800 
   1801 STATIC int
   1802 _bcm_xgs3_trunk_fabric_set(int unit,
   1803                            bcm_trunk_t hgtid,
   1804                            _esw_trunk_add_info_t *add_info,
   1805                            trunk_private_t *t_info)
   1806 {
   1807     int                i, local_id;
   1808     int port[BCM_XGS3_TRUNK_MAX_PORTCNT];
   1809     pbmp_t             old_trunk_pbmp, new_trunk_pbmp, hg_pbm, pbm;
   1810     bcm_gport_t gport;
   1811     bcm_module_t mod_id;
   1812     bcm_trunk_t trunk, tid;
   1813 
   1814     SOC_PBMP_CLEAR(new_trunk_pbmp);
   1815     tid = hgtid + _BCM_FP_TRUNK_NUM_MAX;
   1816     for (i = 0; i < add_info->num_ports; i++) {
   1817         /* if given modid is -1 devport was used */
   1818         if (BCM_MODID_INVALID != add_info->tm[i]) {
   1819             BCM_GPORT_MODPORT_SET(gport, add_info->tm[i], add_info->tp[i]);
   1820 
   1821             BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport, &mod_id,
   1822                         &port[i], &trunk, &local_id));
   1823         } else {
   1824             port[i] = add_info->tp[i];
   1825         }
   1826 
   1827         if (!SOC_PORT_VALID(unit, port[i])) {
   1828             return BCM_E_PORT;
   1829         }
   1830         if (!IS_ST_PORT(unit, port[i])) {
   1831             return BCM_E_PARAM;
   1832         }
   1833         SOC_PBMP_PORT_ADD(new_trunk_pbmp, port[i]);
   1834 
   1835         /* Save new trunk member info */
   1836         MEMBER_INFO(unit, tid).modport[i] = port[i];
   1837         MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i];
   1838     }
   1839     MEMBER_INFO(unit, tid).num_ports = add_info->num_ports;
   1840 
   1841     if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) && 
   1842         soc_feature(unit, soc_feature_hg_trunking)) {
   1843         uint32              hg_group_entry, hg_cntl_entry;
   1844         uint32              hgp, pword;
   1845         soc_field_t        *trunkf, rtagf, bmapf; 
   1846         bcm_port_t          port;
   1847         int                 cena, ctid;
   1848 #if defined(BCM_FIREBOLT2_SUPPORT)
   1849         soc_field_t         sizef;
   1850 #endif /* BCM_FIREBOLT2_SUPPORT */
   1851 
   1852         switch (hgtid) {
   1853         case 0:
   1854             trunkf = _hg_trunk0f;
   1855             rtagf = HIGIG_TRUNK_RTAG0f;
   1856             bmapf = HIGIG_TRUNK_BITMAP0f;
   1857 #if defined(BCM_FIREBOLT2_SUPPORT)
   1858             sizef = HIGIG_TRUNK_SIZE0f;
   1859 #endif /* BCM_FIREBOLT2_SUPPORT */
   1860             break;
   1861         case 1:
   1862             trunkf = _hg_trunk1f;
   1863             rtagf = HIGIG_TRUNK_RTAG1f;
   1864             bmapf = HIGIG_TRUNK_BITMAP1f;
   1865 #if defined(BCM_FIREBOLT2_SUPPORT)
   1866             sizef = HIGIG_TRUNK_SIZE1f;
   1867 #endif /* BCM_FIREBOLT2_SUPPORT */
   1868             break;
   1869         default:
   1870             return BCM_E_PARAM;
   1871         }
   1872 
   1873         SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_GROUPr(unit, &hg_group_entry));
   1874 
   1875         for (i = 0; i < 4; i++) {
   1876             if (SOC_IS_RAVEN(unit)) { 
   1877                 /* For Raven, write port number directly */ 
   1878                 hgp = add_info->tp[i%add_info->num_ports];
   1879             } else { 
   1880                 /* For other FBX, write higig port number */
   1881                 BCM_IF_ERROR_RETURN(
   1882                     soc_xgs3_port_to_higig_bitmap(unit, 
   1883                              add_info->tp[i%add_info->num_ports], &hgp));
   1884                 BCM_IF_ERROR_RETURN(
   1885                     soc_xgs3_higig_bitmap_to_higig_port_num(hgp, &hgp));
   1886             }
   1887             soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry,
   1888                               trunkf[i], hgp);
   1889         }
   1890 
   1891 #if defined(BCM_FIREBOLT2_SUPPORT)
   1892         if (soc_feature(unit, soc_feature_trunk_group_size)) {
   1893             soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry,
   1894                                sizef, add_info->num_ports-1);
   1895         }
   1896 #endif /* BCM_FIREBOLT2_SUPPORT */
   1897         soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry,
   1898                           rtagf, t_info->rtag);
   1899         SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_GROUPr(unit, hg_group_entry));
   1900 
   1901         SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_CONTROLr(unit, &hg_cntl_entry));
   1902         SOC_PBMP_CLEAR(old_trunk_pbmp);
   1903         pword = soc_reg_field_get(unit, HIGIG_TRUNK_CONTROLr,
   1904                                   hg_cntl_entry, bmapf);
   1905 
   1906         if (SOC_IS_RAVEN(unit)) {
   1907             /* Use the bitmap directly */
   1908             SOC_PBMP_WORD_SET(old_trunk_pbmp, 0, pword);
   1909         } else { 
   1910             /* For other FBX, map the higig bitmap to the physical bitmap */
   1911             SOC_PBMP_WORD_SET(hg_pbm, 0, pword);
   1912             SOC_PBMP_CLEAR(pbm);
   1913             soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbm, &pbm);
   1914             SOC_PBMP_ASSIGN(old_trunk_pbmp, pbm);
   1915         }
   1916         PBMP_ST_ITER(unit, port) {
   1917             if (BCM_PBMP_MEMBER(new_trunk_pbmp, port)) {
   1918                 cena = 1;
   1919                 ctid = hgtid;
   1920             } else if (BCM_PBMP_MEMBER(old_trunk_pbmp, port)) {
   1921                 cena = 0;
   1922                 ctid = 0;
   1923             } else {
   1924                 continue;
   1925             }
   1926             BCM_IF_ERROR_RETURN(
   1927                 soc_xgs3_port_to_higig_bitmap(unit, port, &hgp));
   1928             BCM_IF_ERROR_RETURN(
   1929                 soc_xgs3_higig_bitmap_to_higig_port_num(hgp, &hgp));
   1930             soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   1931                               _hg_cntl1f[hgp], cena);
   1932             soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   1933                               _hg_cntl0f[hgp], ctid);
   1934         }
   1935         if (SOC_IS_RAVEN(unit)) {
   1936             soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   1937                               bmapf, SOC_PBMP_WORD_GET(new_trunk_pbmp, 0));
   1938         } else { 
   1939             SOC_PBMP_CLEAR(hg_pbm);
   1940             soc_xgs3_bitmap_to_higig_bitmap(unit, new_trunk_pbmp, &hg_pbm);
   1941             soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   1942                               bmapf, SOC_PBMP_WORD_GET(hg_pbm, 0));
   1943         } 
   1944         SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_CONTROLr(unit, hg_cntl_entry));
   1945 
   1946         BCM_IF_ERROR_RETURN
   1947             (_bcm_xgs3_trunk_swfailover_fabric_set(unit,
   1948                                                    hgtid,
   1949                                                    t_info->rtag,
   1950                                                    new_trunk_pbmp));
   1951         return BCM_E_NONE;
   1952     }
   1953 #if defined(BCM_TRIUMPH2_SUPPORT)
   1954     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1955         SOC_IS_VALKYRIE2(unit)) {
   1956         uint64          val64;
   1957 
   1958         SOC_IF_ERROR_RETURN
   1959             (READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64));
   1960         SOC_PBMP_CLEAR(hg_pbm);
   1961         SOC_PBMP_WORD_SET(hg_pbm, 0,
   1962                           soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
   1963                                                 val64, HIGIG_TRUNK_BITMAP_LOf));
   1964         SOC_PBMP_WORD_SET(hg_pbm, 1,
   1965                           soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
   1966                                                 val64, HIGIG_TRUNK_BITMAP_HIf));
   1967         SOC_PBMP_CLEAR(old_trunk_pbmp);
   1968         SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm);
   1969 
   1970         COMPILER_64_ZERO(val64);
   1971         SOC_PBMP_CLEAR(hg_pbm);
   1972         SOC_PBMP_ASSIGN(hg_pbm, new_trunk_pbmp);
   1973         soc_reg64_field32_set(unit, HG_TRUNK_BITMAP_64r, &val64,
   1974                               HIGIG_TRUNK_BITMAP_LOf, 
   1975                               SOC_PBMP_WORD_GET(hg_pbm, 0));
   1976         soc_reg64_field32_set(unit, HG_TRUNK_BITMAP_64r, &val64, 
   1977                               HIGIG_TRUNK_BITMAP_HIf, 
   1978                               SOC_PBMP_WORD_GET(hg_pbm, 1));
   1979         SOC_IF_ERROR_RETURN
   1980             (WRITE_HG_TRUNK_BITMAP_64r(unit, hgtid, val64));
   1981 
   1982         COMPILER_64_ZERO(val64);
   1983         for (i = 0; i < 8; i++) {
   1984             soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   1985                 _hg_trunk[i], port[i%add_info->num_ports]);
   1986         }
   1987         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   1988                               HIGIG_TRUNK_SIZEf, add_info->num_ports-1);
   1989         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   1990                               HIGIG_TRUNK_RTAGf, t_info->rtag);
   1991         SOC_IF_ERROR_RETURN
   1992             (WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64));
   1993         COMPILER_64_ZERO(val64);
   1994 
   1995 	BCM_IF_ERROR_RETURN
   1996 	    (_bcm_xgs3_trunk_fabric_port_set(unit,
   1997 					     hgtid,
   1998 					     old_trunk_pbmp,
   1999 					     new_trunk_pbmp));
   2000 
   2001         if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   2002             BCM_IF_ERROR_RETURN
   2003                 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, add_info));
   2004         }
   2005 
   2006         BCM_IF_ERROR_RETURN
   2007             (_bcm_xgs3_trunk_swfailover_fabric_set(unit,
   2008                                                    hgtid,
   2009                                                    t_info->rtag,
   2010                                                    new_trunk_pbmp));
   2011 
   2012         return BCM_E_NONE;
   2013     }
   2014 #endif /* BCM_TRIUMPH2_SUPPORT */
   2015 #if defined(BCM_BRADLEY_SUPPORT)
   2016     if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) {
   2017         uint32          val;
   2018         uint64          val64;
   2019 #if defined(BCM_GREYHOUND2_SUPPORT)
   2020         uint64          hg_trunk_bmap_f;
   2021         if (soc_feature(unit, soc_feature_high_portcount_register)) {
   2022             SOC_IF_ERROR_RETURN
   2023                 (READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64));
   2024             hg_trunk_bmap_f =
   2025                 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr,
   2026                                     val64, HIGIG_TRUNK_BITMAPf);
   2027             SOC_PBMP_CLEAR(hg_pbm);
   2028             SOC_PBMP_WORD_SET(hg_pbm, 0, COMPILER_64_LO(hg_trunk_bmap_f));
   2029             SOC_PBMP_WORD_SET(hg_pbm, 1, COMPILER_64_HI(hg_trunk_bmap_f));
   2030             SOC_IF_ERROR_RETURN
   2031                 (READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64));
   2032             hg_trunk_bmap_f =
   2033                 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr,
   2034                                     val64, HIGIG_TRUNK_BITMAPf);
   2035             SOC_PBMP_WORD_SET(hg_pbm, 2, COMPILER_64_LO(hg_trunk_bmap_f));
   2036 
   2037             SOC_PBMP_CLEAR(old_trunk_pbmp);
   2038             SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm);
   2039 
   2040             SOC_PBMP_CLEAR(hg_pbm);
   2041             SOC_PBMP_ASSIGN(hg_pbm, new_trunk_pbmp);
   2042 
   2043             COMPILER_64_ZERO(val64);
   2044             COMPILER_64_SET(hg_trunk_bmap_f, SOC_PBMP_WORD_GET(hg_pbm, 1),
   2045                             SOC_PBMP_WORD_GET(hg_pbm, 0));
   2046             soc_reg64_field_set(unit, HG_TRUNK_BITMAP_LOr, &val64,
   2047                                 HIGIG_TRUNK_BITMAPf, hg_trunk_bmap_f);
   2048             SOC_IF_ERROR_RETURN
   2049                 (WRITE_HG_TRUNK_BITMAP_LOr(unit, hgtid, val64));
   2050 
   2051             COMPILER_64_ZERO(val64);
   2052             COMPILER_64_SET(hg_trunk_bmap_f, 0,
   2053                             SOC_PBMP_WORD_GET(hg_pbm, 2));
   2054             soc_reg64_field_set(unit, HG_TRUNK_BITMAP_HIr, &val64,
   2055                                 HIGIG_TRUNK_BITMAPf, hg_trunk_bmap_f);
   2056             SOC_IF_ERROR_RETURN
   2057                 (WRITE_HG_TRUNK_BITMAP_HIr(unit, hgtid, val64));
   2058 
   2059         } else
   2060 #endif /* BCM_GREYHOUND2_SUPPORT */
   2061         {
   2062             SOC_IF_ERROR_RETURN
   2063                 (READ_HG_TRUNK_BITMAPr(unit, hgtid, &val));
   2064             SOC_PBMP_CLEAR(hg_pbm);
   2065             SOC_PBMP_WORD_SET(hg_pbm, 0,
   2066                               soc_reg_field_get(unit, HG_TRUNK_BITMAPr,
   2067                                                 val, HIGIG_TRUNK_BITMAPf));
   2068             SOC_PBMP_CLEAR(old_trunk_pbmp);
   2069             soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbm, &old_trunk_pbmp);
   2070 
   2071             val = 0;
   2072             SOC_PBMP_CLEAR(hg_pbm);
   2073             soc_xgs3_bitmap_to_higig_bitmap(unit, new_trunk_pbmp, &hg_pbm);
   2074             soc_reg_field_set(unit, HG_TRUNK_BITMAPr, &val, HIGIG_TRUNK_BITMAPf,
   2075                               SOC_PBMP_WORD_GET(hg_pbm, 0));
   2076             SOC_IF_ERROR_RETURN
   2077                 (WRITE_HG_TRUNK_BITMAPr(unit, hgtid, val));
   2078         }
   2079 
   2080         COMPILER_64_ZERO(val64);
   2081         if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit) ||
   2082             SOC_IS_HURRICANE2(unit) ||
   2083             soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) {
   2084             for (i = 0; i < 4; i++) {
   2085                 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   2086                                       _hg_trunk[i], 
   2087                                       add_info->tp[i%add_info->num_ports]);
   2088             }
   2089         } else {
   2090             for (i = 0; i < 8; i++) {
   2091                 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   2092                                       _hg_trunk[i], 
   2093                                       add_info->tp[i%add_info->num_ports]);
   2094             }
   2095         }
   2096         if (SOC_REG_FIELD_VALID(unit, HG_TRUNK_GROUPr, HIGIG_TRUNK_SIZEf)) { /* PR 34459 */
   2097             soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   2098                                   HIGIG_TRUNK_SIZEf, add_info->num_ports-1);
   2099         }
   2100         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64,
   2101                               HIGIG_TRUNK_RTAGf, t_info->rtag);
   2102         SOC_IF_ERROR_RETURN
   2103             (WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64));
   2104         COMPILER_64_ZERO(val64);
   2105 
   2106 #if defined(BCM_SCORPION_SUPPORT)
   2107         if (SOC_IS_SC_CQ(unit)) {
   2108             for (i = 8; i < 16; i++) {
   2109                 soc_reg64_field32_set(unit, HG_TRUNK_GROUP_HIr, &val64,
   2110                           _hg_trunk_hi[i - BCM_SWITCH_TRUNK_MAX_PORTCNT], 
   2111                                       add_info->tp[i%add_info->num_ports]);
   2112             }
   2113             SOC_IF_ERROR_RETURN
   2114                 (WRITE_HG_TRUNK_GROUP_HIr(unit, hgtid, val64));
   2115         }
   2116 #endif
   2117 
   2118 	BCM_IF_ERROR_RETURN
   2119 	    (_bcm_xgs3_trunk_fabric_port_set(unit,
   2120 					     hgtid,
   2121 					     old_trunk_pbmp,
   2122 					     new_trunk_pbmp));
   2123 
   2124 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   2125     if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   2126         BCM_IF_ERROR_RETURN
   2127             (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, add_info));
   2128     }
   2129 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   2130 
   2131         BCM_IF_ERROR_RETURN
   2132             (_bcm_xgs3_trunk_swfailover_fabric_set(unit,
   2133                                                    hgtid,
   2134                                                    t_info->rtag,
   2135                                                    new_trunk_pbmp));
   2136 
   2137         return BCM_E_NONE;
   2138     }
   2139 #endif /* BCM_BRADLEY_SUPPORT */
   2140     return BCM_E_UNAVAIL;
   2141 }
   2142 
   2143 /*
   2144  * Function:
   2145  *      _bcm_xgs3_trunk_property_migrate
   2146  * Purpose:
   2147  *      Migrate trunk properties from old members to new members of the trunk
   2148  *      group
   2149  * Parameters:
   2150  *      unit        - (IN) SOC unit number. 
   2151  *      num_leaving - (IN) Number of old members leaving the trunk group
   2152  *      leaving_arr - (IN) Array containing leaving members
   2153  *      num_staying - (IN) Number of old members staying in the trunk group
   2154  *      staying_arr - (IN) Array containing staying members
   2155  *      num_joining - (IN) Number of new members joining the trunk group
   2156  *      joining_arr - (IN) Array containing joining members
   2157  * Returns:
   2158  *      BCM_X_XXX
   2159  */
   2160 int 
   2161 _bcm_xgs3_trunk_property_migrate(int unit,
   2162                 int num_leaving, bcm_gport_t *leaving_arr,
   2163                 int num_staying, bcm_gport_t *staying_arr,
   2164                 int num_joining, bcm_gport_t *joining_arr)
   2165 {
   2166     bcm_module_t mod;
   2167     bcm_port_t port;
   2168     int stm_idx;
   2169     source_trunk_map_table_entry_t stm_entry;
   2170     int rv;
   2171 
   2172     if ((num_leaving > 0) && (NULL == leaving_arr)) {
   2173         return BCM_E_PARAM;
   2174     }
   2175     if ((num_staying > 0) && (NULL == staying_arr)) {
   2176         return BCM_E_PARAM;
   2177     }
   2178     if ((num_joining > 0) && (NULL == joining_arr)) {
   2179         return BCM_E_PARAM;
   2180     }
   2181 
   2182     if (num_leaving > 0) {
   2183         if (!BCM_GPORT_IS_MODPORT(leaving_arr[0])) {
   2184             return BCM_E_PARAM;
   2185         }
   2186         mod = BCM_GPORT_MODPORT_MODID_GET(leaving_arr[0]);
   2187         port = BCM_GPORT_MODPORT_PORT_GET(leaving_arr[0]);
   2188 
   2189     } else if (num_staying > 0) {
   2190         if (!BCM_GPORT_IS_MODPORT(staying_arr[0])) {
   2191             return BCM_E_PARAM;
   2192         }
   2193         mod = BCM_GPORT_MODPORT_MODID_GET(staying_arr[0]);
   2194         port = BCM_GPORT_MODPORT_PORT_GET(staying_arr[0]);
   2195 
   2196     } else {
   2197         /* Both num_leaving and num_staying are zeroes. This is a newly
   2198          * created trunk group. There is no trunk properties to migrate.
   2199          */ 
   2200         return BCM_E_NONE;
   2201     }
   2202 
   2203     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2204     rv = _bcm_esw_src_mod_port_table_index_get(unit, mod,
   2205                 port, &stm_idx);
   2206 
   2207     if (SOC_FAILURE(rv)) {
   2208         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2209         return rv;
   2210     }
   2211 
   2212     rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, stm_idx,
   2213                                       &stm_entry);
   2214     if (SOC_FAILURE(rv)) {
   2215         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2216         return rv;
   2217     }
   2218 
   2219     if (soc_feature(unit, soc_feature_vlan_translation_range)) {
   2220 #ifdef BCM_TRX_SUPPORT
   2221         if (SOC_IS_TRX(unit)) {
   2222             soc_field_t vlan_range_field;
   2223             soc_field_t inner_vlan_range_field;
   2224             int32 old_inner_vlan_range_idx, old_vlan_range_idx;
   2225             int32 inner_vlan_range_idx, vlan_range_idx;
   2226             int32 i;
   2227 
   2228             if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   2229                         OUTER_VLAN_RANGE_IDXf)) {
   2230                 vlan_range_field = OUTER_VLAN_RANGE_IDXf;
   2231             } else if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   2232                                            VLAN_RANGE_IDXf)) {
   2233                 vlan_range_field = VLAN_RANGE_IDXf;
   2234             } else {
   2235                 vlan_range_field = INVALIDf;
   2236             }
   2237 
   2238             if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm,
   2239                         INNER_VLAN_RANGE_IDXf)) {
   2240                 inner_vlan_range_field = INNER_VLAN_RANGE_IDXf;
   2241             } else {
   2242                 inner_vlan_range_field = INVALIDf;
   2243             }
   2244 
   2245             /* If VLAN RANGE fields are not valid to the device, return */
   2246             if ((vlan_range_field == INVALIDf) && 
   2247                 (inner_vlan_range_field == INVALIDf)) {
   2248                 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2249                 return BCM_E_NONE;
   2250             }
   2251 
   2252             /* Get trunk group's VLAN_RANGE_IDX */
   2253             vlan_range_idx = (vlan_range_field != INVALIDf) ? 
   2254                              soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
   2255                              &stm_entry, vlan_range_field): -1;
   2256 
   2257             /* Get trunk group's INNER_VLAN_RANGE_IDX */
   2258             inner_vlan_range_idx = (inner_vlan_range_field != INVALIDf) ?
   2259                                    soc_mem_field32_get(unit, 
   2260                                    SOURCE_TRUNK_MAP_TABLEm,
   2261                                    &stm_entry, inner_vlan_range_field): -1;
   2262 
   2263             /* Update VLAN_RANGE_IDX for members joining the trunk group */
   2264             for (i = 0; i < num_joining; i++) {
   2265                 if (!BCM_GPORT_IS_MODPORT(joining_arr[i])) {
   2266                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2267                     return BCM_E_PARAM;
   2268                 }
   2269                 mod = BCM_GPORT_MODPORT_MODID_GET(joining_arr[i]);
   2270                 port = BCM_GPORT_MODPORT_PORT_GET(joining_arr[i]);
   2271 
   2272                 rv = _bcm_esw_src_mod_port_table_index_get(unit,
   2273                             mod, port, &stm_idx);
   2274                 if(BCM_FAILURE(rv)) {
   2275                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2276                     return rv;
   2277                 }
   2278 
   2279                 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit,
   2280                             MEM_BLOCK_ANY, stm_idx, &stm_entry);
   2281                 if(BCM_FAILURE(rv)) {
   2282                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2283                     return rv;
   2284                 }
   2285 
   2286                 if (vlan_range_field != INVALIDf) { 
   2287                 /* Delete port's old VLAN range profile */
   2288                   old_vlan_range_idx = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(
   2289                                        unit, &stm_entry, vlan_range_field);
   2290 
   2291                   rv = _bcm_trx_vlan_range_profile_entry_delete(
   2292                                        unit, old_vlan_range_idx);
   2293 
   2294                   if(BCM_FAILURE(rv)) {
   2295                        soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2296                        return rv;
   2297                   }
   2298 
   2299                 /* Set port to use trunk group's VLAN range profile */
   2300                   _bcm_trx_vlan_range_profile_entry_increment(unit, 
   2301                                                                 vlan_range_idx);
   2302                 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry,
   2303                         vlan_range_field, vlan_range_idx);
   2304                 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   2305                             MEM_BLOCK_ALL, stm_idx, &stm_entry);
   2306                 if(BCM_FAILURE(rv)) {
   2307                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2308                     return rv;
   2309                 }
   2310             }
   2311 
   2312                 if (inner_vlan_range_field != INVALIDf) {
   2313                    /* Delete port's old INNER VLAN range profile */
   2314                    old_inner_vlan_range_idx = 
   2315                        soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry,
   2316                                                         inner_vlan_range_field);
   2317                    rv = _bcm_trx_vlan_range_profile_entry_delete(
   2318                                                      unit,
   2319                                                      old_inner_vlan_range_idx);
   2320 
   2321                    if(BCM_FAILURE(rv)) {
   2322                        soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2323                        return rv;
   2324                    }
   2325 
   2326                    /* Set port to use trunk group's INNER VLAN range profile */
   2327                    _bcm_trx_vlan_range_profile_entry_increment(unit, 
   2328                                                           inner_vlan_range_idx);
   2329                    soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry,
   2330                                   inner_vlan_range_field, inner_vlan_range_idx);
   2331                    rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   2332                                            MEM_BLOCK_ALL, stm_idx, &stm_entry);
   2333                    if(BCM_FAILURE(rv)) {
   2334                        soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2335                        return rv;
   2336                    }
   2337                 }
   2338             }
   2339 
   2340             /* Update VLAN_RANGE_IDX for members leaving the trunk group */
   2341             for (i = 0; i < num_leaving; i++) {
   2342                 if (!BCM_GPORT_IS_MODPORT(leaving_arr[i])) {
   2343                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2344                     return BCM_E_PARAM;
   2345                 }
   2346                 mod = BCM_GPORT_MODPORT_MODID_GET(leaving_arr[i]);
   2347                 port = BCM_GPORT_MODPORT_PORT_GET(leaving_arr[i]);
   2348                 rv = _bcm_esw_src_mod_port_table_index_get(unit,
   2349                             mod, port, &stm_idx);
   2350                 if(BCM_FAILURE(rv)) {
   2351                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2352                     return rv;
   2353                 }
   2354 
   2355                 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit,
   2356                             MEM_BLOCK_ANY, stm_idx, &stm_entry);
   2357 
   2358                 if(BCM_FAILURE(rv)) {
   2359                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2360                     return rv;
   2361                 }
   2362 
   2363                 if (vlan_range_field != INVALIDf) { 
   2364                 /* Delete port's old VLAN range profile */
   2365                    old_vlan_range_idx = 
   2366                       soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 
   2367                                                               &stm_entry, 
   2368                                                               vlan_range_field);
   2369                    rv = _bcm_trx_vlan_range_profile_entry_delete(unit,
   2370                                                             old_vlan_range_idx);
   2371                    if(BCM_FAILURE(rv)) {
   2372                        soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2373                        return rv;
   2374                    }
   2375 
   2376                 /* Set port to use the default VLAN range profile 0 */
   2377                 _bcm_trx_vlan_range_profile_entry_increment(unit, 0);
   2378                    soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, 
   2379                                                          &stm_entry,
   2380                                                          vlan_range_field, 0);
   2381                 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   2382                             MEM_BLOCK_ALL, stm_idx, &stm_entry);
   2383                 if(BCM_FAILURE(rv)) {
   2384                     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2385                     return rv;
   2386                 }
   2387             }
   2388 
   2389                 if (inner_vlan_range_field != INVALIDf) {
   2390                    /* Delete port's old INNER VLAN range profile */
   2391                    old_inner_vlan_range_idx = 
   2392                        soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry,
   2393                                                         inner_vlan_range_field);
   2394                    rv = _bcm_trx_vlan_range_profile_entry_delete(unit,
   2395                                                      old_inner_vlan_range_idx);
   2396                    if(BCM_FAILURE(rv)) {
   2397                        soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2398                        return rv;
   2399                    }
   2400 
   2401                    /* Set port to use trunk group's INNER VLAN range profile */
   2402                    _bcm_trx_vlan_range_profile_entry_increment(unit, 0); 
   2403                    soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry,
   2404                                                           inner_vlan_range_field,
   2405                                                           0);
   2406                    rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit,
   2407                                            MEM_BLOCK_ALL, stm_idx, &stm_entry);
   2408 
   2409                    if(BCM_FAILURE(rv)) {
   2410                        soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2411                        return rv;
   2412                    }
   2413                 }
   2414             }
   2415 
   2416         }
   2417 #endif /* BCM_TRX_SUPPORT */
   2418     }
   2419 
   2420     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
   2421     return BCM_E_NONE;
   2422 }
   2423 
   2424 /*
   2425  * Function:
   2426  *      _bcm_xgs3_trunk_set
   2427  * Purpose:
   2428  *      Set trunk members.
   2429  * Parameters:
   2430  *      unit     - (IN) SOC unit number. 
   2431  *      tid      - (IN) Trunk group ID.
   2432  *      add_info - (IN) Pointer to trunk add info structure.
   2433  *      t_info   - (IN) Pointer to trunk info.
   2434  * Returns:
   2435  *      BCM_E_xxx
   2436  */
   2437 STATIC int
   2438 _bcm_xgs3_trunk_set(int unit,
   2439         bcm_trunk_t tid,
   2440         _esw_trunk_add_info_t *add_info,
   2441         trunk_private_t *t_info)
   2442 {
   2443     int rv = BCM_E_NONE;
   2444     trunk_bitmap_entry_t        trunk_bitmap_entry;
   2445     uint32                      tg_entry[SOC_MAX_MEM_WORDS];
   2446     pbmp_t                      old_trunk_pbmp;
   2447     pbmp_t                      new_trunk_pbmp;
   2448     pbmp_t                      nuc_trunk_pbmp;
   2449     bcm_gport_t                 gport;
   2450     bcm_port_t                  loc_port;
   2451     int                         port, mod, mod_out, port_out;
   2452     int                         i, j, k, remove_trunk_port;
   2453     int                         hwmod[BCM_XGS3_TRUNK_MAX_PORTCNT];
   2454     int                         egr_hwmod[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   2455     int                         uc_egr_hwmod[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   2456     int                         hwport[BCM_XGS3_TRUNK_MAX_PORTCNT];
   2457     int                         egr_hwport[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   2458     int                         uc_egr_hwport[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   2459     uint32                      egr_member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   2460     int                         max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT;
   2461     bcm_trunk_chip_info_t       chip_info;
   2462     uint32                      my_modid_bmap = 0;
   2463     uint32                      nuc_member_count = 0;
   2464     uint32                      nuc_tpbm = 0;
   2465     uint32                      negr_disable_port = 0;
   2466     uint32                      num_uc_egr_disable_port = 0;
   2467     int                         num_leaving_members = 0;
   2468     bcm_gport_t                 leaving_members[BCM_SWITCH_TRUNK_MAX_PORTCNT];
   2469     int                         match_leaving_members;
   2470     int                         num_staying_members = 0;
   2471     bcm_gport_t                 staying_members[BCM_SWITCH_TRUNK_MAX_PORTCNT];
   2472     int                         match_staying_members;
   2473     int                         num_joining_members = 0;
   2474     bcm_gport_t                 joining_members[BCM_SWITCH_TRUNK_MAX_PORTCNT];
   2475     int                         match_joining_members;
   2476     soc_mem_t                   trunk_mem = TRUNK_GROUPm;
   2477 
   2478     if (soc_feature(unit, soc_feature_fastlag)) {
   2479         trunk_mem = FAST_TRUNK_GROUPm;
   2480     }
   2481 
   2482     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2483     if (chip_info.trunk_fabric_id_min >= 0 &&
   2484         tid >= chip_info.trunk_fabric_id_min) {        /* fabric trunk */
   2485         tid -= chip_info.trunk_fabric_id_min;
   2486         /* coverity[stack_use_callee] */
   2487         /* coverity[stack_use_overflow] */
   2488         return _bcm_xgs3_trunk_fabric_set(unit, tid, add_info, t_info);
   2489     }
   2490 
   2491     if (add_info->flags & BCM_TRUNK_FLAG_IPMC_CLEAVE) {
   2492         return BCM_E_UNAVAIL;
   2493     }
   2494 
   2495     /* Audit unsupported flag combination */
   2496     for (i = 0; i < add_info->num_ports; i++) {
   2497         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE &&
   2498             add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   2499                 return BCM_E_PARAM;
   2500         }
   2501         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE &&
   2502             add_info->member_flags[i] & BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   2503                 return BCM_E_PARAM;
   2504         }
   2505     }
   2506 
   2507     if (add_info->dlf_index == -1) {
   2508         BCM_IF_ERROR_RETURN(_bcm_nuc_tpbm_get(unit, 
   2509                                               add_info->num_ports, 
   2510                                               add_info->tm, 
   2511                                               &nuc_tpbm));
   2512     } else {
   2513         nuc_tpbm = (0x1 << add_info->dlf_index);
   2514     }
   2515 
   2516     SOC_PBMP_CLEAR(new_trunk_pbmp);
   2517     SOC_PBMP_CLEAR(nuc_trunk_pbmp);
   2518     for (i = 0; i < add_info->num_ports; i++) {
   2519         mod = add_info->tm[i];
   2520         port = add_info->tp[i];
   2521         BCM_IF_ERROR_RETURN
   2522             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   2523                                      mod, port,
   2524                                      &mod_out, &port_out));
   2525         if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
   2526             return BCM_E_BADID;
   2527         }
   2528         if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
   2529             return BCM_E_PORT;
   2530         }
   2531 
   2532         /** Don't add the port in trunk group if egress disable is set */
   2533         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   2534             nuc_tpbm &= ~(1 << i); 
   2535             negr_disable_port++;
   2536         } else if (add_info->member_flags[i] &
   2537                 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   2538             num_uc_egr_disable_port++;
   2539         }
   2540 
   2541         /* Save mapped version */
   2542         hwmod[i] = mod_out;
   2543         hwport[i] = port_out;
   2544 
   2545         BCM_GPORT_MODPORT_SET(gport, mod_out, port_out);
   2546         if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) { 
   2547             if (!IS_E_PORT(unit, loc_port)) {
   2548                 return BCM_E_PARAM;
   2549             }
   2550             SOC_PBMP_PORT_ADD(new_trunk_pbmp, loc_port);
   2551             if (nuc_tpbm & (1 << i)) {
   2552                 /* Eligible for NUC forwarding */
   2553                 SOC_PBMP_PORT_ADD(nuc_trunk_pbmp, loc_port);
   2554                 my_modid_bmap |= (1 << nuc_member_count);
   2555             }
   2556         }
   2557 
   2558         if (nuc_tpbm & (1 << i)) {
   2559             /* Eligible for NUC forwarding */
   2560             nuc_member_count++;
   2561         }
   2562     }
   2563 
   2564     /*
   2565      * Clean up old trunk membership 
   2566      */
   2567     SOC_PBMP_CLEAR(old_trunk_pbmp);
   2568     if (t_info->in_use) {
   2569         for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   2570             mod = MEMBER_INFO(unit, tid).modport[i] >> 8;
   2571             port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   2572             BCM_GPORT_MODPORT_SET(gport, mod, port);
   2573             if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) {
   2574                 if (SOC_PORT_VALID(unit, loc_port)) {
   2575                     SOC_PBMP_PORT_ADD(old_trunk_pbmp, loc_port);
   2576                 }
   2577             } else {
   2578                 loc_port = BCM_GPORT_INVALID;
   2579             }
   2580             /* Invalidate port only if it is not a part of the new trunk group */
   2581             remove_trunk_port = TRUE;
   2582             for (j = 0; j < add_info->num_ports; j++) {
   2583                 /* Note: Compare with the mapped version as thats the one set in h/w */
   2584                 if (mod == hwmod[j] && port == hwport[j]) { 
   2585                     remove_trunk_port = FALSE;
   2586                 }
   2587             }
   2588             if (remove_trunk_port) {
   2589                 /* Add port to array containing members leaving the trunk
   2590                  * group if it is different from previous leaving members
   2591                  */
   2592                 match_leaving_members = FALSE;
   2593                 for (k = 0; k < num_leaving_members; k++) {
   2594                     if (gport == leaving_members[k]) {
   2595                         match_leaving_members = TRUE;
   2596                         break;
   2597                     }
   2598                 }
   2599                 if (!match_leaving_members) {
   2600                     leaving_members[num_leaving_members++] = gport;
   2601                 }
   2602 
   2603                 BCM_IF_ERROR_RETURN
   2604                     (_bcm_xgs3_trunk_set_port_property(unit, mod, port, -1));
   2605 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   2606                 if (soc_feature(unit, soc_feature_port_lag_failover) &&
   2607                     (BCM_GPORT_INVALID != loc_port) &&
   2608                     IS_E_PORT(unit, loc_port)) 
   2609                 {
   2610                     /* Clear HW failover info for deleted port */
   2611                     BCM_IF_ERROR_RETURN
   2612                         (_bcm_xgs3_trunk_hwfailover_set(unit, tid, FALSE,
   2613                                                         port, mod,
   2614                                                         add_info->psc,
   2615                                                         0, 0, NULL, NULL));
   2616                 }
   2617 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   2618             } else {
   2619                 /* Add port to array containing members staying in the trunk
   2620                  * group if it is different from previous staying members
   2621                  */
   2622                 match_staying_members = FALSE;
   2623                 for (k = 0; k < num_staying_members; k++) {
   2624                     if (gport == staying_members[k]) {
   2625                         match_staying_members = TRUE;
   2626                         break;
   2627                     }
   2628                 }
   2629                 if (!match_staying_members) {
   2630                     staying_members[num_staying_members++] = gport;
   2631                 }
   2632             }
   2633         }
   2634     }
   2635 
   2636     /* Generate array containing new members joining the trunk group */
   2637     for (i = 0; i < add_info->num_ports; i++) {
   2638         BCM_GPORT_MODPORT_SET(gport, hwmod[i], hwport[i]); 
   2639         match_staying_members = FALSE;
   2640         for (j = 0; j < num_staying_members; j++) {
   2641             if (gport == staying_members[j]) {
   2642                 match_staying_members = TRUE;
   2643                 break;
   2644             }
   2645         }
   2646         if (!match_staying_members) {
   2647             match_joining_members = FALSE;
   2648             for (j = 0; j < num_joining_members; j++) {
   2649                 if (gport == joining_members[j]) {
   2650                     match_joining_members = TRUE;
   2651                     break;
   2652                 }
   2653             }
   2654             if (!match_joining_members) {
   2655                 joining_members[num_joining_members++] = gport;
   2656             }
   2657         }
   2658     }
   2659 
   2660     sal_memset(&tg_entry, 0, sizeof(tg_entry));
   2661 
   2662     if (soc_feature(unit, soc_feature_fastlag)) {
   2663         soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, t_info->rtag);
   2664     } else {
   2665         soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, t_info->rtag);
   2666     }
   2667 
   2668     if (soc_feature(unit, soc_feature_trunk_group_size)) { /* TG_SIZE field exists */
   2669         if ( (add_info->num_ports - negr_disable_port -
   2670                     num_uc_egr_disable_port) == 0 ) {
   2671             if (soc_feature(unit, soc_feature_fastlag)) {
   2672                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0);
   2673             } else {
   2674                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0);
   2675             }
   2676         } else {
   2677             if (soc_feature(unit, soc_feature_fastlag)) {
   2678                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf,
   2679                                                   add_info->num_ports - 1
   2680                                                   - negr_disable_port
   2681                                                   - num_uc_egr_disable_port);
   2682             } else {
   2683                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   2684                                              TG_SIZEf, add_info->num_ports - 1
   2685                                              - negr_disable_port
   2686                                              - num_uc_egr_disable_port);
   2687             }
   2688         }
   2689     }
   2690 
   2691     if ((add_info->num_ports - negr_disable_port - num_uc_egr_disable_port) > 0 ) {
   2692         for (i = 0, j = 0; i < add_info->num_ports; i++) {
   2693             if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   2694                 continue;
   2695 	    }
   2696             egr_hwmod[j] = hwmod[i];
   2697             egr_hwport[j] = hwport[i];
   2698             egr_member_flags[j] = add_info->member_flags[i];
   2699             j++;
   2700         }
   2701         for (i = 0, k = 0; i < j; i++) {
   2702             if (egr_member_flags[i] & BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   2703                 continue;
   2704 	    }
   2705             uc_egr_hwmod[k] = egr_hwmod[i];
   2706             uc_egr_hwport[k] = egr_hwport[i];
   2707             k++;
   2708         }
   2709         if (k != 0) {
   2710             for (i = 0; i < max_ports; i++) {
   2711                 mod = uc_egr_hwmod[i%k];
   2712                 port = uc_egr_hwport[i%k];
   2713                 if (soc_feature(unit, soc_feature_fastlag)) {
   2714                     soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_modulef[i], mod);
   2715                     soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_portf[i], port);
   2716                 } else {
   2717                     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_modulef[i], mod);
   2718                     soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_portf[i], port);
   2719                 }
   2720             }
   2721         }
   2722     } else {
   2723         /** no ports are enabled in the trunk */
   2724         for ( i = 0; i < max_ports; i++ ) {
   2725 	    /** drop packets */
   2726             if (soc_feature(unit, soc_feature_fastlag)) {
   2727                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_modulef[i], 0);
   2728                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_portf[i], 0);
   2729             } else {
   2730                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_modulef[i], 0);
   2731                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_portf[i], 0);
   2732             }
   2733         }
   2734     }
   2735 
   2736     /** Don't add the port in the source trunk map if ingress disable is set */
   2737     for (i = 0; i < add_info->num_ports; i++) {
   2738         mod = hwmod[i%add_info->num_ports];
   2739         port = hwport[i%add_info->num_ports];
   2740 
   2741         if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE) {
   2742             BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_set_port_property(unit, mod, 
   2743                                                                   port, -1));
   2744         } else {
   2745             BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_set_port_property(unit, mod, 
   2746                                                                   port, tid));
   2747         }
   2748     }    
   2749 
   2750     /*
   2751      * Update TRUNK_BITMAP table
   2752      */
   2753     BCM_IF_ERROR_RETURN(
   2754         soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid,
   2755                      &trunk_bitmap_entry));
   2756     soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   2757                            TRUNK_BITMAPf, &new_trunk_pbmp);
   2758     BCM_IF_ERROR_RETURN(
   2759         soc_mem_write(unit, TRUNK_BITMAPm, MEM_BLOCK_ALL, tid,
   2760                       &trunk_bitmap_entry));
   2761     /*
   2762      * Update TRUNK_GROUP table
   2763      */
   2764     BCM_IF_ERROR_RETURN(
   2765         soc_mem_write(unit, trunk_mem, MEM_BLOCK_ALL, tid, &tg_entry));
   2766 
   2767     /*
   2768      * Update the trunk block mask
   2769      */
   2770     if (SOC_PBMP_NOT_NULL(new_trunk_pbmp) ||
   2771         SOC_PBMP_NOT_NULL(old_trunk_pbmp)) {
   2772         BCM_IF_ERROR_RETURN(
   2773             _bcm_xgs3_trunk_block_mask(unit,
   2774                                        old_trunk_pbmp,
   2775                                        new_trunk_pbmp,
   2776                                        nuc_trunk_pbmp,
   2777                                        my_modid_bmap,
   2778                                        nuc_member_count));
   2779     }
   2780     /*
   2781      * Trunk Failover
   2782      */
   2783 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   2784     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   2785         BCM_IF_ERROR_RETURN
   2786             (_bcm_xgs3_trunk_failover_set(unit, tid, FALSE, add_info));
   2787     }
   2788 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   2789     BCM_IF_ERROR_RETURN
   2790        (_bcm_xgs3_trunk_swfailover_set(unit,
   2791                                        tid,
   2792                                        t_info->rtag,
   2793                                        add_info->num_ports - negr_disable_port,
   2794                                        egr_hwmod,
   2795                                        egr_hwport,
   2796                                        egr_member_flags));
   2797 
   2798     /* Migrate trunk properties from old members to new members */
   2799     BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_property_migrate(unit,
   2800                 num_leaving_members, leaving_members,
   2801                 num_staying_members, staying_members,
   2802                 num_joining_members, joining_members));
   2803 
   2804     /* Save new trunk member info */
   2805     for (i = 0; i < add_info->num_ports; i++) {
   2806         MEMBER_INFO(unit, tid).modport[i] = ((hwmod[i] & 0xff) << 8) |
   2807                                             (hwport[i] & 0xff);
   2808         MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i];
   2809     }
   2810     MEMBER_INFO(unit, tid).num_ports = add_info->num_ports;
   2811 
   2812 #ifdef BCM_GREYHOUND2_SUPPORT
   2813 #ifdef INCLUDE_L3
   2814     /* Call VXLAN module to clear states for local leaving members */
   2815     if (soc_feature(unit, soc_feature_vxlan_lite)) {
   2816         if (num_leaving_members > 0) {
   2817             rv = _bcm_esw_vxlan_trunk_member_delete(unit, tid,
   2818                                                     num_leaving_members,
   2819                                                     leaving_members);
   2820             if (BCM_FAILURE(rv)) {
   2821                 return rv;
   2822             }
   2823         }
   2824     }
   2825 #endif /* INCLUDE_L3 */
   2826 #endif /* BCM_GREYHOUND2_SUPPORT */
   2827 
   2828     return rv;
   2829 }
   2830 
   2831 /*
   2832  * Function:
   2833  *      _xgs3_trunk_add_info_member_alloc
   2834  * Purpose:
   2835  *      Allocate member_flags, tp, and tm of _esw_trunk_add_info_t.
   2836  * Parameters:
   2837  *      add_info  - (IN) Pointer to trunk add info structure.
   2838  *      num_ports - (IN) Number of member ports.
   2839  * Returns:
   2840  *      BCM_E_xxx
   2841  */
   2842 STATIC int
   2843 _xgs3_trunk_add_info_member_alloc(_esw_trunk_add_info_t *add_info,
   2844         int num_ports)
   2845 {
   2846     int rv = BCM_E_NONE;
   2847 
   2848     add_info->member_flags = sal_alloc(sizeof(uint32) * num_ports,
   2849             "_xgs3_trunk_add_info_member_flags");
   2850     if (add_info->member_flags == NULL) {
   2851         rv = BCM_E_MEMORY;
   2852         goto error;
   2853     }
   2854     sal_memset(add_info->member_flags, 0, sizeof(uint32) * num_ports);
   2855 
   2856     add_info->tp = sal_alloc(sizeof(bcm_port_t) * num_ports,
   2857             "_xgs3_trunk_add_info_tp");
   2858     if (add_info->tp == NULL) {
   2859         rv = BCM_E_MEMORY;
   2860         goto error;
   2861     }
   2862     sal_memset(add_info->tp, 0, sizeof(bcm_port_t) * num_ports);
   2863 
   2864     add_info->tm = sal_alloc(sizeof(bcm_module_t) * num_ports,
   2865             "_xgs3_trunk_add_info_tm");
   2866     if (add_info->tm == NULL) {
   2867         rv = BCM_E_MEMORY;
   2868         goto error;
   2869     }
   2870     sal_memset(add_info->tm, 0, sizeof(bcm_module_t) * num_ports);
   2871 
   2872     return rv;
   2873 
   2874 error:
   2875     if (NULL != add_info->member_flags) {
   2876         sal_free(add_info->member_flags);
   2877     }
   2878     if (NULL != add_info->tp) {
   2879         sal_free(add_info->tp);
   2880     }
   2881     if (NULL != add_info->tm) {
   2882         sal_free(add_info->tm);
   2883     }
   2884 
   2885     return rv;
   2886 }
   2887 
   2888 /*
   2889  * Function:
   2890  *      _xgs3_trunk_add_info_member_free
   2891  * Purpose:
   2892  *      Free member_flags, tp, and tm of _esw_trunk_add_info_t.
   2893  * Parameters:
   2894  *      add_info  - (IN) Pointer to trunk add info structure.
   2895  * Returns:
   2896  *      BCM_E_xxx
   2897  */
   2898 STATIC void 
   2899 _xgs3_trunk_add_info_member_free(_esw_trunk_add_info_t *add_info)
   2900 {
   2901     if (NULL != add_info->member_flags) {
   2902         sal_free(add_info->member_flags);
   2903     }
   2904     if (NULL != add_info->tp) {
   2905         sal_free(add_info->tp);
   2906     }
   2907     if (NULL != add_info->tm) {
   2908         sal_free(add_info->tm);
   2909     }
   2910 }
   2911 
   2912 /*
   2913  * Function:
   2914  *      bcm_xgs3_trunk_modify
   2915  * Purpose:
   2916  *      Set trunk members.
   2917  * Parameters:
   2918  *      unit       - (IN) SOC unit number. 
   2919  *      tid        - (IN) Trunk group ID.
   2920  *      trunk_info - (IN) Pointer to user provided trunk info.
   2921  *      member_count - (IN) Number of trunk members.
   2922  *      member_array - (IN) Array of trunk members.
   2923  *      t_info       - (IN) Pointer to internal trunk info.
   2924  *      op           - (IN) Not used by this procedure.
   2925  *      member       - (IN) Not used by this procedure.
   2926  * Returns:
   2927  *      BCM_E_xxx
   2928  */
   2929 int
   2930 bcm_xgs3_trunk_modify(int unit,
   2931         bcm_trunk_t tid,
   2932         bcm_trunk_info_t *trunk_info,
   2933         int member_count,
   2934         bcm_trunk_member_t *member_array,
   2935         trunk_private_t *t_info,
   2936         int op,
   2937         bcm_trunk_member_t *member)
   2938 {
   2939     int rv = BCM_E_NONE;
   2940     bcm_trunk_chip_info_t chip_info;
   2941     _esw_trunk_add_info_t add_info;
   2942     int i;
   2943     int higig_trunk;
   2944 
   2945     if (trunk_info->psc <= 0) {
   2946         trunk_info->psc = BCM_TRUNK_PSC_DEFAULT;
   2947     }
   2948     BCM_IF_ERROR_RETURN
   2949         (_bcm_xgs3_trunk_psc_to_rtag(unit, trunk_info->psc, &(t_info->rtag)));
   2950 
   2951     t_info->flags = trunk_info->flags;
   2952 
   2953     if ((trunk_info->dlf_index != trunk_info->mc_index) ||
   2954         (trunk_info->dlf_index != trunk_info->ipmc_index)) {
   2955         return BCM_E_PARAM;
   2956     }
   2957 
   2958     t_info->dlf_index_spec =
   2959         t_info->dlf_index_used =
   2960         t_info->mc_index_spec = 
   2961         t_info->mc_index_used =
   2962         t_info->ipmc_index_spec =
   2963         t_info->ipmc_index_used = trunk_info->dlf_index;
   2964 
   2965     if (member_count < 1) {
   2966         if (t_info->in_use) {
   2967             /* Delete existing trunk member ports */
   2968             BCM_IF_ERROR_RETURN
   2969                 (bcm_xgs3_trunk_destroy(unit, tid, t_info));
   2970         }
   2971     } else {
   2972         sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t));
   2973 
   2974         add_info.flags = trunk_info->flags;
   2975         add_info.num_ports = member_count;
   2976         add_info.psc = trunk_info->psc;
   2977         add_info.ipmc_psc = trunk_info->ipmc_psc;
   2978         add_info.dlf_index = trunk_info->dlf_index;
   2979         add_info.mc_index = trunk_info->mc_index;
   2980         add_info.ipmc_index = trunk_info->ipmc_index;
   2981 
   2982         BCM_IF_ERROR_RETURN
   2983             (_xgs3_trunk_add_info_member_alloc(&add_info, member_count));
   2984 
   2985         for (i = 0; i < member_count; i++) {
   2986             add_info.member_flags[i] = member_array[i].flags;
   2987             add_info.tp[i] = member_array[i].gport;
   2988             add_info.tm[i] = -1;
   2989         }
   2990 
   2991         /* Convert member gport to module and port */
   2992         BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   2993         if (chip_info.trunk_fabric_id_min >= 0 &&
   2994             tid >= chip_info.trunk_fabric_id_min) {
   2995             higig_trunk = 1;
   2996         } else {
   2997             higig_trunk = 0;
   2998         }
   2999         rv = _bcm_esw_trunk_gport_array_resolve(unit,
   3000                 higig_trunk,
   3001                 member_count,
   3002                 add_info.tp,
   3003                 add_info.tp,
   3004                 add_info.tm);
   3005         if (BCM_FAILURE(rv)) {
   3006             _xgs3_trunk_add_info_member_free(&add_info);
   3007             return rv;
   3008         }
   3009 
   3010         rv = _bcm_xgs3_trunk_set(unit, tid, &add_info, t_info);
   3011         _xgs3_trunk_add_info_member_free(&add_info);
   3012     }
   3013 
   3014     return rv;
   3015 }
   3016 
   3017 STATIC int
   3018 _bcm_xgs3_trunk_fabric_destroy(int unit,
   3019                                bcm_trunk_t hgtid,
   3020                                trunk_private_t *t_info)
   3021 {
   3022     int i, tid;
   3023 
   3024     /* Clear trunk member info */
   3025     tid = hgtid + _BCM_FP_TRUNK_NUM_MAX;
   3026     for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   3027         MEMBER_INFO(unit, tid).modport[i] = 0;
   3028         MEMBER_INFO(unit, tid).member_flags[i] = 0;
   3029     }
   3030     MEMBER_INFO(unit, tid).num_ports = 0;
   3031 
   3032     if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) &&
   3033         soc_feature(unit, soc_feature_hg_trunking)) {
   3034         uint32                hg_group_entry, hg_cntl_entry;
   3035         pbmp_t                pbmp, hg_pbmp;
   3036         uint32                pword, hgp;
   3037         soc_field_t          *trunkf, rtagf, bmapf; 
   3038         bcm_port_t            port;
   3039 #if defined(BCM_FIREBOLT2_SUPPORT)
   3040         soc_field_t           sizef;
   3041 #endif /* BCM_FIREBOLT2_SUPPORT */
   3042 
   3043         switch (hgtid) {
   3044         case 0:
   3045             trunkf = _hg_trunk0f;
   3046             rtagf = HIGIG_TRUNK_RTAG0f;
   3047             bmapf = HIGIG_TRUNK_BITMAP0f;
   3048 #if defined(BCM_FIREBOLT2_SUPPORT)
   3049             sizef = HIGIG_TRUNK_SIZE0f;
   3050 #endif /* BCM_FIREBOLT2_SUPPORT */
   3051             break;
   3052         case 1:
   3053             trunkf = _hg_trunk1f;
   3054             rtagf = HIGIG_TRUNK_RTAG1f;
   3055             bmapf = HIGIG_TRUNK_BITMAP1f;
   3056 #if defined(BCM_FIREBOLT2_SUPPORT)
   3057             sizef = HIGIG_TRUNK_SIZE1f;
   3058 #endif /* BCM_FIREBOLT2_SUPPORT */
   3059             break;
   3060         default:
   3061             return BCM_E_PARAM;
   3062         }
   3063 
   3064         SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_CONTROLr(unit, &hg_cntl_entry));
   3065         pword = soc_reg_field_get(unit, HIGIG_TRUNK_CONTROLr, hg_cntl_entry,
   3066                                   bmapf);
   3067         SOC_PBMP_CLEAR(pbmp);
   3068         SOC_PBMP_CLEAR(hg_pbmp);
   3069         SOC_PBMP_WORD_SET(hg_pbmp, 0, pword);
   3070         if (SOC_IS_RAVEN(unit)) {
   3071             /* Use the bitmap directly for Raven */
   3072             SOC_PBMP_ASSIGN(pbmp, hg_pbmp); 
   3073         } else {
   3074             /* For other FBX, map the read higig bitmap to the physical bitmap */
   3075             soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp);
   3076         }
   3077         soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   3078                           bmapf, 0);
   3079 
   3080         PBMP_ITER(pbmp, port) {
   3081             BCM_IF_ERROR_RETURN(
   3082                 soc_xgs3_port_to_higig_bitmap(unit, port, &hgp)); 
   3083             BCM_IF_ERROR_RETURN(
   3084                 soc_xgs3_higig_bitmap_to_higig_port_num(hgp, &hgp));
   3085             soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   3086                               _hg_cntl0f[hgp], 0);
   3087             soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry,
   3088                               _hg_cntl1f[hgp], 0);
   3089         }
   3090         SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_CONTROLr(unit, hg_cntl_entry));
   3091 
   3092         SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_GROUPr(unit, &hg_group_entry));
   3093         for (i = 0; i < 4; i++) {
   3094             soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry,
   3095                               trunkf[i], 0);
   3096         }
   3097 #if defined(BCM_FIREBOLT2_SUPPORT)
   3098         if (soc_feature(unit, soc_feature_trunk_group_size)) {
   3099             soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry,
   3100                               sizef, 0);
   3101         }          
   3102 #endif /* BCM_FIREBOLT2_SUPPORT */
   3103         soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry,
   3104                           rtagf, 0);
   3105         SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_GROUPr(unit, hg_group_entry));
   3106 
   3107         SOC_PBMP_CLEAR(hg_pbmp);
   3108         BCM_IF_ERROR_RETURN
   3109             (_bcm_xgs3_trunk_swfailover_fabric_set(unit,
   3110                                                    hgtid,
   3111                                                    0,
   3112                                                    hg_pbmp));
   3113 
   3114         t_info->in_use = FALSE;
   3115         return BCM_E_NONE;
   3116     }
   3117 #if defined(BCM_TRIUMPH2_SUPPORT)
   3118     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   3119         SOC_IS_VALKYRIE2(unit)) {
   3120         uint64		val64;
   3121         pbmp_t		old_trunk_pbmp, new_trunk_pbmp, hg_pbm;
   3122 
   3123         SOC_IF_ERROR_RETURN
   3124             (READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64));
   3125         SOC_PBMP_CLEAR(hg_pbm);
   3126         SOC_PBMP_WORD_SET(hg_pbm, 0,
   3127                           soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
   3128                                                 val64, HIGIG_TRUNK_BITMAP_LOf));
   3129         SOC_PBMP_WORD_SET(hg_pbm, 1,
   3130                           soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
   3131                                                 val64, HIGIG_TRUNK_BITMAP_HIf));
   3132         SOC_PBMP_CLEAR(old_trunk_pbmp);
   3133         SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm);
   3134 
   3135         COMPILER_64_ZERO(val64);
   3136         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAP_64r(unit, hgtid, val64));
   3137         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64));
   3138 
   3139         SOC_PBMP_CLEAR(new_trunk_pbmp);
   3140 	BCM_IF_ERROR_RETURN
   3141 	    (_bcm_xgs3_trunk_fabric_port_set(unit,
   3142 					     hgtid,
   3143 					     old_trunk_pbmp,
   3144 					     new_trunk_pbmp));
   3145 
   3146        if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   3147             BCM_IF_ERROR_RETURN
   3148                 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, NULL));
   3149         }
   3150 
   3151         BCM_IF_ERROR_RETURN
   3152             (_bcm_xgs3_trunk_swfailover_fabric_set(unit,
   3153                                                    hgtid,
   3154                                                    0,
   3155                                                    new_trunk_pbmp));
   3156 
   3157         t_info->in_use = FALSE;
   3158         return BCM_E_NONE;
   3159     }
   3160 #endif /* BCM_TRIUMPH2_SUPPORT */
   3161 #if defined(BCM_GREYHOUND2_SUPPORT)
   3162     if (soc_feature(unit, soc_feature_high_portcount_register)) {
   3163         uint64 val64;
   3164         uint64 hg_trunk_bmap_f;
   3165         pbmp_t old_trunk_pbmp, new_trunk_pbmp, hg_pbm;
   3166 
   3167         SOC_IF_ERROR_RETURN
   3168             (READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64));
   3169         hg_trunk_bmap_f =
   3170             soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr,
   3171                                 val64, HIGIG_TRUNK_BITMAPf);
   3172 
   3173         SOC_PBMP_CLEAR(hg_pbm);
   3174         SOC_PBMP_WORD_SET(hg_pbm, 0, COMPILER_64_LO(hg_trunk_bmap_f));
   3175         SOC_PBMP_WORD_SET(hg_pbm, 1, COMPILER_64_HI(hg_trunk_bmap_f));
   3176 
   3177         SOC_IF_ERROR_RETURN
   3178             (READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64));
   3179         hg_trunk_bmap_f =
   3180             soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr,
   3181                                 val64, HIGIG_TRUNK_BITMAPf);
   3182         SOC_PBMP_WORD_SET(hg_pbm, 2, COMPILER_64_LO(hg_trunk_bmap_f));
   3183 
   3184         SOC_PBMP_CLEAR(old_trunk_pbmp);
   3185         SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm);
   3186 
   3187         COMPILER_64_ZERO(val64);
   3188         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAP_LOr(unit, hgtid, val64));
   3189         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAP_HIr(unit, hgtid, val64));
   3190         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64));
   3191 
   3192         SOC_PBMP_CLEAR(new_trunk_pbmp);
   3193         BCM_IF_ERROR_RETURN(
   3194             _bcm_xgs3_trunk_fabric_port_set(unit, hgtid,
   3195                                             old_trunk_pbmp, new_trunk_pbmp));
   3196 
   3197        if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   3198             BCM_IF_ERROR_RETURN
   3199                 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, NULL));
   3200         }
   3201 
   3202         BCM_IF_ERROR_RETURN
   3203             (_bcm_xgs3_trunk_swfailover_fabric_set(unit, hgtid,
   3204                                                    0, new_trunk_pbmp));
   3205 
   3206         t_info->in_use = FALSE;
   3207         return BCM_E_NONE;
   3208     }
   3209 #endif /* BCM_GREYHOUND2_SUPPORT */
   3210 #if defined(BCM_BRADLEY_SUPPORT)
   3211     if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) {
   3212         uint32		val;
   3213         uint64		val64;
   3214         pbmp_t		old_trunk_pbmp, new_trunk_pbmp, hg_pbm;
   3215 
   3216         SOC_IF_ERROR_RETURN
   3217             (READ_HG_TRUNK_BITMAPr(unit, hgtid, &val));
   3218         SOC_PBMP_CLEAR(hg_pbm);
   3219         SOC_PBMP_WORD_SET(hg_pbm, 0,
   3220                           soc_reg_field_get(unit, HG_TRUNK_BITMAPr,
   3221                                             val, HIGIG_TRUNK_BITMAPf));
   3222         SOC_PBMP_CLEAR(old_trunk_pbmp);
   3223         soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbm, &old_trunk_pbmp);
   3224 
   3225         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAPr(unit, hgtid, 0));
   3226         COMPILER_64_ZERO(val64);
   3227         SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64));
   3228 
   3229 #if defined(BCM_SCORPION_SUPPORT)
   3230         if (SOC_IS_SC_CQ(unit)) {
   3231             SOC_IF_ERROR_RETURN
   3232                 (WRITE_HG_TRUNK_GROUP_HIr(unit, hgtid, val64));
   3233         }
   3234 #endif
   3235         SOC_PBMP_CLEAR(new_trunk_pbmp);
   3236 	BCM_IF_ERROR_RETURN
   3237 	    (_bcm_xgs3_trunk_fabric_port_set(unit,
   3238 					     hgtid,
   3239 					     old_trunk_pbmp,
   3240 					     new_trunk_pbmp));
   3241         
   3242         if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   3243             BCM_IF_ERROR_RETURN
   3244                 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, NULL));
   3245         }
   3246 
   3247         BCM_IF_ERROR_RETURN
   3248             (_bcm_xgs3_trunk_swfailover_fabric_set(unit,
   3249                                                    hgtid,
   3250                                                    0,
   3251                                                    new_trunk_pbmp));
   3252 
   3253         t_info->in_use = FALSE;
   3254         return BCM_E_NONE;
   3255     }
   3256 #endif /* BCM_BRADLEY_SUPPORT */
   3257 
   3258 
   3259     return BCM_E_UNAVAIL;
   3260 }
   3261 
   3262 /*
   3263  * Function:
   3264  *      bcm_xgs3_trunk_destroy
   3265  * Purpose:
   3266  *      Multiplexed trunking function for XGS3
   3267  */
   3268 int
   3269 bcm_xgs3_trunk_destroy(int unit,
   3270                        bcm_trunk_t tid,
   3271                        trunk_private_t *t_info)
   3272 {
   3273     bcm_module_t                mod;
   3274     bcm_port_t                  port, loc_port;
   3275     bcm_gport_t                 gport;
   3276     pbmp_t                      old_ports, new_ports;
   3277     int                         i;
   3278     bcm_trunk_chip_info_t       chip_info;
   3279     int                         num_leaving_members = 0;
   3280     bcm_gport_t                 leaving_members[BCM_SWITCH_TRUNK_MAX_PORTCNT];
   3281     soc_mem_t                   trunk_mem = TRUNK_GROUPm;
   3282 
   3283     if (soc_feature(unit, soc_feature_fastlag)) {
   3284         trunk_mem = FAST_TRUNK_GROUPm;
   3285     }
   3286 
   3287     SOC_PBMP_CLEAR(new_ports);
   3288     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3289     if (chip_info.trunk_fabric_id_min >= 0 &&
   3290         tid >= chip_info.trunk_fabric_id_min) {        /* fabric trunk */
   3291         tid -= chip_info.trunk_fabric_id_min;
   3292         return _bcm_xgs3_trunk_fabric_destroy(unit, tid, t_info);
   3293     }
   3294 
   3295     /* front panel trunks */
   3296 
   3297     SOC_PBMP_CLEAR(old_ports);
   3298     for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   3299         mod = MEMBER_INFO(unit, tid).modport[i] >> 8;
   3300         port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   3301         BCM_GPORT_MODPORT_SET(gport, mod, port);
   3302         if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) { 
   3303             SOC_PBMP_PORT_ADD(old_ports, loc_port);
   3304         }
   3305         leaving_members[num_leaving_members++] = gport;
   3306         BCM_IF_ERROR_RETURN
   3307             (_bcm_xgs3_trunk_set_port_property(unit, mod, port, -1));
   3308     }
   3309 
   3310     /*
   3311      * Remove ports from the block mask table
   3312      */
   3313     if (SOC_PBMP_NOT_NULL(old_ports)) {
   3314         SOC_PBMP_CLEAR(new_ports);
   3315         /* coverity[divide_by_zero] */
   3316         BCM_IF_ERROR_RETURN(
   3317             _bcm_xgs3_trunk_block_mask(unit, old_ports, new_ports, 
   3318                                        new_ports, 0, 0));
   3319     }
   3320 
   3321     /*
   3322      * Reset table entries to empty state
   3323      */
   3324     if (soc_feature(unit, soc_feature_trunk_egress)) {
   3325         BCM_IF_ERROR_RETURN(
   3326             soc_mem_write(unit, TRUNK_EGR_MASKm, MEM_BLOCK_ALL, tid,
   3327                           soc_mem_entry_null(unit, TRUNK_EGR_MASKm)));
   3328     }
   3329     BCM_IF_ERROR_RETURN(
   3330         soc_mem_write(unit, TRUNK_BITMAPm, MEM_BLOCK_ALL, tid,
   3331                       soc_mem_entry_null(unit, TRUNK_BITMAPm)));
   3332     BCM_IF_ERROR_RETURN(
   3333         soc_mem_write(unit, trunk_mem, MEM_BLOCK_ALL, tid,
   3334                       soc_mem_entry_null(unit, trunk_mem)));
   3335     /*
   3336      * Remove ports from failover
   3337      */
   3338 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   3339     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   3340         BCM_IF_ERROR_RETURN
   3341             (_bcm_xgs3_trunk_failover_set(unit, tid, FALSE, NULL));
   3342     }
   3343 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   3344 
   3345     BCM_IF_ERROR_RETURN
   3346         (_bcm_xgs3_trunk_swfailover_set(unit,
   3347                                         tid,
   3348                                         0,
   3349                                         0,
   3350                                         (int *)0,
   3351                                         (int *)0,
   3352                                         NULL));
   3353 
   3354     /* Clear trunk properties from members */
   3355     BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_property_migrate(unit,
   3356                 num_leaving_members, leaving_members,
   3357                 0, NULL, 0, NULL));
   3358 
   3359     /* Clear trunk member info */
   3360     for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   3361         MEMBER_INFO(unit, tid).modport[i] = 0;
   3362         MEMBER_INFO(unit, tid).member_flags[i] = 0;
   3363     }
   3364     MEMBER_INFO(unit, tid).num_ports = 0;
   3365 
   3366     t_info->in_use = FALSE;
   3367     return BCM_E_NONE;
   3368 }
   3369 
   3370 STATIC int
   3371 _bcm_xgs3_trunk_fabric_get(int unit,
   3372                            bcm_trunk_t hgtid,
   3373                            _esw_trunk_add_info_t *t_data,
   3374                            trunk_private_t *t_info)
   3375 {
   3376     bcm_trunk_t tid;
   3377     bcm_module_t modid;
   3378     bcm_port_t port;
   3379     int i;
   3380 
   3381     tid = hgtid + _BCM_FP_TRUNK_NUM_MAX;
   3382 
   3383     if (t_data->num_ports == 0) {
   3384         t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   3385     } else {
   3386         if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) {
   3387             t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   3388         } 
   3389 
   3390         if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &modid))) {
   3391             modid = 0;
   3392         }
   3393 
   3394         for (i = 0; i < t_data->num_ports; i++) {
   3395             port = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   3396             BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit,
   3397                         BCM_STK_MODMAP_GET, modid, port,
   3398                         &t_data->tm[i], &t_data->tp[i]));
   3399         }
   3400     }
   3401 
   3402     return BCM_E_NONE;
   3403 }
   3404 
   3405 /*
   3406  * Function:
   3407  *      _bcm_xgs3_trunk_get
   3408  * Purpose:
   3409  *      Multiplexed trunking function for XGS3
   3410  */
   3411 STATIC int
   3412 _bcm_xgs3_trunk_get(int unit,
   3413                    bcm_trunk_t tid,
   3414                    _esw_trunk_add_info_t *t_data,
   3415                    trunk_private_t *t_info)
   3416 {
   3417     bcm_module_t                mod_out;
   3418     bcm_port_t                  port_out;
   3419     int                         i;
   3420     bcm_trunk_chip_info_t        chip_info;
   3421 
   3422     t_data->flags = t_info->flags;
   3423     t_data->psc = t_info->psc;
   3424     t_data->ipmc_psc = t_info->ipmc_psc;
   3425     t_data->dlf_index = t_info->dlf_index_used;
   3426     t_data->mc_index = t_info->mc_index_used;
   3427     t_data->ipmc_index = t_info->ipmc_index_used;
   3428 
   3429     if (!t_info->in_use) {
   3430         t_data->num_ports = 0;
   3431         return BCM_E_NONE;
   3432     }
   3433 
   3434     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3435     if (chip_info.trunk_fabric_id_min >= 0 &&
   3436         tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */
   3437         tid -= chip_info.trunk_fabric_id_min;
   3438         return _bcm_xgs3_trunk_fabric_get(unit, tid, t_data, t_info);
   3439     }
   3440 
   3441     if (t_data->num_ports == 0) {
   3442         t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   3443     } else {
   3444         if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) {
   3445             t_data->num_ports = MEMBER_INFO(unit, tid).num_ports;
   3446         } 
   3447 
   3448         for (i = 0; i < t_data->num_ports; i++) {
   3449             BCM_IF_ERROR_RETURN
   3450                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   3451                                          MEMBER_INFO(unit, tid).modport[i] >> 8,
   3452                                          MEMBER_INFO(unit, tid).modport[i] & 0xff,
   3453                                          &mod_out, &port_out));
   3454             t_data->tm[i] = mod_out;
   3455             t_data->tp[i] = port_out;
   3456             /* Copy member flags */
   3457             t_data->member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i];
   3458         }
   3459     }
   3460 
   3461     return BCM_E_NONE;
   3462 }
   3463 
   3464 /*
   3465  * Function:
   3466  *	bcm_xgs3_trunk_get
   3467  * Purpose:
   3468  *      Return a trunk information of given trunk ID.
   3469  * Parameters:
   3470  *      unit   - (IN) StrataSwitch PCI device unit number (driver internal).
   3471  *      tid    - (IN) Trunk ID.
   3472  *      trunk_info   - (OUT) Place to store returned trunk info.
   3473  *      member_max   - (IN) Size of member_array.
   3474  *      member_array - (OUT) Array of trunk member structures.
   3475  *      member_count - (OUT) Number of trunk members returned.
   3476  *      t_info       - (IN) Internal trunk info.
   3477  * Returns:
   3478  *      BCM_E_NONE              Success.
   3479  *      BCM_E_XXX
   3480  */
   3481 int
   3482 bcm_xgs3_trunk_get(int unit,
   3483         bcm_trunk_t tid,
   3484         bcm_trunk_info_t *trunk_info,
   3485         int member_max, 
   3486         bcm_trunk_member_t *member_array,
   3487         int *member_count,
   3488         trunk_private_t *t_info)
   3489 {
   3490     _esw_trunk_add_info_t add_info;
   3491     int i;
   3492     int rv = BCM_E_NONE;
   3493     bcm_trunk_chip_info_t chip_info;
   3494     int higig_trunk;
   3495 
   3496     sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t));
   3497     add_info.num_ports = member_max;
   3498     if (member_max > 0) {
   3499         BCM_IF_ERROR_RETURN
   3500             (_xgs3_trunk_add_info_member_alloc(&add_info, member_max));
   3501     }
   3502 
   3503     rv = _bcm_xgs3_trunk_get(unit, tid, &add_info, t_info);
   3504     if (BCM_FAILURE(rv)) {
   3505         if (member_max > 0) {
   3506             _xgs3_trunk_add_info_member_free(&add_info);
   3507         }
   3508         return rv;
   3509     }
   3510 
   3511     trunk_info->flags = add_info.flags;
   3512     trunk_info->psc = add_info.psc;
   3513     trunk_info->ipmc_psc = add_info.ipmc_psc;
   3514     trunk_info->dlf_index = add_info.dlf_index;
   3515     trunk_info->mc_index = add_info.mc_index;
   3516     trunk_info->ipmc_index = add_info.ipmc_index;
   3517 
   3518     *member_count = add_info.num_ports;
   3519 
   3520     if (member_max > 0) {
   3521         if (member_max < *member_count) {
   3522             *member_count = member_max;
   3523         }
   3524 
   3525         /* Construct member gport */
   3526         rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
   3527         if (BCM_FAILURE(rv)) {
   3528             _xgs3_trunk_add_info_member_free(&add_info);
   3529             return rv;
   3530         }
   3531         if (chip_info.trunk_fabric_id_min >= 0 &&
   3532             tid >= chip_info.trunk_fabric_id_min) {
   3533             higig_trunk = 1;
   3534         } else {
   3535             higig_trunk = 0;
   3536         }
   3537         rv = _bcm_esw_trunk_gport_construct(unit, higig_trunk,
   3538                 *member_count,
   3539                 add_info.tp, add_info.tm,
   3540                 add_info.tp);
   3541         if (BCM_FAILURE(rv)) {
   3542             _xgs3_trunk_add_info_member_free(&add_info);
   3543             return rv;
   3544         }
   3545 
   3546         for (i = 0; i < *member_count; i++) {
   3547             bcm_trunk_member_t_init(&member_array[i]);
   3548             member_array[i].flags = add_info.member_flags[i];
   3549             member_array[i].gport = add_info.tp[i];
   3550         }
   3551 
   3552         _xgs3_trunk_add_info_member_free(&add_info);
   3553     }
   3554 
   3555     return rv;
   3556 }
   3557 
   3558 /*
   3559  * Function:
   3560  *      bcm_xgs3_trunk_mcast_join
   3561  * Purpose:
   3562  *      Multiplexed function for XGS3
   3563  * Returns:
   3564  *     BCM_E_NONE - Success
   3565  *     BCM_E_INTERNAL - Read failure
   3566  *     BCM_E_XXX      - from bcm_mcast_port_get() or bcm_mcast_port_add()
   3567  */
   3568 int
   3569 bcm_xgs3_trunk_mcast_join(int unit, bcm_trunk_t tid, bcm_vlan_t vid,
   3570                           sal_mac_addr_t mac, trunk_private_t *t_info)
   3571 {
   3572     trunk_bitmap_entry_t        trunk_bitmap_entry;
   3573     bcm_mcast_addr_t            mc_addr;
   3574     bcm_trunk_chip_info_t chip_info;
   3575     
   3576     /* initialising and setting the mc_addr struct by bcm_mcast_addr_t_init() */
   3577     bcm_mcast_addr_t_init(&mc_addr,mac,vid);
   3578 
   3579     BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info));
   3580     if ((tid >= chip_info.trunk_id_min) && (tid <= chip_info.trunk_id_max)) {
   3581         /* get the ports in the trunk group */
   3582         SOC_IF_ERROR_RETURN
   3583             (soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid,
   3584                           &trunk_bitmap_entry));
   3585         soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry,
   3586                                TRUNK_BITMAPf, &mc_addr.pbmp);
   3587     } else {
   3588         return BCM_E_PARAM;
   3589     }
   3590 
   3591     /* Add the trunk group's ports to the multicast group. */
   3592     return bcm_esw_mcast_port_add(unit, &mc_addr);
   3593 }
   3594 
   3595 int
   3596 _bcm_xgs3_trunk_swfailover_init(int unit)
   3597 {
   3598     if (_xgs3_trunk_swfail[unit] == NULL) {
   3599         _xgs3_trunk_swfail[unit] = sal_alloc(sizeof(_xgs3_trunk_swfail_t), 
   3600                                              "_xgs3_trunk_swfail");
   3601         if (_xgs3_trunk_swfail[unit] == NULL) {
   3602             return BCM_E_MEMORY;
   3603         }
   3604     }
   3605     sal_memset(_xgs3_trunk_swfail[unit], 0, sizeof(_xgs3_trunk_swfail_t));
   3606     return BCM_E_NONE;
   3607 }
   3608 
   3609 void
   3610 _bcm_xgs3_trunk_swfailover_detach(int unit)
   3611 {
   3612     if (_xgs3_trunk_swfail[unit] != NULL) {
   3613         sal_free(_xgs3_trunk_swfail[unit]);
   3614         _xgs3_trunk_swfail[unit] = NULL;
   3615     }
   3616 }
   3617 
   3618 STATIC int
   3619 _bcm_xgs3_trunk_swfailover_set(int unit,
   3620                                bcm_trunk_t tid,
   3621                                int rtag,
   3622                                int nports,
   3623                                int mods[BCM_XGS3_TRUNK_MAX_PORTCNT],
   3624                                int ports[BCM_XGS3_TRUNK_MAX_PORTCNT],
   3625                                uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT])
   3626 {
   3627     _xgs3_trunk_swfail_t       *swf;
   3628     _xgs3_tinfo_t *swft;
   3629     bcm_pbmp_t          localports;
   3630     bcm_port_t          port;
   3631     bcm_module_t        my_modid;
   3632     int                 i;
   3633 
   3634     if (_xgs3_trunk_swfail[unit] == NULL) {
   3635         return BCM_E_INIT;
   3636     }
   3637 
   3638     BCM_IF_ERROR_RETURN
   3639         (bcm_esw_stk_my_modid_get(unit, &my_modid));
   3640 
   3641     swf = _xgs3_trunk_swfail[unit];
   3642     swft = &swf->tinfo[tid];
   3643 
   3644     swf->mymodid = my_modid;
   3645     swft->rtag = rtag;
   3646     swft->num_ports = nports;
   3647     BCM_PBMP_CLEAR(localports);
   3648     for (i = 0; i < nports; i++) {
   3649         swft->modport[i] = (mods[i] << 8) | ports[i];
   3650         swft->member_flags[i] = member_flags[i];
   3651         if (mods[i] == my_modid) {
   3652             BCM_PBMP_PORT_ADD(localports, ports[i]);
   3653         }
   3654     }
   3655     PBMP_ALL_ITER(unit, port) {
   3656         if (BCM_PBMP_MEMBER(localports, port)) {
   3657             swf->trunk[port] = tid + 1;
   3658         } else if (swf->trunk[port] == tid + 1) {
   3659             swf->trunk[port] = 0;       /* remove stale pointers to tid */
   3660         }
   3661     }
   3662     return BCM_E_NONE;
   3663 }
   3664 
   3665 STATIC int
   3666 _bcm_xgs3_trunk_swfailover_fabric_set(int unit,
   3667                                       bcm_trunk_t hgtid,
   3668                                       int rtag,
   3669                                       bcm_pbmp_t ports)
   3670 {
   3671     _xgs3_trunk_swfail_t       *swf;
   3672     _xgs3_tinfo_t              *swft;
   3673     bcm_port_t                 port;
   3674     int                        nports;
   3675  
   3676     if (_xgs3_trunk_swfail[unit] == NULL) {
   3677         return BCM_E_INIT;
   3678     }
   3679 
   3680     swf = _xgs3_trunk_swfail[unit];
   3681     swft = &swf->tinfo[hgtid + _BCM_FP_TRUNK_NUM_MAX];
   3682 
   3683     swft->rtag = rtag;
   3684     nports = 0;
   3685     PBMP_ITER(ports, port) {
   3686         swft->modport[nports] = port;
   3687         nports += 1;
   3688     }
   3689     swft->num_ports = nports;
   3690     PBMP_ALL_ITER(unit, port) {
   3691         if (BCM_PBMP_MEMBER(ports, port)) {
   3692             swf->trunk[port] = hgtid + _BCM_FABRIC_TRUNK_SWF_TID_OFFSET;
   3693         } else if (swf->trunk[port] ==
   3694                    (hgtid + _BCM_FABRIC_TRUNK_SWF_TID_OFFSET)) {
   3695             swf->trunk[port] = 0;       /* remove stale pointers to tid */
   3696         }
   3697     }
   3698     return BCM_E_NONE;
   3699 }   
   3700 
   3701 #ifdef BCM_TRUNK_FAILOVER_SUPPORT
   3702 
   3703 /* fields from HIGIG_TRUNK_GROUPr */
   3704 static soc_field_t      _hg_trunkf[2][4] = {
   3705   {
   3706     HIGIG_TRUNK_ID0_PORT0f, HIGIG_TRUNK_ID0_PORT1f,
   3707     HIGIG_TRUNK_ID0_PORT2f, HIGIG_TRUNK_ID0_PORT3f},
   3708   {
   3709     HIGIG_TRUNK_ID1_PORT0f, HIGIG_TRUNK_ID1_PORT1f,
   3710     HIGIG_TRUNK_ID1_PORT2f, HIGIG_TRUNK_ID1_PORT3f}
   3711 };
   3712 
   3713 static soc_field_t _hg_trunk_rtagf[2] = {
   3714     HIGIG_TRUNK_RTAG0f, HIGIG_TRUNK_RTAG1f
   3715 };
   3716 
   3717 /*
   3718  * Re-programs fabric trunk
   3719  */
   3720 STATIC void
   3721 _bcm_xgs3_trunk_fabric_swfailover_trigger(int unit,
   3722                                           bcm_port_t port,
   3723                                           int hgtid,
   3724                                           _xgs3_trunk_swfail_t *swf)
   3725 {
   3726     int i, j, k, nmp, p;
   3727     _xgs3_tinfo_t *swft;
   3728 
   3729     swft = &swf->tinfo[hgtid + _BCM_FP_TRUNK_NUM_MAX];
   3730 
   3731     /* update the _xgs3_trunk_swfail entry */
   3732     nmp = swft->num_ports;
   3733     for (i = j = 0; i < nmp; i++) {
   3734          if (swft->modport[i] != port) {
   3735              if (i != j) {
   3736                  swft->modport[j] = swft->modport[i];
   3737              }
   3738              j += 1;
   3739          }
   3740     }
   3741            
   3742     if (j == nmp) {
   3743         return; /* no changes, so no need to write out */
   3744     }
   3745 
   3746     swft->num_ports = nmp = j;
   3747 
   3748     if (SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) {
   3749         uint32  hgtrunk;
   3750         hgtrunk = 0;
   3751 
   3752         for (k = j = 0; k < 2; k++) {
   3753              swft = &swf->tinfo[_BCM_FP_TRUNK_NUM_MAX + k];
   3754              nmp = swft->num_ports;
   3755              soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hgtrunk,
   3756                                _hg_trunk_rtagf[k], swft->rtag);
   3757              if (nmp == 0) {
   3758                  p = 0;
   3759              } else {
   3760                  if (SOC_IS_RAVEN(unit)) {
   3761                      p = swft->modport[0];
   3762                  } else {
   3763                      if(soc_xgs3_port_to_higig_bitmap(unit, 
   3764                                       swft->modport[0], (uint32 *)&p) != BCM_E_NONE) {
   3765                         return;
   3766                      }
   3767                      if(soc_xgs3_higig_bitmap_to_higig_port_num(p, 
   3768                                       (uint32 *)&p) != BCM_E_NONE) {
   3769                         return;
   3770                      }
   3771                  }
   3772              }
   3773 
   3774              for (i = 0; i < 4; i++) {
   3775                   soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hgtrunk,
   3776                                     _hg_trunkf[k][i], p);
   3777                   if (nmp > 1) {
   3778                       j += 1;
   3779                       if (j >= nmp) {
   3780                           j = 0;
   3781                       }
   3782                       if (SOC_IS_RAVEN(unit)) {
   3783                           p = swft->modport[j];
   3784                       } else {
   3785                          if(soc_xgs3_port_to_higig_bitmap(unit, 
   3786                                      swft->modport[j], (uint32 *)&p) != BCM_E_NONE) {
   3787                             return;
   3788                          }
   3789                          if(soc_xgs3_higig_bitmap_to_higig_port_num(p, 
   3790                                     (uint32 *)&p) != BCM_E_NONE) {
   3791                             return;
   3792                          }
   3793                       }
   3794                   }
   3795              }
   3796         }
   3797 
   3798         (void)WRITE_HIGIG_TRUNK_GROUPr(unit, hgtrunk);
   3799     } else if (SOC_IS_HB_GW(unit)) {
   3800 #if defined(BCM_BRADLEY_SUPPORT)
   3801         uint64  hgtrunk;
   3802 
   3803         COMPILER_64_ZERO(hgtrunk);
   3804         if (nmp == 0) {
   3805             p = 31;     /* just drop it */
   3806         } else {
   3807             p = swft->modport[0];
   3808         }
   3809         for (i = j = 0; i < 8; i++) {
   3810              soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk,
   3811                                    _hg_trunk[i], p);
   3812              if (nmp > 1) {
   3813                  j += 1;
   3814                  if (j >= nmp) {
   3815                      j = 0;
   3816                  }
   3817                  p = swft->modport[j];
   3818              }
   3819         }
   3820 
   3821         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk,
   3822                               HIGIG_TRUNK_SIZEf, nmp ? nmp-1 : 0);
   3823         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk,
   3824                               HIGIG_TRUNK_RTAGf, swft->rtag);
   3825         (void)WRITE_HG_TRUNK_GROUPr(unit, hgtid, hgtrunk);
   3826 #endif  /* BCM_BRADLEY_SUPPORT */
   3827     } else if (SOC_IS_SC_CQ(unit)) {
   3828 #if defined(BCM_SCORPION_SUPPORT)
   3829         uint64  hgtrunk;
   3830         
   3831 
   3832         COMPILER_64_ZERO(hgtrunk);
   3833         if (nmp == 0) {
   3834             p = 31;     /* just drop it */
   3835         } else {
   3836             p = swft->modport[0];
   3837         }
   3838         for (i = j = 0; i < 8; i++) {
   3839              soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk,
   3840                                    _hg_trunk[i], p);
   3841              if (nmp > 1) {
   3842                  j += 1;
   3843                  if (j >= nmp) {
   3844                      j = 0;
   3845                  }
   3846                  p = swft->modport[j];
   3847              }
   3848         }
   3849 
   3850         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk,
   3851                               HIGIG_TRUNK_SIZEf, nmp ? nmp-1 : 0);
   3852         soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk,
   3853                               HIGIG_TRUNK_RTAGf, swft->rtag);
   3854         (void)WRITE_HG_TRUNK_GROUPr(unit, hgtid, hgtrunk);
   3855 #endif  /* BCM_SCORPION_SUPPORT */
   3856     }
   3857 }
   3858 
   3859 int
   3860 _bcm_xgs3_trunk_swfailover_trigger(int unit,
   3861                                    bcm_pbmp_t ports_active,
   3862                                    bcm_pbmp_t ports_status)
   3863 {
   3864     bcm_port_t           port;
   3865     int                  tid;
   3866     _xgs3_trunk_swfail_t *swf;
   3867     _xgs3_tinfo_t        *swft;
   3868     soc_mem_t            trunk_mem = TRUNK_GROUPm;
   3869 
   3870     if (soc_feature(unit, soc_feature_fastlag)) {
   3871         trunk_mem = FAST_TRUNK_GROUPm;
   3872     }
   3873 
   3874     swf = _xgs3_trunk_swfail[unit];
   3875 
   3876     if (swf == NULL) {
   3877         return BCM_E_NONE;
   3878     }
   3879 
   3880     PBMP_ITER(ports_active, port) {
   3881         if (BCM_PBMP_MEMBER(ports_status, port)) {
   3882             continue;   /* link up */
   3883         }
   3884 
   3885         /* link down */
   3886         tid = swf->trunk[port];
   3887         swf->trunk[port] = 0;
   3888         if (tid <= 0) {
   3889             continue;   /* already removed */
   3890         }
   3891 
   3892         if (tid >= 1 && tid < _BCM_FP_TRUNK_NUM_MAX + 1) {
   3893             uint32               tg_entry[SOC_MAX_MEM_WORDS];
   3894             uint16               modport;
   3895             int                  i, j, nmp;
   3896             int                  uc_nmp;
   3897             pbmp_t               old_trunk_pbmp;
   3898             pbmp_t               new_trunk_pbmp;
   3899             pbmp_t               nuc_trunk_pbmp;
   3900             trunk_bitmap_entry_t tb_entry;
   3901             bcm_module_t         mods[BCM_XGS3_TRUNK_MAX_PORTCNT];
   3902             uint16               uc_modport[BCM_XGS3_TRUNK_MAX_PORTCNT];
   3903             int                  max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT;
   3904             uint32               my_modid_bmap = 0;
   3905             uint32               nuc_member_count = 0;
   3906             uint32               nuc_tpbm = 0;
   3907 
   3908             tid = tid - 1;
   3909             swft = &swf->tinfo[tid];
   3910             SOC_PBMP_CLEAR(old_trunk_pbmp);
   3911             SOC_PBMP_CLEAR(new_trunk_pbmp);
   3912 
   3913             /* update _xgs3_trunk_swfail: remove matching ports, update size */
   3914             modport = (swf->mymodid << 8) | port;
   3915             nmp = swft->num_ports;
   3916 
   3917             for (i = j = 0; i < nmp; i++) {
   3918                 if (swft->modport[i] != modport) {
   3919                     if (i != j) {
   3920                         swft->modport[j] = swft->modport[i];
   3921                         swft->member_flags[j] = swft->member_flags[i];
   3922                     }
   3923                     j++;
   3924                 }
   3925                 if (swf->mymodid == (swft->modport[i] >> 8)) {
   3926                     SOC_PBMP_PORT_ADD(old_trunk_pbmp, swft->modport[i] & 0xff);
   3927                 }
   3928             }
   3929             if (j == nmp) {
   3930                 continue; /* no changes, so no need to write out */
   3931             }
   3932 
   3933             swft->num_ports = nmp = j;
   3934 
   3935             uc_nmp = 0;
   3936             for (i = 0; i < nmp; i++) {
   3937                 if (swft->member_flags[i] &
   3938                         BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) {
   3939                     continue;
   3940                 }
   3941                 uc_modport[uc_nmp++] = swft->modport[i];
   3942             }
   3943 
   3944             /* convert _xgs3_trunk_swfail into trunk_group entry */
   3945             if (soc_feature(unit, soc_feature_fastlag)) {
   3946                 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, swft->rtag);
   3947             } else {
   3948                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, swft->rtag);
   3949             }
   3950 #if defined(BCM_BRADLEY_SUPPORT)
   3951             if (SOC_IS_HBX(unit)) {
   3952                 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf,
   3953                                              uc_nmp ? uc_nmp-1 : 0);
   3954             }
   3955 #endif /* BCM_BRADLEY_SUPPORT */
   3956             if (uc_nmp == 0) {
   3957                 for (i = 0; i < max_ports; i++) {
   3958                     if (soc_feature(unit, soc_feature_fastlag)) {
   3959                         soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3960                             _xgs_fast_modulef[i], swf->mymodid);
   3961                         soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3962                             _xgs_fast_portf[i], SOC_PORT_ADDR_MAX(unit));
   3963                     } else {
   3964                         soc_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3965                             _xgs_modulef[i], swf->mymodid);
   3966                         soc_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3967                             _xgs_portf[i], SOC_PORT_ADDR_MAX(unit));
   3968                     }
   3969                     /* The assumption here is that SOC_PORT_ADDR_MAX is an
   3970                      * invalid port number. Hardware will drop packets destined
   3971                      * to an invalid port number.
   3972                      */
   3973                 }
   3974             } else {
   3975                 for (i = 0; i < max_ports; i++) {
   3976                     if (soc_feature(unit, soc_feature_fastlag)) {
   3977                         soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3978                              _xgs_fast_modulef[i], uc_modport[i%uc_nmp] >> 8);
   3979                         soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3980                              _xgs_fast_portf[i], uc_modport[i%uc_nmp] & 0xff);
   3981                     } else {
   3982                        soc_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3983                             _xgs_modulef[i], uc_modport[i%uc_nmp] >> 8);
   3984                        soc_TRUNK_GROUPm_field32_set(unit, &tg_entry,
   3985                             _xgs_portf[i], uc_modport[i%uc_nmp] & 0xff);
   3986                     }
   3987                 }
   3988             }
   3989 
   3990             /* write out the trunk_group entry */
   3991             (void)soc_mem_write(unit, trunk_mem, MEM_BLOCK_ALL,
   3992                                 tid, &tg_entry);
   3993 
   3994             /* update TRUNK_BITMAP table */
   3995             SOC_PBMP_CLEAR(new_trunk_pbmp);
   3996             for (i = 0; i < nmp; i++) {
   3997                  if ((swft->modport[i] >> 8) == swf->mymodid) {
   3998                      SOC_PBMP_PORT_ADD(new_trunk_pbmp, swft->modport[i] & 0xff);
   3999                  }
   4000             }
   4001             (void)soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid,
   4002                                &tb_entry);
   4003             soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &tb_entry,
   4004                                    TRUNK_BITMAPf, &new_trunk_pbmp);
   4005             (void)soc_mem_write(unit, TRUNK_BITMAPm, MEM_BLOCK_ALL, tid,
   4006                                 &tb_entry);
   4007 
   4008             /* update non uc trunk block mask table */
   4009             for (i = 0; i < nmp; i++) {
   4010                 mods[i] = swft->modport[i] >> 8;
   4011             }
   4012             BCM_IF_ERROR_RETURN(_bcm_nuc_tpbm_get(unit, nmp, mods, &nuc_tpbm));
   4013 
   4014             SOC_PBMP_CLEAR(nuc_trunk_pbmp);
   4015             for (i= 0; i < nmp; i++) {
   4016                  if (swf->mymodid == (swft->modport[i] >> 8)) {
   4017                      /* local port */
   4018                      if (nuc_tpbm & (1 << i)) {
   4019                          /* Eligible for NUC forwarding */
   4020                          SOC_PBMP_PORT_ADD(nuc_trunk_pbmp, 
   4021                                            swft->modport[i] & 0xff);
   4022                          my_modid_bmap |= (1 << nuc_member_count);
   4023                      }
   4024                  }
   4025 
   4026                  if (nuc_tpbm & (1 << i)) {
   4027                      /* Eligible for NUC forwarding */
   4028                      nuc_member_count++;
   4029                  }
   4030             }
   4031 
   4032             BCM_IF_ERROR_RETURN
   4033                (_bcm_xgs3_trunk_block_mask(unit, 
   4034                                            old_trunk_pbmp,
   4035                                            new_trunk_pbmp,   
   4036                                            nuc_trunk_pbmp,
   4037                                            my_modid_bmap,
   4038                                            nuc_member_count));
   4039         } else if ((tid >= _BCM_FABRIC_TRUNK_SWF_TID_OFFSET) && 
   4040                    (tid < (_BCM_FABRIC_TRUNK_NUM_MAX +
   4041                            _BCM_FABRIC_TRUNK_SWF_TID_OFFSET))) {
   4042             /* higig trunk */
   4043             _bcm_xgs3_trunk_fabric_swfailover_trigger(unit,
   4044                                                       port,
   4045                             tid - _BCM_FABRIC_TRUNK_SWF_TID_OFFSET,
   4046                                                       swf);
   4047         }
   4048     }
   4049 
   4050     return BCM_E_NONE;
   4051 }
   4052 #endif /* BCM_TRUNK_FAILOVER_SUPPORT */
   4053 
   4054 #ifdef BCM_WARM_BOOT_SUPPORT
   4055 /* Set psc argument to trunk group default first, then call this */
   4056 STATIC void
   4057 _bcm_xgs3_trunk_rtag_to_psc(int unit, int rtag, int *psc)
   4058 {
   4059     if (7 == rtag) {
   4060         if (soc_feature(unit,
   4061                         soc_feature_port_flow_hash)) {
   4062             *psc = BCM_TRUNK_PSC_PORTFLOW;
   4063         } else if (soc_feature(unit,
   4064                                soc_feature_port_trunk_index)) {
   4065             *psc = BCM_TRUNK_PSC_PORTINDEX;
   4066         } /* Else, unknown, use default */
   4067     } else if (0 < rtag) {
   4068         /* HW and SW values match */
   4069         *psc = rtag;
   4070     } else {
   4071         /* Use trunk group value as the default */
   4072     }
   4073 }
   4074 
   4075 /*
   4076  * Handle state recovery for front panel trunks
   4077  */
   4078 int
   4079 _xgs3_trunk_reinit(int unit, int ngroups_fp, trunk_private_t *trunk_info)
   4080 {
   4081     int rv = BCM_E_UNAVAIL;
   4082 
   4083 #if defined(BCM_FIREBOLT_SUPPORT)
   4084     if (SOC_IS_FBX(unit)) {
   4085         bcm_trunk_t tid, tid_get;
   4086         trunk_private_t *t_info; 
   4087         uint32 tg_entry[SOC_MAX_MEM_WORDS];
   4088         bcm_module_t egr_hw_mods[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   4089         bcm_port_t egr_hw_ports[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   4090         uint32 egr_member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 };
   4091         bcm_module_t om[BCM_XGS3_TRUNK_MAX_PORTCNT];
   4092         pbmp_t op[BCM_XGS3_TRUNK_MAX_PORTCNT];
   4093         int max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT;
   4094         source_trunk_map_table_entry_t  stm; /* Hw entry buffer. */
   4095         int i, j, num_mod, tgsize, ptype, idx;
   4096         int psc, num_egr_ports;
   4097 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4098         _xgs3_hw_tinfo_t  *hwft;
   4099         int               tix, rtag, psc_local;
   4100 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4101         soc_mem_t trunk_mem = TRUNK_GROUPm;
   4102         soc_field_t tid_fld = TGIDf;
   4103 
   4104         if (soc_feature(unit, soc_feature_src_tgid_valid)) {
   4105             tid_fld = SRC_TGIDf;
   4106         }
   4107 
   4108         if (soc_feature(unit, soc_feature_fastlag)) {
   4109             trunk_mem = FAST_TRUNK_GROUPm;
   4110         }
   4111 
   4112         rv = BCM_E_NONE;
   4113         tgsize = soc_mem_entry_words(unit, trunk_mem);
   4114         tgsize = WORDS2BYTES(tgsize);
   4115 
   4116         for (tid = 0; tid < ngroups_fp; tid++, trunk_info++) {
   4117              SOC_IF_ERROR_RETURN
   4118                 (soc_mem_read(unit, trunk_mem, MEM_BLOCK_ANY, tid,
   4119                               &tg_entry));
   4120              if (sal_memcmp(&tg_entry, soc_mem_entry_null(unit, trunk_mem),
   4121                             tgsize) == 0) {
   4122                  /*
   4123                   * Invalid trunk ID
   4124                   */
   4125                  continue;
   4126              }
   4127 
   4128              if (MEMBER_INFO(unit, tid).recovered_from_scache) {
   4129                  for (i = 0, j = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   4130                      if (MEMBER_INFO(unit, tid).member_flags[i] &
   4131                              BCM_TRUNK_MEMBER_EGRESS_DISABLE) {
   4132                          continue;
   4133                      }
   4134                      egr_hw_mods[j] = MEMBER_INFO(unit, tid).modport[i] >> 8;
   4135                      egr_hw_ports[j] = MEMBER_INFO(unit, tid).modport[i] & 0xff;
   4136                      egr_member_flags[j] = MEMBER_INFO(unit, tid).member_flags[i];
   4137                      j++;
   4138                  }
   4139                  num_egr_ports = j;
   4140 
   4141              } else {
   4142                  /* In level 1 warm boot, not all egress trunk members can be
   4143                   * recovered from TRUNK_GROUP table, as those members with
   4144                   * the UNICAST_EGRESS_DISABLE flag set will not be in
   4145                   * TRUNK_GROUP table.
   4146                   */
   4147 
   4148                  num_mod = 0;
   4149                  sal_memset(om, 0, sizeof(om));
   4150                  sal_memset(op, 0, sizeof(op));
   4151 
   4152                  for (i = 0; i < max_ports; i++) {
   4153                      int found = 0;
   4154 
   4155                      if (soc_feature(unit, soc_feature_fastlag)) {
   4156                          egr_hw_mods[i] = soc_FAST_TRUNK_GROUPm_field32_get(unit,
   4157                             &tg_entry, _xgs_fast_modulef[i]);
   4158                          egr_hw_ports[i] = soc_FAST_TRUNK_GROUPm_field32_get(unit,
   4159                             &tg_entry, _xgs_fast_portf[i]);
   4160                      } else {
   4161                           egr_hw_mods[i] = soc_TRUNK_GROUPm_field32_get(unit,
   4162                              &tg_entry, _xgs_modulef[i]);
   4163                           egr_hw_ports[i] = soc_TRUNK_GROUPm_field32_get(unit,
   4164                              &tg_entry, _xgs_portf[i]);
   4165                      }
   4166                      for (j = 0; j < num_mod; j++) {
   4167                          if (om[j] == egr_hw_mods[i]) {
   4168                              SOC_PBMP_PORT_ADD(op[j], egr_hw_ports[i]);
   4169                              found = 1;
   4170                              break;
   4171                          }
   4172                      }
   4173                      if (!found) {
   4174                          SOC_PBMP_PORT_ADD(op[num_mod], egr_hw_ports[i]);
   4175                          om[num_mod++] = egr_hw_mods[i];
   4176                      }
   4177                  }
   4178 
   4179                  num_egr_ports = 0;
   4180                  for (i = 0; i < num_mod; i++) {
   4181                      int pbmp_count;
   4182                      SOC_PBMP_COUNT(op[i], pbmp_count);
   4183                      num_egr_ports += pbmp_count;
   4184                  }
   4185 
   4186                  for (i = 0; i < num_egr_ports; i++) {
   4187                      /* Compare values with source trunk map to recreate
   4188                       * ingress disable flag
   4189                       */
   4190 #ifdef BCM_TRX_SUPPORT
   4191                      if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   4192                          idx = (egr_hw_mods[i] * (SOC_PORT_ADDR_MAX(unit) + 1)) +
   4193                              egr_hw_ports[i];
   4194                      } else
   4195 #endif
   4196                      {
   4197                          idx = (egr_hw_mods[i] << SOC_TRUNK_BIT_POS(unit)) +
   4198                              egr_hw_ports[i];
   4199                      }
   4200 
   4201                      rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm,
   4202                              MEM_BLOCK_ANY, idx, &stm);
   4203                      if (BCM_SUCCESS(rv)) {
   4204                          ptype = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit,
   4205                                  &stm, PORT_TYPEf);
   4206                          tid_get = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit,
   4207                                    &stm, tid_fld);
   4208                          if (ptype != 1 || tid_get != tid) {
   4209                              egr_member_flags[i] |=
   4210                                  BCM_TRUNK_MEMBER_INGRESS_DISABLE;
   4211                          }
   4212                      }
   4213                  } 
   4214 
   4215                  MEMBER_INFO(unit, tid).num_ports = num_egr_ports;
   4216                  for (i = 0; i < num_egr_ports; i++) {
   4217                      MEMBER_INFO(unit, tid).modport[i] =
   4218                          (egr_hw_mods[i] << 8) | egr_hw_ports[i];
   4219                      MEMBER_INFO(unit, tid).member_flags[i] =
   4220                          egr_member_flags[i];
   4221                  }
   4222              }
   4223 
   4224              if (soc_feature(unit, soc_feature_fastlag)) {
   4225                  psc = soc_FAST_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   4226                                                                RTAGf);
   4227              } else {
   4228                  psc = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry,
   4229                                                           RTAGf);
   4230              }
   4231              if (psc <= 0) {
   4232                  psc = BCM_TRUNK_PSC_DEFAULT;
   4233              }
   4234 
   4235              /*
   4236               * Update trunk control state
   4237               */
   4238              TRUNK_LOCK(unit);
   4239              t_info = trunk_info; 
   4240              t_info->tid = tid;
   4241              t_info->in_use = TRUE;
   4242              t_info->psc = psc;
   4243              _bcm_xgs3_trunk_rtag_to_psc(unit, psc, &(t_info->psc));
   4244 
   4245              /* Recover software trunk failover internal state */
   4246              rv = _bcm_xgs3_trunk_swfailover_set(unit, 
   4247                                                  tid, 
   4248                                                  psc,
   4249                                                  num_egr_ports, 
   4250                                                  egr_hw_mods, 
   4251                                                  egr_hw_ports,
   4252                                                  egr_member_flags);
   4253 
   4254              /* Recover hardware trunk failover internal state */
   4255 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4256              if (BCM_SUCCESS(rv) &&
   4257                  soc_feature(unit, soc_feature_port_lag_failover)) {
   4258                  /* Record trunk info for HW failover */
   4259                  hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid]);
   4260                  hwft->num_ports = num_egr_ports;
   4261                  for (tix = 0; tix < num_egr_ports; tix++) {
   4262                      hwft->modport[tix] =
   4263                          (egr_hw_mods[tix] << 8) | egr_hw_ports[tix];
   4264                      rv = _bcm_xgs3_trunk_hwfailover_read(unit,
   4265                                                           egr_hw_ports[tix],
   4266                                                           0, &rtag,
   4267                                                           NULL, NULL, NULL);
   4268 
   4269                      if (BCM_SUCCESS(rv)) {
   4270                          psc_local = BCM_TRUNK_PSC_DEFAULT;
   4271                          _bcm_xgs3_trunk_rtag_to_psc(unit, rtag,
   4272                                                      &psc_local);
   4273                          hwft->psc[tix] = psc_local;
   4274                          /* Flags already handled */
   4275                      } else {
   4276                          /* Propagate error */
   4277                          break;
   4278                      }
   4279                  }
   4280              }
   4281 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4282 
   4283              TRUNK_UNLOCK(unit); 
   4284         } /* for each tid */
   4285 
   4286         /* Recover source mod port trunk cache and trunk members with
   4287          * egress disable flag set.
   4288          */
   4289         /*
   4290          * For source module ID base indexing supported, 
   4291          * _bcm_xgs3_trunk_mod_port_map_reinit is called during stacking 
   4292          * module reinit, since the number of ports in a given module is not known until then.
   4293          */
   4294         if (BCM_SUCCESS(rv) && !soc_feature(unit, soc_feature_src_modid_base_index)) {
   4295             rv = _xgs3_trunk_mod_port_map_reinit(unit);
   4296         }
   4297 
   4298     }
   4299 #endif /* BCM_FIREBOLT_SUPPORT */
   4300 
   4301     return rv;
   4302 }
   4303 
   4304 /*
   4305  * Handles state recovery for fabric trunks
   4306  */
   4307 int
   4308 _xgs3_trunk_fabric_reinit(int unit, int min_tid, int max_tid,
   4309                           trunk_private_t *trunk_info)
   4310 {
   4311     int rv = BCM_E_NONE;
   4312     uint32 hg_cntl_entry;
   4313     uint32 hg_group_entry;
   4314     pbmp_t hg_pbmp, pbmp;
   4315     uint32 higig_bitmap;
   4316     bcm_trunk_t tid, hgtid;
   4317     trunk_private_t *t_info;
   4318     bcm_port_t tp[BCM_XGS3_TRUNK_MAX_PORTCNT] = {0};
   4319     int num_ports;
   4320     int psc = 0;
   4321     bcm_port_t port;
   4322     int i=0;
   4323 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
   4324     uint64 hg_trunk_group, hg_trunk_group_hi;
   4325     _xgs3_hw_tinfo_t  *hwft;
   4326     int               tix, rtag;
   4327 #endif
   4328 
   4329     for (tid = min_tid; tid <= max_tid; tid++, trunk_info++) {
   4330  
   4331         hgtid = tid - min_tid;
   4332         SOC_PBMP_CLEAR(hg_pbmp);
   4333         if (SOC_IS_FB_FX_HX(unit)) { 
   4334             SOC_IF_ERROR_RETURN
   4335                 (READ_HIGIG_TRUNK_CONTROLr(unit, &hg_cntl_entry));
   4336             SOC_PBMP_WORD_SET(hg_pbmp, 
   4337                               0,
   4338                               soc_reg_field_get(unit, 
   4339                                                 HIGIG_TRUNK_CONTROLr, 
   4340                                                 hg_cntl_entry,
   4341                                                 (tid == min_tid) ?
   4342                                                 HIGIG_TRUNK_BITMAP0f :
   4343                                                 HIGIG_TRUNK_BITMAP1f));
   4344         }
   4345 #if defined(BCM_TRIUMPH2_SUPPORT)
   4346         else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   4347                  SOC_IS_VALKYRIE2(unit)) {
   4348             uint64		val64;
   4349             /* Triumph2 / Apollo / Valkyrie2 */
   4350             SOC_IF_ERROR_RETURN
   4351                 (READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64));
   4352             SOC_PBMP_CLEAR(hg_pbmp);
   4353             SOC_PBMP_WORD_SET(hg_pbmp, 0,
   4354                      soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
   4355                                            val64, HIGIG_TRUNK_BITMAP_LOf));
   4356             SOC_PBMP_WORD_SET(hg_pbmp, 1,
   4357                      soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r,
   4358                                            val64, HIGIG_TRUNK_BITMAP_HIf));
   4359         }
   4360 #endif
   4361 #if defined(BCM_GREYHOUND2_SUPPORT)
   4362         else if (soc_feature(unit, soc_feature_high_portcount_register)) {
   4363             uint64 val64, hg_trunk_bmap_f;
   4364 
   4365             SOC_IF_ERROR_RETURN
   4366                 (READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64));
   4367             hg_trunk_bmap_f =
   4368                 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr,
   4369                                     val64, HIGIG_TRUNK_BITMAPf);
   4370             SOC_PBMP_CLEAR(hg_pbmp);
   4371             SOC_PBMP_WORD_SET(hg_pbmp, 0, COMPILER_64_LO(hg_trunk_bmap_f));
   4372             SOC_PBMP_WORD_SET(hg_pbmp, 1, COMPILER_64_HI(hg_trunk_bmap_f));
   4373 
   4374             SOC_IF_ERROR_RETURN
   4375                 (READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64));
   4376             hg_trunk_bmap_f =
   4377                 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr,
   4378                                     val64, HIGIG_TRUNK_BITMAPf);
   4379             SOC_PBMP_WORD_SET(hg_pbmp, 2, COMPILER_64_LO(hg_trunk_bmap_f));
   4380         }
   4381 #endif /* BCM_GREYHOUND2_SUPPORT */
   4382 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
   4383         else if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) {
   4384             /* Humv / Bradley / Scorpion / Conqueror / Triumph / Valkyrie */
   4385             SOC_IF_ERROR_RETURN
   4386                 (READ_HG_TRUNK_BITMAPr(unit, hgtid, &hg_cntl_entry));
   4387             SOC_PBMP_WORD_SET(hg_pbmp, 
   4388                               0,
   4389                               soc_reg_field_get(unit, 
   4390                                                 HG_TRUNK_BITMAPr, 
   4391                                                 hg_cntl_entry,
   4392                                                 HIGIG_TRUNK_BITMAPf));
   4393         }
   4394 #endif
   4395 
   4396         SOC_PBMP_CLEAR(pbmp);
   4397         if (SOC_IS_RAVEN(unit) || SOC_IS_TRIUMPH2(unit) ||
   4398             SOC_IS_APOLLO(unit) ||  SOC_IS_VALKYRIE2(unit) ||
   4399             soc_feature(unit, soc_feature_high_portcount_register)) {
   4400             /* Use the bitmap directly for Raven from HIGIG_TRUNK_CONTROL */
   4401             SOC_PBMP_ASSIGN(pbmp, hg_pbmp);
   4402         } else {
   4403             /* For other FBX, map the read higig bitmap to the physical bitmap */
   4404             soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp);
   4405         }
   4406 
   4407         num_ports = 0;
   4408         if (SOC_IS_FB_FX_HX(unit)) {
   4409             PBMP_ITER(pbmp, port) {
   4410                 BCM_IF_ERROR_RETURN
   4411                     (soc_xgs3_port_to_higig_bitmap(unit, port, &higig_bitmap));
   4412                 BCM_IF_ERROR_RETURN
   4413                     (soc_xgs3_higig_bitmap_to_higig_port_num(higig_bitmap,
   4414                                                              (uint32 *)&(tp[num_ports])));
   4415                 num_ports += 1;
   4416             }
   4417         } 
   4418 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
   4419         else if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) {
   4420             int port_limit;
   4421             COMPILER_64_ZERO(hg_trunk_group);
   4422             COMPILER_64_ZERO(hg_trunk_group_hi);
   4423 
   4424             COMPILER_REFERENCE(hg_trunk_group_hi);
   4425 
   4426             if (SOC_PBMP_NOT_NULL(pbmp)) {
   4427                 SOC_IF_ERROR_RETURN
   4428                     (READ_HG_TRUNK_GROUPr(unit, hgtid, &hg_trunk_group));
   4429                 if (SOC_REG_FIELD_VALID(unit,
   4430                     HG_TRUNK_GROUPr, HIGIG_TRUNK_SIZEf)) { /* PR 34459 */
   4431                     i = soc_reg64_field32_get(unit, HG_TRUNK_GROUPr,
   4432                                               hg_trunk_group,
   4433                                               HIGIG_TRUNK_SIZEf);
   4434                     num_ports = i + 1;
   4435                 } else {
   4436                     BCM_PBMP_COUNT(pbmp, num_ports);
   4437                 }
   4438                 port_limit = num_ports;
   4439 #if defined(BCM_SCORPION_SUPPORT)
   4440                 if (SOC_IS_SC_CQ(unit) &&
   4441                     (port_limit > BCM_SWITCH_TRUNK_MAX_PORTCNT)) {
   4442                     port_limit = BCM_SWITCH_TRUNK_MAX_PORTCNT;   
   4443                 }
   4444 #endif
   4445                 for (i = 0; i < port_limit; i++) {
   4446                     tp[i] = 
   4447                         soc_reg64_field32_get(unit, HG_TRUNK_GROUPr,
   4448                                               hg_trunk_group, _hg_trunk[i]);
   4449                 }
   4450 #if defined(BCM_SCORPION_SUPPORT)
   4451                 if (SOC_IS_SC_CQ(unit) &&
   4452                     (num_ports > BCM_SWITCH_TRUNK_MAX_PORTCNT)) {
   4453                     SOC_IF_ERROR_RETURN
   4454                         (READ_HG_TRUNK_GROUP_HIr(unit, hgtid,
   4455                                                  &hg_trunk_group_hi));
   4456                     for (i = BCM_SWITCH_TRUNK_MAX_PORTCNT;
   4457                          i < num_ports; i++) {
   4458                         tp[i] =
   4459                             soc_reg64_field32_get(unit, HG_TRUNK_GROUP_HIr,
   4460                                                   hg_trunk_group_hi, 
   4461                                                   _hg_trunk_hi[i - BCM_SWITCH_TRUNK_MAX_PORTCNT]);
   4462                     }
   4463                 }
   4464 #endif
   4465             }
   4466         }
   4467 #endif
   4468 
   4469         /* Recover trunk member info internal state */
   4470         for (i = 0; i < num_ports; i++) {
   4471             MEMBER_INFO(unit, (hgtid + _BCM_FP_TRUNK_NUM_MAX)).modport[i] = tp[i];
   4472         }
   4473         MEMBER_INFO(unit, (hgtid + _BCM_FP_TRUNK_NUM_MAX)).num_ports = num_ports;
   4474 
   4475         if (num_ports == 0) {
   4476             continue;
   4477         }
   4478          
   4479         if (SOC_IS_FB_FX_HX(unit)) {
   4480             SOC_IF_ERROR_RETURN
   4481                 (READ_HIGIG_TRUNK_GROUPr(unit, &hg_group_entry));
   4482 
   4483             psc = soc_reg_field_get(unit, 
   4484                                             HIGIG_TRUNK_GROUPr,
   4485                                             hg_group_entry,
   4486                                             (tid == min_tid) ?           \
   4487                                             HIGIG_TRUNK_RTAG0f : \
   4488                                             HIGIG_TRUNK_RTAG1f);
   4489         } 
   4490 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
   4491         else {
   4492             /* Humv / Bradley / Scorpion / Conqueror / Triumph / Valkyrie */
   4493             psc = soc_reg64_field32_get(unit, 
   4494                                                 HG_TRUNK_GROUPr,
   4495                                                 hg_trunk_group,
   4496                                                 HIGIG_TRUNK_RTAGf);
   4497         }
   4498 #endif
   4499         /*
   4500          * Update trunk control state
   4501          */
   4502         TRUNK_LOCK(unit);
   4503         t_info = trunk_info;
   4504         t_info->tid = tid;
   4505         t_info->psc = psc;
   4506         t_info->in_use = TRUE;
   4507         rv = _bcm_xgs3_trunk_swfailover_fabric_set(unit, hgtid,
   4508                                                    psc, pbmp);
   4509         TRUNK_UNLOCK(unit);
   4510 
   4511         if (BCM_FAILURE(rv)) {
   4512             break;
   4513         }
   4514 
   4515 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4516         if (soc_feature(unit, soc_feature_hg_trunk_failover)) {
   4517             /* Record trunk info for HW failover */
   4518             hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[hgtid +
   4519                                                _BCM_FP_TRUNK_NUM_MAX]);
   4520             hwft->num_ports = num_ports;
   4521             for (tix = 0; tix < num_ports; tix++) {
   4522                 hwft->modport[tix] = tp[tix];
   4523                 rv = _bcm_xgs3_trunk_hwfailover_hg_read(unit,
   4524                                                         tp[tix],
   4525                                                    0, &rtag, NULL, NULL, NULL);
   4526 
   4527                 if (BCM_SUCCESS(rv)) {
   4528                     TRUNK_LOCK(unit);
   4529                     if (7 == rtag) {
   4530                         if (soc_feature(unit, soc_feature_port_flow_hash)) {
   4531                             hwft->psc[tix] = BCM_TRUNK_PSC_PORTFLOW;
   4532                         } else if (soc_feature(unit,
   4533                                        soc_feature_port_trunk_index)) {
   4534                             hwft->psc[tix] = BCM_TRUNK_PSC_PORTINDEX;
   4535                         } /* Else, unknown */
   4536                     } else if (0 != rtag) {
   4537                         /* HW and SW values match */
   4538                         hwft->psc[tix] = rtag;
   4539                     } else {
   4540                         /* Use trunk group value as the default */
   4541                         hwft->psc[tix] = psc;
   4542                     }
   4543                     /* Flags already handled */
   4544                     TRUNK_UNLOCK(unit);
   4545                 }
   4546             }
   4547         }
   4548 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4549     }
   4550 
   4551     return rv;
   4552 }
   4553 
   4554 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4555 void
   4556 _bcm_xgs3_hw_failover_flags_set(int unit, bcm_trunk_t tid,
   4557                                 int port_index, int hg_trunk, uint8 flags)
   4558 {
   4559     int tid_ix;
   4560 
   4561     tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0);
   4562 
   4563     TRUNK_LOCK(unit);
   4564     _xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix].flags[port_index] = flags;
   4565     TRUNK_UNLOCK(unit);
   4566 
   4567     return;
   4568 }
   4569 
   4570 uint8
   4571 _bcm_xgs3_hw_failover_flags_get(int unit, bcm_trunk_t tid,
   4572                                 int port_index, int hg_trunk)
   4573 {
   4574     int tid_ix;
   4575     uint8 flags;
   4576 
   4577     tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0);
   4578 
   4579     TRUNK_LOCK(unit);
   4580     flags = _xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix].flags[port_index];
   4581     TRUNK_UNLOCK(unit);
   4582 
   4583     return flags;
   4584 }
   4585 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4586 
   4587 void
   4588 _bcm_xgs3_trunk_member_info_set(int unit, bcm_trunk_t tid,
   4589                                 uint8 num_ports,
   4590                                 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT],
   4591                                 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT])
   4592 {
   4593     int i;
   4594 
   4595     MEMBER_INFO(unit, tid).num_ports = num_ports;
   4596     for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) {
   4597         MEMBER_INFO(unit, tid).modport[i] = modport[i];
   4598         MEMBER_INFO(unit, tid).member_flags[i] = member_flags[i];
   4599     }
   4600     MEMBER_INFO(unit, tid).recovered_from_scache = 1;
   4601 
   4602     return;
   4603 }
   4604 
   4605 void
   4606 _bcm_xgs3_trunk_member_info_get(int unit, bcm_trunk_t tid,
   4607                                 uint8 *num_ports,
   4608                                 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT],
   4609                                 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT])
   4610 {
   4611     int i;
   4612 
   4613     *num_ports = MEMBER_INFO(unit, tid).num_ports;
   4614     for (i = 0; i < BCM_XGS3_TRUNK_MAX_PORTCNT; i++) {
   4615         modport[i] = MEMBER_INFO(unit, tid).modport[i];
   4616         member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i];
   4617     }
   4618 
   4619     return;
   4620 }
   4621 #endif /* BCM_WARM_BOOT_SUPPORT */
   4622 
   4623 #ifndef BCM_SW_STATE_DUMP_DISABLE
   4624 /*
   4625  * Function:
   4626  *     _bcm_xgs3_trunk_sw_dump
   4627  * Purpose:
   4628  *     Displays trunk information maintained by software.
   4629  * Parameters:
   4630  *     unit - Device unit number
   4631  *      tid - Trunk id
   4632  * Returns:
   4633  *     None
   4634  */
   4635 void
   4636 _bcm_xgs3_trunk_sw_dump(int unit)
   4637 {
   4638     int rv, i, j, tid_ix, tid_min = -1, tid_max;
   4639     bcm_trunk_chip_info_t       chip_info;
   4640     _xgs3_trunk_swfail_t       *swf;
   4641     _xgs3_tinfo_t *swft;
   4642 
   4643     swf = _xgs3_trunk_swfail[unit];
   4644 
   4645     rv = bcm_esw_trunk_chip_info_get(unit, &chip_info);
   4646     if (BCM_FAILURE(rv)) {
   4647         LOG_CLI((BSL_META_U(unit,
   4648                             "Unable to retrieve unit %d chip info %d\n"),
   4649                  unit, rv));
   4650     }
   4651 
   4652     if (chip_info.trunk_id_min < 0) {
   4653         if (chip_info.trunk_fabric_id_min < 0) {
   4654             /* No trunks!  Abort */
   4655             LOG_CLI((BSL_META_U(unit,
   4656                                 "No trunk groups on unit %d\n"), unit));
   4657             return;
   4658         } else {
   4659             tid_min = chip_info.trunk_fabric_id_min;
   4660             tid_max = chip_info.trunk_fabric_id_max;
   4661         }
   4662     } else {
   4663         tid_min = chip_info.trunk_id_min;
   4664         if (chip_info.trunk_fabric_id_min < 0) {
   4665             tid_max = chip_info.trunk_id_max;
   4666         } else {
   4667             tid_max = chip_info.trunk_fabric_id_max;
   4668         }
   4669     }
   4670 
   4671     if (NULL != swf) {
   4672         LOG_CLI((BSL_META_U(unit,
   4673                             "Software failover parameters:\n")));
   4674         LOG_CLI((BSL_META_U(unit,
   4675                             "   Local modid:  %d\n"), swf->mymodid));
   4676         LOG_CLI((BSL_META_U(unit,
   4677                             "   Port:  Trunk\n")));
   4678         for (j = 0; j < SOC_MAX_NUM_PORTS; j++) {
   4679             if (0 != swf->trunk[j]) {
   4680                 LOG_CLI((BSL_META_U(unit,
   4681                                     "   %d:  %d\n"),
   4682                          j, swf->trunk[j]));
   4683             }
   4684         }
   4685         LOG_CLI((BSL_META_U(unit,
   4686                             "   Trunk SW failover parameters\n")));
   4687         for (i = tid_min; i <= tid_max; i++) {
   4688             if (i >= chip_info.trunk_fabric_id_min) {
   4689                 tid_ix = (i - chip_info.trunk_fabric_id_min) +
   4690                     _BCM_FP_TRUNK_NUM_MAX;
   4691             } else {
   4692                 tid_ix = i;
   4693             }
   4694 
   4695             swft = &swf->tinfo[tid_ix];
   4696             if (0 != swft->num_ports) {
   4697                 LOG_CLI((BSL_META_U(unit,
   4698                                     "   Trunk %d, index %d\n"), i, tid_ix));
   4699                 LOG_CLI((BSL_META_U(unit,
   4700                                     "      RTAG value %d\n"), swft->rtag));
   4701                 LOG_CLI((BSL_META_U(unit,
   4702                                     "      Port count %d\n"), swft->num_ports));
   4703                 for (j = 0; j < swft->num_ports; j++) {
   4704                     LOG_CLI((BSL_META_U(unit,
   4705                                         "      ModPort 0x%04x\n"), swft->modport[j]));
   4706                 }
   4707             }
   4708         }
   4709     } else {
   4710         LOG_CLI((BSL_META_U(unit,
   4711                             "SW trunk failover not initialized on unit %d\n"),
   4712                  unit));
   4713     }
   4714 
   4715 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
   4716     if (soc_feature(unit, soc_feature_port_lag_failover) ||
   4717         soc_feature(unit, soc_feature_hg_trunk_failover)) {
   4718         _xgs3_hw_tinfo_t           *hwft;
   4719 
   4720         if (NULL == _xgs3_trunk_hwfail[unit]) {
   4721             LOG_CLI((BSL_META_U(unit,
   4722                                 "HW trunk failover not initialized on unit %d\n"),
   4723                      unit));
   4724             return;
   4725         }
   4726 
   4727         LOG_CLI((BSL_META_U(unit,
   4728                             "   Trunk HW failover parameters\n")));
   4729         for (i = tid_min; i <= tid_max; i++) {
   4730             if (i >= chip_info.trunk_fabric_id_min) {
   4731                 tid_ix = (i - chip_info.trunk_fabric_id_min) +
   4732                     _BCM_FP_TRUNK_NUM_MAX;
   4733             } else {
   4734                 tid_ix = i;
   4735             }
   4736 
   4737             hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]);
   4738             if (0 != hwft->num_ports) {
   4739                 LOG_CLI((BSL_META_U(unit,
   4740                                     "   Trunk %d, index %d\n"), i, tid_ix));
   4741                 LOG_CLI((BSL_META_U(unit,
   4742                                     "      Port count %d\n"), hwft->num_ports));
   4743                 for (j = 0; j < hwft->num_ports; j++) {
   4744                     LOG_CLI((BSL_META_U(unit,
   4745                                         "      PSC value %d\n"), hwft->psc[j]));
   4746                     LOG_CLI((BSL_META_U(unit,
   4747                                         "      Flags 0x%08x\n"), hwft->flags[j]));
   4748                     LOG_CLI((BSL_META_U(unit,
   4749                                         "      ModPort 0x%04x\n"), hwft->modport[j]));
   4750                 }
   4751             }
   4752         }
   4753     }
   4754 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
   4755 
   4756     if (NULL != _xgs3_trunk_member_info[unit]) {
   4757         LOG_CLI((BSL_META_U(unit,
   4758                             "Trunk membership info:\n")));
   4759         for (i = tid_min; i <= tid_max; i++) {
   4760             if (i >= chip_info.trunk_fabric_id_min) {
   4761                 tid_ix = (i - chip_info.trunk_fabric_id_min) +
   4762                     _BCM_FP_TRUNK_NUM_MAX;
   4763             } else {
   4764                 tid_ix = i;
   4765             }
   4766 
   4767             if (0 != MEMBER_INFO(unit, tid_ix).num_ports) {
   4768                 LOG_CLI((BSL_META_U(unit,
   4769                                     "   Trunk %d, index %d\n"), i, tid_ix));
   4770                 LOG_CLI((BSL_META_U(unit,
   4771                                     "      Port count %d\n"),
   4772                          MEMBER_INFO(unit, tid_ix).num_ports));
   4773                 for (j = 0; j < MEMBER_INFO(unit, tid_ix).num_ports; j++) {
   4774                     LOG_CLI((BSL_META_U(unit,
   4775                                         "      ModPort 0x%04x\n"),
   4776                              MEMBER_INFO(unit, tid_ix).modport[j]));
   4777                     LOG_CLI((BSL_META_U(unit,
   4778                                         "      Member flags 0x%x\n"),
   4779                              MEMBER_INFO(unit, tid_ix).member_flags[j]));
   4780                 }
   4781             }
   4782         }
   4783     } else {
   4784         LOG_CLI((BSL_META_U(unit,
   4785                             "Trunk membership info not initialized on unit %d\n"),
   4786                  unit));
   4787     }
   4788 
   4789     return;
   4790 }
   4791 #endif /* BCM_SW_STATE_DUMP_DISABLE */