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 (179925B)


      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:     Apache SOC Port driver.
      9  *
     10  *              Contains information and interfaces for the
     11  *              physical port in the device.
     12  */
     13 
     14 #include <shared/bsl.h>
     15 #include <soc/defs.h>
     16 
     17 #if defined(BCM_MONTEREY_SUPPORT)
     18 #include <soc/drv.h>
     19 #include <soc/scache.h>
     20 #include <soc/error.h>
     21 #include <soc/monterey.h>
     22 #include <soc/apache.h>
     23 #include <soc/esw/port.h>
     24 #include <soc/esw/portctrl.h>
     25 #include <soc/portmod/portmod_legacy_phy.h>
     26 #include <soc/mem.h>
     27 #include <sal/appl/sal.h>
     28 #include <soc/portmod/portmod_defs.h>
     29 
     30 #define MN_PORTS_PER_TSC        4
     31 #define MN_NUM_PGWS             2
     32 #define MN_TSCS_PER_PGW         8 
     33 
     34 #define PORT_BLOCK_BASE_PORT(port) \
     35         (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0x3));
     36 
     37 #ifdef BCM_WARM_BOOT_SUPPORT
     38 
     39 #define SOC_FLEXPORT_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     40 #define SOC_FLEXPORT_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
     41 #define SOC_FLEXPORT_WB_DEFAULT_VERSION            SOC_FLEXPORT_WB_VERSION_1_1
     42 
     43 #endif
     44 extern int
     45 soc_monterey_port_is_falcon(int unit, int phy_port);
     46 
     47 /*
     48  * Physical Port Information
     49  *
     50  *     Some information are defined in HW and others are defined
     51  *     through SOC properties during configuration time.
     52  */
     53 typedef struct mn_phy_port_s {
     54     /*
     55      * The following fields are defined in HW
     56      */
     57     soc_port_lane_info_t lane_info;    /* Lane information in PGW block */
     58     uint32               lanes_valid;  /* Lanes capabilities */
     59     int                  pipe;         /* unused */
     60     int                  sisters_ports[MN_PORTS_PER_TSC];
     61                                        /* Ports part of the XLPORT/XLMAC/TSC-4
     62                                           where the physical port resides */
     63 
     64     /*
     65      * The following fields are configurable throught SOC properties
     66      */
     67     uint16               prio_mask;    /* Packet priority to priority
     68                                           group mapping mask */
     69     int                  flex;         /* Flex enable by SOC property
     70                                           'port_flex_enable' */
     71 } mn_phy_port_t;
     72 
     73 /*
     74  * Physical Device information
     75  */
     76 typedef struct mn_info_s {
     77     mn_phy_port_t  phy_port[SOC_MAX_NUM_PORTS];
     78     int              phy_ports_max;   /* Max physical ports in device */
     79     uint32           speed_valid[SOC_PORT_RESOURCE_LANES_MAX+1];
     80                                       /* Port rate ability on serdes lane */
     81     int              speed_max;       /* Max speed on any port in device */
     82     int              port_max;        /* Max logical ports */
     83 
     84     /*
     85      * The following fields are configurable throught SOC properties
     86      */
     87     int              mmu_lossless;    /* MMU lossless */
     88     int              flex_legacy;     /* Flex enable by legacy ':i' in
     89                                          SOC property 'portmap' */
     90 
     91 } mn_info_t;
     92 
     93 /*
     94  * Contains information corresponding to each physical port.
     95  * This information is fixed in a device and is calculated
     96  * only during init time.
     97  */
     98 static mn_info_t                  *mn_info[SOC_MAX_NUM_DEVICES];
     99 
    100 #define MN_INFO(_u)               (mn_info[(_u)])
    101 #define MN_PHY_PORT(_u, _p)       (MN_INFO(_u)->phy_port[(_p)])
    102 #define MN_PHY_PORT_LANE(_u, _p)  (MN_PHY_PORT(_u, _p).lane_info)
    103 
    104 
    105 /* Lanes support */
    106 #define MN_PHY_XLPORT_LANES_1      (1 << 0)
    107 #define MN_PHY_XLPORT_LANES_2      (1 << 1)
    108 #define MN_PHY_XLPORT_LANES_4      (1 << 2)
    109 #define MN_PHY_XLPORT_LANES_10     (1 << 3)
    110 #define MN_PHY_XLPORT_LANES_12     (1 << 4)
    111 
    112 
    113 /* Port Rate support */
    114 /* Ethernet */
    115 #define MN_PHY_PORT_RATE_1       (1 << 0)
    116 #define MN_PHY_PORT_RATE_2_5     (1 << 1)
    117 #define MN_PHY_PORT_RATE_5       (1 << 2)
    118 #define MN_PHY_PORT_RATE_10      (1 << 3)
    119 #define MN_PHY_PORT_RATE_20      (1 << 4)
    120 #define MN_PHY_PORT_RATE_25      (1 << 5)
    121 #define MN_PHY_PORT_RATE_40      (1 << 6)
    122 #define MN_PHY_PORT_RATE_50      (1 << 7)
    123 #define MN_PHY_PORT_RATE_100     (1 << 8)
    124 /* HG */
    125 #define MN_PHY_PORT_RATE_11      (1 << 9)
    126 #define MN_PHY_PORT_RATE_21      (1 << 10)
    127 #define MN_PHY_PORT_RATE_27      (1 << 11)
    128 #define MN_PHY_PORT_RATE_42      (1 << 12)
    129 #define MN_PHY_PORT_RATE_53      (1 << 13)
    130 #define MN_PHY_PORT_RATE_106     (1 << 14)
    131 #define MN_PHY_PORT_RATE_127     (1 << 15)
    132 
    133 
    134 /* Default for the max port speed configured for device */
    135 #define MN_FLEX_MAX_NUM_PORTS        67 
    136 #define MN_FLEX_SPEED_MAX_DEFAULT    106000
    137 
    138 /* 100GE Mode Lanes */
    139 #define MONTEREY_100GE_MLD_MAP_4_4_2_STR  "0xff9876543210"
    140 #define MONTEREY_100GE_MLD_MAP_3_4_3_STR  "0xf9876543f210"
    141 #define MONTEREY_100GE_MLD_MAP_2_4_4_STR  "0x98765432ff10"
    142 #define PORT_IS_FALCON(pport) \
    143     ((((pport >= 1) && (pport <= 20)) || ((pport >= 45 ) && (pport <= 64 ))) ? TRUE : FALSE)
    144 
    145 /*
    146  * Define:
    147  *      MN_INFO_INIT_CHECK
    148  * Purpose:
    149  *      Causes a routine to return SOC_E_INIT if module is not yet initialized.
    150  */
    151 #define MN_INFO_INIT_CHECK(_u) \
    152     if (mn_info[_u] == NULL) { return SOC_E_INIT; }
    153 
    154 /*
    155  * Define:
    156  *      MN_PHY_PORT_ADDRESSABLE
    157  * Purpose:
    158  *      Checks that physical port is addressable (within valid range).
    159  */
    160 #define MN_PHY_PORT_ADDRESSABLE(_u, _phy_port)                  \
    161     (soc_mn_phy_port_addressable((_u), (_phy_port)) == SOC_E_NONE)
    162 
    163 
    164 /*
    165  * Miscellaneous SOC port data used for validation
    166  *
    167  * Most fields are equivalent to the fields in the SOC_INFO data
    168  * structure.  Use same field names.
    169  */
    170 typedef struct soc_info_mn_misc_s {
    171     int              port_l2p_mapping[SOC_MAX_NUM_PORTS]; /* Logic to phys */
    172     int              port_p2l_mapping[SOC_MAX_NUM_PORTS]; /* Phys to logic */
    173     int              port_speed_max[SOC_MAX_NUM_PORTS];   /* Max speed */
    174     int              port_speed[SOC_MAX_NUM_PORTS];       /* Current speed */
    175     int              port_num_lanes[SOC_MAX_NUM_PORTS];   /* lanes  */
    176     soc_encap_mode_t port_encap[SOC_MAX_NUM_PORTS];       /* Encap mode */
    177     int              bandwidth;  
    178     pbmp_t           oversub_pbm;                         /* Oversubscription */
    179     pbmp_t           disabled_bitmap;                     /* Disabled ports */
    180 } soc_info_mn_misc_t;
    181  int
    182 soc_mn_port_ovs_speed_group_validate(int unit);
    183 STATIC int
    184 _soc_mn_port_resource_ovs_speed_group_validate(int unit, soc_info_mn_misc_t *post_si);
    185 /*
    186  * Function:
    187  *      _soc_mn_phy_port_lane_info_init
    188  * Purpose:
    189  *      Initialize the physical port lane information in the
    190  *      SW device information data structure.
    191  * Parameters:
    192  *      unit     - (IN) Unit number.
    193  * Returns:
    194  *      SOC_E_XXX
    195  * Note:
    196  *      Assumes SW data structure memory is valid.
    197  */
    198 STATIC int
    199 _soc_mn_phy_port_lane_info_init(int unit)
    200 {
    201     int i;
    202     int tsc, pgw;
    203     int blk, bindex;
    204     int phy_port, phy_port_base;
    205 
    206     /* Set information to invalid */
    207     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
    208         MN_PHY_PORT(unit, phy_port).pipe = -1;
    209         MN_PHY_PORT_LANE(unit, phy_port).pgw = -1;
    210         MN_PHY_PORT_LANE(unit, phy_port).xlp = -1;
    211         MN_PHY_PORT_LANE(unit, phy_port).port_index = -1;
    212     }
    213 
    214     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
    215 
    216         /* Check for end of port list */
    217         if (SOC_PORT_BLOCK(unit, phy_port) < 0 &&
    218             SOC_PORT_BINDEX(unit, phy_port) < 0) {
    219             break;
    220         }
    221 
    222         /* Skip internal ports */
    223         if ((phy_port == MN_PHY_PORT_CPU) ||
    224             (phy_port == MN_PHY_PORT_MACSEC) ||
    225             (phy_port == MN_PHY_PORT_LB)) {
    226             continue;
    227         }
    228 
    229         /* Set lane information */
    230         for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
    231             /* Find PGW block */
    232             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
    233             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
    234 
    235             if ((blk < 0) || (bindex < 0)) {
    236                 continue;
    237             }
    238 
    239             /* Set PGW block information for lane */
    240             if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_PGW_CL) {
    241                 /* Get PGW, TSC and Port Index values */
    242                 MN_PHY_PORT_LANE(unit, phy_port).pgw =
    243                     SOC_BLOCK_NUMBER(unit, blk);
    244                 MN_PHY_PORT_LANE(unit, phy_port).tsc =
    245                     bindex / MN_PORTS_PER_TSC;
    246                 MN_PHY_PORT_LANE(unit, phy_port).port_index =
    247                     bindex % MN_PORTS_PER_TSC;
    248             }
    249 
    250             /* Set port lane capabilites */
    251             if ((SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_XLPORT) ||
    252                 (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_XLPORTB0)) {
    253                 MN_PHY_PORT(unit, phy_port).lanes_valid =
    254                     MN_PHY_XLPORT_LANES_1;
    255                 if (bindex == 0) {
    256                     MN_PHY_PORT(unit, phy_port).lanes_valid |=
    257                         MN_PHY_XLPORT_LANES_2 | MN_PHY_XLPORT_LANES_4;
    258                 } else if (bindex == 2) {
    259                     MN_PHY_PORT(unit, phy_port).lanes_valid |=
    260                         MN_PHY_XLPORT_LANES_2;
    261                 }
    262             } else if ((SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLPORT) ||
    263                        (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLG2PORT)) {
    264                 MN_PHY_PORT(unit, phy_port).lanes_valid =
    265                     MN_PHY_XLPORT_LANES_1;
    266                 if (bindex == 0) {
    267                     MN_PHY_PORT(unit, phy_port).lanes_valid |=
    268                         MN_PHY_XLPORT_LANES_2 | MN_PHY_XLPORT_LANES_4;
    269                 } else if (bindex == 2) {
    270                     MN_PHY_PORT(unit, phy_port).lanes_valid |=
    271                         MN_PHY_XLPORT_LANES_2;
    272                 }
    273             }
    274 
    275             if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CXXPORT) {
    276                 MN_PHY_PORT(unit, phy_port).lanes_valid |=
    277                     MN_PHY_XLPORT_LANES_10 | MN_PHY_XLPORT_LANES_12;
    278             }
    279 
    280         } /* for port_num_blktype */
    281 
    282     } /* for phy_port */
    283 
    284     /* Set total number of physical ports in device */
    285     MN_INFO(unit)->phy_ports_max = phy_port;
    286 
    287     /*
    288      * Fill sisters ports
    289      * This logic assumes a given physical layout in the device
    290      */
    291     for (phy_port = 0; phy_port < MN_INFO(unit)->phy_ports_max;) {
    292 
    293         if (MN_PHY_PORT_LANE(unit, phy_port).pgw == -1) {
    294             phy_port++;
    295             continue;
    296         }
    297 
    298         pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw;
    299         tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc;
    300         phy_port_base = phy_port;
    301         while ((MN_PHY_PORT_LANE(unit, phy_port).pgw == pgw) &&
    302                (MN_PHY_PORT_LANE(unit, phy_port).tsc == tsc)) {
    303             for (i = 0; i < MN_PORTS_PER_TSC; i++) {
    304                 MN_PHY_PORT(unit, phy_port).sisters_ports[i] =
    305                     phy_port_base + i;
    306             }
    307             phy_port++;
    308         }
    309     }
    310 
    311     return SOC_E_NONE;
    312 }
    313 
    314 
    315 
    316 /*
    317  * Function:
    318  *      _soc_mn_prio_mask_init
    319  * Purpose:
    320  *      Initialize the packet priority to priority group mapping mask
    321  *      for physical ports in the SW device information data structure.
    322  * Parameters:
    323  *      unit     - (IN) Unit number.
    324  * Returns:
    325  *      SOC_E_XXX
    326  * Note:
    327  *      Assumes SW data structure memory is valid.
    328  */
    329 STATIC int
    330 _soc_mn_prio_mask_init(int unit)
    331 {
    332     int phy_port;
    333     uint16 prio_mask;
    334 
    335     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
    336         /* Skip ports not addressable */
    337         if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port)) {
    338             continue;
    339         }
    340 
    341         prio_mask = 0xffff;
    342         /*
    343          * Check per physical port property first.
    344          * If property is not available on physical port,
    345          * use property on logical port.
    346          */
    347 
    348         /*
    349          * TBD once SOC property is approved.
    350          * if (property_physical) {
    351          *     ...
    352          * } else {
    353          *     ... logical property
    354          * }
    355          */
    356 
    357 #if 0
    358         /* Set based on logical port property */
    359         port = si->port_p2l_mapping[phy_port];
    360         if (port != -1) {
    361             SOC_IF_ERROR_RETURN
    362                 (soc_mn_get_prio_map(unit, port, &prio_mask));
    363         }
    364 #endif
    365 
    366         MN_PHY_PORT(unit, phy_port).prio_mask = prio_mask;
    367     }
    368 
    369     return SOC_E_NONE;
    370 }
    371 
    372 
    373 /*
    374  * Function:
    375  *      _soc_mn_flex_enable_init
    376  * Purpose:
    377  *      Initialize the flex enable capability
    378  *      for physical ports in the SW device information data structure.
    379  *
    380  *      The flexing capabality on a port is defined based on
    381  *      these SOC properties:
    382  *
    383  *      (1) 'portmap' with ':i' option (inactive ports)
    384  *          When defined, this allows flexing in the entire device.
    385  *          This sets MN_INFO(unit)->flex_legacy
    386  *
    387  *      (2) 'port_flex_enable'
    388  *           This SOC property is set per TSC.
    389  *           When set, FlexPort operations are allowed in the TSC.
    390  *           Property should be specified in the base physical port of a TSC.
    391  *           This sets MN_PHY_PORT(unit, phy_port).flex
    392  *
    393  *       The defined SDK behaviour is that if both, (1) and (2) are true,
    394  *       (1) takes precedence.
    395  *
    396  * Parameters:
    397  *      unit     - (IN) Unit number.
    398  * Returns:
    399  *      SOC_E_XXX
    400  * Note:
    401  *      Assumes SW data structure memory is valid.
    402  *      Assumes _soc_monterey_phy_port_lane_info_init() has been called.
    403  */
    404 STATIC int
    405 _soc_mn_flex_enable_init(int unit)
    406 {
    407     int phy_port;
    408     int port_base;
    409     int flex;
    410     int i;
    411     soc_info_t *si = &SOC_INFO(unit);
    412 
    413     /*
    414      * This field is set in SOC_INFO if inactive ports are specified
    415      * in the SOC property 'portmap' with the ':i' option.
    416      */
    417     MN_INFO(unit)->flex_legacy = si->flex_eligible;
    418 
    419     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS;) {
    420         /* Skip ports not addressable, CPU and Loopback ports */
    421         if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port) ||
    422             (phy_port == MN_PHY_PORT_CPU) ||
    423             (phy_port == MN_PHY_PORT_MACSEC) ||
    424             (phy_port == MN_PHY_PORT_LB)) {
    425             phy_port++;
    426             continue;
    427         }
    428 
    429         /* Check for flex ability in 'port_flex_enable' SOC property */
    430         port_base = MN_PHY_PORT(unit, phy_port).sisters_ports[0];
    431         flex = soc_property_phys_port_get(unit, port_base,
    432                                           spn_PORT_FLEX_ENABLE, 0);
    433         /*
    434          * Set flex ability in all ports in the TSC based on
    435          * property set on base port in TSC
    436          *
    437          * Assumes Apache specific physical device layout
    438  */
    439         for (i = 0; i < MN_PORTS_PER_TSC; i++) {
    440             MN_PHY_PORT(unit, phy_port).flex = flex;
    441             phy_port++;
    442             if (phy_port >= SOC_MAX_NUM_PORTS) {
    443                 break;
    444             }
    445         }
    446     }
    447 
    448     return SOC_E_NONE;
    449 }
    450 
    451 /*
    452  * Function:
    453  *      soc_mn_soc_info_mn_misc_t_init
    454  * Purpose:
    455  *      Initialize soc_info_mn_misc_t structure by the current SOC_INFO(unit).
    456  * Parameters:
    457  *      unit - StrataSwitch Unit #.
    458  *      si_m - soc_info_misc data
    459  * Note:
    460  *      port_speed is initialized by si->port_speed_max
    461  */
    462 STATIC void
    463 _soc_mn_soc_info_mn_misc_t_init(int unit, soc_info_mn_misc_t *si_m)
    464 {
    465     soc_info_t *si = &SOC_INFO(unit);
    466     int i;
    467     int logic_port;
    468     int phy_port;
    469     int speed;
    470     sal_memset(si_m, 0, sizeof(*si_m));
    471 
    472     /* Get current information */
    473     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
    474         si_m->port_l2p_mapping[i] = si->port_l2p_mapping[i];
    475         si_m->port_p2l_mapping[i] = si->port_p2l_mapping[i];
    476         si_m->port_speed_max[i] = si->port_speed_max[i];
    477         si_m->port_num_lanes[i] = si->port_num_lanes[i];
    478         si_m->port_speed[i] = -1;
    479         si_m->port_encap[i] = -1;
    480 
    481         logic_port = i;
    482         phy_port = si->port_l2p_mapping[logic_port];
    483 
    484         /* Skip ports not defined, LB, CPU, etc. */
    485         if (!SOC_PORT_ADDRESSABLE(unit, logic_port) ||
    486             !((phy_port >= 0) && (phy_port <= SOC_MAX_NUM_PORTS)) ||
    487             IS_LB_PORT(unit, logic_port) ||
    488             IS_MACSEC_PORT(unit, logic_port) ||
    489             IS_CPU_PORT (unit, logic_port)) {
    490             continue;
    491         }
    492 
    493         /* Get current port speed */
    494         speed = si->port_speed_max[logic_port];
    495         si_m->port_speed[logic_port] = speed;
    496 
    497         /*
    498          * Get encapsulation mode
    499          *
    500          * Validate need to differentiate between HG and non-HG modes,
    501          * so using SOC_ENCAP_HIGIG2 and SOC_ENCAP_IEEE will suffice
    502          * to indicate HG vs non-HG.
    503          */
    504         if (IS_HG_PORT(unit, logic_port)) {
    505             si_m->port_encap[logic_port] = SOC_ENCAP_HIGIG2;
    506         } else if (IS_CPRI_PORT(unit, logic_port)) {
    507             si_m->port_encap[logic_port] = SOC_ENCAP_CPRI;
    508         } else if (IS_RSVD4_PORT(unit, logic_port)) {
    509             si_m->port_encap[logic_port] = SOC_ENCAP_RSVD4;
    510         } else {
    511             si_m->port_encap[logic_port] = SOC_ENCAP_IEEE;
    512         }
    513     }
    514     si_m->bandwidth = si->bandwidth;
    515     SOC_PBMP_ASSIGN(si_m->oversub_pbm, si->oversub_pbm);
    516     SOC_PBMP_ASSIGN(si_m->disabled_bitmap, si->all.disabled_bitmap);
    517 
    518     return;
    519 }
    520 
    521 /*
    522  * Function:
    523  *      soc_mn_port_oversub_get
    524  * Purpose:
    525  *      Get the Oversub for given port.
    526  * Parameters:
    527  *      unit         - (IN) Unit number.
    528  *      phy_port     - (IN) Physical port number, used
    529  *                          for NEW property.
    530  *      logical_port - (IN) Logical port number.
    531  *                          This is used for LEGACY property in
    532  *                          case the NEW property is not present.
    533  *      oversub      - (OUT) Returns TRUE if port is set for Oversub,
    534  *                           FALSE otherwise.
    535  * Returns:
    536  *      SOC_E_XXX
    537  * Notes:
    538  *      Assumes port is valid.
    539  */
    540 STATIC int
    541 soc_mn_port_oversub_get(int unit, int phy_port, soc_port_t logical_port, int *oversub)
    542 {
    543     soc_pbmp_t pbmp;
    544     int oversub_mode = 0;
    545 
    546     SOC_PBMP_CLEAR(pbmp);
    547 
    548     oversub_mode = soc_property_get(unit, spn_OVERSUBSCRIBE_MODE, 0);
    549 
    550     if (oversub_mode == 0) {
    551         *oversub = 0;
    552     } else if (oversub_mode == 1) {
    553         *oversub = 1;
    554     } else if (oversub_mode == 2) {
    555         /*
    556          * Check per physical port property first.
    557          * If property is not available on physical port,
    558          * use property on logical port.
    559          */
    560         *oversub = soc_property_phys_port_get(unit, phy_port,
    561                                               spn_PORT_OVERSUBSCRIBE, 0xFFFFFFFF);
    562         if (*oversub == 0xFFFFFFFF) {
    563             *oversub = 0;
    564             if (logical_port != -1) {
    565                 pbmp = soc_property_get_pbmp(unit, spn_PBMP_OVERSUBSCRIBE, 0);
    566                 if (SOC_PBMP_MEMBER(pbmp, logical_port)) {
    567                     *oversub = 1;
    568                 }
    569             }
    570         }
    571     }
    572     return SOC_E_NONE;
    573 }
    574 
    575 /*
    576  * Function:
    577  *      _soc_mn_post_soc_info_get
    578  * Purpose:
    579  *      Get the post FlexPort SOC INFO port information (subset).
    580  *
    581  *      Certain validations need the post FlexPort information for all
    582  *      the ports at the same time (mostly contained in SOC_INFO).
    583  *      The global SOC_INFO is updated after the validation phase so
    584  *      the information is not available yet.
    585  * Parameters:
    586  *      unit           - (IN) Unit number.
    587  *      nport          - (IN) Number of elements in array resource.
    588  *      resource       - (IN/OUT) Port Resource FlexPort configuration.
    589  *      post_si        - (OUT) Returns the new SOC port information
    590  *                       after FlexPort.  Note that this does NOT
    591  *                       modify the global SOC_INFO SW database.
    592  * Returns:
    593  *      SOC_E_XXX
    594  * Note:
    595  *      This function does NOT modify the global SOC_INFO SW database,
    596  *      the post information is returned in the local argument.
    597  *
    598  *      Assumes values in resource are valid (logical port, etc.)
    599  */
    600 STATIC int
    601 _soc_mn_post_soc_info_get(int unit,
    602                             int nport,
    603                             soc_port_resource_t *resource,
    604                             soc_info_mn_misc_t *post_si)
    605 {
    606     int rv;
    607     soc_info_t *si = &SOC_INFO(unit);
    608     soc_port_resource_t *pr;
    609     int i;
    610     int oversub;
    611     int logic_port;
    612     int phy_port;
    613 
    614     _soc_mn_soc_info_mn_misc_t_init(unit, post_si);
    615 
    616     /* First process 'delete' mappings */
    617     for (i = 0, pr = &resource[0];
    618          (i < nport) && (pr->physical_port == -1);
    619          i++, pr++) {
    620         logic_port = pr->logical_port;
    621         phy_port = si->port_l2p_mapping[logic_port];
    622 
    623         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
    624             SOC_PBMP_PORT_ADD(post_si->disabled_bitmap, logic_port);
    625             continue;
    626         }
    627 
    628         post_si->port_l2p_mapping[logic_port] = -1;
    629         if (phy_port >= 0) {
    630             post_si->port_p2l_mapping[phy_port] = -1;
    631         }
    632         post_si->port_speed_max[logic_port] = -1;
    633         post_si->port_speed[logic_port] = -1;
    634         post_si->port_num_lanes[logic_port] = -1;
    635         post_si->port_encap[logic_port] = -1;
    636 
    637         SOC_PBMP_PORT_REMOVE(post_si->oversub_pbm, logic_port);
    638         SOC_PBMP_PORT_REMOVE(post_si->disabled_bitmap, logic_port);
    639     }
    640 
    641     /* Continue with 'add' mappings in rest of array */
    642     for (; i < nport; i++, pr++) {
    643         logic_port = pr->logical_port;
    644         phy_port = pr->physical_port;
    645 
    646         post_si->port_l2p_mapping[logic_port] = phy_port;
    647         post_si->port_p2l_mapping[phy_port] = logic_port;
    648         post_si->port_speed_max[logic_port] = pr->speed;
    649         post_si->port_speed[logic_port] = pr->speed;
    650         post_si->port_num_lanes[logic_port] = pr->num_lanes;
    651         post_si->port_encap[logic_port] = pr->encap;
    652 
    653         rv = soc_mn_port_oversub_get(unit, phy_port, logic_port, &oversub);
    654         if (SOC_FAILURE(rv)) {
    655             LOG_ERROR(BSL_LS_SOC_PORT,
    656                       (BSL_META_U(unit,
    657                                   "Cannot get oversubscription mode, "
    658                                   "logical_port=%d physical_port=%d rv=%d\n"),
    659                        logic_port, phy_port, rv));
    660             return SOC_E_INTERNAL;
    661         }
    662         if (oversub) {
    663             SOC_PBMP_PORT_ADD(post_si->oversub_pbm, logic_port);
    664         } else {
    665             SOC_PBMP_PORT_REMOVE(post_si->oversub_pbm, logic_port);
    666         }
    667 
    668         SOC_PBMP_PORT_REMOVE(post_si->disabled_bitmap, logic_port);
    669     }
    670 
    671 
    672     LOG_VERBOSE(BSL_LS_SOC_PORT,
    673                 (BSL_META_U(unit,
    674                             "\n--- SOC INFO Post FlexPort Data ---\n")));
    675     LOG_VERBOSE(BSL_LS_SOC_PORT,
    676                 (BSL_META_U(unit,
    677                             "Index L2P  P2L  MaxSpeed   Speed  "
    678                             "Encap Ovs Disabled\n")));
    679     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
    680         if ((post_si->port_l2p_mapping[i] == -1) &&
    681             (post_si->port_p2l_mapping[i] == -1)) {
    682             continue;
    683         }
    684         if (!MN_PHY_PORT_ADDRESSABLE(unit, i)) {
    685             continue;
    686         }
    687         LOG_VERBOSE(BSL_LS_SOC_PORT,
    688                     (BSL_META_U(unit,
    689                                 " %3d  %3d  %3d   %6d   %6d   "
    690                                 "%3s   %1d     %1d\n"),
    691                      i,
    692                      post_si->port_l2p_mapping[i],
    693                      post_si->port_p2l_mapping[i],
    694                      post_si->port_speed_max[i],
    695                      post_si->port_speed[i],
    696                      (post_si->port_encap[i] == SOC_ENCAP_HIGIG2) ?
    697                      "HG" : "!HG",
    698                      SOC_PBMP_MEMBER(post_si->oversub_pbm, i) ? 1 : 0,
    699                      SOC_PBMP_MEMBER(post_si->disabled_bitmap, i) ? 1 : 0));
    700     }
    701     LOG_VERBOSE(BSL_LS_SOC_PORT,
    702                 (BSL_META_U(unit,
    703                             "\n")));
    704 
    705     return SOC_E_NONE;
    706 }
    707 
    708 
    709 /*
    710  * Function:
    711  *      _soc_mn_speed_valid_init
    712  * Purpose:
    713  *      Initialize the SW device information data structure
    714  *      for the valid port rates according to the number of serdes lanes.
    715  * Parameters:
    716  *      unit      - (IN) Unit number.
    717  * Returns:
    718  *      SOC_E_XXX
    719  * Note:
    720  *      - Assumes SW data structure memory is valid.
    721  */
    722 STATIC int
    723 _soc_mn_speed_valid_init(int unit)
    724 {
    725     int lanes;
    726     uint32 speed_valid;
    727 
    728     /* Set port rate based on number of serdes lanes */
    729     for (lanes = 0; lanes <= SOC_PORT_RESOURCE_LANES_MAX; lanes++) {
    730 
    731         if (lanes == 1) {
    732             speed_valid =
    733                 MN_PHY_PORT_RATE_1 |
    734                 MN_PHY_PORT_RATE_2_5 |
    735                 MN_PHY_PORT_RATE_5 |
    736                 MN_PHY_PORT_RATE_10 |
    737                 MN_PHY_PORT_RATE_20 |
    738                 MN_PHY_PORT_RATE_11 |
    739                 MN_PHY_PORT_RATE_21 |
    740                 MN_PHY_PORT_RATE_25 |
    741                 MN_PHY_PORT_RATE_27 ;
    742 
    743         } else if (lanes == 2) {
    744             speed_valid =
    745                 MN_PHY_PORT_RATE_10 |
    746                 MN_PHY_PORT_RATE_11 |
    747                 MN_PHY_PORT_RATE_20 |
    748                 MN_PHY_PORT_RATE_21 |
    749                 MN_PHY_PORT_RATE_25 |
    750                 MN_PHY_PORT_RATE_40 |
    751                 MN_PHY_PORT_RATE_42 |
    752                 MN_PHY_PORT_RATE_50 |
    753                 MN_PHY_PORT_RATE_53 ;
    754 
    755         } else if (lanes == 4) {
    756             speed_valid =
    757                 MN_PHY_PORT_RATE_10 |
    758                 MN_PHY_PORT_RATE_20 |
    759                 MN_PHY_PORT_RATE_40 |
    760                 MN_PHY_PORT_RATE_11 |
    761                 MN_PHY_PORT_RATE_42 |
    762                 MN_PHY_PORT_RATE_21 |
    763                 MN_PHY_PORT_RATE_25 |
    764                 MN_PHY_PORT_RATE_100 |
    765                 MN_PHY_PORT_RATE_106;
    766 
    767         } else if (lanes == 10) {
    768             speed_valid =
    769                 MN_PHY_PORT_RATE_100 |
    770                 MN_PHY_PORT_RATE_106;
    771 
    772         } else if (lanes == 12) {
    773             speed_valid =
    774                 MN_PHY_PORT_RATE_127;
    775 
    776         } else {
    777             speed_valid = 0;
    778         }
    779 
    780         MN_INFO(unit)->speed_valid[lanes] = speed_valid;
    781     }
    782 
    783     return SOC_E_NONE;
    784 }
    785 
    786 
    787 /*
    788  * Function:
    789  *      _soc_mn_ports_pipe_max_init
    790  * Purpose:
    791  *      Initialize the SW device information data structure for:
    792  *      - speed_max      : Maximum allowed port speed in device.
    793  *      - port_max       : Maximum logical port number.
    794  *
    795  *
    796  * Parameters:
    797  *      unit      - (IN) Unit number.
    798  * Returns:
    799  *      SOC_E_XXX
    800  * Note:
    801  *      - Assumes SW data structure memory is valid.
    802  *      - Assumes SOC information is initialized.
    803  */
    804 STATIC int
    805 _soc_mn_ports_pipe_max_init(int unit)
    806 {
    807 
    808     int speed_max;
    809 
    810     /* Get speed from SOC property */
    811     speed_max = soc_property_get(unit, spn_PORT_FLEX_SPEED_MAX,
    812                                  MN_FLEX_SPEED_MAX_DEFAULT);
    813     MN_INFO(unit)->speed_max = speed_max;
    814     MN_INFO(unit)->port_max = 66;
    815     return SOC_E_NONE;
    816 }
    817 
    818 
    819 /*
    820  * Function:
    821  *      _soc_mn_mmu_lossless_init
    822  * Purpose:
    823  *      Initialize the SW device information data structure
    824  *      for the MMU lossless.
    825  * Parameters:
    826  *      unit      - (IN) Unit number.
    827  * Returns:
    828  *      SOC_E_XXX
    829  * Note:
    830  *      Assumes SW data structure memory is valid.
    831  */
    832 STATIC int
    833 _soc_mn_mmu_lossless_init(int unit)
    834 {
    835     MN_INFO(unit)->mmu_lossless =
    836         soc_property_get(unit, spn_MMU_LOSSLESS, 0);
    837 
    838     return SOC_E_NONE;
    839 }
    840 
    841 
    842 /*
    843  * Function:
    844  *      soc_mn_phy_info_init
    845  * Purpose:
    846  *      Initialize the main SW device information data structure.
    847  *
    848  *      It populates the information of the device that are relevant
    849  *      to the physical port interface such as,
    850  *      PGW, XLP, port index, lane capabilities, speed, etc.
    851  *
    852  *      Information is derived from the HW port design specification
    853  *      and configuration properties on a physical port.
    854  *
    855  *      This routine does not modify any HW.  It only
    856  *      modifies the SW data structure.
    857  * Parameters:
    858  *      unit     - (IN) Unit number.
    859  * Returns:
    860  *      SOC_E_XXX
    861  * Notes:
    862  *      - Assumes SOC Control information has been initialized.
    863  *      - Must be called after the AP port configuration init routine
    864  *        soc_monterey_port_config_init().
    865  */
    866 int
    867 soc_mn_phy_info_init(int unit)
    868 {
    869     int phy_port;    /* Physical port */
    870     int lanes;       /* Serdes lane */
    871 
    872     /* Allocate memory for main SW data structure */
    873     if (mn_info[unit] == NULL) {
    874         mn_info[unit] = sal_alloc(sizeof(mn_info_t), "mn_info");
    875         if (mn_info[unit] == NULL) {
    876             LOG_ERROR(BSL_LS_SOC_PORT,
    877                       (BSL_META_U(unit,
    878                                   "Unable to allocate memory for "
    879                                   "monterey_info")));
    880             return SOC_E_MEMORY;
    881         }
    882     }
    883 
    884     /* Clear data structure */
    885     sal_memset(mn_info[unit], 0, sizeof(mn_info_t));
    886 
    887     /* Initialize device information */
    888     SOC_IF_ERROR_RETURN(_soc_mn_phy_port_lane_info_init(unit));
    889 
    890     SOC_IF_ERROR_RETURN(_soc_mn_prio_mask_init(unit));
    891 
    892     SOC_IF_ERROR_RETURN(_soc_mn_flex_enable_init(unit));
    893 
    894     SOC_IF_ERROR_RETURN(_soc_mn_speed_valid_init(unit));
    895 
    896     SOC_IF_ERROR_RETURN(_soc_mn_ports_pipe_max_init(unit));
    897 
    898     SOC_IF_ERROR_RETURN(_soc_mn_mmu_lossless_init(unit));
    899 
    900     /* Debug output */
    901     LOG_VERBOSE(BSL_LS_SOC_PORT,
    902                 (BSL_META_U(unit,
    903                             "Physical ports max: %d  speed_max=%d "
    904                             "port_max=%d mmu_lossless=%d flex_legacy=%d\n\n"),
    905                  MN_INFO(unit)->phy_ports_max,
    906                  MN_INFO(unit)->speed_max,
    907                  MN_INFO(unit)->port_max,
    908                  MN_INFO(unit)->mmu_lossless,
    909                  MN_INFO(unit)->flex_legacy));
    910 
    911     for (phy_port = 0; phy_port < MN_INFO(unit)->phy_ports_max; phy_port++) {
    912         LOG_VERBOSE(BSL_LS_SOC_PORT,
    913                     (BSL_META_U(unit,
    914                                 "Phy port=%d pgw=%d tsc=%d index=%d "
    915                                 "valid=0x%x "
    916                                 "prio_mask=0x%x flex=%d\n"),
    917                      phy_port,
    918                      MN_PHY_PORT_LANE(unit, phy_port).pgw,
    919                      MN_PHY_PORT_LANE(unit, phy_port).tsc,
    920                      MN_PHY_PORT_LANE(unit, phy_port).port_index,
    921                      MN_PHY_PORT(unit, phy_port).lanes_valid,
    922                      MN_PHY_PORT(unit, phy_port).prio_mask,
    923                      MN_PHY_PORT(unit, phy_port).flex));
    924         LOG_VERBOSE(BSL_LS_SOC_PORT,
    925                     (BSL_META_U(unit,
    926                                 "    sisters_ports={%d,%d,%d,%d}\n"),
    927                      MN_PHY_PORT(unit, phy_port).sisters_ports[0],
    928                      MN_PHY_PORT(unit, phy_port).sisters_ports[1],
    929                      MN_PHY_PORT(unit, phy_port).sisters_ports[2],
    930                      MN_PHY_PORT(unit, phy_port).sisters_ports[3]));
    931 
    932     }
    933 
    934     for (lanes = 0; lanes <= SOC_PORT_RESOURCE_LANES_MAX; lanes++) {
    935         LOG_VERBOSE(BSL_LS_SOC_PORT,
    936                     (BSL_META_U(unit,
    937                                 "Serdes lane=%d port_rate=0x%x\n"),
    938                      lanes, MN_INFO(unit)->speed_valid[lanes]));
    939     }
    940 
    941     return SOC_E_NONE;
    942 }
    943 
    944 /*
    945  * Function:
    946  *      soc_mn_phy_info_deinit
    947  * Purpose:
    948  *      Free mn_info data structure.
    949  *
    950  * Parameters:
    951  *      unit     - (IN) Unit number.
    952  * Returns:
    953  *      SOC_E_XXX
    954  */
    955 int
    956 soc_mn_phy_info_deinit(int unit)
    957 {
    958     /* Allocate memory for main SW data structure */
    959     if (mn_info[unit] != NULL) {
    960         sal_free(mn_info[unit]);
    961         mn_info[unit] = NULL;
    962     }
    963 
    964     return SOC_E_NONE;
    965 }
    966 
    967 
    968 
    969 
    970 /*
    971  * Function:
    972  *      _soc_mn_phy_port_flex_valid
    973  * Purpose:
    974  *      Check that FlexPort operation is valid on given physical port.
    975  * Parameters:
    976  *      unit      - (IN) Unit number.
    977  *      phy_port  - (IN) Physical port number.
    978  * Returns:
    979  *      SOC_E_XXX
    980  */
    981 STATIC int
    982 _soc_mn_phy_port_flex_valid(int unit, int phy_port)
    983 {
    984     if (!MN_INFO(unit)->flex_legacy &&
    985         !MN_PHY_PORT(unit, phy_port).flex) {
    986         LOG_ERROR(BSL_LS_SOC_PORT,
    987                   (BSL_META_U(unit,
    988                               "FlexPort operation is not enabled on "
    989                               "physical port %d\n"),
    990                    phy_port));
    991         return SOC_E_CONFIG;
    992     }
    993 
    994     return SOC_E_NONE;
    995 }
    996 
    997 
    998 /*
    999  * Function:
   1000  *      soc_monterey_is_flex_enable
   1001  * Purpose:
   1002  *      Check that FlexPort operation is valid on the unit.
   1003  *      Checks for both legacy and new flex operation.
   1004  * Parameters:
   1005  *      unit      - (IN) Unit number.
   1006  * Returns:
   1007  *      TRUE or FALSE.
   1008  */
   1009 int
   1010 soc_monterey_is_flex_enable(int unit)
   1011 {
   1012     int phy_port, num_phy_port;
   1013     soc_info_t *si = &SOC_INFO(unit);
   1014 
   1015     num_phy_port = 130;
   1016     if (si->flex_eligible) {
   1017         return TRUE;
   1018     } else {
   1019         for (phy_port = 0; phy_port < num_phy_port;
   1020              phy_port++) {
   1021             if (soc_property_phys_port_get(unit,
   1022                                            phy_port,
   1023                                            spn_PORT_FLEX_ENABLE, 0)) {
   1024                 return TRUE;
   1025             }
   1026         }
   1027     }
   1028     return FALSE;
   1029 }
   1030 
   1031 /*
   1032  * Function:
   1033  *      soc_monterey_subsidiary_ports_get
   1034  * Purpose:
   1035  *      Given a controlling port, return a set of ancillary ports
   1036  *      belonging to the group (port block) that can be configured to operate
   1037  *      either as a single high-speed port or multiple low speed ports. If the input
   1038  *      port is not a controlling port, SOC_E_PORT error will be returned.
   1039  * Parameters:
   1040  *      unit - (IN) Unit number.
   1041  *      port - (IN) Port
   1042  *      pbmp - (OUT) Set of ancillary ports
   1043  * Returns:
   1044  *      SOC_E_XXX
   1045  */
   1046 soc_error_t
   1047 soc_monterey_subsidiary_ports_get(int unit, soc_port_t port, soc_pbmp_t *pbmp)
   1048 {
   1049     soc_info_t *si = &SOC_INFO(unit);
   1050     soc_port_t phy_port_base, phy_port;
   1051     soc_pbmp_t pbm;
   1052     int max_subport;
   1053 
   1054     if (!SOC_PORT_VALID(unit, port) || IS_CPU_PORT(unit, port) ||
   1055         IS_LB_PORT(unit, port) || IS_MACSEC_PORT(unit, port)) {
   1056          /* CPU, LB, RDB ports do not support flexport */
   1057         return SOC_E_PORT;
   1058     }
   1059 
   1060     phy_port = si->port_l2p_mapping[port];
   1061     phy_port_base = PORT_BLOCK_BASE_PORT(port);
   1062 
   1063     /* Only lane 0 and lane 2 of a PM can be controlling ports */
   1064     if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) {
   1065         /* Not a controlling port */
   1066         return SOC_E_PORT;
   1067     }
   1068     max_subport = phy_port + (4 - ((phy_port - 1) % 4));
   1069     SOC_PBMP_CLEAR(pbm);
   1070     for (; phy_port < max_subport; phy_port++) {
   1071         if (si->port_p2l_mapping[phy_port] == -1) {
   1072             continue;
   1073         }
   1074         SOC_PBMP_PORT_ADD(pbm, si->port_p2l_mapping[phy_port]);
   1075     }
   1076     SOC_PBMP_ASSIGN(*pbmp, pbm);
   1077 
   1078     return SOC_E_NONE;
   1079 }
   1080 
   1081 /*
   1082  * Function:
   1083  *      soc_monterey_port_lane_config_get
   1084  * Purpose:
   1085  *      Get the mode lane configuration for given physical port.
   1086  *      This is only applicable on 100GE ports.
   1087  * Parameters:
   1088  *      unit      - (IN) Unit number.
   1089  *      phy_port  - (IN) Physical port number.
   1090  *      mode_lane - (OUT) Returns the lane distribution for given port
   1091  *                        SOC_LANE_CONFIG_100G_XYZ
   1092  *      found     - (OUT) Returns TRUE if property is specified,
   1093  *                        FALSE if property is not found.
   1094  * Returns:
   1095  *      SOC_E_XXX
   1096  * Notes:
   1097  *      Assumes physical port is valid.
   1098  */
   1099 int
   1100 soc_monterey_port_lane_config_get(int unit, int phy_port, int *mode_lane,
   1101                                 int *found)
   1102 {
   1103     char *str;
   1104 
   1105     /*
   1106      * The PHY_MLD_MAP SOC property (Multi Lane Distribution) value
   1107      * is interpreted as follows:
   1108      *
   1109      * Each nibble-index is the TSC lane number (0..11) and
   1110      * the nibble value is the 100GE port lane number.
   1111      * A nibble value of "f" indicates the TSC lane is not used.
   1112      *
   1113      * Supported 100GE lane distributions:
   1114      *   TSC 100g 4-4-2 mode:  phy_mld_map{x} = 0xff9876543210
   1115      *   TSC 100g 3-4-3 mode:  phy_mld_map{x} = 0xf9876543f210
   1116      *   TSC 100g 2-4-4 mode:  phy_mld_map{x} = 0x98765432ff10
   1117      *
   1118      * Default is 4-4-2
   1119      * This matches Apache port init soc_monterey_port_config_init().
   1120      */
   1121     str = soc_property_phy_get_str(unit, phy_port, -1, -1, -1,
   1122                                    spn_PHY_MLD_MAP);
   1123 
   1124     /* Return default if property is not found */
   1125     if (str == NULL) {
   1126         *mode_lane = SOC_LANE_CONFIG_100G_DEFAULT;
   1127         *found = FALSE;
   1128         return SOC_E_NONE;
   1129     }
   1130 
   1131     *found = TRUE;
   1132     if (!sal_strcasecmp(str, MONTEREY_100GE_MLD_MAP_4_4_2_STR)) {
   1133         *mode_lane = SOC_LANE_CONFIG_100G_4_4_2;
   1134     } else if (!sal_strcasecmp(str, MONTEREY_100GE_MLD_MAP_3_4_3_STR)) {
   1135         *mode_lane = SOC_LANE_CONFIG_100G_3_4_3;
   1136     } else if (!sal_strcasecmp(str, MONTEREY_100GE_MLD_MAP_2_4_4_STR)) {
   1137         *mode_lane = SOC_LANE_CONFIG_100G_2_4_4;
   1138     } else {
   1139         LOG_WARN(BSL_LS_SOC_PORT,
   1140                  (BSL_META_U(unit,
   1141                              "Physical Port %d: "
   1142                              "Invalid lane configuration.\n"
   1143                              "Using default lane mode.\n"),
   1144                   phy_port));
   1145         *mode_lane = SOC_LANE_CONFIG_100G_DEFAULT;
   1146         *found = FALSE;
   1147     }
   1148 
   1149     return SOC_E_NONE;
   1150 }
   1151 
   1152 /*
   1153  * Function:
   1154  *      soc_monterey_port_autoneg_core_get
   1155  * Purpose:
   1156  *      Get the autoneg configuration for given physical port.
   1157  *      This is only applicable on 100GE ports.
   1158  * Parameters:
   1159  *      unit      - (IN) Unit number.
   1160  *      phy_port  - (IN) Physical port number.
   1161  *      an_core   - (OUT) Returns the an_core index for given port
   1162  *      found     - (OUT) Returns TRUE if property is specified,
   1163  *                        FALSE if property is not found.
   1164  * Returns:
   1165  *      SOC_E_XXX
   1166  * Notes:
   1167  *      Assumes physical port is valid.
   1168  */
   1169 int
   1170 soc_monterey_port_autoneg_core_get(int unit, int phy_port, int *an_core,
   1171                                  int *found)
   1172 {
   1173     *found = TRUE;
   1174     *an_core = soc_property_phy_get(unit, phy_port, -1, -1, -1,
   1175                                     spn_PHY_AN_CORE_NUM,
   1176                                     -1);
   1177     if (*an_core < 0 || *an_core > 2) {
   1178         *an_core = SOC_LANE_CONFIG_100G_AN_CORE_DEFAULT;
   1179         *found = FALSE;
   1180     }
   1181 
   1182     return SOC_E_NONE;
   1183 }
   1184 
   1185 
   1186 /*
   1187  * Function:
   1188  *      _soc_mn_speed_valid
   1189  * Purpose:
   1190  *      Check that given speed is valid for the number of
   1191  *      serdes lanes.
   1192  * Parameters:
   1193  *      unit     - (IN) Unit number.
   1194  *      phy_port - (IN) Physical port number.
   1195  *      lanes    - (IN) Number of PHY lanes.
   1196  *      speed    - (IN) Port rate to check.
   1197  * Returns:
   1198  *      SOC_E_XXX
   1199  */
   1200 STATIC int
   1201 _soc_mn_speed_valid(int unit, int phy_port, int lanes, int speed)
   1202 {
   1203     uint32 speed_mask = 0;
   1204     int speed_max;
   1205 
   1206     SOC_IF_ERROR_RETURN
   1207         (soc_mn_port_resource_speed_max_get(unit, &speed_max));
   1208 
   1209     if (speed > speed_max) {
   1210         LOG_ERROR(BSL_LS_SOC_PORT,
   1211                   (BSL_META_U(unit,
   1212                               "Invalid speed configuration for "
   1213                               "physical_port=%d, speed=%d, max=%d\n"),
   1214                    phy_port, speed, speed_max));
   1215         return SOC_E_CONFIG;
   1216     }
   1217 
   1218 if (lanes == 1) {
   1219         switch (speed) {
   1220             case 10:
   1221             case 100:
   1222                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_1;
   1223                 break;
   1224             case 1000:
   1225                 speed_mask = MN_PHY_PORT_RATE_1;
   1226                 break;
   1227             case 2500:
   1228                 speed_mask =  MN_PHY_PORT_RATE_2_5;
   1229                 break;
   1230             case 5000:
   1231                 speed_mask =  MN_PHY_PORT_RATE_5;
   1232                 break;
   1233             case 10000:
   1234                 speed_mask = MN_PHY_PORT_RATE_10;
   1235                 break;
   1236             case 11000:
   1237                 speed_mask = MN_PHY_PORT_RATE_11;
   1238                 break;
   1239             case 25000:
   1240                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_25 : 0;
   1241                 break;
   1242             case 27000:
   1243                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_27 : 0;
   1244                 break;
   1245         }
   1246     } else if (lanes == 2) {
   1247         switch (speed) {
   1248             case 10000:
   1249                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_10;
   1250                 break;
   1251             case 11000:
   1252                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_11;
   1253                 break;
   1254             case 20000:
   1255                 speed_mask = MN_PHY_PORT_RATE_20;
   1256                 break;
   1257             case 21000:
   1258                 speed_mask = MN_PHY_PORT_RATE_21;
   1259                 break;
   1260             case 40000:
   1261                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_40 : 0;
   1262                 break;
   1263             case 42000:
   1264                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_42 : 0;
   1265                 break;
   1266             case 50000:
   1267                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_50 : 0;
   1268                 break;
   1269             case 53000:
   1270                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_53 : 0;
   1271                 break;
   1272         }
   1273      } else if (lanes == 4) {
   1274         switch (speed) {
   1275             case 10000:
   1276                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_10;
   1277                 break;
   1278             case 11000:
   1279                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_11;
   1280                 break;
   1281             case 20000:
   1282                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_20;
   1283                 break;
   1284             case 21000:
   1285                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_21;
   1286                 break;
   1287             case 25000:
   1288                 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_25;
   1289                 break;
   1290             case 40000:
   1291                 speed_mask = MN_PHY_PORT_RATE_40;
   1292                 break;
   1293             case 42000:
   1294                 speed_mask = MN_PHY_PORT_RATE_42;
   1295                 break;
   1296             case 100000:
   1297                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_100 : 0;
   1298                 break;
   1299             case 106000:
   1300                 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_106 : 0;
   1301                 break;
   1302         }
   1303     }
   1304     if (!(MN_INFO(unit)->speed_valid[lanes] & speed_mask)) {
   1305         LOG_ERROR(BSL_LS_SOC_PORT,
   1306                   (BSL_META_U(unit,
   1307                               "Invalid speed configuration for "
   1308                               "physical_port=%d, speed=%d\n"),
   1309                    phy_port, speed));
   1310         return SOC_E_CONFIG;
   1311     }
   1312 
   1313     return SOC_E_NONE;
   1314 }
   1315 
   1316 
   1317 /*
   1318  * Function:
   1319  *      _soc_mn_phy_port_lanes_valid
   1320  * Purpose:
   1321  *      Check that given lane setting is valid for physical port.
   1322  * Parameters:
   1323  *      unit     - (IN) Unit number.
   1324  *      port     - (IN) Base physical port.
   1325  *      lanes    - (IN) Number of PHY lanes.
   1326  * Returns:
   1327  *      SOC_E_XXX
   1328  */
   1329 STATIC int
   1330 _soc_mn_phy_port_lanes_valid(int unit, int phy_port, int lanes)
   1331 {
   1332     uint32 lane_mask = 0;
   1333 
   1334     if (lanes == 1) {
   1335         lane_mask = MN_PHY_XLPORT_LANES_1;
   1336     } else if (lanes == 2) {
   1337         lane_mask = MN_PHY_XLPORT_LANES_2;
   1338     } else if (lanes == 4) {
   1339         lane_mask = MN_PHY_XLPORT_LANES_4;
   1340     } else if (lanes == 10) {
   1341         lane_mask = MN_PHY_XLPORT_LANES_10;
   1342     } else if (lanes == 12) {
   1343         lane_mask = MN_PHY_XLPORT_LANES_12;
   1344     } else {
   1345         LOG_ERROR(BSL_LS_SOC_PORT,
   1346                   (BSL_META_U(unit,
   1347                               "Invalid number of lanes for "
   1348                               "physical_port=%d, lanes=%d\n"),
   1349                    phy_port, lanes));
   1350         return SOC_E_CONFIG;
   1351     }
   1352 
   1353     if (!(MN_PHY_PORT(unit, phy_port).lanes_valid & lane_mask)) {
   1354         LOG_ERROR(BSL_LS_SOC_PORT,
   1355                   (BSL_META_U(unit,
   1356                               "Invalid lane configuration for "
   1357                               "physical port %d, lane=%d, "
   1358                               "valid_lanes=%s %s %s  %s %s\n"),
   1359                    phy_port, lanes,
   1360                    (MN_PHY_PORT(unit, phy_port).lanes_valid &
   1361                     MN_PHY_XLPORT_LANES_1) ? "1" : "",
   1362                    (MN_PHY_PORT(unit, phy_port).lanes_valid &
   1363                     MN_PHY_XLPORT_LANES_2) ? "2" : "",
   1364                    (MN_PHY_PORT(unit, phy_port).lanes_valid &
   1365                     MN_PHY_XLPORT_LANES_4) ? "4" : "",
   1366                    (MN_PHY_PORT(unit, phy_port).lanes_valid &
   1367                     MN_PHY_XLPORT_LANES_10) ? "10" : "",
   1368                    (MN_PHY_PORT(unit, phy_port).lanes_valid &
   1369                     MN_PHY_XLPORT_LANES_12) ? "12" : ""));
   1370 
   1371         return SOC_E_CONFIG;
   1372     }
   1373 
   1374     return SOC_E_NONE;
   1375 }
   1376 
   1377 
   1378 /*
   1379  * Function:
   1380  *      soc_mn_port_lanes_valid
   1381  * Purpose:
   1382  *      Check that given lane setting is valid for logical port.
   1383  * Parameters:
   1384  *      unit     - (IN) Unit number.
   1385  *      port     - (IN) Logical port.
   1386  *      lanes    - (IN) Number of PHY lanes.
   1387  * Returns:
   1388  *      SOC_E_XXX
   1389  */
   1390 int
   1391 soc_mn_port_lanes_valid(int unit, soc_port_t port, int lanes)
   1392 {
   1393     soc_info_t *si = &SOC_INFO(unit);
   1394     int phy_port;
   1395 
   1396     MN_INFO_INIT_CHECK(unit);
   1397 
   1398     phy_port = si->port_l2p_mapping[port];
   1399     if (phy_port == -1) {
   1400         LOG_ERROR(BSL_LS_SOC_PORT,
   1401                   (BSL_META_U(unit,
   1402                               "Invalid physical port for logical port %d\n"),
   1403                    port));
   1404         return SOC_E_PORT;
   1405     }
   1406 
   1407     return _soc_mn_phy_port_lanes_valid(unit, phy_port, lanes);
   1408 }
   1409 
   1410 
   1411 /*
   1412  * Function:
   1413  *      soc_mn_port_resource_speed_max_get
   1414  * Purpose:
   1415  *      Get the maximum allowed speed in the device.
   1416  *
   1417  *      This information is used to determine the total number of
   1418  *      logical  ports allowed in the system as well as the
   1419  *      pre-allocation of MMU port numbers.
   1420  * Parameters:
   1421  *      unit  - (IN) Unit number.
   1422  *      speed - (OUT) Maximum speed of any port in device.
   1423  * Returns:
   1424  *      SOC_E_XXX
   1425  * Note:
   1426  */
   1427 int
   1428 soc_mn_port_resource_speed_max_get(int unit, int *speed)
   1429 {
   1430     MN_INFO_INIT_CHECK(unit);
   1431 
   1432     *speed = MN_INFO(unit)->speed_max;
   1433 
   1434     return SOC_E_NONE;
   1435 }
   1436 
   1437 
   1438 /*
   1439  * Function:
   1440  *      soc_mn_port_addressable
   1441  * Purpose:
   1442  *      Check that given logical port number is addressable.
   1443  * Parameters:
   1444  *      unit  - (IN) Unit number.
   1445  *      port  - (IN) Logical port number.
   1446  * Returns:
   1447  *      SOC_E_NONE - If logical port number is addressable
   1448  *      SOC_E_PORT - If logical port number is not addressable.
   1449  * NOTE:
   1450  *      This routine only checks that the logical port number is
   1451  *      within the valid range.  It does NOT check whether the logical
   1452  *      port has a valid port mapping.
   1453  */
   1454 int
   1455 soc_mn_port_addressable(int unit, soc_port_t port)
   1456 {
   1457     MN_INFO_INIT_CHECK(unit);
   1458 
   1459     if ((port < 0) ||
   1460         (port > MN_INFO(unit)->port_max)) {
   1461         LOG_ERROR(BSL_LS_SOC_PORT,
   1462                   (BSL_META_U(unit,
   1463                               "Invalid logical port number %d. "
   1464                               "Valid logical ports are %d to %d.\n"),
   1465                    port, 0, MN_INFO(unit)->port_max));
   1466         return SOC_E_PORT;
   1467     }
   1468 
   1469     return SOC_E_NONE;
   1470 }
   1471 
   1472 /*
   1473  * Function:
   1474  *      soc_mn_phy_port_addressable
   1475  * Purpose:
   1476  *      Check that given physical port number is addressable.
   1477  * Parameters:
   1478  *      unit      - (IN) Unit number.
   1479  *      phy_port  - (IN) Physical port number.
   1480  * Returns:
   1481  *      SOC_E_NONE - If physical port number is addressable
   1482  *      SOC_E_PORT - If physical port number is not addressable.
   1483  * NOTE:
   1484  *      This routine only checks that the physical port number is
   1485  *      within the valid range.  It does NOT check whether the physical
   1486  *      port has a port mapping.
   1487  */
   1488 int
   1489 soc_mn_phy_port_addressable(int unit, int phy_port)
   1490 {
   1491     MN_INFO_INIT_CHECK(unit);
   1492 
   1493     if ((phy_port < 0) ||
   1494         (phy_port >= MN_INFO(unit)->phy_ports_max)) {
   1495         return SOC_E_PORT;
   1496     }
   1497 
   1498     return SOC_E_NONE;
   1499 }
   1500 
   1501 
   1502 /*
   1503  * Function:
   1504  *      soc_mn_phy_port_pgw_info_get
   1505  * Purpose:
   1506  *      Provide the PGW information for given physical port.
   1507  * Parameters:
   1508  *      unit        - (IN) Unit number.
   1509  *      phy_port    - (IN) Physical port number.
   1510  *      pgw         - (OUT) PGW instance where port resides.
   1511  *      tsc         - (OUT) TSC number within PGW
   1512  *      port_index  - (OUT) Port index within TSC
   1513  * Returns:
   1514  *      SOC_E_XXX
   1515  */
   1516 int
   1517 soc_mn_phy_port_pgw_info_get(int unit, int phy_port,
   1518                                int *pgw, int *tsc, int *port_index)
   1519 {
   1520     MN_INFO_INIT_CHECK(unit);
   1521 
   1522     if (phy_port == -1) {
   1523         LOG_ERROR(BSL_LS_SOC_PORT,
   1524                   (BSL_META_U(unit,
   1525                               "Invalid physical port %d\n"),
   1526                    phy_port));
   1527         return SOC_E_PORT;
   1528     }
   1529 
   1530     *pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw;
   1531     *tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc;
   1532     *port_index = MN_PHY_PORT_LANE(unit, phy_port).port_index;
   1533 
   1534     return SOC_E_NONE;
   1535 }
   1536 
   1537 
   1538 /*
   1539  * Function:
   1540  *      _soc_mn_logic_ports_max_validate
   1541  * Purpose:
   1542  *      Check that number of logical ports do not exceed maximum allowed
   1543  *      based on physical port mappings provided in bitmap.
   1544  * Parameters:
   1545  *      unit     - (IN) Unit number.
   1546  *      phy_pbmp - (IN) Bitmap of physical ports.
   1547  *                      A bit set indicates physical port is mapped.
   1548  * Returns:
   1549  *      SOC_E_XXX
   1550  * Note:
   1551  */
   1552 STATIC int
   1553 _soc_mn_logic_ports_max_validate(int unit, portmod_pbmp_t phy_pbmp )
   1554 {
   1555     int phy_port;
   1556     int ports_max;
   1557     int port_count = 0;
   1558 
   1559     /* Get maximum number of logical ports allowed */
   1560     ports_max = MN_INFO(unit)->port_max;
   1561 
   1562     /* Check number of logical ports do not exceed maximum allowed */
   1563     /* coverity[overrun-local] */
   1564 
   1565     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
   1566         /* Skip CPU, Loopback */
   1567         if ((phy_port == MN_PHY_PORT_CPU) ||
   1568             (phy_port == MN_PHY_PORT_LB)  ||
   1569              (phy_port == MN_PHY_PORT_MACSEC)) {
   1570             continue;
   1571         }
   1572         if (!PORTMOD_PBMP_MEMBER(phy_pbmp, phy_port)) {
   1573             continue;
   1574         }
   1575 
   1576         port_count++;
   1577     }
   1578 
   1579     if (port_count > ports_max) {
   1580         LOG_ERROR(BSL_LS_SOC_PORT,
   1581                   (BSL_META_U(unit,
   1582                               "Number of logical ports exceeds "
   1583                               "max allowed: port_coun=%d ports_max=%d\n"),
   1584                    port_count, ports_max));
   1585         return SOC_E_RESOURCE;
   1586     }
   1587 
   1588     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1589                 (BSL_META_U(unit,
   1590                             "Number of logical ports exceeds "
   1591                             "max allowed: port_coun=%d ports_max=%d\n"),
   1592                  port_count, ports_max));
   1593 
   1594     return SOC_E_NONE;
   1595 }
   1596 
   1597 
   1598 /*
   1599  * Function:
   1600  *      _soc_mn_port_resource_tdm_config_validate
   1601  * Purpose:
   1602  *      Validate that the given port configuration is a
   1603  *      standard configuration supported by the TDM.
   1604  * Parameters:
   1605  *      unit     - (IN) Unit number.
   1606  *      nport    - (IN) Number of elements in array resource.
   1607  *      resource - (IN) Port resource configuration array.
   1608  *      phy_pbm  - (IN) Physical port bitmap.  A bit set indicates
   1609  *                      physical port is defined (mapped).
   1610  * Returns:
   1611  *      SOC_E_XXX
   1612  * Note:
   1613  *      - Resource is not NULL.
   1614  *      - Assumes array order is correct
   1615  *        ('delete' operations are first in array).
   1616  *      - Ports are not replicated.
   1617  */
   1618 STATIC int
   1619 _soc_mn_port_resource_tdm_config_validate(int unit,
   1620                                             int nport,
   1621                                             soc_port_resource_t *resource,
   1622                                             portmod_pbmp_t phy_pbmp)
   1623 {
   1624     soc_info_t *si = &SOC_INFO(unit);
   1625     soc_port_resource_t *pr;
   1626     int xlport_mask[MN_NUM_PGWS][MN_TSCS_PER_PGW];
   1627     int xlport_validated[MN_NUM_PGWS][MN_TSCS_PER_PGW];
   1628     int pgw;
   1629     int tsc;
   1630     int port_index;
   1631     int phy_port;
   1632     int i;
   1633 
   1634     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1635                 (BSL_META_U(unit,
   1636                             "--- VALIDATE: TDM configuration\n")));
   1637 
   1638     /* Clear data */
   1639     for (pgw = 0; pgw < MN_NUM_PGWS; pgw++) {
   1640         for (tsc = 0; tsc < MN_TSCS_PER_PGW; tsc++) {
   1641             xlport_mask[pgw][tsc] = 0x0;
   1642             xlport_validated[pgw][tsc] = 0;
   1643         }
   1644     }
   1645 
   1646     /*
   1647      * Determine configuration on each XLPORT (PortMacro or TSC-4)
   1648      *
   1649      * A bit set means physical port is defined (mapped).
   1650      */
   1651     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
   1652         pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw;
   1653         if (pgw == -1) {
   1654             continue;
   1655         }
   1656 
   1657         tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc;
   1658         port_index = MN_PHY_PORT_LANE(unit, phy_port).port_index;
   1659 
   1660         /* Check if physical port is mapped */
   1661         /* coverity[overrun-local] */
   1662          if (PORTMOD_PBMP_MEMBER(phy_pbmp, phy_port)) {
   1663             xlport_mask[pgw][tsc] |= 1 << port_index;
   1664         }
   1665     }
   1666 
   1667     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1668                 (BSL_META_U(unit, "Check Port Configuration block\n")));
   1669     for (pgw = 0; pgw < MN_NUM_PGWS; pgw++) {
   1670         LOG_VERBOSE(BSL_LS_SOC_PORT,
   1671                     (BSL_META_U(unit, "    PGW_%d:"), pgw));
   1672         for (tsc = 0; tsc < MN_TSCS_PER_PGW; tsc++) {
   1673             LOG_VERBOSE(BSL_LS_SOC_PORT,
   1674                         (BSL_META_U(unit,
   1675                                     " tsc_%d=0x%x"), tsc,
   1676                          xlport_mask[pgw][tsc]));
   1677         }
   1678         LOG_VERBOSE(BSL_LS_SOC_PORT,
   1679                     (BSL_META_U(unit, "\n")));
   1680     }
   1681 
   1682     /*
   1683      * Check configuration only on blocks where ports are being flexed.
   1684      * Assume configuration on other blocks is valid.
   1685      */
   1686     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   1687         if (pr->physical_port == -1) {
   1688             phy_port = si->port_l2p_mapping[pr->logical_port];
   1689         } else {
   1690             phy_port = pr->physical_port;
   1691         }
   1692 
   1693         pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw;
   1694         tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc;
   1695 
   1696         if (pgw == -1) {
   1697             LOG_ERROR(BSL_LS_SOC_PORT,
   1698                       (BSL_META_U(unit,
   1699                                   "Invalid PGW block -1 for "
   1700                                   "physical port %d\n"),
   1701                        phy_port));
   1702             return SOC_E_INTERNAL;
   1703         }
   1704 
   1705         if (xlport_validated[pgw][tsc]) {
   1706             /* Configuration in block was already validated. skip */
   1707             continue;
   1708         }
   1709 
   1710 
   1711         xlport_validated[pgw][tsc] = 1;
   1712     }
   1713 
   1714     return SOC_E_NONE;
   1715 }
   1716 
   1717 
   1718 /*
   1719  * Function:
   1720  *      _soc_mn_port_mapping_validate
   1721  * Purpose:
   1722  *      Validate:
   1723  *      - Port numbers are available and mappings are not replicated.
   1724  *      - Number of logical port numbers do not exceed max allowed.
   1725  *      - Port configuration mode is valid (based on valid TDM cases).
   1726  * Parameters:
   1727  *      unit     - (IN) Unit number.
   1728  *      nport    - (IN) Number of elements in array resource.
   1729  *      resource - (IN) Port resource configuration array.
   1730  * Returns:
   1731  *      SOC_E_XXX
   1732  * Note:
   1733  *      - Resource is not NULL.
   1734  *      - Assumes array order is correct
   1735  *        ('delete' operations are first in array).
   1736  */
   1737 STATIC int
   1738 _soc_mn_port_mapping_validate(int unit, 
   1739                                 int nport,
   1740                                 soc_port_resource_t *resource)
   1741 {
   1742     soc_info_t *si = &SOC_INFO(unit);
   1743     soc_port_resource_t *pr;
   1744     char phy_pfmt[SOC_PBMP_FMT_LEN];
   1745     char logic_pfmt[SOC_PBMP_FMT_LEN];
   1746     portmod_pbmp_t phy_pbmp;
   1747     pbmp_t logic_pbmp;
   1748     pbmp_t phy_pbmp_tmp;
   1749     int phy_port;
   1750     int i;
   1751     int lane;
   1752     int num_lanes;
   1753 
   1754     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1755                 (BSL_META_U(unit,
   1756                             "--- VALIDATE: Port mappings\n")));
   1757     /*
   1758      * Determine bitmaps of used/mapped logical ports and
   1759      * physical ports.
   1760      *
   1761      * A bit set indicates port is mapped.
   1762      */
   1763     PORTMOD_PBMP_CLEAR(phy_pbmp);
   1764     SOC_PBMP_CLEAR(logic_pbmp);
   1765 
   1766     /* Get current port assignment */
   1767     for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
   1768         /* Skip not-addressable and invalid ports */
   1769         if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port) ||
   1770             (si->port_p2l_mapping[phy_port] == -1)) {
   1771             continue;
   1772         }
   1773 
   1774     /* coverity[overrun-local] */
   1775         SOC_PBMP_PORT_ADD(logic_pbmp, si->port_p2l_mapping[phy_port]);
   1776     /* coverity[overrun-local] */
   1777         PORTMOD_PBMP_PORT_ADD(phy_pbmp, phy_port);
   1778     }
   1779 
   1780     /* First 'delete' mappings */
   1781     for (i = 0, pr = &resource[0];
   1782          (i < nport) && (pr->physical_port == -1);
   1783          i++, pr++) {
   1784         phy_port = si->port_l2p_mapping[pr->logical_port];
   1785         if (phy_port == -1) {
   1786             LOG_ERROR(BSL_LS_SOC_PORT,
   1787                       (BSL_META_U(unit,
   1788                                   "Logical port %d is not currently mapped\n"),
   1789                        pr->logical_port));
   1790             return SOC_E_CONFIG;
   1791         }
   1792         SOC_PBMP_PORT_REMOVE(logic_pbmp, pr->logical_port);
   1793         SOC_PBMP_PORT_REMOVE(phy_pbmp, phy_port);
   1794     }
   1795 
   1796     /* Continue with 'add' mappings in rest of array */
   1797     for (; i < nport; i++, pr++) {
   1798         /* Check that port number is 'available' */
   1799         if (SOC_PBMP_MEMBER(logic_pbmp, pr->logical_port) ||
   1800              PORTMOD_PBMP_MEMBER(phy_pbmp, pr->physical_port)) {
   1801             LOG_ERROR(BSL_LS_SOC_PORT,
   1802                       (BSL_META_U(unit,
   1803                                   "Either Logical port %d or "
   1804                                   "Physical port %d is already mapped\n"),
   1805                        pr->logical_port, pr->physical_port));
   1806             return SOC_E_BUSY;
   1807         }
   1808 
   1809         SOC_PBMP_PORT_ADD(logic_pbmp, pr->logical_port);
   1810         PORTMOD_PBMP_PORT_ADD(phy_pbmp, pr->physical_port);
   1811     }
   1812     SOC_PBMP_CLEAR(phy_pbmp_tmp);
   1813     PORTMOD_PBMP_OR(phy_pbmp_tmp, phy_pbmp);
   1814     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1815                 (BSL_META_U(unit,
   1816                             "New port bitmap\n"
   1817                             "    logical  = %s\n"
   1818                             "    physical = %s\n"),
   1819                  SOC_PBMP_FMT(logic_pbmp, logic_pfmt),
   1820                  SOC_PBMP_FMT(phy_pbmp_tmp, phy_pfmt)));
   1821 
   1822     /* Check maximum number of logical ports allowed */
   1823     SOC_IF_ERROR_RETURN
   1824         (_soc_mn_logic_ports_max_validate(unit, phy_pbmp));
   1825 
   1826 
   1827     /*
   1828      * Lanes availability
   1829      *
   1830      * Check that lanes needed by the physical port are not
   1831      * not being used by any other port.
   1832      *
   1833      * Assume physical port numbers are consecutive in device
   1834      * with respect of the lanes.
   1835      */
   1836     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1837                 (BSL_META_U(unit,
   1838                             "--- VALIDATE: Port lanes assignment\n")));
   1839     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   1840         /* Skip delete entries */
   1841         if (pr->physical_port == -1) {
   1842             continue;
   1843         }
   1844 
   1845         /*
   1846          * For 100GE or more, we need to check all 12 lanes
   1847          * even though only 10 lanes are actually used.
   1848          */
   1849         num_lanes = pr->num_lanes;
   1850         if ((pr->speed >= 100000) && IS_CXX_PORT(unit, pr->logical_port)) {
   1851             num_lanes = 12;
   1852         }
   1853 
   1854         for (lane = 1; lane < num_lanes; lane++) {
   1855             /* Check lane is not being used */
   1856             if (PORTMOD_PBMP_MEMBER(phy_pbmp, pr->physical_port + lane)) {
   1857                 LOG_ERROR(BSL_LS_SOC_PORT,
   1858                           (BSL_META_U(unit,
   1859                                       "Port=%d physical_port=%d, lane on "
   1860                                       "physical port %d is being used\n"),
   1861                                       pr->logical_port, pr->physical_port,
   1862                                       pr->physical_port + lane));
   1863                 return SOC_E_BUSY;
   1864             }
   1865         }
   1866     }
   1867     if (!(SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) &&
   1868                     !soc_property_get(unit, "skip_tdm_init", 0)) {
   1869         /* Check TDM port configuration */
   1870         SOC_IF_ERROR_RETURN
   1871          (_soc_mn_port_resource_tdm_config_validate(unit,
   1872                                                      nport, resource,
   1873                                                      phy_pbmp));
   1874     }
   1875     return SOC_E_NONE;
   1876 }
   1877 
   1878 /*
   1879  * Function:
   1880  *      _soc_mn_port_resource_mixed_sister_validate
   1881  * Purpose:
   1882  *      Validate Oversubscription mode:
   1883  *      - Ports with speed 100GE or more are not in oversubscription mode.
   1884  *      - Line rate or Oversub is the same in all ports within the same
   1885  *        Port Macro (non-mixed mode in sister ports).
   1886  * Parameters:
   1887  *      unit     - (IN) Unit number.
   1888  *      nport    - (IN) Number of elements in array resource.
   1889  *      resource - (IN) Port resource configuration array.
   1890  *      post_si  - (IN) SOC_INFO data after FlexPort.
   1891  * Returns:
   1892  *      SOC_E_XXX
   1893  * Note:
   1894  *      - Resource is not NULL.
   1895  *      - Assumes array order is correct
   1896  *        ('delete' operations are first in array).
   1897  */
   1898 STATIC int
   1899 _soc_mn_port_resource_mixed_sisters_validate(int unit,
   1900                                          int nport,
   1901                                          soc_port_resource_t *resource,
   1902                                          soc_info_mn_misc_t *post_si)
   1903 {
   1904 
   1905     soc_port_resource_t *pr;
   1906     int i;
   1907     int j;
   1908     int logic_port;
   1909     int phy_port  ;
   1910     int sister_port;
   1911     int speed;
   1912     int spd_cls, sister_spd_cls;
   1913     uint32 sp_spacing = 0;
   1914     int sister_speed,lanes_sister[MN_PORTS_PER_TSC];
   1915     int encap_sister[MN_PORTS_PER_TSC];  
   1916     int speed_sister[MN_PORTS_PER_TSC];  
   1917     int size = 0; 
   1918     int rv = 0;
   1919     int type;
   1920     LOG_VERBOSE(BSL_LS_SOC_PORT,
   1921                 (BSL_META_U(unit,
   1922                             "--- VALIDATE: Mixed speed sister ports\n")));
   1923 
   1924      for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   1925         phy_port = pr->physical_port;
   1926 
   1927         /* Skip delete entries */
   1928         if (phy_port == -1) {
   1929             continue;
   1930         }
   1931 
   1932         sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[0];
   1933        
   1934 
   1935         phy_port = pr->physical_port;
   1936         speed = pr->speed;
   1937 
   1938         size = 0 ; 
   1939         for (j = 0; j < MN_PORTS_PER_TSC; j++) {
   1940             sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[j];
   1941             logic_port = post_si->port_p2l_mapping[sister_port];
   1942 
   1943             if (logic_port < 0) {
   1944                 continue;  /* Skip if port is not defined */
   1945             }
   1946             if (SOC_PBMP_MEMBER(post_si->disabled_bitmap, logic_port)) {
   1947                 continue;  /* Skip inactive ports */
   1948             }
   1949             lanes_sister[size] = post_si->port_num_lanes[logic_port];
   1950             encap_sister[size] = post_si->port_encap[logic_port];
   1951             speed_sister[size] = post_si->port_speed[logic_port];
   1952             size++; 
   1953         }
   1954         SOC_IF_ERROR_RETURN(soc_mn_portctrl_pm_type_get(unit, phy_port, &type));
   1955 
   1956         if (type != portmodDispatchTypePm4x10) {
   1957             rv =  soc_esw_portmod_port_vcos_get(unit , phy_port, type, lanes_sister,
   1958                                       speed_sister , encap_sister, size); 
   1959         }
   1960         if (rv != SOC_E_NONE) {  
   1961             LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   1962                              "TSC PLL no availabe pll to support the speed   "
   1963                                     "%d \n"), phy_port));
   1964                 return SOC_E_CONFIG;                    
   1965         }
   1966         
   1967         /* Skip Line Rate ports */
   1968         if (!SOC_PBMP_MEMBER(post_si->oversub_pbm, pr->logical_port)) {
   1969             continue;
   1970         }
   1971 
   1972         /*
   1973          * Check that Oversub sister ports (ports within a Port Macro)
   1974          * have the same speed class
   1975          */
   1976         speed = pr->speed;
   1977         SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit,
   1978                                 &speed, &spd_cls, &sp_spacing));
   1979 
   1980         for (j = 0; j < MN_PORTS_PER_TSC; j++) {
   1981             sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[j];
   1982             logic_port = post_si->port_p2l_mapping[sister_port];
   1983 
   1984             if (logic_port < 0) {
   1985                 continue;  /* Skip if port is not defined */
   1986             }
   1987             if (SOC_PBMP_MEMBER(post_si->disabled_bitmap, logic_port)) {
   1988                 continue;  /* Skip inactive ports */
   1989             }
   1990 
   1991             sister_speed = post_si->port_speed[logic_port];
   1992             if (sister_speed <= 0) {
   1993                 continue;
   1994             }
   1995             SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit,
   1996                                      &sister_speed, &sister_spd_cls, &sp_spacing));
   1997             if (((speed == 10000) && (post_si->port_speed[logic_port] <= 5000)) ||
   1998                ((pr->speed <= 5000) && (sister_speed == 10000))) {
   1999                     continue;
   2000             }
   2001          
   2002             if (spd_cls != sister_spd_cls) {
   2003 
   2004                   LOG_ERROR(BSL_LS_SOC_PORT,
   2005                           (BSL_META_U(unit,
   2006                                       "Speed class must be the same on "
   2007                                       "oversub sister physical ports "
   2008                                       "%d %d %d %d\n"),
   2009                            MN_PHY_PORT(unit, phy_port).sisters_ports[0],
   2010                            MN_PHY_PORT(unit, phy_port).sisters_ports[1],
   2011                            MN_PHY_PORT(unit, phy_port).sisters_ports[2],
   2012                            MN_PHY_PORT(unit, phy_port).sisters_ports[3]));
   2013                    LOG_ERROR(BSL_LS_SOC_PORT,
   2014                           (BSL_META_U(unit,
   2015                                       "Speed class mismatch: \n"
   2016                                       "  logical_port=%d physical_port=%d "
   2017                                       "speed=%d\n"
   2018                                       "  logical_port=%d physical_port=%d "
   2019                                       "speed=%d\n"),
   2020                            pr->logical_port, pr->physical_port, speed,
   2021                            logic_port, sister_port, sister_speed));
   2022                   return SOC_E_CONFIG;
   2023             }
   2024         }
   2025      }
   2026 
   2027      return SOC_E_NONE;
   2028 }
   2029 
   2030 /*
   2031  * Function:
   2032  *      soc_mn_port_mixed_sister_speed_validate
   2033  * Purpose:
   2034  *      Check all sister ports has same speed in oversub mode
   2035  * Parameters:
   2036  *      unit     - (IN) Unit number.
   2037  * Returns:
   2038  *      SOC_E_XXX
   2039  * Note:
   2040  *      Assumes that this function is called at early stage of initialization
   2041  *      (For example, soc_apache_port_config_init).
   2042  *      Because portctrl/portmod API is not ready to use,
   2043  *      use port_speed_max or port_init_speed instead.
   2044  */
   2045 int
   2046 soc_mn_port_mixed_sister_speed_validate(int unit)
   2047 {
   2048     int i,j;
   2049     int lport, sister_lport, phy_port, sister_port;
   2050     int speed, sister_speed;
   2051     int spd_cls, sister_spd_cls ;
   2052     soc_info_t *si = &SOC_INFO(unit);
   2053     uint32 sp_spacing = 0;
   2054     int speed_sister[MN_PORTS_PER_TSC]={0};
   2055     int lanes_sister[MN_PORTS_PER_TSC]={0};
   2056     int encap_sister[MN_PORTS_PER_TSC]={0};
   2057     int size = 0;
   2058     int rv = 0; 
   2059     int type;
   2060     int roe_speed_rsvd4, roe_speed_cpri;
   2061     soc_pbmp_t          pbmp_xport_cpri;
   2062     SOC_PBMP_CLEAR(pbmp_xport_cpri);
   2063     pbmp_xport_cpri = soc_property_get_pbmp_default(unit, spn_PBMP_XPORT_CPRI,
   2064                                  pbmp_xport_cpri);
   2065     /* Loop for 1st physical port in PortMacro */
   2066     for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port += MN_PORTS_PER_TSC) {
   2067 
   2068         lport = si->port_p2l_mapping[phy_port];
   2069         if (lport < 0) {
   2070             continue;
   2071         }
   2072         if (si->port_speed_max[lport] < 0) {
   2073             continue;
   2074         }
   2075 
   2076         sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[0];
   2077         size = 0; 
   2078         for (j = phy_port; j <( phy_port + MN_PORTS_PER_TSC); j++) {
   2079              
   2080     /* coverity[overrun-local] */
   2081              sister_lport = si->port_p2l_mapping[j];
   2082        
   2083              if (sister_lport < 0) {
   2084                  continue;  /* Skip if port is not defined */
   2085              }    
   2086              if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, sister_lport)) {
   2087                  continue;  /* Skip inactive ports */
   2088              } 
   2089              lanes_sister[size] = si->port_num_lanes[sister_lport];
   2090              roe_speed_cpri = soc_property_port_get(unit, sister_lport, spn_CPRI_PORT_INIT_SPEED_ID, -1);
   2091              roe_speed_rsvd4 =  soc_property_port_get(unit, sister_lport, spn_RSVD4_PORT_INIT_SPEED_ID, -1);
   2092              if (IS_HG_PORT(unit,sister_lport)) { 
   2093                  encap_sister[size] = SOC_ENCAP_HIGIG;
   2094                  speed_sister[size] = si->port_speed_max[sister_lport];
   2095              } else if ((SOC_PBMP_MEMBER(pbmp_xport_cpri, sister_lport)) && (roe_speed_cpri > 0)) {
   2096                  encap_sister[size] = SOC_ENCAP_CPRI;
   2097                  speed_sister[size] = roe_speed_cpri;
   2098              } else if ((SOC_PBMP_MEMBER(pbmp_xport_cpri, sister_lport)) && (roe_speed_rsvd4 > 0)) {
   2099                  encap_sister[size] = SOC_ENCAP_RSVD4;
   2100                  speed_sister[size] = roe_speed_rsvd4;
   2101              } else { 
   2102                  encap_sister[size] = SOC_ENCAP_IEEE;
   2103                  speed_sister[size] = si->port_speed_max[sister_lport];
   2104              }
   2105              size++;
   2106         }
   2107         SOC_IF_ERROR_RETURN(soc_mn_portctrl_pm_type_get(unit, phy_port, &type));
   2108 
   2109         if (type != portmodDispatchTypePm4x10) {
   2110             rv =  soc_esw_portmod_port_vcos_get(unit, phy_port, type, lanes_sister,
   2111                                    speed_sister ,encap_sister, size);
   2112         }
   2113         if (rv != SOC_E_NONE) {
   2114             LOG_VERBOSE(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   2115                       "TSC PLL no availabe pll to support the speed   "
   2116                                         "%d \n"), phy_port));
   2117             return SOC_E_CONFIG;
   2118        } 
   2119 
   2120         /* Skip Line Rate ports
   2121            Assumes mixed oversub mode is already checked */
   2122         if (!SOC_PBMP_MEMBER(si->oversub_pbm, lport)) {
   2123             continue;
   2124         }
   2125 
   2126         /*
   2127          * Check that Oversub sister ports (ports within a Port Macro)
   2128          * have the same speed class
   2129          */
   2130         speed = si->port_speed_max[lport]; 
   2131         SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit,
   2132                                 &speed, &spd_cls, &sp_spacing));
   2133 
   2134         for (i = 1; i < MN_PORTS_PER_TSC; i++) {
   2135             sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[i];
   2136             sister_lport = si->port_p2l_mapping[sister_port];
   2137             if (sister_lport < 0) {
   2138                 continue;
   2139             }
   2140 
   2141             if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, sister_lport)) {
   2142                 continue;
   2143             }
   2144 
   2145             sister_speed = si->port_speed_max[sister_lport];
   2146 
   2147             SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit,
   2148                                     &sister_speed, &sister_spd_cls, &sp_spacing));
   2149             
   2150             if (((speed == 10000) && (si->port_speed_max[sister_lport] <= 5000)) ||
   2151                 ((si->port_speed_max[lport] <= 5000) && (sister_speed ==10000))) {
   2152                     continue;
   2153             }
   2154             if (spd_cls != sister_spd_cls) {  
   2155 
   2156                 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   2157                           "Mixed port speed is not acceptable in oversub mode "
   2158                           "on physical ports %d %d %d %d\n"),
   2159                            MN_PHY_PORT(unit, phy_port).sisters_ports[0],
   2160                            MN_PHY_PORT(unit, phy_port).sisters_ports[1],
   2161                            MN_PHY_PORT(unit, phy_port).sisters_ports[2],
   2162                            MN_PHY_PORT(unit, phy_port).sisters_ports[3]));
   2163                 return SOC_E_CONFIG;
   2164             }
   2165         }
   2166     }
   2167 
   2168     return SOC_E_NONE;
   2169 }
   2170 
   2171 /*
   2172  * Function:
   2173  *      _soc_mn_port_resource_validate_output
   2174  * Purpose:
   2175  *      Debug output for given port resource array.
   2176  * Parameters:
   2177  *      unit           - (IN) Unit number.
   2178  *      nport          - (IN) Number of elements in array resource.
   2179  *      resource       - (IN) Port Resource FlexPort configuration.
   2180  * Returns:
   2181  *      SOC_E_XXX
   2182  */
   2183 STATIC void
   2184 _soc_mn_port_resource_validate_output(int unit,
   2185                                         int nport,
   2186                                         soc_port_resource_t *resource)
   2187 {
   2188     int i;
   2189     soc_port_resource_t *pr;
   2190 
   2191     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2192                 (BSL_META_U(unit,
   2193                             "--- SOC Port Resource Input Array ---\n")));
   2194 
   2195     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2196                 (BSL_META_U(unit,
   2197                             "Logical Physical  Speed  Lanes   "
   2198                             "Encap  Flags\n")));
   2199 
   2200     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2201 
   2202         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2203                     (BSL_META_U(unit,
   2204                                 "  %3d     %3d    "),
   2205                      pr->logical_port, pr->physical_port));
   2206         if (pr->physical_port == -1) {
   2207             LOG_VERBOSE(BSL_LS_SOC_PORT,
   2208                         (BSL_META_U(unit,
   2209                                     "---------------------  0x%8.8x\n"),
   2210                          pr->flags));
   2211             continue;
   2212         }
   2213 
   2214         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2215                     (BSL_META_U(unit,
   2216                                 "%6d    %2d  %6s   0x%8.8x\n"),
   2217                      pr->speed, pr->num_lanes,
   2218                      (pr->encap == BCM_PORT_ENCAP_HIGIG2) ? "HG" : "!HG",
   2219                      pr->flags));
   2220     }
   2221 
   2222     return;
   2223 }
   2224 
   2225 /*
   2226  * Function:
   2227  *      soc_mn_port_resource_validate
   2228  * Purpose:
   2229  *      Validate that the given FlexPort configuration is valid.
   2230  * Parameters:
   2231  *      unit     - (IN) Unit number.
   2232  *      nport    - (IN) Number of elements in array resource.
   2233  *      resource - (IN) Port resource configuration array.
   2234  * Returns:
   2235  *      SOC_E_XXX
   2236  * Note:
   2237  */
   2238 int
   2239 soc_mn_port_resource_validate(int unit, int nport, soc_port_resource_t *resource)
   2240 {
   2241     int i, rv;
   2242     soc_port_resource_t *pr;
   2243     soc_info_mn_misc_t *post_si;
   2244     int is_speed_set = FALSE;
   2245 
   2246     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2247                 (BSL_META_U(unit,
   2248                             "\n=============================================\n"
   2249                             "========= SOC PORT RESOURCE VALIDATE ========\n"
   2250                             "=============================================\n"
   2251                             )));
   2252     _soc_mn_port_resource_validate_output(unit, nport, resource);
   2253     /*
   2254      * Check lanes and speed assignment
   2255      */
   2256     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2257                 (BSL_META_U(unit,
   2258                             "--- VALIDATE: Port flex enable, lanes, speed\n")));
   2259     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2260         /* Skip delete entries */
   2261 
   2262         if (!(pr->flags & SOC_PORT_RESOURCE_SPEED)) {
   2263              if (pr->physical_port == -1) {
   2264                  /* Check if flex operation is enabled on old phy port */
   2265                  SOC_IF_ERROR_RETURN(_soc_mn_phy_port_flex_valid
   2266                                            (unit, SOC_INFO(unit).port_l2p_mapping[pr->logical_port]));
   2267                  /* Skip delete entries */
   2268                  continue;
   2269                  } else { 
   2270                  /* Check if flex operation is enabled on new phy port */
   2271                     SOC_IF_ERROR_RETURN(_soc_mn_phy_port_flex_valid
   2272                                                     (unit, pr->physical_port));
   2273                  }
   2274             /* Check if flex is enabled on port */
   2275             SOC_IF_ERROR_RETURN(_soc_mn_phy_port_flex_valid(unit, pr->physical_port));
   2276 
   2277             if ( !soc_feature(unit,soc_feature_rsvd4_support) &&  (pr->encap == SOC_ENCAP_RSVD4)) {
   2278               return SOC_E_UNAVAIL;
   2279             } 
   2280             /* Check lane assignment */
   2281             SOC_IF_ERROR_RETURN(_soc_mn_phy_port_lanes_valid(unit, pr->physical_port,
   2282                                                              pr->num_lanes));
   2283             if ((pr->encap != SOC_ENCAP_CPRI) && (pr->encap != SOC_ENCAP_RSVD4)) {
   2284             /* Check speed (port rate) */
   2285                 SOC_IF_ERROR_RETURN(_soc_mn_speed_valid(unit, pr->physical_port,
   2286                                                     pr->num_lanes, pr->speed));
   2287             }   
   2288         } else {
   2289             is_speed_set = TRUE;
   2290         }
   2291     }
   2292 
   2293     /* Check port mappings */
   2294     if (is_speed_set != TRUE) {
   2295         SOC_IF_ERROR_RETURN(_soc_mn_port_mapping_validate(unit, nport, resource));
   2296     }
   2297 
   2298     post_si = sal_alloc(sizeof(soc_info_mn_misc_t), "soc_info_mn_misc");
   2299     if (NULL == post_si) {
   2300         return SOC_E_MEMORY;
   2301     }
   2302 
   2303     /*
   2304      * Get additional port information needed for validation,
   2305      * Post FlexPort SOC INFO port data
   2306      *
   2307      * NOTE that this is a local subset of the global SOC_INFO
   2308      * which at this point should not be updated yet.
   2309      */
   2310     rv = _soc_mn_post_soc_info_get(unit, nport, resource, post_si);
   2311     
   2312     if (SOC_SUCCESS(rv)) {
   2313         /* Validate oversub speed group limits */
   2314         rv = _soc_mn_port_resource_ovs_speed_group_validate(unit, post_si);
   2315     }
   2316     /* Check mixed speed on sister ports */
   2317     if (SOC_SUCCESS(rv)) {
   2318         rv = _soc_mn_port_resource_mixed_sisters_validate(unit, nport, resource, post_si);
   2319     }
   2320 
   2321     sal_free(post_si);
   2322     return rv;
   2323 }
   2324 
   2325 
   2326 
   2327 
   2328 /*
   2329  * Function:
   2330  *      _soc_mn_port_resource_data_cleanup
   2331  * Purpose:
   2332  *      Cleanup give data structure (deallocate memory).
   2333  * Parameters:
   2334  *      unit           - (IN) Unit number.
   2335  *      pre_resource   - (IN/OUT) Memory to deallocate.
   2336  * Returns:
   2337  *      None
   2338  * Note:
   2339  */
   2340 STATIC void
   2341 _soc_mn_port_resource_data_cleanup(soc_port_resource_t **pre_resource)
   2342 {
   2343     if (*pre_resource != NULL) {
   2344         sal_free(*pre_resource);
   2345         *pre_resource = NULL;
   2346     }
   2347 
   2348     return;
   2349 }
   2350 
   2351 /*
   2352  * Function:
   2353  *      soc_monterey_port_mode_get
   2354  * Description:
   2355  *      Get port mode by giving first logical port of TSC4
   2356  * Parameters:
   2357  *      unit          - Device number
   2358  *      port          - Logical port
   2359  *      int*          - Port Mode
   2360  *
   2361  * Each TSC4 can be configured into following 5 mode:
   2362  *   Lane number    0    1    2    3
   2363  *   ------------  ---  ---  ---  ---
   2364  *      quad port  10G  10G  10G  10G
   2365  *   tri_012 port  10G  10G  20G   x
   2366  *   tri_023 port  20G   x   10G  10G
   2367  *      dual port  20G   x   20G   x
   2368  *    single port  40G   x    x    x
   2369  */
   2370 int
   2371 soc_monterey_port_mode_get(int unit, int logical_port, int *mode)
   2372 {
   2373     soc_info_t *si;
   2374     int lane;
   2375     int port, first_phyport, phy_port;
   2376     int num_lanes[MN_PORTS_PER_TSC];
   2377 
   2378     si = &SOC_INFO(unit);
   2379     /* Each core is 4 lane core to get the first divide by 4 then multiply by 4
   2380      * physical port is 2 => ((2-1)/4)*4+1 = 1
   2381      * physical port is 9 => ((12-1)/4)*4+1 = 9
   2382      */
   2383     first_phyport = (((si->port_l2p_mapping[logical_port]-1)/4)*4)+1;
   2384 
   2385     for (lane = 0; lane < MN_PORTS_PER_TSC; lane++) {
   2386         phy_port = first_phyport + lane;
   2387         port = si->port_p2l_mapping[phy_port];
   2388         if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   2389             num_lanes[lane] = -1;
   2390         } else {
   2391             num_lanes[lane] = si->port_num_lanes[port];
   2392         }
   2393     }
   2394 
   2395     if (num_lanes[0] == 4) {
   2396         *mode = SOC_MONTEREY_PORT_MODE_QUAD;
   2397     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
   2398         *mode = SOC_MONTEREY_PORT_MODE_DUAL;
   2399     } else if (num_lanes[0] == 2 && num_lanes[2] == 1 && num_lanes[3] == 1) {
   2400         *mode = SOC_MONTEREY_PORT_MODE_TRI_023;
   2401     } else if (num_lanes[0] == 1 && num_lanes[1] == 1 && num_lanes[2] == 2) {
   2402         *mode = SOC_MONTEREY_PORT_MODE_TRI_012;
   2403     } else {
   2404         *mode = SOC_MONTEREY_PORT_MODE_SINGLE;
   2405     }
   2406 
   2407     return SOC_E_NONE;
   2408 }
   2409 #if 0
   2410 /*
   2411  * Function:
   2412  *      _soc_mn_port_mode_get
   2413  * Description:
   2414  *      Get port mode by giving first logical port of TSC4
   2415  *      Same as above function but uses post soc info to calculate mode
   2416  * Parameters:
   2417  *      unit          - Device number
   2418  *      logical_port  - Logical port
   2419  *      post_si       - Post Soc info
   2420  *      int*          - Port Mode
   2421  *
   2422  * Each TSC4 can be configured into following 5 mode:
   2423  *   Lane number    0    1    2    3
   2424  *   ------------  ---  ---  ---  ---
   2425  *      quad port  10G  10G  10G  10G
   2426  *   tri_012 port  10G  10G  20G   x
   2427  *   tri_023 port  20G   x   10G  10G
   2428  *      dual port  20G   x   20G   x
   2429  *    single port  40G   x    x    x
   2430  */
   2431 STATIC int
   2432 _soc_mn_port_mode_get(int unit, int logical_port, soc_info_mn_misc_t *post_si, int *mode)
   2433 {
   2434     int lane;
   2435     int port, first_phyport, phy_port;
   2436     int num_lanes[MN_PORTS_PER_TSC];
   2437 
   2438     first_phyport = post_si->port_l2p_mapping[logical_port];
   2439 
   2440     for (lane = 0; lane < MN_PORTS_PER_TSC; lane++) {
   2441         phy_port = first_phyport + lane;
   2442         port = post_si->port_p2l_mapping[phy_port];
   2443         if (port == -1 || SOC_PBMP_MEMBER(post_si->disabled_bitmap, port)) {
   2444             num_lanes[lane] = -1;
   2445         } else {
   2446             num_lanes[lane] = post_si->port_num_lanes[port];
   2447         }
   2448     }
   2449 
   2450     if (num_lanes[0] == 4) {
   2451         *mode = SOC_MONTEREY_PORT_MODE_QUAD;
   2452     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
   2453         *mode = SOC_MONTEREY_PORT_MODE_DUAL;
   2454     } else if (num_lanes[0] == 2 && num_lanes[2] == 1 && num_lanes[3] == 1) {
   2455         *mode = SOC_MONTEREY_PORT_MODE_TRI_023;
   2456     } else if (num_lanes[0] == 1 && num_lanes[1] == 1 && num_lanes[2] == 2) {
   2457         *mode = SOC_MONTEREY_PORT_MODE_TRI_012;
   2458     } else {
   2459         *mode = SOC_MONTEREY_PORT_MODE_SINGLE;
   2460     }
   2461 
   2462     return SOC_E_NONE;
   2463 }
   2464 #endif
   2465 
   2466 
   2467 /*
   2468  * Function:
   2469  *      _soc_mn_port_resource_mode_get
   2470  * Purpose:
   2471  *      Get and return the port mode in the given
   2472  *      Port Resource configuration structure.
   2473  * Parameters:
   2474  *      unit           - (IN) Unit number.
   2475  *      nport          - (IN) Number of elements in array resource.
   2476  *      resource       - (IN/OUT) Port Resource FlexPort configuration.
   2477  * Returns:
   2478  *      SOC_E_XXX
   2479  * Note:
   2480  *      If some ports are not present (inactive), routine will
   2481  *      try to figure out best match.
   2482  */
   2483 STATIC int
   2484 _soc_mn_port_resource_mode_get(int unit,
   2485                                  int nport,
   2486                                  soc_port_resource_t *resource)
   2487 {
   2488     soc_info_t *si = &SOC_INFO(unit); 
   2489     soc_port_resource_t *pr;
   2490     int i;
   2491     int j;
   2492     int logic_port;
   2493     int phy_port;
   2494     int sister_port;
   2495     int num_lanes[MN_PORTS_PER_TSC];
   2496     int one_active_lane;
   2497     int two_active_lane;
   2498     int four_active_lane;
   2499     char *modes_str[] = {"Quad", "Tri_012", "Tri_023", "Dual", "Single"};
   2500 
   2501     soc_pbmp_t new_disabled_bitmap;
   2502     int new_port_p2l_mapping[SOC_MAX_NUM_PORTS];
   2503     int new_port_num_lanes[SOC_MAX_NUM_PORTS];
   2504 
   2505     /*
   2506      * Build information needed to determine port mode
   2507      */
   2508 
   2509     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2510                 (BSL_META_U(unit,
   2511                             "--- Get Port Mode\n")));
   2512 
   2513     /* Get current information */
   2514     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
   2515         new_port_p2l_mapping[i] = si->port_p2l_mapping[i];
   2516         new_port_num_lanes[i] = si->port_num_lanes[i];
   2517     }
   2518     SOC_PBMP_ASSIGN(new_disabled_bitmap, si->all.disabled_bitmap);
   2519 
   2520     /* First 'delete' mappings */
   2521     for (i = 0, pr = &resource[0];
   2522          (i < nport) && (pr->physical_port == -1);
   2523          i++, pr++) {
   2524         logic_port = pr->logical_port;
   2525 
   2526         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   2527             SOC_PBMP_PORT_ADD(new_disabled_bitmap, logic_port);
   2528             continue;
   2529         }
   2530 
   2531         SOC_PBMP_PORT_REMOVE(new_disabled_bitmap, logic_port);
   2532         new_port_p2l_mapping[si->port_l2p_mapping[logic_port]] = -1;
   2533         new_port_num_lanes[logic_port] = -1;
   2534     }
   2535 
   2536     /* Continue with 'add' mappings in rest of array */
   2537     for (; i < nport; i++, pr++) {
   2538         logic_port = pr->logical_port;
   2539         phy_port = pr->physical_port;
   2540 
   2541         SOC_PBMP_PORT_REMOVE(new_disabled_bitmap, logic_port);
   2542         new_port_p2l_mapping[phy_port] = logic_port;
   2543         new_port_num_lanes[logic_port] = pr->num_lanes;
   2544     }
   2545 
   2546 
   2547     /*
   2548      * Determine port mode based on sister ports lane configuration
   2549      */
   2550     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2551         /* Skip delete entries (assume these to be first in array) */
   2552         if (pr->physical_port == -1) {
   2553             continue;
   2554         }
   2555 
   2556         one_active_lane = 0;
   2557         two_active_lane = 0;
   2558         four_active_lane = 0;
   2559 
   2560         /* Get number of active lanes on sister ports */
   2561         phy_port = pr->physical_port;
   2562 
   2563 
   2564         for (j = 0; j < MN_PORTS_PER_TSC; j++) {
   2565             sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[j];
   2566             logic_port = new_port_p2l_mapping[sister_port];
   2567 
   2568             if (logic_port < 0) {
   2569                 num_lanes[j] = 0;
   2570                 continue;
   2571             }
   2572 
   2573             if (SOC_PBMP_MEMBER(new_disabled_bitmap, logic_port)) {
   2574                 num_lanes[j] = 0;
   2575             } else {
   2576                 num_lanes[j] = new_port_num_lanes[logic_port];
   2577             }
   2578         }
   2579 
   2580 
   2581         /*
   2582          * Quad:    Lane0, Lane1, Lane2, Lane3 are active (individually)
   2583          * Dual:    Lane0, Lane2, are active (Lane0 and Lane2 are dual)
   2584          * Single:  Lane0 is active, one physical port using all lanes, 4/10/12
   2585          * Tri_012: Lane0, Lane1, Lane2 are active (Lane2 is dual)
   2586          * Tri_023: Lane0, Lane2, Lane3 are active (Lane0 is dual)
   2587          *
   2588          * If any lane is -1, make best guess.
   2589          */
   2590 
   2591         /* Count active lanes */
   2592         for (j = 0; j < MN_PORTS_PER_TSC; j++) {
   2593             if (num_lanes[j] == 1) {
   2594                 one_active_lane++;
   2595             } else if (num_lanes[j] == 2) {
   2596                 two_active_lane++;
   2597             } else if (num_lanes[j] >= 4) {
   2598                 /* No more checking is needed */
   2599                 four_active_lane++;
   2600                 break;
   2601             }
   2602         }
   2603 
   2604         /* Get mode based on active lanes */
   2605         if (four_active_lane) {
   2606             pr->mode = SOC_MONTEREY_PORT_MODE_SINGLE;
   2607         } else if (one_active_lane && !two_active_lane) {
   2608             pr->mode = SOC_MONTEREY_PORT_MODE_QUAD;
   2609         } else if (!one_active_lane && two_active_lane) {
   2610             pr->mode = SOC_MONTEREY_PORT_MODE_DUAL;
   2611         } else if (one_active_lane && two_active_lane) {
   2612             if (num_lanes[0] == 1) {
   2613                 pr->mode = SOC_MONTEREY_PORT_MODE_TRI_012;
   2614             } else {
   2615                 pr->mode = SOC_MONTEREY_PORT_MODE_TRI_023;
   2616             }
   2617         } else {
   2618             LOG_ERROR(BSL_LS_SOC_PORT,
   2619                       (BSL_META_U(unit,
   2620                                   "Invalid number of lanes "
   2621                                   "logical_port=%d physical_port=%d "
   2622                                   "num_lanes=%d\n"),
   2623                        pr->logical_port, pr->physical_port, pr->num_lanes));
   2624             return SOC_E_INTERNAL;
   2625         }
   2626 
   2627         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2628                     (BSL_META_U(unit,
   2629                                 "Port mode is %s for "
   2630                                 "logical_port=%d physical_port=%d\n"),
   2631                      modes_str[pr->mode],
   2632                      pr->logical_port, pr->physical_port));
   2633     }
   2634 
   2635     return SOC_E_NONE;
   2636 }
   2637 
   2638 
   2639 /*
   2640  * Function:
   2641  *      _soc_mn_port_resource_output
   2642  * Purpose:
   2643  *      Debug output for given port resource array.
   2644  * Parameters:
   2645  *      unit           - (IN) Unit number.
   2646  *      header         - (IN) Header outout string.
   2647  *      nport          - (IN) Number of elements in array resource.
   2648  *      resource       - (IN) Port Resource FlexPort configuration.
   2649  * Returns:
   2650  *      SOC_E_XXX
   2651  */
   2652 STATIC void
   2653 _soc_mn_port_resource_output(int unit, char *header,
   2654                                int nport, soc_port_resource_t *resource)
   2655 {
   2656     int i;
   2657     int lane;
   2658     soc_port_resource_t *pr;
   2659     char *modes_str[] = {"Quad", "T012", "T023", "Dual", "Sngl"};
   2660     char *mode_str;
   2661 
   2662     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2663                 (BSL_META_U(unit,
   2664                             "%s\n"), header));
   2665 
   2666     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2667                 (BSL_META_U(unit,
   2668                             "Logical Physical MMU "
   2669                             "Speed Lanes Mode Ovs PrioMask Flags       "
   2670                             "PGW XLP PIDX\n")));
   2671 
   2672     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2673         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2674                     (BSL_META_U(unit,
   2675                                 "  %3d     %3d    "),
   2676                      pr->logical_port, pr->physical_port));
   2677         if (pr->physical_port == -1) {
   2678             LOG_VERBOSE(BSL_LS_SOC_PORT,
   2679                         (BSL_META_U(unit,
   2680                                     "------------------------------------- "
   2681                                     "0x%8.8x\n"),
   2682                          pr->flags));
   2683             continue;
   2684         }
   2685 
   2686         /*
   2687          * This arrays used to determine the 'string' assumes
   2688          * certain values on the Port Modes defined in soc_monterey_port_mode_e.
   2689          */
   2690         if ((pr->mode < 0) ||  (pr->mode > 4)) {
   2691             mode_str = "----";
   2692         } else {
   2693             mode_str = modes_str[pr->mode];
   2694         }
   2695         LOG_VERBOSE(BSL_LS_SOC_PORT,
   2696                     (BSL_META_U(unit,
   2697                                 "  %3d    "
   2698                                 "%6d  %2d   %4s  %1d  0x%4.4x 0x%8.8x"),
   2699                      pr->mmu_port, pr->speed, pr->num_lanes, mode_str,
   2700                      pr->oversub, pr->prio_mask, pr->flags));
   2701         if (pr->num_lanes == 0) {
   2702             LOG_VERBOSE(BSL_LS_SOC_PORT,
   2703                         (BSL_META_U(unit,
   2704                                     "  %2d  %2d  %2d\n"),
   2705                          -1, -1, -1));
   2706         } else {
   2707             for (lane = 0; lane < pr->num_lanes; lane++) {
   2708                 if (lane > 0) {
   2709                     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2710                                 (BSL_META_U(unit, "%65s"), " "));
   2711                 }
   2712                 LOG_VERBOSE(BSL_LS_SOC_PORT,
   2713                             (BSL_META_U(unit,
   2714                                         "  %2d  %2d  %2d\n"),
   2715                          pr->lane_info[lane]->pgw,
   2716                          pr->lane_info[lane]->tsc,
   2717                          pr->lane_info[lane]->port_index));
   2718             }
   2719         }
   2720     }
   2721 
   2722     return;
   2723 }
   2724 
   2725 
   2726 /*
   2727  * Function:
   2728  *      _soc_mn_port_resource_data_output
   2729  * Purpose:
   2730  *      Debug output.
   2731  * Parameters:
   2732  *      unit           - (IN) Unit number.
   2733  *      nport          - (IN) Number of elements in array resource.
   2734  *      resource       - (IN) Port Resource FlexPort configuration.
   2735  *      pre_count      - (IN) Array size for pre-FlexPort array.
   2736  *      pre_resource   - (IN) Pre-FlexPort configuration array.
   2737  *      post_count     - (IN) Array size for post-FlexPort array.
   2738  *      post_resource  - (IN) Pre-FlexPort configuration array.
   2739  * Returns:
   2740  *      SOC_E_XXX
   2741  */
   2742 STATIC void
   2743 _soc_mn_port_resource_data_output(int unit,
   2744                                     int nport, soc_port_resource_t *resource,
   2745                                     int pre_count,
   2746                                     soc_port_resource_t *pre_resource,
   2747                                     int post_count,
   2748                                     soc_port_resource_t *post_resource)
   2749 {
   2750     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2751                 (BSL_META_U(unit,
   2752                             "\n=============================================\n"
   2753                             "=========== SOC PORT RESOURCE DATA ==========\n"
   2754                             "=============================================\n"
   2755                             )));
   2756 
   2757     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2758                 (BSL_META_U(unit, "\n")));
   2759     _soc_mn_port_resource_output(unit,
   2760                                    "=== FlexPort Port Resource Data ===",
   2761                                    nport, resource);
   2762     
   2763     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2764                 (BSL_META_U(unit, "\n")));
   2765     _soc_mn_port_resource_output(unit,
   2766                                    "=== Pre-FlexPort Port Resource Data ===",
   2767                                    pre_count, pre_resource);
   2768 
   2769     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2770                 (BSL_META_U(unit, "\n")));
   2771     _soc_mn_port_resource_output(unit,
   2772                                    "=== Post-FlexPort Port Resource Data ===",
   2773                                    post_count, post_resource);
   2774 
   2775     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2776                 (BSL_META_U(unit, "\n")));
   2777     return;
   2778 }
   2779 
   2780 
   2781 /*
   2782  * Function:
   2783  *      _soc_mn_port_resource_data_init
   2784  * Purpose:
   2785  *      Allocate and get pre and post FlexPort Port Resource
   2786  *      information for given FlexPort configuration.
   2787  * Parameters:
   2788  *      unit           - (IN) Unit number.
   2789  *      nport          - (IN) Number of elements in array resource.
   2790  *      resource       - (IN/OUT) Port Resource FlexPort configuration.
   2791  *      pre_count      - (OUT) Array size for pre-FlexPort array.
   2792  *      pre_resource   - (OUT) Pre-FlexPort configuration array.
   2793  *      post_count     - (OUT) Array size for post-FlexPort array.
   2794  *      post_resource  - (OUT) Pre-FlexPort configuration array.
   2795  *      pre_soc_info   - (OUT) A subset of the SOC_INFO information
   2796  *                             before the FlexPort operation.
   2797  * Returns:
   2798  *      SOC_E_XXX
   2799  * Note:
   2800  *      - Assumes data is Port Resource has been validated.
   2801  *      - Assumes array order is correct (deletes are first in array).
   2802  *      - Assumes pointer parameters are not null.
   2803  *      - Assumes the following fields have been filled already in input
   2804  *        SOC Port Resource data structure:
   2805  *          flags
   2806  *          logical_port
   2807  *          physical_port
   2808  *          speed
   2809  *          num_lanes 
   2810  *
   2811  *
   2812  * The 'resource' or main-FlexPort list contains both, all the elements
   2813  * in the pre-FlexPort list followed by the elements in the post-FlexPort
   2814  * list (in that order):
   2815  *     resource = pre_resource + post_resource
   2816  *
   2817  * The pre-FlexPort and post-FlexPort operation arrays are filled
   2818  * out as follows:
   2819  *
   2820  * Pre-FlexPort array
   2821  *     This is the array of 'old' ports.
   2822  *     It contains current information for ports that are configured in the
   2823  *     system and are to be modified after the FlexPort operation.
   2824  *     This should include all mappings where ports are deleted/cleared
   2825  *     (i.e. physical_port is -1).
   2826  *     NOTE that even though the port is set to be 'deleted',
   2827  *     the actual final port mapping (after FlexPort) may
   2828  *     result to be the same, destroyed, or remapped based on what the rest
   2829  *     of the array configuration.
   2830  *
   2831  * Post-FlexPort array
   2832  *     This is the array of 'new' ports.
   2833  *     It contains the configuration information on the new ports that will
   2834  *     be configured in the system and are active (present) after
   2835  *     the FlexPort operation.
   2836  *     This should include mappings where the physical ports are not (-1).
   2837  *     The actual ports mappings can result to be the same, remapped or new,
   2838  *     based on the rest of the array information.
   2839  *
   2840  * Example:
   2841  *
   2842  *     Logical_port --> Physical_port
   2843  *
   2844  *     Main FlexPort array ('resource')
   2845  *               L1 --> -1 (current mapped to P1), mapping is SAME
   2846  *               L2 --> -1 (current mapped to P2), mapping is REMAP
   2847  *               L3 --> -1 (current mapped to P3), mapping is DESTROY
   2848  *               L1 --> P1                       , mapping is SAME
   2849  *               L2 --> P5                       , mapping is REMAP
   2850  *               L9 --> P9                       , mapping is NEW
   2851  *
   2852  *     Pre-FlexPort array
   2853  *               L1 --> P1 mapping is SAME
   2854  *               L2 --> P2 mapping is REMAP
   2855  *               L3 --> P3 mapping is DESTROY
   2856  *
   2857  *     Post-FlexPort array
   2858  *               L1 --> P1 mapping is SAME
   2859  *               L2 --> P5 mapping is REMAP
   2860  *               L9 --> P9 mapping is NEW
   2861  */
   2862 STATIC int
   2863 _soc_mn_port_resource_data_init(int unit,
   2864                                   int nport, soc_port_resource_t *resource,
   2865                                   int *pre_count,
   2866                                   soc_port_resource_t **pre_resource,
   2867                                   int *post_count,
   2868                                   soc_port_resource_t **post_resource,
   2869                                   soc_mn_info_t *pre_soc_info)
   2870 {
   2871     int i;
   2872     int lane;
   2873     int num_lanes;
   2874     int phy_port;
   2875     int delete_count = 0;
   2876     soc_port_resource_t *pr;
   2877     soc_port_resource_t *pre_pr;
   2878     soc_info_t *si = &SOC_INFO(unit);
   2879 
   2880     /* Init parameters */
   2881     *pre_count = 0;
   2882     *pre_resource = NULL;
   2883     *post_count = 0;
   2884     *post_resource = NULL;
   2885 
   2886 
   2887     /*************************************
   2888      * Fill main FlexPort information
   2889      */
   2890 
   2891 
   2892     LOG_VERBOSE(BSL_LS_SOC_PORT,
   2893                 (BSL_META_U(unit,
   2894                             "\n====== SOC PORT RESOURCE DATA GATHER =====\n")));
   2895 
   2896     /* Get rest of SOC FlexPort information */
   2897     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   2898         pr->mode = -1;
   2899         /* Skip delete entries (assume these to be first in array) */
   2900         if (pr->physical_port == -1) {
   2901             delete_count++;
   2902             continue;
   2903         }
   2904 
   2905         phy_port = pr->physical_port;
   2906         pr->prio_mask = MN_PHY_PORT(unit, phy_port).prio_mask;
   2907         SOC_IF_ERROR_RETURN
   2908             (soc_mn_port_oversub_get(unit, phy_port, pr->logical_port,
   2909                                        &pr->oversub));
   2910 
   2911         /*
   2912          * Get Lanes information
   2913          * Assume lanes are arranged consecutively with respect to
   2914          * the physical port number.
   2915          */
   2916         for (lane = 0; lane < pr->num_lanes; lane++) {
   2917             pr->lane_info[lane] = &MN_PHY_PORT_LANE(unit, phy_port + lane);
   2918         }
   2919     }
   2920 
   2921     /*
   2922      * Get port mode (quad, dual, single, tri) into 'resource' array.
   2923      */
   2924     SOC_IF_ERROR_RETURN
   2925         (_soc_mn_port_resource_mode_get(unit,
   2926                                           nport, resource));
   2927 
   2928     /* Set count for pre and post FlexPort arrays */
   2929     *pre_count = delete_count;
   2930     *post_count = nport - delete_count;
   2931 
   2932 
   2933     /********************************
   2934      * Pre-FlexPort array
   2935      */
   2936     /* Allocate memory */
   2937     if ((*pre_count) > 0) {
   2938         *pre_resource = sal_alloc(sizeof(soc_port_resource_t) * (*pre_count),
   2939                                   "pre_port_resource");
   2940         if (*pre_resource == NULL) {
   2941             LOG_ERROR(BSL_LS_SOC_PORT,
   2942                       (BSL_META_U(unit,
   2943                                   "Unable to allocate memory for pre resource "
   2944                                   "array in FlexPort operation\n")));
   2945             return SOC_E_MEMORY;
   2946         }
   2947         sal_memset(*pre_resource, 0,
   2948                    sizeof(soc_port_resource_t) * (*pre_count));
   2949     }
   2950     /* Fill information */
   2951     for (i = 0, pre_pr = *pre_resource, pr = &resource[0];
   2952          i < *pre_count;
   2953          i++, pre_pr++, pr++) {
   2954 
   2955         /* Assume physical port is valid */
   2956         phy_port = si->port_l2p_mapping[pr->logical_port];
   2957 
   2958         pre_pr->flags = pr->flags;
   2959         pre_pr->logical_port = pr->logical_port;
   2960         pre_pr->physical_port = phy_port;
   2961         pre_pr->mmu_port = si->port_p2m_mapping[phy_port];
   2962         pre_pr->num_lanes = si->port_num_lanes[pr->logical_port];
   2963         pre_pr->prio_mask = MN_PHY_PORT(unit, phy_port).prio_mask;
   2964         pre_pr->oversub =
   2965             SOC_PBMP_MEMBER(si->oversub_pbm, pre_pr->logical_port) ? 1 : 0;
   2966 
   2967          pre_pr->speed = si->port_speed_max[pr->logical_port];
   2968         /* Set inactive flag to indicate port is disabled */
   2969         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, pr->logical_port)) {
   2970             pre_pr->flags |= SOC_PORT_RESOURCE_INACTIVE;
   2971 
   2972             pre_pr->mode = -1;
   2973         } else {
   2974             SOC_IF_ERROR_RETURN
   2975                 (soc_portctrl_port_mode_get(unit, pr->logical_port,
   2976                                             &(pre_pr->mode), &num_lanes));
   2977         }
   2978 
   2979         /*
   2980          * Get Lanes information
   2981          * Assume lanes are arranged consecutively with respect to
   2982          * the physical port number.
   2983          */
   2984         for (lane = 0; lane < pre_pr->num_lanes; lane++) {
   2985             pre_pr->lane_info[lane] =
   2986                 &MN_PHY_PORT_LANE(unit, phy_port + lane);
   2987         }
   2988 
   2989     }
   2990 
   2991 
   2992     /********************************
   2993      * Post-FlexPort array
   2994      *
   2995      * Just use the main FlexPort array since this has
   2996      * all the new information that is needed for the 'post' array.
   2997      */
   2998     if ((*post_count) > 0) {
   2999         *post_resource = &resource[(*pre_count)];
   3000     }
   3001 
   3002 
   3003     /********************************
   3004      * Pre-FlexPort SOC info data
   3005      *
   3006      * This contains partial information of the current
   3007      * SOC information (pre-FlexPort) needed during later
   3008      * stages of the FlexPort reconfiguration sequence.
   3009      */
   3010     sal_memset(pre_soc_info, 0, sizeof(*pre_soc_info));
   3011     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
   3012         pre_soc_info->port_l2p_mapping[i] = si->port_l2p_mapping[i];
   3013         pre_soc_info->port_p2l_mapping[i] = si->port_p2l_mapping[i];
   3014         pre_soc_info->port_p2m_mapping[i] = si->port_p2m_mapping[i];
   3015         pre_soc_info->port_m2p_mapping[i] = si->port_m2p_mapping[i];
   3016         pre_soc_info->port_group[i] = si->port_group[i];
   3017         pre_soc_info->port_speed_max[i] = si->port_speed_max[i];
   3018         pre_soc_info->port_num_lanes[i] = si->port_num_lanes[i];
   3019     }
   3020 
   3021     SOC_PBMP_ASSIGN(pre_soc_info->xpipe_pbm, si->xpipe_pbm);
   3022     SOC_PBMP_ASSIGN(pre_soc_info->oversub_pbm, si->oversub_pbm);
   3023 
   3024     return SOC_E_NONE;
   3025 }
   3026 
   3027 /*
   3028  * Function:
   3029  *      _soc_mn_soc_info_ptype_update
   3030  * Purpose:
   3031  *      Update the SOC_INFO ptype information and port names based
   3032  *      on the port type bitmaps.
   3033  * Parameters:
   3034  *      unit           - (IN) Unit number.
   3035  * Returns:
   3036  *      SOC_E_XXX
   3037  * Notes:
   3038  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3039  *      locks are taken.
   3040  */
   3041 STATIC int
   3042 _soc_mn_soc_info_ptype_update(int unit)
   3043 {
   3044     soc_info_t *si = &SOC_INFO(unit);
   3045     int phy_port;
   3046     int logic_port;
   3047     int blk;
   3048     int bindex;
   3049     int port_idx;
   3050 
   3051     /*
   3052      * Update ptype information
   3053      */
   3054 #define RECONFIGURE_PORT_TYPE_INFO(ptype)                   \
   3055     si->ptype.num = 0;                                      \
   3056     si->ptype.min = si->ptype.max = -1;                     \
   3057     sal_memset(si->ptype.port, 0, sizeof(si->ptype.port)); \
   3058     PBMP_ITER(si->ptype.bitmap, logic_port) {               \
   3059         si->port_offset[logic_port] = si->ptype.num;        \
   3060         si->ptype.port[si->ptype.num++] = logic_port;       \
   3061         if (si->ptype.min < 0) {                            \
   3062             si->ptype.min = logic_port;                     \
   3063         }                                                   \
   3064         if (logic_port > si->ptype.max) {                   \
   3065             si->ptype.max = logic_port;                     \
   3066         }                                                   \
   3067     }
   3068 
   3069     RECONFIGURE_PORT_TYPE_INFO(ge);
   3070     RECONFIGURE_PORT_TYPE_INFO(xe);
   3071     RECONFIGURE_PORT_TYPE_INFO(cxx);
   3072     RECONFIGURE_PORT_TYPE_INFO(ce);
   3073     RECONFIGURE_PORT_TYPE_INFO(xl);
   3074     RECONFIGURE_PORT_TYPE_INFO(cl);
   3075     RECONFIGURE_PORT_TYPE_INFO(gx);
   3076     RECONFIGURE_PORT_TYPE_INFO(ether);
   3077     RECONFIGURE_PORT_TYPE_INFO(hg);
   3078     RECONFIGURE_PORT_TYPE_INFO(st);
   3079     RECONFIGURE_PORT_TYPE_INFO(port);
   3080     RECONFIGURE_PORT_TYPE_INFO(all);
   3081     RECONFIGURE_PORT_TYPE_INFO(cpri);
   3082     RECONFIGURE_PORT_TYPE_INFO(rsvd4);
   3083 
   3084 #undef  RECONFIGURE_PORT_TYPE_INFO
   3085 
   3086 
   3087     /*
   3088      * Update block port
   3089      * Use first logical port on block (logic follows ESW driver
   3090      * soc_info_config().
   3091      */
   3092     for (phy_port = 0; ; phy_port++) {
   3093 
   3094         blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0);
   3095         bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0);
   3096         if (blk < 0 && bindex < 0) { /* End of port list */
   3097             break;
   3098         }
   3099 
   3100         logic_port = si->port_p2l_mapping[phy_port];
   3101         if (logic_port < 0) {
   3102             continue;
   3103         }
   3104 
   3105         for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) {
   3106             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx);
   3107             if (blk < 0) { /* End of block list of each port */
   3108                 break;
   3109             }
   3110 
   3111             if (si->block_port[blk] < 0) {
   3112                 si->block_port[blk] = logic_port;
   3113             }
   3114         }
   3115     }
   3116 
   3117     /* Update user port mappings (includes port names update) */
   3118     soc_esw_dport_init(unit);
   3119 
   3120     return SOC_E_NONE;
   3121 }
   3122 
   3123 #define PORT_IS_CXX(pport)  FALSE 
   3124     
   3125 /*
   3126  * Function:
   3127  *      _soc_mn_soc_info_ptype_ports_add
   3128  * Purpose:
   3129  *      Set the port type bitmaps and block information in SOC_INFO
   3130  *      for ports to be configured during the FlexPort operation.
   3131  * Parameters:
   3132  *      unit           - (IN) Unit number.
   3133  *      post_count     - (IN) Array size.
   3134  *      post_resource  - (IN) Array of ports to add.
   3135  * Returns:
   3136  *      SOC_E_XXX
   3137  * Notes:
   3138  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3139  *      locks are taken.
   3140  */
   3141 STATIC int
   3142 _soc_mn_soc_info_ptype_ports_add(int unit,
   3143                                    int post_count,
   3144                                    soc_port_resource_t *post_resource)
   3145 {
   3146     soc_info_t *si = &SOC_INFO(unit);
   3147     soc_port_resource_t *pr;
   3148     int i;
   3149     int phy_port;
   3150     int logic_port;
   3151     int blk;
   3152     int bindex;
   3153     int blktype;
   3154     int old_blktype;
   3155     int port_idx;
   3156 
   3157     /*
   3158      * Add to port type bitmaps and block information
   3159      */
   3160     for (i = 0, pr = &post_resource[0]; i < post_count; i++, pr++) {
   3161 
   3162         logic_port = pr->logical_port;
   3163         phy_port = pr->physical_port;
   3164 
   3165         if (!si->port_speed_max[logic_port]) {
   3166             LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   3167                                         "Invalid speed %d for "
   3168                                         "logical port %d\n"),
   3169                                         si->port_speed_max[logic_port], logic_port));
   3170             return SOC_E_INTERNAL;
   3171         }
   3172 
   3173         /* Clear bitmaps */
   3174         SOC_PBMP_PORT_REMOVE(si->cl.bitmap, logic_port);
   3175         SOC_PBMP_PORT_REMOVE(si->cxx.bitmap, logic_port);
   3176         SOC_PBMP_PORT_REMOVE(si->clg2.bitmap, logic_port);
   3177         SOC_PBMP_PORT_REMOVE(si->xl.bitmap, logic_port);
   3178         SOC_PBMP_PORT_REMOVE(si->xlb0.bitmap, logic_port);
   3179         SOC_PBMP_PORT_REMOVE(si->ether.bitmap, logic_port);
   3180         SOC_PBMP_PORT_REMOVE(si->hg.bitmap, logic_port);
   3181         SOC_PBMP_PORT_REMOVE(si->xe.bitmap, logic_port);
   3182         SOC_PBMP_PORT_REMOVE(si->ce.bitmap, logic_port);
   3183         SOC_PBMP_PORT_REMOVE(si->ge.bitmap, logic_port);
   3184         SOC_PBMP_PORT_REMOVE(si->st.bitmap, logic_port);
   3185 
   3186         if (pr->encap == SOC_ENCAP_IEEE) {
   3187             if (si->port_speed_max[logic_port] >= 100000) {    /* CE */
   3188                 SOC_PBMP_PORT_ADD(si->ce.bitmap, logic_port);
   3189             } else if (si->port_speed_max[logic_port] < 10000) {    /* GE */
   3190                 SOC_PBMP_PORT_ADD(si->ge.bitmap, logic_port);
   3191             } else { /* XE */
   3192                 SOC_PBMP_PORT_ADD(si->xe.bitmap, logic_port);
   3193             }
   3194             SOC_PBMP_PORT_ADD(si->ether.bitmap, logic_port);
   3195         } else if ((pr->encap == SOC_ENCAP_CPRI) || (pr->encap == SOC_ENCAP_RSVD4)) {
   3196             SOC_PBMP_PORT_ADD(si->cpri.bitmap, logic_port);
   3197         } else { /* HG */
   3198                 SOC_PBMP_PORT_ADD(si->hg.bitmap, logic_port);
   3199                 SOC_PBMP_PORT_ADD(si->st.bitmap, logic_port);
   3200         }
   3201 
   3202         SOC_PBMP_PORT_ADD(si->port.bitmap, logic_port);
   3203         SOC_PBMP_PORT_ADD(si->all.bitmap, logic_port);
   3204         SOC_PBMP_PORT_ADD(si->gx.bitmap, logic_port);
   3205 
   3206 
   3207         blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0);
   3208         bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0);
   3209         if (blk < 0 && bindex < 0) { /* End of regsfile port list */
   3210             continue;
   3211         }
   3212 
   3213         blktype = -1;
   3214         for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) {
   3215 
   3216             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx);
   3217             if (blk < 0) { /* End of block list of each port */
   3218                 break;
   3219             }
   3220 
   3221             old_blktype = blktype;
   3222             blktype = SOC_BLOCK_INFO(unit, blk).type;
   3223 
   3224             switch (blktype) {
   3225 
   3226             case SOC_BLK_CLPORT:
   3227                 if (PORT_IS_FALCON(phy_port) ||
   3228                     ((PORT_IS_CXX(phy_port) && (si->port_speed_max[logic_port] >= 100000)))) {
   3229                     /*PM4x25 or PM12x10 in CAUI10 mode */
   3230                     SOC_PBMP_PORT_ADD(si->cl.bitmap, logic_port);
   3231                 } else {
   3232                     blktype = old_blktype;
   3233                     continue;
   3234                 }
   3235                 break;
   3236 
   3237             case SOC_BLK_CLG2PORT:
   3238                 if (PORT_IS_FALCON(phy_port)) {
   3239                     SOC_PBMP_PORT_ADD(si->clg2.bitmap, logic_port);
   3240                 } else {
   3241                     blktype = old_blktype;
   3242                     continue;
   3243                 }
   3244                 break;
   3245 
   3246             case SOC_BLK_XLPORT:
   3247                 if ((PORT_IS_CXX(phy_port)) && (si->port_speed_max[logic_port] >= 100000)) {
   3248                     /* In CAUI10 mode, enable XLPORT block for all 3 cores */
   3249                     if (si->block_port[blk] < 0) {
   3250                         si->block_port[blk] = logic_port;
   3251                     }
   3252                     if (si->block_port[blk + 1] < 0) {
   3253                         si->block_port[blk + 1] = logic_port;
   3254                     }
   3255                     if (si->block_port[blk + 2] < 0) {
   3256                         si->block_port[blk + 2] = logic_port;
   3257                     }
   3258                     si->block_valid[blk] += 1;
   3259                     si->block_valid[blk + 1] += 1;
   3260                     si->block_valid[blk + 2] += 1;
   3261                     /* No need to add in bitmap */
   3262                     continue;
   3263                 } else {
   3264                     SOC_PBMP_PORT_ADD(si->xl.bitmap, logic_port);
   3265                 }
   3266                 break;
   3267 
   3268             case SOC_BLK_PGW_CL:
   3269                 /* Don't use the name from this block */
   3270                 blktype = old_blktype;
   3271                 break;
   3272 
   3273             default:
   3274                 break;
   3275             }
   3276              /* Block info is still intact in case of legacy flexport
   3277              * Only update port bitmaps and continue
   3278              */
   3279             if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   3280                 continue;
   3281             }
   3282             /* Update block information */
   3283             si->block_valid[blk] += 1;
   3284 
   3285             if (si->block_port[blk] < 0) {
   3286                 si->block_port[blk] = logic_port;
   3287             }
   3288             SOC_PBMP_PORT_ADD(si->block_bitmap[blk], logic_port);
   3289 
   3290         } /* For each block in the given port */
   3291 
   3292          /* Block info is still intact, so skip updating it in case of legacy flexport
   3293          */
   3294         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   3295             continue;
   3296         }
   3297 
   3298         si->port_type[logic_port] = blktype;
   3299         si->port_num++;
   3300 
   3301         /* Update CXXPORT block information */
   3302         if (SOC_SUCCESS(soc_monterey_port_reg_blk_index_get
   3303                     (unit, logic_port, SOC_BLK_CXXPORT, &blk))) {
   3304             si->block_valid[blk] += 1;
   3305 
   3306             if (si->block_port[blk] < 0) si->block_port[blk] = logic_port;
   3307         }
   3308 
   3309     } /* For each port */
   3310 
   3311     /* Need to update rest of ptype information */
   3312     SOC_IF_ERROR_RETURN(_soc_mn_soc_info_ptype_update(unit));
   3313 
   3314     return SOC_E_NONE;
   3315 }
   3316 
   3317 
   3318 /*
   3319  * Function:
   3320  *      _soc_mn_soc_info_ptype_ports_delete
   3321  * Purpose:
   3322  *      Clear the port type bitmaps and block information in SOC_INFO
   3323  *      for ports to be removed during the FlexPort operation.
   3324  * Parameters:
   3325  *      unit           - (IN) Unit number.
   3326  *      pre_count      - (IN) Array size.
   3327  *      pre_resource   - (IN) Array for ports to delete.
   3328  * Returns:
   3329  *      SOC_E_XXX
   3330  * Notes:
   3331  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3332  *      locks are taken.
   3333  */
   3334 STATIC int
   3335 _soc_mn_soc_info_ptype_ports_delete(int unit,
   3336                                       int pre_count,
   3337                                       soc_port_resource_t *pre_resource)
   3338 {
   3339     soc_info_t *si = &SOC_INFO(unit);
   3340     soc_port_resource_t *pr;
   3341     int i;
   3342     int phy_port;
   3343     int logic_port;
   3344     int blk;
   3345     int blktype;
   3346     int bindex;
   3347     int port_idx;
   3348 
   3349     /*
   3350      * Clear port bitmaps and block information
   3351      */
   3352     for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) {
   3353          
   3354         /* Skip deletion of block info in case of legacy flexport
   3355          * Port bitmaps will be cleared and updated in _soc_ap_soc_info_ptype_ports_add
   3356          * as per post_resource
   3357          */
   3358 
   3359         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   3360             continue;
   3361         }
   3362 
   3363         logic_port = pr->logical_port;
   3364         phy_port = pr->physical_port;
   3365 
   3366         /*
   3367          * Clear port from all possible port bitmaps where a flexed port
   3368          * can be a member of.
   3369          */
   3370 
   3371         if (phy_port == -1) {
   3372             continue;
   3373         }
   3374 
   3375         blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0);
   3376         bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0);
   3377         if (blk < 0 && bindex < 0) { /* End of regsfile port list */
   3378             continue;
   3379         }
   3380 
   3381         blktype = -1;
   3382         /* Clear block information */
   3383         for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) {
   3384 
   3385             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx);
   3386             blktype = SOC_BLOCK_INFO(unit, blk).type;
   3387             if (blk < 0) { /* End of block list of each port */
   3388                 break;
   3389             }
   3390 
   3391             /* Update block information */
   3392             if (si->block_valid[blk] > 0) {
   3393                 si->block_valid[blk] -= 1;
   3394             }
   3395             if (si->block_port[blk] == logic_port) {
   3396                 si->block_port[blk] = REG_PORT_ANY;
   3397             }
   3398             if (blktype == SOC_BLK_XLPORT) {
   3399             /* Disable XLPORT block for last 2 cores in case CAUI10 port is being deleted */
   3400                 if (PORT_IS_CXX(phy_port) && (si->port_speed_max[logic_port] >= 100000)) {
   3401                     if (si->block_valid[blk + 1] > 0) {
   3402                         si->block_valid[blk + 1] -= 1;
   3403                     }
   3404                     if (si->block_valid[blk + 2] > 0) {
   3405                         si->block_valid[blk + 2] -= 1;
   3406                     }
   3407                     if (si->block_port[blk + 1] == logic_port) {
   3408                         si->block_port[blk + 1] = REG_PORT_ANY;
   3409                     }
   3410                     if (si->block_port[blk + 2] == logic_port) {
   3411                         si->block_port[blk + 2] = REG_PORT_ANY;
   3412                     }
   3413                 }
   3414             }
   3415 
   3416             SOC_PBMP_PORT_REMOVE(si->block_bitmap[blk], logic_port);
   3417 
   3418         } /* For each block in the given port */
   3419 
   3420         si->port_type[logic_port] = 0;
   3421         si->port_offset[logic_port] = 0;
   3422 
   3423         if (si->port_num > 0) {
   3424             si->port_num--;
   3425         }
   3426         /* Clear CXXPORT block information */
   3427         if (SOC_SUCCESS(soc_monterey_port_reg_blk_index_get
   3428                     (unit, logic_port, SOC_BLK_CXXPORT, &blk))) {
   3429             if (si->block_valid[blk] > 0) {
   3430                 si->block_valid[blk] -= 1;
   3431             }
   3432             if (si->block_port[blk] == logic_port) {
   3433                 si->block_port[blk] = REG_PORT_ANY;
   3434             }
   3435         }
   3436         /*
   3437         * Clear port from all possible port bitmaps where a flexed port
   3438         * can be a member of.
   3439         */
   3440         SOC_PBMP_PORT_REMOVE(si->ge.bitmap, logic_port);
   3441         SOC_PBMP_PORT_REMOVE(si->xe.bitmap, logic_port);
   3442         SOC_PBMP_PORT_REMOVE(si->cxx.bitmap, logic_port);
   3443         SOC_PBMP_PORT_REMOVE(si->ce.bitmap, logic_port);
   3444         SOC_PBMP_PORT_REMOVE(si->xl.bitmap, logic_port);
   3445         SOC_PBMP_PORT_REMOVE(si->xlb0.bitmap, logic_port);
   3446         SOC_PBMP_PORT_REMOVE(si->cl.bitmap, logic_port);
   3447         SOC_PBMP_PORT_REMOVE(si->clg2.bitmap, logic_port);
   3448         SOC_PBMP_PORT_REMOVE(si->gx.bitmap, logic_port);
   3449         SOC_PBMP_PORT_REMOVE(si->ether.bitmap, logic_port);
   3450         SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, logic_port);
   3451         SOC_PBMP_PORT_REMOVE(si->hg.bitmap, logic_port);
   3452         SOC_PBMP_PORT_REMOVE(si->st.bitmap, logic_port);
   3453         SOC_PBMP_PORT_REMOVE(si->port.bitmap, logic_port);
   3454         SOC_PBMP_PORT_REMOVE(si->all.bitmap, logic_port);
   3455 
   3456     } /* For each port */
   3457 
   3458     /* Update rest of ptype information */
   3459     SOC_IF_ERROR_RETURN(_soc_mn_soc_info_ptype_update(unit));
   3460 
   3461     return SOC_E_NONE;
   3462 }
   3463 
   3464 
   3465 /*
   3466  * Function:
   3467  *      _soc_mn_soc_counter_ports_add
   3468  * Purpose:
   3469  *      Add ports to SOC counter map.
   3470  * Parameters:
   3471  *      unit           - (IN) Unit number.
   3472  *      post_count     - (IN) Array size.
   3473  *      post_resource  - (IN) Array of ports to add.
   3474  * Returns:
   3475  *      SOC_E_XXX
   3476  * Notes:
   3477  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3478  *      locks are taken.
   3479  */
   3480 STATIC int
   3481 _soc_mn_soc_counter_ports_add(int unit,
   3482                                 int post_count,
   3483                                 soc_port_resource_t *post_resource)
   3484 {
   3485     soc_control_t *soc = SOC_CONTROL(unit);
   3486     soc_port_resource_t *pr;
   3487     int i;
   3488     int phy_port;
   3489     int logic_port;
   3490     int blk;
   3491     int bindex;
   3492     int blktype;
   3493     int port_idx;
   3494     soc_ctr_type_t ctype;
   3495     int rv = SOC_E_NONE;
   3496 
   3497     for (i = 0, pr = &post_resource[0]; i < post_count; i++, pr++) {
   3498         logic_port = pr->logical_port;
   3499         phy_port = pr->physical_port;
   3500 
   3501         blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0);
   3502         bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0);
   3503         if (blk < 0 && bindex < 0) { /* End of regsfile port list */
   3504             continue;
   3505         }
   3506 
   3507         for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) {
   3508             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx);
   3509             if (blk < 0) { /* End of block list of each port */
   3510                 break;
   3511             }
   3512 
   3513             blktype = SOC_BLOCK_INFO(unit, blk).type;
   3514 
   3515             switch (blktype) {
   3516             case SOC_BLK_CLPORT:
   3517             case SOC_BLK_XLPORT:
   3518             case SOC_BLK_XLPORTB0:
   3519                 ctype = SOC_CTR_TYPE_XE;
   3520                 break;
   3521             case SOC_BLK_CLG2PORT:
   3522                 ctype = SOC_CTR_TYPE_CE;
   3523                 break;
   3524             case SOC_BLK_CPRI:
   3525                if(IS_CPRI_PORT(unit, logic_port) &&
   3526                             SOC_IS_MONTEREY(unit) ) {
   3527                    ctype = SOC_CTR_TYPE_CPU;
   3528                } else
   3529                {
   3530                  ctype = -1;
   3531                }
   3532                break;
   3533             default:
   3534                 ctype = -1;
   3535                 break;
   3536             }
   3537 
   3538             if (ctype != -1) {
   3539                 /* Adding of dma counter descriptors is only necessary when the
   3540                  * counter thread is running
   3541                  * this check is necessary to avoid reallocating the dma descriptos
   3542                  * when the conter thread is stopped running before the
   3543                  * flex operation
   3544                  */
   3545                 if (soc->counter_interval) {
   3546                     rv = soc_counter_port_sbusdma_desc_alloc(unit, logic_port);
   3547                     if (SOC_FAILURE(rv)) {
   3548                         LOG_ERROR(BSL_LS_SOC_PORT,
   3549                         (BSL_META_U(unit,
   3550                         "Error! Unable to allocate SBUS DMA descriptors per"
   3551                         " logical_port %d  \n"),
   3552                              logic_port));
   3553                        return rv;
   3554                     }
   3555                 }
   3556                 SOC_IF_ERROR_RETURN
   3557                     (soc_port_cmap_set(unit, logic_port, ctype));
   3558                 SOC_PBMP_PORT_ADD(soc->counter_pbmp, logic_port);
   3559                 break;
   3560             }
   3561         } /* For each block in the given port */
   3562 
   3563     } /* For each port */
   3564 
   3565     return SOC_E_NONE;
   3566 }
   3567 
   3568 
   3569 /*
   3570  * Function:
   3571  *      _soc_mn_soc_counter_ports_delete
   3572  * Purpose:
   3573  *      Delete ports from SOC counter map.
   3574  * Parameters:
   3575  *      unit           - (IN) Unit number.
   3576  *      pre_count      - (IN) Array size.
   3577  *      pre_resource   - (IN) Array of ports to delete.
   3578  * Returns:
   3579  *      SOC_E_XXX
   3580  * Notes:
   3581  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3582  *      locks are taken.
   3583  */
   3584 STATIC int
   3585 _soc_mn_soc_counter_ports_delete(int unit,
   3586                                    int pre_count,
   3587                                    soc_port_resource_t *pre_resource)
   3588 {
   3589     soc_control_t *soc = SOC_CONTROL(unit);
   3590     soc_port_resource_t *pr;
   3591     int i;
   3592     int phy_port;
   3593     int logic_port;
   3594     int  rv = SOC_E_NONE;
   3595 
   3596     /* Clear counter */
   3597     for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) {
   3598         logic_port = pr->logical_port;
   3599         phy_port = pr->physical_port;
   3600 
   3601         if (phy_port == -1) {
   3602             continue;
   3603         }
   3604 
   3605         /* Delete the counter dma descriptors */
   3606         rv = soc_counter_port_sbusdma_desc_free(unit, logic_port);
   3607         if (SOC_FAILURE(rv)) {
   3608            LOG_ERROR(BSL_LS_SOC_PORT,
   3609                (BSL_META_U(unit,
   3610                 "Error! Unable to delete SBUS DMA descriptors per"
   3611                             " logical_port %d  \n"),
   3612                                  logic_port));
   3613            return rv;
   3614         }
   3615 
   3616         /*
   3617          * If 'inactive' flag, don't do anything
   3618          */
   3619         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   3620             continue;
   3621         }
   3622 
   3623         soc->counter_map[logic_port] = 0;
   3624         SOC_PBMP_PORT_REMOVE(soc->counter_pbmp, logic_port);
   3625     }
   3626 
   3627     return SOC_E_NONE;
   3628 }
   3629 
   3630 
   3631 /*
   3632  * Function:
   3633  *      _soc_mn_soc_info_ports_add
   3634  * Purpose:
   3635  *      Add ports to the SOC_INFO and SOC data structures.
   3636  *
   3637  *      Set information for mappings that are:
   3638  *      - Same     : logical to physical mapping are the same.
   3639  *      - Remapped : different port mapping assignment, logical port existed.
   3640  *      - New      : logical port did not exist prior to FlexPort.
   3641  *
   3642  * Parameters:
   3643  *      unit           - (IN) Unit number.
   3644  *      pre_count      - (IN) Array size.
   3645  *      pre_resource   - (IN) Array for ports to delete.
   3646  * Returns:
   3647  *      SOC_E_XXX
   3648  * Notes:
   3649  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3650  *      locks are taken.
   3651  */
   3652 STATIC int
   3653 _soc_mn_soc_info_ports_add(int unit,
   3654                              int post_count,
   3655                              soc_port_resource_t *post_resource)
   3656 {
   3657     soc_info_t *si = &SOC_INFO(unit);
   3658     soc_port_resource_t *pr;
   3659     int i;
   3660     int logic_port;
   3661     int phy_port, port_is_hsp;
   3662 
   3663     LOG_VERBOSE(BSL_LS_SOC_PORT,
   3664                 (BSL_META_U(unit,
   3665                             "SOC_INFO Ports Add\n")));
   3666 
   3667 
   3668     for (i = 0, pr = &post_resource[0]; i < post_count; i++, pr++) {
   3669         logic_port = pr->logical_port;
   3670         phy_port = pr->physical_port;
   3671 
   3672         LOG_VERBOSE(BSL_LS_SOC_PORT,
   3673                     (BSL_META_U(unit,
   3674                                 "  SOC_INFO: "
   3675                                 "Add logical=%d physical=%d\n"),
   3676                      logic_port, phy_port));
   3677 
   3678 
   3679         /* Always remove from disabled bitmap */
   3680         SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, logic_port);
   3681 
   3682         /* Port Mapping related information */
   3683         si->port_l2p_mapping[logic_port] = phy_port;
   3684         si->port_p2l_mapping[phy_port] = logic_port;
   3685 
   3686         /* Pipeline */
   3687         SOC_PBMP_PORT_ADD(si->xpipe_pbm, logic_port);  
   3688         si->port_pipe[logic_port] = 0;
   3689 
   3690         /* Port data information */
   3691         /* Port data information */
   3692         if (!(pr->flags & SOC_PORT_RESOURCE_SPEED)) {
   3693             si->port_init_speed[logic_port] = pr->speed;
   3694         }
   3695         si->port_speed_max[logic_port] = pr->speed;
   3696         si->port_num_lanes[logic_port] = pr->num_lanes;
   3697         si->port_group[logic_port] = MN_PHY_PORT_LANE(unit, phy_port).pgw;
   3698         si->port_serdes[logic_port] = (phy_port - 1) / MN_PORTS_PER_TSC;
   3699         if (pr->roe_compression) {
   3700             SOC_PBMP_PORT_ADD(si->roe_compression, logic_port);
   3701         }
   3702         if (pr->oversub) {
   3703             SOC_PBMP_PORT_ADD(si->oversub_pbm, logic_port);
   3704         } else {
   3705             SOC_PBMP_PORT_REMOVE(si->oversub_pbm, logic_port);
   3706         }
   3707         if (pr->encap == SOC_ENCAP_CPRI) {
   3708             SOC_PBMP_PORT_ADD(si->cpri.bitmap, logic_port);
   3709             SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, logic_port);
   3710         } else if (pr->encap == SOC_ENCAP_RSVD4) {
   3711             SOC_PBMP_PORT_ADD(si->cpri.bitmap, logic_port);
   3712             SOC_PBMP_PORT_ADD(si->rsvd4.bitmap, logic_port);
   3713         } else {
   3714             SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, logic_port);
   3715             SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, logic_port);
   3716         }
   3717         if ((pr->encap == SOC_ENCAP_CPRI) || (pr->encap == SOC_ENCAP_RSVD4)) {
   3718             si->port_init_speed[logic_port]  = pr->speed;
   3719         }
   3720 
   3721         if (pr->encap == SOC_ENCAP_IEEE) {
   3722             SOC_PBMP_PORT_ADD(si->xe.bitmap, logic_port);
   3723         } else {
   3724             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, logic_port);
   3725         }
   3726 
   3727         /* If this is a high speed port, we need to add it to the extended
   3728            queues port bitmap so that nodes and queues will be able to be
   3729            assigned properly. */
   3730         port_is_hsp = (soc_property_port_get(unit, logic_port, spn_PORT_SCHED_HSP, -1));
   3731         if (port_is_hsp == -1) {
   3732             port_is_hsp = soc_monterey_mmu_hsp_port_reserve(unit, logic_port, pr->speed);
   3733         }
   3734 
   3735         if (port_is_hsp) {
   3736             SOC_PBMP_PORT_ADD(si->eq_pbm, logic_port);
   3737         } else {
   3738             SOC_PBMP_PORT_REMOVE(si->eq_pbm, logic_port);
   3739         }
   3740     }
   3741 
   3742     SOC_PBMP_ASSIGN(si->pipe_pbm[0], si->xpipe_pbm);
   3743 
   3744 
   3745     /* Add to port ptype bitmap and block information */
   3746     SOC_IF_ERROR_RETURN
   3747         (_soc_mn_soc_info_ptype_ports_add(unit,
   3748                                             post_count, post_resource));
   3749 
   3750     /* Add to counter map */
   3751     SOC_IF_ERROR_RETURN
   3752         (_soc_mn_soc_counter_ports_add(unit,
   3753                                          post_count, post_resource));
   3754 
   3755     return SOC_E_NONE;
   3756 }
   3757 
   3758 
   3759 /*
   3760  * Function:
   3761  *      _soc_mn_soc_info_ports_delete
   3762  * Purpose:
   3763  *      Delete ports from the SOC_INFO and SOC data structures.
   3764  *
   3765  *      This would be called to clear information for mappings that are:
   3766  *      - Same     : logical to physical mapping are the same after FlexPort.
   3767  *      - Remapped : different port mapping assignment, logical port existed.
   3768  *      - Destroyed: logical port do no longer exist after FlexPort.
   3769  *
   3770  * Parameters:
   3771  *      unit           - (IN) Unit number.
   3772  *      pre_count      - (IN) Array size.
   3773  *      pre_resource   - (IN) Array for ports to delete.
   3774  * Returns:
   3775  *      SOC_E_XXX
   3776  * Notes:
   3777  *      Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK
   3778  *      locks are taken.
   3779  */
   3780 STATIC int
   3781 _soc_mn_soc_info_ports_delete(int unit,
   3782                                 int pre_count,
   3783                                 soc_port_resource_t *pre_resource)
   3784 {
   3785     soc_info_t *si = &SOC_INFO(unit);
   3786     soc_port_resource_t *pr;
   3787     int i;
   3788     int logic_port;
   3789     int phy_port;
   3790 
   3791     LOG_VERBOSE(BSL_LS_SOC_PORT,
   3792                 (BSL_META_U(unit,
   3793                             "SOC_INFO Ports Delete\n")));
   3794 
   3795 
   3796     /* Delete from counter map */
   3797     SOC_IF_ERROR_RETURN
   3798         (_soc_mn_soc_counter_ports_delete(unit,
   3799                                             pre_count, pre_resource));
   3800 
   3801      /* Delete from port ptype bitmap and block information */
   3802     SOC_IF_ERROR_RETURN
   3803         (_soc_mn_soc_info_ptype_ports_delete(unit,
   3804                                                pre_count, pre_resource));
   3805 
   3806     /* Port Mapping related information */
   3807     for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) {
   3808         logic_port = pr->logical_port;
   3809         phy_port = pr->physical_port;
   3810 
   3811         LOG_VERBOSE(BSL_LS_SOC_PORT,
   3812                     (BSL_META_U(unit,
   3813                                 "  SOC_INFO: "
   3814                                 "Delete logical=%d physical=%d\n"),
   3815                      logic_port, phy_port));
   3816 
   3817         /*
   3818          * If 'inactive' flag, just add port to disabled bitmap.
   3819          * This is part of the legacy API behavior.
   3820          */
   3821         if (pr->flags & SOC_PORT_RESOURCE_I_MAP) {
   3822             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, logic_port);
   3823             continue;
   3824         }
   3825 
   3826         /* Remove from disabled bitmap */
   3827         SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, logic_port);
   3828 
   3829         /* Port Mapping related information */
   3830         si->port_l2p_mapping[logic_port] = -1;
   3831         if (phy_port != -1) {
   3832             si->port_p2l_mapping[phy_port] = -1;
   3833         }
   3834 
   3835         /* Pipeline */
   3836         if (phy_port != -1) {
   3837             SOC_PBMP_PORT_REMOVE(si->xpipe_pbm, logic_port);
   3838         }
   3839 
   3840         if (SOC_PBMP_MEMBER(si->eq_pbm, logic_port)) {
   3841             SOC_PBMP_PORT_REMOVE(si->eq_pbm, logic_port);
   3842         }
   3843 
   3844         /* Logical port related information */
   3845         if (!(pr->flags & SOC_PORT_RESOURCE_SPEED)) {
   3846             si->port_init_speed[logic_port] = -1;
   3847         }
   3848         si->port_speed_max[logic_port] = -1;
   3849         si->port_num_lanes[logic_port] = -1;
   3850         si->port_group[logic_port] = -1;
   3851         si->port_serdes[logic_port] = -1;
   3852         SOC_PBMP_PORT_ADD(si->roe_compression, logic_port);
   3853         SOC_PBMP_PORT_REMOVE(si->oversub_pbm, logic_port);
   3854     }
   3855 
   3856     SOC_PBMP_ASSIGN(si->pipe_pbm[0], si->xpipe_pbm);
   3857 
   3858 
   3859 
   3860     return SOC_E_NONE;
   3861 }
   3862 
   3863 
   3864 /*
   3865  * Function:
   3866  *       _soc_mn_clear_enabled_port_data
   3867  * Purpose:
   3868  *      Clear set of HW register in order to have correct parity value.
   3869  * Parameters:
   3870  *      unit      - (IN) Unit number.
   3871  *      port      - (IN) Logical Port to clear.
   3872  * Returns:
   3873  *      SOC_E_XXX
   3874  */
   3875 STATIC int
   3876 _soc_mn_clear_enabled_port_data(int unit, soc_port_t port)
   3877 {
   3878     uint64 rval64;
   3879     uint32 evc = 0;
   3880     egr_vlan_control_1_entry_t entry_1;
   3881     egr_vlan_control_2_entry_t entry_2;
   3882     egr_vlan_control_3_entry_t entry_3;
   3883 
   3884     /* Some registers are implemented in memory, need to clear them in order
   3885      * to have correct parity value */
   3886     COMPILER_64_ZERO(rval64);
   3887 
   3888     sal_memset(&entry_1, 0, sizeof(entry_1));
   3889     sal_memset(&entry_2, 0, sizeof(entry_2));
   3890     sal_memset(&entry_3, 0, sizeof(entry_3));
   3891 
   3892     SOC_IF_ERROR_RETURN
   3893         (WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry_1));
   3894     SOC_IF_ERROR_RETURN
   3895         (WRITE_EGR_VLAN_CONTROL_2m(unit, MEM_BLOCK_ANY, port, &entry_2));
   3896     SOC_IF_ERROR_RETURN
   3897         (WRITE_EGR_VLAN_CONTROL_3m(unit, MEM_BLOCK_ANY, port, &entry_3));
   3898 
   3899     SOC_IF_ERROR_RETURN(WRITE_EGR_PVLAN_EPORT_CONTROLr(unit, port, 0));
   3900     SOC_IF_ERROR_RETURN(WRITE_EGR_SF_SRC_MODID_CHECKr(unit, port, rval64));
   3901     SOC_IF_ERROR_RETURN(WRITE_EGR_1588_LINK_DELAY_64r(unit, port, rval64));
   3902     SOC_IF_ERROR_RETURN(WRITE_EGR_IPMC_CFG2m(unit, MEM_BLOCK_ALL, port, &evc));
   3903     SOC_IF_ERROR_RETURN(WRITE_STORM_CONTROL_METER_CONFIGr(unit, port, 0));
   3904     SOC_IF_ERROR_RETURN(WRITE_SFLOW_ING_THRESHOLDr(unit, port, 0));
   3905 
   3906     return SOC_E_NONE;
   3907 }
   3908 
   3909 
   3910 /*
   3911  * Function:
   3912  *       _soc_monterey_misc_port_attach
   3913  * Purpose:
   3914  *      Initialize HW for new attached port.
   3915  *      This routine covers the port initialization performed by
   3916  *      the SOC MISC routine soc_misc_init()
   3917  * Parameters:
   3918  *      unit      - (IN) Unit number.
   3919  *      port      - (IN) Logical Port.
   3920  * Returns:
   3921  *      SOC_E_XXX
   3922  */
   3923 STATIC int
   3924 _soc_monterey_misc_port_attach(int unit, soc_port_t port)
   3925 {
   3926     soc_info_t *si;
   3927     int phy_port;
   3928     uint32 rval;
   3929     soc_pbmp_t pbmp;
   3930     egr_ing_port_entry_t egr_ing_entry;
   3931     ing_en_efilter_bitmap_entry_t ing_en_efilter_entry;
   3932     egr_vlan_control_1_entry_t egr_vlan_entry;
   3933     int higig2;
   3934     int rv = SOC_E_NONE;
   3935     soc_control_t  *soc = SOC_CONTROL(unit);
   3936 
   3937     LOG_VERBOSE(BSL_LS_SOC_PORT,
   3938                 (BSL_META_U(unit,
   3939                             "  SOC MISC attach unit=%d port=%d(%s)\n"),
   3940                  unit, port, SOC_PORT_NAME(unit, port)));
   3941 
   3942     si = &SOC_INFO(unit);
   3943 
   3944     if (IS_LB_PORT(unit, port) || IS_CPU_PORT (unit, port) ||
   3945         IS_TDM_PORT(unit, port)) {
   3946         LOG_ERROR(BSL_LS_SOC_PORT,
   3947                   (BSL_META_U(unit,
   3948                               "Port cannot be a Loopback, CPU, or TDM port "
   3949                               "unit=%d port=%d\n"),
   3950                    unit, port));
   3951         return SOC_E_PORT;
   3952     }
   3953 
   3954     phy_port = si->port_l2p_mapping[port];
   3955     if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port)) {
   3956         LOG_ERROR(BSL_LS_SOC_PORT,
   3957                   (BSL_META_U(unit,
   3958                               "Invalid physical port "
   3959                               "unit=%d port=%d physical=%d\n"),
   3960                    unit, port, phy_port));
   3961         return SOC_E_INTERNAL;
   3962     }
   3963 
   3964 
   3965     /*****************
   3966      * Clear port data */
   3967     SOC_IF_ERROR_RETURN
   3968         (_soc_mn_clear_enabled_port_data(unit, port));
   3969 
   3970 
   3971     /*****************
   3972      * Port Mappings
   3973      *
   3974      * NOTE: This only covers IFP_GM_LOGICAL_TO_PHYSICAL_MAPPING.
   3975      * It does NOT set the IP or EP port mappings.  These
   3976      * are covered in the following functions as specified by the
   3977      * FlexPort uArch specs:
   3978      *   - soc_mn_port_resource_ip_set()
   3979      *   - soc_mn_port_resource_ep_set()
   3980      */
   3981     rval = 0;
   3982     soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr, &rval,
   3983                       VALIDf, 1);
   3984     if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { /* Y pipe */
   3985         soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr,
   3986                           &rval, Y_PIPEf, 1);
   3987     }
   3988     /*
   3989      * IFP_GM_LOGICAL_TO_PHYSICAL_MAPPING.PHYSICAL_PORT_NUM is
   3990      * merely a unique stream ID, it's not physical port number.
   3991      */
   3992     soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr, &rval,
   3993                       PHYSICAL_PORT_NUMf,
   3994                       si->port_p2m_mapping[phy_port] & 0x7f);
   3995     MEM_LOCK(unit,FP_GLOBAL_MASK_TCAMm);
   3996     rv = WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval);
   3997     if (rv < 0) {
   3998         MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm);
   3999         return rv;
   4000     }
   4001     soc_mem_fp_global_mask_tcam_cache_update_set(unit, TRUE);
   4002     MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm);
   4003     sal_sem_give(soc->mem_scan_notify);
   4004 
   4005     /*****************
   4006      * Ingress Port egress configuration
   4007      */
   4008     sal_memset(&egr_ing_entry, 0, sizeof(egr_ing_port_entry_t));
   4009     if (IS_HG_PORT(unit, port)) {
   4010         soc_mem_field32_set(unit, EGR_ING_PORTm, &egr_ing_entry,
   4011                             PORT_TYPEf, 1);
   4012         higig2 = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE,
   4013             soc_feature(unit, soc_feature_no_higig_plus) ? 1 : 0) ? 1 : 0;
   4014         soc_mem_field32_set(unit, EGR_ING_PORTm, &egr_ing_entry,
   4015                             HIGIG2f, higig2);
   4016     }
   4017     SOC_IF_ERROR_RETURN
   4018         (WRITE_EGR_ING_PORTm(unit, MEM_BLOCK_ALL, port, &egr_ing_entry));
   4019 
   4020 
   4021 
   4022 
   4023     /*****************
   4024      * VLAN Controls
   4025      * The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which
   4026      * causes the outer tag to be removed from packets that don't have
   4027      * a hit in the egress vlan tranlation table. Set to 0 to disable this.
   4028      */
   4029     sal_memset(&egr_vlan_entry, 0, sizeof(egr_vlan_control_1_entry_t));
   4030     soc_mem_field32_set(unit, EGR_VLAN_CONTROL_1m, &egr_vlan_entry,
   4031                         VT_MISS_UNTAGf, 0);
   4032     /* Enable pri/cfi remarking on egress ports. */
   4033     soc_mem_field32_set(unit, EGR_VLAN_CONTROL_1m, &egr_vlan_entry,
   4034                         REMARK_OUTER_DOT1Pf, 1);
   4035     SOC_IF_ERROR_RETURN
   4036         (WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ALL, port,
   4037                                    &egr_vlan_entry));
   4038 
   4039     /* Ingress port VLAN membership check */
   4040     SOC_IF_ERROR_RETURN
   4041         (READ_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0,
   4042                                      &ing_en_efilter_entry));
   4043     soc_mem_pbmp_field_get(unit, ING_EN_EFILTER_BITMAPm,
   4044                            &ing_en_efilter_entry, BITMAPf, &pbmp);
   4045     SOC_PBMP_PORT_ADD(pbmp, port);
   4046     soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm,
   4047                            &ing_en_efilter_entry, BITMAPf, &pbmp);
   4048     SOC_IF_ERROR_RETURN
   4049         (WRITE_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0,
   4050                                       &ing_en_efilter_entry));
   4051 
   4052     return SOC_E_NONE;
   4053 }
   4054 
   4055 
   4056 /*
   4057  * Function:
   4058  *       _soc_monterey_misc_port_detach
   4059  * Purpose:
   4060  *      Clear HW for port to be detached.
   4061  *      This routine clears what is programmed during during
   4062  *      the equivalent attach routine _soc_monterey_misc_port_attach().
   4063  * Parameters:
   4064  *      unit      - (IN) Unit number.
   4065  *      port      - (IN) Logical Port.
   4066  * Returns:
   4067  *      SOC_E_XXX
   4068  */
   4069 STATIC int
   4070 _soc_monterey_misc_port_detach(int unit, soc_port_t port)
   4071 {
   4072     soc_info_t *si;
   4073     int phy_port;
   4074     uint32 rval;
   4075     soc_pbmp_t pbmp;
   4076     egr_ing_port_entry_t egr_ing_entry;
   4077     ing_en_efilter_bitmap_entry_t ing_en_efilter_entry;
   4078     int rv = SOC_E_NONE;
   4079     soc_control_t  *soc = SOC_CONTROL(unit);
   4080 
   4081     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4082                 (BSL_META_U(unit,
   4083                             "  SOC MISC detach unit=%d port=%d(%s)\n"),
   4084                  unit, port, SOC_PORT_NAME(unit, port)));
   4085 
   4086      si = &SOC_INFO(unit);
   4087 
   4088     if (IS_LB_PORT(unit, port) || IS_CPU_PORT (unit, port) ||
   4089         IS_TDM_PORT(unit, port)) {
   4090         LOG_ERROR(BSL_LS_SOC_PORT,
   4091                   (BSL_META_U(unit,
   4092                               "Port cannot be a Loopback, CPU, or TDM port "
   4093                               "unit=%d port=%d\n"),
   4094                    unit, port));
   4095         return SOC_E_PORT;
   4096     }
   4097 
   4098     phy_port = si->port_l2p_mapping[port];
   4099     if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port)) {
   4100         LOG_ERROR(BSL_LS_SOC_PORT,
   4101                   (BSL_META_U(unit,
   4102                               "Invalid physical port "
   4103                               "unit=%d port=%d physical=%d\n"),
   4104                    unit, port, phy_port));
   4105         return SOC_E_INTERNAL;
   4106     }
   4107 
   4108 
   4109     /*****************
   4110      * Clear port data */
   4111     SOC_IF_ERROR_RETURN
   4112         (_soc_mn_clear_enabled_port_data(unit, port));
   4113 
   4114 
   4115     /*****************
   4116      * Port Mappings
   4117      *
   4118      * NOTE: This only covers IFP_GM_LOGICAL_TO_PHYSICAL_MAPPING.
   4119      * It does NOT set the IP or EP port mappings.  These
   4120      * are covered in the following functions as specified by the
   4121      * FlexPort uArch specs:
   4122      *   - soc_mn_port_resource_ip_set()
   4123      *   - soc_mn_port_resource_ep_set()
   4124      */
   4125     rval = 0;
   4126     SOC_IF_ERROR_RETURN
   4127         (WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval));
   4128      MEM_LOCK(unit,FP_GLOBAL_MASK_TCAMm);
   4129     rv = WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval);
   4130     if (rv < 0) {
   4131         MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm);
   4132         return rv;
   4133     }
   4134     soc_mem_fp_global_mask_tcam_cache_update_set(unit, TRUE);
   4135     MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm);
   4136     sal_sem_give(soc->mem_scan_notify);
   4137 
   4138     /*****************
   4139      * Ingress Port egress configuration
   4140      */
   4141     sal_memset(&egr_ing_entry, 0, sizeof(egr_ing_port_entry_t));
   4142     SOC_IF_ERROR_RETURN
   4143         (WRITE_EGR_ING_PORTm(unit, MEM_BLOCK_ALL, port, &egr_ing_entry));
   4144 
   4145 
   4146     /*****************
   4147      * VLAN Controls
   4148      */
   4149     /* Ingress port VLAN membership check */
   4150     SOC_IF_ERROR_RETURN
   4151         (READ_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0,
   4152                                      &ing_en_efilter_entry));
   4153     soc_mem_pbmp_field_get(unit, ING_EN_EFILTER_BITMAPm,
   4154                            &ing_en_efilter_entry, BITMAPf, &pbmp);
   4155     SOC_PBMP_PORT_REMOVE(pbmp, port);
   4156     soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm,
   4157                            &ing_en_efilter_entry, BITMAPf, &pbmp);
   4158     SOC_IF_ERROR_RETURN
   4159         (WRITE_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0,
   4160                                       &ing_en_efilter_entry));
   4161 
   4162     return SOC_E_NONE;
   4163 }
   4164 
   4165 
   4166 /*
   4167  * Function:
   4168  *      _soc_mn_port_resource_misc_attach
   4169  * Purpose:
   4170  *      Initialize the SOC MISC area for given set of ports.
   4171  *      It covers HW programming that is done during SOC MISC.
   4172  *
   4173  * Parameters:
   4174  *      unit           - (IN) Unit number.
   4175  *      nport          - (IN) Number of elements in array resource.
   4176  *      resource       - (IN) Port Resource FlexPort configuration.
   4177  * Returns:
   4178  *      SOC_E_XXX
   4179  * Notes:
   4180  *      - Assumes this is NOT called during Warmboot.
   4181  *      - Assumes SOC_INFO is current.
   4182  */
   4183 STATIC int
   4184 _soc_mn_port_resource_misc_attach(int unit,
   4185                                     int nport,
   4186                                     soc_port_resource_t *resource)
   4187 {
   4188     int rv = SOC_E_NONE;
   4189     soc_port_resource_t *pr;
   4190     int i;
   4191 
   4192     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4193                 (BSL_META_U(unit,
   4194                             "SOC MISC Attach\n")));
   4195 
   4196     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   4197         if (pr->flags & SOC_PORT_RESOURCE_ATTACH) {
   4198             rv = _soc_monterey_misc_port_attach(unit, pr->logical_port);
   4199             if (SOC_FAILURE(rv)) {
   4200                 LOG_ERROR(BSL_LS_SOC_PORT,
   4201                           (BSL_META_U(unit,
   4202                                       "Error: Unable to initialize SOC MISC "
   4203                                       "unit=%d port=%d rv=%d\n"),
   4204                            unit, pr->logical_port, rv));
   4205                 return rv;
   4206             }
   4207         }
   4208     }
   4209 
   4210     return SOC_E_NONE;
   4211 }
   4212 
   4213 
   4214 /*
   4215  * Function:
   4216  *      _soc_mn_port_resource_misc_detach
   4217  * Purpose:
   4218  *      Clears the SOC MISC area for given set of ports.
   4219  *      It covers HW programming that is done during SOC MISC.
   4220  *
   4221  * Parameters:
   4222  *      unit           - (IN) Unit number.
   4223  *      nport          - (IN) Number of elements in array resource.
   4224  *      resource       - (IN) Port Resource FlexPort configuration.
   4225  * Returns:
   4226  *      SOC_E_XXX
   4227  * Notes:
   4228  *      - Assumes this is NOT called during Warmboot.
   4229  *      - Assumes SOC_INFO is current.
   4230  */
   4231 STATIC int
   4232 _soc_mn_port_resource_misc_detach(int unit,
   4233                                     int nport,
   4234                                     soc_port_resource_t *resource)
   4235 {
   4236     int rv = SOC_E_NONE;
   4237     soc_port_resource_t *pr;
   4238     int i;
   4239 
   4240     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4241                 (BSL_META_U(unit,
   4242                             "SOC MISC Detach\n")));
   4243 
   4244     for (i = 0, pr = &resource[0]; i < nport; i++, pr++) {
   4245         if (pr->flags & SOC_PORT_RESOURCE_DETACH) {
   4246             rv = _soc_monterey_misc_port_detach(unit, pr->logical_port);
   4247             if (SOC_FAILURE(rv)) {
   4248                 LOG_ERROR(BSL_LS_SOC_PORT,
   4249                           (BSL_META_U(unit,
   4250                                       "Error: Unable to clear SOC MISC "
   4251                                       "unit=%d port=%d rv=%d\n"),
   4252                            unit, pr->logical_port, rv));
   4253                 return rv;
   4254             }
   4255         }
   4256     }
   4257 
   4258     return SOC_E_NONE;
   4259 }
   4260 
   4261 /*
   4262  * Function:
   4263  *      _soc_mn_port_resource_speed_set
   4264  * Purpose:
   4265  *      Execute the Speed Set operation
   4266  *
   4267  *      This function is very similar with _soc_mn_port_resource_execute
   4268  *      which execute full flex operation.
   4269  *      Following functions are not called.
   4270  *      - soc_esw_portctrl_pm_ports_delete
   4271  *      - soc_esw_portctrl_pm_ports_add
   4272  *      - _soc_mn_port_resource_misc_detach
   4273  *      - _soc_mn_port_resource_misc_attach
   4274  *      - soc_mn_port_resource_pgw_set
   4275  *      - soc_mn_port_resource_ip_set
   4276  *      - soc_mn_port_resource_ep_set
   4277  *      But speed set operation may re-assign MMU port.
   4278  *      So speed_set operation also requires to call
   4279  *      - _soc_mn_soc_info_ports_delete
   4280  *      - _soc_mn_soc_info_ports_add
   4281  *
   4282  * Parameters:
   4283  *      unit           - (IN) Unit number.
   4284  *      nport          - (IN) Number of elements in array resource.
   4285  *      resource       - (IN) Port Resource FlexPort configuration.
   4286  *      pre_count      - (IN) Array size for pre-FlexPort array.
   4287  *      pre_resource   - (IN) Pre-FlexPort configuration array.
   4288  *      post_count     - (IN) Array size for post-FlexPort array.
   4289  *      post_resource  - (IN) Pre-FlexPort configuration array.
   4290  * Returns:
   4291  *      SOC_E_XXX
   4292  * Note:
   4293  *      - Assumes all data is Port Resource arrays has been validated.
   4294  */
   4295 STATIC int
   4296 _soc_mn_port_resource_speed_set(int unit,
   4297                                 int nport, soc_port_resource_t *resource,
   4298                                 int pre_count,
   4299                                 soc_port_resource_t *pre_resource,
   4300                                 int post_count,
   4301                                 soc_port_resource_t *post_resource,
   4302                                 soc_mn_info_t *pre_soc_info)
   4303 {
   4304     int delete_count;
   4305 
   4306     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4307                 (BSL_META_U(unit,
   4308                             "\n====== SOC PORT RESOURCE SPEED SET ======\n")));
   4309 
   4310     delete_count = pre_count;
   4311 
   4312     /* Clear MMU Port Mappings */
   4313     SOC_IF_ERROR_RETURN
   4314         (soc_mn_port_resource_mmu_mapping_set(unit,
   4315                                                 delete_count, resource));
   4316 
   4317     SOC_IF_ERROR_RETURN
   4318         (_soc_mn_soc_info_ports_delete(unit,
   4319                                          pre_count, pre_resource));
   4320 
   4321     /* Add ports to SOC SW */
   4322     SOC_IF_ERROR_RETURN
   4323         (_soc_mn_soc_info_ports_add(unit,
   4324                                       post_count, post_resource));
   4325 
   4326     /*
   4327      * Note: At this point, the SOC_INFO data structure reflects
   4328      * the new information for all the ports.
   4329      */
   4330 
   4331 
   4332     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4333                 (BSL_META_U(unit,
   4334                             "\n--- SOC FLEXPORT RECONFIGURE ---\n")));
   4335     /* Check speed class is same */
   4336     if (!soc_esw_portctrl_is_same_speed_class(unit, pre_resource[0].speed,
   4337                                                     post_resource[0].speed)) {
   4338         if (!(SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) &&
   4339                     !soc_property_get(unit, "skip_tdm_init", 0)) {
   4340  
   4341             /* Reconfigure Schedulers */
   4342             LOG_VERBOSE(BSL_LS_SOC_PORT,
   4343                       (BSL_META_U(unit,
   4344                                 "--- TDM Reconfigure\n")));
   4345             SOC_IF_ERROR_RETURN
   4346                  (soc_mn_port_resource_tdm_set(unit,
   4347                                             pre_count, pre_resource,
   4348                                             post_count, post_resource,
   4349                                             pre_soc_info,
   4350                                             MN_INFO(unit)->mmu_lossless));
   4351         }
   4352 
   4353     }
   4354 
   4355     /* Reconfigure MMU */
   4356     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4357                 (BSL_META_U(unit,
   4358                             "--- MMU Reconfigure\n")));
   4359 
   4360     SOC_IF_ERROR_RETURN
   4361         (soc_mn_port_resource_mmu_set(unit, post_count, post_resource));
   4362 
   4363     return SOC_E_NONE;
   4364 }
   4365 
   4366 /*
   4367  * Function:
   4368  *      _soc_mn_port_resource_execute
   4369  * Purpose:
   4370  *      Execute the FlexPort operation.
   4371  *
   4372  *      This function updates the main SOC_INFO SW data structure and
   4373  *      makes changes to HW.
   4374  * 
   4375  *      If any error occurs the operation, changes cannot be undone.
   4376  * Parameters:
   4377  *      unit           - (IN) Unit number.
   4378  *      nport          - (IN) Number of elements in array resource.
   4379  *      resource       - (IN) Port Resource FlexPort configuration.
   4380  *      pre_count      - (IN) Array size for pre-FlexPort array.
   4381  *      pre_resource   - (IN) Pre-FlexPort configuration array.
   4382  *      post_count     - (IN) Array size for post-FlexPort array.
   4383  *      post_resource  - (IN) Pre-FlexPort configuration array.
   4384  * Returns:
   4385  *      SOC_E_XXX
   4386  * Note:
   4387  *      - Assumes all data is Port Resource arrays has been validated.
   4388  */
   4389 STATIC int
   4390 _soc_mn_port_resource_execute(int unit,
   4391                                 int nport, soc_port_resource_t *resource,
   4392                                 int pre_count,
   4393                                 soc_port_resource_t *pre_resource,
   4394                                 int post_count,
   4395                                 soc_port_resource_t *post_resource,
   4396                                 soc_mn_info_t *pre_soc_info)
   4397 {
   4398     int delete_count;
   4399     /**********************************************
   4400      * Execution Flow
   4401      *
   4402      * The flow consists of the following high level steps,
   4403      * the order is important.
   4404      *
   4405      * - Detach 'old' ports from SOC layer:
   4406      *     + These are all ports to be cleared/deleted (indicated by physical
   4407      *       port -1), EXCEPT those that will become inactive after the
   4408      *       FlexPort operation (this is only true with legacy API).
   4409      *     + Clear ports in HW MISC
   4410      *     + Clearing any other port references in HW
   4411      *     + Delete ports from Port Macro
   4412      *     + Clear port information in SOC_INFO SW
   4413      * - Attach ports in SOC layer
   4414      *     + These are all ports that are active after the FlexPort operation.
   4415      *     + Add port information in SOC_INFO SW
   4416      *     + Init ports in HW MISC
   4417      *     + Add ports to Port Macro
   4418      * - Execute FlexPort operation as defined by HW specs
   4419      *
   4420      * ------------------
   4421      * Port Mapping
   4422      * ------------
   4423      * A logical to physical port mapping is given as part of the port resource
   4424      * array.  This can lead to the following operations:
   4425      * - Port Mapping Delete (or clear)
   4426      *   This is indicated when the physical port is set to (-1) and
   4427      *   the port to be flexed is considered an 'old' port.
   4428      *   The logical port in the array entry must always be valid.
   4429      *   A 'delete' may result in the following actions for a port mapping:
   4430      *      (1) Destroyed
   4431      *      (2) Same
   4432      *      (3) Remapped
   4433      *
   4434      * - Port Mapping Add (or set)
   4435      *   This is indicated when the physical port is set to a valid
   4436      *   physical port number (>=0).
   4437      *   The logical port in the array entry must always be valid.
   4438      *   An 'add' may result in the following actions for a port mapping:
   4439      *      (1) New
   4440      *      (2) Same
   4441      *      (3) Remapped
   4442      *
   4443      * Destroyed: Logical port no longer exist after FlexPort.
   4444      * Remapped:  Logical port will continue to exist after FlexPort
   4445      *            but is mapped to a different physical port.
   4446      * New:       Logical port did not exist before FlexPort.
   4447      * Same:      Logical to physical port mapping remains the same.
   4448      *
   4449      * NOTE that the 'PortMacro' module handles things
   4450      * a bit different.  The Port Macro requires ALL ports, including
   4451      * those going inactive, to always be 'deleted'
   4452      * and 'added' back.
   4453      *
   4454      * ------------------
   4455      * SOC_INFO Update
   4456      * ---------------
   4457      * Some HW updates need to be performed BEFORE the
   4458      * SOC_INFO structure is updated, and some AFTER.
   4459      *
   4460      * Once the SOC_INFO structure is updated, the SOC register
   4461      * functions will no longer be able to access addresses of
   4462      * ports that were 'deleted' from SOC_INFO.  The mapping will
   4463      * either not be available or not be correct (remapped to a new port).
   4464      *
   4465      * For example, the soc_reg_addr_get() figures out the
   4466      * correct index/address looking into the 'l2p' or 'p2m' in SOC_INFO.
   4467      *
   4468      * Another example is the Port Macro reconfiguration:
   4469      * This operation needs to done in two steps:
   4470      * (1) Deletion of ports from the Port Macro needs to be done
   4471      *     BEFORE the SOC_INFO is updated.  PortMod needs to
   4472      *     access the port mappings before the pre-FlexPort to clear
   4473      *     old ports.
   4474      *
   4475      * (2) Addition of new ports to the Port Macro needs to be done
   4476      *     AFTER the SOC_INFO is updated.  PortMod needs to
   4477      *     access the new ports using the new port mappings.
   4478      *
   4479      * In general:
   4480      * - HW programming on 'older' ports needs to be done BEFORE
   4481      *   the SOC_INFO is updated.
   4482      * - HW programming on 'new' ports needs to be done AFTER
   4483      *   the SOC_INFO is updated.
   4484      */
   4485     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4486                 (BSL_META_U(unit,
   4487                             "\n====== SOC PORT RESOURCE EXECUTE ======\n")));
   4488 
   4489     /**********************************************
   4490      *
   4491      * DELETE
   4492      *
   4493      * Clear ports to be marked as 'delete'.
   4494      * These operations must take place BEFORE SOC_INFO is updated.
   4495      */
   4496     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4497                 (BSL_META_U(unit,
   4498                             "--- SOC DETACH PORTS ---\n")));
   4499     delete_count = pre_count;
   4500 
   4501     /* Clear SOC MISC */
   4502     SOC_IF_ERROR_RETURN
   4503         (_soc_mn_port_resource_misc_detach(unit,
   4504                                              nport, resource));
   4505     /* Clear MMU Port Mappings */
   4506     SOC_IF_ERROR_RETURN
   4507         (soc_mn_port_resource_mmu_mapping_set(unit,
   4508                                                 delete_count, resource));
   4509     /* Delete ports from Port Macro */
   4510     SOC_IF_ERROR_RETURN
   4511         (soc_esw_portctrl_pm_ports_delete(unit, delete_count, pre_resource));
   4512 
   4513     /*
   4514      * Delete ports from SOC SW
   4515      * This must happen last during the 'delete' process
   4516      */
   4517     SOC_IF_ERROR_RETURN
   4518         (_soc_mn_soc_info_ports_delete(unit,
   4519                                          pre_count, pre_resource));
   4520 
   4521 
   4522     /**********************************************
   4523      *
   4524      * ADD
   4525      *
   4526      * Configure ports to be added.
   4527      */
   4528     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4529                 (BSL_META_U(unit,
   4530                             "\n--- SOC ATTACH PORTS ---\n")));
   4531 
   4532     /*
   4533      * Add ports to SOC SW
   4534      * This must happen first during the 'add' process
   4535      */
   4536     SOC_IF_ERROR_RETURN
   4537         (_soc_mn_soc_info_ports_add(unit,
   4538                                       post_count, post_resource));
   4539     /* Enable/Disable used/unused TSCs */
   4540     if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) {
   4541         SOC_IF_ERROR_RETURN(soc_monterey_tsc_disable(unit));
   4542     }
   4543     /* 
   4544      * Verify if the TDM will satisfy the new port config
   4545  */
   4546     SOC_IF_ERROR_RETURN(soc_monterey_port_config_bandwidth_check(unit));
   4547     /*
   4548      * Note: At this point, the SOC_INFO data structure reflects
   4549      * the new information for all the ports.
   4550      */
   4551 
   4552     /* Init SOC MISC */
   4553     SOC_IF_ERROR_RETURN
   4554         (_soc_mn_port_resource_misc_attach(unit,
   4555                                              nport, resource));
   4556 
   4557     /* Add ports to Port Macro */
   4558     SOC_IF_ERROR_RETURN
   4559         (soc_esw_portctrl_pm_ports_add(unit, nport, resource));
   4560 
   4561 
   4562     /**********************************************
   4563      *
   4564      * FLEXPORT
   4565      *
   4566      * Device reconfiguration as defined by specs.
   4567      */
   4568     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4569                 (BSL_META_U(unit,
   4570                             "\n--- SOC FLEXPORT RECONFIGURE ---\n")));
   4571     /* Reconfigure Schedulers */
   4572     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4573                 (BSL_META_U(unit,
   4574                             "--- TDM Reconfigure\n")));
   4575     if (!(SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) &&
   4576                     !soc_property_get(unit, "skip_tdm_init", 0)) {
   4577 
   4578          SOC_IF_ERROR_RETURN
   4579             (soc_mn_port_resource_tdm_set(unit,
   4580                                         pre_count, pre_resource,
   4581                                         post_count, post_resource,
   4582                                         pre_soc_info,
   4583                                         MN_INFO(unit)->mmu_lossless));
   4584     }
   4585     
   4586     /* Reconfigure PGW */
   4587     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4588                 (BSL_META_U(unit,
   4589                             "--- PGW Reconfigure\n")));
   4590     SOC_IF_ERROR_RETURN
   4591         (soc_mn_port_resource_pgw_set(unit,
   4592                                         pre_count, pre_resource,
   4593                                         post_count, post_resource,
   4594                                         MN_INFO(unit)->mmu_lossless));
   4595 
   4596     /* Reconfigure IP */
   4597     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4598                 (BSL_META_U(unit,
   4599                             "--- IP Reconfigure\n")));
   4600     SOC_IF_ERROR_RETURN
   4601         (soc_mn_port_resource_ip_set(unit,
   4602                                        pre_count, pre_resource,
   4603                                        post_count, post_resource,
   4604                                        pre_soc_info));
   4605 
   4606     /* Reconfigure EP */
   4607     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4608                 (BSL_META_U(unit,
   4609                             "--- EP Reconfigure\n")));
   4610     SOC_IF_ERROR_RETURN
   4611         (soc_mn_port_resource_ep_set(unit,
   4612                                        pre_count, pre_resource,
   4613                                        post_count, post_resource,
   4614                                        pre_soc_info));
   4615 
   4616     /* Reconfigure MMU */
   4617     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4618                 (BSL_META_U(unit,
   4619                             "--- MMU Reconfigure\n")));
   4620 
   4621     SOC_IF_ERROR_RETURN
   4622         (soc_mn_port_resource_mmu_set(unit, post_count, post_resource));
   4623 
   4624     return SOC_E_NONE;
   4625 }
   4626 
   4627 
   4628 /*
   4629  * Function:
   4630  *      soc_mn_port_resource_configure
   4631  * Purpose:
   4632  *      Configure device ports based on given FlexPort information.
   4633  *
   4634  *      This routine validates that the given FlexPort configuration
   4635  *      is valid and if successful, executes the FlexPort operation.
   4636  * Parameters:
   4637  *      unit     - (IN) Unit number.
   4638  *      nport    - (IN) Number of elements in array resource.
   4639  *      resource - (IN) Port resource configuration array.
   4640  *      flag     - (IN) Check if Full flex sequence or speed set sequence
   4641  * Returns:
   4642  *      SOC_E_XXX
   4643  * Note:
   4644  *      Assumes:
   4645  *      - Input has been validated.
   4646  *        E.g.
   4647  *          . Array is in order (deletes are first)
   4648  *          . Logical and physical ports are addressable
   4649  *          . Speeds and lanes are valid for physical port.
   4650  *          . etc.
   4651  *      - Caller has lock.
   4652  */
   4653 int
   4654 soc_mn_port_resource_configure(int unit, int nport,
   4655                                  soc_port_resource_t *resource,
   4656                                  int flag)
   4657 {
   4658     int rv;
   4659     int pre_count;
   4660     int post_count;
   4661     soc_port_resource_t *pre_resource;
   4662     soc_port_resource_t *post_resource;
   4663     soc_mn_info_t *pre_soc_info = NULL;
   4664 
   4665     MN_INFO_INIT_CHECK(unit);
   4666 
   4667     pre_soc_info = sal_alloc(sizeof(soc_mn_info_t), "pre_soc_info");
   4668 
   4669     if (pre_soc_info == NULL) {
   4670         LOG_ERROR(BSL_LS_SOC_PORT,
   4671                   (BSL_META_U(unit, "Memory Allocation Failure")));
   4672         rv = SOC_E_MEMORY;
   4673         return rv;
   4674     }
   4675 
   4676     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4677                 (BSL_META_U(unit,
   4678                             "\n=============================================\n"
   4679                             "======== SOC PORT RESOURCE CONFIGURE ========\n"
   4680                             "=============================================\n"
   4681                             )));
   4682 
   4683     /* Get all Port Resource information needed for operation */
   4684     rv = _soc_mn_port_resource_data_init(unit, nport, resource,
   4685                                            &pre_count, &pre_resource,
   4686                                            &post_count, &post_resource,
   4687                                            pre_soc_info);
   4688     if (SOC_FAILURE(rv)) {
   4689         _soc_mn_port_resource_data_cleanup(&pre_resource);
   4690         sal_free(pre_soc_info);
   4691         return rv;
   4692     }
   4693     /* Pause linkscan */
   4694     soc_linkscan_pause(unit);
   4695 
   4696     /* Pause counter collection */
   4697     COUNTER_LOCK(unit);
   4698 
   4699     /* Lock the SOC structures */
   4700     SOC_CONTROL_LOCK(unit);
   4701 
   4702     /*
   4703      * Execute FlexPort operation
   4704      *
   4705      * At this point:
   4706      *   - Validation is successfull
   4707      *   - FlexPort information is ready
   4708      *
   4709      * Changes are done to the to the SOC_INFO SW data structure and HW.
   4710      * If any error occurs the operation, changes cannot be undone.
   4711      */
   4712     if (flag == SOC_PORT_RESOURCE_CONFIGURE_FLEX) {
   4713         rv = _soc_mn_port_resource_execute(unit, nport, resource,
   4714                                            pre_count, pre_resource,
   4715                                            post_count, post_resource,
   4716                                            pre_soc_info);
   4717     } else {
   4718         rv = _soc_mn_port_resource_speed_set(unit, nport, resource,
   4719                                              pre_count, pre_resource,
   4720                                              post_count, post_resource,
   4721                                              pre_soc_info);
   4722     }
   4723     /* Unlock the SOC structures */
   4724     SOC_CONTROL_UNLOCK(unit);
   4725 
   4726     /* Resume counter collection */
   4727     COUNTER_UNLOCK(unit);
   4728 
   4729     /* Resume linkscan */
   4730     soc_linkscan_continue(unit);
   4731 
   4732     /* Debug output */
   4733     _soc_mn_port_resource_data_output(unit,
   4734                                         nport, resource,
   4735                                         pre_count, pre_resource,
   4736                                         post_count, post_resource);
   4737 
   4738     if (SOC_FAILURE(rv)) {
   4739         LOG_ERROR(BSL_LS_SOC_PORT,
   4740                   (BSL_META_U(unit,
   4741                               "Error executing FlexPort operation (%d)\n"),
   4742                    rv));
   4743         LOG_ERROR(BSL_LS_SOC_PORT,
   4744                   (BSL_META_U(unit,
   4745                               "Changes to device may have been partially "
   4746                               "executed.  System may be unstable.\n")));
   4747     }
   4748 
   4749     /* Deallocate memory */
   4750     _soc_mn_port_resource_data_cleanup(&pre_resource);
   4751     sal_free(pre_soc_info);
   4752 
   4753     return rv;
   4754 }
   4755 #define MONTEREY_MAX_OVS_SPG 8
   4756 /*
   4757  * Function:
   4758  *      _soc_mn_port_resource_ovs_speed_group_validate
   4759  * Purpose:
   4760  *      Validate oversub speed group of all ports:
   4761  *      Total number of oversub speed groups cannot exceed 4 at any given time
   4762  *
   4763  * Parameters:
   4764  *      unit     - (IN) Unit number.
   4765  *      post_si  - (IN) Post SOC INFO information
   4766  * Returns:
   4767  *      SOC_E_XXX
   4768  */
   4769 STATIC int
   4770 _soc_mn_port_resource_ovs_speed_group_validate(int unit, soc_info_mn_misc_t *post_si)
   4771 {
   4772     int i, j, found;
   4773     int logic_port, phy_port;
   4774     int speed, spd_cls ,spg_count =0;
   4775     int spg_num[MONTEREY_MAX_OVS_SPG] = {0};
   4776     uint32 sp_spacing = 0;
   4777 
   4778     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4779                 (BSL_META_U(unit,
   4780                             "--- VALIDATE: Oversub Speed groups\n")));
   4781 
   4782     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
   4783         logic_port = i;
   4784         phy_port = post_si->port_l2p_mapping[logic_port];
   4785 
   4786         /* Skip ports not defined, LB, CPU, etc. */
   4787         if (!SOC_PORT_ADDRESSABLE(unit, logic_port) ||
   4788             !((phy_port >= 0) && (phy_port <= SOC_MAX_NUM_PORTS)) ||
   4789             IS_LB_PORT(unit, logic_port) ||
   4790             IS_RDB_PORT(unit, logic_port) ||
   4791             IS_CPU_PORT (unit, logic_port)) {
   4792             continue;
   4793         }
   4794 
   4795         /* Skip Line Rate ports */
   4796         if (!SOC_PBMP_MEMBER(post_si->oversub_pbm, logic_port)) {
   4797             continue;
   4798         }
   4799 
   4800         /* Skip inactive ports */
   4801         if (SOC_PBMP_MEMBER(post_si->disabled_bitmap, logic_port)) {
   4802             continue;
   4803         }
   4804 
   4805 
   4806         /* Get speed class */
   4807         speed = post_si->port_speed[logic_port];
   4808         SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit,
   4809                             &speed, &spd_cls, &sp_spacing));
   4810         found = 0;
   4811         for (j = 0; j < MONTEREY_MAX_OVS_SPG; j++) {
   4812             /* Check if speed group already exists */
   4813             if (spd_cls == spg_num[j]) {
   4814                 found = 1;
   4815                 break;
   4816             }
   4817         }
   4818         if (!found) {
   4819             if (spg_count == MONTEREY_MAX_OVS_SPG) {
   4820                 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   4821                           "More than %d oversub speed groups not supported\n"),
   4822                            MONTEREY_MAX_OVS_SPG));
   4823                 return SOC_E_CONFIG;
   4824             }
   4825             /* Keep track of all speed groups */
   4826             spg_num[spg_count++] = spd_cls;
   4827         }
   4828     }
   4829 
   4830     return SOC_E_NONE;
   4831 }
   4832 
   4833 /*
   4834  * Function:
   4835  *      soc_mn_port_ovs_speed_group_validate
   4836  * Purpose:
   4837  *      Validate oversub speed group of all ports:
   4838  *      Total number of oversub speed groups cannot exceed 4 at any given time
   4839  *
   4840  * Parameters:
   4841  *      unit     - (IN) Unit number.
   4842  *      post_si  - (IN) Post SOC INFO information
   4843  * Returns:
   4844  *      SOC_E_XXX
   4845  * Note:
   4846  *      Assumes that this function is called at early stage of initialization
   4847  *      (For example, soc_apache_port_config_init).
   4848  *      Because portctrl/portmod API is not ready to use,
   4849  *      use port_speed_max or port_init_speed instead.
   4850  */
   4851 int
   4852 soc_mn_port_ovs_speed_group_validate(int unit)
   4853 {
   4854     int i, j, found;
   4855     int logic_port, phy_port;
   4856     int speed, spd_cls, spg_count = 0;
   4857     int spg_num[MONTEREY_MAX_OVS_SPG] = {0};
   4858     uint32 sp_spacing = 0;
   4859     soc_info_t *si = &SOC_INFO(unit);
   4860 
   4861     LOG_VERBOSE(BSL_LS_SOC_PORT,
   4862                 (BSL_META_U(unit,
   4863                             "--- VALIDATE: Oversub Speed groups\n")));
   4864 
   4865     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
   4866         logic_port = i;
   4867         phy_port = si->port_l2p_mapping[logic_port];
   4868 
   4869         /* Skip ports not defined, LB, CPU, etc. */
   4870         if (!SOC_PORT_ADDRESSABLE(unit, logic_port) ||
   4871             !((phy_port >= 0) && (phy_port <= SOC_MAX_NUM_PORTS)) ||
   4872             IS_LB_PORT(unit, logic_port) ||
   4873             IS_MACSEC_PORT(unit, logic_port) ||
   4874             IS_CPU_PORT (unit, logic_port)) {
   4875             continue;
   4876         }
   4877 
   4878         /* Skip Line Rate ports */
   4879         if (!SOC_PBMP_MEMBER(si->oversub_pbm, logic_port)) {
   4880             continue;
   4881         }
   4882 
   4883         /* Skip inactive ports */
   4884         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, logic_port)) {
   4885             continue;
   4886         }
   4887 
   4888 
   4889         /* Get speed class */
   4890         speed = si->port_speed_max[logic_port];
   4891         SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit,
   4892                             &speed, &spd_cls, &sp_spacing));
   4893         found = 0;
   4894         for (j = 0; j < MONTEREY_MAX_OVS_SPG; j++) {
   4895             /* Check if speed group already exists */
   4896             if (spd_cls == spg_num[j]) {
   4897                 found = 1;
   4898                 break;
   4899             }
   4900         }
   4901         if (!found) {
   4902             if (spg_count == MONTEREY_MAX_OVS_SPG) {
   4903                 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   4904                           "More than %d oversub speed groups not supported\n"),
   4905                            MONTEREY_MAX_OVS_SPG));
   4906                 return SOC_E_CONFIG;
   4907             }
   4908             /* Keep track of all speed groups */
   4909             spg_num[spg_count++] = spd_cls;
   4910         }
   4911     }
   4912 
   4913     return SOC_E_NONE;
   4914 }
   4915 #ifdef BCM_WARM_BOOT_SUPPORT
   4916 int
   4917 soc_monterey_flexport_scache_allocate(int unit)
   4918 {
   4919     int rv = SOC_E_NONE;
   4920     uint8 *flexport_scache_ptr;
   4921     soc_scache_handle_t scache_handle;
   4922     uint32 alloc_get = 0;
   4923     uint32 alloc_size = 0;
   4924     int stable_size;
   4925     int default_ver = SOC_FLEXPORT_WB_DEFAULT_VERSION;
   4926 
   4927 
   4928     alloc_size =   (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to logical*/
   4929                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* logical to phy */
   4930                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to mmu */
   4931                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* mmu to phy */
   4932                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* num lanes */
   4933                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* group number */
   4934                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* serdes number */
   4935                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* max port speed */
   4936                    (sizeof(pbmp_t))                      + /* oversub pbm */
   4937                    (sizeof(pbmp_t))                      +/* Disabled bitmap */
   4938                    (sizeof(pbmp_t));                       /* roe compression bitmap */
   4939 
   4940     alloc_get = alloc_size;
   4941 
   4942     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0);
   4943 
   4944     /* check to see if an scache table has been configured */
   4945     rv = soc_stable_size_get(unit, &stable_size);
   4946     if (SOC_FAILURE(rv) || stable_size <= 0) {
   4947         return rv;
   4948     }
   4949 
   4950     rv = soc_versioned_scache_ptr_get(unit, scache_handle, TRUE, &alloc_get,
   4951                                       &flexport_scache_ptr, default_ver, NULL);
   4952 
   4953     if (rv  == SOC_E_CONFIG) {
   4954         /* Probably Level1 */
   4955         return SOC_E_NONE;
   4956     }
   4957 
   4958     if (NULL == flexport_scache_ptr) {
   4959         LOG_ERROR(BSL_LS_SOC_COMMON,
   4960                 (BSL_META_U(unit,
   4961                  "ERROR: scache memory not allocated for flexport"
   4962                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   4963         return SOC_E_MEMORY;
   4964     }
   4965 
   4966     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4967                 (BSL_META_U(unit,
   4968                 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   4969 
   4970     return SOC_E_NONE;
   4971 }
   4972 
   4973 int
   4974 soc_monterey_flexport_scache_sync(int unit)
   4975 {
   4976     uint8 *flexport_scache_ptr;
   4977     soc_scache_handle_t scache_handle;
   4978     uint32 alloc_get=0;
   4979     uint32 alloc_size = 0;
   4980     soc_info_t *si = &SOC_INFO(unit);
   4981     uint32 scache_offset=0;
   4982     uint32 var_size, hole_size;
   4983     int rv = 0;
   4984 
   4985 
   4986     alloc_size =   (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to logical*/
   4987                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* logical to phy */
   4988                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to mmu */
   4989                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* mmu to phy */
   4990                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* num lanes */
   4991                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* group number */
   4992                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* serdes number */
   4993                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* max port speed */
   4994                    (sizeof(pbmp_t))                      + /* oversub pbm */
   4995                    (sizeof(pbmp_t))                      +  /* Disabled bitmap */
   4996                    (sizeof(pbmp_t));                       /* roe compression bitmap */
   4997 
   4998     hole_size = (sizeof(int));
   4999     var_size = (sizeof(int) * (MN_FLEX_MAX_NUM_PORTS - 1));
   5000     alloc_get = alloc_size;
   5001 
   5002     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0);
   5003 
   5004     rv = soc_versioned_scache_ptr_get(unit, scache_handle, FALSE, &alloc_get, &flexport_scache_ptr,
   5005                                       SOC_FLEXPORT_WB_DEFAULT_VERSION, NULL);
   5006     if (rv == SOC_E_NOT_FOUND) {
   5007         /* Probably Level1 */
   5008         return SOC_E_NONE;
   5009     }
   5010 
   5011     if (alloc_get != alloc_size) {
   5012         /* Expected size doesn't match retrieved size */
   5013         LOG_ERROR(BSL_LS_SOC_COMMON,
   5014                 (BSL_META_U(unit,
   5015                  "ERROR: scache memory for flexport size mismatch"
   5016                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   5017         return SOC_E_INTERNAL;
   5018     }
   5019 
   5020     if (NULL == flexport_scache_ptr) {
   5021         LOG_ERROR(BSL_LS_SOC_COMMON,
   5022                 (BSL_META_U(unit,
   5023                  "ERROR: scache memory not allocated for flexport"
   5024                  "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   5025         return SOC_E_MEMORY;
   5026     }
   5027 
   5028     /* Physical to logical port mapping */
   5029     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5030                si->port_p2l_mapping, var_size);
   5031     scache_offset += (var_size + hole_size);
   5032 
   5033     /* Logical to Physical port mapping */
   5034     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5035                si->port_l2p_mapping, var_size);
   5036     scache_offset += (var_size + hole_size);
   5037 
   5038     /* Physical to mmu port mapping */
   5039     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5040                si->port_p2m_mapping, var_size);
   5041     scache_offset += (var_size + hole_size);
   5042 
   5043     /* MMU to Physical port mapping */
   5044     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5045                si->port_m2p_mapping, var_size);
   5046     scache_offset += (var_size + hole_size);
   5047 
   5048     /* Num lanes per port */
   5049     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5050                si->port_num_lanes, var_size);
   5051     scache_offset += (var_size + hole_size);
   5052 
   5053     /* Port Group */
   5054     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5055                si->port_group, var_size);
   5056     scache_offset += (var_size + hole_size);
   5057 
   5058     /* Port Serdes */
   5059     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5060                si->port_serdes, var_size);
   5061     scache_offset += (var_size + hole_size);
   5062 
   5063     /* Max port speed */
   5064     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5065                si->port_speed_max, var_size);
   5066     scache_offset += (var_size + hole_size);
   5067 
   5068     /* Oversub pbm */
   5069     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5070                &si->oversub_pbm, sizeof(pbmp_t));
   5071     scache_offset += sizeof(pbmp_t);
   5072 
   5073     /* Disabled Port Bitmap */
   5074     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5075                &si->all.disabled_bitmap, sizeof(pbmp_t));
   5076     scache_offset += sizeof(pbmp_t);
   5077     sal_memcpy(&flexport_scache_ptr[scache_offset],
   5078                &si->roe_compression, sizeof(pbmp_t));
   5079     scache_offset += sizeof(pbmp_t);
   5080 
   5081 
   5082     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   5083                 (BSL_META_U(unit,
   5084                  "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
   5085 
   5086     return SOC_E_NONE;
   5087 }
   5088 
   5089 int
   5090 soc_monterey_flexport_scache_recovery(int unit)
   5091 {
   5092     uint32 alloc_get=0;
   5093     uint32 alloc_size = 0;
   5094     uint32 additional_scache_size = 0;
   5095     int rv = SOC_E_NONE;
   5096     int phy_port;
   5097     uint8 *flexport_scache_ptr = NULL;
   5098     soc_scache_handle_t scache_handle;
   5099     uint32 scache_offset=0;
   5100     uint32 var_size, hole_size;
   5101     uint16 recovered_ver = 0;
   5102     soc_info_t *si = &SOC_INFO(unit);
   5103 
   5104 
   5105     alloc_size =   (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to logical*/
   5106                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* logical to phy */
   5107                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to mmu */
   5108                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* mmu to phy */
   5109                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* num lanes */
   5110                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* group number */
   5111                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* serdes number */
   5112                    (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* max port speed */
   5113                    (sizeof(pbmp_t))                      + /* oversub pbm */
   5114                    (sizeof(pbmp_t))                      + /* Disabled bitmap */
   5115                    (sizeof(pbmp_t));                       /* roe compression */
   5116 
   5117     hole_size = (sizeof(int));
   5118     var_size = (sizeof(int) * (MN_FLEX_MAX_NUM_PORTS - 1));
   5119     alloc_get = alloc_size;
   5120 
   5121     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0);
   5122     rv = soc_versioned_scache_ptr_get(unit, scache_handle, FALSE, &alloc_get,
   5123                                       &flexport_scache_ptr, SOC_FLEXPORT_WB_DEFAULT_VERSION,
   5124                                       &recovered_ver);
   5125 
   5126     if (SOC_FAILURE(rv)) {
   5127         if ((rv == SOC_E_CONFIG) ||
   5128             (rv == SOC_E_NOT_FOUND)) {
   5129             /* warmboot file does not contain this
   5130             * module, or the warmboot state does not exist.
   5131             * in this case return SOC_E_NOT_FOUND
   5132             */
   5133             return SOC_E_NOT_FOUND;
   5134         } else {
   5135             /* Only Level2 - flexport treat this as a error */
   5136             LOG_ERROR(BSL_LS_SOC_COMMON,
   5137                      (BSL_META_U(unit,
   5138                      "Failed to recover scache data - %s\n"),soc_errmsg(rv)));
   5139             return rv;
   5140         }
   5141     }
   5142 
   5143     if (alloc_get != alloc_size) {
   5144          /* Expected size doesn't match retrieved size */
   5145         LOG_ERROR(BSL_LS_SOC_COMMON,
   5146                 (BSL_META_U(unit,
   5147                  "ERROR: scache recovery for flexport"
   5148                  "%s()[LINE:%d] DONE \n"),
   5149                   FUNCTION_NAME(),  __LINE__));
   5150         return SOC_E_INTERNAL;
   5151     }
   5152 
   5153     if (NULL == flexport_scache_ptr) {
   5154         LOG_ERROR(BSL_LS_SOC_COMMON,
   5155                 (BSL_META_U(unit,
   5156                  "ERROR: scache recovery for flexport"
   5157                  "%s()[LINE:%d] DONE \n"),
   5158                   FUNCTION_NAME(),  __LINE__));
   5159         return SOC_E_MEMORY;
   5160     }
   5161 
   5162     /* Physical to logical port mapping */
   5163     sal_memcpy(si->port_p2l_mapping,
   5164                &flexport_scache_ptr[scache_offset],
   5165                var_size);
   5166     scache_offset += (var_size + hole_size);
   5167 
   5168     /* Logical to Physical port mapping */
   5169     sal_memcpy(si->port_l2p_mapping,
   5170                &flexport_scache_ptr[scache_offset],
   5171                var_size);
   5172     scache_offset += (var_size + hole_size);
   5173 
   5174     /* Physical to mmu port mapping */
   5175     sal_memcpy(si->port_p2m_mapping,
   5176                &flexport_scache_ptr[scache_offset],
   5177                var_size);
   5178     scache_offset += (var_size + hole_size);
   5179 
   5180     /* MMU to Physical port mapping */
   5181     sal_memcpy(si->port_m2p_mapping,
   5182                &flexport_scache_ptr[scache_offset],
   5183                var_size);
   5184     scache_offset += (var_size + hole_size);
   5185 
   5186     /* Num lanes per port */
   5187     sal_memcpy(si->port_num_lanes,
   5188                &flexport_scache_ptr[scache_offset],
   5189                var_size);
   5190     scache_offset += (var_size + hole_size);
   5191 
   5192     /* Port Group */
   5193     sal_memcpy(si->port_group,
   5194                &flexport_scache_ptr[scache_offset],
   5195                var_size);
   5196     scache_offset += (var_size + hole_size);
   5197 
   5198     /* Port Serdes */
   5199     sal_memcpy(si->port_serdes,
   5200                &flexport_scache_ptr[scache_offset],
   5201                var_size);
   5202     scache_offset += (var_size + hole_size);
   5203 
   5204     /* Max port speed */
   5205     sal_memcpy(si->port_speed_max,
   5206                &flexport_scache_ptr[scache_offset],
   5207                var_size);
   5208     scache_offset += (var_size + hole_size);
   5209 
   5210     /* Oversub pbm */
   5211     sal_memcpy(&si->oversub_pbm,
   5212                &flexport_scache_ptr[scache_offset],
   5213                sizeof(pbmp_t));
   5214     scache_offset += sizeof(pbmp_t);
   5215 
   5216     /* Disabled Port Bitmap */
   5217     sal_memcpy(&si->all.disabled_bitmap,
   5218            &flexport_scache_ptr[scache_offset],
   5219            sizeof(pbmp_t));
   5220     scache_offset += sizeof(pbmp_t);
   5221     if (recovered_ver > SOC_FLEXPORT_WB_VERSION_1_0) {
   5222         sal_memcpy(&si->roe_compression,
   5223            &flexport_scache_ptr[scache_offset],
   5224            sizeof(pbmp_t));
   5225         scache_offset += sizeof(pbmp_t);
   5226     } else { 
   5227       additional_scache_size += sizeof(pbmp_t);
   5228     }
   5229     if (additional_scache_size > 0) {
   5230         SOC_IF_ERROR_RETURN(soc_scache_realloc(unit, scache_handle,
   5231                                                additional_scache_size));
   5232     }
   5233 
   5234     SOC_PBMP_CLEAR(si->xpipe_pbm);
   5235     SOC_PBMP_CLEAR(si->pipe_pbm[0]);
   5236 
   5237     for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
   5238         if (si->port_p2l_mapping[phy_port] == -1) {
   5239             continue;
   5240         }
   5241         SOC_PBMP_PORT_ADD(si->xpipe_pbm, si->port_p2l_mapping[phy_port]);
   5242         SOC_PBMP_PORT_ADD(si->pipe_pbm[0], si->port_p2l_mapping[phy_port]);
   5243     }
   5244 
   5245     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   5246                 (BSL_META_U(unit,
   5247                  "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
   5248 
   5249     return SOC_E_NONE;
   5250 }
   5251 #endif /* BCM_WARM_BOOT_SUPPORT */
   5252 
   5253 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   5254 void
   5255 soc_monterey_flexport_sw_dump(int unit) {
   5256     int port;
   5257     int portGroup;
   5258     int portSerdes;
   5259     int portLanes;
   5260     int bandwidth;
   5261     int l2p;
   5262     int p2m;
   5263     int m2p;
   5264     int p2l;
   5265     char  pfmt[SOC_PBMP_FMT_LEN];
   5266     int phy_port, mmu_port, cosq, numq, uc_cosq, uc_numq;
   5267 
   5268     LOG_CLI((BSL_META_U(unit,
   5269                             "           logical  p2l  "
   5270                "l2p  p2m   m2p  ucast_Qbase/Numq  mcast_Qbase/Numq\n")));
   5271     for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
   5272         port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   5273         if (port == -1) {
   5274             continue;
   5275         }
   5276         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   5277         cosq = SOC_INFO(unit).port_cosq_base[port];
   5278         numq = SOC_INFO(unit).port_num_cosq[port];
   5279         uc_cosq = SOC_INFO(unit).port_uc_cosq_base[port];
   5280         uc_numq = SOC_INFO(unit).port_num_uc_cosq[port];
   5281         cosq = soc_monterey_logical_qnum_hw_qnum(unit, port, cosq, 0);
   5282         uc_cosq = soc_monterey_logical_qnum_hw_qnum(unit, port, uc_cosq,
   5283                                                1);
   5284         l2p = phy_port;
   5285         p2m = mmu_port;
   5286 
   5287         m2p = SOC_INFO(unit).port_m2p_mapping[mmu_port];
   5288         p2l = SOC_INFO(unit).port_p2l_mapping[phy_port];
   5289         LOG_CLI((BSL_META_U(unit,
   5290                             "  %8s  %3d     %3d  "
   5291                 "%3d   %3d  %3d      %4d/%-4d            %4d/%-4d\n"),
   5292                 SOC_INFO(unit).port_name[port], port,
   5293                 p2l, l2p, p2m, m2p,
   5294                 uc_cosq, uc_numq, cosq, numq));
   5295     }
   5296     LOG_CLI((BSL_META_U(unit,
   5297               "\nlogical  physical  bandwidth  "
   5298               "portLanes  portGroup  portSerdes  ")));
   5299 
   5300     for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) {
   5301         port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   5302         if (port == -1) {
   5303             continue;
   5304         }
   5305         bandwidth = SOC_INFO(unit).port_speed_max[port];
   5306         portLanes = SOC_INFO(unit).port_num_lanes[port];
   5307         portGroup = SOC_INFO(unit).port_group[port];
   5308         portSerdes = SOC_INFO(unit).port_serdes[port];
   5309         LOG_CLI((BSL_META_U(unit,
   5310                           "\n%3d     %3d       "
   5311                           "%9d        "
   5312                           "%3d        "
   5313                           "%3d        "
   5314                           "%3d         "),
   5315                           port, phy_port, bandwidth,
   5316                           portLanes, portGroup, portSerdes));
   5317     }
   5318 
   5319     LOG_CLI((BSL_META_U(unit,
   5320                         "\n    Oversub Bitmap: %s"),
   5321        SOC_PBMP_FMT(SOC_INFO(unit).oversub_pbm, pfmt)));
   5322     LOG_CLI((BSL_META_U(unit,
   5323                         "\n    Disabled Bitmap: %s \n"),
   5324        SOC_PBMP_FMT(SOC_INFO(unit).all.disabled_bitmap, pfmt)));
   5325 
   5326 
   5327 }
   5328 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   5329 
   5330 
   5331 #endif /* BCM_MONTEREY_SUPPORT */