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


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