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

lb_util.c (157152B)


      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  * Utilities for Loopback Tests, Mark 2
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/boot.h>
     13 #include <sal/appl/sal.h>
     14 #include <shared/bsl.h>
     15 #include <appl/diag/system.h>
     16 #include <appl/diag/test.h>
     17 
     18 
     19 #include <soc/debug.h>
     20 #include <soc/hash.h>
     21 #include <soc/higig.h>
     22 #include <soc/drv.h>
     23 #ifdef BCM_ESW_SUPPORT
     24 #include <soc/firebolt.h>
     25 #endif
     26 #ifdef BCM_TRIUMPH3_SUPPORT
     27 #include <soc/ism.h>
     28 #endif /* BCM_TRIUMPH3_SUPPORT */
     29 #ifdef BCM_ESW_SUPPORT
     30 #include <bcm_int/esw/mbcm.h>
     31 #endif
     32 
     33 
     34 #include <bcm/error.h>
     35 #include <bcm/vlan.h>
     36 #include <bcm/link.h>
     37 #include <bcm/stg.h>
     38 #include <bcm/tx.h>
     39 #include <bcm/stat.h>
     40 #include <bcm/mcast.h>
     41 #include <bcm/stack.h>
     42 #include <bcm/cosq.h>
     43 #include <bcm/port.h>
     44 
     45 #include <appl/test/loopback.h>
     46 #include <appl/test/loopback2.h>
     47 #include <appl/test/lb_util.h>
     48 
     49 #ifdef PORTMOD_SUPPORT
     50 #include <soc/portmod/portmod.h>
     51 #include <soc/portmod/portmod_common.h>
     52 #endif /* PORTMOD_SUPPORT */
     53 
     54 #ifdef BCM_TOMAHAWK3_SUPPORT
     55 #include <soc/tomahawk3.h>
     56 #endif
     57 
     58 /*
     59  * De-allocate any packet buffers in the RX packet pool.
     60  * Then clear all that memory.
     61  */
     62 #define CLEAR_RX_PKTS(lw, lp)                                           \
     63     do {                                                                \
     64         int idxm;                                                       \
     65         for (idxm = 0; idxm < lp->ppt_end; idxm++) {                    \
     66             if (LB2_RX_PKT(lw, idxm)->alloc_ptr) {                      \
     67                 bcm_rx_free((lw)->unit, LB2_RX_PKT(lw, idxm)->alloc_ptr); \
     68             }                                                           \
     69         }                                                               \
     70         sal_memset((lw)->rx_pkts, 0, (lp)->ppt_end * sizeof(bcm_pkt_t));\
     71     } while (0)
     72 
     73 
     74 /* sal_mac_addr_t lbu_mac_default = {0x00, 0x00, 0x00, 0xde, 0xad, 0x00}; */
     75 sal_mac_addr_t lbu_mac_src = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
     76 sal_mac_addr_t lbu_mac_dst = {0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb};
     77 
     78 const char *lb2_parse_speed[] = {
     79     LB2_SPEED_INIT_STR,
     80     NULL
     81 };
     82 
     83 
     84 STATIC uint32 lbu_saved_srcmod[SOC_MAX_NUM_DEVICES];
     85 STATIC uint32 lbu_saved_srcport[SOC_MAX_NUM_DEVICES];
     86 
     87 STATIC
     88 char *lb2_crc_mode[] = { "CpuNone", "CpuAppend", "MacRegen", NULL };
     89 
     90 const char *lb2_parse_snake[] = {
     91     "INCreasing",
     92     "DECreasing",
     93     "TWOways",
     94     NULL
     95 };
     96 
     97 const char *lb2_parse_lbmode[] = {
     98     "MAC",
     99     "PHY",
    100     "EXTernal",
    101     NULL
    102 };
    103 
    104 static char *send_mech_list[] = {
    105     "Single", "Array", NULL /* "LinkList" */
    106 };
    107 
    108 /* Forward declarations */
    109 STATIC void mac_params_init(int unit, int num_cos, loopback2_testdata_t *lp);
    110 STATIC void phy_params_init(int unit, int num_cos, loopback2_testdata_t *lp);
    111 STATIC void ext_params_init(int unit, int num_cos, loopback2_testdata_t *lp);
    112 STATIC void snake_params_init(int unit, int num_cos, loopback2_testdata_t *lp);
    113 
    114 STATIC  uint32
    115 lbu_timeout_usec(int unit)
    116 {
    117     uint32              defl;
    118 
    119     /* These values are given in seconds, then converted to us below */
    120     if (SAL_BOOT_QUICKTURN) {
    121         defl = LB2_PACKET_TIMEOUT_QT;
    122     } else if (SAL_BOOT_PLISIM) {
    123         defl = LB2_PACKET_TIMEOUT_PLI;
    124     } else {
    125         defl = LB2_PACKET_TIMEOUT;
    126     }
    127     
    128     return (soc_property_get(unit, spn_DIAG_LB_PACKET_TIMEOUT, defl) *
    129             SECOND_USEC);
    130 }
    131 
    132 /*
    133  * Loopback work structure
    134  */
    135 
    136 void
    137 lbu_pkt_param_add(int unit, parse_table_t *pt, loopback2_testdata_t *lp)
    138  /*
    139  * Returns:     0 for success, -1 for failed.
    140  */
    141 {
    142     if (lp->test_type == LB2_TT_EXT) {
    143         parse_table_add(pt, "TxPortBitMap",PQ_PBMP|PQ_DFL,      0,
    144                         &lp->pbm_tx,    NULL);
    145         parse_table_add(pt, "DestinationIncrement",PQ_INT|PQ_DFL, 0,
    146                         &lp->dst_inc,   NULL);
    147     } else {
    148         parse_table_add(pt, "PortBitMap", PQ_PBMP | PQ_DFL, 0, 
    149                         &lp->pbm, NULL);
    150     }
    151     if ((lp->test_type == LB2_TT_MAC) || (lp->test_type == LB2_TT_PHY)) {
    152         if (!SOC_IS_XGS12_FABRIC(unit)){
    153             parse_table_add(pt, "UntagBitMap",  PQ_PBMP|PQ_DFL, 0,
    154                             &lp->ubm,   NULL);
    155         }
    156     }
    157 
    158     parse_table_add(pt, "HGDestMOD",     PQ_DFL|PQ_INT,  0,
    159                     &lp->d_mod,      NULL);
    160     if (lp->test_type == LB2_TT_SNAKE) {
    161         parse_table_add(pt, "HGDestMODInc",     PQ_DFL|PQ_INT,  0,
    162                         &lp->d_mod_inc,      NULL);
    163     }
    164     parse_table_add(pt, "HGDestPORT",    PQ_DFL|PQ_INT, 0,
    165                     &lp->d_port,     NULL);
    166     parse_table_add(pt, "OpCode",    PQ_DFL|PQ_INT, 0,
    167                     &lp->opcode,     NULL);
    168 
    169     parse_table_add(pt, "SourceMac",    PQ_DFL|PQ_MAC,  0,
    170                     &lp->mac_src,       NULL);
    171     parse_table_add(pt, "SourceMacInc",PQ_DFL|PQ_INT,   0,
    172                     &lp->mac_src_inc,NULL);
    173     parse_table_add(pt, "DestMac",      PQ_DFL|PQ_MAC,  0,
    174                     &lp->mac_dst,       NULL);
    175     parse_table_add(pt, "DestMacInc",   PQ_DFL|PQ_INT,  0,
    176                     &lp->mac_dst_inc,NULL);
    177     parse_table_add(pt, "Pattern", PQ_HEX | PQ_DFL, 0, &lp->pattern, NULL);
    178     parse_table_add(pt, "PatternIncrement", PQ_HEX | PQ_DFL, 0,
    179                     &lp->pattern_inc, NULL);
    180     parse_table_add(pt, "VLantag",      PQ_INT|PQ_DFL,  0,
    181                     &lp->vlan,  NULL);
    182     parse_table_add(pt, "LengthStart", PQ_INT | PQ_DFL, 0,
    183                     &lp->len_start, NULL);
    184     parse_table_add(pt, "LengthEnd",    PQ_INT|PQ_DFL,  0,
    185                     &lp->len_end,       NULL);
    186     parse_table_add(pt, "LengthIncrement",PQ_INT|PQ_DFL, 0,
    187                     &lp->len_inc,       NULL);
    188     parse_table_add(pt, "PktsPerTrialStart",PQ_INT|PQ_DFL, 0,
    189                     &lp->ppt_start,     NULL);
    190     parse_table_add(pt, "PktsPerTrialEnd",PQ_INT|PQ_DFL, 0,
    191                     &lp->ppt_end,       NULL);
    192     parse_table_add(pt, "PktsPerTrialInc",PQ_INT|PQ_DFL, 0,
    193                     &lp->ppt_inc,       NULL);
    194     parse_table_add(pt, "SENDMethod", PQ_DFL|PQ_MULTI, 0,
    195                     &lp->send_mech, send_mech_list);
    196     parse_table_add(pt, "Count", PQ_INT | PQ_DFL, 0, &lp->iterations, NULL);
    197     parse_table_add(pt, "CRC",          PQ_MULTI|PQ_DFL, 0,
    198                     &lp->crc_mode, lb2_crc_mode);
    199     parse_table_add(pt, "PortSelectMode",     PQ_INT|PQ_DFL, 0,
    200                     &lp->port_select_mode, NULL);
    201 }
    202 
    203 void
    204 lbu_port_param_add(int unit, parse_table_t *pt, loopback2_testdata_t *lp)
    205 {
    206     parse_table_add(pt, "Speed",        PQ_MULTI|PQ_DFL,0,
    207                     &lp->speed, lb2_parse_speed);
    208     parse_table_add(pt, "AutoNeg",      PQ_BOOL|PQ_DFL, 0,
    209                     &lp->autoneg,       NULL);
    210     if (lp->test_type == LB2_TT_SNAKE) {
    211         parse_table_add(pt, "LoopbackMode", PQ_MULTI | PQ_DFL, 0,
    212                         &lp->loopback, lb2_parse_lbmode);
    213     }
    214 }
    215 
    216 void
    217 lbu_other_param_add(int unit, parse_table_t *pt, loopback2_testdata_t *lp)
    218 {
    219     parse_table_add(pt, "COSStart",     PQ_INT|PQ_DFL,  0,
    220                     &lp->cos_start,NULL);
    221     parse_table_add(pt, "COSEnd",       PQ_INT|PQ_DFL,  0,
    222                     &lp->cos_end,NULL);
    223     parse_table_add(pt, "CheckData",    PQ_BOOL|PQ_DFL, 0,
    224                     &lp->check_data,NULL);
    225     parse_table_add(pt, "CheckCrc",     PQ_BOOL|PQ_DFL, 0,
    226                     &lp->check_crc,NULL);
    227     parse_table_add(pt, "InjectPackets", PQ_BOOL | PQ_DFL, 0,
    228                     &lp->inject, NULL);
    229     if (lp->test_type == LB2_TT_SNAKE) {
    230         parse_table_add(pt, "Duration", PQ_INT | PQ_DFL, 0,
    231                         &lp->duration, NULL);
    232         parse_table_add(pt, "Interval", PQ_INT | PQ_DFL, 0,
    233                         &lp->interval, NULL);
    234         parse_table_add(pt, "SnakePath", PQ_MULTI | PQ_DFL, 0,
    235                         &lp->snake_way, lb2_parse_snake);
    236 #ifdef BCM_TOMAHAWK_SUPPORT
    237         parse_table_add(pt, "LineRate", PQ_BOOL | PQ_DFL, 0,
    238                         &lp->line_rate, NULL);
    239 #endif
    240     }
    241 }
    242 
    243 bcm_rx_t
    244 lbu_rx_callback(int unit, bcm_pkt_t *info, void *cookie)
    245 /*
    246  * Function:    lbu_rx_callback
    247  * Purpose:     This is the callback handler for the packets forwarded to
    248  *              the CMIC.
    249  * Parameters:
    250  *              unit - device code.
    251  *              info - received packet description structure.
    252  *              cookie - lw - pointer to lb work.
    253  * Returns:     0 - success, -1 failed.
    254  * Notes:
    255  *       Called in INTERRUPT CONTEXT
    256  */
    257 {
    258     loopback2_test_t     *lw = (loopback2_test_t *)cookie;
    259     int                  num_pkts = lw->tx_ppt;
    260     bcm_pkt_t            *local_info;
    261 
    262     if (lw->expect_pkts) {
    263         /* Queue the packet */
    264         /* Copy pkt into array at location rx_pkt_cnt */
    265         local_info = LB2_RX_CUR_PKT(lw);
    266         sal_memcpy(local_info, info, sizeof(bcm_pkt_t));
    267         /* Fix internal packet pointer */
    268         local_info->pkt_data = &local_info->_pkt_data;
    269         if (++lw->rx_pkt_cnt >= num_pkts) {
    270             lw->expect_pkts = FALSE;
    271             /* Wake up thread to check things out */
    272             if (!lw->sema_woke) {
    273                 lw->sema_woke = TRUE;
    274                 if (sal_sem_give(lw->sema)) {
    275                     cli_out("Warning: LB RX done give failed\n");
    276                 }
    277             }
    278         }
    279         return BCM_RX_HANDLED_OWNED;
    280     } 
    281 
    282     /* Not accepting packets; let rx discard */
    283     return BCM_RX_NOT_HANDLED;
    284 
    285 }
    286 
    287 int
    288 lbu_port_monitor_task(int unit, bcm_rx_cb_f callback, void *cookie)
    289 {
    290     int rv = BCM_E_NONE;
    291     bcm_rx_cfg_t rx_cfg;
    292 
    293 #ifdef INCLUDE_RCPU
    294     
    295     if ((soc_property_get_str(unit, spn_RCPU_PORT) == NULL) && (BCM_RX_INIT_DONE(unit))) {
    296         cli_out("lbu monitor:  RX already running (u=%d)\n", unit);
    297         return BCM_E_INIT;
    298     }
    299 #else
    300     if (BCM_RX_INIT_DONE(unit)) {
    301         cli_out("lbu monitor:  RX already running (u=%d)\n", unit);
    302         return BCM_E_INIT;
    303     }
    304 #endif /* INCLUDE_RCPU */
    305 
    306     /* Get current configuration */
    307     bcm_rx_cfg_init(unit);   /* Re-init in case in bad state */
    308     bcm_rx_cfg_get(unit, &rx_cfg);
    309     rx_cfg.global_pps = BCM_RX_RATE_NOLIMIT;
    310     rx_cfg.chan_cfg[BCM_RX_CHAN_DFLT].rate_pps = BCM_RX_RATE_NOLIMIT;
    311     rv = bcm_rx_start(unit, &rx_cfg);
    312 #ifdef INCLUDE_RCPU
    313 #else
    314     if (BCM_E_NONE != rv) {
    315         cli_out("lbu_port_monitor_task:"
    316                 "rx_start failed: %s\n", bcm_errmsg(rv));
    317         return rv;
    318     }
    319 #endif /* INCLUDE_RCPU */
    320 
    321     /* Allow BCM Rx thread to prepare DMA buffers */
    322     sal_usleep(500000);
    323     
    324     rv = bcm_rx_register(unit, "loopback test", callback,
    325                          BCM_RX_PRIO_MAX, cookie,
    326                          BCM_RCO_F_ALL_COS);
    327     if (BCM_E_NONE != rv) {
    328         cli_out("lbu_port_monitor_task:"
    329                 "rx_register failed: %s\n", bcm_errmsg(rv));
    330         return rv;
    331     }
    332 
    333     return BCM_E_NONE;
    334 }
    335 
    336 STATIC int
    337 lbu_packet_compare(loopback2_test_t *lw, bcm_pkt_t *tx_info, 
    338                    bcm_pkt_t *rx_info)
    339 {
    340     loopback2_testdata_t        *lp = lw->cur_params;
    341     int         unit = lw->unit;
    342     int         i;
    343     int         rv = 0;
    344     int         tx_compare_len, crc_length = 0;
    345     uint8       *tx_data, *rx_data;
    346 
    347     tx_data = BCM_PKT_IEEE(tx_info);
    348     rx_data = BCM_PKT_IEEE(rx_info);
    349 
    350 #ifdef BCM_XGS_SUPPORT
    351     /* Inspect HIGIG/XGS header if received from HG port */
    352     if (SOC_IS_XGS12_FABRIC(unit)) {
    353         soc_higig_hdr_t *tx_hdr = (soc_higig_hdr_t*)tx_info->_higig;
    354         soc_higig_hdr_t *rx_hdr = (soc_higig_hdr_t*)rx_info->_higig;
    355 
    356         if (soc_higig_field_get(unit, rx_hdr, HG_start) != 
    357             SOC_HIGIG_START) {
    358             cli_out("ERROR: HIGIG START not detected (rx=%x)\n",
    359                     soc_higig_field_get(unit, rx_hdr, HG_start));
    360             rv = -1;
    361         }
    362 
    363         if (soc_higig_field_get(unit, rx_hdr, HG_hgi) != 
    364             SOC_HIGIG_HGI) {
    365             cli_out("ERROR: HIGIG identifier not detected (rx=%x)\n",
    366                     soc_higig_field_get(unit, rx_hdr, HG_hgi));
    367             rv = -1;
    368         }
    369 
    370         if (soc_higig_field_get(unit, tx_hdr, HG_vlan_pri) != 
    371             soc_higig_field_get(unit, rx_hdr, HG_vlan_pri)) {
    372             cli_out("ERROR: HIGIG VLAN priority miscompare (tx=%x,rx=%x)\n",
    373                     soc_higig_field_get(unit, tx_hdr, HG_vlan_pri), 
    374                     soc_higig_field_get(unit, rx_hdr, HG_vlan_pri));
    375             rv = -1;
    376         }
    377 
    378         if (soc_higig_field_get(unit, tx_hdr, HG_vlan_cfi) != 
    379             soc_higig_field_get(unit, rx_hdr, HG_vlan_cfi)) {
    380             cli_out("ERROR: HIGIG VLAN cfi miscompare (tx=%x,rx=%x)\n",
    381                     soc_higig_field_get(unit, tx_hdr, HG_vlan_cfi), 
    382                     soc_higig_field_get(unit, rx_hdr, HG_vlan_cfi));
    383             rv = -1;
    384         }
    385 
    386         if (soc_higig_field_get(unit, tx_hdr, HG_vlan_id) != 
    387             soc_higig_field_get(unit, rx_hdr, HG_vlan_id)) {
    388             cli_out("ERROR: HIGIG VLAN id miscompare (tx=%x,rx=%x)\n",
    389                     soc_higig_field_get(unit, tx_hdr, HG_vlan_id), 
    390                     soc_higig_field_get(unit, rx_hdr, HG_vlan_id));
    391             rv = -1;
    392         }
    393 
    394         if (soc_higig_field_get(unit, tx_hdr, HG_opcode) != 
    395             soc_higig_field_get(unit, rx_hdr, HG_opcode)) {
    396             cli_out("ERROR: HIGIG opcode miscompare (tx=%x,rx=%x)\n",
    397                     soc_higig_field_get(unit, tx_hdr, HG_opcode), 
    398                     soc_higig_field_get(unit, rx_hdr, HG_opcode));
    399             rv = -1;
    400         }
    401 
    402         /* What about remapping the COS? */
    403         if (soc_higig_field_get(unit, tx_hdr, HG_cos) != 
    404             soc_higig_field_get(unit, rx_hdr, HG_cos)) {
    405             cli_out("ERROR: HIGIG cos miscompare (tx=%x,rx=%x)\n",
    406                     soc_higig_field_get(unit, tx_hdr, HG_cos), 
    407                     soc_higig_field_get(unit, rx_hdr, HG_cos));
    408             rv = -1;
    409         }
    410 
    411         
    412     }
    413 #endif /* BCM_XGS_SUPPORT */
    414     
    415     /* Check source and destination MAC address */
    416 
    417     if (ENET_CMP_MACADDR(BCM_PKT_DMAC(tx_info), BCM_PKT_DMAC(rx_info)) ||
    418         ENET_CMP_MACADDR(BCM_PKT_DMAC(tx_info) + 6, 
    419                          BCM_PKT_DMAC(rx_info) + 6)) {
    420         char    src_mac[SAL_MACADDR_STR_LEN],
    421                 dst_mac[SAL_MACADDR_STR_LEN],
    422                 exp_src_mac[SAL_MACADDR_STR_LEN],
    423                 exp_dst_mac[SAL_MACADDR_STR_LEN];
    424         format_macaddr(exp_src_mac, BCM_PKT_DMAC(tx_info) + 6);
    425         format_macaddr(exp_dst_mac, BCM_PKT_DMAC(tx_info));
    426         format_macaddr(src_mac, BCM_PKT_DMAC(rx_info) + 6);
    427         format_macaddr(dst_mac, BCM_PKT_DMAC(rx_info));
    428         cli_out("ERROR: MAC address miscompare:\n"
    429                 "\tExpected src=%s dst=%s\n\tReceived src=%s dst=%s\n",
    430                 exp_src_mac, exp_dst_mac, src_mac, dst_mac);
    431 
    432         rv = -1;
    433     }
    434 
    435 #ifdef BCM_ESW_SUPPORT
    436     crc_length = ((lp->crc_mode == LB2_CRC_MODE_CPU_APPEND) ? 4 : 0);
    437 #endif /* BCM_ESW_SUPPORT */
    438 
    439     /* Verify lengths, and if they match, verify payload */
    440     tx_compare_len = tx_info->_pkt_data.len; 
    441     if (lp->crc_mode != LB2_CRC_MODE_CPU_APPEND) {
    442         tx_compare_len -= 4;
    443     }
    444 
    445     if (rx_info->pkt_len != (tx_info->_pkt_data.len + crc_length)) {
    446 #ifdef BCM_ESW_SUPPORT
    447         if (SOC_IS_ESW(unit)) {
    448             soc_pci_analyzer_trigger(unit);
    449         }
    450 #endif /* BCM_ESW_SUPPORT */
    451         cli_out("ERROR: Length miscompare: TX(%d) RX(%d)\n",
    452                 tx_info->_pkt_data.len, rx_info->pkt_len);
    453         rv = -1;
    454     } else if ((i = packet_compare(BCM_PKT_VLAN_PTR(rx_info),
    455                                    BCM_PKT_VLAN_PTR(tx_info),
    456                                    4)) >= 0) {
    457         cli_out("ERROR: VLAN tag miscompare: offset 0x%x\n", i + 12);
    458         rv = -1;
    459     } else if ((i = packet_compare(rx_data + 16,
    460                                    tx_data + 16,
    461                                    4)) >= 0) {
    462         cli_out("ERROR: Sequence # miscompare: offset 0x%x\n"
    463                 "\tExpected 0x%08x, Received 0x%08x\n", 16,
    464                 packet_load(tx_data + 16, 4),
    465                 packet_load(rx_data + 16, 4));
    466         rv = -1;
    467     } else if ((i = packet_compare(rx_data + 20,
    468                                    tx_data + 20,
    469                                    tx_compare_len - 20)) >= 0) {
    470         cli_out("ERROR: Payload miscompare: offset 0x%x\n", i + 20);
    471         rv = -1;
    472     }
    473 
    474     if (lp->check_crc) {
    475         uint32 calc_crc = 0, rx_crc;
    476         if (lp->vlan) {
    477             if (rx_info->pkt_len > 0) {
    478                 /* Skip Vlan Tag for CRC calculation */
    479                 uint8 *rx_data_crc;
    480                 rx_data_crc = sal_alloc(rx_info->pkt_len, "rx_data_crc");
    481                 sal_memset(rx_data_crc, 0, rx_info->pkt_len);
    482                 sal_memcpy(rx_data_crc, rx_data, 12);
    483                 sal_memcpy(rx_data_crc + 12, rx_data + 16,
    484                            rx_info->pkt_len - 16);
    485                 calc_crc = ~_shr_crc32(~0, rx_data_crc, rx_info->pkt_len - 8);
    486                 sal_free(rx_data_crc);
    487             }
    488         } else {
    489             calc_crc = ~_shr_crc32(~0, rx_data, rx_info->pkt_len - 4);
    490         }
    491         rx_crc = packet_load(rx_data + rx_info->pkt_len - 4, 4);
    492 
    493         if (calc_crc != rx_crc) {
    494             cli_out("ERROR: CRC miscompare: calc=0x%08x rx=0x%08x\n",
    495                     calc_crc, rx_crc);
    496             
    497             rv = -1;
    498         }
    499     }
    500 
    501     if (rv) {
    502         /* On error, dump tx/rx packets, and call test_error once */
    503 
    504         cli_out("TX packet: len=%d\n", tx_info->_pkt_data.len);
    505 #ifdef BCM_ESW_SUPPORT
    506         soc_dma_dump_pkt(unit, "  ", tx_data, tx_info->_pkt_data.len, TRUE);
    507         cli_out("RX packet: len=%d\n", rx_info->pkt_len);
    508         soc_dma_dump_pkt(unit, "  ", rx_data, rx_info->pkt_len, TRUE);
    509 #endif
    510         test_error(unit,
    511                    "ERROR Found when verifying received packet\n");
    512     }
    513 
    514     return(rv);
    515 }
    516 
    517 STATIC int
    518 lbu_snake_pkt_match(loopback2_test_t *lw, bcm_pkt_t *rx_info, int *match_idx)
    519 /*
    520  * Function:    lb_isnake_pkt_match
    521  * Purpose:     Search for tx packet matching rx packet.
    522  * Parameters:  lw - pointer to lb work.
    523  *              rx_info - pointer to rx packet  info
    524  *              match_idx - return index for tx matching packet
    525  * Returns:     0 for match, -1 for no match, -2 for duplicate match.
    526  */
    527 {
    528     int             tx_idx;
    529     bcm_pkt_t       *compare_info;
    530 
    531     for (tx_idx = 0; tx_idx < lw->tx_ppt; tx_idx++) {
    532 
    533         compare_info = lw->tx_pkts[tx_idx];
    534 
    535         if (ENET_CMP_MACADDR(BCM_PKT_DMAC(compare_info), 
    536                              BCM_PKT_DMAC(rx_info)) ||
    537             ENET_CMP_MACADDR(BCM_PKT_DMAC(compare_info) + 6, 
    538                              BCM_PKT_DMAC(rx_info) + 6)) {
    539             /* Wrong macs */
    540             continue;
    541         }
    542 
    543         if (BCM_PKT_DMAC(compare_info)[LB2_ID_POS] != 
    544             BCM_PKT_DMAC(rx_info)[LB2_ID_POS]) {
    545             /* Wrong SW identifying tag */
    546             continue;
    547         }
    548 
    549         *match_idx = tx_idx;
    550 
    551         if (lw->tx_pkt_match[tx_idx]) {
    552             /* Already matched this packet, duplicate arrival */
    553             return -2;
    554         }
    555 
    556         lw->tx_pkt_match[tx_idx]  = TRUE;
    557 
    558         return 0;
    559     }
    560 
    561     return -1;
    562 }
    563 
    564 int
    565 lbu_snake_analysis(loopback2_test_t *lw)
    566 {
    567     int             unit = lw->unit;
    568     int             ix, ev = 0;
    569     bcm_pkt_t       *tx_info, *rx_info;
    570     int             match_idx;
    571 
    572     for (ix = 0; ix < lw->rx_pkt_cnt; ix++) {
    573         rx_info = LB2_RX_PKT(lw, ix);
    574         match_idx = -1;
    575         if ((ev = lbu_snake_pkt_match(lw, rx_info, &match_idx)) < 0) {
    576             if (match_idx >=0) {
    577                 tx_info = lw->tx_pkts[match_idx];
    578                 cli_out("TX packet: len=%d\n", tx_info->_pkt_data.len);
    579                 
    580 #ifdef BCM_ESW_SUPPORT                
    581                 soc_dma_dump_pkt(unit, "  ", BCM_PKT_IEEE(tx_info), 
    582                                  tx_info->_pkt_data.len, TRUE);
    583 #endif
    584             } else {
    585                 cli_out("No TX match\n");
    586             }
    587             
    588             if (ev == -2) {
    589                 test_error(unit, 
    590                            "Duplicate packet from port %s\n",
    591                            SOC_PORT_NAME(unit, rx_info->rx_port));
    592             } else {
    593                 test_error(unit, 
    594                            "Unrecognized packet from port %s\n",
    595                            SOC_PORT_NAME(unit, rx_info->rx_port));
    596             }
    597           
    598             return -1;
    599         }
    600         
    601         tx_info = lw->tx_pkts[match_idx];
    602 
    603         if (lbu_packet_compare(lw, tx_info, rx_info) < 0) {
    604             return -1;
    605        }
    606     }
    607     return 0;
    608 }
    609 
    610 STATIC int
    611 lbu_set_l2_addr(int unit, bcm_port_t p, bcm_vlan_t vlan, 
    612                 bcm_l2_addr_t *l2_addr, sal_mac_addr_t mac_addr)
    613 /*
    614  * Function:    lbu_set_l2_addr
    615  * Purpose:     Set an L2 entry
    616  * Parameters:  unit - SOC unit #
    617  *              p - port to set address for.
    618  *              vlan - vlan tag to use in ARL entry.
    619  *              l2_addr - pointer to arl entry to use.
    620  * Returns:     0 - success, -1 failed.
    621  */
    622 {
    623     int rv;
    624 
    625     if ((rv = bcm_l2_addr_delete(unit, mac_addr, vlan)) < 0) {
    626         if (rv != BCM_E_NOT_FOUND) {
    627             cli_out("bcm_l2_addr_delete FAILED\n");
    628             return rv;
    629         } /* else, non-existent entry */
    630     }
    631 
    632     sal_memcpy(l2_addr->mac, mac_addr, sizeof(sal_mac_addr_t));
    633     l2_addr->vid = vlan;
    634     l2_addr->flags = BCM_L2_STATIC;
    635     l2_addr->port = p;
    636     return(bcm_l2_addr_add(unit, l2_addr));
    637 }
    638 
    639 int
    640 lbu_setup_arl_cmic(loopback2_test_t *lw)
    641 /*
    642  * Function:    lbu_setup_arl
    643  * Purpose:     Setup an ARL entry for the specified port
    644  * Parameters:  unit - unit #
    645  *              dst_port - port to which packet is sent
    646  * Returns:     0 - success
    647  *              -1 - failed.
    648  * Notes:       Only the destination port CBIT is returned, as only
    649  *              it is required for the test.
    650  */
    651 {
    652     loopback2_testdata_t *lp = lw->cur_params;
    653     int                  unit = lw->unit;
    654     int                  rv = 0;
    655     sal_mac_addr_t       cur_mac;
    656     bcm_l2_addr_t        *l2_addr = &lw->l2_addr_scratch;
    657     int                  pkt_cur;
    658 #ifdef BCM_TRIUMPH_SUPPORT
    659     int ext_index_max = -1;
    660 #endif /* BCM_TRIUMPH_SUPPORT */
    661 
    662     ENET_SET_MACADDR(cur_mac, lw->base_mac_dst);
    663     bcm_l2_addr_t_init(l2_addr, cur_mac, 0);
    664 
    665     /* Get the module ID for this unit */
    666     if (SOC_IS_XGS_SWITCH(unit)) {
    667         if ((rv = bcm_stk_my_modid_get(unit, &l2_addr->modid)) < 0) {
    668             test_error(unit,
    669                        "Modid retrieval failed: %s\n",
    670                        soc_errmsg(rv));
    671             return(-1);
    672         }
    673     }
    674 
    675 #ifdef BCM_TRIUMPH_SUPPORT
    676     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    677         ext_index_max = SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max;
    678         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = -1;
    679     }
    680 #endif /* BCM_TRIUMPH_SUPPORT */
    681     for (pkt_cur = 0; pkt_cur < lp->ppt_end; pkt_cur++) {
    682         rv |= lbu_set_l2_addr(unit, CMIC_PORT(unit), lp->vlan,
    683                               l2_addr, cur_mac);
    684         increment_macaddr(cur_mac, lp->mac_dst_inc);
    685     }
    686 #ifdef BCM_TRIUMPH_SUPPORT
    687     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    688         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = ext_index_max;
    689     }
    690 #endif /* BCM_TRIUMPH_SUPPORT */
    691 
    692     if (rv) {
    693         test_error(unit,
    694                    "Failed to set up L2 address: port %s\n",
    695                    SOC_PORT_NAME(unit, CMIC_PORT(unit)));
    696         return(-1);
    697     } else if (l2_addr->port != CMIC_PORT(unit)) {
    698         test_error(unit,
    699                    "Port %s: invalid destination arl port: %s\n",
    700                    SOC_PORT_NAME(unit, CMIC_PORT(unit)),
    701                    SOC_PORT_NAME(unit, l2_addr->port));
    702         return(-1);
    703     }
    704 
    705     return 0;
    706 }
    707 
    708 #ifdef BCM_HERCULES_SUPPORT 
    709 STATIC int
    710 lbu_connect_herc_ports(int unit, lb2s_port_connect_t *pc_info,
    711                        int connect)
    712 {
    713     pbmp_t             uc;
    714     uint32             ucdata;
    715     int                blk;
    716 
    717     /* Configure UC table for packet forwarding */
    718     SOC_PBMP_CLEAR(uc);
    719     blk = SOC_PORT_BLOCK(unit, pc_info->this_port);
    720     if (connect) {
    721         SOC_PBMP_PORT_ADD(uc, pc_info->to_port);
    722         ucdata = SOC_PBMP_WORD_GET(uc, 0);
    723         SOC_IF_ERROR_RETURN(soc_mem_write(unit, MEM_UCm, blk,
    724                                           pc_info->src_modid, &ucdata));
    725     } else {
    726         ucdata = SOC_PBMP_WORD_GET(uc, 0);
    727         SOC_IF_ERROR_RETURN(soc_mem_write(unit, MEM_UCm, blk,
    728                                           pc_info->src_modid, &ucdata));
    729     }
    730     return 0;
    731 }
    732 #endif
    733 
    734 STATIC int
    735 lbu_connect_ether_ports(int unit, lb2s_port_connect_t *pc_info,
    736                         int connect)
    737 {
    738     int rv;
    739 #ifdef BCM_TRIUMPH_SUPPORT
    740     int ext_index_max = -1;
    741 #endif /* BCM_TRIUMPH_SUPPORT */
    742 
    743     if (MAC_IS_MCAST(pc_info->dst_mac)) {
    744         if (connect) {
    745             bcm_mcast_addr_t   l2mc_addr;
    746             sal_memset(&l2mc_addr, 0, sizeof (bcm_mcast_addr_t));
    747             ENET_SET_MACADDR(l2mc_addr.mac, pc_info->dst_mac);
    748             l2mc_addr.vid = pc_info->added_vlan;
    749             SOC_PBMP_CLEAR(l2mc_addr.pbmp);
    750             SOC_PBMP_PORT_ADD(l2mc_addr.pbmp, pc_info->this_port);
    751             SOC_PBMP_PORT_ADD(l2mc_addr.pbmp, pc_info->to_port);
    752             SOC_PBMP_ASSIGN(l2mc_addr.ubmp, l2mc_addr.pbmp);
    753             BCM_IF_ERROR_RETURN(bcm_mcast_addr_add(unit, &l2mc_addr));
    754         } else {
    755             BCM_IF_ERROR_RETURN(bcm_mcast_addr_remove(unit, pc_info->dst_mac, 
    756                                                       pc_info->added_vlan));
    757         }
    758     } else {
    759         if (connect) {
    760             bcm_l2_addr_t   l2_addr;
    761             bcm_l2_addr_t_init(&l2_addr,
    762                                pc_info->dst_mac, pc_info->added_vlan);
    763             if (NUM_MODID(unit) == 3 &&
    764                 pc_info->to_port % (SOC_PORT_ADDR_MAX(unit) + 1) > 63) {
    765                 l2_addr.port =
    766                     (pc_info->to_port % (SOC_PORT_ADDR_MAX(unit) + 1)) - 64;
    767                 l2_addr.modid = pc_info->dst_modid + 2;
    768             } else if (NUM_MODID(unit) >= 2 &&
    769                        pc_info->to_port % (SOC_PORT_ADDR_MAX(unit) + 1) > 31) {
    770                 l2_addr.port =
    771                     (pc_info->to_port % (SOC_PORT_ADDR_MAX(unit) + 1)) - 32; 
    772                 l2_addr.modid = pc_info->dst_modid + 1;
    773             } else {
    774                 l2_addr.port =
    775                     pc_info->to_port % (SOC_PORT_ADDR_MAX(unit) + 1);
    776                 l2_addr.modid = pc_info->dst_modid;
    777             }
    778 #ifdef BCM_TRIUMPH_SUPPORT
    779             if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    780                 ext_index_max =
    781                     SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max;
    782                 SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = -1;
    783             }
    784 #endif /* BCM_TRIUMPH_SUPPORT */
    785             rv = bcm_l2_addr_add(unit, &l2_addr);
    786 #ifdef BCM_TRIUMPH_SUPPORT
    787             if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    788                 SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max =
    789                     ext_index_max;
    790             }
    791 #endif /* BCM_TRIUMPH_SUPPORT */
    792             if (BCM_FAILURE(rv)) {
    793                 return rv;
    794             }
    795 
    796             if ((pc_info->this_port == pc_info->to_port) &&
    797                 (pc_info->dst_modid == pc_info->src_modid)) {
    798                 BCM_IF_ERROR_NOT_UNAVAIL_RETURN(
    799                     bcm_port_control_set(unit, pc_info->this_port, 
    800                                          bcmPortControlBridge, 1));
    801             }
    802         } else {
    803 #ifdef BCM_TRIUMPH_SUPPORT
    804             if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    805                 ext_index_max =
    806                     SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max;
    807                 SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = -1;
    808             }
    809 #endif /* BCM_TRIUMPH_SUPPORT */
    810             rv = bcm_l2_addr_delete(unit, pc_info->dst_mac,
    811                                     pc_info->added_vlan);
    812 #ifdef BCM_TRIUMPH_SUPPORT
    813             if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    814                 SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max =
    815                     ext_index_max;
    816             }
    817 #endif /* BCM_TRIUMPH_SUPPORT */
    818             if (BCM_FAILURE(rv)) {
    819                 if (rv != BCM_E_NOT_FOUND) {
    820                     return rv;
    821                 } /* else, non-existent entry */
    822             }
    823 
    824             /* Disable Port bridging if src and dest ports are same */
    825             if ((pc_info->this_port == pc_info->to_port) &&
    826                 (pc_info->dst_modid == pc_info->src_modid)) {
    827                 BCM_IF_ERROR_NOT_UNAVAIL_RETURN(
    828                     bcm_port_control_set(unit, pc_info->this_port, 
    829                                          bcmPortControlBridge, 0));
    830             }
    831         }
    832      }
    833     return 0;
    834 }
    835 
    836 STATIC int
    837 lbu_set_modport(int unit, bcm_port_t src_port, int dst_port, int modid)
    838 {
    839     /*      
    840      * A ghastly construct.  Select correct modid field, 
    841      * and modify dest port into field.
    842      */
    843 
    844 #ifdef BCM_FIREBOLT_SUPPORT
    845     if (SOC_IS_FB_FX_HX(unit) || SOC_IS_TR_VL(unit)) {
    846         return 0;
    847     }
    848     if (SOC_IS_HBX(unit)) {
    849         int rv;
    850         modport_map_entry_t uc;
    851         int idx = (src_port * (SOC_MODID_MAX(unit) + 1)) + modid;
    852         soc_mem_lock(unit, MODPORT_MAPm);
    853         rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, idx, &uc);
    854         if (SOC_SUCCESS(rv)) {
    855             /* Use MODPORT_MAP for forwarding packets for both HG and XE ports.
    856              */
    857             soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf,
    858                                          1 << dst_port);
    859             rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, idx, &uc);
    860         }
    861         soc_mem_unlock(unit, MODPORT_MAPm);
    862         return rv;
    863     }
    864 #endif /* BCM_FIREBOLT_SUPPORT */
    865     return 0;
    866 }
    867 
    868 STATIC int
    869 lbu_connect_ether_to_hg_port(int unit, lb2s_port_connect_t *pc_info, 
    870                              int connect)
    871 {
    872     bcm_l2_addr_t   l2_addr;
    873 
    874     if (connect) {
    875         bcm_l2_addr_t_init(&l2_addr, pc_info->dst_mac, pc_info->added_vlan);
    876         l2_addr.modid = pc_info->dst_modid;
    877         l2_addr.port = pc_info->to_port % (SOC_PORT_ADDR_MAX(unit) + 1);
    878         BCM_IF_ERROR_RETURN(bcm_l2_addr_add(unit, &l2_addr));
    879         SOC_IF_ERROR_RETURN(lbu_set_modport(unit, pc_info->this_port,
    880                                     pc_info->to_port, pc_info->dst_modid));
    881     } else {
    882         int rv;
    883 
    884         if ((rv = bcm_l2_addr_delete(unit, pc_info->dst_mac,
    885                                      pc_info->added_vlan)) < 0) {
    886             if (rv != BCM_E_NOT_FOUND) {
    887                 return rv;
    888             } /* else, non-existent entry */
    889         }
    890         
    891     }
    892     return 0;
    893 }
    894 
    895 STATIC int
    896 lbu_connect_hg_to_ether_port(int unit, lb2s_port_connect_t *pc_info, 
    897                              int connect)
    898 {
    899     if (connect) {
    900         SOC_IF_ERROR_RETURN(lbu_set_modport(unit, pc_info->this_port,
    901                                     pc_info->to_port, pc_info->src_modid));
    902     } else {
    903         
    904     }
    905     return 0;
    906 }
    907 
    908 int
    909 lbu_connect_ports(int unit, lb2s_port_connect_t *pc_info,
    910                   int connect)
    911 {
    912     int rv;
    913 
    914     if (!pc_info->valid_info) {
    915         /* Nothing to do */
    916         return 0;
    917     }
    918 
    919     if (connect) {
    920         LOG_INFO(BSL_LS_APPL_TESTS,
    921                  (BSL_META_U(unit,
    922                              "Port connection:\n"
    923                              "  RX(mod,port)=%d,%d, TX(mod,port)=%d,%d, VLAN=0x%03x,\n"
    924                              "  SA=%02x:%02x:%02x:%02x:%02x:%02x, "
    925                              "DA=%02x:%02x:%02x:%02x:%02x:%02x\n"),
    926                   pc_info->src_modid, pc_info->this_port,
    927                   pc_info->dst_modid, pc_info->to_port,
    928                   pc_info->added_vlan,
    929                   pc_info->src_mac[0], pc_info->src_mac[1], pc_info->src_mac[2],
    930                   pc_info->src_mac[3], pc_info->src_mac[4], pc_info->src_mac[5],
    931                   pc_info->dst_mac[0], pc_info->dst_mac[1], pc_info->dst_mac[2],
    932                   pc_info->dst_mac[3], pc_info->dst_mac[4], pc_info->dst_mac[5]));
    933     }
    934     /* Sort out things into the proper subsettings */
    935 #ifdef BCM_HERCULES_SUPPORT
    936     if (SOC_IS_HERCULES(unit)) {
    937         rv = lbu_connect_herc_ports(unit, pc_info, connect);
    938     } else 
    939 #endif
    940     {
    941         if (IS_E_PORT(unit, pc_info->this_port)) {
    942             if (IS_E_PORT(unit, pc_info->to_port)) {
    943                 rv = lbu_connect_ether_ports(unit, pc_info, connect);
    944             } else if (IS_ST_PORT(unit, pc_info->to_port)) {
    945                 rv = lbu_connect_ether_to_hg_port(unit, pc_info, connect);
    946             } else { /* Should be CMIC */
    947                 rv = lbu_connect_ether_ports(unit, pc_info, connect);
    948             }
    949         } else {
    950             if (IS_ST_PORT(unit, pc_info->to_port)) {
    951                 if (SOC_IS_HBX(unit)) {
    952                     rv = lbu_set_modport(unit, pc_info->this_port,
    953                                          pc_info->to_port, pc_info->dst_modid);
    954                 } else {
    955                     /* Uhhh, now what? Two HG ports */
    956                     /* Not supported for FB/ER */
    957                     LOG_INFO(BSL_LS_APPL_TESTS,
    958                              (BSL_META_U(unit,
    959                                          "lbu_connect_ports: Two HG ports rv = %d\n"),
    960                               BCM_E_UNAVAIL));
    961                     return BCM_E_UNAVAIL;
    962                 }
    963             } else { /* Ether or CMIC */
    964                 rv = lbu_connect_hg_to_ether_port(unit, pc_info, connect);
    965             } 
    966         }
    967     }
    968     LOG_INFO(BSL_LS_APPL_TESTS,
    969              (BSL_META_U(unit,
    970                          "lbu_connect_ports: rv = %d\n"), rv));
    971     return rv;
    972 }
    973 
    974 
    975 void
    976 lbu_cleanup_arl(loopback2_test_t *lw)
    977 {
    978     loopback2_testdata_t *lp;
    979     int                  unit;
    980     sal_mac_addr_t       cur_mac;
    981     int                  pkt_cur;
    982 #ifdef BCM_TRIUMPH_SUPPORT
    983     int ext_index_max = -1;
    984 #endif /* BCM_TRIUMPH_SUPPORT */
    985 
    986     if (lw == NULL) {
    987         return;
    988     }
    989     unit = lw->unit;
    990     lp = lw->cur_params;
    991     if (lp == NULL) {
    992         return;
    993     }
    994 
    995 #ifdef BCM_TRIUMPH_SUPPORT
    996     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
    997         ext_index_max = SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max;
    998         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = -1;
    999     }
   1000 #endif /* BCM_TRIUMPH_SUPPORT */
   1001 
   1002     /* Source MAC flush */
   1003     ENET_SET_MACADDR(cur_mac, lw->base_mac_src);
   1004     for (pkt_cur = 0; pkt_cur < lp->ppt_end; pkt_cur++) {
   1005         (void)bcm_l2_addr_delete(unit, cur_mac, lp->vlan);
   1006         increment_macaddr(cur_mac, lp->mac_src_inc);
   1007     }
   1008 
   1009     /* Destination MAC flush */
   1010     ENET_SET_MACADDR(cur_mac, lw->base_mac_dst);
   1011     for (pkt_cur = 0; pkt_cur < lp->ppt_end; pkt_cur++) {
   1012         (void)bcm_l2_addr_delete(unit, cur_mac, lp->vlan);
   1013         increment_macaddr(cur_mac, lp->mac_dst_inc);
   1014     }
   1015 
   1016 #ifdef BCM_TRIUMPH_SUPPORT
   1017     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
   1018         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = ext_index_max;
   1019     }
   1020 #endif /* BCM_TRIUMPH_SUPPORT */
   1021 }
   1022 
   1023 STATIC int
   1024 lbu_save_port(loopback2_test_t *lw, loopback2_testdata_t *lp)
   1025 {
   1026     int         rv;
   1027     bcm_port_t  port;
   1028     pbmp_t      save_ports;
   1029     int         unit = lw->unit;
   1030 
   1031     if (SOC_IS_XGS12_FABRIC(unit)) {
   1032         BCM_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(unit));
   1033     } else {
   1034         BCM_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(unit));
   1035         BCM_PBMP_AND(save_ports, lp->pbm);
   1036     }
   1037 
   1038     PBMP_ITER(save_ports, port) {
   1039         if ((rv = bcm_port_info_save(unit, port,
   1040                                     &lw->save_port[port])) < 0) {
   1041             test_error(unit,
   1042                        "Port %s: Could not get port info: %s\n",
   1043                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   1044             return(-1);
   1045         }
   1046 #ifdef BCM_TOMAHAWK3_SUPPORT
   1047         /* Save original fec, phy config and link training info. Note pm8x50
   1048          * (cd ports) need this information
   1049          */
   1050         if ((SOC_IS_TOMAHAWK3(unit)) && (IS_CD_PORT(unit, port))) {
   1051             rv = bcm_port_resource_speed_get(unit, port,
   1052                                              &lw->port_info[port]);
   1053             if (rv < 0) {
   1054                 test_error(unit,
   1055                            "Port %s: bcm_port_resource_speed_get failed:"
   1056                            " %s\n", SOC_PORT_NAME(unit, port),
   1057                            bcm_errmsg(rv));
   1058                 return(-1);
   1059             }
   1060         }
   1061 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1062     }
   1063 
   1064     
   1065     if (bcm_rx_cfg_get(unit, NULL) == BCM_E_NONE) {
   1066         test_error(unit, "BCM_RX is currently not active; cannot run test\n");
   1067         return(-1);
   1068     }
   1069 
   1070 #ifdef BCM_ESW_SUPPORT
   1071     if (SOC_IS_XGS_SWITCH(unit)) {
   1072         int     not_my_mod;
   1073         /* Save current source port/module and change to != lp->d_mod */
   1074 
   1075         lbu_saved_srcmod[unit] = SOC_DEFAULT_DMA_SRCMOD_GET(unit);
   1076         lbu_saved_srcport[unit] = SOC_DEFAULT_DMA_SRCPORT_GET(unit);
   1077         not_my_mod = (lp->d_mod == 0);
   1078         SOC_DEFAULT_DMA_SRCMOD_SET(unit, not_my_mod);
   1079         SOC_DEFAULT_DMA_SRCPORT_SET(unit, CMIC_PORT(unit));
   1080 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1081         if (SOC_IS_XGS3_SWITCH(unit)) {
   1082             /*
   1083              * Should save(Not yet done here) ICONTROL_OPCODE_BITMAP before
   1084              * the test and restore it after test is done
   1085              * Redirect all packets with CPU control opcode
   1086              * from HG ports to CPU.
   1087              * Replace with API. 
   1088              */
   1089             int pbm_len;
   1090             uint32 cpu_pbm;
   1091             if (SOC_MEM_IS_VALID(unit, ICONTROL_OPCODE_BITMAPm)) {
   1092                 cpu_pbm = 0; /* init it, some compiler has false warning */
   1093             } else if (SOC_IS_TR_VL(unit) && !SOC_IS_TRIUMPH2(unit) 
   1094                 && !SOC_IS_APOLLO(unit) && !SOC_IS_VALKYRIE2(unit)) {
   1095                 SOC_IF_ERROR_RETURN
   1096                     (soc_xgs3_port_to_higig_bitmap(unit, CMIC_PORT(unit),
   1097                                                     &cpu_pbm));
   1098             } else if (CMIC_PORT(unit)) {
   1099                 pbm_len = soc_reg_field_length(unit, ICONTROL_OPCODE_BITMAPr,
   1100                                                BITMAPf);
   1101 		/* Bad shift complaint by Coverity */
   1102                 cpu_pbm = pbm_len > 0? 1 << (pbm_len - 1): 0;
   1103             } else {
   1104                 cpu_pbm = 1;
   1105             }
   1106             PBMP_ST_ITER(unit, port) {
   1107                 if (SOC_MEM_IS_VALID(unit, ICONTROL_OPCODE_BITMAPm)) {
   1108                     icontrol_opcode_bitmap_entry_t entry;
   1109                     sal_memset(&entry, 0, sizeof(entry));
   1110                     soc_mem_pbmp_field_set(unit, ICONTROL_OPCODE_BITMAPm,
   1111                                            &entry, BITMAPf, &PBMP_CMIC(unit));
   1112                     rv = soc_mem_write(unit, ICONTROL_OPCODE_BITMAPm,
   1113                                        MEM_BLOCK_ANY, port, &entry);
   1114                 } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
   1115                     SOC_IS_VALKYRIE2(unit)) {
   1116                     uint64 cpu_pbm_64;
   1117                     COMPILER_64_ZERO(cpu_pbm_64);
   1118                     COMPILER_64_SET(cpu_pbm_64, 0, cpu_pbm);
   1119                     SOC_IF_ERROR_RETURN
   1120                         (WRITE_ICONTROL_OPCODE_BITMAP_64r(unit, port,
   1121                                                           cpu_pbm_64));
   1122                 } else if (SOC_REG_IS_VALID(unit, ICONTROL_OPCODE_BITMAP_LOr) &&
   1123                            SOC_REG_IS_VALID(unit, ICONTROL_OPCODE_BITMAP_HIr)) {
   1124 
   1125                     uint64      fval64, rval64;
   1126                     uint32      t_port;
   1127                     pbmp_t      curr_pbmp;
   1128                     soc_reg_t   reg;
   1129 
   1130                     BCM_PBMP_CLEAR(curr_pbmp);
   1131                     COMPILER_64_ZERO(fval64);
   1132 
   1133                     /* Set HG ingress CPU Opcode map to the CPU */
   1134                     if (CMIC_PORT(unit) < 64) {
   1135                         reg = ICONTROL_OPCODE_BITMAP_LOr;
   1136                         t_port = CMIC_PORT(unit);
   1137                     } else {
   1138                         reg = ICONTROL_OPCODE_BITMAP_HIr;
   1139                         t_port = CMIC_PORT(unit) - 64;
   1140                     }
   1141 
   1142                     SOC_PBMP_PORT_ADD(curr_pbmp, t_port);
   1143 
   1144                     SOC_IF_ERROR_RETURN(
   1145                             soc_reg_get(unit, reg, port, 0, &rval64));
   1146                     COMPILER_64_SET(fval64,
   1147                                     SOC_PBMP_WORD_GET(curr_pbmp, 1),
   1148                                     SOC_PBMP_WORD_GET(curr_pbmp, 0));
   1149 
   1150                     soc_reg64_field_set(unit, 
   1151                             reg, &rval64, BITMAPf, fval64);
   1152                     SOC_IF_ERROR_RETURN(
   1153                             soc_reg_set(unit, reg, port, 0, rval64));
   1154                 } else {
   1155                     SOC_IF_ERROR_RETURN
   1156                         (WRITE_ICONTROL_OPCODE_BITMAPr(unit, port, cpu_pbm));
   1157                 }
   1158             }
   1159         }
   1160 #endif
   1161     } 
   1162 #ifdef BCM_XGS12_FABRIC_SUPPORT
   1163     else if (SOC_IS_XGS12_FABRIC(unit)) {
   1164         uint32      ucdata;
   1165         pbmp_t      uc;
   1166         int         blk;
   1167         
   1168         SOC_PBMP_CLEAR(uc);
   1169         SOC_PBMP_PORT_ADD(uc, CMIC_PORT(unit));
   1170         ucdata = SOC_PBMP_WORD_GET(uc, 0);
   1171         PBMP_ITER(save_ports, port) {
   1172             blk = SOC_PORT_BLOCK(unit, port);
   1173             SOC_IF_ERROR_RETURN(soc_mem_write(unit, MEM_UCm, blk,
   1174                                               lp->d_mod, &ucdata));
   1175         }
   1176     }
   1177 #endif /* BCM_XGS12_FABRIC_SUPPORT */
   1178 #endif /* BCM_ESW_SUPPORT */
   1179 
   1180     return(0);
   1181 }
   1182 
   1183 int
   1184 lbu_setup_port(int unit, bcm_port_t port, int req_speed, int autoneg)
   1185 {
   1186     int                    speed = 0, duplex = 0, max_speed;
   1187     bcm_port_ability_t     req_ability;
   1188     bcm_port_ability_t     actual_ability;
   1189     bcm_port_medium_t      medium;
   1190 
   1191     sal_memset(&req_ability, 0, sizeof(bcm_port_ability_t));
   1192 
   1193     BCM_IF_ERROR_RETURN(
   1194         bcm_port_speed_max(unit, port, &max_speed));
   1195     if (max_speed > SOC_INFO(unit).port_speed_max[port]) {
   1196         max_speed = SOC_INFO(unit).port_speed_max[port];
   1197     }
   1198 
   1199     switch (req_speed) {
   1200         case LB_SPEED_10FD:
   1201             speed = 10 ; 
   1202             req_ability.speed_full_duplex = SOC_PA_SPEED_10MB;
   1203             duplex = SOC_PORT_DUPLEX_FULL;
   1204             break;
   1205         case LB_SPEED_100FD:
   1206             speed = 100; 
   1207             req_ability.speed_full_duplex = SOC_PA_SPEED_100MB;
   1208             duplex = SOC_PORT_DUPLEX_FULL;
   1209             break;
   1210         case LB_SPEED_1000FD:
   1211             speed = 1000; 
   1212             req_ability.speed_full_duplex = SOC_PA_SPEED_1000MB;
   1213             duplex = SOC_PORT_DUPLEX_FULL;
   1214             break;
   1215         case LB_SPEED_2500FD:
   1216             speed = 2500; 
   1217             req_ability.speed_full_duplex = SOC_PA_SPEED_2500MB;
   1218             duplex = SOC_PORT_DUPLEX_FULL;
   1219             break;
   1220         case LB_SPEED_3000FD:
   1221             speed = 3000; 
   1222             req_ability.speed_full_duplex = SOC_PA_SPEED_3000MB;
   1223             duplex = SOC_PORT_DUPLEX_FULL;
   1224             break;
   1225         case LB_SPEED_5000FD:
   1226             speed = 5000; 
   1227             req_ability.speed_full_duplex = SOC_PA_SPEED_5000MB;
   1228             duplex = SOC_PORT_DUPLEX_FULL;
   1229             break;
   1230         case LB_SPEED_10G_FD:
   1231             speed = 10000; 
   1232             req_ability.speed_full_duplex = SOC_PA_SPEED_10GB;
   1233             duplex = SOC_PORT_DUPLEX_FULL;
   1234             break;
   1235         case LB_SPEED_11G_FD:
   1236             speed = 11000; 
   1237             req_ability.speed_full_duplex = SOC_PA_SPEED_11GB;
   1238             duplex = SOC_PORT_DUPLEX_FULL;
   1239             break;
   1240         case LB_SPEED_12G_FD:
   1241             speed = 12000;
   1242             req_ability.speed_full_duplex = SOC_PA_SPEED_12GB;
   1243             duplex = SOC_PORT_DUPLEX_FULL;
   1244             break;
   1245         case LB_SPEED_13G_FD:
   1246             speed = 13000;
   1247             req_ability.speed_full_duplex = SOC_PA_SPEED_13GB;
   1248             duplex = SOC_PORT_DUPLEX_FULL;
   1249             break;
   1250         case LB_SPEED_15G_FD:
   1251             speed = 15000;
   1252             req_ability.speed_full_duplex = SOC_PA_SPEED_15GB;
   1253             duplex = SOC_PORT_DUPLEX_FULL;
   1254             break;
   1255         case LB_SPEED_16G_FD:
   1256             speed = 16000; 
   1257             req_ability.speed_full_duplex = SOC_PA_SPEED_16GB;
   1258             duplex = SOC_PORT_DUPLEX_FULL;
   1259             break;
   1260         case LB_SPEED_20G_FD:
   1261             speed = 20000; 
   1262             req_ability.speed_full_duplex = SOC_PA_SPEED_20GB;
   1263             duplex = SOC_PORT_DUPLEX_FULL;
   1264             break;
   1265         case LB_SPEED_21G_FD:
   1266             speed = 21000; 
   1267             req_ability.speed_full_duplex = SOC_PA_SPEED_21GB;
   1268             duplex = SOC_PORT_DUPLEX_FULL;
   1269             break;
   1270         case LB_SPEED_23G_FD:
   1271             speed = 23000; 
   1272             req_ability.speed_full_duplex = SOC_PA_SPEED_23GB;
   1273             duplex = SOC_PORT_DUPLEX_FULL;
   1274             break;
   1275         case LB_SPEED_24G_FD:
   1276             speed = 24000; 
   1277             req_ability.speed_full_duplex = SOC_PA_SPEED_24GB;
   1278             duplex = SOC_PORT_DUPLEX_FULL;
   1279             break;
   1280         case LB_SPEED_25G_FD:
   1281             speed = 25000; 
   1282             req_ability.speed_full_duplex = SOC_PA_SPEED_25GB;
   1283             duplex = SOC_PORT_DUPLEX_FULL;
   1284             break;
   1285         case LB_SPEED_30G_FD:
   1286             speed = 30000; 
   1287             req_ability.speed_full_duplex = SOC_PA_SPEED_30GB;
   1288             duplex = SOC_PORT_DUPLEX_FULL;
   1289             break;
   1290         case LB_SPEED_32G_FD:
   1291             speed = 32000; 
   1292             req_ability.speed_full_duplex = SOC_PA_SPEED_32GB;
   1293             duplex = SOC_PORT_DUPLEX_FULL;
   1294             break;
   1295         case LB_SPEED_40G_FD:
   1296             speed = 40000; 
   1297             req_ability.speed_full_duplex = SOC_PA_SPEED_40GB;
   1298             duplex = SOC_PORT_DUPLEX_FULL;
   1299             break;
   1300         case LB_SPEED_42G_FD:
   1301             speed = 42000; 
   1302             req_ability.speed_full_duplex = SOC_PA_SPEED_42GB;
   1303             duplex = SOC_PORT_DUPLEX_FULL;
   1304             break;
   1305         case LB_SPEED_50G_FD:
   1306             speed = 50000;
   1307             duplex = SOC_PORT_DUPLEX_FULL;
   1308             break;
   1309         case LB_SPEED_100G_FD:
   1310             speed = 100000; 
   1311             req_ability.speed_full_duplex = SOC_PA_SPEED_100GB;
   1312             duplex = SOC_PORT_DUPLEX_FULL;
   1313             break;
   1314         case LB_SPEED_106G_FD:
   1315             speed = 106000; 
   1316             req_ability.speed_full_duplex = SOC_PA_SPEED_106GB;
   1317             duplex = SOC_PORT_DUPLEX_FULL;
   1318             break;
   1319         case LB_SPEED_120G_FD:
   1320             speed = 120000; 
   1321             req_ability.speed_full_duplex = SOC_PA_SPEED_120GB;
   1322             duplex = SOC_PORT_DUPLEX_FULL;
   1323             break;
   1324         case LB_SPEED_127G_FD:
   1325             speed = 127000; 
   1326             req_ability.speed_full_duplex = SOC_PA_SPEED_127GB;
   1327             duplex = SOC_PORT_DUPLEX_FULL;
   1328             break;
   1329         case LB_SPEED_200G_FD:
   1330             speed = 200000;
   1331             duplex = SOC_PORT_DUPLEX_FULL;
   1332             break;
   1333         case LB_SPEED_400G_FD:
   1334             speed = 400000;
   1335             duplex = SOC_PORT_DUPLEX_FULL;
   1336             break;
   1337         case LB_SPEED_MAX:
   1338             /* PM8x50 does not support port_ability_local_get. Use max speed */
   1339             if (!IS_CD_PORT(unit, port)) {
   1340             BCM_IF_ERROR_RETURN(
   1341                 bcm_port_ability_local_get(unit, port, &req_ability)); 
   1342             }
   1343             duplex = SOC_PORT_DUPLEX_FULL;
   1344             speed = max_speed;
   1345             break;
   1346         default:
   1347             return(BCM_E_PARAM);
   1348     }
   1349 
   1350     BCM_IF_ERROR_RETURN( 
   1351         bcm_port_enable_set(unit, port, TRUE));
   1352     BCM_IF_ERROR_RETURN(
   1353         bcm_port_medium_get(unit, port, &medium));
   1354     if ((medium == BCM_PORT_MEDIUM_FIBER) && 
   1355         (duplex != SOC_PORT_DUPLEX_FULL)) {
   1356         LOG_ERROR(BSL_LS_APPL_TESTS,
   1357                   (BSL_META_U(unit,
   1358                               "unit %d Port %s is in Fiber mode. "
   1359                               "Forcing FullDuplex\n"),
   1360                    unit, SOC_PORT_NAME(unit, port)));
   1361         duplex = SOC_PORT_DUPLEX_FULL;
   1362     }
   1363 
   1364     if (autoneg) {
   1365         BCM_IF_ERROR_RETURN(
   1366             bcm_port_ability_advert_set(unit, port, &req_ability));
   1367         BCM_IF_ERROR_RETURN(
   1368             bcm_port_autoneg_set(unit, port, TRUE));
   1369     } else {
   1370         /* PM8x50 does not support port_ability_local_get. Use max speed */
   1371         if (!IS_CD_PORT(unit, port)) {
   1372         BCM_IF_ERROR_RETURN(
   1373             bcm_port_ability_local_get(unit, port, &actual_ability));
   1374 
   1375         if (!(actual_ability.speed_full_duplex & req_ability.speed_full_duplex)) {
   1376             LOG_ERROR(BSL_LS_APPL_TESTS,
   1377                   (BSL_META_U(unit,
   1378                               "unit %d Port %s: Speed %uMbps is unsupported, "
   1379                               "Forcing %uMbps\n"),
   1380                    unit, SOC_PORT_NAME(unit, port), speed, max_speed));
   1381             speed = max_speed;
   1382         }
   1383         }
   1384 
   1385         BCM_IF_ERROR_RETURN(
   1386             bcm_port_autoneg_set(unit, port, FALSE));
   1387        if (IS_CD_PORT(unit, port)) {
   1388            bcm_port_resource_t pr;
   1389            BCM_IF_ERROR_RETURN(bcm_port_resource_speed_get(unit, port,
   1390                                                            &pr));
   1391 #ifdef BCM_TOMAHAWK3_SUPPORT
   1392            if (SOC_IS_TOMAHAWK3(unit)) {
   1393                int lanes_match = 1;
   1394                bcm_port_phy_fec_t fec_type = bcmPortPhyFecNone;
   1395                int phy_lane_config;
   1396                int link_training;
   1397 
   1398                /* We will proceed only if speed specified by the user matches
   1399                 * (for a given number of lanes) one of the speeds with equal
   1400                 * number of lanes
   1401                 */
   1402                switch(pr.lanes) {
   1403                    case 8:
   1404                        if (speed != 400000) {
   1405                            lanes_match = 0;
   1406                        }
   1407 
   1408                        fec_type = bcmPortPhyFecRs544_2xN;
   1409                        break;
   1410                    case 4:
   1411                        if ((speed != 200000) &&
   1412                            (speed != 100000) &&
   1413                            (speed != 40000)) {
   1414                            lanes_match = 0;
   1415                        }
   1416                        switch (speed) {
   1417                            case 200000:
   1418                                fec_type = bcmPortPhyFecRs544;
   1419                                break;
   1420                            case 100000:
   1421                            case 40000:
   1422                            default:
   1423                                fec_type = bcmPortPhyFecNone;
   1424                                break;
   1425                        }
   1426                        break;
   1427                    case 2:
   1428                        if ((speed != 100000) &&
   1429                            (speed != 50000) &&
   1430                            (speed != 40000)) {
   1431                            lanes_match = 0;
   1432                        }
   1433 
   1434                        switch (speed) {
   1435                            case 100000:
   1436                            case 50000:
   1437                                fec_type = bcmPortPhyFecRs544;
   1438                                break;
   1439                            case 40000:
   1440                            default:
   1441                                fec_type = bcmPortPhyFecNone;
   1442                                break;
   1443                        }
   1444                        break;
   1445                    case 1:
   1446                        if ((speed != 50000) &&
   1447                            (speed != 25000) &&
   1448                            (speed != 10000)) {
   1449                            lanes_match = 0;
   1450                        }
   1451 
   1452                        switch (speed) {
   1453                            case 50000:
   1454                                fec_type = bcmPortPhyFecRs544;
   1455                                break;
   1456                            case 25000:
   1457                            case 10000:
   1458                            default:
   1459                                fec_type = bcmPortPhyFecNone;
   1460                                break;
   1461                        }
   1462                        break;
   1463 
   1464                    default:
   1465                        lanes_match = 0;
   1466                        break;
   1467                }
   1468 
   1469                phy_lane_config = -1;
   1470                link_training = 0;
   1471 
   1472                 if (!lanes_match) {
   1473                     LOG_ERROR(BSL_LS_APPL_TESTS, (BSL_META_U(unit, "unit %d"
   1474                                   " Port %s: Speed %uMbps is not supported for %d"
   1475                                   " lane(s)\n"), unit,
   1476                                   SOC_PORT_NAME(unit, port), speed, pr.lanes));
   1477                     return(BCM_E_PARAM);
   1478                 }
   1479 
   1480                 pr.fec_type = fec_type;
   1481                 pr.phy_lane_config = phy_lane_config;
   1482                 pr.link_training = link_training;
   1483            }
   1484 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1485            if (pr.speed != speed) {
   1486                LOG_INFO(BSL_LS_BCM_PORT,
   1487                         (BSL_META_U(unit,
   1488                          "port speed (%d) does NOT match "
   1489                          " current speed (%d).\n"),
   1490                          pr.speed, speed));
   1491            }
   1492            pr.speed = speed;
   1493            BCM_IF_ERROR_RETURN(bcm_port_resource_speed_set(unit, port, &pr));
   1494        } else {
   1495         BCM_IF_ERROR_RETURN(
   1496             bcm_port_speed_set(unit, port, speed));
   1497        }
   1498         BCM_IF_ERROR_RETURN(
   1499             bcm_port_duplex_set(unit, port, duplex));
   1500     }
   1501 
   1502     return (BCM_E_NONE);
   1503 }
   1504 
   1505 STATIC int
   1506 lbu_port_init(loopback2_test_t *lw, loopback2_testdata_t *lp)
   1507 {
   1508     char                 pfmt[SOC_PBMP_FMT_LEN];
   1509     bcm_port_t           p;
   1510     int                  rv, unit = lw->unit;
   1511     int                  rcpu;
   1512 
   1513     /* Save all the current port states */
   1514 
   1515     LOG_INFO(BSL_LS_APPL_TESTS,
   1516              (BSL_META("Saving ports\n")));
   1517     if (lbu_save_port(lw, lp) < 0) {
   1518         return (-1);
   1519     }
   1520     
   1521     /* Port setup */
   1522     LOG_INFO(BSL_LS_APPL_TESTS,
   1523              (BSL_META("Port setup, bitmap %s\n"),
   1524               SOC_PBMP_FMT(lp->pbm, pfmt)));
   1525     if (lp->loopback == LB2_MODE_EXT) {
   1526         PBMP_ITER(lp->pbm, p) {
   1527             /* Forwarding, egress enable, epc_link */
   1528             if ((rv = bcm_port_stp_set(unit, p,
   1529                                        BCM_STG_STP_FORWARD)) < 0) {
   1530                 test_error(unit,
   1531                            "Unable to set port %s in forwarding state: %s\n",
   1532                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1533                 return -1;
   1534             }
   1535         }
   1536     }
   1537 
   1538     if (lp->loopback == LB2_MODE_MAC) {
   1539         LOG_INFO(BSL_LS_APPL_TESTS,
   1540                  (BSL_META("MAC loopback at speed %s\n"), 
   1541                   lb2_parse_speed[lp->speed]));
   1542 
   1543         PBMP_ITER(lp->pbm, p) {
   1544             if (SOC_IS_HAWKEYE(unit)||SOC_IS_GREYHOUND2(unit)) {
   1545                 if ((rv = lbu_setup_port(unit, p, lp->speed, FALSE)) < 0) {
   1546                     test_error(unit,
   1547                                "Port %s: Port setup failed: %s\n",
   1548                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1549                     return(-1);
   1550                 }
   1551                 if ((rv = bcm_port_loopback_set(unit, p, 
   1552                                                 BCM_PORT_LOOPBACK_MAC)) < 0) {
   1553                     test_error(unit,
   1554                                "Port %s: Failed to set MAC loopback: %s\n",
   1555                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1556                     return(-1);
   1557                 }
   1558             } else {
   1559                 /*
   1560                  * Set loopback mode before speed, since it may affect
   1561                  * the allowable speeds.
   1562                  */
   1563 
   1564                 if ((rv = bcm_port_loopback_set(unit, p, 
   1565                                                 BCM_PORT_LOOPBACK_MAC)) < 0) {
   1566                     test_error(unit,
   1567                                "Port %s: Failed to set MAC loopback: %s\n",
   1568                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1569                     return(-1);
   1570                 }
   1571 
   1572                 if (IS_HG_PORT(unit, p)) {
   1573                     /*
   1574                      *      Disabling pause reuiqred on IPIC/XPORT
   1575                      *      HG ports. Should already be disabled on
   1576                      *      GE (stack) ports during init.
   1577                      */
   1578                     bcm_port_pause_set(unit, p, FALSE, FALSE);
   1579                 }
   1580 
   1581                 if ((rv = lbu_setup_port(unit, p, lp->speed, FALSE)) < 0) {
   1582                     test_error(unit,
   1583                                "Port %s: Port setup failed: %s\n",
   1584                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1585                     return(-1);
   1586                 }
   1587             }
   1588         }
   1589 
   1590         if (SOC_IS_XGS12_FABRIC(unit)) {
   1591             pbmp_t               pbm;
   1592 
   1593             /*
   1594              * If there is an external cable looped back, 5670 will
   1595              * receive packets on ports that may not be in the test
   1596              * and these packets will go to the CPU and interfere.
   1597              */
   1598 
   1599             BCM_PBMP_ASSIGN(pbm, lp->pbm);
   1600             BCM_PBMP_XOR(pbm, PBMP_PORT_ALL(unit));
   1601             PBMP_ITER(pbm, p) {
   1602                 if ((rv = bcm_port_enable_set(unit, p, FALSE)) < 0) {
   1603                     test_error(unit,
   1604                                "Port %s: Failed to set MAC enable: %s\n",
   1605                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1606                     return(-1);
   1607                 }
   1608             }
   1609         }
   1610     } else if (lp->loopback == LB2_MODE_PHY) {
   1611         LOG_INFO(BSL_LS_APPL_TESTS,
   1612                  (BSL_META("PHY loopback at speed %s\n"), 
   1613                   lb2_parse_speed[lp->speed]));
   1614 
   1615         rcpu = soc_property_get(unit, spn_RCPU_PORT, -1);
   1616         PBMP_ITER(lp->pbm, p) {
   1617             if (rcpu !=0 && rcpu != -1 && SOC_IS_RAVEN(unit)) {
   1618                 if ((rv = bcm_port_loopback_set(unit, p,
   1619                                                 BCM_PORT_LOOPBACK_PHY)) < 0) {
   1620                     test_error(unit,
   1621                                "Port %s: Failed to set PHY loopback: %s\n",
   1622                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1623                     return(-1);                     /* In case they continue */
   1624                 }
   1625 
   1626                 if ((rv = lbu_setup_port(unit, p, lp->speed, FALSE)) < 0) {
   1627                     test_error(unit,
   1628                                "Port %s: Port setup failed: %s\n",
   1629                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1630                     return(-1);
   1631                 }
   1632 
   1633             } else {
   1634                 if ((rv = lbu_setup_port(unit, p, lp->speed, FALSE)) < 0) {
   1635                     test_error(unit,
   1636                                "Port %s: Port setup failed: %s\n",
   1637                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1638                     return(-1);
   1639                 }
   1640 
   1641                 if ((rv = bcm_port_loopback_set(unit, p,
   1642                                                 BCM_PORT_LOOPBACK_PHY)) < 0) {
   1643                     test_error(unit,
   1644                                "Port %s: Failed to set PHY loopback: %s\n",
   1645                                SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1646                     return(-1);                     /* In case they continue */
   1647                 }
   1648             }
   1649         }
   1650     } else { /* External */
   1651 
   1652         PBMP_ITER(lp->pbm, p) {
   1653             if ((rv = lbu_setup_port(unit, p, lp->speed, FALSE)) < 0) {
   1654                 test_error(unit,
   1655                            "Port %s: Port setup failed: %s\n",
   1656                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1657                 return(-1);
   1658             }
   1659         }
   1660     }
   1661     if(SOC_IS_ESW(unit)){       
   1662         if (lp->test_type == LB2_TT_SNAKE) {
   1663             PBMP_ITER(lp->pbm, p) {
   1664                 if ((rv = bcm_port_learn_set(unit, p, BCM_PORT_LEARN_FWD)) < 0) {
   1665                     test_error(unit,
   1666                            "Unable to set learn state: port %s: %s\n",
   1667                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1668                     return (-1);
   1669                 }
   1670             }
   1671         }
   1672     }
   1673 #ifdef BCM_TRIUMPH_SUPPORT
   1674     if(SOC_IS_TRX(unit)){       
   1675         PBMP_ITER(lp->pbm, p) {
   1676 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   1677             if (SOC_MEM_IS_VALID(unit, EGR_VLAN_CONTROL_1m)) {
   1678                 if (soc_feature(unit, soc_feature_egr_all_profile)) {
   1679                     BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit,
   1680                         p, EGR_VLAN_CONTROL_1m, REMARK_OUTER_DOT1Pf, 0));
   1681                 } else {
   1682                     egr_vlan_control_1_entry_t entry;
   1683                     BCM_IF_ERROR_RETURN
   1684                         (READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, p, &entry));
   1685                     soc_EGR_VLAN_CONTROL_1m_field32_set(unit, &entry,
   1686                                                         REMARK_OUTER_DOT1Pf, 0);
   1687                     BCM_IF_ERROR_RETURN
   1688                         (WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, p, &entry));
   1689                 }
   1690             } else
   1691 #endif
   1692             if ((rv = soc_reg_field32_modify(unit, EGR_VLAN_CONTROL_1r, p,
   1693                                              REMARK_OUTER_DOT1Pf, 0x0)) < 0) {
   1694                 test_error(unit,
   1695                        "Unable to disable outer dot1p remarking: port %s: %s\n",
   1696                        SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   1697                 return (-1);
   1698             }
   1699         }
   1700     }
   1701 #endif
   1702     {
   1703         bcm_pbmp_t lw_pbm;
   1704         BCM_PBMP_ASSIGN(lw_pbm, lp->pbm);
   1705         rv = bcm_link_wait(unit, &lw_pbm, 1000000);
   1706         if (rv < 0) {
   1707             return -1;
   1708         }
   1709     }
   1710 
   1711 
   1712     return 0;
   1713 }
   1714 
   1715 STATIC int
   1716 lbu_vlan_init(loopback2_test_t *lw, loopback2_testdata_t *lp)
   1717 {
   1718     int                 rv, unit = lw->unit;
   1719     pbmp_t              empty_pbm, vlan_pbm;
   1720     bcm_port_t          p;
   1721     bcm_vlan_t          vlan;
   1722 
   1723     if (!lp->inject) {
   1724         if ((rv = bcm_vlan_destroy_all(unit)) < 0) {
   1725             test_error(unit,
   1726                        "Could not destroy existing VLANs: %s\n",
   1727                        bcm_errmsg(rv));
   1728             return (-1);
   1729         }
   1730     }
   1731 
   1732     if (lp->test_type == LB2_TT_SNAKE) {
   1733         PBMP_ITER(lp->pbm, p) {
   1734             /* Each port in all VLANs for test */
   1735             vlan = lp->vlan + p + 1;
   1736             if ( ((rv = bcm_vlan_create(unit, vlan)) < 0) &&
   1737                  (rv != BCM_E_EXISTS) ) {
   1738                 test_error(unit,
   1739                            "Could not create VLAN %d: %s\n",
   1740                            vlan, bcm_errmsg(rv));
   1741                 return (-1);
   1742             }
   1743         
   1744             /* Untagged! */
   1745             BCM_PBMP_ASSIGN(vlan_pbm, lp->pbm);
   1746             BCM_PBMP_PORT_ADD(vlan_pbm, CMIC_PORT(unit));
   1747             if ((rv = bcm_vlan_port_add(unit, vlan, vlan_pbm, vlan_pbm)) < 0) {
   1748                 test_error(unit,
   1749                            "Could not add test ports to VLAN %d: %s\n",
   1750                            vlan, bcm_errmsg(rv));
   1751                 return (-1);
   1752             }
   1753 
   1754             /* Set port to tag with vlan */
   1755             if (IS_E_PORT(unit, p)) {
   1756                 if ((rv = bcm_port_untagged_vlan_set(unit, p, vlan)) < 0) {
   1757                     test_error(unit,
   1758                                "Could not set port %s to "
   1759                                "tag packet with VLAN %d: %s\n",
   1760                                SOC_PORT_NAME(unit, p), vlan, bcm_errmsg(rv));
   1761                     return (-1);
   1762                 }
   1763             }
   1764         }
   1765     } else {
   1766         if ((rv = bcm_vlan_create(unit, lp->vlan)) < 0 &&
   1767             rv != BCM_E_EXISTS) {
   1768             test_error(unit,
   1769                        "Could not create VLAN %d: %s\n",
   1770                        lp->vlan, bcm_errmsg(rv));
   1771             return (-1);
   1772         }
   1773 
   1774         SOC_PBMP_CLEAR(empty_pbm);
   1775         SOC_PBMP_ASSIGN(vlan_pbm, lp->pbm);
   1776         SOC_PBMP_PORT_ADD(vlan_pbm, CMIC_PORT(unit));
   1777         if ((rv = bcm_vlan_port_add(unit, lp->vlan, vlan_pbm,
   1778                                     empty_pbm)) < 0) {
   1779             test_error(unit,
   1780                        "Could not add selected ports to VLAN %d: %s\n",
   1781                        lp->vlan, bcm_errmsg(rv));
   1782             return (-1);
   1783         }
   1784 
   1785         SOC_PBMP_ASSIGN(vlan_pbm, lp->pbm);
   1786         SOC_PBMP_AND(vlan_pbm, PBMP_E_ALL(unit));
   1787         PBMP_ITER(vlan_pbm, p) {
   1788             if ((rv = bcm_port_untagged_vlan_set(unit, p, lp->vlan)) < 0) {
   1789                 test_error(unit,
   1790                      "Could not set port %s to tag packet with VLAN %d: %s\n",
   1791                            SOC_PORT_NAME(unit, p), lp->vlan, bcm_errmsg(rv));
   1792                 return (-1);
   1793             }
   1794         }
   1795     }
   1796 
   1797     return 0;
   1798 }
   1799 
   1800 STATIC int
   1801 lbu_stack_check(int unit)
   1802 {
   1803     if (SOC_SL_MODE(unit)) {
   1804         return -1;
   1805     }
   1806     return 0;
   1807 }
   1808 
   1809 int
   1810 lbu_init(loopback2_test_t *lw, loopback2_testdata_t *lp)
   1811 {
   1812     int                 unit = lw->unit;
   1813     uint32              flags = BCM_TX_NO_PAD;
   1814     
   1815     if (NULL == (lw->sema = sal_sem_create("lb2-sema", sal_sem_BINARY, 0))) {
   1816         return (-1);
   1817     }
   1818 
   1819     lw->sema_woke = FALSE;
   1820     lw->timeout_usec = lbu_timeout_usec(unit);
   1821 
   1822     lw->tx_seq = 0;
   1823     lw->tx_len = 0;
   1824 
   1825     /* Don't want any stack ports lying about */
   1826     if (lbu_stack_check(unit) < 0) {
   1827         return (-1);
   1828     }
   1829 
   1830     if (lbu_vlan_init(lw, lp) < 0) {
   1831         return (-1);
   1832     }
   1833 
   1834     /* Initialize ports */
   1835     if (lbu_port_init(lw, lp) < 0) {
   1836         return (-1);
   1837     }
   1838 
   1839     /* Allocate the tx packets */
   1840     /* Set up TX pkts once, for max length */
   1841     if (lp->crc_mode == LB2_CRC_MODE_MAC_REGEN) {
   1842         flags |= BCM_TX_CRC_REGEN;
   1843     } else if (lp->crc_mode == LB2_CRC_MODE_CPU_APPEND) {
   1844         flags |= BCM_TX_CRC_APPEND;
   1845     } /* else, do not add a flag */
   1846     bcm_pkt_blk_alloc(unit, lp->ppt_end, lp->len_end, flags, &(lw->tx_pkts));
   1847     if (!lw->tx_pkts) {
   1848         test_error(unit, "Unable to allocate tx packet memory\n");
   1849         return -1;
   1850     }
   1851     lw->rx_pkts = sal_alloc(lp->ppt_end * sizeof(bcm_pkt_t), "lb2 rx pkts");
   1852     if (!lw->rx_pkts) {
   1853         bcm_pkt_blk_free(unit, lw->tx_pkts, lp->ppt_end);
   1854         test_error(unit, "Unable to allocate rx packet memory\n");
   1855         return -1;
   1856     }
   1857     sal_memset(lw->rx_pkts, 0, lp->ppt_end * sizeof(bcm_pkt_t));
   1858 
   1859     /* Now that all mems are safely created, fire off the handler */
   1860     if (!lp->inject) {
   1861         LOG_INFO(BSL_LS_APPL_TESTS,
   1862                  (BSL_META_U(unit,
   1863                              "Port monitor init\n")));
   1864         /* Let rx handler ignore packets until testing */
   1865         lw->expect_pkts = FALSE; 
   1866         lw->rx_pkt_cnt = 0;
   1867         if (lbu_port_monitor_task(unit, lbu_rx_callback, lw) < 0) {
   1868             return (-1);
   1869         }
   1870     }
   1871 
   1872     lw->cur_params = lp;
   1873 
   1874     return 0;
   1875 }
   1876 
   1877 int
   1878 lbu_snake_init(loopback2_test_t *lw, loopback2_testdata_t *lp)
   1879 /*
   1880  * Function:    lbu_snake_init
   1881  * Purpose:     Link adjacent ports to forward packets.
   1882  * Parameters:  lw - pointer to current work structure.
   1883  * Returns:     0 - OK
   1884  *              -1 - failed.
   1885  */
   1886 {
   1887     int         unit = lw->unit;
   1888     int         snake_way = lp->snake_way;
   1889     bcm_port_t  port, first_port, last_port;
   1890     int         forward, reverse;
   1891     lb2s_port_connect_t *work_info, *f_info, *r_info;
   1892     int         modid = 0, modid_hi = 0, ipic_my_modid, ipic_my_modid_hi;
   1893     int         rv, pix; /* port index */
   1894     int         port_count, install_count;
   1895     int         close_loop = (lp->duration != 0);
   1896 #ifdef BCM_TOMAHAWK_SUPPORT
   1897     int         line_rate = lp->line_rate;
   1898     int         speed_linerate = 0, speed = 0;
   1899 #endif
   1900     /* Get the module ID for this unit */
   1901     if (SOC_IS_XGS_SWITCH(unit)) {
   1902         BCM_IF_ERROR_RETURN(bcm_stk_my_modid_get(unit, &modid));
   1903     }
   1904 #ifdef BCM_ESW_SUPPORT
   1905     /* Why does this make the snake work? */
   1906 #ifdef BCM_TRIUMPH3_SUPPORT
   1907     if (soc_feature(unit, soc_feature_ism_memory)) {
   1908         
   1909         uint8 banks[_SOC_ISM_MAX_BANKS], count, bank_ix;
   1910         uint32 bank_size[_SOC_ISM_MAX_BANKS];
   1911         rv = soc_ism_get_banks_for_mem(unit, L2_ENTRY_1m,
   1912                                        banks, bank_size, &count);
   1913         if (rv  < 0) {
   1914             test_error(unit, "ISM L2 bank enumeration retrieval failed\n");
   1915             return rv;
   1916         }
   1917         
   1918         for (bank_ix = 0; bank_ix < count; bank_ix++) {
   1919             /* Offset 0 is CRC32 low */
   1920             rv = soc_ism_hash_offset_config(unit, banks[bank_ix], 0);
   1921             if (rv  < 0) {
   1922                 test_error(unit, "ISM L2 bank %d hash offset set failure\n",
   1923                            banks[bank_ix]);
   1924                 return rv;
   1925             }
   1926         }
   1927     } else 
   1928 #endif /* BCM_TRIUMPH3_SUPPORT */
   1929     if (SOC_IS_XGS3_SWITCH(unit) && !(SOC_IS_TOMAHAWK3(unit))) {
   1930 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1931         uint32  hc;
   1932         LOG_INFO(BSL_LS_APPL_TESTS,
   1933                  (BSL_META_U(unit,
   1934                              "Hash select reset to CRC32 low\n")));
   1935         rv = READ_HASH_CONTROLr(unit, &hc);
   1936         if (rv >= 0) {
   1937             soc_reg_field_set(unit, HASH_CONTROLr, &hc,
   1938                               L2_AND_VLAN_MAC_HASH_SELECTf,
   1939                               FB_HASH_CRC32_LOWER);
   1940             rv = WRITE_HASH_CONTROLr(unit, hc);
   1941         }
   1942         if (rv  < 0) {
   1943             test_error(unit, "Hash select setting failed\n");
   1944             return rv;
   1945         }
   1946 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1947     } else if (SOC_IS_XGS_SWITCH(unit)) {
   1948         LOG_INFO(BSL_LS_APPL_TESTS,
   1949                  (BSL_META_U(unit,
   1950                              "Hash select reset to CRC32 low\n")));
   1951         if ((rv = WRITE_HASH_CONTROLr(unit, XGS_HASH_CRC32_LOWER)) < 0) {
   1952             test_error(unit, "Hash select setting failed\n");
   1953             return rv;
   1954         }
   1955     }
   1956 #endif
   1957 
   1958     ipic_my_modid = lp->d_mod + lp->d_mod_inc;
   1959     if ((ipic_my_modid == (lp->d_mod == 0)) || (ipic_my_modid == modid)) {
   1960         ipic_my_modid += lp->d_mod_inc;
   1961     }
   1962     if ((ipic_my_modid == (lp->d_mod == 0)) || (ipic_my_modid == modid)) {
   1963         ipic_my_modid += lp->d_mod_inc;
   1964     }
   1965 
   1966     ipic_my_modid_hi = ipic_my_modid;
   1967 
   1968     forward = (snake_way == LB2_SNAKE_BOTH) || (snake_way == LB2_SNAKE_INCR);
   1969     reverse = (snake_way == LB2_SNAKE_BOTH) || (snake_way == LB2_SNAKE_DECR);
   1970 
   1971     first_port = last_port = -1;
   1972     PBMP_ITER(lp->pbm, port) {
   1973         last_port = port;
   1974         if (first_port < 0) {
   1975             first_port = port;
   1976         }
   1977     }
   1978 
   1979     if (first_port < 0) {
   1980         return BCM_E_NOT_FOUND;
   1981     }
   1982 
   1983     BCM_PBMP_COUNT(lp->pbm, port_count);
   1984     lw->port_count = port_count;
   1985 
   1986 #ifdef BCM_TOMAHAWK_SUPPORT
   1987     if (line_rate) {
   1988         PBMP_ITER(lp->pbm, port) {
   1989             BCM_IF_ERROR_RETURN(bcm_port_speed_get(unit,port,&speed));
   1990             if (speed_linerate && speed && (speed != speed_linerate)){
   1991                 cli_out("line rate snake test requires all tested ports have same speed\n");
   1992                 return BCM_E_PORT;
   1993             }
   1994             speed_linerate = speed;
   1995         }
   1996         /*For each one 10G port, we send 10 packets to achieve line rate in snake test.
   1997          *This is not a precise value but should be enough.
   1998          */
   1999         lp->line_rate_count= speed_linerate / 1000 * lw->port_count;
   2000     }
   2001 #endif
   2002 
   2003     if (forward) {
   2004         if (!(lw->port_cnct_f = 
   2005               sal_alloc((port_count + 1) * sizeof(lb2s_port_connect_t), 
   2006                         "Forward snake port info"))) {
   2007             return BCM_E_MEMORY;
   2008         }
   2009         sal_memset(lw->port_cnct_f, 0, (port_count + 1)* 
   2010                    sizeof(lb2s_port_connect_t));
   2011     } else {
   2012         lw->port_cnct_f = NULL;
   2013     }
   2014 
   2015     if (reverse) {
   2016         if (!(lw->port_cnct_r = 
   2017               sal_alloc((port_count + 1) * sizeof(lb2s_port_connect_t), 
   2018                         "Reverse snake port info"))) {
   2019             return BCM_E_MEMORY;
   2020         }
   2021         sal_memset(lw->port_cnct_r, 0, (port_count + 1) * 
   2022                    sizeof(lb2s_port_connect_t));
   2023     } else {
   2024         lw->port_cnct_r = NULL;
   2025     }
   2026 
   2027     if (!(lw->tx_pkt_match = sal_alloc(lp->ppt_end * sizeof(int), 
   2028                                        "Snake TX match markers"))) {
   2029         return BCM_E_MEMORY;
   2030     }
   2031     sal_memset(lw->tx_pkt_match, 0, lp->ppt_end * sizeof(int));
   2032  
   2033     f_info = lw->port_cnct_f;
   2034     r_info = lw->port_cnct_r;
   2035     work_info = forward ? f_info : r_info;
   2036 
   2037     work_info->this_port = work_info->to_port = first_port;
   2038     work_info->added_vlan = lp->vlan + first_port + 1;
   2039     ENET_SET_MACADDR(work_info->src_mac, lp->mac_src);
   2040     ENET_SET_MACADDR(work_info->dst_mac, lp->mac_dst);
   2041 
   2042     if (!IS_E_PORT(unit, first_port)) {
   2043         work_info->src_modid = ipic_my_modid_hi + lp->d_mod_inc;
   2044     } else {
   2045         work_info->src_modid = 
   2046             SOC_PORT_MOD1(unit, first_port) ? modid_hi : modid;
   2047     }
   2048     work_info->dst_modid = work_info->src_modid;
   2049 
   2050     if (snake_way == LB2_SNAKE_BOTH) {
   2051         r_info->to_port = f_info->this_port;
   2052         r_info->dst_modid = f_info->src_modid;
   2053         ENET_SET_MACADDR(r_info->src_mac, f_info->src_mac);
   2054         increment_macaddr(r_info->src_mac, lp->mac_src_inc);
   2055         ENET_SET_MACADDR(r_info->dst_mac, f_info->dst_mac);
   2056         increment_macaddr(r_info->dst_mac, lp->mac_dst_inc);
   2057     }
   2058 
   2059     if (snake_way == LB2_SNAKE_BOTH || snake_way == LB2_SNAKE_DECR) {
   2060         if (SOC_IS_XGS12_FABRIC(unit) || 
   2061             (SOC_IS_HBX(unit) && IS_ST_PORT(unit, first_port))) {
   2062             r_info->dst_modid += lp->d_mod_inc;
   2063         }
   2064     }
   2065 
   2066     
   2067      
   2068     /* Generate the port connection info */
   2069     pix = 0;
   2070     PBMP_ITER(lp->pbm, port) {
   2071         if (pix > 0) {
   2072             if (forward) {
   2073                 f_info[pix].this_port = f_info[pix - 1].to_port = port;
   2074 
   2075                 if (IS_ST_PORT(unit, port) && SOC_IS_XGS_SWITCH(unit)) {
   2076                     f_info[pix].added_vlan = f_info[pix - 1].added_vlan;
   2077                     f_info[pix].src_modid = 
   2078                         f_info[pix - 1].dst_modid = 
   2079                         ipic_my_modid_hi + lp->d_mod_inc;
   2080                 } else {
   2081                     f_info[pix].added_vlan = lp->vlan + port + 1;
   2082                     if (IS_E_PORT(unit, port)) {
   2083                         f_info[pix].src_modid = 
   2084                             f_info[pix - 1].dst_modid = 
   2085                             SOC_PORT_MOD1(unit, port) ? 
   2086                             modid_hi : modid;
   2087                     } else {
   2088                         f_info[pix].src_modid = 
   2089                             f_info[pix - 1].dst_modid = 
   2090                             f_info[pix - 1].src_modid;
   2091                     }
   2092 
   2093                 }
   2094                 ENET_SET_MACADDR(f_info[pix].src_mac, f_info[pix - 1].src_mac);
   2095                 ENET_SET_MACADDR(f_info[pix].dst_mac, f_info[pix - 1].dst_mac);
   2096 
   2097                 f_info[pix - 1].valid_info = TRUE;
   2098             }
   2099 
   2100             if (reverse) {
   2101                 r_info[pix].to_port = r_info[pix - 1].this_port = port;
   2102                 if (!IS_E_PORT(unit, port) && SOC_IS_XGS_SWITCH(unit)) {
   2103                     r_info[pix - 1].added_vlan = r_info[pix - 2].added_vlan;
   2104                     r_info[pix].dst_modid = 
   2105                         r_info[pix - 1].src_modid = 
   2106                         ipic_my_modid_hi + (2 * lp->d_mod_inc);
   2107                 } else {
   2108                     r_info[pix - 1].added_vlan = lp->vlan + port + 1;
   2109                     if (IS_E_PORT(unit, port)) {
   2110                         r_info[pix].dst_modid = 
   2111                             r_info[pix - 1].src_modid = 
   2112                             SOC_PORT_MOD1(unit, port) ? 
   2113                             modid_hi : modid;
   2114                     } else {
   2115                         r_info[pix].dst_modid = 
   2116                             r_info[pix - 1].src_modid = 
   2117                             r_info[pix - 1].dst_modid;
   2118                     }
   2119                 }
   2120                 ENET_SET_MACADDR(r_info[pix].src_mac, r_info[pix - 1].src_mac);
   2121                 ENET_SET_MACADDR(r_info[pix].dst_mac, r_info[pix - 1].dst_mac);
   2122                 r_info[pix - 1].valid_info = TRUE;
   2123             }
   2124         }
   2125 
   2126 #ifdef BCM_ESW_SUPPORT
   2127         if (IS_ST_PORT(unit, port) && SOC_IS_XGS_SWITCH(unit)) {
   2128             if (SOC_IS_FBX(unit)) {
   2129 #ifdef BCM_FIREBOLT_SUPPORT
   2130                 port_tab_entry_t pte;
   2131                 int     hg_port;
   2132                 uint32  config = 0;
   2133 
   2134                 
   2135                 if (soc_mem_field_valid(unit, PORT_TABm, MY_MODIDf)) {
   2136                     PBMP_ST_ITER(unit, hg_port) {
   2137                         SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm,
   2138                                                 MEM_BLOCK_ANY, hg_port, &pte));
   2139                         soc_PORT_TABm_field32_set(unit, &pte, MY_MODIDf,
   2140                                                       ipic_my_modid);
   2141                         SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm,
   2142                                                 MEM_BLOCK_ALL, hg_port, &pte));
   2143                     }
   2144                 } else if (soc_reg_field_valid(unit, XPORT_CONFIGr, MY_MODIDf)) {
   2145                     PBMP_ST_ITER(unit, hg_port) {
   2146                         if (SOC_REG_PORT_VALID(unit, XPORT_CONFIGr, hg_port )) {
   2147                             BCM_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, hg_port,
   2148                                                     &config));
   2149                             soc_reg_field_set(unit, XPORT_CONFIGr, &config,
   2150                                                   MY_MODIDf, ipic_my_modid);
   2151                             BCM_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit,
   2152                                                     hg_port, config));
   2153                         }
   2154                     }
   2155                 }
   2156 #endif /* BCM_FIREBOLT_SUPPORT */
   2157             }
   2158         }
   2159 #endif /* BCM_ESW_SUPPORT */
   2160         pix++;
   2161     }
   2162 
   2163     assert(pix == port_count);
   2164     if (forward) {
   2165         /* Close loop */
   2166         f_info[pix - 1].to_port = f_info[0].this_port;
   2167         f_info[pix - 1].dst_modid = f_info[0].src_modid;
   2168         f_info[pix - 1].valid_info = close_loop;
   2169 
   2170         /* Record CPU redirect */
   2171         f_info[pix].this_port = f_info[pix - 1].this_port;
   2172         f_info[pix].added_vlan = f_info[pix - 1].added_vlan;
   2173         f_info[pix].src_modid = f_info[pix - 1].src_modid;
   2174         ENET_SET_MACADDR(f_info[pix].src_mac, f_info[pix - 1].src_mac);
   2175         ENET_SET_MACADDR(f_info[pix].dst_mac, f_info[pix - 1].dst_mac);
   2176         f_info[pix].to_port = CMIC_PORT(unit);
   2177         f_info[pix].dst_modid = modid;
   2178         f_info[pix].valid_info = TRUE;
   2179     }
   2180     if (reverse) {
   2181         /* Close loop */
   2182         r_info[pix - 1].this_port = r_info[0].to_port;
   2183         r_info[pix - 1].added_vlan = 
   2184             lp->vlan + r_info[pix - 1].this_port + 1;
   2185         r_info[pix - 1].src_modid = r_info[0].dst_modid;
   2186         r_info[pix - 1].valid_info = close_loop;
   2187 
   2188         /* Record CPU redirect */
   2189         r_info[pix].this_port = r_info[pix - 1].this_port;
   2190         r_info[pix].added_vlan = r_info[pix - 1].added_vlan;
   2191         r_info[pix].src_modid = r_info[pix - 1].src_modid;
   2192         ENET_SET_MACADDR(r_info[pix].src_mac, r_info[pix - 1].src_mac);
   2193         ENET_SET_MACADDR(r_info[pix].dst_mac, r_info[pix - 1].dst_mac);
   2194         r_info[pix].to_port = CMIC_PORT(unit);
   2195         r_info[pix].dst_modid = modid;
   2196         r_info[pix].valid_info = TRUE;
   2197     }
   2198 
   2199     /* If not closing loop, install the CPU return path also. */
   2200     install_count = port_count + (close_loop ? 0 : 1);
   2201 
   2202     for (pix = 0; pix < install_count; pix++) {
   2203         if (forward) {
   2204             if ((rv = lbu_connect_ports(unit, &f_info[pix], TRUE)) < 0 ) {
   2205                 return rv;
   2206             }
   2207         }
   2208         if (reverse) {
   2209             if ((rv = lbu_connect_ports(unit, &r_info[pix], TRUE)) < 0 ) {
   2210                 return rv;
   2211             }
   2212         }
   2213     }
   2214 
   2215     return 0;
   2216 }
   2217 
   2218 int
   2219 lbu_snake_done(loopback2_test_t *lw)
   2220 /*
   2221  * Function:    lbu_snake_done
   2222  * Purpose:     Link adjacent ports to forward packets.
   2223  * Parameters:  lw - pointer to current work structure.
   2224  * Returns:     0 - OK
   2225  *              -1 - failed.
   2226  */
   2227 {
   2228     int         unit = lw->unit;
   2229     int         pix, rv;
   2230     lb2s_port_connect_t *f_info, *r_info;
   2231 
   2232     f_info = lw->port_cnct_f;
   2233     r_info = lw->port_cnct_r;
   2234     for (pix = 0; pix < lw->port_count; pix++) {
   2235         if (f_info) {
   2236             if ((rv = lbu_connect_ports(unit, &f_info[pix], FALSE)) < 0 ) {
   2237                 return rv;
   2238             }
   2239         }
   2240         if (r_info) {
   2241             if ((rv = lbu_connect_ports(unit, &r_info[pix], FALSE)) < 0 ) {
   2242                 return rv;
   2243             }
   2244         }
   2245     }
   2246     
   2247     if (lw->port_cnct_f) {
   2248         sal_free(lw->port_cnct_f);
   2249     }
   2250     lw->port_cnct_f = NULL;
   2251     if (lw->port_cnct_r) {
   2252         sal_free(lw->port_cnct_r);
   2253     }
   2254     lw->port_cnct_r = NULL;
   2255     if (lw->tx_pkt_match) {
   2256         sal_free(lw->tx_pkt_match);
   2257     }
   2258     lw->tx_pkt_match = NULL;
   2259 
   2260     return 0;
   2261 }
   2262 
   2263 
   2264 /* These values are used to keep the number of packets per test within the
   2265  * limits that the MMU COS settings can handle. */
   2266 static int _lb_ppte_initval(int unit, int *lene, int *ppte)
   2267 {
   2268     int max_cells, num_cells, num_ports, num_cos, mmu_cell_size;
   2269     int len = *lene;
   2270 #if defined(BCM_HERCULES_SUPPORT)
   2271     int port = 0, cos = 0;
   2272     uint32 num_cells_per_port_cos = 0;
   2273 #endif
   2274     int ppte_max = SOC_DV_PKTS_MAX;
   2275     
   2276 
   2277     *ppte = ppte_max;
   2278 
   2279     if (SOC_IS_XGS_SWITCH(unit) || SOC_IS_XGS12_FABRIC(unit)) {
   2280         /* Check that we don't overload the MMU HOL cell limits */
   2281         /*  (This should be from #defines somewhere else)  */
   2282         mmu_cell_size = 128;
   2283         BCM_IF_ERROR_RETURN(bcm_cosq_config_get(unit, &num_cos));
   2284         max_cells = (len + mmu_cell_size - 1) / mmu_cell_size;
   2285 #if defined(BCM_FIREBOLT_SUPPORT)
   2286         if (SOC_IS_FBX(unit) && !SOC_IS_KATANAX(unit)) {
   2287 #ifdef BCM_TOMAHAWK3_SUPPORT
   2288             if (SOC_IS_TOMAHAWK3(unit)) {
   2289                 num_cells = _TH3_MMU_TOTAL_CELLS_PER_ITM;
   2290             } else
   2291 #endif
   2292             {
   2293             num_cells = soc_mem_index_count(unit, MMU_CBPDATA0m);
   2294             }
   2295         } else
   2296 #endif /* BCM_FIREBOLT_SUPPORT */        
   2297         {
   2298             num_cells = 8192;
   2299         }
   2300         num_ports = NUM_ALL_PORT(unit);
   2301         *ppte = (num_cells / (num_cos * num_ports * max_cells)) - 1;
   2302 
   2303 #if defined(BCM_HERCULES_SUPPORT)
   2304         if (SOC_IS_HERCULES(unit)) {
   2305             /* look at what is configured for any port/cos 0,0 */
   2306             SOC_IF_ERROR_RETURN(READ_MMU_CELLLMTCOS_LOWERr(unit, port, cos, 
   2307                                                            &num_cells_per_port_cos));
   2308             /* overwrite ppte */
   2309             *ppte = (num_cells_per_port_cos / max_cells) - 1; 
   2310         }
   2311 #endif /* BCM_HERCULES_SUPPORT */
   2312 
   2313         if (*ppte < 1) {
   2314             *ppte = 1;
   2315         }
   2316         if (*ppte > ppte_max) {
   2317             *ppte = ppte_max;
   2318         }
   2319         /*
   2320          * Number of cells allocated to this port 
   2321          * Assume DYNCELL_PERCENT 50
   2322          */
   2323         len = num_cells / num_ports / 2;
   2324 
   2325         /*
   2326          * Number of cells usable by a cos queue
   2327          */
   2328         len += (len / num_cos);
   2329         /*
   2330          * Max packet size supported
   2331          */
   2332         len *= mmu_cell_size;
   2333         if (*lene > len) {
   2334             *lene = len;
   2335         }
   2336     }
   2337     return(SOC_E_NONE);
   2338 }
   2339 
   2340 int
   2341 lbu_check_parms(loopback2_test_t *lw, loopback2_testdata_t *lp)
   2342 /*
   2343  * Function:    lbu_check_parms
   2344  * Purpose:     Check parameters for reasonable values.
   2345  * Parameters:  lw - pointer to current work structure.
   2346  * Returns:     0 - OK
   2347  *              -1 - failed.
   2348  */
   2349 {
   2350     int         nLen, nCOS, nPort;
   2351     int         unit = lw->unit;
   2352     pbmp_t      pbm;
   2353     char        pfmt[SOC_PBMP_FMT_LEN];
   2354     int         max_pkt;
   2355     int         max_adj = 0;
   2356     int         jumbo_adj = 0;
   2357     int         num_ports, num_cos;
   2358     int         ppt_max = SOC_DV_PKTS_MAX;
   2359 #ifdef BCM_ESW_SUPPORT
   2360     int         max_set;
   2361     bcm_port_t  port;
   2362 #endif
   2363 
   2364     if (lp->len_start < 64) {
   2365         test_error(unit, "Packet start length %d too small\n", lp->len_start);
   2366         return(-1);
   2367     }
   2368 
   2369     /*
   2370      * Adjust FE_MAXFr, MAXFRr, and GTH_MAXFr as necessary, to
   2371      * accommodate requested packet size.
   2372      */
   2373     max_pkt = lp->len_start;
   2374 
   2375     if (max_pkt < lp->len_end) {
   2376         max_pkt = lp->len_end;
   2377     }
   2378 
   2379     if (max_pkt > LB_JUMBO_MAXSZ) {
   2380         max_pkt = LB_JUMBO_MAXSZ;
   2381     }
   2382 
   2383     if (lp->ppt_start > ppt_max || lp->ppt_end > ppt_max) {
   2384         test_error(unit, "Too many packets per trial (%d, %d).  Max is %d.\n",
   2385                lp->ppt_start, lp->ppt_end, ppt_max);
   2386         lp->ppt_end = lp->ppt_start = ppt_max;
   2387         return -1;
   2388     }
   2389 #ifdef BCM_ESW_SUPPORT
   2390     {
   2391         BCM_PBMP_ASSIGN(pbm, PBMP_E_ALL(unit));
   2392         BCM_PBMP_AND(pbm, lp->pbm);
   2393         BCM_PBMP_ITER(pbm, port) {
   2394             BCM_IF_ERROR_RETURN
   2395                 (bcm_port_frame_max_get(unit, port, &max_set));
   2396             if (max_set < max_pkt) {
   2397                 BCM_IF_ERROR_RETURN
   2398                     (bcm_port_frame_max_set(unit, port, max_pkt));
   2399                 max_adj = 1;
   2400             }
   2401         }
   2402     
   2403         BCM_PBMP_ASSIGN(pbm, PBMP_GE_ALL(unit));
   2404         BCM_PBMP_AND(pbm, lp->pbm);
   2405         PBMP_ITER(pbm, port) {
   2406             if (max_pkt > 1536) {
   2407                 if (soc_feature(unit, soc_feature_trimac)) {
   2408                    uint32              gmacc1;
   2409  
   2410                    SOC_IF_ERROR_RETURN
   2411                        (READ_GMACC1r(unit, port, &gmacc1));
   2412  
   2413                    if (! soc_reg_field_get(unit, GMACC1r, gmacc1, JUMBOf)) {
   2414                        soc_reg_field_set(unit, GMACC1r, &gmacc1, JUMBOf, 1);
   2415                         SOC_IF_ERROR_RETURN
   2416                             (WRITE_GMACC1r(unit, port, gmacc1));
   2417                         jumbo_adj = 1;
   2418                     }
   2419                 }
   2420 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   2421                 else if (soc_feature(unit, soc_feature_unimac)) {
   2422                     SOC_IF_ERROR_RETURN(WRITE_FRM_LENGTHr(unit, port, LB_JUMBO_MAXSZ));
   2423                 }
   2424 #endif
   2425             }
   2426         }
   2427     }
   2428 #endif
   2429 
   2430     if (max_adj) {
   2431         cli_out("NOTICE: Increased max frame size for %d-byte packets\n",
   2432                 max_pkt);
   2433     }
   2434 
   2435     if (jumbo_adj) {
   2436         cli_out("NOTICE: Enabled JUMBO frames on GE\n");
   2437     }
   2438 
   2439     if (lp->len_inc <= 0) {
   2440         test_error(unit, "Increments must be > 0\n");
   2441         return(-1);
   2442     }
   2443 
   2444     if (SOC_IS_XGS(unit) && (lp->test_type == LB2_TT_SNAKE)) {
   2445         if (lp->d_mod_inc <= 0) {
   2446             test_error(unit, "Module increments must be > 0\n");
   2447             return(-1);
   2448         }
   2449     }
   2450 
   2451     BCM_PBMP_ASSIGN(pbm, lp->pbm);
   2452     BCM_PBMP_REMOVE(pbm, PBMP_PORT_ALL(unit));
   2453     if (BCM_PBMP_NOT_NULL(pbm)) {
   2454         test_error(unit,
   2455                    "Invalid bits in port bitmap.\n"
   2456                    "Allowable ports are %s\n",
   2457                    SOC_PBMP_FMT(PBMP_PORT_ALL(unit), pfmt));
   2458         return(-1);
   2459     }
   2460 
   2461     if (lp->cos_start < 0 ||
   2462         lp->cos_end < lp->cos_start ||
   2463         lp->cos_end >= NUM_COS(unit)) {
   2464         test_error(unit,
   2465                    "Invalid COS values: start=%d end=%d\n",
   2466                    lp->cos_start, lp->cos_end);
   2467         return(-1);
   2468     }
   2469 
   2470     if (lp->check_crc) {
   2471         if (lp->crc_mode == LB2_CRC_MODE_CPU_NONE) {
   2472             test_error(unit, "Can't check CRC if not generating it\n");
   2473             return(-1);
   2474         }
   2475         if (lp->loopback == LB2_MODE_MAC) { 
   2476             /* CRC not generated in MAC loopback */
   2477             test_error(unit, "Can't check CRC (not generated in MAC loopback mode)\n");
   2478             return(-1);
   2479         }
   2480     }
   2481 
   2482     nLen = (lp->len_end - lp->len_start) / lp->len_inc + 1;
   2483     nCOS = (lp->cos_end - lp->cos_start) / 1 + 1;
   2484     BCM_PBMP_COUNT(lp->pbm, nPort);
   2485 
   2486     if (lp->test_type == LB2_TT_EXT) {
   2487         assert(nPort % 2 == 0);
   2488         nPort /= 2;
   2489     }
   2490 
   2491     BCM_PBMP_ASSIGN(pbm, lp->pbm);
   2492     BCM_PBMP_AND(pbm, PBMP_HG_ALL(unit));
   2493 
   2494     /*
   2495      *  Packet accumulaion and discard possible due to speed mismatch.
   2496      *  Check if MMU bufering is capable of absorbing this.
   2497      */
   2498     if (SOC_IS_XGS_SWITCH(unit) && 
   2499         ((lp->speed == LB_SPEED_10FD) ||
   2500          (SOC_IS_RAPTOR(unit)) ||
   2501          BCM_PBMP_NOT_NULL(pbm))) {
   2502         int ppte;
   2503         int lene = lp->len_end;
   2504         /* Check that we don't overload the MMU HOL cell limits */
   2505         BCM_IF_ERROR_RETURN(bcm_cosq_config_get(unit, &num_cos));
   2506         num_ports = NUM_ALL_PORT(unit);
   2507         SOC_IF_ERROR_RETURN(_lb_ppte_initval(unit, &lene, &ppte));
   2508         if (lp->len_end > lene) {
   2509             test_error(unit,
   2510                    "Packet length (%d) too Large. Try (%d)\n"
   2511                    "\twith current configuration of %d COS, %d ports.\n",
   2512                    lp->len_end, lene, num_cos, num_ports);
   2513             return (-1);
   2514         }
   2515         if ((lp->ppt_end > ppte) &&
   2516             ((lp->speed == LB_SPEED_100FD) ||
   2517              (lp->speed == LB_SPEED_10FD))) {
   2518             test_error(unit,
   2519                    "Too many packets per chain (%d) for maximum length: %d\n"
   2520                     "\twith current configuration of %d COS, %d ports.\n",
   2521                    lp->ppt_end, lp->len_end, num_cos, num_ports);
   2522             return (-1);
   2523         }
   2524     }
   2525 
   2526     if (lp->test_type == LB2_TT_SNAKE) {
   2527         int icnt, pkt;
   2528         lw->tx_total = 0;
   2529         pkt = lp->ppt_start;
   2530         for (icnt = 0; icnt < lp->iterations; icnt++ ) {
   2531             lw->tx_total += pkt;
   2532 
   2533             if ( lp->ppt_end != lp->ppt_start ) {
   2534                 pkt += lp->ppt_inc;
   2535                 while ( pkt > lp->ppt_end ) {
   2536                     pkt -= lp->ppt_end - lp->ppt_start;
   2537                 }
   2538             }
   2539         }
   2540         test_msg("LB: total %d pkt over %d runs\n",
   2541                  lw->tx_total, lp->iterations);
   2542     } else {
   2543         int ppt, nPkt = 0;
   2544 
   2545         /* Count up total number of pkts per run */
   2546         for (ppt = lp->ppt_start; ppt <= lp->ppt_end; ppt += lp->ppt_inc) {
   2547             nPkt += ppt;
   2548         }
   2549         lw->tx_total = nLen * nCOS * nPort * nPkt * lp->iterations;
   2550         test_msg("LB: total %d pkt (%d len "
   2551                  "* %d COS * %d port * %d packets * %d count)\n",
   2552                  lw->tx_total,
   2553                  nLen, nCOS, nPort, nPkt, lp->iterations);
   2554     }
   2555 
   2556 #ifdef BCM_TOMAHAWK_SUPPORT
   2557     if (!SOC_IS_TOMAHAWKX(unit) && lp->line_rate){
   2558         test_error(unit,
   2559                    "Line rate snake test is only supported on TH/TH2\n");
   2560         lp->line_rate = 0;
   2561         lp->line_rate_count = 1;
   2562         return (-1);
   2563     }
   2564     if (SOC_IS_TOMAHAWKX(unit) && lp->line_rate && SOC_INFO(unit).mmu_lossless){
   2565         test_error(unit, "Line rate snake test is not supported when mmu_lossless = 1\n");
   2566         lp->line_rate = 0;
   2567         lp->line_rate_count = 1;
   2568         return (-1);
   2569     }
   2570 #endif
   2571 
   2572     return(0);
   2573 }
   2574 
   2575 /*
   2576  * Loopback Statistics Report
   2577  */
   2578 
   2579 void
   2580 lbu_stats_init(loopback2_test_t *lw)
   2581 {
   2582     lw->tx_count = 0;
   2583     lw->rx_count = 0;
   2584 
   2585     lw->tx_bytes = 0;
   2586     lw->rx_bytes = 0;
   2587 
   2588     lw->tx_stime = sal_time();
   2589     lw->tx_rtime = lw->tx_stime + sh_set_report_time;
   2590 
   2591     lw->stats_init = TRUE;
   2592 }
   2593 
   2594 STATIC void
   2595 lbu_stats_report(loopback2_test_t *lw)
   2596 {
   2597     sal_time_t          now;
   2598     int                 secs;
   2599 
   2600     if (!sh_set_report_status) {
   2601         return;
   2602     }
   2603 
   2604     /*
   2605      * Feel free to call this routine after every packet sent.
   2606      * It will only report stats every "sh_set_report_time" seconds.
   2607      */
   2608 
   2609     now = sal_time();
   2610 
   2611     if ((secs = (now - lw->tx_stime)) == 0) {
   2612         secs = 1;
   2613     }
   2614 
   2615     if (now >= lw->tx_rtime) {
   2616         test_msg("LB: xmit %d pkt (%d%%, %d pkt/s, %d KB/s avg), "
   2617                  "recv %d pkt (%d sec)\n", lw->tx_count,
   2618                  100 * lw->rx_count / lw->tx_total,
   2619                  lw->tx_count / secs,
   2620                  lw->tx_bytes / 1024 / secs,
   2621                  lw->rx_count, secs);
   2622 
   2623         lw->tx_rtime += sh_set_report_time;
   2624     }
   2625 }
   2626 
   2627 void
   2628 lbu_stats_done(loopback2_test_t *lw)
   2629 {
   2630     if (lw->stats_init && lw->tx_count > 0) {
   2631         lw->tx_rtime = 0;               /* Force output now */
   2632         lbu_stats_report(lw);
   2633     }
   2634 }
   2635 
   2636 
   2637 /*
   2638  * Print bytes as %d,%2.2fK, %2.2fG, etc.
   2639  */
   2640 static void
   2641 snake_show_number(uint64 size)
   2642 {
   2643     uint32 value;
   2644     char *s;
   2645 
   2646     s = _shr_scale_uint64(size, 1024, 100, &value);
   2647     if (s) {
   2648         cli_out("%d.%02d%s", value / 100, value % 100, s);
   2649     } else {
   2650         value = COMPILER_64_LO(size);
   2651         cli_out("%d", value);
   2652     }
   2653 }
   2654 
   2655 /*
   2656  * Print rate as %d,%2.2fG, etc.
   2657  */
   2658 static void
   2659 snake_show_rate(uint32 size)
   2660 {
   2661     uint64 size64;
   2662     uint32 value;
   2663     char *s;
   2664 
   2665     COMPILER_64_SET(size64, 0, size);
   2666     s = _shr_scale_uint64(size64, 1024, 100, &value);
   2667     if (s) {
   2668         cli_out("%d.%02d%s", value / 100, value % 100, s);
   2669     } else {
   2670         cli_out("%d", size);
   2671     }
   2672 }
   2673 
   2674 int
   2675 lbu_snake_stats(int unit, bcm_pbmp_t sel_pbm, int lb_mode, 
   2676                 lb2_port_stat_t *stats)
   2677 /*
   2678  * Function:    lbu_snake_stats
   2679  * Purpose:     Check error/pkt stats during run to see if packets still
   2680  *              running smoothly.  Notify if not.
   2681  *              Most of this routine is blantanly stolen from the
   2682  *              traffic test.
   2683  * Parameters:  unit - device number.
   2684  *              sel_pbm - port bitmap of selected ports.
   2685  *              mac_lb - (BOOL) TRUE if MAC loopback mode.
   2686  *              stats - pointer to stats records.
   2687  * Returns:     0 - success, -1 error detected.
   2688  */
   2689 {
   2690     int             port;
   2691     int             port_error, error = 0;
   2692     int             stopped;
   2693     pbmp_t          pbm;
   2694     uint32          tolerance;
   2695 
   2696     uint64 rbyt, tbyt, rpkt, tpkt, rerr,raln, rdisc, dropped;
   2697     uint64 drbyt, dtbyt, drpkt, dtpkt, drerr, draln, drdisc, ddropped;
   2698 
   2699     COMPILER_64_ZERO(rbyt);    COMPILER_REFERENCE(&rbyt);
   2700     COMPILER_64_ZERO(tbyt);    COMPILER_REFERENCE(&tbyt);   
   2701     COMPILER_64_ZERO(rpkt);    COMPILER_REFERENCE(&rpkt);   
   2702     COMPILER_64_ZERO(tpkt);    COMPILER_REFERENCE(&tpkt);   
   2703     COMPILER_64_ZERO(rerr);    COMPILER_REFERENCE(&rerr);   
   2704     COMPILER_64_ZERO(raln);    COMPILER_REFERENCE(&raln);   
   2705     COMPILER_64_ZERO(rdisc);   COMPILER_REFERENCE(&rdisc);    
   2706     COMPILER_64_ZERO(dropped); COMPILER_REFERENCE(&dropped);
   2707     COMPILER_64_ZERO(drbyt);   COMPILER_REFERENCE(&drbyt); 
   2708     COMPILER_64_ZERO(dtbyt);   COMPILER_REFERENCE(&dtbyt);   
   2709     COMPILER_64_ZERO(drpkt);   COMPILER_REFERENCE(&drpkt);   
   2710     COMPILER_64_ZERO(dtpkt);   COMPILER_REFERENCE(&dtpkt);    
   2711     COMPILER_64_ZERO(drerr);   COMPILER_REFERENCE(&drerr);   
   2712     COMPILER_64_ZERO(draln);   COMPILER_REFERENCE(&draln);    
   2713     COMPILER_64_ZERO(drdisc);  COMPILER_REFERENCE(&drdisc);    
   2714     COMPILER_64_ZERO(ddropped);COMPILER_REFERENCE(&ddropped);
   2715 
   2716     bcm_stat_sync(unit);
   2717 
   2718     PBMP_ITER(sel_pbm, port) {
   2719         /*
   2720          *      To account for counters such as IRDISC
   2721          */
   2722         tolerance = IS_HG_PORT(unit, port) ? 1 : 0;
   2723         port_error = 0;
   2724         stopped = 0;
   2725 
   2726         bcm_stat_get(unit, port, snmpIfInOctets, &rbyt);
   2727         bcm_stat_get(unit, port, snmpIfOutOctets,&tbyt);
   2728         bcm_stat_get(unit, port, snmpDot1dTpPortOutFrames, &tpkt);
   2729         bcm_stat_get(unit, port, snmpDot1dTpPortInFrames,  &rpkt);
   2730         bcm_stat_get(unit, port, snmpDot3StatsAlignmentErrors, 
   2731                      &raln);
   2732         bcm_stat_get(unit, port, 
   2733                      snmpDot3StatsInternalMacReceiveErrors, &rdisc);
   2734         bcm_stat_get(unit, port, snmpIfInDiscards, &dropped);
   2735 
   2736         if (!stats[port].initialized) {
   2737             stats[port].rbyt = rbyt;
   2738             stats[port].tbyt = tbyt;
   2739             stats[port].rpkt = rpkt;
   2740             stats[port].tpkt = tpkt;            
   2741 
   2742             stats[port].raln = raln;            
   2743             stats[port].rdisc = rdisc;
   2744             stats[port].dropped = dropped; 
   2745             stats[port].error = 0;
   2746 #ifdef BCM_TOMAHAWK_SUPPORT
   2747             COMPILER_64_ZERO(stats[port].rate);
   2748 #endif
   2749             stats[port].initialized = TRUE;
   2750         } else {
   2751             int speed, duplex;
   2752             uint32 dtpktl, dtbytl, drpktl, drbytl;
   2753             uint32 dralnl, drdiscl, ddroppedl;
   2754 
   2755             COMPILER_64_DELTA(drbyt, stats[port].rbyt, rbyt);
   2756             COMPILER_64_DELTA(dtbyt, stats[port].tbyt, tbyt);
   2757             COMPILER_64_DELTA(drpkt, stats[port].rpkt, rpkt);
   2758             COMPILER_64_DELTA(dtpkt, stats[port].tpkt, tpkt);
   2759             COMPILER_64_DELTA(draln, stats[port].raln, raln);
   2760             COMPILER_64_DELTA(drdisc, stats[port].rdisc,
   2761                              rdisc);
   2762             COMPILER_64_DELTA(ddropped, stats[port].dropped,
   2763                              dropped);
   2764 
   2765             COMPILER_64_TO_32_LO(drbytl, drbyt);
   2766             COMPILER_64_TO_32_LO(dtbytl, dtbyt);
   2767             COMPILER_64_TO_32_LO(drpktl, drpkt);
   2768             COMPILER_64_TO_32_LO(dtpktl, dtpkt);
   2769             COMPILER_64_TO_32_LO(dralnl, draln);
   2770             COMPILER_64_TO_32_LO(drdiscl, drdisc);
   2771             COMPILER_64_TO_32_LO(ddroppedl, ddropped);
   2772 
   2773             switch (lb_mode) {
   2774             case LB2_MODE_MAC:
   2775                 if (dtpktl == 0 || dtbytl == 0 ||
   2776                     ((drpktl == 0 || drbytl == 0) &&
   2777                      (IS_FE_PORT(unit, port) || IS_GE_PORT(unit, port)))) {
   2778                     stopped = -1;
   2779                 }
   2780                 break;
   2781             case LB2_MODE_PHY:
   2782                 if (dtpktl == 0 || dtbytl == 0 || 
   2783                     drpktl == 0 || drbytl == 0) {
   2784                     stopped = -1;
   2785                 }
   2786                 break;
   2787             case LB2_MODE_EXT:
   2788                 /* Don't check for stopped yet */
   2789                 break;
   2790             default:
   2791                 assert(0);
   2792             }
   2793 
   2794             if ((drdiscl > tolerance) || (ddroppedl > 0) || 
   2795                 (stopped < 0) || 
   2796                 ((dralnl > tolerance) && 
   2797                  (IS_FE_PORT(unit, port) || IS_GE_PORT(unit, port)))) {
   2798                 port_error = -1;
   2799                 error = -1;
   2800             }
   2801 
   2802             bcm_port_speed_get(unit, port, &speed);
   2803             bcm_port_duplex_get(unit, port, &duplex);
   2804 
   2805             if (port_error < 0) {
   2806                 cli_out("Port %s (%d) (",
   2807                         SOC_PORT_NAME(unit, port), port);
   2808                 snake_show_rate(speed * 1000000);
   2809                 cli_out("b %s): ",
   2810                         duplex ? "FD" : "HD");
   2811                 if ((dralnl > tolerance) && 
   2812                     (IS_FE_PORT(unit, port) || IS_GE_PORT(unit, port))) {
   2813                     cli_out("ALN Error Detected\n");
   2814                 } else if (drdiscl > tolerance) {
   2815                     cli_out("Discard Error Detected\n");
   2816                 } else if (ddroppedl > 0) {
   2817                     cli_out("Dropped Error Detected\n");
   2818                 } else if (stopped < 0) {
   2819                     cli_out("FAIL->NO TRAFFIC\n");
   2820                 } else {
   2821                     cli_out("PASSED\n");
   2822                 }
   2823 
   2824                 cli_out("\tTX packets ");
   2825                 snake_show_number(tpkt);
   2826                 cli_out(" +");
   2827                 snake_show_number(dtpkt);
   2828                 cli_out("/s, bytes ");
   2829                 snake_show_number(tbyt);
   2830                 cli_out("B +");
   2831                 snake_show_number(dtbyt);
   2832                 cli_out("B/s [");
   2833                 snake_show_rate(dtbytl*8);
   2834                 cli_out("b/s]\n");               
   2835                 cli_out("\tRX packets ");
   2836                 snake_show_number(rpkt);
   2837                 cli_out(" +");
   2838                 snake_show_number(drpkt);
   2839                 cli_out("/s, bytes ");
   2840                 snake_show_number(rbyt);
   2841                 cli_out("B +");
   2842                 snake_show_number(drbyt);
   2843                 cli_out("B/s [");
   2844                 snake_show_rate(drbytl*8);
   2845                 cli_out("b/s]\n");
   2846             }
   2847 
   2848             /* Zero packet rate increase indicates failure */
   2849 
   2850             if (stopped < 0) {
   2851                 test_error(unit, 
   2852                            "ERROR: traffic stopped on port %s (%d)\n",
   2853                            SOC_PORT_NAME(unit, port), port);
   2854  
   2855                 /* Give us a clue .. */
   2856                 cli_out("Port %s (%d) statistics:\n",
   2857                         SOC_PORT_NAME(unit, port), port);
   2858                 SOC_PBMP_CLEAR(pbm);
   2859                 SOC_PBMP_PORT_ADD(pbm, port);
   2860                 if (SOC_IS_ESW(unit)) {
   2861 #ifdef BCM_ESW_SUPPORT
   2862                         do_show_counters(unit,
   2863                                      INVALIDr,
   2864                                      pbm,
   2865                                  SHOW_CTR_CHANGED|
   2866                                  SHOW_CTR_SAME|
   2867                                  SHOW_CTR_NZ);              
   2868 #endif
   2869                     } else {
   2870                     }               
   2871             }
   2872 
   2873             stats[port].rbyt = rbyt;
   2874             stats[port].tbyt = tbyt;
   2875             stats[port].rpkt = rpkt;
   2876             stats[port].tpkt = tpkt;            
   2877 
   2878             stats[port].raln = raln;            
   2879             stats[port].rdisc = rdisc;
   2880             stats[port].dropped = dropped;      
   2881             stats[port].error = port_error;
   2882         }
   2883     }
   2884 
   2885     return error;
   2886 }
   2887 
   2888 STATIC int
   2889 lbu_snake_diag(loopback2_test_t *lw, lb2_port_stat_t *stats, 
   2890                lb2s_port_connect_t *connect_info)
   2891 /*
   2892  * Function:    lbu_snake_diag
   2893  * Purpose:     Attempt to determing snake failure cause
   2894  * Parameters:  lw - pointer to lb work.
   2895  *              stats - pointer to port statistics.
   2896  *              connect_info - port interlink data.
   2897  * Returns:     0 - success, -1 failed.
   2898  */
   2899 {
   2900     loopback2_testdata_t  *lp = lw->cur_params;
   2901     int             unit = lw->unit;
   2902     soc_port_t      thisPort, toPort;
   2903     int             ix, rv = 0;
   2904     uint32          tempStat, tolerance = 0;
   2905     uint64          tempDiff;
   2906 
   2907     COMPILER_64_ZERO(tempDiff);
   2908 
   2909     for (ix = 0; ix < lw->port_count; ix++) {
   2910         thisPort = connect_info[ix].this_port;
   2911         toPort = connect_info[ix].to_port;
   2912 
   2913         COMPILER_64_TO_32_LO(tempStat, stats[thisPort].tpkt);
   2914         LOG_INFO(BSL_LS_APPL_TESTS,
   2915                  (BSL_META_U(unit,
   2916                              "Port %s Tx Count = 0x%x\n"), 
   2917                   SOC_PORT_NAME(unit, thisPort), tempStat));
   2918 
   2919         if (tempStat == 0) {
   2920             test_error(unit, "Port %s failed to send packets\n", 
   2921                        SOC_PORT_NAME(unit, thisPort));
   2922             rv = -1;
   2923         }
   2924 
   2925         /* BigMac receive counters don't work in MAC loopback */
   2926         if (((IS_FE_PORT(unit, thisPort) || IS_GE_PORT(unit, thisPort)) &&
   2927               (lp->loopback == LB2_MODE_MAC))) {
   2928             COMPILER_64_TO_32_LO(tempStat, stats[thisPort].rpkt);
   2929             LOG_INFO(BSL_LS_APPL_TESTS,
   2930                      (BSL_META_U(unit,
   2931                                  "Port %s Rx Count = 0x%x\n"), 
   2932                       SOC_PORT_NAME(unit, thisPort), tempStat));
   2933 
   2934             if (tempStat == 0) {
   2935                 test_error(unit, "Port %s failed to receive packets\n", 
   2936                            SOC_PORT_NAME(unit, thisPort));
   2937                 rv = -1;
   2938             }
   2939 
   2940             COMPILER_64_DELTA(tempDiff, stats[thisPort].rpkt, 
   2941                              stats[thisPort].tpkt);
   2942             COMPILER_64_TO_32_LO(tempStat, tempDiff);
   2943             if ((tempStat > tolerance) && (tempStat < (~tolerance + 1))) {
   2944                 COMPILER_64_TO_32_LO(tempStat, stats[thisPort].tpkt);
   2945                 cli_out("\t0x%x packets transmitted by port %s\n",
   2946                         tempStat, SOC_PORT_NAME(unit, thisPort));
   2947                 COMPILER_64_TO_32_LO(tempStat, stats[thisPort].rpkt);
   2948                 cli_out("\t0x%x packets received by port %s\n", 
   2949                         tempStat, SOC_PORT_NAME(unit, thisPort));
   2950                 test_error(unit, "Port %s loopback failure\n", 
   2951                            SOC_PORT_NAME(unit, thisPort));
   2952                 rv = -1;
   2953             }
   2954         }
   2955 
   2956         /* BigMac receive counters don't work in MAC loopback */
   2957         if (((IS_FE_PORT(unit, toPort) || IS_GE_PORT(unit, toPort)) &&
   2958               (lp->loopback == LB2_MODE_MAC))) {
   2959             COMPILER_64_DELTA(tempDiff, stats[toPort].tpkt, 
   2960                              stats[toPort].rpkt);
   2961             COMPILER_64_TO_32_LO(tempStat, tempDiff);
   2962 
   2963             tolerance = (IS_HG_PORT(unit, toPort) || 
   2964                          IS_HG_PORT(unit, thisPort)) ? 
   2965                 lw->tx_ppt : 0;
   2966             if ((tempStat > tolerance) && (tempStat < (~tolerance + 1))) {
   2967                 COMPILER_64_TO_32_LO(tempStat, stats[toPort].rpkt);
   2968                 cli_out("\t0x%x packets received by port %s\n", 
   2969                         tempStat, SOC_PORT_NAME(unit, toPort));
   2970                 COMPILER_64_TO_32_LO(tempStat, stats[thisPort].tpkt);
   2971                 cli_out("\t0x%x packets transmitted by port %s\n",
   2972                         tempStat, SOC_PORT_NAME(unit, thisPort));
   2973                 test_error(unit, 
   2974                            "Port %s failed to switch packets to port %s\n",
   2975                            SOC_PORT_NAME(unit, toPort),
   2976                            SOC_PORT_NAME(unit, thisPort));
   2977                 rv = -1;
   2978             }
   2979         }
   2980 
   2981         
   2982     }
   2983 
   2984     return rv;
   2985 }
   2986 
   2987 void
   2988 lbu_snake_dump_stats(int unit, bcm_pbmp_t sel_pbm, lb2_port_stat_t *stats)
   2989 /*
   2990  * Function:    lbu_snake_dump_stats
   2991  * Purpose:     Display port stats for diagnosis purposes
   2992  * Parameters:  unit - device number.
   2993  *              sel_pbm - port bitmap of selected ports.
   2994  *              stats - pointer to stats records.
   2995  */
   2996 {
   2997     soc_port_t      port;
   2998 #ifdef BCM_TOMAHAWK_SUPPORT
   2999     char            buf_rate[32];
   3000     int             commachr = soc_property_get(unit, spn_DIAG_COMMA, ',');
   3001 #endif
   3002     COMPILER_REFERENCE(unit);
   3003 
   3004     PBMP_ITER(sel_pbm, port) {
   3005         cli_out("Port %s", SOC_PORT_NAME(unit, port));
   3006         cli_out("\tTX ");
   3007         snake_show_number(stats[port].tpkt);
   3008         cli_out("pkt ");
   3009         snake_show_number(stats[port].tbyt);
   3010         cli_out("B,\tRX ");
   3011         snake_show_number(stats[port].rpkt);
   3012         cli_out("pkt ");
   3013         snake_show_number(stats[port].rbyt);
   3014         cli_out("B");
   3015 #ifdef BCM_TOMAHAWK_SUPPORT
   3016         if (!COMPILER_64_IS_ZERO(stats[port].rate)){
   3017             format_uint64_decimal(buf_rate, stats[port].rate, commachr);
   3018             cli_out("  Rate %16sB/s", buf_rate);
   3019         }
   3020 #endif
   3021         cli_out("\n");
   3022     }
   3023 }
   3024 
   3025 
   3026 /* Set up the basic packet data that can vary with each transmit */
   3027 
   3028 STATIC void
   3029 lbu_serial_higig_setup(int unit, loopback2_testdata_t *lp, bcm_pkt_t *pkt)
   3030 {
   3031     pkt->opcode = lp->opcode;
   3032     pkt->dest_port = lp->d_port;
   3033     pkt->dest_mod = lp->d_mod;
   3034     bcm_tx_pkt_setup(unit, pkt);
   3035 }
   3036 
   3037 STATIC void
   3038 lbu_snake_higig_setup(int unit, loopback2_testdata_t *lp,
   3039                       lb2s_port_connect_t *port_info, bcm_pkt_t *pkt)
   3040 {
   3041     pkt->opcode = lp->opcode;
   3042     pkt->dest_port = port_info->to_port;
   3043     pkt->dest_mod = port_info->dst_modid;
   3044     bcm_tx_pkt_setup(unit, pkt);
   3045 }
   3046 
   3047 STATIC void
   3048 lbu_pkt_data_setup(loopback2_test_t *lw, bcm_pkt_t *pkt, bcm_vlan_t vlan,
   3049                    sal_mac_addr_t mac_dst, sal_mac_addr_t mac_src, int seq_no)
   3050 {
   3051     loopback2_testdata_t *lp = lw->cur_params;
   3052     enet_hdr_t           *eh = NULL;
   3053     int tx_len, payload_len;
   3054     uint8                *sequence_p;
   3055     int cur_offset;
   3056 
   3057     tx_len = pkt->pkt_data[0].len;
   3058     if (pkt->flags & BCM_TX_CRC_ALLOC) {
   3059         payload_len = tx_len - 18;
   3060     } else {
   3061         payload_len = tx_len - 22;
   3062     }
   3063 
   3064     eh = (enet_hdr_t *)BCM_PKT_DMAC(pkt);
   3065 
   3066     /* Write source/destination MAC address */
   3067     ENET_SET_MACADDR(&eh->en_dhost, mac_dst);
   3068     ENET_SET_MACADDR(&eh->en_shost, mac_src);
   3069 
   3070     /* Write VLAN tag (16 + 16 bits) and sequence number (32 bits) */
   3071     packet_store((uint8 *)&eh->en_tag_tpid, 2, 0x8100 << 16, 0);
   3072     packet_store((uint8 *)&eh->en_tag_ctrl, 2,
   3073                  VLAN_CTRL(0, 0, vlan) << 16, 0);
   3074     packet_store((uint8*)eh + 16, 4, lw->tx_seq++, 0);
   3075     packet_store((uint8*)&eh->en_tag_len, 2, payload_len << 16, 0);
   3076 
   3077     /*
   3078      * Fill data from after header & seq # to end of packet.  Byte data
   3079      * starts with the pattern MSByte through LSByte and recycles.
   3080      * Optionally overwrite last 4 bytes of packet with correct CRC.
   3081      */
   3082     cur_offset = 20;
   3083     lp->pattern = packet_store((uint8*)eh + cur_offset, tx_len - cur_offset,
   3084                                   lp->pattern, lp->pattern_inc);
   3085 
   3086     /* Store the sequence number of the packet */
   3087     sequence_p = (uint8 *)eh + LB2_ID_POS;
   3088     *sequence_p = (uint8)seq_no;
   3089 
   3090     if (lp->crc_mode == LB2_CRC_MODE_CPU_APPEND) {
   3091         packet_store((uint8*)eh + tx_len - 4, 4,
   3092                      ~_shr_crc32(~0, (uint8*)eh, tx_len - 4), 0);
   3093     } 
   3094 
   3095     if (SOC_IS_XGS12_FABRIC(lw->unit)) { 
   3096         if (lp->crc_mode == LB2_CRC_MODE_MAC_REGEN) { 
   3097             /* hercules always requires CRC field to be zero */
   3098             packet_store(((uint8*)eh + (tx_len) - 4), 4, 0, 0);
   3099         }
   3100     }
   3101 }
   3102 
   3103 /*
   3104  * This routine is called by
   3105  * The dest ports only need to be set up once */
   3106 
   3107 STATIC void
   3108 lbu_pkt_init(bcm_pkt_t **pkts, int max_ppt, int tx_port, int tagged)
   3109 {
   3110     int i;
   3111     bcm_pkt_t *pkt;
   3112 
   3113     for (i = 0; i < max_ppt; i++) {
   3114         pkt = pkts[i];
   3115 
   3116         SOC_PBMP_CLEAR(pkt->tx_pbmp);
   3117         SOC_PBMP_PORT_ADD(pkt->tx_pbmp, tx_port);
   3118         SOC_PBMP_CLEAR(pkt->tx_upbmp);
   3119         if (!tagged) {
   3120             SOC_PBMP_PORT_ADD(pkt->tx_upbmp, tx_port);
   3121         }
   3122     }
   3123 }
   3124 
   3125 /* Set up a chain of packets according to current settings */
   3126 
   3127 STATIC int
   3128 lbu_pkt_chain_setup(bcm_pkt_t **pkts, int ppt, int len, int cos,
   3129                     loopback2_test_t *lw)
   3130 {
   3131     loopback2_testdata_t *lp = lw->cur_params;
   3132     int                  i;
   3133     sal_mac_addr_t       cur_mac_dst, cur_mac_src;
   3134     bcm_pkt_t            *pkt;
   3135 
   3136     /* Init the src/dest mac addresses each chain */
   3137     ENET_SET_MACADDR(cur_mac_dst, lw->base_mac_dst);
   3138     ENET_SET_MACADDR(cur_mac_src, lw->base_mac_src);
   3139 
   3140     for (i = 0; i < ppt; i++) {
   3141 
   3142         pkt = pkts[i];
   3143         pkt->cos = cos;
   3144         /* For now, internal priority matches COS (or v.v.) */
   3145         pkt->prio_int = cos;
   3146         pkt->pkt_data[0].len = len; /* Set length properly for pkt */
   3147 
   3148         lbu_pkt_data_setup(lw, pkt, lp->vlan, cur_mac_dst, cur_mac_src, i);
   3149         if (SOC_IS_XGS(lw->unit)) {
   3150             lbu_serial_higig_setup(lw->unit, lp, pkt);
   3151         }
   3152 #ifdef BCM_XGS3_SWITCH_SUPPORT
   3153         /*
   3154          * Setup the Higig header for XGS3 devices
   3155          */
   3156         if (SOC_IS_XGS3_SWITCH(lw->unit) && !(SOC_IS_TOMAHAWK3(lw->unit))) {
   3157             int         dmod;
   3158             uint32      vlan;
   3159             int         unit = lw->unit;
   3160             soc_higig_hdr_t  *xgh = (soc_higig_hdr_t*)pkt->_higig;
   3161             BCM_IF_ERROR_RETURN(bcm_stk_my_modid_get(unit, &dmod));
   3162             if (SOC_IS_HAWKEYE(unit) || (SOC_IS_RAPTOR(unit) && IS_E_PORT(unit, lw->tx_port))) {
   3163             } else {
   3164                 /* Fabric mapped mode TX */
   3165                 pkt->flags |= (BCM_TX_ETHER | BCM_TX_HG_READY);
   3166             }
   3167             pkt->dest_mod = dmod;
   3168             pkt->src_mod = dmod + 1;
   3169             pkt->src_port =  CMIC_PORT(unit);
   3170             pkt->dest_port = lw->tx_port;
   3171             if (IS_ST_PORT(unit,  pkt->dest_port)) {
   3172                 pkt->opcode = 0; /* CPU control for HG ports */
   3173             } else {
   3174                 pkt->opcode = 1; /* UNICAST  for E ports */
   3175             }
   3176             sal_memset(xgh, 0, sizeof(pkt->_higig));
   3177 #ifdef BCM_HIGIG2_SUPPORT
   3178             if (soc_feature(unit, soc_feature_higig2)) {
   3179                 soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG2_START);
   3180             } else {
   3181                 soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG_START);
   3182             }
   3183 #else
   3184             soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG_START);
   3185 #endif
   3186             soc_higig_field_set(unit, xgh, HG_hgi, SOC_HIGIG_HGI);
   3187             soc_higig_field_set(unit, xgh, HG_opcode, pkt->opcode);
   3188             soc_higig_field_set(unit, xgh, HG_hdr_format, SOC_HIGIG_HDR_DEFAULT);
   3189             vlan = BCM_PKT_VLAN_CONTROL(pkt);
   3190             soc_higig_field_set(unit, xgh, HG_vlan_tag, vlan);
   3191             soc_higig_field_set(unit, xgh, HG_dst_mod, pkt->dest_mod);
   3192             soc_higig_field_set(unit, xgh, HG_dst_port, pkt->dest_port);
   3193             soc_higig_field_set(unit, xgh, HG_src_mod, pkt->src_mod);
   3194             soc_higig_field_set(unit, xgh, HG_src_port, pkt->src_port);
   3195             soc_higig_field_set(unit, xgh, HG_cos, pkt->cos);
   3196             soc_higig_field_set(unit, xgh, HG_ingress_tagged, 1);
   3197         }
   3198 #endif
   3199         increment_macaddr(cur_mac_dst, lp->mac_dst_inc);
   3200         increment_macaddr(cur_mac_src, lp->mac_src_inc);
   3201     }
   3202 
   3203     return BCM_E_NONE;
   3204 }
   3205 
   3206 /* Set up a chain of packets according to current settings */
   3207 
   3208 STATIC int
   3209 lbu_snake_pkt_chain_setup(bcm_pkt_t **pkts, int ppt, int len, int cos,
   3210                     loopback2_test_t *lw)
   3211 {
   3212     loopback2_testdata_t *lp = lw->cur_params;
   3213     int                  i;
   3214     bcm_pkt_t           *pkt;
   3215     lb2s_port_connect_t *work_info, *f_info, *r_info;
   3216     int                 snake_way = lp->snake_way;
   3217     int                 forward, both;
   3218 
   3219     both = (snake_way == LB2_SNAKE_BOTH);
   3220     forward = (snake_way == LB2_SNAKE_BOTH) || (snake_way == LB2_SNAKE_INCR);
   3221 
   3222     f_info = lw->port_cnct_f;
   3223     r_info = lw->port_cnct_r;
   3224     work_info = forward ? f_info : r_info;
   3225 
   3226     for (i = 0; i < ppt; i++) {
   3227 
   3228         pkt = pkts[i];
   3229         pkt->cos = cos;
   3230         /* For now, internal priority matches COS (or v.v.) */
   3231         pkt->prio_int = cos;
   3232         pkt->pkt_data[0].len = len; /* Set length properly for pkt */
   3233         SOC_PBMP_CLEAR(pkt->tx_pbmp);
   3234         SOC_PBMP_PORT_ADD(pkt->tx_pbmp, work_info->this_port);
   3235         SOC_PBMP_CLEAR(pkt->tx_upbmp);
   3236         SOC_PBMP_PORT_ADD(pkt->tx_upbmp, work_info->this_port);
   3237 
   3238         if (both) {
   3239             work_info = (i % 2) ? r_info : f_info;
   3240         }
   3241         
   3242         lbu_pkt_data_setup(lw, pkt, work_info[lw->port_count].added_vlan, 
   3243                            work_info->dst_mac, work_info->src_mac, i);
   3244         if (SOC_IS_XGS(lw->unit)) {
   3245             lbu_snake_higig_setup(lw->unit, lp, work_info, pkt);
   3246         }
   3247 #ifdef BCM_XGS3_SWITCH_SUPPORT
   3248         /*
   3249          * Setup the Higig header for XGS3 devices
   3250          */
   3251         if (SOC_IS_XGS3_SWITCH(lw->unit) && 
   3252             !IS_ST_PORT(lw->unit, work_info->this_port) &&
   3253             !SOC_IS_TOMAHAWK3(lw->unit)) {
   3254             int         dmod;
   3255             uint32      vlan;
   3256             int         unit = lw->unit;
   3257             soc_higig_hdr_t  *xgh = (soc_higig_hdr_t*)pkt->_higig;
   3258             BCM_IF_ERROR_RETURN(bcm_stk_my_modid_get(unit, &dmod));
   3259             if (SOC_IS_HAWKEYE(unit) || (SOC_IS_RAPTOR(unit) && IS_E_PORT(unit, work_info->this_port))) {
   3260             } else {
   3261                 /* Fabric mapped mode TX */
   3262                 pkt->flags |= (BCM_TX_ETHER | BCM_TX_HG_READY);
   3263             }
   3264             pkt->src_mod = pkt->dest_mod = dmod;
   3265             pkt->src_port =  CMIC_PORT(unit);
   3266             pkt->dest_port = work_info->this_port;
   3267             pkt->opcode = lp->opcode;
   3268             sal_memset(xgh, 0, sizeof(pkt->_higig));
   3269 #ifdef BCM_HIGIG2_SUPPORT
   3270             if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_TR_VL(unit)) {
   3271                 soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG2_START);
   3272             } else {
   3273                 soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG_START);
   3274             }
   3275 #else
   3276             soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG_START);
   3277 #endif
   3278             soc_higig_field_set(unit, xgh, HG_hgi, SOC_HIGIG_HGI);
   3279             soc_higig_field_set(unit, xgh, HG_opcode, pkt->opcode);
   3280             soc_higig_field_set(unit, xgh, HG_hdr_format, SOC_HIGIG_HDR_DEFAULT);
   3281             vlan = BCM_PKT_VLAN_CONTROL(pkt);
   3282             soc_higig_field_set(unit, xgh, HG_vlan_tag, vlan);
   3283             soc_higig_field_set(unit, xgh, HG_dst_mod, pkt->dest_mod);
   3284             soc_higig_field_set(unit, xgh, HG_dst_port, pkt->dest_port);
   3285             soc_higig_field_set(unit, xgh, HG_src_mod, pkt->src_mod);
   3286             soc_higig_field_set(unit, xgh, HG_src_port, pkt->src_port);
   3287             soc_higig_field_set(unit, xgh, HG_cos, pkt->cos);
   3288             soc_higig_field_set(unit, xgh, HG_ingress_tagged, 1);
   3289         }
   3290 #endif
   3291     }
   3292 
   3293     return BCM_E_NONE;
   3294 }
   3295 
   3296 STATIC int
   3297 lbu_send_packets(int unit, bcm_pkt_t **pkts, int ppt, loopback2_test_t *lw)
   3298 {
   3299     int rv = BCM_E_NONE, i;
   3300     int try_cnt = 0;
   3301 #ifdef BCM_TOMAHAWK_SUPPORT
   3302     int j;
   3303 #endif
   3304 
   3305     lw->expect_pkts = TRUE; /* Let RX handler accept packets */
   3306 
   3307     switch (lw->cur_params->send_mech) {
   3308         case LBD_SEND_SINGLE:
   3309 #ifdef BCM_TOMAHAWK_SUPPORT
   3310             if (!lw->cur_params->line_rate) {
   3311                 lw->cur_params->line_rate_count = 1;
   3312             }
   3313             for (j = 0; j < lw->cur_params->line_rate_count; j++) {
   3314 #endif
   3315                 for (i = 0; i < ppt; i++ ) {
   3316                     /*Need try until the memor was free and then send next one*/
   3317                     for (try_cnt = 50; try_cnt > 0; try_cnt--) {
   3318                         rv = bcm_tx(unit, pkts[i], NULL);
   3319                         if (rv == BCM_E_MEMORY) {
   3320                             sal_usleep(1);
   3321                             continue;
   3322                         }
   3323                         break;
   3324                     }
   3325 
   3326                     if (rv < 0) {
   3327                         cli_out("lbu_send_packets: ERROR: port%d: bcm_tx:%s\n",
   3328                                  lw->tx_port, bcm_errmsg(rv));
   3329                     }
   3330                     lw->tx_count++;
   3331                     lw->tx_bytes += lw->tx_len;
   3332                 }
   3333 #ifdef BCM_TOMAHAWK_SUPPORT
   3334             }
   3335 #endif
   3336         break;
   3337         case LBD_SEND_ARRAY:
   3338         if ((rv = bcm_tx_array(unit, pkts, ppt, NULL, NULL)) < 0) {
   3339             cli_out("lbu_send_packets (array): ERROR: port %d; ppt %d; "
   3340                     "bcm_tx: %s\n", lw->tx_port, ppt, bcm_errmsg(rv));
   3341         }
   3342         lw->tx_count += ppt;
   3343         lw->tx_bytes += lw->tx_len * ppt;
   3344         break;
   3345     case LBD_SEND_LLIST:
   3346     default:
   3347         cli_out("lbu_send_packets: Unsupported send mechanism\n");
   3348         return BCM_E_UNAVAIL;
   3349         break;
   3350     }
   3351 
   3352     return rv;
   3353 }
   3354 
   3355 STATIC int
   3356 lbu_serial_wait(loopback2_test_t *lw)
   3357 {
   3358     int unit = lw->unit;
   3359     int ix;
   3360     bcm_pkt_t *next_rx;
   3361 
   3362     if (sal_sem_take(lw->sema, lw->timeout_usec)) {
   3363         cli_out("Time-out waiting for completion Tx(%s) Rx(%s)\n",
   3364                 SOC_PORT_NAME(unit, lw->tx_port),
   3365                 SOC_PORT_NAME(unit, lw->rx_port));
   3366         cli_out("Receive count is %d; expecting %d pkts.\n",
   3367                 lw->rx_pkt_cnt, lw->tx_ppt);
   3368         lbu_stats_report(lw);
   3369         lw->sema_woke = FALSE;
   3370         return (-1);
   3371     }
   3372 
   3373     lw->sema_woke = FALSE;    
   3374     /*
   3375         The reason for this change is some strange SW synchronization 
   3376         issue that is observed only on NSX CPU with Linux 2.6 OS 
   3377         Seems that an RX handler releases the semaphor but not all 
   3378         packets are updated in the SW structure.
   3379     */
   3380 #if 0 
   3381     lw->expect_pkts = FALSE; /* Let RX handler ignore packets */
   3382 #endif
   3383 
   3384     for (ix = 0; ix < lw->tx_ppt; ix++) {
   3385         next_rx = LB2_RX_PKT(lw, ix);
   3386         if (!next_rx->_pkt_data.data) {
   3387             /* This change is intentional to avoid a strange miss 
   3388             synchronization on NSX CPU with Linux 2.6 OS */
   3389             ix--;
   3390             continue;
   3391         }
   3392         if (lbu_packet_compare(lw, lw->tx_pkts[ix], next_rx) < 0) {
   3393             cli_out("Compare error on packet %d in chain\n", ix);
   3394             return (-1);
   3395         }
   3396         lw->rx_bytes += next_rx->pkt_len;
   3397         lw->rx_count++;
   3398     }
   3399 
   3400     return 0;
   3401 }
   3402 
   3403 /* Dump TX packets on error */
   3404 STATIC void
   3405 lbu_dump_tx_packets(loopback2_test_t *lw)
   3406 {
   3407     int ix;
   3408 
   3409     cli_out("Transmitted packets\n");
   3410     for (ix = 0; ix < lw->tx_ppt; ix++) {
   3411         cli_out("TX packet %d: len=%d\n",
   3412                 ix, lw->tx_pkts[ix]->_pkt_data.len);
   3413     
   3414 #ifdef BCM_ESW_SUPPORT
   3415         soc_dma_dump_pkt(lw->unit, "  ", lw->tx_pkts[ix]->_pkt_data.data, 
   3416                          lw->tx_pkts[ix]->_pkt_data.len, TRUE);
   3417 #endif
   3418     }
   3419 }
   3420 
   3421 /* Setup a chain of packets, tx it and wait for packets back */
   3422 STATIC int
   3423 lbu_do_chain(int unit, int len, int ppt, int cos, int i,
   3424              loopback2_test_t *lw)
   3425 {
   3426     loopback2_testdata_t        *lp = lw->cur_params;
   3427     int rv = BCM_E_NONE;
   3428 
   3429     if ((rv = lbu_pkt_chain_setup(lw->tx_pkts, ppt, len, cos, lw)) < 0) {
   3430         test_error(unit, "Could not setup chain\n\tPort TX(%s) RX(%s)\n"
   3431                    "\tPacket Length=%d bytes\n"
   3432                    "\tPPT=%d\n"
   3433                    "\tCurrent COS=%d\n"
   3434                    "\tIteration %d of %d\n",
   3435                    SOC_PORT_NAME(unit, lw->tx_port),
   3436                    SOC_PORT_NAME(unit, lw->rx_port),
   3437                    len, ppt, cos, i + 1, lp->iterations);
   3438         return rv;
   3439     }
   3440 
   3441     if ((rv = lbu_send_packets(unit, lw->tx_pkts, ppt, lw)) < 0) {
   3442         test_error(unit, "Packet TX failed: ERROR: %s\n",
   3443                    bcm_errmsg(rv));
   3444         lbu_dump_tx_packets(lw);
   3445         return rv;
   3446     }
   3447     if (lp->inject) { /* Diagnostic */
   3448         return 0;
   3449     }
   3450 
   3451     if ((rv = lbu_serial_wait(lw)) < 0) {
   3452         test_error(unit, "See error description\n\tPort TX(%s) RX(%s)\n"
   3453                    "\tPacket Length=%d bytes\n"
   3454                    "\tPPT=%d\n"
   3455                    "\tCurrent COS=%d\n"
   3456                    "\tIteration %d of %d\n",
   3457                    SOC_PORT_NAME(unit, lw->tx_port),
   3458                    SOC_PORT_NAME(unit, lw->rx_port),
   3459                    len, ppt, cos, i + 1, lp->iterations);
   3460         lbu_dump_tx_packets(lw);
   3461         return rv;
   3462     }
   3463 
   3464     lbu_stats_report(lw);
   3465     CLEAR_RX_PKTS(lw, lp);
   3466 
   3467     return 0;
   3468 }
   3469 
   3470 
   3471 int
   3472 lbu_serial_txrx(loopback2_test_t *lw)
   3473 /*
   3474  * Function:    lbu_serial_txrx
   3475  * Purpose:     Loop over requested lengths and chaining sizes, and
   3476  *              transmit/receive packets.
   3477  * Parameters:  lw - pointer to work structure
   3478  * Returns:     0 - success
   3479  *              -1- failed.
   3480  */
   3481 {
   3482     loopback2_testdata_t        *lp = lw->cur_params;
   3483     int         len, ppt, cos, i;
   3484     int         unit = lw->unit;
   3485     int         tagged, rv, test_rv = 0;
   3486     uint32      tx_count, rx_count;
   3487     uint32      rx_count0, rx_count1, rx_count2, rx_count3;
   3488 
   3489     /* Clear port rx/tx counters */
   3490     if ((rv = bcm_stat_clear(unit, lw->tx_port)) < 0) {
   3491         test_error(unit, "Could not clear port %s counters: %s\n",
   3492                    SOC_PORT_NAME(unit, lw->tx_port),
   3493                    soc_errmsg(rv));
   3494         test_rv = -1;
   3495         goto error;
   3496     }
   3497 
   3498     if ((rv = bcm_stat_clear(unit, lw->rx_port)) < 0) {
   3499         test_error(unit, "Could not clear port %s counters: %s\n",
   3500                    SOC_PORT_NAME(unit, lw->rx_port),
   3501                    soc_errmsg(rv));
   3502         test_rv = -1;
   3503         goto error;
   3504     }
   3505 
   3506     LOG_INFO(BSL_LS_APPL_TESTS,
   3507              (BSL_META_U(unit,
   3508                          "Testing Port %s --> %s cnt(%d) pkt/trial(%d,%d += %d) "
   3509                          "l(%d,%d += %d) cos(%d,%d)\n"),
   3510               SOC_PORT_NAME(unit, lw->tx_port),
   3511               SOC_PORT_NAME(unit, lw->rx_port),
   3512               lp->iterations,
   3513               lp->ppt_start, lp->ppt_end, lp->ppt_inc,
   3514               lp->len_start, lp->len_end, lp->len_inc,
   3515               lp->cos_start, lp->cos_end));
   3516 
   3517     /* One time setup of packets */
   3518     tagged = !SOC_PBMP_MEMBER(lp->ubm, lw->tx_port);
   3519     lbu_pkt_init(lw->tx_pkts, lp->ppt_end, lw->tx_port, tagged);
   3520 
   3521     for (i = 0; i < lp->iterations; i++) {
   3522         for (len = lp->len_start; len <= lp->len_end; len += lp->len_inc) {
   3523             for (cos = lp->cos_start; cos <= lp->cos_end; cos++) {
   3524                 for (ppt = lp->ppt_start; ppt <= lp->ppt_end;
   3525                      ppt += lp->ppt_inc) {
   3526                     lw->tx_ppt = ppt;
   3527                     lw->tx_len = len;
   3528                     lw->rx_pkt_cnt = 0;
   3529                     if (lbu_do_chain(unit, len, ppt, cos, i, lw) < 0) {
   3530                         test_rv = -1;
   3531                         goto done;
   3532                     }
   3533                 }
   3534             }
   3535         }
   3536     } /* Test iterations */
   3537 
   3538 done:
   3539     /* Verify port rx/tx stats */
   3540     bcm_stat_sync(unit);
   3541     if ((IS_FE_PORT(unit, lw->rx_port) || IS_GE_PORT(unit, lw->rx_port))) {
   3542         bcm_stat_val_t rx_stat;
   3543         bcm_stat_val_t tx_stat;
   3544         if ((SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) && 
   3545             IS_ST_PORT(unit, lw->tx_port)) {
   3546             /* WAR for stacking ports of Raptor/Raven, where Higig unicast
   3547                packets are accounted as multicast by the MAC */
   3548             tx_stat = snmpIfOutMulticastPkts;
   3549             rx_stat = snmpIfInMulticastPkts;
   3550         } else {
   3551             tx_stat = snmpIfOutUcastPkts;
   3552             rx_stat = snmpIfInUcastPkts;
   3553         }
   3554         if ((rv = bcm_stat_get32(unit, lw->tx_port,
   3555                                  tx_stat, &tx_count)) < 0) {
   3556             test_error(unit,
   3557                        "Could not get port %s tx %s stats : %s\n",
   3558                        SOC_PORT_NAME(unit, lw->tx_port),
   3559                        "snmpIfOutUcastPkts",
   3560                        soc_errmsg(rv));
   3561             test_rv = -1;
   3562             goto error;
   3563         }
   3564         if ((rv = bcm_stat_get32(unit, lw->rx_port,
   3565                                  rx_stat, &rx_count)) < 0) {
   3566             test_error(unit,
   3567                        "Could not get port %s rx %s stats : %s\n",
   3568                        SOC_PORT_NAME(unit, lw->rx_port),
   3569                        "snmpIfInUcastPkts",
   3570                        soc_errmsg(rv));
   3571             test_rv = -1;
   3572             goto error;
   3573         }
   3574         if (tx_count != rx_count) {
   3575             test_error(unit,
   3576                        "TX/RX packet stats mismatch: (%s) TX=%d, (%s) RX=%d\n",
   3577                        SOC_PORT_NAME(unit, lw->tx_port),
   3578                        (int) tx_count,
   3579                        SOC_PORT_NAME(unit, lw->rx_port),
   3580                        (int) rx_count);
   3581             test_rv = -1;
   3582         }
   3583     }
   3584     
   3585     /* Check for port TX error statistics */
   3586     if ((rv = bcm_stat_get32(unit, lw->tx_port,
   3587                              snmpIfOutErrors, &tx_count)) < 0) {
   3588         test_error(unit,
   3589                    "Could not get port %s tx error %s stats : %s\n",
   3590                    SOC_PORT_NAME(unit, lw->tx_port),
   3591                    "snmpIfOutErrors", 
   3592                    soc_errmsg(rv));
   3593         test_rv = -1;
   3594         goto error;
   3595     }
   3596     if (tx_count) {
   3597         test_error(unit,
   3598                    "TX error stats found: TX (%s) error count=%d\n",
   3599                    SOC_PORT_NAME(unit, lw->tx_port), (int) tx_count);
   3600         test_rv = -1;
   3601     }
   3602 
   3603     /* Check for port RX error statistics
   3604      * Use individual stat to count rx errors instead of snmpIfInErrors
   3605      * which includes good oversize packets.
   3606      */
   3607     if ((rv = bcm_stat_get32(unit, lw->rx_port,
   3608                              snmpEtherStatsUndersizePkts, &rx_count0)) < 0) {
   3609         test_error(unit,
   3610                    "Could not get port %s rx %s stats : %s\n",
   3611                    SOC_PORT_NAME(unit, lw->rx_port),
   3612                    "snmpEtherStatsUndersizePkts",
   3613                    soc_errmsg(rv));
   3614         test_rv = -1;
   3615         goto error;
   3616     }
   3617     if ((rv = bcm_stat_get32(unit, lw->rx_port,
   3618                              snmpEtherStatsFragments, &rx_count1)) < 0) {
   3619         test_error(unit,
   3620                    "Could not get port %s rx %s stats : %s\n",
   3621                    SOC_PORT_NAME(unit, lw->rx_port),
   3622                    "snmpEtherStatsFragments",
   3623                    soc_errmsg(rv));
   3624         test_rv = -1;
   3625         goto error;
   3626     }
   3627     if ((rv = bcm_stat_get32(unit, lw->rx_port,
   3628                              snmpEtherStatsCRCAlignErrors, &rx_count2)) < 0) {
   3629         test_error(unit,
   3630                    "Could not get port %s rx %s stats : %s\n",
   3631                    SOC_PORT_NAME(unit, lw->rx_port),
   3632                    "snmpEtherStatsCRCAlignErrors",
   3633                    soc_errmsg(rv));
   3634         test_rv = -1;
   3635         goto error;
   3636     }
   3637     if ((rv = bcm_stat_get32(unit, lw->rx_port,
   3638                              snmpEtherStatsJabbers, &rx_count3)) < 0) {
   3639         test_error(unit,
   3640                    "Could not get port %s rx %s stats : %s\n",
   3641                    SOC_PORT_NAME(unit, lw->rx_port),
   3642                    "snmpEtherStatsJabbers",
   3643                    soc_errmsg(rv));
   3644         test_rv = -1;
   3645         goto error;
   3646     }
   3647     rx_count = rx_count0 + rx_count1 + rx_count2 + rx_count3;
   3648     if (rx_count) {
   3649         test_error(unit,
   3650                    "RX error stats found: RX (%s) error count=%d\n",
   3651                    SOC_PORT_NAME(unit, lw->rx_port), (int) rx_count);
   3652         test_rv = -1;
   3653     }
   3654 
   3655     if (test_rv) {
   3656         goto error;
   3657     }
   3658     return(0);
   3659 
   3660 error:
   3661     CLEAR_RX_PKTS(lw, lp);
   3662     return (test_rv);
   3663 }
   3664 
   3665 int
   3666 lbu_snake_tx(loopback2_test_t *lw)
   3667 /*
   3668  * Function:    lbu_snake_tx
   3669  * Purpose:     Inject packets into snake sources.
   3670  * Parameters:  lw - pointer to work structure
   3671  * Returns:     0 - success
   3672  *              -1- failed.
   3673  */
   3674 {
   3675     int rv = BCM_E_NONE;
   3676 
   3677     if ((rv = lbu_snake_pkt_chain_setup(lw->tx_pkts, lw->tx_ppt, lw->tx_len, 
   3678                                         lw->tx_cos, lw)) < 0) {
   3679         test_error(lw->unit, "Could not setup snake\n"
   3680                    "\tPacket Length=%d bytes\n"
   3681                    "\tPPT=%d\n"
   3682                    "\tCurrent COS=%d\n",
   3683                    lw->tx_len, lw->tx_ppt, lw->tx_cos);
   3684         return rv;
   3685     }
   3686 
   3687     if ((rv = lbu_send_packets(lw->unit, lw->tx_pkts, lw->tx_ppt, lw)) < 0) {
   3688         test_error(lw->unit, "Packet TX failed: ERROR: %s\n",
   3689                    bcm_errmsg(rv));
   3690         lbu_dump_tx_packets(lw);
   3691         return rv;
   3692     }
   3693     return 0;
   3694 }
   3695 #ifdef BCM_TOMAHAWK_SUPPORT
   3696 /*
   3697  * Function:
   3698  *      lbu_snake_check_mib_counters
   3699  * Purpose:
   3700  *      Checks Error counters in MAC.
   3701  */
   3702 
   3703 static int
   3704 lbu_snake_check_mib_counters(int unit, loopback2_testdata_t *lp)
   3705 {
   3706     uint32 j, column;
   3707     uint64 rdata;
   3708     int rv;
   3709     int pblk;
   3710     bcm_port_t   pt;
   3711 
   3712     soc_reg_t error_counters[][4] = {
   3713                                     {RFLRr,   XLMIB_RFLRr,   CLMIB_RFLRr,   GRFLRr},
   3714                                     {RFCSr,   XLMIB_RFCSr,   CLMIB_RFCSr,   GRFCSr},
   3715                                     {RJBRr,   XLMIB_RJBRr,   CLMIB_RJBRr,   GRJBRr},
   3716                                     {RMTUEr,  XLMIB_RMTUEr,  CLMIB_RMTUEr,  GRMTUEr},
   3717                                     {RTRFUr,  XLMIB_RTRFUr,  CLMIB_RTRFUr,  INVALIDr},
   3718                                     {RERPKTr, XLMIB_RERPKTr, CLMIB_RERPKTr, GRCDEr},
   3719                                     {RRPKTr,  XLMIB_RRPKTr,  CLMIB_RRPKTr,  GRRPKTr},
   3720                                     {RUNDr,   XLMIB_RUNDr,   CLMIB_RUNDr,   GRUNDr},
   3721                                     {RFRGr,   XLMIB_RFRGr,   CLMIB_RFRGr,   GRFRGr},
   3722                                     {RRBYTr,  XLMIB_RRBYTr,  CLMIB_RRBYTr,  GRRBYTr},
   3723                                     {TJBRr,   XLMIB_TJBRr,   CLMIB_TJBRr,   GTJBRr},
   3724                                     {TFCSr,   XLMIB_TFCSr,   CLMIB_TFCSr,   GTFCSr},
   3725                                     {TERRr,   XLMIB_TERRr,   CLMIB_TERRr,   GTXCLr},
   3726                                     {TFRGr,   XLMIB_TFRGr,   CLMIB_TFRGr,   GTFRGr},
   3727                                     {TRPKTr,  XLMIB_TRPKTr,  CLMIB_TRPKTr,  INVALIDr},
   3728                                     {TUFLr,   XLMIB_TUFLr,   CLMIB_TUFLr,   INVALIDr},
   3729                                     {TPCEr,   TPCE_64r,      TPCE_64r,      TPCE_64r},
   3730                                     {RDISCr,  RDISC_64r,     RDISC_64r,     RDISC_64r},
   3731                                     {RIPHE4r, RIPHE4_64r,    RIPHE4_64r,    RIPHE4_64r},
   3732                                     {RIPHE6r, RIPHE6_64r,    RIPHE6_64r,    RIPHE6_64r},
   3733                                     {RIPD4r,  RIPD4_64r,     RIPD4_64r,     RIPD4_64r},
   3734                                     {RIPD6r,  RIPD6_64r,     RIPD6_64r,     RIPD6_64r},
   3735                                     {RPORTDr, RPORTD_64r,    RPORTD_64r,    RPORTD_64r}
   3736                                  };
   3737 
   3738     PBMP_ITER(lp->pbm, pt) {
   3739         column = 0;
   3740         if (soc_feature(unit, soc_feature_cxl_mib)) {
   3741             pblk = SOC_PORT_BLOCK(unit, SOC_INFO(unit).port_l2p_mapping[pt]);
   3742             if (SOC_BLOCK_IS_CMP(unit, pblk, SOC_BLK_CLPORT)) {
   3743                 column = 2;
   3744             } else if (IS_QSGMII_PORT(unit, pt)) {
   3745                 column = 3;
   3746             } else if (SOC_BLOCK_IS_CMP(unit, pblk, SOC_BLK_XLPORT)) {
   3747                 column = 1;
   3748             }
   3749         }
   3750         for (j = 0; j < (sizeof(error_counters) / sizeof(error_counters[0])); j++) {
   3751             if (SOC_REG_IS_VALID(unit, error_counters[j][column])) {
   3752                 rv = soc_reg_get(unit, error_counters[j][column], pt, 0, &rdata);
   3753 
   3754                 if (SOC_FAILURE(rv)) {
   3755                     test_error(unit, "\nError reading MIB counter %s",
   3756                                             SOC_REG_NAME(unit, error_counters[j][column]));
   3757                     return -1;
   3758                 } else if (!(COMPILER_64_IS_ZERO(rdata))) {
   3759                     test_error (unit, "\n*ERROR: Error counter %s has a non zero value "
   3760                                 "for device port %0d",
   3761                                 SOC_REG_NAME(unit, error_counters[j][column]), pt);
   3762                     return -1;
   3763                 }
   3764             }
   3765         }
   3766     }
   3767     return 0;
   3768 }
   3769 
   3770 /*
   3771  * Function:
   3772  *      lbu_snake_check_rate
   3773  * Purpose:
   3774  *      check rate in snake test.
   3775  */
   3776 static int
   3777 lbu_snake_check_rate(int unit, loopback2_test_t *lw, lb2_port_stat_t  *stats)
   3778 {
   3779     bcm_port_t   pt;
   3780     int speed, first = TRUE, cell_num, pipe, dpp_ratio = 10;
   3781     uint32 rate_core, rate_pipe, rate_limit;
   3782     uint64 rate_tolerance, act_rate;
   3783     loopback2_testdata_t   *lp = lw->cur_params;
   3784     soc_reg_t reg = INVALIDr;
   3785     soc_info_t *si;
   3786     int port_c[4] = {0,0,0,0}, max_port_num = 0;
   3787 
   3788     si = &SOC_INFO(unit);
   3789     COMPILER_64_ZERO(rate_tolerance);
   3790     cell_num = lw->tx_len <= 144 ? 1: (1 + (lw->tx_len - 144 + 207) / 208);
   3791     rate_core = si->frequency * (lw->tx_len + 20) * 8 / cell_num;
   3792     if (SOC_IS_TOMAHAWK2(unit)){
   3793         dpp_ratio = si->dpp_clk_ratio_x10;
   3794     }
   3795     rate_pipe = si->frequency * (lw->tx_len + 20) * 8 * 10 / dpp_ratio;
   3796 
   3797     PBMP_ITER(lp->pbm, pt) {
   3798         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit,pt,&pipe));
   3799         if (pipe >= 0 && pipe < 4){
   3800             port_c[pipe]++;
   3801             if (port_c[pipe] > max_port_num) {
   3802                 max_port_num = port_c[pipe];
   3803             }
   3804         }
   3805     }
   3806     rate_limit = rate_core < rate_pipe ?
   3807                  rate_core / max_port_num : rate_pipe / max_port_num;
   3808 
   3809     PBMP_ITER(lp->pbm, pt) {
   3810         if (first) {
   3811             if (soc_feature(unit, soc_feature_cxl_mib)) {
   3812                 if (SOC_BLOCK_IS_CMP(unit, SOC_PORT_BLOCK(unit,
   3813                     SOC_INFO(unit).port_l2p_mapping[pt]), SOC_BLK_CLPORT)) {
   3814                     reg = CLMIB_TBYTr;
   3815                 } else if (IS_QSGMII_PORT(unit, pt)) {
   3816                     reg = GTBYTr;
   3817                 } else {
   3818                     reg = XLMIB_TBYTr;
   3819                 }
   3820             } else {
   3821                 reg = TBYTr;
   3822             }
   3823             if (!SOC_REG_IS_VALID(unit, reg)) {
   3824                 cli_out("reg %s is not valid", SOC_REG_NAME(unit,reg));
   3825                 return -1;
   3826             }
   3827             BCM_IF_ERROR_RETURN(bcm_port_speed_get(unit, pt, &speed));
   3828             if (speed > rate_limit) {
   3829                 speed = rate_limit;
   3830             }
   3831             cli_out("port max line rate is  %d MB/s for packet length %d Byte \n",
   3832                      speed, lw->tx_len);
   3833             /*give a 5% margin, rate_tolerance = speed * 1000000 * 95 / 100 */
   3834             COMPILER_64_SET(rate_tolerance, 0, speed);
   3835             COMPILER_64_UMUL_32(rate_tolerance, 950000);
   3836             first = FALSE;
   3837         }
   3838 
   3839         soc_counter_get_rate(unit, pt, reg, 0, &(stats[pt].rate));
   3840         /*change to real rate in bit.
   3841          *act_rate = stats[pt].rate * 8 * (lw->tx_len + 20) / (lw->tx_len)
   3842          */
   3843         COMPILER_64_COPY(act_rate, stats[pt].rate);
   3844         COMPILER_64_UMUL_32(act_rate, (8 * (lw->tx_len + 20)));
   3845         COMPILER_64_UDIV_32(act_rate, lw->tx_len);
   3846 
   3847         if (COMPILER_64_LT(act_rate, rate_tolerance)) {
   3848             cli_out("Cannot reach line rate for port %s\n",
   3849                      SOC_PORT_NAME(unit, pt));
   3850             return -1;
   3851         }
   3852     }
   3853     return 0;
   3854 }
   3855 
   3856 /*
   3857  * Function:
   3858  *      lbu_snake_check_drop_pkt
   3859  * Purpose:
   3860  *      check packet loss in snake test.
   3861  */
   3862 
   3863 static int
   3864 lbu_snake_check_drop_pkt(int unit, loopback2_testdata_t *lp, lb2_port_stat_t  *stats)
   3865 {
   3866     bcm_port_t pt;
   3867     int first = TRUE;
   3868     uint64 byte, pkt;
   3869     COMPILER_64_ZERO(byte);
   3870     COMPILER_64_ZERO(pkt);
   3871 
   3872     PBMP_ITER(lp->pbm, pt) {
   3873         if (first) {
   3874             COMPILER_64_COPY(byte, stats[pt].tbyt);
   3875             COMPILER_64_COPY(pkt, stats[pt].tpkt);
   3876             first = FALSE;
   3877         }
   3878         if (!(COMPILER_64_EQ(byte, stats[pt].rbyt) && COMPILER_64_EQ(byte, stats[pt].tbyt) &&
   3879               COMPILER_64_EQ(pkt, stats[pt].rpkt) && COMPILER_64_EQ(pkt, stats[pt].tpkt))) {
   3880             cli_out("pkt counter mismatch for port %s\n", SOC_PORT_NAME(unit, pt));
   3881             return -1;
   3882         }
   3883     }
   3884     return 0;
   3885 }
   3886 #endif /*BCM_TOMAHAWK_SUPPORT */
   3887 
   3888 int
   3889 lbu_snake_txrx(loopback2_test_t *lw, lb2_port_stat_t  *stats)
   3890 /*
   3891  * Function:    lbu_snake_txrx
   3892  * Purpose:     Transmit and receive packets from snake.
   3893  * Parameters:  lw - pointer to work structure
   3894  * Returns:     0 - success
   3895  *              -1- failed.
   3896  */
   3897 {
   3898     loopback2_testdata_t   *lp = lw->cur_params;
   3899     int             unit = lw->unit;
   3900     int             rv = BCM_E_NONE;
   3901     int             ix, timer, sleep_time;
   3902     lb2s_port_connect_t *work_info;
   3903 
   3904     /* This is the init call */
   3905     if (lbu_snake_stats(unit, lp->pbm, lp->loopback, stats) < 0) {
   3906         lbu_snake_dump_stats(unit, lp->pbm, stats);
   3907         return (-1);
   3908     }
   3909 
   3910     lw->rx_pkt_cnt = 0;
   3911     lbu_snake_tx(lw);
   3912 
   3913     timer = 0;
   3914     while (lp->duration > timer) {
   3915         sleep_time = lp->interval;
   3916 
   3917         if (lp->interval > (lp->duration - timer)) {
   3918             sleep_time = (lp->duration - timer);
   3919         }
   3920 
   3921         sal_sleep(sleep_time);
   3922         timer += sleep_time;
   3923         cli_out("Time elapsed:  %d seconds\n", timer);
   3924 
   3925         if (!SAL_BOOT_QUICKTURN) {
   3926             if (lbu_snake_stats(unit, lp->pbm, lp->loopback, stats) < 0) {
   3927                 lbu_snake_dump_stats(unit, lp->pbm, stats);
   3928                 return (-1);
   3929             }
   3930         } else {
   3931             /* JUMBO: */
   3932             uint64 tpkt;
   3933             uint32 tempStat;
   3934             bcm_port_t port;
   3935 
   3936             work_info = (lw->port_cnct_f != NULL) ? 
   3937                 lw->port_cnct_f : lw->port_cnct_r;
   3938 
   3939             port = work_info[0].this_port;
   3940 
   3941             COMPILER_64_ZERO(tpkt);    COMPILER_REFERENCE(&tpkt);   
   3942             bcm_stat_get(unit, port, 
   3943                          snmpDot1dTpPortOutFrames, &tpkt);
   3944             COMPILER_64_TO_32_LO(tempStat, tpkt);
   3945             cli_out("Port %s Tx Count = 0x%x\n", 
   3946                     SOC_PORT_NAME(unit, port), 
   3947                     tempStat);
   3948         }
   3949     }
   3950 #ifdef BCM_TOMAHAWK_SUPPORT
   3951     /*check line rate*/
   3952     if (lp->line_rate){
   3953         if(lbu_snake_check_rate(unit, lw, stats) < 0) {
   3954            lbu_snake_dump_stats(unit, lp->pbm, stats);
   3955             return -1;
   3956         }
   3957     }
   3958 #endif
   3959     /* Redirect packets to CPU if loop was closed */
   3960     if (lp->duration) {
   3961         lw->expect_pkts = TRUE;
   3962         if (lw->port_cnct_f != NULL) {
   3963             work_info = &(lw->port_cnct_f[lw->port_count]);
   3964             if ((rv = lbu_connect_ports(unit, work_info, TRUE)) < 0) {
   3965                 test_error(unit,
   3966                            "CPU redirect failure on forward loop: %s\n",
   3967                            soc_errmsg(rv));
   3968                 return -1;
   3969             }
   3970         }
   3971 
   3972         if (lw->port_cnct_r != NULL) {
   3973             work_info = &(lw->port_cnct_r[lw->port_count]);
   3974             if ((rv = lbu_connect_ports(unit, work_info, TRUE)) < 0) {
   3975                 test_error(unit,
   3976                            "CPU redirect failure on reverse loop: %s\n",
   3977                            soc_errmsg(rv));
   3978                 return -1;
   3979             }
   3980         }
   3981     }
   3982 
   3983     bcm_stat_sync(unit);
   3984 
   3985     if (sal_sem_take(lw->sema, lw->timeout_usec)) {
   3986         cli_out("Time-out waiting for snake completion\n");
   3987         cli_out("Receive count is %d; expecting %d pkts.\n",
   3988                 lw->rx_pkt_cnt, lw->tx_ppt);
   3989         lbu_snake_stats(unit, lp->pbm, lp->loopback, stats);
   3990         lbu_snake_dump_stats(unit, lp->pbm, stats);
   3991         lw->sema_woke = FALSE;
   3992         return (-1);
   3993     }
   3994 
   3995     lw->sema_woke = FALSE;    
   3996     lw->expect_pkts = FALSE; /* Let RX handler ignore packets */
   3997 
   3998     if (lbu_snake_analysis(lw) < 0) {
   3999         if (lbu_snake_stats(unit, lp->pbm, lp->loopback, stats) < 0) {
   4000             if (lw->port_cnct_f != NULL) {
   4001                 lbu_snake_diag(lw, stats, lw->port_cnct_f);
   4002             }
   4003             if (lw->port_cnct_r != NULL) {
   4004                 lbu_snake_diag(lw, stats, lw->port_cnct_r);
   4005             }
   4006         }
   4007         lbu_snake_dump_stats(unit, lp->pbm, stats);
   4008         return (-1);
   4009     }
   4010 
   4011     rv = 0;
   4012     for (ix = 0; ix < lw->tx_ppt; ix++) {
   4013         if (lw->tx_pkt_match[ix] == 0) {
   4014             rv = -1;
   4015             test_error(unit,
   4016                        "TX packet %d did not return to CPU\n", (ix + 1));
   4017         }
   4018     }
   4019 
   4020     if (lbu_snake_stats(unit, lp->pbm, lp->loopback, stats) < 0) {
   4021         rv = -1;
   4022     }
   4023 
   4024 #ifdef BCM_TOMAHAWK_SUPPORT
   4025     if (lp->line_rate){
   4026         if (lbu_snake_check_mib_counters(unit, lp) < 0) {
   4027             return -1;
   4028         }
   4029         /*skip packet drop check for small packets*/
   4030         if (lw->tx_len > 352){
   4031             if (lbu_snake_check_drop_pkt(unit, lp, stats) < 0) {
   4032                 rv = -1;
   4033             }
   4034         }
   4035     }
   4036 #endif
   4037 
   4038     lbu_snake_dump_stats(unit, lp->pbm, stats);
   4039 
   4040     if (rv < 0) {
   4041         return rv;
   4042     }
   4043 
   4044     /* Close loop again */
   4045     if (lp->duration) {
   4046         if (lw->port_cnct_f != NULL) {
   4047             work_info = &(lw->port_cnct_f[lw->port_count]);
   4048             if ((rv = lbu_connect_ports(unit, work_info, FALSE)) < 0) {
   4049                 test_error(unit,
   4050                            "CPU undirect failure on forward loop: %s\n",
   4051                            soc_errmsg(rv));
   4052                 return -1;
   4053             }
   4054            
   4055             work_info = &(lw->port_cnct_f[lw->port_count - 1]);
   4056             if ((rv = lbu_connect_ports(unit, work_info, TRUE)) < 0) {
   4057                 test_error(unit,
   4058                            "Forward loop closure failed: %s\n",
   4059                            soc_errmsg(rv));
   4060                 return -1;
   4061             }
   4062         }
   4063 
   4064         if (lw->port_cnct_r != NULL) {
   4065             work_info = &(lw->port_cnct_r[lw->port_count]);
   4066             if ((rv = lbu_connect_ports(unit, work_info, FALSE)) < 0) {
   4067                 test_error(unit,
   4068                            "CPU redirect failure on reverse loop: %s\n",
   4069                            soc_errmsg(rv));
   4070                 return -1;
   4071             }
   4072            
   4073             work_info = &(lw->port_cnct_r[lw->port_count - 1]);
   4074             if ((rv = lbu_connect_ports(unit, work_info, TRUE)) < 0) {
   4075                 test_error(unit,
   4076                            "Reverse loop closure failed: %s\n",
   4077                            soc_errmsg(rv));
   4078                 return -1;
   4079             }
   4080         }
   4081     }
   4082 
   4083     /* Clean up packet data */
   4084     CLEAR_RX_PKTS(lw, lp);
   4085     sal_memset(lw->tx_pkt_match, 0, lp->ppt_end * sizeof(int));
   4086 
   4087     return 0;
   4088 }
   4089 
   4090 void
   4091 lbu_setup(int unit, loopback2_test_t *lw)
   4092 /*
   4093  * Function:    lbu_setup
   4094  * Purpose:     Fill in defaults for the parameters.
   4095  * Parameters:  unit - unit #.
   4096  *              lw - pointer to work struct.
   4097  * Returns:     Nothing
   4098  */
   4099 {
   4100     int                  num_cos;
   4101 
   4102     /* Keep statistics from printing if user ^C's before test starts */
   4103     lw->stats_init = FALSE;
   4104 
   4105     if (lw->set_up) {
   4106         return;
   4107     }
   4108 
   4109     if (bcm_cosq_config_get(unit, &num_cos) < 0 || num_cos == 0) {
   4110         num_cos = 1;
   4111     }
   4112 
   4113     lw->unit = unit;
   4114 
   4115     /* Set up parameters for different tests */
   4116     mac_params_init(unit, num_cos, &lw->params[LB2_TT_MAC]);
   4117     phy_params_init(unit, num_cos, &lw->params[LB2_TT_PHY]);
   4118     ext_params_init(unit, num_cos, &lw->params[LB2_TT_EXT]);
   4119     snake_params_init(unit, num_cos, &lw->params[LB2_TT_SNAKE]);
   4120 
   4121     lw->set_up = TRUE;
   4122 }
   4123 
   4124 STATIC int
   4125 lbu_restore_port(loopback2_test_t *lw)
   4126 {
   4127     loopback2_testdata_t        *lp = lw->cur_params;
   4128     int         rv;
   4129     int         unit = lw->unit;
   4130     soc_port_t  port;
   4131     pbmp_t      save_ports;
   4132     int         ms;
   4133 
   4134     if (SOC_IS_XGS12_FABRIC(unit)) {
   4135         SOC_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(unit));
   4136     } else {
   4137         SOC_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(unit));
   4138         SOC_PBMP_AND(save_ports, lp->pbm);
   4139     }
   4140 
   4141     PBMP_ITER(save_ports, port) {
   4142        /* If port is FE port, remove phy_master attributes controlled by it */
   4143        if(IS_FE_PORT(unit, port)) {
   4144           lw->save_port[port].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   4145        }
   4146         /* If the Master mode is not changed, remove phy_master attributes from action_mask*/
   4147         ms = 0;
   4148         if ((rv = bcm_port_master_get(unit, port, &ms)) != BCM_E_NONE) {
   4149             test_error(unit,
   4150                        "Port %s: Could not get port Master mode: %s\n",
   4151                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4152             return (-1);
   4153         }
   4154         if (ms == lw->save_port[port].phy_master) {
   4155             lw->save_port[port].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
   4156         }
   4157         if ((rv = bcm_port_info_restore(unit, port,
   4158                                     &lw->save_port[port])) < 0) {
   4159             test_error(unit,
   4160                        "Port %s: Could not restore port info: %s\n",
   4161                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4162             return(-1);
   4163         }
   4164 #ifdef BCM_TOMAHAWK3_SUPPORT
   4165         /* Restore original fec, phy config and link training info. Note pm8x50
   4166          * (cd ports) have this additional configuration information
   4167          */
   4168         if ((SOC_IS_TOMAHAWK3(unit)) && (IS_CD_PORT(unit, port))) {
   4169             rv = bcm_port_resource_speed_set(unit, port,
   4170                                              &lw->port_info[port]);
   4171             if (rv < 0) {
   4172                 test_error(unit,
   4173                            "Port %s: bcm_port_resource_set failed: %s\n",
   4174                            SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4175                 return(-1);
   4176             }
   4177         }
   4178 #endif /* BCM_TOMAHAWK3_SUPPORT */
   4179     }
   4180 
   4181     if (SOC_IS_XGS_SWITCH(unit)) {
   4182         /* Restore source port/module for ipic */
   4183         SOC_DEFAULT_DMA_SRCMOD_SET(unit, lbu_saved_srcmod[unit]);
   4184         SOC_DEFAULT_DMA_SRCPORT_SET(unit, lbu_saved_srcport[unit]);
   4185     }
   4186 #ifdef BCM_TRIUMPH_SUPPORT
   4187     if(SOC_IS_TRX(unit)){
   4188         PBMP_ITER(save_ports, port) {
   4189 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4190             if (SOC_MEM_IS_VALID(unit, EGR_VLAN_CONTROL_1m)) {
   4191                 if (soc_feature(unit, soc_feature_egr_all_profile)) {
   4192                     BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit,
   4193                         port, EGR_VLAN_CONTROL_1m, REMARK_OUTER_DOT1Pf, 1));
   4194                 } else {
   4195                     SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   4196                         EGR_VLAN_CONTROL_1m, port, REMARK_OUTER_DOT1Pf, 1));
   4197                 }
   4198             } else
   4199 #endif
   4200             if ((rv = soc_reg_field32_modify(unit, EGR_VLAN_CONTROL_1r, port,
   4201                                              REMARK_OUTER_DOT1Pf, 0x1)) < 0) {
   4202                 test_error(unit,
   4203                        "Unable to re-enable outer dot1p remarking: port %s: %s\n",
   4204                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4205                 return (-1);
   4206             }
   4207         }
   4208     }
   4209 #endif
   4210     return(0);
   4211 }
   4212 
   4213 int
   4214 lbu_done(loopback2_test_t *lw)
   4215 /*
   4216  * Function:    lbu_done
   4217  * Purpose:     Generic loopback done function
   4218  * Parameters:  lw - pointer to lw to clean up.
   4219  * Returns:
   4220  */
   4221 {
   4222     int         rv = 0;
   4223     loopback2_testdata_t        *lp = lw->cur_params;
   4224     int unit = lw->unit;
   4225 
   4226     if (lp) {
   4227         if (!lp->inject) {
   4228             /* Unregister the callback */
   4229             if ((rv = bcm_rx_unregister(lw->unit, lbu_rx_callback,
   4230                                         BCM_RX_PRIO_MAX)) < 0) {
   4231                 test_error(lw->unit,
   4232                            "Failed to unregister RX handler.\n");
   4233             }
   4234 #if defined(__KERNEL__) && (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICDV2_SUPPORT))
   4235             (void)soc_cmicm_cmcx_intr0_disable(unit, 0, 0xff00);
   4236             sal_usleep(500);
   4237 #endif
   4238             /* lbu_restore_port resets initial state below */
   4239             if ((rv = bcm_rx_stop(lw->unit, NULL)) < 0) {
   4240                 cli_out("lbu_done: could not stop packet driver: %s\n",
   4241                         bcm_errmsg(rv));
   4242             }
   4243 
   4244             if (lw->tx_pkts) {
   4245                 bcm_pkt_blk_free(unit, lw->tx_pkts, lp->ppt_end);
   4246                 lw->tx_pkts = NULL;
   4247             }
   4248             if (lw->rx_pkts) {
   4249                 CLEAR_RX_PKTS(lw, lp);
   4250                 sal_free(lw->rx_pkts);
   4251                 lw->rx_pkts = NULL;
   4252             }
   4253         }
   4254 
   4255     }
   4256 
   4257 
   4258 #if defined(__KERNEL__) && (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICDV2_SUPPORT))
   4259         sal_sem_destroy(lw->sema);
   4260         lw->sema = NULL;
   4261 #endif
   4262 
   4263     if (lw->sema) {
   4264         sal_sem_destroy(lw->sema);
   4265         lw->sema = NULL;
   4266     }
   4267 
   4268     /* Clean up ARL if interrupted in middle */
   4269     lbu_cleanup_arl(lw);
   4270 
   4271     /* ENABLE ALL PORTS */
   4272     if (lp) {
   4273         rv |= lbu_restore_port(lw);
   4274     }
   4275 
   4276     lp = NULL;
   4277 
   4278 #if defined(__KERNEL__) && (defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICDV2_SUPPORT))
   4279     bcm_vlan_destroy_all(unit);
   4280 #endif
   4281 
   4282     return(rv);
   4283 }
   4284 
   4285 /* Test parameter init routines */
   4286 
   4287 STATIC void
   4288 mac_params_init(int unit, int num_cos, loopback2_testdata_t *lp)
   4289 {
   4290     int                 lene_ignore = 0;
   4291 
   4292     lp->test_type       = LB2_TT_MAC;
   4293 
   4294     SOC_PBMP_ASSIGN(lp->pbm, PBMP_PORT_ALL(unit));
   4295     lp->dst_inc         = 0;
   4296     SOC_PBMP_CLEAR(lp->ubm);
   4297     lp->pattern         = 0xa5a4a3a2;
   4298     lp->pattern_inc     = 0;
   4299     lp->vlan            = LB2_VLAN_ID;
   4300     lp->d_port          = CMIC_PORT(unit);
   4301     if (SOC_IS_XGS_SWITCH(unit)) {
   4302         if (bcm_stk_my_modid_get(unit, &lp->d_mod) < 0) {
   4303             lp->d_mod = 0;
   4304         }
   4305     } else {
   4306 #ifdef BCM_XGS_SUPPORT
   4307         lp->d_mod       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
   4308 #else
   4309         lp->d_mod       = 0;
   4310 #endif
   4311     }
   4312 #ifdef BCM_XGS_SUPPORT
   4313     lp->opcode          = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
   4314 #else
   4315     lp->opcode          = 0;
   4316 #endif
   4317     lp->len_start       = 68;
   4318     lp->len_end         = 1522;
   4319     lp->len_inc         = 512;
   4320     lp->ppt_start       = 1;
   4321     lene_ignore         = lp->len_end;
   4322     (void)_lb_ppte_initval(unit, &lene_ignore, &lp->ppt_end);
   4323     lp->ppt_inc         = lp->ppt_end - lp->ppt_start;
   4324 #ifdef BCM_TOMAHAWK_SUPPORT
   4325     lp->line_rate       = 0;
   4326     lp->line_rate_count = 1;
   4327 #endif
   4328     lp->cos_start       = 0;
   4329     lp->cos_end         = num_cos - 1;
   4330     lp->iterations      = 10;
   4331     lp->crc_mode        = LB2_CRC_MODE_MAC_REGEN;
   4332     lp->check_data      = TRUE;
   4333     lp->check_crc       = FALSE;
   4334     lp->loopback        = LB2_MODE_MAC;
   4335     lp->inject          = FALSE;
   4336     lp->port_select_mode = LB2_TH_ASCEND_PORT_MODE;
   4337     if (lp->ppt_inc == 0) {
   4338         lp->ppt_inc = 1;
   4339     }
   4340 
   4341     ENET_SET_MACADDR(lp->mac_src, lbu_mac_src);
   4342     lp->mac_src_inc     = 0;
   4343     ENET_SET_MACADDR(lp->mac_dst, lbu_mac_dst);
   4344     lp->mac_dst_inc     = 0;
   4345 }
   4346 
   4347 STATIC void
   4348 phy_params_init(int unit, int num_cos, loopback2_testdata_t *lp)
   4349 {
   4350     int                 lene_ignore = 0;
   4351 
   4352     lp->test_type       = LB2_TT_PHY;
   4353 
   4354     SOC_PBMP_ASSIGN(lp->pbm, PBMP_PORT_ALL(unit));
   4355     
   4356 
   4357     lp->dst_inc         = 0;
   4358     SOC_PBMP_CLEAR(lp->ubm);
   4359     lp->pattern         = 0xa5a4a3a2;
   4360     lp->pattern_inc     = 0;
   4361     lp->vlan            = LB2_VLAN_ID;
   4362     lp->d_port          = CMIC_PORT(unit);
   4363     if (SOC_IS_XGS_SWITCH(unit)) {
   4364         if (bcm_stk_my_modid_get(unit, &lp->d_mod) < 0) {
   4365             lp->d_mod = 0;
   4366         }
   4367     } else {
   4368 #ifdef BCM_XGS_SUPPORT
   4369         lp->d_mod       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
   4370 #else
   4371         lp->d_mod       = 0;
   4372 #endif
   4373     }
   4374 #ifdef BCM_XGS_SUPPORT
   4375     lp->opcode          = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
   4376 #else
   4377     lp->opcode          = 0;
   4378 #endif
   4379     lp->len_start       = 68;
   4380     lp->len_end         = 1522;
   4381     lp->len_inc         = 512;
   4382     lp->ppt_start       = 1;
   4383     lene_ignore         = lp->len_end;
   4384     (void)_lb_ppte_initval(unit, &lene_ignore, &lp->ppt_end);
   4385     lp->ppt_inc         = lp->ppt_end - lp->ppt_start;
   4386 #ifdef BCM_TOMAHAWK_SUPPORT
   4387     lp->line_rate       = 0;
   4388     lp->line_rate_count = 1;
   4389 #endif
   4390     lp->cos_start       = 0;
   4391     lp->cos_end         = num_cos - 1;
   4392     lp->iterations      = 10;
   4393     lp->crc_mode        = LB2_CRC_MODE_MAC_REGEN;
   4394     lp->check_data      = TRUE;
   4395     lp->check_crc       = FALSE;
   4396     lp->loopback        = LB2_MODE_PHY;
   4397     lp->inject          = FALSE;
   4398     lp->port_select_mode = LB2_TH_ASCEND_PORT_MODE;
   4399 
   4400     if (lp->ppt_inc == 0) {
   4401         lp->ppt_inc = 1;
   4402     }
   4403 
   4404     ENET_SET_MACADDR(lp->mac_src, lbu_mac_src);
   4405     lp->mac_src_inc     = 0;
   4406     ENET_SET_MACADDR(lp->mac_dst, lbu_mac_dst);
   4407     lp->mac_dst_inc     = 0;
   4408 }
   4409 
   4410 STATIC void
   4411 ext_params_init(int unit, int num_cos, loopback2_testdata_t *lp)
   4412 {
   4413     int setport;
   4414     int p;
   4415     int                 lene_ignore = 0;
   4416 
   4417     lp->test_type       = LB2_TT_EXT;
   4418 
   4419     SOC_PBMP_CLEAR(lp->pbm);
   4420     /* set up pairs of transmitting and receiving ports */
   4421     SOC_PBMP_CLEAR(lp->pbm_tx);
   4422     setport = 1;
   4423     PBMP_PORT_ITER(unit, p) {
   4424         if (setport) {
   4425             SOC_PBMP_PORT_ADD(lp->pbm_tx, p);
   4426         }
   4427         setport = !setport;
   4428     }
   4429     lp->dst_inc         = 1;
   4430     SOC_PBMP_CLEAR(lp->ubm);
   4431     lp->pattern         = 0xa5a4a3a2;
   4432     lp->pattern_inc     = 0;
   4433     lp->vlan            = LB2_VLAN_ID;
   4434     lp->d_port          = CMIC_PORT(unit);
   4435     if (SOC_IS_XGS_SWITCH(unit)) {
   4436         if (bcm_stk_my_modid_get(unit, &lp->d_mod) < 0) {
   4437             lp->d_mod = 0;
   4438         }
   4439     } else {
   4440 #ifdef BCM_XGS_SUPPORT
   4441         lp->d_mod       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
   4442 #else
   4443         lp->d_mod       = 0;
   4444 #endif
   4445     }
   4446 #ifdef BCM_XGS_SUPPORT
   4447     lp->opcode          = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
   4448 #else
   4449     lp->opcode          = 0;
   4450 #endif
   4451     lp->len_start       = 68;
   4452     lp->len_end         = 1522;
   4453     lp->len_inc         = 512;
   4454     lp->ppt_start       = 1;
   4455     lene_ignore         = lp->len_end;
   4456     (void)_lb_ppte_initval(unit, &lene_ignore, &lp->ppt_end);
   4457     lp->ppt_inc         = lp->ppt_end - lp->ppt_start;
   4458 #ifdef BCM_TOMAHAWK_SUPPORT
   4459     lp->line_rate       = 0;
   4460     lp->line_rate_count = 1;
   4461 #endif
   4462     lp->cos_start       = 0;
   4463     lp->cos_end         = num_cos - 1;
   4464     lp->iterations      = 10;
   4465     lp->crc_mode        = LB2_CRC_MODE_MAC_REGEN;
   4466     lp->check_data      = TRUE;
   4467     lp->check_crc       = FALSE;
   4468     lp->loopback        = LB2_MODE_EXT;
   4469     lp->inject          = FALSE;
   4470     lp->port_select_mode = LB2_TH_ASCEND_PORT_MODE;
   4471 
   4472     if (lp->ppt_inc == 0) {
   4473         lp->ppt_inc = 1;
   4474     }
   4475 
   4476     ENET_SET_MACADDR(lp->mac_src, lbu_mac_src);
   4477     lp->mac_src_inc     = 0;
   4478     ENET_SET_MACADDR(lp->mac_dst, lbu_mac_dst);
   4479     lp->mac_dst_inc     = 0;
   4480 }
   4481 
   4482 STATIC void
   4483 snake_params_init(int unit, int num_cos, loopback2_testdata_t *lp)
   4484 {
   4485     int                 lene_ignore = 0;
   4486 
   4487     lp->test_type       = LB2_TT_SNAKE;
   4488 
   4489     SOC_PBMP_ASSIGN(lp->pbm, PBMP_PORT_ALL(unit));
   4490 
   4491     /* Snake test supported only on Ethernet ports on FB */
   4492     if (SOC_IS_FB_FX_HX(unit)) {
   4493         SOC_PBMP_AND(lp->pbm, PBMP_E_ALL(unit));
   4494     }
   4495 
   4496     lp->dst_inc         = 1;
   4497     SOC_PBMP_CLEAR(lp->ubm);
   4498     lp->pattern         = 0xa5a4a3a2;
   4499     lp->pattern_inc     = 0;
   4500     lp->vlan            = LB2_VLAN_ID;
   4501     lp->d_port          = CMIC_PORT(unit);
   4502     if (SOC_IS_XGS_SWITCH(unit)) {
   4503         if (bcm_stk_my_modid_get(unit, &lp->d_mod) < 0) {
   4504             lp->d_mod = 0;
   4505         }
   4506     } else {
   4507 #ifdef BCM_XGS_SUPPORT
   4508         lp->d_mod       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
   4509 #else
   4510         lp->d_mod       = 0;
   4511 #endif
   4512     }
   4513 #ifdef BCM_XGS_SUPPORT
   4514     lp->opcode          = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
   4515 #else
   4516     lp->opcode          = 0;
   4517 #endif
   4518     lp->d_mod_inc       = 1;
   4519     lp->len_start       = 68;
   4520     lp->len_end         = 1522;
   4521     lp->len_inc         = 512;
   4522     lp->ppt_start       = 1;
   4523     lene_ignore         = lp->len_end;
   4524     (void)_lb_ppte_initval(unit, &lene_ignore, &lp->ppt_end);
   4525     lp->ppt_inc         = 6;
   4526 #ifdef BCM_TOMAHAWK_SUPPORT
   4527     lp->line_rate       = 0;
   4528     lp->line_rate_count = 1;
   4529 #endif
   4530     lp->cos_start       = 0;
   4531     lp->cos_end         = num_cos - 1;
   4532     lp->iterations      = 5;
   4533     lp->crc_mode        = SOC_IS_XGS12_FABRIC(unit) ? LB2_CRC_MODE_MAC_REGEN :
   4534                              LB2_CRC_MODE_CPU_APPEND;
   4535     lp->check_data      = FALSE;
   4536     lp->check_crc       = FALSE;
   4537     lp->duration        = 10;
   4538     lp->interval        = sh_set_report_time;
   4539     lp->snake_way       = LB2_SNAKE_INCR;
   4540     lp->port_select_mode = LB2_TH_ASCEND_PORT_MODE;
   4541 
   4542     lp->loopback        = LB2_MODE_MAC;
   4543     lp->inject          = FALSE;
   4544 
   4545     if (lp->ppt_inc == 0) {
   4546         lp->ppt_inc = 1;
   4547     }
   4548 
   4549 #ifdef BCM_FIREBOLT_SUPPORT
   4550     if (SOC_IS_HBX(unit)) {
   4551         int port;
   4552         PBMP_ITER(lp->pbm, port) {
   4553             if (IS_ST_PORT(unit, port)) {
   4554                 lp->opcode = SOC_HIGIG_OP_UC;
   4555             }
   4556         }
   4557     }
   4558 #endif
   4559 
   4560     ENET_SET_MACADDR(lp->mac_src, lbu_mac_src);
   4561     lp->mac_src_inc     = 0;
   4562     ENET_SET_MACADDR(lp->mac_dst, lbu_mac_dst);
   4563     lp->mac_dst_inc     = 1;
   4564 }
   4565