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


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 
      9 #include <soc/defs.h>
     10 
     11 #include <assert.h>
     12 #include <shared/bsl.h>
     13 #include <sal/core/libc.h>
     14 #if defined(BCM_HURRICANE2_SUPPORT)
     15 
     16 #include <shared/util.h>
     17 #include <soc/mem.h>
     18 #include <soc/cm.h>
     19 #include <soc/drv.h>
     20 #include <soc/register.h>
     21 #include <soc/memory.h>
     22 #include <soc/hurricane2.h>
     23 #include <bcm/error.h>
     24 #include <bcm_int/esw/port.h>
     25 #include <bcm_int/esw/firebolt.h>
     26 #include <bcm_int/esw/trx.h>
     27 #include <bcm_int/esw/xgs3.h>
     28 
     29 #include <bcm_int/esw_dispatch.h>
     30 
     31 /*
     32  * Each TSC can be configured into following 5 mode:
     33  *   Lane number    0    1    2    3
     34  *   ------------  ---  ---  ---  ---
     35  *    single port  40G   x    x    x
     36  *      dual port  20G   x   20G   x
     37  *   tri_023 port  20G   x   10G  10G
     38  *   tri_012 port  10G  10G  20G   x
     39  *      quad port  10G  10G  10G  10G
     40  *
     41  *          lanes                mode         valid lane index
     42  *       ------------      ----------------   ----------------
     43  *       new  current        new    current
     44  *       ---  -------      -------  -------
     45  * #1     4      1         single    quad            0
     46  * #2     4      1         single   tri_012          0
     47  * #3     4      2         single   tri_023          0
     48  * #4     4      2         single    dual            0
     49  * #5     2      1         tri_023   quad            0
     50  * #6     2      1         tri_012   quad            2
     51  * #7     2      1          dual    tri_023          2
     52  * #8     2      1          dual    tri_012          0
     53  * #9     2      4          dual    single           0
     54  * #10    1      2         tri_023   dual            2
     55  * #11    1      2         tri_012   dual            0
     56  * #12    1      2          quad    tri_023          0
     57  * #13    1      2          quad    tri_012          2
     58  * #14    1      4          quad    single           0
     59  * Following mode change requires 2 transition
     60  *   - from single to tri_023: #9 + #10
     61  *   - from single to tri_012: #9 + #11
     62  * Following mode change are the result of lane change on multiple ports
     63  *   - from quad to dual: #12 + #7 or #13 + #8
     64  *   - from dual to quad: #10 + #12 or #11 + # 13
     65  *   - from tri_023 to tri_012: #7 + #11 or #12 + #6
     66  *   - from tri_012 to tri_023: #8 + #10 or #13 + #5
     67  *
     68  * Logical port number will stay the same after conversion, for example
     69  *     converting single port to dual port, the logical port number of lane 0
     70  *     will be changed.
     71  */
     72 int
     73 soc_hurricane2_port_lanes_set(int unit, soc_port_t port_base, int lanes,
     74                             int *cur_lanes, int *phy_ports, int *phy_ports_len)
     75 {
     76     soc_info_t *si = &SOC_INFO(unit);
     77     soc_field_t fields[2];
     78     uint32 values[2];
     79     int mode, cur_mode;
     80     int phy_port_base, port, i;
     81     int blk, bindex;
     82     uint32 rval;
     83 
     84     /* Find physical port number and lane index of the specified port */
     85     phy_port_base = si->port_l2p_mapping[port_base];
     86     if (phy_port_base == -1) {
     87         return SOC_E_PORT;
     88     }
     89 
     90     bindex = -1;
     91     for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
     92         blk = SOC_PORT_IDX_BLOCK(unit, phy_port_base, i);
     93         if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) {
     94             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port_base, i);
     95             break;
     96         }
     97     }
     98 
     99     /* Get the current mode */
    100     SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port_base, &rval));
    101     cur_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval,
    102                                  XPORT0_CORE_PORT_MODEf);
    103 
    104     /* Figure out the current number of lane from current mode */
    105     switch (cur_mode) {
    106     case SOC_HU2_PORT_MODE_QUAD:
    107         *cur_lanes = 1;
    108         break;
    109     case SOC_HU2_PORT_MODE_TRI_012:
    110         *cur_lanes = bindex == 0 ? 1 : 2;
    111         break;
    112     case SOC_HU2_PORT_MODE_TRI_023:
    113         *cur_lanes = bindex == 0 ? 2 : 1;
    114         break;
    115     case SOC_HU2_PORT_MODE_DUAL:
    116         *cur_lanes = 2;
    117         break;
    118     case SOC_HU2_PORT_MODE_SINGLE:
    119         *cur_lanes = 4;
    120         break;
    121     default:
    122         return SOC_E_FAIL;
    123     }
    124 
    125     if (lanes == 4 || *cur_lanes == 4) {
    126         if (bindex & 0x3) {
    127             return SOC_E_PARAM;
    128         }
    129     } else if (lanes == 2 || *cur_lanes == 2) {
    130         if (bindex & 0x1) {
    131             return SOC_E_PARAM;
    132         }
    133     }
    134 
    135     if (lanes == *cur_lanes) {
    136         return SOC_E_NONE;
    137     }
    138 
    139     /* Figure out new mode */
    140     if (lanes == 4) {
    141         mode = SOC_HU2_PORT_MODE_SINGLE;
    142     } else if (lanes == 2) {
    143         if (cur_mode == SOC_HU2_PORT_MODE_QUAD) {
    144             mode = bindex == 0 ?
    145                 SOC_HU2_PORT_MODE_TRI_023 : SOC_HU2_PORT_MODE_TRI_012;
    146         } else {
    147             mode = SOC_HU2_PORT_MODE_DUAL;
    148         }
    149     } else{
    150         if (cur_mode == SOC_HU2_PORT_MODE_DUAL) {
    151             mode = bindex == 0 ?
    152                 SOC_HU2_PORT_MODE_TRI_012 : SOC_HU2_PORT_MODE_TRI_023;
    153         } else {
    154             mode = SOC_HU2_PORT_MODE_QUAD;
    155         }
    156     }
    157 
    158     *phy_ports_len = 0;
    159     if (lanes > *cur_lanes) { /* Figure out which port(s) to be removed */
    160         if (lanes == 4) {
    161             if (cur_mode == SOC_HU2_PORT_MODE_TRI_012 ||
    162                 cur_mode == SOC_HU2_PORT_MODE_QUAD) {
    163                 if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
    164                     phy_ports[(*phy_ports_len)++] = phy_port_base + 1;
    165                 }
    166             }
    167             if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
    168                 phy_ports[(*phy_ports_len)++] = phy_port_base + 2;
    169             }
    170             if (cur_mode == SOC_HU2_PORT_MODE_TRI_023 ||
    171                 cur_mode == SOC_HU2_PORT_MODE_QUAD) {
    172                 if (si->port_p2l_mapping[phy_port_base + 3] != -1) {
    173                     phy_ports[(*phy_ports_len)++] = phy_port_base + 3;
    174                 }
    175             }
    176         } else {
    177             if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
    178                 phy_ports[(*phy_ports_len)++] = phy_port_base + 1;
    179             }
    180         }
    181     } else { /* Figure out which port(s) to be added */
    182         if (lanes == 2) {
    183             if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
    184                 phy_ports[(*phy_ports_len)++] = phy_port_base + 2;
    185             }
    186         } else {
    187             if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
    188                 phy_ports[(*phy_ports_len)++] = phy_port_base + 1;
    189             }
    190             if (cur_mode == SOC_HU2_PORT_MODE_SINGLE) {
    191                 if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
    192                     phy_ports[(*phy_ports_len)++] = phy_port_base + 2;
    193                 }
    194                 if (si->port_p2l_mapping[phy_port_base + 3] != -1) {
    195                     phy_ports[(*phy_ports_len)++] = phy_port_base + 3;
    196                 }
    197             }
    198         }
    199     }
    200     
    201     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
    202         static char *mode_name[] = {
    203             "QUAD", "TRI_012", "TRI_023", "DUAL", "SINGLE"
    204         };
    205         LOG_CLI((BSL_META_U(unit,
    206                             "port %d physical port %d bindex %d\n"),
    207                  port_base, phy_port_base, bindex));
    208         LOG_CLI((BSL_META_U(unit,
    209                             "mode (new:%s cur:%s) lanes (new:%d cur:%d)\n"),
    210                  mode_name[mode], mode_name[cur_mode], lanes, *cur_lanes));
    211         for (i = 0; i < *phy_ports_len; i++) {
    212             LOG_CLI((BSL_META_U(unit,
    213                                 "%s physical port %d (port %d)\n"),
    214                      lanes > *cur_lanes ? "del" : "add",
    215                      phy_ports[i], si->port_p2l_mapping[phy_ports[i]]));
    216         }
    217     }
    218 
    219     /* Update soc_control information */
    220     SOC_CONTROL_LOCK(unit);
    221     if (lanes > *cur_lanes) { /* port(s) to be removed */
    222         for (i = 0; i < *phy_ports_len; i++) {
    223             port = si->port_p2l_mapping[phy_ports[i]];
    224             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
    225             if (IS_HG_PORT(unit, phy_ports[i])) {
    226                 SOC_PBMP_PORT_REMOVE(si->st.bitmap, port);
    227                 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port);
    228             } else {
    229                 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port);
    230                 if (IS_GE_PORT(unit, port)) {
    231                     SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port);
    232                 } else {
    233                     SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
    234                 }
    235             }
    236         }
    237     } else { /* port(s) to be added */
    238         for (i = 0; i < *phy_ports_len; i++) {
    239             port = si->port_p2l_mapping[phy_ports[i]];
    240             SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, port);
    241             if (IS_HG_PORT(unit, port)) {
    242                 SOC_PBMP_PORT_ADD(si->st.bitmap, port);
    243                 SOC_PBMP_PORT_ADD(si->hg.bitmap, port);
    244             } else {
    245                 SOC_PBMP_PORT_ADD(si->ether.bitmap, port);
    246                 if (IS_GE_PORT(unit, port)) {
    247                     SOC_PBMP_PORT_ADD(si->ge.bitmap, port);
    248                 } else {
    249                     SOC_PBMP_PORT_ADD(si->xe.bitmap, port);
    250                 }
    251             }
    252         }
    253     }
    254 
    255 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \
    256     si->ptype.num = 0; \
    257     si->ptype.min = si->ptype.max = -1; \
    258     PBMP_ITER(si->ptype.bitmap, port) { \
    259         si->ptype.port[si->ptype.num++] = port; \
    260         if (si->ptype.min < 0) { \
    261             si->ptype.min = port; \
    262         } \
    263         if (port > si->ptype.max) { \
    264             si->ptype.max = port; \
    265         } \
    266     }
    267 
    268     RECONFIGURE_PORT_TYPE_INFO(ether);
    269     RECONFIGURE_PORT_TYPE_INFO(st);
    270     RECONFIGURE_PORT_TYPE_INFO(hg);
    271     RECONFIGURE_PORT_TYPE_INFO(xe);
    272     RECONFIGURE_PORT_TYPE_INFO(ge);
    273 
    274 #undef RECONFIGURE_PORT_TYPE_INFO
    275 
    276     /* Update num of lanes info which is used by SerDes driver */
    277     SOC_PORT_NUM_LANES_SET(unit, port_base, lanes);
    278     for (i = 0; i < *phy_ports_len; i++) {
    279         port = si->port_p2l_mapping[phy_ports[i]];
    280         SOC_PORT_NUM_LANES_SET(unit, port, lanes > *cur_lanes ? 0 : lanes);
    281     }
    282 
    283     soc_dport_map_update(unit);
    284     SOC_CONTROL_UNLOCK(unit);
    285 
    286     fields[0] = XPORT0_CORE_PORT_MODEf;
    287     values[0] = mode;
    288     fields[1] = XPORT0_PHY_PORT_MODEf;
    289     values[1] = mode;
    290     SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, XLPORT_MODE_REGr,
    291                                                 port_base, 2, fields, values));
    292 
    293     if (*phy_ports_len == 0) {
    294         return SOC_E_NONE;
    295     }
    296 
    297     /* Update TDM */
    298 #ifdef _HURRICANE2_DEBUG
    299     SOC_IF_ERROR_RETURN
    300         (_soc_hurricane2_port_lanes_update_tdm(unit, port_base, lanes,
    301                                              *cur_lanes, phy_ports,
    302                                              *phy_ports_len));
    303 #endif
    304     return SOC_E_NONE;
    305 }
    306 
    307 
    308 int
    309 soc_hurricane2_port_lanes_get(int unit, soc_port_t port_base, int *cur_lanes)
    310 {
    311     soc_info_t *si = &SOC_INFO(unit);
    312     int cur_mode;
    313     int phy_port_base, i;
    314     int blk, bindex;
    315     uint32 rval;
    316 
    317     /* Find physical port number and lane index of the specified port */
    318     phy_port_base = si->port_l2p_mapping[port_base];
    319     if (phy_port_base == -1) {
    320         return SOC_E_PORT;
    321     }
    322 
    323     bindex = -1;
    324     for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
    325         blk = SOC_PORT_IDX_BLOCK(unit, phy_port_base, i);
    326         if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) {
    327             bindex = SOC_PORT_IDX_BINDEX(unit, phy_port_base, i);
    328             break;
    329         }
    330     }
    331 
    332     /* Get the current mode */
    333     SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port_base, &rval));
    334     cur_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval,
    335                                  XPORT0_CORE_PORT_MODEf);
    336 
    337     /* Figure out the current number of lane from current mode */
    338     switch (cur_mode) {
    339     case SOC_HU2_PORT_MODE_QUAD:
    340         *cur_lanes = 1;
    341         break;
    342     case SOC_HU2_PORT_MODE_TRI_012:
    343         *cur_lanes = bindex == 0 ? 1 : 2;
    344         break;
    345     case SOC_HU2_PORT_MODE_TRI_023:
    346         *cur_lanes = bindex == 0 ? 2 : 1;
    347         break;
    348     case SOC_HU2_PORT_MODE_DUAL:
    349         *cur_lanes = 2;
    350         break;
    351     case SOC_HU2_PORT_MODE_SINGLE:
    352         *cur_lanes = 4;
    353         break;
    354     default:
    355         return SOC_E_FAIL;
    356     }
    357 
    358     return SOC_E_NONE;
    359 }
    360 
    361 int
    362 _bcm_hr2_dual_port_mode_pilot_tx(int unit, int port, bcm_pkt_t *pkt) {
    363     int rv;
    364     uint64 old_tpok;
    365     uint64 new_tpok;
    366     uint64 tx_ctl;
    367 
    368     /* Save original counter */
    369     SOC_IF_ERROR_RETURN(READ_TPOKr(unit, port, &old_tpok));
    370 
    371     /* Setup */
    372     if (bcm_esw_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_PHY) < 0) {
    373         LOG_ERROR(BSL_LS_BCM_PORT,
    374                   (BSL_META_U(unit,
    375                               "Port %d LoopBack Set Failed\n"), port));
    376     }
    377     /* 
    378      * stop the packet from actually going out on the wire, 
    379      * while still incrementing the MAC counters 
    380      */
    381     SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctl));
    382     soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctl, DISCARDf, 1);
    383     SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctl));
    384 
    385     /* Send Packets */
    386     BCM_PBMP_CLEAR(pkt->tx_pbmp);
    387     BCM_PBMP_PORT_ADD(pkt->tx_pbmp, port);
    388     rv = bcm_esw_tx(unit, pkt, NULL);
    389     if (rv < 0) {
    390     	LOG_ERROR(BSL_LS_BCM_PORT,
    391                   (BSL_META_U(unit,
    392                               "Tx Error %d\n"), rv));
    393     	return BCM_E_INTERNAL; 
    394     }
    395     sal_udelay(10000);
    396 
    397     /* Verify Counters */
    398     SOC_IF_ERROR_RETURN(READ_TPOKr(unit, port, &new_tpok));
    399     LOG_VERBOSE(BSL_LS_BCM_PORT, \
    400                 (BSL_META_U(unit, \
    401                             "old TPOK(port=%d)=0x%x, 0x%x\n"), \
    402                             port, COMPILER_64_HI(old_tpok), COMPILER_64_LO(old_tpok)));
    403     LOG_VERBOSE(BSL_LS_BCM_PORT, \
    404                 (BSL_META_U(unit, \
    405                             "new TPOK(port=%d)=0x%x, 0x%x\n"), \
    406                             port, COMPILER_64_HI(new_tpok), COMPILER_64_LO(new_tpok)));
    407     if ((COMPILER_64_HI(new_tpok) == COMPILER_64_HI(old_tpok)) && \
    408         (COMPILER_64_LO(new_tpok) == COMPILER_64_LO(old_tpok))) {
    409         /* packet not transmit out */
    410         return BCM_E_FAIL;
    411     }
    412     LOG_VERBOSE(BSL_LS_BCM_PORT, \
    413                 (BSL_META_U(unit, \
    414                             "Dual port mode check pass on port %d\n"),port));
    415 
    416     /* Cleanup */
    417     if (bcm_esw_l2_addr_delete_by_port(unit, -1, port, 0) < 0) {
    418         LOG_ERROR(BSL_LS_BCM_PORT,
    419                   (BSL_META_U(unit,
    420                               "Port %d L2 entry delete Failed\n"), port));
    421     }
    422     SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctl));
    423     soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctl, DISCARDf, 0);
    424     SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctl));
    425     if (bcm_esw_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_NONE) < 0) {
    426         LOG_ERROR(BSL_LS_BCM_PORT,
    427                   (BSL_META_U(unit,
    428                               "Port %d LoopBack Set Failed\n"), port));
    429     }
    430     if (bcm_esw_stat_clear(unit, port) < 0) {
    431         LOG_ERROR(BSL_LS_BCM_PORT,
    432                   (BSL_META_U(unit,
    433                               "Port %d Stat Clear Failed\n"), port));
    434     }
    435     return rv;
    436 }
    437 
    438 int _bcm_hr2_dual_port_mode_check(int unit, bcm_port_t port, uint32 *tx_pkt)
    439 {
    440     bcm_pkt_t   pkt_info;
    441     uint32 rval = 0;
    442     int mode = 0;
    443     int timeout_cnt = 0;
    444     int i;
    445     int rv = 0;
    446     sal_memset(&pkt_info, 0, sizeof(bcm_pkt_t));
    447     pkt_info.unit = unit;
    448     pkt_info._pkt_data.data = (uint8 *) tx_pkt;
    449     pkt_info.pkt_data = &pkt_info._pkt_data;
    450     pkt_info.blk_count = 1;
    451     pkt_info._pkt_data.len = 68;
    452     pkt_info.call_back = NULL;
    453     pkt_info.flags = 0x20; 
    454 
    455     timeout_cnt = 0;
    456     for (i = 0; i < 10 ; i++) {
    457         /* coverity[overrun-buffer-val] */
    458         rv = _bcm_hr2_dual_port_mode_pilot_tx(unit, port, &pkt_info);
    459         if (rv == BCM_E_NONE) {
    460             break;
    461         } else {
    462             /* Re-write the MODEs */
    463             /* program the port to quad port mode */
    464             LOG_VERBOSE(BSL_LS_BCM_PORT, \
    465                         (BSL_META_U(unit, \
    466                                     "WAR step 1: program the port to quad port mode\n")));
    467             mode = 0; /* quad port mode */
    468             SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port, &rval));
    469             soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval,
    470                               XPORT0_CORE_PORT_MODEf, mode);
    471             soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval,
    472                               XPORT0_PHY_PORT_MODEf, mode);
    473             SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval));
    474     
    475             /* re-program the port to dual port mode */
    476             LOG_VERBOSE(BSL_LS_BCM_PORT, \
    477                         (BSL_META_U(unit, \
    478                                     "WAR step 2: re-program the port to dual port mode\n")));
    479             mode = 3; /* dual port mode */
    480             soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval,
    481                               XPORT0_CORE_PORT_MODEf, mode);
    482             soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval,
    483                               XPORT0_PHY_PORT_MODEf, mode);
    484     	    SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval));
    485     	}
    486         timeout_cnt++;
    487     }
    488     LOG_VERBOSE(BSL_LS_BCM_PORT, \
    489                 (BSL_META_U(unit, \
    490                             "WAR retried %d times on port %d\n"), timeout_cnt, port));
    491     if (timeout_cnt >= 10) {
    492         return BCM_E_TIMEOUT;
    493     }
    494     return BCM_E_NONE;
    495 }
    496 
    497 int
    498 bcm_hr2_dual_port_mode_reinit(int unit) {
    499     uint32 *tx_pkt;
    500     uint32 *buff;
    501     int rv,i;
    502     sal_usecs_t stime = sal_time_usecs();
    503     bcm_port_t test_ports[2];
    504     uint16      dev_id;
    505     uint8       rev_id;
    506     int hu2_config_id;
    507     int check_required = 0;
    508     int enable = 0;
    509     uint32 pkt[17] = {0x66778899, 0xaabb0011, 0x22334455, 0x81000001,
    510                       0x002e0000, 0x56761234, 0x56771234, 0x56781234,
    511                       0x56791234, 0x567a1234, 0x567b1234, 0x567c1234,
    512                       0x567d1234, 0x567e1234, 0x567f1234, 0x56801234,
    513                       0x00000000};
    514 
    515     /* Qualify situation that should apply the WAR */
    516     /* get the port number for the checking */
    517     soc_cm_get_id(unit, &dev_id, &rev_id);
    518     hu2_config_id = soc_property_get(unit, spn_BCM5615X_CONFIG, 0);
    519 
    520     /* Test both the dual mode port */
    521     check_required = 0;
    522     switch (dev_id) {
    523         case BCM56150_DEVICE_ID:
    524         case BCM56151_DEVICE_ID:
    525         case BCM53346_DEVICE_ID:
    526         case BCM53347_DEVICE_ID:
    527         case BCM56152_DEVICE_ID:
    528         case BCM53344_DEVICE_ID:
    529             if ((hu2_config_id == 1) || (hu2_config_id == 10)) {
    530                 check_required = 1;
    531                 test_ports[0] = 28;
    532                 test_ports[1] = 29;
    533             } else if (hu2_config_id == 11) {
    534                 check_required = 1;
    535                 test_ports[0] = 26;
    536                 test_ports[1] = 27;
    537 
    538             }
    539             break;
    540         default :
    541             break;
    542     }
    543     
    544     if (check_required) {
    545         tx_pkt = soc_cm_salloc(unit, 256, "tx_pilot_pkt");
    546         if (tx_pkt == NULL) {
    547             return BCM_E_MEMORY;
    548         }
    549         buff = tx_pkt;
    550         for(i = 0; i < 17; i++) {
    551             *buff = pkt[i];
    552             buff++;
    553         }
    554         soc_cm_sflush(unit, tx_pkt, 256);
    555         for (i = 0; i < 2; i++) {
    556             /* Apply to valid ports */
    557             if (BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), test_ports[i])) {
    558                 /* 
    559                  * Check if port is enabled already 
    560                  * Ports could be disabled in this state because of 
    561                  * 'CFLAGS += -DBCM_PORT_DEFAULT_DISABLE'
    562                  * Check the state and enable port if necessary.
    563                  */
    564                 rv = bcm_esw_port_enable_get(unit, \
    565                                      test_ports[i], &enable);
    566                 if (rv < 0) {
    567                     LOG_ERROR(BSL_LS_BCM_PORT, \
    568                               (BSL_META_U(unit, \
    569                                           "Failed to get Port %d enable status\n"), test_ports[i]));
    570                 }
    571                 if (!enable) {
    572                     rv = bcm_esw_port_enable_set(unit, \
    573                                             test_ports[i], 1);
    574                     if (rv < 0) {
    575                         LOG_ERROR(BSL_LS_BCM_PORT, \
    576                                   (BSL_META_U(unit, \
    577                                               "Failed to set Port %d enable status\n"), test_ports[i]));
    578                     }
    579                 }
    580                 LOG_VERBOSE(BSL_LS_BCM_PORT, \
    581                             (BSL_META_U(unit, \
    582                                         "Apply Dual Port Mode WAR to port(%d)\n"), test_ports[i]));
    583                 rv = _bcm_hr2_dual_port_mode_check(unit, test_ports[i], tx_pkt);
    584                 if (rv < 0) {
    585                     LOG_ERROR(BSL_LS_BCM_PORT,
    586                               (BSL_META_U(unit,
    587                                           "Dual port mode WAR Failed on port %d\n"), test_ports[i]));
    588                 }
    589 
    590                 /* recover the port enable state */
    591                 if (!enable) {
    592                     rv = bcm_esw_port_enable_set(unit, \
    593                                          test_ports[i], enable);
    594                     if (rv < 0) {
    595                         LOG_ERROR(BSL_LS_BCM_PORT, \
    596                                   (BSL_META_U(unit, \
    597                                               "Failed to recover Port %d enable status\n"), test_ports[i]));
    598                     }
    599                 }
    600             }
    601         }
    602         soc_cm_sfree(unit, tx_pkt);
    603     }
    604 
    605     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    606                 (BSL_META_U(unit,
    607                             "Dual port mode WAR: took %d usec\n"),
    608                             SAL_USECS_SUB(sal_time_usecs(), stime)));
    609 
    610     /* Always return OK so that further init can go on */
    611     return BCM_E_NONE;
    612 }
    613 
    614 #endif