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


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