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

port.c (115212B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        port.c
      8  * Purpose:     Port driver.
      9  */
     10 
     11 #include <soc/defs.h>
     12 
     13 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     14 #include <shared/bsl.h>
     15 #include <soc/drv.h>
     16 #include <soc/types.h>
     17 #include <soc/td2_td2p.h>
     18 #include <bcm_int/esw_dispatch.h>
     19 #include <bcm_int/esw/port.h>
     20 #include <bcm_int/esw/stack.h>
     21 #include <bcm_int/esw/mirror.h>
     22 #include <bcm_int/esw/portctrl.h>
     23 #include <bcm_int/esw/firebolt.h>
     24 #include <bcm_int/esw/triumph.h>
     25 #include <bcm_int/esw/triumph2.h>
     26 #include <bcm_int/esw/triumph3.h>
     27 #include <bcm_int/esw/trx.h>
     28 #include <bcm_int/esw/xgs5.h>
     29 #include <bcm_int/esw/xgs3.h>
     30 #include <bcm_int/esw/trident2.h>
     31 #include <bcm_int/esw/trident2plus.h>
     32 #include <bcm_int/esw/trx.h>
     33 #include <bcm/error.h>
     34 #include <bcm/port.h>
     35 
     36 
     37 /*
     38  * FlexPort Operations Changes
     39  *
     40  * Flags to be used to determine the type of operations required
     41  * when the FlexPort API multi_set() is called.
     42  *
     43  * OP_NONE  - No changes.
     44  * OP_PMAP  - Change in port mapping.  It requires FlexPort sequence.
     45  * OP_LANES - Change in lanes.  It requires FlexPort sequence.
     46  * OP_SPEED - Change in speed.  This is covered in a FlexPort sequence.
     47  *            A change in speed may require a FlexPort sequence.
     48  *            If it is not required, then calling the 'speed' set
     49  *            function is sufficient.
     50  * OP_ENCAP - Change in encap mode.  It is NOT covered in a FlexPort
     51  *            sequence, so an explicit call must be made to change
     52  *            the encap mode.
     53  * OP_ALL   - All the above.  It requires FlexPort sequence.  
     54  */
     55 #define BCM_TD2P_PORT_RESOURCE_OP_NONE     0
     56 #define BCM_TD2P_PORT_RESOURCE_OP_PMAP    (1 << 0)
     57 #define BCM_TD2P_PORT_RESOURCE_OP_LANES   (1 << 1)
     58 #define BCM_TD2P_PORT_RESOURCE_OP_SPEED   (1 << 2)
     59 #define BCM_TD2P_PORT_RESOURCE_OP_ENCAP   (1 << 3)
     60 #define BCM_TD2P_PORT_RESOURCE_OP_ALL           \
     61     (BCM_TD2P_PORT_RESOURCE_OP_PMAP |           \
     62      BCM_TD2P_PORT_RESOURCE_OP_LANES |          \
     63      BCM_TD2P_PORT_RESOURCE_OP_SPEED |          \
     64      BCM_TD2P_PORT_RESOURCE_OP_ENCAP) 
     65 
     66 soc_profile_mem_t *egr_pri_cng_profile[BCM_MAX_NUM_UNITS] = {NULL};
     67 
     68 /*
     69  *  DSCP
     70  */
     71 #define DSCP_CODE_POINT_CNT 64
     72 
     73 
     74 /*
     75  * Internal BCM Port Resource Configuration
     76  */
     77 typedef struct bcm_td2p_port_resource_s {
     78     uint32 flags;              /* SOC_PORT_RESOURCE_XXX */
     79     bcm_gport_t port;          /* Local logical port number to connect to
     80                                   the given physical port */
     81     int physical_port;         /* Local physical port, -1 if the logical to
     82                                   physical mapping is to be deleted */
     83     int speed;                 /* Initial speed after FlexPort operation */
     84     int lanes;                 /* Number of PHY lanes for this physical port */
     85     bcm_port_encap_t encap;    /* Encapsulation mode for port */
     86 } bcm_td2p_port_resource_t;
     87 
     88 
     89 /*
     90  * Forward static function declaration
     91  */
     92 STATIC int
     93 _bcm_td2p_port_resource_multi_set(int unit, 
     94                                   int nport, bcm_port_resource_t *resource);
     95 STATIC int
     96 _bcm_td2p_port_resource_speed_set(int unit, bcm_port_t port, int speed);
     97 
     98 /*
     99  * Function Vector
    100  */
    101 static bcm_esw_port_drv_t bcm_td2p_port_drv = {
    102     /* fn_drv_init                */ bcmi_td2p_port_fn_drv_init,
    103     /* resource_set               */ bcmi_xgs5_port_resource_set,
    104     /* resource_get               */ bcmi_xgs5_port_resource_get,
    105     /* resource_multi_set         */ _bcm_td2p_port_resource_multi_set,
    106     /* resource_speed_set         */ _bcm_td2p_port_resource_speed_set,
    107     /* resource_traverse          */ bcmi_xgs5_port_resource_traverse,
    108     /* port_redirect_set          */ NULL,
    109     /* port_redirect_get          */ NULL,
    110     /* port_enable_set            */ NULL,
    111     /* encap_speed_check          */ bcmi_xgs5_port_encap_speed_check,
    112     /* force_lb_set               */ NULL,
    113     /* force_lb_check             */ NULL,
    114     /* resource_status_update     */ bcmi_xgs5_port_resource_status_update
    115 };
    116 
    117 
    118 /*
    119  * Function:
    120  *      bcmi_td2p_port_fn_drv_init
    121  * Purpose:
    122  *      Initialize the Port function driver.
    123  * Parameters:
    124  *      unit - (IN) Unit number.
    125  * Returns:
    126  *      BCM_E_xxx
    127  * Notes:
    128  */
    129 int
    130 bcmi_td2p_port_fn_drv_init(int unit)
    131 {
    132     /* Initialize Common XGS5 Port module */
    133     BCM_IF_ERROR_RETURN
    134         (bcmi_xgs5_port_fn_drv_init(unit, &bcm_td2p_port_drv, NULL, NULL));
    135 
    136     return BCM_E_NONE;
    137 }
    138 
    139 
    140 /*
    141  * Function:
    142  *     _bcm_td2p_port_trunk_src_trunk_map_table_entry_init
    143  * Purpose:
    144  *     This function is used by Flexport feature. It programs
    145  *     SOURCE_TRUNK_MAP_TABLE entries for a port to the values programmed
    146  *     during chip initialization.
    147  * Parameters:
    148  *     unit  - (IN) SOC unit number.
    149  *     port  - (IN) Source Port num.
    150  *     index - (OUT) Source mod port table index. Can be NULL if the caller is
    151  *                   not interested in the table's index corresponding to the
    152  *                   port. May be used for debugging.
    153  * Returns:
    154  *     BCM_E_xxx
    155  */
    156 STATIC int
    157 _bcm_td2p_port_trunk_src_trunk_map_table_entry_init(int unit, bcm_port_t port,
    158                                                     int *index)
    159 {
    160     int my_modid;
    161     int src_trk_idx = 0;
    162     int rv;
    163     source_trunk_map_table_entry_t trunk_map_entry;
    164 
    165     /* Get module id for unit. */
    166     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    167 
    168     /* Get index to source trunk map table */
    169     BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid,
    170                                                               port,
    171                                                               &src_trk_idx));
    172 
    173     /* Read source trunk map table */
    174     soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm);
    175     rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL,
    176                       src_trk_idx, &trunk_map_entry);
    177 
    178     if (SOC_FAILURE(rv)) {
    179         soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
    180         return rv;
    181     }
    182 
    183     /* Initialize relevant fields */
    184     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &trunk_map_entry,
    185                                             PORT_TYPEf, 0);
    186 
    187     soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &trunk_map_entry,
    188                                             TGIDf, 0);
    189 
    190     /* Write entry to hw. */
    191     rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL,
    192                        src_trk_idx, &trunk_map_entry);
    193 
    194     soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm);
    195 
    196     if ((index != NULL) && SOC_SUCCESS(rv)) {
    197         *index = src_trk_idx;
    198     }
    199 
    200     return rv;
    201 }
    202 
    203 /*
    204  * Function:
    205  *     _bcm_td2p_port_trunk_port_attach
    206  * Purpose:
    207  *     This function initializes trunk tables for newly added port. It is
    208  *     used for Flexport feature.
    209  * Parameters:
    210  *     unit     - (IN) Unit number.
    211  *     port     - (IN) Logical port, BCM format.
    212  * Returns:
    213  *     BCM_E_NONE              Success.
    214  *     BCM_E_XXX
    215  */
    216 
    217 STATIC int
    218 _bcm_td2p_port_trunk_port_attach(int unit, bcm_port_t port)
    219 {
    220 
    221     bcm_pbmp_t pbmp;
    222     higig_trunk_control_entry_t entry;
    223     int rv = BCM_E_NONE;
    224     int index = -1;
    225 
    226     BCM_IF_ERROR_RETURN(_bcm_td2p_port_trunk_src_trunk_map_table_entry_init(
    227                         unit, port, &index));
    228 
    229     LOG_INFO(BSL_LS_BCM_PORT,
    230              (BSL_META_U(unit,
    231                          "table_entry_init: unit=%d port=%d index=%d\n"),
    232                          unit, port, index));
    233 
    234     soc_mem_lock(unit, HIGIG_TRUNK_CONTROLm);
    235 
    236     rv = soc_mem_read(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ANY, 0, &entry);
    237 
    238     if (SOC_FAILURE(rv)) {
    239         soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm);
    240         return (rv);
    241     }
    242 
    243     BCM_PBMP_CLEAR(pbmp);
    244 
    245     /* Read port bmap from hardware, and add new port to the bitmap */
    246     soc_mem_pbmp_field_get(unit, HIGIG_TRUNK_CONTROLm, &entry,
    247                            ACTIVE_PORT_BITMAPf, &pbmp);
    248 
    249     BCM_PBMP_PORT_ADD(pbmp, port);
    250 
    251     soc_mem_pbmp_field_set(unit, HIGIG_TRUNK_CONTROLm, &entry,
    252                            ACTIVE_PORT_BITMAPf, &pbmp);
    253 
    254     rv = soc_mem_write(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ALL, 0,
    255                        &entry);
    256 
    257     soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm);
    258 
    259     return rv;
    260 }
    261 
    262 /*
    263  * Function:
    264  *     _bcm_td2p_port_trunk_port_detach
    265  * Purpose:
    266  *     This function updates the trunk tables for a deleted port. It is
    267  *     used for Flexport feature.
    268  * Parameters:
    269  *     unit     - (IN) Unit number.
    270  *     port     - (IN) Logical port, BCM format.
    271  * Returns:
    272  *     BCM_E_NONE              Success.
    273  *     BCM_E_XXX
    274  * Notes:
    275  *     The internal databases will be updated when a port is removed from trunk
    276  *     group, or when the trunk itself is destroyed
    277  */
    278 
    279 STATIC int
    280 _bcm_td2p_port_trunk_port_detach(int unit, bcm_port_t port)
    281 {
    282     bcm_pbmp_t pbmp;
    283     higig_trunk_control_entry_t entry;
    284     int rv = BCM_E_NONE;
    285 
    286     soc_mem_lock(unit, HIGIG_TRUNK_CONTROLm);
    287 
    288     rv = soc_mem_read(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ANY, 0, &entry);
    289 
    290     if (SOC_FAILURE(rv)) {
    291         soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm);
    292         return (rv);
    293     }
    294 
    295     BCM_PBMP_CLEAR(pbmp);
    296 
    297     /* Read port bmap from hardware, and remove port from the bitmap */
    298     soc_mem_pbmp_field_get(unit, HIGIG_TRUNK_CONTROLm, &entry,
    299                            ACTIVE_PORT_BITMAPf, &pbmp);
    300 
    301     BCM_PBMP_PORT_REMOVE(pbmp, port);
    302 
    303     soc_mem_pbmp_field_set(unit, HIGIG_TRUNK_CONTROLm, &entry,
    304                            ACTIVE_PORT_BITMAPf, &pbmp);
    305 
    306     rv = soc_mem_write(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ALL, 0,
    307                        &entry);
    308 
    309     soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm);
    310 
    311     return rv;
    312 }
    313 
    314 /*
    315  * Function:
    316  *     _bcm_td2p_port_ipmc_port_state_change
    317  * Purpose:
    318  *     This function updates ipmc related fields in hardware tables/registers,
    319  *     for a specified port. It is used for Flexport feature.
    320  * Parameters:
    321  *     unit     - (IN) Unit number.
    322  *     port     - (IN) Logical port, BCM format.
    323  *     enable   - (IN) Port specific enable/disable of IPMC config and related
    324  *                     features. Set TRUE to enable them, FALSE to disable them
    325  * Returns:
    326  *     BCM_E_NONE              Success.
    327  *     BCM_E_XXX
    328  * Notes:
    329  */
    330 STATIC int
    331 _bcm_td2p_port_ipmc_port_state_change(int unit, bcm_port_t port, int enable)
    332 {
    333     int do_vlan = soc_property_get(unit, spn_IPMC_DO_VLAN, 1);
    334 
    335     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, port,
    336                             _bcmPortIpmcV4Enable, enable));
    337     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, port,
    338                             _bcmPortIpmcV6Enable, enable));
    339     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, port,
    340                             _bcmPortIpmcVlanKey, (enable && do_vlan) ? 1 : 0));
    341 
    342     /* Update LPORT Profile Table */
    343     BCM_IF_ERROR_RETURN(_bcm_lport_profile_field32_modify(unit,
    344                             LPORT_PROFILE_LPORT_TAB, V4IPMC_ENABLEf, enable));
    345     BCM_IF_ERROR_RETURN(_bcm_lport_profile_field32_modify(unit,
    346                             LPORT_PROFILE_LPORT_TAB, V6IPMC_ENABLEf, enable));
    347     BCM_IF_ERROR_RETURN(_bcm_lport_profile_field32_modify(unit,
    348                             LPORT_PROFILE_LPORT_TAB, IPMC_DO_VLANf,
    349                             (enable && do_vlan) ? 1 : 0));
    350 
    351     return BCM_E_NONE;
    352 }
    353 
    354 /*
    355  * Function:
    356  *     _bcm_td2p_port_ipmc_port_attach
    357  * Purpose:
    358  *     This function programs hardware tables and registers for enabling IPMC
    359  *     functionality and related features. It is used for Flexport feature.
    360  * Parameters:
    361  *     unit     - (IN) Unit number.
    362  *     port     - (IN) Logical port, BCM format.
    363  * Returns:
    364  *     BCM_E_NONE              Success.
    365  *     BCM_E_XXX
    366  */
    367 STATIC int
    368 _bcm_td2p_port_ipmc_port_attach(int unit, bcm_port_t port)
    369 {
    370     if (soc_feature(unit, soc_feature_ip_mcast)) {
    371         BCM_IF_ERROR_RETURN(_bcm_td2p_port_ipmc_port_state_change(unit,
    372                                 port, TRUE));
    373 
    374 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    375         if (soc_feature(unit, soc_feature_ip_mcast_repl)) {
    376             BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_port_attach_repl_init(unit, port));
    377         }
    378 
    379         if (IS_E_PORT(unit, port)) {
    380             BCM_IF_ERROR_RETURN(bcm_esw_ipmc_egress_port_set(unit, port,
    381                                     _soc_mac_all_zeroes, 0, 0, 0));
    382         }
    383 #endif
    384     }
    385 
    386     return BCM_E_NONE;
    387 }
    388 
    389 /*
    390  * Function:
    391  *     _bcm_td2p_port_ipmc_port_detach
    392  * Purpose:
    393  *     This function clears hardware tables and registers in IPMC
    394  *     functionality and related features. It is used for Flexport feature.
    395  * Parameters:
    396  *     unit     - (IN) Unit number.
    397  *     port     - (IN) Logical port, BCM format.
    398  * Returns:
    399  *     BCM_E_NONE              Success.
    400  *     BCM_E_XXX
    401  */
    402 STATIC int
    403 _bcm_td2p_port_ipmc_port_detach(int unit, bcm_port_t port)
    404 {
    405     if (soc_feature(unit, soc_feature_ip_mcast)) {
    406         BCM_IF_ERROR_RETURN(_bcm_td2p_port_ipmc_port_state_change(unit,
    407                                 port, FALSE));
    408 
    409 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
    410         if (soc_feature(unit, soc_feature_ip_mcast_repl)) {
    411             /* See bcm_tr_ipmc_detach, bcm_tr3_ipmc_repl_detach for more
    412              * information
    413              */
    414             BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_port_detach_repl_deinit(unit, port));
    415         }
    416 #endif
    417     }
    418 
    419     return BCM_E_NONE;
    420 }
    421 
    422 
    423 /*
    424  * Function:
    425  *      _bcm_td2p_port_rate_port_attach
    426  * Purpose:
    427  *      Initialize port related information in the Rate module.
    428  * Parameters:
    429  *      unit   - (IN) Unit number.
    430  *      port   - (IN) Logical port, BCM format.
    431  * Returns:
    432  *      BCM_E_XXX
    433  */
    434 STATIC int
    435 _bcm_td2p_port_rate_port_attach(int unit, bcm_port_t port)
    436 {
    437     soc_field_t fields[] = {PACKET_QUANTUMf, BYTE_MODEf};
    438     uint32 values[] = {0x100, 1};
    439 
    440     SOC_IF_ERROR_RETURN
    441         (WRITE_STORM_CONTROL_METER_CONFIGr(unit, port, 0));
    442 
    443     SOC_IF_ERROR_RETURN
    444         (soc_reg_fields32_modify(unit,  
    445                                  STORM_CONTROL_METER_CONFIGr, 
    446                                  port, COUNTOF(fields), 
    447                                  fields, values));
    448 
    449     return BCM_E_NONE;
    450 }
    451 
    452 
    453 /*
    454  * Function:
    455  *      _bcm_td2p_port_rate_port_detach
    456  * Purpose:
    457  *      Clear port related information in the Rate module.
    458  * Parameters:
    459  *      unit   - (IN) Unit number.
    460  *      port   - (IN) Logical port, BCM format.
    461  * Returns:
    462  *      BCM_E_XXX
    463  */
    464 STATIC int
    465 _bcm_td2p_port_rate_port_detach(int unit, bcm_port_t port)
    466 {
    467     SOC_IF_ERROR_RETURN
    468         (WRITE_STORM_CONTROL_METER_CONFIGr(unit, port, 0));
    469 
    470     return BCM_E_NONE;
    471 }
    472 
    473 
    474 /*
    475  * Function:
    476  *      _bcm_td2p_port_stack_port_attach
    477  * Purpose:
    478  *      Initialize port related information in the Stack module.
    479  *      Set my_modid and other modid related initialization.
    480  * Parameters:
    481  *      unit   - (IN) Unit number.
    482  *      port   - (IN) Logical port, BCM format.
    483  * Returns:
    484  *      BCM_E_XXX
    485  * Notes:
    486  *      - Assumes port is valid.
    487  */
    488 int
    489 _bcm_td2p_port_stack_port_attach(int unit, bcm_port_t port)
    490 {
    491     modport_map_subport_entry_t subport_entry;
    492     modport_map_subport_mirror_entry_t subport_m_entry;
    493 
    494     /* Configure logical subport numbers */
    495     sal_memset(&subport_entry, 0, sizeof(subport_entry));
    496     soc_MODPORT_MAP_SUBPORTm_field32_set(unit, &subport_entry, ENABLEf, 1);
    497     soc_MODPORT_MAP_SUBPORTm_field32_set(unit, &subport_entry, DESTf, port);
    498     SOC_IF_ERROR_RETURN
    499         (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL,
    500                                     port, &subport_entry));
    501 
    502     /* Configure logical subport mirror numbers */
    503     sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry));
    504     soc_MODPORT_MAP_SUBPORT_M0m_field32_set(unit, &subport_m_entry,
    505                                             ENABLEf, 1);
    506     soc_MODPORT_MAP_SUBPORT_M0m_field32_set(unit, &subport_m_entry,
    507                                             DESTf, port);
    508     SOC_IF_ERROR_RETURN
    509         (WRITE_MODPORT_MAP_SUBPORT_MIRRORm(unit, MEM_BLOCK_ALL,
    510                                            port, &subport_m_entry));
    511 
    512     /* Initialize modport map profiles ptr on port.*/
    513     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
    514         BCM_IF_ERROR_RETURN
    515             (bcm_td_stk_modport_map_port_attach(unit, port));
    516     }
    517 
    518     return BCM_E_NONE;
    519 }
    520 
    521 
    522 /*
    523  * Function:
    524  *      _bcm_td2p_port_stack_port_detach
    525  * Purpose:
    526  *      Clear port related information in the Stack module.
    527  * Parameters:
    528  *      unit   - (IN) Unit number.
    529  *      port   - (IN) Logical port, BCM format.
    530  * Returns:
    531  *      BCM_E_XXX
    532  * Notes:
    533  *      - Assumes port is valid.
    534  */
    535 int
    536 _bcm_td2p_port_stack_port_detach(int unit, bcm_port_t port)
    537 {
    538     modport_map_subport_entry_t subport_entry;
    539     modport_map_subport_mirror_entry_t subport_m_entry;
    540 
    541     /* Clear logical subport numbers */
    542     sal_memset(&subport_entry, 0, sizeof(subport_entry));
    543     SOC_IF_ERROR_RETURN
    544         (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL,
    545                                     port, &subport_entry));
    546 
    547     /* Clear logical subport mirror numbers */
    548     sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry));
    549     SOC_IF_ERROR_RETURN
    550         (WRITE_MODPORT_MAP_SUBPORT_MIRRORm(unit, MEM_BLOCK_ALL,
    551                                        port, &subport_m_entry));
    552 
    553     /* detach port from modport map profiles */
    554     if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) {
    555         BCM_IF_ERROR_RETURN
    556             (bcm_td_stk_modport_map_port_detach(unit, port));
    557     }
    558 
    559     return BCM_E_NONE;
    560 }
    561 
    562 
    563 /*
    564  * Function:
    565  *      _bcm_td2p_port_dscp_table_default_add
    566  * Purpose:
    567  *      Add DSCP default profile entry to given port.
    568  * Parameters:
    569  *      unit   - (IN) Unit number.
    570  *      port   - (IN) Logical port, BCM format.
    571  * Returns:
    572  *      BCM_E_XXX
    573  * Notes:
    574  *      - Assumes port is valid.
    575  */
    576 STATIC int
    577 _bcm_td2p_port_dscp_table_default_add(int unit, bcm_port_t port)
    578 {
    579     BCM_IF_ERROR_RETURN
    580         (_bcm_esw_port_tab_set(unit, port,
    581                                _BCM_CPU_TABS_ETHER,
    582                                TRUST_DSCP_PTRf,
    583                                0));
    584     return BCM_E_NONE;
    585 }
    586 
    587 /*
    588  * Function:
    589  *      _bcm_td2p_port_outer_tpid_ref_count_update
    590  * Purpose:
    591  *      Update TPID reference count.
    592  * Parameters:
    593  *      unit   - (IN) Unit number.
    594  *      port   - (IN) Logical port, BCM format.
    595  *      add    - (IN) Indicates whether port is added or deleted from BCM.
    596  * Returns:
    597  *      BCM_E_XXX
    598  * Notes:
    599  */
    600 STATIC int
    601 _bcm_td2p_port_outer_tpid_ref_count_update(int unit, bcm_port_t port, int add)
    602 {
    603     egr_vlan_control_1_entry_t entry;
    604     int index;
    605     int enabled;
    606 
    607     if (soc_feature(unit, soc_feature_egr_all_profile)) {
    608         BCM_IF_ERROR_RETURN(
    609             bcm_esw_port_egr_lport_field_get(unit, port,
    610             EGR_VLAN_CONTROL_1m, OUTER_TPID_INDEXf, (void *)&index));
    611     } else {
    612         SOC_IF_ERROR_RETURN
    613             (READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry));
    614         index = soc_EGR_VLAN_CONTROL_1m_field32_get(unit, &entry,
    615                                                     OUTER_TPID_INDEXf);
    616     }
    617     if (add) {
    618         BCM_IF_ERROR_RETURN
    619             (_bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1));
    620     } else {
    621         /* Ignore error when deleting */
    622         (void) _bcm_fb2_outer_tpid_entry_delete(unit, index);
    623     }
    624 
    625     enabled = 0;
    626     BCM_IF_ERROR_RETURN
    627         (_bcm_esw_port_config_get(unit, port,
    628                                   _bcmPortOuterTpidEnables, &enabled));
    629     index = 0;
    630     while (enabled) {
    631         if (enabled & 1) {
    632             if (add) {
    633                 BCM_IF_ERROR_RETURN
    634                     (_bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1));
    635             } else {
    636                 /* Ignore error when deleting */
    637                 (void) _bcm_fb2_outer_tpid_entry_delete(unit, index);
    638             }
    639         }
    640         enabled = enabled >> 1;
    641         index++;
    642     }
    643 
    644     return BCM_E_NONE;
    645 }
    646 
    647 
    648 /*
    649  * Function:
    650  *      _bcm_td2p_port_priority_map_init
    651  * Purpose:
    652  *      Initialize priority map for given port.
    653  * Parameters:
    654  *      unit   - (IN) Unit number.
    655  *      port   - (IN) Logical port, BCM format.
    656  * Returns:
    657  *      BCM_E_XXX
    658  * Notes:
    659  */
    660 STATIC int
    661 _bcm_td2p_port_priority_map_init(int unit, bcm_port_t port)
    662 {
    663     int rv = BCM_E_NONE;
    664 
    665     if (soc_feature(unit, soc_feature_egr_qos_combo_profile)) {
    666        rv = _bcm_esw_egr_port_tab_set(unit, port, EGR_QOS_PROFILE_INDEXf, 0);
    667        if (BCM_FAILURE(rv)) {
    668             return rv;
    669         }
    670     } else if (SOC_IS_TRIDENT3X(unit)) {
    671        rv = _bcm_esw_egr_port_tab_set(unit, port, EGR_QOS_PROFILE_INDEXf, 0);
    672        if (BCM_FAILURE(rv)) {
    673             return rv;
    674         }
    675     }
    676 
    677     return rv;
    678 }
    679 
    680 /*
    681  * Function:
    682  *      _bcm_td2p_port_software_free
    683  * Purpose:
    684  *      Deallocates memory for a given port from the BCM PORT module
    685  *      data structure.
    686  * Parameters:
    687  *      unit   - (IN) Unit number.
    688  *      port   - (IN) Logical port, BCM format.
    689  * Returns:
    690  *      BCM_E_XXX
    691  * Notes:
    692  *      - Assumes main BCM PORT module initialization has been executed.
    693  *      - Assumes port is valid.
    694  */
    695 STATIC int
    696 _bcm_td2p_port_software_free(int unit, bcm_port_t port)
    697 {
    698     _bcm_port_info_t *pinfo;
    699 
    700     /* Get PORT info structure pointer */
    701     BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
    702     if  (pinfo == NULL) {
    703         return BCM_E_INTERNAL;
    704     }
    705 
    706     /* Proto-based VLAN_DATA state */
    707     if (pinfo->p_vd_pbvl != NULL) {
    708         sal_free(pinfo->p_vd_pbvl);
    709         pinfo->p_vd_pbvl = NULL;
    710     }
    711 
    712     /* End-to-end congestion control configuration */
    713     if (pinfo->e2ecc_config != NULL) {
    714         sal_free(pinfo->e2ecc_config);
    715         pinfo->e2ecc_config = NULL;
    716     }
    717 
    718     /* Reset all fields */
    719     sal_memset(pinfo, 0, sizeof(_bcm_port_info_t));
    720 
    721     return BCM_E_NONE;
    722 }
    723 
    724 
    725 /*
    726  * Function:
    727  *      _bcm_td2p_port_software_alloc
    728  * Purpose:
    729  *      Allocates software memory in the BCM PORT module for given port.
    730  * Parameters:
    731  *      unit   - (IN) Unit number.
    732  *      port   - (IN) Logical port, BCM format.
    733  * Returns:
    734  *      BCM_E_XXX
    735  * Notes:
    736  *      - Assumes main BCM PORT module initialization has been executed.
    737  *      - Assumes port is valid.
    738  */
    739 STATIC int
    740 _bcm_td2p_port_software_alloc(int unit, bcm_port_t port)
    741 {
    742     _bcm_port_info_t *pinfo;
    743     int idxmax = soc_mem_index_count(unit, VLAN_PROTOCOLm);
    744     int inds_bytes = (idxmax + (_BCM_PORT_VD_PBVL_ESIZE -  1)) / \
    745         _BCM_PORT_VD_PBVL_ESIZE; /* Round to the next entry */
    746 
    747     /* Free memory in case this is already allocated */
    748     BCM_IF_ERROR_RETURN(_bcm_td2p_port_software_free(unit, port));
    749 
    750     /* Get PORT info structure pointer */
    751     BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
    752     if  (pinfo == NULL) {
    753         LOG_ERROR(BSL_LS_BCM_PORT,
    754                   (BSL_META_U(unit,
    755                               "Unable to get PORT info data for "
    756                               "unit=%d port=%d\n"),
    757                    unit, port));
    758         return BCM_E_INTERNAL;
    759     }
    760 
    761     /* Reset all fields */
    762     sal_memset(pinfo, 0, sizeof(_bcm_port_info_t));
    763 
    764     /* Proto-based VLAN_DATA state */
    765     pinfo->p_vd_pbvl = sal_alloc(inds_bytes, "vdv_info");
    766     if (pinfo->p_vd_pbvl == NULL) {
    767         LOG_ERROR(BSL_LS_BCM_PORT,
    768                   (BSL_META_U(unit,
    769                               "Unable to allocate memory for PORT vlan "
    770                               "unit=%d port=%d\n"),
    771                    unit, port));
    772         return BCM_E_MEMORY;
    773     }
    774     sal_memset(pinfo->p_vd_pbvl, 0, inds_bytes);
    775 
    776     return BCM_E_NONE;
    777 }
    778 
    779 /*
    780  * Function:
    781  *      _bcm_td2p_port_bridge_port_init
    782  * Purpose:
    783  *      This function initializes PORT_BRIDGE_BMAP memory (for a normal port),
    784  *      and/or PORT_BRIDGE_MIRROR_BMAP (for a Higig port). The initialization is
    785  *      required for ensuring that port bit in one of the above memories
    786  *      (depending on port type), and PORT_TAB.PORT_BRIDGE bit have the same
    787  *      value. See notes.
    788  * Parameters:
    789  *      unit   - (IN) Unit number.
    790  *      port   - (IN) Logical port, BCM format.
    791  *      value  - 1 Set bit in PORT_BRIDGE_BMAP and/or PORT_BRIDGE_MIRROR_BMAP
    792  *                 memory.
    793  *               0 Reset bit in PORT_BRIDGE_BMAP and/or PORT_BRIDGE_MIRROR_BMAP
    794  *                 memory.
    795  *                 See Notes.
    796  * Returns:
    797  *      BCM_E_XXX
    798  * Notes:
    799  *      - PORT_TAB.PORT_BRIDGE is reset in function
    800  *        mbcm_driver[unit]->mbcm_port_cfg_init()
    801  *      - If this function is called outside of port attach and detach
    802  *        functions then the caller must make sure that PORT_TAB.PORT_BRIDGE is
    803  *        programmed to the same value as in these memories, for a given port
    804  *        Refer to memory description of these two memories for more information
    805  *      - Assumes port is valid.
    806  *      - Assumes this is NOT called during Warmboot.
    807  */
    808 STATIC int
    809 _bcm_td2p_port_bridge_port_init(int unit, bcm_port_t port, int value)
    810 {
    811     int rv = BCM_E_NONE;
    812     bcm_pbmp_t  pbmp;
    813 
    814     if (IS_E_PORT(unit, port)
    815         || IS_CPU_PORT(unit, port)
    816         || IS_HG_PORT(unit, port)) {
    817         port_bridge_bmap_entry_t entry;
    818 
    819         SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_BRIDGE_BMAPm,
    820                             MEM_BLOCK_ANY, 0, &entry));
    821         soc_mem_pbmp_field_get(unit, PORT_BRIDGE_BMAPm, &entry,
    822                                BITMAPf, &pbmp);
    823 
    824         if (value) {
    825             SOC_PBMP_PORT_ADD(pbmp, port);
    826         } else {
    827             SOC_PBMP_PORT_REMOVE(pbmp, port);
    828         }
    829 
    830         soc_mem_pbmp_field_set(unit, PORT_BRIDGE_BMAPm, &entry,
    831                                BITMAPf, &pbmp);
    832 
    833         SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_BRIDGE_BMAPm,
    834                             MEM_BLOCK_ANY, 0, &entry));
    835     }
    836 
    837     if (IS_HG_PORT(unit, port)) {
    838         port_bridge_mirror_bmap_entry_t entry;
    839 
    840         SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_BRIDGE_MIRROR_BMAPm,
    841                             MEM_BLOCK_ANY, 0, &entry));
    842         soc_mem_pbmp_field_get(unit, PORT_BRIDGE_MIRROR_BMAPm, &entry,
    843                                BITMAPf, &pbmp);
    844         if (value) {
    845             SOC_PBMP_PORT_ADD(pbmp, port);
    846         } else {
    847             SOC_PBMP_PORT_REMOVE(pbmp, port);
    848         }
    849         soc_mem_pbmp_field_set(unit, PORT_BRIDGE_MIRROR_BMAPm, &entry,
    850                                BITMAPf, &pbmp);
    851         SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_BRIDGE_MIRROR_BMAPm,
    852                             MEM_BLOCK_ANY, 0, &entry));
    853     }
    854 
    855     return rv;
    856 }
    857 
    858 /*
    859  * Function:
    860  *      _bcm_td2_port_basic_init
    861  * Purpose:
    862  *      Initialize the BCM PORT module portion (basic) for a given port
    863  *      (bcm_esw_port_init).
    864  * Parameters:
    865  *      unit   - (IN) Unit number.
    866  *      port   - (IN) Logical port, BCM format.
    867  * Returns:
    868  *      BCM_E_XXX
    869  * Notes:
    870  *      - Assumes main BCM PORT module initialization has been executed.
    871  *      - Assumes port is valid.
    872  *      - Caller must call other corresponding module routines
    873  *        that need to initialize any port related information.
    874  *      - Assumes this is NOT called during Warmboot.
    875  */
    876 STATIC int
    877 _bcm_td2_port_basic_init(int unit, bcm_port_t port)
    878 {
    879     int rv;
    880     _bcm_port_info_t *pinfo;
    881     bcm_vlan_action_set_t action;
    882     bcm_pbmp_t port_pbmp;
    883     bcm_vlan_data_t vd;
    884     int length_check;
    885     uint32 addr;
    886     int block;
    887     uint8 acc_type;
    888     uint32 rval;
    889     uint32 profile_index;
    890     int blk;
    891     int blk_num = -1;
    892     int bindex = 0;
    893     int tx_pbm = 0;
    894     uint32 rx_los;
    895     int enable;
    896     int value;
    897 
    898     LOG_VERBOSE(BSL_LS_BCM_PORT,
    899                 (BSL_META_U(unit,
    900                             "BCM Port Basic Init unit=%d port=%d(%s)\n"),
    901                  unit, port, SOC_PORT_NAME(unit, port)));
    902 
    903     /* Get PORT info structure pointer */
    904     BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
    905     if  (pinfo == NULL) {
    906         LOG_ERROR(BSL_LS_BCM_PORT,
    907                   (BSL_META_U(unit,
    908                               "Unable to get PORT info data for "
    909                               "unit=%d port=%d\n"),
    910                    unit, port));
    911         return BCM_E_INTERNAL;
    912     }
    913 
    914 
    915     /**********
    916      * VLAN TPID reference count
    917      * Priority Map
    918      * Double-Tag mode
    919      */
    920     BCM_IF_ERROR_RETURN
    921         (_bcm_td2p_port_outer_tpid_ref_count_update(unit, port, 1));
    922     BCM_IF_ERROR_RETURN
    923         (_bcm_td2p_port_priority_map_init(unit, port));
    924 
    925     pinfo->dtag_mode = BCM_PORT_DTAG_MODE_NONE;
    926 
    927     /**********
    928      * VLAN Action
    929      * soc_feature_vlan_action
    930      */
    931     bcm_vlan_action_set_t_init(&action);
    932     pinfo->vp_count = 0;
    933     if (!IS_LB_PORT(unit, port)) {
    934         BCM_IF_ERROR_RETURN
    935             (_bcm_port_vlan_prot_index_alloc(unit, &(pinfo->vlan_prot_ptr)));
    936     }
    937 
    938     /* Update Egress VLAN profile table count */
    939     _bcm_trx_egr_vlan_action_profile_entry_increment
    940         (unit, BCM_TRX_EGR_VLAN_ACTION_PROFILE_DEFAULT);
    941 
    942     if (IS_HG_PORT(unit, port)) {
    943         BCM_IF_ERROR_RETURN
    944             (_bcm_trx_vlan_port_egress_default_action_get(unit,
    945                                                       port, &action));
    946         /* Backward compatible defaults */
    947         action.ot_outer = bcmVlanActionDelete;
    948         action.dt_outer = bcmVlanActionDelete;
    949         BCM_IF_ERROR_RETURN
    950             (_bcm_trx_vlan_port_egress_default_action_set(unit,
    951                                                           port, &action));
    952     }
    953 
    954     /**********
    955      * Write port configuration tables to contain the Initial System
    956      * Configuration (see init.c).
    957      *
    958      * Note:  Logically, it would make more sense to call mbcm_port_cfg_init()
    959      * and bcm_port_settings_init() first.  However, we are maintaining
    960      * the same order sequence as in bcm_esw_port_init() to avoid
    961      * introducing dependencies issues on code above. 
    962      */
    963     SOC_PBMP_CLEAR(port_pbmp);
    964     BCM_PBMP_ASSIGN(port_pbmp, PBMP_ALL(unit));
    965     SOC_PBMP_REMOVE(port_pbmp, PBMP_TDM(unit));
    966 
    967     vd.vlan_tag = BCM_VLAN_DEFAULT;
    968     BCM_PBMP_ASSIGN(vd.port_bitmap, port_pbmp);
    969     BCM_PBMP_ASSIGN(vd.ut_port_bitmap, port_pbmp);
    970     BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_CMIC(unit));
    971 
    972     BCM_IF_ERROR_RETURN
    973         (mbcm_driver[unit]->mbcm_port_cfg_init(unit, port, &vd));
    974 
    975     BCM_IF_ERROR_RETURN(_bcm_td2p_port_bridge_port_init(unit, port, 0));
    976 
    977     BCM_IF_ERROR_RETURN(bcm_port_settings_init(unit, port));
    978 
    979     /**********
    980      * DSCP Profile
    981      */
    982     BCM_IF_ERROR_RETURN
    983         (_bcm_td2p_port_dscp_table_default_add(unit, port));
    984 
    985     /**********
    986      * COS_MAP Profile
    987      */
    988     if (SOC_IS_TRIDENT2PLUS(unit)) {
    989         BCM_IF_ERROR_RETURN
    990             (bcm_td2p_port_cosq_config_set(unit, port, TRUE));
    991     }
    992 
    993     if (soc_feature(unit, soc_feature_pgw_mac_rsv_mask_remap)) {
    994         /**********
    995          * Frame Length Check
    996          */
    997         length_check = soc_property_get(unit, spn_MAC_LENGTH_CHECK_ENABLE, 0);
    998         addr = soc_reg_addr_get(unit, PGW_MAC_RSV_MASKr, port, 0, FALSE, &block,
    999                                 &acc_type);
   1000         addr &= 0xffffff00;
   1001         addr |= (SOC_INFO(unit).port_l2p_mapping[port] - 1) & 0xf;
   1002         SOC_IF_ERROR_RETURN
   1003             (_soc_reg32_get(unit, block, acc_type, addr, &rval));
   1004         if (length_check) {
   1005             rval |= 0x20;  /* Set bit 5 to enable frame length check */
   1006         } else {
   1007             rval &= ~0x20; /* Clear bit 5 to disable frame length check */
   1008         }
   1009         rval |= 1 << 18;   /* Set PFC frame detected indicator */
   1010         SOC_IF_ERROR_RETURN
   1011             (_soc_reg32_set(unit, block, acc_type, addr, rval));
   1012     }
   1013 
   1014 #ifdef BCM_RCPU_SUPPORT
   1015     if ((uint32)port == soc_property_get(unit, spn_RCPU_PORT, -1)) {
   1016         BCM_IF_ERROR_RETURN
   1017             (bcm_esw_port_frame_max_set(unit, port, BCM_PORT_JUMBO_MAXSZ));
   1018     }
   1019 #endif /* BCM_RCPU_SUPPORT */
   1020 
   1021     /**********
   1022      * Outer TPID
   1023      * soc_feature_vlan_ctrl
   1024      */
   1025     BCM_IF_ERROR_RETURN
   1026         (bcm_esw_port_tpid_set(unit, port,
   1027                                _bcm_fb2_outer_tpid_default_get(unit)));
   1028 
   1029     /**********
   1030      * Profile Indexes
   1031      */
   1032     /* Initialize egress block profile pointer to invalid value */
   1033     BCM_IF_ERROR_RETURN
   1034         (bcmi_esw_port_egr_prof_ptr_set(unit, port, -1));
   1035 
   1036     /* Program the VLAN_PROTOCOL_DATA / FP_PORT_FIELD_SEL_INDEX
   1037        / PROTOCOL_PKT_INDEX pointers */
   1038     if (!IS_LB_PORT(unit, port) && !IS_TDM_PORT(unit, port)) {
   1039         if (soc_mem_index_max(unit, VLAN_PROTOCOLm) > 0) {
   1040             value = pinfo->vlan_prot_ptr /
   1041             soc_mem_index_count(unit, VLAN_PROTOCOLm);
   1042 
   1043             BCM_IF_ERROR_RETURN
   1044                 (_bcm_esw_port_tab_set(unit, port,
   1045                                        _BCM_CPU_TABS_ETHER,
   1046                                        VLAN_PROTOCOL_DATA_INDEXf,
   1047                                        value));
   1048         }
   1049 
   1050         BCM_IF_ERROR_RETURN
   1051             (_bcm_esw_port_tab_set(unit, port,
   1052                                    _BCM_CPU_TABS_ETHER,
   1053                                    FP_PORT_FIELD_SEL_INDEXf,
   1054                                    port));
   1055         BCM_IF_ERROR_RETURN
   1056             (_bcm_prot_pkt_ctrl_add(unit, 0, 0, &profile_index));
   1057         BCM_IF_ERROR_RETURN
   1058             (_bcm_esw_port_tab_set(unit, port,
   1059                                    _BCM_CPU_TABS_ETHER,
   1060                                    PROTOCOL_PKT_INDEXf,
   1061                                    profile_index));
   1062     }
   1063 
   1064     /********
   1065      * E2ECC
   1066      *
   1067      * Ports are enabled to send E2ECC messages by default.
   1068      * Disable E2ECC message TX here until congestion config
   1069      * set enables the port.
   1070      */
   1071     blk = SOC_PORT_BLOCK(unit, SOC_INFO(unit).port_l2p_mapping[port]);
   1072     bindex = SOC_PORT_BINDEX(unit, SOC_INFO(unit).port_l2p_mapping[port]);
   1073     blk_num = SOC_BLOCK_INFO(unit, blk).number;
   1074 
   1075     SOC_IF_ERROR_RETURN(READ_E2ECC_TX_ENABLE_BMPr(unit, blk_num, &rval));
   1076     tx_pbm = soc_reg_field_get(unit, E2ECC_TX_ENABLE_BMPr, rval,
   1077                                TX_ENABLE_BMPf);
   1078     tx_pbm &= ~(1 << bindex);
   1079     soc_reg_field_set(unit, E2ECC_TX_ENABLE_BMPr, &rval,
   1080                       TX_ENABLE_BMPf, tx_pbm);
   1081     SOC_IF_ERROR_RETURN(WRITE_E2ECC_TX_ENABLE_BMPr(unit, blk_num, rval));
   1082 
   1083     /**********
   1084      * EEE Config
   1085      * soc_feature_eee
   1086      */
   1087     if (!IS_LB_PORT(unit, port) && !IS_CPU_PORT (unit, port) &&
   1088         !IS_TDM_PORT(unit, port)) {
   1089         /* EEE standard compliance Work Around:
   1090          * Initialize the software state of native eee in MAC
   1091          */
   1092         BCM_IF_ERROR_RETURN
   1093             (bcmi_esw_port_eee_cfg_set(unit, port, 0));
   1094         /* Check if MAC supports Native EEE and set the value of
   1095          * eee_cfg by reading the EEE status from MAC*/
   1096         rv = bcmi_esw_portctrl_eee_enable_get(unit, port, &value);
   1097         if (rv != BCM_E_UNAVAIL) {
   1098             BCM_IF_ERROR_RETURN
   1099                 (bcmi_esw_port_eee_cfg_set(unit, port, value));
   1100         }
   1101     }
   1102 
   1103     /**********
   1104      * HIGIG
   1105      */
   1106     if (IS_HG_PORT(unit, port)) {
   1107         BCM_IF_ERROR_RETURN
   1108             (bcmi_esw_portctrl_higig_mode_set(unit, port, TRUE));
   1109 #ifdef BCM_HIGIG2_SUPPORT
   1110         /* soc_feature_higig2 */
   1111         BCM_IF_ERROR_RETURN
   1112             (bcmi_esw_portctrl_higig2_mode_set(unit, port, TRUE));
   1113         SOC_HG2_ENABLED_PORT_ADD(unit, port);
   1114 #endif /* BCM_HIGIG2_SUPPORT */
   1115     } else {  /* IEEE */
   1116         BCM_IF_ERROR_RETURN
   1117             (bcmi_esw_portctrl_higig_mode_set(unit, port, FALSE));
   1118 #ifdef BCM_HIGIG2_SUPPORT
   1119         /* soc_feature_higig2 */
   1120         BCM_IF_ERROR_RETURN
   1121             (bcmi_esw_portctrl_higig2_mode_set(unit, port, FALSE));
   1122         SOC_HG2_ENABLED_PORT_REMOVE(unit, port);
   1123 #endif /* BCM_HIGIG2_SUPPORT */
   1124     }
   1125 
   1126     /***********
   1127      * SW RX LOS configuration from PHY driver
   1128      */
   1129     if (IS_E_PORT(unit, port)) {
   1130         rv = bcm_esw_port_phy_control_get(unit, port,
   1131                                           BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS,
   1132                                           &rx_los);
   1133         if (BCM_SUCCESS(rv)) {
   1134             pinfo->rx_los = rx_los;
   1135         }
   1136     }
   1137 
   1138     /***********
   1139      * SW port enable status from HW
   1140      */
   1141     rv = bcm_esw_port_enable_get(unit, port, &enable);
   1142     if (BCM_SUCCESS(rv)) {
   1143         pinfo->enable = enable;
   1144     }
   1145 
   1146     return BCM_E_NONE;
   1147 }
   1148 
   1149 /*
   1150  * Function:
   1151  *      _bcm_td2_port_basic_attach
   1152  * Purpose:
   1153  *      Initialize the BCM PORT module portion (basic) for a given port
   1154  *      (bcm_esw_port_init) and allocates any memory needed by the BCM PORT
   1155  *      module.
   1156  * Parameters:
   1157  *      unit   - (IN) Unit number.
   1158  *      port   - (IN) Logical port, BCM format.
   1159  * Returns:
   1160  *      BCM_E_XXX
   1161  * Notes:
   1162  *      - Assumes main BCM PORT module initialization has been executed.
   1163  *      - Assumes port is valid.
   1164  *      - Caller must call other corresponding module routines
   1165  *        that need to initialize any port related information.
   1166  *      - Assumes this is NOT called during Warmboot.
   1167  */
   1168 STATIC int
   1169 _bcm_td2_port_basic_attach(int unit, bcm_port_t port)
   1170 {
   1171     int rv, rv1;
   1172 
   1173     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1174                 (BSL_META_U(unit,
   1175                             "BCM Attach Basic unit=%d port=%d(%s)\n"),
   1176                  unit, port, SOC_PORT_NAME(unit, port)));
   1177 
   1178     /* Allocate SW memory needed by PORT module */
   1179     BCM_IF_ERROR_RETURN(_bcm_td2p_port_software_alloc(unit, port));
   1180 
   1181     /* Initialize PORT module */
   1182     rv = _bcm_td2_port_basic_init(unit, port);
   1183 
   1184     /*
   1185      * Only free memory during failure.
   1186      * Memory is used by PORT module while port exists (attached).
   1187      */
   1188     if (BCM_FAILURE(rv)) {
   1189         rv1 = _bcm_td2p_port_software_free(unit, port);
   1190         if (BCM_FAILURE(rv1)) {
   1191             rv = rv1;
   1192         }
   1193     }
   1194 
   1195     return rv;
   1196 }
   1197 
   1198 
   1199 /*
   1200  * Function:
   1201  *      _bcm_td2_port_basic_detach
   1202  * Purpose:
   1203  *      Clear the BCM PORT module portion (basic) for a given port.
   1204  * Parameters:
   1205  *      unit   - (IN) Unit number.
   1206  *      port   - (IN) Logical port, BCM format.
   1207  * Returns:
   1208  *      BCM_E_XXX
   1209  * Notes:
   1210  *      - Assumes port is valid.
   1211  *      - Caller must call other corresponding module routines
   1212  *        where any port related information needs to be cleared.
   1213  */
   1214 STATIC int
   1215 _bcm_td2_port_basic_detach(int unit, bcm_port_t port)
   1216 {
   1217     _bcm_port_info_t *pinfo;
   1218     bcm_pbmp_t port_pbmp;
   1219     bcm_vlan_data_t vd;
   1220     int value;
   1221 
   1222     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1223                 (BSL_META_U(unit,
   1224                             "BCM Detach Basic unit=%d port=%d(%s)\n"),
   1225                  unit, port, SOC_PORT_NAME(unit, port)));
   1226 
   1227     /* Get PORT info structure pointer */
   1228     BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo));
   1229     if  (pinfo == NULL) {
   1230         LOG_ERROR(BSL_LS_BCM_PORT,
   1231                   (BSL_META_U(unit,
   1232                               "Unable to get PORT info data for "
   1233                               "unit=%d port=%d\n"),
   1234                    unit, port));
   1235         return BCM_E_INTERNAL;
   1236     }
   1237 
   1238     /**********
   1239      * COS_MAP Profile
   1240      */
   1241     if (SOC_IS_TRIDENT2PLUS(unit)) {
   1242         BCM_IF_ERROR_RETURN
   1243             (bcm_td2p_port_cosq_config_set(unit, port, FALSE));
   1244     }
   1245 
   1246     /**********
   1247      * HIGIG
   1248      */
   1249     BCM_IF_ERROR_RETURN
   1250         (bcmi_esw_portctrl_higig_mode_set(unit, port, FALSE));
   1251 #ifdef BCM_HIGIG2_SUPPORT
   1252     /* soc_feature_higig2 */
   1253     BCM_IF_ERROR_RETURN
   1254         (bcmi_esw_portctrl_higig2_mode_set(unit, port, FALSE));
   1255     SOC_HG2_ENABLED_PORT_REMOVE(unit, port);
   1256 #endif /* BCM_HIGIG2_SUPPORT */
   1257 
   1258     /*******
   1259      * EEE Config
   1260      */
   1261     if (!IS_LB_PORT(unit, port) && !IS_CPU_PORT (unit, port) &&
   1262         !IS_TDM_PORT(unit, port)) {
   1263         BCM_IF_ERROR_RETURN
   1264             (bcmi_esw_port_eee_cfg_set(unit, port, 0));
   1265     }
   1266 
   1267     /**********
   1268      * Profile Indexes
   1269      */
   1270     /* Program the VLAN_PROTOCOL_DATA / FP_PORT_FIELD_SEL_INDEX
   1271        / PROTOCOL_PKT_INDEX pointers */
   1272     if (!IS_LB_PORT(unit, port) && !IS_TDM_PORT(unit, port)) {
   1273         if (soc_mem_index_max(unit, VLAN_PROTOCOLm) > 0) {
   1274             BCM_IF_ERROR_RETURN
   1275                 (_bcm_esw_port_tab_set(unit, port,
   1276                                        _BCM_CPU_TABS_ETHER,
   1277                                        VLAN_PROTOCOL_DATA_INDEXf,
   1278                                        0));
   1279         }
   1280 
   1281         BCM_IF_ERROR_RETURN
   1282             (_bcm_esw_port_tab_set(unit, port,
   1283                                    _BCM_CPU_TABS_ETHER,
   1284                                    FP_PORT_FIELD_SEL_INDEXf,
   1285                                    0));
   1286         BCM_IF_ERROR_RETURN
   1287             (_bcm_esw_port_tab_get(unit, port,
   1288                                    PROTOCOL_PKT_INDEXf,
   1289                                    &value));
   1290         BCM_IF_ERROR_RETURN
   1291             (_bcm_prot_pkt_ctrl_delete(unit, value));
   1292     }
   1293     /* Initialize egress block profile pointer to invalid value */
   1294     BCM_IF_ERROR_RETURN
   1295         (bcmi_esw_port_egr_prof_ptr_set(unit, port, -1));
   1296 
   1297     /**********
   1298      * VLAN Action
   1299      * soc_feature_vlan_action
   1300      */
   1301     BCM_IF_ERROR_RETURN
   1302         (_bcm_trx_vlan_port_egress_default_action_delete(unit, port));
   1303 
   1304     if (!IS_LB_PORT(unit, port)) {
   1305         BCM_IF_ERROR_RETURN
   1306             (_bcm_port_vlan_prot_index_free(unit, pinfo->vlan_prot_ptr));
   1307     }
   1308 
   1309     /**********
   1310      * VLAN TPID reference count
   1311      */
   1312     BCM_IF_ERROR_RETURN
   1313         (_bcm_td2p_port_outer_tpid_ref_count_update(unit, port, 0));
   1314 
   1315     /**********
   1316      * Init port configuration tables
   1317      */
   1318     SOC_PBMP_CLEAR(port_pbmp);
   1319     BCM_PBMP_ASSIGN(port_pbmp, PBMP_ALL(unit));
   1320     SOC_PBMP_REMOVE(port_pbmp, PBMP_TDM(unit));
   1321 
   1322     vd.vlan_tag = BCM_VLAN_NONE;
   1323     BCM_PBMP_ASSIGN(vd.port_bitmap, port_pbmp);
   1324     BCM_PBMP_ASSIGN(vd.ut_port_bitmap, port_pbmp);
   1325     BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_CMIC(unit));
   1326 
   1327     BCM_IF_ERROR_RETURN
   1328         (mbcm_driver[unit]->mbcm_port_cfg_init(unit, port, &vd));
   1329 
   1330     BCM_IF_ERROR_RETURN(_bcm_td2p_port_bridge_port_init(unit, port, 0));
   1331 
   1332     BCM_IF_ERROR_RETURN(bcm_port_settings_init(unit, port));
   1333 
   1334     /**********
   1335      * Reset fields
   1336      * Deallocate SW memory
   1337      */
   1338     BCM_IF_ERROR_RETURN(_bcm_td2p_port_software_free(unit, port));
   1339 
   1340     return BCM_E_NONE;
   1341 }
   1342 
   1343 #ifdef INCLUDE_L3
   1344 
   1345 /*
   1346  * Function:
   1347  *      _bcm_td2p_vfi_membership_change
   1348  * Purpose:
   1349  *  Add/remove a port to/from the vlan_vfi_membership profile at the given
   1350  *  index. This is mainly used for adding a port to the default profile 1
   1351  *  for VFI membership. By default, the default porfile should contain all
   1352  *  port numbers.  Normally profile should be accessed through 
   1353  *  soc_profile_mem_xxx functions.
   1354  *  
   1355  * Returns:
   1356  *      BCM_E_XXX
   1357  */
   1358 
   1359 STATIC int
   1360 _bcm_td2p_vfi_membership_change(int unit, int profile_inx,bcm_port_t port, int add)
   1361 {
   1362     bcm_pbmp_t pbmp;
   1363     ing_vlan_vfi_membership_entry_t ing_vlan_vfi;
   1364     egr_vlan_vfi_membership_entry_t egr_vlan_vfi;
   1365 
   1366     BCM_PBMP_CLEAR(pbmp);
   1367     BCM_IF_ERROR_RETURN(READ_ING_VLAN_VFI_MEMBERSHIPm(unit, 
   1368           MEM_BLOCK_ANY, profile_inx, &ing_vlan_vfi));
   1369 
   1370     soc_mem_pbmp_field_get(unit, ING_VLAN_VFI_MEMBERSHIPm, &ing_vlan_vfi,
   1371             ING_PORT_BITMAPf, &pbmp);
   1372      if (add) {
   1373          BCM_PBMP_PORT_ADD(pbmp, port);
   1374      } else {
   1375          BCM_PBMP_PORT_REMOVE(pbmp, port);
   1376      }
   1377      soc_mem_pbmp_field_set(unit, ING_VLAN_VFI_MEMBERSHIPm, &ing_vlan_vfi,
   1378             ING_PORT_BITMAPf, &pbmp);
   1379      BCM_IF_ERROR_RETURN(WRITE_ING_VLAN_VFI_MEMBERSHIPm(unit, 
   1380                MEM_BLOCK_ALL, profile_inx, &ing_vlan_vfi));
   1381 
   1382     BCM_PBMP_CLEAR(pbmp);
   1383     BCM_IF_ERROR_RETURN(READ_EGR_VLAN_VFI_MEMBERSHIPm(unit, 
   1384           MEM_BLOCK_ANY, profile_inx, &egr_vlan_vfi));
   1385 
   1386     soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_MEMBERSHIPm, &egr_vlan_vfi,
   1387             PORT_BITMAPf, &pbmp);
   1388      if (add) {
   1389          BCM_PBMP_PORT_ADD(pbmp, port);
   1390      } else {
   1391          BCM_PBMP_PORT_REMOVE(pbmp, port);
   1392      }
   1393 
   1394      soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_MEMBERSHIPm, &egr_vlan_vfi,
   1395             PORT_BITMAPf, &pbmp);
   1396      BCM_IF_ERROR_RETURN(WRITE_EGR_VLAN_VFI_MEMBERSHIPm(unit,
   1397                MEM_BLOCK_ALL, profile_inx, &egr_vlan_vfi));
   1398      return BCM_E_NONE;
   1399 }
   1400 
   1401 /*
   1402  * Function:
   1403  *      _bcm_td2p_vfi_membership_port_attach
   1404  * Purpose:
   1405  *  Add a port to the default vfi membership profile
   1406  * 
   1407  * Returns:
   1408  *      BCM_E_XXX
   1409  */
   1410 
   1411 int
   1412 _bcm_td2p_vfi_membership_port_attach(int unit, bcm_port_t port)
   1413 {
   1414     BCM_IF_ERROR_RETURN(_bcm_td2p_vfi_membership_change(unit,1, port,TRUE));
   1415     return BCM_E_NONE;
   1416 }
   1417 
   1418 /*
   1419  * Function:
   1420  *      _bcm_td2p_vfi_membership_port_detach
   1421  * Purpose:
   1422  *  Remove a port from the default vfi membership profile
   1423  *
   1424  * Returns:
   1425  *      BCM_E_XXX
   1426  */
   1427 
   1428 int
   1429 _bcm_td2p_vfi_membership_port_detach(int unit, bcm_port_t port)
   1430 {
   1431     BCM_IF_ERROR_RETURN(_bcm_td2p_vfi_membership_change(unit,1, port,FALSE));
   1432     return BCM_E_NONE;
   1433 }
   1434 #endif /* INCLUDE_L3 */
   1435 
   1436 /*
   1437  * Function:
   1438  *      _bcm_td2p_port_attach
   1439  * Purpose:
   1440  *      Attach given port to the BCM layer and initialize it
   1441  *      to its default state.
   1442  * Parameters:
   1443  *      unit     - (IN) Unit number.
   1444  *      port     - (IN) Logical port, BCM format.
   1445  * Returns:
   1446  *      BCM_E_XXX
   1447  * Note:
   1448  *      - Assumes port is a valid BCM logical port.
   1449  *      - Assumes function is called when a new port is added into the system,
   1450  *        so it is not called during WarmBoot.
   1451  *      - Assumes BCM PORT module initialization routine has
   1452  *        been called.
   1453  *      - Assumes this is NOT called during Warmboot.
   1454  */
   1455 STATIC int
   1456 _bcm_td2p_port_attach(int unit, bcm_port_t port)
   1457 {
   1458     int rv = BCM_E_NONE;
   1459 #ifndef BCM_VLAN_NO_DEFAULT_ETHER
   1460     bcm_pbmp_t pbmp;
   1461 #endif
   1462 
   1463     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1464                 (BSL_META_U(unit,
   1465                             "BCM Attach unit=%d port=%d(%s)\n"),
   1466                  unit, port, SOC_PORT_NAME(unit, port)));
   1467 
   1468     /*
   1469      * Initialization of port logic in BCM modules
   1470      *
   1471      * There are order dependencies among the BCM modules.
   1472      * This follows the current order of execution in _bcm_modules_init()
   1473      * which is well established.
   1474      */
   1475 
   1476     /* PORT */
   1477     rv = _bcm_td2_port_basic_attach(unit, port);
   1478     if (BCM_FAILURE(rv)) {
   1479         LOG_ERROR(BSL_LS_BCM_PORT,
   1480                   (BSL_META_U(unit,
   1481                               "Unable to initialize basic port "
   1482                               "unit=%d port=%d rv=%d\n"),
   1483                    unit, port, rv));
   1484         return rv;
   1485     }
   1486 
   1487     /* STG */
   1488     rv = bcm_esw_vlan_stp_set(unit, BCM_VLAN_DEFAULT,
   1489                               port, BCM_STG_STP_FORWARD);
   1490     if (BCM_FAILURE(rv)) {
   1491         LOG_ERROR(BSL_LS_BCM_PORT,
   1492                   (BSL_META_U(unit,
   1493                               "Unable to set port STP for default VLAN "
   1494                               "unit=%d port=%d rv=%d\n"),
   1495                    unit, port, rv));
   1496         return rv;
   1497     }
   1498 
   1499     /* VLAN */
   1500 #ifndef BCM_VLAN_NO_DEFAULT_ETHER
   1501     /* Add ports to default VLAN only if vlan policy allows it */
   1502     BCM_PBMP_CLEAR(pbmp);
   1503     BCM_PBMP_PORT_ADD(pbmp, port);
   1504     rv = bcm_esw_vlan_port_add(unit, BCM_VLAN_DEFAULT, pbmp, pbmp);
   1505     if (BCM_FAILURE(rv)) {
   1506         LOG_ERROR(BSL_LS_BCM_PORT,
   1507                   (BSL_META_U(unit,
   1508                               "Unable to add port to default VLAN "
   1509                               "unit=%d port=%d rv=%d\n"),
   1510                    unit, port, rv));
   1511         return rv;
   1512     }
   1513 #endif
   1514 
   1515 
   1516     /* TRUNK */
   1517     rv = _bcm_td2p_port_trunk_port_attach(unit, port);
   1518     if (BCM_FAILURE(rv)) {
   1519         LOG_ERROR(BSL_LS_BCM_PORT,
   1520                   (BSL_META_U(unit,
   1521                               "Unable to initialize port "
   1522                               "Source Trunk Map table "
   1523                               "unit=%d port=%d rv=%d\n"),
   1524                    unit, port, rv));
   1525         return rv;
   1526     }
   1527 
   1528     /* LINKSCAN */
   1529     rv = _soc_linkscan_hw_port_init(unit, port);
   1530     if (SOC_FAILURE(rv)) {
   1531         LOG_ERROR(BSL_LS_BCM_PORT,
   1532                   (BSL_META_U(unit,
   1533                               "Unable to initialize port Linkscan "
   1534                               "unit=%d port=%d rv=%d\n"),
   1535                    unit, port, rv));
   1536         return rv;
   1537     }
   1538 
   1539     /* STACK */
   1540     rv = _bcm_td2p_port_stack_port_attach(unit, port);
   1541     if (BCM_FAILURE(rv)) {
   1542         LOG_ERROR(BSL_LS_BCM_PORT,
   1543                   (BSL_META_U(unit,
   1544                               "Unable to initialize port Stack "
   1545                               "unit=%d port=%d rv=%d\n"),
   1546                    unit, port, rv));
   1547         return rv;
   1548     }
   1549 
   1550     /* STAT */
   1551     rv = bcmi_td2p_stat_port_attach(unit, port);
   1552     if (BCM_FAILURE(rv)) {
   1553         LOG_ERROR(BSL_LS_BCM_PORT,
   1554                   (BSL_META_U(unit,
   1555                               "Unable to initialize port Stat "
   1556                               "unit=%d port=%d rv=%d\n"),
   1557                    unit, port, rv));
   1558         return rv;
   1559     }
   1560 
   1561     /* RATE */
   1562     rv = _bcm_td2p_port_rate_port_attach(unit, port);
   1563     if (BCM_FAILURE(rv)) {
   1564         LOG_ERROR(BSL_LS_BCM_PORT,
   1565                   (BSL_META_U(unit,
   1566                               "Unable to initialize port Rate "
   1567                               "unit=%d port=%d rv=%d\n"),
   1568                    unit, port, rv));
   1569         return rv;
   1570     }
   1571 
   1572 #ifdef BCM_FIELD_SUPPORT
   1573     /* FIELD */
   1574     rv = bcm_esw_port_control_set(unit, port, bcmPortControlFilterLookup, 1);
   1575     if (BCM_SUCCESS(rv)) {
   1576         rv = bcm_esw_port_control_set(unit, port,
   1577                                       bcmPortControlFilterIngress, 1);
   1578     }
   1579     if (BCM_SUCCESS(rv)) {
   1580         rv = bcm_esw_port_control_set(unit, port,
   1581                                       bcmPortControlFilterEgress, 1);
   1582     }
   1583     if (BCM_FAILURE(rv)) {
   1584         LOG_ERROR(BSL_LS_BCM_PORT,
   1585                   (BSL_META_U(unit,
   1586                               "Unable to initialize port Field "
   1587                               "unit=%d port=%d rv=%d\n"),
   1588                    unit, port, rv));
   1589         return rv;
   1590     }
   1591 #if defined(BCM_TRX_SUPPORT)
   1592     rv = _bcm_field_flex_port_attach(unit, port);
   1593     if (BCM_FAILURE(rv)) {
   1594         LOG_ERROR(BSL_LS_BCM_PORT,
   1595                   (BSL_META_U(unit,
   1596                               "Unable to attach port in Field Port Based Groups"
   1597                               "unit=%d port=%d rv=%d\n"),
   1598                    unit, port, rv));
   1599         return rv;
   1600     }
   1601 #endif
   1602 #endif /* BCM_FIELD_SUPPORT */
   1603 
   1604     /* MIRROR */
   1605     rv = bcmi_esw_mirror_port_attach(unit, port);
   1606     if (BCM_FAILURE(rv)) {
   1607         LOG_ERROR(BSL_LS_BCM_PORT,
   1608                   (BSL_META_U(unit,
   1609                               "Unable to initialize port Mirror "
   1610                               "unit=%d port=%d rv=%d\n"),
   1611                    unit, port, rv));
   1612         return rv;
   1613     }
   1614 
   1615 #ifdef INCLUDE_L3
   1616     /* L3 */
   1617     if (!IS_ST_PORT(unit, port)) {
   1618         rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP4, 1);
   1619         if (BCM_SUCCESS(rv)) {
   1620             rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP6, 1);
   1621         }
   1622         if (BCM_FAILURE(rv)) {
   1623             LOG_ERROR(BSL_LS_BCM_PORT,
   1624                       (BSL_META_U(unit,
   1625                                   "Unable to enable port L3 "
   1626                                   "unit=%d port=%d rv=%d\n"),
   1627                        unit, port, rv));
   1628             return rv;
   1629         }
   1630     }
   1631 
   1632     /* IPMC */
   1633     rv = _bcm_td2p_port_ipmc_port_attach(unit, port);
   1634     if (BCM_FAILURE(rv)) {
   1635         LOG_ERROR(BSL_LS_BCM_PORT,
   1636                   (BSL_META_U(unit,
   1637                               "Unable to enable port IPMC "
   1638                               "unit=%d port=%d rv=%d\n"),
   1639                    unit, port, rv));
   1640         return rv;
   1641     }
   1642 
   1643 #ifdef BCM_MPLS_SUPPORT
   1644     /* MPLS */
   1645     if (!IS_ST_PORT(unit, port)) {
   1646         rv = bcm_esw_port_control_set(unit, port, bcmPortControlMpls, 1);
   1647         if (BCM_FAILURE(rv)) {
   1648             LOG_ERROR(BSL_LS_BCM_PORT,
   1649                       (BSL_META_U(unit,
   1650                                   "Unable to enable port MPLS "
   1651                                   "unit=%d port=%d rv=%d\n"),
   1652                        unit, port, rv));
   1653             return rv;
   1654         }
   1655     }
   1656 #endif /* BCM_MPLS_SUPPORT */
   1657 
   1658     /* MIM */
   1659     if (!IS_ST_PORT(unit, port) && soc_feature(unit, soc_feature_mim)) {
   1660         rv = bcm_esw_port_control_set(unit, port, bcmPortControlMacInMac, 1);
   1661         if (BCM_FAILURE(rv)) {
   1662             LOG_ERROR(BSL_LS_BCM_PORT,
   1663                       (BSL_META_U(unit,
   1664                                   "Unable to enable port MIM "
   1665                                   "unit=%d port=%d rv=%d\n"),
   1666                        unit, port, rv));
   1667             return rv;
   1668         }
   1669     }
   1670 
   1671     /* VFI */
   1672     rv = _bcm_td2p_vfi_membership_port_attach(unit, port);
   1673     if (BCM_FAILURE(rv)) {
   1674         LOG_ERROR(BSL_LS_BCM_PORT,
   1675                   (BSL_META_U(unit,
   1676                               "Unable to add port to default VFI membership "
   1677                               "unit=%d port=%d rv=%d\n"),
   1678                    unit, port, rv));
   1679         return rv;
   1680     }
   1681 #endif /* INCLUDE_L3 */
   1682 
   1683     /* PFC */
   1684     rv = bcm_esw_port_control_set(unit, port, bcmPortControlPFCPassFrames, 0);
   1685     if (BCM_FAILURE(rv)) {
   1686         LOG_ERROR(BSL_LS_BCM_PORT,
   1687                   (BSL_META_U(unit,
   1688                               "Unable to initialize PFC settings "
   1689                               "unit=%d port=%d rv=%d\n"),
   1690                    unit, port, rv));
   1691         return rv;
   1692     }
   1693 
   1694     if (SOC_IS_TRIDENT2PLUS(unit)) {
   1695         rv = bcm_td2_cosq_default_llfc_profile_attach(unit, port);
   1696         if (BCM_FAILURE(rv)) {
   1697             LOG_ERROR(BSL_LS_BCM_PORT,
   1698                       (BSL_META_U(unit,
   1699                                   "Unable to add default entries for PRIO2COS_PROFILE"
   1700                                   "register profile unit=%d port=%d rv=%d\n"),
   1701                        unit, port, rv));
   1702             return rv;
   1703         }
   1704     }
   1705 
   1706     return BCM_E_NONE;
   1707 }
   1708 
   1709 
   1710 /*
   1711  * Function:
   1712  *      _bcm_td2p_port_detach
   1713  * Purpose:
   1714  *      Detach given port from the BCM layer and clear any data
   1715  *      that is normally configured when a port is initialized.
   1716  * Parameters:
   1717  *      unit     - (IN) Unit number.
   1718  *      port     - (IN) Logical port, BCM format.
   1719  * Returns:
   1720  *      BCM_E_XXX
   1721  * Note:
   1722  *      - Assumes port is a valid BCM logical port.
   1723  *      - Assumes this is NOT called during Warmboot.
   1724  */
   1725 STATIC int
   1726 _bcm_td2p_port_detach(int unit, bcm_port_t port)
   1727 {
   1728     int rv = BCM_E_NONE;
   1729     bcm_pbmp_t pbmp;
   1730 
   1731     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1732                 (BSL_META_U(unit,
   1733                             "BCM Detach unit=%d port=%d(%s)\n"),
   1734                  unit, port, SOC_PORT_NAME(unit, port)));
   1735 
   1736     /*
   1737      * Clear of port logic in BCM modules
   1738      *
   1739      * For the most part, this follows the reverse logic
   1740      * of its counter part function _bcm_td2p_port_attach().
   1741      */
   1742 
   1743 #ifdef INCLUDE_L3
   1744     /* MIM */
   1745     if (!IS_ST_PORT(unit, port) && soc_feature(unit, soc_feature_mim)) {
   1746         rv = bcm_esw_port_control_set(unit, port, bcmPortControlMacInMac, 0);
   1747         if (BCM_FAILURE(rv)) {
   1748             LOG_ERROR(BSL_LS_BCM_PORT,
   1749                       (BSL_META_U(unit,
   1750                                   "Unable to clear port MIM "
   1751                                   "unit=%d port=%d rv=%d\n"),
   1752                        unit, port, rv));
   1753             return rv;
   1754         }
   1755     }
   1756 
   1757 #ifdef BCM_MPLS_SUPPORT
   1758     /* MPLS */
   1759     if (!IS_ST_PORT(unit, port)) {
   1760         rv = bcm_esw_port_control_set(unit, port, bcmPortControlMpls, 0);
   1761         if (BCM_FAILURE(rv)) {
   1762             LOG_ERROR(BSL_LS_BCM_PORT,
   1763                       (BSL_META_U(unit,
   1764                                   "Unable to clear port MPLS "
   1765                                   "unit=%d port=%d rv=%d\n"),
   1766                        unit, port, rv));
   1767             return rv;
   1768         }
   1769     }
   1770 #endif /* BCM_MPLS_SUPPORT */
   1771 
   1772     /* IPMC */
   1773     rv = _bcm_td2p_port_ipmc_port_detach(unit, port);
   1774     if (BCM_FAILURE(rv)) {
   1775         LOG_ERROR(BSL_LS_BCM_PORT,
   1776                   (BSL_META_U(unit,
   1777                               "Unable to clear port IPMC "
   1778                               "unit=%d port=%d rv=%d\n"),
   1779                    unit, port, rv));
   1780         return rv;
   1781     }
   1782 
   1783     /* L3 */
   1784     if (!IS_ST_PORT(unit, port)) {
   1785         rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP4, 0);
   1786         if (BCM_SUCCESS(rv)) {
   1787             rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP6, 0);
   1788         }
   1789         if (BCM_FAILURE(rv)) {
   1790             LOG_ERROR(BSL_LS_BCM_PORT,
   1791                       (BSL_META_U(unit,
   1792                                   "Unable to clear port L3 "
   1793                                   "unit=%d port=%d rv=%d\n"),
   1794                        unit, port, rv));
   1795             return rv;
   1796         }
   1797     }
   1798 #endif /* INCLUDE_L3 */
   1799 
   1800     /* MIRROR */
   1801     rv = bcmi_esw_mirror_port_detach(unit, port);
   1802     if (BCM_FAILURE(rv)) {
   1803         LOG_ERROR(BSL_LS_BCM_PORT,
   1804                   (BSL_META_U(unit,
   1805                               "Unable to clear port Mirror "
   1806                               "unit=%d port=%d rv=%d\n"),
   1807                    unit, port, rv));
   1808         return rv;
   1809     }
   1810 
   1811 #ifdef BCM_FIELD_SUPPORT
   1812     /* FIELD */
   1813     rv = bcm_esw_port_control_set(unit, port, bcmPortControlFilterLookup, 0);
   1814     if (BCM_SUCCESS(rv)) {
   1815         rv = bcm_esw_port_control_set(unit, port,
   1816                                       bcmPortControlFilterIngress, 0);
   1817     }
   1818     if (BCM_SUCCESS(rv)) {
   1819         rv = bcm_esw_port_control_set(unit, port,
   1820                                       bcmPortControlFilterEgress, 0);
   1821     }
   1822     if (BCM_FAILURE(rv)) {
   1823         LOG_ERROR(BSL_LS_BCM_PORT,
   1824                   (BSL_META_U(unit,
   1825                               "Unable clear port Field "
   1826                               "unit=%d port=%d rv=%d\n"),
   1827                    unit, port, rv));
   1828         return rv;
   1829     }
   1830 #if defined(BCM_TRX_SUPPORT)
   1831     rv = _bcm_field_flex_port_detach(unit, port);
   1832     if (BCM_FAILURE(rv)) {
   1833         LOG_ERROR(BSL_LS_BCM_PORT,
   1834                   (BSL_META_U(unit,
   1835                               "Unable to clear port in Field Port Based Groups"
   1836                               "unit=%d port=%d rv=%d\n"),
   1837                    unit, port, rv));
   1838         return rv;
   1839     }
   1840 #endif
   1841 #endif /* BCM_FIELD_SUPPORT */
   1842 
   1843     /* RATE */
   1844     rv = _bcm_td2p_port_rate_port_detach(unit, port);
   1845     if (BCM_FAILURE(rv)) {
   1846         LOG_ERROR(BSL_LS_BCM_PORT,
   1847                   (BSL_META_U(unit,
   1848                               "Unable to clear port Rate "
   1849                               "unit=%d port=%d rv=%d\n"),
   1850                    unit, port, rv));
   1851         return rv;
   1852     }
   1853 
   1854     /* STAT*/
   1855     rv = bcmi_td2p_stat_port_detach(unit, port);
   1856     if (BCM_FAILURE(rv)) {
   1857         LOG_ERROR(BSL_LS_BCM_PORT,
   1858                   (BSL_META_U(unit,
   1859                               "Unable to clear port Stat "
   1860                               "unit=%d port=%d rv=%d\n"),
   1861                    unit, port, rv));
   1862         return rv;
   1863     }
   1864 
   1865     /* STACK */
   1866     rv = _bcm_td2p_port_stack_port_detach(unit, port);
   1867     if (BCM_FAILURE(rv)) {
   1868         LOG_ERROR(BSL_LS_BCM_PORT,
   1869                   (BSL_META_U(unit,
   1870                               "Unable to clear port Stack "
   1871                               "unit=%d port=%d rv=%d\n"),
   1872                    unit, port, rv));
   1873         return rv;
   1874     }
   1875 
   1876     /* TRUNK */
   1877     rv = _bcm_td2p_port_trunk_port_detach(unit, port);
   1878     if (BCM_FAILURE(rv)) {
   1879         LOG_ERROR(BSL_LS_BCM_PORT,
   1880                   (BSL_META_U(unit,
   1881                               "Unable to clear port Source Trunk Map table "
   1882                               "unit=%d port=%d rv=%d\n"),
   1883                    unit, port, rv));
   1884         return rv;
   1885     }
   1886 
   1887     /* VLAN */
   1888     BCM_PBMP_CLEAR(pbmp);
   1889     BCM_PBMP_PORT_ADD(pbmp, port);
   1890     rv = bcm_esw_vlan_port_remove(unit, BCM_VLAN_DEFAULT, pbmp);
   1891     if (BCM_FAILURE(rv)) {
   1892         LOG_ERROR(BSL_LS_BCM_PORT,
   1893                   (BSL_META_U(unit,
   1894                               "Unable to remove port from default VLAN "
   1895                               "unit=%d port=%d rv=%d\n"),
   1896                    unit, port, rv));
   1897         return rv;
   1898     }
   1899 
   1900     /* STG */
   1901     rv = bcm_esw_vlan_stp_set(unit, BCM_VLAN_DEFAULT,
   1902                               port, BCM_STG_STP_DISABLE);
   1903     if (BCM_FAILURE(rv)) {
   1904         LOG_ERROR(BSL_LS_BCM_PORT,
   1905                   (BSL_META_U(unit,
   1906                               "Unable to clear port STP for default VLAN "
   1907                               "unit=%d port=%d rv=%d\n"),
   1908                    unit, port, rv));
   1909         return rv;
   1910     }
   1911 
   1912     /* PORT */
   1913     rv = _bcm_td2_port_basic_detach(unit, port);
   1914     if (BCM_FAILURE(rv)) {
   1915         LOG_ERROR(BSL_LS_BCM_PORT,
   1916                   (BSL_META_U(unit,
   1917                               "Unable to detach basic port "
   1918                               "unit=%d port=%d rv=%d\n"),
   1919                    unit, port, rv));
   1920         return rv;
   1921     }
   1922 
   1923 #ifdef INCLUDE_L3
   1924     /* VFI */
   1925     rv = _bcm_td2p_vfi_membership_port_detach(unit, port);
   1926     if (BCM_FAILURE(rv)) {
   1927         LOG_ERROR(BSL_LS_BCM_PORT,
   1928                   (BSL_META_U(unit,
   1929                               "Unable to clear port in default VFI membership "
   1930                               "unit=%d port=%d rv=%d\n"),
   1931                    unit, port, rv));
   1932         return rv;
   1933     }
   1934 #endif /* INCLUDE_L3 */
   1935     /* PFC */
   1936     if (SOC_IS_TRIDENT2PLUS(unit)) {
   1937         rv = bcm_td2_cosq_llfc_profile_detach(unit, port);
   1938         if (BCM_FAILURE(rv)) {
   1939             LOG_ERROR(BSL_LS_BCM_PORT,
   1940                       (BSL_META_U(unit,
   1941                                   "Unable to delete default entries for PRIO2COS_PROFILE"
   1942                                   "register profile unit=%d port=%d rv=%d\n"),
   1943                        unit, port, rv));
   1944             return rv;
   1945         }
   1946     }
   1947 
   1948     return BCM_E_NONE;
   1949 }
   1950 
   1951 /*
   1952  * Function:
   1953  *         bcm_esw_td2p_flexport_port_attach
   1954  * Purpose:
   1955  *         External wrapper for _bcm_td2p_port_attach
   1956  */
   1957 int
   1958 bcm_esw_td2p_flexport_port_attach(int unit, bcm_port_t port)
   1959 {
   1960     return _bcm_td2p_port_attach(unit, port);
   1961 }
   1962 
   1963 
   1964 /*
   1965  * Function:
   1966  *         bcm_esw_td2p_flexport_port_detach
   1967  * Purpose:
   1968  *         External wrapper for _bcm_td2p_port_detach
   1969  */
   1970 int
   1971 bcm_esw_td2p_flexport_port_detach(int unit, bcm_port_t port)
   1972 {
   1973     return _bcm_td2p_port_detach(unit, port);
   1974 }
   1975 
   1976 
   1977 /*
   1978  * Function:
   1979  *      _bcm_td2p_port_resource_attach
   1980  * Purpose:
   1981  *      Attach ports to the BCM layer and initialize them
   1982  *      to the default state.
   1983  *
   1984  * Parameters:
   1985  *      unit           - (IN) Unit number.
   1986  *      nport          - (IN) Number of elements in array resource.
   1987  *      resource       - (IN) Port Resource FlexPort configuration.
   1988  * Returns:
   1989  *      BCM_E_XXX
   1990  * Notes:
   1991  *      - Assumes caller have detached any ports that will be attached
   1992  *        in this routine.
   1993  *      - Assumes this is NOT called during Warmboot.
   1994  *      - Set current MY_MODID for all newly attached ports.
   1995  */
   1996 STATIC int
   1997 _bcm_td2p_port_resource_attach(int unit,
   1998                                int nport,
   1999                                bcm_td2p_port_resource_t *resource)
   2000 {
   2001     int rv = BCM_E_NONE;
   2002     bcm_td2p_port_resource_t *pr;
   2003     int i, my_modid;
   2004 
   2005     LOG_VERBOSE(BSL_LS_BCM_PORT,
   2006                 (BSL_META_U(unit,
   2007                             "--- BCM Attach ---\n")));
   2008 
   2009     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2010 
   2011     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2012         if (pr->flags & SOC_PORT_RESOURCE_ATTACH) {
   2013             rv = _bcm_td2p_port_attach(unit, pr->port);
   2014             if (BCM_FAILURE(rv)) {
   2015                 LOG_ERROR(BSL_LS_BCM_PORT,
   2016                           (BSL_META_U(unit,
   2017                                       "Error: Unable to attach BCM port "
   2018                                       "unit=%d port=%d rv=%d\n"),
   2019                            unit, pr->port, rv));
   2020                 return rv;
   2021             }
   2022         }
   2023     }
   2024 
   2025     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_set(unit, my_modid));
   2026 
   2027     return BCM_E_NONE;
   2028 }
   2029 
   2030 
   2031 /*
   2032  * Function:
   2033  *      _bcm_td2p_port_resource_detach
   2034  * Purpose:
   2035  *      Detach ports from the BCM layer.
   2036  *
   2037  *      It clears any HW or SW state that was programmed
   2038  *      by the SDK initialization routines.  It does NOT clear
   2039  *      references to logical ports that have been programmed by the
   2040  *      application.  Applications are responsible for doing that.
   2041  *
   2042  * Parameters:
   2043  *      unit           - (IN) Unit number.
   2044  *      nport          - (IN) Number of elements in array resource.
   2045  *      resource       - (IN) Port Resource FlexPort configuration.
   2046  * Returns:
   2047  *      BCM_E_XXX
   2048  * Notes:
   2049  *      - Assumes this is NOT called during Warmboot.
   2050  */
   2051 STATIC int
   2052 _bcm_td2p_port_resource_detach(int unit,
   2053                                int nport,
   2054                                bcm_td2p_port_resource_t *resource)
   2055 {
   2056     int rv = BCM_E_NONE;
   2057     bcm_td2p_port_resource_t *pr;
   2058     int i;
   2059 
   2060     LOG_VERBOSE(BSL_LS_BCM_PORT,
   2061                 (BSL_META_U(unit,
   2062                             "--- BCM Detach ---\n")));
   2063 
   2064     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2065         if (pr->flags & SOC_PORT_RESOURCE_DETACH) {
   2066             rv = _bcm_td2p_port_detach(unit, pr->port);
   2067             if (BCM_FAILURE(rv)) {
   2068                 LOG_ERROR(BSL_LS_BCM_PORT,
   2069                           (BSL_META_U(unit,
   2070                                       "Error: Unable to detach BCM port "
   2071                                       "unit=%d port=%d rv=%d\n"),
   2072                            unit, pr->port, rv));
   2073                 return rv;
   2074             }
   2075         }
   2076     }
   2077 
   2078     return BCM_E_NONE;
   2079 }
   2080 
   2081 
   2082 /*
   2083  * Function:
   2084  *      _bcm_td2p_port_resource_resolve
   2085  * Purpose:
   2086  *      Convert logical port number GPORT to BCM local port format and
   2087  *      validate port numbers:
   2088  *      - Logical and physical port numbers are within the valid range.
   2089  *      - Ports must not be CPU or Loopback ports.
   2090  * Parameters:
   2091  *      unit     - (IN) Unit number.
   2092  *      nport    - (IN) Number of elements in array resource.
   2093  *      resource - (IN/OUT) Port resource configuration array.
   2094  * Returns:
   2095  *      BCM_E_XXX
   2096  * Note:
   2097  *      - Assumes caller has lock.
   2098  *      - Resource is not NULL.
   2099  */
   2100 STATIC int
   2101 _bcm_td2p_port_resource_resolve(int unit, 
   2102                                 int nport,
   2103                                 bcm_td2p_port_resource_t *resource)
   2104 {
   2105     int i;
   2106     bcm_td2p_port_resource_t *pr;
   2107     soc_info_t *si = &SOC_INFO(unit);
   2108 
   2109     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2110 
   2111         /* Check that logical port number is addressable and convert */
   2112         BCM_IF_ERROR_RETURN
   2113             (bcmi_xgs5_port_addressable_local_get(unit,
   2114                                                   pr->port,
   2115                                                   &pr->port));
   2116 
   2117         /*
   2118          * Check that logical port number is valid for TD2+
   2119          * (above check is generic)
   2120          */
   2121         SOC_IF_ERROR_RETURN
   2122             (soc_td2p_port_addressable(unit, pr->port));
   2123 
   2124         /* Check that physical port is within the valid range */
   2125         if (pr->physical_port != -1) {
   2126             SOC_IF_ERROR_RETURN
   2127                 (soc_td2p_phy_port_addressable(unit, pr->physical_port));
   2128         }
   2129 
   2130         /* Check that ports, logical and physical, are not a management port */
   2131         if ((si->port_l2p_mapping[pr->port] == TD2P_PHY_PORT_CPU) ||
   2132             (si->port_l2p_mapping[pr->port] == TD2P_PHY_PORT_LB) ||
   2133             (pr->physical_port == TD2P_PHY_PORT_CPU) ||
   2134             (pr->physical_port == TD2P_PHY_PORT_LB) ||
   2135             SOC_PBMP_MEMBER(si->management_pbm, pr->port)) {
   2136             LOG_ERROR(BSL_LS_BCM_PORT,
   2137                       (BSL_META_U(unit,
   2138                                   "Port cannot be CPU, LB, or management "
   2139                                   "port "
   2140                                   "unit=%d port=%d\n"),
   2141                        unit, pr->port));
   2142             return BCM_E_PORT;
   2143         }
   2144     }
   2145 
   2146     return BCM_E_NONE;
   2147 }
   2148 
   2149 
   2150 /*
   2151  * Function:
   2152  *      _bcm_td2p_port_resource_input_validate
   2153  * Purpose:
   2154  *      Validate function input requirements.
   2155  *
   2156  *      This routine checks for function semantics and guidelines
   2157  *      from the API perspective:
   2158  *      - Check the order of elements in array, 'delete' operations must
   2159  *        be placed first in array.
   2160  *      - Ports must not be CPU or Loopback ports.
   2161  *      - Ports must be disabled.
   2162  *      - Ports linkscan mode must be NONE.
   2163  * Parameters:
   2164  *      unit     - (IN) Unit number.
   2165  *      nport    - (IN) Number of elements in array resource.
   2166  *      resource - (IN/OUT) Port resource configuration array.
   2167  * Returns:
   2168  *      BCM_E_XXX
   2169  * Note:
   2170  *      - Assumes caller has lock.
   2171  *      - Resource is not NULL.
   2172  *      - Assumes port values has been validated.
   2173  */
   2174 STATIC int
   2175 _bcm_td2p_port_resource_input_validate(int unit, 
   2176                                        int nport,
   2177                                        bcm_td2p_port_resource_t *resource)
   2178 {
   2179     int i;
   2180     bcm_td2p_port_resource_t *pr;
   2181     int delete = 1;
   2182     int enable;
   2183     soc_info_t *si = &SOC_INFO(unit);
   2184 
   2185 
   2186     /* Check array order and port state disable */
   2187     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2188 
   2189         /* Skip check for speed change */
   2190         if (pr->flags & SOC_PORT_RESOURCE_SPEED) {
   2191             continue;
   2192         }
   2193 
   2194         /* Check that delete operations are first */
   2195         if (pr->physical_port != -1) {  /* First non-delete found */
   2196             delete = 0;
   2197         } else if ((pr->physical_port == -1) && !delete) {
   2198             LOG_ERROR(BSL_LS_BCM_PORT,
   2199                       (BSL_META_U(unit,
   2200                                   "Delete operations must be "
   2201                                   "first in array\n")));
   2202             return BCM_E_CONFIG;
   2203         }
   2204 
   2205         if ((pr->encap != BCM_PORT_ENCAP_IEEE) &&
   2206             (pr->encap != BCM_PORT_ENCAP_HIGIG2)) {
   2207             LOG_ERROR(BSL_LS_BCM_PORT,
   2208                       (BSL_META_U(unit,
   2209                                   "Encap modes can only be IEEE or HIGIG2 "
   2210                                   "unit=%d port=%d\n"),
   2211                        unit, pr->port));
   2212             return BCM_E_CONFIG;
   2213         }
   2214 
   2215         /* Skip ports that are not currently defined */
   2216         if (si->port_l2p_mapping[pr->port] == -1) {
   2217             continue;
   2218         }
   2219 
   2220         /* Check that ports are disabled */
   2221         BCM_IF_ERROR_RETURN
   2222             (bcm_esw_port_enable_get(unit, pr->port, &enable));
   2223         if (enable) {
   2224             LOG_ERROR(BSL_LS_BCM_PORT,
   2225                       (BSL_META_U(unit,
   2226                                   "Port %d needs to be disabled\n"),
   2227                        pr->port));
   2228             return BCM_E_BUSY;
   2229         }
   2230 
   2231         /*
   2232          * Check that ports to be 'detached' do not
   2233          * have linkscan mode set.  See _bcm_td2p_port_resource_pmap_get().
   2234          */
   2235         if (pr->flags & SOC_PORT_RESOURCE_DETACH) {
   2236             if (bcm_esw_linkscan_enable_port_get(unit, pr->port) !=
   2237                 BCM_E_DISABLED) {
   2238                 LOG_ERROR(BSL_LS_BCM_PORT,
   2239                           (BSL_META_U(unit,
   2240                                       "Linkscan mode needs to be "
   2241                                       "disabled on ports to be detached, "
   2242                                       "port=%d\n"),
   2243                            pr->port));
   2244                 return BCM_E_BUSY;
   2245             }
   2246         }
   2247     }
   2248 
   2249     return BCM_E_NONE;
   2250 }
   2251 
   2252 
   2253 /*
   2254  * Function:
   2255  *      _bcm_td2p_port_resource_pmap_get
   2256  * Purpose:
   2257  *      Determine the type of port mapping changes, if any,
   2258  *      as a result of the FlexPort operation.  In addition, it
   2259  *      determines whether the port needs to go through the attach
   2260  *      and/or detach process.
   2261  *
   2262  *      All ports that are being flexed will be detached except for those
   2263  *      that will become inactive (this is only for legacy mode).
   2264  *      All ports that are active after flexed are always attached (this is
   2265  *      for new and legacy mode).
   2266  *
   2267  *      When a port is 'marked' as 'delete' (physical port is -1),
   2268  *      this does not mean the logical port will be destroyed.  Depending
   2269  *      on the rest of the information in the array, the port mapping
   2270  *      may be the same, remapped, or it may no longer exist after FlexPort.
   2271  *
   2272  *      Likewise, when a valid port mapping is given, the port may
   2273  *      not be necessarily new.
   2274  *
   2275  *      Example:
   2276  *
   2277  *      Main FlexPort array ('resource') (application input)
   2278  *               L1 --> -1 (current mapped to P1), mapping is SAME
   2279  *               L2 --> -1 (current mapped to P2), mapping is REMAP
   2280  *               L3 --> -1 (current mapped to P3), mapping is DESTROY
   2281  *               L1 --> P1                       , mapping is SAME
   2282  *               L2 --> P5                       , mapping is REMAP
   2283  *               L9 --> P9                       , mapping is NEW
   2284  *
   2285  * Parameters:
   2286  *      unit           - (IN) Unit number.
   2287  *      nport          - (IN) Number of elements in array resource.
   2288  *      resource       - (IN/OUT) Port Resource FlexPort configuration.
   2289  * Returns:
   2290  *      SOC_E_XXX
   2291  * Notes:
   2292  *      Assumes all 'delete' elements are first in array.
   2293  */
   2294 STATIC int
   2295 _bcm_td2p_port_resource_pmap_get(int unit, 
   2296                                  int nport, bcm_td2p_port_resource_t *resource)
   2297 {
   2298     int i;
   2299     int j;
   2300     bcm_td2p_port_resource_t *pr;
   2301     soc_info_t *si = &SOC_INFO(unit);
   2302 
   2303     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2304 
   2305         if (pr->physical_port == -1) {
   2306             /*
   2307              * Find if port is given in later elements.
   2308              * If so, check if port is remapped.
   2309              * If not found, port is marked to be destroyed
   2310              * (port will no longer exist after FlexPort)
   2311              *
   2312              * Note that all the 'delete' ports must always first
   2313              * in array.
   2314              */
   2315             for (j = i; j < nport; j++) {
   2316                 if (resource[j].physical_port == -1) {
   2317                     continue;
   2318                 }
   2319                 if (resource[j].port == pr->port) {  /* Found */
   2320                     /* Check if mapping is same */
   2321                     if (resource[j].physical_port !=
   2322                         si->port_l2p_mapping[pr->port]) {
   2323                         pr->flags |= SOC_PORT_RESOURCE_REMAP;
   2324                     }
   2325                     break;
   2326                 }
   2327             }
   2328 
   2329             if (j >= nport) {  /* Not found */
   2330                 pr->flags |= SOC_PORT_RESOURCE_DESTROY;
   2331 
   2332             }
   2333 
   2334             /*
   2335              * Detach only if the port is not becoming inactive (legacy).
   2336              *
   2337              * A port that is becoming inactive after flex is indicated
   2338              * when both of the following flags are set:
   2339              *     DESTROY
   2340              *     I_MAP
   2341              */
   2342             if (!(pr->flags & SOC_PORT_RESOURCE_DESTROY) ||
   2343                 !(pr->flags & SOC_PORT_RESOURCE_I_MAP)) {
   2344                 pr->flags |= SOC_PORT_RESOURCE_DETACH;
   2345             }
   2346 
   2347         } else {
   2348 
   2349             /*
   2350              * Check if logical port is new (port does exist), or
   2351              * port is being remapped.
   2352              */
   2353             if (si->port_l2p_mapping[pr->port] == -1) {
   2354                 pr->flags |= SOC_PORT_RESOURCE_NEW;
   2355             } else if (pr->physical_port != si->port_l2p_mapping[pr->port]) {
   2356                 pr->flags |= SOC_PORT_RESOURCE_REMAP;
   2357             }
   2358 
   2359             /* All active ports after flexed are always attached */
   2360             pr->flags |= SOC_PORT_RESOURCE_ATTACH;
   2361         }
   2362 
   2363     }
   2364 
   2365     return BCM_E_NONE;
   2366 }
   2367 
   2368 
   2369 /*
   2370  * Function:
   2371  *      _bcm_td2p_port_resource_op_get
   2372  * Purpose:
   2373  *      Get the type of FlexPort operations/changes:
   2374  *          none, port-mapping, lanes, speed, encap.
   2375  *
   2376  *      Some operations only need speed or encap changes.  In this
   2377  *      case, the actual FlexPort operation is not necessary and
   2378  *      only calls to set to speed and/or encap mode are made.
   2379  *
   2380  * Parameters:
   2381  *      unit     - (IN) Unit number.
   2382  *      nport    - (IN) Number of elements in array resource.
   2383  *      resource - (IN) Port resource configuration array.
   2384  *      op       - (OUT) FlexPort operation BCM_TD2P_PORT_RESOURCE_OP_...
   2385  * Returns:
   2386  *      BCM_E_XXX
   2387  * Note:
   2388  *      Assumes caller has lock.
   2389  *      Resource is not NULL.
   2390  *      Logical port in 'resource' is in BCM port format (non GPORT).
   2391  */
   2392 STATIC int
   2393 _bcm_td2p_port_resource_op_get(int unit, 
   2394                                int nport, bcm_td2p_port_resource_t *resource,
   2395                                int *op)
   2396 {
   2397     int i;
   2398     bcm_td2p_port_resource_t *pr;
   2399     soc_info_t *si = &SOC_INFO(unit);
   2400     int speed = 0;
   2401     int encap = 0;
   2402 
   2403     *op = BCM_TD2P_PORT_RESOURCE_OP_NONE;
   2404     
   2405     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2406 
   2407         /* Check port speed */
   2408         if (pr->flags & SOC_PORT_RESOURCE_SPEED) {
   2409             /*
   2410              * NOTE: speed_set sequence
   2411              *
   2412              * pr->flags & SOC_PORT_RESOURCE_SPEED is set by speed_set API.
   2413              * No logical-physical port mapping changes.
   2414              * OP_PMAP flag doesn't need to be set in this case.
   2415              * _bcm_td2p_port_resource_speed_execute will be called.
   2416              */
   2417             *op |= BCM_TD2P_PORT_RESOURCE_OP_SPEED;
   2418             LOG_VERBOSE(BSL_LS_BCM_PORT,
   2419                         (BSL_META_U(unit,
   2420                                     "Speed change detected: "
   2421                                     "logical=%d physical=%d\n"),
   2422                          pr->port, pr->physical_port));
   2423             continue;
   2424         }
   2425 
   2426         /* Check port mapping change */
   2427         if (pr->flags &
   2428             (SOC_PORT_RESOURCE_NEW | SOC_PORT_RESOURCE_DESTROY |
   2429              SOC_PORT_RESOURCE_REMAP)) {
   2430             *op |= BCM_TD2P_PORT_RESOURCE_OP_PMAP;
   2431 
   2432             LOG_VERBOSE(BSL_LS_BCM_PORT,
   2433                         (BSL_META_U(unit,
   2434                                     "Port map change detected: "
   2435                                     "%s %s %s l=%d p=%d\n"),
   2436                          (pr->flags & SOC_PORT_RESOURCE_NEW) ? "new" : "",
   2437                          (pr->flags & SOC_PORT_RESOURCE_DESTROY) ?
   2438                          "destroy" : "",
   2439                          (pr->flags & SOC_PORT_RESOURCE_REMAP) ? "remap" : "",
   2440                          pr->port, pr->physical_port));
   2441         }
   2442 
   2443         /* Skip ports that are being deleted or not defined */
   2444         if ((pr->physical_port == -1) ||
   2445             (si->port_l2p_mapping[pr->port] == -1)) {
   2446             continue;
   2447         }
   2448 
   2449         /*
   2450          * NOTE: Execute full flex operation if speed is different
   2451          */
   2452         if (!(*op & BCM_TD2P_PORT_RESOURCE_OP_SPEED)) {
   2453             BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, pr->port, &speed));
   2454             if (pr->speed != speed) {
   2455                 *op |= BCM_TD2P_PORT_RESOURCE_OP_PMAP;
   2456             }
   2457         }
   2458 
   2459         /* Check port lanes */
   2460         if (!(*op & BCM_TD2P_PORT_RESOURCE_OP_LANES)) {
   2461             if (pr->lanes != si->port_num_lanes[pr->port]) {
   2462                 *op |= BCM_TD2P_PORT_RESOURCE_OP_LANES;
   2463             }
   2464         }
   2465 
   2466         /* Check port encap */
   2467         if (!(*op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP)) {
   2468             BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, pr->port, &encap));
   2469             if (pr->encap != encap) {
   2470                 *op |= BCM_TD2P_PORT_RESOURCE_OP_ENCAP;
   2471             }
   2472         }
   2473 
   2474         /* If all are set, no more checking is necessary */
   2475         if (*op == BCM_TD2P_PORT_RESOURCE_OP_ALL) {
   2476             break;
   2477         }
   2478     }
   2479     
   2480     return BCM_E_NONE;
   2481 }
   2482 
   2483 
   2484 /*
   2485  * Function:
   2486  *      _bcm_td2p_port_resource_loopback_clear
   2487  * Purpose:
   2488  *      Clear the loopback mode for the given set of ports.
   2489  *
   2490  * Parameters:
   2491  *      unit           - (IN) Unit number.
   2492  *      nport          - (IN) Number of elements in array resource.
   2493  *      resource       - (IN) Port Resource FlexPort configuration.
   2494  * Returns:
   2495  *      SOC_E_XXX
   2496  * Notes:
   2497  *      Assumes all 'delete' elements are first in array.
   2498  */
   2499 STATIC int
   2500 _bcm_td2p_port_resource_loopback_clear(int unit,
   2501                                        int nport,
   2502                                        bcm_td2p_port_resource_t *resource)
   2503 {
   2504     int i;
   2505     int loopback;
   2506     bcm_td2p_port_resource_t *pr;
   2507 
   2508     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2509         if (pr->physical_port == -1) {
   2510             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_get(unit,
   2511                                                 pr->port, &loopback));
   2512             if (loopback != BCM_PORT_LOOPBACK_NONE) {
   2513                 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit,
   2514                                                 pr->port,
   2515                                                 BCM_PORT_LOOPBACK_NONE));
   2516             }
   2517         }
   2518     }
   2519 
   2520     return BCM_E_NONE;
   2521 
   2522 }
   2523 
   2524 /*
   2525  * Function:
   2526  *      _bcm_td2p_port_soc_resource_validate
   2527  * Purpose:
   2528  *      Perform soc resource validation.
   2529  *
   2530  * Parameters:
   2531  *      unit     - (IN) Unit number.
   2532  *      nport    - (IN) Number of elements in array resource.
   2533  *      resource - (IN) Port resource configuration array.
   2534  * Returns:
   2535  *      BCM_E_XXX
   2536  * Note:
   2537  *      Assumes caller has lock.
   2538  *      Assumes BCM data has been validated (basic API semantics)
   2539  */
   2540 STATIC int
   2541 _bcm_td2p_port_soc_resource_validate(int unit,
   2542                                      int nport, bcm_td2p_port_resource_t *resource)
   2543 {
   2544     int rv;
   2545     int i;
   2546     soc_port_resource_t *soc_resource;
   2547 
   2548     soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport,
   2549                              "port_resource");
   2550     if (soc_resource == NULL) {
   2551         LOG_ERROR(BSL_LS_BCM_PORT,
   2552                   (BSL_META_U(unit,
   2553                               "Unable to allocate memory for SOC FlexPort "
   2554                               "array\n")));
   2555         return BCM_E_MEMORY;
   2556     }
   2557 
   2558     /* Clear data structure */
   2559     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
   2560 
   2561     /* Copy initial information */
   2562     for (i = 0; i < nport; i++) {
   2563         soc_resource[i].flags = resource[i].flags;
   2564         soc_resource[i].logical_port = resource[i].port;
   2565         soc_resource[i].physical_port = resource[i].physical_port;
   2566         soc_resource[i].speed = resource[i].speed;
   2567         soc_resource[i].num_lanes = resource[i].lanes;
   2568         soc_resource[i].encap = resource[i].encap;
   2569     }
   2570 
   2571     rv = soc_td2p_port_resource_validate(unit, nport, soc_resource);
   2572     if (SOC_FAILURE(rv)) {
   2573         sal_free(soc_resource);
   2574         return rv;
   2575     }
   2576 
   2577     sal_free(soc_resource);
   2578 
   2579     return rv;
   2580 }
   2581 
   2582 /*
   2583  * Function:
   2584  *      _bcm_td2p_port_resource_speed_execute
   2585  * Purpose:
   2586  *      Perform a speed set operation.
   2587  *      This includes speed change only
   2588  *
   2589  * Parameters:
   2590  *      unit     - (IN) Unit number.
   2591  *      nport    - (IN) Number of elements in array resource.
   2592  *      resource - (IN) Port resource configuration array.
   2593  * Returns:
   2594  *      BCM_E_XXX
   2595  * Note:
   2596  *      Assumes caller has lock.
   2597  *      Assumes BCM data has been validated (basic API semantics)
   2598  *
   2599  * Details:
   2600  *     This function is pretty similar as _bcm_td2p_port_resource_execute.
   2601  *     But speed set doesn't change logical-physical port mapping.
   2602  *     So this function should skip detach, attach function calls.
   2603  *       _bcm_td2p_port_resource_detach
   2604  *       _bcm_td2p_port_resource_attach
   2605  *     Also this calls soc_td2p_port_resource_configure with
   2606  *     the flag:SOC_PORT_RESOURCE_CONFIGURE_SPEED_SET to make slightly
   2607  *     different sequence from full flex operation.
   2608  */
   2609 STATIC int
   2610 _bcm_td2p_port_resource_speed_execute(int unit,
   2611                                   int nport, bcm_td2p_port_resource_t *resource)
   2612 {
   2613     int rv;
   2614     int i;
   2615     soc_port_resource_t *soc_resource;
   2616 
   2617     soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport,
   2618                              "port_resource");
   2619     if (soc_resource == NULL) {
   2620         LOG_ERROR(BSL_LS_BCM_PORT,
   2621                   (BSL_META_U(unit,
   2622                               "Unable to allocate memory for SOC FlexPort "
   2623                               "array\n")));
   2624         return BCM_E_MEMORY;
   2625     }
   2626 
   2627     /* Clear data structure */
   2628     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
   2629 
   2630     /* Copy initial information */
   2631     for (i = 0; i < nport; i++) {
   2632         soc_resource[i].flags = resource[i].flags;
   2633         soc_resource[i].logical_port = resource[i].port;
   2634         soc_resource[i].physical_port = resource[i].physical_port;
   2635         soc_resource[i].speed = resource[i].speed;
   2636         soc_resource[i].num_lanes = resource[i].lanes;
   2637         soc_resource[i].encap = resource[i].encap;
   2638     }
   2639 
   2640     rv = soc_td2p_port_resource_validate(unit, nport, soc_resource);
   2641     if (SOC_FAILURE(rv)) {
   2642         sal_free(soc_resource);
   2643         return rv;
   2644     }
   2645 
   2646     /* SOC Port Resource Configure */
   2647     rv = soc_td2p_port_resource_configure(unit, nport, soc_resource,
   2648                         SOC_PORT_RESOURCE_CONFIGURE_SPEED_ONLY);
   2649 
   2650     if (BCM_FAILURE(rv)) {
   2651         LOG_ERROR(BSL_LS_BCM_PORT,
   2652                   (BSL_META_U(unit,
   2653                               "Changes to device may have been partially "
   2654                               "executed.  System may be unstable.\n")));
   2655     }
   2656 
   2657     sal_free(soc_resource);
   2658 
   2659     return rv;
   2660 }
   2661 
   2662 /*
   2663  * Function:
   2664  *      _bcm_td2p_port_resource_execute
   2665  * Purpose:
   2666  *      Perform a FlexPort operation.
   2667  *      This includes changes that involve:
   2668  *      - Logical to physical port mapping
   2669  *      - Speed
   2670  *      - Number of PHY lanes
   2671  *
   2672  * Parameters:
   2673  *      unit     - (IN) Unit number.
   2674  *      nport    - (IN) Number of elements in array resource.
   2675  *      resource - (IN) Port resource configuration array.
   2676  * Returns:
   2677  *      BCM_E_XXX
   2678  * Note:
   2679  *      Assumes caller has lock.
   2680  *      Assumes BCM data has been validated (basic API semantics)
   2681  *
   2682  * Details:
   2683  *
   2684  * Port Mapping
   2685  * ------------
   2686  * A logical to physical port mapping is given as part of the port resource
   2687  * array.  This can lead to the following operations:
   2688  * - Port Mapping Delete (or clear)
   2689  *   This is indicated when the physical port is set to (-1) and
   2690  *   the port to be flexed is considered an 'old' port.
   2691  *   The logical port in the array entry must always be valid.
   2692  *   A 'delete' may result in the following actions for a port mapping:
   2693  *      (1) Destroyed
   2694  *      (2) Same
   2695  *      (3) Remapped
   2696  *
   2697  * - Port Mapping Add (or set)
   2698  *   This is indicated when the physical port is set to a valid
   2699  *   physical port number (>=0).
   2700  *   The logical port in the array entry must always be valid.
   2701  *   An 'add' may result in the following actions for a port mapping:
   2702  *      (1) New
   2703  *      (2) Same
   2704  *      (3) Remapped
   2705  *
   2706  * Destroyed: Logical port no longer exist after FlexPort.
   2707  * Remapped:  Logical port will continue to exist after FlexPort
   2708  *            but is mapped to a different physical port.
   2709  * New:       Logical port did not exist before FlexPort.
   2710  * Same:      Logical to physical port mapping remains the same.
   2711  */
   2712 STATIC int
   2713 _bcm_td2p_port_resource_execute(int unit, 
   2714                                 int nport, bcm_td2p_port_resource_t *resource,
   2715                                 int op)
   2716 {
   2717     int rv;
   2718     int i;
   2719     int flag;
   2720     soc_port_resource_t *soc_resource;
   2721 
   2722     /*
   2723      * Main FlexPort Sequence
   2724      *
   2725      * - SOC Validation:
   2726      *     + More validation takes place in the SOC layer.
   2727      *     + These check for abilities and configurations based on
   2728      *       the physical aspects of the device.
   2729      *
   2730      * NOTE: Up to this point, no changes has taken place in SW
   2731      *       data structures or HW.
   2732      *       From this point forward, HW and SW data will be modified,
   2733      *       any errors will leave the system unstabled.
   2734      *
   2735      * - Clear any port related settings in BCM layer as needed.
   2736      *
   2737      * - Detach 'old' ports from BCM layer:
   2738      *     + These are all ports to be cleared/deleted (indicated by physical
   2739      *       port -1), EXCEPT those that will become inactive after the
   2740      *       FlexPort operation (this is only true with legacy API).
   2741      *     + The port state should be the same as the state of a
   2742      *       port that was never configured during SDK initialization.
   2743      *     + This involves SW and HW changes.
   2744      *
   2745      * - SOC Port Resource Configure:
   2746      *     Takes place in the SOC layer.
   2747      *     It consists primarliy of these steps:
   2748      *       + Delete ports in SOC layer (SOC_INFO SW, HW update).
   2749      *       + Add ports in SOC layer (SOC_INFO SW, HW update).
   2750      *       + Execute FlexPort operation as defined by HW specs.
   2751      *
   2752      * - Attach 'new' ports to BCM layer:
   2753      *     + These are all ports that are active after the FlexPort operation.
   2754      *     + Ports are initialized to a default state
   2755      *       (same state when a port is brought up after SDK is initialized).
   2756      *     + This involves SW and HW changes.
   2757      *
   2758      * - Set BCM properties on flexed ports as needed.
   2759      */
   2760 
   2761     /*
   2762      * SOC Port Structure initialization
   2763      */
   2764     /* Allocate memory for SOC Port Resource array data structure */
   2765     soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport,
   2766                              "port_resource");
   2767     if (soc_resource == NULL) {
   2768         LOG_ERROR(BSL_LS_BCM_PORT,
   2769                   (BSL_META_U(unit,
   2770                               "Unable to allocate memory for SOC FlexPort "
   2771                               "array\n")));
   2772         return BCM_E_MEMORY;
   2773     }
   2774 
   2775     /* Clear data structure */
   2776     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
   2777 
   2778     /* Copy initial information */
   2779     for (i = 0; i < nport; i++) {
   2780         soc_resource[i].flags = resource[i].flags;
   2781         soc_resource[i].logical_port = resource[i].port;
   2782         soc_resource[i].physical_port = resource[i].physical_port;
   2783         soc_resource[i].speed = resource[i].speed;
   2784         soc_resource[i].num_lanes = resource[i].lanes;
   2785         soc_resource[i].encap = resource[i].encap;
   2786     }
   2787 
   2788 
   2789     /* SOC Validation */
   2790     rv = soc_td2p_port_resource_validate(unit, nport, soc_resource);
   2791     if (SOC_FAILURE(rv)) {
   2792         sal_free(soc_resource);
   2793         return rv;
   2794     }
   2795 
   2796     /* Detach ports from BCM layer */
   2797     rv = _bcm_td2p_port_resource_detach(unit, nport, resource);
   2798 
   2799     /* SOC Port Resource Configure */
   2800     if (op == BCM_TD2P_PORT_RESOURCE_OP_LANES) {
   2801         flag = SOC_PORT_RESOURCE_CONFIGURE_LANES_ONLY;
   2802     } else {
   2803         flag = SOC_PORT_RESOURCE_CONFIGURE_FLEX;
   2804     }
   2805     if (BCM_SUCCESS(rv)) {
   2806         rv = soc_td2p_port_resource_configure(unit, nport, soc_resource, flag);
   2807     }
   2808 
   2809     /* Attach ports to BCM layer */
   2810     if (BCM_SUCCESS(rv)) {
   2811         rv = _bcm_td2p_port_resource_attach(unit, nport, resource);
   2812     }
   2813 
   2814     if (BCM_FAILURE(rv)) {
   2815         LOG_ERROR(BSL_LS_BCM_PORT,
   2816                   (BSL_META_U(unit,
   2817                               "Changes to device may have been partially "
   2818                               "executed.  System may be unstable.\n")));
   2819     }
   2820 
   2821     sal_free(soc_resource);
   2822 
   2823     return rv;
   2824 }
   2825 
   2826 
   2827 /*
   2828  * Function:
   2829  *      _bcm_td2p_port_resource_configure
   2830  * Purpose:
   2831  *      Modify the following port resources:
   2832  *      - Logical to physical port mapping
   2833  *      - Speed
   2834  *      - Number of PHY lanes
   2835  *      - Encapsulation mode
   2836  * Parameters:
   2837  *      unit     - (IN) Unit number.
   2838  *      nport    - (IN) Number of elements in array resource.
   2839  *      resource - (IN/OUT) Port resource configuration array.
   2840  * Returns:
   2841  *      BCM_E_XXX
   2842  * Note:
   2843  *      - Assumes caller has lock.
   2844  *      - The data is modified by the function.
   2845  *      - It takes the internal bcm_td2p_port_resource_t data type.
   2846  */
   2847 STATIC int
   2848 _bcm_td2p_port_resource_configure(int unit, 
   2849                                   int nport,
   2850                                   bcm_td2p_port_resource_t *resource)
   2851 {
   2852     int op;
   2853     int i;
   2854 
   2855     /* Convert port format and validate logical and physical port numbers */
   2856     BCM_IF_ERROR_RETURN
   2857         (_bcm_td2p_port_resource_resolve(unit,
   2858                                          nport, resource));
   2859 
   2860     /* Get port mapping change */
   2861     BCM_IF_ERROR_RETURN
   2862         (_bcm_td2p_port_resource_pmap_get(unit, nport, resource));
   2863 
   2864     /* clear loopback */
   2865     BCM_IF_ERROR_RETURN
   2866         (_bcm_td2p_port_resource_loopback_clear(unit, nport, resource));
   2867 
   2868     /*
   2869      * Validate function input requirements
   2870      *
   2871      * This steps checks for function semantics and guidelines
   2872      * from the API perspective.
   2873      */
   2874     BCM_IF_ERROR_RETURN
   2875         (_bcm_td2p_port_resource_input_validate(unit, nport, resource));
   2876 
   2877     /*
   2878      * FlexPort operations types:
   2879      *     NONE                             => Nothing to do
   2880      *     PMAP or LANES                    => FlexPort sequence
   2881      *     ENCAP                            => Encap set
   2882      *     SPEED, but not PMAP or LANES     => Speed set
   2883      */
   2884     BCM_IF_ERROR_RETURN
   2885         (_bcm_td2p_port_resource_op_get(unit, nport, resource, &op));
   2886 
   2887     LOG_VERBOSE(BSL_LS_BCM_PORT,
   2888                 (BSL_META_U(unit,
   2889                             "FlexPort operations 0x%x: %s %s %s %s\n"),
   2890                  op,
   2891                  (op & BCM_TD2P_PORT_RESOURCE_OP_PMAP) ? "pmap" : "",
   2892                  (op & BCM_TD2P_PORT_RESOURCE_OP_SPEED) ? "speed" : "",
   2893                  (op & BCM_TD2P_PORT_RESOURCE_OP_LANES) ? "lanes" : "",
   2894                  (op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP) ? "encap" : ""));
   2895 
   2896     if (op == BCM_TD2P_PORT_RESOURCE_OP_NONE) {
   2897         return BCM_E_NONE;     /* No changes, just return */
   2898     }
   2899 
   2900     /*
   2901      * Port Mapping / Lane
   2902      *
   2903      * These changes always require a FlexPort operation.
   2904      */
   2905     if ((op & BCM_TD2P_PORT_RESOURCE_OP_PMAP) ||
   2906         (op & BCM_TD2P_PORT_RESOURCE_OP_LANES)) {
   2907         LOG_VERBOSE(BSL_LS_BCM_PORT,
   2908                     (BSL_META_U(unit,
   2909                                 "--- Execute FlexPort sequence ---\n")));
   2910         BCM_IF_ERROR_RETURN
   2911             (_bcm_td2p_port_resource_execute(unit,
   2912                                              nport, resource, op));
   2913         /*
   2914          * Bring new ports down to ensure port state is proper
   2915          */
   2916         for (i = 0; i < nport; i++) {
   2917             if (resource[i].physical_port == -1) {
   2918                 continue;
   2919             }
   2920             BCM_IF_ERROR_RETURN
   2921                 (bcmi_esw_portctrl_enable_set(unit, resource[i].port, 0));
   2922         }
   2923     } else if (op & BCM_TD2P_PORT_RESOURCE_OP_SPEED) {
   2924         LOG_VERBOSE(BSL_LS_BCM_PORT,
   2925                     (BSL_META_U(unit,
   2926                                 "--- Execute Speed Set sequence ---\n")));
   2927         BCM_IF_ERROR_RETURN
   2928             (_bcm_td2p_port_resource_speed_execute(unit,
   2929                                                nport, resource));
   2930     } else if (op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP) {
   2931         BCM_IF_ERROR_RETURN
   2932             (_bcm_td2p_port_soc_resource_validate(unit, nport, resource));
   2933     }
   2934 
   2935     /*
   2936      * Encap
   2937      */
   2938     if (op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP) {
   2939         LOG_VERBOSE(BSL_LS_BCM_PORT,
   2940                     (BSL_META_U(unit,
   2941                                 "Execute Encap change\n")));
   2942 
   2943         for (i = 0; i < nport; i++) {
   2944             if (resource[i].physical_port == -1) {
   2945                 continue;
   2946             }
   2947 
   2948             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_encap_set_execute(unit,
   2949                                     resource[i].port,
   2950                                     resource[i].encap, TRUE));
   2951         }
   2952     }
   2953 
   2954     return BCM_E_NONE;
   2955 }
   2956 
   2957 
   2958 /*
   2959  * Function:
   2960  *      _bcm_td2p_port_resource_multi_set
   2961  * Purpose:
   2962  *      Modify the following port resources:
   2963  *      - Logical to physical port mapping
   2964  *      - Speed
   2965  *      - Number of PHY lanes
   2966  *      - Encapsulation mode
   2967  * Parameters:
   2968  *      unit     - (IN) Unit number.
   2969  *      nport    - (IN) Number of elements in array resource.
   2970  *      resource - (IN) Port resource configuration array.
   2971  * Returns:
   2972  *      BCM_E_XXX
   2973  * Note:
   2974  *      - Assumes caller has lock.
   2975  *      - This is to be called by the API dispatch driver.
   2976  *      - It takes the public bcm_port_resource_t data type.
   2977  */
   2978 STATIC int
   2979 _bcm_td2p_port_resource_multi_set(int unit, 
   2980                                   int nport,
   2981                                   bcm_port_resource_t *resource)
   2982 {
   2983     int rv;
   2984     int i;
   2985     bcm_td2p_port_resource_t *port_resource;
   2986 
   2987     if (resource == NULL) {
   2988         return BCM_E_PARAM;
   2989     }
   2990 
   2991     /*
   2992      * Use internal port resource structure type.
   2993      * Called routines will be modifying the data, so
   2994      * having a copy avoids modifying user's data.
   2995      */
   2996     port_resource = sal_alloc(sizeof(bcm_td2p_port_resource_t) * nport,
   2997                               "port_resource");
   2998     if (port_resource == NULL) {
   2999         LOG_ERROR(BSL_LS_BCM_PORT,
   3000                   (BSL_META_U(unit,
   3001                               "Unable to allocate memory for internal "
   3002                               "FlexPort array\n")));
   3003         return BCM_E_MEMORY;
   3004     }
   3005 
   3006     /* Clear data structure */
   3007     sal_memset(port_resource, 0, sizeof(bcm_td2p_port_resource_t) * nport);
   3008 
   3009     /* Copy initial information */
   3010     for (i = 0; i < nport; i++) {
   3011         /*
   3012          * No current flags defined in bcm_port_resource_t, otherwise
   3013          * need to translate from public to internal flags.
   3014          */
   3015         port_resource[i].flags = 0;
   3016         port_resource[i].port = resource[i].port;
   3017         port_resource[i].physical_port = resource[i].physical_port;
   3018         port_resource[i].speed = resource[i].speed;
   3019         port_resource[i].lanes = resource[i].lanes;
   3020         port_resource[i].encap = resource[i].encap;
   3021     }
   3022 
   3023     rv = _bcm_td2p_port_resource_configure(unit, nport, port_resource);
   3024 
   3025     sal_free(port_resource);
   3026 
   3027     return rv;
   3028 }
   3029 
   3030 /*
   3031  * Function:
   3032  *      _bcm_td2p_port_core_chip_speed_get
   3033  * Purpose:
   3034  *      This API is to obtain core chip speed
   3035  * Parameters:
   3036  *      unit     - (IN) Unit number
   3037  *      port     - (IN) Logical port number(bcm_port_t, not bcm_gport_t)
   3038  *      speed    - (IN) Port speed
   3039  * Returns:
   3040  *      BCM_E_XXX
   3041  * Note:
   3042  *      - Assumes caller has lock.
   3043  *      - This is to be called by the API dispatch driver.
   3044  */
   3045 STATIC int
   3046 _bcm_td2p_port_core_chip_speed_get(int unit, bcm_port_t port, int *speed)
   3047 {
   3048     SOC_IF_ERROR_RETURN(soc_td2p_port_speed_get(unit, port, speed));
   3049 
   3050     return BCM_E_NONE;
   3051 }
   3052 
   3053 /*
   3054  * Function:
   3055  *      _bcm_td2p_port_resource_speed_set
   3056  * Purpose:
   3057  *      Changes the speed but keeps the same number of lanes
   3058  * Parameters:
   3059  *      unit     - (IN) Unit number
   3060  *      port     - (IN) Logical port number(bcm_port_t, not bcm_gport_t)
   3061  *      speed    - (IN) Port speed
   3062  * Returns:
   3063  *      BCM_E_XXX
   3064  * Note:
   3065  *      - Assumes caller has lock.
   3066  *      - This is to be called by the API dispatch driver.
   3067  */
   3068 STATIC int
   3069 _bcm_td2p_port_resource_speed_set(int unit, bcm_port_t port, int speed)
   3070 {
   3071     soc_info_t *si = &SOC_INFO(unit);
   3072     bcm_td2p_port_resource_t resource[2]; /* resource for pre and post */
   3073     int cur_lanes, cur_speed, cur_encap;
   3074     int phy_port;
   3075 
   3076     /* Get current core chip port speed */
   3077     BCM_IF_ERROR_RETURN(_bcm_td2p_port_core_chip_speed_get(
   3078                             unit, port, &cur_speed));
   3079     if (cur_speed == 0) {
   3080         /* port is detached */
   3081         cur_speed = SOC_INFO(unit).port_speed_max[port];
   3082     }
   3083 
   3084     if (cur_speed == speed) {
   3085         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3086                     (BSL_META_U(unit,
   3087                     "Speed is already configured as %d\n"), cur_speed));
   3088         return BCM_E_NONE;
   3089     }
   3090 
   3091     /* Check current number of lanes */
   3092     BCM_IF_ERROR_RETURN(bcmi_td2p_port_lanes_get(unit, port, &cur_lanes));
   3093 
   3094     /* Get current port encap */
   3095     BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap));
   3096 
   3097     /*
   3098      * Clear mapping for physical ports involved in FlexPort operation.
   3099      */
   3100     phy_port = si->port_l2p_mapping[port];
   3101     /* Check valid physical port */
   3102     if (phy_port == -1) {
   3103         LOG_ERROR(BSL_LS_BCM_PORT,
   3104                   (BSL_META_U(unit,
   3105                               "Invalid physical port "
   3106                               "for logical port %d\n"),
   3107                    port));
   3108         return BCM_E_INTERNAL;
   3109     }
   3110 
   3111     resource[0].flags = SOC_PORT_RESOURCE_I_MAP | SOC_PORT_RESOURCE_SPEED;
   3112     resource[0].port = port;
   3113     resource[0].physical_port = -1;
   3114 
   3115     resource[1].flags = SOC_PORT_RESOURCE_I_MAP | SOC_PORT_RESOURCE_SPEED;
   3116     resource[1].port = port;
   3117     resource[1].physical_port = phy_port;
   3118     resource[1].speed = speed;
   3119     resource[1].lanes = cur_lanes;
   3120     resource[1].encap = cur_encap;
   3121 
   3122     BCM_IF_ERROR_RETURN(_bcm_td2p_port_resource_configure(unit, 2, resource));
   3123 
   3124     return BCM_E_NONE;
   3125 }
   3126 
   3127 /*
   3128  * Function:
   3129  *      bcmi_td2p_port_lanes_get
   3130  * Purpose:
   3131  *      Get the number of PHY lanes for the given port.
   3132  * Parameters:
   3133  *      unit     - (IN) Unit number.
   3134  *      port     - (IN) Logical port.
   3135  *      lanes    - (OUT) Returns number of lanes for port.
   3136  * Returns:
   3137  *      BCM_E_XXX
   3138  */
   3139 int
   3140 bcmi_td2p_port_lanes_get(int unit, bcm_port_t port, int *lanes)
   3141 {
   3142     bcm_port_resource_t resource;
   3143 
   3144     BCM_IF_ERROR_RETURN(bcm_esw_port_resource_get(unit, port, &resource));
   3145 
   3146     *lanes = resource.lanes;
   3147 
   3148     return BCM_E_NONE;
   3149 }
   3150 
   3151 
   3152 /*
   3153  * Function:
   3154  *      bcmi_td2p_port_lanes_set
   3155  * Purpose:
   3156  *      Set the number of PHY lanes for the given port.
   3157  *
   3158  *      This function should only be used to support the legacy
   3159  *      FlexPort API bcm_port_control_set(... , bcmPortControlLanes).
   3160  *
   3161  *      The legacy API does not delete the port mappings when flexing
   3162  *      to fewer lanes.  Ports which lanes are used by the base
   3163  *      physical port becomes inactive.
   3164  *
   3165  * Parameters:
   3166  *      unit     - (IN) Unit number.
   3167  *      port     - (IN) Logical port.
   3168  *      lanes    - (IN) Number of lanes to set on given port.
   3169  * Returns:
   3170  *      BCM_E_XXX
   3171  * Notes:
   3172  *      - Only to be used by legacy API to support TD2 behavior
   3173  *        bcm_port_control_set(... , bcmPortControlLanes).
   3174  *      - Supports only up to 4 lanes (TSC-4).
   3175  *      - 'port' must be in BCM port format (non-GPORT) and mapped to
   3176  *        the base physical port.
   3177  *      - Several calls to legacy API may be required to
   3178  *        achieve desired configuration.
   3179  */
   3180 int
   3181 bcmi_td2p_port_lanes_set(int unit, bcm_port_t port, int lanes)
   3182 {
   3183     soc_info_t *si = &SOC_INFO(unit);
   3184     bcm_td2p_port_resource_t resource[8]; /* Max sz to support up to 4 lanes */
   3185     int max_array_cnt;
   3186     int i;
   3187     int cur_lanes;
   3188     int cur_speed;
   3189     int cur_encap = 0;
   3190     int phy_port;
   3191     int speed;
   3192     int num_ports_clear;
   3193     int num_ports_new;
   3194 
   3195     /* Support legacy API up to 4 lanes */
   3196     if ((lanes != 1) && (lanes != 2) && (lanes != 4)) {
   3197         return BCM_E_PARAM;
   3198     }
   3199 
   3200     /* Check current number of lanes */
   3201     BCM_IF_ERROR_RETURN(bcmi_td2p_port_lanes_get(unit, port, &cur_lanes));
   3202     if (cur_lanes == lanes) {
   3203         return BCM_E_NONE;
   3204     }
   3205 
   3206     /* Check that port can support number of lanes specified */
   3207     SOC_IF_ERROR_RETURN(soc_td2p_port_lanes_valid(unit, port, lanes));
   3208 
   3209     /* Get current port speed */
   3210     BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, port, &cur_speed));
   3211 
   3212     /* Get current port encap */
   3213     BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap));
   3214 
   3215     /* Clear array */
   3216     max_array_cnt = COUNTOF(resource);
   3217     sal_memset(resource, 0, sizeof(resource));
   3218 
   3219     /*
   3220      * Build port resource array
   3221      * Certain information is derived from 'best' guess,
   3222      * similar to the legacy behaviour.
   3223      */
   3224 
   3225     /*
   3226      * Select speed based on number of lanes
   3227      *
   3228      * For HG, if the current HG speed is the higher speed
   3229      * (i.e. 42 vs 40) select the higher HG speed for the number of lanes.
   3230      * Example
   3231      *    1xHG[42] --> 4xHG[11]
   3232      *    1xHG[40] --> 4xHG[10]
   3233      *
   3234      * Notes:  Assumes encap is HIGIG2 if it is not IEEE
   3235      */
   3236     switch(lanes) {
   3237     case 1:
   3238         if (cur_encap == BCM_PORT_ENCAP_IEEE) {    /* IEEE */
   3239             speed = 10000;
   3240         } else {                                   /* Assume HG */
   3241             if (((cur_lanes == 4) && (cur_speed > 40000)) ||
   3242                 ((cur_lanes == 2) && (cur_speed > 20000))) {
   3243                 speed = 11000;
   3244             } else {
   3245                 speed = 10000;
   3246             }
   3247         }
   3248         break;
   3249     case 2:
   3250         if (cur_encap == BCM_PORT_ENCAP_IEEE) {    /* IEEE */
   3251             speed = 20000;
   3252         } else {                                   /* Assume HG */
   3253             if (((cur_lanes == 4) && (cur_speed > 40000)) ||
   3254                 ((cur_lanes == 1) && (cur_speed > 10000))) {
   3255                 speed = 21000;
   3256             } else {
   3257                 speed = 20000;
   3258             }
   3259         }
   3260         break;
   3261     case 4:
   3262         if (cur_encap == BCM_PORT_ENCAP_IEEE) {    /* IEEE */
   3263             speed = 40000;
   3264         } else {                                   /* Assume HG */
   3265             if (((cur_lanes == 2) && (cur_speed > 20000)) ||
   3266                 ((cur_lanes == 1) && (cur_speed > 10000))) {
   3267                 speed = 42000;
   3268             } else {
   3269                 speed = 40000;
   3270             }
   3271         }
   3272         break;
   3273     /*
   3274      * COVERITY
   3275      *
   3276      * Case for default is intentional as a defensive check.
   3277      */
   3278     /* coverity[dead_error_begin] */
   3279     default:
   3280         return BCM_E_PARAM;
   3281         break;
   3282     }
   3283 
   3284     switch (cur_lanes) {
   3285     case 1:
   3286         /*
   3287          * 2x10 flex to: 2 lanes -> 1x20
   3288          * 4x10 flex to: 4 lanes -> 1x40
   3289          */
   3290         if (lanes == 2) {
   3291             int first_phy_port;
   3292             int physical_port = si->port_l2p_mapping[port];
   3293 
   3294             SOC_IF_ERROR_RETURN (soc_td2p_port_macro_first_phy_port_get(unit,
   3295                                  physical_port, &first_phy_port));
   3296 
   3297             /* In tri-mode, either first two lanes of a tsc (1,2) can be
   3298              * selected for 20G speed, or the last two lanes (3, 4). In the
   3299              * second case, we should create only one new 20G port
   3300              */
   3301             if (physical_port == first_phy_port) {
   3302                 num_ports_clear = 4;
   3303                 num_ports_new = 2;
   3304             } else {
   3305                 num_ports_clear = 2;
   3306                 num_ports_new = 1;
   3307             }
   3308         } else {
   3309             num_ports_clear = 4;
   3310             num_ports_new = 1;
   3311         }
   3312         break;
   3313     case 2:
   3314         /*
   3315          * 1x20 flex to: 1 lane  -> 2x10
   3316          * 2x20 flex to: 4 lanes -> 1x40
   3317          */
   3318         if (lanes == 1) {
   3319             num_ports_clear = 2;
   3320             num_ports_new = 2;
   3321         } else {
   3322             num_ports_clear = 4;
   3323             num_ports_new = 1;
   3324         }
   3325         break;
   3326     case 4:
   3327         /*
   3328          * 1x40 flex to: 1 lane  -> 4x10
   3329          *               2 lanes -> 2x20
   3330          */
   3331         if (lanes == 1) {
   3332             num_ports_clear = 4;
   3333             num_ports_new = 4;
   3334         } else {
   3335             num_ports_clear = 4;
   3336             num_ports_new = 2;
   3337         }
   3338         break;
   3339     default:
   3340         return BCM_E_CONFIG;
   3341         break;
   3342     }
   3343 
   3344     if ((num_ports_clear + num_ports_new) > max_array_cnt) {
   3345         LOG_ERROR(BSL_LS_BCM_PORT,
   3346                   (BSL_META_U(unit,
   3347                               "Invalid array FlexPort calculation "
   3348                               "num_ports_clear=%d num_ports_new=%d "
   3349                               "max_array=%d\n"),
   3350                    num_ports_clear, num_ports_new, max_array_cnt));
   3351         return BCM_E_INTERNAL;
   3352     }
   3353 
   3354     /*
   3355      * Clear mapping for physical ports involved in FlexPort operation.
   3356      * Assume physical ports are numbered consecutively in device.
   3357      */
   3358     phy_port = si->port_l2p_mapping[port];
   3359     for (i = 0; i < num_ports_clear; i++) {
   3360         resource[i].flags = SOC_PORT_RESOURCE_I_MAP;
   3361         resource[i].port = si->port_p2l_mapping[phy_port++];
   3362         resource[i].physical_port = -1;
   3363     }
   3364 
   3365     /*
   3366      * Map new ports
   3367      *
   3368      * Legacy API requires that logical-physical port mapping
   3369      * is valid in the SOC_INFO SW data.
   3370      */
   3371     phy_port = si->port_l2p_mapping[port];
   3372     for (; i < (num_ports_clear + num_ports_new); i++) {
   3373         /* Check valid physical port */
   3374         if (phy_port == -1) {
   3375             LOG_ERROR(BSL_LS_BCM_PORT,
   3376                       (BSL_META_U(unit,
   3377                                   "Invalid physical port "
   3378                                   "for logical port %d\n"),
   3379                        port));
   3380             return BCM_E_INTERNAL;
   3381         }
   3382 
   3383         resource[i].flags = SOC_PORT_RESOURCE_I_MAP;
   3384         resource[i].port = si->port_p2l_mapping[phy_port];
   3385         resource[i].physical_port = phy_port;
   3386         resource[i].lanes = lanes;
   3387         resource[i].speed = speed;
   3388         resource[i].encap = cur_encap;
   3389         phy_port += lanes;
   3390     }
   3391 
   3392     BCM_IF_ERROR_RETURN
   3393         (_bcm_td2p_port_resource_configure(unit,
   3394                                            (num_ports_clear + num_ports_new),
   3395                                            resource));
   3396 
   3397     return BCM_E_NONE;
   3398 }
   3399 
   3400 /*
   3401  * Function:
   3402  *      bcm_td2p_flexport_pbmp_update
   3403  * Description:
   3404  *      given a pbmp, add flexport pbmp
   3405  * Parameters:
   3406  *      unit    - (IN) BCM device number
   3407  *      pbmp    - (IN/OUT) port bit map
   3408  */
   3409 
   3410 int
   3411 bcm_td2p_flexport_pbmp_update(int unit, bcm_pbmp_t *pbmp)
   3412 {
   3413     bcm_port_t port;
   3414 
   3415     if (NULL == pbmp) {
   3416         return BCM_E_PARAM;
   3417     }
   3418     for (port = 0; port < TD2P_MAX_NUM_PORTS; port++) {
   3419         BCM_PBMP_PORT_ADD(*pbmp, port);
   3420     }
   3421     return BCM_E_NONE;
   3422 }
   3423 
   3424 /*
   3425  * Function:
   3426  *      _bcm_td2p_port_control_class_select_set
   3427  * Description:
   3428  *      Function to add an entry to MISC_PORT_PROFILE table.
   3429  * Parameters:
   3430  *      unit     - (IN) Device number
   3431  *      port     - (IN) Port number
   3432  *      table_id - (IN) 0 for FP_I2E_CLASSID_SELECTm
   3433  *                      1 for FP_HG_CLASSID_SELECT
   3434  *      mem      - (IN) FP_I2E_CLASSID_SELECTm or FP_HG_CLASSID_SELECTm
   3435  *      field    - (IN) Field to modify.
   3436  *      value    - (IN) New field value.
   3437  * Return Value:
   3438  *      BCM_E_XXX
   3439  */
   3440 STATIC int
   3441 _bcm_td2p_port_control_class_select_set(int unit, bcm_port_t port, int table_id,
   3442                                         soc_mem_t mem, soc_field_t field, uint32 value)
   3443 {
   3444     fp_i2e_classid_select_entry_t fp_ent;
   3445     fp_hg_classid_select_entry_t hg_ent;
   3446     void *entries[2];
   3447     uint32 profile_index = 0;
   3448     int cur_profile_index = 0;
   3449 
   3450     entries[0] = &fp_ent;
   3451     entries[1] = &hg_ent;
   3452 
   3453     BCM_IF_ERROR_RETURN
   3454         (_bcm_esw_port_tab_get(unit, port, MISC_PORT_PROFILE_INDEXf, &cur_profile_index));
   3455 
   3456     BCM_IF_ERROR_RETURN
   3457         (_bcm_misc_port_profile_entry_get(unit, cur_profile_index, 1, entries));
   3458 
   3459     soc_mem_field32_set(unit, mem, entries[table_id], field, value);
   3460 
   3461     BCM_IF_ERROR_RETURN
   3462         (_bcm_misc_port_profile_entry_add(unit, entries, 1, &profile_index));
   3463 
   3464     BCM_IF_ERROR_RETURN
   3465         (_bcm_esw_port_tab_set(unit, port,_BCM_CPU_TABS_NONE,
   3466                                MISC_PORT_PROFILE_INDEXf, profile_index));
   3467 
   3468     if (cur_profile_index != 0) {
   3469        BCM_IF_ERROR_RETURN
   3470           (_bcm_misc_port_profile_entry_delete(unit, cur_profile_index));
   3471     }
   3472 
   3473     return BCM_E_NONE;
   3474 }
   3475 
   3476 /*
   3477  * Function:
   3478  *      _bcm_td2p_port_control_class_select_get
   3479  * Description:
   3480  *      Funtion to get an entry from MISC_PORT_PROFILE table.
   3481  * Parameters:
   3482  *      unit     - (IN) Device number
   3483  *      port     - (IN) Port number
   3484  *      table_id - (IN) 0 for FP_I2E_CLASSID_SELECTm
   3485  *                      1 for FP_HG_CLASSID_SELECT
   3486  *      mem      - (IN) FP_I2E_CLASSID_SELECTm or FP_HG_CLASSID_SELECTm
   3487  *      field    - (IN) Field to read.
   3488  *      value    - (OUT) Field value.
   3489  * Return Value:
   3490  *      BCM_E_XXX
   3491  */
   3492 STATIC int
   3493 _bcm_td2p_port_control_class_select_get(int unit, bcm_port_t port, int table_id,
   3494                                         soc_mem_t mem, soc_field_t field, uint32* value)
   3495 {
   3496     fp_i2e_classid_select_entry_t fp_ent;
   3497     fp_hg_classid_select_entry_t hg_ent;
   3498     void *entries[2];
   3499     int profile_index;
   3500 
   3501     entries[0] = &fp_ent;
   3502     entries[1] = &hg_ent;
   3503 
   3504     BCM_IF_ERROR_RETURN
   3505         (_bcm_esw_port_tab_get(unit, port, MISC_PORT_PROFILE_INDEXf, &profile_index));
   3506 
   3507     BCM_IF_ERROR_RETURN(_bcm_misc_port_profile_entry_get(unit, profile_index, 1, entries));
   3508 
   3509     *value = soc_mem_field32_get(unit, mem, entries[table_id], field);
   3510 
   3511     return BCM_E_NONE;
   3512 }
   3513 
   3514 /*
   3515  * Function:
   3516  *      _bcm_td2p_port_control_egress_class_select_set
   3517  * Description:
   3518  *      Helper funtion to modify fields in FP_I2E_CLASSID_SELECTm memory.
   3519  * Parameters:
   3520  *      unit  - (IN) Device number
   3521  *      port  - (IN) Port number
   3522  *      value - (IN) New field value
   3523  * Return Value:
   3524  *      BCM_E_XXX
   3525  */
   3526 int
   3527 _bcm_td2p_port_control_egress_class_select_set(int unit, bcm_port_t port, uint32 value)
   3528 {
   3529     soc_mem_t mem = FP_I2E_CLASSID_SELECTm;
   3530     soc_field_t field = PORT_SELf;
   3531     /* table_id = 0 for FP_I2E_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */
   3532     int table_id = 0;
   3533     /* Check for valid inputs for FP_I2E_CLASSID_SELECT */
   3534     /* coverity[unsigned_compare] : FALSE */
   3535     if ((value < bcmPortEgressClassSelectNone) ||
   3536         (value >= bcmPortEgressClassSelectFieldIngress)) {
   3537         return BCM_E_PARAM;
   3538     }
   3539 
   3540     BCM_IF_ERROR_RETURN
   3541         (_bcm_td2p_port_control_class_select_set(unit, port, table_id, mem, field, value));
   3542 
   3543     return BCM_E_NONE;
   3544 }
   3545 
   3546 /*
   3547  * Function:
   3548  *      _bcm_td2p_port_control_egress_class_select_get
   3549  * Description:
   3550  *      Helper funtion to get fields in FP_I2E_CLASSID_SELECTm memory.
   3551  * Parameters:
   3552  *      unit  - (IN) Device number
   3553  *      port  - (IN) Port number
   3554  *      value - (OUT) New field value
   3555  * Return Value:
   3556  *      BCM_E_XXX
   3557  */
   3558 int
   3559 _bcm_td2p_port_control_egress_class_select_get(int unit, bcm_port_t port, uint32 *value)
   3560 {
   3561     soc_mem_t mem = FP_I2E_CLASSID_SELECTm;
   3562     soc_field_t field = PORT_SELf;
   3563     /* table_id = 0 for FP_I2E_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */
   3564     int table_id = 0;
   3565 
   3566     BCM_IF_ERROR_RETURN
   3567         (_bcm_td2p_port_control_class_select_get(unit, port, table_id, mem, field, value));
   3568 
   3569     return BCM_E_NONE;
   3570 }
   3571 
   3572 /*
   3573  * Function:
   3574  *      _bcm_td2p_port_control_higig_class_select_set
   3575  * Description:
   3576  *      Helper funtion to modify fields in FP_HG_CLASSID_SELECT memory.
   3577  * Parameters:
   3578  *      unit  - (IN) Device number
   3579  *      port  - (IN) Port number
   3580  *      value - (IN) New field value
   3581  * Return Value:
   3582  *      BCM_E_XXX
   3583  */
   3584 int
   3585 _bcm_td2p_port_control_higig_class_select_set(int unit, bcm_port_t port, uint32 value)
   3586 {
   3587     soc_mem_t mem = FP_HG_CLASSID_SELECTm;
   3588     soc_field_t field = PORT_SELf;
   3589     /* table_id = 1 for FP_HG_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */
   3590     int table_id = 1;
   3591     /* Check for valid inputs for FP_HG_CLASSID_SELECT */
   3592     /* coverity[unsigned_compare] : FALSE */
   3593     if ((value < bcmPortFieldHiGigClassSelectNone) ||
   3594         (value >= bcmPortFieldHiGigClassSelectCount) ||
   3595         (value == bcmPortFieldHiGigClassSelectL3Egress) ||
   3596         (value == bcmPortFieldHiGigClassSelectL3EgressIntf)) {
   3597         return BCM_E_PARAM;
   3598     }
   3599 
   3600     BCM_IF_ERROR_RETURN
   3601         (_bcm_td2p_port_control_class_select_set(unit, port, table_id, mem, field, value));
   3602 
   3603     return BCM_E_NONE;
   3604 }
   3605 
   3606 /*
   3607  * Function:
   3608  *      _bcm_td2p_port_control_higig_class_select_get
   3609  * Description:
   3610  *      Helper funtion to get fields in FP_HG_CLASSID_SELECT memory.
   3611  * Parameters:
   3612  *      unit  - (IN) Device number
   3613  *      port  - (IN) Port number
   3614  *      value - (OUT) New field value
   3615  * Return Value:
   3616  *      BCM_E_XXX
   3617  */
   3618 int
   3619 _bcm_td2p_port_control_higig_class_select_get(int unit, bcm_port_t port, uint32 *value)
   3620 {
   3621     soc_mem_t mem = FP_HG_CLASSID_SELECTm;
   3622     soc_field_t field = PORT_SELf;
   3623     /* table_id = 1 for FP_HG_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */
   3624     int table_id = 1;
   3625 
   3626     BCM_IF_ERROR_RETURN
   3627         (_bcm_td2p_port_control_class_select_get(unit, port, table_id, mem, field, value));
   3628 
   3629     return BCM_E_NONE;
   3630 }
   3631 
   3632 #else /* BCM_TRIDENT2PLUS_SUPPORT */
   3633 int bcm_esw_td2p_port_not_empty;
   3634 #endif /* BCM_TRIDENT2PLUS_SUPPORT */