openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

port.c (57979B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        port.c
      8  * Purpose:     Port driver.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 
     15 #if defined(BCM_MONTEREY_SUPPORT)
     16 #include <soc/drv.h>
     17 #include <soc/types.h>
     18 #include <soc/monterey.h>
     19 #include <soc/apache.h>
     20 #include <bcm_int/esw_dispatch.h>
     21 #include <bcm_int/esw/port.h>
     22 #include <bcm_int/esw/stack.h>
     23 #include <bcm_int/esw/portctrl.h>
     24 #include <bcm_int/esw/xgs5.h>
     25 #include <bcm_int/esw/trident2.h>
     26 #include <bcm_int/esw/trident2plus.h>
     27 #include <bcm_int/esw/monterey.h>
     28 #include <bcm_int/esw/apache.h>
     29 #include <bcm/error.h>
     30 #include <bcm/port.h>
     31 
     32 #define MN_FLEX_MAX_NUM_PORTS        65
     33 
     34 #define IS_MN_HSP_PORT(u,p)   \
     35     ((_soc_apache_port_sched_type_get((u),(p)) == SOC_APACHE_SCHED_HSP) ? 1 : 0)
     36 
     37 /*
     38  * Function:
     39  *      _bcm_monterey_port_mac_get
     40  * Description:
     41  *      Get EGR_PORT/LPORT table mac address
     42  * Parameters:
     43  *      unit    - (IN)  BCM device number
     44  *      port    - (IN)  Port number if valid.
     45  *      oui     - (IN)  Indicates mac field is OUI/Non-OUI
     46  *      mac     - (OUT) OUI/Non-OUI part of MAC-ADDRESS
     47  * Return Value:
     48  *      BCM_E_XXX
     49  */
     50 int
     51 _bcm_monterey_port_mac_get(int unit, bcm_port_t port, int oui, uint32* mac)
     52 {
     53     egr_port_entry_t   egr_port_entry;
     54     bcm_module_t       modid;
     55     bcm_port_t         local_port;
     56     bcm_trunk_t        tgid;
     57     int                id;
     58     int                is_local = FALSE;
     59     soc_field_t        field;
     60 
     61     if (oui) {
     62         field = MAC_ADDRESS_UPPERf;
     63     } else {
     64         field = MAC_ADDRESS_LOWERf;
     65     }
     66 
     67     if (BCM_GPORT_IS_SET(port)) {
     68 
     69         /* GPORT Validations */
     70         BCM_IF_ERROR_RETURN(
     71            _bcm_esw_gport_resolve(
     72                           unit, port, &modid, &local_port, &tgid, &id));
     73 
     74         if (-1 == local_port) {
     75             return BCM_E_PARAM;
     76         }
     77 
     78         BCM_IF_ERROR_RETURN(
     79                            _bcm_esw_modid_is_local(unit, modid, &is_local));
     80         if (!is_local) {
     81             return BCM_E_PARAM;
     82         }
     83 
     84         /* For subports get from EGR_LPORT_PROFILE table */
     85         if (BCM_GPORT_IS_SUBPORT_PORT(port)) {
     86             return bcm_esw_port_egr_lport_field_get(unit,
     87                                                     port,
     88                                                     EGR_LPORT_PROFILEm,
     89                                                     field,
     90                                                     mac);
     91         }
     92 
     93 
     94     } else {
     95         BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &local_port));
     96     }
     97 
     98     SOC_IF_ERROR_RETURN(
     99             READ_EGR_PORTm(unit, MEM_BLOCK_ANY, local_port, &egr_port_entry));
    100 
    101     *mac = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, field);
    102 
    103     return BCM_E_NONE;
    104 }
    105 
    106 /*
    107  * Function:
    108  *      _bcm_monterey_port_mac_set
    109  * Description:
    110  *      Configure EGR_PORT/LPORT table mac address
    111  * Parameters:
    112  *      unit  - (IN) BCM device number
    113  *      port  - (IN) Port number if valid.
    114  *      oui   - (IN) Indicates mac field is OUI/Non-OUI
    115  *      mac   - (IN) OUI/Non-OUI part of MAC-ADDRESS
    116  * Return Value:
    117  *      BCM_E_XXX
    118  */
    119 int
    120 _bcm_monterey_port_mac_set(int unit, bcm_port_t port, int oui, uint32 mac)
    121 {
    122     egr_port_entry_t   egr_port_entry;
    123     bcm_module_t       modid;
    124     bcm_port_t         local_port;
    125     bcm_trunk_t        tgid;
    126     int                id;
    127     int                is_local = FALSE;
    128     soc_field_t        field;
    129 
    130     if (oui) {
    131         field = MAC_ADDRESS_UPPERf;
    132     } else {
    133         field = MAC_ADDRESS_LOWERf;
    134     }
    135 
    136     if (BCM_GPORT_IS_SET(port)) {
    137 
    138         /* GPORT Validations */
    139         BCM_IF_ERROR_RETURN(
    140             _bcm_esw_gport_resolve(
    141                                    unit, port, &modid, &local_port, &tgid, &id));
    142 
    143         if (-1 == local_port) {
    144             return BCM_E_PARAM;
    145         }
    146 
    147         BCM_IF_ERROR_RETURN(
    148                            _bcm_esw_modid_is_local(unit, modid, &is_local));
    149         if (!is_local) {
    150             return BCM_E_PARAM;
    151         }
    152 
    153         /* For subports set the EGR_LPORT_PROFILE table */
    154         if (BCM_GPORT_IS_SUBPORT_PORT(port)) {
    155             return bcm_esw_port_egr_lport_field_set(unit,
    156                                                     port,
    157                                                     EGR_LPORT_PROFILEm,
    158                                                     field,
    159                                                     mac);
    160         }
    161 
    162     } else {
    163         BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &local_port));
    164     }
    165 
    166 
    167     SOC_IF_ERROR_RETURN(
    168                  READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry));
    169 
    170     soc_EGR_PORTm_field_set(unit, &egr_port_entry, field, &mac);
    171 
    172     SOC_IF_ERROR_RETURN(
    173             WRITE_EGR_PORTm(unit, MEM_BLOCK_ALL, port, &egr_port_entry));
    174 
    175     return BCM_E_NONE;
    176 }
    177 
    178 
    179 
    180 /*
    181  * FlexPort Operations Changes
    182  *
    183  * Flags to be used to determine the type of operations required
    184  * when the FlexPort API multi_set() is called.
    185  *
    186  * OP_NONE  - No changes.
    187  * OP_PMAP  - Change in port mapping.  It requires FlexPort sequence.
    188  * OP_LANES - Change in lanes.  It requires FlexPort sequence.
    189  * OP_SPEED - Change in speed.  This is covered in a FlexPort sequence.
    190  *            A change in speed may require a FlexPort sequence.
    191  *            If it is not required, then calling the 'speed' set
    192  *            function is sufficient.
    193  * OP_ENCAP - Change in encap mode.  It is NOT covered in a FlexPort
    194  *            sequence, so an explicit call must be made to change
    195  *            the encap mode.
    196  * OP_ALL   - All the above.  It requires FlexPort sequence.  
    197  */
    198 #define BCM_MN_PORT_RESOURCE_OP_NONE     0
    199 #define BCM_MN_PORT_RESOURCE_OP_PMAP    (1 << 0)
    200 #define BCM_MN_PORT_RESOURCE_OP_LANES   (1 << 1)
    201 #define BCM_MN_PORT_RESOURCE_OP_SPEED   (1 << 2)
    202 #define BCM_MN_PORT_RESOURCE_OP_ENCAP   (1 << 3)
    203 #define BCM_MN_PORT_RESOURCE_OP_ALL           \
    204     (BCM_MN_PORT_RESOURCE_OP_PMAP  |          \
    205      BCM_MN_PORT_RESOURCE_OP_LANES |          \
    206      BCM_MN_PORT_RESOURCE_OP_SPEED |          \
    207      BCM_MN_PORT_RESOURCE_OP_ENCAP) 
    208 
    209 /*
    210  * Internal BCM Port Resource Configuration
    211  */
    212 typedef struct bcm_monterey_port_resource_s {
    213     uint32 flags;              /* SOC_PORT_RESOURCE_XXX */
    214     bcm_gport_t port;          /* Local logical port number to connect to
    215                                   the given physical port */
    216     int physical_port;         /* Local physical port, -1 if the logical to
    217                                   physical mapping is to be deleted */
    218     int speed;                 /* Initial speed after FlexPort operation */
    219     int lanes;                 /* Number of PHY lanes for this physical port */
    220     bcm_port_encap_t encap;    /* Encapsulation mode for port */
    221     int roe_compression;       /* cpri compression enabled */
    222 } bcm_monterey_port_resource_t;
    223 
    224 
    225 
    226 /*
    227  * Forward static function declaration
    228  */
    229 STATIC int
    230 _bcm_monterey_port_resource_multi_set(int unit, 
    231                                     int nport, bcm_port_resource_t *resource);
    232 STATIC int
    233 _bcm_monterey_port_resource_speed_set(int unit, bcm_port_t port, int speed);
    234 
    235 
    236 /*
    237  * Device Specific HW Tables
    238  */
    239 
    240 /* Egr port table */
    241 static bcmi_xgs5_port_redirection_egr_port_table_t
    242             bcmi_monterey_port_redirection_egr_port_table = {
    243     /* mem */ 	              EGR_PORTm,
    244     /* dest_type */           ER_REDIR_DEST_TYPEf,
    245     /* dest_value */          ER_REDIR_DESTINATIONf,
    246     /* drop_original */       ER_REDIR_DROP_ORIGINALf,
    247     /* pkt_priority */        ER_REDIR_NEW_PRIf,
    248     /* pkt_change_priority */ ER_REDIR_CHANGE_PRIf,
    249     /* pkt_color */           ER_REDIR_NEW_COLORf,
    250     /* pkt_change_color */    ER_REDIR_CHANGE_COLORf,
    251     /* strength */            ER_REDIR_STRENGTHf,
    252     /* buffer_priority */     ER_REDIR_RDB_PRIORITYf,
    253     /* action */              ER_REDIR_ACTIONf,
    254     /* redir_pkt_source */    ER_REDIR_SOURCEf,
    255     /* redir_pkt_truncate */  ER_REDIR_FIRST_CELL_ONLYf
    256 };
    257 
    258 /* HW Definitions */
    259 static bcmi_xgs5_port_hw_defs_t  bcmi_monterey_port_hw_defs;
    260 
    261 
    262 /*
    263  * Function Vector
    264  */
    265 static bcm_esw_port_drv_t bcm_monterey_port_drv = {
    266     /* fn_drv_init                */ bcmi_monterey_port_fn_drv_init,
    267     /* resource_set               */ bcmi_xgs5_port_resource_set,
    268     /* resource_get               */ bcmi_xgs5_port_resource_get,
    269     /* resource_multi_set         */ _bcm_monterey_port_resource_multi_set,
    270     /* resource_speed_set         */ _bcm_monterey_port_resource_speed_set,
    271     /* resource_traverse          */ bcmi_xgs5_port_resource_traverse,
    272     /* port_redirect_set          */ bcmi_xgs5_port_redirect_config_set,
    273     /* port_redirect_get          */ bcmi_xgs5_port_redirect_config_get,
    274     /* port_enable_set            */ NULL,
    275     /* encap_speed_check          */ NULL,
    276     /* force_lb_set               */ NULL,
    277     /* force_lb_check             */ NULL,
    278     /* resource_status_update     */ bcmi_xgs5_port_resource_status_update
    279 
    280 };
    281 
    282 
    283 /*
    284  * Function:
    285  *      bcmi_monterey_port_fn_drv_init
    286  * Purpose:
    287  *      Initialize the Port function driver.
    288  * Parameters:
    289  *      unit - (IN) Unit number.
    290  * Returns:
    291  *      BCM_E_xxx
    292  * Notes:
    293  */
    294 int
    295 bcmi_monterey_port_fn_drv_init(int unit)
    296 {
    297     /* HW Definition Tables */
    298     sal_memset(&bcmi_monterey_port_hw_defs, 0,
    299                sizeof(bcmi_monterey_port_hw_defs));
    300     bcmi_monterey_port_hw_defs.egr_port =
    301         &bcmi_monterey_port_redirection_egr_port_table;
    302 
    303     /* Initialize Common XGS5 Port module */
    304     BCM_IF_ERROR_RETURN
    305         (bcmi_xgs5_port_fn_drv_init(unit, &bcm_monterey_port_drv, NULL,
    306                             &bcmi_monterey_port_hw_defs));
    307 
    308     return BCM_E_NONE;
    309 }
    310 
    311 
    312 /*
    313  * Function:
    314  *      _bcm_monterey_port_attach
    315  * Purpose:
    316  *      Attach given port to the BCM layer and initialize it
    317  *      to its default state.
    318  * Parameters:
    319  *      unit     - (IN) Unit number.
    320  *      port     - (IN) Logical port, BCM format.
    321  * Returns:
    322  *      BCM_E_XXX
    323  * Note:
    324  *      - Assumes port is a valid BCM logical port.
    325  *      - Assumes function is called when a new port is added into the system,
    326  *        so it is not called during WarmBoot.
    327  *      - Assumes BCM PORT module initialization routine has
    328  *        been called.
    329  *      - Assumes this is NOT called during Warmboot.
    330  */
    331 STATIC int
    332 _bcm_monterey_port_attach(int unit, bcm_port_t port)
    333 {
    334     int rv = BCM_E_NONE;
    335      rv = bcm_mn_cosq_default_llfc_profile_attach(unit, port);
    336      if (BCM_FAILURE(rv)) {
    337          LOG_ERROR(BSL_LS_BCM_PORT,
    338          (BSL_META_U(unit,
    339                     "Unable to add default entries for PRIO2COS_PROFILE"
    340                      "register profile unit=%d port=%d rv=%d\n"),
    341                      unit, port, rv));
    342           return rv;
    343     }
    344     rv = bcm_esw_td2p_flexport_port_attach(unit, port);
    345     BCM_IF_ERROR_RETURN(rv);
    346     BCM_IF_ERROR_RETURN(
    347 
    348     bcm_mn_cosq_flex_port_update( unit , port , TRUE));
    349      rv = _bcm_mn_port_hsp_config_set(unit, port);
    350       if (BCM_FAILURE(rv)) {
    351           LOG_ERROR(BSL_LS_BCM_PORT,
    352                    (BSL_META_U(unit,
    353                              "Error: Unable config HSP node "
    354                                "unit=%d port=%d rv=%d\n"),
    355                        unit, port, rv));
    356             return rv;
    357         }
    358         SOC_IF_ERROR_RETURN(
    359            soc_monterey_port_mmu_tx_enable_set(unit, port, 1));
    360         
    361     SOC_IF_ERROR_RETURN(
    362        soc_monterey_port_edb_reset(unit, port));
    363  
    364     rv = soc_monterey_mmu_config_init(unit, 0, port);
    365     BCM_IF_ERROR_RETURN(rv);
    366 
    367 
    368     return BCM_E_NONE;
    369 }
    370 
    371 
    372 /*
    373  * Function:
    374  *      _bcm_monterey_port_detach
    375  * Purpose:
    376  *      Detach given port from the BCM layer and clear any data
    377  *      that is normally configured when a port is initialized.
    378  * Parameters:
    379  *      unit     - (IN) Unit number.
    380  *      port     - (IN) Logical port, BCM format.
    381  * Returns:
    382  *      BCM_E_XXX
    383  * Note:
    384  *      - Assumes port is a valid BCM logical port.
    385  *      - Assumes this is NOT called during Warmboot.
    386  */
    387 STATIC int
    388 _bcm_monterey_port_detach(int unit, bcm_port_t port)
    389 {
    390     bcm_gport_t gport;
    391     int rv = BCM_E_NONE;
    392 
    393     rv = bcm_esw_td2p_flexport_port_detach(unit, port);
    394     if (BCM_FAILURE(rv)) {
    395         LOG_ERROR(BSL_LS_BCM_PORT,
    396                   (BSL_META_U(unit,
    397                               "Error: Unable to detach BCM port "
    398                               "unit=%d port=%d rv=%d\n"),
    399                    unit, port, rv));
    400         return rv;
    401     }
    402     
    403     rv = bcm_mn_cosq_llfc_profile_detach(unit, port);
    404     if (BCM_FAILURE(rv)) {
    405         LOG_ERROR(BSL_LS_BCM_PORT,
    406         (BSL_META_U(unit,
    407         "Unable to delete default entries for PRIO2COS_PROFILE"
    408         "register profile unit=%d port=%d rv=%d\n"),
    409           unit, port, rv));
    410         return rv;
    411    } 
    412     /* Delete CoS queue tree */
    413     rv = bcm_esw_port_gport_get(unit, port, &gport);
    414     if (BCM_FAILURE(rv)) {
    415         LOG_ERROR(BSL_LS_BCM_PORT,
    416                   (BSL_META_U(unit,
    417                               "Error: Unable to retrieve gport "
    418                               "unit=%d port=%d rv=%d\n"),
    419                    unit, port, rv));
    420         return rv;
    421     }
    422 
    423     rv = bcm_mn_cosq_gport_delete(unit, gport);
    424     if (BCM_FAILURE(rv)) {
    425         LOG_ERROR(BSL_LS_BCM_PORT,
    426                   (BSL_META_U(unit,
    427                               "Error: Unable to destroy LLS tree "
    428                               "unit=%d port=%d rv=%d\n"),
    429                    unit, port, rv));
    430         return rv;
    431     }
    432     BCM_IF_ERROR_RETURN(
    433     bcm_mn_cosq_flex_port_update( unit , port , FALSE));
    434 
    435     return BCM_E_NONE;
    436 }
    437 
    438 
    439 /*
    440  * Function:
    441  *      bcm_monterey_flexport_pbmp_update
    442  * Description:
    443  *      Returns bitmap of max valid ports
    444  * Parameters:
    445  *      unit    - (IN) BCM device number
    446  *      pbmp    - (IN/OUT) port bit map
    447  */
    448 
    449 int
    450 bcm_monterey_flexport_pbmp_update(int unit, bcm_pbmp_t *pbmp)
    451 {
    452     bcm_port_t port;
    453     if (NULL == pbmp) {
    454         return BCM_E_PARAM;
    455     }
    456     for (port = 0; port < MN_FLEX_MAX_NUM_PORTS; port++) {
    457         BCM_PBMP_PORT_ADD(*pbmp, port);
    458     }
    459     return BCM_E_NONE;
    460 }
    461 
    462 
    463 
    464 /*
    465  * Function:
    466  *      _bcm_monterey_port_resource_attach
    467  * Purpose:
    468  *      Attach ports to the BCM layer and initialize them
    469  *      to the default state.
    470  *
    471  * Parameters:
    472  *      unit           - (IN) Unit number.
    473  *      nport          - (IN) Number of elements in array resource.
    474  *      resource       - (IN) Port Resource FlexPort configuration.
    475  * Returns:
    476  *      BCM_E_XXX
    477  * Notes:
    478  *      - Assumes caller have detached any ports that will be attached
    479  *        in this routine.
    480  *      - Assumes this is NOT called during Warmboot.
    481  *      - Set current MY_MODID for all newly attached ports.
    482  */
    483 STATIC int
    484 _bcm_monterey_port_resource_attach(int unit,
    485                                int nport,
    486                                bcm_monterey_port_resource_t *resource)
    487 {
    488     int rv = BCM_E_NONE;
    489     bcm_monterey_port_resource_t *pr;
    490     int i;
    491     int my_modid;
    492 
    493     LOG_VERBOSE(BSL_LS_BCM_PORT,
    494                 (BSL_META_U(unit,
    495                             "--- BCM Attach ---\n")));
    496     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
    497 
    498 
    499     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    500         if (pr->flags & SOC_PORT_RESOURCE_ATTACH) {
    501             rv = _bcm_monterey_port_attach(unit, pr->port);
    502             if (BCM_FAILURE(rv)) {
    503                 LOG_ERROR(BSL_LS_BCM_PORT,
    504                           (BSL_META_U(unit,
    505                                       "Error: Unable to attach BCM port "
    506                                       "unit=%d port=%d rv=%d\n"),
    507                            unit, pr->port, rv));
    508                 return rv;
    509             }
    510         }
    511     }
    512 
    513     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_set(unit, my_modid));
    514 
    515     return BCM_E_NONE;
    516 }
    517 
    518 
    519 /*
    520  * Function:
    521  *      _bcm_monterey_port_resource_detach
    522  * Purpose:
    523  *      Detach ports from the BCM layer.
    524  *
    525  *      It clears any HW or SW state that was programmed
    526  *      by the SDK initialization routines.  It does NOT clear
    527  *      references to logical ports that have been programmed by the
    528  *      application.  Applications are responsible for doing that.
    529  *
    530  * Parameters:
    531  *      unit           - (IN) Unit number.
    532  *      nport          - (IN) Number of elements in array resource.
    533  *      resource       - (IN) Port Resource FlexPort configuration.
    534  * Returns:
    535  *      BCM_E_XXX
    536  * Notes:
    537  *      - Assumes this is NOT called during Warmboot.
    538  */
    539 STATIC int
    540 _bcm_monterey_port_resource_detach(int unit,
    541                                int nport,
    542                                bcm_monterey_port_resource_t *resource)
    543 {
    544     int rv = BCM_E_NONE;
    545     bcm_monterey_port_resource_t *pr;
    546     int i;
    547 
    548     LOG_VERBOSE(BSL_LS_BCM_PORT,
    549                 (BSL_META_U(unit,
    550                             "--- BCM Detach ---\n")));
    551 
    552     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    553         if (pr->flags & SOC_PORT_RESOURCE_DETACH) {
    554             rv = _bcm_monterey_port_detach(unit, pr->port);
    555             if (BCM_FAILURE(rv)) {
    556                 LOG_ERROR(BSL_LS_BCM_PORT,
    557                           (BSL_META_U(unit,
    558                                       "Error: Unable to detach BCM port "
    559                                       "unit=%d port=%d rv=%d\n"),
    560                            unit, pr->port, rv));
    561                 return rv;
    562             }
    563         }
    564     }
    565 
    566     return BCM_E_NONE;
    567 }
    568 
    569 
    570 /*
    571  * Function:
    572  *      _bcm_monterey_port_resource_resolve
    573  * Purpose:
    574  *      Convert logical port number GPORT to BCM local port format and
    575  *      validate port numbers:
    576  *      - Logical and physical port numbers are within the valid range.
    577  *      - Ports must not be CPU or Loopback ports.
    578  * Parameters:
    579  *      unit     - (IN) Unit number.
    580  *      nport    - (IN) Number of elements in array resource.
    581  *      resource - (IN/OUT) Port resource configuration array.
    582  * Returns:
    583  *      BCM_E_XXX
    584  * Note:
    585  *      - Assumes caller has lock.
    586  *      - Resource is not NULL.
    587  */
    588 STATIC int
    589 _bcm_monterey_port_resource_resolve(int unit, 
    590                                   int nport,
    591                                   bcm_monterey_port_resource_t *resource)
    592 {
    593     int i;
    594     bcm_monterey_port_resource_t *pr;
    595     soc_info_t *si = &SOC_INFO(unit);
    596 
    597     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    598 
    599         /* Check that logical port number is addressable and convert */
    600         BCM_IF_ERROR_RETURN
    601             (bcmi_xgs5_port_addressable_local_get(unit,
    602                                                   pr->port,
    603                                                   &pr->port));
    604 
    605         /*
    606          * Check that logical port number is valid for Apache
    607          * (above check is generic)
    608          */
    609         SOC_IF_ERROR_RETURN
    610             (soc_mn_port_addressable(unit, pr->port));
    611 
    612         /* Check that physical port is within the valid range */
    613         if (pr->physical_port != -1) {
    614             SOC_IF_ERROR_RETURN
    615                 (soc_mn_phy_port_addressable(unit, pr->physical_port));
    616         }
    617 
    618         /* Check that ports, logical and physical, are not a management port */
    619         if ((si->port_l2p_mapping[pr->port] == MN_PHY_PORT_CPU) ||
    620             (si->port_l2p_mapping[pr->port] == MN_PHY_PORT_LB) ||
    621             (pr->physical_port == MN_PHY_PORT_CPU) ||
    622             (pr->physical_port == MN_PHY_PORT_LB)) {
    623             LOG_ERROR(BSL_LS_BCM_PORT,
    624                       (BSL_META_U(unit,
    625                                   "Port cannot be CPU, LB, or RDB port "
    626                                   "unit=%d port=%d\n"),
    627                        unit, pr->port));
    628             return BCM_E_PORT;
    629         }
    630     }
    631 
    632     return BCM_E_NONE;
    633 }
    634 
    635 
    636 /*
    637  * Function:
    638  *      _bcm_monterey_port_resource_input_validate
    639  * Purpose:
    640  *      Validate function input requirements.
    641  *
    642  *      This routine checks for function semantics and guidelines
    643  *      from the API perspective:
    644  *      - Check the order of elements in array, 'delete' operations must
    645  *        be placed first in array.
    646  *      - Ports must not be CPU or Loopback ports.
    647  *      - Ports must be disabled.
    648  *      - Ports linkscan mode must be NONE.
    649  * Parameters:
    650  *      unit     - (IN) Unit number.
    651  *      nport    - (IN) Number of elements in array resource.
    652  *      resource - (IN/OUT) Port resource configuration array.
    653  * Returns:
    654  *      BCM_E_XXX
    655  * Note:
    656  *      - Assumes caller has lock.
    657  *      - Resource is not NULL.
    658  *      - Assumes port values has been validated.
    659  */
    660 STATIC int
    661 _bcm_monterey_port_resource_input_validate(int unit, 
    662                                          int nport,
    663                                          bcm_monterey_port_resource_t *resource)
    664 {
    665     int i;
    666     bcm_monterey_port_resource_t *pr;
    667     int delete = 1;
    668     int enable;
    669     soc_info_t *si = &SOC_INFO(unit);
    670 
    671     /* Check array order and port state disable */
    672     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    673 
    674         /* Skip check for speed change */
    675         if (pr->flags & SOC_PORT_RESOURCE_SPEED) {
    676             continue;
    677         }
    678 
    679         /* Check that delete operations are first */
    680         if (pr->physical_port != -1) {  /* First non-delete found */
    681             delete = 0;
    682         } else if ((pr->physical_port == -1) && !delete) {
    683             LOG_ERROR(BSL_LS_BCM_PORT,
    684                       (BSL_META_U(unit,
    685                                   "Delete operations must be "
    686                                   "first in array\n")));
    687             return BCM_E_CONFIG;
    688         }
    689 
    690         if ((pr->encap != BCM_PORT_ENCAP_IEEE) &&
    691             (pr->encap != BCM_PORT_ENCAP_HIGIG2) &&
    692             (pr->encap != BCM_PORT_ENCAP_CPRI) &&
    693             (pr->encap != BCM_PORT_ENCAP_RSVD4)) {
    694             LOG_ERROR(BSL_LS_BCM_PORT,
    695                       (BSL_META_U(unit,
    696                                   "Encap modes can only be IEEE or HIGIG2 or CPRI "
    697                                   "unit=%d port=%d\n"),
    698                        unit, pr->port));
    699             return BCM_E_CONFIG;
    700         }
    701 
    702         /* Skip ports that are not currently defined */
    703         if (si->port_l2p_mapping[pr->port] == -1) {
    704             continue;
    705         }
    706 
    707         /* Check that ports are disabled */
    708         BCM_IF_ERROR_RETURN
    709             (bcm_esw_port_enable_get(unit, pr->port, &enable));
    710         if (enable) {
    711             LOG_ERROR(BSL_LS_BCM_PORT,
    712                       (BSL_META_U(unit,
    713                                   "Port %d needs to be disabled\n"),
    714                        pr->port));
    715             return BCM_E_BUSY;
    716         }
    717 
    718         /*
    719          * Check that ports to be 'detached' do not
    720          * have linkscan mode set.  See _bcm_monterey_port_resource_pmap_get().
    721          */
    722         if (pr->flags & SOC_PORT_RESOURCE_DETACH) {
    723             if (bcm_esw_linkscan_enable_port_get(unit, pr->port) !=
    724                 BCM_E_DISABLED) {
    725                 LOG_ERROR(BSL_LS_BCM_PORT,
    726                           (BSL_META_U(unit,
    727                                       "Linkscan mode needs to be "
    728                                       "disabled on ports to be detached, "
    729                                       "port=%d\n"),
    730                            pr->port));
    731                 return BCM_E_BUSY;
    732             }
    733         }
    734     }
    735 
    736     return BCM_E_NONE;
    737 }
    738 
    739 
    740 
    741 /*
    742  * Function:
    743  *      _bcm_monterey_port_resource_pmap_get
    744  * Purpose:
    745  *      Determine the type of port mapping changes, if any,
    746  *      as a result of the FlexPort operation.  In addition, it
    747  *      determines whether the port needs to go through the attach
    748  *      and/or detach process.
    749  *
    750  *      All ports that are being flexed will be detached except for those
    751  *      that will become inactive (this is only for legacy mode).
    752  *      All ports that are active after flexed are always attached (this is
    753  *      for new and legacy mode).
    754  *
    755  *      When a port is 'marked' as 'delete' (physical port is -1),
    756  *      this does not mean the logical port will be destroyed.  Depending
    757  *      on the rest of the information in the array, the port mapping
    758  *      may be the same, remapped, or it may no longer exist after FlexPort.
    759  *
    760  *      Likewise, when a valid port mapping is given, the port may
    761  *      not be necessarily new.
    762  *
    763  *      Example:
    764  *
    765  *      Main FlexPort array ('resource') (application input)
    766  *               L1 --> -1 (current mapped to P1), mapping is SAME
    767  *               L2 --> -1 (current mapped to P2), mapping is REMAP
    768  *               L3 --> -1 (current mapped to P3), mapping is DESTROY
    769  *               L1 --> P1                       , mapping is SAME
    770  *               L2 --> P5                       , mapping is REMAP
    771  *               L9 --> P9                       , mapping is NEW
    772  *
    773  * Parameters:
    774  *      unit           - (IN) Unit number.
    775  *      nport          - (IN) Number of elements in array resource.
    776  *      resource       - (IN/OUT) Port Resource FlexPort configuration.
    777  * Returns:
    778  *      SOC_E_XXX
    779  * Notes:
    780  *      Assumes all 'delete' elements are first in array.
    781  */
    782 STATIC int
    783 _bcm_monterey_port_resource_pmap_get(int unit, int nport,
    784                                    bcm_monterey_port_resource_t *resource)
    785 {
    786     int i;
    787     int j;
    788     bcm_monterey_port_resource_t *pr;
    789     soc_info_t *si = &SOC_INFO(unit);
    790 
    791     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    792 
    793         if (pr->physical_port == -1) {
    794             /*
    795              * Find if port is given in later elements.
    796              * If so, check if port is remapped.
    797              * If not found, port is marked to be destroyed
    798              * (port will no longer exist after FlexPort)
    799              *
    800              * Note that all the 'delete' ports must always first
    801              * in array.
    802              */
    803             for (j = i; j < nport; j++) {
    804                 if (resource[j].physical_port == -1) {
    805                     continue;
    806                 }
    807                 if (resource[j].port == pr->port) {  /* Found */
    808                     /* Check if mapping is same */
    809                     if (resource[j].physical_port !=
    810                         si->port_l2p_mapping[pr->port]) {
    811                         pr->flags |= SOC_PORT_RESOURCE_REMAP;
    812                     }
    813                     break;
    814                 }
    815             }
    816 
    817             if (j >= nport) {  /* Not found */
    818                 pr->flags |= SOC_PORT_RESOURCE_DESTROY;
    819             }
    820 
    821             /*
    822              * Detach only if the port is not becoming inactive (legacy).
    823              *
    824              * A port that is becoming inactive after flex is indicated
    825              * when both of the following flags are set:
    826              *     DESTROY
    827              *     I_MAP
    828              */
    829             if (!(pr->flags & SOC_PORT_RESOURCE_DESTROY) ||
    830                 !(pr->flags & SOC_PORT_RESOURCE_I_MAP)) {
    831                 pr->flags |= SOC_PORT_RESOURCE_DETACH;
    832             }
    833 
    834         } else {
    835 
    836             /*
    837              * Check if logical port is new (port does exist), or
    838              * port is being remapped.
    839              */
    840             if (si->port_l2p_mapping[pr->port] == -1) {
    841                 pr->flags |= SOC_PORT_RESOURCE_NEW;
    842             } else if (pr->physical_port != si->port_l2p_mapping[pr->port]) {
    843                 pr->flags |= SOC_PORT_RESOURCE_REMAP;
    844             }
    845 
    846             /* All active ports after flexed are always attached */
    847             pr->flags |= SOC_PORT_RESOURCE_ATTACH;
    848         }
    849 
    850     }
    851 
    852     return BCM_E_NONE;
    853 }
    854 
    855 /*
    856  * Function:
    857  *      _bcm_monterey_port_resource_op_get
    858  * Purpose:
    859  *      Get the type of FlexPort operations/changes:
    860  *          none, port-mapping, lanes, speed, encap.
    861  *
    862  *      Some operations only need speed or encap changes.  In this
    863  *      case, the actual FlexPort operation is not necessary and
    864  *      only calls to set to speed and/or encap mode are made.
    865  *
    866  * Parameters:
    867  *      unit     - (IN) Unit number.
    868  *      nport    - (IN) Number of elements in array resource.
    869  *      resource - (IN) Port resource configuration array.
    870  *      op       - (OUT) FlexPort operation BCM_MN_PORT_RESOURCE_OP_...
    871  * Returns:
    872  *      BCM_E_XXX
    873  * Note:
    874  *      Assumes caller has lock.
    875  *      Resource is not NULL.
    876  *      Logical port in 'resource' is in BCM port format (non GPORT).
    877  */
    878 STATIC int
    879 _bcm_monterey_port_resource_op_get(int unit, int nport,
    880                                 bcm_monterey_port_resource_t *resource, int *op)
    881 {
    882     int i;
    883     bcm_monterey_port_resource_t *pr;
    884     soc_info_t *si = &SOC_INFO(unit);
    885     int speed = 0;
    886     int encap = 0;
    887 
    888     *op = BCM_MN_PORT_RESOURCE_OP_NONE;
    889 
    890     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    891 
    892         /* Check port speed */
    893         if (pr->flags & SOC_PORT_RESOURCE_SPEED) {
    894             /*
    895              * NOTE: speed_set sequence
    896              *
    897              * pr->flags & SOC_PORT_RESOURCE_SPEED is set by speed_set API.
    898              * No logical-physical port mapping changes.
    899              * OP_PMAP flag doesn't need to be set in this case.
    900              * _bcm_mn_port_resource_speed_execute will be called.
    901              */
    902             *op |= BCM_MN_PORT_RESOURCE_OP_SPEED;
    903             LOG_VERBOSE(BSL_LS_BCM_PORT,
    904                         (BSL_META_U(unit,
    905                                     "Speed change detected: "
    906                                     "logical=%d physical=%d\n"),
    907                          pr->port, pr->physical_port));
    908             continue;
    909         }
    910 
    911         /* Check port mapping change */
    912         if (pr->flags &
    913             (SOC_PORT_RESOURCE_NEW | SOC_PORT_RESOURCE_DESTROY |
    914              SOC_PORT_RESOURCE_REMAP)) {
    915             *op |= BCM_MN_PORT_RESOURCE_OP_PMAP;
    916 
    917             LOG_VERBOSE(BSL_LS_BCM_PORT,
    918                         (BSL_META_U(unit,
    919                                     "Port map change detected: "
    920                                     "%s %s %s l=%d p=%d\n"),
    921                          (pr->flags & SOC_PORT_RESOURCE_NEW) ? "new" : "",
    922                          (pr->flags & SOC_PORT_RESOURCE_DESTROY) ?
    923                          "destroy" : "",
    924                          (pr->flags & SOC_PORT_RESOURCE_REMAP) ? "remap" : "",
    925                          pr->port, pr->physical_port));
    926         }
    927 
    928         /* Skip ports that are being deleted or not defined */
    929         if ((pr->physical_port == -1) ||
    930             (si->port_l2p_mapping[pr->port] == -1)) {
    931             continue;
    932         }
    933 
    934         /*
    935          * NOTE: Execute full flex operation if speed is different
    936          */
    937         if (!(*op & BCM_MN_PORT_RESOURCE_OP_SPEED)) {
    938             BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, pr->port, &speed));
    939             if (pr->speed != speed) {
    940                 *op |= BCM_MN_PORT_RESOURCE_OP_PMAP;
    941             }
    942         }
    943 
    944         /* Check port lanes */
    945         if (!(*op & BCM_MN_PORT_RESOURCE_OP_LANES)) {
    946             if (pr->lanes != si->port_num_lanes[pr->port]) {
    947                 *op |= BCM_MN_PORT_RESOURCE_OP_LANES;
    948             }
    949         }
    950 
    951         /* Check port encap */
    952         if (!(*op & BCM_MN_PORT_RESOURCE_OP_ENCAP)) {
    953             BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, pr->port, &encap));
    954             if (pr->encap != encap) {
    955                 *op |= BCM_MN_PORT_RESOURCE_OP_ENCAP;
    956                 if((encap == BCM_PORT_ENCAP_CPRI) || (encap == BCM_PORT_ENCAP_RSVD4)) {
    957                     *op |= BCM_MN_PORT_RESOURCE_OP_PMAP;
    958                 }
    959             }
    960         }
    961 
    962         /* If all are set, no more checking is necessary */
    963         if (*op == BCM_MN_PORT_RESOURCE_OP_ALL) {
    964             break;
    965         }
    966     }
    967     
    968     return BCM_E_NONE;
    969 }
    970 
    971 
    972 /*
    973  * Function:
    974  *      _bcm_monterey_port_resource_loopback_clear
    975  * Purpose:
    976  *      Clear the loopback mode for the given set of ports.
    977  *
    978  * Parameters:
    979  *      unit           - (IN) Unit number.
    980  *      nport          - (IN) Number of elements in array resource.
    981  *      resource       - (IN) Port Resource FlexPort configuration.
    982  * Returns:
    983  *      SOC_E_XXX
    984  * Notes:
    985  *      Assumes all 'delete' elements are first in array.
    986  */
    987 STATIC int
    988 _bcm_monterey_port_resource_loopback_clear(int unit,
    989                                          int nport,
    990                                          bcm_monterey_port_resource_t *resource)
    991 {
    992     int i;
    993     int loopback;
    994     bcm_monterey_port_resource_t *pr;
    995 
    996     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
    997         if (pr->physical_port == -1) {
    998             BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_get(unit,
    999                                                 pr->port, &loopback));
   1000             if (loopback != BCM_PORT_LOOPBACK_NONE) {
   1001                 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit,
   1002                                                 pr->port,
   1003                                                 BCM_PORT_LOOPBACK_NONE));
   1004             }
   1005         }
   1006     }
   1007 
   1008     return BCM_E_NONE;
   1009 
   1010 }
   1011 
   1012 /*
   1013  * Function:
   1014  *      _bcm_monterey_port_resource_speed_execute
   1015  * Purpose:
   1016  *      Perform a speed set operation.
   1017  *      This includes speed change only
   1018  *
   1019  * Parameters:
   1020  *      unit     - (IN) Unit number.
   1021  *      nport    - (IN) Number of elements in array resource.
   1022  *      resource - (IN) Port resource configuration array.
   1023  * Returns:
   1024  *      BCM_E_XXX
   1025  * Note:
   1026  *      Assumes caller has lock.
   1027  *      Assumes BCM data has been validated (basic API semantics)
   1028  *
   1029  * Details:
   1030  *     This function is pretty similar as _bcm_monterey_port_resource_execute.
   1031  *     But speed set doesn't change logical-physical port mapping.
   1032  *     So this function should skip detach, attach function calls.
   1033  *       _bcm_monterey_port_resource_detach
   1034  *       _bcm_monterey_port_resource_attach
   1035  *     Also this calls soc_monterey_port_resource_configure with
   1036  *     the flag:SOC_PORT_RESOURCE_CONFIGURE_SPEED_SET to make slightly
   1037  *     different sequence from full flex operation.
   1038  */
   1039 STATIC int
   1040 _bcm_monterey_port_resource_speed_execute(int unit,
   1041                                   int nport, bcm_monterey_port_resource_t *resource)
   1042 {
   1043     int rv;
   1044     int i;
   1045     soc_port_resource_t *soc_resource;
   1046 
   1047     soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport,
   1048                              "port_resource");
   1049     if (soc_resource == NULL) {
   1050         LOG_ERROR(BSL_LS_BCM_PORT,
   1051                   (BSL_META_U(unit,
   1052                               "Unable to allocate memory for SOC FlexPort "
   1053                               "array\n")));
   1054         return BCM_E_MEMORY;
   1055     }
   1056 
   1057     /* Clear data structure */
   1058     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
   1059 
   1060     /* Copy initial information */
   1061     for (i = 0; i < nport; i++) {
   1062         soc_resource[i].flags = resource[i].flags;
   1063         soc_resource[i].logical_port = resource[i].port;
   1064         soc_resource[i].physical_port = resource[i].physical_port;
   1065         soc_resource[i].speed = resource[i].speed;
   1066         soc_resource[i].num_lanes = resource[i].lanes;
   1067         soc_resource[i].encap = resource[i].encap;
   1068         soc_resource[i].roe_compression = resource[i].roe_compression;
   1069     }
   1070 
   1071     rv = soc_mn_port_resource_validate(unit, nport, soc_resource);
   1072     if (SOC_FAILURE(rv)) {
   1073         sal_free(soc_resource);
   1074         return rv;
   1075     }
   1076 
   1077     /* SOC Port Resource Configure */
   1078     rv = soc_mn_port_resource_configure(unit, nport, soc_resource,
   1079                         SOC_PORT_RESOURCE_CONFIGURE_SPEED_ONLY);
   1080 
   1081     if (BCM_FAILURE(rv)) {
   1082         LOG_ERROR(BSL_LS_BCM_PORT,
   1083                   (BSL_META_U(unit,
   1084                               "Changes to device may have been partially "
   1085                               "executed.  System may be unstable.\n")));
   1086     }
   1087 
   1088     sal_free(soc_resource);
   1089 
   1090     return rv;
   1091 }
   1092 
   1093 /*
   1094  * Function:
   1095  *      _bcm_monterey_port_resource_execute
   1096  * Purpose:
   1097  *      Perform a FlexPort operation.
   1098  *      This includes changes that involve:
   1099  *      - Logical to physical port mapping
   1100  *      - Speed
   1101  *      - Number of PHY lanes
   1102  *
   1103  * Parameters:
   1104  *      unit     - (IN) Unit number.
   1105  *      nport    - (IN) Number of elements in array resource.
   1106  *      resource - (IN) Port resource configuration array.
   1107  * Returns:
   1108  *      BCM_E_XXX
   1109  * Note:
   1110  *      Assumes caller has lock.
   1111  *      Assumes BCM data has been validated (basic API semantics)
   1112  *
   1113  * Details:
   1114  *
   1115  * Port Mapping
   1116  * ------------
   1117  * A logical to physical port mapping is given as part of the port resource
   1118  * array.  This can lead to the following operations:
   1119  * - Port Mapping Delete (or clear)
   1120  *   This is indicated when the physical port is set to (-1) and
   1121  *   the port to be flexed is considered an 'old' port.
   1122  *   The logical port in the array entry must always be valid.
   1123  *   A 'delete' may result in the following actions for a port mapping:
   1124  *      (1) Destroyed
   1125  *      (2) Same
   1126  *      (3) Remapped
   1127  *
   1128  * - Port Mapping Add (or set)
   1129  *   This is indicated when the physical port is set to a valid
   1130  *   physical port number (>=0).
   1131  *   The logical port in the array entry must always be valid.
   1132  *   An 'add' may result in the following actions for a port mapping:
   1133  *      (1) New
   1134  *      (2) Same
   1135  *      (3) Remapped
   1136  *
   1137  * Destroyed: Logical port no longer exist after FlexPort.
   1138  * Remapped:  Logical port will continue to exist after FlexPort
   1139  *            but is mapped to a different physical port.
   1140  * New:       Logical port did not exist before FlexPort.
   1141  * Same:      Logical to physical port mapping remains the same.
   1142  */
   1143 STATIC int
   1144 _bcm_monterey_port_resource_execute(int unit, 
   1145                                   int nport, bcm_monterey_port_resource_t *resource)
   1146 {
   1147     int rv;
   1148     int i;
   1149     soc_port_resource_t *soc_resource;
   1150 
   1151     /*
   1152      * Main FlexPort Sequence
   1153      *
   1154      * - SOC Validation:
   1155      *     + More validation takes place in the SOC layer.
   1156      *     + These check for abilities and configurations based on
   1157      *       the physical aspects of the device.
   1158      *
   1159      * NOTE: Up to this point, no changes has taken place in SW
   1160      *       data structures or HW.
   1161      *       From this point forward, HW and SW data will be modified,
   1162      *       any errors will leave the system unstabled.
   1163      *
   1164      * - Clear any port related settings in BCM layer as needed.
   1165      *
   1166      * - Detach 'old' ports from BCM layer:
   1167      *     + These are all ports to be cleared/deleted (indicated by physical
   1168      *       port -1), EXCEPT those that will become inactive after the
   1169      *       FlexPort operation (this is only true with legacy API).
   1170      *     + The port state should be the same as the state of a
   1171      *       port that was never configured during SDK initialization.
   1172      *     + This involves SW and HW changes.
   1173      *
   1174      * - SOC Port Resource Configure:
   1175      *     Takes place in the SOC layer.
   1176      *     It consists primarliy of these steps:
   1177      *       + Delete ports in SOC layer (SOC_INFO SW, HW update).
   1178      *       + Add ports in SOC layer (SOC_INFO SW, HW update).
   1179      *       + Execute FlexPort operation as defined by HW specs.
   1180      *
   1181      * - Attach 'new' ports to BCM layer:
   1182      *     + These are all ports that are active after the FlexPort operation.
   1183      *     + Ports are initialized to a default state
   1184      *       (same state when a port is brought up after SDK is initialized).
   1185      *     + This involves SW and HW changes.
   1186      *
   1187      * - Set BCM properties on flexed ports as needed.
   1188      */
   1189 
   1190     /*
   1191      * SOC Port Structure initialization
   1192      */
   1193     /* Allocate memory for SOC Port Resource array data structure */
   1194     soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport,
   1195                              "port_resource");
   1196     if (soc_resource == NULL) {
   1197         LOG_ERROR(BSL_LS_BCM_PORT,
   1198                   (BSL_META_U(unit,
   1199                               "Unable to allocate memory for SOC FlexPort "
   1200                               "array\n")));
   1201         return BCM_E_MEMORY;
   1202     }
   1203 
   1204     /* Clear data structure */
   1205     sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport);
   1206 
   1207     /* Copy initial information */
   1208     for (i = 0; i < nport; i++) {
   1209         soc_resource[i].flags = resource[i].flags;
   1210         soc_resource[i].logical_port = resource[i].port;
   1211         soc_resource[i].physical_port = resource[i].physical_port;
   1212         soc_resource[i].speed = resource[i].speed;
   1213         soc_resource[i].num_lanes = resource[i].lanes;
   1214         soc_resource[i].encap = resource[i].encap;
   1215         soc_resource[i].roe_compression = resource[i].roe_compression;
   1216     }
   1217 
   1218     /* SOC Validation */
   1219     rv = soc_mn_port_resource_validate(unit, nport, soc_resource);
   1220     if (SOC_FAILURE(rv)) {
   1221         sal_free(soc_resource);
   1222         return rv;
   1223     }
   1224 
   1225     /* Detach ports from BCM layer */
   1226     rv = _bcm_monterey_port_resource_detach(unit, nport, resource);
   1227 
   1228     /* SOC Port Resource Configure */
   1229     if (BCM_SUCCESS(rv)) {
   1230         rv = soc_mn_port_resource_configure(unit, nport, soc_resource,
   1231                        SOC_PORT_RESOURCE_CONFIGURE_FLEX);
   1232     }
   1233 
   1234     /* Attach ports to BCM layer */
   1235     if (BCM_SUCCESS(rv)) {
   1236         rv = _bcm_monterey_port_resource_attach(unit, nport, resource);
   1237     }
   1238 
   1239     if (BCM_FAILURE(rv)) {
   1240         LOG_ERROR(BSL_LS_BCM_PORT,
   1241                   (BSL_META_U(unit,
   1242                               "Changes to device may have been partially "
   1243                               "executed.  System may be unstable.\n")));
   1244     }
   1245 
   1246     sal_free(soc_resource);
   1247 
   1248     return rv;
   1249 }
   1250 
   1251 
   1252 /*
   1253  * Function:
   1254  *      _bcm_monterey_port_resource_configure
   1255  * Purpose:
   1256  *      Modify the following port resources:
   1257  *      - Logical to physical port mapping
   1258  *      - Speed
   1259  *      - Number of PHY lanes
   1260  *      - Encapsulation mode
   1261  * Parameters:
   1262  *      unit     - (IN) Unit number.
   1263  *      nport    - (IN) Number of elements in array resource.
   1264  *      resource - (IN/OUT) Port resource configuration array.
   1265  * Returns:
   1266  *      BCM_E_XXX
   1267  * Note:
   1268  *      - Assumes caller has lock.
   1269  *      - The data is modified by the function.
   1270  *      - It takes the internal bcm_monterey_port_resource_t data type.
   1271  */
   1272 STATIC int
   1273 _bcm_monterey_port_resource_configure(int unit, 
   1274                                     int nport,
   1275                                     bcm_monterey_port_resource_t *resource)
   1276 {
   1277     int op;
   1278     int i;
   1279 
   1280     /* Convert port format and validate logical and physical port numbers */
   1281     BCM_IF_ERROR_RETURN
   1282         (_bcm_monterey_port_resource_resolve(unit,
   1283                                          nport, resource));
   1284 
   1285     /* Get port mapping change */
   1286     BCM_IF_ERROR_RETURN
   1287         (_bcm_monterey_port_resource_pmap_get(unit, nport, resource));
   1288 
   1289     /* clear loopback */
   1290     BCM_IF_ERROR_RETURN
   1291         (_bcm_monterey_port_resource_loopback_clear(unit, nport, resource));
   1292 
   1293     /*
   1294      * Validate function input requirements
   1295      *
   1296      * This steps checks for function semantics and guidelines
   1297      * from the API perspective.
   1298      */
   1299     BCM_IF_ERROR_RETURN
   1300         (_bcm_monterey_port_resource_input_validate(unit, nport, resource));
   1301 
   1302     /*
   1303      * FlexPort operations types:
   1304      *     NONE                             => Nothing to do
   1305      *     PMAP or LANES                    => FlexPort sequence
   1306      *     ENCAP                            => Encap set
   1307      *     SPEED, but not PMAP or LANES     => Speed set
   1308      */
   1309     BCM_IF_ERROR_RETURN
   1310         (_bcm_monterey_port_resource_op_get(unit, nport, resource, &op));
   1311 
   1312 
   1313     LOG_VERBOSE(BSL_LS_BCM_PORT,
   1314                 (BSL_META_U(unit,
   1315                             "FlexPort operations 0x%x: %s %s %s %s\n"),
   1316                  op,
   1317                  (op & BCM_MN_PORT_RESOURCE_OP_PMAP) ? "pmap" : "",
   1318                  (op & BCM_MN_PORT_RESOURCE_OP_SPEED) ? "speed" : "",
   1319                  (op & BCM_MN_PORT_RESOURCE_OP_LANES) ? "lanes" : "",
   1320                  (op & BCM_MN_PORT_RESOURCE_OP_ENCAP) ? "encap" : ""));
   1321 
   1322     if (op == BCM_MN_PORT_RESOURCE_OP_NONE) {
   1323         return BCM_E_NONE;     /* No changes, just return */
   1324     }
   1325 
   1326     /*
   1327      * Port Mapping / Lane
   1328      *
   1329      * These changes always require a FlexPort operation.
   1330      */
   1331     if ((op & BCM_MN_PORT_RESOURCE_OP_PMAP) ||
   1332         (op & BCM_MN_PORT_RESOURCE_OP_LANES)) {
   1333         LOG_VERBOSE(BSL_LS_BCM_PORT,
   1334                     (BSL_META_U(unit,
   1335                                 "--- Execute FlexPort sequence ---\n")));
   1336         BCM_IF_ERROR_RETURN
   1337             (_bcm_monterey_port_resource_execute(unit,
   1338                                            nport, resource));
   1339         for (i = 0; i < nport; i++) {
   1340             if (resource[i].physical_port == -1) {
   1341                 continue;
   1342             }
   1343 
   1344             /* Bring new ports down to ensure port state is proper */
   1345             BCM_IF_ERROR_RETURN
   1346                 (bcmi_esw_portctrl_enable_set(unit, resource[i].port, 0));
   1347        }
   1348     } else if (op & BCM_MN_PORT_RESOURCE_OP_SPEED) {
   1349         LOG_VERBOSE(BSL_LS_BCM_PORT,
   1350                     (BSL_META_U(unit,
   1351                                 "--- Execute Speed Set sequence ---\n")));
   1352         BCM_IF_ERROR_RETURN
   1353             (_bcm_monterey_port_resource_speed_execute(unit,
   1354                                                      nport, resource));
   1355     }
   1356 
   1357     /*
   1358      * Encap
   1359      */
   1360     if (op & BCM_MN_PORT_RESOURCE_OP_ENCAP) {
   1361         LOG_VERBOSE(BSL_LS_BCM_PORT,
   1362                     (BSL_META_U(unit,
   1363                                 "Execute Encap change\n")));
   1364         for (i = 0; i < nport; i++) {
   1365             if (resource[i].physical_port == -1) {
   1366                 continue;
   1367             }
   1368 
   1369             BCM_IF_ERROR_RETURN
   1370                 (bcmi_esw_portctrl_encap_set(unit, resource[i].port,
   1371                                              resource[i].encap, TRUE));
   1372         }
   1373     }
   1374 
   1375     return BCM_E_NONE;
   1376 }
   1377 
   1378 
   1379 /*
   1380  * Function:
   1381  *      _bcm_monterey_port_resource_multi_set
   1382  * Purpose:
   1383  *      Modify the following port resources:
   1384  *      - Logical to physical port mapping
   1385  *      - Speed
   1386  *      - Number of PHY lanes
   1387  *      - Encapsulation mode
   1388  * Parameters:
   1389  *      unit     - (IN) Unit number.
   1390  *      nport    - (IN) Number of elements in array resource.
   1391  *      resource - (IN) Port resource configuration array.
   1392  * Returns:
   1393  *      BCM_E_XXX
   1394  * Note:
   1395  *      - Assumes caller has lock.
   1396  *      - This is to be called by the API dispatch driver.
   1397  *      - It takes the public bcm_monterey_port_resource_t data type.
   1398  */
   1399 STATIC int
   1400 _bcm_monterey_port_resource_multi_set(int unit, 
   1401                                     int nport,
   1402                                     bcm_port_resource_t *resource)
   1403 {
   1404     int rv;
   1405     int i;
   1406     bcm_monterey_port_resource_t *port_resource;
   1407 
   1408     if (resource == NULL) {
   1409         return BCM_E_PARAM;
   1410     }
   1411 
   1412     /*
   1413      * Use internal port resource structure type.
   1414      * Called routines will be modifying the data, so
   1415      * having a copy avoids modifying user's data.
   1416      */
   1417     port_resource = sal_alloc(sizeof(bcm_monterey_port_resource_t) * nport,
   1418                               "port_resource");
   1419     if (port_resource == NULL) {
   1420         LOG_ERROR(BSL_LS_BCM_PORT,
   1421                   (BSL_META_U(unit,
   1422                               "Unable to allocate memory for internal "
   1423                               "FlexPort array\n")));
   1424         return BCM_E_MEMORY;
   1425     }
   1426 
   1427     /* Clear data structure */
   1428     sal_memset(port_resource, 0, sizeof(bcm_monterey_port_resource_t) * nport);
   1429 
   1430     /* Copy initial information */
   1431     for (i = 0; i < nport; i++) {
   1432         /*
   1433          * No current flags defined in bcm_monterey_port_resource_t, otherwise
   1434          * need to translate from public to internal flags.
   1435          */
   1436         port_resource[i].flags = 0;
   1437         port_resource[i].port = resource[i].port;
   1438         port_resource[i].physical_port = resource[i].physical_port;
   1439         port_resource[i].speed = resource[i].speed;
   1440         port_resource[i].lanes = resource[i].lanes;
   1441         port_resource[i].encap = resource[i].encap;
   1442         port_resource[i].roe_compression = resource[i].roe_compression;
   1443     }
   1444 
   1445     rv = _bcm_monterey_port_resource_configure(unit, nport, port_resource);
   1446 
   1447     sal_free(port_resource);
   1448 
   1449     return rv;
   1450 }
   1451 
   1452 /*
   1453  * Function:
   1454  *      _bcm_monterey_port_resource_speed_set
   1455  * Purpose:
   1456  *      Changes the speed but keeps the same number of lanes
   1457  * Parameters:
   1458  *      unit     - (IN) Unit number
   1459  *      port     - (IN) Logical port number(bcm_port_t, not bcm_gport_t)
   1460  *      speed    - (IN) Port speed
   1461  * Returns:
   1462  *      BCM_E_XXX
   1463  * Note:
   1464  *      - Assumes caller has lock.
   1465  *      - This is to be called by the API dispatch driver.
   1466  */
   1467 STATIC int
   1468 _bcm_monterey_port_resource_speed_set(int unit, bcm_port_t port, int speed)
   1469 {
   1470     soc_info_t *si = &SOC_INFO(unit);
   1471     bcm_monterey_port_resource_t resource[2]; /* resource for pre and post */
   1472     int cur_lanes,  cur_encap;
   1473     int phy_port;
   1474 
   1475  /* si->port_speed_max is the current speed at which MMU/TDM is configured */
   1476     if (si->port_speed_max[port] == speed  || (speed == 0)) {
   1477         LOG_VERBOSE(BSL_LS_BCM_PORT,
   1478                     (BSL_META_U(unit,
   1479                     "Speed is already configured as %d\n"), speed));
   1480         return BCM_E_NONE;
   1481     }
   1482 
   1483     /* Check current number of lanes */
   1484     BCM_IF_ERROR_RETURN(bcmi_monterey_port_lanes_get(unit, port, &cur_lanes));
   1485 
   1486     /* Get current port encap */
   1487     BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap));
   1488 
   1489     /*
   1490      * Clear mapping for physical ports involved in FlexPort operation.
   1491      */
   1492     phy_port = si->port_l2p_mapping[port];
   1493     /* Check valid physical port */
   1494     if (phy_port == -1) {
   1495         LOG_ERROR(BSL_LS_BCM_PORT,
   1496                   (BSL_META_U(unit,
   1497                               "Invalid physical port "
   1498                               "for logical port %d\n"),
   1499                    port));
   1500         return BCM_E_INTERNAL;
   1501     }
   1502 
   1503     resource[0].flags = SOC_PORT_RESOURCE_SPEED;
   1504     resource[0].port = port;
   1505     resource[0].physical_port = -1;
   1506 
   1507     resource[1].flags = SOC_PORT_RESOURCE_SPEED;
   1508     resource[1].port = port;
   1509     resource[1].physical_port = phy_port;
   1510     resource[1].speed = speed;
   1511     resource[1].lanes = cur_lanes;
   1512     resource[1].encap = cur_encap;
   1513     resource[1].roe_compression = 0;
   1514 
   1515     BCM_IF_ERROR_RETURN(_bcm_monterey_port_resource_configure(unit, 2, resource));
   1516 
   1517     return BCM_E_NONE;
   1518 }
   1519 
   1520 /*
   1521  * Function:
   1522  *      bcmi_monterey_port_lanes_get
   1523  * Purpose:
   1524  *      Get the number of PHY lanes for the given port.
   1525  * Parameters:
   1526  *      unit     - (IN) Unit number.
   1527  *      port     - (IN) Logical port.
   1528  *      lanes    - (OUT) Returns number of lanes for port.
   1529  * Returns:
   1530  *      BCM_E_XXX
   1531  */
   1532 int
   1533 bcmi_monterey_port_lanes_get(int unit, bcm_port_t port, int *lanes)
   1534 {
   1535     bcm_port_resource_t resource;
   1536 
   1537     BCM_IF_ERROR_RETURN(bcm_esw_port_resource_get(unit, port, &resource));
   1538 
   1539     *lanes = resource.lanes;
   1540 
   1541     return BCM_E_NONE;
   1542 }
   1543 
   1544 /*
   1545  * Function:
   1546  *      bcmi_monterey_port_lanes_set
   1547  * Purpose:
   1548  *      Set the number of PHY lanes for the given port.
   1549  *
   1550  *      This function should only be used to support the legacy
   1551  *      FlexPort API bcm_port_control_set(... , bcmPortControlLanes).
   1552  *
   1553  *      The legacy API does not delete the port mappings when flexing
   1554  *      to fewer lanes.  Ports which lanes are used by the base
   1555  *      physical port becomes inactive.
   1556  *
   1557  * Parameters:
   1558  *      unit     - (IN) Unit number.
   1559  *      port     - (IN) Logical port.
   1560  *      lanes    - (IN) Number of lanes to set on given port.
   1561  * Returns:
   1562  *      BCM_E_XXX
   1563  * Notes:
   1564  *      - Only to be used by legacy API to support TD2 behavior
   1565  *        bcm_port_control_set(... , bcmPortControlLanes).
   1566  *      - Supports only up to 4 lanes (TSC-4).
   1567  *      - 'port' must be in BCM port format (non-GPORT) and mapped to
   1568  *        the base physical port.
   1569  *      - Several calls to legacy API may be required to
   1570  *        achieve desired configuration.
   1571  */
   1572 int
   1573 bcmi_monterey_port_lanes_set(int unit, bcm_port_t port, int lanes)
   1574 {
   1575     soc_info_t *si = &SOC_INFO(unit);
   1576     bcm_monterey_port_resource_t resource[8];  /* Max size to support up to 4 lanes */
   1577     int max_array_cnt;
   1578     int i;
   1579     int cur_lanes;
   1580     int cur_speed;
   1581     int cur_encap = 0;
   1582     int phy_port;
   1583     int speed;
   1584     int num_ports_clear;
   1585     int num_ports_new;
   1586     int falconport = 0; 
   1587 
   1588     /* Support legacy API up to 4 lanes */
   1589     if ((lanes != 1) && (lanes != 2) && (lanes != 4)) {
   1590         return BCM_E_PARAM;
   1591     }
   1592 
   1593     /* Check current number of lanes */
   1594     BCM_IF_ERROR_RETURN(bcmi_monterey_port_lanes_get(unit, port, &cur_lanes));
   1595     if (cur_lanes == lanes) {
   1596         return BCM_E_NONE;
   1597     }
   1598 
   1599     /* Check that port can support number of lanes specified */
   1600     SOC_IF_ERROR_RETURN(soc_mn_port_lanes_valid(unit, port, lanes));
   1601 
   1602     /* Get current port speed */
   1603     BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, port, &cur_speed));
   1604 
   1605     /* Get current port encap */
   1606     BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap));
   1607 
   1608     /* Clear array */
   1609     max_array_cnt = COUNTOF(resource);
   1610     sal_memset(resource, 0, sizeof(resource));
   1611 
   1612     /*
   1613      * Build port resource array
   1614      * Certain information is derived from 'best' guess,
   1615      * similar to the legacy behaviour.
   1616      */
   1617 
   1618     /*
   1619      * Select speed based on number of lanes
   1620      *
   1621      * For HG, if the current HG speed is the higher speed
   1622      * (i.e. 42 vs 40) select the higher HG speed for the number of lanes.
   1623      * Example
   1624      *    1xHG[42] --> 4xHG[11]
   1625      *    1xHG[40] --> 4xHG[10]
   1626      *
   1627      * Notes:  Assumes encap is HIGIG2 if it is not IEEE
   1628      */
   1629    if ( MONTEREY_PORT_IS_PM4x25_PORT(unit, port) 
   1630         || MONTEREY_PORT_IS_CPM4x25_PORT(unit, port)) { 
   1631         falconport  = 1; 
   1632     }
   1633     switch(lanes) {
   1634     case 1:
   1635         if (cur_encap == BCM_PORT_ENCAP_IEEE) {    /* IEEE */
   1636             speed = falconport ? 25000: 10000;
   1637          } else if (cur_encap == BCM_PORT_ENCAP_CPRI) {    /* IEEE */
   1638             speed = 10000;
   1639         } else {                                   /* HG2  */
   1640             speed = falconport ? 27000: 11000;
   1641         }
   1642         break;
   1643     case 2:
   1644         if (cur_encap == BCM_PORT_ENCAP_IEEE) {    /* IEEE */
   1645             speed = falconport ? 50000: 20000;
   1646         } else {                                   /* HG2  */
   1647             speed = falconport ? 53000: 21000;
   1648         }
   1649 
   1650         break;
   1651     case 4:
   1652         if (cur_encap == BCM_PORT_ENCAP_IEEE) {    /* IEEE */
   1653             speed = falconport ? 100000: 40000;
   1654         } else {                                   /* HG2  */
   1655             speed = PORT_IS_PM4x25_PORT(unit, port) ? 106000: 42000;
   1656         }
   1657         break;
   1658     /*
   1659      * COVERITY
   1660      *
   1661      * Case for default is intentional as a defensive check.
   1662      */
   1663     /* coverity[dead_error_begin] */
   1664 
   1665     default:
   1666         return BCM_E_PARAM;
   1667         break;
   1668     }
   1669 
   1670     switch (cur_lanes) {
   1671     case 1:
   1672         /*
   1673          * 2x10 flex to: 2 lanes -> 1x20
   1674          * 4x10 flex to: 4 lanes -> 1x40
   1675          */
   1676         if (lanes == 2) {
   1677             num_ports_clear = 2;
   1678             num_ports_new = 1;
   1679         } else {
   1680             num_ports_clear = 4;
   1681             num_ports_new = 1;
   1682         }
   1683         break;
   1684     case 2:
   1685         /*
   1686          * 1x20 flex to: 1 lane  -> 2x10
   1687          * 2x20 flex to: 4 lanes -> 1x40
   1688          */
   1689         if (lanes == 1) {
   1690             num_ports_clear = 2;
   1691             num_ports_new = 2;
   1692         } else {
   1693             num_ports_clear = 4;
   1694             num_ports_new = 1;
   1695         }
   1696         break;
   1697     case 4:
   1698         /*
   1699          * 1x40 flex to: 1 lane  -> 4x10
   1700          *               2 lanes -> 2x20
   1701          */
   1702         if (lanes == 1) {
   1703             num_ports_clear = 4;
   1704             num_ports_new = 4;
   1705         } else {
   1706             num_ports_clear = 4;
   1707             num_ports_new = 2;
   1708         }
   1709         break;
   1710     default:
   1711         return BCM_E_CONFIG;
   1712         break;
   1713     }
   1714 
   1715     if ((num_ports_clear + num_ports_new) > max_array_cnt) {
   1716         LOG_ERROR(BSL_LS_BCM_PORT,
   1717                   (BSL_META_U(unit,
   1718                               "Invalid array FlexPort calculation "
   1719                               "num_ports_clear=%d num_ports_new=%d "
   1720                               "max_array=%d\n"),
   1721                    num_ports_clear, num_ports_new, max_array_cnt));
   1722         return BCM_E_INTERNAL;
   1723     }
   1724 
   1725     /*
   1726      * Clear mapping for physical ports involved in FlexPort operation.
   1727      * Assume physical ports are numbered consecutively in device.
   1728      */
   1729     phy_port = si->port_l2p_mapping[port];
   1730     for (i = 0; i < num_ports_clear; i++) {
   1731         resource[i].flags = SOC_PORT_RESOURCE_I_MAP;
   1732         resource[i].port = si->port_p2l_mapping[phy_port++];
   1733         resource[i].physical_port = -1;
   1734     }
   1735 
   1736 
   1737     /*
   1738      * Map new ports
   1739      *
   1740      * Legacy API requires that logical-physical port mapping
   1741      * is valid in the SOC_INFO SW data.
   1742      */
   1743     phy_port = si->port_l2p_mapping[port];
   1744     for (; i < (num_ports_clear + num_ports_new); i++) {
   1745         /* Check valid physical port */
   1746         if (phy_port == -1) {
   1747             LOG_ERROR(BSL_LS_BCM_PORT,
   1748                       (BSL_META_U(unit,
   1749                                   "Invalid physical port "
   1750                                   "for logical port %d\n"),
   1751                        port));
   1752             return BCM_E_INTERNAL;
   1753         }
   1754 
   1755         resource[i].flags = SOC_PORT_RESOURCE_I_MAP;
   1756         resource[i].port = si->port_p2l_mapping[phy_port];
   1757         resource[i].physical_port = phy_port;
   1758         resource[i].lanes = lanes;
   1759         resource[i].speed = speed;
   1760         resource[i].encap = cur_encap;
   1761         phy_port += lanes;
   1762     }
   1763 
   1764 
   1765     BCM_IF_ERROR_RETURN
   1766         (_bcm_monterey_port_resource_configure(unit,
   1767                                              (num_ports_clear + num_ports_new),
   1768                                              resource));
   1769 
   1770     return BCM_E_NONE;
   1771 }
   1772 
   1773 /*
   1774  * Function:
   1775  *     _bcm_monterey_port_drain_cells
   1776  * Purpose:
   1777  *     To drain cells associated to the port.
   1778  * Parameters:
   1779  *     unit       - (IN) unit number
   1780  *     port       - (IN) Port
   1781  * Returns:
   1782  *     BCM_E_XXX
   1783  */
   1784 STATIC int
   1785 _bcm_monterey_port_drain_cells(int unit, int port)
   1786 {
   1787     return bcmi_esw_portctrl_egress_queue_drain(unit, port);
   1788 }
   1789 
   1790 int
   1791 bcm_monterey_port_drain_cells(int unit, int port)
   1792 {
   1793     return (_bcm_monterey_port_drain_cells(unit, port));
   1794 }
   1795 
   1796 #else /* BCM_MONTEREY_SUPPORT */
   1797 int bcm_esw_mn_port_not_empty;
   1798 #endif /* BCM_MONTEREY_SUPPORT */