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

portctrl.c (354784B)


      1 
      2 /* 
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:        portctrl.c
      9  * Purpose:     SDK Port Control Layer
     10  *
     11  *              The purpose is to encapsulate port functionality
     12  *              related to the xxPORT block (i.e. XLPORT, CPORT)
     13  *              MAC and PHY.
     14  *
     15  *              Currently, only the PortMod library is being supported.
     16  *              The PortMod library provides support for the MAC, PHY,
     17  *              and xxPORT registers.
     18  *
     19  *              Callers of the Port Control routines should check
     20  *              before calling into them with the macro:
     21  *                  SOC_USE_PORTCTRL()
     22  */
     23 
     24 #include <shared/error.h>
     25 #include <shared/bsl.h>
     26 #include <sal/core/dpc.h>
     27 #include <soc/types.h>
     28 #include <soc/error.h>
     29 #include <soc/macutil.h>
     30 #include <soc/drv.h>
     31 
     32 #include <bcm_int/esw_dispatch.h>
     33 #include <bcm_int/esw/portctrl.h>
     34 #include <bcm_int/esw/port.h>
     35 #include <bcm_int/esw/link.h>
     36 #include <bcm_int/esw/xgs5.h>
     37 
     38 #ifdef BCM_XGS3_SWITCH_SUPPORT
     39 #include <bcm_int/esw/mirror.h>
     40 #endif
     41 
     42 #include <bcm/error.h>
     43 #include <soc/firebolt.h>
     44 #include <bcm_int/esw/triumph.h>
     45 #include <bcm_int/esw/mbcm.h>
     46 
     47 #if defined(BCM_TRIDENT2_SUPPORT)
     48 #include <bcm_int/esw/trident2.h>
     49 #include <soc/trident2.h>
     50 #include <bcm_int/esw/trunk.h>
     51 #endif /* BCM_TRIDENT2_SUPPORT */
     52 
     53 #if defined(BCM_TOMAHAWK3_SUPPORT)
     54 #include <bcm_int/esw/pfc.h>
     55 #include <bcm_int/esw/tomahawk3.h>
     56 #endif /* BCM_TOMAHAWK3_SUPPOT */
     57 
     58 #if defined(BCM_MONTEREY_SUPPORT)
     59 #include <soc/monterey.h>
     60 #include <bcm_int/esw/monterey.h>
     61 #endif
     62 #ifdef SW_AUTONEG_SUPPORT
     63 #include <bcm_int/common/sw_an.h>
     64 #endif
     65 
     66 #ifdef BCM_HELIX5_SUPPORT
     67 #include <soc/helix5.h>
     68 #endif
     69 
     70 #ifdef PORTMOD_SUPPORT
     71 #include <soc/portmod/portmod.h>
     72 #include <soc/portmod/portmod_common.h>
     73 #include <soc/portmod/portmod_legacy_phy.h>
     74 #include <soc/esw/portctrl_internal.h>
     75 
     76 extern uint32_t phymod_dbg_mask;
     77 extern uint32_t phymod_dbg_addr;
     78 extern uint32_t phymod_dbg_lane;
     79 
     80 /*
     81  * Define:
     82  *      PORTCTRL_PORT_RESOLVE
     83  * Purpose:
     84  *      Converts a GPORT or non-GPORT format port into:
     85  *      - BCM local port '_lport'
     86  *      - Port type used in PortMod functions '_pport'
     87  */
     88 #define PORTCTRL_PORT_RESOLVE(_unit, _port, _lport, _pport)             \
     89     _bcm_esw_portctrl_port_resolve((_unit), (_port), (_lport), (_pport))
     90 
     91 /*
     92  * Define:
     93  *      PORTCTRL_INIT_CHECK
     94  * Purpose:
     95  *      Checks that Port Control module has been initialized for given
     96  *      unit.  If failure, it causes routine to return with BCM_E_INIT.
     97  */
     98 #define PORTCTRL_INIT_CHECK(_unit)    \
     99     SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(_unit))
    100 
    101 
    102 #define _ERR_MSG_MODULE_NAME           BSL_BCM_OTHER
    103 
    104 
    105 #define BCM_ESW_PORTCTRL_PHY_REG_INDIRECT _SHR_PORT_PHY_REG_INDIRECT
    106 #define BCM_ESW_PORTCTRL_PHYCTRL_PRBS_RX_ENABLE _SHR_PORT_PHY_CONTROL_PRBS_RX_ENABLE
    107 
    108 STATIC int
    109 _bcm_esw_portctrl_speed_chip_reconfigure(int unit, bcm_port_t port, int speed);
    110 extern int bcmi_esw_port_eee_cfg_set(int unit, bcm_port_t port, int value);
    111 
    112 /*
    113  * 8 Priority Groups supported.
    114  */
    115 #define PORTCTRL_PRIOROTY_GROUP_ID_MIN 0
    116 #define PORTCTRL_PRIOROTY_GROUP_ID_MAX 7
    117 
    118 #define PORTCTRL_AUTONEG_ABILITY_MAX_COUNT 20
    119 #define PORTCTRL_SPEED_ABILITY_MAX_COUNT 50
    120 #endif /* PORTMOD_SUPPORT */
    121 
    122 /*
    123  * Macros for use with encapsulation set related functions
    124  */
    125 #define BCM_ESW_PORTCTRL_CFG_ENCAP_MODE 1
    126 #define BCM_ESW_PORTCTRL_CFG_INTERFACE  2
    127 #define BCM_ESW_PORTCTRL_CFG_SPEED      3
    128 
    129 #define BCM_PA_ENCAP(e) \
    130     ((e == BCM_PORT_ENCAP_IEEE)                ? BCM_PA_ENCAP_IEEE                : \
    131      (e == BCM_PORT_ENCAP_HIGIG)               ? BCM_PA_ENCAP_HIGIG               : \
    132      (e == BCM_PORT_ENCAP_B5632)               ? BCM_PA_ENCAP_B5632               : \
    133      (e == BCM_PORT_ENCAP_HIGIG2)              ? BCM_PA_ENCAP_HIGIG2              : \
    134      (e == BCM_PORT_ENCAP_HIGIG2_LITE)         ? BCM_PA_ENCAP_HIGIG2_LITE         : \
    135      (e == BCM_PORT_ENCAP_HIGIG2_L2)           ? BCM_PA_ENCAP_HIGIG2_L2           : \
    136      (e == BCM_PORT_ENCAP_HIGIG2_IP_GRE)       ? BCM_PA_ENCAP_HIGIG2_IP_GRE       : \
    137      (e == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) ? BCM_PA_ENCAP_HIGIG_OVER_ETHERNET : \
    138      (e == BCM_PORT_ENCAP_CPRI)                ? BCM_PA_ENCAP_CPRI                : \
    139      (e == BCM_PORT_ENCAP_RSVD4)               ? BCM_PA_ENCAP_RSVD4               : 0)
    140 
    141 #ifdef PORTMOD_SUPPORT
    142 
    143 /*
    144  * Function:
    145  *      _bcm_esw_portctrl_port_resolve
    146  * Purpose:
    147  *      Converts the given BCM port type, bcm_gport_t, to
    148  *      the BCM local port type and the port type expected by
    149  *      the PortMod functions.
    150  * Parameters:
    151  *      unit     - (IN) Unit number.
    152  *      port     - (IN) BCM Port number, this can be in GPORT format.
    153  *      lport    - (OUT) Returns BCM logical local port number.
    154  *      pport    - (OUT) Returns port in expected PortMod port type.
    155  * Returns:
    156  *      BCM_E_xxx
    157  */
    158 STATIC int
    159 _bcm_esw_portctrl_port_resolve(int unit, bcm_gport_t port,
    160                                bcm_port_t *lport, portctrl_pport_t *pport)
    161 {
    162     /*
    163      * Currently, the PortMod library expects a logical local
    164      * port number, which is equivalent to the BCM port local port.
    165      */
    166     BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, lport));
    167 
    168     *pport = *lport;
    169     return BCM_E_NONE;
    170 }
    171 
    172 
    173 /*
    174  * Function:
    175  *      _bcm_esw_portctrl_from_portmod_ability
    176  * Purpose:
    177  *      Converts the _port_ability_t structure from PortMod to
    178  *      BCM _port_ability_t
    179  * Parameters:
    180  *      portmod_ability - (IN) PortMod _ability_ structure to convert.
    181  *      port_ability    - (OUT) Returns information in BCM bcm_port_ability_t.
    182  * Returns:
    183  *      None
    184  */
    185 STATIC void
    186 _bcm_esw_portctrl_from_portmod_ability(portmod_port_ability_t *portmod_ability,
    187                                        bcm_port_ability_t *port_ability)
    188 {
    189     /*
    190      * Currently, the portmod_port_ability_t definition uses
    191      * _shr_port_ability_t, which is used by the 
    192      * SOC soc_port_ability_t and BCM bcm_port_ability_t.
    193      */
    194     *port_ability = *portmod_ability;
    195 
    196     return;
    197 }
    198 
    199 /*
    200  * Function:
    201  *     _bcm_esw_portctrl_from_portmod_autoneg_ability
    202  * Purpose:
    203  *     Converts the portmod_port_speed_ability_t structure array
    204  *     to bcm_port_speed_ability_t structure array.
    205  * Parameters:
    206  *     unit        - (IN) device unit number
    207  *     num_ability - (IN) Number of abilities in the array.
    208  *     portmod_abilities - (IN) portmod_port_speed_ability_t array.
    209  *     max_num_abilities - (IN) maximum abilities the user array can take
    210  *     port_abilities - (OUT) bcm_port_speed_ability_t array.
    211  *     valid_abilities - (OUT) abilities supported by the device
    212  *
    213  * Returns:
    214  *     None.
    215  */
    216 STATIC int
    217 _bcm_esw_portctrl_from_portmod_autoneg_ability(int unit,
    218                                                int num_ability,
    219                                                portmod_port_speed_ability_t *portmod_abilities,
    220                                                int max_num_abilities,
    221                                                bcm_port_speed_ability_t *port_abilities,
    222                                                int *valid_abilities)
    223 {
    224     int i, rv = BCM_E_NONE;
    225     int valid = 0;
    226 
    227     for (i = 0; i < num_ability; i++) {
    228         if (BCM_ESW_PORT_DRV(unit)!= NULL) {
    229             if (BCM_ESW_PORT_DRV(unit)->device_speed_check != NULL) {
    230                 
    231                 /* We don't want to add speeds that may be supported by the
    232                  * port macro, but not the device */
    233                 rv = (BCM_ESW_PORT_DRV(unit)->device_speed_check(unit,
    234                                                  portmod_abilities[i].speed,
    235                                                  portmod_abilities[i].num_lanes));
    236                 if (BCM_FAILURE(rv)) {
    237                     continue;
    238                 }
    239             }
    240         }
    241 
    242         /* Do not write beyond the max size of the buffer */
    243         if (valid >= max_num_abilities) {
    244             rv = BCM_E_PARAM;
    245         } else {
    246             port_abilities[valid].speed = portmod_abilities[i].speed;
    247             port_abilities[valid].resolved_num_lanes = portmod_abilities[i].num_lanes;
    248             port_abilities[valid].fec_type = portmod_abilities[i].fec_type;
    249             port_abilities[valid].medium = portmod_abilities[i].medium;
    250             port_abilities[valid].pause = portmod_abilities[i].pause;
    251             port_abilities[valid].channel = portmod_abilities[i].channel;
    252             /* coverity[mixed_enums:FALSE] */
    253             port_abilities[valid].an_mode = portmod_abilities[i].an_mode;
    254         }
    255 
    256         /* Increase valid just so we know how many the device can support,
    257          * not just how many the PM supports */
    258         valid++;
    259     }
    260 
    261     if (BCM_FAILURE(rv)) {
    262         LOG_ERROR(BSL_LS_BCM_PORT,
    263                   (BSL_META_U(unit,
    264                                "ERROR: Buffer for abilities (%d) not "
    265                                "large enough for size (%d). )\n"),
    266                    max_num_abilities, valid));
    267         *valid_abilities = -1;
    268     } else {
    269         /* Set the number of valid abilities for the device */
    270         *valid_abilities = valid;
    271     }
    272 
    273     return rv;
    274 }
    275 
    276 /*
    277  * Function:
    278  *     _bcm_esw_portmod_from_portctrl_autoneg_ability
    279  * Purpose:
    280  *     Converts the bcm_port_speed_ability_t structure array
    281  *     to portmod_port_speed_ability_t sturcture array
    282  * Parameters:
    283  *     num_ability - (IN) Number of abilities in the array.
    284  *     port_abilities - (IN) bcm_port_speed_ability_t array.
    285  *     portmod_abilities - (OUT) portmod_port_speed_ability_t array.
    286  * Returns:
    287  *     None.
    288  */
    289 STATIC void
    290 _bcm_esw_portmod_from_portctrl_autoneg_ability(int num_ability,
    291                                                bcm_port_speed_ability_t *port_abilities,
    292                                                portmod_port_speed_ability_t *portmod_abilities)
    293 {
    294     int i;
    295 
    296     for (i = 0; i < num_ability; i++) {
    297         portmod_abilities[i].speed = port_abilities[i].speed;
    298         portmod_abilities[i].num_lanes = port_abilities[i].resolved_num_lanes;
    299         portmod_abilities[i].fec_type = port_abilities[i].fec_type;
    300         portmod_abilities[i].medium = port_abilities[i].medium;
    301         portmod_abilities[i].pause = port_abilities[i].pause;
    302         portmod_abilities[i].channel = port_abilities[i].channel;
    303         /* coverity[mixed_enums:FALSE] */
    304         portmod_abilities[i].an_mode = port_abilities[i].an_mode;
    305     }
    306 }
    307 
    308 /*
    309  * Function:
    310  *      _bcm_esw_portctrl_port_fifo_reset
    311  * Purpose:
    312  *      Toggle the port soft reset.
    313  * Parameters:
    314  *      unit    - (IN) Unit number.
    315  *      port    - (IN) Logical BCM Port number (non-GPORT).
    316  *      pport   - (IN) Port type expected by PortMod.
    317  * Returns:
    318  *      BCM_E_XXX
    319  * Notes:
    320  *      Must be called with PORT_LOCK held.
    321  */
    322 STATIC int
    323 _bcm_esw_portctrl_port_fifo_reset(int unit, bcm_port_t port,
    324                                   portctrl_pport_t pport)
    325 {
    326     int phy_port, block, bindex, i;
    327 
    328     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
    329     for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
    330         block = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
    331         if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) ||
    332             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORTB0) ||
    333             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLG2PORT) ||
    334             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_GXPORT) ||
    335             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLPORT)) {
    336             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
    337             PORTMOD_IF_ERROR_RETURN
    338                 (portmod_port_soft_reset_toggle(unit, pport, bindex));
    339             break;
    340         }
    341     }
    342 
    343     return BCM_E_NONE;
    344 }
    345 
    346 
    347 /*
    348  * Function:
    349  *      _bcm_esw_portctrl_port_soft_reset
    350  * Purpose:
    351  *      Release or hold OBM, cell assembly and port logic from/in reset.
    352  * Parameters:
    353  *      unit    - (IN) Unit number.
    354  *      port    - (IN) Logical BCM Port number (non-GPORT).
    355  *      pport   - (IN) Port type expected by PortMod.
    356  *      reset   - (IN) O: Release from reset.
    357  *                     1: Hold port in reset.
    358  * Returns:
    359  *      BCM_E_XXX
    360  * Notes:
    361  *      Must be called with PORT_LOCK held.
    362  */
    363 STATIC int
    364 _bcm_esw_portctrl_port_soft_reset(int unit, bcm_port_t port,
    365                                   portctrl_pport_t pport,
    366                                   int reset)
    367 {
    368     int phy_port;
    369     int block;
    370     int bindex;
    371     int i;
    372     int flags = PORTMOD_PORT_REG_ACCESS_DEFAULT;
    373 
    374     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
    375 
    376     for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
    377         block = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
    378 
    379         if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) ||
    380             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORTB0) ||
    381             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLG2PORT) ||
    382             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_GXPORT) ||
    383             (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLPORT)) {
    384             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
    385             PORTMOD_IF_ERROR_RETURN
    386                (portmod_port_soft_reset_set(unit, pport, bindex, reset, flags));
    387             break;
    388         }
    389     }
    390 
    391     return BCM_E_NONE;
    392 }
    393 
    394 
    395 /*
    396  * Function:
    397  *      _bcm_esw_portctrl_tx_fifo_empty
    398  * Purpose:
    399  *      Poll until the MAC TX FIFO is empty, or until
    400  *      it times out.
    401  * Parameters:
    402  *      unit    - (IN) Unit number.
    403  *      port    - (IN) Logical BCM Port number (non-GPORT).
    404  *      pport   - (IN) Port type expected by PortMod.
    405  * Returns:
    406  *      BCM_E_XXX
    407  * Notes:
    408  *      Must be called with PORT_LOCK held.
    409  */
    410 
    411 STATIC int
    412 _bcm_esw_portctrl_tx_fifo_empty(int unit, bcm_port_t port,
    413                                 portctrl_pport_t pport)
    414 {
    415     uint32 cell_count;
    416     soc_timeout_t to;
    417     int wait_time = 250000;
    418 
    419     if (SAL_BOOT_QUICKTURN) {
    420         wait_time *= 20;
    421     }
    422 
    423     /* Wait until MAC TX fifo cell count is 0 */
    424     soc_timeout_init(&to, wait_time, 0);
    425     for (;;) {
    426         PORTMOD_IF_ERROR_RETURN
    427             (portmod_port_txfifo_cell_cnt_get(unit, pport, &cell_count));
    428 
    429         if (cell_count == 0) {
    430             break;
    431         }
    432         if (soc_timeout_check(&to)) {
    433             LOG_ERROR(BSL_LS_BCM_PORT,
    434                       (BSL_META_UP(unit, port,
    435                                    "ERROR: u=%d p=%d timeout draining "
    436                                    "MAC TX FIFO (%d cells remain)\n"),
    437                        unit, port, cell_count));
    438             return BCM_E_INTERNAL;
    439         }
    440     }
    441 
    442     return BCM_E_NONE;
    443 }
    444 
    445 
    446 /*
    447  * Function:
    448  *      _bcm_esw_portctrl_drain_cells
    449  * Purpose:
    450  *      Drain cells for given port.
    451  * Parameters:
    452  *      unit    - (IN) Unit number.
    453  *      port    - (IN) Logical BCM Port number (non-GPORT).
    454  *      pport   - (IN) Port type expected by PortMod.
    455  * Returns:
    456  *      BCM_E_XXX
    457  * Notes:
    458  *      Must be called with PORT_LOCK held.
    459  */
    460 STATIC int
    461 _bcm_esw_portctrl_drain_cells(int unit, bcm_port_t port,
    462                               portctrl_pport_t pport)
    463 {
    464     portmod_drain_cells_t drain_cells;
    465     uint32 cell_count;
    466     soc_timeout_t to;
    467     int rv = BCM_E_NONE;
    468     int wait_time = 250000;
    469     int qmode = 0;
    470 
    471     if (SAL_BOOT_QUICKTURN) {
    472         wait_time *= 20;
    473     }
    474 
    475     PORTMOD_IF_ERROR_RETURN
    476         (portmod_port_drain_cell_get(unit, pport, &drain_cells));
    477 
    478     /* Start TX FIFO draining */
    479     PORTMOD_IF_ERROR_RETURN
    480         (portmod_port_drain_cell_start(unit, pport));
    481 
    482 #ifdef BCM_HELIX5_SUPPORT
    483     if (SOC_IS_HELIX5(unit)) {
    484        soc_helix5_port_qsgmii_mode_get(unit, pport, &qmode);
    485      }
    486 #endif
    487     /* Can't reset EP credit if mac is unimac, or else credit would be mismatched */
    488     if (!qmode) {
    489         /* Reset EP credit before de-assert SOFT_RESET */
    490         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    491     }
    492 
    493     /* De-assert SOFT_RESET to let the drain start */
    494     PORTMOD_IF_ERROR_RETURN
    495         (portmod_port_mac_reset_set(unit, pport, 0));
    496 
    497     /* Wait until mmu cell count is 0 */
    498     rv = soc_egress_drain_cells(unit, port, wait_time);
    499     if (BCM_E_NONE == rv) {
    500         /* Wait until TX fifo cell count is 0 */
    501         soc_timeout_init(&to, wait_time, 0);
    502         for (;;) {
    503             rv = portmod_port_txfifo_cell_cnt_get(unit, pport, &cell_count);
    504             if (BCM_E_NONE != rv) {
    505                 break;
    506             }
    507             if (cell_count == 0) {
    508                 break;
    509             }
    510             if (soc_timeout_check(&to)) {
    511                 LOG_ERROR(BSL_LS_BCM_PORT,
    512                           (BSL_META_UP(unit, port,
    513                                        "ERROR: u=%d p=%d timeout draining "
    514                                        "TX FIFO (%d cells remain)\n"),
    515                                        unit, port, cell_count));
    516                 rv = BCM_E_INTERNAL;
    517                 break;
    518             }
    519         }
    520     }
    521    
    522     /* Stop TX FIFO draining */
    523     PORTMOD_IF_ERROR_RETURN
    524         (portmod_port_drain_cell_stop(unit, pport, &drain_cells));
    525 
    526     return rv;
    527 }
    528 
    529 
    530 /*
    531  * Function:
    532  *      _bcm_esw_portctrl_mmu_flush
    533  * Purpose:
    534  *      Flush port in MMU.
    535  * Parameters:
    536  *      unit    - (IN) Unit number.
    537  *      port    - (IN) Logical BCM Port number (non-GPORT).
    538  *      pport   - (IN) Port type expected by PortMod.
    539  * Returns:
    540  *      BCM_E_XXX
    541  * Notes:
    542  *      Must be called with PORT_LOCK hed.
    543  */
    544 
    545 STATIC int
    546 _bcm_esw_portctrl_mmu_flush(int unit, bcm_port_t port,
    547                             portctrl_pport_t pport)
    548 {
    549     portmod_pfc_control_t pfc, prev_pfc;
    550     portmod_llfc_control_t llfc, prev_llfc;
    551     portmod_pause_control_t pause, prev_pause;
    552     int rv = BCM_E_NONE;
    553     int wait_time = 250000;
    554 
    555     if (SAL_BOOT_QUICKTURN) {
    556         wait_time *= 20;
    557     }
    558 
    559 
    560     /* Disable flow control (store current settings) */
    561     PORTMOD_IF_ERROR_RETURN
    562         (portmod_port_pause_control_get(unit, pport, &pause));
    563     prev_pause = pause;
    564     pause.rx_enable = 0;
    565     PORTMOD_IF_ERROR_RETURN
    566         (portmod_port_pause_control_set(unit, pport, &pause));
    567 
    568     PORTMOD_IF_ERROR_RETURN
    569         (portmod_port_pfc_control_get(unit, pport, &pfc));
    570     prev_pfc = pfc;
    571     pfc.rx_enable = 0;
    572     PORTMOD_IF_ERROR_RETURN
    573         (portmod_port_pfc_control_set(unit, pport, &pfc));
    574 
    575     PORTMOD_IF_ERROR_RETURN
    576         (portmod_port_llfc_control_get(unit, pport, &llfc));
    577     prev_llfc = llfc;
    578     llfc.rx_enable = 0;
    579     PORTMOD_IF_ERROR_RETURN
    580         (portmod_port_llfc_control_set(unit, pport, &llfc));
    581 
    582     /* Wait until mmu cell count is 0 */
    583     rv = soc_egress_drain_cells(unit, port, 250000);
    584 
    585     /* Restore flow control settings */
    586     PORTMOD_IF_ERROR_RETURN
    587         (portmod_port_pause_control_set(unit, pport, &prev_pause));
    588     PORTMOD_IF_ERROR_RETURN
    589         (portmod_port_pfc_control_set(unit, pport, &prev_pfc));
    590     PORTMOD_IF_ERROR_RETURN
    591         (portmod_port_llfc_control_set(unit, pport, &prev_llfc));
    592 
    593     /*
    594      * Delay 1 usec to ensure all cells drained from MMU
    595      * during the flush have left EP.
    596      */
    597     sal_udelay(1);
    598 
    599     return rv;
    600 }
    601 
    602 
    603 /*
    604  * Function:
    605  *      _bcm_esw_portctrl_enable_set
    606  * Purpose:
    607  *      Core function to enable or disable a port.
    608  *      This includes all the necessary steps to correctly bring
    609  *      up or down a port.
    610  *
    611  *      The sequence to bring a port UP or DOWN requires a series of
    612  *      interleaved steps that falls inside and outside the PortMod library.
    613  *      Some operations need to occur in the xxPORT, or MAC, or PHY blocks,
    614  *      whereas others need to occur at the EP, or MMU blocks.
    615  *
    616  *      There are two approaches:
    617  *      1) SDK drives the logic calling the corresponding PortMod and
    618  *         non-PortMod routines.
    619  *      2) PortMod drive the logic calling callback routines provided
    620  *         by SDK to perform operations outside the PortMod.
    621  *
    622  *      At the moment (1) is implemented.
    623  * Parameters:
    624  *      unit    - (IN) Unit number.
    625  *      port    - (IN) Logical BCM Port number (non-GPORT).
    626  *      pport   - (IN) Port type expected by PortMod.
    627  *      flags   - (IN) Indicates whether to enable PHY, MAC, or both.
    628  *      enable  - (IN) Indicates whether to enable or disable port.
    629  * Returns:
    630  *      BCM_E_XXX
    631  * Notes:
    632  *      Must be called with PORT_LOCK held.
    633  *      This follows the new sequence provided by the design team.
    634  *
    635  *      Currently, the PortMod API portmod_port_enable_set() do enable/disable
    636  *      the MAC does not have the complete bringup sequence.  Callers
    637  *      should be calling this routine instead to bring the port up or down
    638  *      properly.
    639  */
    640 STATIC int
    641 _bcm_esw_portctrl_enable_set(int unit, bcm_port_t port,
    642                              portctrl_pport_t pport,
    643                              int flags, int enable)
    644 {
    645     pbmp_t mask;
    646     int flags_temp;
    647     int mac_reset;
    648     int wait_us, mngport;
    649 #if defined(BCM_MONTEREY_SUPPORT)
    650     uint32 preemption_enable = 0 ;
    651 #endif
    652     if (enable) {
    653         /*
    654          * PORT UP
    655          */
    656 
    657         /* Enable PHY if PHY flag is set */
    658         if (PORTMOD_PORT_ENABLE_PHY_GET(flags)) {
    659             flags_temp = flags;
    660             PORTMOD_PORT_ENABLE_MAC_CLR(flags_temp);
    661             PORTMOD_IF_ERROR_RETURN
    662                 (portmod_port_enable_set(unit, pport, flags_temp, 1));
    663         }
    664 
    665         /*
    666          * Check if MAC needs to be modified based on whether
    667          * we want to enable or disable the MAC.
    668          * If not changes are needed, assume port is
    669          * already UP and just skip enabling MAC.
    670          */
    671         PORTMOD_IF_ERROR_RETURN
    672             (portmod_port_mac_reset_check(unit, pport,
    673                                           enable, &mac_reset));
    674         /*
    675          * If MAC flag is set and MAC is not UP yet, continue with rest of
    676          * sequence to bring the port UP, including resetting credits,
    677          * cells draining, etc.
    678          */
    679         if (mac_reset && PORTMOD_PORT_ENABLE_MAC_GET(flags)) {
    680 
    681             if (soc_feature(unit, soc_feature_port_leverage)) {
    682                 if (BCM_ESW_PORT_DRV(unit)!= NULL) {
    683                     if (BCM_ESW_PORT_DRV(unit)->port_enable_set != NULL) {
    684                         BCM_IF_ERROR_RETURN
    685                             (BCM_ESW_PORT_DRV(unit)->port_enable_set(unit,
    686                                                                      port,
    687                                                                      1));
    688                     }
    689                 }
    690             } else {
    691                 /*
    692                  * Initialize EP credits,
    693                  * release EDB port buffer reset and enable cell request
    694                  * generation in EP.
    695                  */
    696                 SOC_IF_ERROR_RETURN
    697                     (soc_port_egress_buffer_sft_reset(unit, port, 0));
    698 
    699                 /* Release OBM, cell assembly and port logic from reset */
    700                 BCM_IF_ERROR_RETURN
    701                     (_bcm_esw_portctrl_port_soft_reset(unit, port, pport, 0));
    702 
    703                 /* Release Ingress buffers from reset */
    704                 SOC_IF_ERROR_RETURN
    705                     (soc_port_ingress_buffer_reset(unit, port, 0));
    706 
    707                 /* Enable MAC TX and RX and take MAC out of reset */
    708                 PORTMOD_IF_ERROR_RETURN
    709                     (portmod_port_drain_cells_rx_enable(unit, pport, 1));
    710 
    711             }
    712         }
    713         /* Add port to EPC_LINK and ING_DEST_PORT_ENABLE */
    714         soc_link_mask2_get(unit, &mask);
    715         SOC_PBMP_PORT_ADD(mask, port);
    716         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    717 
    718 #if defined(BCM_MONTEREY_SUPPORT)
    719         if (SOC_IS_MONTEREY(unit) && PORTMOD_PORT_ENABLE_MAC_GET(flags)) { 
    720             SOC_IF_ERROR_RETURN(
    721             bcmi_mn_preemption_capability_get(unit , port , &preemption_enable)); 
    722             if (preemption_enable) {  
    723                 portmod_port_discard_set( unit,  port, 1);
    724                 bcm_monterey_send_packetport(unit , port , 0 , 250);
    725                 portmod_port_discard_set( unit, port, 0);
    726         }
    727         } 
    728 #endif
    729     } else {
    730         /*
    731          * PORT DOWN
    732          */
    733 
    734         /*
    735          * Remove from EPC_LINK and ING_DEST_PORT_ENABLE to prevent packets
    736          * queued to this port from TX
    737          */
    738         soc_link_mask2_get(unit, &mask);
    739         SOC_PBMP_PORT_REMOVE(mask, port);
    740         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    741 
    742         /* Wait 8ms if management port configured to 10/100, else 80 us.
    743          * please refer TH2/TD2p_uA_flexport.pdf, Section 6.6.1 */
    744         wait_us = 80;
    745         SOC_PBMP_ITER(PBMP_MANAGEMENT(unit), mngport) {
    746             if (SOC_INFO(unit).port_init_speed[mngport] <= 100) {
    747                 wait_us = 8000;
    748                 break;
    749             }
    750         }
    751         if (SAL_BOOT_QUICKTURN) {
    752             wait_us *= 10000;
    753         }
    754         sal_usleep(wait_us);
    755 
    756         /*
    757          * Due to a HW issue, the MAC RX needs to be disabled
    758          * before disabling PHY (SW workaround)
    759          */
    760 
    761         /*
    762          * If only PHY flag is set, just disable PHY.
    763          * Otherwise, PHY is disabled later along with the MAC
    764          * following the right order.
    765          */
    766         if (PORTMOD_PORT_ENABLE_PHY_GET(flags) &&
    767             !PORTMOD_PORT_ENABLE_MAC_GET(flags)) {
    768             PORTMOD_IF_ERROR_RETURN
    769                 (portmod_port_enable_set(unit, pport, flags, 0));
    770         }
    771 
    772         /*
    773          * If MAC flag is set, continue with rest of sequence
    774          * to bring the port DOWN.
    775          */
    776         if (PORTMOD_PORT_ENABLE_MAC_GET(flags)) {
    777 
    778             /*
    779              * Disable MAC RX and PHY (if flag is supplied).
    780              *
    781              * NOTE: MAC RX needs to be disabled before the TSC.
    782              */
    783             PORTMOD_IF_ERROR_RETURN
    784                 (portmod_port_rx_mac_enable_set(unit, pport, 0));
    785             if (PORTMOD_PORT_ENABLE_PHY_GET(flags)) {
    786                 PORTMOD_IF_ERROR_RETURN
    787                     (portmod_port_enable_set(unit, pport,
    788                                              PORTMOD_PORT_ENABLE_PHY, 0));
    789             }
    790 
    791             /*
    792              * Check if MAC needs to be modified based on whether
    793              * we want to enable or disable the MAC.
    794              * If not changes are needed, assume port is
    795              * already DOWN and just return.
    796              */
    797             PORTMOD_IF_ERROR_RETURN
    798                 (portmod_port_mac_reset_check(unit, pport,
    799                                               enable, &mac_reset));
    800             if (!mac_reset) {
    801                 return BCM_E_NONE;
    802             }
    803 
    804             if (soc_feature(unit, soc_feature_port_leverage)) {
    805                 if (BCM_ESW_PORT_DRV(unit)!= NULL) {
    806                     if (BCM_ESW_PORT_DRV(unit)->port_enable_set != NULL) {
    807                         BCM_IF_ERROR_RETURN
    808                             (BCM_ESW_PORT_DRV(unit)->port_enable_set(unit,
    809                                                                      port,
    810                                                                      0));
    811                     }
    812                 }
    813             } else {
    814                 /* Hold MAC in reset state */
    815                 BCM_IF_ERROR_RETURN
    816                     (portmod_port_mac_reset_set(unit, pport, 1));
    817 
    818 
    819                 /* Put port in flush state using MAC discard */
    820                 PORTMOD_IF_ERROR_RETURN
    821                     (portmod_port_discard_set(unit, pport, 1));
    822 
    823                 /* Remove MAC reset */
    824                 BCM_IF_ERROR_RETURN
    825                     (portmod_port_mac_reset_set(unit, pport, 0));
    826 
    827                 /* Reset Ingress buffers */
    828                 SOC_IF_ERROR_RETURN
    829                     (soc_port_ingress_buffer_reset(unit, port, 1));
    830 
    831 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
    832                 if (SOC_IS_TRIDENT2PLUS(unit)) {
    833                     /* Hold OBM in reset will clear OBM counters.
    834                      * Clear in counter thread accordingly.
    835                      */
    836                     SOC_IF_ERROR_RETURN
    837                         (soc_td2_obm_counters_reset(unit, port));
    838                 }
    839 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
    840                 /* Hold OBM, cell assembly and port logic in reset */
    841                 BCM_IF_ERROR_RETURN
    842                     (_bcm_esw_portctrl_port_soft_reset(unit, port, pport, 1));
    843 
    844                 /* MMU flush */
    845                 BCM_IF_ERROR_RETURN
    846                     (_bcm_esw_portctrl_mmu_flush(unit, port, pport));
    847 
    848                 /* Reset Egress buffers */
    849                 SOC_IF_ERROR_RETURN
    850                     (soc_port_egress_buffer_sft_reset(unit, port, 1));
    851 
    852                 /* Poll until MAC TX FIFO is empty */
    853                 BCM_IF_ERROR_RETURN
    854                     (_bcm_esw_portctrl_tx_fifo_empty(unit, port, pport));
    855 
    856                 /* Disable MAC TX and power down TSC */
    857                 PORTMOD_IF_ERROR_RETURN
    858                     (portmod_port_tx_down(unit, pport));
    859             }
    860         } /* MAC flag is set */
    861 
    862     } /* PORT DOWN */
    863 
    864     return BCM_E_NONE;
    865 }
    866 
    867 
    868 /*
    869  * Function:
    870  *      _bcm_esw_portctrl_egress_queue_drain
    871  * Purpose:
    872  *      Drain the egress queues without bringing down the port.
    873  * Parameters:
    874  *      unit    - (IN) Unit number.
    875  *      port    - (IN) Logical BCM Port number (non-GPORT).
    876  *      pport   - (IN) Port type expected by PortMod.
    877  * Returns:
    878  *      BCM_E_XXX
    879  * Notes:
    880  *      Must be called with PORT_LOCK held.
    881  *      Helper to bcm_esw_portctrl_egress_queue_drain.
    882  */
    883 STATIC int
    884 _bcm_esw_portctrl_egress_queue_drain(int unit, bcm_port_t port,
    885                                      portctrl_pport_t pport)
    886 {
    887     uint64 mac_ctrl;
    888     int rx_enable = 0;
    889     pbmp_t mask;
    890     int is_active = 0;
    891     int qmode = 0;
    892 
    893     PORTMOD_IF_ERROR_RETURN
    894         (portmod_port_egress_queue_drain_get(unit, pport,
    895                                              &mac_ctrl, &rx_enable));
    896 
    897     /* Remove port from EPC_LINK */
    898     soc_link_mask2_get(unit, &mask);
    899     if (SOC_PBMP_MEMBER(mask, port)) {
    900         is_active = 1;
    901         SOC_PBMP_PORT_REMOVE(mask, port);
    902         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    903     }
    904 
    905     /* Drain cells */
    906     BCM_IF_ERROR_RETURN
    907         (_bcm_esw_portctrl_drain_cells(unit, port, pport));
    908 
    909     /* Reset port FIFO */
    910     BCM_IF_ERROR_RETURN
    911         (_bcm_esw_portctrl_port_fifo_reset(unit, port, pport));
    912 
    913     /* Put port into SOFT_RESET */
    914     PORTMOD_IF_ERROR_RETURN
    915         (portmod_port_mac_reset_set(unit, pport, 1));
    916 
    917 #ifdef BCM_HELIX5_SUPPORT
    918     if (SOC_IS_HELIX5(unit)) {
    919        soc_helix5_port_qsgmii_mode_get(unit, pport, &qmode);
    920      }
    921 #endif
    922     /* Can't reset EP credit if mac is unimac, or else credit would be mismatched */
    923     if (!qmode) {
    924         /* Reset EP credit before de-assert SOFT_RESET */
    925         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    926     }
    927 
    928     /* Enable TX, set RX, de-assert SOFT_RESET */
    929     PORTMOD_IF_ERROR_RETURN
    930         (portmod_port_egress_queue_drain_rx_en(unit, pport, rx_enable));
    931 
    932     /* Restore XLMAC_CTRL to original value */
    933     PORTMOD_IF_ERROR_RETURN
    934         (portmod_port_mac_ctrl_set(unit, pport, mac_ctrl));
    935 
    936     /* Add port to EPC_LINK */
    937     if(is_active) {
    938         soc_link_mask2_get(unit, &mask);
    939         SOC_PBMP_PORT_ADD(mask, port);
    940         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    941     }
    942  
    943     return BCM_E_NONE;
    944 }
    945 
    946 /*
    947  * Function:
    948  *      _bcm_esw_portctrl_interface_config_set
    949  * Purpose:
    950  *      Core function to set the port interface configuration.
    951  * Parameters:
    952  *      unit    - (IN) Unit number.
    953  *      port    - (IN) Logical BCM Port number (non-GPORT).
    954  *      pport   - (IN) Port type expected by PortMod.
    955  *      if_cfg  - (IN) Port Configuration to set.
    956  * Returns:
    957  *      BCM_E_XXX
    958  * Notes:
    959  *      Must be called with PORT_LOCK held.
    960  *
    961  *      SDK drivers should NOT call portmod_port_interface_config_set()
    962  *      directly, expect for this routine.  Drivers should call
    963  *      this routine instead to set the port interface configuration.
    964  *
    965  *      In order to change a port inteface configuration, the port must
    966  *      be properly be disabled and then re-enabled back.  Since the
    967  *      port bringup sequence is currenlty in the SDK and not in the PortMod
    968  *      library, the complete function to modify the port configuration will
    969  *      resides in the SDK driver.
    970  */
    971 STATIC int
    972 _bcm_esw_portctrl_interface_config_set(int unit, bcm_port_t port,
    973                                        portctrl_pport_t pport,
    974                                        portmod_port_interface_config_t *if_cfg,
    975                                        uint32 all_phy)
    976 {
    977     int enable, phy_init_flag = PORTMOD_INIT_F_EXTERNAL_MOST_ONLY;
    978 
    979     PORTCTRL_INIT_CHECK(unit);
    980 
    981     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
    982 
    983     PORTMOD_IF_ERROR_RETURN
    984         (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, &enable));
    985 
    986     if (enable) {
    987         /* Disable port */
    988         BCM_IF_ERROR_RETURN
    989             (_bcm_esw_portctrl_enable_set(unit, port, pport,
    990                                           PORTMOD_PORT_ENABLE_MAC, 0));
    991     }
    992 
    993     if (if_cfg->encap_mode & BCM_PORT_ENCAP_CPRI) {
    994         if_cfg->interface_modes |= PHYMOD_INTF_MODES_HIGIG;
    995     } else if (if_cfg->encap_mode & BCM_PORT_ENCAP_HIGIG2) {
    996         if_cfg->interface_modes |= PHYMOD_INTF_MODES_HIGIG;
    997     } else {
    998         if_cfg->interface_modes &= ~PHYMOD_INTF_MODES_HIGIG;
    999     }
   1000 
   1001     if (all_phy){
   1002         phy_init_flag = PORTMOD_INIT_F_ALL_PHYS;
   1003     }
   1004 
   1005     PORTMOD_IF_ERROR_RETURN
   1006         (portmod_port_interface_config_set(unit, pport, if_cfg, phy_init_flag));
   1007 
   1008     if (enable) {
   1009         /* Re-enable port */
   1010         BCM_IF_ERROR_RETURN
   1011             (_bcm_esw_portctrl_enable_set(unit, port, pport,
   1012                                           PORTMOD_PORT_ENABLE_MAC, 1));
   1013     }
   1014 
   1015     return BCM_E_NONE;
   1016 }
   1017 
   1018 /*
   1019  * Function:
   1020  *      _bcm_esw_portctrl_speed_config_set
   1021  * Purpose:
   1022  *      Core function to set the port speed configuration.
   1023  * Parameters:
   1024  *      unit    - (IN) Unit number.
   1025  *      port    - (IN) Logical BCM Port number (non-GPORT).
   1026  *      pport   - (IN) Port type expected by PortMod.
   1027  *      sp_cfg  - (IN) Port Configuration to set.
   1028  * Returns:
   1029  *      BCM_E_XXX
   1030  * Notes:
   1031  *      Must be called with PORT_LOCK held.
   1032  *
   1033  *      SDK drivers should NOT call portmod_port_speed_config_set()
   1034  *      directly, expect for this routine.  Drivers should call
   1035  *      this routine instead to set the port interface configuration.
   1036  *
   1037  *      In order to change a port inteface configuration, the port must
   1038  *      be properly be disabled and then re-enabled back.  Since the
   1039  *      port bringup sequence is currenlty in the SDK and not in the PortMod
   1040  *      library, the complete function to modify the port configuration will
   1041  *      resides in the SDK driver.
   1042  */
   1043 STATIC int
   1044 _bcm_esw_portctrl_speed_config_set(int unit, bcm_port_t port,
   1045                                        portctrl_pport_t pport,
   1046                                        portmod_speed_config_t *sp_cfg)
   1047 {
   1048     int enable;
   1049 
   1050     PORTCTRL_INIT_CHECK(unit);
   1051 
   1052     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1053 
   1054     PORTMOD_IF_ERROR_RETURN
   1055         (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, &enable));
   1056 
   1057     if (enable) {
   1058         /* Disable port */
   1059         BCM_IF_ERROR_RETURN
   1060             (_bcm_esw_portctrl_enable_set(unit, port, pport,
   1061                                           PORTMOD_PORT_ENABLE_MAC, 0));
   1062     }
   1063 
   1064     PORTMOD_IF_ERROR_RETURN
   1065         (portmod_port_speed_config_set(unit, pport, sp_cfg));
   1066 
   1067     if (enable) {
   1068         /* Re-enable port */
   1069         BCM_IF_ERROR_RETURN
   1070             (_bcm_esw_portctrl_enable_set(unit, port, pport,
   1071                                           PORTMOD_PORT_ENABLE_MAC, 1));
   1072     }
   1073 
   1074     return BCM_E_NONE;
   1075 }
   1076 #endif /* PORTMOD_SUPPORT */
   1077 
   1078 /*
   1079  * Function:
   1080  *      bcmi_esw_portctrl_probe
   1081  * Purpose:
   1082  *      Probe given port and add to Portmod.
   1083  * Parameters:
   1084  *      unit      - (IN) Unit number.
   1085  *      port      - (IN) Port number.
   1086  *      okay      - (OUT) Returns true is port was successfully added.
   1087  * Returns:
   1088  *      BCM_E_NONE
   1089  *      BCM_E_XXX
   1090  * Notes:
   1091  *     If port is already attached/added in the PortMod, port
   1092  *     is first removed(detached) and then added again.
   1093  */
   1094 int
   1095 bcmi_esw_portctrl_probe(int unit, bcm_gport_t port, int init_flag, void *add_info,
   1096                         int *okay)
   1097 {
   1098 #ifdef PORTMOD_SUPPORT
   1099     portmod_pbmp_t p_pbmp;
   1100     int rv = BCM_E_NONE, valid, flags=0, lane=0, num_lanes, speed, physical_port;
   1101     portctrl_pport_t pport;
   1102     bcm_port_if_t intf;
   1103     portmod_dispatch_type_t pm_type;
   1104 #ifdef PORTMOD_PM8X50_SUPPORT
   1105     portmod_pm_capability_t pm_cap;
   1106     int phy_port, pm, lanes_per_pm;
   1107 #endif
   1108 
   1109     PORTCTRL_INIT_CHECK(unit);
   1110     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1111 
   1112     *okay = FALSE;
   1113 
   1114     /* Check if port is already in PM */
   1115     rv = portmod_port_is_valid(unit, pport, &valid);
   1116     if (PORTMOD_FAILURE(rv)) {
   1117         return rv;
   1118     }
   1119 
   1120 
   1121     /* Remove port from PM if this has been already added */
   1122     if (valid) {
   1123         if ((!init_flag) || (init_flag == PORTMOD_PORT_ADD_F_INIT_CORE_PROBE)) {
   1124             rv = portmod_port_pm_type_get(unit, port, &port, &pm_type);
   1125             if (rv != BCM_E_NONE) {
   1126                 return rv;
   1127             }
   1128 #ifdef PORTMOD_PM8X50_SUPPORT
   1129             if (pm_type == portmodDispatchTypePm8x50) {
   1130                 rv = BCM_E_NONE;
   1131             } else
   1132 #endif
   1133             {
   1134                 rv = bcm_esw_port_interface_get(unit, port, &intf);
   1135                 /* Don't update speed if the port is attached to PHY_NULL */
   1136                 if (BCM_SUCCESS(rv) && (intf != SOC_PORT_IF_NULL)) {
   1137                     speed = SOC_INFO(unit).port_init_speed[port] > 0 ?
   1138                             SOC_INFO(unit).port_init_speed[port] :
   1139                             SOC_INFO(unit).port_speed_max[port];
   1140                     rv = _bcm_esw_portctrl_speed_chip_reconfigure(unit, port, speed);
   1141                 }
   1142              }
   1143             if (BCM_SUCCESS(rv)) {
   1144                 PORT_LOCK(unit);
   1145                 /* PortMod requires port to be disabled before removing it */
   1146                 PORTMOD_PORT_ENABLE_PHY_SET(flags);
   1147                 PORTMOD_PORT_ENABLE_MAC_SET(flags);
   1148                 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0);
   1149                 if (BCM_SUCCESS(rv)) {
   1150                     rv = soc_esw_portctrl_delete(unit, pport);
   1151 #ifdef PORTMOD_PM8X50_SUPPORT
   1152                     /* for PM8x50 need to set vco to reconfigure because since
   1153                      * the port got deleted, the VCOs have been reset in the
   1154                      * portmod driver */
   1155                     if (pm_type == portmodDispatchTypePm8x50) {
   1156                         phy_port = SOC_INFO(unit).port_l2p_mapping[pport];
   1157                         PORTMOD_IF_ERROR_RETURN(
   1158                             portmod_pm_capability_get(unit, pm_type, &pm_cap));
   1159                         lanes_per_pm = pm_cap.pm_capability.pm8x50_cap.num_lanes;
   1160                         pm = (phy_port - 1) / lanes_per_pm;
   1161                         SOC_INFO(unit).pm_vco_info[pm].is_tvco_new = 1;
   1162                         SOC_INFO(unit).pm_vco_info[pm].is_ovco_new = 1;
   1163                         SOC_IF_ERROR_RETURN(
   1164                                 soc_esw_portctrl_pm_vco_reconfigure(unit));
   1165                     }
   1166 #endif
   1167                 }
   1168                 PORT_UNLOCK(unit);
   1169             }
   1170         }
   1171     }
   1172 
   1173     /* Add port to PM */
   1174     if (SOC_SUCCESS(rv)) {
   1175         /* Attach external PHY to Portmod
   1176          * Don't attach external PHY to Portmod if port is inactive, like "portmap_2=2:10:i" for flexport
   1177          */
   1178         if (((!init_flag) || (init_flag == PORTMOD_PORT_ADD_F_INIT_CORE_PROBE)) &&
   1179              !SOC_PBMP_MEMBER(SOC_INFO(unit).all.disabled_bitmap, port)) {
   1180             PORTMOD_PBMP_CLEAR(p_pbmp);
   1181             num_lanes = SOC_INFO(unit).port_num_lanes[port];
   1182             if(num_lanes == 10) {
   1183                 num_lanes=12;
   1184             }
   1185             for (lane = 0; lane < num_lanes; lane++) {
   1186                 PORT_LOCK(unit);
   1187                 physical_port = SOC_INFO(unit).port_l2p_mapping[port];
   1188 #ifdef BCM_TRIDENT3_SUPPORT
   1189                 /*To support the 2nd MGMT port, convert its physical port to the dummy port number 131 on TD3.*/
   1190                 if((SOC_IS_TRIDENT3(unit)) && (physical_port == 128) && (SOC_PBMP_MEMBER(SOC_INFO(unit).management_pbm, port))){
   1191                     physical_port = 131;
   1192                 }
   1193 #endif /* BCM_TRIDENT3_SUPPORT */
   1194 #ifdef BCM_TOMAHAWK3_SUPPORT
   1195                 /* Tomahawk 3's Management Port Macro requires a spacing between
   1196                  * the lanes, so even though the two management ports' physical
   1197                  * ports are 257 and 258, the lane needs to be the next one,
   1198                  * so logical port 118 being mapped to physical port 258 needs
   1199                  * to pass 259 to portmod because portmod only recognizes lane
   1200                  * 0 (physical port 257) and lane 2 (physial port 259).
   1201                  */
   1202                 if (SOC_IS_TOMAHAWK3(unit) && port == 118) {
   1203                     physical_port = 259;
   1204                 }
   1205 #endif
   1206                 portmod_xphy_lane_detach(unit, physical_port+lane, 1);
   1207                 PORT_UNLOCK(unit);
   1208                 PORTMOD_PBMP_PORT_ADD(p_pbmp, physical_port+lane);
   1209             }
   1210             PORT_LOCK(unit);
   1211             rv = soc_esw_portctrl_setup_ext_phy_add(unit, port, &p_pbmp);
   1212             PORT_UNLOCK(unit);
   1213             if (SOC_FAILURE(rv)) {
   1214                 return rv;
   1215             }
   1216         }
   1217         PORT_LOCK(unit);
   1218         rv = soc_esw_portctrl_add(unit, port, init_flag, add_info);
   1219         PORT_UNLOCK(unit);
   1220     }
   1221 
   1222     if (SOC_SUCCESS(rv)) {
   1223         if ((init_flag == PORTMOD_PORT_ADD_F_INIT_PASS2) || !init_flag) {
   1224             /* Probe function should leave port disabled */
   1225             PORT_LOCK(unit);
   1226             rv = _bcm_esw_portctrl_enable_set(unit, port, pport,
   1227                                    PORTMOD_PORT_ENABLE_PHY, 0);
   1228             PORT_UNLOCK(unit);
   1229             if (SOC_FAILURE(rv)) {
   1230                 return rv;
   1231             }
   1232         }
   1233     }
   1234 
   1235     *okay = TRUE;
   1236 
   1237     return rv;
   1238 
   1239 #else  /* PORTMOD_SUPPORT */
   1240     return BCM_E_UNAVAIL;
   1241 #endif /* PORTMOD_SUPPORT */
   1242 }
   1243 
   1244 
   1245 /*
   1246  * Function:
   1247  *      bcmi_esw_portctrl_probe_pbmp
   1248  * Purpose:
   1249  *      Probe give port bitmap to identify which ports to add to Portmod.
   1250  * Parameters:
   1251  *      unit      - (IN) Unit number.
   1252  *      pbmp      - (IN) Port bitmap.
   1253  *      okay_pbmp - (OUT) Port bitmap okay.
   1254  * Returns:
   1255  *      BCM_E_NONE
   1256  *      BCM_E_XXX
   1257  */
   1258 int
   1259 bcmi_esw_portctrl_probe_pbmp(int unit, pbmp_t pbmp, pbmp_t *okay_pbmp)
   1260 {
   1261 #ifdef PORTMOD_SUPPORT
   1262     pbmp_t     lcl_pbmp;
   1263     soc_port_t port;
   1264     int okay = 0;
   1265     int rv = BCM_E_NONE;
   1266     portctrl_pport_t pport;
   1267     phymod_operation_mode_t phy_op_mode;
   1268     _bcm_port_info_t *port_info = NULL;
   1269     portmod_port_add_info_t *add_info = NULL;
   1270     portmod_port_add_info_t *port_add_info = NULL;
   1271     int count = 0;
   1272     int physical_port;
   1273 #ifdef FW_BCAST_DOWNLOAD
   1274     int bcast_flag, crc_en;
   1275 #endif
   1276 
   1277     PORTCTRL_INIT_CHECK(unit);
   1278 
   1279     SOC_PBMP_CLEAR(lcl_pbmp);
   1280     SOC_PBMP_CLEAR(*okay_pbmp);
   1281 
   1282     PBMP_ITER(pbmp, port) {
   1283         /* Skip RCPU ports */
   1284 #ifdef BCM_RCPU_SUPPORT
   1285         if (SOC_IS_RCPU_ONLY(unit) &&
   1286             SOC_PORT_VALID(unit, RCPU_PORT(unit)) &&
   1287             BCM_PBMP_MEMBER(pbmp, RCPU_PORT(unit))) {
   1288             continue;
   1289         }
   1290 #endif /* BCM_RCPU_SUPPORT */
   1291         if (IS_TDM_PORT(unit, port)) {
   1292             continue;
   1293         }
   1294         SOC_PBMP_PORT_ADD(lcl_pbmp, port);
   1295     }
   1296 
   1297     if (!SOC_WARM_BOOT(unit)) {
   1298         SOC_PBMP_COUNT(pbmp, count);
   1299 
   1300         add_info = sal_alloc(sizeof(portmod_port_add_info_t)*count,
   1301                              "portmod_port_add_info_t");
   1302         if (add_info == NULL) {
   1303             rv = SOC_E_MEMORY;
   1304             return rv;
   1305         }
   1306 
   1307         /*step1: probe Serdes and external PHY core*/
   1308         count = 0;
   1309         PBMP_ITER(lcl_pbmp, port) {
   1310             port_add_info = add_info + count;
   1311             rv = bcmi_esw_portctrl_probe(unit, port,
   1312                        PORTMOD_PORT_ADD_F_INIT_CORE_PROBE,
   1313                        port_add_info, &okay);
   1314             if (BCM_FAILURE(rv)) {
   1315                 goto cleanup;
   1316             }
   1317 
   1318             count++;
   1319         }
   1320 
   1321         /*step2 : initialize PASS1 for SerDes and external PHY*/
   1322         count = 0;
   1323         PBMP_ITER(lcl_pbmp, port) {
   1324             port_add_info = add_info + count;
   1325             rv = bcmi_esw_portctrl_probe(unit, port, 
   1326                     PORTMOD_PORT_ADD_F_INIT_PASS1, port_add_info, &okay);
   1327             if (BCM_FAILURE(rv)) {
   1328                 goto cleanup;
   1329             }
   1330 
   1331             count++;
   1332         }
   1333 
   1334 #ifdef FW_BCAST_DOWNLOAD
   1335         bcast_flag = soc_property_get(unit, spn_LOAD_FIRMWARE, 0);
   1336         if (bcast_flag & 0xff0000) {
   1337             crc_en = (bcast_flag >> 8) & 0xFF;
   1338             rv = portmod_common_serdes_fw_bcst(unit, lcl_pbmp, crc_en);
   1339             if (BCM_FAILURE(rv)) {
   1340                 goto cleanup;
   1341             }
   1342         }
   1343 #endif
   1344 
   1345         /* step3:broadcast firmware download for all external phys inculde legacy and Phymod PHYs*/
   1346         if (!(SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit))) {
   1347             rv = portmod_legacy_ext_phy_init(unit, pbmp);
   1348             if (BCM_FAILURE(rv)) {
   1349                 goto cleanup;
   1350             }
   1351 
   1352             rv = portmod_common_ext_phy_fw_bcst(unit, &lcl_pbmp);
   1353             if (BCM_FAILURE(rv)) {
   1354                 goto cleanup;
   1355             }
   1356         }
   1357 
   1358         /*step4:initialize PASS2 for Serdes and external PHY*/
   1359         count = 0;
   1360         PBMP_ITER(lcl_pbmp, port) {
   1361             port_add_info = add_info + count;
   1362             rv = bcmi_esw_portctrl_probe(unit, port, 
   1363                       PORTMOD_PORT_ADD_F_INIT_PASS2, port_add_info, &okay);
   1364             if (BCM_FAILURE(rv)) {
   1365                 goto cleanup;
   1366             }
   1367 
   1368             if (okay) {
   1369                 SOC_PBMP_PORT_ADD(*okay_pbmp, port);
   1370                 soc_counter_port_pbmp_add(unit, port);
   1371             }
   1372             count++;
   1373         }
   1374 cleanup:
   1375         if (add_info != NULL) {
   1376             sal_free(add_info);
   1377         }
   1378         if (BCM_FAILURE(rv)) {
   1379             return rv;
   1380         }
   1381     }
   1382 
   1383     /* warmboot boot, restore external phys data base. */
   1384     if (SOC_WARM_BOOT(unit)) {
   1385         BCM_IF_ERROR_RETURN(soc_esw_portctrl_xphy_wb_db_restore(unit));
   1386     }
   1387 
   1388     PBMP_ITER(pbmp, port) {
   1389         BCM_IF_ERROR_RETURN
   1390             (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1391         if (!SOC_WARM_BOOT(unit)) {
   1392             rv = _bcm_esw_portctrl_enable_set(unit, port, pport,
   1393                                               PORTMOD_PORT_ENABLE_MAC, FALSE);
   1394             if (BCM_FAILURE(rv)) {
   1395                 SOC_PBMP_PORT_REMOVE(*okay_pbmp, port);
   1396                 soc_counter_port_pbmp_remove(unit, port);
   1397                 LOG_WARN(BSL_LS_BCM_PORT,
   1398                          (BSL_META_U(unit,
   1399                                      "MAC init failed on port %s\n"),
   1400                           SOC_PORT_NAME(unit, port)));
   1401                 break;
   1402             }
   1403         } else {
   1404             portmod_port_interface_config_t interface_config;
   1405             portmod_port_init_config_t      init_config;
   1406             portmod_pbmp_t p_pbmp;
   1407             int lane=0, num_lanes=0;
   1408             int legacy_phy = 0;
   1409 
   1410             rv = soc_esw_portctrl_config_get(unit, port,
   1411                                      &interface_config,
   1412                                      &init_config,
   1413                                      &phy_op_mode);
   1414             if (BCM_FAILURE(rv)) {
   1415                 break;
   1416             }
   1417 
   1418             /* restore external phy attach */
   1419             PORTMOD_PBMP_CLEAR(p_pbmp);
   1420             num_lanes = SOC_INFO(unit).port_num_lanes[port];
   1421             if(num_lanes == 10) num_lanes=12;
   1422             for (lane = 0; lane < num_lanes; lane++) {
   1423                 physical_port = SOC_INFO(unit).port_l2p_mapping[port];
   1424 #ifdef BCM_TRIDENT3_SUPPORT
   1425                 /*To support the 2nd MGMT port, convert its physical port to the dummy port number 131 on TD3.*/
   1426                 if((SOC_IS_TRIDENT3X(unit)) && (physical_port == 128) && (SOC_PBMP_MEMBER(SOC_INFO(unit).management_pbm, port))){
   1427                     physical_port = 131;
   1428                 }
   1429 #endif /* BCM_TRIDENT3_SUPPORT */
   1430 #ifdef BCM_TOMAHAWK3_SUPPORT
   1431                 if (SOC_IS_TOMAHAWK3(unit) && (physical_port == 258)) {
   1432                     physical_port = 259;
   1433                 }
   1434 #endif
   1435                 PORTMOD_PBMP_PORT_ADD(p_pbmp, physical_port + lane);
   1436             }
   1437             SOC_IF_ERROR_RETURN(soc_esw_portctrl_setup_ext_phy_add(unit, port, &p_pbmp));
   1438 
   1439             /* Restore ports with legacy external phys */
   1440             rv = portmod_port_check_legacy_phy(unit, port, &legacy_phy);
   1441             if (BCM_FAILURE(rv)) {
   1442                 break;
   1443             }
   1444 
   1445             if (legacy_phy) {
   1446                 BCM_IF_ERROR_RETURN(portmod_port_legacy_phy_init(unit, port));
   1447             }
   1448 
   1449             rv = portmod_port_warmboot_db_restore(unit, pport, &interface_config, &init_config, phy_op_mode);
   1450             if (BCM_FAILURE(rv)) {
   1451                 break;
   1452             }
   1453         }
   1454 
   1455         if (soc_property_get(unit, spn_SAME_SPEED_INTF_DO_NOT_OVERWRITE,
   1456                              (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM))) {
   1457             _bcm_port_info_access(unit, port, &port_info);
   1458 
   1459             /* PM8x50 ports do not support port_interface_get */
   1460             if (IS_CD_PORT(unit, port)) {
   1461                 port_info->intf = BCM_PORT_IF_NOCXN;
   1462             } else {
   1463                 if ((rv = bcm_esw_port_interface_get(unit, port,
   1464                                                      &port_info->intf)) < 0) {
   1465                     port_info->intf = BCM_PORT_IF_NOCXN;
   1466                 }
   1467             }
   1468         }
   1469 
   1470         if (soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0)) {
   1471             soc_persist_t       *sop = SOC_PERSIST(unit);
   1472             SOC_PBMP_PORT_ADD(sop->lc_pbm_fc, port);
   1473         }
   1474 
   1475         /* Check if the port is set in EtherRAM buffer mode */
   1476         if (soc_property_port_get(unit, port, spn_PHY_OPERATIONAL_MODE, 0) == 3) {
   1477             soc_persist_t       *sop = SOC_PERSIST(unit);
   1478             SOC_PBMP_PORT_ADD(sop->lc_pbm_eth_buffer_mode, port);
   1479         }
   1480     }
   1481 
   1482     return BCM_E_NONE;
   1483 
   1484 #else  /* PORTMOD_SUPPORT */
   1485     return BCM_E_UNAVAIL;
   1486 #endif /* PORTMOD_SUPPORT */
   1487 }
   1488 
   1489 
   1490 /*
   1491  * Function:
   1492  *      bcmi_esw_portctrl_ability_get
   1493  * Purpose:
   1494  *      Retrieve the local port abilities.
   1495  * Parameters:
   1496  *      unit         - (IN) Unit number.
   1497  *      port         - (IN) Port number.
   1498  *      port_ability - (OUT) Returns bcm_port_ability_t structure information.
   1499  *      ability_mask - (OUT) If !NULL, returns mask of BCM_PORT_ABIL_
   1500  *                           values indicating the ability of the MAC/PHY.
   1501  * Returns:
   1502  *      BCM_E_NONE
   1503  *      BCM_E_XXX
   1504  */
   1505 int
   1506 bcmi_esw_portctrl_ability_get(int unit, bcm_gport_t port,
   1507                               bcm_port_ability_t *port_ability,
   1508                               bcm_port_abil_t *ability_mask)
   1509 {
   1510 #ifdef PORTMOD_SUPPORT
   1511     int rv = BCM_E_NONE;
   1512     portctrl_pport_t pport;
   1513     portmod_port_ability_t portmod_ability;
   1514 
   1515     PORTCTRL_INIT_CHECK(unit);
   1516 
   1517     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1518 
   1519     if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) {
   1520        return BCM_E_PORT;
   1521     }
   1522 
   1523     if (IS_CD_PORT(unit, port)) {
   1524         return BCM_E_UNAVAIL;
   1525     }
   1526 
   1527     sal_memset(port_ability, 0, sizeof(*port_ability));
   1528     sal_memset(&portmod_ability, 0, sizeof(portmod_ability));
   1529     if (ability_mask != NULL) {
   1530         *ability_mask = 0;
   1531     }
   1532 
   1533     PORT_LOCK(unit);
   1534     rv = portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &portmod_ability);
   1535     PORT_UNLOCK(unit);
   1536 
   1537     if (PORTMOD_SUCCESS(rv)) {
   1538         _bcm_esw_portctrl_from_portmod_ability(&portmod_ability,
   1539                                                port_ability);
   1540 
   1541 #if defined (BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) || defined (BCM_TOMAHAWK3_SUPPORT)
   1542         if ((SOC_IS_TOMAHAWK2(unit) || SOC_IS_TRIDENT3X(unit) ||
   1543              SOC_IS_TOMAHAWK3(unit)) &&
   1544             soc_feature(unit, soc_feature_flexport_based_speed_set)) {
   1545             bcm_port_abil_t mask;
   1546 
   1547             BCM_IF_ERROR_RETURN
   1548                 (bcmi_xgs5_flexport_based_speed_ability_get(unit, port, &mask));
   1549             port_ability->speed_full_duplex &= mask;
   1550             port_ability->speed_half_duplex &= mask;
   1551         }
   1552 #endif
   1553         port_ability->loopback  |= BCM_PORT_ABILITY_LB_NONE;
   1554         if(SAL_BOOT_SIMULATION) {
   1555             port_ability->loopback |= BCM_PORT_ABILITY_LB_MAC;
   1556             port_ability->loopback &= ~BCM_PORT_ABILITY_LB_PHY;
   1557         }
   1558 
   1559         if ((soc_feature(unit, soc_feature_embedded_higig)) &&
   1560             IS_E_PORT(unit, port)) {
   1561             port_ability->encap |= BCM_PA_ENCAP_HIGIG2_L2;
   1562             port_ability->encap |= BCM_PA_ENCAP_HIGIG2_IP_GRE;
   1563         }
   1564 
   1565         if ((soc_feature(unit, soc_feature_higig_over_ethernet))) {
   1566             port_ability->encap |= BCM_PA_ENCAP_HIGIG_OVER_ETHERNET;
   1567         }
   1568 
   1569         if (soc_feature(unit, soc_feature_no_higig_plus)) {
   1570             port_ability->encap &= ~BCM_PA_ENCAP_HIGIG;
   1571         }
   1572 
   1573         if (soc_feature(unit, soc_feature_roe)) {
   1574             port_ability->encap |= BCM_PA_ENCAP_CPRI;
   1575             port_ability->encap |= BCM_PA_ENCAP_RSVD4;
   1576         }
   1577 
   1578         SOC_IF_ERROR_RETURN(
   1579             soc_esw_portctrl_port_ability_update(unit, port, port_ability));
   1580 
   1581         /* Convert to BCM_PORT_ABIL_ mask if needed */
   1582         if (ability_mask != NULL) {
   1583             rv = soc_port_ability_to_mode(port_ability, ability_mask);
   1584         }
   1585     }
   1586 
   1587     if (ability_mask != NULL) {
   1588         LOG_INFO(BSL_LS_BCM_PORT,
   1589                  (BSL_META_UP(unit, port,
   1590                               "Port ability get: u=%d p=%d abil=0x%x "
   1591                               "rv=%d\n"),
   1592                   unit, port, *ability_mask, rv));
   1593     } else {
   1594         LOG_INFO(BSL_LS_BCM_PORT,
   1595                  (BSL_META_UP(unit, port,
   1596                               "Port ability get: u=%d p=%d rv=%d\n"),
   1597                   unit, port, rv));
   1598     }
   1599 
   1600     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1601                 (BSL_META_UP(unit, port,
   1602                              "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x abl_get\n"
   1603                              "Interface=0x%08x Medium=0x%08x EEE=0x%08x "
   1604                              "Loopback=0x%08x Flags=0x%08x\n"),
   1605                  port_ability->speed_half_duplex,
   1606                  port_ability->speed_full_duplex,
   1607                  port_ability->pause, port_ability->interface,
   1608                  port_ability->medium, port_ability->eee,
   1609                  port_ability->loopback, port_ability->flags));
   1610 
   1611     return rv;
   1612 #else  /* PORTMOD_SUPPORT */
   1613     return BCM_E_UNAVAIL;
   1614 #endif /* PORTMOD_SUPPORT */
   1615 }
   1616 
   1617 /* Function:
   1618  *      bcmi_esw_portctrl_speed_ability_local_get
   1619  * Purpose:
   1620  *     Retrieve the local speed abilities
   1621  * Parameters:
   1622  *     unit - (IN) Unit number.
   1623  *     port - (IN) Port number.
   1624  *     max_num_ability - (IN) Maximum number of abilities that can be returned.
   1625  *     abilities - (OUT) Abilities array.
   1626  *     actual_num_ability - (OUT) Actual number of abilities in abilities array.
   1627  * Returns:
   1628  *     BCM_E_NONE
   1629  *     BCM_E_XXX
   1630  */
   1631 int
   1632 bcmi_esw_portctrl_speed_ability_local_get(int unit,
   1633                                              bcm_gport_t port,
   1634                                              int max_num_ability,
   1635                                              bcm_port_speed_ability_t *abilities,
   1636                                              int *actual_num_ability)
   1637 {
   1638 #ifdef PORTMOD_SUPPORT
   1639     int rv = BCM_E_NONE, sp_abilities_size = 0;
   1640     portctrl_pport_t pport;
   1641     portmod_port_speed_ability_t *sp_abilities = NULL;
   1642     int valid_abilities;
   1643 
   1644     PORTCTRL_INIT_CHECK(unit);
   1645 
   1646     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1647 
   1648     sp_abilities_size = PORTCTRL_SPEED_ABILITY_MAX_COUNT;
   1649 
   1650     sp_abilities =  sal_alloc(sp_abilities_size * sizeof(portmod_port_speed_ability_t), "abilities array");
   1651     if (sp_abilities == NULL) {
   1652         rv = SOC_E_MEMORY;
   1653         return rv;
   1654     }
   1655 
   1656     sal_memset(sp_abilities, 0, sp_abilities_size * sizeof(portmod_port_speed_ability_t));
   1657     *actual_num_ability = 0;
   1658 
   1659     PORT_LOCK(unit);
   1660     rv = portmod_port_speed_ability_local_get(unit, pport, sp_abilities_size,
   1661                                             sp_abilities, actual_num_ability);
   1662     PORT_UNLOCK(unit);
   1663 
   1664     if (PORTMOD_SUCCESS(rv)) {
   1665          BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_from_portmod_autoneg_ability(unit, 
   1666                 *actual_num_ability, sp_abilities, max_num_ability,
   1667                 abilities, &valid_abilities));
   1668          *actual_num_ability = valid_abilities;
   1669     }
   1670 
   1671     LOG_INFO(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port,
   1672                                            "Port speed ability local get: u=%d p=%d rv=%d\n"), unit, port, rv));
   1673 
   1674     if (NULL != sp_abilities) {
   1675         sal_free(sp_abilities);
   1676     }
   1677     return rv;
   1678 #else  /* PORTMOD_SUPPORT */
   1679     return BCM_E_UNAVAIL;
   1680 #endif /* PORTMOD_SUPPORT */
   1681 }
   1682 /*
   1683  * Function:
   1684  *      bcmi_esw_portctrl_ability_remote_get
   1685  * Purpose:
   1686  *      Retrieve the remote advertised port abilities.
   1687  * Parameters:
   1688  *      unit         - (IN) Unit number.
   1689  *      port         - (IN) Port number.
   1690  *      port_ability - (OUT) Returns bcm_port_ability_t structure information.
   1691  *      ability_mask - (OUT) If !NULL, returns mask of BCM_PORT_ABIL_
   1692  *                           values indicating the ability of the MAC/PHY.
   1693  * Returns:
   1694  *      BCM_E_NONE
   1695  *      BCM_E_XXX
   1696  */
   1697 int
   1698 bcmi_esw_portctrl_ability_remote_get(int unit, bcm_gport_t port,
   1699                                      bcm_port_ability_t *port_ability,
   1700                                      bcm_port_abil_t *ability_mask)
   1701 {
   1702 #ifdef PORTMOD_SUPPORT
   1703     int rv = BCM_E_NONE;
   1704     portctrl_pport_t pport;
   1705     portmod_port_ability_t portmod_ability;
   1706     phymod_autoneg_status_t an_status;
   1707 
   1708     PORTCTRL_INIT_CHECK(unit);
   1709 
   1710     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1711 
   1712     sal_memset(port_ability, 0, sizeof(*port_ability));
   1713     sal_memset(&portmod_ability, 0, sizeof(portmod_ability));
   1714     if (ability_mask != NULL) {
   1715         *ability_mask = 0;
   1716     }
   1717 
   1718     PORT_LOCK(unit);
   1719 
   1720     rv = portmod_port_autoneg_status_get(unit, pport, &an_status);
   1721 
   1722     if (PORTMOD_SUCCESS(rv)) {
   1723         if (an_status.enabled && an_status.locked) {
   1724 #ifdef SW_AUTONEG_SUPPORT
   1725             {
   1726                 int an_mode = 0;
   1727 
   1728                 an_mode = soc_property_port_get(unit, port,
   1729                                   spn_PHY_AN_C73, an_mode);
   1730                 if (soc_feature(unit, soc_feature_sw_autoneg)) {
   1731                     /* phy_an_c73 value of 3 indicated MSA AN mode */
   1732                     if ((an_mode == SW_AN_MODE_CL73_MSA) ||
   1733                         (an_mode == SW_AN_MODE_MSA_ONLY)) {
   1734                         rv = bcm_sw_an_ability_remote_get(unit, port, port_ability);
   1735                         if (PORTMOD_SUCCESS(rv)) {
   1736                             /* Convert to BCM_PORT_ABIL_ mask if needed */
   1737                             if (ability_mask != NULL) {
   1738                                 rv = soc_port_ability_to_mode(port_ability, ability_mask);
   1739                             }
   1740                             PORT_UNLOCK(unit);
   1741                             return rv;
   1742                         }
   1743                     }
   1744                 }
   1745             }
   1746 #endif
   1747             rv = portmod_port_ability_remote_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY,
   1748                                                  &portmod_ability);
   1749         }
   1750     }
   1751 
   1752     PORT_UNLOCK(unit);
   1753 
   1754     if (PORTMOD_SUCCESS(rv)) {
   1755         _bcm_esw_portctrl_from_portmod_ability(&portmod_ability,
   1756                                                port_ability);
   1757 
   1758         /* Convert to BCM_PORT_ABIL_ mask if needed */
   1759         if (ability_mask != NULL) {
   1760             rv = soc_port_ability_to_mode(port_ability, ability_mask);
   1761         }
   1762     }
   1763 
   1764     if (ability_mask != NULL) {
   1765         LOG_INFO(BSL_LS_BCM_PORT,
   1766                  (BSL_META_UP(unit, port,
   1767                               "Port ability remote get: u=%d p=%d abil=0x%x "
   1768                               "rv=%d\n"),
   1769                   unit, port, *ability_mask, rv));
   1770     } else {
   1771         LOG_INFO(BSL_LS_BCM_PORT,
   1772                  (BSL_META_UP(unit, port,
   1773                               "Port ability remote get: u=%d p=%d rv=%d\n"),
   1774                   unit, port, rv));
   1775     }
   1776 
   1777     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1778                 (BSL_META_UP(unit, port,
   1779                              "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x abl_remote_get\n"
   1780                              "Interface=0x%08x Medium=0x%08x "
   1781                              "Loopback=0x%08x Flags=0x%08x\n"),
   1782                  port_ability->speed_half_duplex,
   1783                  port_ability->speed_full_duplex,
   1784                  port_ability->pause, port_ability->interface,
   1785                  port_ability->medium,
   1786                  port_ability->loopback, port_ability->flags));
   1787 
   1788     return rv;
   1789 #else  /* PORTMOD_SUPPORT */
   1790     return BCM_E_UNAVAIL;
   1791 #endif /* PORTMOD_SUPPORT */
   1792 }
   1793 
   1794 /* Function:
   1795  *      bcmi_esw_portctrl_autoneg_ability_remote_get
   1796  * Purpose:
   1797  *     Retrieve the remote advertised autoneg abilities
   1798  * Parameters:
   1799  *     unit - (IN) Unit number.
   1800  *     port - (IN) Port number.
   1801  *     max_num_ability - (IN) Maximum number of abilities that can be returned.
   1802  *     abilities - (OUT) Abilities array.
   1803  *     actual_num_ability - (OUT) Actual number of abilities in abilities array.
   1804  * Returns:
   1805  *     BCM_E_NONE
   1806  *     BCM_E_XXX
   1807  */
   1808 int
   1809 bcmi_esw_portctrl_autoneg_ability_remote_get(int unit,
   1810                                              bcm_gport_t port,
   1811                                              int max_num_ability,
   1812                                              bcm_port_speed_ability_t *abilities,
   1813                                              int *actual_num_ability)
   1814 {
   1815 #ifdef PORTMOD_SUPPORT
   1816     int rv = BCM_E_NONE, an_abilities_size = 0;
   1817     portctrl_pport_t pport;
   1818     portmod_port_speed_ability_t *an_abilities = NULL;
   1819     phymod_autoneg_status_t an_status;
   1820     int valid_abilities;
   1821 
   1822     PORTCTRL_INIT_CHECK(unit);
   1823 
   1824     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1825 
   1826     an_abilities_size = PORTCTRL_AUTONEG_ABILITY_MAX_COUNT;
   1827 
   1828     an_abilities =  sal_alloc(an_abilities_size * sizeof(portmod_port_speed_ability_t), "abilities array");
   1829     if (an_abilities == NULL) {
   1830         rv = SOC_E_MEMORY;
   1831         return rv;
   1832     }
   1833 
   1834     sal_memset(an_abilities, 0, an_abilities_size * sizeof(portmod_port_speed_ability_t));
   1835     *actual_num_ability = 0;
   1836 
   1837     PORT_LOCK(unit);
   1838     rv = portmod_port_autoneg_status_get(unit, pport, &an_status);
   1839     if (PORTMOD_SUCCESS(rv)) {
   1840         if (an_status.enabled && an_status.locked) {
   1841             rv = portmod_port_autoneg_ability_remote_get(unit, pport,
   1842                     an_abilities_size, an_abilities, actual_num_ability);
   1843         }
   1844     }
   1845     PORT_UNLOCK(unit);
   1846 
   1847     if (PORTMOD_SUCCESS(rv)) {
   1848         _bcm_esw_portctrl_from_portmod_autoneg_ability(unit,
   1849                                 *actual_num_ability, an_abilities,
   1850                                 max_num_ability, abilities, &valid_abilities);
   1851         *actual_num_ability = valid_abilities;
   1852     }
   1853 
   1854     LOG_INFO(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port,
   1855                                            "Port autoneg ability remote get: u=%d p=%d rv=%d\n"), unit, port, rv));
   1856 
   1857     if (NULL != an_abilities) {
   1858         sal_free(an_abilities);
   1859     }
   1860     return rv;
   1861 #else  /* PORTMOD_SUPPORT */
   1862     return BCM_E_UNAVAIL;
   1863 #endif /* PORTMOD_SUPPORT */
   1864 }
   1865 
   1866 /*
   1867  * Function:
   1868  *      bcmi_esw_portctrl_enable_get
   1869  * Purpose:
   1870  *      Gets the enable state as defined by bcm_port_enable_set()
   1871  * Parameters:
   1872  *      unit   - (IN) Unit number.
   1873  *      port   - (IN) Port number.
   1874  *      enable - (OUT) TRUE, port is enabled, FALSE port is disabled.
   1875  * Returns:
   1876  *      BCM_E_XXX
   1877  * Notes:
   1878  *      The PHY enable holds the port enable state set by the user.
   1879  *      The MAC enable transitions up and down automatically via linkscan
   1880  *      even if user port enable is always up.
   1881  */
   1882 int
   1883 bcmi_esw_portctrl_enable_get(int unit, bcm_gport_t port, int *enable)
   1884 {
   1885 #ifdef PORTMOD_SUPPORT
   1886     int rv = BCM_E_NONE;
   1887     portctrl_pport_t pport;
   1888     _bcm_port_info_t *port_info = NULL;
   1889 
   1890     PORTCTRL_INIT_CHECK(unit);
   1891 
   1892     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1893 
   1894     if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port)) {
   1895         *enable = 0;
   1896         return BCM_E_NONE;
   1897     }
   1898 
   1899     PORT_LOCK(unit);
   1900 
   1901     rv = portmod_port_enable_get(unit, pport, PORTMOD_PORT_ENABLE_PHY, enable);
   1902 
   1903     _bcm_port_info_access(unit, port, &port_info);
   1904 
   1905     if (port_info == NULL) {
   1906         PORT_UNLOCK(unit);
   1907         return BCM_E_INIT;
   1908     }
   1909     *enable = port_info->enable & (*enable);
   1910 
   1911     PORT_UNLOCK(unit);
   1912 
   1913     LOG_INFO(BSL_LS_BCM_PORT,
   1914              (BSL_META_UP(unit, port,
   1915                           "Port enable get: u=%d p=%d rv=%d enable=%d\n"),
   1916               unit, port, rv, *enable));
   1917 
   1918     return rv;
   1919 
   1920 #else  /* PORTMOD_SUPPORT */
   1921     return BCM_E_UNAVAIL;
   1922 #endif /* PORTMOD_SUPPORT */
   1923 }
   1924 
   1925 
   1926 /*
   1927  * Function:
   1928  *      bcmi_esw_portctrl_enable_set
   1929  * Purpose:
   1930  *      Physically enable/disable the MAC/PHY on this port.
   1931  * Parameters:
   1932  *      unit   - (IN) Unit number.
   1933  *      port   - (IN) Port number.
   1934  *      enable - (IN) TRUE, port is enabled, FALSE port is disabled.
   1935  * Returns:
   1936  *      BCM_E_XXX
   1937  * Notes:
   1938  *      If linkscan is running, it also controls the MAC enable state.
   1939  */
   1940 int
   1941 bcmi_esw_portctrl_enable_set(int unit, bcm_gport_t port, int enable)
   1942 {
   1943 #ifdef PORTMOD_SUPPORT
   1944     int rv = BCM_E_NONE;
   1945     portctrl_pport_t pport;
   1946     int link, loopback = BCM_PORT_LOOPBACK_NONE;
   1947     soc_persist_t *sop = SOC_PERSIST(unit);
   1948     _bcm_port_info_t *port_info;
   1949     int flags = 0;
   1950     pbmp_t pbm;
   1951 
   1952 #if defined(INCLUDE_L3)
   1953 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   1954     int ecmp_dlb_restore = 0;
   1955     int dlb_link_status;
   1956 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */
   1957 #endif /* INCLUDE_L3 */
   1958 
   1959     PORTCTRL_INIT_CHECK(unit);
   1960 
   1961     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   1962 
   1963 #ifdef BCM_RCPU_SUPPORT
   1964     if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   1965         return BCM_E_PORT;
   1966     }
   1967 #endif /* BCM_RCPU_SUPPORT */
   1968 
   1969     BCM_IF_ERROR_RETURN
   1970         (bcmi_esw_portctrl_loopback_get(unit, port, &loopback));
   1971 
   1972     PORT_LOCK(unit);
   1973 
   1974     if (enable) {
   1975         if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit, all), port)) {
   1976             PORT_UNLOCK(unit);
   1977             return BCM_E_NONE;
   1978         }
   1979 
   1980         rv = _bcm_esw_portctrl_enable_set(unit, port, pport,
   1981                                           PORTMOD_PORT_ENABLE_PHY, 1);
   1982         if (BCM_FAILURE(rv)) {
   1983             PORT_UNLOCK(unit);
   1984             return rv;
   1985         }
   1986 
   1987         /* Get link status after PHY state has been set */
   1988         rv = bcm_esw_port_link_status_get(unit, port, &link);
   1989         if (BCM_FAILURE(rv)) {
   1990             if (rv == BCM_E_INIT) {
   1991                 link = FALSE;
   1992                 rv = BCM_E_NONE;
   1993             } else {
   1994                 PORT_UNLOCK(unit);
   1995                 return rv;
   1996             }
   1997         }
   1998         if (link || (loopback != BCM_PORT_LOOPBACK_NONE)
   1999             || SOC_PBMP_MEMBER(sop->lc_pbm_fc, port)
   2000             || SOC_PBMP_MEMBER(sop->lc_pbm_linkdown_tx, port)) {
   2001             rv = _bcm_esw_portctrl_enable_set(unit, port, pport,
   2002                                               PORTMOD_PORT_ENABLE_MAC, 1);
   2003             if (BCM_FAILURE(rv)) {
   2004                 PORT_UNLOCK(unit);
   2005                 return rv;
   2006             }
   2007         }
   2008 
   2009     } else {
   2010 
   2011         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2012                     (BSL_META_UP(unit, port,
   2013                                  "Disable and isolate u=%d p=%d\n"),
   2014                      unit, port));
   2015 
   2016         /*
   2017          * When the port is configured to MAC loopback,
   2018          * cannot disable MAC.
   2019          */
   2020         PORTMOD_PORT_ENABLE_PHY_SET(flags);
   2021         if (loopback != BCM_PORT_LOOPBACK_MAC) {
   2022             PORTMOD_PORT_ENABLE_MAC_SET(flags);
   2023         }
   2024 #if defined(INCLUDE_L3)
   2025 #if defined (BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2026         if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) {
   2027             soc_mem_lock(unit, DLB_ECMP_LINK_CONTROLm);
   2028             rv = _bcm_esw_port_ecmp_dlb_link_status_get(unit, port, &dlb_link_status);
   2029             if (rv != BCM_E_NONE) {
   2030                 if (rv != BCM_E_UNAVAIL) {
   2031                     soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm);
   2032                     PORT_UNLOCK(unit);
   2033                     return rv;
   2034                 }
   2035             } else {
   2036                 if (dlb_link_status == BCM_L3_ECMP_DYNAMIC_MEMBER_HW_DOWN ||
   2037                     dlb_link_status == BCM_L3_ECMP_DYNAMIC_MEMBER_HW_UP) {
   2038                     dlb_link_status = BCM_L3_ECMP_DYNAMIC_MEMBER_HW;
   2039                 }
   2040                 if (dlb_link_status != BCM_L3_ECMP_DYNAMIC_MEMBER_FORCE_DOWN) {
   2041                     rv = _bcm_esw_port_ecmp_dlb_link_status_set(unit, port,
   2042                              BCM_L3_ECMP_DYNAMIC_MEMBER_FORCE_DOWN);
   2043                     if (rv != BCM_E_NONE) {
   2044                         if (rv != BCM_E_UNAVAIL) {
   2045                             soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm);
   2046                             PORT_UNLOCK(unit);
   2047                             return rv;
   2048                         }
   2049                     } else {
   2050                         ecmp_dlb_restore = 1;
   2051                     }
   2052                 }
   2053             }
   2054         }
   2055 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */
   2056 #endif /* INCLUDE_L3 */
   2057         rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0);
   2058         if (BCM_FAILURE(rv)) {
   2059 #if defined(INCLUDE_L3)
   2060 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2061             if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) {
   2062                 soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm);
   2063             }
   2064 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */
   2065 #endif /* INCLUDE_L3 */
   2066             PORT_UNLOCK(unit);
   2067             return rv;
   2068         }
   2069 
   2070 #if defined(INCLUDE_L3)
   2071 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2072         if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) {
   2073             if (ecmp_dlb_restore) {
   2074                 rv = _bcm_esw_port_ecmp_dlb_link_status_set(unit, port,
   2075                                                             dlb_link_status);
   2076                 if (rv != BCM_E_NONE && rv != BCM_E_UNAVAIL) {
   2077                     soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm);
   2078                     PORT_UNLOCK(unit);
   2079                     return rv;
   2080                 }
   2081             }
   2082             soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm);
   2083         }
   2084 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */
   2085 #endif /* INCLUDE_L3 */
   2086     }
   2087 
   2088     _bcm_port_info_access(unit, port, &port_info);
   2089     port_info->enable = enable;
   2090 
   2091 #ifdef SW_AUTONEG_SUPPORT
   2092     rv = _bcm_esw_port_notify_link_down_evt(unit, port);
   2093     if (BCM_FAILURE(rv)) {
   2094         LOG_WARN(BSL_LS_BCM_PORT,
   2095                  (BSL_META_U(unit,
   2096                              "u=%d p=%d NOTIFY LINK DOWN EVT rv=%d\n"),unit, port, rv));
   2097         PORT_UNLOCK(unit);
   2098         return rv;
   2099     }
   2100 #endif
   2101     PORT_UNLOCK(unit);
   2102 
   2103     /* Unlock before link call */
   2104     if (loopback != BCM_PORT_LOOPBACK_NONE) {
   2105         if (loopback == BCM_PORT_LOOPBACK_MAC) {
   2106             rv = _bcm_esw_link_force(unit, 0, port, TRUE, TRUE);
   2107         } else {
   2108             rv = _bcm_esw_link_force(unit, 0, port, TRUE, enable);
   2109         }
   2110     } else {
   2111         /* Check for change in link status to avoid race with linkscan thread
   2112          */
   2113         SOC_PBMP_CLEAR(pbm);
   2114         SOC_PBMP_PORT_ADD(pbm, port);
   2115         (void)bcm_esw_linkscan_update(unit, pbm);
   2116     }
   2117 
   2118     LOG_INFO(BSL_LS_BCM_PORT,
   2119              (BSL_META_UP(unit, port,
   2120                           "Port enable set: u=%d p=%d enable=%d rv=%d\n"),
   2121               unit, port, enable, rv));
   2122 
   2123 #ifdef BCM_WARM_BOOT_SUPPORT
   2124     SOC_CONTROL_LOCK(unit);
   2125     SOC_CONTROL(unit)->scache_dirty = 1;
   2126     SOC_CONTROL_UNLOCK(unit);
   2127 #endif
   2128 
   2129     return rv;
   2130 
   2131 #else  /* PORTMOD_SUPPORT */
   2132     return BCM_E_UNAVAIL;
   2133 #endif /* PORTMOD_SUPPORT */
   2134 }
   2135 
   2136 
   2137 /*
   2138  * Function:
   2139  *      bcmi_esw_portctrl_mac_enable_set
   2140  * Purpose:
   2141  *      Physically enable/disable the MAC on this port.
   2142  * Parameters:
   2143  *      unit   - (IN) Unit number.
   2144  *      port   - (IN) Port number.
   2145  *      enable - (IN) TRUE, port is enabled, FALSE port is disabled.
   2146  * Returns:
   2147  *      BCM_E_XXX
   2148  * Notes:
   2149  *      Unlike bcmi_esw_portctl_enable_set(), this routine
   2150  *      only enables the MAC.  It does not contain any logic
   2151  *      to handle loopback cases, PHY, or current port state.
   2152  */
   2153 int
   2154 bcmi_esw_portctrl_mac_enable_set(int unit, bcm_gport_t port, int enable)
   2155 {
   2156 #ifdef PORTMOD_SUPPORT
   2157     int rv = BCM_E_NONE;
   2158     portctrl_pport_t pport;
   2159 
   2160     PORTCTRL_INIT_CHECK(unit);
   2161 
   2162     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2163 
   2164     PORT_LOCK(unit);
   2165     rv =  _bcm_esw_portctrl_enable_set(unit, port, pport,
   2166                                        PORTMOD_PORT_ENABLE_MAC, enable);
   2167     PORT_UNLOCK(unit);
   2168 
   2169     return rv;
   2170 
   2171 #else  /* PORTMOD_SUPPORT */
   2172     return BCM_E_UNAVAIL;
   2173 #endif /* PORTMOD_SUPPORT */
   2174 }
   2175 
   2176 
   2177 /*
   2178  * Function:
   2179  *      bcmi_esw_portctrl_phy_enable_set
   2180  * Purpose:
   2181  *      Physically enable/disable the PHY on this port.
   2182  * Parameters:
   2183  *      unit   - (IN) Unit number.
   2184  *      port   - (IN) Port number.
   2185  *      enable - (IN) TRUE, PHY port is enabled, FALSE PHY port is disabled.
   2186  * Returns:
   2187  *      BCM_E_XXX
   2188  * Notes:
   2189  *      Unlike bcmi_esw_portctl_enable_set(), this routine
   2190  *      only enables the PHY.  It does not contain any logic
   2191  *      to handle loopback cases, MAC, or current port state.
   2192  */
   2193 int
   2194 bcmi_esw_portctrl_phy_enable_set(int unit, bcm_gport_t port, int enable)
   2195 {
   2196 #ifdef PORTMOD_SUPPORT
   2197     int rv = BCM_E_NONE;
   2198     portctrl_pport_t pport;
   2199 
   2200     PORTCTRL_INIT_CHECK(unit);
   2201 
   2202     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2203 
   2204     PORT_LOCK(unit);
   2205     rv = portmod_port_enable_set(unit, pport,
   2206                                  PORTMOD_PORT_ENABLE_PHY, enable);
   2207     PORT_UNLOCK(unit);
   2208 
   2209     return rv;
   2210 
   2211 #else  /* PORTMOD_SUPPORT */
   2212     return BCM_E_UNAVAIL;
   2213 #endif /* PORTMOD_SUPPORT */
   2214 }
   2215 
   2216 
   2217 /*
   2218  * Function:
   2219  *      bcmi_esw_portctrl_egress_queue_drain
   2220  * Purpose:
   2221  *      Drain the egress queues without bringing down the port.
   2222  * Parameters:
   2223  *      unit   - (IN) Unit number.
   2224  *      port   - (IN) Port number.
   2225  * Returns:
   2226  *      BCM_E_XXX
   2227  * Notes:
   2228  */
   2229 int
   2230 bcmi_esw_portctrl_egress_queue_drain(int unit, bcm_gport_t port)
   2231 {
   2232 #ifdef PORTMOD_SUPPORT
   2233     int rv = BCM_E_NONE;
   2234     portctrl_pport_t pport;
   2235 
   2236     PORTCTRL_INIT_CHECK(unit);
   2237 
   2238     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2239 
   2240     PORT_LOCK(unit);
   2241     rv = _bcm_esw_portctrl_egress_queue_drain(unit, port, pport);
   2242     PORT_UNLOCK(unit);
   2243 
   2244     return rv;
   2245 
   2246 #else  /* PORTMOD_SUPPORT */
   2247     return BCM_E_UNAVAIL;
   2248 #endif /* PORTMOD_SUPPORT */
   2249 }
   2250 
   2251 /*
   2252  * Function:
   2253  *      bcmi_esw_portctrl_notify
   2254  * Description:
   2255  *      Notify application the chip reconfigure failure from a auto-neg speed.
   2256  * Parameters:
   2257  *      unit_vp   - (IN) Device number.
   2258  *      event_vp  - (IN) Port number.
   2259  *      port_vp   - (IN) Port number.
   2260  *      arg1      - (IN) arg1
   2261  *      arg2      - (IN) arg2
   2262  * Returns:
   2263  *      No
   2264  * Notes:
   2265  */
   2266 #ifdef PORTMOD_SUPPORT
   2267 STATIC void
   2268 bcmi_esw_portctrl_notify(void *unit_vp, void *event_vp,
   2269                          void *port_vp, void *arg1_vp, void *arg2_vp)
   2270 {
   2271     int unit, event, port, arg1, arg2;
   2272 
   2273     unit = PTR_TO_INT(unit_vp);
   2274     event = PTR_TO_INT(event_vp);
   2275     port = PTR_TO_INT(port_vp);
   2276     arg1 = PTR_TO_INT(arg1_vp);
   2277     arg2 = PTR_TO_INT(arg2_vp);
   2278 
   2279     (void)soc_event_generate(unit, event, port, arg1, arg2);
   2280 }
   2281 #endif /* PORTMOD_SUPPORT */
   2282 
   2283 /*
   2284  * Function:
   2285  *      bcmi_esw_portctrl_update
   2286  * Description:
   2287  *      Get port characteristics from PHY and program MAC to match.
   2288  * Parameters:
   2289  *      unit   - (IN) Device number.
   2290  *      port   - (IN) Port number.
   2291  *      link   - (IN) TRUE - process as link up.
   2292  *                    FALSE - process as link down.
   2293  * Returns:
   2294  *      BCM_E_XXX
   2295  * Notes:
   2296  *      This function cannot hold the PORT_LOCK because it is called
   2297  *      by the linkscan thread.
   2298  */
   2299 int
   2300 bcmi_esw_portctrl_update(int unit, bcm_gport_t port, int link)
   2301 {
   2302 #ifdef PORTMOD_SUPPORT
   2303     portctrl_pport_t pport;
   2304     portmod_port_interface_config_t if_config;
   2305 #ifdef PORTMOD_PM8X50_SUPPORT
   2306     portmod_speed_config_t speed_config;
   2307     portmod_dispatch_type_t pm_type = portmodDispatchTypeCount;
   2308     int phy_port;
   2309 #endif
   2310     int config_speed;
   2311     int speed, enable;
   2312     int duplex;
   2313     phymod_autoneg_status_t an_status;
   2314     int is_legacy_phy, skip_spd_sync;
   2315     int rv = BCM_E_NONE;
   2316 
   2317     is_legacy_phy = 0;
   2318     skip_spd_sync = 0;
   2319 
   2320     PORTCTRL_INIT_CHECK(unit);
   2321 
   2322     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2323 
   2324     if (!link) {
   2325 #ifdef SW_AUTONEG_SUPPORT
   2326     rv = _bcm_esw_port_notify_link_down_evt(unit, port);
   2327     if (BCM_FAILURE(rv)) {
   2328         LOG_WARN(BSL_LS_BCM_PORT,
   2329                  (BSL_META_U(unit,
   2330                              "u=%d p=%d NOTIFY LINK DOWN EVT rv=%d\n"),unit, port, rv));
   2331         return rv;
   2332     }
   2333 #endif
   2334         /*need to check if Pm8x50 Gen1/Gen2 400G AN workaround*/
   2335         /* if 400G AN enabled, bypass the port update */
   2336 #ifdef PORTMOD_PM8X50_SUPPORT
   2337         /* first get physical port */
   2338         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   2339         /* get the PM type */
   2340         PORTMOD_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type));
   2341         if (pm_type == portmodDispatchTypePm8x50) {
   2342             sal_memset(&an_status, 0, sizeof(an_status));
   2343             PORTMOD_IF_ERROR_RETURN
   2344                 (portmod_port_autoneg_status_get(unit, pport, &an_status));
   2345             if ((an_status.enabled) && (an_status.data_rate == 400000)) {
   2346                 return rv;
   2347             }
   2348         }
   2349 #endif
   2350         /* PHY is down.  Disable the MAC. */
   2351         PORTMOD_IF_ERROR_RETURN 
   2352             ( _bcm_esw_portctrl_enable_set(unit, port, pport,
   2353                                            PORTMOD_PORT_ENABLE_MAC, 0));
   2354         /* PHY link down event */
   2355         rv = (portmod_port_phy_link_down_event(unit, port));
   2356         if (BCM_FAILURE(rv) && (BCM_E_UNAVAIL != rv)) {
   2357             LOG_WARN(BSL_LS_BCM_PORT,
   2358                      (BSL_META_U(unit,
   2359                                  "u=%d p=%d portmod_port_phy_link_down_event rv=%d\n"),unit, port, rv));
   2360             return rv;
   2361         }
   2362         return BCM_E_NONE;
   2363     }
   2364 
   2365     /* PHY link up event */
   2366     rv = (portmod_port_phy_link_up_event(unit, port));
   2367     if (BCM_FAILURE(rv) && (BCM_E_UNAVAIL != rv)) {
   2368         LOG_WARN(BSL_LS_BCM_PORT,
   2369                  (BSL_META_U(unit,
   2370                              "u=%d p=%d portmod_port_phy_link_up_event rv=%d\n"),unit, port, rv));
   2371         return rv;
   2372     }
   2373 
   2374     sal_memset(&an_status, 0, sizeof(an_status));
   2375     PORTMOD_IF_ERROR_RETURN
   2376         (portmod_port_autoneg_status_get(unit, pport, &an_status));
   2377 
   2378     /*
   2379      * Set MAC speed first, since for GTH ports, this will switch
   2380      * between the 1000Mb/s or 10/100Mb/s MACs.
   2381      */
   2382     if (!IS_HG_PORT(unit, port) || IS_GX_PORT(unit, port)) {
   2383 #ifdef PORTMOD_PM8X50_SUPPORT
   2384         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   2385 #ifdef BCM_TOMAHAWK3_SUPPORT
   2386         /* Tomahawk 3's Management Port Macro requires a spacing between
   2387          * the lanes, so even though the two management ports' physical
   2388          * ports are 257 and 258, the lane needs to be the next one,
   2389          * so logical port 118 being mapped to physical port 258 needs
   2390          * to pass 259 to portmod because portmod only recognizes lane
   2391          * 0 (physical port 257) and lane 2 (physial port 259).
   2392          */
   2393         if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) {
   2394             phy_port = 259;
   2395         }
   2396 #endif
   2397         PORTMOD_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type));
   2398         if (pm_type == portmodDispatchTypePm8x50) {
   2399             PORTMOD_IF_ERROR_RETURN
   2400                 (portmod_port_speed_config_get(unit, pport, &speed_config));
   2401             speed = speed_config.speed;
   2402         } else 
   2403 #endif
   2404         {
   2405             PORTMOD_IF_ERROR_RETURN
   2406                 (portmod_port_interface_config_get(unit, pport, &if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY));
   2407             speed = if_config.speed;
   2408 
   2409             if (IS_HG_PORT(unit, port) && (if_config.speed < 5000)) {
   2410                 speed = 0;
   2411             }
   2412         }
   2413 
   2414         PORTMOD_IF_ERROR_RETURN
   2415             (portmod_port_duplex_get(unit, pport, &duplex));
   2416 
   2417 
   2418 #ifdef INCLUDE_FCMAP
   2419         /*
   2420          * In the FC-mode the switch and the system side of the PHY operates
   2421          * at max_speed of the port in full duplex.
   2422          */
   2423         if (soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0)) {
   2424             speed = if_config.max_speed;
   2425             duplex = 1;
   2426         }
   2427 #endif
   2428 
   2429         if (an_status.enabled) {
   2430             /* If AN is enabled, get both "line side speed" and
   2431              * "SERDES speed(multiply number of lanes", then compare them.
   2432              * Otherwise, set LINKUP flag and continue. 
   2433             */
   2434             int line_speed, serdes_speed;
   2435 
   2436             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_speed_get(
   2437                                     unit, port, &line_speed));
   2438             PORTMOD_IF_ERROR_RETURN(portmod_port_speed_get(
   2439                                     unit, port, &serdes_speed));
   2440              
   2441             BCM_IF_ERROR_RETURN(
   2442                 portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_phy));
   2443             if (is_legacy_phy) {
   2444                 skip_spd_sync = portmod_port_legacy_is_skip_spd_sync(unit, port);   
   2445             }
   2446 
   2447             if ((line_speed != serdes_speed) &&  (!skip_spd_sync)) {
   2448 #ifdef PORTMOD_PM8X50_SUPPORT
   2449                 if (pm_type == portmodDispatchTypePm8x50) {
   2450                     
   2451                     speed_config.speed = speed;
   2452                     /* following is for 400G autoneg only */
   2453                     /* if 400G AN< bypass port update */
   2454                     if (speed == 400000) {
   2455                         return BCM_E_NONE;
   2456                     }
   2457                 } else 
   2458 #endif 
   2459                 {
   2460                 if_config.speed = serdes_speed;
   2461             }
   2462             }
   2463             if_config.flags |= PHYMOD_INTF_F_UPDATE_SPEED_LINKUP;
   2464         }
   2465 
   2466         /* 1. Assuming Autoneg process is still running.
   2467          * We should not call speed_set function because speed_set involves
   2468          * disable AN, and IP/EP/MMU/TDM reconfiguration.
   2469          * just call _bcm_esw_portctrl_interface_config_set to update interface 
   2470          * 2. For PHY devices that has line and system side operate at different speeds 
   2471          * speed sync between line and system side is not required.
   2472          */   
   2473 #ifdef PORTMOD_PM8X50_SUPPORT
   2474         if (pm_type == portmodDispatchTypePm8x50) {
   2475             config_speed = speed_config.speed;
   2476         } else
   2477 #endif 
   2478         {
   2479             config_speed = if_config.speed;
   2480         }
   2481         if (((config_speed != speed) || (((an_status.enabled) && (an_status.locked)))) &&
   2482             (!skip_spd_sync) && link) {
   2483             PORTMOD_IF_ERROR_RETURN
   2484                 (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC,
   2485                                          &enable));
   2486             if (enable) {
   2487                 /* Disable MAC */
   2488                 BCM_IF_ERROR_RETURN
   2489                     (_bcm_esw_portctrl_enable_set(unit, port, pport,
   2490                                                   PORTMOD_PORT_ENABLE_MAC, 0));
   2491             }
   2492 
   2493             /* reconfigure chip (TDM/IP/EP/MMU) */
   2494             rv = _bcm_esw_portctrl_speed_chip_reconfigure(unit, port, speed);
   2495             if (BCM_FAILURE(rv) && (an_status.enabled)) {
   2496                 sal_dpc(bcmi_esw_portctrl_notify,
   2497                         INT_TO_PTR(unit),
   2498                         INT_TO_PTR(SOC_SWITCH_EVENT_AUTONEG_SPEED_ERROR),
   2499                         INT_TO_PTR(port),
   2500                         INT_TO_PTR(speed),
   2501                         INT_TO_PTR(rv));
   2502                 return rv;
   2503             }
   2504 #ifdef PORTMOD_PM8X50_SUPPORT
   2505             if (pm_type == portmodDispatchTypePm8x50) {
   2506                 /* Do nothing for PM8x50. The PM does not support
   2507                  * interface_config_set
   2508                  */
   2509             } else
   2510 #endif
   2511             {
   2512             if_config.speed = speed;
   2513             PORTMOD_IF_ERROR_RETURN
   2514                 (_bcm_esw_portctrl_interface_config_set(unit, port, pport,
   2515                                                         &if_config, 0));
   2516             }
   2517 
   2518             if (enable) {
   2519                 /* Re-enable port */
   2520                 BCM_IF_ERROR_RETURN
   2521                     (_bcm_esw_portctrl_enable_set(unit, port, pport,
   2522                                                   PORTMOD_PORT_ENABLE_MAC,
   2523                                                   1));
   2524             }
   2525         }
   2526         
   2527         PORTMOD_IF_ERROR_RETURN
   2528             (portmod_port_duplex_set(unit, pport, duplex));
   2529     } else {
   2530         duplex = 1;
   2531     }
   2532 
   2533     /*
   2534      * If autonegotiating, check the negotiated PAUSE values, and program
   2535      * MACs accordingly. Link can also be achieved thru parallel detect.
   2536      * In this case, it should be treated as in the forced mode.
   2537      */
   2538 #ifdef PORTMOD_PM8X50_SUPPORT
   2539     if (pm_type == portmodDispatchTypePm8x50) {
   2540         /* Do nothing for PM8x50. Pause settings for AN will be taken care
   2541          * inside Portmod.
   2542          */
   2543     } else
   2544 #endif
   2545     {
   2546         if (an_status.enabled && an_status.locked) {
   2547             bcm_port_ability_t local_advert, remote_advert;
   2548             int tx_pause, rx_pause;
   2549             portmod_pause_control_t pause_control;
   2550 
   2551             BCM_IF_ERROR_RETURN
   2552                 (bcmi_esw_portctrl_ability_advert_get(unit, port,
   2553                                                       &local_advert, NULL));
   2554             BCM_IF_ERROR_RETURN
   2555                 (bcmi_esw_portctrl_ability_remote_get(unit, port,
   2556                                                       &remote_advert, NULL));
   2557 
   2558             /*
   2559              * IEEE 802.3 Flow Control Resolution.
   2560              * Please see $SDK/doc/pause-resolution.txt for more information.
   2561              */
   2562             if (duplex) {
   2563                 tx_pause =
   2564                          ((remote_advert.pause & SOC_PA_PAUSE_RX) &&
   2565                           (local_advert.pause & SOC_PA_PAUSE_RX)) ||
   2566                          ((remote_advert.pause & SOC_PA_PAUSE_RX) &&
   2567                           !(remote_advert.pause & SOC_PA_PAUSE_TX) &&
   2568                           (local_advert.pause & SOC_PA_PAUSE_TX));
   2569 
   2570                 rx_pause =
   2571                          ((remote_advert.pause & SOC_PA_PAUSE_RX) &&
   2572                           (local_advert.pause & SOC_PA_PAUSE_RX)) ||
   2573                          ((local_advert.pause & SOC_PA_PAUSE_RX) &&
   2574                           (remote_advert.pause & SOC_PA_PAUSE_TX) &&
   2575                           !(local_advert.pause & SOC_PA_PAUSE_TX));
   2576             } else {
   2577                 rx_pause = tx_pause = 0;
   2578             }
   2579 
   2580             PORTMOD_IF_ERROR_RETURN
   2581                 (portmod_port_pause_control_get(unit, pport, &pause_control));
   2582             pause_control.rx_enable = rx_pause;
   2583             pause_control.tx_enable = tx_pause;
   2584             PORTMOD_IF_ERROR_RETURN
   2585                 (portmod_port_pause_control_set(unit, pport, &pause_control));
   2586         }
   2587     }
   2588 
   2589     /* Enable the MAC */
   2590     BCM_IF_ERROR_RETURN
   2591         (_bcm_esw_portctrl_enable_set(unit, port, pport,
   2592                                       PORTMOD_PORT_ENABLE_MAC, 1));
   2593 
   2594 
   2595     /* When a link comes up, hardware will not update the
   2596      * LINK_STATUS register until software has toggled the
   2597      * the LAG_FAILOVER_CONFIG.LINK_STATUS_UP field.
   2598      * When a link goes down, hardware will update the
   2599      * LINK_STATUS register without software intervention.
   2600      */
   2601     /* Toggle link_status_up bit to notify IPIPE on link up */
   2602     if (!IS_QSGMII_PORT(unit, pport)) {
   2603         PORTMOD_IF_ERROR_RETURN
   2604             (portmod_port_lag_failover_status_toggle(unit, pport));
   2605     }
   2606 
   2607     return BCM_E_NONE;
   2608 
   2609 #else  /* PORTMOD_SUPPORT */
   2610     return BCM_E_UNAVAIL;
   2611 #endif /* PORTMOD_SUPPORT */
   2612 }
   2613 
   2614 
   2615 /*
   2616  * Function:
   2617  *      bcmi_esw_portctrl_fault_get
   2618  * Description:
   2619  *      Get link fault type.
   2620  * Parameters:
   2621  *      unit   - (IN) Device number.
   2622  *      port   - (IN) Port number.
   2623  *      flags  - (OUT) flags to indicate fault type.
   2624  * Returns:
   2625  *      BCM_E_XXX
   2626  */
   2627 int
   2628 bcmi_esw_portctrl_fault_get(int unit, bcm_gport_t port, uint32 *flags)
   2629 {
   2630 #ifdef PORTMOD_SUPPORT
   2631     int rv = BCM_E_NONE;
   2632     portctrl_pport_t pport;
   2633     int local_fault = 0, remote_fault = 0;
   2634     portmod_local_fault_control_t local_control;
   2635     portmod_remote_fault_control_t remote_control;
   2636 
   2637     PORTCTRL_INIT_CHECK(unit);
   2638 
   2639     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2640 
   2641     PORT_LOCK(unit);
   2642 
   2643     /*
   2644      * NOTE:
   2645      * The PortMod functions portmod_port_local/remote_fault_status_get()
   2646      * only return the fault status field values and do not check
   2647      * for the fault disable fields.
   2648      *
   2649      * In order to maintain the same API behavior,
   2650      * we need to call additional PortMod functions to check
   2651      * the fault disable fields.
   2652      */
   2653 
   2654     rv = portmod_port_local_fault_control_get(unit, pport, &local_control);
   2655     if (PORTMOD_SUCCESS(rv)) {
   2656         if (local_control.enable) {
   2657             rv = portmod_port_local_fault_status_get(unit, pport,
   2658                                                      &local_fault);
   2659         }
   2660     }
   2661 
   2662     if (PORTMOD_SUCCESS(rv)) {
   2663         rv = portmod_port_remote_fault_control_get(unit, pport,
   2664                                                    &remote_control);
   2665         if (PORTMOD_SUCCESS(rv)) {
   2666             if (remote_control.enable) {
   2667                 rv = portmod_port_remote_fault_status_get(unit, pport,
   2668                                                           &remote_fault);
   2669             }
   2670         }
   2671     }
   2672 
   2673     PORT_UNLOCK(unit);
   2674 
   2675     *flags = 0;
   2676     if (local_fault) {
   2677         *flags |= BCM_PORT_FAULT_LOCAL;
   2678     }
   2679     if (remote_fault) {
   2680         *flags |= BCM_PORT_FAULT_REMOTE;
   2681     }
   2682 
   2683     return rv;
   2684 
   2685 #else  /* PORTMOD_SUPPORT */
   2686     return BCM_E_UNAVAIL;
   2687 #endif /* PORTMOD_SUPPORT */
   2688 }
   2689 
   2690 
   2691 /*
   2692  * Function:
   2693  *      bcmi_esw_portctrl_link_fault_get
   2694  * Description:
   2695  *      Get the fault and remote fault status.
   2696  * Parameters:
   2697  *      unit         - (IN) Device number.
   2698  *      port         - (IN) Port number.
   2699  *      local_fault  - (OUT) Local fault status
   2700  *      remote_fault - (OUT) Remote fault status
   2701  * Returns:
   2702  *      BCM_E_XXX
   2703  */
   2704 int
   2705 bcmi_esw_portctrl_link_fault_get(int unit, bcm_gport_t port,
   2706                                  int *local_fault, int *remote_fault)
   2707 {
   2708 #ifdef PORTMOD_SUPPORT
   2709     int rv = BCM_E_NONE;
   2710     portctrl_pport_t pport;
   2711 
   2712     PORTCTRL_INIT_CHECK(unit);
   2713 
   2714     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2715 
   2716     PORT_LOCK(unit);
   2717     rv = portmod_port_local_fault_status_get(unit, pport, local_fault);
   2718     if (PORTMOD_SUCCESS(rv)) {
   2719         rv = portmod_port_remote_fault_status_get(unit, pport, remote_fault);
   2720     }
   2721     PORT_UNLOCK(unit);
   2722 
   2723     return rv;
   2724 
   2725 #else  /* PORTMOD_SUPPORT */
   2726     return BCM_E_UNAVAIL;
   2727 #endif /* PORTMOD_SUPPORT */
   2728 }
   2729 
   2730 
   2731 /*
   2732  * Function:
   2733  *      bcmi_esw_portctrl_loopback_get
   2734  * Purpose:
   2735  *      Recover the current loopback operation for the specified port.
   2736  * Parameters:
   2737  *      unit     - (IN) Unit number.
   2738  *      port     - (IN) Port number.
   2739  *      loopback - (OUT) One of:
   2740  *                       BCM_PORT_LOOPBACK_NONE
   2741  *                       BCM_PORT_LOOPBACK_MAC
   2742  *                       BCM_PORT_LOOPBACK_PHY
   2743  * Returns:
   2744  *      BCM_E_NONE
   2745  *      BCM_E_XXX
   2746  */
   2747 int
   2748 bcmi_esw_portctrl_loopback_get(int unit, bcm_gport_t port, int *loopback)
   2749 {
   2750 #ifdef PORTMOD_SUPPORT
   2751     int rv = BCM_E_NONE;
   2752     portctrl_pport_t pport;
   2753     int i = 0, enable = 0;
   2754     int phy_lane = -1;
   2755     int phyn = 0, sys_side = 0;
   2756     bcm_port_t  local_port = -1;
   2757     uint32 phy_lb = 0;
   2758 
   2759     portmod_loopback_mode_t portmod_lb_modes[] = {
   2760         portmodLoopbackMacOuter,
   2761         portmodLoopbackPhyGloopPMD,
   2762         portmodLoopbackPhyGloopPCS,
   2763         portmodLoopbackPhyRloopPMD
   2764         /* portmodLoopbackPhyRloopPCS - no support */
   2765     };
   2766     int bcm_lb_modes[] = {
   2767         BCM_PORT_LOOPBACK_MAC,
   2768         BCM_PORT_LOOPBACK_PHY,
   2769         BCM_PORT_LOOPBACK_PHY,
   2770         BCM_PORT_LOOPBACK_PHY_REMOTE,
   2771         BCM_PORT_LOOPBACK_PHY_REMOTE
   2772     };
   2773 
   2774     PORTCTRL_INIT_CHECK(unit);
   2775 
   2776     BCM_IF_ERROR_RETURN(
   2777         _bcm_esw_port_gport_phyn_validate(unit, port,
   2778                                           &local_port, &phyn,
   2779                                           &phy_lane, &sys_side));
   2780 
   2781     if (local_port != -1) {
   2782         port = local_port;
   2783     }
   2784 
   2785     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2786 
   2787     if (local_port != -1) {
   2788         PORT_LOCK(unit);
   2789         rv = portmod_port_redirect_loopback_get(unit, pport, phyn,
   2790                                                 phy_lane, sys_side,
   2791                                                 &phy_lb);
   2792         PORT_UNLOCK(unit);
   2793         if (PORTMOD_FAILURE(rv)) {
   2794             LOG_VERBOSE(BSL_LS_BCM_PORT,
   2795                         (BSL_META_UP(unit, port,
   2796                             "Redirect loopback get failed: p=%d, rv=%d"),
   2797                         port, rv));
   2798             return rv;
   2799         }
   2800     }
   2801 
   2802     *loopback = BCM_PORT_LOOPBACK_NONE;
   2803 
   2804     for (i = 0; i < COUNTOF(portmod_lb_modes); i++) {
   2805         PORT_LOCK(unit);
   2806         rv = portmod_port_loopback_get(unit, pport,
   2807                                        portmod_lb_modes[i], &enable);
   2808         PORT_UNLOCK(unit);
   2809 
   2810         if (PORTMOD_FAILURE(rv)) {
   2811             LOG_VERBOSE(BSL_LS_BCM_PORT,
   2812                         (BSL_META_UP(unit, port,
   2813                                      "Loopback get failed: p=%d, rv=%d"),
   2814                         port, rv));
   2815             return rv;
   2816         }
   2817 
   2818         if (enable) {
   2819             *loopback = bcm_lb_modes[i];
   2820             break;
   2821         }
   2822     }
   2823 
   2824     if (*loopback != BCM_PORT_LOOPBACK_MAC && phy_lb) {
   2825         *loopback = BCM_PORT_LOOPBACK_PHY;
   2826     }
   2827 
   2828     return BCM_E_NONE;
   2829 
   2830 #else  /* PORTMOD_SUPPORT */
   2831     return BCM_E_UNAVAIL;
   2832 #endif /* PORTMOD_SUPPORT */
   2833 }
   2834 
   2835 
   2836 /*
   2837  * Function:
   2838  *      bcmi_esw_portctrl_loopback_set
   2839  * Purpose:
   2840  *      Set loopback mode for the specified port.
   2841  * Parameters:
   2842  *      unit - StrataSwitch Unit #.
   2843  *      port - StrataSwitch port #.
   2844  *      loopback - one of:
   2845  *              BCM_PORT_LOOPBACK_NONE
   2846  *              BCM_PORT_LOOPBACK_MAC
   2847  *              BCM_PORT_LOOPBACK_PHY
   2848  * Returns:
   2849  *      BCM_E_NONE
   2850  *      BCM_E_XXX
   2851  */
   2852 int
   2853 bcmi_esw_portctrl_loopback_set(int unit, bcm_gport_t port, int loopback)
   2854 {
   2855 #ifdef PORTMOD_SUPPORT
   2856     int rv = BCM_E_NONE, link = TRUE;
   2857     portctrl_pport_t pport;
   2858     int lpbk_type;
   2859     int phy_lane = -1;
   2860     int phyn = 0, sys_side = 0;
   2861     int flags = 0, is_loopback_set = 0;
   2862     int mac_lpbk = 0, phy_lpbk = 0, rmt_lpbk = 0;
   2863     bcm_port_t local_port = -1;
   2864     int tmp_flags=0, soc_flag = 0;
   2865     soc_persist_t *sop = SOC_PERSIST(unit);
   2866     portmod_dispatch_type_t pm_type = portmodDispatchTypeCount;
   2867 
   2868     PORTCTRL_INIT_CHECK(unit);
   2869 
   2870     BCM_IF_ERROR_RETURN(
   2871         _bcm_esw_port_gport_phyn_validate(unit, port,
   2872                                           &local_port, &phyn,
   2873                                           &phy_lane, &sys_side));
   2874 
   2875     if (local_port != -1) {
   2876         port = local_port;
   2877     }
   2878 
   2879     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   2880 
   2881 #ifdef BCM_RCPU_SUPPORT
   2882     if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   2883         return BCM_E_PORT;
   2884     }
   2885 #endif /* BCM_RCPU_SUPPORT */
   2886 
   2887     /* get current loopback state.  Do nothing if the current state matches requested state */
   2888     if (local_port == -1) {
   2889         rv = portmod_port_loopback_get(unit, pport, portmodLoopbackMacOuter,    &mac_lpbk); 
   2890         if (PORTMOD_FAILURE(rv)) return(rv);
   2891  
   2892         rv = portmod_port_loopback_get(unit, pport, portmodLoopbackPhyGloopPCS, &phy_lpbk);
   2893         if (PORTMOD_FAILURE(rv)) return(rv);
   2894 
   2895         rv = portmod_port_loopback_get(unit, pport, portmodLoopbackPhyRloopPMD, &rmt_lpbk);
   2896         if (PORTMOD_FAILURE(rv)) return(rv);
   2897 
   2898         if (((loopback == BCM_PORT_LOOPBACK_MAC) && mac_lpbk) ||
   2899             ((loopback == BCM_PORT_LOOPBACK_PHY) && phy_lpbk) ||
   2900             ((loopback == BCM_PORT_LOOPBACK_PHY_REMOTE) && rmt_lpbk) ||
   2901             ((loopback == BCM_PORT_LOOPBACK_NONE) && !mac_lpbk && !phy_lpbk && !rmt_lpbk)) {
   2902 
   2903             /* current state matches with requested state - dont need to do anything */
   2904             LOG_VERBOSE(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, "Port%d : Loopback Command Skip (State Match)\n"), port));
   2905             is_loopback_set = 1;
   2906         }
   2907     }
   2908 
   2909     PORTMOD_PORT_ENABLE_PHY_SET(flags);
   2910     PORT_LOCK(unit);
   2911     rv = portmod_port_enable_get(unit, pport, flags, &link);
   2912     PORT_UNLOCK(unit);
   2913 
   2914     if (PORTMOD_FAILURE(rv)) {
   2915         LOG_VERBOSE(BSL_LS_BCM_PORT,
   2916                     (BSL_META_UP(unit, port,
   2917                                  "Get port enable failed: p=%d, rv=%d"),
   2918                     port, rv));
   2919     }
   2920 
   2921     if (TRUE == link) {
   2922         PORT_LOCK(unit);
   2923 
   2924         if (SOC_PBMP_MEMBER(sop->lc_pbm_override_ports, port)) {
   2925             if(!SOC_PBMP_MEMBER(sop->lc_pbm_override_link, port)) {
   2926                 link = FALSE;
   2927             }
   2928         }
   2929 
   2930         PORT_UNLOCK(unit);
   2931     }
   2932 
   2933     /*
   2934      * Always force link before changing hardware to avoid
   2935      * race with the linkscan thread.
   2936      */
   2937     if (!(loopback == BCM_PORT_LOOPBACK_NONE)) {
   2938         rv = _bcm_esw_link_force(unit, 0 /*flags*/, port, TRUE, FALSE);
   2939 
   2940         if(rv == BCM_E_NONE) {
   2941             /* Force the update function to be called so the state is
   2942                updated */
   2943             if (_soc_linkscan_phy_flags_test(unit, port, PHY_FLAGS_EXTERNAL_PHY)) {
   2944                 rv = bcm_esw_port_update(unit, port, TRUE);
   2945             }
   2946         }
   2947     }
   2948 
   2949     if (BCM_FAILURE(rv)) {
   2950         return (rv);
   2951     }
   2952 
   2953     rv = portmod_port_pm_type_get(unit, port, &port, &pm_type);
   2954     if (rv != BCM_E_NONE) {
   2955         return rv;
   2956     }
   2957 
   2958     if (!is_loopback_set) {
   2959         PORT_LOCK(unit);
   2960 
   2961         if (local_port == -1) {
   2962             lpbk_type = portmodLoopbackCount;
   2963 #ifdef PORTMOD_PM12X10_SUPPORT
   2964             if (pm_type == portmodDispatchTypePm12x10){
   2965                 soc_flag = 1;
   2966             }
   2967 #endif
   2968             /* MAC loopback needs to clear the credits of
   2969              * EDB at the stage of soft_reset of clmac in
   2970              * portmod_port_loopback_set (PM4x25)
   2971              */
   2972             if (soc_flag) {
   2973                 if ((loopback == BCM_PORT_LOOPBACK_MAC) ||
   2974                        ((loopback != BCM_PORT_LOOPBACK_MAC) && (mac_lpbk == BCM_PORT_LOOPBACK_MAC))) {
   2975                        rv = soc_egress_enable(unit, pport, 0);
   2976                        if (BCM_FAILURE(rv)) {
   2977                            PORT_UNLOCK(unit);
   2978                            return rv;
   2979                        }
   2980                        rv = soc_port_credit_reset(unit, pport);
   2981                        if (BCM_FAILURE(rv)) {
   2982                            PORT_UNLOCK(unit);
   2983                            return rv;
   2984                        }
   2985                        rv = soc_egress_enable(unit, pport, 1);
   2986                        if (BCM_FAILURE(rv)) {
   2987                            PORT_UNLOCK(unit);
   2988                            return rv;
   2989                        }
   2990                 }
   2991             }
   2992 
   2993             /* clear if any loopback was set prior */
   2994             if (BCM_SUCCESS(rv) && mac_lpbk) {
   2995                 rv = portmod_port_loopback_set(unit, pport,
   2996                                                portmodLoopbackMacOuter, 0);
   2997             }
   2998             if (BCM_SUCCESS(rv) && phy_lpbk) {
   2999                 rv = portmod_port_loopback_set(unit, pport,
   3000                                                portmodLoopbackPhyGloopPCS, 0);
   3001             }
   3002             if (BCM_SUCCESS(rv) && rmt_lpbk) {
   3003                 rv = portmod_port_loopback_set(unit, pport,
   3004                                                portmodLoopbackPhyRloopPMD, 0);
   3005             }
   3006 
   3007             if (BCM_FAILURE(rv)) {
   3008                 PORT_UNLOCK(unit);
   3009                 return (rv);
   3010             }
   3011 
   3012             if (loopback == BCM_PORT_LOOPBACK_MAC) {
   3013                 lpbk_type =  portmodLoopbackMacOuter;
   3014             } else if (loopback == BCM_PORT_LOOPBACK_PHY){
   3015                 lpbk_type =  portmodLoopbackPhyGloopPCS;
   3016             } else if (loopback == BCM_PORT_LOOPBACK_PHY_REMOTE) {
   3017                 lpbk_type = portmodLoopbackPhyRloopPMD;
   3018             }
   3019 
   3020             if (lpbk_type != portmodLoopbackCount) {
   3021                 rv = portmod_port_loopback_set(unit, pport, lpbk_type, 1);
   3022             }
   3023         } else {
   3024             rv = portmod_port_redirect_loopback_set(unit, pport,
   3025                             phyn, phy_lane, sys_side,
   3026                             (loopback == BCM_PORT_LOOPBACK_PHY)? 1 : 0);
   3027         }
   3028         PORT_UNLOCK(unit);  /* unlock before link call */
   3029     }
   3030 
   3031     flags = 0;
   3032     PORTMOD_PORT_ENABLE_PHY_SET(flags);
   3033     PORTMOD_PORT_ENABLE_MAC_SET(flags);
   3034 
   3035     if ((loopback == BCM_PORT_LOOPBACK_NONE) || PORTMOD_FAILURE(rv)) {
   3036         _bcm_esw_link_force(unit, 0 /*flags*/, port, FALSE, DONT_CARE);
   3037 
   3038         if ((FALSE == link) && (loopback == BCM_PORT_LOOPBACK_NONE)) {
   3039             PORT_LOCK(unit);
   3040             rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0);
   3041             PORT_UNLOCK(unit);
   3042         } else {
   3043             /* Phy need to be re-enable when the port is enabled and
   3044                clearing the loopback. */
   3045             tmp_flags = 0;
   3046             PORTMOD_PORT_ENABLE_PHY_SET(tmp_flags);
   3047             PORTMOD_IF_ERROR_RETURN
   3048                 (portmod_port_enable_set(unit, port, tmp_flags, 1));
   3049         }
   3050     } else {
   3051 #ifdef PORTMOD_PM8X50_SUPPORT
   3052         if (pm_type == portmodDispatchTypePm8x50){
   3053             PORTMOD_PORT_ENABLE_PHY_CLR(flags);
   3054         }
   3055 #endif
   3056         PORT_LOCK(unit);
   3057         rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 1);
   3058 
   3059         /* If the port is disabled and apply loopback, phy need to
   3060            be disabled. */
   3061         if(FALSE == link){
   3062             tmp_flags = 0;
   3063             PORTMOD_PORT_ENABLE_PHY_SET(tmp_flags);
   3064             rv = portmod_port_enable_set(unit, port, tmp_flags, 0);
   3065             if (PORTMOD_FAILURE(rv)) {
   3066                 PORT_UNLOCK(unit);
   3067                 return rv;
   3068             }
   3069         }
   3070 
   3071         PORT_UNLOCK(unit);
   3072 
   3073         if (PORTMOD_SUCCESS(rv)) {
   3074             /* Make sure that the link status is updated only after the
   3075              * MAC is enabled so that link_mask2 is set before the
   3076              * calling thread synchronizes with linkscan thread in
   3077              * _bcm_link_force call.
   3078              * If the link is forced before MAC is enabled, there could
   3079              * be a race condition in _soc_link_update where linkscan 
   3080              * may use an old view of link_mask2 and override the
   3081              * EPC_LINK_BMAP after the mac_enable_set updates 
   3082              * link_mask2 and EPC_LINK_BMAP. 
   3083              */
   3084             if (loopback == BCM_PORT_LOOPBACK_MAC) {
   3085                 rv = _bcm_esw_link_force(unit, 0 /*flags*/, port, TRUE, TRUE);
   3086             } else {
   3087                 rv = _bcm_esw_link_force(unit, 0 /*flags*/, port, TRUE, link);
   3088             }
   3089         }
   3090     }
   3091 
   3092     LOG_INFO(BSL_LS_BCM_PORT,
   3093              (BSL_META_UP(unit, port,
   3094                           "bcm_port_loopback_set: p=%d lb=%d rv=%d\n"),
   3095               port, loopback, rv));
   3096 
   3097     return rv;
   3098 
   3099 #else   /* PORTMOD_SUPPORT */
   3100     return BCM_E_UNAVAIL;
   3101 #endif  /* PORTMOD_SUPPORT */
   3102 }
   3103 
   3104 /*
   3105  * Function:
   3106  *      bcmi_esw_portctrl_speed_get
   3107  * Purpose:
   3108  *      Getting the speed of the port
   3109  * Parameters:
   3110  *      unit - StrataSwitch Unit #.
   3111  *      port - StrataSwitch port #.
   3112  *      speed - (OUT) Value in megabits/sec (10, 100, etc)
   3113  * Returns:
   3114  *      BCM_E_NONE
   3115  *      BCM_E_XXX
   3116  * Notes:
   3117  *      If port is in MAC loopback, the speed of the loopback is returned.
   3118  */
   3119 int
   3120 bcmi_esw_portctrl_speed_get(int unit, bcm_gport_t port, int *speed)
   3121 {
   3122 #ifdef PORTMOD_SUPPORT
   3123     int rv = BCM_E_NONE, valid = 0;
   3124     portctrl_pport_t  pport;
   3125     portmod_port_interface_config_t portmod_if_config;
   3126 #ifdef PORTMOD_PM8X50_SUPPORT
   3127     portmod_speed_config_t portmod_sp_config;
   3128     portmod_dispatch_type_t pm_type;
   3129     int phy_port;
   3130 #endif
   3131 
   3132     PORTCTRL_INIT_CHECK(unit);
   3133 
   3134     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   3135 
   3136     BCM_IF_ERROR_RETURN(portmod_port_is_valid(unit, pport, &valid));
   3137     if (!valid) {
   3138         return BCM_E_PORT;
   3139     }
   3140 
   3141 #ifdef PORTMOD_PM8X50_SUPPORT
   3142     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   3143 #ifdef BCM_TOMAHAWK3_SUPPORT
   3144         /* Tomahawk 3's Management Port Macro requires a spacing between
   3145          * the lanes, so even though the two management ports' physical
   3146          * ports are 257 and 258, the lane needs to be the next one,
   3147          * so logical port 118 being mapped to physical port 258 needs
   3148          * to pass 259 to portmod because portmod only recognizes lane
   3149          * 0 (physical port 257) and lane 2 (physial port 259).
   3150          */
   3151         if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) {
   3152             phy_port = 259;
   3153         }
   3154 #endif
   3155 
   3156     BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type));
   3157     if (pm_type == portmodDispatchTypePm8x50) {
   3158         PORT_LOCK(unit);
   3159         rv = portmod_port_speed_config_get(unit, pport, &portmod_sp_config);
   3160         PORT_UNLOCK(unit);
   3161 
   3162         if (PORTMOD_SUCCESS(rv)) {
   3163             *speed = portmod_sp_config.speed;
   3164         }
   3165         LOG_INFO(BSL_LS_BCM_PORT,
   3166              (BSL_META_UP(unit, port,
   3167                           "Get port speed: p=%d speed=%d rv=%d\n"),
   3168               port, BCM_SUCCESS(rv) ? *speed : 0, rv));
   3169 
   3170         return rv;
   3171     }
   3172 #endif
   3173 
   3174 
   3175     PORT_LOCK(unit);
   3176     rv = portmod_port_interface_config_get(unit, pport, &portmod_if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   3177     PORT_UNLOCK(unit);
   3178 
   3179     if (PORTMOD_SUCCESS(rv)) {
   3180         *speed = portmod_if_config.speed;
   3181 
   3182         if (IS_HG_PORT(unit, port) && *speed < 5000) {
   3183             *speed = 0;
   3184         }
   3185     }
   3186 
   3187     LOG_INFO(BSL_LS_BCM_PORT,
   3188              (BSL_META_UP(unit, port,
   3189                           "Get port speed: p=%d speed=%d rv=%d\n"),
   3190               port, BCM_SUCCESS(rv) ? *speed : 0, rv));
   3191 
   3192     return rv;
   3193 
   3194 #else   /* PORTMOD_SUPPORT */
   3195     return BCM_E_UNAVAIL;
   3196 #endif  /* PORTMOD_SUPPORT */
   3197 }
   3198 
   3199 STATIC int
   3200 bcmi_esw_portctrl_speed_ability_local_max(int unit, bcm_gport_t port,
   3201                                             int *speed_max)
   3202 {
   3203 #ifdef PORTMOD_SUPPORT
   3204     bcm_port_speed_ability_t *abilities;
   3205     int actual_num_ability = 0, max = 0;
   3206     int i, rv;
   3207 
   3208     abilities = sal_alloc(PORTCTRL_SPEED_ABILITY_MAX_COUNT *
   3209                             sizeof(bcm_port_speed_ability_t), "speed abilities");
   3210     if (NULL == abilities) {
   3211         return BCM_E_MEMORY;
   3212     }
   3213 
   3214     rv = bcmi_esw_portctrl_speed_ability_local_get(unit,
   3215                                               port,
   3216                                               PORTCTRL_SPEED_ABILITY_MAX_COUNT,
   3217                                               abilities,
   3218                                               &actual_num_ability);
   3219     if (BCM_FAILURE(rv)) {
   3220         goto cleanup;
   3221     }
   3222 
   3223     for (i = 0; i < actual_num_ability; i++) {
   3224         if (abilities[i].speed > max) {
   3225             max = abilities[i].speed;
   3226         }
   3227     }
   3228 
   3229     *speed_max = max;
   3230 
   3231 cleanup:
   3232     if (NULL != abilities) {
   3233         sal_free(abilities);
   3234     }
   3235 
   3236     return BCM_E_NONE;
   3237 #else /* Portmod Support */
   3238     return BCM_E_UNAVAIL;
   3239 #endif /* Portmod Support */
   3240 }
   3241 
   3242 /*
   3243  * Function:
   3244  *      bcmi_esw_portctrl_speed_max
   3245  * Purpose:
   3246  *      Getting the maximum speed of the port
   3247  * Parameters:
   3248  *      unit - StrataSwitch Unit #.
   3249  *      port - StrataSwitch port #.
   3250  *      speed - (OUT) Value in megabits/sec (10, 100, etc)
   3251  * Returns:
   3252  *      BCM_E_NONE
   3253  *      BCM_E_XXX
   3254  */
   3255 int
   3256 bcmi_esw_portctrl_speed_max(int unit, bcm_gport_t port, int *speed)
   3257 {
   3258 #ifdef PORTMOD_SUPPORT
   3259     int rv;
   3260     bcm_port_ability_t ability;
   3261     portctrl_pport_t  pport;
   3262 #ifdef PORTMOD_PM8X50_SUPPORT
   3263     portmod_dispatch_type_t pm_type;
   3264     int phy_port;
   3265 #endif
   3266 
   3267     PORTCTRL_INIT_CHECK(unit);
   3268 
   3269     sal_memset(&ability, 0, sizeof(bcm_port_ability_t));
   3270 
   3271     if (speed == NULL) {
   3272         return (BCM_E_PARAM);
   3273     }
   3274 
   3275     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   3276 
   3277 #ifdef PORTMOD_PM8X50_SUPPORT
   3278     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   3279 #ifdef BCM_TOMAHAWK3_SUPPORT
   3280         /* Tomahawk 3's Management Port Macro requires a spacing between
   3281          * the lanes, so even though the two management ports' physical
   3282          * ports are 257 and 258, the lane needs to be the next one,
   3283          * so logical port 118 being mapped to physical port 258 needs
   3284          * to pass 259 to portmod because portmod only recognizes lane
   3285          * 0 (physical port 257) and lane 2 (physial port 259).
   3286          */
   3287         if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) {
   3288             phy_port = 259;
   3289         }
   3290 #endif
   3291     BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type));
   3292     
   3293     if (pm_type == portmodDispatchTypePm8x50) {
   3294         rv = bcmi_esw_portctrl_speed_ability_local_max(unit, port,
   3295                                         speed);
   3296     } else
   3297 #endif
   3298     {
   3299 
   3300     rv = bcmi_esw_portctrl_ability_get(unit, port, &ability, NULL);
   3301 
   3302     if (BCM_SUCCESS(rv)) {
   3303             {
   3304         *speed = BCM_PORT_ABILITY_SPEED_MAX(ability.speed_full_duplex |
   3305                                             ability.speed_half_duplex);
   3306             }
   3307 
   3308         if (IS_HG_PORT(unit, port)) {
   3309             if (SOC_INFO(unit).port_speed_max[port]) {
   3310                 switch (*speed) {
   3311                 case 10000:
   3312                 case 20000:
   3313                 case 40000:
   3314                 case 100000:
   3315                 case 120000:
   3316                     *speed = SOC_INFO(unit).port_speed_max[port];
   3317                     break;
   3318                 default:
   3319                     break;
   3320                 }
   3321             }
   3322         } else {
   3323             switch (*speed) {
   3324             case 11000:
   3325             case 21000:
   3326             case 42000:
   3327             case 106000:
   3328             case 127000:
   3329                 *speed = SOC_INFO(unit).port_speed_max[port];
   3330                 break;
   3331             case 13000:
   3332             case 16000:
   3333                 if(SOC_IS_TITAN2PLUS(unit)){
   3334                     *speed = SOC_INFO(unit).port_speed_max[port];
   3335                 }
   3336                 break;
   3337             default:
   3338                 break;
   3339             }
   3340         }
   3341 
   3342     } else {
   3343         *speed = 0;
   3344     }
   3345     }
   3346 
   3347     LOG_INFO(BSL_LS_BCM_PORT,
   3348              (BSL_META_UP(unit, port,
   3349                           "Max port speed: p=%d speed=%d rv=%d\n"),
   3350               port, *speed, rv));
   3351 
   3352     return rv;
   3353 
   3354 #else   /* PORTMOD_SUPPORT */
   3355     return BCM_E_UNAVAIL;
   3356 #endif  /* PORTMOD_SUPPORT */
   3357 }
   3358 
   3359 #ifdef PORTMOD_SUPPORT
   3360 
   3361 /*
   3362  * Function:
   3363  *      _bcm_esw_portctrl_speed_validate
   3364  * Purpose:
   3365  *      Validate the speed change can be supported
   3366  * Parameters:
   3367  *      unit     - SOC unit number
   3368  *      port     - bcm_gport_t port number
   3369  *      speed    - port speed
   3370  * Returns:
   3371  *      BCM_E_XXX
   3372  */
   3373 STATIC int
   3374 _bcm_esw_portctrl_speed_validate(int unit, bcm_gport_t port, int speed)
   3375 {
   3376     bcm_port_ability_t port_ability, requested_ability;
   3377     int mode = -1;
   3378     int rv;
   3379     int max_speed;
   3380 
   3381     /* PM8x50 ports will have their speed config checked in portmod */
   3382     if (IS_CD_PORT(unit, port)) {
   3383         if (BCM_ESW_PORT_DRV(unit)!= NULL) {
   3384             if (BCM_ESW_PORT_DRV(unit)->device_speed_check != NULL) {
   3385                 
   3386                 rv = (BCM_ESW_PORT_DRV(unit)->device_speed_check(unit,
   3387                                                             speed, -1));
   3388                 if (BCM_FAILURE(rv)) {
   3389                     return rv;
   3390                 }
   3391             }
   3392         }
   3393 
   3394         /* On a speed change validate, don't allow higher speed than
   3395          * port_speed_max. User needs to flex up */
   3396         BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_speed_ability_local_max(
   3397                     unit, port, &max_speed));
   3398         if (speed > max_speed) {
   3399             return BCM_E_CONFIG;
   3400         }
   3401         return BCM_E_NONE;
   3402     }
   3403 
   3404     sal_memset(&port_ability, 0, sizeof(bcm_port_ability_t));
   3405     sal_memset(&requested_ability, 0, sizeof(bcm_port_ability_t));
   3406 
   3407     BCM_IF_ERROR_RETURN
   3408         (bcmi_esw_portctrl_ability_get(unit, port, &port_ability, NULL));
   3409     BCM_IF_ERROR_RETURN
   3410         (bcmi_esw_portctrl_encap_get(unit, port, &mode));
   3411 
   3412     requested_ability.speed_full_duplex = SOC_PA_SPEED(speed);
   3413     requested_ability.speed_half_duplex = SOC_PA_SPEED(speed);
   3414 
   3415     if (((port_ability.speed_full_duplex &
   3416           requested_ability.speed_full_duplex) == 0) &&
   3417         ((port_ability.speed_half_duplex &
   3418           requested_ability.speed_half_duplex) == 0)) {
   3419         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3420                     (BSL_META_UP(unit, port,
   3421                                  "Port %d doesn't support %d Mbps speed.\n"),
   3422                     port, speed));
   3423         return BCM_E_CONFIG;
   3424     }
   3425 
   3426     /* Higig speed on Ethernet port is not supported */
   3427     if ((mode == BCM_PORT_ENCAP_IEEE) && SOC_PORTCTRL_IS_HG2_SPEED(speed)) {
   3428         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3429                     (BSL_META_UP(unit, port,
   3430                                  "Port %d doesn't support %d Mbps speed.\n"),
   3431                     port, speed));
   3432         return BCM_E_CONFIG;
   3433     }
   3434 
   3435     return BCM_E_NONE;
   3436 }
   3437 
   3438 /*
   3439  * Function:
   3440  *      _bcm_esw_portctrl_disable_autoneg
   3441  * Purpose:
   3442  *      Disable Autoneg
   3443  * Parameters:
   3444  *      unit     - SOC unit number
   3445  *      pport    - port type for portmod function
   3446  * Returns:
   3447  *      BCM_E_XXX
   3448  */
   3449 STATIC int
   3450 _bcm_esw_portctrl_disable_autoneg(int unit, portctrl_pport_t  pport)
   3451 {
   3452     int rv;
   3453     phymod_autoneg_control_t an;
   3454 
   3455     sal_memset(&an, 0, sizeof(phymod_autoneg_control_t));
   3456 
   3457     PORT_LOCK(unit);
   3458     rv = portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an);
   3459     if (PORTMOD_FAILURE(rv)) {
   3460         PORT_UNLOCK(unit);
   3461         return rv;
   3462     }
   3463 
   3464     an.enable = FALSE;
   3465 
   3466     rv = portmod_port_autoneg_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an);
   3467     if (PORTMOD_FAILURE(rv)) {
   3468         PORT_UNLOCK(unit);
   3469         return rv;
   3470     }
   3471     PORT_UNLOCK(unit);
   3472 
   3473     return BCM_E_NONE;
   3474 }
   3475 
   3476 /*
   3477  * Function:
   3478  *      _bcm_esw_portctrl_speed_chip_reconfig
   3479  * Purpose:
   3480  *      Reconfigure chip(PGW/TDM/IP/EP/MMU) for speed set change
   3481  * Parameters:
   3482  *      unit     - SOC unit number
   3483  *      port     - bcm_port_t port number
   3484  *      speed    - port speed
   3485  * Returns:
   3486  *      BCM_E_XXX
   3487  */
   3488 STATIC int
   3489 _bcm_esw_portctrl_speed_chip_reconfigure(int unit, bcm_port_t port, int speed)
   3490 {
   3491     int rv = BCM_E_NONE;
   3492 
   3493     PORT_LOCK(unit);
   3494     if (BCM_ESW_PORT_DRV(unit)!= NULL) {
   3495         if (BCM_ESW_PORT_DRV(unit)->resource_speed_set != NULL) {
   3496             rv = BCM_ESW_PORT_DRV(unit)->resource_speed_set(unit, port,
   3497                                                             speed);
   3498         }
   3499     }
   3500     PORT_UNLOCK(unit);
   3501 
   3502     if (BCM_FAILURE(rv)) {
   3503         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3504                     (BSL_META_UP(unit, port,
   3505                                  "Set speed for chip resource failed\n")));
   3506     }
   3507 
   3508     return rv;
   3509 }
   3510 
   3511 /*
   3512  * Function:
   3513  *      _bcm_esw_portctrl_speed_interface_config_set
   3514  * Purpose:
   3515  *      Change interface for speed.
   3516  * Parameters:
   3517  *      unit     - SOC unit number
   3518  *      port     - bcm_port_t port number
   3519  *      pport    - port number for portmod function
   3520  *      speed    - port speed
   3521  * Returns:
   3522  *      BCM_E_XXX
   3523  */
   3524 STATIC int
   3525 _bcm_esw_portctrl_speed_interface_config_set(int unit, bcm_gport_t port,
   3526                                              portctrl_pport_t pport, int speed)
   3527 {
   3528     int rv;
   3529     portmod_port_interface_config_t portmod_if_config;
   3530     soc_port_if_t sys_interface;
   3531     soc_port_if_t default_interface;
   3532     bcm_gport_t   gport;
   3533 
   3534     PORT_LOCK(unit);
   3535 
   3536     rv = portmod_port_interface_config_get(unit, pport, &portmod_if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   3537     if (PORTMOD_FAILURE(rv)) {
   3538         PORT_UNLOCK(unit);
   3539         return rv;
   3540     }
   3541 
   3542     /* When changing the speed, the existing interface type of the
   3543      * port may not be valid anymore. Need to retrieve the default
   3544      * interface type based on the new speed and update 
   3545      * portmod_if_config.
   3546      */
   3547     if (portmod_if_config.speed != speed) {
   3548         portmod_if_config.speed = speed;
   3549         default_interface = SOC_PORT_IF_NULL;
   3550         rv = portmod_port_default_interface_get(
   3551                 unit, port, &portmod_if_config, &default_interface);
   3552         if (SOC_FAILURE(rv)) {
   3553             PORT_UNLOCK(unit);
   3554             return (rv);
   3555         }
   3556         if (default_interface != SOC_PORT_IF_NULL) {
   3557             portmod_if_config.interface = default_interface;
   3558         } else {
   3559             SOC_IF_ERROR_RETURN(
   3560                     portmod_common_default_interface_get(&portmod_if_config));
   3561         }
   3562     }
   3563 
   3564 
   3565     if (PORTMOD_SUCCESS(rv)) {
   3566         rv = _bcm_esw_portctrl_interface_config_set(unit, port, pport,
   3567                                                     &portmod_if_config, 1);
   3568     }
   3569 
   3570     sys_interface = soc_property_port_get(unit, port,
   3571                                 spn_PHY_SYS_INTERFACE, SOC_PORT_IF_COUNT);
   3572 
   3573     if (sys_interface != SOC_PORT_IF_COUNT) {
   3574         BCM_PHY_GPORT_PHYN_SYS_SIDE_PORT_SET(gport, 0, port);
   3575         bcmi_esw_portctrl_phy_control_set(unit, gport, SOC_PHY_CONTROL_INTERFACE,
   3576                                             sys_interface);
   3577     }
   3578 
   3579     PORT_UNLOCK(unit);
   3580 
   3581     if (PORTMOD_FAILURE(rv)) {
   3582         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3583                     (BSL_META_UP(unit, port,
   3584                                 "Set port speed failed: p=%d speed=%d rv=%d\n"),
   3585                     port, speed, rv));
   3586     }
   3587 
   3588     return rv;
   3589 }
   3590 #endif
   3591 
   3592 /*
   3593  * Function:
   3594  *      bcmi_esw_portctrl_speed_set
   3595  * Purpose:
   3596  *      Setting the speed for a given port
   3597  * Parameters:
   3598  *      unit - StrataSwitch Unit #.
   3599  *      port - StrataSwitch port #.
   3600  *      speed - Value in megabits/sec (10, 100, etc)
   3601  * Returns:
   3602  *      BCM_E_NONE
   3603  *      BCM_E_XXX
   3604  */
   3605 int
   3606 bcmi_esw_portctrl_speed_set(int unit, bcm_gport_t port, int speed)
   3607 {
   3608 #ifdef PORTMOD_SUPPORT
   3609     portctrl_pport_t  pport;
   3610     int cur_speed;
   3611     int loopback;
   3612     int enable;
   3613     int rv = SOC_E_NONE;
   3614 
   3615     /* If current speed is different from target speed,
   3616        need to call full speed_set sequence which includes IP/EP/MMU/TDM reprogramming
   3617        If current speed is same as target speed, just
   3618        need to disable Autoneg and call interface_config_set to apply interface change */
   3619 #define IS_FULL_SPEED_SET_REQUIRED(cur_speed, new_speed) \
   3620         ((cur_speed) != (new_speed))
   3621 
   3622     PORTCTRL_INIT_CHECK(unit);
   3623 
   3624     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   3625 
   3626     /* check inactive port */
   3627     if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port)) {
   3628         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3629                     (BSL_META_UP(unit, port,
   3630                                  "Port %d is inactive port\n"), port));
   3631         return BCM_E_NONE;
   3632     }
   3633 
   3634     /* if speed is 0, set the port speed to max */
   3635     if (speed == 0) {
   3636         BCM_IF_ERROR_RETURN
   3637             (bcmi_esw_portctrl_speed_max(unit, port, &speed));
   3638     }
   3639 
   3640     /* get current speed */
   3641     BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_speed_get(unit, port, &cur_speed));
   3642 
   3643 
   3644     if (IS_FULL_SPEED_SET_REQUIRED(cur_speed, speed)) {
   3645         /* validation : speed change is supported */
   3646         BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_speed_validate(unit, port, speed));
   3647 
   3648         /* clear loopback */
   3649         BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_get(unit,
   3650                                             port, &loopback));
   3651         if (loopback != BCM_PORT_LOOPBACK_NONE) {
   3652             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit,
   3653                                             port,
   3654                                             BCM_PORT_LOOPBACK_NONE));
   3655         }
   3656         BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_enable_get(unit, port, &enable));
   3657         if (enable == TRUE) {
   3658             /* disable MAC and PHY */
   3659             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_enable_set(unit, port, FALSE));
   3660         }
   3661 
   3662         /* disable AN */
   3663         BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_disable_autoneg(unit, pport));
   3664 
   3665         /* reconfigure chip (PGW/TDM/IP/EP/MMU) */
   3666         rv = _bcm_esw_portctrl_speed_chip_reconfigure(unit, port, speed);
   3667         if (BCM_SUCCESS(rv)) {
   3668             /* reconfigure MAC & PHY */
   3669             BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_speed_interface_config_set(
   3670                                         unit, port, pport, speed));
   3671         }
   3672         if (enable == TRUE) {
   3673             /* Restore port's enable state based on what was read prior to
   3674                setting speed */
   3675             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_enable_set(unit, port, TRUE));
   3676         }
   3677         /* restore loopback */
   3678         if (loopback != BCM_PORT_LOOPBACK_NONE) {
   3679             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit,
   3680                                             port,
   3681                                             loopback));
   3682         }
   3683     } else {
   3684         PORTMOD_IF_ERROR_RETURN
   3685             (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, &enable));
   3686 
   3687         /* No full sequence is not required. If speed is same,
   3688            just disable autoneg and apply interface_config_set */
   3689         if (enable == TRUE) {
   3690             /* Disable port */
   3691             BCM_IF_ERROR_RETURN
   3692                 (_bcm_esw_portctrl_enable_set(unit, port, pport,
   3693                                               PORTMOD_PORT_ENABLE_MAC, 0));
   3694         }
   3695 
   3696         /* Autoneg should be disabled after disabling the MAC */
   3697         BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_disable_autoneg(unit, pport));
   3698 
   3699         /* reconfigure MAC & PHY */
   3700         BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_speed_interface_config_set(
   3701                                     unit, port, pport, speed));
   3702         if (enable == TRUE) {
   3703             /* Restore port's enable state. */
   3704             BCM_IF_ERROR_RETURN
   3705                 (_bcm_esw_portctrl_enable_set(unit, port, pport,
   3706                                               PORTMOD_PORT_ENABLE_MAC, 1));
   3707         }
   3708     }
   3709     return rv;
   3710 
   3711 #else   /* PORTMOD_SUPPORT */
   3712     return BCM_E_UNAVAIL;
   3713 #endif  /* PORTMOD_SUPPORT */
   3714 }
   3715 
   3716 /* Function:
   3717  *      bcmi_esw_portctrl_resource_speed_config_validate
   3718  * Purpose:
   3719  *      Validate the resource configuration
   3720  * Parameters:
   3721  *     unit     - (IN) Unit number.
   3722  *     resource - (IN) The resource being validated
   3723  *     pbmp     - (OUT) The port bitmap of affected sister ports
   3724  * Returns:
   3725  *     BCM_E_NONE - Config is honored without affecting sister ports
   3726  *     BCM_E_PARAM - Config will affect sister ports in pbmp
   3727  */
   3728 int
   3729 bcmi_esw_portctrl_resource_speed_config_validate(int unit,
   3730                             bcm_port_resource_t *resource, bcm_pbmp_t *pbmp)
   3731 {
   3732 #ifdef PORTMOD_SUPPORT
   3733     int rv = BCM_E_NONE;
   3734     int port;
   3735     portctrl_pport_t pport;
   3736     portmod_speed_config_t sp_config;
   3737     portmod_pbmp_t portmod_pbm;
   3738 
   3739     PORTCTRL_INIT_CHECK(unit);
   3740 
   3741     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, resource->port,
   3742                                             &(resource->port), &pport));
   3743 
   3744     sp_config.speed = resource->speed;
   3745     sp_config.num_lane = resource->lanes;
   3746     sp_config.fec = resource->fec_type;
   3747     sp_config.link_training = resource->link_training;
   3748     sp_config.lane_config = resource->phy_lane_config;
   3749 
   3750     PORT_LOCK(unit);
   3751     rv = portmod_port_speed_config_validate(unit, pport, &sp_config, &portmod_pbm);
   3752     PORT_UNLOCK(unit);
   3753 
   3754     PORTMOD_PBMP_ITER(portmod_pbm, port) {
   3755         if (port >= BCM_PBMP_PORT_MAX) {
   3756             LOG_ERROR(BSL_LS_BCM_PORT,
   3757                       (BSL_META_UP(unit, port,
   3758                                    "ERROR: Portmod Port %d greater than BCM "
   3759                                    "Bitmap number of bits %d)\n"),
   3760                        port, (int)(sizeof(bcm_pbmp_t) * 4)));
   3761             return BCM_E_INTERNAL;
   3762         }
   3763 
   3764         BCM_PBMP_PORT_ADD(*pbmp, port);
   3765     }
   3766 
   3767     return rv;
   3768 #else  /* PORTMOD_SUPPORT */
   3769     return BCM_E_UNAVAIL;
   3770 #endif /* PORTMOD_SUPPORT */
   3771 }
   3772 
   3773 #ifdef PORTMOD_SUPPORT
   3774 /*
   3775  * Function:
   3776  *      _bcm_esw_portctrl_speed_multi_set_chip_reconfigure
   3777  * Purpose:
   3778  *      Reconfigure chip(PGW/TDM/IP/EP/MMU) for speed set change
   3779  * Parameters:
   3780  *      unit     - SOC unit number
   3781  *      nport    - number of bcm_port_resource_t structs
   3782  *      resource - structure holding speed information
   3783  * Returns:
   3784  *      BCM_E_XXX
   3785  */
   3786 STATIC int
   3787 _bcm_esw_portctrl_speed_multi_set_chip_reconfigure(int unit, int nport,
   3788                                     bcm_port_resource_t *resource)
   3789 {
   3790     int rv = BCM_E_UNAVAIL;
   3791 
   3792     PORT_LOCK(unit);
   3793     if (BCM_ESW_PORT_DRV(unit)!= NULL) {
   3794         if (BCM_ESW_PORT_DRV(unit)->port_resource_speed_multi_set != NULL) {
   3795             rv = BCM_ESW_PORT_DRV(unit)->port_resource_speed_multi_set(unit,
   3796                                                     nport, resource);
   3797         }
   3798     }
   3799     PORT_UNLOCK(unit);
   3800 
   3801     if (BCM_FAILURE(rv)) {
   3802         LOG_VERBOSE(BSL_LS_BCM_PORT,
   3803                     (BSL_META_U(unit,
   3804                                 "Speed multi set for chip resource failed\n")));
   3805     }
   3806 
   3807     return rv;
   3808 }
   3809 #endif /* PORTMOD_SUPPORT */
   3810 
   3811 /*
   3812  * Function:
   3813  *      bcmi_esw_portctrl_speed_multi_set
   3814  * Purpose:
   3815  *      Setting the speed given ports
   3816  * Parameters:
   3817  *      unit - StrataSwitch Unit #.
   3818  *      nport - number of resource structures
   3819  *      resource - structures holding speed information
   3820  * Returns:
   3821  *      BCM_E_NONE
   3822  *      BCM_E_XXX
   3823  */
   3824 int
   3825 bcmi_esw_portctrl_speed_multi_set(int unit, int nport,
   3826                                   bcm_port_resource_t *resource)
   3827 {
   3828 #ifdef PORTMOD_SUPPORT
   3829     int i;
   3830     int *cur_speed = NULL;
   3831     int *loopback = NULL;
   3832     int *enable = NULL;
   3833     portctrl_pport_t *pport = NULL;
   3834     int rv = BCM_E_NONE;
   3835 #ifdef PORTMOD_PM8X50_SUPPORT
   3836     int phy_port = 0;
   3837     portmod_speed_config_t sp_cfg;
   3838     portmod_dispatch_type_t pm_type = portmodDispatchTypeCount;
   3839 #endif
   3840     PORTCTRL_INIT_CHECK(unit);
   3841 
   3842     cur_speed = sal_alloc(nport * sizeof(int), "cur_speed array");
   3843     loopback = sal_alloc(nport * sizeof(int), "loopback array");
   3844     enable = sal_alloc(nport * sizeof(int), "enable array");
   3845     pport = sal_alloc(nport * sizeof(portctrl_pport_t), "pport array");
   3846     if (NULL == cur_speed || NULL == loopback || NULL == enable ||
   3847         NULL == pport) {
   3848         goto multi_set_cleanup;
   3849     }
   3850 
   3851     /* Perform everything BEFORE the speed multi set call for each of the
   3852      * ports first.
   3853      * EVERYTHING is considered a full sequence change! */
   3854     for (i = 0; i < nport; i++) {
   3855 
   3856         rv = PORTCTRL_PORT_RESOLVE(unit, resource[i].port,
   3857                             &(resource[i].port), &pport[i]);
   3858         if (!BCM_SUCCESS(rv)) {
   3859             goto multi_set_cleanup;
   3860         }
   3861 
   3862         /* check inactive port */
   3863         if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all),
   3864                             resource[i].port)) {
   3865             LOG_VERBOSE(BSL_LS_BCM_PORT,
   3866                         (BSL_META_UP(unit, resource[i].port,
   3867                                      "Port %d is inactive port\n"),
   3868                                      resource[i].port));
   3869             goto multi_set_cleanup;
   3870         }
   3871         
   3872         /* if speed is 0, set the port speed to max */
   3873         if (resource[i].speed == 0) {
   3874             rv =
   3875                 bcmi_esw_portctrl_speed_max(unit, resource[i].port,
   3876                                              &resource[i].speed);
   3877             if (!BCM_SUCCESS(rv)) {
   3878                 goto multi_set_cleanup;
   3879             }
   3880         }
   3881 
   3882         /* get current speed */
   3883         rv = bcmi_esw_portctrl_speed_get(unit, resource[i].port,
   3884                                         &(cur_speed[i]));
   3885         if (!BCM_SUCCESS(rv)) {
   3886             goto multi_set_cleanup;
   3887         }
   3888         /* validation : speed change is supported */
   3889         rv = _bcm_esw_portctrl_speed_validate(unit,
   3890                 resource[i].port, resource[i].speed);
   3891         if (!BCM_SUCCESS(rv)) {
   3892             goto multi_set_cleanup;
   3893         }
   3894         /* clear loopback */
   3895         rv = bcmi_esw_portctrl_loopback_get(unit, resource[i].port,
   3896                                             &(loopback[i]));
   3897         if (!BCM_SUCCESS(rv)) {
   3898             goto multi_set_cleanup;
   3899         }
   3900 
   3901         if (loopback[i] != BCM_PORT_LOOPBACK_NONE) {
   3902             rv = bcmi_esw_portctrl_loopback_set(unit,
   3903                                             resource[i].port,
   3904                                             BCM_PORT_LOOPBACK_NONE);
   3905             if (!BCM_SUCCESS(rv)) {
   3906                 goto multi_set_cleanup;
   3907             }
   3908         }
   3909         rv = bcmi_esw_portctrl_enable_get(unit, resource[i].port,
   3910                                           &enable[i]);
   3911         if (!BCM_SUCCESS(rv)) {
   3912             goto multi_set_cleanup;
   3913         }
   3914 
   3915         if (enable[i] == TRUE) {
   3916             /* disable MAC and PHY */
   3917             rv = bcmi_esw_portctrl_enable_set(unit, resource[i].port, FALSE);
   3918             if (!BCM_SUCCESS(rv)) {
   3919                 goto multi_set_cleanup;
   3920             }
   3921         }
   3922 
   3923         /* disable AN */
   3924         rv = _bcm_esw_portctrl_disable_autoneg(unit, pport[i]);
   3925         if (!BCM_SUCCESS(rv)) {
   3926             goto multi_set_cleanup;
   3927         }
   3928     }
   3929 
   3930     /* Perform the single call to speed multi set for all ports */
   3931     /* Reconfigure chip (PGW/TDM/IP/EP/MMU) */
   3932     rv = _bcm_esw_portctrl_speed_multi_set_chip_reconfigure(unit, nport,
   3933                                                             resource);
   3934     if (!BCM_SUCCESS(rv)) {
   3935         goto multi_set_cleanup;
   3936     }
   3937 
   3938 
   3939     /* Perform everything AFTER the speed multi set call */
   3940     for (i = 0; i < nport; i++) {
   3941 
   3942 #ifdef PORTMOD_PM8X50_SUPPORT
   3943         /* Find out what kind of Port Macro we're dealing with */
   3944         phy_port = SOC_INFO(unit).port_l2p_mapping[resource[i].port];
   3945 #ifdef BCM_TOMAHAWK3_SUPPORT
   3946         /* Tomahawk 3's Management Port Macro requires a spacing between
   3947          * the lanes, so even though the two management ports' physical
   3948          * ports are 257 and 258, the lane needs to be the next one,
   3949          * so logical port 118 being mapped to physical port 258 needs
   3950          * to pass 259 to portmod because portmod only recognizes lane
   3951          * 0 (physical port 257) and lane 2 (physial port 259).
   3952          */
   3953         if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) {
   3954             phy_port = 259;
   3955         }
   3956 #endif
   3957         rv = portmod_phy_pm_type_get(unit, phy_port, &pm_type);
   3958         if (!BCM_SUCCESS(rv)) {
   3959             goto multi_set_cleanup;
   3960         }
   3961 
   3962         /* reconfigure MAC & PHY */
   3963         /* for PM8x50, use speed_config_set */
   3964         if (pm_type == portmodDispatchTypePm8x50) {
   3965             sp_cfg.speed = resource[i].speed;
   3966             sp_cfg.num_lane = SOC_INFO(unit).port_num_lanes[resource[i].port];
   3967             sp_cfg.fec = resource[i].fec_type;
   3968             sp_cfg.lane_config = resource[i].phy_lane_config;
   3969             sp_cfg.link_training = resource[i].link_training;
   3970             rv = _bcm_esw_portctrl_speed_config_set(unit, resource[i].port,
   3971                                                     pport[i],
   3972                                                     &sp_cfg);
   3973         } else
   3974 #endif
   3975         {
   3976             rv = _bcm_esw_portctrl_speed_interface_config_set(
   3977                     unit, resource[i].port, pport[i], resource[i].speed);
   3978         }
   3979 
   3980         if (!BCM_SUCCESS(rv)) {
   3981             goto multi_set_cleanup;
   3982         }
   3983 
   3984         if (enable[i] == TRUE) {
   3985             /* Restore port's enable state based on what was read prior to
   3986                setting speed */
   3987             rv = bcmi_esw_portctrl_enable_set(unit, resource[i].port, TRUE);
   3988             if (!BCM_SUCCESS(rv)) {
   3989                 goto multi_set_cleanup;
   3990             }
   3991         }
   3992         /* restore loopback */
   3993         if (loopback[i] != BCM_PORT_LOOPBACK_NONE) {
   3994             rv = bcmi_esw_portctrl_loopback_set(unit,
   3995                                             resource[i].port,
   3996                                             loopback[i]);
   3997             if (!BCM_SUCCESS(rv)) {
   3998                 goto multi_set_cleanup;
   3999             }
   4000         }
   4001     }
   4002 
   4003 multi_set_cleanup:
   4004     if (NULL != pport) {
   4005         sal_free(pport);
   4006     }
   4007     if (NULL != enable) {
   4008         sal_free(enable);
   4009     }
   4010     if (NULL != loopback) {
   4011         sal_free(loopback);
   4012     }
   4013     if (NULL != cur_speed) {
   4014         sal_free(cur_speed);
   4015     }
   4016 
   4017     return rv;
   4018 
   4019 #else   /* PORTMOD_SUPPORT */
   4020     return BCM_E_UNAVAIL;
   4021 #endif  /* PORTMOD_SUPPORT */
   4022 }
   4023 
   4024 
   4025 /*
   4026  * Function:
   4027  *      bcmi_esw_portctrl_stk_my_modid_set
   4028  * Purpose:
   4029  *      Set the module-id in the Port block
   4030  * Parameters:
   4031  *      unit  - SOC unit#
   4032  *      port - port #
   4033  *      my_modid - the value to set
   4034  * Returns:
   4035  *      BCM_E_XXX
   4036  */
   4037 int
   4038 bcmi_esw_portctrl_stk_my_modid_set(int unit, bcm_gport_t port, int my_modid)
   4039 {
   4040 #ifdef PORTMOD_SUPPORT
   4041     int rv = BCM_E_NONE;
   4042     portctrl_pport_t pport;
   4043 
   4044     PORTCTRL_INIT_CHECK(unit);
   4045 
   4046     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4047 
   4048     if (IS_HG_PORT(unit, port)) {
   4049         PORT_LOCK(unit);
   4050         rv = portmod_port_modid_set(unit, pport, my_modid);
   4051         PORT_UNLOCK(unit);
   4052     }
   4053 
   4054     return rv;
   4055 
   4056 #else   /* PORTMOD_SUPPORT */
   4057     return BCM_E_UNAVAIL;
   4058 #endif  /* PORTMOD_SUPPORT */
   4059 }
   4060 
   4061 /*
   4062  * Function:
   4063  *      bcmi_esw_portctrl_pause_get
   4064  * Purpose:
   4065  *      Get the TX and RX settings for pause frames.
   4066  * Parameters:
   4067  *      unit     - (IN) Unit number.
   4068  *      port     - (IN) Port number.
   4069  *      pause_tx - (OUT) Boolean value.
   4070  *      pause_rx - (OUT) Boolean value.
   4071  * Returns:
   4072  *      BCM_E_XXX
   4073  */
   4074 int
   4075 bcmi_esw_portctrl_pause_get(int unit, bcm_gport_t port,
   4076                             int *pause_tx, int *pause_rx)
   4077 {
   4078 #ifdef PORTMOD_SUPPORT
   4079     int rv = BCM_E_NONE;
   4080     portctrl_pport_t pport;
   4081     portmod_pause_control_t pause_control;
   4082 
   4083     PORTCTRL_INIT_CHECK(unit);
   4084 
   4085     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4086 
   4087     PORT_LOCK(unit);
   4088     rv = portmod_port_pause_control_get(unit, pport, &pause_control);
   4089     PORT_UNLOCK(unit);
   4090 
   4091     if (PORTMOD_SUCCESS(rv)) {
   4092         *pause_tx = pause_control.tx_enable;
   4093         *pause_rx = pause_control.rx_enable;
   4094     }
   4095 
   4096     return rv;
   4097 
   4098 #else  /* PORTMOD_SUPPORT */
   4099     return BCM_E_UNAVAIL;
   4100 #endif /* PORTMOD_SUPPORT */
   4101 }
   4102 
   4103 
   4104 /*
   4105  * Function:
   4106  *      bcmi_esw_portctrl_pause_set
   4107  * Purpose:
   4108  *      Enable or disable transmission of pause frames and
   4109  *      honoring received pause frames on a port.
   4110  * Parameters:
   4111  *      unit     - (IN) Unit number.
   4112  *      port     - (IN) Port number.
   4113  *      pause_tx - (IN) 0 to disable transmission of pauseframes, 1 to enable.
   4114  *      pause_rx - (IN) 0 to ignore received pause frames, 1 to honor
   4115  *                      received pause frames.
   4116  * Returns:
   4117  *      BCM_E_XXX
   4118  */
   4119 int
   4120 bcmi_esw_portctrl_pause_set(int unit, bcm_gport_t port,
   4121                             int pause_tx, int pause_rx)
   4122 {
   4123 #ifdef PORTMOD_SUPPORT
   4124     int rv = BCM_E_NONE;
   4125     portctrl_pport_t pport;
   4126     portmod_pause_control_t pause_control;
   4127 
   4128     PORTCTRL_INIT_CHECK(unit);
   4129 
   4130     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4131 
   4132     PORT_LOCK(unit);
   4133 
   4134     rv = portmod_port_pause_control_get(unit, pport, &pause_control);
   4135     if (PORTMOD_SUCCESS(rv)) {
   4136         pause_control.rx_enable = pause_rx;
   4137         pause_control.tx_enable = pause_tx;
   4138         rv = portmod_port_pause_control_set(unit, pport, &pause_control);
   4139     }
   4140 
   4141     PORT_UNLOCK(unit);
   4142 
   4143     return rv;
   4144 
   4145 #else  /* PORTMOD_SUPPORT */
   4146     return BCM_E_UNAVAIL;
   4147 #endif /* PORTMOD_SUPPORT */
   4148 }
   4149 
   4150 
   4151 /*
   4152  * Function:
   4153  *      bcmi_esw_portctrl_pause_addr_get
   4154  * Purpose:
   4155  *      Get the source address for transmitted PAUSE frames.
   4156  * Parameters:
   4157  *      unit   - (IN) Unit number.
   4158  *      port   - (IN) Port number.
   4159  *      mac    - (OUT) MAC address sent with pause frames.
   4160  * Returns:
   4161  *      BCM_E_XXX
   4162  */
   4163 int
   4164 bcmi_esw_portctrl_pause_addr_get(int unit, bcm_gport_t port, bcm_mac_t mac)
   4165 {
   4166 #ifdef PORTMOD_SUPPORT
   4167     int rv = BCM_E_NONE;
   4168     portctrl_pport_t pport;
   4169 
   4170     PORTCTRL_INIT_CHECK(unit);
   4171 
   4172     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4173 
   4174     /* sal_mac_addr_t and bcm_mac_t typedefs definitions are the same */
   4175     PORT_LOCK(unit);
   4176     rv = portmod_port_tx_mac_sa_get(unit, pport, mac);
   4177     PORT_UNLOCK(unit);
   4178 
   4179     return rv;
   4180 
   4181 #else  /* PORTMOD_SUPPORT */
   4182     return BCM_E_UNAVAIL;
   4183 #endif /* PORTMOD_SUPPORT */
   4184 }
   4185 
   4186 
   4187 /*
   4188  * Function:
   4189  *      bcmi_esw_portctrl_pause_addr_set
   4190  * Purpose:
   4191  *      Set the source address for transmitted PAUSE frames.
   4192  * Parameters:
   4193  *      unit   - (IN) Unit number.
   4194  *      port   - (IN) Port number.
   4195  *      mac    - (IN) Station MAC address used for pause frames.
   4196  * Returns:
   4197  *      BCM_E_XXX
   4198  */
   4199 int
   4200 bcmi_esw_portctrl_pause_addr_set(int unit, bcm_gport_t port, bcm_mac_t mac)
   4201 {
   4202 #ifdef PORTMOD_SUPPORT
   4203     int rv = BCM_E_NONE;
   4204     portctrl_pport_t pport;
   4205 
   4206     PORTCTRL_INIT_CHECK(unit);
   4207 
   4208     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4209 
   4210     /* sal_mac_addr_t and bcm_mac_t typedefs definitions are the same */
   4211     PORT_LOCK(unit);
   4212     rv = portmod_port_tx_mac_sa_set(unit, pport, mac);
   4213     PORT_UNLOCK(unit);
   4214 
   4215     return rv;
   4216 
   4217 #else  /* PORTMOD_SUPPORT */
   4218     return BCM_E_UNAVAIL;
   4219 #endif /* PORTMOD_SUPPORT */
   4220 }
   4221 
   4222 
   4223 /*
   4224  * Function:
   4225  *      bcmi_esw_portctrl_eee_enable_get
   4226  * Purpose:
   4227  *      Retrieve eee enable field.
   4228  * Parameters:
   4229  *      unit         - (IN) Unit number.
   4230  *      port         - (IN) Port number.
   4231  *      enable       - (OUT) Returns eee enable field.
   4232  * Returns:
   4233  *      BCM_E_NONE
   4234  *      BCM_E_XXX
   4235  */
   4236 int
   4237 bcmi_esw_portctrl_eee_enable_get(int unit, bcm_gport_t port, int *enable)
   4238 {
   4239 #ifdef PORTMOD_SUPPORT
   4240     int rv = BCM_E_NONE;
   4241     portctrl_pport_t  pport;
   4242     portmod_eee_t eee;
   4243 
   4244     PORTCTRL_INIT_CHECK(unit);
   4245 
   4246     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4247 
   4248     PORT_LOCK(unit);
   4249     rv = portmod_port_eee_get(unit, pport, &eee);
   4250     *enable = eee.enable;
   4251     PORT_UNLOCK(unit);
   4252 
   4253     return rv;
   4254 #else  /* PORTMOD_SUPPORT */
   4255     return BCM_E_UNAVAIL;
   4256 #endif /* PORTMOD_SUPPORT */
   4257 }
   4258 
   4259 
   4260 /*
   4261  * Function:
   4262  *      bcmi_esw_portctrl_eee_enable_set
   4263  * Purpose:
   4264  *      Set the eee enable field if different from what is to be set.
   4265  * Parameters:
   4266  *      unit         - (IN) Unit number.
   4267  *      port         - (IN) Port number.
   4268  *      enable       - (IN) eee enable field.
   4269  * Returns:
   4270  *      BCM_E_NONE
   4271  *      BCM_E_XXX
   4272  */
   4273 int
   4274 bcmi_esw_portctrl_eee_enable_set(int unit, bcm_gport_t port, int enable)
   4275 {
   4276 #ifdef PORTMOD_SUPPORT
   4277     int rv = BCM_E_NONE;
   4278     portctrl_pport_t  pport;
   4279     portmod_eee_t eee;
   4280 
   4281     PORTCTRL_INIT_CHECK(unit);
   4282     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4283 
   4284     PORT_LOCK(unit);
   4285     rv = portmod_port_eee_get(unit, pport, &eee);
   4286     if (PORTMOD_SUCCESS(rv)) {
   4287         if (eee.enable != enable) {
   4288             eee.enable = enable;
   4289             rv = portmod_port_eee_set(unit, pport, &eee);
   4290         }
   4291     }
   4292     PORT_UNLOCK(unit);
   4293 
   4294     return rv;
   4295 #else  /* PORTMOD_SUPPORT */
   4296     return BCM_E_UNAVAIL;
   4297 #endif /* PORTMOD_SUPPORT */
   4298 }
   4299 
   4300 /*
   4301  * Function:
   4302  *      bcmi_portctrl_master_get
   4303  * Purpose:
   4304  *      Getting the master status of the port
   4305  * Parameters:
   4306  *      unit - StrataSwitch Unit #.
   4307  *      port - StrataSwitch port #.
   4308  *      ms - (OUT) BCM_PORT_MS_*
   4309  * Returns:
   4310  *      BCM_E_NONE
   4311  *      BCM_E_XXX
   4312  * Notes:
   4313  *      WARNING: assumes BCM_PORT_MS_* matches SOC_PORT_MS_*
   4314  */
   4315 
   4316 int
   4317 bcmi_esw_portctrl_master_get(int unit, bcm_gport_t port, int *ms)
   4318 {
   4319 #ifdef PORTMOD_SUPPORT
   4320     int rv = BCM_E_NONE;
   4321     portctrl_pport_t pport;
   4322     portmod_dispatch_type_t pm_type;
   4323     int pm_type_supported = 0;
   4324 
   4325     /* Make sure port module is initialized. */
   4326     PORTCTRL_INIT_CHECK(unit);
   4327 
   4328     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4329 
   4330     rv = portmod_port_pm_type_get(unit, port, &port, &pm_type);
   4331     if (rv != BCM_E_NONE) {
   4332         return rv;
   4333     }
   4334 
   4335     /*
   4336      * portmod_port_master_get() fetches the master_mode regsiter value ONLY WHEN
   4337      * there is a legacy ext PHY attaching to a port. Currently there is no
   4338      * master_mode_get API implemented for PHYMOD-based int/ext PHY. When a portmod
   4339      * port is NOT attaching to an ext PHY, it simply updates the master mode as
   4340      * slave since the internal PHY only operates in the slave mode. When the portmod
   4341      * port is attaching to a PHYMOD-based ext PHY, the master mode will be updated as
   4342      * BCM_PORT_MS_NONE to reflect the unknown status.
   4343      */
   4344 
   4345 #ifdef PORTMOD_PM4X10_SUPPORT
   4346     if (pm_type == portmodDispatchTypePm4x10
   4347 #ifdef PORTMOD_PM4X10TD_SUPPORT 
   4348         || pm_type == portmodDispatchTypePm4x10td
   4349 #endif /* PORTMOD_PM4X10TD_SUPPORT */
   4350        ) {
   4351         rv = portmod_port_master_get(unit, port, ms);
   4352         pm_type_supported = 1;
   4353     }
   4354 #endif /* PORTMOD_PM4X10_SUPPORT */
   4355 
   4356 #ifdef PORTMOD_PM4X25_SUPPORT
   4357     if (pm_type == portmodDispatchTypePm4x25
   4358 #ifdef PORTMOD_PM4X25TD_SUPPORT
   4359         || pm_type == portmodDispatchTypePm4x25td
   4360 #endif /* PORTMOD_PM4X25TD_SUPPORT */
   4361        ) {
   4362         rv = portmod_port_master_get(unit, port, ms);
   4363         pm_type_supported = 1;
   4364     }
   4365 #endif /* PORTMOD_PM4X25_SUPPORT */
   4366 #ifdef PORTMOD_CPM4X25_SUPPORT
   4367     if (pm_type == portmodDispatchTypeCpm4x25
   4368        ) {
   4369         rv = portmod_port_master_get(unit, port, ms);
   4370         pm_type_supported = 1;
   4371     }
   4372 #endif /* PORTMOD_PM4X25_SUPPORT */
   4373 #ifdef PORTMOD_PM4X10_QTC_SUPPORT
   4374     if (pm_type == portmodDispatchTypePm4x10_qtc) {
   4375         rv = portmod_port_master_get(unit, port, ms);
   4376         pm_type_supported = 1;
   4377     }
   4378 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */
   4379     if (!pm_type_supported) {
   4380         *ms = BCM_PORT_MS_NONE;
   4381     }
   4382 
   4383     return rv;
   4384 
   4385 #else   /* PORTMOD_SUPPORT */
   4386     return BCM_E_UNAVAIL;
   4387 #endif  /* PORTMOD_SUPPORT */
   4388 }
   4389 
   4390 /*
   4391  * Function:
   4392  *      bcmi_portctrl_medium_config_set
   4393  * Description:
   4394  *      Set the medium config of a combo port
   4395  * Parameters:
   4396  *      unit     - Device number
   4397  *      port     - Port number
   4398  *      medium   - The medium (BCM_PORT_MEDIUM_COPPER or BCM_PORT_MEDIUM_FIBER)
   4399  *                 which is currently selected
   4400  *      config   - Medium config
   4401  * Return Value:
   4402  *      BCM_E_XXX
   4403  */
   4404 int
   4405 bcmi_esw_portctrl_medium_config_set(int unit, bcm_gport_t port, bcm_port_medium_t medium,
   4406                                     bcm_phy_config_t *config)
   4407 {
   4408 #ifdef PORTMOD_SUPPORT
   4409     int rv = BCM_E_NONE;
   4410     portctrl_pport_t pport;
   4411 
   4412     /* Make sure port module is initialized. */
   4413     PORTCTRL_INIT_CHECK(unit);
   4414     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4415 
   4416     PORT_LOCK(unit);
   4417     rv = portmod_port_medium_config_set(unit, pport, medium, config);
   4418     PORT_UNLOCK(unit);
   4419     
   4420     return rv;
   4421 
   4422 #else   /* PORTMOD_SUPPORT */
   4423     return BCM_E_UNAVAIL;
   4424 #endif  /* PORTMOD_SUPPORT */
   4425 }
   4426 
   4427 /*
   4428  * Function:
   4429  *      bcmi_portctrl_medium_config_get
   4430  * Description:
   4431  *      Get the medium config of a combo port
   4432  * Parameters:
   4433  *      unit     - Device number
   4434  *      port     - Port number
   4435  *      medium   - The medium (BCM_PORT_MEDIUM_COPPER or BCM_PORT_MEDIUM_FIBER)
   4436  *                 which is currently selected
   4437  *      config   - Medium config
   4438  * Return Value:
   4439  *      BCM_E_XXX
   4440  */
   4441 int
   4442 bcmi_esw_portctrl_medium_config_get(int unit, bcm_gport_t port, bcm_port_medium_t medium,
   4443                                     bcm_phy_config_t *config)
   4444 {
   4445 #ifdef PORTMOD_SUPPORT
   4446     int rv = BCM_E_NONE;
   4447     portctrl_pport_t pport;
   4448     int ext_phy_present;
   4449 
   4450     /* Make sure port module is initialized. */
   4451     PORTCTRL_INIT_CHECK(unit);
   4452     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4453 
   4454     /* PORTMOD currently only supports medium config get for ports with legacy ext PHY */
   4455     SOC_IF_ERROR_RETURN(portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present));
   4456     if (!ext_phy_present) { 
   4457         return BCM_E_UNAVAIL; 
   4458     }
   4459 
   4460     PORT_LOCK(unit);
   4461     rv = portmod_port_medium_config_get(unit, pport, medium, config);
   4462     PORT_UNLOCK(unit);
   4463     
   4464     return rv;
   4465 
   4466 #else   /* PORTMOD_SUPPORT */
   4467     return BCM_E_UNAVAIL;
   4468 #endif  /* PORTMOD_SUPPORT */
   4469 }
   4470 
   4471 /*
   4472  * Function:
   4473  *      bcmi_port_medium_get
   4474  * Description:
   4475  *      Get the current medium used by a combo port
   4476  * Parameters:
   4477  *      unit     - Device number
   4478  *      port     - Port number
   4479  *      medium   - The medium (BCM_PORT_MEDIUM_COPPER or BCM_PORT_MEDIUM_FIBER)
   4480  *                 which is currently selected
   4481  * Return Value:
   4482  *      BCM_E_XXX
   4483  */
   4484 int
   4485 bcmi_esw_portctrl_medium_get(int unit, bcm_gport_t port,
   4486                              bcm_port_medium_t *medium)
   4487 {
   4488 #ifdef PORTMOD_SUPPORT
   4489     int rv = BCM_E_NONE;
   4490     portctrl_pport_t pport;
   4491     int ext_phy_present;
   4492 
   4493     /* Make sure port module is initialized. */
   4494     PORTCTRL_INIT_CHECK(unit);
   4495     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4496 
   4497     *medium = SOC_PORT_MEDIUM_NONE;
   4498 
   4499     /* dig further if there is an ext PHY present and medium type is not yet found */
   4500     rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present);
   4501     if (ext_phy_present && *medium == SOC_PORT_MEDIUM_NONE){
   4502         PORT_LOCK(unit);
   4503         portmod_port_medium_get(unit, pport, medium);
   4504         PORT_UNLOCK(unit);
   4505     }
   4506 
   4507     return rv;
   4508 
   4509 #else   /* PORTMOD_SUPPORT */
   4510     return BCM_E_UNAVAIL;
   4511 #endif  /* PORTMOD_SUPPORT */
   4512 }
   4513 
   4514 /*
   4515  * Function:
   4516  *      bcmi_portctrl_master_set
   4517  * Purpose:
   4518  *      Setting the master status for a given port
   4519  * Parameters:
   4520  *      unit - StrataSwitch Unit #.
   4521  *      port - StrataSwitch port #.
   4522  *      ms - BCM_PORT_MS_*
   4523  * Returns:
   4524  *      BCM_E_NONE
   4525  *      BCM_E_XXX
   4526  * Notes:
   4527  *      Ignored if not supported on port.
   4528  *      WARNING: assumes BCM_PORT_MS_* matches SOC_PORT_MS_*
   4529  */
   4530 int
   4531 bcmi_esw_portctrl_master_set(int unit, bcm_gport_t port, int ms)
   4532 {
   4533 #ifdef PORTMOD_SUPPORT
   4534     int rv = BCM_E_NONE;
   4535     pbmp_t pbm;
   4536     portctrl_pport_t pport;
   4537     portmod_dispatch_type_t pm_type;
   4538     int pm_type_supported = 0;
   4539 
   4540     /* Make sure port module is initialized. */
   4541     PORTCTRL_INIT_CHECK(unit);
   4542 
   4543     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4544 
   4545     rv = portmod_port_pm_type_get(unit, port, &port, &pm_type);
   4546     if (rv != BCM_E_NONE) {
   4547         return rv;
   4548     }
   4549 
   4550 #ifdef BCM_RCPU_SUPPORT
   4551     if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   4552         return BCM_E_PORT;
   4553     }
   4554 #endif /* BCM_RCPU_SUPPORT */
   4555 
   4556 #ifdef PORTMOD_PM4X10_SUPPORT
   4557     if (pm_type == portmodDispatchTypePm4x10
   4558 #ifdef PORTMOD_PM4X10TD_SUPPORT 
   4559         || pm_type == portmodDispatchTypePm4x10td
   4560 #endif /* PORTMOD_PM4X10TD_SUPPORT */
   4561        ) {
   4562         rv = portmod_port_master_set(unit, port, ms);
   4563         pm_type_supported = 1;
   4564     }
   4565 #endif /* PORTMOD_PM4X10_SUPPORT */
   4566 
   4567 #ifdef PORTMOD_PM4X25_SUPPORT
   4568     if (pm_type == portmodDispatchTypePm4x25
   4569 #ifdef PORTMOD_PM4X25TD_SUPPORT
   4570         || pm_type == portmodDispatchTypePm4x25td
   4571 #endif /* PORTMOD_PM4X25TD_SUPPORT */
   4572        ) {
   4573         rv = portmod_port_master_set(unit, port, ms);
   4574         pm_type_supported = 1;
   4575     }
   4576 #endif /* PORTMOD_PM4X25_SUPPORT */
   4577 #ifdef PORTMOD_PM4X10_QTC_SUPPORT
   4578     if (pm_type == portmodDispatchTypePm4x10_qtc) {
   4579         rv = portmod_port_master_set(unit, port, ms);
   4580         pm_type_supported = 1;
   4581     }
   4582 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */
   4583     SOC_PBMP_CLEAR(pbm);
   4584     SOC_PBMP_PORT_ADD(pbm, port);
   4585     (void)bcm_esw_link_change(unit, pbm);
   4586 
   4587     if (pm_type_supported == 1) {
   4588         return rv;
   4589     } else {
   4590         return BCM_E_UNAVAIL;
   4591     }
   4592 
   4593 #else   /* PORTMOD_SUPPORT */
   4594     return BCM_E_UNAVAIL;
   4595 #endif  /* PORTMOD_SUPPORT */
   4596 
   4597 }
   4598 
   4599 
   4600 /*
   4601  * Function:
   4602  *      bcmi_portctrl_interface_get
   4603  * Purpose:
   4604  *      Getting the interface type of a port
   4605  * Parameters:
   4606  *      unit - StrataSwitch Unit #.
   4607  *      port - StrataSwitch port #.
   4608  *      intf - (OUT) BCM_PORT_IF_*
   4609  * Returns:
   4610  *      BCM_E_NONE
   4611  *      BCM_E_XXX
   4612  * Notes:
   4613  *      WARNING: assumes BCM_PORT_IF_* matches SOC_PORT_IF_*
   4614  */
   4615 
   4616 int
   4617 bcmi_esw_portctrl_interface_get(int unit, bcm_gport_t port, bcm_port_if_t *intf)
   4618 {
   4619 #ifdef PORTMOD_SUPPORT
   4620     int         rv;
   4621     portmod_port_interface_config_t port_if_cfg;
   4622     portctrl_pport_t pport;
   4623 
   4624     /* Make sure port module is initialized. */
   4625     PORTCTRL_INIT_CHECK(unit);
   4626 
   4627     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4628 
   4629     if (!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) {
   4630         return BCM_E_PORT;
   4631     }
   4632 
   4633     portmod_port_interface_config_t_init(unit, &port_if_cfg);
   4634 
   4635     PORT_LOCK(unit);
   4636     rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   4637     PORT_UNLOCK(unit);
   4638 
   4639     if (PORTMOD_SUCCESS(rv)) {
   4640         *intf = port_if_cfg.interface;
   4641     }
   4642 
   4643     return rv;
   4644 #else   /* PORTMOD_SUPPORT */
   4645     return BCM_E_UNAVAIL;
   4646 #endif  /* PORTMOD_SUPPORT */
   4647 
   4648 }
   4649 
   4650 /*
   4651  * Function:
   4652  *      bcmi_portctrl_interface_set
   4653  * Purpose:
   4654  *      Setting the interface type for a given port
   4655  * Parameters:
   4656  *      unit - StrataSwitch Unit #.
   4657  *      port - StrataSwitch port #.
   4658  *      if - BCM_PORT_IF_*
   4659  * Returns:
   4660  *      BCM_E_NONE
   4661  *      BCM_E_XXX
   4662  * Notes:
   4663  *      WARNING: assumes BCM_PORT_IF_* matches SOC_PORT_IF_*
   4664  */
   4665 int
   4666 bcmi_esw_portctrl_interface_set(int unit, bcm_gport_t port, bcm_port_if_t intf)
   4667 {
   4668 #ifdef PORTMOD_SUPPORT
   4669     int rv = BCM_E_NONE;
   4670     char *str = "";
   4671     pbmp_t pbm;
   4672     portmod_port_interface_config_t port_if_cfg;
   4673     portctrl_pport_t pport;
   4674     _bcm_port_info_t *port_info = NULL;
   4675 
   4676     /* Make sure port module is initialized. */
   4677     PORTCTRL_INIT_CHECK(unit);
   4678 
   4679     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4680 
   4681     if (!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) {
   4682         return BCM_E_PORT;
   4683     }
   4684 
   4685 #ifdef BCM_RCPU_SUPPORT
   4686     if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   4687         return BCM_E_PORT;
   4688     }
   4689 #endif /* BCM_RCPU_SUPPORT */
   4690 
   4691     portmod_port_interface_config_t_init(unit, &port_if_cfg);
   4692 
   4693     PORT_LOCK(unit);
   4694     rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   4695 
   4696     if (PORTMOD_SUCCESS(rv)) {
   4697         
   4698         /* Set interface type */
   4699         port_if_cfg.interface = intf;
   4700         port_if_cfg.flags     = PHYMOD_INTF_F_INTF_PARAM_SET_ONLY ;
   4701 
   4702         rv = _bcm_esw_portctrl_interface_config_set(unit, port, pport,
   4703                                                     &port_if_cfg, 0);
   4704         PORT_UNLOCK(unit);
   4705 
   4706         /* Unlock before link call */
   4707         if (PORTMOD_SUCCESS(rv)) {
   4708             SOC_PBMP_CLEAR(pbm);
   4709             SOC_PBMP_PORT_ADD(pbm, port);
   4710             (void)bcm_esw_link_change(unit, pbm);
   4711             if (soc_property_get(unit, spn_SAME_SPEED_INTF_DO_NOT_OVERWRITE,
   4712                                  (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM))) {
   4713                 _bcm_port_info_access(unit, port, &port_info);
   4714                 port_info->intf = intf;
   4715             }
   4716         } else {
   4717             str = "set";
   4718         }
   4719     } else {
   4720         PORT_UNLOCK(unit);
   4721         str = "get";
   4722     }
   4723 
   4724     if (BCM_FAILURE(rv)) {
   4725         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4726                     (BSL_META_UP(unit, port,
   4727                     "Interface_%s failed:%s\n"), str, bcm_errmsg(rv)));
   4728     }
   4729 
   4730     return rv;
   4731 
   4732 #else  /* PORTMOD_SUPPORT */
   4733     return BCM_E_UNAVAIL;
   4734 #endif /* PORTMOD_SUPPORT */
   4735 }
   4736 
   4737 /*
   4738  * Function:
   4739  *      bcmi_portctrl_mdix_get
   4740  * Description:
   4741  *      Get the Auto-MDIX mode of a port/PHY
   4742  * Parameters:
   4743  *      unit - Device number
   4744  *      port - Port number
   4745  *      mode - (Out) One of:
   4746  *              BCM_PORT_MDIX_AUTO
   4747  *                      Enable auto-MDIX when autonegotiation is enabled
   4748  *              BCM_PORT_MDIX_FORCE_AUTO
   4749  *                      Enable auto-MDIX always
   4750  *              BCM_PORT_MDIX_NORMAL
   4751  *                      Disable auto-MDIX
   4752  *              BCM_PORT_MDIX_XOVER
   4753  *                      Disable auto-MDIX, and swap cable pairs
   4754  * Return Value:
   4755  *      BCM_E_UNAVAIL - feature unsupported by hardware
   4756  *      BCM_E_XXX - other error
   4757  */
   4758 int
   4759 bcmi_esw_portctrl_mdix_get(int unit, bcm_gport_t port, bcm_port_mdix_t *mode)
   4760 {
   4761 #ifdef PORTMOD_SUPPORT
   4762     int rv = BCM_E_NONE;
   4763     portctrl_pport_t pport;
   4764     int ext_phy_present = 0;
   4765     char *str = "";
   4766 
   4767     /* Make sure port module is initialized. */
   4768     PORTCTRL_INIT_CHECK(unit);
   4769 
   4770     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4771 
   4772     PORT_LOCK(unit);
   4773     rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present);
   4774 
   4775     if (PORTMOD_SUCCESS(rv)) {
   4776         if (ext_phy_present) {
   4777             rv = portmod_port_ext_phy_mdix_get(unit, pport, mode);
   4778 
   4779             str = "portmod_port_ext_phy_mdix_get";
   4780         } else {
   4781             /* MDIX is supported for external phys only, so we return a fixed
   4782              * value for internal phys
   4783              */
   4784             *mode = SOC_PORT_MDIX_NORMAL;
   4785         }
   4786     } else {
   4787         str = "portmod_port_is_legacy_ext_phy_present";
   4788     }
   4789 
   4790     PORT_UNLOCK(unit);
   4791     if (PORTMOD_FAILURE(rv)) {
   4792 
   4793         LOG_VERBOSE(BSL_LS_BCM_PORT,
   4794                     (BSL_META_UP(unit, port, "MDIX get: %s failed:\n"
   4795                     "port=%d, pport=%d, rv=%d\n"), str, port, pport, rv));
   4796     }
   4797 
   4798     return rv;
   4799 #else  /* PORTMOD_SUPPORT */
   4800     return BCM_E_UNAVAIL;
   4801 #endif /* PORTMOD_SUPPORT */
   4802 }
   4803 
   4804 /*
   4805  * Function:
   4806  *      bcmi_portctrl_mdix_set
   4807  * Description:
   4808  *      Set the Auto-MDIX mode of a port/PHY
   4809  * Parameters:
   4810  *      unit - Device number
   4811  *      port - Port number
   4812  *      mode - One of:
   4813  *              BCM_PORT_MDIX_FORCE_AUTO
   4814  *                      Enable auto-MDIX always
   4815  *              BCM_PORT_MDIX_NORMAL
   4816  *                      Disable auto-MDIX
   4817  *              BCM_PORT_MDIX_XOVER
   4818  *                      Disable auto-MDIX, and swap cable pairs
   4819  * Return Value:
   4820  *      BCM_E_UNAVAIL - feature unsupported by hardware
   4821  *      BCM_E_XXX - other error
   4822  */
   4823 int
   4824 bcmi_esw_portctrl_mdix_set(int unit, bcm_gport_t port, bcm_port_mdix_t mode)
   4825 {
   4826 #ifdef PORTMOD_SUPPORT
   4827     int rv = BCM_E_NONE;
   4828     portctrl_pport_t pport;
   4829     int ext_phy_present = 0;
   4830     char *str = "";
   4831 
   4832     /* Make sure port module is initialized. */
   4833     PORTCTRL_INIT_CHECK(unit);
   4834     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4835 
   4836     PORT_LOCK(unit);
   4837     rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present);
   4838 
   4839     if (PORTMOD_SUCCESS(rv)) {
   4840         if (ext_phy_present) {
   4841             rv = portmod_port_ext_phy_mdix_set(unit, pport, mode);
   4842 
   4843             str = "portmod_port_ext_phy_mdix_set failed:";
   4844         } else {
   4845             /* The behavior of this function should match legacy mdix API's,
   4846              * so if mdix mode is other than normal, we return error
   4847              */
   4848             if (mode != SOC_PORT_MDIX_NORMAL) {
   4849                 rv = BCM_E_UNAVAIL;
   4850                 str = "mode is not 'normal' ";
   4851             }
   4852         }
   4853 
   4854         /* For internal phys, we do not program h/w; we return success */
   4855     } else {
   4856         str = "portmod_port_is_legacy_ext_phy_present failed:";
   4857     }
   4858 
   4859     PORT_UNLOCK(unit);
   4860     if (PORTMOD_FAILURE(rv)) {
   4861 
   4862         LOG_VERBOSE(BSL_LS_BCM_PORT,
   4863                     (BSL_META_UP(unit, port, "MDIX set: %s\nport=%d,"
   4864                     " pport=%d, rv=%d\n"), str, port, pport, rv));
   4865     }
   4866 
   4867     return rv;
   4868 #else  /* PORTMOD_SUPPORT */
   4869     return BCM_E_UNAVAIL;
   4870 #endif /* PORTMOD_SUPPORT */
   4871 }
   4872 
   4873 /*
   4874  * Function:
   4875  *      bcmi_portctrl_mdix_status_get
   4876  * Description:
   4877  *      Get the current MDIX status on a port/PHY
   4878  * Parameters:
   4879  *      unit    - Device number
   4880  *      port    - Port number
   4881  *      status  - (OUT) One of:
   4882  *              BCM_PORT_MDIX_STATUS_NORMAL
   4883  *                      Straight connection
   4884  *              BCM_PORT_MDIX_STATUS_XOVER
   4885  *                      Crossover has been performed
   4886  * Return Value:
   4887  *      BCM_E_UNAVAIL - feature unsupported by hardware
   4888  *      BCM_E_XXX - other error
   4889  */
   4890 int
   4891 bcmi_esw_portctrl_mdix_status_get(int unit, bcm_gport_t port,
   4892                                   bcm_port_mdix_status_t *status)
   4893 {
   4894 #ifdef PORTMOD_SUPPORT
   4895     int rv = BCM_E_NONE;
   4896     portctrl_pport_t pport;
   4897     int ext_phy_present = 0;
   4898     char *str = "";
   4899 
   4900     /* Make sure port module is initialized. */
   4901     PORTCTRL_INIT_CHECK(unit);
   4902     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4903 
   4904     PORT_LOCK(unit);
   4905     rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present);
   4906 
   4907     if (PORTMOD_SUCCESS(rv)) {
   4908 
   4909         /* MDIX is supported for external phys only */
   4910         if (ext_phy_present) {
   4911             rv = portmod_port_ext_phy_mdix_status_get(unit, pport, status);
   4912 
   4913             str = "portmod_port_ext_phy_mdix_status_get";
   4914         } else {
   4915             *status = SOC_PORT_MDIX_STATUS_NORMAL;
   4916         }
   4917     } else {
   4918         str = "portmod_port_is_legacy_ext_phy_present";
   4919     }
   4920 
   4921     PORT_UNLOCK(unit);
   4922     if (PORTMOD_FAILURE(rv)) {
   4923 
   4924         LOG_VERBOSE(BSL_LS_BCM_PORT,
   4925                     (BSL_META_UP(unit, port, "MDIX status get: %s failed:\n"
   4926                     "port=%d, pport=%d, rv=%d\n"), str, port, pport, rv));
   4927     }
   4928     return rv;
   4929 #else  /* PORTMOD_SUPPORT */
   4930     return BCM_E_UNAVAIL;
   4931 #endif /* PORTMOD_SUPPORT */
   4932 }
   4933 
   4934 /*
   4935  * Function:
   4936  *      bcmi_esw_portctrl_phy_get
   4937  * Description:
   4938  *      General PHY register read
   4939  * Parameters:
   4940  *      unit - Device number
   4941  *      port - Port number or PHY MDIO address (refer BCM_PORT_PHY_NOMAP)
   4942  *      flags - Logical OR of one or more of the following flags:
   4943  *              BCM_PORT_PHY_INTERNAL
   4944  *                      Address internal SERDES PHY for port
   4945  *              BCM_PORT_PHY_NOMAP
   4946  *                      Instead of mapping port to PHY MDIO address,
   4947  *                      treat port parameter as actual PHY MDIO address.
   4948  *              BCM_PORT_PHY_CLAUSE45
   4949  *                      Assume Clause 45 device instead of Clause 22
   4950  *      phy_addr - PHY internal register address
   4951  *      phy_data - (OUT) Data that was read
   4952  * Returns:
   4953  *      BCM_E_XXX
   4954  */
   4955 int
   4956 bcmi_esw_portctrl_phy_get(int unit, bcm_gport_t port, uint32 flags,
   4957                           uint32 phy_reg_addr, uint32 *phy_data)
   4958 {
   4959 #ifdef PORTMOD_SUPPORT
   4960     uint16  phy_id;
   4961     uint8  phy_devad;
   4962     uint16 phy_reg;
   4963     uint16 phy_rd_data;
   4964     uint32 reg_flag;
   4965     int    rv;
   4966     portctrl_pport_t pport=0;
   4967     int lane = -1;
   4968     int phyn = -1, sys_side = 0;
   4969     bcm_port_t local_port = -1;
   4970 
   4971     /* Make sure port module is initialized. */
   4972     PORTCTRL_INIT_CHECK(unit);
   4973 
   4974     if (!(flags & BCM_PORT_PHY_NOMAP)) {
   4975         BCM_IF_ERROR_RETURN
   4976             (_bcm_esw_port_gport_phyn_validate(unit, port,
   4977                                            &local_port, &phyn,
   4978                                            &lane, &sys_side));
   4979         if (local_port != -1) {
   4980             port = local_port;
   4981         }
   4982         BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   4983         if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) {
   4984             return BCM_E_PORT;
   4985         }
   4986     }
   4987 
   4988     if (flags & (BCM_PORT_PHY_I2C_DATA8 | BCM_PORT_PHY_I2C_DATA16 | BCM_PORT_PHY_PVT_DATA)) {
   4989         PORT_LOCK(unit);
   4990         rv = portmod_port_phy_reg_read(unit, pport, lane, flags, phy_reg_addr, phy_data);
   4991         PORT_UNLOCK(unit);
   4992         return rv;
   4993     }
   4994 
   4995     rv       = BCM_E_UNAVAIL;
   4996     reg_flag = BCM_PORT_PHY_REG_FLAGS(phy_reg_addr);
   4997     if (reg_flag & BCM_ESW_PORTCTRL_PHY_REG_INDIRECT) {
   4998         if (flags & BCM_PORT_PHY_NOMAP) {
   4999             /* Indirect register access is performed through PHY driver.
   5000              * Therefore, indirect register access is not supported if
   5001              * BCM_PORT_PHY_NOMAP flag is set.
   5002              */
   5003             return BCM_E_PARAM;
   5004         }
   5005         phy_reg_addr &= ~BCM_ESW_PORTCTRL_PHY_REG_INDIRECT;
   5006         if (phyn == 1) {
   5007             flags |= BCM_PORT_PHY_INTERNAL;
   5008         }
   5009         PORT_LOCK(unit);
   5010         rv = portmod_port_phy_reg_read(unit, pport, lane, flags, phy_reg_addr, phy_data);
   5011         PORT_UNLOCK(unit);
   5012     }
   5013 
   5014     if (rv == BCM_E_UNAVAIL) {
   5015         if (flags & BCM_PORT_PHY_NOMAP) {
   5016             phy_id = (uint16) port;
   5017         } else if (flags & BCM_PORT_PHY_INTERNAL) {
   5018             PORT_LOCK(unit);
   5019             phy_id = portmod_port_to_phyaddr_int(unit, pport);
   5020             PORT_UNLOCK(unit);
   5021         } else {
   5022             PORT_LOCK(unit);
   5023             phy_id = portmod_port_to_phyaddr(unit, pport);
   5024             PORT_UNLOCK(unit);
   5025         }
   5026 
   5027         PORT_LOCK(unit);
   5028         if (flags & BCM_PORT_PHY_CLAUSE45) {
   5029             phy_devad = BCM_PORT_PHY_CLAUSE45_DEVAD(phy_reg_addr);
   5030             phy_reg   = BCM_PORT_PHY_CLAUSE45_REGAD(phy_reg_addr);
   5031             rv = soc_miimc45_read(unit, phy_id, phy_devad,
   5032                                   phy_reg, &phy_rd_data);
   5033 
   5034         } else {
   5035             phy_reg = phy_reg_addr;
   5036             rv = soc_miim_read(unit, phy_id, phy_reg, &phy_rd_data);
   5037         }
   5038         PORT_UNLOCK(unit);
   5039 
   5040         if (BCM_SUCCESS(rv)) {
   5041            *phy_data = phy_rd_data;
   5042         }
   5043     }
   5044 
   5045     LOG_INFO(BSL_LS_BCM_PORT,
   5046              (BSL_META_U(unit,
   5047                          "portctrl_phy_get: u=%d p=%d flags=0x%08x "
   5048                          "phy_reg=0x%08x, phy_data=0x%08x, rv=%d\n"),
   5049                          unit, port, flags, phy_reg_addr, *phy_data, rv));
   5050 
   5051     return rv;
   5052 #else  /* PORTMOD_SUPPORT */
   5053     return BCM_E_UNAVAIL;
   5054 #endif /* PORTMOD_SUPPORT */
   5055 }
   5056 
   5057 /*
   5058  * Function:
   5059  *      bcmi_esw_portctrl_phy_multi_get
   5060  * Description:
   5061  *      General PHY register read
   5062  * Parameters:
   5063  *      unit - Device number
   5064  *      port - Port number
   5065  *      flags - Phy's read-specific flags
   5066  *      dev_addr - Device address on the PHY's bus (ex. I2C addr)
   5067  *      offset - Offset within device
   5068  *      max_size - Requested data size
   5069  *      data - Data buffer
   5070  *      actual_size - Received data size
   5071  * Returns:
   5072  *      BCM_E_XXX
   5073  */
   5074 int
   5075 bcmi_esw_portctrl_phy_multi_get(int unit, bcm_gport_t port, uint32 flags,
   5076                                 uint32 dev_addr, uint32 offset, int max_size,
   5077                                 uint8 *data, int *actual_size)
   5078 {
   5079 #ifdef PORTMOD_SUPPORT
   5080     int rv;
   5081     portctrl_pport_t pport;
   5082     portmod_multi_get_t phy_reg_read;
   5083 
   5084     /* Make sure port module is initialized. */
   5085     PORTCTRL_INIT_CHECK(unit);
   5086     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5087 
   5088     /* Initialize and fill the structure */
   5089     portmod_multi_get_t_init(unit, &phy_reg_read);
   5090 
   5091     phy_reg_read.flags = flags;
   5092     phy_reg_read.dev_addr = dev_addr;
   5093     phy_reg_read.offset = offset;
   5094     phy_reg_read.max_size = max_size;
   5095     phy_reg_read.data = data;
   5096     phy_reg_read.actual_size = (uint32 *)actual_size;
   5097 
   5098     PORT_LOCK(unit);
   5099     rv = portmod_port_multi_get(unit, pport, &phy_reg_read);
   5100     PORT_UNLOCK(unit);
   5101 
   5102     return rv;
   5103 #else  /* PORTMOD_SUPPORT */
   5104     return BCM_E_UNAVAIL;
   5105 #endif /* PORTMOD_SUPPORT */
   5106 }
   5107 
   5108 /*
   5109  * Function:
   5110  *      bcmi_esw_portctrl_phy_modify
   5111  * Description:
   5112  *      General PHY register modify
   5113  * Parameters:
   5114  *      unit - Device number
   5115  *      port - Port number  or PHY MDIO address (refer BCM_PORT_PHY_NOMAP)
   5116  *      flags - Logical OR of one or more of the following flags:
   5117  *              BCM_PORT_PHY_INTERNAL
   5118  *                      Address internal SERDES PHY for port
   5119  *              BCM_PORT_PHY_NOMAP
   5120  *                      Instead of mapping port to PHY MDIO address,
   5121  *                      treat port parameter as actual PHY MDIO address.
   5122  *              BCM_PORT_PHY_CLAUSE45
   5123  *                      Assume Clause 45 device instead of Clause 22
   5124  *      phy_reg_addr - PHY internal register address
   5125  *      phy_data - Data to write
   5126  *      phy_mask - Bits to modify using phy_data
   5127  * Returns:
   5128  *      BCM_E_XXX
   5129  */
   5130 int
   5131 bcmi_esw_portctrl_phy_modify(int unit, bcm_gport_t port, uint32 flags,
   5132                              uint32 phy_reg_addr, uint32 phy_data,
   5133                              uint32 phy_mask)
   5134 {
   5135 #ifdef PORTMOD_SUPPORT
   5136     uint16 phy_id;
   5137     uint8  phy_devad;
   5138     uint16 phy_reg;
   5139     uint16 phy_rd_data;
   5140     uint16 phy_wr_data;
   5141     uint32 reg_flag;
   5142     int    rv;
   5143     portctrl_pport_t pport=0;
   5144     int lane = -1;
   5145     uint32 rd_data;
   5146     int phyn = -1, sys_side = 0;
   5147     bcm_port_t local_port = -1;
   5148 
   5149     /* Make sure port module is initialized. */
   5150     PORTCTRL_INIT_CHECK(unit);
   5151 
   5152     if (!(flags & BCM_PORT_PHY_NOMAP)) {
   5153         BCM_IF_ERROR_RETURN
   5154             (_bcm_esw_port_gport_phyn_validate(unit, port,
   5155                                            &local_port, &phyn,
   5156                                            &lane, &sys_side));
   5157 
   5158         if (local_port != -1) {
   5159             port = local_port;
   5160         }
   5161 
   5162         BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5163         if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) {
   5164             return BCM_E_PORT;
   5165         }
   5166     }
   5167 
   5168     LOG_INFO(BSL_LS_BCM_PORT,
   5169              (BSL_META_U(unit,
   5170                          "portctrl_phy_modify: u=%d p=%d flags=0x%08x "
   5171                          "phy_reg=0x%08x phy_data=0x%08x phy_mask=0x%08x\n"),
   5172                          unit, port, flags, phy_reg_addr, phy_data, phy_mask));
   5173 
   5174     rv       = BCM_E_UNAVAIL;
   5175     reg_flag = BCM_PORT_PHY_REG_FLAGS(phy_reg_addr);
   5176     if (reg_flag & BCM_ESW_PORTCTRL_PHY_REG_INDIRECT) {
   5177         if (flags & BCM_PORT_PHY_NOMAP) {
   5178             /* Indirect register access is performed through PHY driver.
   5179              * Therefore, indirect register access is not supported if
   5180              * BCM_PORT_PHY_NOMAP flag is set.
   5181              */
   5182             return BCM_E_PARAM;
   5183         }
   5184         phy_reg_addr &= ~BCM_ESW_PORTCTRL_PHY_REG_INDIRECT;
   5185         if (phyn == 1) {
   5186             flags |= BCM_PORT_PHY_INTERNAL;
   5187         } else {
   5188             flags = 0;
   5189         }
   5190         PORT_LOCK(unit);
   5191         rv = portmod_port_phy_reg_read(unit, pport, lane, flags, phy_reg_addr, &rd_data);
   5192         PORT_UNLOCK(unit);
   5193         
   5194         phy_data = (rd_data & ~phy_mask) | (phy_data & phy_mask);
   5195 
   5196         PORT_LOCK(unit);
   5197         rv = portmod_port_phy_reg_write(unit, pport, lane, flags, phy_reg_addr, phy_data);
   5198         PORT_UNLOCK(unit);
   5199     }
   5200 
   5201     if (rv == BCM_E_UNAVAIL) {
   5202         if (flags & BCM_PORT_PHY_NOMAP) {
   5203             phy_id = (uint16) port;
   5204         } else if (flags & BCM_PORT_PHY_INTERNAL) {
   5205             PORT_LOCK(unit);
   5206             phy_id = portmod_port_to_phyaddr_int(unit, pport);
   5207             PORT_UNLOCK(unit);
   5208         } else {
   5209             PORT_LOCK(unit);
   5210             phy_id = portmod_port_to_phyaddr(unit, pport);
   5211             PORT_UNLOCK(unit);
   5212         }
   5213 
   5214         phy_wr_data = (uint16) (phy_data & phy_mask & 0xffff);
   5215         PORT_LOCK(unit);
   5216         if (flags & BCM_PORT_PHY_CLAUSE45) {
   5217             phy_devad = BCM_PORT_PHY_CLAUSE45_DEVAD(phy_reg_addr);
   5218             phy_reg   = BCM_PORT_PHY_CLAUSE45_REGAD(phy_reg_addr);
   5219             rv = soc_miimc45_read(unit, phy_id, phy_devad,
   5220                                   phy_reg, &phy_rd_data);
   5221             phy_wr_data |= (phy_rd_data & ~phy_mask);
   5222             rv = soc_miimc45_write(unit, phy_id, phy_devad,
   5223                                    phy_reg, phy_wr_data);
   5224         } else {
   5225             phy_reg = phy_reg_addr;
   5226             rv = soc_miim_read(unit, phy_id, phy_reg, &phy_rd_data);
   5227             if (BCM_SUCCESS(rv)) {
   5228                 phy_wr_data |= (phy_rd_data & ~phy_mask);
   5229                 rv = soc_miim_write(unit, phy_id, phy_reg, phy_wr_data);
   5230             }
   5231         }
   5232         PORT_UNLOCK(unit);
   5233     }
   5234     return rv;
   5235 #else  /* PORTMOD_SUPPORT */
   5236     return BCM_E_UNAVAIL;
   5237 #endif /* PORTMOD_SUPPORT */
   5238 }
   5239 
   5240 /*
   5241  * Function:
   5242  *      bcmi_esw_portctrl_phy_set
   5243  * Description:
   5244  *      General PHY register write
   5245  * Parameters:
   5246  *      unit - Device number
   5247  *      port - Port number or PHY MDIO address (refer BCM_PORT_PHY_NOMAP)
   5248  *      flags - Logical OR of one or more of the following flags:
   5249  *              BCM_PORT_PHY_INTERNAL
   5250  *                      Address internal SERDES PHY for port
   5251  *              BCM_PORT_PHY_NOMAP
   5252  *                      Instead of mapping port to PHY MDIO address,
   5253  *                      treat port parameter as actual PHY MDIO address.
   5254  *              BCM_PORT_PHY_CLAUSE45
   5255  *                      Assume Clause 45 device instead of Clause 22
   5256  *      phy_reg_addr - PHY internal register address
   5257  *      phy_data - Data to write
   5258  * Returns:
   5259  *      BCM_E_XXX
   5260  */
   5261 int
   5262 bcmi_esw_portctrl_phy_set(int unit, bcm_gport_t port, uint32 flags,
   5263                           uint32 phy_reg_addr, uint32 phy_data)
   5264 {
   5265 #ifdef PORTMOD_SUPPORT
   5266     uint16 phy_id;
   5267     uint8  phy_devad;
   5268     uint16 phy_reg;
   5269     uint16 phy_wr_data;
   5270     uint32 reg_flag;
   5271     int    rv;
   5272     portctrl_pport_t pport=0;
   5273     int lane = -1;
   5274     int phyn = -1, sys_side = 0;
   5275     bcm_port_t local_port = -1;
   5276 
   5277     /* Make sure port module is initialized. */
   5278     PORTCTRL_INIT_CHECK(unit);
   5279 
   5280     if (!(flags & BCM_PORT_PHY_NOMAP)) {
   5281         BCM_IF_ERROR_RETURN
   5282         (_bcm_esw_port_gport_phyn_validate(unit, port,
   5283                                            &local_port, &phyn,
   5284                                            &lane, &sys_side));
   5285 
   5286         if (local_port != -1) {
   5287             port = local_port;
   5288         }
   5289 
   5290         BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5291         if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) {
   5292             return BCM_E_PORT;
   5293         }
   5294     }
   5295 
   5296     LOG_INFO(BSL_LS_BCM_PORT,
   5297              (BSL_META_U(unit,
   5298                          "portctrl_phy_set: u=%d p=%d flags=0x%08x "
   5299                          "phy_reg=0x%08x phy_data=0x%08x\n"),
   5300                          unit, port, flags, phy_reg_addr, phy_data));
   5301 
   5302     if (flags & (BCM_PORT_PHY_I2C_DATA8 | BCM_PORT_PHY_I2C_DATA16 | BCM_PORT_PHY_PVT_DATA)) {
   5303         PORT_LOCK(unit);
   5304         rv = portmod_port_phy_reg_write(unit, pport, lane, flags, phy_reg_addr, phy_data);
   5305         PORT_UNLOCK(unit);
   5306         return rv;
   5307     }
   5308 
   5309     rv       = BCM_E_UNAVAIL;
   5310     reg_flag = BCM_PORT_PHY_REG_FLAGS(phy_reg_addr);
   5311     if (reg_flag & BCM_ESW_PORTCTRL_PHY_REG_INDIRECT) {
   5312         if (flags & BCM_PORT_PHY_NOMAP) {
   5313             /* Indirect register access is performed through PHY driver.
   5314              * Therefore, indirect register access is not supported if
   5315              * BCM_PORT_PHY_NOMAP flag is set.
   5316              */
   5317             return BCM_E_PARAM;
   5318         }
   5319         phy_reg_addr &= ~BCM_ESW_PORTCTRL_PHY_REG_INDIRECT;
   5320         if (phyn == 1) {
   5321             flags |= BCM_PORT_PHY_INTERNAL;
   5322         } else {
   5323             flags = 0;
   5324         }
   5325         PORT_LOCK(unit);
   5326         rv = portmod_port_phy_reg_write(unit, pport, lane, flags, phy_reg_addr, phy_data);
   5327         PORT_UNLOCK(unit);
   5328     }
   5329 
   5330     if (rv == BCM_E_UNAVAIL) {
   5331         if (flags & BCM_PORT_PHY_NOMAP) {
   5332             phy_id = (uint16) port;
   5333         } else if (flags & BCM_PORT_PHY_INTERNAL) {
   5334             PORT_LOCK(unit);
   5335             phy_id = portmod_port_to_phyaddr_int(unit, port);
   5336             PORT_UNLOCK(unit);
   5337         } else {
   5338             PORT_LOCK(unit);
   5339             phy_id = portmod_port_to_phyaddr(unit, port);
   5340             PORT_UNLOCK(unit);
   5341         }
   5342 
   5343         phy_wr_data = (uint16) (phy_data & 0xffff);
   5344         PORT_LOCK(unit);
   5345         if (flags & BCM_PORT_PHY_CLAUSE45) {
   5346             phy_devad = BCM_PORT_PHY_CLAUSE45_DEVAD(phy_reg_addr);
   5347             phy_reg   = BCM_PORT_PHY_CLAUSE45_REGAD(phy_reg_addr);
   5348             rv = soc_miimc45_write(unit, phy_id, phy_devad,
   5349                                    phy_reg, phy_wr_data);
   5350         } else {
   5351             phy_reg = phy_reg_addr;
   5352             rv = soc_miim_write(unit, phy_id, phy_reg, phy_wr_data);
   5353         }
   5354         PORT_UNLOCK(unit);
   5355     }
   5356     return rv;
   5357 #else  /* PORTMOD_SUPPORT */
   5358     return BCM_E_UNAVAIL;
   5359 #endif /* PORTMOD_SUPPORT */
   5360 }
   5361 
   5362 /*
   5363  * Function:
   5364  *      bcmi_portctrl_phy_drv_name_get
   5365  * Purpose:
   5366  *      Return the name of the PHY driver being used on a port.
   5367  * Parameters:
   5368  *      unit - StrataSwitch unit #
   5369  *      port - StrataSwitch port #
   5370  * Returns:
   5371  *      Pointer to static string
   5372  */
   5373 int
   5374 bcmi_esw_portctrl_phy_drv_name_get(int unit, bcm_gport_t port, char *name,
   5375                                    int len)
   5376 {
   5377 #ifdef PORTMOD_SUPPORT
   5378     int str_len;
   5379     int rv;
   5380     portctrl_pport_t pport;
   5381 
   5382     /* Make sure port module is initialized. */
   5383     PORTCTRL_INIT_CHECK(unit);
   5384 
   5385     rv = PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport);
   5386 
   5387     if (BCM_FAILURE(rv)) {
   5388         str_len = sal_strlen("invalid port");
   5389         if (str_len <= len) {
   5390             sal_strncpy(name, "invalid port", len);
   5391         }
   5392         return BCM_E_PORT;
   5393     }
   5394 
   5395     PORT_LOCK(unit);
   5396 
   5397     rv = portmod_port_phy_drv_name_get(unit, pport, name, len);
   5398 
   5399     PORT_UNLOCK(unit);
   5400 
   5401     return rv;
   5402 #else  /* PORTMOD_SUPPORT */
   5403     return BCM_E_UNAVAIL;
   5404 #endif /* PORTMOD_SUPPORT */
   5405 }
   5406 
   5407 /*
   5408  * Function:
   5409  *      bcmi_portctrl_phy_reset
   5410  * Description:
   5411  *      This function performs the low-level PHY reset and is intended to be
   5412  *      called ONLY from callback function registered with
   5413  *      bcm_port_phy_reset_register. Attempting to call it from any other
   5414  *      place will break lots of things.
   5415  * Parameters:
   5416  *      unit    - Device number
   5417  *      port    - Port number
   5418  * Returns:
   5419  *      BCM_E_XXX
   5420  */
   5421 int
   5422 bcmi_esw_portctrl_phy_reset(int unit, bcm_gport_t port)
   5423 {
   5424 #ifdef PORTMOD_SUPPORT
   5425     int rv;
   5426     portctrl_pport_t pport;
   5427 
   5428     /* Make sure port module is initialized. */
   5429     PORTCTRL_INIT_CHECK(unit);
   5430     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5431 
   5432     PORT_LOCK(unit);
   5433     rv = portmod_port_reset_set(unit, pport, 
   5434                                 phymodResetModeHard /* Hard reset */,
   5435                                 0 /* Not used */,
   5436                                 phymodResetDirectionInOut /* Toggle reset */);
   5437     PORT_UNLOCK(unit);
   5438     return rv;
   5439 #else  /* PORTMOD_SUPPORT */
   5440     return BCM_E_UNAVAIL;
   5441 #endif /* PORTMOD_SUPPORT */
   5442 }
   5443 
   5444 
   5445 /*
   5446  * Function:
   5447  *      bcmi_esw_portctrl_ability_advert_get
   5448  * Purpose:
   5449  *      Retrieve the local port advertisement for autonegotiation.
   5450  * Parameters:
   5451  *      unit - StrataSwitch Unit #.
   5452  *      port - StrataSwitch port #.
   5453  *      port_ability - (OUT) Local advertisement in bcm_port_ability_t structure.
   5454  *      ability_mask - (OUT) Local advertisement in bcm_port_abil_t.
   5455  *                           If !NULL, returns mask of BCM_PORT_ABIL_.
   5456  * Returns:
   5457  *      BCM_E_NONE
   5458  *      BCM_E_XXX
   5459  */
   5460 int
   5461 bcmi_esw_portctrl_ability_advert_get(int unit, bcm_gport_t port, 
   5462                                      bcm_port_ability_t *port_ability,
   5463                                      bcm_port_abil_t *ability_mask)
   5464 {
   5465 #ifdef PORTMOD_SUPPORT
   5466     int rv;
   5467     portctrl_pport_t pport;
   5468     portmod_port_ability_t portmod_ability;
   5469 
   5470     /* Make sure port module is initialized. */
   5471     PORTCTRL_INIT_CHECK(unit);
   5472     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5473 
   5474     bcm_port_ability_t_init(port_ability);
   5475     sal_memset(&portmod_ability, 0, sizeof(portmod_port_ability_t));
   5476 
   5477     PORT_LOCK(unit);
   5478 #ifdef SW_AUTONEG_SUPPORT
   5479     {
   5480         int an_mode = 0;
   5481 
   5482         an_mode = soc_property_port_get(unit, port,
   5483                           spn_PHY_AN_C73, an_mode);
   5484         if (soc_feature(unit, soc_feature_sw_autoneg)) {
   5485             /* phy_an_c73 value of 3 indicated MSA AN mode 
   5486  */
   5487             if ((an_mode == SW_AN_MODE_CL73_MSA) || (an_mode == SW_AN_MODE_MSA_ONLY)) {
   5488                 rv = bcm_sw_an_ability_advert_get(unit, port, port_ability);
   5489                 if (PORTMOD_SUCCESS(rv)) {
   5490                     /* Convert to BCM_PORT_ABIL_ mask if needed 
   5491  */
   5492                     if (ability_mask != NULL) {
   5493                         rv = soc_port_ability_to_mode(port_ability, ability_mask);
   5494                     }
   5495                     PORT_UNLOCK(unit);
   5496                     return rv;
   5497                 }
   5498             }
   5499         }
   5500     }
   5501 #endif
   5502     rv = portmod_port_ability_advert_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &portmod_ability);
   5503     PORT_UNLOCK(unit);
   5504 
   5505     if (PORTMOD_SUCCESS(rv)) {
   5506         _bcm_esw_portctrl_from_portmod_ability(&portmod_ability, port_ability);
   5507 
   5508         /* Convert to BCM_PORT_ABIL_ mask if needed */
   5509         if (ability_mask != NULL) {
   5510             rv = soc_port_ability_to_mode(port_ability, ability_mask);
   5511         }
   5512     }
   5513 
   5514     LOG_VERBOSE(BSL_LS_BCM_PORT,
   5515                 (BSL_META_UP(unit, port,
   5516                              "Get port ability advert: u=%d p=%d rv=%d\n"),
   5517                 unit, port, rv));
   5518 
   5519     return rv;
   5520 
   5521 #else  /* PORTMOD_SUPPORT */
   5522     return BCM_E_UNAVAIL;
   5523 #endif /* PORTMOD_SUPPORT */
   5524 }
   5525 
   5526 
   5527 /*
   5528  * Function:
   5529  *      bcmi_esw_portctrl_ability_advert_set
   5530  * Purpose:
   5531  *      Set the local port advertisement for autonegotiation.
   5532  * Parameters:
   5533  *      unit - StrataSwitch Unit #.
   5534  *      port - StrataSwitch port #.
   5535  *      port_ability - Local advertisement in bcm_port_ability_t structure.
   5536  *      ability_mask - Local advertisement in bcm_port_abil_t.
   5537  *                           If !NULL, returns mask of BCM_PORT_ABIL_.
   5538  * Returns:
   5539  *      BCM_E_NONE
   5540  *      BCM_E_XXX
   5541   * Notes:
   5542  *      This call MAY NOT restart autonegotiation (depending on the phy).
   5543  *      To do that, follow this call with bcm_port_autoneg_set(TRUE).
   5544  */
   5545 int
   5546 bcmi_esw_portctrl_ability_advert_set(int unit, bcm_gport_t port, 
   5547                                      bcm_port_ability_t *ability_mask,
   5548                                      bcm_port_abil_t port_abil)
   5549 {
   5550 #ifdef PORTMOD_SUPPORT
   5551     int rv;
   5552     portctrl_pport_t pport;
   5553     bcm_port_ability_t local_ability, temp_ability_mask, temp_ability;
   5554 
   5555     /* Make sure port module is initialized. */
   5556     PORTCTRL_INIT_CHECK(unit);
   5557 
   5558     sal_memset(&local_ability, 0, sizeof(bcm_port_ability_t));
   5559     sal_memset(&temp_ability_mask, 0, sizeof(bcm_port_ability_t));
   5560 
   5561     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5562 
   5563     BCM_IF_ERROR_RETURN
   5564         (bcmi_esw_portctrl_ability_get(unit, port, &local_ability, NULL));
   5565 
   5566     /* If ability_mask is NULL then it means the call came through
   5567      * old API bcm_esw_port_advert_set. We need to convert
   5568      * BCM_PORT_ABIL_ mask to bcm_port_ability_t structure */
   5569     if (ability_mask == NULL) {
   5570         SOC_IF_ERROR_RETURN(soc_port_mode_to_ability(port_abil, &temp_ability_mask));
   5571     } else {
   5572         temp_ability_mask = *ability_mask;
   5573     }
   5574     /* temporary store speed_half_duplex ability */
   5575     temp_ability.speed_half_duplex = temp_ability_mask.speed_half_duplex;
   5576     /* Make sure to advertise only abilities supported by the port */
   5577     SOC_IF_ERROR_RETURN(soc_port_ability_mask(&local_ability, &temp_ability_mask));
   5578     /* restore half duplex speed ability, even if some mac don't support it */
   5579     local_ability.speed_half_duplex = temp_ability.speed_half_duplex;
   5580 
   5581     PORT_LOCK(unit);
   5582 #ifdef SW_AUTONEG_SUPPORT
   5583     {
   5584         int an_mode = 0;
   5585 
   5586         an_mode = soc_property_port_get(unit, port,
   5587                           spn_PHY_AN_C73, an_mode);
   5588         if (soc_feature(unit, soc_feature_sw_autoneg)) {
   5589             /* phy_an_c73 value of 3 indicated MSA AN mode 
   5590  */
   5591             if ((an_mode == SW_AN_MODE_CL73_MSA) ||
   5592             (an_mode == SW_AN_MODE_MSA_ONLY)) {
   5593                 rv = bcm_sw_an_ability_advert_set(unit, port, &local_ability);
   5594                 PORT_UNLOCK(unit);
   5595                 return rv;
   5596             }
   5597         }
   5598 }
   5599 #endif
   5600     rv = portmod_port_ability_advert_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &local_ability);
   5601     PORT_UNLOCK(unit);
   5602 
   5603     LOG_INFO(BSL_LS_BCM_PORT,
   5604              (BSL_META_UP(unit, port,
   5605                          "Set port ability advert: u=%d p=%d rv=%d\n"),
   5606               unit, port, rv));
   5607 
   5608     LOG_VERBOSE(BSL_LS_BCM_PORT,
   5609                 (BSL_META_UP(unit, port,
   5610                      "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x abl_advert_set\n"
   5611                             "Interface=0x%08x Medium=0x%08x Loopback=0x%08x Flags=0x%08x\n"),
   5612                      local_ability.speed_half_duplex,
   5613                      local_ability.speed_full_duplex,
   5614                      local_ability.pause, local_ability.interface,
   5615                      local_ability.medium, local_ability.loopback,
   5616                      local_ability.flags));
   5617 
   5618     return rv;
   5619 
   5620 #else  /* PORTMOD_SUPPORT */
   5621     return BCM_E_UNAVAIL;
   5622 #endif /* PORTMOD_SUPPORT */
   5623 }
   5624 
   5625 /*
   5626  * Function:
   5627  *      bcmi_esw_portctrl_autoneg_get
   5628  * Purpose:
   5629  *      Get the autonegotiation state of the port
   5630  * Parameters:
   5631  *      unit - Unit #
   5632  *      port - GPORT #
   5633  *      autoneg - (OUT) Boolean value
   5634  * Returns:
   5635  *      BCM_E_NONE
   5636  *      BCM_E_XXX
   5637  */
   5638 int
   5639 bcmi_esw_portctrl_autoneg_get(int unit, bcm_gport_t port, int *autoneg)
   5640 {
   5641 #ifdef PORTMOD_SUPPORT
   5642     int rv;
   5643     portctrl_pport_t pport;
   5644     int phy_lane = -1;
   5645     int phyn = 0, sys_side = 0;
   5646     bcm_port_t local_port = -1;
   5647     phymod_autoneg_control_t an;
   5648 
   5649     /* Make sure port module is initialized. */
   5650     PORTCTRL_INIT_CHECK(unit);
   5651 
   5652     phymod_autoneg_control_t_init(&an);
   5653 
   5654     BCM_IF_ERROR_RETURN(
   5655         _bcm_esw_port_gport_phyn_validate(unit, port,
   5656                                           &local_port, &phyn,
   5657                                           &phy_lane, &sys_side));
   5658 
   5659     if (local_port != -1) {
   5660         port = local_port;
   5661     }
   5662 
   5663     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5664 
   5665     PORT_LOCK(unit);
   5666     if (local_port == -1) {
   5667         /* Configure outermost PHY (common case) */
   5668         rv = portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an);
   5669     } else {
   5670         /* Configure PHY specified by GPORT */
   5671         rv = portmod_port_redirect_autoneg_get(unit, pport, phyn,
   5672                                                phy_lane, sys_side, &an);
   5673     }
   5674     PORT_UNLOCK(unit);
   5675 
   5676     if (PORTMOD_SUCCESS(rv)) {
   5677         *autoneg = an.enable;
   5678     }
   5679 
   5680     LOG_INFO(BSL_LS_BCM_PORT,
   5681              (BSL_META_UP(unit, port,
   5682                           "Get port autoneg: u=%d p=%d an=%d rv=%d\n"),
   5683               unit, port, *autoneg, rv));
   5684 
   5685     return rv;
   5686 
   5687 #else  /* PORTMOD_SUPPORT */
   5688     return BCM_E_UNAVAIL;
   5689 #endif /* PORTMOD_SUPPORT */
   5690 }
   5691 
   5692 /*
   5693  * Function:
   5694  *      bcmi_esw_portctrl_autoneg_set
   5695  * Purpose:
   5696  *      Set the autonegotiation state for a given port
   5697  * Parameters:
   5698  *      unit - Unit #
   5699  *      port - GPORT #
   5700  *      autoneg - Boolean value
   5701  * Returns:
   5702  *      BCM_E_NONE
   5703  *      BCM_E_XXX
   5704  */
   5705 int
   5706 bcmi_esw_portctrl_autoneg_set(int unit, bcm_port_t port, int autoneg)
   5707 {
   5708 #ifdef PORTMOD_SUPPORT
   5709     int rv;
   5710     portctrl_pport_t pport;
   5711     int phy_lane = -1;
   5712     int phyn = 0, sys_side = 0;
   5713     bcm_port_t local_port = -1;
   5714     phymod_autoneg_control_t an;
   5715 
   5716     /* Make sure port module is initialized. */
   5717     PORTCTRL_INIT_CHECK(unit);
   5718 
   5719 #ifdef BCM_RCPU_SUPPORT
   5720     if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   5721         return BCM_E_PORT;
   5722     }
   5723 #endif /* BCM_RCPU_SUPPORT */
   5724 
   5725     phymod_autoneg_control_t_init(&an);
   5726 
   5727     BCM_IF_ERROR_RETURN(
   5728         _bcm_esw_port_gport_phyn_validate(unit, port,
   5729                                           &local_port, &phyn,
   5730                                           &phy_lane, &sys_side));
   5731 
   5732     if (local_port != -1) {
   5733         port = local_port;
   5734     }
   5735 
   5736     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5737 
   5738     BCM_IF_ERROR_RETURN(portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an));
   5739     an.enable = autoneg;
   5740 
   5741     PORT_LOCK(unit);
   5742 #ifdef SW_AUTONEG_SUPPORT
   5743 {
   5744     int           an_mode = 0;
   5745 
   5746     an_mode = soc_property_port_get(unit, port,
   5747                       spn_PHY_AN_C73, an_mode);
   5748     if (soc_feature(unit, soc_feature_sw_autoneg)) {
   5749         /* phy_an_c73 value of 3 indicated MSA AN mode 
   5750  */
   5751         if ((an_mode == SW_AN_MODE_CL73_MSA) ||
   5752         (an_mode == SW_AN_MODE_MSA_ONLY)) {
   5753             if (autoneg) {
   5754                 rv = bcm_sw_an_port_register(unit, port);
   5755                 if (rv == BCM_E_NONE) {
   5756                     PORT_UNLOCK(unit);
   5757                     return rv;
   5758                 } else if (rv == BCM_E_PORT) {
   5759                     /* when an_set is called during the init
   5760                      * ports wouldn't have been added to SW AN
   5761  */
   5762                     rv = BCM_E_NONE;
   5763                     PORT_UNLOCK(unit);
   5764                     return rv;
   5765                 } else {
   5766                     /* add bsl log 
   5767  */
   5768                     PORT_UNLOCK(unit);
   5769                     return rv;
   5770                 }
   5771             } else {
   5772                 rv = bcm_sw_an_port_unregister(unit, port);
   5773                 if (rv == BCM_E_NONE) {
   5774                     PORT_UNLOCK(unit);
   5775                     return rv;
   5776                 } else if (rv == BCM_E_PORT) {
   5777                     /* when an_set is called during the init
   5778                      * ports wouldn't have been added to SW AN
   5779  */
   5780                     rv = BCM_E_NONE;
   5781                     PORT_UNLOCK(unit);
   5782                     return rv;
   5783                 } else {
   5784                     /* add bsl log */
   5785                     PORT_UNLOCK(unit);
   5786                     return rv;
   5787                 }
   5788             }
   5789         }
   5790     }
   5791 }
   5792 #endif
   5793     if (local_port == -1) {
   5794         /* Configure outermost PHY (common case) */
   5795         rv = portmod_port_autoneg_set(unit, port, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an);
   5796     } else {
   5797         /* Configure PHY specified by GPORT */
   5798         rv = portmod_port_redirect_autoneg_set(unit, pport, phyn,
   5799                                                phy_lane, sys_side, &an);
   5800     }
   5801     PORT_UNLOCK(unit);
   5802 
   5803     LOG_INFO(BSL_LS_BCM_PORT,
   5804              (BSL_META_UP(unit, port,
   5805                           "Set port autoneg: u=%d p=%d an=%d rv=%d\n"),
   5806               unit, port, autoneg, rv));
   5807 
   5808     return rv;
   5809 
   5810 #else  /* PORTMOD_SUPPORT */
   5811     return BCM_E_UNAVAIL;
   5812 #endif /* PORTMOD_SUPPORT */
   5813 }
   5814 
   5815 /* Function:
   5816  *     bcmi_esw_portctrl_autoneg_ability_advert_get
   5817  * Purpose:
   5818  *     Retrieve the local port advertisement for autonegotiation.
   5819  * Parameters:
   5820  *     unit - StrataSwitch Unit #.
   5821  *     port - StrataSwtich port #.
   5822  *     max_num_ability - Maximum number of abilities that can be returned.
   5823  *     abilities - AN abilities array.
   5824  *     actual_num_ability - Actual number of abilities in abilities array.
   5825  * Returns:
   5826  *     BCM_E_NONE
   5827  *     BCM_E_XXX
   5828  */
   5829 int
   5830 bcmi_esw_portctrl_autoneg_ability_advert_get(int unit,
   5831                                              bcm_gport_t port,
   5832                                              int max_num_ability,
   5833                                              bcm_port_speed_ability_t *abilities,
   5834                                              int *actual_num_ability)
   5835 {
   5836 #ifdef PORTMOD_SUPPORT
   5837     int rv, an_abilities_size = 0;
   5838     portctrl_pport_t pport;
   5839     portmod_port_speed_ability_t *an_abilities = NULL;
   5840     int valid_abilities;
   5841 
   5842     /* Make sure port module is initialized. */
   5843     PORTCTRL_INIT_CHECK(unit);
   5844     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5845 
   5846     if (abilities == NULL) {
   5847         rv = BCM_E_PARAM;
   5848         return rv;
   5849     }
   5850 
   5851     an_abilities_size = PORTCTRL_AUTONEG_ABILITY_MAX_COUNT;
   5852 
   5853     an_abilities = sal_alloc(an_abilities_size * sizeof(portmod_port_speed_ability_t), "abilities array");
   5854 
   5855     if (an_abilities == NULL) {
   5856         rv = SOC_E_MEMORY;
   5857         return rv;
   5858     }
   5859 
   5860     sal_memset(an_abilities, 0, an_abilities_size * sizeof(portmod_port_speed_ability_t));
   5861     *actual_num_ability = 0;
   5862 
   5863     PORT_LOCK(unit);
   5864     rv = portmod_port_autoneg_ability_advert_get(unit, pport, an_abilities_size, an_abilities, actual_num_ability);
   5865     PORT_UNLOCK(unit);
   5866 
   5867     if (PORTMOD_SUCCESS(rv)) {
   5868         BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_from_portmod_autoneg_ability(unit,
   5869                                 *actual_num_ability, an_abilities, max_num_ability,
   5870                                 abilities, &valid_abilities));
   5871         *actual_num_ability = valid_abilities;
   5872     }
   5873 
   5874     LOG_VERBOSE(BSL_LS_BCM_PORT,
   5875                 (BSL_META_UP(unit, port,
   5876                              "Get port autoneg advert ability: u=%d p=%d rv=%d\n"),
   5877                 unit, port, rv));
   5878     if (NULL != an_abilities) {
   5879         sal_free(an_abilities);
   5880     }
   5881     return rv;
   5882 #else  /* PORTMOD_SUPPORT */
   5883     return BCM_E_UNAVAIL;
   5884 #endif /* PORTMOD_SUPPORT */
   5885 }
   5886 
   5887 /*
   5888  * Function:
   5889  *     bcmi_esw_portctrl_autoneg_ability_advert_set
   5890  * Purpose:
   5891  *     Set the local port advertisement for autonegotiation.
   5892  *     Only applicable to PM8x50.
   5893  * Parameters:
   5894  *     unit - StrataSwitch Unit #.
   5895  *     port - StrataSwtich port #.
   5896  *     num_ability - Number of local advertising abilities.
   5897  *     abilities - AN abilities array.
   5898  * Returns:
   5899  *     BCM_E_NONE
   5900  *     BCM_E_XXX
   5901  * Notes:
   5902  *     This call will not start autonegotiation.
   5903  *     To do that, follow this call with bcm_port_autoneg_set(TRUE).
   5904  */
   5905 int
   5906 bcmi_esw_portctrl_autoneg_ability_advert_set(int unit,
   5907                                              bcm_gport_t port,
   5908                                              int num_ability,
   5909                                              bcm_port_speed_ability_t *abilities)
   5910 {
   5911 #ifdef PORTMOD_SUPPORT
   5912     int rv = BCM_E_NONE;
   5913     portctrl_pport_t pport;
   5914     int num_lanes, max_speed, i;
   5915     char *str="";
   5916     portmod_port_speed_ability_t *an_abilities = NULL;
   5917 
   5918     /* Make sure port module is initialized. */
   5919     PORTCTRL_INIT_CHECK(unit);
   5920     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   5921 
   5922     if (abilities == NULL) {
   5923         rv = BCM_E_PARAM;
   5924         return rv;
   5925     }
   5926 
   5927     num_lanes = SOC_INFO(unit).port_num_lanes[port];
   5928     max_speed = SOC_INFO(unit).port_speed_max[port];
   5929 
   5930     /* In this layer, we only do max_speed and num_lane check */
   5931     /* PORTMOD will do more validation during autoneg_ability_advert_set */
   5932     for (i = 0; i < num_ability; i++) {
   5933         if (abilities[i].speed > max_speed) {
   5934             str = "abilities.speed exceeds port's maximum speed:";
   5935             rv = BCM_E_CONFIG;
   5936             break;
   5937         }
   5938         if (abilities[i].resolved_num_lanes > num_lanes) {
   5939             str = "abilities.resolved_num_lanes exceeds port's number of lanes:";
   5940             rv = BCM_E_CONFIG;
   5941             break;
   5942         }
   5943     }
   5944 
   5945     if (num_ability > PORTCTRL_AUTONEG_ABILITY_MAX_COUNT) {
   5946         str = "Too many abilities requested:";
   5947         rv = BCM_E_CONFIG;
   5948     }
   5949 
   5950     if (PORTMOD_FAILURE(rv)) {
   5951         LOG_VERBOSE(BSL_LS_BCM_PORT,
   5952               (BSL_META_UP(unit, port, "autoneg_ablity_advert_set: %s\nport=%d,"
   5953               "rv=%d\n"), str, port, rv));
   5954         return rv;
   5955     }
   5956 
   5957     an_abilities = sal_alloc(num_ability * sizeof(portmod_port_speed_ability_t), "abilities array");
   5958     if (an_abilities == NULL) {
   5959         rv = SOC_E_MEMORY;
   5960         return rv;
   5961     }
   5962     sal_memset(an_abilities, 0, num_ability * sizeof(portmod_port_speed_ability_t));
   5963 
   5964     _bcm_esw_portmod_from_portctrl_autoneg_ability(num_ability, abilities, an_abilities);
   5965 
   5966     PORT_LOCK(unit);
   5967     rv = portmod_port_autoneg_ability_advert_set(unit, pport, num_ability, an_abilities);
   5968     PORT_UNLOCK(unit);
   5969 
   5970     LOG_INFO(BSL_LS_BCM_PORT,
   5971              (BSL_META_UP(unit, port,
   5972                          "Set port autoneg advert ability: u=%d p=%d rv=%d\n"),
   5973               unit, port, rv));
   5974     if (NULL != an_abilities) {
   5975         sal_free(an_abilities);
   5976     }
   5977     return rv;
   5978 #else  /* PORTMOD_SUPPORT */
   5979     return BCM_E_UNAVAIL;
   5980 #endif /* PORTMOD_SUPPORT */
   5981 }
   5982 
   5983 /*
   5984  * Function:
   5985  *      bcmi_esw_portctrl_duplex_get
   5986  * Purpose:
   5987  *      Get the port duplex settings
   5988  * Parameters:
   5989  *      unit - StrataSwitch Unit #.
   5990  *      port - StrataSwitch port #.
   5991  *      duplex - (OUT) Duplex setting, one of SOC_PORT_DUPLEX_xxx
   5992  * Returns:
   5993  *      BCM_E_NONE
   5994  *      BCM_E_XXX
   5995  */
   5996 int
   5997 bcmi_esw_portctrl_duplex_get(int unit, bcm_gport_t port, int *duplex)
   5998 {
   5999 #ifdef PORTMOD_SUPPORT
   6000     int rv;
   6001     portctrl_pport_t pport;
   6002 
   6003     /* Make sure port module is initialized. */
   6004     PORTCTRL_INIT_CHECK(unit);
   6005 
   6006     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6007 
   6008     PORT_LOCK(unit);
   6009     rv = soc_esw_portctrl_duplex_get(unit, port, duplex);
   6010     PORT_UNLOCK(unit);
   6011 
   6012     LOG_INFO(BSL_LS_BCM_PORT,
   6013              (BSL_META_UP(unit, port,
   6014                           "Get port duplex: u=%d p=%d dup=%d rv=%d\n"),
   6015               unit, port, *duplex, rv));
   6016 
   6017     return rv;
   6018 
   6019 #else  /* PORTMOD_SUPPORT */
   6020     return BCM_E_UNAVAIL;
   6021 #endif /* PORTMOD_SUPPORT */
   6022 }
   6023 
   6024 /*
   6025  * Function:
   6026  *      bcmi_esw_portctrl_duplex_set
   6027  * Purpose:
   6028  *      Set the port duplex settings.
   6029  * Parameters:
   6030  *      unit - StrataSwitch Unit #.
   6031  *      port - StrataSwitch port #.
   6032  *      duplex - Duplex setting, one of SOC_PORT_DUPLEX_xxx
   6033  * Returns:
   6034  *      BCM_E_NONE
   6035  *      BCM_E_XXX
   6036  * Notes:
   6037  *      Turns off autonegotiation.  Caller must make sure other forced
   6038  *      parameters (such as speed) are set.
   6039  */
   6040 int
   6041 bcmi_esw_portctrl_duplex_set(int unit, bcm_port_t port, int duplex)
   6042 {
   6043 #ifdef PORTMOD_SUPPORT
   6044     int         rv;
   6045     pbmp_t      pbm;
   6046     portctrl_pport_t pport;
   6047 
   6048     /* Make sure port module is initialized. */
   6049     PORTCTRL_INIT_CHECK(unit);
   6050 
   6051     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6052 
   6053 #ifdef BCM_RCPU_SUPPORT
   6054     if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   6055         return BCM_E_PORT;
   6056     }
   6057 #endif /* BCM_RCPU_SUPPORT */
   6058 
   6059 #if 0
   6060     /* Disable auto-negotiation if duplex is forced */
   6061     rv = bcmi_esw_portctrl_autoneg_set(unit, port, FALSE);
   6062     if (BCM_FAILURE(rv)) {
   6063         LOG_VERBOSE(BSL_LS_BCM_PORT,
   6064                     (BSL_META_UP(unit, port,
   6065                                  "Set port autonego failed:%s\n"),
   6066                      bcm_errmsg(rv)));
   6067         return rv;
   6068     }
   6069 #endif 
   6070 
   6071     PORT_LOCK(unit);
   6072 
   6073     rv = soc_esw_portctrl_duplex_set(unit, pport, duplex);
   6074 
   6075     PORT_UNLOCK(unit);                  /* Unlock before link call */
   6076 
   6077     if (PORTMOD_SUCCESS(rv) && !SAL_BOOT_SIMULATION) {
   6078         /* Force link change event */
   6079         SOC_PBMP_CLEAR(pbm);
   6080         SOC_PBMP_PORT_ADD(pbm, port);
   6081         (void)bcm_esw_link_change(unit, pbm);
   6082     }
   6083 
   6084     LOG_INFO(BSL_LS_BCM_PORT,
   6085              (BSL_META_UP(unit, port,
   6086                          "Set port duplex: u=%d p=%d dup=%d rv=%d\n"),
   6087               unit, port, duplex, rv));
   6088 
   6089     return rv;
   6090 
   6091 #else  /* PORTMOD_SUPPORT */
   6092     return BCM_E_UNAVAIL;
   6093 #endif /* PORTMOD_SUPPORT */
   6094 }
   6095 
   6096 /*
   6097  * Function:
   6098  *      bcmi_esw_portctrl_clear_rx_lss_status_set
   6099  * Purpose:
   6100  *      set the local and remote fault fields of the lss status register.
   6101  * Parameters:
   6102  *      unit         - (IN) Unit number.
   6103  *      port         - (IN) Port number.
   6104  *      local_fault  - (IN) value of local fault field to be set.
   6105  *      remote_fault - (IN) value of remote fault field to be set.
   6106  * Returns:
   6107  *      BCM_E_NONE
   6108  *      BCM_E_XXX
   6109  */
   6110 
   6111 int
   6112 bcmi_esw_portctrl_clear_rx_lss_status_set(int unit, bcm_gport_t port,
   6113                                           int local_fault, int remote_fault)
   6114 {
   6115 #ifdef PORTMOD_SUPPORT
   6116     int rv = BCM_E_NONE;
   6117     portctrl_pport_t  pport;
   6118 
   6119     PORTCTRL_INIT_CHECK(unit);
   6120 
   6121     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6122 
   6123     PORT_LOCK(unit);
   6124     rv = portmod_port_clear_rx_lss_status_set(unit, pport, local_fault,
   6125                                               remote_fault);
   6126     PORT_UNLOCK(unit);
   6127     return rv;
   6128 #else  /* PORTMOD_SUPPORT */
   6129     return BCM_E_UNAVAIL;
   6130 #endif /* PORTMOD_SUPPORT */
   6131 }
   6132 
   6133 /*
   6134  * Function:
   6135  *      bcmi_esw_portctrl_mode_setup
   6136  * Purpose:
   6137  *      Set initial operating mode for a port.
   6138  * Parameters:
   6139  *      unit - StrataSwitch unit #.
   6140  *      port - StrataSwitch port #.
   6141  *      enable - Whether to enable or disable
   6142  * Returns:
   6143  *      BCM_E_XXX
   6144  * Notes:
   6145  *      Must be called with PORT_LOCK held.
   6146  */
   6147 int
   6148 bcmi_esw_portctrl_mode_setup(int unit, bcm_gport_t port, int enable)
   6149 {
   6150 #ifdef PORTMOD_SUPPORT
   6151 #if 0
   6152     soc_port_if_t   pif;
   6153 #endif
   6154     portmod_port_ability_t  local_port_ability, advert_port_ability;
   6155     portctrl_pport_t pport;
   6156     int rv = BCM_E_NONE;
   6157 
   6158     PORTCTRL_INIT_CHECK(unit);
   6159 
   6160     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6161 
   6162     if (IS_TDM_PORT(unit, port)) {
   6163         return BCM_E_NONE;
   6164     }
   6165 
   6166     LOG_INFO(BSL_LS_BCM_PORT,
   6167              (BSL_META_U(unit,
   6168                          "_bcm_port_mode_setup: u=%d p=%d\n"), unit, port));
   6169 
   6170     sal_memset(&local_port_ability,  0, sizeof(bcm_port_ability_t));
   6171     sal_memset(&advert_port_ability, 0, sizeof(bcm_port_ability_t));
   6172 
   6173     PORT_LOCK(unit);
   6174     if (!IS_CD_PORT(unit, pport)) {
   6175     rv = portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &local_port_ability);
   6176     }
   6177     PORT_UNLOCK(unit);
   6178     
   6179     PORTMOD_IF_ERROR_RETURN(rv);
   6180 
   6181 #if 0
   6182     /* If MII supported, enable it, otherwise use TBI */
   6183     if (local_port_ability.interface & (SOC_PA_INTF_MII | SOC_PA_INTF_GMII |
   6184                               SOC_PA_INTF_SGMII | SOC_PA_INTF_XGMII)) {
   6185         if (IS_GE_PORT(unit, port)) {
   6186             pif = SOC_PORT_IF_GMII;
   6187         } else if (IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port)) {
   6188             if (local_port_ability.interface & SOC_PA_INTF_XGMII) {
   6189                 pif = SOC_PORT_IF_XGMII;
   6190             } else { /*  external GbE phy in xe port mode */
   6191                 pif = SOC_PORT_IF_SGMII;
   6192             }
   6193         } else {
   6194             pif = SOC_PORT_IF_MII;
   6195         }
   6196     } else if (local_port_ability.interface & SOC_PA_INTF_CGMII) {
   6197         pif = SOC_PORT_IF_CGMII;
   6198     } else {
   6199         pif = SOC_PORT_IF_TBI;
   6200     }
   6201 
   6202     SOC_IF_ERROR_RETURN
   6203         (soc_phyctrl_interface_set(unit, port, pif)); 
   6204     _bcm_esw_portctrl_interface_config_set(unit, port, pport, config, 0);
   6205 #endif
   6206 
   6207     if (IS_ST_PORT(unit, port)) {
   6208 
   6209         /* Since stacking port doesn't support flow control,
   6210          * make sure that PHY is not advertising flow control capabilities.
   6211          */
   6212 
   6213         PORT_LOCK(unit);
   6214         rv = portmod_port_ability_advert_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &advert_port_ability);
   6215         if (PORTMOD_SUCCESS(rv)) {
   6216             advert_port_ability.pause &= ~(SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM);
   6217             rv = portmod_port_ability_advert_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY,
   6218                                                  &advert_port_ability);
   6219         }
   6220         PORT_UNLOCK(unit);
   6221     }
   6222     
   6223     PORTMOD_IF_ERROR_RETURN(rv);
   6224 
   6225     if (!SOC_WARM_BOOT(unit) &&
   6226         !(SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit, all), port)) ) {
   6227 #ifdef BCM_RCPU_SUPPORT
   6228         if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) {
   6229             /* Do not enable/disable rcpu port. */
   6230             return BCM_E_NONE;
   6231         }
   6232 #endif /* BCM_RCPU_SUPPORT */
   6233         PORT_LOCK(unit);
   6234         rv = _bcm_esw_portctrl_enable_set(unit, port, pport,
   6235                                           PORTMOD_PORT_ENABLE_MAC, enable); 
   6236         PORT_UNLOCK(unit);
   6237         BCM_IF_ERROR_RETURN(rv);
   6238     }
   6239 
   6240     return BCM_E_NONE;
   6241 #else /* PORTMOD_SUPPORT */
   6242         return BCM_E_UNAVAIL;
   6243 #endif /* PORTMOD_SUPPORT */
   6244 }
   6245 
   6246 
   6247 /*
   6248  * Function:
   6249  *      bcmi_esw_portctrl_clear_rx_lss_status_get
   6250  * Purpose:
   6251  *      get the local and remote fault fields of the lss status register.
   6252  * Parameters:
   6253  *      unit         - (IN) Unit number.
   6254  *      port         - (IN) Port number.
   6255  *      local_fault  - (OUT) value of local fault field to get.
   6256  *      remote_fault - (OUT) value of remote fault field to get.
   6257  * Returns:
   6258  *      BCM_E_NONE
   6259  *      BCM_E_XXX
   6260  */
   6261 
   6262 int
   6263 bcmi_esw_portctrl_clear_rx_lss_status_get(int unit, bcm_gport_t port,
   6264                                           int *local_fault,
   6265                                           int *remote_fault)
   6266 {
   6267 #ifdef PORTMOD_SUPPORT
   6268     int rv = BCM_E_NONE;
   6269     portctrl_pport_t  pport;
   6270 
   6271     PORTCTRL_INIT_CHECK(unit);
   6272 
   6273     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6274 
   6275     PORT_LOCK(unit);
   6276     rv = portmod_port_clear_rx_lss_status_get(unit, pport, local_fault,
   6277                                               remote_fault);
   6278     PORT_UNLOCK(unit);
   6279     return rv;
   6280 #else  /* PORTMOD_SUPPORT */
   6281     return BCM_E_UNAVAIL;
   6282 #endif /* PORTMOD_SUPPORT */
   6283 }
   6284 
   6285 /*
   6286  * Function:
   6287  *      _bcm_esw_portctrl_detach
   6288  * Purpose:
   6289  *      Main part of bcm_port_detach
   6290  */
   6291 
   6292 #ifdef PORTMOD_SUPPORT
   6293 STATIC int
   6294 _bcm_esw_portctrl_detach(int unit, pbmp_t pbmp, pbmp_t *detached)
   6295 {
   6296     soc_port_t port;
   6297     portctrl_pport_t pport;
   6298     soc_persist_t *sop = SOC_PERSIST(unit); 
   6299     int rv;
   6300     int flags = 0;
   6301     portmod_port_add_info_t port_add_info;
   6302     int num_lanes;
   6303     int lane;
   6304 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT)
   6305     int phy_port;
   6306     int lanes_per_pm;
   6307     int pm;
   6308     portmod_dispatch_type_t pm_type;
   6309     portmod_pm_capability_t pm_cap;
   6310 #endif
   6311 
   6312     PORTMOD_PORT_ENABLE_PHY_SET(flags);
   6313     PORTMOD_PORT_ENABLE_MAC_SET(flags);
   6314 
   6315     SOC_PBMP_CLEAR(*detached);
   6316 
   6317     SOC_PBMP_ITER(pbmp, port) {
   6318 
   6319         BCM_IF_ERROR_RETURN
   6320             (bcm_esw_port_stp_set(unit, port, BCM_STG_STP_DISABLE));
   6321         rv = bcmi_esw_portctrl_mode_setup(unit, port, FALSE);
   6322         BCM_IF_ERROR_RETURN(rv);
   6323 
   6324         BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6325         BCM_IF_ERROR_RETURN
   6326             (_bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0));
   6327         PORTMOD_IF_ERROR_RETURN(portmod_port_remove(unit, port));
   6328 
   6329         PORTMOD_IF_ERROR_RETURN(portmod_port_add_info_t_init(unit, &port_add_info));
   6330         port_add_info.interface_config.interface = SOC_PORT_IF_NULL;
   6331         PORTMOD_IF_ERROR_RETURN(portmod_port_add(unit, port, &port_add_info));
   6332 
   6333         SOC_PBMP_PORT_ADD(*detached, port);
   6334 
   6335         if (SOC_PBMP_MEMBER(sop->lc_pbm_fc, port)) {
   6336             /* Bring down the internal PHY */
   6337             rv = bcm_esw_port_update(unit, port, FALSE);
   6338             BCM_IF_ERROR_RETURN(rv);
   6339             SOC_PBMP_PORT_REMOVE(sop->lc_pbm_fc, port);
   6340         }
   6341 
   6342 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT)
   6343         if (IS_CD_PORT(unit, port)) {
   6344             soc_counter_port_pbmp_remove(unit, port);
   6345 
   6346             phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   6347             BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type));
   6348             PORTMOD_IF_ERROR_RETURN(
   6349                 portmod_pm_capability_get(unit, pm_type, &pm_cap));
   6350             lanes_per_pm = pm_cap.pm_capability.pm8x50_cap.num_lanes;
   6351             pm = (phy_port - 1) / lanes_per_pm;
   6352             SOC_INFO(unit).pm_vco_info[pm].is_tvco_new = 1;
   6353             SOC_INFO(unit).pm_vco_info[pm].is_ovco_new = 1;
   6354             SOC_IF_ERROR_RETURN(
   6355                     soc_esw_portctrl_pm_vco_reconfigure(unit));
   6356         }
   6357 #endif
   6358 
   6359         /*
   6360          * Detach xphy lanes from the port.
   6361          */
   6362         num_lanes = SOC_INFO(unit).port_num_lanes[port];
   6363         /*
   6364          * Need to change to 12 because not pm12x10 mode are consecutive lanes.
   6365          * Only 442 is, other like 343 and 244 skip 1 and 2 lanes in the middle.
   6366          */
   6367         if (num_lanes == 10) {
   6368             num_lanes=12;
   6369         }
   6370         for (lane = 0; lane < num_lanes; lane++) {
   6371 #ifdef BCM_TOMAHAWK3_SUPPORT
   6372             /* Tomahawk 3's Management Port Macro requires a spacing between
   6373              * the lanes, so even though the two management ports' physical
   6374              * ports are 257 and 258, the lane needs to be the next one,
   6375              * so logical port 118 being mapped to physical port 258 needs
   6376              * to pass 259 to portmod because portmod only recognizes lane
   6377              * 0 (physical port 257) and lane 2 (physial port 259).
   6378              */
   6379             if (SOC_IS_TOMAHAWK3(unit) && port == 118) {
   6380                 portmod_xphy_lane_detach(unit, 259, 1); 
   6381             }
   6382             else
   6383 #endif
   6384             {
   6385                 portmod_xphy_lane_detach(unit,
   6386                         SOC_INFO(unit).port_l2p_mapping[port]+lane, 1);
   6387             }
   6388         }
   6389     }
   6390 
   6391     return BCM_E_NONE;
   6392 }
   6393 #endif /* PORTMOD_SUPPORT */
   6394 
   6395 /*
   6396  * Function:
   6397  *      bcmi_esw_portctrl_detach
   6398  * Purpose:
   6399  *      Detach a port.  Set phy driver to no connection.
   6400  * Parameters:
   6401  *      unit - StrataSwitch unit number.
   6402  *      pbmp - Bitmap of ports to detach.
   6403  *      detached (OUT) - Bitmap of ports successfully detached.
   6404  * Returns:
   6405  *      BCM_E_NONE
   6406  *      BCM_E_INTERNAL - internal error.
   6407  * Notes:
   6408  *      If a port to be detached does not appear in detached, its
   6409  *      state is not defined.
   6410  */
   6411 
   6412 int
   6413 bcmi_esw_portctrl_detach(int unit, pbmp_t pbmp, pbmp_t *detached)
   6414 {
   6415 #ifdef PORTMOD_SUPPORT
   6416     char pfmtp[SOC_PBMP_FMT_LEN],
   6417          pfmtd[SOC_PBMP_FMT_LEN];
   6418     int rv = BCM_E_NONE;
   6419 
   6420     PORTCTRL_INIT_CHECK(unit);
   6421 
   6422     PORT_LOCK(unit);
   6423 
   6424     rv = _bcm_esw_portctrl_detach(unit, pbmp, detached);
   6425 
   6426     PORT_UNLOCK(unit);
   6427 
   6428     LOG_INFO(BSL_LS_BCM_PORT,
   6429              (BSL_META_U(unit,
   6430              "bcm_port_detach: u=%d pbmp=%s det=%s rv=%d\n"),
   6431              unit,
   6432              SOC_PBMP_FMT(pbmp, pfmtp),
   6433              SOC_PBMP_FMT(*detached, pfmtd),
   6434              rv));
   6435 
   6436     return rv;
   6437 #else /* PORTMOD_SUPPORT */
   6438         return BCM_E_UNAVAIL;
   6439 #endif /* PORTMOD_SUPPORT */
   6440 }
   6441 
   6442 /*
   6443  * Function:
   6444  *      bcmi_esw_portctrl_frame_max_get
   6445  * Purpose:
   6446  *      Get the maximum receive frame size for the port.
   6447  * Parameters:
   6448  *      unit   - (IN) Unit number.
   6449  *      port   - (IN) Port number.
   6450  *      size   - (OUT) Maximum frame size in bytes.
   6451  * Returns:
   6452  *      BCM_E_XXX
   6453  * Notes:
   6454  *      Depending on chip or port type the actual maximum receive frame size
   6455  *      might be slightly higher.
   6456  *
   6457  *      For GE ports that use 2 separate MACs (one for GE and another one for
   6458  *      10/100 modes) the function returns the maximum rx frame size set for
   6459  *      the current mode.
   6460  */
   6461 int
   6462 bcmi_esw_portctrl_frame_max_get(int unit, bcm_gport_t port, int *size)
   6463 {
   6464 #ifdef PORTMOD_SUPPORT
   6465     int rv;
   6466     portctrl_pport_t pport;
   6467 
   6468     PORTCTRL_INIT_CHECK(unit);
   6469 
   6470     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6471 
   6472     PORT_LOCK(unit);
   6473     rv = soc_esw_portctrl_frame_max_get(unit, port, size);
   6474     PORT_UNLOCK(unit);
   6475 
   6476     return rv;
   6477 #else  /* PORTMOD_SUPPORT */
   6478     return BCM_E_UNAVAIL;
   6479 #endif /* PORTMOD_SUPPORT */
   6480 }
   6481 
   6482 /*
   6483  * Function:
   6484  *      bcmi_esw_portctrl_ifg_set
   6485  * Purpose:
   6486  *      Set Inter Frame Gap 
   6487  * Parameters:
   6488  *      unit - StrataSwitch unit number.
   6489  *      port - Port.
   6490  *      speed  - Speed
   6491  *      duplex  - Duplex Setting
   6492  *      ifg  -   InterFrame Gap
   6493  * Returns:
   6494  *      BCM_E_NONE
   6495  *      BCM_E_INTERNAL - internal error.
   6496  * Notes:
   6497  */
   6498 int
   6499 bcmi_esw_portctrl_ifg_set(int unit, bcm_gport_t port, int speed, 
   6500                           bcm_port_duplex_t duplex, int ifg)
   6501 {
   6502 #ifdef PORTMOD_SUPPORT
   6503     int rv;
   6504     portctrl_pport_t pport;
   6505 
   6506     PORTCTRL_INIT_CHECK(unit);
   6507 
   6508     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6509 
   6510     PORT_LOCK(unit); 
   6511     rv = soc_esw_portctrl_ifg_set(unit, port, speed, duplex, ifg);
   6512     PORT_UNLOCK(unit);
   6513 
   6514     return rv;
   6515 #else /* PORTMOD_SUPPORT */
   6516     return BCM_E_UNAVAIL;
   6517 #endif /* PORTMOD_SUPPORT */
   6518 }
   6519 
   6520 /*
   6521  * Function:
   6522  *      bcmi_esw_portctrl_frame_max_set
   6523  * Purpose:
   6524  *      Set the maximum receive frame size for the port.
   6525 
   6526  * Parameters:
   6527  *      unit   - (IN) Unit number.
   6528  *      port   - (IN) Port number.
   6529  *      mac    - (IN) Station MAC address used for pause frames.
   6530  * Returns:
   6531  *      BCM_E_XXX
   6532  */
   6533 int
   6534 bcmi_esw_portctrl_frame_max_set(int unit, bcm_gport_t port, int size)
   6535 {
   6536 #ifdef PORTMOD_SUPPORT
   6537     int rv;
   6538     portctrl_pport_t pport;
   6539 
   6540     PORTCTRL_INIT_CHECK(unit);
   6541 
   6542     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6543 
   6544     PORT_LOCK(unit);
   6545     rv = soc_esw_portctrl_frame_max_set(unit, port, size);
   6546     PORT_UNLOCK(unit);
   6547 
   6548     return rv;
   6549 
   6550 #else  /* PORTMOD_SUPPORT */
   6551     return BCM_E_UNAVAIL;
   6552 #endif /* PORTMOD_SUPPORT */
   6553 }
   6554 
   6555 /*
   6556  * Function:
   6557  *      bcmi_esw_portctrl_ifg_get
   6558  * Purpose:
   6559  *      Set Inter Frame Gap 
   6560  * Parameters:
   6561  *      unit - StrataSwitch unit number.
   6562  *      port - Port.
   6563  *      speed  - Speed
   6564  *      duplex  - Duplex Setting
   6565  *      ifg  -   InterFrame Gap
   6566  * Returns:
   6567  *      BCM_E_NONE
   6568  *      BCM_E_INTERNAL - internal error.
   6569  * Notes:
   6570  */
   6571 int
   6572 bcmi_esw_portctrl_ifg_get(int unit, bcm_gport_t port, int speed, 
   6573                           bcm_port_duplex_t duplex, int *ifg)
   6574 {
   6575 #ifdef PORTMOD_SUPPORT
   6576     int rv;
   6577     portctrl_pport_t pport;
   6578   
   6579     PORTCTRL_INIT_CHECK(unit);
   6580 
   6581     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6582 
   6583     PORT_LOCK(unit);
   6584     rv = soc_esw_portctrl_ifg_get(unit, port, speed, duplex, ifg);
   6585     PORT_UNLOCK(unit);
   6586 
   6587     return rv;
   6588 #else /* PORTMOD_SUPPORT */
   6589     return BCM_E_UNAVAIL;
   6590 #endif /* PORTMOD_SUPPORT */
   6591 }
   6592 
   6593 /*
   6594  * Function:
   6595  *      bcmi_esw_portctrl_mac_rx_control
   6596  * Purpose:
   6597  *      Set Inter Frame Gap 
   6598  * Parameters:
   6599  *      unit - StrataSwitch unit number.
   6600  *      port - Port.
   6601  *      optype  - operation type
   6602  *      enable  - enable/disable
   6603  * Returns:
   6604  *      BCM_E_NONE
   6605  *      BCM_E_INTERNAL - internal error.
   6606  * Notes:
   6607  */
   6608 
   6609 int
   6610 bcmi_esw_portctrl_mac_rx_control(int unit, bcm_port_t port, uint8 optype, int *enable)
   6611 {
   6612 #ifdef PORTMOD_SUPPORT
   6613     int rv = BCM_E_NONE;
   6614 
   6615     PORT_LOCK(unit);
   6616     if(optype) {
   6617         rv = portmod_port_rx_mac_enable_get(unit, port, enable); 
   6618     } else {
   6619         rv = portmod_port_rx_mac_enable_set(unit, port, *enable);
   6620     }
   6621     PORT_UNLOCK(unit);
   6622     return(rv);
   6623 #else /* PORTMOD_SUPPORT */
   6624     return BCM_E_UNAVAIL;
   6625 #endif /* PORTMOD_SUPPORT */
   6626 }
   6627 
   6628 /*
   6629  * Function:
   6630  *      bcmi_esw_portctrl_mac_up
   6631  * Purpose:
   6632  *      Bring up MAC 
   6633  * Parameters:
   6634  *      unit  - (IN) StrataSwitch unit number.
   6635  *      nport - (IN) Number of elements in array port
   6636  *      port  - (IN) Array of logical port.
   6637  * Returns:
   6638  *      BCM_E_NONE
   6639  *      BCM_E_INTERNAL - internal error.
   6640  * Notes:
   6641  */
   6642 int
   6643 bcmi_esw_portctrl_mac_up(int unit, int nport, bcm_port_t *port)
   6644 {
   6645 #ifdef PORTMOD_SUPPORT
   6646     int i;
   6647     bcm_port_t lport;
   6648     portctrl_pport_t pport;
   6649 
   6650     for (i = 0; i < nport; i++) {
   6651         lport = port[i];
   6652 
   6653         BCM_IF_ERROR_RETURN
   6654             (PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport));
   6655 
   6656         /* Remove MAC reset */
   6657         BCM_IF_ERROR_RETURN
   6658             (portmod_port_mac_reset_set(unit, pport, 0));
   6659 
   6660         /* Disable port flush state */
   6661         BCM_IF_ERROR_RETURN
   6662             (portmod_port_discard_set(unit, pport, 0) );
   6663 
   6664         /* Enable MAC TX */
   6665         BCM_IF_ERROR_RETURN
   6666             (portmod_port_rx_mac_enable_set(unit, pport, 1));
   6667 
   6668         /* Enable MAC RX */
   6669         BCM_IF_ERROR_RETURN
   6670             (portmod_port_tx_mac_enable_set(unit, pport, 1));
   6671     }
   6672     return BCM_E_NONE;
   6673 #else /* PORTMOD_SUPPORT */
   6674     return BCM_E_UNAVAIL;
   6675 #endif /* PORTMOD_SUPPORT */
   6676 }
   6677 
   6678 /*
   6679  * Function:
   6680  *      bcmi_esw_portctrl_mac_rx_down
   6681  * Purpose:
   6682  *      Disable MAC receive 
   6683  * Parameters:
   6684  *      unit  - (IN) StrataSwitch unit number.
   6685  *      nport - (IN) Number of elements in array port
   6686  *      port  - (IN) Array of logical port.
   6687  * Returns:
   6688  *      BCM_E_NONE
   6689  *      BCM_E_INTERNAL - internal error.
   6690  * Notes:
   6691  */
   6692 int
   6693 bcmi_esw_portctrl_mac_rx_down(int unit, int nport, bcm_port_t *port)
   6694 {
   6695 #ifdef PORTMOD_SUPPORT
   6696     int i;
   6697     bcm_port_t lport;
   6698     portctrl_pport_t pport;
   6699     portmod_pfc_control_t pfc_control;
   6700 
   6701     for (i = 0; i < nport; i++) {
   6702         lport = port[i];
   6703 
   6704         BCM_IF_ERROR_RETURN
   6705             (PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport));
   6706 
   6707         /* Disable MAC RX */
   6708         BCM_IF_ERROR_RETURN
   6709             (portmod_port_rx_mac_enable_set(unit, pport, 0));
   6710 
   6711         /* TH3 will not suffer from overflow like other devices,
   6712          * but putting the mac into reset will prevent packets
   6713          * from being drained, so only set discard */
   6714         if (!SOC_IS_TOMAHAWK3(unit)) {
   6715             /* Hold MAC in reset state */
   6716             BCM_IF_ERROR_RETURN
   6717                 (portmod_port_mac_reset_set(unit, pport, 1));
   6718         }
   6719 
   6720         /* Put port in flush state */
   6721         BCM_IF_ERROR_RETURN
   6722             (portmod_port_discard_set(unit, pport, 1) );
   6723 
   6724         if (!SOC_IS_TOMAHAWK3(unit)) {
   6725             /* Remove MAC reset */
   6726             BCM_IF_ERROR_RETURN
   6727                 (portmod_port_mac_reset_set(unit, pport, 0));
   6728         }
   6729 
   6730         /* WAR for SDK-183541/TH3-5475*/
   6731         if (SOC_IS_TOMAHAWK3(unit)) {
   6732             if (soc_feature(unit, soc_feature_priority_flow_control)) {
   6733                 /* Toggle Force PFC XON */
   6734                 BCM_IF_ERROR_RETURN
   6735                     (portmod_port_pfc_control_get(unit, pport, &pfc_control));
   6736                 pfc_control.force_xon = 1;
   6737                 BCM_IF_ERROR_RETURN
   6738                     (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   6739                 pfc_control.force_xon = 0;
   6740                 BCM_IF_ERROR_RETURN
   6741                     (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   6742             }
   6743         }
   6744 
   6745     }
   6746     return BCM_E_NONE;
   6747 #else /* PORTMOD_SUPPORT */
   6748     return BCM_E_UNAVAIL;
   6749 #endif /* PORTMOD_SUPPORT */
   6750 }
   6751 
   6752 /*
   6753  * Function:
   6754  *      bcmi_esw_portctrl_mac_tx_down
   6755  * Purpose:
   6756  *      Poll until MAC TX FIFO is empty
   6757  *      Disable MAC transmit 
   6758  * Parameters:
   6759  *      unit  - (IN) StrataSwitch unit number.
   6760  *      nport - (IN) Number of elements in array port
   6761  *      port  - (IN) Array of logical port.
   6762  * Returns:
   6763  *      BCM_E_NONE
   6764  *      BCM_E_INTERNAL - internal error.
   6765  * Notes:
   6766  */
   6767 int
   6768 bcmi_esw_portctrl_mac_tx_down(int unit, int nport, bcm_port_t *port)
   6769 {
   6770 #ifdef PORTMOD_SUPPORT
   6771     int i;
   6772     bcm_port_t lport;
   6773     portctrl_pport_t pport;
   6774 
   6775     for (i = 0; i < nport; i++) {
   6776         lport = port[i];
   6777 
   6778         BCM_IF_ERROR_RETURN
   6779             (PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport));
   6780         if (!SOC_IS_TOMAHAWK3(unit)) {
   6781         /* Drain MAC TX FIFO cells */
   6782         BCM_IF_ERROR_RETURN
   6783             (_bcm_esw_portctrl_drain_cells(unit, pport, lport));
   6784         }
   6785 
   6786         /* MAC TX disable */
   6787         BCM_IF_ERROR_RETURN
   6788             (portmod_port_tx_mac_enable_set(unit, pport, 0));
   6789 
   6790         /* Hold MAC in reset state */
   6791         BCM_IF_ERROR_RETURN
   6792             (portmod_port_mac_reset_set(unit, pport, 1));
   6793 
   6794     }
   6795     return BCM_E_NONE;
   6796 #else /* PORTMOD_SUPPORT */
   6797     return BCM_E_UNAVAIL;
   6798 #endif /* PORTMOD_SUPPORT */
   6799 }
   6800 
   6801 /*
   6802  * Function:
   6803  *      bcmi_esw_portctrl_encap_get
   6804  * Purpose:
   6805  *      Get the port encapsulation mode
   6806  * Parameters:
   6807  *      unit - StrataSwitch unit #
   6808  *      port - StrataSwitch port #
   6809  *      mode (OUT) - One of BCM_PORT_ENCAP_xxx (see port.h)
   6810  * Returns:
   6811  *      BCM_E_XXX
   6812  */
   6813 
   6814 int
   6815 bcmi_esw_portctrl_encap_get(int unit, bcm_gport_t port, int *mode)
   6816 {
   6817 #ifdef PORTMOD_SUPPORT
   6818     int rv = BCM_E_NONE, flags=0, valid = 0;
   6819     portctrl_pport_t pport;
   6820     portmod_port_interface_config_t port_if_cfg;
   6821 
   6822     /* Make sure port module is initialized. */
   6823     PORTCTRL_INIT_CHECK(unit);
   6824 
   6825     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   6826 
   6827     BCM_IF_ERROR_RETURN(portmod_port_is_valid(unit, pport, &valid));
   6828     if (!valid) {
   6829         return BCM_E_PORT;
   6830     }
   6831 
   6832     if ((IS_GE_PORT(unit, port) && IS_ST_PORT(unit, port)) ||
   6833         IS_CD_PORT(unit, port)) {
   6834         if (soc_feature(unit, soc_feature_embedded_higig)) {
   6835             *mode = BCM_PORT_ENCAP_IEEE;
   6836         } else {
   6837             portmod_encap_t val;
   6838 
   6839             PORT_LOCK(unit);
   6840             rv = portmod_port_encap_get(unit, pport, &flags, &val);
   6841             PORT_UNLOCK(unit);
   6842 
   6843             if (PORTMOD_SUCCESS(rv)) {
   6844                 *mode = val ? BCM_PORT_ENCAP_HIGIG2 : BCM_PORT_ENCAP_IEEE;
   6845             } else {
   6846                 return (BCM_E_CONFIG);
   6847             }
   6848         }
   6849     } else {
   6850         portmod_port_interface_config_t_init(unit, &port_if_cfg);
   6851 
   6852         PORT_LOCK(unit);
   6853         rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   6854         PORT_UNLOCK(unit);
   6855 
   6856         if (PORTMOD_SUCCESS(rv)) {
   6857             *mode = port_if_cfg.encap_mode;
   6858         }
   6859     }
   6860 
   6861     LOG_INFO(BSL_LS_BCM_PORT,
   6862              (BSL_META_UP(unit, port,
   6863               "Port encap get: u=%d p=%d mode=%d rv=%d\n"),
   6864               unit, port, *mode, rv));
   6865 
   6866     return rv;
   6867 #else  /* PORTMOD_SUPPORT */
   6868     return BCM_E_UNAVAIL;
   6869 #endif /* PORTMOD_SUPPORT */
   6870 }
   6871  
   6872 #ifdef PORTMOD_SUPPORT
   6873 /*
   6874  * Function:
   6875  *      _bcm_esw_portctrl_interface_cfg_set
   6876  * Purpose:
   6877  *      This function is called by encap set functions to set encap mode,
   6878  *      interface type and speed
   6879  * Parameters:
   6880  *      unit        - (IN) Unit number
   6881  *      port        - (IN) Logical BCM Port number (non-GPORT).
   6882  *      pport       - (IN) Portmod Port number
   6883  *      field       - (IN) Field of portmod_port_interface_config_t to modify
   6884  *                         Only encap_mode, speed and interface can be 
   6885  *                         modified
   6886  *      field_val   - Value of the Portmod field to program
   6887  * Returns:
   6888  *      BCM_E_XXX
   6889  */
   6890 STATIC
   6891 int _bcm_esw_portctrl_interface_cfg_set(int unit, bcm_port_t port,
   6892                                         portctrl_pport_t pport,
   6893                                         int field, void *field_val)
   6894 {
   6895     portmod_port_interface_config_t port_if_cfg;
   6896     soc_port_if_t                   default_interface;
   6897     char *str;
   6898     int rv = BCM_E_NONE;
   6899 
   6900     portmod_port_interface_config_t_init(unit, &port_if_cfg);
   6901 
   6902     PORT_LOCK(unit);
   6903 
   6904     rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY);
   6905 
   6906     if ((port_if_cfg.encap_mode == SOC_ENCAP_HIGIG2) ||
   6907         (port_if_cfg.encap_mode == SOC_ENCAP_HIGIG)) {
   6908         PHYMOD_INTF_MODES_HIGIG_SET(&port_if_cfg);
   6909     } else {
   6910         PHYMOD_INTF_MODES_HIGIG_CLR(&port_if_cfg);
   6911     }
   6912 
   6913     if (PORTMOD_SUCCESS(rv)) {
   6914 
   6915         /* Set value of appropriate field */
   6916         switch (field) {
   6917             case BCM_ESW_PORTCTRL_CFG_ENCAP_MODE:
   6918                 if (port_if_cfg.encap_mode != *((portmod_encap_t *)field_val)) {
   6919                     port_if_cfg.encap_mode = *((portmod_encap_t *)field_val);
   6920 
   6921                     /* need to update the port mode since encap is changed */
   6922                     if ((port_if_cfg.encap_mode == SOC_ENCAP_HIGIG2) ||
   6923                         (port_if_cfg.encap_mode == SOC_ENCAP_HIGIG)) {
   6924                         PHYMOD_INTF_MODES_HIGIG_SET(&port_if_cfg);
   6925                     } else {
   6926                         PHYMOD_INTF_MODES_HIGIG_CLR(&port_if_cfg);
   6927                     }
   6928 
   6929                     /* When changing the encap, the existing interface type of the
   6930                      * port may not be valid anymore. Need to retrieve the default
   6931                      * interface type based on the new encap mode and update 
   6932                      * port_if_cfg.
   6933                      */
   6934                     default_interface = SOC_PORT_IF_NULL;
   6935                     rv = portmod_port_default_interface_get(
   6936                             unit, port, &port_if_cfg, &default_interface);
   6937                     if(SOC_FAILURE(rv)) {
   6938                         PORT_UNLOCK(unit);
   6939                         return rv;
   6940                     }
   6941                     if (default_interface != SOC_PORT_IF_NULL) {
   6942                         port_if_cfg.interface = default_interface;
   6943                     } else {
   6944                         rv = portmod_common_default_interface_get(&port_if_cfg);
   6945                         if(SOC_FAILURE(rv)) {
   6946                             PORT_UNLOCK(unit);
   6947                             return rv;
   6948                         }
   6949                     } 
   6950                 }
   6951                 break;
   6952 
   6953             case BCM_ESW_PORTCTRL_CFG_INTERFACE:
   6954                 port_if_cfg.interface = *((soc_port_if_t *)field_val);
   6955                 break;
   6956 
   6957             case BCM_ESW_PORTCTRL_CFG_SPEED:
   6958                 port_if_cfg.speed = *((int *)field_val);
   6959                 break;
   6960 
   6961             default:
   6962                 PORT_UNLOCK(unit);
   6963                 return BCM_E_PARAM;
   6964         }
   6965 
   6966         
   6967         if (port_if_cfg.speed == 0) {
   6968             port_if_cfg.speed = SOC_CONTROL(unit)->info.port_speed_max[port];
   6969         }
   6970         
   6971         rv = _bcm_esw_portctrl_interface_config_set(unit, port, pport,
   6972                                                     &port_if_cfg, 0);
   6973         PORT_UNLOCK(unit);
   6974 
   6975         if (PORTMOD_FAILURE(rv)) {
   6976             str = "set";
   6977         }
   6978     } else {
   6979         PORT_UNLOCK(unit);
   6980         str = "get";
   6981     }
   6982 
   6983     if (PORTMOD_FAILURE(rv)) {
   6984         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6985                     (BSL_META_U(unit, 
   6986                     "Interface_%s failed:err=%d: %s\n"), str, rv,
   6987                     bcm_errmsg(rv)));
   6988 
   6989         rv = BCM_E_CONFIG; /* Returning BCM_ error code */
   6990     }
   6991 
   6992     return rv;
   6993 }
   6994 #endif /* PORTMOD_SUPPORT */
   6995 
   6996 /*
   6997  * Function:
   6998  *      bcmi_esw_portctrl_encap_xport_set
   6999  * Purpose:
   7000  *      Convert Ether port to Higig port or Cpri, or reverse
   7001  * Parameters:
   7002  *      unit   - (IN) Unit number.
   7003  *      port   - (IN) Port number.
   7004  *      mode   - (IN) Encapsulation mode
   7005  * Returns:
   7006  *      BCM_E_XXX
   7007  * Notes:
   7008  *      Must be called with PORT_LOCK held.
   7009  */
   7010 
   7011 int
   7012 bcmi_esw_portctrl_encap_xport_set(int unit, bcm_gport_t port, int mode)
   7013 {
   7014 #ifdef PORTMOD_SUPPORT
   7015     int rv = BCM_E_NONE;
   7016     portctrl_pport_t pport;
   7017     bcm_stg_t        stg;
   7018     int              to_higig = 0;
   7019     soc_field_t      port_type_field;
   7020     soc_reg_t        egr_port_reg;
   7021     soc_port_ability_t ability;
   7022     soc_port_mode_t  non_ieee_speed;
   7023     int              force_speed, port_type, higig_type;
   7024     phymod_autoneg_control_t an_info;
   7025     bcm_port_abil_t ability_mask=0;
   7026     soc_mem_t ing_port_mem = PORT_TABm;
   7027 
   7028 
   7029     /* Make sure port module is initialized. */
   7030     PORTCTRL_INIT_CHECK(unit);
   7031 
   7032     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   7033     if ( mode != BCM_PORT_ENCAP_IEEE && mode != BCM_PORT_ENCAP_CPRI) {
   7034          to_higig = 1;
   7035     }
   7036 
   7037 
   7038     port_type_field = PORT_TYPEf;
   7039 
   7040     rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport,
   7041                                              BCM_ESW_PORTCTRL_CFG_ENCAP_MODE,
   7042                                              (void *)&mode);
   7043     if (BCM_FAILURE(rv)) {
   7044         return rv;
   7045     }
   7046    
   7047 #if 0
   7048     if (to_higig) {
   7049         soc_port_if_t port_intf;
   7050 
   7051         port_intf = SOC_PORT_IF_XGMII;
   7052         rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport,
   7053                                                  BCM_ESW_PORTCTRL_CFG_INTERFACE,
   7054                                                  (void *)&port_intf);
   7055         if (BCM_FAILURE(rv)) {
   7056             return rv;
   7057         }
   7058     }
   7059 #endif 
   7060 
   7061     /* Specific for GH on avoiding port speed change */
   7062     if (!soc_feature(unit, soc_feature_hg_no_speed_change)) {
   7063         BCM_IF_ERROR_RETURN(bcm_esw_port_ability_local_get(unit, port,
   7064                             &ability));
   7065 
   7066         non_ieee_speed = ability.speed_full_duplex &
   7067                 ~(SOC_PA_SPEED_100GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_10GB |
   7068                   SOC_PA_SPEED_2500MB | SOC_PA_SPEED_1000MB |
   7069                   SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB);
   7070 
   7071         BCM_IF_ERROR_RETURN(bcm_esw_port_ability_advert_get(unit, port,
   7072                             &ability));
   7073         SOC_IF_ERROR_RETURN(soc_esw_portctrl_speed_get(unit, port,
   7074                                                        &force_speed));
   7075         if (to_higig) {
   7076             ability.speed_full_duplex |= non_ieee_speed;
   7077             ability.pause &= ~(SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM);
   7078             force_speed = force_speed == 0 ?
   7079                           SOC_CONTROL(unit)->info.port_speed_max[port] :
   7080                           force_speed;
   7081             ability.speed_full_duplex |= SOC_PA_SPEED(force_speed);
   7082         } else {
   7083             ability.speed_full_duplex &= ~non_ieee_speed;
   7084             force_speed = SOC_PORTCTRL_HG2_TO_IEEE_BW_GET(force_speed);
   7085         }
   7086 
   7087         BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_ability_advert_set(unit, port,
   7088                                                                  &ability,
   7089                                                                  ability_mask));
   7090 
   7091         phymod_autoneg_control_t_init(&an_info);
   7092         
   7093         PORT_LOCK(unit);
   7094         rv = portmod_port_autoneg_get(
   7095                 unit, port, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an_info);
   7096         PORT_UNLOCK(unit);
   7097         if (BCM_FAILURE(rv)) {
   7098             return rv;
   7099         }
   7100 
   7101         /* Some mac driver re-init phy while executing MAC_ENCAP_SET, in that
   7102          * case autoneg is probably always true here
   7103          */
   7104         if (an_info.enable) {
   7105             SOC_IF_ERROR_RETURN(bcm_esw_port_autoneg_set(unit, port, TRUE));
   7106         } else {
   7107             rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport,
   7108                                                      BCM_ESW_PORTCTRL_CFG_SPEED,
   7109                                                      (void *)&force_speed);
   7110             if (BCM_FAILURE(rv)) {
   7111                 return rv;
   7112             }
   7113         }
   7114     }
   7115 
   7116     /* Now we propagate the changes */
   7117     port_type = to_higig ? 1 : 0;
   7118 
   7119     if (port_type == 1) {
   7120         if (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) {
   7121             higig_type = BCM_PORT_HG_TYPE_HGOE_TRANSPORT;
   7122         } else if (mode == BCM_PORT_ENCAP_HIGIG) {
   7123             higig_type = BCM_PORT_HG_TYPE_HIGIGPLUS;
   7124         } else {
   7125             higig_type = BCM_PORT_HG_TYPE_HIGIG2_NORMAL;
   7126         }
   7127     } else {
   7128         higig_type =  0;
   7129     }
   7130 
   7131     if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) {
   7132         ing_port_mem = ING_DEVICE_PORTm;
   7133     }
   7134     if (soc_mem_field_valid(unit, ing_port_mem, port_type_field)) {
   7135         SOC_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port,
   7136                             _BCM_CPU_TABS_NONE, port_type_field, port_type));
   7137     }
   7138 
   7139     if (SOC_MEM_IS_VALID(unit, EGR_PORTm)) {
   7140         if (soc_mem_field_valid(unit, EGR_PORTm, port_type_field)) {
   7141             BCM_IF_ERROR_RETURN(_bcm_esw_egr_port_tab_set(unit, port,
   7142                                 port_type_field, port_type));
   7143         }
   7144         if(soc_mem_field_valid(unit, EGR_PORTm, HG_TYPEf)) {
   7145             SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_PORTm, port,
   7146                                 HG_TYPEf, higig_type));
   7147         }
   7148     } else {
   7149         if (SOC_REG_IS_VALID(unit, EGR_PORT_64r)) {
   7150             egr_port_reg = EGR_PORT_64r;
   7151         } else {
   7152             egr_port_reg = EGR_PORTr;
   7153         }
   7154         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, egr_port_reg, port,
   7155                             port_type_field, port_type));
   7156     }
   7157 
   7158     if (!IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit, port) && !IS_RDB_PORT(unit, port)) {
   7159         if (SOC_MEM_IS_VALID(unit, EGR_ING_PORTm)) {
   7160             SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_ING_PORTm,
   7161                                 port, PORT_TYPEf, port_type));
   7162         }
   7163         if(SOC_MEM_FIELD_VALID(unit, EGR_ING_PORTm, HG_TYPEf)) {
   7164             SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_ING_PORTm,
   7165                                 port, HG_TYPEf, higig_type));
   7166         }
   7167     }
   7168 
   7169     
   7170     if (SOC_MEM_IS_VALID(unit, ICONTROL_OPCODE_BITMAPm)) {
   7171         icontrol_opcode_bitmap_entry_t entry;
   7172         soc_pbmp_t pbmp;
   7173 
   7174         SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY,
   7175                             port, &entry));
   7176         SOC_PBMP_CLEAR(pbmp);
   7177         if (to_higig) {
   7178             SOC_PBMP_PORT_SET(pbmp, CMIC_PORT(unit));
   7179         }
   7180         soc_mem_pbmp_field_set(unit, ICONTROL_OPCODE_BITMAPm, &entry, BITMAPf,
   7181                                &pbmp);
   7182         SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY,
   7183                                                           port, &entry));
   7184     } else {
   7185 
   7186         /* Set HG ingress CPU Opcode map to the CPU */
   7187         /* int pbm_len; */
   7188         uint32 cpu_pbm = 0;
   7189 
   7190         if (to_higig) {
   7191             SOC_IF_ERROR_RETURN(soc_xgs3_port_to_higig_bitmap(unit,
   7192                                 CMIC_PORT(unit), &cpu_pbm));
   7193         } /* else, cpu_pbm = 0 */
   7194 
   7195         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   7196                             ICONTROL_OPCODE_BITMAPr, port, BITMAPf, cpu_pbm));
   7197     }
   7198 
   7199     if (to_higig) {
   7200         /* Embedded Higig ports should be configured and marked as ST ports */
   7201         BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_pause_set(unit, port, 0, 0));
   7202         /* HG ports to forwarding */
   7203         BCM_IF_ERROR_RETURN(bcm_esw_port_stp_set(unit, port,
   7204                                                  BCM_STG_STP_FORWARD));
   7205     } else { 
   7206         BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_pause_set(unit, port, 1, 1));
   7207     }
   7208 
   7209 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7210     /*
   7211      * Higig ports need the MIRROR_CONTROL.M_ENABLE=1 in order to respond to
   7212      * the mirror bit in the Higig headers.
   7213      */
   7214     if (to_higig) {
   7215         BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, TRUE));
   7216     }
   7217 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7218 
   7219     /* Clear mirror enable settings */
   7220     /* coverity[stack_use_callee] */
   7221     /* coverity[stack_use_overflow] */
   7222     BCM_IF_ERROR_RETURN(bcm_esw_mirror_port_set(unit, port, -1, -1, 0));
   7223 
   7224     /* Set untagged state in default VLAN properly */
   7225     BCM_IF_ERROR_RETURN(_bcm_esw_vlan_untag_update(unit, port, to_higig));
   7226 
   7227     /* Resolve STG 0 */
   7228     BCM_IF_ERROR_RETURN(bcm_esw_stg_default_get(unit, &stg));
   7229     BCM_IF_ERROR_RETURN(bcm_esw_stg_stp_set(unit, 0, port,
   7230                         to_higig ? BCM_STG_STP_FORWARD : BCM_STG_STP_DISABLE));
   7231 
   7232 #ifdef BCM_TRX_SUPPORT
   7233     /* Reset the vlan default action */
   7234     if (soc_feature(unit, soc_feature_vlan_action) && (!SOC_IS_TRIDENT3X(unit))) {
   7235         bcm_vlan_action_set_t action;
   7236 
   7237         BCM_IF_ERROR_RETURN(_bcm_trx_vlan_port_egress_default_action_get(unit,
   7238                             port, &action));
   7239         /* Backward compatible defaults */
   7240         if (to_higig) {
   7241             action.ot_outer = bcmVlanActionDelete;
   7242             action.dt_outer = bcmVlanActionDelete;
   7243         } else {
   7244             action.ot_outer = bcmVlanActionNone;
   7245             action.dt_outer = bcmVlanActionNone;
   7246         }
   7247         BCM_IF_ERROR_RETURN(_bcm_trx_vlan_port_egress_default_action_set(unit,
   7248                             port, &action));
   7249     }
   7250 #endif
   7251 
   7252 #ifdef INCLUDE_L3
   7253     if ((soc_feature(unit, soc_feature_ip_mcast)) &&
   7254         (!soc_feature(unit, soc_feature_no_egr_ipmc_cfg))) {
   7255         BCM_IF_ERROR_RETURN(bcm_esw_ipmc_egress_port_set(
   7256                 unit, port, 
   7257                 to_higig ? _soc_mac_all_ones :_soc_mac_all_zeroes, 
   7258                 0, 0, 0));
   7259     }
   7260 #endif /* INCLUDE_L3 */
   7261 
   7262     return rv;
   7263 
   7264 #else  /* PORTMOD_SUPPORT */
   7265     return BCM_E_UNAVAIL;
   7266 #endif /* PORTMOD_SUPPORT */
   7267 }
   7268 
   7269 /*
   7270  * Function:
   7271  *      bcmi_esw_portctrl_encap_higig_lite_set
   7272  * Purpose:
   7273  *      Helper function to force a port into HIGIG2_LITE mode
   7274  * Parameters:
   7275  *      unit            - (IN) device id
   7276  *      port            - (IN) port number
   7277  * Returns:
   7278  *      BCM_E_XXX
   7279  */
   7280 int
   7281 bcmi_esw_portctrl_encap_higig_lite_set(int unit, bcm_gport_t port)
   7282 {
   7283 #ifdef PORTMOD_SUPPORT
   7284     portctrl_pport_t  pport;
   7285     portmod_port_ability_t  ability;
   7286     phymod_autoneg_control_t an_info;
   7287     int rv;
   7288 
   7289     PORTCTRL_INIT_CHECK(unit);
   7290 
   7291     sal_memset(&ability, 0, sizeof(soc_port_ability_t));
   7292     sal_memset(&an_info, 0, sizeof(phymod_autoneg_control_t));
   7293 
   7294     if (soc_feature(unit, soc_feature_hg_no_speed_change)) {
   7295         /* HG-Lite process without 2.5G speed setting can calls to
   7296          * bcmi_esw_portctrl_encap_xport_set() directly.
   7297          */
   7298         return bcmi_esw_portctrl_encap_xport_set(unit, port,
   7299                                                  BCM_PORT_ENCAP_HIGIG2_LITE);
   7300     }
   7301 
   7302     if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) {
   7303 
   7304         BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port,
   7305                             &pport));
   7306 
   7307         /* Restrict the speed to <= 2.5G and set the encap to HG2 */
   7308         BCM_IF_ERROR_RETURN(portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY,
   7309                             &ability));
   7310 
   7311         ability.speed_full_duplex &= ~(SOC_PA_SPEED_10GB |
   7312                 SOC_PA_SPEED_12GB | SOC_PA_SPEED_13GB | SOC_PA_SPEED_15GB |
   7313                 SOC_PA_SPEED_16GB | SOC_PA_SPEED_20GB | SOC_PA_SPEED_21GB |
   7314                 SOC_PA_SPEED_25GB | SOC_PA_SPEED_30GB | SOC_PA_SPEED_40GB);
   7315 
   7316         BCM_IF_ERROR_RETURN(portmod_port_ability_advert_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY,
   7317                             &ability));
   7318         BCM_IF_ERROR_RETURN(portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY,
   7319                             &an_info));
   7320 
   7321         if (!an_info.enable) {
   7322             int speed;
   7323 
   7324             speed = 2500;
   7325             rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport,
   7326                                                      BCM_ESW_PORTCTRL_CFG_SPEED,
   7327                                                      (void *)&speed);
   7328 
   7329             if (BCM_FAILURE(rv)) {
   7330                 return rv;
   7331             }
   7332         }
   7333 
   7334         return bcmi_esw_portctrl_encap_xport_set(unit, port,
   7335                                                  BCM_PORT_ENCAP_HIGIG2);
   7336     } else if (IS_ST_PORT(unit, port) || IS_E_PORT(unit, port)) {
   7337 
   7338         return _bcm_port_encap_stport_set(unit, port, BCM_PORT_ENCAP_HIGIG2);
   7339     }
   7340 
   7341     return BCM_E_CONFIG;
   7342 #else   /* PORTMOD_SUPPORT */
   7343     return BCM_E_UNAVAIL;
   7344 #endif  /* PORTMOD_SUPPORT */
   7345 }
   7346 
   7347 /*
   7348  * Function:
   7349  *      bcmi_esw_portctrl_higig_mode_set
   7350  * Purpose:
   7351  *      Set port Higig mode
   7352  * Parameters:
   7353  *      unit - StrataSwitch unit #
   7354  *      port - StrataSwitch port #
   7355  *      higig_mode - Higig mode
   7356  * Returns:
   7357  *      BCM_E_XXX
   7358  */
   7359 int
   7360 bcmi_esw_portctrl_higig_mode_set(int unit, bcm_gport_t port, int higig_mode)
   7361 {
   7362 #ifdef PORTMOD_SUPPORT
   7363     int rv;
   7364     portctrl_pport_t pport;
   7365 
   7366     PORTCTRL_INIT_CHECK(unit);
   7367 
   7368     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port,
   7369                                               &pport));
   7370 
   7371     PORT_LOCK(unit);
   7372     rv = portmod_port_higig_mode_set(unit, pport, higig_mode);
   7373     PORT_UNLOCK(unit);
   7374 
   7375     return rv;
   7376 #else   /* PORTMOD_SUPPORT */
   7377     return BCM_E_UNAVAIL;
   7378 #endif  /* PORTMOD_SUPPORT */
   7379 }
   7380 /*
   7381  * Function:
   7382  *      bcmi_esw_portctrl_higig2_mode_set
   7383  * Purpose:
   7384  *      Set port Higig2 mode
   7385  * Parameters:
   7386  *      unit - StrataSwitch unit #
   7387  *      port - StrataSwitch port #
   7388  *      higig2_mode - Higig2 mode
   7389  * Returns:
   7390  *      BCM_E_XXX
   7391  */
   7392 int
   7393 bcmi_esw_portctrl_higig2_mode_set(int unit, bcm_gport_t port, int higig2_mode)
   7394 {
   7395 #ifdef PORTMOD_SUPPORT
   7396     soc_reg_t egr_port_reg;
   7397     soc_mem_t egr_port_mem;
   7398     int rv;
   7399     portctrl_pport_t pport;
   7400     int port_hg2_mode = higig2_mode;
   7401 
   7402     PORTCTRL_INIT_CHECK(unit);
   7403 
   7404     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port,
   7405                                               &pport));
   7406 
   7407     if (soc_mem_field_valid(unit, PORT_TABm, HIGIG2f) ||
   7408         soc_mem_field_valid(unit, LPORT_TABm, HIGIG2f)) {
   7409     BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port,
   7410                         _BCM_CPU_TABS_NONE, HIGIG2f, higig2_mode));
   7411     }
   7412 
   7413     if (SOC_IS_TRIDENT3X(unit)) {
   7414         if (higig2_mode) {
   7415             BCM_IF_ERROR_RETURN(
   7416                 _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   7417                 PORT_TYPEf, 1));
   7418         }
   7419     }
   7420 
   7421     if (SOC_REG_IS_VALID(unit, EGR_PORT_64r)) {
   7422         egr_port_reg = EGR_PORT_64r;
   7423     } else {
   7424         egr_port_reg = EGR_PORTr;
   7425     }
   7426 
   7427     if (SOC_REG_FIELD_VALID(unit, egr_port_reg, HIGIG2f)) {
   7428         BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, egr_port_reg, port,
   7429                                                    HIGIG2f, higig2_mode));
   7430     } else if (SOC_MEM_FIELD_VALID(unit, EGR_PORTm, HIGIG2f)) {
   7431         BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_PORTm, port,
   7432                                                    HIGIG2f, higig2_mode));
   7433     }
   7434 
   7435     PORT_LOCK(unit);
   7436     rv = portmod_port_higig2_mode_set(unit, pport, port_hg2_mode);
   7437     PORT_UNLOCK(unit);
   7438 
   7439     if (PORTMOD_FAILURE(rv)) {
   7440         return rv;
   7441     }
   7442 
   7443     egr_port_mem = EGR_ING_PORTm;
   7444     if (SOC_MEM_FIELD_VALID(unit, egr_port_mem, HIGIG2f)) {
   7445         if (IS_CPU_PORT(unit, port)) {
   7446             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, egr_port_mem,
   7447                                 SOC_INFO(unit).cpu_hg_index, HIGIG2f,
   7448                                 higig2_mode));
   7449         } else {
   7450             BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, egr_port_mem,
   7451                                                        port, HIGIG2f,
   7452                                                        higig2_mode));
   7453         }
   7454     }
   7455 
   7456     return BCM_E_NONE;
   7457 #else   /* PORTMOD_SUPPORT */
   7458     return BCM_E_UNAVAIL;
   7459 #endif  /* PORTMOD_SUPPORT */
   7460 }
   7461 
   7462 #ifdef PORTMOD_SUPPORT
   7463 /*
   7464  * Function:
   7465  *      bcmi_esw_portctrl_encap_set_execute
   7466  * Purpose:
   7467  *      Set the port encapsulation mode
   7468  * Parameters:
   7469  *      unit - StrataSwitch unit #
   7470  *      port - StrataSwitch port #
   7471  *      mode - One of BCM_PORT_ENCAP_xxx (see port.h)
   7472  *      force - TRUE  : force encap operation(set xport_swap = TRUE)
   7473  *                      regardless of IS_HG_PORT and mode value.
   7474  *
   7475  * Returns:
   7476  *      BCM_E_XXX
   7477  */
   7478 int
   7479 bcmi_esw_portctrl_encap_set_execute(int unit, bcm_gport_t port, int mode, int force)
   7480 {
   7481     int         rv, xport_swap = FALSE;
   7482     uint64      val64;
   7483     portctrl_pport_t pport;
   7484     int to_higig;
   7485     int size;
   7486 
   7487     PORTCTRL_INIT_CHECK(unit);
   7488 
   7489     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   7490 
   7491     LOG_INFO(BSL_LS_BCM_PORT,
   7492              (BSL_META_UP(unit, port,
   7493              "bcm_esw_port_encap_set: u=%d p=%d mode=%d\n"),
   7494               unit, port, mode));
   7495 
   7496     if ((soc_feature(unit, soc_feature_roe)) && ((mode == BCM_PORT_ENCAP_CPRI) || (mode == BCM_PORT_ENCAP_RSVD4))) {
   7497        return portmod_port_encap_set(unit, pport, 0, BCM_PORT_ENCAP_CPRI);
   7498     }
   7499 
   7500     _bcm_esw_port_mirror_lock(unit);
   7501 
   7502     if (force) {
   7503         xport_swap = TRUE;
   7504     }
   7505 
   7506     if ((IS_HG_PORT(unit,port) && (mode == BCM_PORT_ENCAP_IEEE ||
   7507          (SOC_IS_MONTEREY(unit) && mode == BCM_PORT_ENCAP_CPRI))) ||
   7508         ((IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) ||
   7509           IS_C_PORT(unit, port)) &&
   7510          (mode != BCM_PORT_ENCAP_IEEE))) {
   7511         if (mode == BCM_PORT_ENCAP_CPRI) {
   7512             return portmod_port_encap_set(unit, pport, 0, mode);
   7513         }
   7514 
   7515         if (soc_feature(unit, soc_feature_xport_convertible)) {
   7516             xport_swap = TRUE;
   7517         } else {
   7518             /* Ether <=> Higig not allowed on all systems */
   7519             _bcm_esw_port_mirror_unlock(unit);
   7520             return BCM_E_UNAVAIL;
   7521         }
   7522     }
   7523 
   7524     if ((mode == BCM_PORT_ENCAP_HIGIG)
   7525         && soc_feature(unit, soc_feature_no_higig_plus)) {
   7526         _bcm_esw_port_mirror_unlock(unit);
   7527         return BCM_E_UNAVAIL;
   7528     }
   7529 
   7530     if (xport_swap) {
   7531         COUNTER_LOCK(unit);
   7532         if ((BCM_PORT_ENCAP_HIGIG2_LITE == mode)) {
   7533             rv = bcmi_esw_portctrl_encap_higig_lite_set(unit, port);
   7534         } else {
   7535             rv = bcmi_esw_portctrl_encap_xport_set(unit, port, mode);
   7536         }
   7537         
   7538         COUNTER_UNLOCK(unit);
   7539         if (PORTMOD_FAILURE(rv)) {
   7540             _bcm_esw_port_mirror_unlock(unit);
   7541             return rv;
   7542         }
   7543     } else if (IS_HG_PORT(unit, port)) {
   7544 
   7545         rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport,
   7546                                                 BCM_ESW_PORTCTRL_CFG_ENCAP_MODE,
   7547                                                 (void *)&mode);
   7548             if (BCM_FAILURE(rv)) {
   7549                 _bcm_esw_port_mirror_unlock(unit);
   7550                 return rv;
   7551             }
   7552     } else if (IS_GE_PORT(unit, port) && IS_ST_PORT(unit, port)) {
   7553         if (mode == BCM_PORT_ENCAP_IEEE) {
   7554             bcm_port_encap_config_t encap_config;
   7555 
   7556             rv = bcm_esw_port_encap_config_get(unit, port,
   7557                                                &encap_config);
   7558             if (BCM_SUCCESS(rv)) {
   7559                 if ((BCM_PORT_ENCAP_HIGIG2_L2 == encap_config.encap) ||
   7560                     (BCM_PORT_ENCAP_HIGIG2_IP_GRE == encap_config.encap) ||
   7561                     (BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET == encap_config.encap) ||
   7562                     (BCM_PORT_ENCAP_HIGIG2_LITE == encap_config.encap)) {
   7563                     rv = _bcm_port_encap_stport_set(unit, port,
   7564                                                     BCM_PORT_ENCAP_IEEE);
   7565                 } else {
   7566                     rv = BCM_E_UNAVAIL;
   7567                 }
   7568             }
   7569         } else {
   7570             if ((mode == BCM_PORT_ENCAP_HIGIG2) ||
   7571                 (mode == BCM_PORT_ENCAP_HIGIG2_LITE)) {
   7572                 rv = BCM_E_NONE;
   7573             } else {
   7574                 rv = BCM_E_UNAVAIL;
   7575             }
   7576         }
   7577     } else if (IS_CE_PORT(unit, port) || IS_C_PORT(unit, port)) {
   7578          if ((mode == BCM_PORT_ENCAP_HIGIG2) ||
   7579              (mode == BCM_PORT_ENCAP_HIGIG) ||
   7580              (mode == BCM_PORT_ENCAP_IEEE)) {
   7581              rv = _bcm_port_encap_stport_set(unit, port, mode);
   7582          } else {
   7583              rv = BCM_E_UNAVAIL;
   7584          }
   7585     } else if (mode == BCM_PORT_ENCAP_IEEE) {
   7586         rv = BCM_E_NONE;
   7587     } else {
   7588         rv = BCM_E_UNAVAIL;
   7589     }
   7590 
   7591 #ifdef BCM_GXPORT_SUPPORT
   7592     if (IS_GX_PORT(unit, port) || IS_XG_PORT(unit,port) || 
   7593         IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port) ||
   7594         IS_CE_PORT(unit, port) || IS_C_PORT(unit, port)) {
   7595         int hg2 = FALSE;
   7596 
   7597         if (mode == BCM_PORT_ENCAP_HIGIG2 ||
   7598             mode == BCM_PORT_ENCAP_HIGIG2_LITE) {
   7599             hg2 = TRUE;
   7600         }
   7601 
   7602         if (BCM_SUCCESS(rv)) {
   7603             rv = bcmi_esw_portctrl_higig2_mode_set(unit, port, hg2);
   7604         }
   7605 
   7606         if (BCM_SUCCESS(rv)) {
   7607             /* No need for locking; _bcm_esw_port_mirror_lock does it */
   7608             uint32 port_hg_mode = (mode == BCM_PORT_ENCAP_IEEE) ? 0 : 1;
   7609 
   7610             rv = portmod_port_higig_mode_set(unit, pport, port_hg_mode);
   7611         }
   7612 
   7613         if (PORTMOD_SUCCESS(rv)) {
   7614             if (SOC_MEM_IS_VALID(unit, EGR_PORTm)) {
   7615                 rv = soc_mem_field32_modify(unit, EGR_PORTm, port,
   7616                                             PORT_TYPEf,
   7617                                             mode == BCM_PORT_ENCAP_IEEE ?
   7618                                             0 : 1);
   7619             }
   7620         }
   7621     }
   7622 #endif /* BCM_GXPORT_SUPPORT */
   7623 
   7624     if (soc_feature(unit, soc_feature_embedded_higig)) {
   7625         /* Clear embedded Higig regs, if present */
   7626         soc_reg_t   ehg_tx_reg = EHG_TX_CONTROLr;
   7627         soc_reg_t   ehg_rx_reg = EHG_RX_CONTROLr;
   7628 
   7629         if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, ehg_tx_reg)) {
   7630             rv = soc_reg32_set(unit, ehg_tx_reg, port, 0, 0);
   7631         }
   7632         if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, ehg_rx_reg)) {
   7633             rv = soc_reg32_set(unit, ehg_rx_reg, port, 0, 0);
   7634         }
   7635     }
   7636 
   7637     if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_higig_over_ethernet)) {
   7638         /* Disable HGoE if needed*/
   7639 
   7640         uint32 tab_port_type;
   7641         uint32 tab_higig_type;
   7642 
   7643         tab_port_type =  (mode == BCM_PORT_ENCAP_IEEE) ? 0 : 1;
   7644 
   7645         if (tab_port_type == 1) {
   7646             if (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) {
   7647                 tab_higig_type = BCM_PORT_HG_TYPE_HGOE_TRANSPORT;
   7648             } else if (mode == BCM_PORT_ENCAP_HIGIG) {
   7649                 tab_higig_type = BCM_PORT_HG_TYPE_HIGIGPLUS;
   7650             } else {
   7651                 tab_higig_type = BCM_PORT_HG_TYPE_HIGIG2_NORMAL;
   7652             }
   7653         } else {
   7654             tab_higig_type = 0;
   7655         }
   7656 
   7657         if(SOC_REG_IS_VALID(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r)) {
   7658             uint64 field64;
   7659             uint32 tmp32;
   7660             tmp32 = (BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET == mode);
   7661             COMPILER_64_SET(field64, 0, tmp32);
   7662             if (SOC_FAILURE(soc_reg_get(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r,
   7663                             port, 0, &val64))) {
   7664                 _bcm_esw_port_mirror_unlock(unit);
   7665                 return rv;
   7666             }
   7667             soc_reg64_field_set(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r,
   7668                                 &val64, TRANSPORT_ENf,
   7669                                 field64);
   7670             rv = soc_reg_set(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r, port, 0,
   7671                              val64);
   7672         }
   7673         if (BCM_SUCCESS(rv) &&
   7674             SOC_MEM_FIELD_VALID(unit, EGR_PORTm, PORT_TYPEf)) {
   7675             rv = soc_mem_field32_modify(unit, EGR_PORTm, port, PORT_TYPEf, tab_port_type);
   7676         }
   7677         if (BCM_SUCCESS(rv) && SOC_MEM_FIELD_VALID(unit, EGR_PORTm, HG_TYPEf)) {
   7678             rv = soc_mem_field32_modify(unit, EGR_PORTm, port,
   7679                                         HG_TYPEf, tab_higig_type);
   7680         }
   7681         if (BCM_SUCCESS(rv) &&
   7682             SOC_MEM_FIELD_VALID(unit, EGR_ING_PORTm, PORT_TYPEf)) {
   7683             rv = soc_mem_field32_modify(unit, EGR_ING_PORTm, port, PORT_TYPEf, tab_port_type);
   7684 
   7685         }
   7686         if (BCM_SUCCESS(rv) &&
   7687             SOC_MEM_FIELD_VALID(unit, EGR_ING_PORTm, HG_TYPEf)) {
   7688             rv = soc_mem_field32_modify(unit, EGR_ING_PORTm, port,
   7689                                         HG_TYPEf, tab_higig_type);
   7690         }
   7691 
   7692         if (BCM_SUCCESS(rv) &&
   7693             SOC_MEM_FIELD_VALID(unit, PORT_TABm, PORT_TYPEf)) {
   7694             rv = _bcm_esw_port_tab_set(unit, port,
   7695                                        _BCM_CPU_TABS_NONE, PORT_TYPEf, tab_port_type);
   7696 
   7697         }
   7698         if (BCM_SUCCESS(rv) && SOC_MEM_FIELD_VALID(unit, PORT_TABm, HG_TYPEf)) {
   7699 
   7700             rv = _bcm_esw_port_tab_set(unit, port,
   7701                                        _BCM_CPU_TABS_NONE, HG_TYPEf, tab_higig_type); 
   7702         }
   7703 #ifdef BCM_TRX_SUPPORT
   7704         /* Reset the vlan default action, if not done already */
   7705         if (xport_swap == FALSE) {
   7706             if (soc_feature(unit, soc_feature_vlan_action)) {
   7707                 bcm_vlan_action_set_t action;
   7708 
   7709                 if (BCM_FAILURE(_bcm_trx_vlan_port_egress_default_action_get(
   7710                                     unit, port, &action))) {
   7711                     _bcm_esw_port_mirror_unlock(unit);
   7712                     return rv;
   7713                 }
   7714                 /* Backward compatible defaults */
   7715                 if (((mode == BCM_PORT_ENCAP_HIGIG) ||
   7716                     (mode == BCM_PORT_ENCAP_HIGIG2) ||
   7717                     (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET)) &&
   7718                     (!SOC_IS_TRIDENT3X(unit))) {
   7719                     action.ot_outer = bcmVlanActionDelete;
   7720                     action.dt_outer = bcmVlanActionDelete;
   7721                 } else {
   7722                     action.ot_outer = bcmVlanActionNone;
   7723                     action.dt_outer = bcmVlanActionNone;
   7724                 }
   7725                 if (BCM_FAILURE(_bcm_trx_vlan_port_egress_default_action_set(
   7726                                     unit, port, &action))) {
   7727                     _bcm_esw_port_mirror_unlock(unit);
   7728                     return rv;
   7729                 }
   7730             }
   7731         }
   7732 #endif
   7733     }
   7734 
   7735     /* Update cached version of HiGig2 encapsulation */
   7736     if (BCM_SUCCESS(rv)) {
   7737         if (mode == BCM_PORT_ENCAP_HIGIG2 ||
   7738             mode == BCM_PORT_ENCAP_HIGIG2_LITE) {
   7739             SOC_HG2_ENABLED_PORT_ADD(unit, port);
   7740         } else {
   7741             SOC_HG2_ENABLED_PORT_REMOVE(unit, port);
   7742         }
   7743     }
   7744 
   7745     size = SOC_INFO(unit).max_mtu;
   7746     if ((mode == BCM_PORT_ENCAP_IEEE) ||
   7747         (mode == BCM_PORT_ENCAP_CPRI) ||
   7748         (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) ||
   7749         (mode == BCM_PORT_ENCAP_HIGIG2_L2) ||
   7750         (mode == BCM_PORT_ENCAP_HIGIG2_IP_GRE)) {
   7751         to_higig = 0;
   7752         size -= 4;
   7753     } else {
   7754         to_higig = 1;
   7755     }
   7756 
   7757     if (BCM_SUCCESS(rv)) {
   7758         soc_xport_type_update(unit, port, to_higig);
   7759         rv = bcmi_esw_portctrl_frame_max_set(unit, port, size);
   7760     }
   7761 
   7762     _bcm_esw_port_mirror_unlock(unit);
   7763 
   7764     return rv;
   7765 }
   7766 #endif  /* PORTMOD_SUPPORT */
   7767 
   7768 /*
   7769  * Function:
   7770  *      bcmi_portctrl_encap_set
   7771  * Purpose:
   7772  *      Set the port encapsulation mode
   7773  * Parameters:
   7774  *      unit - StrataSwitch unit #
   7775  *      port - StrataSwitch port #
   7776  *      mode - One of BCM_PORT_ENCAP_xxx (see port.h)
   7777  *      force - TRUE  : force encap operation(set xport_swap = TRUE)
   7778  *                      regardless of IS_HG_PORT and mode value.
   7779  *
   7780  * Returns:
   7781  *      BCM_E_XXX
   7782  */
   7783 int
   7784 bcmi_esw_portctrl_encap_set(int unit, bcm_gport_t port, int mode, int force)
   7785 {
   7786 #ifdef PORTMOD_SUPPORT
   7787     int pport;
   7788     bcm_port_ability_t port_ability;
   7789 
   7790     PORTCTRL_INIT_CHECK(unit);
   7791 
   7792     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   7793 
   7794     BCM_IF_ERROR_RETURN(
   7795         bcmi_esw_portctrl_ability_get(unit, port, &port_ability, NULL));
   7796 
   7797     if (!((port_ability.encap) & BCM_PA_ENCAP(mode))) {
   7798         LOG_VERBOSE(BSL_LS_BCM_PORT,
   7799                     (BSL_META_UP(unit, port,
   7800                                 "Encap mode %d not supported on port %d\n"),
   7801                     mode, port));
   7802         return BCM_E_UNAVAIL;
   7803     }
   7804 
   7805     BCM_IF_ERROR_RETURN(
   7806         bcmi_esw_portctrl_encap_set_execute(unit, port, mode, force));
   7807 
   7808     return BCM_E_NONE;
   7809 #else   /* PORTMOD_SUPPORT */
   7810     return BCM_E_UNAVAIL;
   7811 #endif  /* PORTMOD_SUPPORT */
   7812 }
   7813 
   7814 /*
   7815  * Function:
   7816 *      bcmi_esw_portctrl_llfc_get
   7817  * Purpose:
   7818  *      
   7819  * Parameters:
   7820  *      unit - StrataSwitch unit number.
   7821  *      port - Port.
   7822  *      type - Command Type  
   7823  *      value  - Value  
   7824  * Returns:
   7825  *      BCM_E_NONE
   7826  *      BCM_E_INTERNAL - internal error.
   7827  * Notes:
   7828  */
   7829 
   7830 int
   7831 bcmi_esw_portctrl_llfc_get(int unit, bcm_gport_t port, bcm_port_control_t type, int *value)
   7832 {
   7833 #ifdef PORTMOD_SUPPORT
   7834     int rv = BCM_E_UNAVAIL;
   7835     portmod_llfc_control_t control;
   7836 
   7837     PORT_LOCK(unit);
   7838     switch(type) {
   7839     case bcmPortControlLLFCReceive:
   7840     case bcmPortControlSAFCReceive:
   7841 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7842         if (SOC_IS_XGS3_SWITCH(unit)) {
   7843             if (!SOC_PORT_VALID(unit, port)) {
   7844                 PORT_UNLOCK(unit);
   7845                 return BCM_E_PORT;
   7846             }
   7847             if (!IS_HG_PORT(unit, port)) {
   7848                 PORT_UNLOCK(unit);
   7849                 return BCM_E_UNAVAIL;
   7850             }
   7851             rv = portmod_port_llfc_control_get(unit, port, &control);
   7852             *value = control.rx_enable;
   7853         }
   7854 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7855         break;
   7856     case bcmPortControlLLFCTransmit:
   7857     case bcmPortControlSAFCTransmit:
   7858 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7859         if (SOC_IS_XGS3_SWITCH(unit)) {
   7860             if (!SOC_PORT_VALID(unit, port)) {
   7861                 PORT_UNLOCK(unit);
   7862                 return BCM_E_PORT;
   7863             }
   7864             if (!IS_HG_PORT(unit, port)) {
   7865                 PORT_UNLOCK(unit);
   7866                 return BCM_E_UNAVAIL;
   7867             }
   7868             rv = portmod_port_llfc_control_get(unit, port, &control);
   7869             *value = control.tx_enable;
   7870         }
   7871 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7872         break;
   7873     default:
   7874         break;
   7875     }
   7876     PORT_UNLOCK(unit);
   7877     return(rv);
   7878 #else /* PORTMOD_SUPPORT */
   7879     return BCM_E_UNAVAIL;
   7880 #endif /* PORTMOD_SUPPORT */
   7881 }
   7882 
   7883 
   7884 /*
   7885  * Function:
   7886  *      bcmi_esw_portctrl_llfc_set
   7887  * Purpose:
   7888  *      
   7889  * Parameters:
   7890  *      unit - StrataSwitch unit number.
   7891  *      port - Port.
   7892  *      type - Command Type  
   7893  *      value  - Value  
   7894  */
   7895 int
   7896 bcmi_esw_portctrl_llfc_set(int unit, bcm_port_t port, bcm_port_control_t type, int value)
   7897 {
   7898 #ifdef PORTMOD_SUPPORT
   7899     int rv = BCM_E_UNAVAIL;
   7900     soc_reg_t port_config;
   7901     int llfc_enable = 0;
   7902     portmod_llfc_control_t control;
   7903 #if defined(BCM_APACHE_SUPPORT)
   7904     uint32 rval;
   7905 #endif
   7906 
   7907     switch(type) {
   7908     case bcmPortControlLLFCReceive:
   7909     case bcmPortControlSAFCReceive:
   7910 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7911         if (SOC_IS_XGS3_SWITCH(unit)) {
   7912 
   7913             if (!SOC_PORT_VALID(unit, port)) {
   7914                 return BCM_E_PORT;
   7915             }
   7916             if ((!IS_HG_PORT(unit, port)) && (!IS_CPRI_PORT(unit, port))) {
   7917                 return BCM_E_UNAVAIL;
   7918             }
   7919             PORT_LOCK(unit);
   7920             rv = portmod_port_llfc_control_get(unit, port, &control);
   7921             if(PORTMOD_SUCCESS(rv)) { 
   7922                 control.rx_enable = value;
   7923                 rv =  portmod_port_llfc_control_set(unit,port, &control);
   7924                 if(PORTMOD_SUCCESS(rv)) {
   7925                     if( value == 0 ) {
   7926                         rv = portmod_port_llfc_control_get(unit, port, &control);
   7927                         if(PORTMOD_SUCCESS(rv)) {
   7928                             llfc_enable = control.rx_enable ;
   7929                         }
   7930                     } else {
   7931                         llfc_enable = TRUE;
   7932                     }
   7933                 }
   7934             }
   7935             PORT_UNLOCK(unit);
   7936             if (SOC_REG_FIELD_VALID(unit, XLPORT_CONFIGr, LLFC_ENf)) {
   7937                 port_config = XLPORT_CONFIGr;
   7938             } else if (SOC_REG_FIELD_VALID(unit, XPORT_CONFIGr, LLFC_ENf)) {
   7939                 port_config = XPORT_CONFIGr;
   7940             } else if (SOC_REG_FIELD_VALID(unit, PORT_CONFIGr, LLFC_ENf)) {
   7941                 port_config = PORT_CONFIGr;
   7942             } else {
   7943                 port_config = INVALIDr;
   7944             }
   7945 
   7946             if (port_config != INVALIDr){
   7947                 BCM_IF_ERROR_RETURN
   7948                     (soc_reg_field32_modify(unit, port_config, port, LLFC_ENf,
   7949                                             llfc_enable ? 1 : 0));
   7950             }
   7951         }
   7952 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7953         break;
   7954     case bcmPortControlLLFCTransmit:
   7955     case bcmPortControlSAFCTransmit:
   7956 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7957         if (SOC_IS_XGS3_SWITCH(unit)) {
   7958             if (!SOC_PORT_VALID(unit, port)) {
   7959                 return BCM_E_PORT;
   7960             }
   7961             if (!IS_HG_PORT(unit, port)) {
   7962                 return BCM_E_UNAVAIL;
   7963             }
   7964             PORT_LOCK(unit);
   7965             rv = portmod_port_llfc_control_get(unit, port, &control);
   7966             if(PORTMOD_SUCCESS(rv)) {
   7967                 control.tx_enable = value;
   7968                 rv =  portmod_port_llfc_control_set(unit,port, &control);
   7969                 if(PORTMOD_SUCCESS(rv)) {
   7970                     if( value == 0 ) {
   7971                         rv = portmod_port_llfc_control_get(unit, port, &control);
   7972                         if(PORTMOD_SUCCESS(rv)) {
   7973                             llfc_enable = control.tx_enable ;
   7974                         }
   7975                     } else {
   7976                         llfc_enable = TRUE;
   7977                     }
   7978                 }
   7979             }
   7980             PORT_UNLOCK(unit);
   7981             if (SOC_REG_FIELD_VALID(unit, XLPORT_CONFIGr, LLFC_ENf)) {
   7982                 port_config = XLPORT_CONFIGr;
   7983             } else if (SOC_REG_FIELD_VALID(unit, XPORT_CONFIGr, LLFC_ENf)) {
   7984                 port_config = XPORT_CONFIGr;
   7985             } else if (SOC_REG_FIELD_VALID(unit, PORT_CONFIGr, LLFC_ENf)) {
   7986                 port_config = PORT_CONFIGr;
   7987             } else {
   7988                 port_config = INVALIDr;
   7989             }
   7990 
   7991             if (port_config != INVALIDr){
   7992                 BCM_IF_ERROR_RETURN
   7993                     (soc_reg_field32_modify(unit, port_config, port, LLFC_ENf,
   7994                                             llfc_enable ? 1 : 0));
   7995             }
   7996 #if  defined(BCM_APACHE_SUPPORT)
   7997             if ( SOC_IS_APACHE(unit)) {
   7998                 SOC_IF_ERROR_RETURN
   7999                     (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
   8000                                    port, 0, &rval));
   8001 
   8002                 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8003                                   PORT_PRI_XON_ENABLEf,
   8004                                   llfc_enable ? 0xffff : 0);
   8005                 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8006                                   PORT_PAUSE_ENABLEf, llfc_enable ? 0 : 1);
   8007 
   8008                 SOC_IF_ERROR_RETURN
   8009                     (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr,
   8010                                    port, 0, rval));
   8011             }
   8012 #endif
   8013  
   8014         }
   8015 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   8016         break;
   8017     default:
   8018         break;
   8019     }
   8020     return rv;
   8021 #else /* PORTMOD_SUPPORT */
   8022     return BCM_E_UNAVAIL;
   8023 #endif /* PORTMOD_SUPPORT */
   8024 }
   8025 
   8026 /*
   8027  * Function:
   8028  *      bcmi_esw_portctrl_link_get
   8029  * Purpose:
   8030  *      Return current PHY up/down status
   8031  * Parameters:
   8032  *      unit - StrataSwitch Unit #.
   8033  *      port - StrataSwitch port #.
   8034  *      hw - If TRUE, assume hardware linkscan is active and use it
   8035  *              to reduce PHY reads.
   8036  *           If FALSE, do not use information from hardware linkscan.
   8037  *      up - (OUT) TRUE for link up, FALSE for link down.
   8038  * Returns:
   8039  *      BCM_E_NONE
   8040  *      BCM_E_XXX
   8041  */
   8042 int
   8043 bcmi_esw_portctrl_link_get(int unit, bcm_gport_t port, int hw, int *up)
   8044 {
   8045 #ifdef PORTMOD_SUPPORT
   8046     int rv;
   8047     int flags = 0;
   8048     portctrl_pport_t pport;
   8049 
   8050     /* Make sure port module is initialized. */
   8051     PORTCTRL_INIT_CHECK(unit);
   8052 
   8053     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8054 
   8055     PORT_LOCK(unit);
   8056 
   8057     if (hw) {
   8058         pbmp_t hw_linkstat;
   8059 
   8060         rv = soc_linkscan_hw_link_get(unit, &hw_linkstat);
   8061 
   8062         *up = PBMP_MEMBER(hw_linkstat, port);
   8063 
   8064         /*
   8065          * We need to confirm link down because we may receive false link
   8066          * change interrupts when hardware and software linkscan are mixed.
   8067          * Processing a false link down event is known to cause packet
   8068          * loss, which is obviously unacceptable.
   8069          */
   8070         if (!(*up)) {
   8071             rv = portmod_port_link_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, up);
   8072         }
   8073     } else {
   8074         if (SOC_IS_RCPU_ONLY(unit)) {
   8075             PORTMOD_PORT_ENABLE_MAC_SET(flags);
   8076             rv = portmod_port_enable_get(unit, pport, flags, up);
   8077         } else {
   8078             rv = portmod_port_link_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, up);
   8079         }
   8080     }
   8081 
   8082     PORT_UNLOCK(unit);
   8083 
   8084     LOG_VERBOSE(BSL_LS_BCM_PORT,
   8085                 (BSL_META_UP(unit, port,
   8086                     "Get port link status: u=%d p=%d hw=%d up=%d rv=%d\n"),
   8087                  unit, port, hw, *up, rv));
   8088 
   8089     return rv;
   8090 
   8091 #else  /* PORTMOD_SUPPORT */
   8092     return BCM_E_UNAVAIL;
   8093 #endif /* PORTMOD_SUPPORT */
   8094 }
   8095 
   8096 /*
   8097  * Function:
   8098  *      bcmi_esw_portctrl_lag_failover_disable
   8099  * Purpose:
   8100  *      Disable lag failover
   8101  *
   8102  * Parameters:
   8103  *      unit - StrataSwitch unit number.
   8104  *      port - Port.
   8105  */
   8106 int
   8107 bcmi_esw_portctrl_lag_failover_disable(int unit, bcm_gport_t port)
   8108 {
   8109 #ifdef PORTMOD_SUPPORT
   8110     int rv = BCM_E_NONE;
   8111     portctrl_pport_t  pport;
   8112 
   8113     PORTCTRL_INIT_CHECK(unit);
   8114 
   8115     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8116 
   8117     PORT_LOCK(unit);
   8118     rv = portmod_port_lag_failover_disable(unit, pport);
   8119     PORT_UNLOCK(unit);
   8120     return rv;
   8121 #else  /* PORTMOD_SUPPORT */
   8122     return BCM_E_UNAVAIL;
   8123 #endif /* PORTMOD_SUPPORT */
   8124 }
   8125 
   8126 /*
   8127  * Function:
   8128  *      bcmi_esw_portctrl_lag_failover_loopback_get
   8129  * Purpose:
   8130  *      Get lag failover loopback mode for specified port.
   8131  *
   8132  * Parameters:
   8133  *      unit - StrataSwitch unit number.
   8134  *      port - Port.
   8135  *      value  - Value
   8136  */
   8137 int
   8138 bcmi_esw_portctrl_lag_failover_loopback_get(int unit,
   8139                                             bcm_gport_t port, int* value)
   8140 {
   8141 #ifdef PORTMOD_SUPPORT
   8142     int rv = BCM_E_NONE;
   8143     portctrl_pport_t  pport;
   8144 
   8145     PORTCTRL_INIT_CHECK(unit);
   8146 
   8147     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8148 
   8149     PORT_LOCK(unit);
   8150     rv = portmod_port_lag_failover_loopback_get(unit, pport, value);
   8151     PORT_UNLOCK(unit);
   8152     return rv;
   8153 #else  /* PORTMOD_SUPPORT */
   8154     return BCM_E_UNAVAIL;
   8155 #endif /* PORTMOD_SUPPORT */
   8156 }
   8157 
   8158 /*
   8159  * Function:
   8160  *      bcmi_esw_portctrl_lag_failover_status_toggle
   8161  * Purpose:
   8162  *      Toggle lag failover status
   8163  *
   8164  * Parameters:
   8165  *      unit - StrataSwitch unit number.
   8166  *      port - Port.
   8167  */
   8168 int
   8169 bcmi_esw_portctrl_lag_failover_status_toggle(int unit, bcm_gport_t port)
   8170 {
   8171 #ifdef PORTMOD_SUPPORT
   8172     int rv = BCM_E_NONE;
   8173     portctrl_pport_t  pport;
   8174 
   8175     PORTCTRL_INIT_CHECK(unit);
   8176 
   8177     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8178 
   8179     PORT_LOCK(unit);
   8180     rv = portmod_port_lag_failover_status_toggle(unit, pport);
   8181     PORT_UNLOCK(unit);
   8182     return rv;
   8183 #else  /* PORTMOD_SUPPORT */
   8184     return BCM_E_UNAVAIL;
   8185 #endif /* PORTMOD_SUPPORT */
   8186 }
   8187 
   8188 /*
   8189  * Function:
   8190  *      bcmi_esw_portctrl_lag_remove_failover_lpbk_set
   8191  * Purpose:
   8192  *      Set lag remove failover loopback
   8193  *
   8194  * Parameters:
   8195  *      unit - StrataSwitch unit number.
   8196  *      port - Port.
   8197  */
   8198 int
   8199 bcmi_esw_portctrl_lag_remove_failover_lpbk_set(int unit,
   8200                                                bcm_gport_t port, int value)
   8201 {
   8202 #ifdef PORTMOD_SUPPORT
   8203     int rv = BCM_E_NONE;
   8204     portctrl_pport_t  pport;
   8205 
   8206     PORTCTRL_INIT_CHECK(unit);
   8207 
   8208     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8209 
   8210     PORT_LOCK(unit);
   8211     rv = portmod_port_lag_remove_failover_lpbk_set(unit, pport, value);
   8212     PORT_UNLOCK(unit);
   8213     return rv;
   8214 #else  /* PORTMOD_SUPPORT */
   8215     return BCM_E_UNAVAIL;
   8216 #endif /* PORTMOD_SUPPORT */
   8217 }
   8218 
   8219 /*
   8220  * Function:
   8221  *      bcmi_esw_portctrl_trunk_hwfailover_set
   8222  * Purpose:
   8223  *      Set trunk hwfailover
   8224  *
   8225  * Parameters:
   8226  *      unit - StrataSwitch unit number.
   8227  *      port - Port.
   8228  *      hw_count - hw count
   8229  */
   8230 int
   8231 bcmi_esw_portctrl_trunk_hwfailover_set(int unit, bcm_gport_t port, int hw_count)
   8232 {
   8233 #ifdef PORTMOD_SUPPORT
   8234     int rv = BCM_E_NONE;
   8235     portctrl_pport_t  pport;
   8236 
   8237     PORTCTRL_INIT_CHECK(unit);
   8238 
   8239     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8240 
   8241     PORT_LOCK(unit);
   8242     rv = portmod_port_trunk_hwfailover_config_set(unit, pport, hw_count);
   8243     PORT_UNLOCK(unit);
   8244     return rv;
   8245 #else  /* PORTMOD_SUPPORT */
   8246     return BCM_E_UNAVAIL;
   8247 #endif /* PORTMOD_SUPPORT */
   8248 }
   8249 
   8250 #ifdef BCM_TRIDENT2_SUPPORT
   8251 /*
   8252  * Function:
   8253  *      bcmi_esw_td2_portctrl_lanes_set
   8254  * Purpose:
   8255  *
   8256  * Parameters:
   8257  *      unit - StrataSwitch unit number.
   8258  *      port_base - Port Base.
   8259  *      lanes  - lanes
   8260  * Returns:
   8261  *      BCM_E_NONE
   8262  *      BCM_E_INTERNAL - internal error.
   8263  * Notes:
   8264  */
   8265 int
   8266 bcmi_esw_td2_portctrl_lanes_set(int unit, bcm_port_t port_base, int lanes)
   8267 {
   8268 #ifdef PORTMOD_SUPPORT
   8269     soc_info_t *si = &SOC_INFO(unit);
   8270     soc_td2_port_lanes_t lanes_ctrl;
   8271     int port, i;
   8272     int enable, okay;
   8273 
   8274     sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl));
   8275     lanes_ctrl.port_base = port_base;
   8276     lanes_ctrl.lanes = lanes;
   8277     SOC_IF_ERROR_RETURN
   8278         (soc_trident2_port_lanes_validate(unit, &lanes_ctrl));
   8279 
   8280     if(lanes_ctrl.lanes == lanes_ctrl.cur_lanes) {
   8281         return BCM_E_NONE;
   8282     }
   8283 
   8284     /* All existing ports are required to be disasbled */
   8285     SOC_IF_ERROR_RETURN(bcm_esw_port_enable_get(unit, port_base, &enable));
   8286     if (enable) {
   8287         return BCM_E_BUSY;
   8288     }
   8289     if(lanes_ctrl.lanes > lanes_ctrl.cur_lanes) { /* port(s) to be removed */
   8290         for (i = 0; i < lanes_ctrl.phy_ports_len; i++) {
   8291             port = si->port_p2l_mapping[lanes_ctrl.phy_ports[i]];
   8292             SOC_IF_ERROR_RETURN(bcm_esw_port_enable_get(unit, port, &enable));
   8293             if (enable) {
   8294                 return BCM_E_BUSY;
   8295             }
   8296         }
   8297     }
   8298     SOC_IF_ERROR_RETURN
   8299         (soc_trident2_port_lanes_set(unit, &lanes_ctrl));
   8300 
   8301     /* Probe PHY on all port(s) after conversion */
   8302     BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port_base, &okay));
   8303     BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port_base, FALSE));
   8304     if(lanes_ctrl.lanes < lanes_ctrl.cur_lanes) { /* port(s) to be added */
   8305         for (i = 0; i < lanes_ctrl.phy_ports_len; i++) {
   8306             port = si->port_p2l_mapping[lanes_ctrl.phy_ports[i]];
   8307             BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port, &okay));
   8308             BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, FALSE));
   8309         }
   8310     }
   8311 
   8312     return BCM_E_NONE;
   8313 #else /* PORTMOD_SUPPORT */
   8314     return BCM_E_UNAVAIL;
   8315 #endif /* PORTMOD_SUPPORT */
   8316 
   8317 }
   8318 #endif /* BCM_TRIDENT2_SUPPORT */
   8319 
   8320 
   8321 /*
   8322  * Function:
   8323  *      bcmi_esw_portctrl_hwfailover_enable_set
   8324  * Purpose:
   8325  *      Set front panel trunk hardware failover config.
   8326  * Parameters:
   8327  *      unit - (IN) SOC unit number. 
   8328  *      port - (IN) Port ID of the fail port.
   8329  *      enable - (IN) Set the HW failover config.
   8330  * Returns:
   8331  *      BCM_E_xxx
   8332  */
   8333 int
   8334 bcmi_esw_portctrl_hwfailover_enable_set(int unit, bcm_gport_t port, int enable)
   8335 {
   8336 #ifdef PORTMOD_SUPPORT
   8337     int rv;
   8338     portctrl_pport_t pport;
   8339 
   8340     /* Make sure port module is initialized. */
   8341     PORTCTRL_INIT_CHECK(unit);
   8342 
   8343     BCM_IF_ERROR_RETURN
   8344         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8345 
   8346     PORT_LOCK(unit);
   8347     rv = portmod_port_trunk_hwfailover_config_set(unit, pport, enable);
   8348     PORT_UNLOCK(unit);
   8349 
   8350     if (PORTMOD_FAILURE(rv)) {
   8351         LOG_VERBOSE(BSL_LS_BCM_TRUNK,
   8352                     (BSL_META_UP(unit, port,
   8353                         "Failed to set HW failover: u=%d p=%d rv=%d\n"),
   8354                     unit, port, rv));
   8355     }
   8356 
   8357     return rv;
   8358 
   8359 #else  /* PORTMOD_SUPPORT */
   8360     return BCM_E_UNAVAIL;
   8361 #endif /* PORTMOD_SUPPORT */
   8362 }
   8363 
   8364 /*
   8365  * Function:
   8366  *      bcmi_esw_portctrl_hwfailover_enable_get
   8367  * Purpose:
   8368  *      Get front-panel trunk hardware failover config.
   8369  * Parameters:
   8370  *      unit - (IN) SOC unit number. 
   8371  *      port - (IN) Port ID of the fail port.
   8372  *      enable - (OUT) Get the HW failover config.
   8373  * Returns:
   8374  *      BCM_E_xxx
   8375  */
   8376 int
   8377 bcmi_esw_portctrl_hwfailover_enable_get(int unit, bcm_gport_t port, int *enable)
   8378 {
   8379 #ifdef PORTMOD_SUPPORT
   8380     int rv;
   8381     portctrl_pport_t pport;
   8382 
   8383     /* Make sure port module is initialized. */
   8384     PORTCTRL_INIT_CHECK(unit);
   8385 
   8386     BCM_IF_ERROR_RETURN
   8387         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8388 
   8389     PORT_LOCK(unit);
   8390     rv = portmod_port_trunk_hwfailover_config_get(unit, pport, enable);
   8391     PORT_UNLOCK(unit);
   8392 
   8393     if (PORTMOD_FAILURE(rv)) {
   8394         LOG_VERBOSE(BSL_LS_BCM_TRUNK,
   8395                     (BSL_META_UP(unit, port,
   8396                         "Failed to get HW failover config: u=%d p=%d rv=%d\n"),
   8397                     unit, port, rv));
   8398     }
   8399 
   8400     return rv;
   8401 
   8402 #else  /* PORTMOD_SUPPORT */
   8403     return BCM_E_UNAVAIL;
   8404 #endif /* PORTMOD_SUPPORT */
   8405 }
   8406 
   8407 /*
   8408  * Function:
   8409  *      bcmi_esw_portctrl_hwfailover_status_get
   8410  * Purpose:
   8411  *      Get front-panel trunk hardware failover status.
   8412  * Parameters:
   8413  *      unit - (IN) SOC unit number. 
   8414  *      port - (IN) Port ID of the fail port.
   8415  *      status - (OUT) failover status.
   8416  * Returns:
   8417  *      BCM_E_xxx
   8418  */
   8419 int
   8420 bcmi_esw_portctrl_hwfailover_status_get(int unit, bcm_gport_t port, int *status)
   8421 {
   8422 #ifdef PORTMOD_SUPPORT
   8423     int rv;
   8424     portctrl_pport_t pport;
   8425 
   8426     /* Make sure port module is initialized. */
   8427     PORTCTRL_INIT_CHECK(unit);
   8428 
   8429     BCM_IF_ERROR_RETURN
   8430         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8431 
   8432     PORT_LOCK(unit);
   8433     rv = portmod_port_trunk_hwfailover_status_get(unit, pport, status);
   8434     PORT_UNLOCK(unit);
   8435 
   8436     if (PORTMOD_FAILURE(rv)) {
   8437         LOG_VERBOSE(BSL_LS_BCM_TRUNK,
   8438                     (BSL_META_UP(unit, port,
   8439                         "Failed to get HW failover status: u=%d p=%d rv=%d\n"),
   8440                     unit, port, rv));
   8441     }
   8442 
   8443     return rv;
   8444 
   8445 #else  /* PORTMOD_SUPPORT */
   8446     return BCM_E_UNAVAIL;
   8447 #endif /* PORTMOD_SUPPORT */
   8448 }
   8449 
   8450 /*
   8451  * Function:
   8452  *     bcmi_esw_portctrl_phy_control_get
   8453  * Description:
   8454  *     Set PHY specific properties
   8455  * Parameters:
   8456  *     unit        device number
   8457  *     port        port number
   8458  *     type        configuration type
   8459  *     value       value for the configuration
   8460  * Return:
   8461  *     BCM_E_XXX
   8462  */
   8463 int
   8464 bcmi_esw_portctrl_phy_control_get(int unit, bcm_gport_t port,
   8465                                   bcm_port_phy_control_t type, uint32 *value)
   8466 {
   8467 #ifdef PORTMOD_SUPPORT
   8468     int         rv;
   8469     portctrl_pport_t pport;
   8470     int phy_lane = -1;
   8471     int phyn = -1, sys_side = 0;
   8472     bcm_port_t local_port = -1;
   8473 
   8474     /* Make sure port module is initialized. */
   8475     PORTCTRL_INIT_CHECK(unit);
   8476 
   8477     BCM_IF_ERROR_RETURN
   8478         (_bcm_esw_port_gport_phyn_validate(unit, port,
   8479                                            &local_port, &phyn,
   8480                                            &phy_lane, &sys_side));
   8481 
   8482     if (local_port != -1) {
   8483         port = local_port;
   8484     }
   8485 
   8486     BCM_IF_ERROR_RETURN
   8487         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8488 
   8489     PORT_LOCK(unit);
   8490 
   8491     if (local_port == -1) {
   8492         /* Configure outermost PHY (common case) */
   8493         rv = soc_portctrl_phy_control_get(unit, pport,
   8494                                           -1, -1, 0,
   8495                                           (soc_phy_control_t) type, value);
   8496     } else {
   8497         /* Configure PHY specified by GPORT */
   8498         rv = soc_portctrl_phy_control_get(unit, pport,
   8499                                           phyn, phy_lane, sys_side,
   8500                                           (soc_phy_control_t) type, value);
   8501     }
   8502 
   8503     PORT_UNLOCK(unit);
   8504 
   8505     return rv;
   8506 
   8507 #else  /* PORTMOD_SUPPORT */
   8508     return BCM_E_UNAVAIL;
   8509 #endif /* PORTMOD_SUPPORT */
   8510 }
   8511 
   8512 /*
   8513  * Function:
   8514  *     bcmi_esw_portctrl_phy_control_set
   8515  * Description:
   8516  *     Set PHY specific properties
   8517  * Parameters:
   8518  *     unit        device number
   8519  *     port        port number
   8520  *     type        configuration type
   8521  *     value       new value for the configuration
   8522  * Return:
   8523  *     BCM_E_XXX
   8524  */
   8525 int
   8526 bcmi_esw_portctrl_phy_control_set(int unit, bcm_gport_t port,
   8527                                  bcm_port_phy_control_t type, uint32 value)
   8528 {
   8529 #ifdef PORTMOD_SUPPORT
   8530     int         rv;
   8531     portctrl_pport_t pport;
   8532     int phy_lane = -1;
   8533     int phyn = -1, sys_side = 0;
   8534     bcm_port_t local_port = -1;
   8535     _bcm_port_info_t *port_info;
   8536 
   8537     /* Make sure port module is initialized. */
   8538     PORTCTRL_INIT_CHECK(unit);
   8539 
   8540     BCM_IF_ERROR_RETURN
   8541         (_bcm_esw_port_gport_phyn_validate(unit, port,
   8542                                            &local_port, &phyn,
   8543                                            &phy_lane, &sys_side));
   8544 
   8545     if (local_port != -1) {
   8546         port = local_port;
   8547     }
   8548 
   8549     BCM_IF_ERROR_RETURN
   8550         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   8551 
   8552     PORT_LOCK(unit);
   8553 
   8554     if (local_port == -1) {
   8555         /* Configure outermost PHY (common case) */
   8556         rv = soc_portctrl_phy_control_set(unit, pport,
   8557                                           -1, -1, 0,
   8558                                           (soc_phy_control_t) type, value);
   8559     } else {
   8560         /* Configure PHY specified by GPORT */
   8561         rv = soc_portctrl_phy_control_set(unit, pport,
   8562                                           phyn, phy_lane, sys_side,
   8563                                           (soc_phy_control_t) type, value);
   8564     }
   8565 
   8566     /* Provide Warmboot support for SW RX LOS status */
   8567     if (SOC_SUCCESS(rv) && 
   8568         (type == BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS)) {
   8569         _bcm_port_info_access(unit, port, &port_info);
   8570         port_info->rx_los = value;
   8571     }
   8572 
   8573     PORT_UNLOCK(unit);
   8574 
   8575     return rv;
   8576 
   8577 #else  /* PORTMOD_SUPPORT */
   8578     return BCM_E_UNAVAIL;
   8579 #endif /* PORTMOD_SUPPORT */
   8580 }
   8581 
   8582 
   8583 #ifdef PORTMOD_SUPPORT
   8584 /*
   8585  * Function:
   8586  *      _bcm_esw_portctrl_control_pfc_receive_set
   8587  * Purpose:
   8588  *      Set the bcmPortControlPFCReceive port control.
   8589  * Parameters:
   8590  *      unit      - (IN) Unit number.
   8591  *      port      - (IN) BCM port number (NONE gport format).
   8592  *      pport     - (IN) Portmod port number.
   8593  *      value     - (IN) value to be set.
   8594  * Returns:
   8595  *      BCM_E_XXX
   8596  * Notes:
   8597  *      Assumes caller will:
   8598  *      - Check for PORTCTRL_INIT()
   8599  *      - Provide LOCKs
   8600  */
   8601 STATIC int
   8602 _bcm_esw_portctrl_control_pfc_receive_set(int unit, bcm_port_t port,
   8603                                           portctrl_pport_t pport,
   8604                                           int value)
   8605 {
   8606     int pfc_enable;
   8607     portmod_pfc_control_t pfc_control;
   8608 
   8609     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   8610         return BCM_E_UNAVAIL;
   8611     }
   8612 
   8613     PORTMOD_IF_ERROR_RETURN
   8614         (portmod_port_pfc_control_get(unit, pport, &pfc_control));
   8615 
   8616     pfc_control.rx_enable = value;            
   8617     PORTMOD_IF_ERROR_RETURN
   8618         (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   8619 
   8620     if (value == 0) {
   8621         pfc_enable = pfc_control.tx_enable;
   8622     } else {
   8623         pfc_enable = TRUE;
   8624     }
   8625 
   8626     if (value == 0) {
   8627         /* Disabling RX, flush MMU XOFF state */
   8628         pfc_control.force_xon = 1;
   8629         PORTMOD_IF_ERROR_RETURN
   8630             (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   8631         pfc_control.force_xon = 0;
   8632         PORTMOD_IF_ERROR_RETURN
   8633             (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   8634     }
   8635 
   8636     /* Stats enable */
   8637     pfc_control.stats_en = pfc_enable ? 1 : 0;
   8638     PORTMOD_IF_ERROR_RETURN
   8639         (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   8640     
   8641     if (SOC_REG_IS_VALID(unit, XPORT_TO_MMU_BKPr) && (pfc_enable == 0)) {
   8642         BCM_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKPr(unit, port, 0));
   8643     } else if (SOC_REG_IS_VALID(unit, XPORT_TO_MMU_BKP_64r) && (pfc_enable == 0)) {
   8644         uint64 zero64;
   8645         COMPILER_64_ZERO(zero64);
   8646         BCM_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKP_64r(unit, port, zero64));
   8647     }
   8648     if (SOC_REG_IS_VALID(unit, MMU_INTFI_EGR_PORT_CFGr)) {
   8649         uint32 rval = 0;
   8650         SOC_IF_ERROR_RETURN
   8651             (soc_reg32_get(unit, MMU_INTFI_EGR_PORT_CFGr, port, 0, &rval));
   8652         soc_reg_field_set(unit, MMU_INTFI_EGR_PORT_CFGr,
   8653             &rval, DISABLE_Q_FCf, pfc_enable ? 0 : 1);
   8654         SOC_IF_ERROR_RETURN
   8655             (soc_reg32_set(unit, MMU_INTFI_EGR_PORT_CFGr, port, 0, rval));
   8656     }
   8657     return BCM_E_NONE;
   8658 }
   8659 
   8660 
   8661 /*
   8662  * Function:
   8663  *      _bcm_esw_portctrl_control_pfc_transmit_set
   8664  * Purpose:
   8665  *      Set the bcmPortControlPFCTransmit port control.
   8666  * Parameters:
   8667  *      unit      - (IN) Unit number.
   8668  *      port      - (IN) BCM port number (NONE gport format).
   8669  *      pport     - (IN) Portmod port number.
   8670  *      value     - (IN) value to be set.
   8671  * Returns:
   8672  *      BCM_E_XXX
   8673  * Notes:
   8674  *      Assumes caller will:
   8675  *      - Check for PORTCTRL_INIT()
   8676  *      - Provide LOCKs
   8677  */
   8678 STATIC int
   8679 _bcm_esw_portctrl_control_pfc_transmit_set(int unit, bcm_port_t port,
   8680                                            portctrl_pport_t pport,
   8681                                            int value)
   8682 {
   8683     int pfc_enable;
   8684     portmod_pfc_control_t pfc_control;
   8685     uint32 rval;
   8686 
   8687     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   8688         return BCM_E_UNAVAIL;
   8689     }
   8690 
   8691     PORTMOD_IF_ERROR_RETURN
   8692         (portmod_port_pfc_control_get(unit, pport, &pfc_control));
   8693 
   8694     pfc_control.tx_enable = value;            
   8695     PORTMOD_IF_ERROR_RETURN
   8696         (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   8697 
   8698     if (value == 0) {
   8699         pfc_enable = pfc_control.rx_enable;
   8700     } else {
   8701         pfc_enable = TRUE;
   8702     }
   8703 
   8704 #ifdef BCM_TOMAHAWK3_SUPPORT
   8705     if (SOC_IS_TOMAHAWK3(unit)) {
   8706         SOC_IF_ERROR_RETURN
   8707             (bcm_th3_mmu_pfc_tx_config_set(unit, port,
   8708                                            pfc_enable, 0xff));
   8709     }
   8710 #endif
   8711 
   8712     /* Port config settings */
   8713     if (SOC_REG_IS_VALID(unit, THDI_INPUT_PORT_XON_ENABLESr)) {
   8714         SOC_IF_ERROR_RETURN
   8715             (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
   8716                            port, 0, &rval));
   8717         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8718                           PORT_PRI_XON_ENABLEf,
   8719                           pfc_enable ? 0xffff : 0);
   8720         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8721                           PORT_PAUSE_ENABLEf, pfc_enable ? 0 : 1);
   8722         SOC_IF_ERROR_RETURN
   8723             (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr,
   8724                            port, 0, rval));
   8725     }
   8726 
   8727     /* Stats enable */
   8728     pfc_control.stats_en = pfc_enable ? 1 : 0;
   8729     PORTMOD_IF_ERROR_RETURN
   8730         (portmod_port_pfc_control_set(unit, pport, &pfc_control));
   8731 
   8732     return BCM_E_NONE;
   8733 }
   8734 
   8735 
   8736 /*
   8737  * Function:
   8738  *      _bcm_esw_portctrl_control_eee_enable_set
   8739  * Purpose:
   8740  *      Set the bcmPortControlEEEEnable port control.
   8741  * Parameters:
   8742  *      unit      - (IN) Unit number.
   8743  *      port      - (IN) BCM port number (NONE gport format).
   8744  *      pport     - (IN) Portmod port number.
   8745  *      value     - (IN) value to be set.
   8746  * Returns:
   8747  *      BCM_E_XXX
   8748  * Notes:
   8749  *      Assumes caller will:
   8750  *      - Check for PORTCTRL_INIT()
   8751  *      - Provide LOCKs
   8752  */
   8753 STATIC int
   8754 _bcm_esw_portctrl_control_eee_enable_set(int unit, bcm_port_t port,
   8755                                          portctrl_pport_t pport,
   8756                                          int value)
   8757 {
   8758     portmod_eee_t eee;
   8759     uint32 phy_val;
   8760     bcm_port_t g_port;
   8761     int rv, phyn;
   8762 
   8763 
   8764     PORTMOD_IF_ERROR_RETURN(portmod_eee_t_init(unit, &eee));
   8765 
   8766     rv = portmod_port_eee_get(unit, pport, &eee);
   8767                             
   8768     /*if rv is SOC_E_UNAVAIL, Native EEE is not support for this MAC*/
   8769     if ((rv != SOC_E_UNAVAIL) &&
   8770         (soc_feature (unit, soc_feature_eee)) &&
   8771         (bcmi_esw_portctrl_phy_control_get(unit, port,
   8772                                  BCM_PORT_PHY_CONTROL_EEE,
   8773                                  &phy_val) != SOC_E_UNAVAIL)) {
   8774 
   8775         /* If MAC/Switch is EEE aware (Native EEE mode is supported)
   8776          * and PHY also supports Native EEE mode
   8777          */
   8778 
   8779         /* a. Disable AutoGrEEEn mode by PHY if applicable */
   8780         rv = (bcmi_esw_portctrl_phy_control_get(unit, port,
   8781                                       BCM_PORT_PHY_CONTROL_EEE_AUTO,
   8782                                       &phy_val));
   8783 
   8784         if ((rv != SOC_E_UNAVAIL) && (phy_val != 0)) {
   8785             (void)bcmi_esw_portctrl_phy_control_set(unit, port,
   8786                                          BCM_PORT_PHY_CONTROL_EEE_AUTO,
   8787                                          0);
   8788         }
   8789 
   8790         /* b. Enable/Disable Native EEE in PHY */
   8791         rv = bcmi_esw_portctrl_phy_control_set (unit, port,
   8792                                       BCM_PORT_PHY_CONTROL_EEE, value ? 1 : 0);
   8793 
   8794         if (SOC_SUCCESS(rv)) {
   8795             /* EEE standard compliance Work Around:
   8796              * Store the software copy of eee value in eee_cfg flag
   8797              */
   8798             /*eee_cfg[unit][port] = value;*/
   8799             BCM_IF_ERROR_RETURN
   8800                 (bcmi_esw_port_eee_cfg_set(unit, port, value));
   8801             /* If (value==1), EEE will be enabled in MAC after 1 sec.
   8802              * during linkscan update*/
   8803             if (value == 0) {
   8804                 eee.enable = 0;
   8805                 /* Disable EEE in MAC immediately*/
   8806                 rv = portmod_port_eee_set(unit, port, &eee);
   8807             }
   8808 
   8809             /* Notify Int-PHY to bypass LPI for native EEE mode.
   8810              *
   8811              * Note :
   8812              *  1. Not all internal SerDes support the setting to
   8813              *     enable/disable bypass LPI signal.
   8814              *  2. Int-PHY to bypass LPI will sync with Ext-PHY's EEE
   8815              *     enabling status for Native EEE mode.
   8816              */
   8817             /*phyn ==  0  ( outermost )
   8818               phyn ==  1  ( internal )
   8819               phyn ==  >1 ( ext phy )
   8820              */
   8821             phyn = 1;
   8822             BCM_PHY_GPORT_PHYN_PORT_SET(g_port, phyn, port);
   8823             (void)bcmi_esw_portctrl_phy_control_set (unit, g_port,
   8824                                       BCM_PORT_PHY_CONTROL_EEE, PORTMOD_EEE_ENABLE_LPI_BYPASS_SET(value));
   8825         }
   8826 
   8827     } else {
   8828         /* If native EEE mode is not supported,
   8829          * set PHY in AutoGrEEEn mode.
   8830          */
   8831 
   8832         /* a. Disable Native EEE mode in PHY if applicable */
   8833         rv = (bcmi_esw_portctrl_phy_control_get(unit, port,
   8834                                       BCM_PORT_PHY_CONTROL_EEE,
   8835                                       &phy_val));
   8836 
   8837         if ((rv != SOC_E_UNAVAIL) && (phy_val != 0)) {
   8838             (void)bcmi_esw_portctrl_phy_control_set (unit, port,
   8839                                           BCM_PORT_PHY_CONTROL_EEE,
   8840                                           0);
   8841         }
   8842 
   8843         /* b. Enable/Disable AutoGrEEEn in PHY.
   8844          * If PHY does not support AutoGrEEEn mode,
   8845          * rv will be assigned SOC_E_UNAVAIL.
   8846          */
   8847         rv = bcmi_esw_portctrl_phy_control_set (unit, port,
   8848                                       BCM_PORT_PHY_CONTROL_EEE_AUTO,
   8849                                       value ? 1 : 0);
   8850         if (SOC_SUCCESS(rv)) {
   8851             BCM_IF_ERROR_RETURN
   8852                 (bcmi_esw_port_eee_cfg_set(unit, port, value));
   8853         }
   8854     }
   8855 
   8856     return rv;
   8857 }
   8858 
   8859 /*
   8860  * Function:
   8861  *      _bcm_esw_portctrl_eee_statistics_clear
   8862  * Purpose:
   8863  *      Set the bcmPortControlEEEStatisticsClear port control.
   8864  * Parameters:
   8865  *      unit      - (IN) Unit number.
   8866  *      port      - (IN) BCM port number (NONE gport format).
   8867  *      pport     - (IN) Portmod port number.
   8868  *      value     - (IN) value to be set.
   8869  * Returns:
   8870  *      BCM_E_XXX
   8871  * Notes:
   8872  *      Assumes caller will:
   8873  *      - Check for PORTCTRL_INIT()
   8874  *      - Provide LOCKs
   8875  */
   8876 STATIC int
   8877 _bcm_esw_portctrl_eee_statistics_clear(int unit, bcm_port_t port,
   8878                                          portctrl_pport_t pport,
   8879                                          int value)
   8880 {
   8881 
   8882 #if 0
   8883     uint32 val = 0;
   8884     uint64 val64;
   8885     uint32 phy_val;
   8886     int idx;
   8887     soc_reg_t regs[] = {
   8888         RX_EEE_LPI_DURATION_COUNTERr,
   8889         RX_EEE_LPI_EVENT_COUNTERr,
   8890         TX_EEE_LPI_DURATION_COUNTERr,
   8891         TX_EEE_LPI_EVENT_COUNTERr
   8892     };
   8893 
   8894     if (!soc_feature(unit, soc_feature_eee)) {
   8895         return BCM_E_UNAVAIL;
   8896     }
   8897 
   8898     COMPILER_64_ZERO(val64);
   8899     if ((MAC_CONTROL_GET(PORT(unit, port).p_mac, unit, port,
   8900                          SOC_MAC_CONTROL_EEE_ENABLE, &mac_val)
   8901          != SOC_E_UNAVAIL) &&
   8902         (soc_phyctrl_control_get(unit, port,
   8903                                  BCM_PORT_PHY_CONTROL_EEE, &phy_val)
   8904          != SOC_E_UNAVAIL)) {
   8905 
   8906         only for TD2...
   8907             for (idx = 0; idx < sizeof(regs) / sizeof(regs[0]); idx++) {
   8908                 SOC_IF_ERROR_RETURN
   8909                     (soc_counter_set(unit, port, regs[idx], 0, val64));
   8910             }
   8911         return ??
   8912 
   8913         /* MAC/Switch is EEE aware (Native EEE mode is supported) */
   8914         if (soc_feature(unit, soc_feature_unified_port)) {
   8915             if (SOC_REG_IS_VALID(unit, PORT_XGXS_COUNTER_MODEr)) {
   8916                 _BCM_PORT_IF_ERROR_RETURN_WITH_UNLOCK
   8917                     (READ_PORT_XGXS_COUNTER_MODEr(unit, port, &val));
   8918                 soc_reg_field_set(unit, PORT_XGXS_COUNTER_MODEr, &val,
   8919                                   CNT_MODEf, 0);
   8920                 _BCM_PORT_IF_ERROR_RETURN_WITH_UNLOCK
   8921                     (WRITE_PORT_XGXS_COUNTER_MODEr(unit, port, val));
   8922             }
   8923         } 
   8924 
   8925         /* Read counters to clear them*/
   8926         SOC_IF_ERROR_RETURN
   8927             (READ_RX_EEE_LPI_DURATION_COUNTERr(unit, port, &val64));
   8928         SOC_IF_ERROR_RETURN
   8929             (READ_RX_EEE_LPI_EVENT_COUNTERr(unit, port, &val64));
   8930         SOC_IF_ERROR_RETURN
   8931             (READ_TX_EEE_LPI_DURATION_COUNTERr(unit, port, &val64));
   8932         SOC_IF_ERROR_RETURN
   8933             (READ_TX_EEE_LPI_EVENT_COUNTERr(unit, port, &val64));
   8934 
   8935         /* Set counter rollover bit to 1*/
   8936         if (soc_feature(unit, soc_feature_unified_port)) {
   8937             if (SOC_REG_IS_VALID(unit,
   8938                                  PORT_XGXS_COUNTER_MODEr)) {
   8939                 SOC_IF_ERROR_RETURN
   8940                     (READ_PORT_XGXS_COUNTER_MODEr(unit, port, &val));
   8941                 soc_reg_field_set(unit, PORT_XGXS_COUNTER_MODEr, &val,
   8942                                   CNT_MODEf, 1);
   8943                 SOC_IF_ERROR_RETURN
   8944                     (WRITE_PORT_XGXS_COUNTER_MODEr(unit, port, val));
   8945             }
   8946         }
   8947     } else {
   8948         /* native EEE mode is not supported, */
   8949         rv = soc_phyctrl_control_set
   8950             (unit, port,
   8951              BCM_PORT_PHY_CONTROL_EEE_STATISTICS_CLEAR, value);
   8952     }
   8953 #endif
   8954 
   8955     return BCM_E_NONE;
   8956 }
   8957 #endif /* PORTMOD_SUPPORT */
   8958 
   8959 /*
   8960  * Function:
   8961  *      bcmi_esw_portctrl_priority_group_config_set
   8962  * Purpose:
   8963  *      Set the port priority group configuration.
   8964  * Parameters:
   8965  *      unit       - (IN) device id.
   8966  *      port      - (IN) generic port.
   8967  *      priority_group - (IN) priority group id.
   8968  *      prigrp_config  - (IN) structure describes port PG configuration.
   8969  * Returns:
   8970  *      BCM_E_XXX
   8971  */
   8972 int
   8973 bcmi_esw_portctrl_priority_group_config_set(int unit, bcm_gport_t port,
   8974                                            int priority_group,
   8975                                            bcm_port_priority_group_config_t *prigrp_config)
   8976 {
   8977 #ifdef PORTMOD_SUPPORT
   8978     int rv;
   8979     int pfc_enable;
   8980     portmod_pfc_control_t pfc_control;
   8981     uint32 rval, pri_bmp;
   8982     portctrl_pport_t pport;
   8983 
   8984     /* Make sure port module is initialized. */
   8985     PORTCTRL_INIT_CHECK(unit);
   8986 
   8987     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   8988         return BCM_E_UNAVAIL;
   8989     }
   8990     if ((priority_group < PORTCTRL_PRIOROTY_GROUP_ID_MIN) ||
   8991         (priority_group > PORTCTRL_PRIOROTY_GROUP_ID_MAX)) {
   8992         return BCM_E_PARAM;
   8993     }
   8994     if (prigrp_config == NULL) {
   8995         return BCM_E_PARAM;
   8996     }
   8997     if (prigrp_config->shared_pool_xoff_enable ||
   8998         prigrp_config->shared_pool_discard_enable ||
   8999         prigrp_config->priority_enable_vector_mask) {
   9000         return BCM_E_UNAVAIL;
   9001     }
   9002 
   9003     BCM_IF_ERROR_RETURN
   9004         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   9005 
   9006     PORT_LOCK(unit);
   9007 
   9008     rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9009     if (PORTMOD_FAILURE(rv)) {
   9010         PORT_UNLOCK(unit);
   9011         return rv;
   9012     }
   9013 
   9014     rv = portmod_port_pfc_control_set(unit, pport, &pfc_control);
   9015     if (PORTMOD_FAILURE(rv)) {
   9016         PORT_UNLOCK(unit);
   9017         return rv;
   9018     }
   9019 
   9020     if (prigrp_config->pfc_transmit_enable == 0) {
   9021         pfc_enable = pfc_control.rx_enable;
   9022     } else {
   9023         pfc_enable = TRUE;
   9024     }
   9025 
   9026     /* Port config settings */
   9027     if (SOC_REG_IS_VALID(unit, THDI_INPUT_PORT_XON_ENABLESr)) {
   9028         rv = soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
   9029                            pport, 0, &rval);
   9030         if (PORTMOD_FAILURE(rv)) {
   9031             PORT_UNLOCK(unit);
   9032             return rv;
   9033         }
   9034         pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval,
   9035                                     PORT_PRI_XON_ENABLEf);
   9036         if (prigrp_config->pfc_transmit_enable) {
   9037             pri_bmp |= (1 << priority_group);
   9038         } else {
   9039             pri_bmp &= ~(1 << priority_group);
   9040         }
   9041         /* To cover higher 8 PFC classes that have no corresponding PG. */
   9042         if ((pri_bmp & 0xff) == 0) {
   9043             pri_bmp = 0;
   9044         }
   9045 
   9046         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   9047                           PORT_PRI_XON_ENABLEf,
   9048                           pfc_enable ? pri_bmp : 0);
   9049         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   9050                           PORT_PAUSE_ENABLEf, pfc_enable ? 0 : 1);
   9051         rv = soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr,
   9052                            pport, 0, rval);
   9053         if (PORTMOD_FAILURE(rv)) {
   9054             PORT_UNLOCK(unit);
   9055             return rv;
   9056         }
   9057     }
   9058 
   9059     /* Stats enable */
   9060     pfc_control.stats_en = pfc_enable ? 1 : 0;
   9061     rv = portmod_port_pfc_control_set(unit, pport, &pfc_control);
   9062     PORT_UNLOCK(unit);
   9063 
   9064     return rv;
   9065 #else  /* PORTMOD_SUPPORT */
   9066     return BCM_E_UNAVAIL;
   9067 #endif /* PORTMOD_SUPPORT */
   9068 
   9069 }
   9070 
   9071 /*
   9072  * Function:
   9073  *      bcmi_esw_portctrl_control_validate
   9074  * Purpose:
   9075  *      Check that given port control feature in valid in Port Control.
   9076  * Parameters:
   9077  *      unit    - (IN) Unit number.
   9078  *      type    - (IN) Port control feature bcmPortControlxxx.
   9079  *      valid   - (OUT) Indicates if control feature is valid.
   9080  * Returns:
   9081  *      BCM_E_XXX
   9082  */
   9083 int
   9084 bcmi_esw_portctrl_control_validate(int unit, bcm_port_control_t type,
   9085                                    int *valid)
   9086 {
   9087 #ifdef PORTMOD_SUPPORT
   9088 
   9089     PORTCTRL_INIT_CHECK(unit);
   9090 
   9091     *valid = 0;
   9092     switch (type) {
   9093     case bcmPortControlEEEEnable:
   9094     case bcmPortControlEEEReceiveDuration:
   9095     case bcmPortControlEEEReceiveEventCount:
   9096     case bcmPortControlEEEReceiveQuietTime:
   9097     case bcmPortControlEEEReceiveSleepTime:
   9098     case bcmPortControlEEEReceiveWakeTime:
   9099     case bcmPortControlEEEStatisticsClear:
   9100     case bcmPortControlEEETransmitDuration:
   9101     case bcmPortControlEEETransmitEventCount:
   9102     case bcmPortControlEEETransmitIdleTime:
   9103     case bcmPortControlEEETransmitQuietTime:
   9104     case bcmPortControlEEETransmitRefreshTime:
   9105     case bcmPortControlEEETransmitSleepTime:
   9106     case bcmPortControlEEETransmitWakeTime:
   9107     case bcmPortControlFrameSpacingStretch:
   9108     case bcmPortControlLinkdownTransmit:
   9109     case bcmPortControlLinkFaultLocal:
   9110     case bcmPortControlLinkFaultLocalEnable:
   9111     case bcmPortControlLinkFaultRemote:
   9112     case bcmPortControlLinkFaultRemoteEnable:
   9113     case bcmPortControlPassControlFrames:
   9114     case bcmPortControlPFCClasses:
   9115     case bcmPortControlPFCDestMacNonOui:
   9116     case bcmPortControlPFCDestMacOui:
   9117     case bcmPortControlPFCEthertype:
   9118     case bcmPortControlPFCOpcode:
   9119     case bcmPortControlPFCPassFrames:
   9120     case bcmPortControlPFCReceive:
   9121     case bcmPortControlPFCRefreshTime:
   9122     case bcmPortControlPFCTransmit:
   9123     case bcmPortControlPFCXOffTime:
   9124     case bcmPortControlPrbsPolynomial:
   9125     case bcmPortControlPrbsRxEnable:
   9126     case bcmPortControlPrbsRxStatus:
   9127     case bcmPortControlPrbsTxEnable:
   9128     case bcmPortControlPrbsTxInvertData:
   9129     case bcmPortControlRxEnable:
   9130     case bcmPortControlSerdesDriverTune:
   9131     case bcmPortControlSerdesDriverEqualizationTuneStatusFarEnd:
   9132     case bcmPortControlSerdesTuneMarginMax:
   9133     case bcmPortControlSerdesTuneMarginMode:
   9134     case bcmPortControlSerdesTuneMarginValue:
   9135     case bcmPortControlTimestampTransmit:
   9136     case bcmPortControlVrf:
   9137     case bcmPortControlTimestampEnable:
   9138     case bcmPortControlTXPISDMOverride:
   9139     case bcmPortControlTXPISDMStatus:
   9140     case bcmPortControlOOBFCTxReportIngEnable:
   9141     case bcmPortControlOOBFCTxReportEgrEnable:
   9142         *valid = 1;
   9143         break;
   9144     default:
   9145         *valid = 0;
   9146         break;
   9147     }
   9148 
   9149     return BCM_E_NONE;
   9150 #else  /* PORTMOD_SUPPORT */
   9151     return BCM_E_UNAVAIL;
   9152 #endif /* PORTMOD_SUPPORT */
   9153 }
   9154 
   9155 
   9156 /*
   9157  * Function:
   9158  *      bcmi_esw_portctrl_control_set
   9159  * Purpose:
   9160  *      Set specified port control feature.
   9161  * Parameters:
   9162  *      unit      - (IN) Unit number.
   9163  *      port      - (IN) Port number.
   9164  *      type      - (IN) Port control feature to set.
   9165  *      value     - (IN) Value of port control feature.
   9166  * Returns:
   9167  *      BCM_E_XXX
   9168  * Notes:
   9169  *      Any new control needs to be included in
   9170  *      bcmi_esw_portctrl_control_validate().
   9171  */
   9172 int
   9173 bcmi_esw_portctrl_control_set(int unit, bcm_gport_t port,
   9174                               bcm_port_control_t type, int value)
   9175 {
   9176 #ifdef PORTMOD_SUPPORT
   9177     int rv = BCM_E_UNAVAIL;
   9178     portctrl_pport_t pport;
   9179 
   9180     PORTCTRL_INIT_CHECK(unit);
   9181 
   9182     BCM_IF_ERROR_RETURN
   9183         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   9184 
   9185     switch (type) {
   9186     case bcmPortControlPassControlFrames:
   9187         if (IS_E_PORT(unit, port)) {
   9188             rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE,
   9189                                        PASS_CONTROL_FRAMESf,
   9190                                        (value) ? 1 : 0);
   9191         }
   9192 
   9193         if (IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) ||
   9194             IS_CDE_PORT(unit, port) || IS_C_PORT(unit, port) ||
   9195             (IS_GE_PORT(unit, port)
   9196              && soc_feature(unit, soc_feature_unified_port))) {
   9197             /* Enable Control Frames in BigMAC */
   9198             if(soc_feature(unit, soc_feature_pgw_mac_control_frame)) {
   9199                 uint32 rval32 = 0;
   9200 
   9201                 PORT_LOCK(unit);
   9202                 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32);
   9203                 if (BCM_SUCCESS(rv)) {
   9204                     /* PGW_MAC_RSV_MASK: Bit 11 Control Frame recieved
   9205                      * Enable  Control Frame : Set 0. Packet go through
   9206                      * Disable Control Frame : Set 1. Packet is purged.
   9207                      */
   9208                     if(value) {
   9209                         rval32 &= ~(1 << 11);
   9210                     } else {
   9211                         rval32 |= (1 << 11);
   9212                     }
   9213                     rv = WRITE_PGW_MAC_RSV_MASKr(unit, port, rval32);
   9214                 }
   9215                 PORT_UNLOCK(unit);
   9216             } else {
   9217                 portmod_rx_control_t rx_control;
   9218 
   9219                 PORTMOD_IF_ERROR_RETURN
   9220                     (portmod_rx_control_t_init(unit, &rx_control));
   9221 
   9222                 rx_control.flags = PORTMOD_MAC_PASS_CONTROL_FRAME;
   9223                 rx_control.pass_control_frames = value;
   9224                 PORT_LOCK(unit);
   9225                 rv = portmod_port_rx_control_set(unit, pport, &rx_control);
   9226                 PORT_UNLOCK(unit);
   9227             }
   9228         }
   9229         break;
   9230 
   9231     case bcmPortControlFrameSpacingStretch:
   9232         PORT_LOCK(unit);
   9233         rv = portmod_port_frame_spacing_stretch_set(unit, pport, value);
   9234         PORT_UNLOCK(unit);
   9235         break;
   9236 
   9237     case bcmPortControlPFCEthertype:
   9238         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9239             portmod_pfc_config_t pfc_config;
   9240 
   9241             if (value < 0 || value > 0xffff) {
   9242                 return BCM_E_PARAM;
   9243             }
   9244 
   9245             PORT_LOCK(unit);
   9246             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9247             if (PORTMOD_SUCCESS(rv)) {
   9248                 pfc_config.type = value;
   9249                 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config);
   9250             }
   9251             PORT_UNLOCK(unit);
   9252         }
   9253         break;
   9254 
   9255     case bcmPortControlPFCOpcode:
   9256         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9257             portmod_pfc_config_t pfc_config;
   9258 
   9259             if (value < 0 || value > 0xffff) {
   9260                 return BCM_E_PARAM;
   9261             }
   9262 
   9263             PORT_LOCK(unit);
   9264             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9265             if (PORTMOD_SUCCESS(rv)) {
   9266                 pfc_config.opcode = value;
   9267                 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config);
   9268             }
   9269             PORT_UNLOCK(unit);
   9270         }
   9271         break;
   9272 
   9273     case bcmPortControlPFCReceive:
   9274         PORT_LOCK(unit);
   9275         rv = _bcm_esw_portctrl_control_pfc_receive_set(unit, port,
   9276                                                        pport, value);
   9277         PORT_UNLOCK(unit); 
   9278         break;
   9279 
   9280     case bcmPortControlPFCTransmit:
   9281         PORT_LOCK(unit);
   9282         rv = _bcm_esw_portctrl_control_pfc_transmit_set(unit, port,
   9283                                                         pport, value);
   9284         PORT_UNLOCK(unit); 
   9285         break;
   9286 
   9287     case bcmPortControlPFCClasses:
   9288         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9289             portmod_pfc_config_t pfc_config;
   9290 
   9291             if (value < 0 || value > 0xffffff) {
   9292                 return BCM_E_PARAM;
   9293             }
   9294 
   9295             PORT_LOCK(unit);
   9296             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9297             if (PORTMOD_SUCCESS(rv)) {
   9298                 pfc_config.classes = value;
   9299                 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config);
   9300             }
   9301             PORT_UNLOCK(unit);
   9302         }
   9303         break;
   9304 
   9305     case bcmPortControlPFCPassFrames:
   9306         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9307             if(soc_feature(unit, soc_feature_pgw_mac_pfc_frame)) {
   9308                 uint32 rval32 = 0;
   9309                 PORT_LOCK(unit);
   9310                 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32);
   9311                 if (BCM_SUCCESS(rv)) {
   9312                     /* PGW_MAC_RSV_MASK: Bit 18 PFC frame detected
   9313                      * Enable  PFC Frame : Set 0. Go through
   9314                      * Disable PFC Frame : Set 1. Purged.
   9315                      */
   9316                     if(value) {
   9317                         rval32 &= ~(1 << 18);
   9318                     } else {
   9319                         rval32 |= (1 << 18);
   9320                     }
   9321                     rv = WRITE_PGW_MAC_RSV_MASKr(unit, port, rval32);
   9322                 }
   9323                 PORT_UNLOCK(unit);
   9324             } else {
   9325                 portmod_pfc_config_t pfc_config;
   9326 
   9327                 PORT_LOCK(unit);
   9328                 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9329                 if (PORTMOD_SUCCESS(rv)) {
   9330                     pfc_config.rxpass = value;
   9331                     rv = portmod_port_pfc_config_set(unit, pport, &pfc_config);
   9332                 }
   9333                 PORT_UNLOCK(unit);
   9334             }
   9335         }
   9336         break;
   9337 
   9338     case bcmPortControlPFCDestMacOui:
   9339         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9340             portmod_pfc_config_t pfc_config;
   9341 
   9342             if (value < 0 || value > 0xffffff) {
   9343                 return BCM_E_PARAM;
   9344             }
   9345             
   9346             PORT_LOCK(unit);
   9347             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9348             if (PORTMOD_SUCCESS(rv)) {
   9349                 pfc_config.da_oui = value;
   9350                 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config);
   9351             }
   9352             PORT_UNLOCK(unit);
   9353         }
   9354         break;
   9355 
   9356     case bcmPortControlPFCDestMacNonOui:
   9357         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9358             portmod_pfc_config_t pfc_config;
   9359 
   9360             if (value < 0 || value > 0xffffff) {
   9361                 return BCM_E_PARAM;
   9362             }
   9363 
   9364             PORT_LOCK(unit);
   9365             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9366             if (PORTMOD_SUCCESS(rv)) {
   9367                 pfc_config.da_nonoui = value;
   9368                 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config);
   9369             }
   9370             PORT_UNLOCK(unit);
   9371         }
   9372         break;
   9373 
   9374     case bcmPortControlPFCRefreshTime:
   9375         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9376             portmod_pfc_control_t pfc_control;
   9377 
   9378             if (value < 0 || value > 0xffff) {
   9379                 return BCM_E_PARAM;
   9380             }
   9381 
   9382             PORT_LOCK(unit);
   9383             rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9384             if (PORTMOD_SUCCESS(rv)) {
   9385                 pfc_control.refresh_timer = value;
   9386                 rv = portmod_port_pfc_control_set(unit, pport, &pfc_control);
   9387             }
   9388             PORT_UNLOCK(unit);
   9389         }
   9390         break;
   9391 
   9392     case bcmPortControlPFCXOffTime:
   9393         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9394             portmod_pfc_control_t pfc_control;
   9395 
   9396             if (value < 0 || value > 0xffff) {
   9397                 return BCM_E_PARAM;
   9398             }
   9399 
   9400             PORT_LOCK(unit);
   9401             rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9402             if (PORTMOD_SUCCESS(rv)) {
   9403                 pfc_control.xoff_timer = value;
   9404                 rv = portmod_port_pfc_control_set(unit, pport, &pfc_control);
   9405             }
   9406             PORT_UNLOCK(unit);
   9407         }
   9408         break;
   9409 
   9410     case bcmPortControlPrbsPolynomial:
   9411         PORT_LOCK(unit);
   9412         rv = bcmi_esw_portctrl_phy_control_set(unit, port, 
   9413              BCM_PORT_PHY_CONTROL_PRBS_POLYNOMIAL, value);
   9414         PORT_UNLOCK(unit);
   9415         break;
   9416 
   9417     case bcmPortControlPrbsTxEnable:
   9418         PORT_LOCK(unit);
   9419         rv = bcmi_esw_portctrl_phy_control_set(unit, port, 
   9420              BCM_PORT_PHY_CONTROL_PRBS_TX_ENABLE, value);
   9421         PORT_UNLOCK(unit);
   9422         break;
   9423 
   9424     case bcmPortControlPrbsRxEnable:
   9425         PORT_LOCK(unit);
   9426         rv = bcmi_esw_portctrl_phy_control_set(unit, port, 
   9427              BCM_ESW_PORTCTRL_PHYCTRL_PRBS_RX_ENABLE, value);
   9428         PORT_UNLOCK(unit);
   9429         break;
   9430 
   9431     case bcmPortControlPrbsTxInvertData:
   9432         PORT_LOCK(unit);
   9433         rv = bcmi_esw_portctrl_phy_control_set(unit, port, 
   9434              BCM_PORT_PHY_CONTROL_PRBS_TX_INVERT_DATA, value);
   9435         PORT_UNLOCK(unit);
   9436         break;
   9437 
   9438     case bcmPortControlLinkFaultLocalEnable:
   9439         {
   9440             portmod_local_fault_control_t control;
   9441 
   9442             PORT_LOCK(unit);
   9443             rv = portmod_port_local_fault_control_get(unit, pport, &control);
   9444             if (PORTMOD_SUCCESS(rv)) {
   9445                 control.enable = value;
   9446                 rv = portmod_port_local_fault_control_set(unit,
   9447                                                           pport, &control);
   9448             }
   9449             PORT_UNLOCK(unit);
   9450         }
   9451         break;
   9452 
   9453     case bcmPortControlLinkFaultRemoteEnable:
   9454         {
   9455             portmod_remote_fault_control_t control;
   9456 
   9457             PORT_LOCK(unit);
   9458             rv = portmod_port_remote_fault_control_get(unit, pport, &control);
   9459             if (PORTMOD_SUCCESS(rv)) {
   9460                 control.enable = value;
   9461                 rv = portmod_port_remote_fault_control_set(unit,
   9462                                                            pport, &control);
   9463             }
   9464             PORT_UNLOCK(unit);
   9465         }
   9466         break;
   9467 
   9468     case bcmPortControlSerdesDriverTune:
   9469         PORT_LOCK(unit);
   9470         
   9471         /* rv = soc_phyctrl_control_set(unit, port,
   9472            SOC_PHY_CONTROL_SERDES_DRIVER_TUNE, value);
   9473         */
   9474         PORT_UNLOCK(unit);
   9475         break;
   9476 
   9477     case bcmPortControlLinkdownTransmit:
   9478         PORT_LOCK(unit);
   9479         rv = bcmi_esw_portctrl_phy_control_set(unit, port,
   9480                  BCM_PORT_PHY_CONTROL_LINKDOWN_TRANSMIT, value);
   9481         PORT_UNLOCK(unit);
   9482         /* Most of PHYs have nothing to configure and simply return UNAVAIL*/
   9483         if ((rv == SOC_E_NONE) || (rv == SOC_E_UNAVAIL)) {
   9484             portmod_local_fault_control_t control;
   9485 
   9486             rv = _bcm_esw_link_down_tx_set(unit, port, value);
   9487 
   9488             PORT_LOCK(unit);
   9489             rv = portmod_port_local_fault_control_get(unit, pport, &control);
   9490             if (PORTMOD_SUCCESS(rv)) {
   9491                 control.enable = value ? 0 : 1;
   9492                 rv = portmod_port_local_fault_control_set(unit,
   9493                                                           pport, &control);
   9494             }
   9495             PORT_UNLOCK(unit);
   9496         }
   9497         break;
   9498 
   9499     case bcmPortControlSerdesTuneMarginMode:
   9500         PORT_LOCK(unit);
   9501         
   9502         /* rv = soc_phyctrl_control_set(unit, port,
   9503            SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MODE, value);
   9504         */
   9505         PORT_UNLOCK(unit);
   9506         break;
   9507 
   9508     case bcmPortControlSerdesTuneMarginValue:
   9509         PORT_LOCK(unit);
   9510         
   9511         /* rv = soc_phyctrl_control_set(unit, port,
   9512            SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_VALUE, value);
   9513         */
   9514         PORT_UNLOCK(unit);
   9515         break;
   9516 
   9517     case bcmPortControlEEEEnable:
   9518         PORT_LOCK(unit);
   9519         rv = _bcm_esw_portctrl_control_eee_enable_set(unit, port,
   9520                                                       pport, value);
   9521         PORT_UNLOCK(unit);
   9522 
   9523         break;
   9524 
   9525     case bcmPortControlEEEStatisticsClear:
   9526         PORT_LOCK(unit);
   9527         
   9528         rv = _bcm_esw_portctrl_eee_statistics_clear(unit, port,
   9529                                                     pport, value);
   9530         PORT_UNLOCK (unit);
   9531         break;
   9532 
   9533 
   9534  /**********************      EEE Mode Overview    ************************
   9535  *                      |DET|                              |  WT |
   9536  *   Signalling   |idles|   |------------------------------|     | idles   |
   9537  *   from Tx MAC  | or  |   |   Low Power Idle (LPI)       |idles|  or     |
   9538  *   to local PHY |data |   |------------------------------|     | data    |
   9539  *                          *                              *
   9540  *                          *                              *
   9541  *                          *  -------LPI state------------*
   9542  *   Local PHY    |         |  |      |  |       |  |      |   |           |
   9543  *   signaling    |   Active|Ts|  Tq  |Tr|  Tq   |Tr|  Tq  |Tw |Active     |
   9544  *   on MDI       |         |  |      |  |       |  |      |   |           |
   9545  *                          *------------------------------*
   9546  *                          *                              *
   9547  *                          *                               *
   9548  *   Signaling    |   idles |-------------------------------|id| PHY is    |
   9549  *   from LP PHY  |     or  |  Low Power Idle (LPI)         |le| ready     |
   9550  *   to Rx MAC    |   data  |-------------------------------|s | for data  |
   9551  *
   9552  *   where DET = Delay Entry Timer    WT = Tx MAC Wake Timer
   9553  */
   9554     case bcmPortControlEEETransmitIdleTime:
   9555         /* DET = Time (in microsecs) for which condition to move to LPI state
   9556          * is satisfied, at the end of which MAC TX transitions to LPI state */
   9557         if (soc_feature (unit, soc_feature_eee)) {
   9558             portmod_eee_t eee;
   9559 
   9560             PORT_LOCK(unit);
   9561             rv = portmod_port_eee_get(unit, pport, &eee);
   9562             if (PORTMOD_SUCCESS(rv)) {
   9563                 eee.tx_idle_time = value;
   9564                 rv = portmod_port_eee_set(unit, pport, &eee);
   9565             }
   9566             PORT_UNLOCK(unit);
   9567         }
   9568         break;
   9569 
   9570     case bcmPortControlEEETransmitRefreshTime:
   9571         PORT_LOCK(unit);
   9572         
   9573         /* rv = soc_phyctrl_control_set(unit, port,
   9574            BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME, value);
   9575         */
   9576         PORT_UNLOCK (unit);
   9577         break;
   9578 
   9579     case bcmPortControlEEETransmitSleepTime:
   9580         PORT_LOCK (unit);
   9581         
   9582         /* rv = soc_phyctrl_control_set(unit, port,
   9583            BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME, value);
   9584         */
   9585         PORT_UNLOCK (unit);
   9586         break;
   9587 
   9588     case bcmPortControlEEETransmitQuietTime:
   9589         PORT_LOCK(unit);
   9590         
   9591         /* rv = soc_phyctrl_control_set(unit, port,
   9592            BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME, value);
   9593         */
   9594         PORT_UNLOCK (unit);
   9595         break;
   9596 
   9597     case bcmPortControlEEETransmitWakeTime:
   9598         /* Time(in microsecs) to wait before transmitter can leave LPI State*/
   9599         if (soc_feature (unit, soc_feature_eee)) {
   9600             portmod_eee_t eee;
   9601 
   9602             PORT_LOCK(unit);
   9603             rv = portmod_port_eee_get(unit, pport, &eee);
   9604             if (PORTMOD_SUCCESS(rv)) {
   9605                 eee.tx_wake_time = value;
   9606                 rv = portmod_port_eee_set(unit, pport, &eee);
   9607             }
   9608             PORT_UNLOCK(unit);
   9609         }
   9610         break;
   9611 
   9612      case bcmPortControlEEEReceiveSleepTime:
   9613         PORT_LOCK (unit);
   9614         
   9615         /* rv = soc_phyctrl_control_set(unit, port,
   9616            BCM_PORT_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME, value);
   9617         */
   9618         PORT_UNLOCK (unit);
   9619         break;
   9620 
   9621     case bcmPortControlEEEReceiveQuietTime:
   9622         PORT_LOCK(unit);
   9623         
   9624         /* rv = soc_phyctrl_control_set(unit, port,
   9625            BCM_PORT_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME, value);
   9626         */
   9627         PORT_UNLOCK(unit);
   9628         break;
   9629 
   9630     case bcmPortControlEEEReceiveWakeTime:
   9631         PORT_LOCK(unit);
   9632 
   9633         
   9634         /* rv = soc_phyctrl_control_set (unit, port,
   9635            BCM_PORT_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME, value);
   9636         */
   9637         PORT_UNLOCK(unit);
   9638         break;
   9639 
   9640     case bcmPortControlRxEnable:
   9641         rv = bcmi_esw_portctrl_mac_rx_control(unit, port, 0, &value);
   9642         break;
   9643     case bcmPortControlVrf:
   9644         rv = _bcm_esw_port_vrf_set(unit, port, value);
   9645         break;
   9646     case bcmPortControlTimestampEnable:
   9647         PORT_LOCK(unit);
   9648         rv = portmod_port_mac_timestamp_enable_set(unit, pport, value);
   9649         PORT_UNLOCK(unit);
   9650         break;
   9651     case bcmPortControlTXPISDMOverride:
   9652         {
   9653             portmod_txpi_override_t override;
   9654 
   9655             if (value < -100 || value > 100) {
   9656                 return BCM_E_PARAM;
   9657             }
   9658             override.enable = value ? 1 : 0;
   9659             override.value  = value;
   9660 
   9661             PORT_LOCK(unit);
   9662             rv = portmod_port_txpi_override_set(unit, pport, &override);
   9663             PORT_UNLOCK(unit);
   9664         }
   9665         break;
   9666     case bcmPortControlOOBFCTxReportIngEnable:
   9667         if (soc_feature(unit, soc_feature_oob_fc)) {
   9668 #ifdef BCM_TOMAHAWK3_SUPPORT
   9669             if (SOC_IS_TOMAHAWK3(unit)) {
   9670                 rv = bcm_th3_oob_fc_tx_port_control_set(unit, port, value, 0);
   9671             } else
   9672 #endif
   9673             {
   9674                 rv = BCM_E_UNAVAIL;
   9675             }
   9676         } else {
   9677             rv = BCM_E_UNAVAIL;
   9678         }
   9679         break;
   9680     case bcmPortControlOOBFCTxReportEgrEnable:
   9681         if (soc_feature(unit, soc_feature_oob_fc)) {
   9682 #ifdef BCM_TOMAHAWK3_SUPPORT
   9683             if (SOC_IS_TOMAHAWK3(unit)) {
   9684                 rv = bcm_th3_oob_fc_tx_port_control_set(unit, port, value, 1);
   9685             } else
   9686 #endif
   9687             {
   9688                 rv = BCM_E_UNAVAIL;
   9689             }
   9690         } else {
   9691             rv = BCM_E_UNAVAIL;
   9692         }
   9693         break;
   9694     default:
   9695         /* Control is not supported */
   9696         break;
   9697     }
   9698     return rv;
   9699 
   9700 #else  /* PORTMOD_SUPPORT */
   9701     return BCM_E_UNAVAIL;
   9702 #endif /* PORTMOD_SUPPORT */
   9703 }
   9704 
   9705 
   9706 /*
   9707  * Function:
   9708  *      bcmi_esw_portctrl_control_get
   9709  * Purpose:
   9710  *      Get the status of the specified port control feature.
   9711  * Parameters:
   9712  *      unit      - (IN) Unit number.
   9713  *      port      - (IN) Port number.
   9714  *      type      - (IN) Port control.
   9715  *      value     - (OUT) Value of port control feature.
   9716  * Returns:
   9717  *      BCM_E_XXX
   9718  * Notes:
   9719  *      Any new control needs to be included in
   9720  *      bcmi_esw_portctrl_control_validate().
   9721  */
   9722 int
   9723 bcmi_esw_portctrl_control_get(int unit, bcm_gport_t port,
   9724                               bcm_port_control_t type, int *value)
   9725 {
   9726 #ifdef PORTMOD_SUPPORT
   9727     int rv = BCM_E_UNAVAIL;
   9728     portctrl_pport_t pport;
   9729 
   9730     PORTCTRL_INIT_CHECK(unit);
   9731 
   9732     BCM_IF_ERROR_RETURN
   9733         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
   9734 
   9735     switch (type) {
   9736     case bcmPortControlPassControlFrames:
   9737         if (IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) ||
   9738             IS_CDE_PORT(unit, port) || IS_C_PORT(unit, port) ||
   9739             (IS_GE_PORT(unit, port)
   9740              && soc_feature(unit, soc_feature_unified_port))) {
   9741             if(soc_feature(unit, soc_feature_pgw_mac_control_frame)) {
   9742                 uint32 rval32 = 0;
   9743                 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32);
   9744                 if (BCM_SUCCESS(rv)) {
   9745                     /* PGW_MAC_RSV_MASK: Bit 11 Control Frame recieved
   9746                      * the bit value needs to be reversed
   9747                      */
   9748                     *value = ((rval32 & 0x800) >> 11) ? 0 : 1 ;
   9749                 }
   9750             } else {
   9751                 portmod_rx_control_t rx_control;
   9752                 PORT_LOCK(unit);
   9753                 rv = portmod_port_rx_control_get(unit, pport, &rx_control);
   9754                 PORT_UNLOCK(unit);
   9755                 if (PORTMOD_SUCCESS(rv)) {
   9756                     *value = rx_control.pass_control_frames;
   9757                 }
   9758             }
   9759         }
   9760         break;
   9761 
   9762     case bcmPortControlFrameSpacingStretch:
   9763         PORT_LOCK(unit);
   9764         rv = portmod_port_frame_spacing_stretch_get(unit, pport, value);
   9765         PORT_UNLOCK(unit);
   9766         break;
   9767 
   9768     case bcmPortControlPFCEthertype:
   9769         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9770             portmod_pfc_config_t pfc_config;
   9771 
   9772             PORT_LOCK(unit);
   9773             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9774             PORT_UNLOCK(unit);
   9775             if (PORTMOD_SUCCESS(rv)) {
   9776                 *value = pfc_config.type;
   9777             }
   9778         }
   9779         break;
   9780 
   9781     case bcmPortControlPFCOpcode:
   9782         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9783             portmod_pfc_config_t pfc_config;
   9784 
   9785             PORT_LOCK(unit);
   9786             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9787             PORT_UNLOCK(unit);
   9788             if (PORTMOD_SUCCESS(rv)) {
   9789                 *value = pfc_config.opcode;
   9790             }
   9791         }
   9792         break;
   9793 
   9794     case bcmPortControlPFCReceive:
   9795         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9796             portmod_pfc_control_t pfc_control;
   9797 
   9798             PORT_LOCK(unit);
   9799             rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9800             PORT_UNLOCK(unit);
   9801             if (PORTMOD_SUCCESS(rv)) {
   9802                 *value = pfc_control.rx_enable;
   9803             }
   9804         }
   9805         break;
   9806 
   9807     case bcmPortControlPFCTransmit:
   9808         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9809             portmod_pfc_control_t pfc_control;
   9810 
   9811             PORT_LOCK(unit);
   9812             rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9813             PORT_UNLOCK(unit);
   9814             if (PORTMOD_SUCCESS(rv)) {
   9815                 *value = pfc_control.tx_enable;
   9816             }
   9817         }
   9818         break;
   9819 
   9820     case bcmPortControlPFCClasses:
   9821         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9822             portmod_pfc_config_t pfc_config;
   9823 
   9824             PORT_LOCK(unit);
   9825             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9826             PORT_UNLOCK(unit);
   9827             if (PORTMOD_SUCCESS(rv)) {
   9828                 *value = pfc_config.classes;
   9829             }
   9830         }
   9831         break;
   9832 
   9833     case bcmPortControlPFCPassFrames:
   9834         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9835             if(soc_feature(unit, soc_feature_pgw_mac_pfc_frame)) {
   9836                 uint32 rval32 = 0;
   9837                 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32);
   9838                 if (BCM_SUCCESS(rv)) {
   9839                     /* PGW_MAC_RSV_MASK: Bit 18 PFC frame detected
   9840                      * the bit value needs to be reversed
   9841                      */
   9842                     *value = ((rval32 & 0x40000) >> 18) ? 0 : 1 ;
   9843                 }
   9844             } else {
   9845                 portmod_pfc_config_t pfc_config;
   9846 
   9847                 PORT_LOCK(unit);
   9848                 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9849                 PORT_UNLOCK(unit);
   9850                 if (PORTMOD_SUCCESS(rv)) {
   9851                     *value = pfc_config.rxpass;
   9852                 }
   9853             }
   9854         }
   9855         break;
   9856 
   9857     case bcmPortControlPFCDestMacOui:
   9858         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9859             portmod_pfc_config_t pfc_config;
   9860 
   9861             PORT_LOCK(unit);
   9862             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9863             PORT_UNLOCK(unit);
   9864             if (PORTMOD_SUCCESS(rv)) {
   9865                 *value = pfc_config.da_oui;
   9866             }
   9867         }
   9868         break;
   9869 
   9870     case bcmPortControlPFCDestMacNonOui:
   9871         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9872             portmod_pfc_config_t pfc_config;
   9873 
   9874             PORT_LOCK(unit);
   9875             rv = portmod_port_pfc_config_get(unit, pport, &pfc_config);
   9876             PORT_UNLOCK(unit);
   9877             if (PORTMOD_SUCCESS(rv)) {
   9878                 *value = pfc_config.da_nonoui;
   9879             }
   9880         }
   9881         break;
   9882 
   9883     case bcmPortControlPFCRefreshTime:
   9884         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9885             portmod_pfc_control_t pfc_control;
   9886 
   9887             PORT_LOCK(unit);
   9888             rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9889             PORT_UNLOCK(unit);
   9890             if (PORTMOD_SUCCESS(rv)) {
   9891                 *value = pfc_control.refresh_timer;
   9892             }
   9893         }
   9894         break;
   9895 
   9896     case bcmPortControlPFCXOffTime:
   9897         if (soc_feature(unit, soc_feature_priority_flow_control)) {
   9898             portmod_pfc_control_t pfc_control;
   9899 
   9900             PORT_LOCK(unit);
   9901             rv = portmod_port_pfc_control_get(unit, pport, &pfc_control);
   9902             PORT_UNLOCK(unit);
   9903             if (PORTMOD_SUCCESS(rv)) {
   9904                 *value = pfc_control.xoff_timer;
   9905             }
   9906         }
   9907         break;
   9908 
   9909     case bcmPortControlPrbsPolynomial:
   9910         rv = bcmi_esw_portctrl_phy_control_get(unit, port,
   9911              BCM_PORT_PHY_CONTROL_PRBS_POLYNOMIAL, (uint32 *)value);
   9912         break;
   9913     case bcmPortControlPrbsTxEnable:
   9914         rv = bcmi_esw_portctrl_phy_control_get(unit, port, 
   9915              BCM_PORT_PHY_CONTROL_PRBS_TX_ENABLE, (uint32 *)value);
   9916         break;
   9917 
   9918     case bcmPortControlPrbsRxEnable:
   9919         rv = bcmi_esw_portctrl_phy_control_get(unit, port, 
   9920              BCM_ESW_PORTCTRL_PHYCTRL_PRBS_RX_ENABLE, (uint32 *)value);
   9921         break;
   9922 
   9923     case bcmPortControlPrbsTxInvertData:
   9924         rv = bcmi_esw_portctrl_phy_control_get(unit, port, 
   9925              BCM_PORT_PHY_CONTROL_PRBS_TX_INVERT_DATA, (uint32 *)value);
   9926         break;
   9927 
   9928     case bcmPortControlPrbsRxStatus:
   9929         rv = bcmi_esw_portctrl_phy_control_get(unit, port, 
   9930              BCM_PORT_PHY_CONTROL_PRBS_RX_STATUS, (uint32 *)value);
   9931         break;
   9932 
   9933     case bcmPortControlLinkFaultLocalEnable:
   9934         {
   9935             portmod_local_fault_control_t control;
   9936 
   9937             PORT_LOCK(unit);
   9938             rv = portmod_port_local_fault_control_get(unit, pport, &control);
   9939             PORT_UNLOCK(unit);
   9940             if (PORTMOD_SUCCESS(rv)) {
   9941                 *value = control.enable;
   9942             }
   9943         }
   9944         break;
   9945     case bcmPortControlLinkFaultRemoteEnable:
   9946         {
   9947             portmod_remote_fault_control_t control;
   9948 
   9949             PORT_LOCK(unit);
   9950             rv = portmod_port_remote_fault_control_get(unit, pport, &control);
   9951             PORT_UNLOCK(unit);
   9952             if (PORTMOD_SUCCESS(rv)) {
   9953                 *value = control.enable;
   9954             }
   9955         }
   9956         break;
   9957 
   9958     case bcmPortControlLinkFaultLocal:
   9959         PORT_LOCK(unit);
   9960         rv = portmod_port_local_fault_status_get(unit, pport, value);
   9961         PORT_UNLOCK(unit);
   9962         break;
   9963 
   9964     case bcmPortControlLinkFaultRemote:
   9965         PORT_LOCK(unit);
   9966         rv = portmod_port_remote_fault_status_get(unit, pport, value);
   9967         PORT_UNLOCK(unit);
   9968         break;
   9969 
   9970     case bcmPortControlTimestampTransmit:
   9971         if (soc_feature(unit, soc_feature_timesync_support)) {
   9972             portmod_fifo_status_t info;
   9973 
   9974             PORT_LOCK(unit);
   9975             rv = portmod_port_diag_fifo_status_get(unit, pport, &info);
   9976             PORT_UNLOCK(unit);
   9977             if (PORTMOD_SUCCESS(rv)) {
   9978                 *value = info.timestamps_in_fifo;
   9979             }
   9980         }
   9981 
   9982         break;
   9983 
   9984     case bcmPortControlSerdesDriverEqualizationTuneStatusFarEnd:
   9985         PORT_LOCK(unit);
   9986         
   9987         /* rv = soc_phyctrl_control_get(unit, port,
   9988            SOC_PHY_CONTROL_SERDES_DRIVER_EQUALIZATION_TUNE_STATUS_FAR_END,
   9989            (uint32 *)value);
   9990         */
   9991         PORT_UNLOCK(unit);
   9992         break;
   9993 
   9994     case bcmPortControlLinkdownTransmit:
   9995         PORT_LOCK(unit);
   9996         rv = bcmi_esw_portctrl_phy_control_get(unit, port,
   9997                  BCM_PORT_PHY_CONTROL_LINKDOWN_TRANSMIT, (uint32 *)value);
   9998         PORT_UNLOCK(unit);
   9999         /* Most of PHYs have nothing to configure and simply return UNAVAIL*/
  10000         if ((rv == SOC_E_NONE) || (rv == SOC_E_UNAVAIL)) {
  10001             rv = _bcm_esw_link_down_tx_get(unit, port, value);
  10002         }
  10003         break;
  10004 
  10005     case bcmPortControlSerdesTuneMarginMode:
  10006         PORT_LOCK(unit);
  10007         
  10008         /* rv = soc_phyctrl_control_get(unit, port,
  10009            SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MODE,
  10010            (uint32 *)value);
  10011         */
  10012         PORT_UNLOCK(unit);
  10013         break;
  10014 
  10015     case bcmPortControlSerdesTuneMarginValue:
  10016         PORT_LOCK(unit);
  10017         
  10018         /* rv = soc_phyctrl_control_get(unit, port,
  10019            SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_VALUE,
  10020            (uint32 *)value);
  10021         */
  10022         PORT_UNLOCK(unit);
  10023         break;
  10024 
  10025     case bcmPortControlSerdesTuneMarginMax:
  10026         PORT_LOCK(unit);
  10027         
  10028         /* rv = soc_phyctrl_control_get(unit, port,
  10029            SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MAX,
  10030            (uint32 *)value);
  10031         */
  10032         PORT_UNLOCK(unit);
  10033         break;
  10034 
  10035     case bcmPortControlEEEEnable:
  10036         PORT_LOCK(unit);
  10037         if (soc_feature(unit, soc_feature_eee)) {
  10038             uint32 eeenative, eeeauto;
  10039             int rv1 = BCM_E_UNAVAIL, rv2 = BCM_E_UNAVAIL;
  10040 
  10041             rv = BCM_E_NONE;
  10042             rv1 = (bcmi_esw_portctrl_phy_control_get(unit, port,
  10043                                           BCM_PORT_PHY_CONTROL_EEE,
  10044                                           &eeenative));
  10045             if (rv1 != BCM_E_UNAVAIL) {
  10046                 *value = eeenative;
  10047         }
  10048             rv2 = (bcmi_esw_portctrl_phy_control_get(unit, port,
  10049                                           BCM_PORT_PHY_CONTROL_EEE_AUTO,
  10050                                           &eeeauto));
  10051             if (rv2 != BCM_E_UNAVAIL) {
  10052                 *value = eeeauto;
  10053             }
  10054 
  10055             /* If neither Native EEE nor AutoGrEEEn mode is supported */
  10056             if ((rv1 == BCM_E_UNAVAIL) && (rv2 == BCM_E_UNAVAIL)) {
  10057                 rv = BCM_E_UNAVAIL;
  10058             }
  10059 
  10060             /* If both Native EEE and AutoGrEEEn mode are supported */
  10061             if ((rv1 != SOC_E_UNAVAIL) && (rv2 != SOC_E_UNAVAIL)) {
  10062                 *value = eeenative ? (eeeauto ? 0 : 1) : (eeeauto ? 1 : 0);
  10063             }
  10064         } else {
  10065             rv = BCM_E_UNAVAIL;
  10066         }
  10067         PORT_UNLOCK (unit);
  10068         break;
  10069 
  10070  /**********************      EEE Mode Overview    ************************
  10071  *                      |DET|                              |  WT |
  10072  *   Signalling   |idles|   |------------------------------|     | idles   |
  10073  *   from Tx MAC  | or  |   |   Low Power Idle (LPI)       |idles|  or     |
  10074  *   to local PHY |data |   |------------------------------|     | data    |
  10075  *                          *                              *
  10076  *                          *                              *
  10077  *                          *  -------LPI state------------*
  10078  *   Local PHY    |         |  |      |  |       |  |      |   |           |
  10079  *   signaling    |   Active|Ts|  Tq  |Tr|  Tq   |Tr|  Tq  |Tw |Active     |
  10080  *   on MDI       |         |  |      |  |       |  |      |   |           |
  10081  *                          *------------------------------*
  10082  *                          *                              *
  10083  *                          *                               *
  10084  *   Signaling    |   idles |-------------------------------|id| PHY is    |
  10085  *   from LP PHY  |     or  |  Low Power Idle (LPI)         |le| ready     |
  10086  *   to Rx MAC    |   data  |-------------------------------|s | for data  |
  10087  *
  10088  *   where DET = Delay Entry Timer    WT = MAC Wake Timer
  10089  */
  10090     case bcmPortControlEEETransmitIdleTime:
  10091         /* DET = Time (in microsecs) for which condition to move to LPI state
  10092          * is satisfied, at the end of which MAC TX transitions to LPI state */
  10093         if (soc_feature (unit, soc_feature_eee)) {
  10094             portmod_eee_t eee;
  10095             PORT_LOCK(unit);
  10096             rv = portmod_port_eee_get(unit, pport, &eee);
  10097             PORT_UNLOCK(unit);
  10098             if (PORTMOD_SUCCESS(rv)) {
  10099                 *value = eee.tx_idle_time;
  10100             }
  10101         }
  10102 
  10103         break;
  10104 
  10105     case bcmPortControlEEETransmitEventCount:
  10106         /* Number of time MAC TX enters LPI state for
  10107          * a given measurement interval*/
  10108         if (soc_feature(unit, soc_feature_eee)) {
  10109             uint64 rval64;
  10110             
  10111             rv = READ_TX_EEE_LPI_EVENT_COUNTERr(unit, port, &rval64);
  10112             if (SOC_SUCCESS(rv)) {
  10113                 *value = COMPILER_64_LO(rval64);
  10114             }
  10115         }
  10116         break;
  10117 
  10118     case bcmPortControlEEETransmitDuration:
  10119         /* Time in (microsecs) for which MAC TX enters LPI state
  10120          * during a measurement interval*/
  10121         if (soc_feature(unit, soc_feature_eee)) {
  10122             uint64 rval64;
  10123 
  10124             rv = READ_TX_EEE_LPI_DURATION_COUNTERr(unit, port, &rval64);
  10125             if (SOC_SUCCESS(rv)) {
  10126                 *value = COMPILER_64_LO(rval64);
  10127             }
  10128         }
  10129 
  10130         break;
  10131 
  10132     case bcmPortControlEEEReceiveEventCount:
  10133         /* Number of time MAC RX enters LPI state for
  10134          * a given measurement interval */
  10135         if (soc_feature(unit, soc_feature_eee)) {
  10136             uint64 rval64;
  10137 
  10138             rv = READ_RX_EEE_LPI_EVENT_COUNTERr(unit, port, &rval64);
  10139             if (SOC_SUCCESS(rv)) {
  10140                 *value = COMPILER_64_LO(rval64);
  10141             }
  10142         }
  10143         break;
  10144 
  10145     case bcmPortControlEEEReceiveDuration:
  10146         /* Time in (microsecs) for which MAC RX enters LPI state
  10147          * during a measurement interval*/
  10148         if (soc_feature(unit, soc_feature_eee)) {
  10149             uint64 rval64;
  10150 
  10151             rv = READ_RX_EEE_LPI_DURATION_COUNTERr(unit, port, &rval64);
  10152             if (SOC_SUCCESS(rv)) {
  10153                 *value = COMPILER_64_LO(rval64);
  10154             }
  10155         }
  10156         break;
  10157 
  10158     case bcmPortControlEEETransmitRefreshTime:
  10159         PORT_LOCK(unit);
  10160         
  10161         /* rv = soc_phyctrl_control_get(unit, port,
  10162            BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME,
  10163            (uint32 *)value);
  10164         */
  10165         PORT_UNLOCK (unit);
  10166         break;
  10167 
  10168     case bcmPortControlEEETransmitSleepTime:
  10169         PORT_LOCK(unit);
  10170         
  10171         /* rv = soc_phyctrl_control_get(unit, port,
  10172            BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME, (uint32 *)value);
  10173         */
  10174         PORT_UNLOCK (unit);
  10175         break;
  10176 
  10177     case bcmPortControlEEETransmitQuietTime:
  10178         PORT_LOCK(unit);
  10179         
  10180         /* rv = soc_phyctrl_control_get(unit, port,
  10181            BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME, (uint32 *)value);
  10182         */
  10183         PORT_UNLOCK (unit);
  10184         break;
  10185 
  10186     case bcmPortControlEEETransmitWakeTime:
  10187         /* Time(in microsecs) to wait before transmitter can leave LPI State*/
  10188         if (soc_feature(unit, soc_feature_eee)) {
  10189             portmod_eee_t eee;
  10190 
  10191             PORT_LOCK(unit);
  10192             rv = portmod_port_eee_get(unit, pport, &eee);
  10193             PORT_UNLOCK(unit);
  10194             if (PORTMOD_SUCCESS(rv)) {
  10195                 *value = eee.tx_wake_time;
  10196             }
  10197         }
  10198         break;
  10199 
  10200     case bcmPortControlEEEReceiveSleepTime:
  10201         PORT_LOCK(unit);
  10202         
  10203         /* rv = soc_phyctrl_control_get(unit, port,
  10204            BCM_PORT_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME, (uint32 *)value);
  10205         */
  10206         PORT_UNLOCK(unit);
  10207         break;
  10208 
  10209     case bcmPortControlEEEReceiveQuietTime:
  10210         PORT_LOCK(unit);
  10211         
  10212         /* rv = soc_phyctrl_control_get(unit, port,
  10213            BCM_PORT_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME, (uint32 *)value);
  10214         */
  10215         PORT_UNLOCK(unit);
  10216         break;
  10217 
  10218     case bcmPortControlEEEReceiveWakeTime:
  10219         PORT_LOCK(unit);
  10220         
  10221         /* rv = soc_phyctrl_control_get(unit, port,
  10222            BCM_PORT_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME, (uint32 *)value);
  10223         */
  10224         PORT_UNLOCK(unit);
  10225         break;
  10226 
  10227     case bcmPortControlRxEnable:
  10228         rv = bcmi_esw_portctrl_mac_rx_control(unit, port, 1, value);
  10229         break;
  10230     case bcmPortControlVrf:
  10231         rv = _bcm_esw_port_vrf_get(unit, port, value);
  10232         break;
  10233     case bcmPortControlTimestampEnable:
  10234         PORT_LOCK(unit);
  10235         rv = portmod_port_mac_timestamp_enable_get(unit, pport, value);
  10236         PORT_UNLOCK(unit);
  10237         break;
  10238     case bcmPortControlTXPISDMOverride:
  10239         {
  10240             portmod_txpi_override_t override;
  10241 
  10242             PORT_LOCK(unit);
  10243             rv = portmod_port_txpi_override_get(unit, pport, &override);
  10244             *value = override.enable ? override.value : 0;
  10245             PORT_UNLOCK(unit);
  10246         }
  10247         break;
  10248     case bcmPortControlTXPISDMStatus:
  10249         PORT_LOCK(unit);
  10250         rv = portmod_port_txpi_sdm_data_get(unit, pport, value);
  10251         PORT_UNLOCK(unit);
  10252         break;
  10253     case bcmPortControlOOBFCTxReportIngEnable:
  10254         if (soc_feature(unit, soc_feature_oob_fc)) {
  10255 #ifdef BCM_TOMAHAWK3_SUPPORT
  10256             if (SOC_IS_TOMAHAWK3(unit)) {
  10257                 rv = bcm_th3_oob_fc_tx_port_control_get(unit, port, value, 0);
  10258             } else
  10259 #endif
  10260             {
  10261                 rv = BCM_E_UNAVAIL;
  10262             }
  10263         } else {
  10264             rv = BCM_E_UNAVAIL;
  10265         }
  10266         break;
  10267     case bcmPortControlOOBFCTxReportEgrEnable:
  10268         if (soc_feature(unit, soc_feature_oob_fc)) {
  10269 #ifdef BCM_TOMAHAWK3_SUPPORT
  10270             if (SOC_IS_TOMAHAWK3(unit)) {
  10271                 rv = bcm_th3_oob_fc_tx_port_control_get(unit, port, value, 1);
  10272             } else
  10273 #endif
  10274             {
  10275                 rv = BCM_E_UNAVAIL;
  10276             }
  10277         } else {
  10278             rv = BCM_E_UNAVAIL;
  10279         }
  10280         break;
  10281     default:
  10282         /* Control is not supported */
  10283         break;
  10284     }
  10285 
  10286     return rv;
  10287 
  10288 #else  /* PORTMOD_SUPPORT */
  10289     return BCM_E_UNAVAIL;
  10290 #endif /* PORTMOD_SUPPORT */
  10291 }
  10292 
  10293 /*
  10294  * Function:
  10295  *      bcmi_esw_portctrl_mode_get
  10296  * Description:
  10297  *      Get the current mode used for MAC
  10298  * Parameters:
  10299  *      unit(IN)  - Device number
  10300  *      port(IN)  - Port number
  10301  *      mode(OUT) - The configured MAC mode  
  10302  * Return Value:
  10303  *      BCM_E_XXX
  10304  */
  10305 int
  10306 bcmi_esw_portctrl_mode_get(int unit, bcm_gport_t port, int *mode)
  10307 {
  10308 #ifdef PORTMOD_SUPPORT
  10309     int rv = BCM_E_NONE;
  10310     portctrl_pport_t pport;
  10311     portmod_port_mode_info_t info;
  10312 
  10313     /* Make sure port module is initialized. */
  10314     PORTCTRL_INIT_CHECK(unit);
  10315     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10316 
  10317     portmod_port_mode_info_t_init(unit, &info);
  10318 
  10319     PORT_LOCK(unit);
  10320 
  10321     rv = portmod_port_mode_get(unit, pport, &info);
  10322 
  10323     PORT_UNLOCK(unit);
  10324 
  10325     if (PORTMOD_SUCCESS(rv)) {
  10326         *mode = info.cur_mode;
  10327     }
  10328 
  10329     return rv;
  10330 
  10331 #else   /* PORTMOD_SUPPORT */
  10332     return BCM_E_UNAVAIL;
  10333 #endif  /* PORTMOD_SUPPORT */
  10334 }
  10335 
  10336 /*
  10337  * Function:
  10338  *     bcmi_esw_portctrl_e2e_tx_enable_get
  10339  * Purpose:
  10340  *      Get E2E Enable
  10341  * Parameters:
  10342  *      unit - (IN) SOC unit number.
  10343  *      port - (IN) Port number.
  10344  *      enable - (OUT) Whether to enable or disable
  10345  * Returns:
  10346  *      BCM_E_xxx
  10347  */
  10348 int
  10349 bcmi_esw_portctrl_e2e_tx_enable_get(int unit, bcm_gport_t port, int *enable)
  10350 {
  10351 #ifdef PORTMOD_SUPPORT
  10352     int         rv;
  10353     portctrl_pport_t pport;
  10354 
  10355     /* Make sure port module is initialized. */
  10356     PORTCTRL_INIT_CHECK(unit);
  10357 
  10358     BCM_IF_ERROR_RETURN
  10359         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10360 
  10361     PORT_LOCK(unit);
  10362     rv = portmod_port_e2e_enable_get(unit, pport, enable);
  10363     PORT_UNLOCK(unit);
  10364 
  10365     return rv;
  10366 
  10367 #else  /* PORTMOD_SUPPORT */
  10368     return BCM_E_UNAVAIL;
  10369 #endif /* PORTMOD_SUPPORT */
  10370 }
  10371 
  10372 /*
  10373  * Function:
  10374  *     bcmi_esw_portctrl_e2e_tx_enable_set
  10375  * Purpose:
  10376  *      Set E2E Tx Enable
  10377  * Parameters:
  10378  *      unit - (IN) SOC unit number.
  10379  *      port - (IN) Port number.
  10380  *      enable - (IN) Whether to enable or disable
  10381  * Returns:
  10382  *      BCM_E_xxx
  10383  */
  10384 int
  10385 bcmi_esw_portctrl_e2e_tx_enable_set(int unit, bcm_gport_t port, int enable)
  10386 {
  10387 #ifdef PORTMOD_SUPPORT
  10388     int         rv;
  10389     portctrl_pport_t pport;
  10390 
  10391     /* Make sure port module is initialized. */
  10392     PORTCTRL_INIT_CHECK(unit);
  10393 
  10394     BCM_IF_ERROR_RETURN
  10395         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10396 
  10397     PORT_LOCK(unit);
  10398     rv = portmod_port_e2e_enable_set(unit, pport, enable);
  10399     PORT_UNLOCK(unit);
  10400 
  10401     return rv;
  10402 
  10403 #else  /* PORTMOD_SUPPORT */
  10404     return BCM_E_UNAVAIL;
  10405 #endif /* PORTMOD_SUPPORT */
  10406 }
  10407 
  10408 /*
  10409  * Function:
  10410  *     bcmi_esw_portctrl_e2ecc_hdr_get
  10411  * Purpose:
  10412  *      Get E2ECC header data
  10413  * Parameters:
  10414  *      unit - (IN) SOC unit number.
  10415  *      port - (IN) Port number.
  10416  *      e2ecc_hdr - (OUT) E2ECC header.
  10417  * Returns:
  10418  *      BCM_E_xxx
  10419  */
  10420 int
  10421 bcmi_esw_portctrl_e2ecc_hdr_get(int unit, bcm_gport_t port,
  10422                                soc_higig_e2ecc_hdr_t *e2ecc_hdr)
  10423 {
  10424 #ifdef PORTMOD_SUPPORT
  10425     int         rv;
  10426     portctrl_pport_t pport;
  10427     portmod_port_higig_e2ecc_hdr_t portmod_hdr;
  10428 
  10429     /* Make sure port module is initialized. */
  10430     PORTCTRL_INIT_CHECK(unit);
  10431 
  10432     if (!e2ecc_hdr) {
  10433         return BCM_E_PARAM;
  10434     }
  10435 
  10436     portmod_port_higig_e2ecc_hdr_t_init(unit, &portmod_hdr);
  10437 
  10438     BCM_IF_ERROR_RETURN
  10439         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10440 
  10441     PORT_LOCK(unit);
  10442     rv = portmod_port_e2ecc_hdr_get(unit, pport, &portmod_hdr);
  10443     PORT_UNLOCK(unit);
  10444 
  10445     if (PORTMOD_SUCCESS(rv)) {
  10446         sal_memcpy(e2ecc_hdr, &portmod_hdr, sizeof(soc_higig_e2ecc_hdr_t));
  10447     }
  10448 
  10449     return rv;
  10450 
  10451 #else  /* PORTMOD_SUPPORT */
  10452     return BCM_E_UNAVAIL;
  10453 #endif /* PORTMOD_SUPPORT */
  10454 }
  10455 
  10456 /*
  10457  * Function:
  10458  *     bcmi_esw_portctrl_e2ecc_hdr_set
  10459  * Purpose:
  10460  *      Set E2ECC header data
  10461  * Parameters:
  10462  *      unit - (IN) SOC unit number.
  10463  *      port - (IN) Port number.
  10464  *      e2ecc_hdr - (IN) E2ECC header.
  10465  * Returns:
  10466  *      BCM_E_xxx
  10467  */
  10468 int
  10469 bcmi_esw_portctrl_e2ecc_hdr_set(int unit, bcm_gport_t port,
  10470                                soc_higig_e2ecc_hdr_t *e2ecc_hdr)
  10471 {
  10472 #ifdef PORTMOD_SUPPORT
  10473     int         rv;
  10474     portctrl_pport_t pport;
  10475     portmod_port_higig_e2ecc_hdr_t portmod_hdr;
  10476 
  10477     /* Make sure port module is initialized. */
  10478     PORTCTRL_INIT_CHECK(unit);
  10479 
  10480     if (!e2ecc_hdr) {
  10481         return BCM_E_PARAM;
  10482     }
  10483 
  10484     portmod_port_higig_e2ecc_hdr_t_init(unit, &portmod_hdr);
  10485 
  10486     BCM_IF_ERROR_RETURN
  10487         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10488 
  10489     sal_memcpy(&portmod_hdr, e2ecc_hdr, sizeof(portmod_port_higig_e2ecc_hdr_t));
  10490 
  10491     PORT_LOCK(unit);
  10492     rv = portmod_port_e2ecc_hdr_set(unit, pport, &portmod_hdr);
  10493     PORT_UNLOCK(unit);
  10494 
  10495     return rv;
  10496 
  10497 #else  /* PORTMOD_SUPPORT */
  10498     return BCM_E_UNAVAIL;
  10499 #endif /* PORTMOD_SUPPORT */
  10500 }
  10501 
  10502 /*
  10503  * Function:
  10504  *     bcmi_esw_portctrl_vlan_tpid_set
  10505  * Purpose:
  10506  *      Set TPID in vlan_tag.
  10507  * Parameters:
  10508  *      unit - (IN) SOC unit number.
  10509  *      port - (IN) Port number.
  10510  *      tpid - (IN) tpid value.
  10511  * Returns:
  10512  *      BCM_E_xxx
  10513  */
  10514 int
  10515 bcmi_esw_portctrl_vlan_tpid_set(int unit, bcm_gport_t port, int tpid)
  10516 {
  10517 #ifdef PORTMOD_SUPPORT
  10518     int                rv;
  10519     portctrl_pport_t   pport;
  10520     portmod_vlan_tag_t vlan_tag;
  10521 
  10522     /* Make sure port module is initialized. */
  10523     PORTCTRL_INIT_CHECK(unit);
  10524 
  10525     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10526 
  10527     BCM_IF_ERROR_RETURN(portmod_port_vlan_tag_get(unit, port, &vlan_tag));
  10528 
  10529     vlan_tag.outer_vlan_tag = tpid;
  10530   
  10531     PORT_LOCK(unit);
  10532     rv = portmod_port_vlan_tag_set(unit, port, &vlan_tag);
  10533     PORT_UNLOCK(unit);
  10534 
  10535     return (rv);
  10536 #else  /* PORTMOD_SUPPORT */
  10537     return BCM_E_UNAVAIL;
  10538 #endif /* PORTMOD_SUPPORT */
  10539 }
  10540 
  10541 /*
  10542  * Function:
  10543  *     bcmi_esw_portctrl_vlan_inner_tpid_set
  10544  * Purpose:
  10545  *      Set TPID in vlan_tag.
  10546  * Parameters:
  10547  *      unit - (IN) SOC unit number.
  10548  *      port - (IN) Port number.
  10549  *      tpid - (IN) tpid value.
  10550  * Returns:
  10551  *      BCM_E_xxx
  10552  */
  10553 int
  10554 bcmi_esw_portctrl_vlan_inner_tpid_set(int unit, bcm_gport_t port, int tpid)
  10555 {
  10556 #ifdef PORTMOD_SUPPORT
  10557     int                rv;
  10558     portctrl_pport_t   pport;
  10559     portmod_vlan_tag_t vlan_tag;
  10560 
  10561     /* Make sure port module is initialized. */
  10562     PORTCTRL_INIT_CHECK(unit);
  10563 
  10564     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10565 
  10566     BCM_IF_ERROR_RETURN(portmod_port_vlan_tag_get(unit, port, &vlan_tag));
  10567 
  10568     vlan_tag.inner_vlan_tag = tpid;
  10569     
  10570   
  10571     PORT_LOCK(unit);
  10572     rv = portmod_port_vlan_tag_set(unit, port, &vlan_tag);
  10573     PORT_UNLOCK(unit);
  10574 
  10575     return (rv);
  10576 #else  /* PORTMOD_SUPPORT */
  10577     return BCM_E_UNAVAIL;
  10578 #endif /* PORTMOD_SUPPORT */
  10579 }
  10580 
  10581 /*
  10582  * Function:
  10583  *     bcmi_esw_portctrl_cntmaxsize_get
  10584  * Purpose:
  10585  *      Get the max packet size that is used in statistic counter update
  10586  * Parameters:
  10587  *      unit - (IN) SOC unit number.
  10588  *      port - (IN) Port number.
  10589  *      val - (OUT) max packet size.
  10590  * Returns:
  10591  *      BCM_E_xxx
  10592  */
  10593 int
  10594 bcmi_esw_portctrl_cntmaxsize_get(int unit, bcm_gport_t port, int *val)
  10595 {
  10596 #ifdef PORTMOD_SUPPORT
  10597     int         rv;
  10598     portctrl_pport_t pport;
  10599 
  10600 /* Make sure port module is initialized. */
  10601     PORTCTRL_INIT_CHECK(unit);
  10602 
  10603     BCM_IF_ERROR_RETURN
  10604         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10605 
  10606     PORT_LOCK(unit);
  10607     rv = portmod_port_cntmaxsize_get(unit, pport, val);
  10608     PORT_UNLOCK(unit);
  10609 
  10610     return rv;
  10611 #else  /* PORTMOD_SUPPORT */
  10612     return BCM_E_UNAVAIL;
  10613 #endif /* PORTMOD_SUPPORT */
  10614 }
  10615 /*
  10616  * Function:
  10617  *     bcmi_esw_portctrl_cntmaxsize_set
  10618  * Purpose:
  10619  *      Set the max packet size that is used in statistic counter update
  10620  * Parameters:
  10621  *      unit - (IN) SOC unit number.
  10622  *      port - (IN) Port number.
  10623  *      val - (IN) max packet size.
  10624  * Returns:
  10625  *      BCM_E_xxx
  10626  */
  10627 int
  10628 bcmi_esw_portctrl_cntmaxsize_set(int unit, bcm_gport_t port, int val)
  10629 {
  10630 #ifdef PORTMOD_SUPPORT
  10631     int         rv;
  10632     portctrl_pport_t pport;
  10633 
  10634     /* Make sure port module is initialized. */
  10635     PORTCTRL_INIT_CHECK(unit);
  10636 
  10637     BCM_IF_ERROR_RETURN
  10638         (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10639 
  10640     PORT_LOCK(unit);
  10641     rv = portmod_port_cntmaxsize_set(unit, pport, val);
  10642     PORT_UNLOCK(unit);
  10643 
  10644     return rv;
  10645 
  10646 #else  /* PORTMOD_SUPPORT */
  10647     return BCM_E_UNAVAIL;
  10648 #endif /* PORTMOD_SUPPORT */
  10649 }
  10650 
  10651 /*
  10652  * Function:
  10653  *     bcmi_esw_portctrl_cable_diag
  10654  * Description:
  10655  *      Run Cable Diagnostics on port
  10656  * Parameters:
  10657  *      unit - Device number
  10658  *      port - Port number
  10659  *      status - (OUT) cable diag status structure
  10660  * Return Value:
  10661  *      BCM_E_XXX
  10662  * Notes:
  10663  *      Cable diagnostics are only supported by some phy types
  10664  *      (currently 5248 10/100 phy and 546x 10/100/1000 phys)
  10665  */
  10666  int
  10667  bcmi_esw_portctrl_cable_diag(int unit, bcm_port_t port,
  10668                     bcm_port_cable_diag_t *status) 
  10669 {
  10670 #ifdef PORTMOD_SUPPORT
  10671     int rv = BCM_E_NONE;
  10672     portctrl_pport_t pport;
  10673     int ext_phy_present;
  10674 
  10675     /* Make sure port module is initialized. */
  10676     PORTCTRL_INIT_CHECK(unit);
  10677     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10678 
  10679     /* PORTMOD currently only supports medium config get for ports with legacy ext PHY */
  10680     SOC_IF_ERROR_RETURN(portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present));
  10681     if (!ext_phy_present) { 
  10682         return BCM_E_UNAVAIL; 
  10683     }
  10684 
  10685     PORT_LOCK(unit);
  10686     rv = soc_phyctrl_cable_diag(unit, port, status);
  10687     PORT_UNLOCK(unit);
  10688     
  10689     return rv;
  10690 
  10691 #else   /* PORTMOD_SUPPORT */
  10692     return BCM_E_UNAVAIL;
  10693 #endif  /* PORTMOD_SUPPORT */
  10694 }
  10695 
  10696 /*
  10697  * Function:
  10698  *      bcmi_esw_portctrl_preemption_status_tx_get
  10699  * Purpose:
  10700  *      get preemption tx status
  10701  * Parameters:
  10702  *      unit       - (IN) unit number.
  10703  *      port       - (IN) port number
  10704  *      value      - (OUT) value
  10705  * Returns:
  10706  *      BCM_E_XXX
  10707  * Notes:
  10708  */
  10709 int
  10710 bcmi_esw_portctrl_preemption_status_tx_get(int unit, bcm_port_t port,
  10711                                       uint32* value)
  10712 {
  10713 
  10714 #ifdef PORTMOD_SUPPORT
  10715      return (portmod_preemption_tx_status_get(unit, port ,
  10716                                                   value));
  10717 #endif 
  10718      return BCM_E_UNAVAIL; 
  10719 }
  10720 /*
  10721  * Function:
  10722  *      bcmi_esw_portctrl_preemption_status_verify_get
  10723  * Purpose:
  10724  *      get preemption verify status
  10725  * Parameters:
  10726  *      unit       - (IN) unit number.
  10727  *      port       - (IN) port number
  10728  *      value      - (OUT) value
  10729  * Returns:
  10730  *      BCM_E_XXX
  10731  * Notes:
  10732  */
  10733 int
  10734 bcmi_esw_portctrl_preemption_status_verify_get(int unit, bcm_port_t port,
  10735                                       uint32* value)
  10736 {
  10737 
  10738 #ifdef PORTMOD_SUPPORT
  10739     return (portmod_preemption_verify_status_get(unit, port , portmodPreemptionVerifyStatus,
  10740                  value));
  10741 #endif 
  10742      return BCM_E_UNAVAIL; 
  10743 }
  10744 /*
  10745  * Function:
  10746  *      bcmi_esw_portctrl_preemption_mac_config_set
  10747  * Purpose:
  10748  *      set preemption mac config
  10749  * Parameters:
  10750  *      unit       - (IN) unit number.
  10751  *      port       - (IN) port number
  10752  *      type       - (IN) Preemption control type
  10753  *      arg        - (IN) value
  10754  * Returns:
  10755  *      BCM_E_XXX
  10756  * Notes:
  10757  */
  10758 int
  10759 bcmi_esw_portctrl_preemption_mac_config_set(int unit, bcm_port_t port,
  10760                                    bcm_port_preempt_control_t type,
  10761                                    uint32 arg)
  10762 {
  10763  #ifdef PORTMOD_SUPPORT
  10764     portctrl_pport_t pport;
  10765 
  10766     /* Make sure port module is initialized. */
  10767    PORTCTRL_INIT_CHECK(unit);
  10768     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10769 
  10770     switch (type) {
  10771         case bcmPortPreemptControlPreemptionSupport:
  10772               return (portmod_preemption_control_set(unit, port ,
  10773                 portmodPreemptionControlPreemptionSupport, arg));
  10774         case bcmPortPreemptControlEnableTx:
  10775               return (portmod_preemption_control_set(unit, port ,
  10776                       portmodPreemptionControlEnableTx, arg));
  10777         case bcmPortPreemptControlVerifyEnable:
  10778               return (portmod_preemption_control_set(unit, port ,
  10779                       portmodPreemptionControlVerifyEnable, arg));
  10780         case bcmPortPreemptControlVerifyTime:
  10781               return (portmod_preemption_control_set(unit, port ,
  10782                       portmodPreemptionControlVerifyTime, arg));
  10783         case bcmPortPreemptControlVerifyAttempts:
  10784               return (portmod_preemption_control_set(unit, port ,
  10785                       portmodPreemptionControlVerifyAttempts, arg));
  10786         case bcmPortPreemptControlNonFinalFragSizeRx:
  10787               return (portmod_preemption_control_set(unit, port ,
  10788                       portmodPreemptionControlNonFinalFragSizeRx, arg));
  10789         case bcmPortPreemptControlFinalFragSizeRx:
  10790               return (portmod_preemption_control_set(unit, port ,
  10791                       portmodPreemptionControlFinalFragSizeRx, arg));
  10792         default:
  10793             return BCM_E_UNAVAIL;
  10794      }
  10795 #endif 
  10796      return BCM_E_UNAVAIL; 
  10797 }
  10798 /*
  10799  * Function:
  10800  *      bcmi_esw_portctrl_preemption_mac_config_get
  10801  * Purpose:
  10802  *      get preemption mac config
  10803  * Parameters:
  10804  *      unit       - (IN) unit number.
  10805  *      port       - (IN) port number
  10806  *      type       - (IN) Preemption control type
  10807  *      arg        - (OUT) value
  10808  * Returns:
  10809  *      BCM_E_XXX
  10810  * Notes:
  10811  */
  10812 int
  10813 bcmi_esw_portctrl_preemption_mac_config_get(int unit, bcm_port_t port,
  10814                                    bcm_port_preempt_control_t type,
  10815                                    uint32* arg)
  10816 {
  10817 
  10818 #ifdef PORTMOD_SUPPORT
  10819  portctrl_pport_t pport;
  10820 
  10821     /* Make sure port module is initialized. */
  10822     PORTCTRL_INIT_CHECK(unit);
  10823     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10824 
  10825    switch (type) {
  10826         case bcmPortPreemptControlPreemptionSupport:
  10827               return (portmod_preemption_control_get(unit, port ,
  10828                 portmodPreemptionControlPreemptionSupport, arg));
  10829         case bcmPortPreemptControlEnableTx:
  10830               return (portmod_preemption_control_get(unit, port ,
  10831                       portmodPreemptionControlEnableTx, arg));
  10832         case bcmPortPreemptControlVerifyEnable:
  10833               return (portmod_preemption_control_get(unit, port ,
  10834                       portmodPreemptionControlVerifyEnable, arg));
  10835         case bcmPortPreemptControlVerifyTime:
  10836               return (portmod_preemption_control_get(unit, port ,
  10837                       portmodPreemptionControlVerifyTime, arg));
  10838         case bcmPortPreemptControlVerifyAttempts:
  10839               return (portmod_preemption_control_get(unit, port ,
  10840                       portmodPreemptionControlVerifyAttempts, arg));
  10841         case bcmPortPreemptControlNonFinalFragSizeRx:
  10842               return (portmod_preemption_control_get(unit, port ,
  10843                       portmodPreemptionControlNonFinalFragSizeRx, arg));
  10844         case bcmPortPreemptControlFinalFragSizeRx:
  10845               return (portmod_preemption_control_get(unit, port ,
  10846                       portmodPreemptionControlFinalFragSizeRx, arg));
  10847         default:
  10848             return BCM_E_UNAVAIL;
  10849     }
  10850 #endif 
  10851      return BCM_E_UNAVAIL; 
  10852 }
  10853 
  10854 #if defined(INCLUDE_PHY_542XX)
  10855 /*
  10856  * Function:
  10857  *     bcmi_esw_portctrl_serdes_link_update
  10858  * Description:
  10859  *     Update the force link status of Serdes
  10860  * Parameters:
  10861  *      unit - Device number
  10862  *      port - Port number
  10863  *      link - Link Status of the port
  10864  * Return Value:
  10865  *      BCM_E_XXX
  10866  * Notes:
  10867  */
  10868  int
  10869  bcmi_esw_portctrl_serdes_link_update(int unit, bcm_port_t port, int link)
  10870 {
  10871 #ifdef PORTMOD_SUPPORT
  10872     portmod_port_update_control_t portmod_port_update_control;
  10873     int rv = BCM_E_NONE;
  10874     portctrl_pport_t pport;
  10875 
  10876     /* Make sure port module is initialized. */
  10877     PORTCTRL_INIT_CHECK(unit);
  10878     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10879 
  10880     SOC_IF_ERROR_RETURN(portmod_port_update_control_t_init(unit,
  10881                                            &portmod_port_update_control));
  10882     portmod_port_update_control.link_status = link;
  10883     PORTMOD_PORT_UPDATE_F_UPDATE_SERDES_LINK_SET(&portmod_port_update_control);
  10884     PORT_LOCK(unit);
  10885     rv = portmod_port_update(unit, port, &portmod_port_update_control);
  10886     PORT_UNLOCK(unit);
  10887     return rv;
  10888 #else   /* PORTMOD_SUPPORT */
  10889     return BCM_E_UNAVAIL;
  10890 #endif  /* PORTMOD_SUPPORT */
  10891 }
  10892 #endif
  10893 
  10894 /*
  10895  * Function:
  10896  *     bcmi_esw_portctrl_timestamp_adjust_set
  10897  * Purpose:
  10898  *     set OSTS,TSTS timestamp adjust based on speed
  10899  * Parameters:
  10900  *      unit - (IN) Unit number.
  10901  *      port - (IN) Port.
  10902  *      ts_adjust - (IN) configuration for tsts,osts timestamp adjustment.
  10903  * Returns:
  10904  *      BCM_E_xxx
  10905  * Notes:
  10906  */
  10907 int
  10908 bcmi_esw_portctrl_timestamp_adjust_set(int unit, bcm_gport_t port,
  10909                           bcm_port_timestamp_adjust_t *ts_adjust)
  10910 {
  10911 #ifdef PORTMOD_SUPPORT
  10912     int rv;
  10913     portctrl_pport_t pport;
  10914 
  10915     PORTCTRL_INIT_CHECK(unit);
  10916 
  10917     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10918 
  10919     PORT_LOCK(unit);
  10920     rv = portmod_port_timestamp_adjust_set(unit, pport, ts_adjust);
  10921     PORT_UNLOCK(unit);
  10922 
  10923     return rv;
  10924 #else /* PORTMOD_SUPPORT */
  10925     return BCM_E_UNAVAIL;
  10926 #endif /* PORTMOD_SUPPORT */
  10927 }
  10928 
  10929 /*
  10930  * Function:
  10931  *     bcmi_esw_portctrl_timestamp_adjust_get
  10932  * Purpose:
  10933  *     get OSTS,TSTS timestamp adjust based on current speed
  10934  * Parameters:
  10935  *      unit - (IN) Unit number.
  10936  *      port - (IN) Port.
  10937  *      ts_adjust - (OUT) configuration of tsts,osts timestamp adjustment.
  10938  * Returns:
  10939  *      BCM_E_xxx
  10940  * Notes:
  10941  */
  10942 int
  10943 bcmi_esw_portctrl_timestamp_adjust_get(int unit, bcm_gport_t port,
  10944                           bcm_port_timestamp_adjust_t *ts_adjust)
  10945 {
  10946 #ifdef PORTMOD_SUPPORT
  10947     int rv;
  10948     portctrl_pport_t pport;
  10949 
  10950     PORTCTRL_INIT_CHECK(unit);
  10951 
  10952     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  10953 
  10954     PORT_LOCK(unit);
  10955     rv = portmod_port_timestamp_adjust_get(unit, pport, ts_adjust);
  10956     PORT_UNLOCK(unit);
  10957 
  10958     return rv;
  10959 #else /* PORTMOD_SUPPORT */
  10960     return BCM_E_UNAVAIL;
  10961 #endif /* PORTMOD_SUPPORT */
  10962 }
  10963 
  10964 /* Function:
  10965  *     bcmi_esw_portctrl_phy_tx_set
  10966  * Purpose:
  10967  *     Set port phy tx properties
  10968  * Parameters:
  10969  *     unit - StrataSwitch Unit #.
  10970  *     port - StrataSwtich port #.
  10971  *     tx   - tx properties
  10972  * Returns:
  10973  *     BCM_E_NONE
  10974  *     BCM_E_XXX
  10975  */
  10976 int
  10977 bcmi_esw_portctrl_phy_tx_set(int unit,
  10978                                  bcm_port_t port,
  10979                                  bcm_port_phy_tx_t *tx)
  10980 {
  10981 #ifdef PORTMOD_SUPPORT
  10982     int rv;
  10983     portctrl_pport_t pport;
  10984     int phy_lane = -1;
  10985     int phyn = -1, sys_side = 0;
  10986     bcm_port_t local_port = -1;
  10987 
  10988     /* Make sure port module is initialized. */
  10989     PORTCTRL_INIT_CHECK(unit);
  10990 
  10991     BCM_IF_ERROR_RETURN(
  10992         _bcm_esw_port_gport_phyn_validate(unit, port,
  10993                                           &local_port, &phyn,
  10994                                           &phy_lane, &sys_side));
  10995 
  10996     if (local_port != -1) {
  10997         port = local_port;
  10998     }
  10999 
  11000     /* Only support for PM8x50 ports */
  11001     if (!IS_CD_PORT(unit, port)) {
  11002         return BCM_E_UNAVAIL;
  11003     }
  11004 
  11005     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  11006 
  11007     PORT_LOCK(unit);
  11008     port = local_port;
  11009 
  11010     rv = soc_esw_portctrl_phy_tx_set(unit, pport, phyn, phy_lane, sys_side, (soc_port_phy_tx_t *)tx);
  11011     PORT_UNLOCK(unit);
  11012 
  11013     return rv;
  11014 #else  /* PORTMOD_SUPPORT */
  11015     return BCM_E_UNAVAIL;
  11016 #endif /* PORTMOD_SUPPORT */
  11017 }
  11018 
  11019 /* Function:
  11020  *     bcmi_esw_portctrl_phy_tx_get
  11021  * Purpose:
  11022  *     Set port phy tx properties
  11023  * Parameters:
  11024  *     unit - StrataSwitch Unit #.
  11025  *     port - StrataSwtich port #.
  11026  *     tx   - tx properties
  11027  * Returns:
  11028  *     BCM_E_NONE
  11029  *     BCM_E_XXX
  11030  */
  11031 int
  11032 bcmi_esw_portctrl_phy_tx_get(int unit,
  11033                                  bcm_port_t port,
  11034                                  bcm_port_phy_tx_t *tx)
  11035 {
  11036 #ifdef PORTMOD_SUPPORT
  11037     int rv;
  11038     portctrl_pport_t pport;
  11039     int phy_lane = -1;
  11040     int phyn = -1, sys_side = 0;
  11041     bcm_port_t local_port = -1;
  11042 
  11043     /* Make sure port module is initialized. */
  11044     PORTCTRL_INIT_CHECK(unit);
  11045 
  11046     BCM_IF_ERROR_RETURN(
  11047         _bcm_esw_port_gport_phyn_validate(unit, port,
  11048                                           &local_port, &phyn,
  11049                                           &phy_lane, &sys_side));
  11050 
  11051     if (local_port != -1) {
  11052         port = local_port;
  11053     }
  11054 
  11055     /* Only support for PM8x50 ports */
  11056     if (!IS_CD_PORT(unit, port)) {
  11057         return BCM_E_UNAVAIL;
  11058     }
  11059 
  11060     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  11061 
  11062     PORT_LOCK(unit);
  11063     rv = soc_esw_portctrl_phy_tx_get(unit, pport, phyn, phy_lane, sys_side, (soc_port_phy_tx_t *)tx);
  11064 
  11065     PORT_UNLOCK(unit);
  11066 
  11067     return rv;
  11068 #else  /* PORTMOD_SUPPORT */
  11069     return BCM_E_UNAVAIL;
  11070 #endif /* PORTMOD_SUPPORT */
  11071 }
  11072 
  11073 /* Function:
  11074  *     bcmi_esw_portctrl_speed_config_get
  11075  * Purpose:
  11076  *     Fetch the speed config from portmod
  11077  * Parameters:
  11078  *     unit         - (IN)  StrataSwitch Unit #.
  11079  *     port         - (IN)  gport
  11080  *     speed_config - (OUT) pointer to speed_config datatype
  11081  * Returns:
  11082  *     BCM_E_NONE
  11083  *     BCM_E_XXX
  11084  */
  11085 int
  11086 bcmi_esw_portctrl_speed_config_get(int unit,
  11087                                    bcm_gport_t gport,
  11088                                    void *speed_config)
  11089 {
  11090 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT)
  11091     int pport;
  11092     int phy_port;
  11093     int lport;
  11094     int rv = BCM_E_UNAVAIL;
  11095     portmod_dispatch_type_t pm_type;
  11096 
  11097     if (NULL == speed_config) {
  11098         return BCM_E_PARAM;
  11099     }
  11100 
  11101     /* validate the gport to fetch the logical port */
  11102     BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, gport, &lport));
  11103     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport));
  11104 
  11105     /* get the port macro type */
  11106     phy_port = SOC_INFO(unit).port_l2p_mapping[lport];
  11107 #if defined(BCM_TOMAHAWK3_SUPPORT)
  11108     /* The PM4x10 requires a gap between the two management ports in TH3,
  11109      * so portmod sees the management ports as physical ports 257 and 259 while
  11110      * the SDK sees them as physical ports 257 and 258
  11111      */
  11112     if (SOC_IS_TOMAHAWK3(unit) && phy_port == 258) {
  11113         phy_port = 259;
  11114     }
  11115 #endif
  11116     BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type));
  11117 
  11118     /* if pm8x50, then fetch the speed config */
  11119     if (pm_type == portmodDispatchTypePm8x50) {
  11120         PORT_LOCK(unit);
  11121         rv = portmod_port_speed_config_get(unit, pport,
  11122                                 ((portmod_speed_config_t *)speed_config));
  11123         PORT_UNLOCK(unit);
  11124     }
  11125 
  11126     return rv;
  11127 #else
  11128     return BCM_E_UNAVAIL;
  11129 #endif
  11130 }
  11131 
  11132 /* Function:
  11133  *     bcmi_esw_portctrl_rlm_config_set
  11134  * Purpose:
  11135  *     Set port rlm properties
  11136  * Parameters:
  11137  *     unit - StrataSwitch Unit #.
  11138  *     port - StrataSwtich port #.
  11139  *     tx   - tx properties
  11140  *     enable - enable/disable
  11141  * Returns:
  11142  *     BCM_E_NONE
  11143  *     BCM_E_XXX
  11144  */
  11145 int
  11146 bcmi_esw_portctrl_rlm_config_set(int unit,
  11147                                  bcm_port_t port,
  11148                                  bcm_port_rlm_config_t *rlm_config,
  11149                                  int enable)
  11150 {
  11151 #ifdef PORTMOD_SUPPORT
  11152     int rv = BCM_E_NONE;
  11153     portctrl_pport_t pport;
  11154     int phy_lane = -1;
  11155     int phyn = -1, sys_side = 0;
  11156     bcm_port_t local_port = -1;
  11157     portmod_port_rlm_config_t portmod_rlm_config;
  11158 
  11159     /* Make sure port module is initialized. */
  11160     PORTCTRL_INIT_CHECK(unit);
  11161 
  11162     BCM_IF_ERROR_RETURN(
  11163         _bcm_esw_port_gport_phyn_validate(unit, port,
  11164                                           &local_port, &phyn,
  11165                                           &phy_lane, &sys_side));
  11166 
  11167     if (local_port != -1) {
  11168         port = local_port;
  11169     }
  11170 
  11171     /* Only support for PM8x50 ports */
  11172     if (!IS_CD_PORT(unit, port)) {
  11173         return BCM_E_UNAVAIL;
  11174     }
  11175 
  11176     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  11177 
  11178     PORT_LOCK(unit);
  11179 
  11180     portmod_rlm_config.active_lane_bit_map = rlm_config->active_lane_bit_map;
  11181     portmod_rlm_config.is_initiator = rlm_config->is_initiator;
  11182 
  11183     rv = portmod_port_rlm_config_set(unit, port, enable, &portmod_rlm_config);
  11184     PORT_UNLOCK(unit);
  11185 
  11186     return rv;
  11187 #else  /* PORTMOD_SUPPORT */
  11188     return BCM_E_UNAVAIL;
  11189 #endif /* PORTMOD_SUPPORT */
  11190 }
  11191 
  11192 /* Function:
  11193  *     bcmi_esw_portctrl_rlm_config_get
  11194  * Purpose:
  11195  *     Get port rlm properties
  11196  * Parameters:
  11197  *     unit - StrataSwitch Unit #.
  11198  *     port - StrataSwtich port #.
  11199  *     rlm_config - rlm properties
  11200  *     enable - enable/disable
  11201  * Returns:
  11202  *     BCM_E_NONE
  11203  *     BCM_E_XXX
  11204  */
  11205 int
  11206 bcmi_esw_portctrl_rlm_config_get(int unit,
  11207                                  bcm_port_t port,
  11208                                  bcm_port_rlm_config_t *rlm_config,
  11209                                  int *enable)
  11210 {
  11211 #ifdef PORTMOD_SUPPORT
  11212     int rv = BCM_E_NONE;
  11213     portctrl_pport_t pport;
  11214     int phy_lane = -1;
  11215     int phyn = -1, sys_side = 0;
  11216     bcm_port_t local_port = -1;
  11217     portmod_port_rlm_config_t portmod_rlm_config;
  11218 
  11219     /* Make sure port module is initialized. */
  11220     PORTCTRL_INIT_CHECK(unit);
  11221 
  11222     BCM_IF_ERROR_RETURN(
  11223         _bcm_esw_port_gport_phyn_validate(unit, port,
  11224                                           &local_port, &phyn,
  11225                                           &phy_lane, &sys_side));
  11226 
  11227     if (local_port != -1) {
  11228         port = local_port;
  11229     }
  11230 
  11231     /* Only support for PM8x50 ports */
  11232     if (!IS_CD_PORT(unit, port)) {
  11233         return BCM_E_UNAVAIL;
  11234     }
  11235 
  11236     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  11237 
  11238     PORT_LOCK(unit);
  11239     rv = portmod_port_rlm_config_get(unit, port, enable, &portmod_rlm_config);
  11240     rlm_config->active_lane_bit_map = portmod_rlm_config.active_lane_bit_map;
  11241     rlm_config->is_initiator = portmod_rlm_config.is_initiator;
  11242 
  11243     PORT_UNLOCK(unit);
  11244 
  11245     return rv;
  11246 #else  /* PORTMOD_SUPPORT */
  11247     return BCM_E_UNAVAIL;
  11248 #endif /* PORTMOD_SUPPORT */
  11249 }
  11250 
  11251 /* Function:
  11252  *     bcmi_esw_portctrl_rlm_status_get
  11253  * Purpose:
  11254  *     Get port rlm status
  11255  * Parameters:
  11256  *     unit - StrataSwitch Unit #.
  11257  *     port - StrataSwtich port #.
  11258  *     rlm_status - rlm status
  11259  * Returns:
  11260  *     BCM_E_NONE
  11261  *     BCM_E_XXX
  11262  */
  11263 int
  11264 bcmi_esw_portctrl_rlm_status_get(int unit,
  11265                                  bcm_port_t port,
  11266                                  bcm_port_rlm_status_t *rlm_status)
  11267 {
  11268 #ifdef PORTMOD_SUPPORT
  11269     int rv = BCM_E_NONE;
  11270     portctrl_pport_t pport;
  11271     int phy_lane = -1;
  11272     int phyn = -1, sys_side = 0;
  11273     bcm_port_t local_port = -1;
  11274     portmod_port_rlm_status_t portmod_rlm_status;
  11275 
  11276     /* Make sure port module is initialized. */
  11277     PORTCTRL_INIT_CHECK(unit);
  11278 
  11279     BCM_IF_ERROR_RETURN(
  11280         _bcm_esw_port_gport_phyn_validate(unit, port,
  11281                                           &local_port, &phyn,
  11282                                           &phy_lane, &sys_side));
  11283 
  11284     if (local_port != -1) {
  11285         port = local_port;
  11286     }
  11287 
  11288     /* Only support for PM8x50 ports */
  11289     if (!IS_CD_PORT(unit, port)) {
  11290         return BCM_E_UNAVAIL;
  11291     }
  11292 
  11293     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  11294 
  11295     PORT_LOCK(unit);
  11296     /* get the portmod RLM status */
  11297     rv = portmod_port_rlm_status_get(unit, port, &portmod_rlm_status);
  11298     if (portmod_rlm_status.rlm_busy) {
  11299         *rlm_status = bcmPortRlmBusy;
  11300     } else if (portmod_rlm_status.rlm_disabled) {
  11301         *rlm_status = bcmPortRlmDisabled;
  11302     } else if (portmod_rlm_status.rlm_done) {
  11303         *rlm_status = bcmPortRlmDone;
  11304     } else if (portmod_rlm_status.rlm_failed) {
  11305         *rlm_status = bcmPortRlmFailed;
  11306     } else {
  11307         return BCM_E_UNAVAIL;
  11308     }
  11309 
  11310     PORT_UNLOCK(unit);
  11311 
  11312     return rv;
  11313 #else  /* PORTMOD_SUPPORT */
  11314     return BCM_E_UNAVAIL;
  11315 #endif /* PORTMOD_SUPPORT */
  11316 }
  11317 
  11318 /* Function:
  11319  *     bcmi_esw_portctrl_autoneg_status_get
  11320  * Purpose:
  11321  *     Get port autoneg status
  11322  * Parameters:
  11323  *     unit - StrataSwitch Unit #.
  11324  *     port - StrataSwtich port #.
  11325  *     enabled - if AN is enabled
  11326  *     locked  - if AN is locked
  11327  * Returns:
  11328  *     BCM_E_NONE
  11329  *     BCM_E_XXX
  11330  */
  11331 int
  11332 bcmi_esw_portctrl_autoneg_status_get(int unit,
  11333                                      bcm_gport_t port,
  11334                                      int *enabled,
  11335                                      int *locked)
  11336 
  11337 {
  11338     int rv = BCM_E_NONE;
  11339 #ifdef PORTMOD_SUPPORT
  11340     portctrl_pport_t pport;
  11341     phymod_autoneg_status_t an_status;
  11342 
  11343     PORTCTRL_INIT_CHECK(unit);
  11344 
  11345     BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport));
  11346 
  11347     PORT_LOCK(unit);
  11348 
  11349     rv = portmod_port_autoneg_status_get(unit, pport, &an_status);
  11350 
  11351     PORT_UNLOCK(unit);
  11352 
  11353     *enabled = an_status.enabled;
  11354     *locked = an_status.locked;
  11355 #endif
  11356     return rv;
  11357 }