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

loopback.c (242404B)


      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  * Loopback Tests
      8  *
      9  *      DMA     Sends packets from CPU to MMU, and back
     10  *      S/G     Sends packets from CPU to MMU, and back, using multiple
     11  *              descriptors per packet
     12  *      MAC     Sends packets from CPU to MAC in loopback mode, and back
     13  *      MII     Sends packets from CPU to PHY in loopback mode, and back
     14  *      EXT     Sends packets from CPU out one port, in another, and back
     15  *      SNAKE   Sends packets from CPU through a series of ports, and back
     16  *
     17  * In Continuous DMA mode we append a reload descriptor to the end of the
     18  * chain and enable a new controlled descriptor interrupt to manage the
     19  * DMA state. To operate in this mode, two descriptor chains are used rather
     20  * than one and DMA readies one while the other is in use and moves into it
     21  * once the demand is there. In this mode DMA never stops. It only halts
     22  * on the reload descriptor if the next chain is not ready (RX) or there is
     23  * no packet to send (TX).
     24  */
     25 
     26 #include <shared/bsl.h>
     27 
     28 #include <sal/types.h>
     29 #include <sal/core/boot.h>
     30 #include <sal/appl/sal.h>
     31 #include <sal/appl/config.h>
     32 #include <appl/diag/system.h>
     33 #include <appl/test/loopback2.h>
     34 #include <appl/diag/parse.h>
     35 #include <appl/diag/system.h>
     36 #include <shared/bsl.h>
     37 #include <soc/mem.h>
     38 #include <soc/debug.h>
     39 #include <soc/hash.h>
     40 
     41 #include <soc/dma.h>
     42 #include <soc/higig.h>
     43 #include <soc/pbsmh.h>
     44 #include <soc/counter.h>
     45 #include <soc/register.h>
     46 #include <soc/memory.h>
     47 #include <soc/firebolt.h>
     48 #include <bcm/init.h>
     49 #include <bcm_int/control.h>
     50 #include <bcm/error.h>
     51 #include <bcm/l2.h>
     52 #include <bcm/port.h>
     53 #include <bcm/vlan.h>
     54 #include <bcm/link.h>
     55 #include <bcm/stg.h>
     56 #include <bcm/stack.h>
     57 #include <bcm/cosq.h>
     58 #include <bcm/stat.h>
     59 
     60 #if defined(BCM_CMICM_SUPPORT)
     61 #include <soc/cmicm.h>
     62 #endif
     63 
     64 #ifdef BCM_ESW_SUPPORT
     65 #include <bcm_int/esw/mbcm.h>
     66 #endif /* BCM_ESW_SUPPORT */
     67 
     68 #ifdef BCM_TOMAHAWK3_SUPPORT
     69 #include <soc/tomahawk3.h>
     70 #endif
     71 
     72 #if defined (BCM_PETRA_SUPPORT)
     73 #include <soc/dpp/drv.h>
     74 #else
     75 #define SOC_DPP_PP_ENABLE(unit) (0)
     76 #endif
     77 
     78 #include <appl/test/loopback.h>
     79 #include <appl/test/lb_util.h>
     80 
     81 #include "testlist.h"
     82 
     83 #if defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) 
     84 #include <appl/diag/dcmn/counter.h>
     85 #endif
     86 
     87 #ifdef INCLUDE_KNET
     88 #include <kcom.h>
     89 #endif
     90 
     91 
     92 #define LB_LAST_DCB(unit, dcb, cnt) SOC_DCB_IDX2PTR(unit, dcb, cnt-1)
     93 #define LB_LAST_PKT_DCB(unit, dcb, cnt) SOC_DCB_IDX2PTR(unit, dcb, cnt-2)
     94 
     95 #if defined (BCM_ESW_SUPPORT) ||  defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT)
     96 #undef LB_PBM_TEST                      /* Test not yet validated */
     97 
     98 /* sal_mac_addr_t lb_mac_default = {0x00, 0x00, 0x00, 0xde, 0xad, 0x00}; */
     99 sal_mac_addr_t lb_mac_src = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
    100 sal_mac_addr_t lb_mac_dst = {0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb};
    101 
    102 const char *lb_parse_speed[] = {
    103     LB2_SPEED_INIT_STR,
    104     NULL
    105 };
    106 #define CHECK_PBM_SPEED(x, y) ((x) & (y))
    107 /*
    108  * CRC mode handling: Defines MUST MATCH BELOW order
    109  */
    110 
    111 #define CRC_MODE_CPU_NONE               0
    112 #define CRC_MODE_CPU_APPEND             1
    113 #define CRC_MODE_MAC_REGEN              2
    114 
    115 STATIC uint32 lb_saved_srcmod[SOC_MAX_NUM_DEVICES];
    116 STATIC uint32 lb_saved_srcport[SOC_MAX_NUM_DEVICES];
    117 #ifdef BCM_XGS3_SWITCH_SUPPORT
    118 static bcm_l2_cache_addr_t lb_saved_l2[SOC_MAX_NUM_DEVICES];
    119 static int l2_index = -1;
    120 #endif
    121 
    122 #ifdef BCM_SHADOW_SUPPORT
    123 static int lb_setup_static_path(loopback_test_t *lw, int unit, soc_port_t port,
    124                      soc_port_t src_port);
    125 #endif
    126 
    127 STATIC
    128 char *crc_mode[] = { "CpuNone", "CpuAppend", "MacRegen", NULL };
    129 
    130 STATIC INLINE int crc_mode_to_dmac(int m)
    131 {
    132     if (m == CRC_MODE_MAC_REGEN) {
    133         return TRUE;
    134     } else {
    135         return FALSE;
    136     }
    137 }
    138 
    139 /*
    140  * Loopback work structure
    141  */
    142 
    143 STATIC loopback_test_t lb_work[SOC_MAX_NUM_DEVICES];
    144 
    145 loopback_test_t*
    146 lb_get_test(int unit)
    147 {
    148     return &lb_work[unit];
    149 }
    150 
    151 loopback_testdata_t*
    152 lb_get_dma_testdata(int unit)
    153 {
    154     return &lb_get_test(unit)->lw_lp_dma;
    155 }
    156 
    157 int
    158 lb_is_xgs_fabric(int unit)
    159 {
    160     /* True fabric device */
    161     if (SOC_IS_XGS_FABRIC(unit)&& !SOC_IS_TOMAHAWK2(unit)) {
    162         return 1;
    163     }
    164     /* Ethernet ports disabled by config or bond-option */
    165     if (SOC_PBMP_IS_NULL(PBMP_E_ALL(unit))) {
    166         return 1;
    167     }
    168     return 0;
    169 }
    170 
    171 STATIC  uint32
    172 lb_timeout_usec(int unit)
    173 {
    174     uint32              defl;
    175 
    176     if (SAL_BOOT_QUICKTURN) {
    177         defl = LB_PACKET_TIMEOUT_QT;
    178     } else if (SAL_BOOT_PLISIM) {
    179         defl = LB_PACKET_TIMEOUT_PLI;
    180     } else {
    181         defl = LB_PACKET_TIMEOUT;
    182     }
    183 
    184     return (soc_property_get(unit, spn_DIAG_LB_PACKET_TIMEOUT, defl) *
    185             SECOND_USEC);
    186 }
    187 
    188 STATIC int
    189 lb_link_wait(int unit, pbmp_t pbm)
    190 /*
    191  * Function:    lb_link_wait
    192  * Purpose:     Wait for link up status on the spedified ports.
    193  * Parameters:  unit - StrataSwitch unit #.
    194  *              pbm  - port bit map of ports to wait for.
    195  * Returns:     0 - Success
    196  *              -1 - time-out waiting for ports.
    197  */
    198 {
    199     int         rv;
    200     pbmp_t      link_pbm, tpbm;
    201 
    202     BCM_PBMP_ASSIGN(link_pbm, pbm);
    203     if ((rv = bcm_link_wait(unit, &link_pbm, LB_LINK_TIMEOUT))) {
    204         char    b[FORMAT_PBMP_MAX];
    205 
    206         BCM_PBMP_ASSIGN(tpbm, pbm);
    207         BCM_PBMP_REMOVE(tpbm, link_pbm);
    208         (void)format_pbmp(unit, b, sizeof(b), tpbm);
    209         test_error(unit, "Failed to get Link up indication: %s\n", b);
    210         return(-1);
    211     }
    212 
    213     return(0);
    214 }
    215 
    216 /*
    217  * Function:    lb_ppce_initval
    218  * Purpose:     Calculates values that are used to keep the number of packets per 
    219                 chain within the limits that the MMU COS settings can handle.
    220  * Parameters:  unit - unit to be used at a test
    221  *              len -  actual len of a packet
    222  *              ppce - output for packets per chain end
    223  * Returns:     SOC_E_XXX
    224 */
    225 static int 
    226 lb_ppce_initval(int unit, int *lene, int *ppce)
    227 {
    228     int max_cells, num_cells, num_ports, num_cos, mmu_cell_size;
    229     int len;
    230     int ppce_max = SOC_DV_PKTS_MAX; 
    231     
    232 
    233     *ppce = ppce_max;
    234     len = *lene;
    235 
    236     if (SOC_IS_SHADOW(unit)) {
    237         return SOC_E_NONE;
    238     }
    239 
    240     if (SOC_IS_XGS_SWITCH(unit) || SOC_IS_XGS12_FABRIC(unit)) {
    241 
    242         /* Check that we don't overload the MMU HOL cell limits */
    243         /*  (This should be from #defines somewhere else)  */
    244         mmu_cell_size = 128;
    245         BCM_IF_ERROR_RETURN(bcm_cosq_config_get(unit, &num_cos));
    246         max_cells = (len + mmu_cell_size - 1) / mmu_cell_size;
    247 #ifndef _KATANA_DEBUG
    248 		if (SOC_IS_KATANAX(unit)) {
    249 			num_cells = 8192;
    250 		} else 
    251 #endif
    252 #if defined(BCM_ESW_SUPPORT)
    253         if (SOC_IS_FBX(unit)) {
    254             /* MMU_CBPDATA0 does not exist in TH3, so calc total cells */
    255 #ifdef BCM_TOMAHAWK3_SUPPORT
    256             if (SOC_IS_TOMAHAWK3(unit)) {
    257                 num_cells = _TH3_MMU_TOTAL_CELLS_PER_ITM;
    258             } else 
    259 #endif
    260             {
    261                 num_cells = soc_mem_index_count(unit, MMU_CBPDATA0m);
    262             }
    263         } else 
    264 #endif
    265         {
    266             num_cells = 8192;
    267         }
    268         num_ports = NUM_ALL_PORT(unit);
    269         *ppce = (num_cells / (num_cos * num_ports * max_cells)) - 1;
    270 
    271 #if defined(BCM_HERCULES_SUPPORT)
    272         /* For hercules, look at what is configured for any port/cos 0,0 */
    273         if (SOC_IS_HERCULES15(unit)) {
    274             int cos = 0;
    275             int port = 0;
    276             uint32 num_cells_per_port_cos = 0;
    277 
    278             SOC_IF_ERROR_RETURN
    279                 (READ_MMU_CELLLMTCOS_LOWERr(unit, port, cos,
    280                                             &num_cells_per_port_cos));
    281             /* overwrite ppce */
    282             *ppce = (num_cells_per_port_cos / max_cells) - 1; 
    283         }
    284 #endif /* BCM_HERCULES_SUPPORT */
    285 
    286         if (*ppce < 1) {
    287             *ppce = 1;
    288         }
    289         if (*ppce > ppce_max) {
    290             *ppce = ppce_max;
    291         }
    292         /*
    293          * Number of cells allocated to this port
    294          * Assume DYNCELL_PERCENT 50
    295          */
    296         len = num_cells / num_ports / 2;
    297 
    298         /*
    299          * Number of cells usable by a cos queue
    300          */
    301         len += (len / num_cos);
    302         /*
    303          * Max packet size supported
    304          */
    305         len *= mmu_cell_size;
    306         if (*lene > len) {
    307             *lene = len;
    308         }
    309     }
    310     return(SOC_E_NONE);
    311 }
    312 
    313 STATIC  void
    314 lb_setup(int unit, loopback_test_t *lw)
    315 /*
    316  * Function:    lb_setup
    317  * Purpose:     Fill in defaults for the parameters.
    318  * Parameters:  unit - unit #.
    319  *              lw - pointer to work struct.
    320  * Returns:     Nothing
    321  */
    322 {
    323     loopback_testdata_t *lp;
    324     int                 p, setport;
    325     int                 num_cos;
    326     int                 lene_ignore = 0;
    327 
    328     if (bcm_cosq_config_get(unit, &num_cos) < 0 || num_cos == 0) {
    329         num_cos = 1;
    330     }
    331 
    332     /* Keep statistics from printing if user ^C's before test starts */
    333     lw->lw_stats_init = FALSE;
    334 
    335     if (lw->lw_set_up) {
    336         return;
    337     }
    338 
    339     lw->lw_set_up = soc_property_get(unit, "lw_set_up_reinit_skip", TRUE);
    340     lw->lw_unit = unit;
    341 
    342     lw->lw_mac_src_inc = 0;
    343     lw->lw_mac_dst_inc = 0;
    344 
    345     /* Check config for DMA Mode */
    346     lw->lw_dma_mode = LB_LEGACY_DMA_MODE;
    347 #if defined(BCM_CMICDV2_SUPPORT) || defined(BCM_CMICX_SUPPORT)
    348     if (soc_feature(unit, soc_feature_continuous_dma) &&
    349         soc_property_get(unit, spn_PDMA_CONTINUOUS_MODE_ENABLE, 0)) {
    350         lw->lw_dma_mode = LB_CONTINUOUS_DMA_MODE;
    351         cli_out("Using Continuous DMA Mode\n");
    352     }
    353 #endif
    354 
    355     /* CPU */
    356 
    357     lp = &lw->lw_lp_dma;
    358     SOC_PBMP_CLEAR(lp->lp_pbm);
    359     SOC_PBMP_PORT_ADD(lp->lp_pbm, CMIC_PORT(unit));
    360 
    361     lp->lp_dst_inc      = 0;
    362     SOC_PBMP_CLEAR(lp->lp_ubm);
    363     lp->lp_pattern      = 0xa5a4a3a2;
    364     lp->lp_pattern_inc  = 1;
    365     lp->lp_vlan         = LB_VLAN_ID;
    366     lp->lp_l_start      = 64;
    367     lp->lp_l_end        = 2048 + 64;
    368     lp->lp_l_inc        = 256;
    369     lp->lp_c_start      = 1;
    370     lp->lp_c_end        = 16;
    371     lp->lp_c_inc        = 5;
    372     lp->lp_dv_start     = 1;
    373     lp->lp_dv_end       = 1;
    374     lp->lp_dv_inc       = 1;
    375     lp->lp_cos_start    = 0;
    376     lp->lp_cos_end      = num_cos - 1;
    377     lp->lp_count        = 10;
    378     lp->lp_crc_mode     = CRC_MODE_CPU_NONE;
    379     lp->lp_check_data   = TRUE;
    380     lp->lp_check_crc    = FALSE;
    381  
    382     /* MAC */
    383 
    384     lp = &lw->lw_lp_mac;
    385 
    386     SOC_PBMP_ASSIGN(lp->lp_pbm, PBMP_PORT_ALL(unit));
    387     lp->lp_dst_inc      = 0;
    388     SOC_PBMP_CLEAR(lp->lp_ubm);
    389     lp->lp_pattern      = 0xa5a4a3a2;
    390     lp->lp_pattern_inc  = 0;
    391     lp->lp_vlan         = LB_VLAN_ID;
    392     lp->lp_d_port       = CMIC_PORT(unit);
    393     if (SOC_IS_XGS_SWITCH(unit)) {
    394         if (bcm_stk_my_modid_get(unit, &lp->lp_d_mod) < 0) {
    395             lp->lp_d_mod = 0;
    396         }
    397     } else {
    398 #ifdef BCM_XGS_SUPPORT
    399         lp->lp_d_mod    = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
    400 #else
    401         lp->lp_d_mod    = 0;
    402 #endif
    403     }
    404 #ifdef BCM_XGS_SUPPORT
    405     lp->lp_opcode       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
    406 #else
    407     lp->lp_opcode       = 0;
    408 #endif
    409     lp->lp_l_start      = 68;
    410     lp->lp_l_end        = 1522;
    411     lp->lp_l_inc        = 128;
    412     lp->lp_c_start      = 1;
    413     lene_ignore = lp->lp_l_end;
    414     (void)lb_ppce_initval(unit, &lene_ignore, &lp->lp_c_end);
    415     lp->lp_c_inc        = 1;
    416     lp->lp_dv_start     = 1;
    417     lp->lp_dv_end       = LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode) ? 2 : 1;
    418     lp->lp_dv_inc       = 1;
    419     lp->lp_cos_start    = 0;
    420     lp->lp_cos_end      = num_cos - 1;
    421     lp->lp_count        = 10;
    422     lp->lp_crc_mode     = CRC_MODE_MAC_REGEN;
    423     lp->lp_check_data   = TRUE;
    424     lp->lp_check_crc    = FALSE;
    425 
    426     ENET_SET_MACADDR(lp->lp_mac_src, lb_mac_src);
    427     lp->lp_mac_src_inc = 0;
    428     ENET_SET_MACADDR(lp->lp_mac_dst, lb_mac_dst);
    429     lp->lp_mac_dst_inc = 0;
    430 
    431     /* PHY */
    432 
    433     lp = &lw->lw_lp_phy;
    434 
    435     SOC_PBMP_ASSIGN(lp->lp_pbm, PBMP_PORT_ALL(unit));
    436     lp->lp_dst_inc      = 0;
    437     SOC_PBMP_CLEAR(lp->lp_ubm);
    438     lp->lp_pattern      = 0xa5a4a3a2;
    439     lp->lp_pattern_inc  = 0;
    440     lp->lp_vlan         = LB_VLAN_ID;
    441     lp->lp_d_port       = CMIC_PORT(unit);
    442     if (SOC_IS_XGS_SWITCH(unit)) {
    443         if (bcm_stk_my_modid_get(unit, &lp->lp_d_mod) < 0) {
    444             lp->lp_d_mod = 0;
    445         }
    446     } else {
    447 #ifdef BCM_XGS_SUPPORT
    448         lp->lp_d_mod    = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
    449 #else
    450         lp->lp_d_mod    = 0;
    451 #endif
    452     }
    453 #ifdef BCM_XGS_SUPPORT
    454     lp->lp_opcode       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
    455 #else
    456     lp->lp_opcode       = 0;
    457 #endif
    458     lp->lp_l_start      = 68;
    459     lp->lp_l_end        = 1522;
    460     lp->lp_l_inc        = 128;
    461     lp->lp_c_start      = 1;
    462     lene_ignore = lp->lp_l_end;
    463     (void)lb_ppce_initval(unit, &lene_ignore, &lp->lp_c_end);
    464     lp->lp_c_inc        = 1;
    465     lp->lp_dv_start     = 1;
    466     lp->lp_dv_end       = LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode) ? 2 : 1;
    467     lp->lp_dv_inc       = 1;
    468     lp->lp_cos_start    = 0;
    469     lp->lp_cos_end      = num_cos - 1;
    470     lp->lp_count        = 10;
    471     lp->lp_crc_mode     = CRC_MODE_MAC_REGEN;
    472     lp->lp_check_data   = TRUE;
    473     lp->lp_check_crc    = FALSE;
    474 
    475     ENET_SET_MACADDR(lp->lp_mac_src, lb_mac_src);
    476     lp->lp_mac_src_inc = 0;
    477     ENET_SET_MACADDR(lp->lp_mac_dst, lb_mac_dst);
    478     lp->lp_mac_dst_inc = 0;
    479 
    480     /* EXT */
    481 
    482     lp = &lw->lw_lp_ext;
    483 
    484     SOC_PBMP_CLEAR(lp->lp_pbm);
    485     /* set up pairs of transmitting and receiving ports */
    486     SOC_PBMP_CLEAR(lp->lp_pbm_tx);
    487     setport = 1;
    488     PBMP_PORT_ITER(unit, p) {
    489         if (setport) {
    490             SOC_PBMP_PORT_ADD(lp->lp_pbm_tx, p);
    491         }
    492         setport = !setport;
    493     }
    494     lp->lp_dst_inc      = 1;
    495     SOC_PBMP_CLEAR(lp->lp_ubm);
    496     lp->lp_pattern      = 0xa5a4a3a2;
    497     lp->lp_pattern_inc  = 0;
    498     lp->lp_vlan         = LB_VLAN_ID;
    499     lp->lp_d_port       = CMIC_PORT(unit);
    500     if (SOC_IS_XGS_SWITCH(unit)) {
    501         if (bcm_stk_my_modid_get(unit, &lp->lp_d_mod) < 0) {
    502             lp->lp_d_mod = 0;
    503         }
    504     } else {
    505 #ifdef BCM_XGS_SUPPORT
    506         lp->lp_d_mod    = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_DST_MOD_CPU : 0;
    507 #else
    508         lp->lp_d_mod    = 0;
    509 #endif
    510     }
    511 #ifdef BCM_XGS_SUPPORT
    512     lp->lp_opcode       = SOC_IS_XGS12_FABRIC(unit) ? SOC_HIGIG_OP_UC : 0;
    513 #else
    514     lp->lp_opcode       = 0;
    515 #endif
    516     lp->lp_l_start      = 68;
    517     lp->lp_l_end        = 1522;
    518     lp->lp_l_inc        = 128;
    519     lp->lp_c_start      = 1; 
    520     lene_ignore = lp->lp_l_end;
    521     (void)lb_ppce_initval(unit, &lene_ignore, &lp->lp_c_end);
    522     lp->lp_c_inc        = 1;
    523     lp->lp_dv_start     = 1;
    524     lp->lp_dv_end       = 1;
    525     lp->lp_dv_inc       = 1;
    526     lp->lp_cos_start    = 0;
    527     lp->lp_cos_end      = num_cos - 1;
    528     lp->lp_count        = 10;
    529     lp->lp_crc_mode     = CRC_MODE_MAC_REGEN;
    530     lp->lp_check_data   = TRUE;
    531     lp->lp_check_crc    = FALSE;
    532     lp->lp_autoneg      = TRUE;
    533 
    534     ENET_SET_MACADDR(lp->lp_mac_src, lb_mac_src);
    535     lp->lp_mac_src_inc = 0;
    536     ENET_SET_MACADDR(lp->lp_mac_dst, lb_mac_dst);
    537     lp->lp_mac_dst_inc = 0;
    538 
    539     /* S/G DMA */
    540     lp = &lw->lw_lp_sg_dma;
    541 
    542     SOC_PBMP_ASSIGN(lp->lp_pbm, PBMP_PORT_ALL(unit));
    543     lp->lp_dst_inc      = 1;
    544     SOC_PBMP_CLEAR(lp->lp_ubm);
    545     lp->lp_pattern      = 0xa5a4a3a2;
    546     lp->lp_pattern_inc  = 1;
    547     lp->lp_vlan         = LB_VLAN_ID;
    548     lp->lp_l_start      = 64;
    549     lp->lp_l_end        = 1024 + 64;
    550     lp->lp_l_inc        = 128;
    551     lp->lp_ppc_start    = 1;
    552     lene_ignore = lp->lp_l_end;
    553     (void)lb_ppce_initval(unit, &lene_ignore, &lp->lp_ppc_end);
    554     lp->lp_ppc_inc      = 2;
    555     lp->lp_dpp_start    = 1;
    556     lp->lp_dpp_end      = 13;
    557     lp->lp_dpp_inc      = 3;
    558     lp->lp_c_start      = 2;
    559     lp->lp_c_end        = 8;
    560     lp->lp_c_inc        = 2;
    561     lp->lp_dv_start     = 2;
    562     lp->lp_dv_end       = 8;
    563     lp->lp_dv_inc       = 3;
    564     lp->lp_cos_start    = 0;
    565     lp->lp_cos_end      = 0;
    566     lp->lp_count        = 1;
    567     lp->lp_crc_mode     = CRC_MODE_CPU_NONE;
    568     lp->lp_check_data   = TRUE;
    569     lp->lp_check_crc    = FALSE;
    570     lp->lp_seed         = (2 << 24) - 1;
    571     ENET_SET_MACADDR(lp->lp_mac_src, lb_mac_src);
    572     ENET_SET_MACADDR(lp->lp_mac_dst, lb_mac_dst);
    573 
    574     /* S/G RANDOM */
    575     lp = &lw->lw_lp_sg_random;
    576 
    577     SOC_PBMP_ASSIGN(lp->lp_pbm, PBMP_PORT_ALL(unit));
    578     lp->lp_dst_inc      = 1;
    579     SOC_PBMP_CLEAR(lp->lp_ubm);
    580     lp->lp_pattern      = 0xa5a4a3a2;
    581     lp->lp_pattern_inc  = 1;
    582     lp->lp_vlan         = LB_VLAN_ID;
    583     lp->lp_l_start      = 64;
    584     lp->lp_l_end        = 1024 + 64;
    585     lp->lp_l_inc        = 128;
    586     lp->lp_ppc_start    = 1;
    587     lene_ignore = lp->lp_l_end;
    588     (void)lb_ppce_initval(unit, &lene_ignore, &lp->lp_ppc_end);
    589     lp->lp_ppc_inc      = 2;
    590     lp->lp_dpp_start    = 1;
    591     lp->lp_dpp_end      = 13;
    592     lp->lp_dpp_inc      = 3;
    593     lp->lp_c_start      = 2;
    594     lp->lp_c_end        = 8;
    595     lp->lp_c_inc        = 2;
    596     lp->lp_dv_start     = 2;
    597     lp->lp_dv_end       = 8;
    598     lp->lp_dv_inc       = 3;
    599     lp->lp_cos_start    = 0;
    600     lp->lp_cos_end      = 0;
    601     lp->lp_count        = 5;
    602     lp->lp_crc_mode     = CRC_MODE_CPU_NONE;
    603     lp->lp_check_data   = TRUE;
    604     lp->lp_check_crc    = FALSE;
    605     lp->lp_seed         = (2 << 24) - 1;
    606     ENET_SET_MACADDR(lp->lp_mac_src, lb_mac_src);
    607     ENET_SET_MACADDR(lp->lp_mac_dst, lb_mac_dst);
    608 
    609 
    610 }
    611 
    612 STATIC int
    613 lb_unused_10g_ports_enable_set(int unit, soc_port_t rx_port, int enable)
    614 {
    615     int rv = 0;
    616 
    617     /* Disable all but rx_port */
    618     if (SOC_IS_XGS3_SWITCH(unit)) {
    619         int port;
    620         PBMP_HG_ITER(unit, port) {
    621             if (port != rx_port) {
    622                 if ((rv = bcm_port_enable_set(unit, port, enable)) < 0) {
    623                     test_error(unit,
    624                             "Port %s: Failed to set MAC %s: %s\n",
    625                             SOC_PORT_NAME(unit, port),
    626                             (enable ? "Enable" : "Disable"), bcm_errmsg(rv));
    627                     return(-1);
    628                 }
    629             }
    630         }
    631         PBMP_XE_ITER(unit, port) {
    632             if (port != rx_port) {
    633                 if ((rv = bcm_port_enable_set(unit, port, enable)) < 0) {
    634                     test_error(unit,
    635                             "Port %s: Failed to set MAC %s: %s\n",
    636                             SOC_PORT_NAME(unit, port),
    637                             (enable ? "Enable" : "Disable"), bcm_errmsg(rv));
    638                     return(-1);
    639                 }
    640             }
    641         }
    642     }
    643     return(0);
    644 }
    645 
    646 STATIC int
    647 lb_save_port(loopback_test_t *lw)
    648 {
    649     int         rv = 0;
    650     soc_port_t  port;
    651     pbmp_t      save_ports;
    652 
    653     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
    654         /* Save and restore all ports -- see lb_mac_init */
    655         SOC_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(lw->lw_unit));
    656     } else {
    657         SOC_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(lw->lw_unit));
    658         SOC_PBMP_AND(save_ports, lw->lw_lp->lp_pbm);
    659     }
    660     
    661     if (SOC_IS_SHADOW(lw->lw_unit)) {
    662         return SOC_E_NONE;
    663     }
    664     PBMP_ITER(save_ports, port) {
    665         if ((rv = bcm_port_info_save(lw->lw_unit, port,
    666                                      &lw->lw_save_port[port])) < 0) {
    667             test_error(lw->lw_unit,
    668                        "Port %s: Could not get port info: %s\n",
    669                        SOC_PORT_NAME(lw->lw_unit, port), bcm_errmsg(rv));
    670             return(-1);
    671         }
    672     }
    673 
    674     /* Module settings */
    675     if (SOC_IS_XGS_SWITCH(lw->lw_unit)) {
    676         int     not_my_mod;
    677         /* Save current source port/module and change to != 
    678            lw->lw_lp->lp_d_mod */
    679 
    680         lb_saved_srcmod[lw->lw_unit] = SOC_DEFAULT_DMA_SRCMOD_GET(lw->lw_unit);
    681         lb_saved_srcport[lw->lw_unit] =
    682             SOC_DEFAULT_DMA_SRCPORT_GET(lw->lw_unit);
    683         not_my_mod = (lw->lw_lp->lp_d_mod == 0);
    684         SOC_DEFAULT_DMA_SRCMOD_SET(lw->lw_unit, not_my_mod);
    685         SOC_DEFAULT_DMA_SRCPORT_SET(lw->lw_unit, CMIC_PORT(lw->lw_unit));
    686         /* Program these values into CMIC_HGTX_CTRL* register */
    687 #ifdef BCM_XGS3_SWITCH_SUPPORT
    688         if (SOC_IS_XGS3_SWITCH(lw->lw_unit)) {
    689             /*
    690              * Should save (not yet done here) ICONTROL_OPCODE_BITMAP before
    691              * the test and restore it after test is done
    692              * Redirect all packets with CPU control opcode from HG ports to CPU.
    693              */
    694             int pbm_len;
    695             uint32 cpu_pbm;
    696 
    697             if (SOC_IS_TR_VL(lw->lw_unit) && !(SOC_IS_TRIUMPH2(lw->lw_unit) 
    698                 || SOC_IS_APOLLO(lw->lw_unit) || SOC_IS_VALKYRIE2(lw->lw_unit))) {
    699                 SOC_IF_ERROR_RETURN(soc_xgs3_port_to_higig_bitmap
    700                                         (lw->lw_unit, CMIC_PORT(lw->lw_unit),
    701                                          &cpu_pbm));
    702             } else if (CMIC_PORT(lw->lw_unit)) {
    703                 pbm_len = soc_reg_field_length(lw->lw_unit,
    704                                                ICONTROL_OPCODE_BITMAPr,
    705                                                BITMAPf);
    706                 if (pbm_len == 0) {
    707                     return (-1);
    708                 }
    709                 cpu_pbm = 1 << (pbm_len - 1);
    710             } else {
    711                 cpu_pbm = 1;
    712             }
    713             PBMP_ST_ITER(lw->lw_unit, port) {
    714                 if (SOC_MEM_IS_VALID(lw->lw_unit, ICONTROL_OPCODE_BITMAPm)) {
    715                     icontrol_opcode_bitmap_entry_t entry;
    716                     sal_memset(&entry, 0, sizeof(entry));
    717                     soc_mem_pbmp_field_set(lw->lw_unit,
    718                                            ICONTROL_OPCODE_BITMAPm,
    719                                            &entry, BITMAPf,
    720                                            &PBMP_CMIC(lw->lw_unit));
    721                     rv = soc_mem_write(lw->lw_unit, ICONTROL_OPCODE_BITMAPm,
    722                                        MEM_BLOCK_ANY, port, &entry);
    723                 } else if (SOC_IS_TRIUMPH2(lw->lw_unit) ||
    724                            SOC_IS_APOLLO(lw->lw_unit) ||
    725                            SOC_IS_VALKYRIE2(lw->lw_unit)) {
    726                     uint64 cpu_pbm_64;
    727                     COMPILER_64_ZERO(cpu_pbm_64);
    728                     COMPILER_64_SET(cpu_pbm_64, 0, cpu_pbm);
    729                     rv = WRITE_ICONTROL_OPCODE_BITMAP_64r(lw->lw_unit,
    730                                                           port, cpu_pbm_64);
    731                 } else if (SOC_REG_IS_VALID(lw->lw_unit, ICONTROL_OPCODE_BITMAP_LOr) &&
    732                            SOC_REG_IS_VALID(lw->lw_unit, ICONTROL_OPCODE_BITMAP_HIr)) {
    733 
    734                     uint64      fval64, rval64;
    735                     uint32      t_port;
    736                     pbmp_t      curr_pbmp;
    737                     soc_reg_t   reg;
    738 
    739                     BCM_PBMP_CLEAR(curr_pbmp);
    740                     COMPILER_64_ZERO(fval64);
    741 
    742                     /* Set HG ingress CPU Opcode map to the CPU */
    743                     if (CMIC_PORT(lw->lw_unit) < 64) {
    744                         reg = ICONTROL_OPCODE_BITMAP_LOr;
    745                         t_port = CMIC_PORT(lw->lw_unit);
    746                     } else {
    747                         reg = ICONTROL_OPCODE_BITMAP_HIr;
    748                         t_port = CMIC_PORT(lw->lw_unit) - 64;
    749                     }
    750 
    751                     SOC_PBMP_PORT_ADD(curr_pbmp, t_port);
    752 
    753                     rv = soc_reg_get(lw->lw_unit, reg, port, 0, &rval64);
    754                     if (BCM_SUCCESS(rv)) {
    755                         COMPILER_64_SET(fval64,
    756                                         SOC_PBMP_WORD_GET(curr_pbmp, 1),
    757                                         SOC_PBMP_WORD_GET(curr_pbmp, 0));
    758 
    759                         soc_reg64_field_set(lw->lw_unit, 
    760                                 reg, &rval64, BITMAPf, fval64);
    761                     }
    762                     rv = soc_reg_set(lw->lw_unit, reg, port, 0, rval64);
    763                 } else {
    764                     if (SOC_REG_IS_VALID(lw->lw_unit, ICONTROL_OPCODE_BITMAPr)) {
    765                         rv = WRITE_ICONTROL_OPCODE_BITMAPr(lw->lw_unit,
    766                                                            port, cpu_pbm);
    767                     }
    768                 }
    769                 if (rv < 0) {
    770                     test_error(lw->lw_unit,
    771                                "Failed to direct HG traffic to CPU %s\n",
    772                                bcm_errmsg(rv));
    773                     return(-1);
    774                 }
    775             }
    776             if (l2_index >= 0) {
    777                 if ((rv = bcm_l2_cache_get(lw->lw_unit, l2_index,
    778                                            &lb_saved_l2[lw->lw_unit])) < 0) {
    779                     test_error(lw->lw_unit,
    780                                "Failed to save L2 Cache entry %s\n",
    781                                bcm_errmsg(rv));
    782                     return(-1);
    783                 }
    784             }
    785         } else
    786 #endif
    787         {
    788             test_error(lw->lw_unit, "Loopback Error:  Invalid SOC type\n");
    789             return(-1);
    790         }
    791     } 
    792 #ifdef  BCM_XGS12_FABRIC_SUPPORT
    793 	else if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
    794         uint32      ucdata;
    795         pbmp_t      uc;
    796         int         blk;
    797         
    798         SOC_PBMP_CLEAR(uc);
    799         SOC_PBMP_PORT_ADD(uc, CMIC_PORT(lw->lw_unit));
    800         ucdata = SOC_PBMP_WORD_GET(uc, 0);
    801         PBMP_ITER(save_ports, port) {
    802             blk = SOC_PORT_BLOCK(lw->lw_unit, port);
    803 #if defined(BCM_ESW_SUPPORT)
    804 			
    805             if ((rv = soc_mem_write(lw->lw_unit, MEM_UCm, blk,
    806                                     lw->lw_lp->lp_d_mod, &ucdata)) < 0) {
    807                 test_error(lw->lw_unit,
    808                            "Could not write MEM_UC table %s\n",
    809                            bcm_errmsg(rv));
    810                 return(-1);
    811             }
    812 #endif			
    813         }
    814     }
    815 #endif
    816     return(0);
    817 }
    818 
    819 STATIC int
    820 lb_restore_port(loopback_test_t *lw)
    821 {
    822     int         rv;
    823     int         ms;
    824     soc_port_t  port;
    825     pbmp_t      save_ports;
    826 
    827     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
    828         /* Save and restore all ports -- see lb_mac_init */
    829         SOC_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(lw->lw_unit));
    830     } else {
    831         SOC_PBMP_ASSIGN(save_ports, PBMP_PORT_ALL(lw->lw_unit));
    832         SOC_PBMP_AND(save_ports, lw->lw_lp->lp_pbm);
    833     }
    834 
    835     if (SOC_IS_SHADOW(lw->lw_unit)) {
    836         return SOC_E_NONE;
    837     }
    838     PBMP_ITER(save_ports, port) {
    839         /* If the Master mode is not changed, remove phy_master attributes from action_mask*/
    840         ms = 0;
    841         if ((rv = bcm_port_master_get(lw->lw_unit, port, &ms)) != BCM_E_NONE) {
    842             test_error(lw->lw_unit,
    843                        "Port %s: Could not get port Master mode: %s\n",
    844                        SOC_PORT_NAME(lw->lw_unit, port), bcm_errmsg(rv));
    845             return (-1);
    846         }
    847         if (ms == lw->lw_save_port[port].phy_master) {
    848             lw->lw_save_port[port].action_mask &= ~BCM_PORT_ATTR_PHY_MASTER_MASK;
    849         }
    850 
    851         if ((rv = bcm_port_info_restore(lw->lw_unit, port,
    852                                     &lw->lw_save_port[port])) < 0) {
    853             test_error(lw->lw_unit,
    854                        "Port %s: Could not restore port info: %s\n",
    855                        SOC_PORT_NAME(lw->lw_unit, port), bcm_errmsg(rv));
    856             return(-1);
    857         }
    858     }
    859 
    860     if (SOC_IS_XGS_SWITCH(lw->lw_unit)) {
    861         /* Restore source port/module for ipic */
    862         SOC_DEFAULT_DMA_SRCMOD_SET(lw->lw_unit, lb_saved_srcmod[lw->lw_unit]);
    863         SOC_DEFAULT_DMA_SRCPORT_SET(lw->lw_unit, lb_saved_srcport[lw->lw_unit]);
    864     }
    865 #ifdef BCM_XGS3_SWITCH_SUPPORT
    866     if (SOC_IS_XGS3_SWITCH(lw->lw_unit)) {
    867         if (l2_index >= 0) {
    868             if ((rv = bcm_l2_cache_set(lw->lw_unit, l2_index,
    869                                        &lb_saved_l2[lw->lw_unit],
    870                                        &l2_index)) < 0) {
    871                 test_error(lw->lw_unit,
    872                            "Failed to Restore L2 Cache entry %s\n",
    873                            bcm_errmsg(rv));
    874             }
    875         }
    876     }
    877 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    878     return(0);
    879 }
    880 
    881 
    882 STATIC int
    883 lb_setup_port(int unit, soc_port_t port, int req_speed, int autoneg)
    884 {
    885     int         rv;
    886     pbmp_t      pbm;
    887 
    888     rv = lbu_setup_port(unit, port, req_speed, autoneg);
    889 
    890     if (rv >= 0) {
    891         SOC_PBMP_CLEAR(pbm);
    892         SOC_PBMP_PORT_ADD(pbm, port);
    893         bcm_link_wait(unit, &pbm, 200);
    894     }
    895 
    896     return(rv);
    897 }
    898 
    899 STATIC int
    900 lb_save_vlan(loopback_test_t *lw)
    901 {
    902     int         rv;
    903     
    904     if (SOC_IS_SHADOW(lw->lw_unit)) {
    905         return SOC_E_NONE;
    906     }
    907     /* Save the spanning tree group of the vlan */
    908     if ((rv = bcm_vlan_stg_get(lw->lw_unit, lw->lw_lp->lp_vlan, 
    909                                &lw->lw_save_vlan_stg)) < 0) {
    910         if (rv == BCM_E_NOT_FOUND) {
    911             /* vlan is not valid, nothing to save so just return */
    912             return (0);
    913         } else {
    914             test_error(lw->lw_unit,
    915                        "Could not get vlan stg: %s\n", bcm_errmsg(rv));
    916             return(-1);
    917         }
    918     }
    919     
    920     /* Save the vlan port bitmaps */
    921     if ((rv = bcm_vlan_port_get(lw->lw_unit, lw->lw_lp->lp_vlan, 
    922                                 &lw->lw_save_vlan_pbmp,
    923                                 &lw->lw_save_vlan_ubmp)) < 0) {
    924         if (rv == BCM_E_NOT_FOUND) {
    925             /* vlan is not valid, nothing to save so just return */
    926             return (0);
    927         } else {
    928             test_error(lw->lw_unit,
    929                        "Could not get vlan port: %s\n", bcm_errmsg(rv));
    930             return(-1);
    931         }
    932     }
    933 
    934     /* Remove ports before test, they will be re-added when restoring */
    935     if ((rv = bcm_vlan_port_remove(lw->lw_unit, lw->lw_lp->lp_vlan, 
    936                                    lw->lw_save_vlan_pbmp)) < 0) {
    937         test_error(lw->lw_unit,
    938                    "Could not remove vlan ports: %s\n", bcm_errmsg(rv));
    939         return(-1);
    940     } 
    941 
    942     /* A valid vlan was found, remember that */
    943     lw->lw_save_vlan_valid = 1;
    944 
    945     return(0);
    946 }
    947 
    948 STATIC int
    949 lb_restore_vlan(loopback_test_t *lw)
    950 {
    951     int         rv;
    952     pbmp_t      pbmp, ubmp;
    953 
    954     if (SOC_IS_SHADOW(lw->lw_unit)) {
    955         return SOC_E_NONE;
    956     }
    957     if (lw->lw_save_vlan_valid) {
    958         /* the saved vlan was valid, restore it */
    959         
    960         /* Set the spanning tree group */
    961         rv = bcm_vlan_stg_set(lw->lw_unit, lw->lw_lp->lp_vlan,
    962                               lw->lw_save_vlan_stg);
    963         if (rv < 0 && rv != BCM_E_UNAVAIL) {
    964             test_error(lw->lw_unit, "Could not set vlan %d stg %d: %s\n",
    965                        lw->lw_lp->lp_vlan,
    966                        lw->lw_save_vlan_stg,
    967                        bcm_errmsg(rv));
    968             return(-1);
    969         }
    970 
    971         /* Get/remove all the ports that were added during the test */
    972         if ((rv = bcm_vlan_port_get(lw->lw_unit, lw->lw_lp->lp_vlan, 
    973                                     &pbmp, &ubmp)) < 0) {
    974             test_error(lw->lw_unit,
    975                        "Could not get vlan port: %s\n", bcm_errmsg(rv));
    976             return(-1);
    977         } 
    978         if ((rv = bcm_vlan_port_remove(lw->lw_unit, lw->lw_lp->lp_vlan, 
    979                                        pbmp)) < 0) {
    980             test_error(lw->lw_unit,
    981                        "Could not remove vlan ports: %s\n", bcm_errmsg(rv));
    982             return(-1);
    983         }
    984 
    985         /* Re-add the saved ports to the vlan */
    986         if ((rv = bcm_vlan_port_add(lw->lw_unit, lw->lw_lp->lp_vlan, 
    987                                     lw->lw_save_vlan_pbmp,
    988                                     lw->lw_save_vlan_ubmp)) < 0) {
    989             test_error(lw->lw_unit,
    990                        "Could not set vlan port: %s\n", bcm_errmsg(rv));
    991             return(-1);
    992         } 
    993 
    994         SOC_PBMP_CLEAR(lw->lw_save_vlan_pbmp);
    995         SOC_PBMP_CLEAR(lw->lw_save_vlan_ubmp);
    996         lw->lw_save_vlan_stg = 0;
    997         lw->lw_save_vlan_valid = 0;
    998     } else {
    999         /* the vlan is not valid, destroy what we created */
   1000 
   1001         rv = bcm_vlan_destroy(lw->lw_unit, lw->lw_lp->lp_vlan);
   1002         if (rv < 0) {
   1003             test_error(lw->lw_unit, "Could not destroy vlan %d: %s\n",
   1004                        lw->lw_lp->lp_vlan, bcm_errmsg(rv));
   1005             return(-1);
   1006         } 
   1007     }
   1008 
   1009     return(0);
   1010 }
   1011 
   1012 STATIC int
   1013 lb_stack_check(int unit)
   1014 {
   1015     if (SOC_SL_MODE(unit)) {
   1016         return -1;
   1017     }
   1018 
   1019     return 0;
   1020 }
   1021 
   1022 /*
   1023  * Loopback Statistics Report
   1024  */
   1025 
   1026 STATIC void
   1027 lb_stats_init(loopback_test_t *lw)
   1028 {
   1029     lw->lw_tx_count = 0;
   1030     lw->lw_rx_count = 0;
   1031 
   1032     lw->lw_tx_bytes = 0.0;
   1033     lw->lw_rx_bytes = 0.0;
   1034 
   1035     lw->lw_tx_stime = sal_time();
   1036     lw->lw_tx_rtime = lw->lw_tx_stime + sh_set_report_time;
   1037 
   1038     lw->lw_stats_init = TRUE;
   1039 }
   1040 
   1041 STATIC void
   1042 lb_stats_report(loopback_test_t *lw)
   1043 {
   1044     sal_time_t          now;
   1045     int                 secs;
   1046 
   1047     if (!sh_set_report_status) {
   1048         return;
   1049     }
   1050 
   1051     /*
   1052      * Feel free to call this routine after every packet sent.
   1053      * It will only report stats every "sh_set_report_time" seconds.
   1054      */
   1055 
   1056     now = sal_time();
   1057 
   1058     if ((secs = (now - lw->lw_tx_stime)) == 0) {
   1059         secs = 1;
   1060     }
   1061 
   1062     if (now >= lw->lw_tx_rtime) {
   1063         test_msg("LB: xmit %d pkt (%d%%, %d pkt/s, %d KB/s avg), "
   1064                  "recv %d pkt (%d sec)\n",
   1065                  lw->lw_tx_count/lw->lw_tx_dcb_factor,
   1066                  100 * lw->lw_rx_count / lw->lw_tx_total,
   1067                  (int) (lw->lw_tx_count / secs),
   1068                  (int) (lw->lw_tx_bytes / 1024 / secs),
   1069                  lw->lw_rx_count, secs);
   1070 
   1071         lw->lw_tx_rtime += sh_set_report_time;
   1072     }
   1073 }
   1074 
   1075 STATIC void
   1076 lb_stats_done(loopback_test_t *lw)
   1077 {
   1078     if (lw->lw_stats_init && lw->lw_tx_count > 0) {
   1079         lw->lw_tx_rtime = 0;            /* Force output now */
   1080         lb_stats_report(lw);
   1081     }
   1082 }
   1083 
   1084 
   1085 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1086 STATIC  void
   1087 lb_xgs3_higig_setup(loopback_test_t *lw, int cos, uint32 dst_mod,
   1088                     uint32 dst_port, uint32 vlan, uint32 *xghp)
   1089 {
   1090     int         unit = lw->lw_unit;
   1091     soc_higig_hdr_t *xgh = (soc_higig_hdr_t *)xghp; 
   1092     /* loopback_testdata_t      *lp = lw->lw_lp;*/
   1093 
   1094 #if defined(BCM_TOMAHAWK_SUPPORT)
   1095     if ((SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) 
   1096         && !soc_feature(unit, soc_feature_higig2)) {
   1097         soc_pbsmh_hdr_t *pbh = (soc_pbsmh_hdr_t *)xghp;
   1098         if ((SOC_IS_TOMAHAWK(unit)) || (SOC_IS_TOMAHAWK3(unit))) {
   1099             PBS_MH_V9_W0_START_SET(pbh);
   1100             PBS_MH_V9_W1_DPORT_SET(pbh, dst_port);
   1101             PBS_MH_V9_W2_SMOD_COS_SET(pbh, 0, 1, cos);
   1102             return;
   1103         } else if (SOC_IS_TRIDENT3X(unit)) {
   1104             PBS_MH_V11_W0_START_SET(pbh);
   1105             PBS_MH_V11_W1_DPORT_SET(pbh, dst_port);
   1106             PBS_MH_V11_W2_SMOD_COS_SET(pbh, 0, 1, cos);
   1107             return;
   1108         }
   1109     }
   1110 #endif
   1111 
   1112 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
   1113     if (SOC_IS_HAWKEYE(unit) || SOC_IS_SHADOW(unit) ||
   1114        ((SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) && (IS_E_PORT(unit, dst_port)))) {
   1115         soc_pbsmh_hdr_t *pbsh = (soc_pbsmh_hdr_t *)xghp;
   1116         sal_memset(xgh, 0, sizeof(soc_higig2_hdr_t));
   1117         soc_pbsmh_field_set(unit, pbsh, PBSMH_start, 0xff);
   1118         soc_pbsmh_field_set(unit, pbsh, PBSMH_src_mod, dst_mod);
   1119         soc_pbsmh_field_set(unit, pbsh, PBSMH_dst_port, dst_port);
   1120         soc_pbsmh_field_set(unit, pbsh, PBSMH_cos, cos);
   1121         soc_pbsmh_field_set(unit, pbsh, PBSMH_pri, cos);
   1122         return;
   1123     }
   1124 #endif
   1125 
   1126     /*
   1127      * Construct higig header to direct packet to a particular
   1128      * egress port
   1129      */
   1130     if (SOC_IS_XGS3_SWITCH(unit)) {
   1131 #ifdef BCM_HIGIG2_SUPPORT
   1132         sal_memset(xgh, 0, sizeof(soc_higig2_hdr_t));
   1133         soc_higig_field_set(unit, xgh, HG_dst_port, dst_port);
   1134         if (soc_feature(unit, soc_feature_higig2)) {
   1135             soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG2_START);
   1136         } else {
   1137             soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG_START);
   1138         }
   1139 #else
   1140         sal_memset(xgh, 0, sizeof(soc_higig_hdr_t));
   1141         soc_higig_field_set(unit, xgh, HG_start, SOC_HIGIG_START);
   1142 #endif
   1143         soc_higig_field_set(unit, xgh, HG_hgi, SOC_HIGIG_HGI);
   1144         soc_higig_field_set(unit, xgh, HG_hdr_format,
   1145                             SOC_HIGIG_HDR_DEFAULT);
   1146         soc_higig_field_set(unit, xgh, HG_src_mod, dst_mod + 1);
   1147         if (IS_ST_PORT(unit, dst_port)) {
   1148             soc_higig_field_set(unit, xgh, HG_opcode, 0);
   1149             soc_higig_field_set(unit, xgh, HG_src_port, dst_port);
   1150         } else {
   1151             soc_higig_field_set(unit, xgh, HG_opcode, 1);
   1152         }
   1153         soc_higig_field_set(unit, xgh, HG_vlan_id, vlan);
   1154         soc_higig_field_set(unit, xgh, HG_dst_port, dst_port);
   1155         soc_higig_field_set(unit, xgh, HG_dst_mod, dst_mod);
   1156         soc_higig_field_set(unit, xgh, HG_cos, cos);
   1157         soc_higig_field_set(unit, xgh, HG_ingress_tagged, 1);
   1158     }
   1159 }
   1160 #else
   1161 STATIC  void
   1162 lb_xgs3_higig_setup(loopback_test_t *lw, int cos, uint32 dst_mod,
   1163                     uint32 dst_port, uint32 vlan, void *xgh)
   1164 {
   1165 }
   1166 #endif
   1167 
   1168 STATIC  void
   1169 lb_setup_dcbs(uint8 **packets, dv_t *dv, int l, int c, pbmp_t pbm,
   1170               pbmp_t ubm, uint32 crc, uint32 cos, uint32 dport,
   1171               uint32 dmod, uint32 *hgh, int dma_mode, dvt_t dvt, uint8 **dcbs)
   1172 /*
   1173  * Function:    lb_setup_dcbs
   1174  * Purpose:     Fill in DCBs with length, bitmaps etc.
   1175  * Parameters:  packets - pointer to array of packets to use.
   1176  *              dv - DMA I/O vector
   1177  *              l - length for each dcb
   1178  *              c - # of dcbs to chain
   1179  *              pbm, ubm, ip, crc, cos - descriptor control word settings
   1180  *              hgh - Higig header for XGS3 devices
   1181  * Returns:     Nothing
   1182  */
   1183 {
   1184     uint32      flags;
   1185     pbmp_t      empty;
   1186 
   1187     flags = SOC_DMA_COS(cos);
   1188     if (crc) {
   1189         flags |= SOC_DMA_CRC_REGEN;
   1190     }
   1191 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1192     if (SOC_IS_HAWKEYE(dv->dv_unit) || ((!PBMP_MEMBER(pbm, CMIC_PORT(dv->dv_unit))) && (hgh != NULL))) {
   1193 
   1194         SOC_DMA_HG_SET(flags, 1);
   1195         SOC_DMA_STATS_SET(flags, 1);
   1196     }
   1197 
   1198 #endif
   1199     SOC_DMA_DPORT_SET(flags, dport);
   1200     SOC_DMA_DMOD_SET(flags, dmod);
   1201     SOC_PBMP_CLEAR(empty);
   1202 
   1203     while (c--) {
   1204         if(soc_feature(dv->dv_unit, soc_feature_cmicx)) {
   1205             if (dvt == DV_TX) {
   1206                 if (SOC_DMA_HG_GET(flags)) {
   1207                 sal_memcpy(*dcbs, hgh, MH_BYTES);
   1208                 soc_dma_desc_add(dv, (sal_vaddr_t)(*dcbs++), MH_BYTES,
   1209                              pbm, ubm, empty, flags, (uint32 *)hgh);
   1210             }
   1211         }
   1212         }
   1213 
   1214         soc_dma_desc_add(dv, (sal_vaddr_t)(*packets++), l,
   1215                          pbm, ubm, empty, flags, (uint32 *)hgh);
   1216         soc_dma_desc_end_packet(dv);
   1217     }
   1218 
   1219     if (LB_DMA_MODE_IS_CONTINUOUS(dma_mode)) {
   1220         if ((soc_dma_rld_desc_add(dv, 0)) < 0) {
   1221             cli_out("ERROR: Could not add rld desc at end of chain\n");
   1222         }
   1223     }
   1224 }
   1225 
   1226 STATIC void
   1227 lb_done_chain(int unit, dv_t *dv_chain)
   1228 /*
   1229  * Function:    lb_done_chain
   1230  * Purpose:     Process End-of-chain interrupt.
   1231  * Parameters:  unit - unit #
   1232  *              dv_chain - pointer to dv chain that completed, from ISR
   1233  * Returns:     Nothing.
   1234  */
   1235 {
   1236     loopback_test_t     *lw = &lb_work[unit];
   1237     dv_t                *last_dv;
   1238     dcb_t               *last_dcb;
   1239     int                 level;
   1240 
   1241     /* NOTE: This routine is called in interrupt context. */
   1242     assert(dv_chain);
   1243     for (last_dv = dv_chain; last_dv->dv_chain; last_dv = last_dv->dv_chain)
   1244         ;
   1245 
   1246     last_dcb = SOC_DCB_IDX2PTR(unit, last_dv->dv_dcb, last_dv->dv_vcnt - 1);
   1247 
   1248     if (!SOC_DCB_DONE_GET(unit, last_dcb)) {
   1249         cli_out("ERROR: Chain done when not done at dcb %p\n", last_dcb);
   1250         soc_dma_dump_dv(unit, "err vals: ", dv_chain);
   1251     }
   1252 
   1253     if (dv_chain == lw->lw_tx_dv_chain_done) {
   1254         lw->lw_eoc_tx = TRUE;
   1255     } else if (dv_chain == lw->lw_rx_dv_chain_done) {
   1256         lw->lw_eoc_rx = TRUE;
   1257     } else {
   1258         cli_out("Warning: dv chain done on DV_CHAIN[%p] "
   1259                 "Expecting Rx[%p] or Tx[%p]\n",
   1260                 (void *)dv_chain, 
   1261                 (void *)lw->lw_rx_dv_chain_done,
   1262                 (void *)lw->lw_tx_dv_chain_done);
   1263     }
   1264 
   1265     level = sal_splhi();
   1266     /* Wake up thread to check things out */
   1267     if (!lw->lw_sema_woke) {
   1268         lw->lw_sema_woke = TRUE;
   1269         if (sal_sem_give(lw->lw_sema)) {
   1270             cli_out("Warning: Chain done give failed\n");
   1271         }
   1272     }
   1273     sal_spl(level);
   1274 }
   1275 
   1276 STATIC void
   1277 lb_done_desc(int unit, dv_t *dv, dcb_t *dcb)
   1278 /*
   1279  * Function:    lb_done_desc
   1280  * Purpose:     Process End-of-descriptor interrupt.
   1281  * Parameters:  unit - unit #
   1282  *              dv - pointer to dv containing DCB
   1283  *              dcb - pointer to completed DCB
   1284  * Returns:     Nothing.
   1285  */
   1286 {
   1287     loopback_test_t     *lw = &lb_work[unit];
   1288     dcb_t               *last_pkt_dcb;
   1289     int                 level;
   1290 
   1291     COMPILER_REFERENCE(dv);
   1292     COMPILER_REFERENCE(dcb);
   1293     /*
   1294      * NOTE: This routine is called in interrupt context.
   1295      * Wake up thread to check things out.
   1296      */
   1297 
   1298     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   1299         assert(dv);
   1300 
   1301         /*
   1302          * In this mode, the last packet DCB is the second to last DCB in
   1303          * the chain. Find the DCB at index (valid_count - 2).
   1304          */
   1305         last_pkt_dcb = LB_LAST_PKT_DCB(unit, dv->dv_dcb, dv->dv_vcnt);
   1306 
   1307         /* When it is complete set pkt done (use chain done) */
   1308         if (dcb == last_pkt_dcb) {
   1309             if (dv == lw->lw_tx_dv_chain_done) {
   1310                 lw->lw_eoc_tx = TRUE;
   1311             } else if (dv == lw->lw_rx_dv_chain_done) {
   1312                 lw->lw_eoc_rx = TRUE;
   1313             } else {
   1314                 cli_out("Warning: dv desc done on DV[%p] "
   1315                         "Expecting Rx[%p] or Tx[%p]\n",
   1316                         (void *)dv,
   1317                         (void *)lw->lw_rx_dv_chain_done,
   1318                         (void *)lw->lw_tx_dv_chain_done);
   1319             }
   1320             level = sal_splhi();
   1321             /* Wake up thread to check things out */
   1322             if (!lw->lw_sema_woke) {
   1323                 lw->lw_sema_woke = TRUE;
   1324                 if (sal_sem_give(lw->lw_sema)) {
   1325                     cli_out("Warning: Desc done give failed\n");
   1326                 }
   1327             }
   1328             sal_spl(level);
   1329         }
   1330     } else {
   1331         level = sal_splhi();
   1332         /* Wake up thread to check things out */
   1333         if (!lw->lw_sema_woke) {
   1334             lw->lw_sema_woke = TRUE;
   1335             if (sal_sem_give(lw->lw_sema)) {
   1336                 cli_out("Warning: Desc done give failed\n");
   1337             }
   1338         }
   1339         sal_spl(level);
   1340     }
   1341 }
   1342 
   1343 STATIC void
   1344 lb_done_reload(int unit, dv_t *dv)
   1345 /*
   1346  * Function:    lb_done_reload
   1347  * Purpose:     Process End-of-DV.
   1348  * Parameters:  unit - unit #
   1349  *              dv - pointer to dv containing DCB
   1350  * Returns:     Nothing.
   1351  */
   1352 {
   1353     loopback_test_t     *lw = &lb_work[unit];
   1354 
   1355     /*
   1356      * When the reload descriptor has been processed, the dv index is
   1357      * updated to reflect the DV that is currently in use.
   1358      */
   1359     if (dv->dv_op == DV_TX) {
   1360         lw->lw_tx_dv_idx = (lw->lw_tx_dv_idx == 0) ? 1 : 0;
   1361     } else {
   1362         lw->lw_rx_dv_idx = (lw->lw_rx_dv_idx == 0) ? 1 : 0;
   1363     }
   1364 }
   1365 
   1366 
   1367 int
   1368 lb_check_tx(loopback_test_t *lw, int length, int c)
   1369 /*
   1370  * Function:    lb_check_tx
   1371  * Purpose:     Verify the DCB status for each of the packets.
   1372  * Parameters:  lw - pointer to work struct.
   1373  *              length - # bytes in transmitted packet
   1374  *              c - count of # dcbs in chain.
   1375  * Returns:     0 - OK
   1376  *              1 - OK and complete.
   1377  *              -1 - failed.
   1378  */
   1379 {
   1380     dv_t                *dv = lw->lw_tx_dv[lw->lw_tx_dv_idx];
   1381     dcb_t               *dcb;
   1382     dcb_t               *end_dcb;
   1383     int                 unit = lw->lw_unit;
   1384 
   1385     COMPILER_REFERENCE(c);
   1386 
   1387     /* dv->dv_dsc is the next entry to look at */
   1388 
   1389     /* after last dcb */
   1390     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   1391         /*
   1392          * In cont mode, the last DCB is the reload desc. We need to
   1393          * signal done AFTER the last packet DCB (on reload).
   1394          */
   1395         end_dcb = LB_LAST_DCB(unit, dv->dv_dcb, dv->dv_vcnt);
   1396     } else {
   1397         end_dcb = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt);
   1398     }
   1399     dcb = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_dsc);
   1400 
   1401     while ((dcb < end_dcb) && SOC_DCB_DONE_GET(unit, dcb)) {
   1402         /* Check dcb info */
   1403         dcb = SOC_DCB_IDX2PTR(unit, dcb, 1);
   1404         lw->lw_tx_count++;
   1405         lw->lw_tx_bytes += length;
   1406     }
   1407 
   1408     /* Update next to look at */
   1409     dv->dv_dsc = SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb);
   1410 
   1411     return(dcb == end_dcb);
   1412 }
   1413 
   1414 STATIC int
   1415 lb_check_packet(loopback_test_t *lw, uint8 *tx_data, int tx_len,
   1416                 uint8 *rx_data, int rx_len, int rx_crc_valid,
   1417                 sal_mac_addr_t mac_dst, sal_mac_addr_t mac_src, int skip_vlan)
   1418 /*
   1419  * Function:    lb_check_packet
   1420  * Purpose:     Check a received packet to be sure it matches a sent packet.
   1421  * Parameters:  lw - current loopback work structure.
   1422  *              tx_data - transmit data buffer
   1423  *              tx_len - user-requested transmit length
   1424  *              rx_data - receive data buffer
   1425  *              rx_len - actual received packet length, should match tx_len.
   1426  *              mac_src - Source MAC address under test
   1427  *              mac_dst - Dest MAC address under test
   1428  *              skip_vlan - Jump over VLAN tag for higig lb packets
   1429  *              on XGS3 device
   1430  * Returns:     -1 - failed compare
   1431  *              0 - passed compare.
   1432  */
   1433 {
   1434     char        src_mac[SAL_MACADDR_STR_LEN],
   1435                 dst_mac[SAL_MACADDR_STR_LEN],
   1436                 exp_src_mac[SAL_MACADDR_STR_LEN],
   1437                 exp_dst_mac[SAL_MACADDR_STR_LEN];
   1438     int         i;
   1439     int         rv = 0;
   1440     int         tx_compare_len, orig_rx_len;
   1441     uint8       *orig_rx_data;
   1442     uint32      header_size = 0;
   1443 
   1444     if(soc_feature(lw->lw_unit, soc_feature_cmicx)) {
   1445         soc_dma_header_size_get(lw->lw_unit, &header_size);
   1446 
   1447         rx_data += header_size;
   1448         rx_len -= header_size;
   1449     }
   1450 
   1451 #ifdef BCM_XGS12_FABRIC_SUPPORT
   1452     /* Inspect HIGIG/XGS header */
   1453     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   1454         soc_higig_hdr_t *tx_hdr = (soc_higig_hdr_t*)tx_data;
   1455         soc_higig_hdr_t *rx_hdr = (soc_higig_hdr_t*)rx_data;
   1456 
   1457         if (soc_higig_field_get(lw->lw_unit, tx_hdr, HG_start) !=
   1458             soc_higig_field_get(lw->lw_unit, rx_hdr, HG_start)) {
   1459             cli_out("ERROR: HIGIG START not detected (tx=%x,rx=%x)\n",
   1460                     soc_higig_field_get(lw->lw_unit, tx_hdr, HG_start),
   1461                     soc_higig_field_get(lw->lw_unit, rx_hdr, HG_start));
   1462         }
   1463         
   1464         rx_data += SOC_HIGIG_HDR_SIZE;
   1465         tx_data += SOC_HIGIG_HDR_SIZE;
   1466         /* Subtract the header from bytes received and transmitted */
   1467         rx_len -= SOC_HIGIG_HDR_SIZE;
   1468         tx_len -= SOC_HIGIG_HDR_SIZE;
   1469     }
   1470 #endif /* BCM_XGS12_FABRIC_SUPPORT */
   1471 
   1472     /* Check source and destination MAC address */
   1473 
   1474     if (ENET_CMP_MACADDR(mac_dst, &rx_data[0]) ||
   1475         ENET_CMP_MACADDR(mac_src, &rx_data[6])) {
   1476         format_macaddr(exp_src_mac, mac_src);
   1477         format_macaddr(exp_dst_mac, mac_dst);
   1478         format_macaddr(src_mac, &rx_data[6]);
   1479         format_macaddr(dst_mac, &rx_data[0]);
   1480         cli_out("ERROR: MAC address miscompare:\n"
   1481                 "\tExpected src=%s dst=%s\n\tReceived src=%s dst=%s\n",
   1482                 exp_src_mac, exp_dst_mac, src_mac, dst_mac);
   1483 
   1484         rv = -1;
   1485     }
   1486     /* Save these for error printouts */
   1487     orig_rx_data = rx_data;
   1488     orig_rx_len = rx_len;
   1489     if (skip_vlan) {
   1490         rx_len -= 4; /* Account for 4 bytes of VLAN tag added by Egress */   
   1491         rx_data += 4;
   1492     }
   1493     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   1494         if (lw->lw_lp->lp_crc_mode != CRC_MODE_CPU_NONE) {
   1495             tx_len += sizeof(uint32); /* Add length for CRC */
   1496         }
   1497         tx_compare_len = tx_len;
   1498     } else {
   1499         if ((lw->lw_lp->lp_crc_mode == CRC_MODE_CPU_NONE ||
   1500              lw->lw_lp->lp_crc_mode == CRC_MODE_CPU_APPEND) && rx_crc_valid) {
   1501             tx_compare_len = tx_len;
   1502         } else {
   1503             tx_compare_len = tx_len - 4;
   1504         }
   1505     }
   1506 
   1507     /* Verify lengths, and if they match, verify payload */
   1508 
   1509     if (tx_len != rx_len) {
   1510         soc_pci_analyzer_trigger(lw->lw_unit);
   1511         cli_out("ERROR: Length miscompare: TX(%d) RX(%d)\n",
   1512                 tx_len, rx_len);
   1513         rv = -1;
   1514     } else if ((i = packet_compare(rx_data + 12,
   1515                                    tx_data + 12,
   1516                                    4)) >= 0) {
   1517         cli_out("ERROR: VLAN tag miscompare: offset 0x%x\n", i + 12);
   1518         rv = -1;
   1519     } else if ((i = packet_compare(rx_data + 16,
   1520                                    tx_data + 16,
   1521                                    4)) >= 0) {
   1522         cli_out("ERROR: Sequence # miscompare: offset 0x%x\n"
   1523                 "\tExpected 0x%08x, Received 0x%08x\n", 16,
   1524                 packet_load(tx_data + 16, 4),
   1525                 packet_load(rx_data + 16, 4));
   1526         rv = -1;
   1527     } else if ((i = packet_compare(rx_data + 20,
   1528                                    tx_data + 20,
   1529                                    tx_compare_len - 20)) >= 0) {
   1530         cli_out("ERROR: Payload miscompare: offset 0x%x\n", i + 20);
   1531         rv = -1;
   1532     }
   1533 
   1534     if (lw->lw_lp->lp_check_crc) {
   1535         uint32          calc_crc, rx_crc;
   1536 
   1537         calc_crc = ~_shr_crc32(~0, rx_data, rx_len - 4);
   1538         rx_crc = packet_load(rx_data + rx_len - 4, 4);
   1539 
   1540         if (calc_crc != rx_crc) {
   1541             cli_out("ERROR: CRC miscompare: calc=0x%08x rx=0x%08x\n",
   1542                     calc_crc, rx_crc);
   1543             if (! rx_crc_valid)
   1544                 cli_out("ERROR: Note that invalid CRC was expected "
   1545                         "due to chosen parameters.\n");
   1546             rv = -1;
   1547         }
   1548     }
   1549 
   1550     if (rv) {
   1551         /* On error, dump tx/rx packets, and call test_error once */
   1552 
   1553         cli_out("TX packet: len=%d\n", tx_len);
   1554         soc_dma_dump_pkt(lw->lw_unit, "  ", tx_data, tx_len, TRUE);
   1555 
   1556         cli_out("RX packet: len=%d%s\n", orig_rx_len,
   1557                 skip_vlan ? " - 4 (VLAN)" : "");
   1558         soc_dma_dump_pkt(lw->lw_unit, "  ", orig_rx_data, orig_rx_len - header_size, TRUE);
   1559 
   1560         test_error(lw->lw_unit,
   1561                    "ERROR Found when verifying received packet\n");
   1562     }
   1563 
   1564     return(rv);
   1565 }
   1566 
   1567 int
   1568 lb_check_rx(loopback_test_t *lw, int length, int c)
   1569 /*
   1570  * Function:    lb_check_rx
   1571  * Purpose:     Verify the DCB status for each of the packets.
   1572  * Parameters:  lw - pointer to work struct.
   1573  *              length - # bytes in transmitted packet
   1574  *              c - count of # dcbs in chain.
   1575  * Returns:     0 - OK
   1576  *              1 - OK and complete.
   1577  *              -1 - failed.
   1578  */
   1579 {
   1580     dv_t        *dv = lw->lw_rx_dv[lw->lw_rx_dv_idx];
   1581     dcb_t       *rx_dcb, *tx_dcb, *end_dcb;
   1582     int         rv = 0;
   1583     loopback_testdata_t *lp = lw->lw_lp;
   1584     int         unit = lw->lw_unit;
   1585     int         skip_vlan = 0;
   1586     uint8       *rx_data = NULL;
   1587     soc_port_t  sp;
   1588 
   1589     COMPILER_REFERENCE(c);
   1590 
   1591     /* Check the next entry to look at */
   1592     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   1593         /*
   1594          * In cont mode, the last DCB is the reload desc. We need to
   1595          * signal done after the last packet DCB (just before reload)
   1596          */
   1597         end_dcb = LB_LAST_DCB(unit, dv->dv_dcb, dv->dv_vcnt);
   1598     } else {
   1599         end_dcb = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt);
   1600     }
   1601     rx_dcb = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_dsc);
   1602     tx_dcb = SOC_DCB_IDX2PTR(unit,
   1603                              lw->lw_tx_dv[lw->lw_tx_dv_idx]->dv_dcb,
   1604                              dv->dv_dsc + lw->lw_tx_dcb_factor - 1);
   1605 
   1606     while (rx_dcb < end_dcb) {
   1607         int             rx_crc_valid, rx_length;
   1608 
   1609         if (!SOC_DCB_DONE_GET(unit, rx_dcb)) {
   1610             cli_out("RX DCB @%p NOT DONE\n", rx_dcb);
   1611             break;
   1612         }
   1613 
   1614         /*
   1615          * If the CPU, as an egress, was asked to regenerate or append
   1616          * the CRC for this packet, that means the packet was modified
   1617          * at the ingress/MMU and the CRC is known to be invalid.  This
   1618          * was probably an untagged packet that got tagged.
   1619          */
   1620 
   1621         rx_crc_valid = !SOC_DCB_RX_CRC_GET(unit, rx_dcb);
   1622         rx_length = SOC_DCB_XFERCOUNT_GET(unit, rx_dcb);
   1623 
   1624         lw->lw_rx_count++;
   1625         lw->lw_rx_bytes += rx_length;
   1626 
   1627         if(soc_feature(unit, soc_feature_cmicx)) {
   1628             rx_data = (uint8 *)SOC_DCB_ADDR_GET(unit, rx_dcb);
   1629         }
   1630 
   1631         if (lp->lp_check_data) {
   1632             if(soc_feature(unit, soc_feature_cmicx)) {
   1633                 sp = SOC_DCB_RX_INGPORT_GET(unit, rx_data);
   1634             } else {
   1635                 sp = SOC_DCB_RX_INGPORT_GET(unit, rx_dcb);
   1636             }
   1637             if (sp != lp->lp_rx_port) {
   1638                 cli_out("RX packet with invalid port: "
   1639                         "expected port %s, received port %s\n",
   1640                         SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   1641                         SOC_PORT_NAME(lw->lw_unit, sp));
   1642                 rv = -1;
   1643             }
   1644 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1645             if ((SOC_IS_XGS3_SWITCH(lw->lw_unit)) &&
   1646                 (IS_ST_PORT(lw->lw_unit, lp->lp_rx_port))){
   1647                 skip_vlan = 1;
   1648             }
   1649 #endif
   1650             if (lb_check_packet(lw,
   1651                  (uint8 *)SOC_DCB_ADDR_GET(unit, tx_dcb),
   1652                  length,
   1653                  (uint8 *)SOC_DCB_ADDR_GET(unit, rx_dcb),
   1654                  rx_length,
   1655                  rx_crc_valid,
   1656                  lw->lw_cur_mac_dst,
   1657                  lw->lw_cur_mac_src, skip_vlan) < 0) {
   1658                 rv = -1;
   1659             }
   1660 
   1661             if (rv < 0) {
   1662                 int diff = SOC_DCB_PTR2IDX(unit, rx_dcb, dv->dv_dcb);
   1663                 cli_out("Failing DV @%p, DCB[%d]\n", (void *)dv, diff);
   1664                 soc_dma_dump_dv(lw->lw_unit, "bad pkt dv: ", dv);
   1665                 break;                  /* while */
   1666             }
   1667         }
   1668         rx_dcb = SOC_DCB_IDX2PTR(unit, rx_dcb, 1);
   1669         tx_dcb = SOC_DCB_IDX2PTR(unit, tx_dcb, 1 + lw->lw_tx_dcb_factor - 1);
   1670 
   1671         increment_macaddr(lw->lw_cur_mac_dst, lp->lp_mac_dst_inc);
   1672         increment_macaddr(lw->lw_cur_mac_src, lp->lp_mac_src_inc);
   1673     }
   1674 
   1675     dv->dv_dsc = SOC_DCB_PTR2IDX(unit, rx_dcb, dv->dv_dcb); /* Update next */
   1676 
   1677     if (!rv && (rx_dcb == end_dcb)) {
   1678         rv = 1;                         /* Signal done */
   1679     }
   1680 
   1681     return(rv);
   1682 }
   1683 
   1684 STATIC  void
   1685 lb_deallocate(int unit, int dv_cnt, dv_t ***dv_array_ptr,
   1686               int packet_cnt, uint8 ***packet_array_ptr,
   1687               uint8 ***dcb_array_ptr, dvt_t dvt)
   1688 /*
   1689  * Purpose:     Deallocate whatever is allocated by lb_allocate.
   1690  * Parameters:  dv_cnt - number of DVs originally allocated.
   1691  *              dv_array - array of dv pointers.
   1692  *              packet_cnt - number of packets originally allocated.
   1693  *              packet_array - array of packet ptrs
   1694  * Returns:     0 - success
   1695  *              -1 - failed, all allocated memory should be freed.
   1696  */
   1697 {
   1698     int                 i;
   1699     dv_t                **dv_array      = *dv_array_ptr;
   1700     uint8               **packet_array  = *packet_array_ptr;
   1701     uint8               **dcb_array     = NULL;
   1702 
   1703     if(soc_feature(unit, soc_feature_cmicx) && (dvt == DV_TX)) {
   1704         dcb_array     = *dcb_array_ptr;
   1705     }
   1706 
   1707     if (dv_array) {
   1708         *dv_array_ptr = 0;
   1709         for (i = 0; i < dv_cnt; i++)
   1710             if (dv_array[i])
   1711                 soc_dma_dv_free(unit, dv_array[i]);
   1712         sal_free(dv_array);
   1713     }
   1714 
   1715     if (packet_array) {
   1716         *packet_array_ptr = 0;
   1717 
   1718         packet_cnt *= 4;    /* for 2 way and 2 phase */
   1719         for (i = 0; i < packet_cnt; i++)
   1720             if (packet_array[i])
   1721                 soc_cm_sfree(unit, packet_array[i]);
   1722         sal_free(packet_array);
   1723     }
   1724 
   1725     if (dcb_array) {
   1726         *dcb_array_ptr = 0;
   1727 
   1728         for (i = 0; i < packet_cnt; i++)
   1729             if (dcb_array[i])
   1730                 soc_cm_sfree(unit, dcb_array[i]);
   1731         sal_free(dcb_array);
   1732     }
   1733 }
   1734 
   1735 STATIC  int
   1736 lb_allocate(int unit, dvt_t dvt, int dv_cnt, int dv_size, dv_t ***dv_array_ptr,
   1737             int packet_cnt, int packet_size, uint8 ***packet_array_ptr, uint8 ***dcb_array_ptr)
   1738 /*
   1739  * Purpose:     Allocate array of dv and array of packets
   1740  * Parameters:  dvt - Type of operation being allocated for (DV_TX/DV_RX)
   1741  *              dv_cnt - number of DVs to allocate.
   1742  *              dv_size - number of DCBs in DV.
   1743  *              dv_array_ptr - address of pointer to array of dv pointers.
   1744  *              packet_cnt - number of packets to allocate.
   1745  *              packet_size - size of packets to allocate.
   1746  *              packet_array_ptr - address of pointer array of packet ptrs.
   1747  * Returns:     0 - success
   1748  *              -1 - out of memory (no memory is left allocated)
   1749  */
   1750 {
   1751     dv_t        **dv_array = NULL; 
   1752     uint8       **packet_array = NULL;
   1753     uint8       **dcb_array = NULL;
   1754     int         i = 0;
   1755     uint32      header_size = 0;
   1756 
   1757     *dv_array_ptr = 0;
   1758     *packet_array_ptr = 0;
   1759 
   1760     /* Allocate Array for dv pointers */
   1761 
   1762     if (!(dv_array = sal_alloc(dv_cnt * sizeof(dv_t *), "dv_array"))) {
   1763         goto fail;
   1764     }
   1765     sal_memset(dv_array, 0, dv_cnt * sizeof(dv_t *));
   1766     *dv_array_ptr = dv_array;
   1767 
   1768     /* Allocate actual DVs */
   1769 
   1770     for (i = 0; i < dv_cnt; i++) {
   1771         /*
   1772          * Add 1 to DV size to get an extra DCB so soc_dma_dv_join can
   1773          * always be used.
   1774          * *4 because of 2 way and 2 circulation test.
   1775          */
   1776         if (!(dv_array[i] = soc_dma_dv_alloc(unit, dvt, (dv_size*4) + 1))) {
   1777             goto fail;
   1778         }
   1779         dv_array[i]->dv_flags       &= ~DV_F_COMBINE_DCB;
   1780         dv_array[i]->dv_done_chain  = lb_done_chain;
   1781         dv_array[i]->dv_done_desc   = lb_done_desc;
   1782         dv_array[i]->dv_done_reload = lb_done_reload;
   1783         dv_array[i]->dv_dsc         = 0;
   1784         dv_array[i]->dv_pckt        = 0;
   1785     }
   1786 
   1787     /* Allocate packet pointer array, 2 way and 2 phase */
   1788 
   1789     if (!(packet_array = sal_alloc(packet_cnt* 4 * sizeof(uint8 *),
   1790                                    "packet_array"))) {
   1791         goto fail;
   1792     }
   1793     /* remember there are 2 way and 2 phase 2*2=4*/
   1794     sal_memset(packet_array, 0, packet_cnt *4 * sizeof(uint8 *));
   1795     *packet_array_ptr = packet_array;
   1796 
   1797     /* Allocate actual packets */
   1798 
   1799 #ifdef BCM_XGS12_FABRIC_SUPPORT
   1800     if (SOC_IS_XGS12_FABRIC(unit)) {
   1801         packet_size += SOC_HIGIG_HDR_SIZE + sizeof(uint32); /* CRC */
   1802     }
   1803 #endif
   1804 
   1805     if(soc_feature(unit, soc_feature_cmicx)) {
   1806         soc_dma_header_size_get(unit, &header_size);
   1807 
   1808         if (dvt == DV_RX) {
   1809             packet_size += header_size;
   1810         }
   1811 
   1812         if (dvt == DV_TX) {
   1813             *dcb_array_ptr = 0;
   1814 
   1815             if (!(dcb_array = sal_alloc(packet_cnt * 4 * sizeof(uint8 *),
   1816                                    "dcb_array"))) {
   1817                 goto fail;
   1818             }
   1819 
   1820             sal_memset(dcb_array, 0, packet_cnt * 4 * sizeof(uint8 *));
   1821             *dcb_array_ptr = dcb_array;
   1822 
   1823             for (i = 0; i < packet_cnt*4; i++) {
   1824                 if (!(dcb_array[i] =
   1825                     soc_cm_salloc(unit,
   1826                                   SOC_DMA_ROUND_LEN(MH_BYTES), "DCB"))) {
   1827                     goto fail;
   1828                 }
   1829             }
   1830         }
   1831     }
   1832 
   1833     for (i = 0; i < packet_cnt*4; i++) {
   1834         if (!(packet_array[i] =
   1835               soc_cm_salloc(unit,
   1836                             SOC_DMA_ROUND_LEN(packet_size + 4), "LB"))) {
   1837             goto fail;
   1838         }
   1839     }
   1840 
   1841     return(0);                          /* All done */
   1842 
   1843  fail:
   1844     lb_deallocate(unit, dv_cnt, &dv_array, packet_cnt, &packet_array, &dcb_array, dvt);
   1845     return(-1);
   1846 }
   1847 
   1848 int
   1849 lb_wait(loopback_test_t *lw, int length, int chain)
   1850 /*
   1851  * Function:    lb_wait
   1852  * Purpose:     Wait for packets to Tx/Rx and check data/dcbs
   1853  *              as they complete.
   1854  * Parameters:  lw - pointer to work structure.
   1855  *              length - current Tx/Rx length
   1856  *              chain - Current number DCBs valid in chain
   1857  * Returns:     0 - success
   1858  *              !0 - failed
   1859  * Notes:       10-seconds without any activity results in failure.
   1860  */
   1861 {
   1862     int rv = 0;
   1863     int level = 0;
   1864 
   1865     ENET_SET_MACADDR(lw->lw_cur_mac_dst, lw->lw_mac_dst);
   1866     ENET_SET_MACADDR(lw->lw_cur_mac_src, lw->lw_mac_src);
   1867 
   1868     while (!lw->lw_eoc_tx || !lw->lw_eoc_rx) {
   1869         if (sal_sem_take(lw->lw_sema, lw->lw_timeout_usec)) {
   1870             cli_out("Time-out waiting for completion "
   1871                     "Tx(%s)=%s Rx(%s)=%s\n",
   1872                     SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_tx_port),
   1873                     lw->lw_eoc_tx ? "Done" : "Pending",
   1874                     SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_rx_port),
   1875                     lw->lw_eoc_rx ? "Done" : "Pending");
   1876             rv = -1;
   1877             return rv;
   1878         } else {
   1879            level = sal_splhi();
   1880            lw->lw_sema_woke = FALSE;
   1881            sal_spl(level);
   1882         }
   1883     }
   1884 
   1885     if ((lb_check_tx(lw, length, chain) < 0) ||
   1886         (lb_check_rx(lw, length, chain) < 0)) {
   1887         rv = -1;
   1888     }
   1889     if (rv == 0 &&
   1890         bsl_check(bslLayerAppl, bslSourceDma, bslSeverityNormal, lw->lw_unit)) {
   1891         soc_dma_dump_dv(lw->lw_unit, "dma (after): ", lw->lw_rx_dv[0]);
   1892     }
   1893 
   1894     return rv;
   1895 }
   1896 
   1897 STATIC  void
   1898 lb_fill_packet_rx(loopback_test_t *lw, uint8 **packets, int count, int len)
   1899 /*
   1900  * Function:    lb_fill_packet_rx
   1901  * Purpose:     Fill RX buffer before receiving into it
   1902  * Parameters:  lw - pointer to work structure
   1903  *              packets - array of packet pointers
   1904  *              count - number of packets
   1905  *              len - length of packets
   1906  * Returns:     Nothing.
   1907  * Notes:       Optionally fills the RX buffer with 0xdeadbeef before
   1908  *              receiving into it.  This may help reveal holes in the
   1909  *              RX packet the hardware was supposed to DMA but did not.
   1910  *              This feature is turned on by setting the property
   1911  *              diag_lb_fill_rx=1.
   1912  */
   1913 {
   1914     if (lw->lw_rx_fill) {
   1915         int             i;
   1916 
   1917         for (i = 0; i < count; i++) {
   1918             packet_store(packets[i], len, 0xdeadbeef, 0);
   1919         }
   1920     }
   1921 }
   1922 
   1923 
   1924 #define REG_READ(unit, port, RPKTr, GRPKTr, iPhase, rvp)                \
   1925     (NUM_FE_PORT(unit) > 0                                              \
   1926      ? soc_reg32_read((unit),                                           \
   1927                      soc_reg_addr((unit),                               \
   1928                                   (iPhase) != 1 ? (GRPKTr) : (RPKTr),   \
   1929                                   (port), 0),                           \
   1930                      (rvp))                                             \
   1931      : soc_reg32_read((unit),                                           \
   1932                      soc_reg_addr((unit),                               \
   1933                                   (GRPKTr),                             \
   1934                                   (port), 0),                           \
   1935                      (rvp)))
   1936 
   1937 #define REG_WRITE(unit, port, RPKTr, GRPKTr, iPhase, rv)                \
   1938     (NUM_FE_PORT(unit) > 0                                              \
   1939      ? soc_reg32_write((unit),                                          \
   1940                       soc_reg_addr((unit),                              \
   1941                                    (iPhase) != 1 ? (GRPKTr): (RPKTr),   \
   1942                                    (port), 0),                          \
   1943                       (rv))                                             \
   1944      : soc_reg32_write((unit),                                          \
   1945                       soc_reg_addr((unit),                              \
   1946                                    (GRPKTr),                            \
   1947                                    (port), 0),                          \
   1948                       (rv)))
   1949 
   1950 STATIC  int
   1951 lb_do_rx(loopback_test_t *lw, int length, int chain, int cos)
   1952 /*
   1953  * Function:    lb_do_rx
   1954  * Purpose:     Start an RX for the specified length/chain.
   1955  * Parameters:  lw - pointer to lb work.
   1956  *              length - length of packet
   1957  *              chain  - # dcb's in chain
   1958  *              cos    - Class of service
   1959  * Returns:     0 - success, -1 failed.
   1960  */
   1961 {
   1962     dv_t        *dv = lw->lw_rx_dv[0];
   1963     int         rv;
   1964     pbmp_t      empty_pbm;
   1965     int level = 0;
   1966     uint32 header_size = 0;
   1967 
   1968     if(soc_feature(lw->lw_unit, soc_feature_cmicx)) {
   1969         soc_dma_header_size_get(lw->lw_unit, &header_size);
   1970     }
   1971 
   1972     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   1973         /*
   1974          * In continuous mode, 2 DVs are allocated at init to handle the
   1975          * fact that DMA halts on the reload descriptor of the previous DV.
   1976          * If we have already started receiving, then the next DV is
   1977          * appended to the current reload descriptor of the other.
   1978          */
   1979         level = sal_splhi();
   1980         if (!lw->lw_rx_started) {
   1981             lw->lw_rx_started = 1;
   1982             lw->lw_rx_dv_idx = 0;
   1983             dv = lw->lw_rx_dv[lw->lw_rx_dv_idx];
   1984         } else {
   1985             dv = (lw->lw_rx_dv_idx == 0) ? lw->lw_rx_dv[1] : lw->lw_rx_dv[0];
   1986         }
   1987         sal_spl(level);
   1988     }
   1989 
   1990     /*
   1991      * For RX, set flags to call out for each DCB completed.
   1992      */
   1993     soc_dma_dv_reset(DV_RX, dv);
   1994 
   1995     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   1996         dv->dv_flags |= DV_F_NOTIFY_DSC;
   1997     } else {
   1998         dv->dv_flags |= DV_F_NOTIFY_DSC | DV_F_NOTIFY_CHN;
   1999     }
   2000 
   2001     dv->dv_dsc  = 0;
   2002 
   2003     /*
   2004      * Receive buffer lengths are 4 bytes larger than necessary in order
   2005      * to catch receiving packets larger than expected.
   2006      */
   2007 
   2008     SOC_PBMP_CLEAR(empty_pbm);
   2009 
   2010     lb_setup_dcbs(lw->lw_rx_packets, dv, length + 4 + header_size,
   2011                   chain, empty_pbm, empty_pbm, 0, cos, 0, 0,
   2012                   NULL, lw->lw_dma_mode, DV_RX, NULL);
   2013     lb_fill_packet_rx(lw, lw->lw_rx_packets, chain, length + 4 + header_size);
   2014     lw->lw_rx_dv_chain_done = dv;       /* Mark who waiting for */
   2015     lw->lw_eoc_rx = 0;
   2016 
   2017     if ((rv = soc_dma_start(lw->lw_unit, -1, dv)) < 0) {
   2018         test_error(lw->lw_unit, "Failed to start RX DMA: %s\n",
   2019                    soc_errmsg(rv));
   2020         return(-1);
   2021     }
   2022     return(0);
   2023 }
   2024 
   2025 STATIC  void
   2026 lb_fill_packet_tx(loopback_test_t *lw, loopback_testdata_t *lp,
   2027                   uint8 *packet,
   2028                   int *tx_len, sal_mac_addr_t mac_dst, sal_mac_addr_t mac_src)
   2029 /*
   2030  * Function:    lb_fill_packet_tx
   2031  * Purpose:     Fill in a packet for TXing.
   2032  * Parameters:  lw - pointer to work structure
   2033  *              lp - pointer to parameters
   2034  *              packet - pointer to packet to fill in
   2035  *              tx_len - # bytes in packet.
   2036  *              mac_src - Source MAC address under test
   2037  *              mac_dst - Dest MAC address under test
   2038  * Returns:     Nothing.
   2039  */
   2040 {
   2041     enet_hdr_t          *eh = NULL;
   2042 
   2043 #ifdef BCM_XGS12_FABRIC_SUPPORT
   2044     /* All hercules chips need module header prepended to frame */
   2045     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   2046         soc_higig_hdr_t     *xghp = (soc_higig_hdr_t *)packet;
   2047         soc_higig_hdr_t     xghd;
   2048         soc_higig_hdr_t     *xgh = &xghd;
   2049         sal_memset(xgh, 0, SOC_HIGIG_HDR_SIZE);
   2050         eh = (enet_hdr_t *)(packet + SOC_HIGIG_HDR_SIZE);
   2051         soc_higig_field_set(lw->lw_unit, xgh, HG_start, SOC_HIGIG_START);
   2052         soc_higig_field_set(lw->lw_unit, xgh, HG_hgi, SOC_HIGIG_HGI);
   2053         soc_higig_field_set(lw->lw_unit, xgh, HG_vlan_id, lp->lp_vlan);
   2054         soc_higig_field_set(lw->lw_unit, xgh, HG_opcode, lp->lp_opcode);
   2055         soc_higig_field_set(lw->lw_unit, xgh, HG_hdr_format,
   2056                             SOC_HIGIG_HDR_DEFAULT);
   2057         soc_higig_field_set(lw->lw_unit, xgh, HG_dst_port, lp->lp_d_port);
   2058         soc_higig_field_set(lw->lw_unit, xgh, HG_dst_mod, lp->lp_d_mod);
   2059         sal_memcpy(xghp, xgh, sizeof(*xghp));
   2060     } else {
   2061         eh = (enet_hdr_t *)packet;
   2062     }
   2063 #else
   2064     eh = (enet_hdr_t *)packet;
   2065 #endif
   2066 
   2067     /* Write source/destination MAC address */
   2068 
   2069     ENET_SET_MACADDR(&eh->en_dhost, mac_dst);
   2070     ENET_SET_MACADDR(&eh->en_shost, mac_src);
   2071 
   2072     /* Write VLAN tag (16 + 16 bits) and sequence number (32 bits) */
   2073 
   2074     packet_store((uint8 *)&eh->en_tag_tpid, 2,
   2075                  0x8100 << 16, 0);
   2076     packet_store((uint8 *)&eh->en_tag_ctrl, 2,
   2077                  VLAN_CTRL(0, 0, lp->lp_vlan) << 16, 0);
   2078     packet_store((uint8*)eh + 16, 4,
   2079                  lw->lw_tx_seq++, 0);
   2080     packet_store((uint8*)&eh->en_tag_len, 2, (*tx_len - 22) << 16, 0);
   2081 
   2082     /*
   2083      * Fill data from after header & seq # to end of packet.  Byte data
   2084      * starts with the lw_pattern MSByte through LSByte and recycles.
   2085      * Optionally overwrite last 4 bytes of packet with correct CRC.
   2086      */
   2087 
   2088     lp->lp_pattern = packet_store((uint8*)eh + 20, *tx_len - 20,
   2089                                   lp->lp_pattern, lp->lp_pattern_inc);
   2090     if (lp->lp_crc_mode == CRC_MODE_CPU_APPEND) {
   2091         packet_store((uint8*)eh + *tx_len - 4, 4,
   2092                      ~_shr_crc32(~0, (uint8*)eh, *tx_len - 4), 0);
   2093     }
   2094 
   2095 #ifdef BCM_XGS12_FABRIC_SUPPORT
   2096     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   2097         if (lp->lp_crc_mode == CRC_MODE_MAC_REGEN) {
   2098             /* hercules always requires CRC field to be zero */
   2099             packet_store(((uint8*)eh + (*tx_len) - 4), 4, 0, 0);
   2100         }
   2101 
   2102         /* Update length */
   2103         *tx_len += SOC_HIGIG_HDR_SIZE;
   2104     }
   2105 #endif
   2106 }
   2107 
   2108 STATIC int
   2109 lb_do_tx(loopback_test_t *lw, int tx_len, int chain, int cos,
   2110          uint32 dport, uint32 dmod)
   2111 /*
   2112  * Function:    lb_do_tx
   2113  * Purpose:     Start a transmit for the current length/chain.
   2114  * Parameters:  lw - pointer to lb work.
   2115  *              tx_len - user-requested packet length
   2116  *              chain  - # dcb's in chain
   2117  *              cos    - Class of service
   2118  * Returns:     0 - success, -1 failed.
   2119  */
   2120 {
   2121     dv_t        *dv = lw->lw_tx_dv[0];
   2122     loopback_testdata_t *lp = lw->lw_lp;
   2123     int         c;
   2124     int         rv, org_len;
   2125     sal_mac_addr_t  cur_dst_mac;
   2126     sal_mac_addr_t  cur_src_mac;
   2127     pbmp_t      pbm;
   2128 #ifdef BCM_HIGIG2_SUPPORT
   2129     soc_higig2_hdr_t    xgh;
   2130     uint32              *xghp = (uint32 *)&xgh;
   2131 #elif defined(BCM_XGS_SUPPORT)
   2132     soc_higig_hdr_t     xgh;
   2133     uint32              *xghp = (uint32 *)&xgh;
   2134 #else
   2135     uint32              *xghp = NULL;
   2136 #endif
   2137     int level;
   2138 
   2139     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   2140         /*
   2141          * In continuous mode, 2 DVs are allocated at init to handle the
   2142          * fact that DMA halts on the reload descriptor of the previous DV.
   2143          * If we have already started transmitting, then the next DV is
   2144          * appended to the current reload descriptor of the other.
   2145          */
   2146         level = sal_splhi();
   2147         if (!lw->lw_tx_started) {
   2148             lw->lw_tx_started = 1;
   2149             lw->lw_tx_dv_idx = 0;
   2150             dv = lw->lw_tx_dv[lw->lw_tx_dv_idx];
   2151         } else {
   2152             dv = (lw->lw_tx_dv_idx == 0) ? lw->lw_tx_dv[1] : lw->lw_tx_dv[0];
   2153         }
   2154         sal_spl(level);
   2155     }
   2156 
   2157     soc_dma_dv_reset(DV_TX, dv);
   2158 
   2159     if (LB_DMA_MODE_IS_CONTINUOUS(lw->lw_dma_mode)) {
   2160         dv->dv_flags = DV_F_NOTIFY_DSC;
   2161     } else {
   2162         SET_NOTIFY_CHN_ONLY(dv->dv_flags);
   2163     }
   2164 
   2165     dv->dv_dsc = 0;
   2166 
   2167     if (lp->lp_pattern_inc || (lw->lw_tx_init_chn != chain) ||
   2168         (lw->lw_tx_init_len != tx_len)) {
   2169 
   2170         lw->lw_tx_init_chn = chain;
   2171         lw->lw_tx_init_len = tx_len;
   2172 
   2173         /* Fill in start of TX packet --- len/chain/cos value */
   2174 
   2175         ENET_SET_MACADDR(cur_dst_mac, lw->lw_mac_dst);
   2176         ENET_SET_MACADDR(cur_src_mac, lw->lw_mac_src);
   2177         org_len = tx_len;
   2178         for (c = 0; c < chain; c++) {
   2179             int new_len = org_len;
   2180             lb_fill_packet_tx(lw, lp, lw->lw_tx_packets[c], &new_len,
   2181                               cur_dst_mac, cur_src_mac);
   2182             increment_macaddr(cur_dst_mac, lp->lp_mac_dst_inc);
   2183             increment_macaddr(cur_src_mac, lp->lp_mac_src_inc);
   2184             tx_len = lw->lw_tx_init_len = new_len ;
   2185         }
   2186     }
   2187 
   2188     /* Setup # of descriptors desired with current length */
   2189 
   2190     SOC_PBMP_CLEAR(pbm);
   2191     SOC_PBMP_PORT_ADD(pbm, lp->lp_tx_port);
   2192     lb_xgs3_higig_setup(lw, cos, dmod,
   2193                         lp->lp_tx_port, lp->lp_vlan, xghp);
   2194     lb_setup_dcbs(lw->lw_tx_packets, dv, tx_len, chain,
   2195                   pbm, lp->lp_ubm, crc_mode_to_dmac(lp->lp_crc_mode),
   2196                   cos, dport, dmod, xghp, lw->lw_dma_mode, DV_TX, lw->lw_tx_dcbs);
   2197 
   2198     level = sal_splhi();
   2199     lw->lw_tx_dv_chain_done = dv;       /* Mark who waiting for */
   2200     lw->lw_eoc_tx = 0;
   2201     sal_spl(level);
   2202 
   2203     if ((rv = soc_dma_start(lw->lw_unit, -1, dv)) < 0) {
   2204         test_error(lw->lw_unit, "Failed to start TX DMA: %s\n",
   2205                    soc_errmsg(rv));
   2206         return(-1);
   2207     }
   2208     return (0);
   2209 }
   2210 
   2211 int
   2212 lb_do_txrx(loopback_test_t *lw)
   2213 /*
   2214  * Function:    lb_do_txrx
   2215  * Purpose:     Loop over requested lengths and chaining sizes, and
   2216  *              transmit/receive packets.
   2217  * Parameters:  lw - pointer to work structure
   2218  * Returns:     0 - success
   2219  *              -1- failed.
   2220  */
   2221 {
   2222     loopback_testdata_t *lp = lw->lw_lp;
   2223     int         l_cur, c_cur, cos_cur, c_count;
   2224     int         rv, test_rv = 0;
   2225     uint32      tx_count, rx_count;
   2226     uint32      rx_count0, rx_count1, rx_count2, rx_count3;
   2227     int         i = 0;
   2228 
   2229     LOG_INFO(BSL_LS_APPL_TESTS,
   2230              (BSL_META("Testing %s->%s count %d, chain %d-%d += %d, "
   2231                        "len %d-%d += %d, cos %d-%d\n"),
   2232               SOC_PORT_NAME(lw->lw_unit, lp->lp_tx_port),
   2233               SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2234               lp->lp_count,
   2235               lp->lp_c_start, lp->lp_c_end, lp->lp_c_inc,
   2236               lp->lp_l_start, lp->lp_l_end, lp->lp_l_inc,
   2237               lp->lp_cos_start, lp->lp_cos_end));
   2238 
   2239     /* Clear port rx/tx counters */
   2240     if ((rv = bcm_stat_clear(lw->lw_unit, lp->lp_tx_port)) < 0) {
   2241         test_error(lw->lw_unit, "Could not clear port %s counters: %s\n",
   2242                    SOC_PORT_NAME(lw->lw_unit, lp->lp_tx_port),
   2243                    soc_errmsg(rv));
   2244         return -1;
   2245     }
   2246 
   2247     if ((rv = bcm_stat_clear(lw->lw_unit, lp->lp_rx_port)) < 0) {
   2248         test_error(lw->lw_unit, "Could not clear port %s counters: %s\n",
   2249                    SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2250                    soc_errmsg(rv));
   2251         return -1;
   2252     }
   2253 
   2254     for (c_count = 0; c_count < lp->lp_count; c_count++) {
   2255         for (l_cur = lp->lp_l_start; l_cur <= lp->lp_l_end;
   2256              l_cur += lp->lp_l_inc) {
   2257             for (c_cur = lp->lp_c_start; c_cur <= lp->lp_c_end;
   2258                  c_cur += lp->lp_c_inc) {
   2259                 for (cos_cur = lp->lp_cos_start;
   2260                      cos_cur <= lp->lp_cos_end;
   2261                      cos_cur++) {
   2262                      if((0 > lb_do_tx(lw, l_cur, c_cur, cos_cur,
   2263                                       lp->lp_d_port,
   2264                                       lp->lp_d_mod)) ||
   2265                         (0 > lb_do_rx(lw, l_cur, c_cur, cos_cur))) {
   2266                          return(-1);
   2267                      }
   2268                     if (lb_wait(lw, l_cur, c_cur) < 0) {
   2269                         test_error(lw->lw_unit,
   2270                                    "\tPort %s->%s\n"
   2271                                    "\tPacket Length=%d bytes\n"
   2272                                    "\tChain length=%d\n"
   2273                                    "\tCurrent COS=%d\n"
   2274                                    "\tCurrent Count (%d/%d)\n",
   2275                                    SOC_PORT_NAME(lw->lw_unit,
   2276                                                  lp->lp_tx_port),
   2277                                    SOC_PORT_NAME(lw->lw_unit,
   2278                                                  lp->lp_rx_port),
   2279                                    l_cur, c_cur, cos_cur, c_count + 1,
   2280                                    lp->lp_count);
   2281 
   2282                         for (i = 0; i < c_cur; i++) {
   2283                             soc_dma_dump_pkt(lw->lw_unit, "LB TX ", lw->lw_tx_packets[i], l_cur, TRUE);
   2284                         }
   2285 
   2286                         test_rv = -1;
   2287                         goto done;
   2288                     }
   2289                     lb_stats_report(lw);
   2290                 }
   2291             }
   2292         }
   2293     }
   2294 
   2295 done:
   2296     /* Verify port rx/tx stats */
   2297     bcm_stat_sync(lw->lw_unit);
   2298     if (!(IS_ST_PORT(lw->lw_unit, lp->lp_rx_port) || 
   2299           IS_XE_PORT(lw->lw_unit, lp->lp_rx_port) ||
   2300           IS_XL_PORT(lw->lw_unit, lp->lp_rx_port))) {
   2301         if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_tx_port, 
   2302                                  snmpIfOutUcastPkts, &tx_count)) < 0) {
   2303             test_error(lw->lw_unit,
   2304                        "Could not get port %s tx %s stats : %s\n",
   2305                        SOC_PORT_NAME(lw->lw_unit, lp->lp_tx_port),
   2306                        "snmpIfOutUcastPkts",
   2307                        soc_errmsg(rv));
   2308             return -1;
   2309         }
   2310         if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_rx_port, 
   2311                                  snmpIfInUcastPkts, &rx_count)) < 0) {
   2312             test_error(lw->lw_unit,
   2313                        "Could not get port %s rx %s stats : %s\n",
   2314                        SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2315                        "snmpIfInUcastPkts",
   2316                        soc_errmsg(rv));
   2317             return -1;
   2318         }
   2319         if (tx_count != rx_count) {
   2320             test_error(lw->lw_unit,
   2321                        "TX/RX packet stats mismatch: (%s) TX=%d, (%s) RX=%d\n",
   2322                        SOC_PORT_NAME(lw->lw_unit, lp->lp_tx_port),
   2323                        (int) tx_count,
   2324                        SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2325                        (int) rx_count);
   2326             test_rv = -1;
   2327         }
   2328     }
   2329 
   2330     /* Check for port TX error statistics */
   2331     if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_tx_port, 
   2332                              snmpIfOutErrors, &tx_count)) < 0) {
   2333         test_error(lw->lw_unit,
   2334                    "Could not get port %s tx error %s stats : %s\n",
   2335                    SOC_PORT_NAME(lw->lw_unit, lp->lp_tx_port),
   2336                    "snmpIfOutErrors",
   2337                    soc_errmsg(rv));
   2338         return -1;
   2339     }
   2340     if (tx_count) {
   2341         test_error(lw->lw_unit,
   2342                    "TX error stats found: TX (%s) error count=%d\n",
   2343                    SOC_PORT_NAME(lw->lw_unit, lp->lp_tx_port),
   2344                    (int) tx_count);
   2345         test_rv = -1;
   2346     }
   2347 
   2348     /* Check for port RX error statistics 
   2349      * Use individual stat to count rx errors instead of snmpIfInErrors 
   2350      * which includes good oversize packets.
   2351      */
   2352     if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_rx_port, 
   2353                              snmpEtherStatsUndersizePkts, &rx_count0)) < 0) {
   2354         test_error(lw->lw_unit,
   2355                    "Could not get port %s rx %s stats : %s\n",
   2356                    SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2357                    "snmpEtherStatsUndersizePkts",
   2358                    soc_errmsg(rv));
   2359         return -1;
   2360     }
   2361     if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_rx_port, 
   2362                              snmpEtherStatsFragments, &rx_count1)) < 0) {
   2363         test_error(lw->lw_unit,
   2364                    "Could not get port %s rx %s stats : %s\n",
   2365                    SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2366                    "snmpEtherStatsFragments",
   2367                    soc_errmsg(rv));
   2368         return -1;
   2369     }
   2370     if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_rx_port, 
   2371                              snmpEtherStatsCRCAlignErrors, &rx_count2)) < 0) {
   2372         test_error(lw->lw_unit,
   2373                    "Could not get port %s rx %s stats : %s\n",
   2374                    SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2375                    "snmpEtherStatsCRCAlignErrors",
   2376                    soc_errmsg(rv));
   2377         return -1;
   2378     }
   2379     if ((rv = bcm_stat_get32(lw->lw_unit, lp->lp_rx_port, 
   2380                              snmpEtherStatsJabbers, &rx_count3)) < 0) {
   2381         test_error(lw->lw_unit,
   2382                    "Could not get port %s rx %s stats : %s\n",
   2383                    SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2384                    "snmpEtherStatsJabbers",
   2385                    soc_errmsg(rv));
   2386         return -1;
   2387     }
   2388     rx_count = rx_count0 + rx_count1 + rx_count2 + rx_count3;
   2389     if (rx_count) {
   2390         test_error(lw->lw_unit,
   2391                    "RX error stats found: RX (%s) error count=%d\n",
   2392                    SOC_PORT_NAME(lw->lw_unit, lp->lp_rx_port),
   2393                    (int) rx_count);
   2394         test_rv = -1;
   2395     }
   2396 
   2397     return(test_rv);
   2398 }
   2399 
   2400 int
   2401 lb_dma_run_common(int unit, loopback_test_t *lw, loopback_testdata_t *lp)
   2402 /*
   2403  * Function:    dma_test
   2404  * Purpose:     Common code for simple interrupt driven DMA test.
   2405  * Parameters:  <see usage above>
   2406  * Returns:     0 - success
   2407  *              -1 - failed
   2408  */
   2409 {
   2410     int rx_chan, tx_chan, chan;
   2411     /*
   2412      * For each of the DMA channel configurations, run the entire test.
   2413      */
   2414 
   2415     lw->lw_lp = lp;                     /* Assign test # */
   2416 
   2417     lb_stats_init(lw);
   2418 
   2419     lp->lp_tx_port = CMIC_PORT(unit);
   2420     lp->lp_rx_port = CMIC_PORT(unit);
   2421 
   2422     if(soc_feature(unit, soc_feature_cmicx)) {
   2423         chan = CMICX_N_DMA_CHAN;
   2424     } else {
   2425         chan = N_DMA_CHAN;
   2426     }
   2427 
   2428     for (rx_chan = 0; rx_chan < chan; rx_chan++) {
   2429 #ifdef INCLUDE_KNET
   2430         if (SOC_KNET_MODE(unit)) {
   2431             /* Currently KNET uses chan 1 for rx */
   2432             if (rx_chan != KCOM_DMA_RX_CHAN) {
   2433                 continue;
   2434             }
   2435         }
   2436 #endif /* INCLUDE_KNET */
   2437         LOG_INFO(BSL_LS_APPL_TESTS,
   2438                  (BSL_META_U(unit,
   2439                              "Configuring RX-channel: %d\n"), rx_chan));
   2440         if (soc_dma_chan_config(unit, rx_chan, DV_RX, 
   2441                                 SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   2442             test_error(unit, "Unable to configure RX channel: %d\n", rx_chan);
   2443             break;
   2444         }
   2445 #ifdef BCM_CMICM_SUPPORT
   2446         /* Assign all COS to this channel
   2447          * Though this is added for CMICm, 
   2448          * it should be OK if we do this for CMICe as well */
   2449         if(soc_feature(unit, soc_feature_cmicm)) {
   2450             LOG_INFO(BSL_LS_APPL_TESTS,
   2451                      (BSL_META_U(unit,
   2452                                  "Assign all COS to channel: %d\n"), rx_chan));
   2453             BCM_IF_ERROR_RETURN(
   2454                 soc_rx_queue_channel_set(unit, -1, rx_chan));
   2455 
   2456 #if defined(BCM_KATANA2_SUPPORT)
   2457             if(SOC_IS_KATANA2(unit)) {
   2458                 uint32 reg_val, reg_addr;
   2459 
   2460                 /* Including CPU L0 bitmap to support CMIC backpressure */
   2461                 reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, rx_chan);
   2462                 reg_val = soc_pci_read(unit, reg_addr);
   2463                 reg_val |= (1 << 16);
   2464                 soc_pci_write(unit, reg_addr, reg_val);
   2465             }
   2466 #endif
   2467         }
   2468 #endif
   2469 
   2470 #if defined(BCM_RAVEN_SUPPORT)
   2471        if(SOC_IS_RAVEN(unit)) {
   2472             uint32 val;
   2473             /* Increase the dynamic cell limit for cpu port */
   2474             SOC_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, 0, &val));
   2475             if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLSETLIMITf)) {
   2476                soc_reg_field_set(unit, DYNCELLLIMITr, &val,DYNCELLSETLIMITf, 0x1644);
   2477             }
   2478 			
   2479             if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITf)) {
   2480                soc_reg_field_set(unit, DYNCELLLIMITr, &val,  DYNCELLRESETLIMITf, 0x162c);
   2481             }
   2482             SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, 0, val));
   2483         }
   2484 #endif
   2485 #ifdef BCM_CMICX_SUPPORT
   2486         /* Assign all COS to this channel */
   2487         if(soc_feature(unit, soc_feature_cmicx)) {
   2488             LOG_INFO(BSL_LS_APPL_TESTS,
   2489                      (BSL_META_U(unit,
   2490                                  "Assign all COS to channel: %d\n"), rx_chan));
   2491             BCM_IF_ERROR_RETURN(
   2492                 soc_rx_queue_channel_set(unit, -1, rx_chan));
   2493         }
   2494 #endif
   2495 
   2496         for (tx_chan = 0; tx_chan < chan; tx_chan++) {
   2497 #ifdef INCLUDE_KNET
   2498             if (SOC_KNET_MODE(unit)) {
   2499                 /* Currently KNET uses chan 0 for tx */
   2500                 if (tx_chan != KCOM_DMA_TX_CHAN) {
   2501                     continue;
   2502                 }
   2503             }
   2504 #endif /* INCLUDE_KNET */
   2505             if (rx_chan == tx_chan) {   /* Does not make sense */
   2506                 continue;
   2507             }
   2508             LOG_INFO(BSL_LS_APPL_TESTS,
   2509                      (BSL_META_U(unit,
   2510                                  "Configuring TX-channel: %d\n"), tx_chan));
   2511             if (soc_dma_chan_config(unit, tx_chan,
   2512                                     DV_TX, SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   2513                 test_error(unit,
   2514                            "Unable to configure TX channel: %d\n",
   2515                            tx_chan);
   2516                 break;
   2517             }
   2518             if (lb_do_txrx(lw) < 0) {
   2519                 return -1;
   2520             }
   2521 
   2522             if (soc_dma_chan_config(unit, tx_chan, DV_NONE, SOC_DMA_F_INTR)) {
   2523                 test_error(unit,
   2524                            "Unable to de-configure TX channel: %d\n",
   2525                            tx_chan);
   2526                 break;
   2527             }
   2528         }
   2529 
   2530         if (soc_dma_chan_config(unit, rx_chan,
   2531                                 DV_NONE, SOC_DMA_F_INTR)) {
   2532             test_error(unit,
   2533                        "Unable to de-configure RX channel: %d\n", rx_chan);
   2534             break;
   2535         }
   2536     }
   2537 
   2538     lb_stats_done(lw);
   2539 
   2540     return 0;
   2541 }
   2542 
   2543 
   2544 int
   2545 lb_dma_testapi_run(int unit, loopback_test_t *lw, loopback_testdata_t *lp)
   2546 {
   2547 /*
   2548  * Function:    dma_test
   2549  * Purpose:     Perform simple interrupt driven DMA test via API.
   2550  * Parameters:  <see usage above>
   2551  * Returns:     0 - success
   2552  *              -1 - failed
   2553  */
   2554     return lb_dma_run_common(unit, lw, lp);
   2555 }
   2556 
   2557 int
   2558 lb_dma_test(int unit, args_t *a, void *pa)
   2559 /*
   2560  * Function:    dma_test
   2561  * Purpose:     Perform simple interrupt driven DMA test via CLI.
   2562  * Parameters:  <see usage above>
   2563  * Returns:     0 - success
   2564  *              -1 - failed
   2565  */
   2566 {
   2567     loopback_test_t     *lw = (loopback_test_t *)pa;
   2568     loopback_testdata_t *lp = &lw->lw_lp_dma;
   2569     COMPILER_REFERENCE(a);
   2570     lb_stats_init(lw);
   2571 #ifdef BCM_SHADOW_SUPPORT
   2572         if (SOC_IS_SHADOW(unit)) {
   2573             if (lb_setup_static_path(lw, unit, CMIC_PORT(unit), CMIC_PORT(unit))) {
   2574                 return(-1);
   2575             }
   2576         }
   2577         if (SOC_IS_SHADOW(unit)) {
   2578             port_tab_entry_t ptab;
   2579             SOC_IF_ERROR_RETURN
   2580                 (soc_reg_field32_modify(unit, EPC_LINK_BMAPr, REG_PORT_ANY,
   2581                                         PORT_BITMAPf, 0x1ffff));
   2582             /* Disable VLAN checks */
   2583             SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm,
   2584                             MEM_BLOCK_ANY, 0, &ptab));
   2585             if (soc_mem_field_valid(unit, PORT_TABm, DISABLE_VLAN_CHECKSf)) {
   2586                 soc_PORT_TABm_field32_set(unit, &ptab, DISABLE_VLAN_CHECKSf, 1);
   2587             }
   2588             SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
   2589                                 0, &ptab));
   2590             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, THDI_BYPASSr,
   2591                             REG_PORT_ANY, INPUT_THRESHOLD_BYPASSf, 1));
   2592         }
   2593 #endif
   2594 
   2595     lw->lw_tx_dcb_factor = 1;
   2596 
   2597     return lb_dma_run_common(unit, lw, lp);
   2598 }
   2599 
   2600 STATIC int
   2601 lb_set_mac_addr(int unit, soc_port_t p, uint32 vlan, bcm_l2_addr_t *arl,
   2602                 sal_mac_addr_t mac_addr)
   2603 /*
   2604  * Function:    lb_set_arl_mac_addr
   2605  * Purpose:     Set a mac address for a port.
   2606  * Parameters:  unit - SOC unit #
   2607  *              p - port to set address for.
   2608  *              vlan - vlan tag to use in ARL entry.
   2609  *              arl - pointer to arl entry to use.
   2610  * Returns:     0 - success, -1 failed.
   2611  */
   2612 {
   2613     int rv = BCM_E_UNAVAIL;
   2614 
   2615     
   2616     /*
   2617        To avoid flipping external vs internal L2 memory settings 
   2618        for XGS3 devices the same path can be configured using 
   2619        l2_cache_XXX API
   2620     */
   2621 #if defined(BCM_ESW_SUPPORT)
   2622     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
   2623 #if defined(BCM_TRIUMPH_SUPPORT)
   2624         bcm_l2_cache_addr_t l2caddr;
   2625         int index;
   2626 
   2627         rv = bcm_l2_cache_delete_all(unit);
   2628         if (rv < 0) {
   2629             if (rv != BCM_E_NOT_FOUND) {
   2630                 return rv;
   2631             } /* else, non-existent entry */
   2632         }
   2633 
   2634         sal_memset(&l2caddr, 0, sizeof(bcm_l2_cache_addr_t));
   2635         l2caddr.flags = BCM_L2_STATIC;
   2636         l2caddr.vlan = vlan;
   2637         sal_memcpy(l2caddr.mac, mac_addr, sizeof(sal_mac_addr_t));
   2638         l2caddr.src_port = p;
   2639 
   2640         rv = bcm_l2_cache_set(unit, -1, &l2caddr ,&index); 
   2641 #endif
   2642     }	else 
   2643 #endif    
   2644     {
   2645         /*
   2646          * Prior XGS3 don't have external L2 memory so it is 
   2647          * safe to use bcm_l2_XXX API 
   2648          */
   2649         rv = bcm_l2_addr_delete(unit, mac_addr, (vlan_id_t)vlan);
   2650         if (rv < 0) {
   2651             if (rv != BCM_E_NOT_FOUND) {
   2652                 return rv;
   2653             } /* else, non-existent entry */
   2654         }
   2655 
   2656         sal_memcpy(arl->mac, mac_addr, sizeof(sal_mac_addr_t));
   2657         arl->vid = vlan;
   2658         arl->flags = BCM_L2_STATIC;
   2659         arl->port = p;
   2660         rv = bcm_l2_addr_add(unit, arl);
   2661     }
   2662 
   2663     return rv;
   2664 }
   2665 
   2666 STATIC void
   2667 lb_cleanup_arl(loopback_test_t *lw, int unit)
   2668 /*
   2669  * Function:    lb_cleanup_arl
   2670  * Purpose:     Clean up arl entries inserted after a test.
   2671  * Parameters:  lw - pointer to work
   2672  *              unit  - SOC unit #
   2673  * Returns:     Nothing
   2674  */
   2675 {
   2676     loopback_testdata_t *lp = lw->lw_lp;
   2677     sal_mac_addr_t  cur_mac;
   2678     int         c_cur;
   2679 #ifdef BCM_TRIUMPH_SUPPORT
   2680     int ext_index_max = -1;
   2681 #endif /* BCM_TRIUMPH_SUPPORT */
   2682 
   2683 #ifdef BCM_TRIUMPH_SUPPORT
   2684     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
   2685         ext_index_max = SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max;
   2686         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = -1;
   2687     }
   2688 #endif /* BCM_TRIUMPH_SUPPORT */
   2689 
   2690     if (lw->lw_arl_src_delete) {
   2691         ENET_SET_MACADDR(cur_mac, lw->lw_mac_src);
   2692 
   2693         for (c_cur = 0; c_cur < lp->lp_c_end; c_cur++) {
   2694             (void)bcm_l2_addr_delete(unit, cur_mac,
   2695                                      (vlan_id_t)lw->lw_lp->lp_vlan);
   2696             increment_macaddr(cur_mac, lp->lp_mac_src_inc);
   2697         }
   2698 
   2699         lw->lw_arl_src_delete = FALSE;
   2700     }
   2701 
   2702     if (lw->lw_arl_dst_delete) {
   2703         ENET_SET_MACADDR(cur_mac, lw->lw_mac_dst);
   2704 
   2705         for (c_cur = 0; c_cur < lp->lp_c_end; c_cur++) {
   2706             (void)bcm_l2_addr_delete(unit, cur_mac,
   2707                                      (vlan_id_t)lw->lw_lp->lp_vlan);
   2708             increment_macaddr(cur_mac, lp->lp_mac_dst_inc);
   2709         }
   2710 
   2711         lw->lw_arl_dst_delete = FALSE;
   2712     }
   2713 
   2714 #ifdef BCM_TRIUMPH_SUPPORT
   2715     if (soc_mem_is_valid(unit, EXT_L2_ENTRYm)) {
   2716         SOC_PERSIST(unit)->memState[EXT_L2_ENTRYm].index_max = ext_index_max;
   2717     }
   2718 #endif /* BCM_TRIUMPH_SUPPORT */
   2719 }
   2720 
   2721 #ifdef BCM_SHADOW_SUPPORT
   2722 /*
   2723  * Function:    lb_setup_static_path
   2724  * Purpose:     Setup a static path for the specified port
   2725  * Parameters:  unit - unit #
   2726  *              port - port to which address should map
   2727  *              src_port - port under test
   2728  * Returns:     0 - success
   2729  *              -1 - failed.
   2730  * Notes:       Only the destination port CBIT is returned, as only
   2731  *              it is required for the test.
   2732  */
   2733 static int
   2734 lb_setup_static_path(loopback_test_t *lw, int unit, soc_port_t port,
   2735                      soc_port_t src_port)
   2736 {
   2737     loopback_testdata_t *lp = lw->lw_lp;
   2738     int         rv = 0;
   2739     uint32 rval = 0;
   2740 
   2741     ENET_SET_MACADDR(lp->lp_mac_src, lw->lw_mac_src);
   2742     ENET_SET_MACADDR(lp->lp_mac_dst, lw->lw_mac_dst);
   2743 
   2744     LOG_INFO(BSL_LS_APPL_TESTS,
   2745              (BSL_META_U(unit,
   2746                          "Setting up static path for port %s\n"),
   2747               SOC_PORT_NAME(unit, src_port)));
   2748 
   2749     /* Get the module ID for this unit */
   2750     if (SOC_IS_SHADOW(unit)) {
   2751         lw->lw_arl_dst.modid = 0;
   2752     } else if (SOC_IS_XGS_SWITCH(unit)) {
   2753         if ((rv = bcm_stk_my_modid_get(unit, &lw->lw_arl_dst.modid)) < 0) {
   2754             test_error(lw->lw_unit,
   2755                        "Could not get modid: %s\n", bcm_errmsg(rv));
   2756             return(-1);
   2757         }
   2758         if (SOC_PORT_MOD1(unit, port)) {
   2759             lw->lw_arl_dst.modid += 1;
   2760         }
   2761     }
   2762 
   2763     rv = READ_UFLOW_PORT_CONTROLr(unit, src_port, &rval);
   2764     if (rv < 0) {
   2765         return(-1);
   2766     }
   2767     soc_reg_field_set(unit, UFLOW_PORT_CONTROLr, &rval, HASH_MODEf, 0);
   2768     soc_reg_field_set(unit, UFLOW_PORT_CONTROLr, &rval, DEST_PORTf, port);
   2769     rv = WRITE_UFLOW_PORT_CONTROLr(unit, src_port, rval);
   2770 
   2771     lw->lw_arl_dst_delete = TRUE;
   2772 
   2773     if (rv < 0) {
   2774         test_error(lw->lw_unit,
   2775                    "Failed to set static path: port %s\n",
   2776                    SOC_PORT_NAME(lw->lw_unit, port));
   2777         return(-1);
   2778     } else if (lw->lw_arl_dst.port != CMIC_PORT(unit)) {
   2779         test_error(lw->lw_unit,
   2780                    "Port %s: invalid destination port: %s\n",
   2781                    SOC_PORT_NAME(lw->lw_unit, port),
   2782                    SOC_PORT_NAME(lw->lw_unit, lw->lw_arl_dst.port));
   2783         return(-1);
   2784     }
   2785 
   2786     return(0);
   2787 }
   2788 #endif /* BCM_SHADOW_SUPPORT */
   2789 
   2790 /*
   2791  * Function:    lb_setup_arl
   2792  * Purpose:     Setup an ARL entry for the specified port
   2793  * Parameters:  unit - unit #
   2794  *              port - port to which address should map
   2795  *              src_port - port under test
   2796  * Returns:     0 - success
   2797  *              -1 - failed.
   2798  * Notes:       Only the destination port CBIT is returned, as only
   2799  *              it is required for the test.
   2800  */
   2801 int
   2802 lb_setup_arl(loopback_test_t *lw, int unit, soc_port_t port, 
   2803              soc_port_t src_port)
   2804 {
   2805     loopback_testdata_t *lp = lw->lw_lp;
   2806     int         rv = 0;
   2807     sal_mac_addr_t  cur_mac;
   2808     int c_cur;
   2809 
   2810     ENET_SET_MACADDR(lw->lw_mac_src, lp->lp_mac_src);
   2811     ENET_SET_MACADDR(lw->lw_mac_dst, lp->lp_mac_dst);
   2812 
   2813     if (IS_ST_PORT(unit, src_port)) {
   2814         /* Don't install L2 entry if port is HG */
   2815         return(0);
   2816     }
   2817     LOG_INFO(BSL_LS_APPL_TESTS,
   2818              (BSL_META_U(unit,
   2819                          "Setting up ARL for port %s\n"),
   2820               SOC_PORT_NAME(unit, src_port)));
   2821 
   2822     ENET_SET_MACADDR(cur_mac, lw->lw_mac_dst);
   2823 
   2824     /* Get the module ID for this unit */
   2825     if (SOC_IS_XGS_SWITCH(unit)) {
   2826         if ((rv = bcm_stk_my_modid_get(unit, &lw->lw_arl_dst.modid)) < 0) {
   2827             test_error(lw->lw_unit,
   2828                        "Could not get modid: %s\n", bcm_errmsg(rv));
   2829             return(-1);
   2830         } 
   2831         if (SOC_PORT_MOD1(unit, port)) {
   2832             lw->lw_arl_dst.modid += 1;
   2833         }
   2834     }
   2835 
   2836     for (c_cur = 0; c_cur < lp->lp_c_end; c_cur++) {
   2837         rv |= lb_set_mac_addr(unit, port, lw->lw_lp->lp_vlan,
   2838                               &lw->lw_arl_dst, cur_mac);
   2839         increment_macaddr(cur_mac, lp->lp_mac_dst_inc);
   2840     }
   2841 
   2842     lw->lw_arl_dst_delete = TRUE;
   2843 
   2844     if (rv) {
   2845         test_error(lw->lw_unit,
   2846                    "Failed to set MAC address: port %s\n",
   2847                    SOC_PORT_NAME(lw->lw_unit, port));
   2848         return(-1);
   2849     } else if (lw->lw_arl_dst.port != CMIC_PORT(unit)) {
   2850         test_error(lw->lw_unit,
   2851                    "Port %s: invalid destination arl port: %s\n",
   2852                    SOC_PORT_NAME(lw->lw_unit, port),
   2853                    SOC_PORT_NAME(lw->lw_unit, lw->lw_arl_dst.port));
   2854         return(-1);
   2855     }
   2856 
   2857     return(0);
   2858 }
   2859 
   2860 STATIC   int
   2861 lb_done(loopback_test_t *lw)
   2862 /*
   2863  * Function:    lb_done
   2864  * Purpose:     Generic loopback done function
   2865  * Parameters:  lw - pointer to lw to clean up.
   2866  * Returns:
   2867  */
   2868 {
   2869     int         rv = 0;
   2870     dma_chan_t  c, chan;
   2871     loopback_testdata_t *lp = lw->lw_lp;
   2872 
   2873     if(soc_feature(lw->lw_unit, soc_feature_cmicx)) {
   2874         chan = CMICX_N_DMA_CHAN;
   2875     } else {
   2876         chan = N_DMA_CHAN;
   2877     }
   2878 
   2879     (void)soc_dma_abort(lw->lw_unit);   /* Abort all dma */
   2880 
   2881     if (lw->lw_sema) {
   2882         sal_sem_destroy(lw->lw_sema);
   2883         lw->lw_sema = NULL;
   2884     }
   2885 
   2886     if (lp) {
   2887         lb_deallocate(lw->lw_unit, 
   2888                       lp->lp_dv_end, &lw->lw_rx_dv,
   2889                       lp->lp_ppc_end, &lw->lw_rx_packets, NULL, DV_RX);
   2890 
   2891         lb_deallocate(lw->lw_unit, 
   2892                       lp->lp_dv_end, &lw->lw_tx_dv,
   2893                       lp->lp_ppc_end, &lw->lw_tx_packets,  &lw->lw_tx_dcbs, DV_TX);
   2894     }
   2895 
   2896     /* Clean up ARL if interrupted in middle */
   2897 
   2898 #ifdef BCM_SHADOW_SUPPORT
   2899     if (SOC_IS_SHADOW(lw->lw_unit)) {
   2900     } else
   2901 #endif
   2902     {
   2903         lb_cleanup_arl(lw, lw->lw_unit);
   2904     }
   2905 
   2906     /* ENABLE ALL PORTS */
   2907 
   2908     if (lp) {
   2909         rv |= lb_restore_port(lw);
   2910     }
   2911 
   2912 	if (SOC_DPP_PP_ENABLE(lw->lw_unit) && SOC_IS_ARAD(lw->lw_unit)) {
   2913 	    /* RESTORE VLAN */
   2914 	    if (lp) {
   2915 	        rv |= lb_restore_vlan(lw);
   2916 	    }
   2917 	}
   2918         if (SOC_IS_KATANAX(lw->lw_unit) && (SAL_BOOT_QUICKTURN)) {
   2919 	    if (lp) {
   2920                 cli_out("QUICKTURN:: ATTN : Restoring VLAN \n");
   2921 	        rv |= lb_restore_vlan(lw);
   2922 	    }
   2923         }
   2924     /*
   2925      * Deconfigure all DMA channels.
   2926      * Doing this aborts any DMAs that may be left over.
   2927      */
   2928     for (c = 0; c < chan; c++) {
   2929         if (soc_dma_chan_config(lw->lw_unit, c, DV_NONE, 0) < 0) {
   2930             rv = -1;
   2931         }
   2932     }
   2933 
   2934     /*
   2935      * Leave channels configured in default state at end of test.
   2936      */
   2937     rv |= soc_dma_init(lw->lw_unit);
   2938 
   2939     /*
   2940      * Clear L2 cache entries (if used)
   2941      */
   2942 #ifdef BCM_XGS3_SWITCH_SUPPORT
   2943     if (l2_index >= 0) {
   2944         bcm_l2_cache_delete(lw->lw_unit, l2_index);
   2945         l2_index = -1;
   2946     }
   2947 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   2948 
   2949     return(rv);
   2950 }
   2951 
   2952 STATIC int
   2953 lb_init(int unit, loopback_test_t *lw, loopback_testdata_t *lp, int external)
   2954 /*
   2955  * Function:    lb_init
   2956  * Purpose:     Loopback generic initialization
   2957  * Parameters:  unit - unit number to init.
   2958  *              lw - pointer to lw to init.
   2959  *              a - args from test cmd
   2960  *              external - true if actual link up required
   2961  * Returns:     0 on success, -1 on failure
   2962  */
   2963 {
   2964     soc_port_t          port;
   2965     int                 rv;
   2966     pbmp_t              pbm;
   2967 
   2968     lw->lw_lp = lp;
   2969 
   2970     lw->lw_rx_fill = soc_property_get(unit, spn_DIAG_LB_FILL_RX, 0);
   2971 
   2972     if (NULL == (lw->lw_sema = sal_sem_create("lb-sema", sal_sem_BINARY, 0))) {
   2973         return (-1);
   2974     }
   2975 
   2976     lw->lw_sema_woke = FALSE;
   2977     lw->lw_timeout_usec = lb_timeout_usec(unit);
   2978 
   2979     /* Try to allocate required memory */
   2980 
   2981     lw->lw_tx_packet_cnt = lp->lp_ppc_end;
   2982     lw->lw_rx_packet_cnt = lp->lp_ppc_end;
   2983 
   2984     if (lb_allocate(unit, DV_RX, lp->lp_dv_end, lp->lp_c_end, &lw->lw_rx_dv,
   2985                     lp->lp_ppc_end, lp->lp_l_end, &lw->lw_rx_packets, NULL) ||
   2986         lb_allocate(unit, DV_TX, lp->lp_dv_end, lp->lp_c_end, &lw->lw_tx_dv,
   2987                     lp->lp_ppc_end, lp->lp_l_end, &lw->lw_tx_packets, &lw->lw_tx_dcbs)) {
   2988         test_error(unit, "Unable to allocate DCB and/or packet memory\n");
   2989         lb_done(lw);
   2990     }
   2991 
   2992     lw->lw_tx_seq = 0;
   2993 
   2994     lw->lw_tx_init_chn = 0;            /* Start off clean */
   2995     lw->lw_tx_init_len = 0;
   2996 
   2997     lw->lw_tx_started = 0;
   2998     lw->lw_rx_started = 0;
   2999 
   3000     SOC_PBMP_CLEAR(lw->lw_save_vlan_pbmp);
   3001     SOC_PBMP_CLEAR(lw->lw_save_vlan_ubmp);
   3002     lw->lw_save_vlan_stg = 0;
   3003     lw->lw_save_vlan_valid = 0;
   3004 
   3005 #ifdef BCM_XGS12_FABRIC_SUPPORT
   3006     /* Setup H/W specific offsets */
   3007     if (SOC_IS_XGS12_FABRIC(unit)) {
   3008         lw->lw_ether_start = SOC_HIGIG_HDR_SIZE;
   3009     } else {
   3010         lw->lw_ether_start = 0; /* No XGS header */
   3011     }
   3012 #else
   3013     lw->lw_ether_start = 0;
   3014 #endif
   3015 
   3016     /* Save all the current port states */
   3017 
   3018     if (lb_save_port(lw) < 0) {
   3019         return (-1);
   3020     }
   3021     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   3022 		
   3023 	    if (lb_save_vlan(lw) < 0) {
   3024 	        return (-1);
   3025 	    }
   3026     }
   3027     SOC_PBMP_ASSIGN(pbm, PBMP_PORT_ALL(unit));
   3028     SOC_PBMP_AND(pbm, lp->lp_pbm);
   3029 	if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   3030 
   3031 	    if (!SOC_IS_SHADOW(unit)) {
   3032 	        PBMP_ITER(pbm, port) {
   3033 	            if (!external &&
   3034 	                (rv = bcm_port_stp_set(unit, port,
   3035 	                                       BCM_STG_STP_FORWARD)) < 0) {
   3036 	                test_error(unit,
   3037 	                           "Unable to set port %s in forwarding state: %s\n",
   3038 	                           SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   3039 	                return -1;
   3040 	            }
   3041 	        }
   3042 	    }
   3043 	}
   3044     return 0;
   3045 }
   3046 
   3047 /*
   3048  * Adjust FE_MAXFr, MAXFRr, and GTH_MAXFr as necessary, to
   3049  * accommodate requested packet size.
   3050  */
   3051 static int
   3052 _lb_max_frame_set(loopback_test_t *lw, loopback_testdata_t *lp)
   3053 {
   3054     pbmp_t          pbm;
   3055     int             max_pkt, max_set;
   3056     soc_port_t      port;
   3057     int             max_adj = 0;
   3058     int             jumbo_adj = 0;
   3059     int             unit = lw->lw_unit;
   3060 
   3061     max_pkt = lp->lp_l_start;
   3062 
   3063     if (max_pkt < lp->lp_l_end) {
   3064         max_pkt = lp->lp_l_end;
   3065     }
   3066 
   3067     if (max_pkt > LB_JUMBO_MAXSZ) {
   3068         max_pkt = LB_JUMBO_MAXSZ;
   3069     }
   3070 
   3071     if (SOC_IS_SHADOW(unit)) {
   3072         return SOC_E_NONE;
   3073     }
   3074     BCM_PBMP_ASSIGN(pbm, PBMP_PORT_ALL(unit));
   3075     BCM_PBMP_AND(pbm, lp->lp_pbm);
   3076     BCM_PBMP_ITER(pbm, port) {
   3077         BCM_IF_ERROR_RETURN
   3078             (bcm_port_frame_max_get(unit, port, &max_set));
   3079         if (max_set < max_pkt) {
   3080             BCM_IF_ERROR_RETURN
   3081                 (bcm_port_frame_max_set(unit, port, max_pkt));
   3082             max_adj = 1;
   3083         }
   3084     }
   3085 
   3086     SOC_PBMP_ASSIGN(pbm, PBMP_GE_ALL(unit));
   3087     SOC_PBMP_AND(pbm, lp->lp_pbm);
   3088     PBMP_ITER(pbm, port) {
   3089         if (max_pkt > 1536) {
   3090             if (soc_feature(unit, soc_feature_trimac)) {
   3091 #if defined(BCM_ESW_SUPPORT)
   3092 				
   3093                 uint32          gmacc1;
   3094 
   3095                 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1));
   3096 
   3097                 if (! soc_reg_field_get(unit, GMACC1r, gmacc1, JUMBOf)) {
   3098                     soc_reg_field_set(unit, GMACC1r, &gmacc1, JUMBOf, 1);
   3099                     SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1));
   3100                     jumbo_adj = 1;
   3101                 }
   3102 #endif				
   3103             } 
   3104 #if defined(BCM_TRX_SUPPORT) || defined(BCM_RAVEN_SUPPORT)            
   3105             else if (soc_feature(unit, soc_feature_unimac)) {
   3106                 if (SOC_BLOCK_TYPE(unit, SOC_PORT_BLOCK(unit, 
   3107                     SOC_INFO(unit).port_l2p_mapping[port])) != SOC_BLK_XLPORT) {
   3108                         SOC_IF_ERROR_RETURN(WRITE_FRM_LENGTHr(unit, 
   3109                                   port, LB_JUMBO_MAXSZ));
   3110                 }
   3111             }
   3112 #endif /* BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */
   3113         }
   3114     }
   3115 
   3116     if (max_adj) {
   3117         cli_out("NOTICE: Increased max frame size for %d-byte packets\n",
   3118                 max_pkt);
   3119     }
   3120 
   3121     if (jumbo_adj) {
   3122         cli_out("NOTICE: Enabled JUMBO frames on GE\n");
   3123     }
   3124     return(0);
   3125 }
   3126 
   3127 int 
   3128 lb_check_parms(loopback_test_t *lw, loopback_testdata_t *lp, pbmp_t pbm_ok)
   3129 /*
   3130  * Function:    lb_check_parms
   3131  * Purpose:     Check parameters for reasonable values.
   3132  * Parameters:  lw - pointer to current work structure.
   3133  *              lp - pointer to parameters.
   3134  *              pbm_ok - allowable ports for test
   3135  * Returns:     0 - OK
   3136  *              -1 - failed.
   3137  */
   3138 {
   3139     int         i, nLen, nChain, nCOS, nPort, nChanConf;
   3140     int         unit = lw->lw_unit;
   3141     pbmp_t      pbm;
   3142     char        pfmt[SOC_PBMP_FMT_LEN];
   3143     int         num_cos, num_ports;
   3144     
   3145     if(soc_feature(unit, soc_feature_cmicx)) {
   3146         nChanConf = ((lp == &lw->lw_lp_dma) ? CMICX_CHAN_CONFIG_COUNT : 1);
   3147     } else {
   3148     nChanConf = ((lp == &lw->lw_lp_dma) ? CHAN_CONFIG_COUNT : 1);
   3149     }
   3150 
   3151     if (lp->lp_l_start < 24) {
   3152         test_error(unit,
   3153                    "Packet start length %d too small\n",
   3154                    lp->lp_l_start);
   3155         return(-1);
   3156     }
   3157 
   3158     if (bcm_cosq_config_get(unit, &num_cos) < 0 || num_cos == 0) {
   3159         num_cos = 1;
   3160     }
   3161 
   3162     if (lp->lp_cos_start >= num_cos || lp->lp_cos_end >= num_cos) {
   3163         LOG_WARN(BSL_LS_APPL_COMMON,
   3164                  (BSL_META_U(unit,
   3165                              "***NOTICE: COS %d-%d requested, but only %d COS configured\n"),
   3166                   lp->lp_cos_start, lp->lp_cos_end, num_cos));
   3167     }
   3168 
   3169     if ((lp != &lw->lw_lp_dma) || (SOC_IS_XGS3_SWITCH(unit))) {
   3170         _lb_max_frame_set(lw, lp);
   3171     }
   3172 
   3173     if (lp->lp_l_inc <= 0 || lp->lp_c_inc <= 0) {
   3174         test_error(unit, "Increments must be > 0\n");
   3175         return(-1);
   3176     }
   3177 
   3178     SOC_PBMP_ASSIGN(pbm, lp->lp_pbm);
   3179     SOC_PBMP_REMOVE(pbm, pbm_ok);
   3180     if (SOC_PBMP_NOT_NULL(pbm)) {
   3181         test_error(unit,
   3182                    "Invalid bits in port bitmap.\n"
   3183                    "Allowable ports are %s\n",
   3184                    SOC_PBMP_FMT(pbm_ok, pfmt));
   3185         return(-1);
   3186     }
   3187 
   3188     if (lp->lp_cos_start < 0 ||
   3189         lp->lp_cos_end < lp->lp_cos_start ||
   3190         lp->lp_cos_end >= NUM_COS(unit)) {
   3191         test_error(unit,
   3192                    "Invalid COS values: start=%d end=%d\n",
   3193                    lp->lp_cos_start, lp->lp_cos_end);
   3194         return(-1);
   3195     }
   3196 
   3197     if (lp->lp_check_crc && lp->lp_crc_mode == CRC_MODE_CPU_NONE) {
   3198         test_error(unit, "Can't check CRC if not generating it\n");
   3199         return(-1);
   3200     }
   3201 #if defined(BCM_XGS12_FABRIC_SUPPORT)
   3202 
   3203     if (SOC_IS_XGS12_FABRIC(unit)) {
   3204         if (lp->lp_d_mod < soc_mem_index_min(unit, MEM_UCm) ||
   3205              lp->lp_d_mod > soc_mem_index_max(unit, MEM_UCm)) {
   3206             test_error(unit,
   3207                        "Invalid Module ID selection: %d\n",
   3208                        lp->lp_d_mod);
   3209             return (-1);
   3210         }
   3211     }
   3212 #endif
   3213     nLen = (lp->lp_l_end - lp->lp_l_start) / lp->lp_l_inc + 1;
   3214     nCOS = (lp->lp_cos_end - lp->lp_cos_start) / 1 + 1;
   3215     SOC_PBMP_COUNT(lp->lp_pbm, nPort);
   3216 
   3217     if (lp == &lw->lw_lp_ext ||
   3218         (lp == &lw->lw_lp_sg_dma &&
   3219          (lb_is_xgs_fabric(unit) || SOC_IS_XGS3_SWITCH(unit)))) {
   3220         assert(nPort % 2 == 0);
   3221         nPort /= 2;
   3222     }
   3223 
   3224     if (SOC_IS_XGS_SWITCH(unit) &&
   3225         ((lp->lp_speed == LB_SPEED_100FD) ||
   3226          (SOC_IS_RAPTOR(unit)) ||
   3227          (lp->lp_speed == LB_SPEED_10FD))) {
   3228         int ppce = 0; 
   3229         int lene = lp->lp_l_end;
   3230 
   3231         BCM_IF_ERROR_RETURN(bcm_cosq_config_get(unit, &num_cos));
   3232         num_ports = NUM_ALL_PORT(unit);
   3233         SOC_IF_ERROR_RETURN(lb_ppce_initval(unit, &lene, &ppce));
   3234  
   3235         if (lp->lp_l_end > lene) {
   3236             test_error(unit,
   3237                    "Packet length (%d) too Large. Try (%d)\n"
   3238                    "\twith current configuration of %d COS, %d ports.\n",
   3239                    lp->lp_l_end, lene, num_cos, num_ports);
   3240             return (-1);
   3241         }        
   3242         if ((lp->lp_ppc_end > ppce) &&
   3243             ((lp->lp_speed == LB_SPEED_100FD) ||
   3244              (lp->lp_speed == LB_SPEED_10FD))) {
   3245             test_error(unit,
   3246                    "Too many packets per chain (%d) for maximum length: %d\n"
   3247                    "\twith current configuration of %d COS, %d ports.\n",
   3248                    lp->lp_ppc_end, lp->lp_l_end, num_cos, num_ports);
   3249             return (-1);
   3250         }        
   3251     }
   3252 
   3253     nChain = 0;
   3254 
   3255     if (lp->lp_sg) {
   3256         int ppc, dpp, dpp_rx;
   3257         for (ppc = lp->lp_ppc_start; ppc <= lp->lp_ppc_end;
   3258              ppc += lp->lp_ppc_inc) {
   3259             for (dpp = lp->lp_dpp_start; dpp <= lp->lp_dpp_end;
   3260                  dpp += lp->lp_dpp_inc) {
   3261                 for (dpp_rx = lp->lp_dpp_start; dpp_rx <= lp->lp_dpp_end;
   3262                      dpp_rx += lp->lp_dpp_inc) {
   3263                     nChain += ppc;      /* Tx and Rx loop over these */
   3264                 }
   3265             }
   3266         }
   3267         nChain *= lp->lp_sg ? 4 : 1;    /* For alignment */
   3268 
   3269         if(soc_feature(unit, soc_feature_cmicx)) {
   3270             nChanConf = CMICX_CHAN_CONFIG_COUNT;  /* For DMA channel combinations */
   3271         } else {
   3272         nChanConf = CHAN_CONFIG_COUNT;  /* For DMA channel combinations */
   3273         }
   3274     } else {
   3275         for (i = lp->lp_c_start; i <= lp->lp_c_end; i += lp->lp_c_inc) {
   3276             nChain += i;
   3277         }
   3278     }
   3279 
   3280 
   3281     lw->lw_tx_total = nLen * nChain * nCOS * nPort * lp->lp_count * 
   3282         nChanConf;
   3283     test_msg("LB: total %d pkt (%d len "
   3284              "* %d chain * %d COS * %d port * %d count * %d chan)\n",
   3285              lw->lw_tx_total,
   3286              nLen, nChain, nCOS, nPort, lp->lp_count, nChanConf);
   3287 
   3288     return(0);
   3289 }
   3290 
   3291 
   3292 
   3293 int
   3294 lb_dma_init_parse(int unit, args_t* a)
   3295 /*
   3296  * Function:    lb_dma_init_parse
   3297  * Purpose:     Initialize DMA loopback test via parsing args.
   3298  * Parameters:  unit - unit number.
   3299  *              a - pointer to arguments.
   3300  *              p - pointer passed to test function.
   3301  * Returns:     0 for success, -1 for failed.
   3302  */
   3303 {
   3304     loopback_test_t             *lw = &lb_work[unit];
   3305     loopback_testdata_t         *lp = &lw->lw_lp_dma;
   3306     parse_table_t       pt;
   3307 
   3308     bcm_l2_addr_t_init(&lw->lw_arl_src, lb_mac_src, 1);
   3309     bcm_l2_addr_t_init(&lw->lw_arl_dst, lb_mac_dst, 1);
   3310 
   3311     parse_table_init(unit, &pt);
   3312     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   3313                     &lp->lp_pattern,NULL);
   3314     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL, 0,
   3315                     &lp->lp_pattern_inc,NULL);
   3316     parse_table_add(&pt, "LengthStart", PQ_INT|PQ_DFL,  0,
   3317                     &lp->lp_l_start,NULL);
   3318     parse_table_add(&pt, "LengthEnd",   PQ_INT|PQ_DFL,  0,
   3319                     &lp->lp_l_end,      NULL);
   3320     parse_table_add(&pt, "LengthIncrement",PQ_INT|PQ_DFL, 0,
   3321                     &lp->lp_l_inc,      NULL);
   3322     parse_table_add(&pt, "CHainStart",  PQ_INT|PQ_DFL,  0,
   3323                     &lp->lp_c_start,NULL);
   3324     parse_table_add(&pt, "CHainEnd",    PQ_INT|PQ_DFL,  0,
   3325                     &lp->lp_c_end,      NULL);
   3326     parse_table_add(&pt, "CHainIncrement",PQ_INT|PQ_DFL, 0,
   3327                     &lp->lp_c_inc,      NULL);
   3328     parse_table_add(&pt, "COSStart",    PQ_INT|PQ_DFL,  0,
   3329                     &lp->lp_cos_start,NULL);
   3330     parse_table_add(&pt, "COSEnd",      PQ_INT|PQ_DFL,  0,
   3331                     &lp->lp_cos_end,NULL);
   3332     parse_table_add(&pt, "Count",       PQ_INT|PQ_DFL,  0,
   3333                     &lp->lp_count,      NULL);
   3334     parse_table_add(&pt, "CheckData",   PQ_BOOL|PQ_DFL, 0,
   3335                     &lp->lp_check_data,NULL);
   3336 
   3337     lb_setup(unit, lw);
   3338 
   3339     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   3340         test_error(unit,
   3341                    "%s: Invalid option: %s\n",
   3342                    ARG_CMD(a),
   3343                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   3344         parse_arg_eq_done(&pt);
   3345         return(-1);
   3346     }
   3347     parse_arg_eq_done(&pt);
   3348 
   3349 return 0;
   3350 }
   3351 
   3352 
   3353 int
   3354 lb_dma_common_init(int unit,
   3355                    loopback_test_t  *lw,
   3356                    loopback_testdata_t *lp)
   3357 {
   3358     int rv = 0;
   3359     dma_chan_t          c, chan;
   3360 
   3361     if(soc_feature(unit, soc_feature_cmicx)) {
   3362         chan = CMICX_N_DMA_CHAN;
   3363     } else {
   3364         chan = N_DMA_CHAN;
   3365     }
   3366 
   3367     SOC_PBMP_CLEAR(lp->lp_pbm);
   3368     SOC_PBMP_PORT_ADD(lp->lp_pbm, CMIC_PORT(unit));
   3369     lp->lp_rx_port = CMIC_PORT(unit);
   3370 
   3371     /* Packets Per Chain == DCB Per chain for non-S/G */
   3372 
   3373     lp->lp_ppc_start = lp->lp_c_start;
   3374     lp->lp_ppc_end   = lp->lp_c_end;
   3375     lp->lp_ppc_inc   = lp->lp_c_inc;
   3376 
   3377     lp->lp_sg = FALSE;
   3378 
   3379     if ((rv = lb_check_parms(lw, lp, lp->lp_pbm)) < 0) {
   3380         return(rv);
   3381     }
   3382 
   3383     /* Perform common loopback initialization */
   3384 
   3385     if (lb_init(unit, lw, lp, FALSE)) {
   3386         return(-1);
   3387     }
   3388 
   3389     /* Set up MAC addresses (currently constant) */
   3390 
   3391     ENET_SET_MACADDR(lw->lw_mac_src, lb_mac_src);
   3392     ENET_SET_MACADDR(lw->lw_mac_dst, lb_mac_dst);
   3393 
   3394     /*
   3395      * Deconfigure all DMA channels.
   3396      * Doing this aborts any DMAs that may be left over.
   3397      */
   3398     for (c = 0; c < chan; c++) {
   3399         LOG_INFO(BSL_LS_APPL_TESTS,
   3400                  (BSL_META_U(unit,
   3401                              "lb_dma_init: Deconfiguring channel %d\n"), c));
   3402         if (soc_dma_chan_config(unit, c, DV_NONE, 0)) {
   3403             rv = -1;
   3404         }
   3405     }
   3406 
   3407     if (rv) {
   3408         lb_done(lw);
   3409     }
   3410     return rv;
   3411 }
   3412 
   3413 int
   3414 lb_dma_init(int unit, args_t *a, void **p)
   3415 /*
   3416  * Function:    lb_dma_init
   3417  * Purpose:     Initialize DMA loopback test.
   3418  * Parameters:  unit - unit number.
   3419  *              a - pointer to arguments.
   3420  *              p - pointer passed to test function.
   3421  * Returns:     0 for success, -1 for failed.
   3422  */
   3423 {
   3424     loopback_test_t             *lw = &lb_work[unit];
   3425     loopback_testdata_t         *lp = &lw->lw_lp_dma;
   3426     int                 rv = 0;
   3427     
   3428     /* Continuous DMA mode not supported, skip test */
   3429     if (soc_feature(unit, soc_feature_continuous_dma) &&
   3430         soc_property_get(unit, spn_PDMA_CONTINUOUS_MODE_ENABLE, 0)) {
   3431         test_msg("Unit %d : Continuous DMA mode not supported, "
   3432                   "skipping test\n", unit);
   3433         /* return UNAVAIL, upper level test infra checks for
   3434          * SOC_E_UNAVAIL to skip test */
   3435         return -16;
   3436     }
   3437 
   3438     if ((rv = lb_dma_init_parse(unit, a)) < 0) {
   3439         return rv;
   3440     }
   3441     rv = lb_dma_common_init(unit, lw, lp);
   3442     *p = lw;                            /* Pass back cookie */
   3443     if (rv < 0) {
   3444         return rv;
   3445     }
   3446 #ifdef BCM_XGS3_SWITCH_SUPPORT
   3447     if (!SOC_IS_SHADOW(unit) && soc_feature(unit, soc_feature_l2_user_table)) {
   3448         bcm_l2_cache_addr_t l2_cache_addr;
   3449         int dmod;
   3450         int rv;
   3451 
   3452         BCM_IF_ERROR_RETURN(bcm_stk_my_modid_get(unit, &dmod));
   3453 
   3454         bcm_l2_cache_addr_t_init(&l2_cache_addr);
   3455         l2_cache_addr.flags = BCM_L2_CACHE_CPU;
   3456         l2_cache_addr.dest_modid = dmod;
   3457         l2_cache_addr.dest_port = CMIC_PORT(unit);
   3458         /*
   3459          * Valid index in the my station tcam  will be mostly 
   3460          * 4 or 8 incase of emulator.So hardcoding the index to 3 as by
   3461          * default we use two index.
   3462          */
   3463         if (SAL_BOOT_QUICKTURN) {
   3464             l2_index = 3; 
   3465         }
   3466         if ((rv = bcm_l2_cache_set(unit, l2_index, &l2_cache_addr,
   3467                                    &l2_index)) < 0) {
   3468             test_error(lw->lw_unit,
   3469                        "Failed to configure L2 User Entry Table %s\n",
   3470                        bcm_errmsg(rv));
   3471             return(rv);
   3472         }
   3473     }
   3474 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   3475 
   3476     return rv;
   3477 }
   3478 
   3479 
   3480 int lb_dma_testapi_init(int unit,
   3481                         uint32 pattern,
   3482                         uint32 patternIncrement,
   3483                         int startLength,
   3484                         int endLength,
   3485                         int lengthIncrement,
   3486                         int chainStart,
   3487                         int chainEnd,
   3488                         int chainIncrement,
   3489                         int cosStart,
   3490                         int cosEnd,
   3491                         int countPackets,
   3492                         int checkData)
   3493 /*
   3494  * Function:    lb_dma_testapi_init
   3495  * Purpose:     Initialize DMA loopback test API call.
   3496  * Parameters:  unit - unit number.
   3497  *              pattern
   3498  *              patternIncrement
   3499  *              startLength
   3500  *              endLength
   3501  *              lengthIncrement
   3502  *              chainStart
   3503  *              chainEnd
   3504  *              chainIncrement
   3505  *              cosStart
   3506  *              cosEnd
   3507  *              countPackets
   3508  *              checkData
   3509  * Returns:     0 for success, -1 for failed.
   3510  */
   3511 {
   3512 
   3513     loopback_test_t             *lw = &lb_work[unit];
   3514     loopback_testdata_t         *lp = &lw->lw_lp_dma;
   3515 
   3516     lb_setup(unit, lw);
   3517     
   3518     lp->lp_pattern = pattern;
   3519     lp->lp_pattern_inc = patternIncrement;
   3520     lp->lp_l_start = startLength;
   3521     lp->lp_l_end = endLength;
   3522     lp->lp_l_inc = lengthIncrement;
   3523     lp->lp_c_start = chainStart;
   3524     lp->lp_c_end = chainEnd;
   3525     lp->lp_c_inc = chainIncrement;
   3526 
   3527     return lb_dma_common_init(unit, lw, lp);
   3528 }
   3529                     
   3530 
   3531 
   3532 int
   3533 lb_dma_done(int unit, void *pa)
   3534 /*
   3535  * Function:    lb_dma_done
   3536  * Purpose:     Clean up after DMA loopback test.
   3537  * Parameters:  unit - unit number.
   3538  * Returns:     0 for success, -1 for failed.
   3539  */
   3540 {
   3541     COMPILER_REFERENCE(pa);
   3542 
   3543     /* De-configure channels */
   3544     lb_done(&lb_work[unit]);
   3545 #if defined(BCM_ESW_SUPPORT)
   3546 	
   3547     if (SOC_IS_SHADOW(unit)) {
   3548         port_tab_entry_t ptab;
   3549         SOC_IF_ERROR_RETURN
   3550             (soc_reg_field32_modify(unit, EPC_LINK_BMAPr, REG_PORT_ANY,
   3551                                     PORT_BITMAPf, 0x1ffff));
   3552         /* Restore VLAN checks to default */
   3553         SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm,
   3554                         MEM_BLOCK_ANY, 0, &ptab));
   3555         if (soc_mem_field_valid(unit, PORT_TABm, DISABLE_VLAN_CHECKSf)) {
   3556             soc_PORT_TABm_field32_set(unit, &ptab, DISABLE_VLAN_CHECKSf, 0);
   3557         }
   3558         SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
   3559                             0, &ptab));
   3560         /* Thdi bypass is restored */
   3561         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, THDI_BYPASSr,
   3562                         REG_PORT_ANY, INPUT_THRESHOLD_BYPASSf, 0));
   3563     }
   3564 #endif
   3565     return(0);
   3566 }
   3567 
   3568 int
   3569 lb_dma_testapi_done(int unit)
   3570 /*
   3571  * Function:    lb_dma_done
   3572  * Purpose:     Clean up after DMA loopback test API call.
   3573  * Parameters:  unit - unit number.
   3574  * Returns:     0 for success, -1 for failed.
   3575  */
   3576 {
   3577     lb_done(&lb_work[unit]);
   3578     return 0;
   3579 }
   3580 
   3581 int
   3582 lb_mac_init(int unit, args_t *a, void **pa)
   3583 /*
   3584  * Function:    lb_mac_init
   3585  * Purpose:     Initialize MAC loopback test.
   3586  * Parameters:  unit - unit number.
   3587  * Returns:     0 for success, -1 for failed.
   3588  */
   3589 {
   3590   
   3591     loopback_test_t     *lw = &lb_work[unit];
   3592     loopback_testdata_t *lp = &lw->lw_lp_mac;
   3593     soc_port_t          p;
   3594     parse_table_t       pt;
   3595     int                 rv;
   3596     pbmp_t              temp1_pbmp, temp2_pbmp;
   3597     uint16              dev_id;
   3598     uint8               rev_id;
   3599     uint8               flag = 0;
   3600     bcm_port_abil_t     ability;
   3601 
   3602     soc_cm_get_id(unit, &dev_id, &rev_id);	
   3603                                                                               
   3604     bcm_l2_addr_t_init(&lw->lw_arl_src, lb_mac_src, 1);
   3605     bcm_l2_addr_t_init(&lw->lw_arl_dst, lb_mac_dst, 1);
   3606 
   3607     parse_table_init(unit, &pt);
   3608     parse_table_add(&pt, "PortBitMap",  PQ_PBMP|PQ_DFL, 0,
   3609                     &lp->lp_pbm,        NULL);
   3610     if (lb_is_xgs_fabric(unit)) {
   3611         parse_table_add(&pt, "DestMOD",     PQ_DFL|PQ_INT,  0,
   3612                         &lp->lp_d_mod,      NULL);
   3613         parse_table_add(&pt, "DestPORT",    PQ_DFL|PQ_PORT, 0,
   3614                         &lp->lp_d_port,     NULL);
   3615         parse_table_add(&pt, "OpCode",    PQ_DFL|PQ_INT, 0,
   3616                         &lp->lp_opcode,     NULL);
   3617     } else {
   3618         parse_table_add(&pt, "UntagBitMap",     PQ_PBMP|PQ_DFL, 0,
   3619                         &lp->lp_ubm,    NULL);
   3620     }
   3621     parse_table_add(&pt, "Speed",       PQ_MULTI|PQ_DFL,0,
   3622                     &lp->lp_speed,      lb_parse_speed);
   3623     parse_table_add(&pt, "SourceMac",   PQ_DFL|PQ_MAC,  0,
   3624                     &lp->lp_mac_src,    NULL);
   3625     parse_table_add(&pt, "SourceMacInc",PQ_DFL|PQ_INT,  0,
   3626                     &lp->lp_mac_src_inc,NULL);
   3627     parse_table_add(&pt, "DestMac",     PQ_DFL|PQ_MAC,  0,
   3628                     &lp->lp_mac_dst,    NULL);
   3629     parse_table_add(&pt, "DestMacInc",  PQ_DFL|PQ_INT,  0,
   3630                     &lp->lp_mac_dst_inc,NULL);
   3631 
   3632     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   3633                     &lp->lp_pattern,NULL);
   3634     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL, 0,
   3635                     &lp->lp_pattern_inc,NULL);
   3636     parse_table_add(&pt, "VLantag",     PQ_INT|PQ_DFL,  0,
   3637                     &lp->lp_vlan,       NULL);
   3638     parse_table_add(&pt, "LengthStart", PQ_INT|PQ_DFL,  0,
   3639                     &lp->lp_l_start,NULL);
   3640     parse_table_add(&pt, "LengthEnd",   PQ_INT|PQ_DFL,  0,
   3641                     &lp->lp_l_end,      NULL);
   3642     parse_table_add(&pt, "LengthIncrement",PQ_INT|PQ_DFL, 0,
   3643                     &lp->lp_l_inc,      NULL);
   3644     parse_table_add(&pt, "COSStart",    PQ_INT|PQ_DFL,  0,
   3645                     &lp->lp_cos_start,NULL);
   3646     parse_table_add(&pt, "COSEnd",      PQ_INT|PQ_DFL,  0,
   3647                     &lp->lp_cos_end,NULL);
   3648     parse_table_add(&pt, "CRC",         PQ_MULTI|PQ_DFL, 0,
   3649                     &lp->lp_crc_mode, crc_mode);
   3650     parse_table_add(&pt, "PacketsPerChain",PQ_INT|PQ_DFL, 0,
   3651                     &lp->lp_c_start,    NULL);
   3652     parse_table_add(&pt, "Count",       PQ_INT|PQ_DFL,  0,
   3653                     &lp->lp_count,      NULL);
   3654     parse_table_add(&pt, "CheckData",   PQ_BOOL|PQ_DFL, 0,
   3655                     &lp->lp_check_data,NULL);
   3656     parse_table_add(&pt, "CheckCrc",    PQ_BOOL|PQ_DFL, 0,
   3657                     &lp->lp_check_crc,NULL);
   3658 
   3659     lb_setup(unit, lw);
   3660 
   3661     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   3662         test_error(unit,
   3663                    "%s: Invalid option: %s\n",
   3664                    ARG_CMD(a),
   3665                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   3666         parse_arg_eq_done(&pt);
   3667         return(-1);
   3668     }
   3669     parse_arg_eq_done(&pt);
   3670 
   3671     /* Packets Per Chain == DCB Per chain for non-S/G */
   3672 
   3673     lp->lp_ppc_start = lp->lp_c_start;
   3674     lp->lp_ppc_end   = lp->lp_c_end = lp->lp_c_start;
   3675     lp->lp_ppc_inc   = lp->lp_c_inc;
   3676 
   3677     lp->lp_sg = FALSE;
   3678 
   3679     if (lb_check_parms(lw, lp, PBMP_PORT_ALL(unit))) {
   3680         return(-1);
   3681     }
   3682 
   3683 
   3684     /* Perform common loopback initialization */
   3685 
   3686     if (lb_init(unit, lw, lp, FALSE)) {
   3687         return(-1);
   3688     }
   3689     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   3690         if (!SOC_IS_SHADOW(unit)) {
   3691 	    if ((rv = bcm_vlan_create(unit, lp->lp_vlan)) < 0 &&
   3692 	        rv != BCM_E_EXISTS) {
   3693 	        test_error(unit,
   3694 	                  "Could not create VLAN %d: %s\n",
   3695 	                   lp->lp_vlan, bcm_errmsg(rv));
   3696 	        return (-1);
   3697             }
   3698         }
   3699     }    
   3700     SOC_PBMP_CLEAR(temp1_pbmp);
   3701     SOC_PBMP_CLEAR(temp2_pbmp);
   3702     SOC_PBMP_OR(temp1_pbmp, PBMP_PORT_ALL(unit));
   3703     SOC_PBMP_OR(temp1_pbmp, PBMP_CMIC(unit));
   3704     if (SOC_IS_XGS3_SWITCH(unit)) {
   3705         SOC_PBMP_ASSIGN(temp2_pbmp, PBMP_PORT_ALL(unit));
   3706     }
   3707     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   3708         if (!SOC_IS_SHADOW(unit)) {
   3709 	    if ((rv = bcm_vlan_port_add(unit, lp->lp_vlan,
   3710 	                                temp1_pbmp, temp2_pbmp)) < 0) {
   3711 	        test_error(unit,
   3712 	                   "Could not add all ports to VLAN %d: %s\n",
   3713 	                   lp->lp_vlan, bcm_errmsg(rv));
   3714 	        return (-1);
   3715             }
   3716         }
   3717     }
   3718 
   3719     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   3720         /* Set the spanning tree group to 1 since port state is forwarding */
   3721         if (!SOC_IS_SHADOW(unit)) {
   3722             rv = bcm_vlan_stg_set(unit, lp->lp_vlan, 1);
   3723             if (rv < 0 && rv != BCM_E_UNAVAIL) {
   3724                 test_error(unit, "Could not set vlan %d stg 1: %s\n",
   3725                            lp->lp_vlan, bcm_errmsg(rv));
   3726                 return(-1);
   3727             }
   3728         }
   3729     }
   3730     /*
   3731      * Be sure all DMA channels ignore port-bit-map modification.
   3732      *|
   3733 
   3734     if (((rv = soc_dma_chan_config(unit, 0, DV_TX, 
   3735                                    SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) < 0) ||
   3736         ((rv = soc_dma_chan_config(unit, 1, DV_RX, 
   3737                                    SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) < 0)) {
   3738         test_error(unit,
   3739                    "soc_dma_chan_config: Failed: %s\n",
   3740                    soc_errmsg(rv));
   3741         lb_done(lw);
   3742         return(-1);
   3743     } */
   3744 #ifdef BCM_CMICM_SUPPORT
   3745     /* Assign all COS to this channel
   3746      * Though this is added for CMICm, 
   3747      * it should be OK if we do this for CMICe as well */
   3748     if(soc_feature(unit, soc_feature_cmicm)) {
   3749         LOG_INFO(BSL_LS_APPL_TESTS,
   3750                  (BSL_META_U(unit,
   3751                              "Assign all COS to channel: 1\n")));
   3752         SOC_IF_ERROR_RETURN(
   3753             bcm_rx_queue_channel_set(unit, -1, 1));
   3754 
   3755 #if defined(BCM_KATANA2_SUPPORT)
   3756             if(SOC_IS_KATANA2(unit)) {
   3757                 uint32 reg_val, reg_addr;
   3758 
   3759                 /* Including CPU L0 bitmap to support CMIC backpressure */
   3760                 reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, 1);
   3761                 reg_val = soc_pci_read(unit, reg_addr);
   3762                 reg_val |= (1 << 16);
   3763                 soc_pci_write(unit, reg_addr, reg_val);
   3764             }
   3765 #endif
   3766 
   3767     }
   3768 #endif
   3769 #ifdef BCM_CMICX_SUPPORT
   3770     /* Assign all COS to this channel */
   3771     if(soc_feature(unit, soc_feature_cmicx)) {
   3772         LOG_INFO(BSL_LS_APPL_TESTS,
   3773                  (BSL_META_U(unit,
   3774                              "Assign all COS to channel: 1\n")));
   3775         SOC_IF_ERROR_RETURN(
   3776             bcm_rx_queue_channel_set(unit, -1, 1));
   3777     }
   3778 #endif
   3779 
   3780     /* Before we set up the ports, rip out the stack port(s) */
   3781     if (!SOC_IS_SHADOW(unit)) {
   3782         if ((rv = lb_stack_check(unit)) < 0) {
   3783             test_error(unit,
   3784                        "Unable to shut down stacking mode: %s\n",
   3785                        bcm_errmsg(rv));
   3786             lb_done(lw);                    /* In case they continue */
   3787             return(-1);
   3788         }
   3789     }
   3790 
   3791     PBMP_ITER(lp->lp_pbm, p) {
   3792         if(dev_id == BCM56443_DEVICE_ID) {  
   3793             ability = 0;
   3794             flag = 0;
   3795         }
   3796         /*
   3797          * Set loopback mode before speed, since it may affect
   3798          * the allowable speeds.
   3799          */
   3800         if (IS_HG_PORT(unit, p)) {
   3801             /*
   3802              *      Disabling pause reuiqred on IPIC/XPORT
   3803              *      HG ports. Should already be disabled on
   3804              *      GE (stack) ports during init.
   3805              */
   3806             bcm_port_pause_set(unit, p, FALSE, FALSE);
   3807         }
   3808         if(dev_id == BCM56443_DEVICE_ID) {
   3809             if ( bcm_port_ability_get(unit, p, &ability) != BCM_E_NONE) {
   3810                 test_error(unit, "===========> ERROR : fail to get ability\n");
   3811                 return -1;
   3812             }
   3813             switch(lp->lp_speed) {
   3814                 case 1:
   3815                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_10MB))) {
   3816                         flag = 1;
   3817                     }
   3818                     break;
   3819                 case 2:
   3820                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_100MB))) {
   3821                         flag = 1;
   3822                     }
   3823                     break;
   3824                 case 3:
   3825                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_1000MB))) {
   3826                         flag = 1;
   3827                     }
   3828                     break;
   3829                 case 4:
   3830                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_2500MB))) {
   3831                         flag = 1;
   3832                     }
   3833                     break;
   3834                 default :
   3835                     flag = 0;
   3836                     break;
   3837 
   3838             }
   3839             if (flag)
   3840                 continue;
   3841         }
   3842 
   3843         if ((rv = lb_setup_port(unit, p, lp->lp_speed, FALSE)) < 0) {
   3844             test_error(unit,
   3845                        "Port %s: Port setup failed: %s\n",
   3846                        SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   3847             lb_done(lw);                        /* In case they continue */
   3848             return(-1);
   3849         }
   3850 
   3851         if ((rv = bcm_port_loopback_set(unit, p, BCM_PORT_LOOPBACK_MAC)) < 0) {
   3852             test_error(unit,
   3853                        "Port %s: Failed to set MAC loopback: %s\n",
   3854                        SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   3855             lb_done(lw);                        /* In case they continue */
   3856             return(-1);
   3857         }
   3858     }
   3859 
   3860 #ifdef BCM_XGS12_FABRIC_SUPPORT
   3861     if (SOC_IS_XGS12_FABRIC(unit)) {
   3862         pbmp_t          pbm;
   3863 
   3864         /*
   3865          * If there is an external cable looped back, 5670 will
   3866          * receive packets on ports that may not be in the test
   3867          * and these packets will go to the CPU and interfere.
   3868          */
   3869 
   3870         SOC_PBMP_ASSIGN(pbm, lp->lp_pbm);
   3871         SOC_PBMP_XOR(pbm, PBMP_PORT_ALL(unit));
   3872         PBMP_ITER(pbm, p) {
   3873             if ((rv = bcm_port_enable_set(unit, p, FALSE)) < 0) {
   3874                 test_error(unit,
   3875                            "Port %s: Failed to set MAC enable: %s\n",
   3876                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   3877                 lb_done(lw);
   3878                 return(-1);
   3879             }
   3880         }
   3881     }
   3882 #endif
   3883     
   3884     *pa = lw;
   3885 
   3886     return(0);
   3887 }
   3888 
   3889 int
   3890 lb_mac_done(int unit, void *pa)
   3891 /*
   3892  * Function:    lb_mac_done
   3893  * Purpose:     Clean up after MAC loopback test.
   3894  * Parameters:  unit - unit number.
   3895  * Returns:     0 for success, -1 for failed.
   3896  */
   3897 {
   3898     soc_port_t  p;
   3899 
   3900     if (pa) {
   3901         loopback_testdata_t *lp = ((loopback_test_t *)pa)->lw_lp;
   3902 
   3903         /* Clear MAC loopback - Only if pa is set */
   3904 
   3905         PBMP_ITER(lp->lp_pbm, p) {
   3906             int         rv;
   3907 
   3908             rv = bcm_port_loopback_set(unit, p, BCM_PORT_LOOPBACK_NONE);
   3909             if (rv != BCM_E_NONE) {
   3910                 test_error(unit,
   3911                            "Port %s: Failed to reset MAC loopback: %s\n",
   3912                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   3913             }
   3914             if (IS_HG_PORT(unit, p)) {
   3915                 bcm_port_pause_set(unit, p, TRUE, TRUE);
   3916             }
   3917         }
   3918     }
   3919 
   3920     lb_done(&lb_work[unit]);
   3921 
   3922     return(0);
   3923 }
   3924 
   3925 
   3926 /*ARGSUSED*/
   3927 int
   3928 lb_mac_test(int unit, args_t *a, void *pa)
   3929 /*
   3930  * Function:    lb_mac_test
   3931  * Purpose:     Perform MAC loopback tests.
   3932  * Parameters:  unit - unit #
   3933  *              a - arguments (Not used, assumed parse by lb_mac_init).
   3934  * Returns:
   3935  * NOTE:  Reference: BCM569X Errata Sheet 
   3936  *       On 5695A0, port 5 falsely trigger flow-control mechanisms
   3937  *       when the CPU has transmitted packets.  
   3938  */
   3939 {
   3940     loopback_test_t     *lw = (loopback_test_t *)pa;
   3941     loopback_testdata_t *lp = lw->lw_lp;
   3942     int                  port, rv;
   3943     pbmp_t               pbm, tpbm;
   3944     uint16               dev_id;
   3945     uint8                rev_id;
   3946     uint8                flag = 0;
   3947     bcm_port_abil_t      ability;
   3948 
   3949     soc_cm_get_id(unit, &dev_id, &rev_id);	
   3950     
   3951     COMPILER_REFERENCE(a);
   3952 
   3953 
   3954     LOG_INFO(BSL_LS_APPL_TESTS,
   3955              (BSL_META_U(unit,
   3956                          "lb_mac_test: unit %d starting ....\n"), lw->lw_unit));
   3957 
   3958 #ifdef BCM_SHADOW_SUPPORT
   3959     if (SOC_IS_SHADOW(unit)) {
   3960         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, THDI_BYPASSr,
   3961                             REG_PORT_ANY, INPUT_THRESHOLD_BYPASSf, 1));
   3962     }
   3963 #endif /* BCM_SHADOW_SUPPORT */
   3964 
   3965     lb_stats_init(lw);
   3966 
   3967     SOC_PBMP_ASSIGN(pbm, lp->lp_pbm);
   3968     SOC_PBMP_ASSIGN(tpbm, lp->lp_pbm);
   3969     SOC_PBMP_AND(tpbm, PBMP_FE_ALL(unit));
   3970 
   3971     PBMP_ITER(pbm, port) {
   3972         if(dev_id == BCM56443_DEVICE_ID) {  
   3973             ability = 0;
   3974             flag = 0;
   3975         }
   3976         /*
   3977          * Get our current MAC address for this port and be sure the
   3978          * SOC will route packets to the CPU. 
   3979          */
   3980 #ifdef BCM_SHADOW_SUPPORT
   3981         if (SOC_IS_SHADOW(unit)) {
   3982             if (lb_setup_static_path(lw, unit, CMIC_PORT(unit), port)) {
   3983                 return(-1);
   3984             }
   3985 
   3986         } else
   3987 #endif /* BCM_SHADOW_SUPPORT */
   3988         {
   3989             if (lb_setup_arl(lw, unit, CMIC_PORT(unit), port)) {
   3990                 return(-1);
   3991             }
   3992         }
   3993 
   3994         lw->lw_tx_init_chn = 0;         /* Start off clean */
   3995         lw->lw_tx_init_len = 0;         /* Start off clean */
   3996 
   3997         if(soc_feature(unit, soc_feature_cmicx)) {
   3998             /* We send 2 dcbs per packet as the header is no longer part of dcb */
   3999             lw->lw_tx_dcb_factor = 2;
   4000         } else {
   4001             lw->lw_tx_dcb_factor = 1;
   4002         }
   4003 
   4004         if(dev_id == BCM56443_DEVICE_ID) {
   4005             if ( bcm_port_ability_get(unit, port, &ability) != BCM_E_NONE) {
   4006                 test_error(unit, "===========> ERROR : fail to get ability\n");
   4007                 return -1;
   4008             }
   4009             switch(lp->lp_speed) {
   4010                 case 1:
   4011                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_10MB))) {
   4012                         flag = 1;
   4013                     }
   4014                     break;
   4015                 case 2:
   4016                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_100MB))) {
   4017                         flag = 1;
   4018                     }
   4019                     break;
   4020                 case 3:
   4021                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_1000MB))) {
   4022                         flag = 1;
   4023                     }
   4024                     break;
   4025                 case 4:
   4026                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_2500MB))) {
   4027                         flag = 1;
   4028                     }
   4029                     break;
   4030                 default :
   4031                     flag = 0;
   4032                     break;
   4033 
   4034             }
   4035             if (flag)
   4036                 continue;
   4037         }
   4038         lp->lp_tx_port = port;
   4039         lp->lp_rx_port = port;
   4040 
   4041 
   4042         rv = lb_do_txrx(lw);
   4043 
   4044         if (!IS_ST_PORT(unit, port)) {
   4045             lb_cleanup_arl(lw, unit);
   4046         }
   4047         if (rv < 0) {
   4048             pbmp_t  portpbm;
   4049             BCM_PBMP_CLEAR(portpbm);
   4050             BCM_PBMP_PORT_ADD(portpbm, port);
   4051 #if defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT)
   4052             if (SOC_IS_DFE(unit) || SOC_IS_DPP(unit)) {
   4053                 do_show_dpp_counters(unit, INVALIDr, portpbm,
   4054                                SHOW_CTR_CHANGED | SHOW_CTR_SAME | SHOW_CTR_NZ);
   4055             } else 
   4056 #elif defined (BCM_ESW_SUPPORT) 
   4057             {
   4058                 do_show_counters(unit, INVALIDr, portpbm,
   4059                                SHOW_CTR_CHANGED | SHOW_CTR_SAME | SHOW_CTR_NZ);
   4060             }
   4061 #endif
   4062             return -1;
   4063         }
   4064     }
   4065 
   4066     lb_stats_done(lw);
   4067 #ifdef BCM_SHADOW_SUPPORT
   4068     if (SOC_IS_SHADOW(unit)) {
   4069         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, THDI_BYPASSr,
   4070                             REG_PORT_ANY, INPUT_THRESHOLD_BYPASSf, 0));
   4071     }
   4072 #endif /* BCM_SHADOW_SUPPORT */
   4073 
   4074     return(0);
   4075 }
   4076 
   4077 int
   4078 lb_mii_init(int unit, args_t *a, void **pa)
   4079 /*
   4080  * Function:    lb_mii_init
   4081  * Purpose:     Initialize DMA-mii loopback test.
   4082  * Parameters:  unit - unit number.
   4083  * Returns:     0 for success, -1 for failed.
   4084  */
   4085 {
   4086     loopback_test_t             *lw = &lb_work[unit];
   4087     loopback_testdata_t         *lp = &lw->lw_lp_phy;
   4088     soc_port_t          p;
   4089     parse_table_t       pt;
   4090     int                 rv;
   4091     pbmp_t              temp1_pbmp, temp2_pbmp, phy_pbmp;
   4092     int                 rcpu;
   4093     uint16              dev_id;
   4094     uint8               rev_id;
   4095     uint8               flag = 0;
   4096     bcm_port_abil_t     ability;
   4097 
   4098     soc_cm_get_id(unit, &dev_id, &rev_id);	
   4099 
   4100     bcm_l2_addr_t_init(&lw->lw_arl_src, lb_mac_src, 1);
   4101     bcm_l2_addr_t_init(&lw->lw_arl_dst, lb_mac_dst, 1);
   4102 
   4103     parse_table_init(unit, &pt);
   4104     parse_table_add(&pt, "PortBitMap",  PQ_PBMP|PQ_DFL, 0,
   4105                     &lp->lp_pbm,        NULL);
   4106     parse_table_add(&pt, "ExtselfloopPBM",  PQ_PBMP|PQ_DFL, 0,
   4107                     &lp->lp_ext_self_loop_pbm,        NULL);
   4108     if (lb_is_xgs_fabric(unit)) {
   4109         parse_table_add(&pt, "DestMOD",     PQ_DFL|PQ_INT,  0,
   4110                         &lp->lp_d_mod,      NULL);
   4111         parse_table_add(&pt, "DestPORT",    PQ_DFL|PQ_PORT, 0,
   4112                         &lp->lp_d_port,     NULL);
   4113         parse_table_add(&pt, "OpCode",    PQ_DFL|PQ_INT, 0,
   4114                         &lp->lp_opcode,     NULL);
   4115     } else {
   4116         parse_table_add(&pt, "UntagBitMap",     PQ_PBMP|PQ_DFL, 0,
   4117                         &lp->lp_ubm,    NULL);
   4118     }
   4119     parse_table_add(&pt, "Speed",       PQ_MULTI|PQ_DFL,0,
   4120                     &lp->lp_speed,      lb_parse_speed);
   4121     parse_table_add(&pt, "SourceMac",   PQ_DFL|PQ_MAC,  0,
   4122                     &lp->lp_mac_src,    NULL);
   4123     parse_table_add(&pt, "SourceMacInc",PQ_DFL|PQ_INT,  0,
   4124                     &lp->lp_mac_src_inc,NULL);
   4125     parse_table_add(&pt, "DestMac",     PQ_DFL|PQ_MAC,  0,
   4126                     &lp->lp_mac_dst,    NULL);
   4127     parse_table_add(&pt, "DestMacInc",  PQ_DFL|PQ_INT,  0,
   4128                     &lp->lp_mac_dst_inc,NULL);
   4129 
   4130     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   4131                     &lp->lp_pattern,    NULL);
   4132     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL, 0,
   4133                     &lp->lp_pattern_inc,NULL);
   4134     parse_table_add(&pt, "VLantag",     PQ_INT|PQ_DFL,  0,
   4135                     &lp->lp_vlan,       NULL);
   4136     parse_table_add(&pt, "LengthStart", PQ_INT|PQ_DFL,  0,
   4137                     &lp->lp_l_start,    NULL);
   4138     parse_table_add(&pt, "LengthEnd",   PQ_INT|PQ_DFL,  0,
   4139                     &lp->lp_l_end,      NULL);
   4140     parse_table_add(&pt, "LengthIncrement",PQ_INT|PQ_DFL, 0,
   4141                     &lp->lp_l_inc,      NULL);
   4142     parse_table_add(&pt, "COSStart",    PQ_INT|PQ_DFL,  0,
   4143                     &lp->lp_cos_start,  NULL);
   4144     parse_table_add(&pt, "COSEnd",      PQ_INT|PQ_DFL,  0,
   4145                     &lp->lp_cos_end,    NULL);
   4146     parse_table_add(&pt, "CRC",         PQ_MULTI|PQ_DFL, 0,
   4147                     &lp->lp_crc_mode,   crc_mode);
   4148     parse_table_add(&pt, "PacketsPerChain",PQ_INT|PQ_DFL, 0,
   4149                     &lp->lp_c_start,    NULL);
   4150     parse_table_add(&pt, "Count",       PQ_INT|PQ_DFL,  0,
   4151                     &lp->lp_count,      NULL);
   4152     parse_table_add(&pt, "CheckData",   PQ_BOOL|PQ_DFL, 0,
   4153                     &lp->lp_check_data, NULL);
   4154     parse_table_add(&pt, "CheckCrc",    PQ_BOOL|PQ_DFL, 0,
   4155                     &lp->lp_check_crc,  NULL),
   4156 
   4157         lb_setup(unit, lw);
   4158 
   4159     lw->lw_lp = lp;
   4160 
   4161     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   4162         test_error(unit,
   4163                    "%s: Invalid option: %s\n",
   4164                    ARG_CMD(a),
   4165                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   4166         parse_arg_eq_done(&pt);
   4167         return(-1);
   4168     }
   4169     parse_arg_eq_done(&pt);
   4170 
   4171     /* Packets Per Chain == DCB Per chain for non-S/G */
   4172 
   4173     lp->lp_ppc_start = lp->lp_c_start;
   4174     lp->lp_ppc_end   = lp->lp_c_end = lp->lp_c_start;
   4175     lp->lp_ppc_inc   = lp->lp_c_inc;
   4176 
   4177     lp->lp_sg = FALSE;
   4178 
   4179     if (lb_check_parms(lw, lp, PBMP_PORT_ALL(unit))) {
   4180         return(-1);
   4181     }
   4182 
   4183     /* Perform common loopback initialization */
   4184 
   4185     if (lb_init(unit, lw, lp, FALSE)) {
   4186         return(-1);
   4187     }
   4188     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   4189 	if ((rv = bcm_vlan_create(unit, lp->lp_vlan)) < 0 &&
   4190 	    rv != BCM_E_EXISTS) {
   4191 	    test_error(unit,
   4192 	               "Could not create VLAN %d: %s\n",
   4193 	               lp->lp_vlan, bcm_errmsg(rv));
   4194 	    return (-1);
   4195         }
   4196     }    
   4197     SOC_PBMP_CLEAR(temp1_pbmp);
   4198     SOC_PBMP_CLEAR(temp2_pbmp);
   4199     SOC_PBMP_OR(temp1_pbmp, PBMP_PORT_ALL(unit));
   4200     SOC_PBMP_OR(temp1_pbmp, PBMP_CMIC(unit));
   4201     if (SOC_IS_XGS3_SWITCH(unit)) {
   4202         SOC_PBMP_ASSIGN(temp2_pbmp, PBMP_PORT_ALL(unit));
   4203     }
   4204     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   4205 
   4206 	if ((rv = bcm_vlan_port_add(unit, lp->lp_vlan,
   4207 	                            temp1_pbmp, temp2_pbmp)) < 0) {
   4208 	    test_error(unit,
   4209 	               "Could not add all ports to VLAN %d: %s\n",
   4210 	               lp->lp_vlan, bcm_errmsg(rv));
   4211 	    return (-1);
   4212         }
   4213 
   4214         rv = bcm_vlan_stg_set(unit, lp->lp_vlan, 1);
   4215         if (rv < 0 && rv != BCM_E_UNAVAIL) {
   4216             test_error(unit, "Could not set vlan %d stg 1: %s\n",
   4217                        lp->lp_vlan, bcm_errmsg(rv));
   4218             return(-1);
   4219         }
   4220     }
   4221     
   4222     /*
   4223      * Be sure all DMA channels ignore port-bit-map modification.
   4224      */
   4225 
   4226     if (((rv = soc_dma_chan_config(unit, 0, DV_TX, 
   4227                                    SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) < 0) ||
   4228         ((rv = soc_dma_chan_config(unit, 1, DV_RX, 
   4229                                    SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) < 0)) {
   4230         test_error(unit,
   4231                    "soc_dma_chan_config: Failed: %s\n",
   4232                    soc_errmsg(rv));
   4233         lb_done(lw);
   4234         return(-1);
   4235     }
   4236 #ifdef BCM_CMICM_SUPPORT
   4237     /* Assign all COS to this channel
   4238      * Though this is added for CMICm, 
   4239      * it should be OK if we do this for CMICe as well */
   4240     if(soc_feature(unit, soc_feature_cmicm)) {
   4241         LOG_INFO(BSL_LS_APPL_TESTS,
   4242                  (BSL_META_U(unit,
   4243                              "Assign all COS to channel: 1\n")));
   4244         SOC_IF_ERROR_RETURN(
   4245             bcm_rx_queue_channel_set(unit, -1, 1));
   4246 
   4247 #if defined(BCM_KATANA2_SUPPORT)
   4248             if(SOC_IS_KATANA2(unit)) {
   4249                 uint32 reg_val, reg_addr;
   4250 
   4251                 /* Including CPU L0 bitmap to support CMIC backpressure */
   4252                 reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, 1);
   4253                 reg_val = soc_pci_read(unit, reg_addr);
   4254                 reg_val |= (1 << 16);
   4255                 soc_pci_write(unit, reg_addr, reg_val);
   4256             }
   4257 #endif
   4258 
   4259     }
   4260 #endif
   4261 #ifdef BCM_CMICX_SUPPORT
   4262     /* Assign all COS to this channel */
   4263     if(soc_feature(unit, soc_feature_cmicx)) {
   4264         LOG_INFO(BSL_LS_APPL_TESTS,
   4265                  (BSL_META_U(unit,
   4266                              "Assign all COS to channel: 1\n")));
   4267         SOC_IF_ERROR_RETURN(
   4268             bcm_rx_queue_channel_set(unit, -1, 1));
   4269     }
   4270 #endif
   4271 
   4272     /* Before we set up the ports, rip out the stack port(s) */
   4273     if ((rv = lb_stack_check(unit)) < 0) {
   4274         test_error(unit,
   4275                    "Unable to shut down stacking mode: %s\n",
   4276                    bcm_errmsg(rv));
   4277         lb_done(lw);                    /* In case they continue */
   4278         return(-1);
   4279     }
   4280 
   4281     /*
   4282      * Setup the PHY loopback for the ports which are in the lp_pbm but
   4283      * are not in the lb_ext_self_loop_lpm. lb_ext_self_loop_pbm contains
   4284      * the map of the ports which have external self loopback cable connected
   4285      * to then and hence no need to put then in the PHY loopback mode.
   4286      */
   4287     SOC_PBMP_ASSIGN(phy_pbmp, lp->lp_pbm);
   4288     SOC_PBMP_NEGATE(temp1_pbmp, lp->lp_ext_self_loop_pbm);
   4289     SOC_PBMP_AND(phy_pbmp, temp1_pbmp);
   4290 
   4291     rcpu = soc_property_get(unit, spn_RCPU_PORT, -1);
   4292     PBMP_ITER(phy_pbmp, p) {
   4293         if(dev_id == BCM56443_DEVICE_ID) {  
   4294             ability = 0;
   4295             flag = 0;
   4296         }
   4297         if (rcpu !=0 && rcpu != -1 && SOC_IS_RAVEN(unit)) { 
   4298             if ((rv = bcm_port_loopback_set(unit, p,
   4299                                             BCM_PORT_LOOPBACK_PHY)) < 0) {
   4300                 test_error(unit,
   4301                            "Port %s: Failed to set PHY loopback: %s\n",
   4302                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   4303                 lb_done(lw);
   4304                 return(-1);                 /* In case they continue */
   4305             }
   4306             if ((rv = lb_setup_port(unit, p, lp->lp_speed, FALSE)) < 0) {
   4307                 test_error(unit,
   4308                            "Port %s: Port setup failed: %s\n",
   4309                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   4310                 lb_done(lw);
   4311                 return(-1);
   4312             }
   4313         } else {
   4314               if(dev_id == BCM56443_DEVICE_ID) {
   4315                   if ( bcm_port_ability_get(unit, p, &ability) != BCM_E_NONE) {
   4316                       test_error(unit,"======> ERROR : fail to get ability\n");
   4317                       return -1;
   4318                   }
   4319                   switch(lp->lp_speed) {
   4320                      case 1:
   4321                          if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_10MB))) {
   4322                              flag = 1;
   4323                          }
   4324                          break;
   4325                      case 2:
   4326                          if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_100MB))) {
   4327                              flag = 1;
   4328                          }
   4329                          break;
   4330                      case 3:
   4331                          if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_1000MB))) {
   4332                              flag = 1;
   4333                          }
   4334                          break;
   4335                      case 4:
   4336                          if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_2500MB))) {
   4337                              flag = 1;
   4338                          }
   4339                          break;
   4340                      default :
   4341                          flag = 0;
   4342                          break;
   4343 
   4344                   }
   4345                   if (flag)
   4346                       continue;
   4347              }
   4348 
   4349             if ((rv = lb_setup_port(unit, p, lp->lp_speed, FALSE)) < 0) {
   4350                 test_error(unit,
   4351                            "Port %s: Port setup failed: %s\n",
   4352                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   4353                 lb_done(lw);
   4354                 return(-1);
   4355             }
   4356             if ((rv = bcm_port_loopback_set(unit, p,
   4357                                             BCM_PORT_LOOPBACK_PHY)) < 0) {
   4358                 test_error(unit,
   4359                            "Port %s: Failed to set PHY loopback: %s\n",
   4360                            SOC_PORT_NAME(unit, p), bcm_errmsg(rv));
   4361                 lb_done(lw);
   4362                 return(-1);                 /* In case they continue */
   4363             }
   4364         }
   4365         sal_sleep(1);
   4366     }
   4367 
   4368     *pa = lw;
   4369 
   4370     return(0);
   4371 }
   4372 
   4373 int
   4374 lb_mii_done(int unit, void *pa)
   4375 /*
   4376  * Function:    lb_mii_done
   4377  * Purpose:     Clean up after DMA loopback test.
   4378  * Parameters:  unit - unit number.
   4379  * Returns:     0 for success, -1 for failed.
   4380  */
   4381 {
   4382 
   4383     lb_done(&lb_work[unit]);
   4384     return(0);
   4385 }
   4386 
   4387 int
   4388 lb_mii_test(int unit, args_t *a, void *pa)
   4389 /*
   4390  * Function:    lb_mii_test
   4391  * Purpose:     Perform phy loopback tests.
   4392  * Parameters:  unit - unit #
   4393  *              a - arguments
   4394  * Returns:     0 - success, -1 failed. 
   4395  * NOTE:  Reference: BCM569X Errata Sheet 
   4396  *       On 5695A0, port 5 falsely trigger flow-control mechanisms
   4397  *       when the CPU has transmitted packets.  
   4398  */
   4399 {
   4400     loopback_test_t     *lw = (loopback_test_t *)pa;
   4401     loopback_testdata_t *lp = lw->lw_lp;
   4402     int                  port, rv;
   4403     uint16               dev_id;
   4404     uint8                rev_id;
   4405     uint8                flag = 0;
   4406     bcm_port_abil_t      ability;
   4407 
   4408     soc_cm_get_id(unit, &dev_id, &rev_id);	
   4409     
   4410     COMPILER_REFERENCE(a);
   4411 
   4412 
   4413 #ifdef BCM_SHADOW_SUPPORT
   4414     if (SOC_IS_SHADOW(unit)) {
   4415         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, THDI_BYPASSr,
   4416                             REG_PORT_ANY, INPUT_THRESHOLD_BYPASSf, 1));
   4417     }
   4418 #endif /* BCM_SHADOW_SUPPORT */
   4419     lb_stats_init(lw);
   4420 
   4421     /* #################################################################### */
   4422     /* With below wait, tr 19 passes even if tried several times */
   4423     /* Believe it is applicable for other chips but don't want to take risk */
   4424     /* #################################################################### */
   4425     if (SOC_IS_KATANA2(unit)) {
   4426         if (lb_link_wait(unit, lp->lp_pbm) < 0) {
   4427             return(-1);
   4428         }
   4429     }
   4430 
   4431 
   4432     PBMP_ITER(lp->lp_pbm, port) {
   4433         if(dev_id == BCM56443_DEVICE_ID) {  
   4434             ability = 0;
   4435             flag = 0;
   4436         }
   4437 #ifdef BCM_SHADOW_SUPPORT
   4438         if (SOC_IS_SHADOW(unit)) {
   4439             if (lb_setup_static_path(lw, unit, CMIC_PORT(unit), port)) {
   4440                 return(-1);
   4441             }
   4442 
   4443         } else 
   4444 #endif /* BCM_SHADOW_SUPPORT */
   4445         {
   4446             if (!lb_is_xgs_fabric(unit)) {
   4447                 /*
   4448                  * Get our current MAC address for this port and be sure the
   4449                  * SOC will route packets to the CPU.
   4450                  */
   4451                 if (lb_setup_arl(lw, unit, CMIC_PORT(unit), port)) {
   4452                     return(-1);
   4453                 }
   4454             }
   4455         }
   4456         if(dev_id == BCM56443_DEVICE_ID) {
   4457             if ( bcm_port_ability_get(unit, port, &ability) != BCM_E_NONE) {
   4458                 test_error(unit, "===========> ERROR : fail to get ability\n");
   4459                 return -1;
   4460             }
   4461             switch(lp->lp_speed) {
   4462                 case 1:
   4463                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_10MB))) {
   4464                         flag = 1;
   4465                     }
   4466                     break;
   4467                 case 2:
   4468                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_100MB))) {
   4469                         flag = 1;
   4470                     }
   4471                     break;
   4472                 case 3:
   4473                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_1000MB))) {
   4474                         flag = 1;
   4475                     }
   4476                     break;
   4477                 case 4:
   4478                     if (!CHECK_PBM_SPEED(ability, (BCM_PORT_ABIL_2500MB))) {
   4479                         flag = 1;
   4480                     }
   4481                     break;
   4482                 default :
   4483                     flag = 0;
   4484                     break;
   4485 
   4486             }
   4487             if (flag)
   4488                 continue;
   4489         }
   4490         lp->lp_tx_port = port;
   4491         lp->lp_rx_port = port;
   4492 
   4493         lw->lw_tx_init_chn = 0;
   4494         lw->lw_tx_init_len = 0;
   4495 
   4496         if(soc_feature(unit, soc_feature_cmicx)) {
   4497             /* We send 2 dcbs per packet as the header is no longer part of dcb */
   4498             lw->lw_tx_dcb_factor = 2;
   4499         } else {
   4500             lw->lw_tx_dcb_factor = 1;
   4501         }
   4502 
   4503         rv = lb_do_txrx(lw);
   4504 
   4505         if (!lb_is_xgs_fabric(unit) && !IS_ST_PORT(unit, port)) {
   4506             lb_cleanup_arl(lw, unit);
   4507         }
   4508 
   4509         if (rv < 0) {
   4510             pbmp_t  portpbm;
   4511             BCM_PBMP_CLEAR(portpbm);
   4512             BCM_PBMP_PORT_ADD(portpbm, port);
   4513 #if defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT)
   4514             if (SOC_IS_DFE(unit) || SOC_IS_DPP(unit)) {
   4515                 do_show_dpp_counters(unit, INVALIDr, portpbm,
   4516                                SHOW_CTR_CHANGED | SHOW_CTR_SAME | SHOW_CTR_NZ);
   4517             } else 
   4518 #elif defined (BCM_ESW_SUPPORT) 
   4519             {
   4520                 do_show_counters(unit, INVALIDr, portpbm,
   4521                                SHOW_CTR_CHANGED | SHOW_CTR_SAME | SHOW_CTR_NZ);
   4522             }
   4523 #endif
   4524             return -1;
   4525         }
   4526     }
   4527 
   4528     lb_stats_done(lw);
   4529 #ifdef BCM_SHADOW_SUPPORT
   4530     if (SOC_IS_SHADOW(unit)) {
   4531         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, THDI_BYPASSr,
   4532                             REG_PORT_ANY, INPUT_THRESHOLD_BYPASSf, 0));
   4533     }
   4534 #endif /* BCM_SHADOW_SUPPORT */
   4535 
   4536     return(0);
   4537 }
   4538 
   4539 /*
   4540  * Rotate port number by dst_inc.
   4541  * Handles positive or negative dst_inc.
   4542  */
   4543 STATIC soc_port_t
   4544 lb_ext_partner(int unit, soc_port_t port, int dst_inc)
   4545 {
   4546     pbmp_t      bm;
   4547     int         nports, pindex, nindex;
   4548     soc_port_t  p;
   4549 
   4550     if (IS_FE_PORT(unit, port)) {
   4551         nports = NUM_FE_PORT(unit);
   4552         SOC_PBMP_ASSIGN(bm, PBMP_FE_ALL(unit));
   4553     } else if (IS_GE_PORT(unit, port)) {
   4554         nports = NUM_GE_PORT(unit);
   4555         SOC_PBMP_ASSIGN(bm, PBMP_GE_ALL(unit));
   4556     } else if (IS_XE_PORT(unit, port)) {
   4557         nports = NUM_XE_PORT(unit);
   4558         SOC_PBMP_ASSIGN(bm, PBMP_XE_ALL(unit));
   4559     } else if (IS_ST_PORT(unit, port)) {
   4560         nports = NUM_ST_PORT(unit);
   4561         SOC_PBMP_ASSIGN(bm, PBMP_ST_ALL(unit));
   4562     } else {
   4563         return port;
   4564     }
   4565 
   4566     /* short circuit trivial cases */
   4567     if (dst_inc == 0 || nports < 2) {
   4568         return port;
   4569     }
   4570 
   4571     /* find index of old port */
   4572     pindex = -1;
   4573     PBMP_ITER(bm, p) {
   4574         pindex += 1;
   4575         if (p == port) {
   4576             break;
   4577         }
   4578     }
   4579 
   4580     /* increment/decrement index with wrap around */
   4581     nindex = (pindex + dst_inc) % nports;
   4582     if (nindex < 0) {           /* handle C doing modulo or remainder for % */
   4583         nindex = nports + nindex;
   4584     }
   4585 
   4586     /* short circuit another trivial case */
   4587     if (nindex == pindex) {
   4588         return port;
   4589     }
   4590 
   4591     /* find nindex'th port */
   4592     PBMP_ITER(bm, p) {
   4593         if (--nindex < 0) {
   4594             return p;
   4595         }
   4596     }
   4597 
   4598     /* can't get here */
   4599     return port;
   4600 }
   4601 
   4602 int
   4603 lb_ext_init(int unit, args_t *a, void **pa)
   4604 /*
   4605  * Function:    lb_ext_init
   4606  * Purpose:     Initialize external loopback test.
   4607  * Parameters:  unit - unit number.
   4608  * Returns:     0 for success, -1 for failed.
   4609  */
   4610 {
   4611     loopback_test_t             *lw = &lb_work[unit];
   4612     loopback_testdata_t         *lp = &lw->lw_lp_ext;
   4613     parse_table_t       pt;
   4614     soc_port_t          port;
   4615     pbmp_t              pbmp_partners, tpbm;
   4616     int                 rv;
   4617     pbmp_t              temp_pbmp, temp_pbmp2;
   4618     bcm_port_medium_t   medium;
   4619 
   4620 
   4621     bcm_l2_addr_t_init(&lw->lw_arl_src, lb_mac_src, 1);
   4622     bcm_l2_addr_t_init(&lw->lw_arl_dst, lb_mac_dst, 1);
   4623 
   4624     parse_table_init(unit, &pt);
   4625     parse_table_add(&pt, "TxPortBitMap",PQ_PBMP|PQ_DFL, 0,
   4626                     &lp->lp_pbm_tx,     NULL);
   4627     parse_table_add(&pt, "DestinationIncrement",PQ_INT|PQ_DFL, 0,
   4628                     &lp->lp_dst_inc,    NULL);
   4629     if (lb_is_xgs_fabric(unit)) {
   4630         parse_table_add(&pt, "DestMOD",     PQ_DFL|PQ_INT,  0,
   4631                         &lp->lp_d_mod,      NULL);
   4632         parse_table_add(&pt, "DestPORT",    PQ_DFL|PQ_PORT, 0,
   4633                         &lp->lp_d_port,     NULL);
   4634         parse_table_add(&pt, "OpCode",    PQ_DFL|PQ_INT, 0,
   4635                         &lp->lp_opcode,     NULL);
   4636     } else {
   4637         parse_table_add(&pt, "UntagBitMap",     PQ_PBMP|PQ_DFL, 0,
   4638                         &lp->lp_ubm,    NULL);
   4639     }
   4640     parse_table_add(&pt, "Speed",       PQ_MULTI|PQ_DFL, 0,
   4641                     &lp->lp_speed,      lb_parse_speed);
   4642     parse_table_add(&pt, "AutoNeg",     PQ_BOOL|PQ_DFL, 0,
   4643                     &lp->lp_autoneg,    NULL);
   4644     parse_table_add(&pt, "SourceMac",   PQ_DFL|PQ_MAC,  0,
   4645                     &lp->lp_mac_src,    NULL);
   4646     parse_table_add(&pt, "SourceMacInc",PQ_DFL|PQ_INT,  0,
   4647                     &lp->lp_mac_src_inc,NULL);
   4648     parse_table_add(&pt, "DestMac",     PQ_DFL|PQ_MAC,  0,
   4649                     &lp->lp_mac_dst,    NULL);
   4650     parse_table_add(&pt, "DestMacInc",  PQ_DFL|PQ_INT,  0,
   4651                     &lp->lp_mac_dst_inc,NULL);
   4652 
   4653     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   4654                     &lp->lp_pattern,    NULL);
   4655     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL, 0,
   4656                     &lp->lp_pattern_inc,NULL);
   4657     parse_table_add(&pt, "VLantag",     PQ_INT|PQ_DFL,  0,
   4658                     &lp->lp_vlan,       NULL);
   4659     parse_table_add(&pt, "LengthStart", PQ_INT|PQ_DFL,  0,
   4660                     &lp->lp_l_start,    NULL);
   4661     parse_table_add(&pt, "LengthEnd",   PQ_INT|PQ_DFL,  0,
   4662                     &lp->lp_l_end,      NULL);
   4663     parse_table_add(&pt, "LengthIncrement",PQ_INT|PQ_DFL, 0,
   4664                     &lp->lp_l_inc,      NULL);
   4665     parse_table_add(&pt, "COSStart",    PQ_INT|PQ_DFL,  0,
   4666                     &lp->lp_cos_start,  NULL);
   4667     parse_table_add(&pt, "COSEnd",      PQ_INT|PQ_DFL,  0,
   4668                     &lp->lp_cos_end,    NULL);
   4669     parse_table_add(&pt, "CRC",         PQ_MULTI|PQ_DFL, 0,
   4670                     &lp->lp_crc_mode,   crc_mode);
   4671     parse_table_add(&pt, "PacketsPerChain",PQ_INT|PQ_DFL, 0,
   4672                     &lp->lp_c_start,    NULL);
   4673     parse_table_add(&pt, "Count",       PQ_INT|PQ_DFL,  0,
   4674                     &lp->lp_count,      NULL);
   4675     parse_table_add(&pt, "CheckData",   PQ_BOOL|PQ_DFL, 0,
   4676                     &lp->lp_check_data, NULL);
   4677     parse_table_add(&pt, "CheckCrc",    PQ_BOOL|PQ_DFL, 0,
   4678                     &lp->lp_check_crc,  NULL);
   4679 
   4680     lb_setup(unit, lw);
   4681 
   4682     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   4683         test_error(unit,
   4684                    "%s: Invalid option: %s\n",
   4685                    ARG_CMD(a),
   4686                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   4687         parse_arg_eq_done(&pt);
   4688         return(-1);
   4689     }
   4690     parse_arg_eq_done(&pt);
   4691 
   4692     /* Packets Per Chain == DCB Per chain for non-S/G */
   4693 
   4694     lp->lp_ppc_start = lp->lp_c_start;
   4695     lp->lp_ppc_end   = lp->lp_c_end = lp->lp_c_start;
   4696     lp->lp_ppc_inc   = lp->lp_c_inc;
   4697 
   4698     /* Determine other ports that are involved in the test */
   4699 
   4700     SOC_PBMP_CLEAR(pbmp_partners);
   4701 
   4702     PBMP_ITER(lp->lp_pbm_tx, port) {
   4703         SOC_PBMP_PORT_ADD(pbmp_partners,
   4704                           lb_ext_partner(unit, port, lp->lp_dst_inc));
   4705     }
   4706 
   4707     SOC_PBMP_ASSIGN(tpbm, lp->lp_pbm_tx);
   4708     SOC_PBMP_AND(tpbm, pbmp_partners);
   4709     if (SOC_PBMP_NOT_NULL(tpbm)) {
   4710         test_error(unit,
   4711                "Loopback partners of specified ports "
   4712                "may not overlap other specified ports\n");
   4713         return(-1);
   4714     }
   4715 
   4716     SOC_PBMP_ASSIGN(lp->lp_pbm, lp->lp_pbm_tx);         /* All TX+RX ports */
   4717     SOC_PBMP_OR(lp->lp_pbm, pbmp_partners);
   4718 
   4719     /* Packets Per Chain == DCB Per chain for non-S/G */
   4720 
   4721     lp->lp_ppc_start = lp->lp_c_start;
   4722     lp->lp_ppc_end   = lp->lp_c_end;
   4723     lp->lp_ppc_inc   = lp->lp_c_inc;
   4724 
   4725     lp->lp_sg = FALSE;
   4726 
   4727     if (lb_check_parms(lw, lp, PBMP_PORT_ALL(unit))) {
   4728         return(-1);
   4729     }
   4730 
   4731     /* Perform common loopback initialization */
   4732 
   4733     if (lb_init(unit, lw, lp, TRUE)) {
   4734         return(-1);
   4735     }
   4736     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   4737 
   4738 	if ((rv = bcm_vlan_create(unit, lp->lp_vlan)) < 0 &&
   4739 	    rv != BCM_E_EXISTS) {
   4740 	    test_error(unit,
   4741 	               "Could not create VLAN %d: %s\n",
   4742 	               lp->lp_vlan, bcm_errmsg(rv));
   4743 	    return (-1);
   4744         }
   4745     }    
   4746     SOC_PBMP_CLEAR(temp_pbmp);
   4747     if (SOC_IS_XGS3_SWITCH(unit)) {
   4748         SOC_PBMP_ASSIGN(temp_pbmp, PBMP_PORT_ALL(unit));
   4749     }
   4750     SOC_PBMP_ASSIGN(temp_pbmp2, PBMP_ALL(unit));
   4751     SOC_PBMP_REMOVE(temp_pbmp2, PBMP_LB(unit));
   4752     if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   4753 	if ((rv = bcm_vlan_port_add(unit, lp->lp_vlan,
   4754 	                            temp_pbmp2, temp_pbmp)) < 0) {
   4755 	    test_error(unit,
   4756 	               "Could not add all ports to VLAN %d: %s\n",
   4757 	               lp->lp_vlan, bcm_errmsg(rv));
   4758 	        return (-1);
   4759         }
   4760     }
   4761     /* Set the spanning tree group to 1 since port state is forwarding */
   4762     rv = bcm_vlan_stg_set(unit, lp->lp_vlan, 1);
   4763     if (rv < 0 && rv != BCM_E_UNAVAIL) {
   4764         test_error(unit, "Could not set vlan %d stg 1: %s\n",
   4765                lp->lp_vlan, bcm_errmsg(rv));
   4766         return(-1);
   4767     }
   4768 
   4769 #ifdef BCM_CMICM_SUPPORT
   4770     /* Assign all COS to this channel
   4771      * Though this is added for CMICm, 
   4772      * it should be OK if we do this for CMICe as well */
   4773     if(soc_feature(unit, soc_feature_cmicm)) {
   4774         LOG_INFO(BSL_LS_APPL_TESTS,
   4775                  (BSL_META_U(unit,
   4776                              "Assign all COS to channel: 1\n")));
   4777         SOC_IF_ERROR_RETURN(
   4778             bcm_rx_queue_channel_set(unit, -1, 1));
   4779 
   4780 #if defined(BCM_KATANA2_SUPPORT)
   4781             if(SOC_IS_KATANA2(unit)) {
   4782                 uint32 reg_val, reg_addr;
   4783 
   4784                 /* Including CPU L0 bitmap to support CMIC backpressure */
   4785                 reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, 1);
   4786                 reg_val = soc_pci_read(unit, reg_addr);
   4787                 reg_val |= (1 << 16);
   4788                 soc_pci_write(unit, reg_addr, reg_val);
   4789             }
   4790 #endif
   4791 
   4792     }
   4793 #endif
   4794 #ifdef BCM_CMICX_SUPPORT
   4795     /* Assign all COS to this channel */
   4796     if(soc_feature(unit, soc_feature_cmicx)) {
   4797         LOG_INFO(BSL_LS_APPL_TESTS,
   4798                  (BSL_META_U(unit,
   4799                              "Assign all COS to channel: 1\n")));
   4800         SOC_IF_ERROR_RETURN(
   4801             bcm_rx_queue_channel_set(unit, -1, 1));
   4802     }
   4803 #endif
   4804 
   4805     PBMP_ITER(lp->lp_pbm_tx, port) {
   4806         if ((rv = lb_setup_port(unit, port,
   4807                                 lp->lp_speed, lp->lp_autoneg)) < 0) {
   4808             test_error(unit,
   4809                        "Port %s: Port setup failed: %s\n",
   4810                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4811             lb_done(lw);                        /* In case they continue */
   4812             return(-1);
   4813         }
   4814 
   4815         /*
   4816          * Put xmit ports in master mode and recv ports in slave mode
   4817          * (actually only a requirement of gigabit ports)
   4818          */
   4819 
   4820         if ((rv = bcm_port_medium_get(unit, port, &medium)) < 0 ) {
   4821             test_error(unit,
   4822                        "Port %s: Port medium get failed: %s\n",
   4823                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4824             return(-1);
   4825         }
   4826         if (medium == BCM_PORT_MEDIUM_COPPER) {
   4827             if (!lp->lp_autoneg &&
   4828                 (rv = bcm_port_master_set(unit, port,
   4829                                       SOC_PORT_MS_MASTER)) < 0) {
   4830                 test_error(unit,
   4831                        "Port %s: Could not set port master: %s\n",
   4832                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4833                 lb_done(lw);                        /* In case they continue */
   4834                 return(-1);
   4835             }
   4836         }
   4837     }
   4838 
   4839     PBMP_ITER(pbmp_partners, port) {
   4840         if ((rv = lb_setup_port(unit, port,
   4841                                 lp->lp_speed, lp->lp_autoneg)) < 0) {
   4842             test_error(unit,
   4843                        "Port %s: Port setup failed: %s\n",
   4844                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4845             lb_done(lw);                        /* In case they continue */
   4846             return(-1);
   4847         }
   4848 
   4849         /*
   4850          * Put xmit ports in master mode and recv ports in slave mode
   4851          * (actually only a requirement of gigabit ports)
   4852          */
   4853         if ((rv = bcm_port_medium_get(unit, port, &medium)) < 0 ) {
   4854             test_error(unit,
   4855                        "Port %s: Port medium get failed: %s\n",
   4856                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4857             return(-1);
   4858         }
   4859         if (medium == BCM_PORT_MEDIUM_COPPER) {
   4860             if (!lp->lp_autoneg &&
   4861                 (rv = bcm_port_master_set(unit, port,
   4862                                       SOC_PORT_MS_SLAVE)) < 0) {
   4863                 test_error(unit,
   4864                        "Port %s: Could not set port master: %s\n",
   4865                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   4866                 lb_done(lw);                        /* In case they continue */
   4867                 return(-1);
   4868             }
   4869         }
   4870     }
   4871 
   4872     /* Wait for links */
   4873 
   4874     if (lb_link_wait(unit, lp->lp_pbm) < 0) {
   4875         lb_done(lw);
   4876         return(-1);
   4877     }
   4878 
   4879     *pa = lw;
   4880 
   4881     return(0);
   4882 }
   4883 
   4884 int
   4885 lb_ext_test(int unit, args_t *a, void *pa)
   4886 /*
   4887  * Function:    lb_mii_test
   4888  * Purpose:     Perform ext loopback tests.
   4889  * Parameters:  unit - unit #
   4890  *              a - arguments
   4891  * Returns:     0 - success, -1 failed.
   4892  */
   4893 {
   4894     loopback_test_t     *lw = (loopback_test_t *)pa;
   4895     loopback_testdata_t *lp = lw->lw_lp;
   4896     soc_port_t  port, dst_port;
   4897     int         rv;
   4898 
   4899     COMPILER_REFERENCE(a);
   4900 
   4901     lb_stats_init(lw);
   4902 
   4903     PBMP_ITER(lp->lp_pbm_tx, port) {
   4904         /*
   4905          * Figure out RX port and add ARL entry to direct packets to CPU.
   4906          */
   4907 
   4908         dst_port = lb_ext_partner(unit, port, lp->lp_dst_inc);
   4909 
   4910         LOG_INFO(BSL_LS_APPL_TESTS,
   4911                  (BSL_META_U(unit,
   4912                              "lb_ext_test: Looping port %s (%d) ---> %s (%d)\n"),
   4913                   SOC_PORT_NAME(unit, port), port,
   4914                   SOC_PORT_NAME(unit, dst_port), dst_port));
   4915         if (!lb_is_xgs_fabric(unit)) {
   4916             if (lb_setup_arl(lw, unit, CMIC_PORT(unit), port)) {
   4917                 return(-1);
   4918             }
   4919         }
   4920 
   4921         lp->lp_tx_port = port;
   4922         lp->lp_rx_port = dst_port;
   4923 
   4924         lw->lw_tx_init_chn = 0;
   4925         lw->lw_tx_init_len = 0;
   4926 
   4927         if(soc_feature(unit, soc_feature_cmicx)) {
   4928             /* We send 2 dcbs per packet as the header is no longer part of dcb */
   4929             lw->lw_tx_dcb_factor = 2;
   4930         } else {
   4931             lw->lw_tx_dcb_factor = 1;
   4932         }
   4933 
   4934         rv = lb_do_txrx(lw);
   4935         if (!lb_is_xgs_fabric(unit)) {
   4936             lb_cleanup_arl(lw, unit);
   4937         }
   4938         if (rv < 0) {
   4939             return -1;
   4940         }
   4941     }
   4942 
   4943     lb_stats_done(lw);
   4944 
   4945     return(0);
   4946 }
   4947 
   4948 int
   4949 lb_ext_done(int unit, void *pa)
   4950 /*
   4951  * Function:    lb_ext_done
   4952  * Purpose:     Clean up after external loopback test.
   4953  * Parameters:  unit - unit number.
   4954  * Returns:     0 for success, -1 for failed.
   4955  */
   4956 {
   4957     COMPILER_REFERENCE(pa);
   4958 
   4959     lb_done(&lb_work[unit]);
   4960     return(0);
   4961 }
   4962 
   4963 #undef PAUSE_SUPT
   4964 
   4965 STATIC void
   4966 lb_setup_sg_dcbs(dv_t *dv, int l, int sg_c, int end_pkt, void *p, uint32 align, 
   4967                  pbmp_t pbm, pbmp_t ubm, uint32 crc, uint32 cos,
   4968                  uint32 *hgh)
   4969 /*
   4970  * Function:    lb_setup_sg_dcbs
   4971  * Purpose:     Set up the DCBs for a TX/RX
   4972  * Parameters:  dv - Pointer to DV containing chain.
   4973  *              l - total length of packet.
   4974  *              sg_c - number of DCBs to scatter/gather across.
   4975  *              end_pkt - if TRUE, sg bit is cleared on last DCB
   4976  *              p - pointer to packet data.
   4977  *              align - Power of 2 integer alignment required for
   4978  *                      Address/length
   4979  *              pbm - port Bit map to send to.
   4980  *              ubm - Untag port bit map.
   4981  *              crc - CRC value used for DCB.
   4982  *              cos - COS value used in DCBS.
   4983  *              hgh - Higig header for XGS3 devices
   4984  * Returns:     Pointer to NEXT empty DCB.
   4985  *
   4986  * Notes:       Pass in if need to align len, and for Tx, can do weird
   4987  *              lengths ...
   4988  */
   4989 {
   4990     int         dcb_l;                  /* Length per DCB */
   4991     sal_vaddr_t pp = (sal_vaddr_t)p;
   4992     uint32      flags = SOC_DMA_COS(cos) | (crc ? SOC_DMA_CRC_REGEN : 0);
   4993     pbmp_t      l3pbm;
   4994 
   4995 #ifdef BCM_XGS3_SWITCH_SUPPORT
   4996     if (hgh != NULL) {
   4997         SOC_DMA_HG_SET(flags, 1);
   4998         SOC_DMA_STATS_SET(flags, 1);
   4999     }
   5000 #endif
   5001 
   5002     SOC_PBMP_CLEAR(l3pbm);
   5003 
   5004     dcb_l = l / sg_c;
   5005     dcb_l &= -align;
   5006 
   5007     while (sg_c-- > 0) {
   5008         int     cnt;
   5009 
   5010         if (sg_c) {
   5011             cnt = dcb_l;
   5012         } else {
   5013             cnt = l;
   5014         }
   5015         soc_dma_desc_add(dv, pp, cnt, pbm, ubm, l3pbm, flags, (uint32 *)hgh);
   5016         l -= dcb_l;
   5017         pp += dcb_l;
   5018     }
   5019 
   5020     if (end_pkt) {
   5021         soc_dma_desc_end_packet(dv);
   5022     }
   5023 }
   5024 
   5025 STATIC  int
   5026 lb_sg_check_tx(loopback_test_t *lw, int ppc, int dpp, int length)
   5027 /*
   5028  * Function:    lb_sg_check_tx
   5029  * Purpose:     Check the status and correctness of a TX chain.
   5030  * Parameters:  lw - pointer to work structure.
   5031  *              ppc - TX packets-per-chain.
   5032  *              dpp - if >0 DCBs-per-packet, if <0, DCBs-per-packet is
   5033  *                      random.
   5034  *              length - current packet length.
   5035  * Returns:     0 - OK, chain not complete.
   5036  *              1 - OK, chain complete
   5037  *              -1- ERROR found.
   5038  */
   5039 
   5040 {
   5041     int         rv = 0;
   5042     dv_t        *dv = lw->lw_tx_dv[0];
   5043     dcb_t       *start_dcb, *end_dcb, *cur_dcb;
   5044     int         cur_packet, cur_len;    /* Current packet #/pckt length  */
   5045     int         unit = lw->lw_unit;
   5046 
   5047     /* Check next DCB to look at */
   5048 
   5049     start_dcb  = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_dsc);
   5050     cur_packet = dv->dv_pckt;                   /* Total packets in chain */
   5051 
   5052     /* Check for all packets we re transmitting */
   5053 
   5054     while (!rv && (cur_packet < ppc)) {
   5055         assert(start_dcb < SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt));
   5056         /*
   5057          * Find the end of the current packet, be sure it is complete,
   5058          * if not, escape to check later.
   5059          */
   5060         cur_len = 0;
   5061         cur_dcb = start_dcb;
   5062 
   5063         /*
   5064          * Find last DCB for current packet, if dpp is >0, then it
   5065          * indicates number of DCBs, if <0, then random, and last DCB
   5066          * must be scanned for.
   5067          */
   5068 
   5069         if (dpp > 0) {
   5070             end_dcb = start_dcb;
   5071             end_dcb = SOC_DCB_IDX2PTR(unit, end_dcb, dpp - 1);
   5072         } else {
   5073             end_dcb = NULL;             /* Keep gcc happy */
   5074             assert(0);                  /* Not implemented. */
   5075         }
   5076 
   5077         assert(end_dcb <= SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt));
   5078 
   5079         if (!SOC_DCB_DONE_GET(unit, end_dcb)) {
   5080             break;                      /* WHILE (cur_packet < ppc) */
   5081         }
   5082 
   5083         while (cur_dcb <= end_dcb) {
   5084 
   5085             /* Verify DONE */
   5086 
   5087             if (!SOC_DCB_DONE_GET(unit, cur_dcb)) {
   5088                 cli_out("Error: TX: Expected done bit in DCB Pckt(%d)\n",
   5089                         cur_packet);
   5090                 rv = -1;
   5091             }
   5092 
   5093             /* Verify byte count */
   5094 
   5095             if (SOC_DCB_REQCOUNT_GET(unit, cur_dcb) != 
   5096                 SOC_DCB_XFERCOUNT_GET(unit, cur_dcb)) {
   5097                 cli_out("Error: TX: Unexpected count Packet %d: "
   5098                         "Expected %d Got %d dcb=%p\n",
   5099                         cur_packet, 
   5100                         SOC_DCB_REQCOUNT_GET(unit, cur_dcb), 
   5101                         SOC_DCB_XFERCOUNT_GET(unit, cur_dcb), 
   5102                         cur_dcb);
   5103                 rv = -1;
   5104             }
   5105 
   5106             cur_len += SOC_DCB_XFERCOUNT_GET(unit, cur_dcb);
   5107             cur_dcb = SOC_DCB_IDX2PTR(unit, cur_dcb, 1);  /* Next DCB please */
   5108         } /* while (cur_dcb <= end_dcb */
   5109 
   5110         /*
   5111          * One final check - verify total length is what we want.
   5112          * This should be an assert, but useful for debug.
   5113          */
   5114         if (cur_len != length) {
   5115             cli_out("Error: TX: Unexpected total length: "
   5116                     "Expected %d Got %d\n", length, cur_len);
   5117             rv = -1;
   5118         }
   5119         cur_packet++;                   /* Next packet please */
   5120         lw->lw_tx_count++;              /* Count packet */
   5121         lw->lw_tx_bytes += length;      /*  ... and total bytes */
   5122         start_dcb = SOC_DCB_IDX2PTR(unit, end_dcb, 1); /* Next packet please */
   5123     } /* while */
   5124 
   5125     dv->dv_pckt = cur_packet;
   5126     dv->dv_dsc  = SOC_DCB_PTR2IDX(unit, start_dcb, dv->dv_dcb);
   5127 
   5128     if (rv < 0) {
   5129         soc_dma_dump_dv(lw->lw_unit, "TX err", dv);
   5130         test_error(lw->lw_unit, "TX Error detected\n");
   5131         return(rv);
   5132     } else {
   5133         return((cur_packet == ppc) && lw->lw_eoc_rx);
   5134     }
   5135 }
   5136 
   5137 STATIC  int
   5138 lb_sg_check_rx(loopback_test_t *lw, int ppc, int dpp, int length,
   5139                int tx_offset, int rx_offset)
   5140 /*
   5141  * Function:    lb_sg_check_rx
   5142  * Purpose:     Check an RX chain for S/G tests.
   5143  * Parameters:  lw -    pointer to work structure.
   5144  *              ppc -   packets-per-chain, total number of packets to
   5145  *                      expect in the DCB chain.
   5146  *              dpp -   dcbs-per-packet, number of DCBs per packet,
   5147  *                      if -1, then #dcbs is random.
   5148  *              length- # bytes expected in total for a packet.
   5149  *              tx_offset - offset into TX buffer where packet starts.
   5150  *              rx_offset - offset into RX buffer where packet starts.
   5151  * Returns:     0 - OK, chain not complete
   5152  *              1 - OK, chain complete
   5153  *              -1- ERROR found.
   5154  */
   5155 {
   5156     int         rv = 0;
   5157     dv_t        *dv = lw->lw_rx_dv[0];
   5158     dcb_t       *end_dcb, *start_dcb, *cur_dcb;
   5159     int         cur_packet;             /* Current packet number in chain */
   5160     int         cur_len;                /* Current running packet length */
   5161     int         rx_crc_valid;           /* Boolean - TRUE if CRC !HW update*/
   5162     int         unit = lw->lw_unit;
   5163     int         skip_vlan = 0;
   5164 
   5165 #ifdef BCM_XGS3_SWITCH_SUPPORT
   5166     if ((SOC_IS_XGS3_SWITCH(lw->lw_unit)) &&
   5167         (IS_ST_PORT(lw->lw_unit, lw->lw_lp->lp_rx_port))){
   5168         skip_vlan = 1;
   5169     }
   5170 #endif
   5171 
   5172     /* Check next DCB to look at */
   5173 
   5174     start_dcb  = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_dsc);
   5175     cur_packet = dv->dv_pckt;                   /* Total packets in chain */
   5176 
   5177     /* Check for all packets we are expecting */
   5178 
   5179     while (!rv && (cur_packet < ppc)) {
   5180         /*
   5181          * Find the end of the current packet, be sure it is complete,
   5182          * if not, escape to check later.
   5183          */
   5184         cur_len = 0;
   5185         cur_dcb = start_dcb;
   5186 
   5187         /*
   5188          * Find last DCB for current packet, if dpp is >0, then it indicates
   5189          * number of DCBs, if <0, then random, and last DCB must be scanned
   5190          * for.
   5191          */
   5192         if (dpp > 0) {
   5193             end_dcb = SOC_DCB_IDX2PTR(unit, start_dcb, dpp - 1);
   5194         } else {
   5195             end_dcb = NULL;             /* Keep gcc happy */
   5196             assert(0);                  /* Not implemented. */
   5197         }
   5198 
   5199         assert(end_dcb <= SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt));
   5200 
   5201         if (!SOC_DCB_DONE_GET(unit, end_dcb)) {
   5202             break;
   5203         }
   5204 
   5205         /* If debugging DMA - dump the chain */
   5206         if (bsl_check(bslLayerAppl, bslSourceDma, bslSeverityNormal, unit)) {
   5207             soc_dma_dump_dv(lw->lw_unit, "S/G Rx:", dv);
   5208         }
   5209 
   5210         rx_crc_valid = !SOC_DCB_RX_CRC_GET(unit, end_dcb);
   5211 #ifdef BCM_XGS3_SWITCH_SUPPORT
   5212         if (SOC_IS_XGS3_SWITCH(lw->lw_unit)) {
   5213             rx_crc_valid = 0;
   5214         }
   5215 #endif
   5216 
   5217         /* Last DCB must have END bit set */
   5218 
   5219         if (!SOC_DCB_RX_END_GET(unit, end_dcb)) {
   5220             cli_out("Error: RX: DCB (%d) Last DCB for packet does not have "
   5221                     "END bit set\n",
   5222                     SOC_DCB_PTR2IDX(unit, end_dcb, dv->dv_dcb));
   5223             rv = -1;
   5224         }
   5225 
   5226         /* First DCB MUST have Start bit set. */
   5227 
   5228         if (!SOC_DCB_RX_START_GET(unit, cur_dcb) && 
   5229             !soc_feature(unit, soc_feature_dcb_st0_bug)) {
   5230             cli_out("Error: RX: DCB (%d) First for packet does not have "
   5231                     "START set\n",
   5232                     SOC_DCB_PTR2IDX(unit, end_dcb, dv->dv_dcb));
   5233             rv = -1;
   5234         }
   5235 
   5236         /*
   5237          * Loop through looking for the end of the packet, checking
   5238          * along the way that the END and START bits appear in the
   5239          * correct place. When an entire packet is noticed to be complete,
   5240          * check the data.
   5241          */
   5242         while (cur_dcb <= end_dcb) {
   5243 
   5244             /* Check for unexpected start bit */
   5245 
   5246             if ((cur_dcb != start_dcb) && 
   5247                 SOC_DCB_RX_START_GET(unit, cur_dcb)) {
   5248                 cli_out("Error: RX: DCB (%d) Unexpected START bit\n",
   5249                         SOC_DCB_PTR2IDX(unit, cur_dcb, dv->dv_dcb));
   5250                 rv = -1;
   5251             }
   5252 
   5253             /* Check for unexpected END bit */
   5254 
   5255             if ((cur_dcb != end_dcb) &&
   5256                 SOC_DCB_RX_END_GET(unit, cur_dcb)) {
   5257                 cli_out("Error: RX: DCB (%d) Unexpected END bit\n",
   5258                         SOC_DCB_PTR2IDX(unit, cur_dcb, dv->dv_dcb));
   5259                 rv = -1;
   5260             }
   5261 
   5262             /* Verify DONE is set is all DCBs */
   5263 
   5264             if (!SOC_DCB_DONE_GET(unit, cur_dcb)) {
   5265                 cli_out("Error: RX: DCB (%d) Expected DONE set\n",
   5266                         SOC_DCB_PTR2IDX(unit, cur_dcb, dv->dv_dcb));
   5267                 rv = -1;
   5268             }
   5269 
   5270             /* Verify byte count */
   5271 
   5272             if (SOC_DCB_REQCOUNT_GET(unit, cur_dcb) != 
   5273                 SOC_DCB_XFERCOUNT_GET(unit, cur_dcb)) {
   5274                 cli_out("Error: RX: Unexpected count: Expected %d Got %d\n",
   5275                         SOC_DCB_REQCOUNT_GET(unit, cur_dcb), 
   5276                         SOC_DCB_XFERCOUNT_GET(unit, cur_dcb));
   5277                 rv = -1;
   5278             }
   5279             cur_len += SOC_DCB_XFERCOUNT_GET(unit, cur_dcb);
   5280             cur_dcb = SOC_DCB_IDX2PTR(unit, cur_dcb, 1);   /* Next DCB */
   5281         }
   5282 
   5283         /* Check packet Data */
   5284 
   5285         LOG_INFO(BSL_LS_APPL_TESTS,
   5286                  (BSL_META_U(unit,
   5287                              "lb_sg_check_rx : rxlen = %d txlen = %d\n"),cur_len,length));
   5288         if (lb_check_packet(lw, lw->lw_tx_packets[cur_packet] + tx_offset,
   5289                             length,
   5290                             lw->lw_rx_packets[cur_packet] + rx_offset,
   5291                             cur_len,
   5292                             rx_crc_valid,
   5293                             lw->lw_mac_dst, lw->lw_mac_src, skip_vlan) < 0) {
   5294             rv = -1;
   5295         }
   5296 
   5297         /* Bump pointer to start of next packet */
   5298 
   5299         cur_packet++;
   5300         lw->lw_rx_count++;              /* Count RX packets */
   5301         lw->lw_rx_bytes += length;      /*  ... and total bytes */
   5302         start_dcb = SOC_DCB_IDX2PTR(unit, end_dcb, 1);
   5303     }
   5304 
   5305     /* Update current packet */
   5306     dv->dv_pckt = cur_packet;
   5307     /* Update next to look at */
   5308     dv->dv_dsc = SOC_DCB_PTR2IDX(unit, start_dcb, dv->dv_dcb);
   5309 
   5310     if (rv) {
   5311         soc_dma_dump_dv(lw->lw_unit, "Rx ERR ", dv);
   5312         soc_dma_dump_dv(lw->lw_unit, "Tx chn ", lw->lw_tx_dv[0]);
   5313         test_error(lw->lw_unit, "RX: Check failed\n");
   5314         return(-1);
   5315     } else {
   5316         return((cur_packet == ppc) && lw->lw_eoc_rx);
   5317     }
   5318 }
   5319 
   5320 STATIC  int
   5321 lb_sg_wait(loopback_test_t *lw, int length, int ppc, int tx_dpp, int tx_offset,
   5322            int rx_dpp)
   5323 /*
   5324  * Function:    lb_sg_wait
   5325  * Purpose:     Wait for packets to Tx/Rx and check data/dcbs
   5326  *              as they complete.
   5327  * Parameters:  lw - pointer to work structure.
   5328  *              length - current Tx/Rx packet length.
   5329  *              ppc - packets-per-chain
   5330  *              tx_dpp - TX DCBs-per-packet.
   5331  *              tx_offset - offset into tx packet where header starts.
   5332  *              rx_dpp - RX DCBs-per-packet.
   5333  * Returns:     0 - success
   5334  *              !0 - failed
   5335  * Notes:       10-seconds without any activity results in failure.
   5336  */
   5337 {
   5338     int tx_done = 0;
   5339     int rx_done = 0;
   5340     int rv = 0;
   5341     int level = 0;
   5342 
   5343 #ifdef BCM_XGS12_FABRIC_SUPPORT
   5344     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   5345         /* Update length */
   5346         LOG_INFO(BSL_LS_APPL_TESTS,
   5347                  (BSL_META("lb_sg_wait: length = %d\n"), length));
   5348         length += SOC_HIGIG_HDR_SIZE;
   5349     }
   5350 #endif
   5351     while (!lw->lw_eoc_tx || !lw->lw_eoc_rx) {
   5352         if (sal_sem_take(lw->lw_sema, lw->lw_timeout_usec)) {
   5353             cli_out("Time-out waiting for completion "
   5354                     "Tx(%s)=%s Rx(%s)=%s\n",
   5355                     SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_tx_port),
   5356                     lw->lw_eoc_tx ? "Done" : "Pending",
   5357                     SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_rx_port),
   5358                     lw->lw_eoc_rx ? "Done" : "Pending");
   5359             rv = -1;
   5360             return rv;
   5361         } else {
   5362            level = sal_splhi();
   5363             lw->lw_sema_woke = FALSE;
   5364            sal_spl(level);
   5365         }
   5366     }
   5367 
   5368     rv = tx_done = lb_sg_check_tx(lw, ppc, tx_dpp, length);
   5369     if (rv < 0) {
   5370         return rv;
   5371     }
   5372     rv = rx_done = lb_sg_check_rx(lw, ppc, rx_dpp, length,
   5373                                   tx_offset, 0);
   5374 
   5375     return rv;
   5376 }
   5377 
   5378 STATIC  int
   5379 lb_do_sg_rx(loopback_test_t *lw, int p_len, int p_cnt, int dpp)
   5380 /*
   5381  * Function:    lb_do_sg_rx
   5382  * Purpose:     Start an RX for the specified length/chain.
   5383  * Parameters:  lw - pointer to lb work.
   5384  *              p_len - length of each packet.
   5385  *              p_cnt - # of packets per chain.
   5386  *              dpp  - # dcbs per packet.
   5387  * Returns:     0 - success, -1 failed.
   5388  */
   5389 {
   5390     dv_t        *dv = lw->lw_rx_dv[0];
   5391     loopback_testdata_t *lp = lw->lw_lp;
   5392     int         i;
   5393     pbmp_t      pbm;
   5394 
   5395     /*
   5396      * For RX, set flags to call out for each DCB completed.
   5397      */
   5398     soc_dma_dv_reset(DV_RX, dv);
   5399     dv->dv_flags |= DV_F_NOTIFY_DSC | DV_F_NOTIFY_CHN;
   5400     dv->dv_done_chain = lb_done_chain;
   5401     dv->dv_dsc  = 0;                    /* Start at descriptor 0 */
   5402     dv->dv_pckt = 0;                    /* Start at packet 0  */
   5403 
   5404     SOC_PBMP_CLEAR(pbm);
   5405     SOC_PBMP_PORT_ADD(pbm, lp->lp_tx_port);
   5406 
   5407 #ifdef BCM_XGS12_FABRIC_SUPPORT
   5408     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   5409         /* Update length */
   5410         LOG_INFO(BSL_LS_APPL_TESTS,
   5411                  (BSL_META("lb_do_sg_rx: p_len = %d\n"), p_len));
   5412         p_len += SOC_HIGIG_HDR_SIZE;
   5413     }
   5414 #endif
   5415 #ifdef BCM_XGS3_SWITCH_SUPPORT
   5416     if ((SOC_IS_XGS3_SWITCH(lw->lw_unit)) &&
   5417         (IS_ST_PORT(lw->lw_unit, lw->lw_lp->lp_rx_port))){
   5418         p_len += 4;
   5419     }
   5420 #endif
   5421     for (i = 0; i < p_cnt; i++) {
   5422 
   5423         /* Zero recv packet to help with debugging */
   5424 
   5425         sal_memset(lw->lw_rx_packets[i], 0, p_len);
   5426 
   5427         lb_setup_sg_dcbs(dv, p_len, dpp, FALSE, lw->lw_rx_packets[i], 4,
   5428                          pbm, lp->lp_ubm,
   5429                          crc_mode_to_dmac(lp->lp_crc_mode), 0, NULL);
   5430     }
   5431 
   5432     lw->lw_rx_dv_chain_done = dv;
   5433     lw->lw_eoc_rx = 0;
   5434 
   5435     return((soc_dma_start(lw->lw_unit, -1, dv) < 0) ? -1 : 0);
   5436 }
   5437 
   5438 STATIC int
   5439 lb_do_sg_tx(loopback_test_t *lw, int tx_offset, int tx_len,
   5440             int tx_ppc, int tx_dpp, int cos)
   5441 /*
   5442  * Function:    lb_do_sg_tx
   5443  * Purpose:     Start a transmit for the current length/chain.
   5444  * Parameters:  lw - pointer to lb work.
   5445  *              tx_offset - offset into TX buffer where to build packet.
   5446  *              tx_len - length of packet
   5447  *              tx_ppc - TX packets-per-chain.
   5448  *              tx_dpp - TX DCBs-per-packet.
   5449  *              cos    - Class of service
   5450  * Returns:     0 - success, -1 failed.
   5451  */
   5452 {
   5453     dv_t        *dv = lw->lw_tx_dv[0];
   5454     loopback_testdata_t *lp = lw->lw_lp;
   5455     int         i;
   5456     int         o_tx_len;
   5457     pbmp_t      pbm;
   5458     int         dmod = 0;
   5459 #ifdef BCM_HIGIG2_SUPPORT
   5460     soc_higig2_hdr_t    xgh;
   5461     uint32              *xghp = (uint32 *)&xgh;
   5462 #elif defined(BCM_XGS_SUPPORT)
   5463     soc_higig_hdr_t     xgh;
   5464     uint32              *xghp = (uint32 *)&xgh;
   5465 #else
   5466     uint32              *xghp = NULL;
   5467 #endif
   5468     
   5469 #ifdef BCM_XGS3_SWITCH_SUPPORT
   5470     if (SOC_IS_XGS3_SWITCH(lw->lw_unit)) {
   5471         BCM_IF_ERROR_RETURN(bcm_stk_my_modid_get(lw->lw_unit, &dmod));
   5472     }
   5473 #endif
   5474 
   5475     soc_dma_dv_reset(DV_TX, dv);
   5476     dv->dv_done_chain = lb_done_chain;
   5477     SET_NOTIFY_CHN_ONLY(dv->dv_flags);
   5478     dv->dv_dsc  = 0;                    /* Start descriptor 0 */
   5479     dv->dv_pckt = 0;                    /* Start at packet 0  */
   5480 
   5481     SOC_PBMP_CLEAR(pbm);
   5482     SOC_PBMP_PORT_ADD(pbm, lp->lp_tx_port);
   5483 
   5484     for (i = 0; i < tx_ppc; i++) {
   5485         uint8           *packet = lw->lw_tx_packets[i] + tx_offset;
   5486         int             tx_align = 1;
   5487 
   5488         if (soc_feature(lw->lw_unit, soc_feature_pkt_tx_align)) {
   5489             tx_align = 4;
   5490         }
   5491 
   5492         /* Build packet */
   5493         o_tx_len = tx_len;
   5494         lb_fill_packet_tx(lw, lp, packet, &tx_len,
   5495                           lw->lw_mac_dst, lw->lw_mac_src);
   5496 
   5497         lb_xgs3_higig_setup(lw, cos, dmod,
   5498                             lp->lp_tx_port, lp->lp_vlan, xghp);
   5499 #ifdef BCM_SHADOW_SUPPORT
   5500         if (SOC_IS_SHADOW(lw->lw_unit)) {
   5501             lb_setup_sg_dcbs(dv, tx_len, tx_dpp, TRUE,
   5502                              packet, tx_align, pbm, lp->lp_ubm, 
   5503                              crc_mode_to_dmac(lp->lp_crc_mode), cos, NULL);
   5504         } else 
   5505 #endif
   5506         {
   5507             lb_setup_sg_dcbs(dv, tx_len, tx_dpp, TRUE,
   5508                          packet, tx_align, pbm, lp->lp_ubm, 
   5509                          crc_mode_to_dmac(lp->lp_crc_mode), cos, xghp);
   5510         }
   5511 
   5512         tx_len = o_tx_len;
   5513     }
   5514 
   5515     lw->lw_tx_dv_chain_done = dv;
   5516     lw->lw_eoc_tx = 0;
   5517     return((soc_dma_start(lw->lw_unit, -1, dv) < 0) ? -1 : 0);
   5518 }
   5519 
   5520 int
   5521 lb_do_sg_txrx(loopback_test_t *lw)
   5522 /*
   5523  * Function:    lb_do_sg_txrx
   5524  * Purpose:     Loop over requested lengths and chaining sizes, and
   5525  *              transmit/receive packets.
   5526  * Parameters:  lw - pointer to work structure
   5527  * Returns:     0 - success
   5528  *              -1- failed.
   5529  */
   5530 {
   5531     loopback_testdata_t *lp = lw->lw_lp;
   5532     int         l_cur, cos_cur, c_count, cur_ppc;
   5533     int         tx_offset, tx_dpp, rx_dpp;
   5534     int         tx_align = 1;
   5535 
   5536     if (soc_feature(lw->lw_unit, soc_feature_pkt_tx_align)) {
   5537         tx_align = 4;
   5538     }
   5539 
   5540     LOG_INFO(BSL_LS_APPL_TESTS,
   5541              (BSL_META("Testing Port %s --> %s cnt(%d) chn(%d,%d += %d) "
   5542                        "l(%d,%d += %d) cos(%d,%d)\n"),
   5543               SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_tx_port),
   5544               SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_rx_port),
   5545               lp->lp_count,
   5546               lp->lp_c_start, lp->lp_c_end, lp->lp_c_inc,
   5547               lp->lp_l_start, lp->lp_l_end, lp->lp_l_inc,
   5548               lp->lp_cos_start, lp->lp_cos_end));
   5549 
   5550     for (l_cur = lp->lp_l_start;
   5551          l_cur <= lp->lp_l_end;
   5552          l_cur += lp->lp_l_inc) {
   5553         for (cos_cur = lp->lp_cos_start;
   5554              cos_cur <= lp->lp_cos_end;
   5555              cos_cur++) {
   5556             for (tx_offset = 0; tx_offset <= 3; tx_offset += tx_align) {
   5557                 for (cur_ppc = lp->lp_ppc_start;
   5558                      cur_ppc <= lp->lp_ppc_end;
   5559                      cur_ppc += lp->lp_ppc_inc) {
   5560                     for (tx_dpp = lp->lp_dpp_start;
   5561                          tx_dpp <= lp->lp_dpp_end;
   5562                          tx_dpp += lp->lp_dpp_inc) {
   5563                         for (rx_dpp = lp->lp_dpp_start;
   5564                              rx_dpp <= lp->lp_dpp_end;
   5565                              rx_dpp += lp->lp_dpp_inc) {
   5566                             LOG_INFO(BSL_LS_APPL_TESTS,
   5567                                      (BSL_META("Testing cnt=%d L=%d cos=%d "
   5568                                                "TX-offset=%d TX-dpp=%d "
   5569                                                "RX-dpp=%d\n"),
   5570                                       lp->lp_count, l_cur, cos_cur,
   5571                                       tx_offset, tx_dpp,
   5572                                       rx_dpp));
   5573                             for (c_count = 0;
   5574                                  c_count < lp->lp_count;
   5575                                  c_count++) {
   5576                                 lw->lw_sema_woke = FALSE;
   5577                                 lb_do_sg_rx(lw, l_cur, cur_ppc, rx_dpp);
   5578                                 lb_do_sg_tx(lw, tx_offset, l_cur, cur_ppc,
   5579                                             tx_dpp, cos_cur);
   5580 
   5581                                 if (lb_sg_wait(lw, l_cur,
   5582                                                cur_ppc, tx_dpp, tx_offset,
   5583                                                rx_dpp) < 0) {
   5584                                     test_error(lw->lw_unit,
   5585                                         "\tPort %s->%s\n"
   5586                                         "\tPacket Length=%d bytes\n"
   5587                                         "\tCurrent COS=%d\n"
   5588                                         "\tTX offset=%d\n"
   5589                                         "\tCurrent PPC=%d\n"
   5590                                         "\tTX DPP=%d\n"
   5591                                         "\tRX DPP=%d\n"
   5592                                         "\tCurrent Count (%d/%d)\n",
   5593                                         SOC_PORT_NAME(lw->lw_unit,
   5594                                                       lp->lp_tx_port),
   5595                                         SOC_PORT_NAME(lw->lw_unit,
   5596                                                       lp->lp_rx_port),
   5597                                         l_cur, cos_cur, tx_offset,
   5598                                         cur_ppc, tx_dpp, rx_dpp, 
   5599                                         c_count + 1, lp->lp_count);
   5600                                          return(-1);
   5601                                 }
   5602                                 lb_stats_report(lw);
   5603                             }
   5604                         }
   5605                     }
   5606                 }
   5607             }
   5608         }
   5609     }
   5610     return(0);
   5611 }
   5612 
   5613 int
   5614 lb_sg_dma_test(int unit, args_t *a, void *pa)
   5615 /*
   5616  * Function:    lb_sg_dma_test
   5617  * Purpose:     Perform simple interrupt driven DMA test.
   5618  * Parameters:  <see usage above>
   5619  * Returns:     0 - success
   5620  *              -1 - failed
   5621  */
   5622 {
   5623     loopback_test_t     *lw = (loopback_test_t *)pa;
   5624     loopback_testdata_t *lp = &lw->lw_lp_sg_dma;
   5625     int         rx_chan, tx_chan, chan;       /* RX/TX channel numbers */
   5626     int rv;
   5627 
   5628     lb_stats_init(lw);
   5629 
   5630     COMPILER_REFERENCE(a);
   5631 
   5632     if(soc_feature(unit, soc_feature_cmicx)) {
   5633         chan = CMICX_N_DMA_CHAN;
   5634     } else {
   5635         chan = N_DMA_CHAN;
   5636     }
   5637 
   5638     /*
   5639      * For each of the DMA channel configurations, run the entire test.
   5640      */
   5641 
   5642     lw->lw_lp = lp;                     /* Assign test # */
   5643     if ((lb_is_xgs_fabric(unit)) || (SOC_IS_XGS3_SWITCH(unit))) {
   5644         int port;
   5645         pbmp_t      tpbm;
   5646 
   5647         if (lb_is_xgs_fabric(unit)) {
   5648             SOC_PBMP_ASSIGN(tpbm, PBMP_PORT_ALL(unit));
   5649         } else {
   5650             SOC_PBMP_ASSIGN(tpbm, PBMP_E_ALL(unit));
   5651         }
   5652         PBMP_ITER(tpbm, port) {
   5653             break;
   5654         }
   5655         if (!SOC_PORT_VALID(unit,port)) {
   5656             test_error(unit, "No Ports available for loopback\n");
   5657             return(-1);
   5658         }
   5659         SOC_PBMP_PORT_ADD(lp->lp_pbm, port);
   5660         lp->lp_tx_port = port;
   5661         lp->lp_rx_port = port;
   5662         _lb_max_frame_set(lw, lp);
   5663         if ((rv = bcm_port_loopback_set(unit, port,
   5664                                         BCM_PORT_LOOPBACK_MAC)) < 0) {
   5665             test_error(unit,
   5666                    "Port %s: Failed to set MAC loopback: %s\n",
   5667                    SOC_PORT_NAME(unit, 1), bcm_errmsg(rv));
   5668             return(-1);
   5669         }
   5670 
   5671         if (IS_HG_PORT(unit, port)) {
   5672             bcm_port_pause_set(unit, port, FALSE, FALSE);
   5673         }
   5674         /*
   5675          * Get our current MAC address for this port and be sure the
   5676          * SOC will route packets to the CPU.
   5677          */
   5678         if (lb_setup_arl(lw, unit, CMIC_PORT(unit), port)) {
   5679             return(-1);
   5680         }
   5681         if (SOC_IS_XGS3_SWITCH(unit) && !(SOC_IS_SHADOW(unit))) {
   5682             pbmp_t              temp_pbmp;
   5683             SOC_PBMP_CLEAR(temp_pbmp);
   5684             /*
   5685              * Setup VLAN
   5686              */
   5687             SOC_PBMP_PORT_ADD(temp_pbmp, CMIC_PORT(unit));
   5688             SOC_PBMP_PORT_ADD(temp_pbmp, port);
   5689 			if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   5690 	            if ((rv = bcm_vlan_port_add(unit, lp->lp_vlan,
   5691 	                                        temp_pbmp, temp_pbmp)) < 0) {
   5692 	                test_error(unit,
   5693 	                           "Could not add all ports to VLAN %d: %s\n",
   5694 	                           lp->lp_vlan, bcm_errmsg(rv));
   5695 	                return (-1);
   5696 	            }
   5697 			}
   5698         }
   5699 
   5700         if ((rv = lb_setup_port(unit, port, LB_SPEED_MAX, FALSE)) < 0) { 
   5701             test_error(unit,
   5702                        "Port %s: Port setup failed: %s\n",
   5703                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   5704             return(-1);
   5705         }
   5706     } else {
   5707         lp->lp_tx_port = CMIC_PORT(unit);
   5708         lp->lp_rx_port = CMIC_PORT(unit);
   5709     }
   5710 
   5711     lw->lw_tx_dcb_factor = 1;
   5712 
   5713     for (rx_chan = 0; rx_chan < chan; rx_chan++) {
   5714 #ifdef INCLUDE_KNET
   5715         if (SOC_KNET_MODE(unit)) {
   5716             /* Currently KNET uses chan 1 for rx */
   5717             if (rx_chan != KCOM_DMA_RX_CHAN) {
   5718                 continue;
   5719             }
   5720         }
   5721 #endif /* INCLUDE_KNET */
   5722         LOG_INFO(BSL_LS_APPL_TESTS,
   5723                  (BSL_META_U(unit,
   5724                              "Configuring RX-channel: %d\n"), rx_chan));
   5725 
   5726         if (soc_dma_chan_config(unit, rx_chan, DV_RX, 
   5727                                 SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   5728             test_error(unit, "Unable to configure RX channel: %d\n", rx_chan);
   5729             break;
   5730         }
   5731 #ifdef BCM_CMICM_SUPPORT
   5732         /* Assign all COS to this channel
   5733          * Though this is added for CMICm, 
   5734          * it should be OK if we do this for CMICe as well */
   5735         if(soc_feature(unit, soc_feature_cmicm)) {
   5736             LOG_INFO(BSL_LS_APPL_TESTS,
   5737                      (BSL_META_U(unit,
   5738                                  "Assign all COS to channel: 1\n")));
   5739             SOC_IF_ERROR_RETURN(
   5740                 bcm_rx_queue_channel_set(unit, -1, rx_chan));
   5741 
   5742 #if defined(BCM_KATANA2_SUPPORT)
   5743                 if(SOC_IS_KATANA2(unit)) {
   5744                     uint32 reg_val, reg_addr;
   5745 
   5746                     /* Including CPU L0 bitmap to support CMIC backpressure */
   5747                     reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, rx_chan);
   5748                     reg_val = soc_pci_read(unit, reg_addr);
   5749                     reg_val |= (1 << 16);
   5750                     soc_pci_write(unit, reg_addr, reg_val);
   5751                 }
   5752 #endif
   5753 
   5754         }
   5755 #endif
   5756 #ifdef BCM_CMICX_SUPPORT
   5757         /* Assign all COS to this channel */
   5758         if(soc_feature(unit, soc_feature_cmicx)) {
   5759             LOG_INFO(BSL_LS_APPL_TESTS,
   5760                      (BSL_META_U(unit,
   5761                                  "Assign all COS to channel: 1\n")));
   5762             SOC_IF_ERROR_RETURN(
   5763                 bcm_rx_queue_channel_set(unit, -1, rx_chan));
   5764         }
   5765 #endif
   5766 
   5767         for (tx_chan = 0; tx_chan < chan; tx_chan++) {
   5768 #ifdef INCLUDE_KNET
   5769             if (SOC_KNET_MODE(unit)) {
   5770                 /* Currently KNET uses chan 0 for tx */
   5771                 if (tx_chan != KCOM_DMA_TX_CHAN) {
   5772                     continue;
   5773                 }
   5774             }
   5775 #endif /* INCLUDE_KNET */
   5776             if (rx_chan == tx_chan) {   /* Does not make sense */
   5777                 continue;
   5778             }
   5779 
   5780             LOG_INFO(BSL_LS_APPL_TESTS,
   5781                      (BSL_META_U(unit,
   5782                                  "Configuring TX-channel: %d\n"), tx_chan));
   5783 
   5784             if (soc_dma_chan_config(unit, tx_chan, DV_TX,
   5785                                     SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   5786                 test_error(unit,
   5787                            "Unable to configure TX channel: %d\n",
   5788                            tx_chan);
   5789                 break;
   5790             }
   5791 
   5792             if (lb_do_sg_txrx(lw)) {
   5793                 return -1;
   5794             }
   5795 
   5796             if (soc_dma_chan_config(unit, tx_chan, DV_NONE, 0)) {
   5797                 test_error(unit,
   5798                            "Unable to de-configure TX channel: %d\n",
   5799                            tx_chan);
   5800                 break;
   5801             }
   5802         }
   5803 
   5804         if (soc_dma_chan_config(unit, rx_chan, DV_NONE, 0)) {
   5805             test_error(unit,
   5806                        "Unable to de-configure RX channel: %d\n",
   5807                        rx_chan);
   5808             break;
   5809         }
   5810     }
   5811 
   5812     lb_stats_done(lw);
   5813 
   5814     return(0);
   5815 }
   5816 
   5817 int
   5818 lb_sg_dma_init(int unit, args_t *a, void **p)
   5819 /*
   5820  * Function:    lb_sg_dma_init
   5821  * Purpose:     Initialize scatter/gather DMA loopback test.
   5822  * Parameters:  unit - unit number.
   5823  *              a - pointer to arguments.
   5824  *              p - pointer passed to test function.
   5825  * Returns:     0 for success, -1 for failed.
   5826  */
   5827 {
   5828     loopback_test_t             *lw = &lb_work[unit];
   5829     loopback_testdata_t         *lp = &lw->lw_lp_sg_dma;
   5830     int                 i;
   5831     int                 rv = 0;
   5832     parse_table_t       pt;
   5833     int chan;
   5834 
   5835     if(soc_feature(unit, soc_feature_cmicx)) {
   5836         chan = CMICX_N_DMA_CHAN;
   5837     } else {
   5838         chan = N_DMA_CHAN;
   5839     }
   5840 
   5841     bcm_l2_addr_t_init(&lw->lw_arl_src, lb_mac_src, 1);
   5842     bcm_l2_addr_t_init(&lw->lw_arl_dst, lb_mac_dst, 1);
   5843 
   5844     parse_table_init(unit, &pt);
   5845     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   5846                     &lp->lp_pattern,NULL);
   5847     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL,0,
   5848                     &lp->lp_pattern_inc,NULL);
   5849     parse_table_add(&pt, "LengthStart", PQ_INT|PQ_DFL,  0,
   5850                     &lp->lp_l_start,NULL);
   5851     parse_table_add(&pt, "LengthEnd",   PQ_INT|PQ_DFL,  0,
   5852                     &lp->lp_l_end,      NULL);
   5853     parse_table_add(&pt, "LengthIncrement",PQ_INT|PQ_DFL,0,
   5854                     &lp->lp_l_inc,      NULL);
   5855     parse_table_add(&pt, "PacketsPerChainStart",PQ_INT|PQ_DFL,0,
   5856                     &lp->lp_ppc_start,NULL);
   5857     parse_table_add(&pt, "PacketsPerChainEnd",PQ_INT|PQ_DFL,0,
   5858                     &lp->lp_ppc_end,NULL);
   5859     parse_table_add(&pt, "PacketsPerChainInc",PQ_INT|PQ_DFL,0,
   5860                     &lp->lp_ppc_inc,NULL);
   5861     parse_table_add(&pt, "DcbsPerPacketStart",PQ_INT|PQ_DFL,0,
   5862                     &lp->lp_dpp_start,NULL);
   5863     parse_table_add(&pt, "DcbsPerPacketsEnd",PQ_INT|PQ_DFL,0,
   5864                     &lp->lp_dpp_end,NULL);
   5865     parse_table_add(&pt, "DcbsPerPacketInc",PQ_INT|PQ_DFL,0,
   5866                     &lp->lp_dpp_inc,NULL);
   5867     parse_table_add(&pt, "COSStart",    PQ_INT|PQ_DFL,  0,
   5868                     &lp->lp_cos_start,NULL);
   5869     parse_table_add(&pt, "COSEnd",      PQ_INT|PQ_DFL,  0,
   5870                     &lp->lp_cos_end,NULL);
   5871     parse_table_add(&pt, "Count",       PQ_INT|PQ_DFL,  0,
   5872                     &lp->lp_count,      NULL);
   5873     parse_table_add(&pt, "CheckData",   PQ_BOOL|PQ_DFL, 0,
   5874                     &lp->lp_check_data,NULL);
   5875     parse_table_add(&pt, "CheckCrc",    PQ_BOOL|PQ_DFL, 0,
   5876                     &lp->lp_check_crc,NULL);
   5877 
   5878     lb_setup(unit, lw);
   5879 
   5880     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   5881         test_error(unit,
   5882                    "%s: Invalid option: %s\n",
   5883                    ARG_CMD(a),
   5884                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   5885         parse_arg_eq_done(&pt);
   5886         return(-1);
   5887     }
   5888     parse_arg_eq_done(&pt);
   5889 
   5890 #ifdef INCLUDE_KNET
   5891     if (SOC_KNET_MODE(unit)) {
   5892         cli_out("Invalid test case under KNET mode.\n");
   5893         return(-1);
   5894     }
   5895 #endif /* INCLUDE_KNET */
   5896 
   5897     SOC_PBMP_CLEAR(lp->lp_pbm);
   5898     if ((lb_is_xgs_fabric(unit)) || (SOC_IS_XGS3_SWITCH(unit))) {
   5899         int port;
   5900         pbmp_t      tpbm;
   5901 
   5902         if (lb_is_xgs_fabric(unit)) {
   5903             SOC_PBMP_ASSIGN(tpbm, PBMP_PORT_ALL(unit));
   5904         } else {
   5905             SOC_PBMP_ASSIGN(tpbm, PBMP_E_ALL(unit));
   5906         }
   5907         PBMP_ITER(tpbm, port) {
   5908             break;
   5909         }
   5910         if (!SOC_PORT_VALID(unit,port)) {
   5911             test_error(unit, "No Ports available for loopback\n");
   5912             return(-1);
   5913         }
   5914         SOC_PBMP_PORT_ADD(lp->lp_pbm, CMIC_PORT(unit));
   5915         SOC_PBMP_PORT_ADD(lp->lp_pbm, port);
   5916         lp->lp_rx_port = port;
   5917     } else {
   5918         SOC_PBMP_PORT_ADD(lp->lp_pbm, CMIC_PORT(unit));
   5919         lp->lp_rx_port = CMIC_PORT(unit);
   5920     }
   5921 
   5922     /* Update chain sizes */
   5923 
   5924     lp->lp_c_start = lp->lp_ppc_start * lp->lp_dpp_start;
   5925     lp->lp_c_end   = lp->lp_ppc_end * lp->lp_dpp_end;
   5926     lp->lp_c_inc   = 1;
   5927 
   5928     lp->lp_sg = TRUE;
   5929 
   5930     if ((rv = lb_check_parms(lw, lp, lp->lp_pbm)) < 0) {
   5931         return(rv);
   5932     }
   5933 
   5934     /* Verify parameters make sense */
   5935 
   5936     if (lp->lp_ppc_start > lp->lp_ppc_end) {
   5937         test_error(lw->lw_unit,
   5938                    "Packets-per-chain start/end values don't make sense\n");
   5939         return(-1);
   5940     }
   5941 
   5942     /* Perform common loopback initialization */
   5943 
   5944     if (lb_init(unit, lw, lp, FALSE)) {
   5945         lb_sg_dma_done(unit, NULL);
   5946         return(-1);
   5947     }
   5948 
   5949     /*
   5950      * Allow us to run with external loopback cables plugged in as the
   5951      * BigMAC loopback allows the packets to go out on the wire.
   5952      */
   5953     if (lb_unused_10g_ports_enable_set(unit, lp->lp_rx_port, 0)) {
   5954         lb_sg_dma_done(unit, NULL);
   5955         return(-1);
   5956     }
   5957 
   5958     /* Set up MAC addresses (currently constant) */
   5959 
   5960     ENET_SET_MACADDR(lw->lw_mac_src, lb_mac_src);
   5961     ENET_SET_MACADDR(lw->lw_mac_dst, lb_mac_dst);
   5962 
   5963     if (!SOC_PBMP_MEMBER(lp->lp_pbm, CMIC_PORT(unit))) {
   5964         LOG_INFO(BSL_LS_APPL_TESTS,
   5965                  (BSL_META_U(unit,
   5966                              "Warning: CPU port not set in bitmap.\n"
   5967                              "Packet will not be received, receive DMA will hang.\n")));
   5968     }
   5969 
   5970     *p = lw;                            /* Pass back cookie */
   5971 
   5972     for (i = 0; i < chan; i++) {
   5973         LOG_INFO(BSL_LS_APPL_TESTS,
   5974                  (BSL_META_U(unit,
   5975                              "lb_dma_init: Deconfiguring channel %d\n"), i));
   5976 
   5977         if (soc_dma_chan_config(unit, i, DV_NONE, 0)) {
   5978             rv = -1;
   5979         }
   5980     }
   5981 
   5982     if (rv) {
   5983         lb_sg_dma_done(unit, NULL);
   5984     }
   5985 
   5986     return(rv);
   5987 }
   5988 
   5989 int
   5990 lb_sg_dma_done(int unit, void *pa)
   5991 /*
   5992  * Function:    lb_sg_dma_done
   5993  * Purpose:     Clean up after DMA loopback test.
   5994  * Parameters:  unit - unit number.
   5995  * Returns:     0 for success, -1 for failed.
   5996  */
   5997 {
   5998     COMPILER_REFERENCE(pa);
   5999 
   6000     lb_unused_10g_ports_enable_set(unit, lb_work[unit].lw_lp->lp_rx_port, 1);
   6001 
   6002     /* Re-configure channels */
   6003     lb_done(&lb_work[unit]);
   6004 
   6005     return(0);
   6006 }
   6007 
   6008 STATIC  void
   6009 lb_dump_dv(int unit, char *pfx, dv_t **dv_array, int dv_cnt)
   6010 /*
   6011  * Function:    lb_dump_dv
   6012  * Purpose:     Dump a DV list including RLD/Chained descriptors
   6013  * Parameters:  pfx - Prefix printed with messages
   6014  *              dv_array - array of dv pointers
   6015  *              dv_cnt - number of dvs to look at.
   6016  * Returns:     Nothing.
   6017  */
   6018 {
   6019     dv_t        *dv;
   6020     int         i = 0;
   6021 
   6022     while (i < dv_cnt) {
   6023         dv = dv_array[i];
   6024 
   6025         soc_dma_dump_dv(unit, pfx, dv);
   6026 
   6027         while (dv) {
   6028             dv = dv->dv_chain;
   6029             i++;
   6030         }
   6031     }
   6032 }
   6033 
   6034 int
   6035 lb_reload_init(int unit, args_t *a, void **p)
   6036 /*
   6037  * Function:    lb_reload_init
   6038  * Purpose:     Initialize loopback "reload" test.
   6039  * Parameters:  unit - unit #
   6040  *              a - pointer to args
   6041  *              p - pointer passed to test function.
   6042  * Returns:     0 - success
   6043  *              -1 - failed
   6044  */
   6045 {
   6046     loopback_test_t             *lw = &lb_work[unit];
   6047     loopback_testdata_t         *lp = &lw->lw_lp_sg_random;
   6048     int                 i;
   6049     int                 rv = 0;
   6050     parse_table_t       pt;
   6051     int chan;
   6052 
   6053     if(soc_feature(unit, soc_feature_cmicx)) {
   6054         chan = CMICX_N_DMA_CHAN;
   6055     } else {
   6056         chan = N_DMA_CHAN;
   6057     }
   6058 
   6059     bcm_l2_addr_t_init(&lw->lw_arl_src, lb_mac_src, 1);
   6060     bcm_l2_addr_t_init(&lw->lw_arl_dst, lb_mac_dst, 1);
   6061 
   6062     parse_table_init(unit, &pt);
   6063     parse_table_add(&pt, "Pattern",     PQ_HEX|PQ_DFL,  0,
   6064                     &lp->lp_pattern,NULL);
   6065     parse_table_add(&pt, "PatternIncrement",PQ_HEX|PQ_DFL,0,
   6066                     &lp->lp_pattern_inc,NULL);
   6067     parse_table_add(&pt, "PacketsPerChainStart",PQ_INT|PQ_DFL,0,
   6068                     &lp->lp_ppc_start,NULL);
   6069     parse_table_add(&pt, "PacketsPerChainEnd",PQ_INT|PQ_DFL,0,
   6070                     &lp->lp_ppc_end,NULL);
   6071     parse_table_add(&pt, "PacketsPerChainInc",PQ_INT|PQ_DFL,0,
   6072                     &lp->lp_ppc_inc,NULL);
   6073     parse_table_add(&pt, "LengthStart", PQ_INT|PQ_DFL,  0,
   6074                     &lp->lp_l_start,NULL);
   6075     parse_table_add(&pt, "LengthEnd",   PQ_INT|PQ_DFL,  0,
   6076                     &lp->lp_l_end,      NULL);
   6077     parse_table_add(&pt, "LengthIncrement",PQ_INT|PQ_DFL,0,
   6078                     &lp->lp_l_inc,      NULL);
   6079     parse_table_add(&pt, "DVStart",     PQ_INT|PQ_DFL,0,
   6080                     &lp->lp_dv_start,NULL);
   6081     parse_table_add(&pt, "DVEnd",       PQ_INT|PQ_DFL,0,
   6082                     &lp->lp_dv_end,NULL);
   6083     parse_table_add(&pt, "DVInc",       PQ_INT|PQ_DFL,0,
   6084                     &lp->lp_dv_inc,NULL);
   6085     parse_table_add(&pt, "DcbStart",    PQ_INT|PQ_DFL,0,
   6086                     &lp->lp_c_start,NULL);
   6087     parse_table_add(&pt, "DcbEnd",      PQ_INT|PQ_DFL,0,
   6088                     &lp->lp_c_end,NULL);
   6089     parse_table_add(&pt, "DcbIncrement",PQ_INT|PQ_DFL,0,
   6090                     &lp->lp_c_inc,NULL);
   6091     parse_table_add(&pt, "Count",       PQ_INT|PQ_DFL,  0,
   6092                     &lp->lp_count,      NULL);
   6093     parse_table_add(&pt, "SEED",        PQ_INT|PQ_DFL,  0,
   6094                     &lp->lp_seed,       NULL);
   6095     parse_table_add(&pt, "CheckData",   PQ_BOOL|PQ_DFL, 0,
   6096                     &lp->lp_check_data,NULL);
   6097     parse_table_add(&pt, "CheckCrc",    PQ_BOOL|PQ_DFL, 0,
   6098                     &lp->lp_check_crc,NULL);
   6099 
   6100     lb_setup(unit, lw);
   6101 
   6102     if (parse_arg_eq(a, &pt) < 0 || ARG_CNT(a) != 0) {
   6103         test_error(unit,
   6104                    "%s: Invalid option: %s\n",
   6105                    ARG_CMD(a),
   6106                    ARG_CUR(a) ? ARG_CUR(a) : "*");
   6107         parse_arg_eq_done(&pt);
   6108         return(-1);
   6109     }
   6110     parse_arg_eq_done(&pt);
   6111 
   6112 #ifdef INCLUDE_KNET
   6113     if (SOC_KNET_MODE(unit)) {
   6114         cli_out("Invalid test case under KNET mode.\n");
   6115         return(-1);
   6116     }
   6117 #endif /* INCLUDE_KNET */
   6118 
   6119     SOC_PBMP_CLEAR(lp->lp_pbm);
   6120     SOC_PBMP_PORT_ADD(lp->lp_pbm, CMIC_PORT(unit));
   6121     if ((lb_is_xgs_fabric(unit)) || (SOC_IS_XGS3_SWITCH(unit))) {
   6122         int port;
   6123         PBMP_PORT_ITER(unit, port) {
   6124             break;
   6125         }
   6126         if (!SOC_PORT_VALID(unit,port)) {
   6127             test_error(unit, "No Ports available for loopback\n");
   6128             return(-1);
   6129         }
   6130         SOC_PBMP_PORT_ADD(lp->lp_pbm, port);
   6131         lp->lp_tx_port = port;
   6132         lp->lp_rx_port = port;
   6133     } else {
   6134         lp->lp_tx_port = CMIC_PORT(unit);
   6135         lp->lp_rx_port = CMIC_PORT(unit);
   6136     }
   6137 
   6138     lp->lp_sg = TRUE;
   6139 
   6140     /* Perform common loopback initialization */
   6141 
   6142     if (lb_init(unit, lw, lp, FALSE)) {
   6143         return(-1);
   6144     }
   6145 
   6146     /*
   6147      * Allow us to run with external loopback cables plugged in as the
   6148      * BigMAC loopback allows the packets to go out on the wire.
   6149      */
   6150     if (lb_unused_10g_ports_enable_set(unit, lp->lp_rx_port, 0)) {
   6151         return(-1);
   6152     }
   6153 
   6154     /* Check Parameters and update useful things. */
   6155 
   6156     *p = lw;                            /* Pass back cookie */
   6157 
   6158     for (i = 0; i < chan; i++) {
   6159         LOG_INFO(BSL_LS_APPL_TESTS,
   6160                  (BSL_META_U(unit,
   6161                              "lb_dma_init: Deconfiguring channel %d\n"), i));
   6162 
   6163         if (soc_dma_chan_config(unit, i, DV_NONE, 0)) {
   6164             rv = -1;
   6165         }
   6166     }
   6167 
   6168     if (rv) {
   6169         lb_done(lw);
   6170     }
   6171 
   6172     return(rv);
   6173 }
   6174 
   6175 int
   6176 lb_random_init(int unit, args_t *a, void **p)
   6177 /*
   6178  * Function:    lb_random_init
   6179  * Purpose:     Initialize loopback "random" test.
   6180  * Parameters:  unit - unit #
   6181  *              a - pointer to args
   6182  *              p - pointer passed to test function.
   6183  * Returns:     0 - success
   6184  *              -1 - failed
   6185  */
   6186 {
   6187     /* Currently same as reload init */
   6188     return lb_reload_init(unit, a, p);
   6189 }
   6190 
   6191 int
   6192 lb_reload_done(int unit, void *pa)
   6193 /*
   6194  * Function:    lb_reload_done
   6195  * Purpose:     Clean up after reload test complete
   6196  * Parameters:  unit - unit #
   6197  *              pa - argument returned from init (may be NULL)
   6198  * Returns:     0 - success.
   6199  *              -1 - failed.
   6200  */
   6201 {
   6202     COMPILER_REFERENCE(pa);
   6203 
   6204     lb_unused_10g_ports_enable_set(unit, lb_work[unit].lw_lp->lp_rx_port, 1);
   6205 
   6206     lb_done(&lb_work[unit]);
   6207 
   6208     return(0);
   6209 }
   6210 
   6211 int
   6212 lb_random_done(int unit, void *pa)
   6213 /*
   6214  * Function:    lb_random_done
   6215  * Purpose:     Clean up after random test complete
   6216  * Parameters:  unit - unit #
   6217  *              pa - argument returned from init (may be NULL)
   6218  * Returns:     0 - success.
   6219  *              -1 - failed.
   6220  */
   6221 {
   6222     /* Currently same as reload done */
   6223     return lb_reload_done(unit, pa);
   6224 }
   6225 
   6226 #define LB_START_MAGIC  (('S' << 24) | ('t' << 16) | ('r' << 8) | 't')
   6227 #define LB_END_MAGIC    (('E' << 24) | ('n' << 16) | ('d' << 8) | 's')
   6228 
   6229 STATIC int
   6230 lb_random_restore_dv(int unit, uint8 *packet, int length,
   6231                      dv_t **dv_array, int *dv_idx, int dv_cnt)
   6232 /*
   6233  * Function:    lb_random_restore_dv
   6234  * Purpose:     Inspect dv/dcbs and copy out the received data into
   6235  *              a received buffer.
   6236  * Parameters:  unit - current unit number being operated on.
   6237  *              packet - pointer to packet to copy data into.
   6238  *              dv_array - pointer to array of pointers to dvs to fill in.
   6239  *              dv_idx - index into dv array of "current" dv, updated on
   6240  *                      return.
   6241  *              dv_cnt - total # DVs in DV list.
   6242  * Returns:     0 - OK.
   6243  *              -1 - failed.
   6244  * Notes:       Verifies the prefix/suffix Magic numbers.
   6245  */
   6246 {
   6247     dv_t                *dv = dv_array[*dv_idx];
   6248     dcb_t               *dcb;
   6249     dcb_t               *dcb_end;
   6250     int                 rv = 0;
   6251     int                 length_rcv = 0;
   6252     uint32              magic;                  /* 32-bit Magic Holder */
   6253 
   6254     if (NULL == dv) {
   6255         return -1;
   6256     }
   6257     dcb = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_dsc);
   6258     dcb_end = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt);
   6259 
   6260     while ((NULL !=dv) && (length_rcv < length)) {
   6261         uint8   *p;                     /* Current data pointer */
   6262 
   6263         /* Verify DCB is complete */
   6264 
   6265         if (!SOC_DCB_DONE_GET(unit, dcb)) {
   6266             cli_out("Expected DONE not set in dv[%d@%p] dcb[%d@%p]\n",
   6267                     *dv_idx, (void *)dv,
   6268                     SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb), (void *)dcb);
   6269             rv = -1;
   6270             break;
   6271         }
   6272 
   6273         /*
   6274          * Check for RELOAD, if this is a reload DCB, follow on to the
   6275          * new chain. The dv_chain pointer points to the next dv in the
   6276          * list.
   6277          */
   6278 
   6279         if (SOC_DCB_RELOAD_GET(unit, dcb)) {
   6280             (*dv_idx)++;
   6281             assert(*dv_idx < dv_cnt);
   6282             assert(dv_array[*dv_idx] == dv->dv_chain);
   6283             dv = dv_array[*dv_idx];
   6284             if (NULL == dv) {
   6285                 /* Internal error -- this list should be valid */
   6286                 return -1;
   6287             }
   6288             dcb = dv->dv_dcb;
   6289             dcb_end = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt);
   6290             continue;                   /* while */
   6291         }
   6292 
   6293         /* if first Chunk - verify SW set, if not verify not set */
   6294 
   6295         if (length_rcv == 0) {
   6296             if (!SOC_DCB_RX_START_GET(unit, dcb) && 
   6297                 !soc_feature(unit, soc_feature_dcb_st0_bug)) {
   6298                 cli_out("Expected Start dv[%d@%p] dcb[%d] not set\n",
   6299                         *dv_idx, (void *)dv,
   6300                         SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb));
   6301                 rv = -1;
   6302                 break;                  /* while */
   6303             }
   6304         } else if (SOC_DCB_RX_START_GET(unit, dcb)) {
   6305             cli_out("Un-expected Start dv[%d@%p] dcb[%d] set\n",
   6306                     *dv_idx, (void *)dv, 
   6307                     SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb));
   6308             rv = -1;
   6309             break;                      /* while */
   6310         }
   6311 
   6312         /*
   6313          * For current DCB, verify prefix/suffix.  Since it is receive,
   6314          * we know the length and alignment are multiples of 4.
   6315          */
   6316 
   6317         p = (uint8 *)SOC_DCB_ADDR_GET(unit, dcb);
   6318 
   6319         magic = packet_load(p - 4, 4);
   6320 
   6321         if (magic != LB_START_MAGIC) {
   6322             rv = -1;
   6323             cli_out("Prefix of block clobbered: "
   6324                     "Addr: %p Exp: 0x%x Rcv: 0x%x\n",
   6325                     (void *)(p - 4), LB_START_MAGIC, magic);
   6326             break;                      /* while */
   6327         }
   6328 
   6329         magic = packet_load(p + SOC_DCB_REQCOUNT_GET(unit, dcb), 4);
   6330 
   6331         if (magic != LB_END_MAGIC) {
   6332             rv = -1;
   6333             cli_out("Suffix of block clobbered: "
   6334                     "Addr: %p Exp: 0x%x Rcv: 0x%x\n",
   6335                     (void *)(p + SOC_DCB_REQCOUNT_GET(unit, dcb)), 
   6336                     LB_END_MAGIC, magic);
   6337             break;                      /* while */
   6338         }
   6339 
   6340         /* Don't run over expected length */
   6341 
   6342         if (SOC_DCB_XFERCOUNT_GET(unit, dcb) > (uint32)(length - length_rcv)) {
   6343             rv = -1;
   6344             cli_out("Too many bytes: Exp: <= 0x%x Rcv: 0x%x\n",
   6345                     length - length_rcv, SOC_DCB_XFERCOUNT_GET(unit, dcb));
   6346             break;                      /* while */
   6347         }
   6348 
   6349         length_rcv += SOC_DCB_XFERCOUNT_GET(unit, dcb);
   6350 
   6351         /* Copy out data */
   6352 
   6353         sal_memcpy(packet, p, SOC_DCB_XFERCOUNT_GET(unit, dcb));
   6354 
   6355         packet += SOC_DCB_XFERCOUNT_GET(unit, dcb);
   6356 
   6357         /* Verify EW bit settings */
   6358 
   6359         if (length_rcv >= length) {
   6360             if (!SOC_DCB_RX_END_GET(unit, dcb)) {
   6361                 cli_out("Expected End dv[%d] dcb[%d] not set\n",
   6362                         *dv_idx, SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb));
   6363                 rv = -1;
   6364                 break;                  /* while */
   6365             }
   6366         } else if (SOC_DCB_RX_END_GET(unit, dcb)) {
   6367             cli_out("Un-expected End dv[%d] dcb[%d] set\n",
   6368                     *dv_idx, SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb));
   6369             rv = -1;
   6370             break;                      /* while */
   6371         }
   6372 
   6373         /*
   6374          * Move to next dcb, if in current DV, simple increment,
   6375          * otherwise, must follow the dv_chain pointer to the next
   6376          * dcb, verify the expected completion status for the dcb.
   6377          * The very last DCB in the entire chain of chains is also
   6378          * special since.
   6379          */
   6380 
   6381         dcb = SOC_DCB_IDX2PTR(unit, dcb, 1);
   6382 
   6383         if (dcb == dcb_end) {           /* On to next DV */
   6384             (*dv_idx)++;
   6385             if (*dv_idx == dv_cnt) {    /* End of DVs */
   6386                 dv = NULL;
   6387                 break;
   6388             } else {
   6389                 dv = dv_array[*dv_idx];
   6390                 if (NULL == dv) {
   6391                     /* Internal error -- this list should be valid */
   6392                     return -1;
   6393                 }
   6394                 dcb = dv->dv_dcb;
   6395                 dcb_end = SOC_DCB_IDX2PTR(unit, dv->dv_dcb, dv->dv_vcnt);
   6396             }
   6397         }
   6398 
   6399     } /* while */
   6400 
   6401     if (dv) {
   6402         dv->dv_dsc = SOC_DCB_PTR2IDX(unit, dcb, dv->dv_dcb); /* Update current */
   6403     }
   6404 
   6405     if (length_rcv < length) { /* Something went wrong */
   6406         cli_out("End of chain and length-received=%d expected=%d\n",
   6407                 length_rcv, length);
   6408         rv = -1;
   6409     }
   6410 
   6411     return(rv);
   6412 }
   6413 
   6414 STATIC int
   6415 lb_random_setup_dv(int unit, uint8 *packet, int length, int align, int *dcb_cnt,
   6416                    int dv_idx, int dv_max_dcb, dv_t *dv_array[], pbmp_t pbm,
   6417                    pbmp_t ubm, int cos, uint32 *hgh)
   6418 /*
   6419  * Function:    lb_random_setup_dv
   6420  * Purpose:     Setup dcb/DV chain in "random" manner, allocate memory
   6421  *              for EACH segment, add sentinel at beginning/end.
   6422  * Parameters:  packet - pointer to packet data, if NULL, buffers
   6423  *                      allocated but not filled in.
   6424  *              length - # bytes in packets.
   6425  *              align - alignment requirements (1 for TX, 4 for RX)
   6426  *              dcb_cnt - Maximum # of DCBs to use on entry, number used
   6427  *                      on return.
   6428  *              dv_idx - current index in DV list working on.
   6429  *              dv_max_dcb - max number of DCBs to use in a dv.
   6430  *              dv_array - array of DVs to fill in.
   6431  *              pbm/ubm/cos - values used for DCB fields.
   6432  *              hgh - Higig header for XGS3 devices
   6433  * Returns:     index into dv_array where finished.
   6434  */
   6435 {
   6436     dv_t        *dv = dv_array[dv_idx];
   6437     uint8       *p;
   6438     int         dcb_idx, dcb_length, dcb_align;
   6439     int         max_dcbs = *dcb_cnt;
   6440     int         dcb_used = 0;
   6441     pbmp_t      l3pbm;
   6442     uint32      flags = SOC_DMA_COS(cos);
   6443 #ifdef BCM_XGS3_SWITCH_SUPPORT
   6444     if (hgh != NULL) {
   6445         SOC_DMA_HG_SET(flags, 1);
   6446         SOC_DMA_STATS_SET(flags, 1);
   6447     }
   6448 #endif
   6449 
   6450     dcb_idx = dv->dv_vcnt;
   6451 
   6452     assert(dcb_idx <= dv_max_dcb);
   6453 
   6454     SOC_PBMP_CLEAR(l3pbm);
   6455 
   6456     while (length > 0) {
   6457         /* If require next DV, link onto last, and bump dv idx/pointer */
   6458 
   6459         assert(dcb_idx <= dv_max_dcb);
   6460 
   6461         if (dcb_idx == dv_max_dcb) {
   6462             dv = dv_array[++dv_idx];
   6463             dcb_idx = 0;
   6464             if (dv_idx && (sal_rand() & (0x8080))) {
   6465                 soc_dma_dv_join(dv_array[dv_idx - 1], dv);
   6466             }
   6467         }
   6468 
   6469         if (max_dcbs == 1) {
   6470             /*
   6471              * This MUST be our last DCB - consume rest of packet.
   6472              */
   6473             dcb_length = length;
   6474         } else {
   6475             dcb_length = sal_rand() % length;
   6476             dcb_length |= dcb_length ? 0 : 1; /* Be sure 1 byte */
   6477         }
   6478 
   6479         dcb_align  = sal_rand() & -align & 3;
   6480         dcb_length = (dcb_length + align - 1) & -align;
   6481         length -= dcb_length;
   6482 
   6483         /*
   6484          * Based on the length, allocate that # bytes, +4 for magic at
   6485          * head + 4 for magic at tail +4 for arbitrary alignment.
   6486          */
   6487 
   6488         p = soc_cm_salloc(unit,
   6489                           SOC_DMA_ROUND_LEN(dcb_length + 4 + 4 + 4),
   6490                           "LB-Rand");
   6491 
   6492         /* set data in header/tail */
   6493 
   6494         packet_store(p, dcb_align + 4, LB_START_MAGIC, 0);
   6495         p += dcb_align + 4;             /* Move past prefix */
   6496         packet_store(p + dcb_length, 4, LB_END_MAGIC, 0);
   6497 
   6498         if (packet) {
   6499             /* Copy in packet data - if supplied */
   6500             sal_memcpy(p, packet, dcb_length);
   6501             packet += dcb_length;       /* Bump packet contents pointer */
   6502         }
   6503 
   6504         /*
   6505          * We now have the length for the next DCB, if 'length' is now
   6506          * <= 0, S/G is set to 0, otherwise it is set to 1.
   6507          */
   6508 
   6509         soc_dma_desc_add(dv, (sal_vaddr_t)p, dcb_length, pbm, ubm, l3pbm,
   6510                          flags, (uint32 *)hgh);
   6511 
   6512         max_dcbs--;
   6513 
   6514         dcb_idx++;
   6515         dcb_used++;
   6516     }
   6517 
   6518     soc_dma_desc_end_packet(dv);
   6519     *dcb_cnt = dcb_used;
   6520 
   6521     return(dv_idx);
   6522 }
   6523 
   6524 
   6525 void
   6526 lb_reset_dv(int unit, dv_t **dv_array, int dv_cnt)
   6527 /*
   6528  * Function:    lb_reset_dv
   6529  * Purpose:     Reset the current dv list to a clean state.
   6530  * Parameters:  dv_array - array of pointers to dv structures to reset
   6531  *              dv_cnt - # of dv pointers in dv_array.
   6532  * Returns:     Nothing
   6533  */
   6534 {
   6535     sal_vaddr_t         addr;
   6536     dcb_t               *dcb;
   6537     int                 i; 
   6538 
   6539     while (dv_cnt--) {
   6540         dv_array[dv_cnt]->dv_pckt = 0;
   6541         dv_array[dv_cnt]->dv_dsc  = 0;
   6542 
   6543         /* Free memory */
   6544 
   6545         for (i = 0; i < dv_array[dv_cnt]->dv_vcnt; i++) {
   6546             dcb = SOC_DCB_IDX2PTR(unit, dv_array[dv_cnt]->dv_dcb, i);
   6547 
   6548             /* Don't free reload */
   6549             if (!SOC_DCB_RELOAD_GET(unit, dcb) &&
   6550                 SOC_DCB_ADDR_GET(unit, dcb)) {
   6551                 /* Before prefix */
   6552                 addr = (SOC_DCB_ADDR_GET(unit, dcb) & -4) - 4;
   6553                 soc_cm_sfree(unit, (void *)addr);
   6554                 SOC_DCB_ADDR_SET(unit, dcb, 0);
   6555             }
   6556         }
   6557 
   6558         soc_dma_dv_reset(dv_array[dv_cnt]->dv_op, dv_array[dv_cnt]);
   6559     }
   6560 }
   6561 
   6562 
   6563 STATIC  int
   6564 lb_random_pkt(loopback_test_t *lw, loopback_testdata_t *lp, dma_chan_t tx_chan,
   6565               dma_chan_t rx_chan, int l, int p_cnt, int c_cnt, int dv_cnt)
   6566 /*
   6567  * Function:    lb_random_pkt
   6568  * Purpose:     Setup and transmit/receive random packets.
   6569  *              scatter/gather DMA and unaligned address DMA.
   6570  * Parameters:  lw - pointer to work structure
   6571  *              lp - pointer to parameters
   6572  *              tx_chan - transmit channel #
   6573  *              rx_chan - receive channel #.
   6574  *              l - length of packet to transmit.
   6575  *              p_cnt - total number of packets to place in current
   6576  *                      dv/dcb list.
   6577  *              c_cnt - current # dcbs to use for packets in each dv.
   6578  *              dv_cnt - total # of DV's to use for p_cnt packets.
   6579  * Returns:     0 - success
   6580  *              -1 - failed
   6581  */
   6582 {
   6583     int         tx_dv_idx, rx_dv_idx, p_idx;
   6584     int         rx_dcb_remain, tx_dcb_remain;
   6585     int         dcb_cnt;
   6586     int         tx_rv, rx_rv;
   6587     int         rv = 0, i;
   6588     pbmp_t      port_pbm, empty_pbm;
   6589     int         o_l;
   6590     int         skip_vlan = 0;
   6591     int         dmod = 0;
   6592     int        level = 0;
   6593 #ifdef BCM_HIGIG2_SUPPORT
   6594     soc_higig2_hdr_t    xgh;
   6595     uint32              *xghp = (uint32 *)&xgh;
   6596 #elif defined(BCM_XGS_SUPPORT)
   6597     soc_higig_hdr_t     xgh;
   6598     uint32              *xghp = (uint32 *)&xgh;
   6599 #else
   6600     uint32              *xghp = NULL;
   6601 #endif
   6602 #ifdef BCM_XGS3_SWITCH_SUPPORT
   6603     if (SOC_IS_XGS3_SWITCH(lw->lw_unit)) {
   6604         BCM_IF_ERROR_RETURN(bcm_stk_my_modid_get(lw->lw_unit, &dmod));
   6605         if (IS_ST_PORT(lw->lw_unit, lw->lw_lp->lp_rx_port)) {
   6606             skip_vlan = 1;
   6607         }
   6608     }
   6609 #endif
   6610 
   6611     LOG_INFO(BSL_LS_APPL_TESTS,
   6612              (BSL_META("Random: Tx-chan(%d) Rx-chan(%d) l=%d pkt-cnt=%d "
   6613                        "chn-cnt=%d dv-cnt=%d\n"),
   6614               tx_chan, rx_chan, l, p_cnt, c_cnt, dv_cnt));
   6615 
   6616     SOC_PBMP_CLEAR(empty_pbm);
   6617     SOC_PBMP_CLEAR(port_pbm);
   6618     SOC_PBMP_PORT_ADD(port_pbm, lp->lp_tx_port);
   6619 
   6620     /*
   6621      * For number of packets desired, fill in DV/DCB, each
   6622      * packet is allowed a maximum of #remaining
   6623      * DCBs/#remaining packets.
   6624      */
   6625 
   6626     dcb_cnt = c_cnt * dv_cnt;           /* Total DCB count */
   6627 
   6628     rx_dcb_remain = dcb_cnt;
   6629     tx_dcb_remain = dcb_cnt;
   6630 
   6631     tx_dv_idx = 0;
   6632     rx_dv_idx = 0;
   6633 
   6634     for (p_idx = 0; p_idx < p_cnt; p_idx++) {
   6635         int     tmp_dcb_cnt;
   6636         int     tx_align = 1;
   6637 
   6638         if (soc_feature(lw->lw_unit, soc_feature_pkt_tx_align)) {
   6639             tx_align = 4;
   6640         }
   6641 
   6642         /* Build packet */
   6643 
   6644         lb_xgs3_higig_setup(lw, 0, dmod,
   6645                             lp->lp_tx_port, lp->lp_vlan, xghp);
   6646 
   6647         o_l = l;
   6648         lb_fill_packet_tx(lw, lp, lw->lw_tx_packets[p_idx], &l,
   6649                           lw->lw_mac_dst, lw->lw_mac_src);
   6650 
   6651         tmp_dcb_cnt = tx_dcb_remain / (p_cnt - p_idx);
   6652         tx_dv_idx =
   6653             lb_random_setup_dv(lw->lw_unit, lw->lw_tx_packets[p_idx],
   6654                                l, tx_align, &tmp_dcb_cnt,
   6655                                tx_dv_idx, c_cnt, lw->lw_tx_dv,
   6656                                port_pbm, lp->lp_ubm, 0, xghp);
   6657         tx_dcb_remain -= tmp_dcb_cnt;
   6658         tmp_dcb_cnt = rx_dcb_remain / (p_cnt - p_idx);
   6659 #ifdef BCM_XGS3_SWITCH_SUPPORT
   6660         if ((SOC_IS_XGS3_SWITCH(lw->lw_unit)) &&
   6661             (IS_ST_PORT(lw->lw_unit, lw->lw_lp->lp_rx_port))) {
   6662             l += 4;
   6663         }
   6664 #endif
   6665         rx_dv_idx =
   6666             lb_random_setup_dv(lw->lw_unit, NULL, l, 4,
   6667                                &tmp_dcb_cnt,
   6668                                rx_dv_idx, c_cnt, lw->lw_rx_dv,
   6669                                empty_pbm, empty_pbm, 0, NULL);
   6670         l = o_l;
   6671         rx_dcb_remain -= tmp_dcb_cnt;
   6672 
   6673         lw->lw_tx_bytes += l;
   6674         lw->lw_tx_count++;
   6675     }
   6676 
   6677     /* Now fire off dma for Tx and Rx */
   6678 
   6679     lw->lw_eoc_tx = FALSE;
   6680     lw->lw_eoc_rx = FALSE;
   6681 
   6682     rx_rv = SOC_E_NONE;
   6683     tx_rv = SOC_E_NONE;
   6684 
   6685     for (i = 0; (rx_rv == SOC_E_NONE) && (i <= rx_dv_idx); i++) {
   6686         dv_t    *dv, *dv_start = lw->lw_rx_dv[i];
   6687 
   6688         for (dv = dv_start; dv->dv_chain; i++, dv = dv->dv_chain)
   6689             ;
   6690 
   6691         if (i == rx_dv_idx) {           /* Last chain */
   6692             /*
   6693              * dv_start points to beginning of LAST dv-joined chain, set
   6694              * NOTIFY_CHN in that DV only.
   6695              */
   6696             dv_start->dv_flags |= DV_F_NOTIFY_CHN;
   6697             lw->lw_rx_dv_chain_done = dv_start;
   6698         }
   6699 
   6700         if ((rx_rv = soc_dma_start(lw->lw_unit, rx_chan, dv_start)) < 0) {
   6701             break;
   6702         }
   6703     }
   6704 
   6705     for (i = 0;
   6706          (rx_rv == SOC_E_NONE) && (tx_rv == SOC_E_NONE) && i <= tx_dv_idx;
   6707          i++) {
   6708         dv_t    *dv, *dv_start = lw->lw_tx_dv[i];
   6709 
   6710         for (dv = dv_start; dv->dv_chain; i++, dv = dv->dv_chain)
   6711             ;
   6712 
   6713         if (i == tx_dv_idx) {
   6714             /*
   6715              * dv_start points to beginning of LAST dv-joined chain, set
   6716              * NOTIFY_CHN in that DV only.
   6717              */
   6718             dv_start->dv_flags |= DV_F_NOTIFY_CHN;
   6719             lw->lw_tx_dv_chain_done = dv_start;
   6720         }
   6721 
   6722         if ((tx_rv = soc_dma_start(lw->lw_unit, tx_chan, dv_start)) < 0) {
   6723             break;
   6724         }
   6725     }
   6726 
   6727     if (tx_rv < 0 || rx_rv < 0) {
   6728         rv = -1;
   6729         test_error(lw->lw_unit,
   6730                    "Unexpected Tx/Rx Status: tx=%s rx=%s\n",
   6731                    soc_errmsg(tx_rv), soc_errmsg(rx_rv));
   6732     } else {
   6733         int     dv_idx = 0;
   6734 
   6735         /* Wait for completion */
   6736 
   6737         while (!lw->lw_eoc_tx || !lw->lw_eoc_rx) {
   6738             if (sal_sem_take(lw->lw_sema, lw->lw_timeout_usec)) {
   6739                 cli_out("Time-out waiting for completion "
   6740                         "Tx(%s)=%s Rx(%s)=%s\n",
   6741                         SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_tx_port),
   6742                         lw->lw_eoc_tx ? "Done" : "Pending",
   6743                         SOC_PORT_NAME(lw->lw_unit, lw->lw_lp->lp_rx_port),
   6744                         lw->lw_eoc_rx ? "Done" : "Pending");
   6745                 rv = -1;
   6746                 break;
   6747             } else {
   6748                level = sal_splhi();
   6749                 lw->lw_sema_woke = FALSE;
   6750                sal_spl(level);
   6751             }
   6752         }
   6753 
   6754         /*
   6755          * Copy data out into normal rcv buffers - checking
   6756          * the start/end sentinels.
   6757          */
   6758 
   6759 #ifdef BCM_XGS12_FABRIC_SUPPORT
   6760     if (SOC_IS_XGS12_FABRIC(lw->lw_unit)) {
   6761         /* Update length */
   6762         LOG_INFO(BSL_LS_APPL_TESTS,
   6763                  (BSL_META("lb_random_restore_dv: l = %d\n"), l));
   6764         l += SOC_HIGIG_HDR_SIZE;
   6765     }
   6766 #endif
   6767         for (p_idx = 0; !rv && (p_idx < p_cnt); p_idx++) {
   6768             rv |= lb_random_restore_dv(lw->lw_unit,
   6769                                        lw->lw_rx_packets[p_idx],
   6770                                        l + (skip_vlan ? 4 : 0),
   6771                                        lw->lw_rx_dv,
   6772                                        &dv_idx, dv_cnt);
   6773             if (rv) {
   6774                 break;
   6775             }
   6776         }
   6777 
   6778         /* Verify Data */
   6779 
   6780         if (!rv && lp->lp_check_data) {
   6781             for (p_idx = 0; p_idx < p_cnt; p_idx++) {
   6782                 rv |= lb_check_packet(lw,
   6783                                       lw->lw_tx_packets[p_idx], l,
   6784                                       lw->lw_rx_packets[p_idx], 
   6785                                       l + (skip_vlan ? 4 : 0),
   6786                                       lp->lp_check_crc,
   6787                                       lw->lw_mac_dst, lw->lw_mac_src, skip_vlan);
   6788                 lw->lw_rx_bytes += l;
   6789                 lw->lw_rx_count++;
   6790             }
   6791         }
   6792     }
   6793 
   6794     /* If an error occurred, dump the DVs now */
   6795 
   6796     if (rv) {
   6797         lb_dump_dv(lw->lw_unit, "Rand-Tx:", lw->lw_tx_dv, tx_dv_idx + 1);
   6798         lb_dump_dv(lw->lw_unit, "Rand-Rx:", lw->lw_rx_dv, rx_dv_idx + 1);
   6799         test_error(lw->lw_unit, "Something went wrong folks\n");
   6800         soc_dma_abort(lw->lw_unit);  /* Abort active DMAs before reset_dv */
   6801     }
   6802 
   6803     /* Free up allocated memory */
   6804 
   6805     lb_reset_dv(lw->lw_unit, lw->lw_rx_dv, dv_cnt);
   6806     lb_reset_dv(lw->lw_unit, lw->lw_tx_dv, dv_cnt);
   6807 
   6808     lw->lw_tx_dv_chain_done = NULL;
   6809     lw->lw_rx_dv_chain_done = NULL;
   6810 
   6811     return(rv);
   6812 }
   6813 
   6814 int
   6815 lb_random_exec(int unit, loopback_test_t *lw, int dry_run)
   6816 {
   6817     loopback_testdata_t *lp = lw->lw_lp;
   6818     dma_chan_t  tx_chan, rx_chan, chan;
   6819     int         c_cur, l_cur, p_cur, dv_cur;
   6820     int         rv = 0;
   6821 
   6822     if(soc_feature(lw->lw_unit, soc_feature_cmicx)) {
   6823         chan = CMICX_N_DMA_CHAN;
   6824     } else {
   6825         chan = N_DMA_CHAN;
   6826     }
   6827 
   6828     for (tx_chan = 0; tx_chan < chan; tx_chan++) {
   6829 #ifdef INCLUDE_KNET
   6830         if (SOC_KNET_MODE(unit)) {
   6831             /* Currently KNET uses chan 0 for tx */
   6832             if (tx_chan != KCOM_DMA_TX_CHAN) {
   6833                 continue;
   6834             }
   6835         }
   6836 #endif /* INCLUDE_KNET */
   6837         if (soc_dma_chan_config(lw->lw_unit, tx_chan,
   6838                                 DV_TX, SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   6839             test_error(lw->lw_unit,
   6840                        "Unable to configure TX channel: %d\n",
   6841                        tx_chan);
   6842             break;
   6843         }
   6844 
   6845         for (rx_chan = 0; rx_chan < chan; rx_chan++) {
   6846 #ifdef INCLUDE_KNET
   6847             if (SOC_KNET_MODE(unit)) {
   6848                 /* Currently KNET uses chan 1 for rx */
   6849                 if (rx_chan != KCOM_DMA_RX_CHAN) {
   6850                     continue;
   6851                 }
   6852             }
   6853 #endif /* INCLUDE_KNET */
   6854             if (rx_chan == tx_chan) {
   6855                 continue;
   6856             }
   6857             if (soc_dma_chan_config(lw->lw_unit, rx_chan,
   6858                                     DV_RX, SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   6859                 test_error(lw->lw_unit,
   6860                            "Unable to configure RX channel: %d\n",
   6861                            rx_chan);
   6862                 break;
   6863             }
   6864 #ifdef BCM_CMICM_SUPPORT
   6865             /* Assign all COS to this channel
   6866              * Though this is added for CMICm, 
   6867              * it should be OK if we do this for CMICe as well */
   6868             if(soc_feature(lw->lw_unit, soc_feature_cmicm)) {
   6869                 LOG_INFO(BSL_LS_APPL_TESTS,
   6870                          (BSL_META("Assign all COS to channel: 1\n")));
   6871                 SOC_IF_ERROR_RETURN(
   6872                     bcm_rx_queue_channel_set(lw->lw_unit, -1, rx_chan));
   6873 
   6874 #if defined(BCM_KATANA2_SUPPORT)
   6875                 if(SOC_IS_KATANA2(unit)) {
   6876                     uint32 reg_val, reg_addr;
   6877 
   6878                     /* Including CPU L0 bitmap to support CMIC backpressure */
   6879                     reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, rx_chan);
   6880                     reg_val = soc_pci_read(unit, reg_addr);
   6881                     reg_val |= (1 << 16);
   6882                     soc_pci_write(unit, reg_addr, reg_val);
   6883                 }
   6884 #endif
   6885 
   6886             }
   6887 #endif
   6888 #ifdef BCM_CMICX_SUPPORT
   6889             /* Assign all COS to this channel */
   6890             if(soc_feature(lw->lw_unit, soc_feature_cmicx)) {
   6891                 LOG_INFO(BSL_LS_APPL_TESTS,
   6892                          (BSL_META("Assign all COS to channel: 1\n")));
   6893                 SOC_IF_ERROR_RETURN(
   6894                     bcm_rx_queue_channel_set(lw->lw_unit, -1, rx_chan));
   6895             }
   6896 #endif
   6897             for (p_cur = lp->lp_ppc_start;
   6898                  !rv && p_cur <= lp->lp_ppc_end;
   6899                  p_cur += lp->lp_ppc_inc) {
   6900                 for (c_cur = lp->lp_c_start;
   6901                      !rv && c_cur<=lp->lp_c_end;
   6902                      c_cur += lp->lp_c_inc) {
   6903                     for (l_cur = lp->lp_l_start;
   6904                          !rv && l_cur <= lp->lp_l_end;
   6905                          l_cur += lp->lp_l_inc) {
   6906                         for (dv_cur = lp->lp_dv_start;
   6907                              !rv && dv_cur <= lp->lp_dv_end;
   6908                              dv_cur += lp->lp_dv_inc) {
   6909                             if (p_cur >= c_cur * dv_cur) {
   6910                                 continue;
   6911                             }
   6912 
   6913                             if (dry_run) {
   6914                                 lw->lw_tx_total += p_cur;
   6915                             } else if (lb_random_pkt(lw, lp,
   6916                                                      tx_chan, rx_chan,
   6917                                                      l_cur, p_cur, c_cur,
   6918                                                      dv_cur) < 0) {
   6919                                 rv = -1;
   6920                                 break;
   6921                             } else {
   6922                                 lb_stats_report(lw);
   6923                             }
   6924                         }
   6925                     }
   6926                 }
   6927             }
   6928 
   6929             if (soc_dma_chan_config(lw->lw_unit, rx_chan,
   6930                                     DV_NONE, SOC_DMA_F_INTR)) {
   6931                 test_error(lw->lw_unit,
   6932                            "Unable to de-configure RX channel: %d\n",
   6933                            rx_chan);
   6934                 break;
   6935             }
   6936         }
   6937 
   6938         if (soc_dma_chan_config(lw->lw_unit, tx_chan,
   6939                                 DV_NONE, SOC_DMA_F_INTR)) {
   6940             test_error(lw->lw_unit,
   6941                        "Unable to de-configure TX channel: %d\n",
   6942                        tx_chan);
   6943             break;
   6944         }
   6945     }
   6946 
   6947     return(rv);
   6948 }
   6949 
   6950 int
   6951 lb_random_test(int unit, args_t *a, void *pa)
   6952 /*
   6953  * Function:    lb_random_test
   6954  * Purpose:     Perform random packet loopback.
   6955  * Parameters:  lw - pointer to work structure.
   6956  *              lp - pointer to work parameters.
   6957  *              pa - parameter returned from lb_random_init.
   6958  * Returns:     0 - success
   6959  *              -1 - failed
   6960  */
   6961 {
   6962     loopback_test_t     *lw = (loopback_test_t *)pa;
   6963     loopback_testdata_t *lp = lw->lw_lp;
   6964     int         rv, count;
   6965 
   6966     COMPILER_REFERENCE(unit);
   6967     COMPILER_REFERENCE(a);
   6968 
   6969     if ((lb_is_xgs_fabric(unit)) || (SOC_IS_XGS3_SWITCH(unit))) {
   6970         int port;
   6971         PBMP_PORT_ITER(unit, port) {
   6972             break;
   6973         }
   6974         if (!SOC_PORT_VALID(unit,port)) {
   6975             test_error(unit, "No Ports available for loopback\n");
   6976             return(-1);
   6977         }
   6978         lp->lp_tx_port = port;
   6979         lp->lp_rx_port = port;
   6980 
   6981         _lb_max_frame_set(lw, lp);
   6982         if ((rv = bcm_port_loopback_set(unit, port,
   6983                                         BCM_PORT_LOOPBACK_MAC)) < 0) {
   6984             test_error(unit,
   6985                    "Port %s: Failed to set MAC loopback: %s\n",
   6986                    SOC_PORT_NAME(unit, 1), bcm_errmsg(rv));
   6987             return(-1);
   6988         }
   6989 
   6990         if (IS_HG_PORT(unit, port)) {
   6991             bcm_port_pause_set(unit, port, FALSE, FALSE);
   6992         }
   6993         /*
   6994          * Get our current MAC address for this port and be sure the
   6995          * SOC will route packets to the CPU.
   6996          */
   6997         if (lb_setup_arl(lw, unit, CMIC_PORT(unit), port)) {
   6998             return(-1);
   6999         }
   7000         if (SOC_IS_XGS3_SWITCH(unit)) {
   7001             pbmp_t              temp_pbmp;
   7002             SOC_PBMP_CLEAR(temp_pbmp);
   7003             /*
   7004              * Setup VLAN
   7005              */
   7006             SOC_PBMP_PORT_ADD(temp_pbmp, CMIC_PORT(unit));
   7007             SOC_PBMP_PORT_ADD(temp_pbmp, port);
   7008 			if ((SOC_DPP_PP_ENABLE(unit) && SOC_IS_ARAD(unit)) || (!SOC_IS_ARAD(unit))) {
   7009 	            if ((rv = bcm_vlan_port_add(unit, lp->lp_vlan,
   7010 	                                        temp_pbmp, temp_pbmp)) < 0) {
   7011 	                test_error(unit,
   7012 	                           "Could not add all ports to VLAN %d: %s\n",
   7013 	                           lp->lp_vlan, bcm_errmsg(rv));
   7014 	                return (-1);
   7015 	            }
   7016 			}
   7017         }
   7018 
   7019         if ((rv = lb_setup_port(unit, port, LB_SPEED_MAX, FALSE)) < 0) {
   7020             test_error(unit,
   7021                        "Port %s: Port setup failed: %s\n",
   7022                        SOC_PORT_NAME(unit, port), bcm_errmsg(rv));
   7023             return(-1);
   7024         }
   7025     }
   7026 
   7027     lb_stats_init(lw);
   7028 
   7029     if (lp->lp_seed) {
   7030         sal_srand(lp->lp_seed);
   7031     }
   7032 
   7033     lw->lw_tx_dcb_factor = 1;
   7034 
   7035     /*
   7036      * First do a dry run without actually sending packets, as a lazy
   7037      * way to calculate the total # packets for statistics reporting.
   7038      */
   7039 
   7040     lw->lw_tx_total = 0;
   7041 
   7042     for (count = 0; count < lp->lp_count; count++) {
   7043         if ((rv = lb_random_exec(unit, lw, 1)) < 0) {
   7044             return rv;
   7045         }
   7046     }
   7047 
   7048     test_msg("LB: total %d pkt\n", lw->lw_tx_total);
   7049 
   7050     for (count = 0; count < lp->lp_count; count++)
   7051         if ((rv = lb_random_exec(unit, lw, 0)) < 0)
   7052             return rv;
   7053 
   7054     lb_stats_done(lw);
   7055 
   7056     return 0;
   7057 }
   7058 
   7059 #ifdef LB_PBM_TEST
   7060 int
   7061 lb_pbm_test(loopback_test_t *lw, loopback_testdata_t *lp)
   7062 /*
   7063  * Function:    lb_pbm_test
   7064  * Purpose:     Test that a PBM of 0 results in 0-bytes transferred,
   7065  *              and does not hang DMA engine.
   7066  * Parameters:  lw - pointer to work structure.
   7067  *              lp - pointer to parameters.
   7068  * Returns:     0 - success, -1 - failed.
   7069  */
   7070 {
   7071     int         rv = 0;
   7072     soc_dma_t   srv;
   7073     dv_t        *dv = lw->lw_tx_dv[0];
   7074     dma_chan_t  channel, chan;
   7075     dcb_type_t  dt = dv->dv_dcb_type;
   7076 
   7077     if(soc_feature(unit, soc_feature_cmicx)) {
   7078         chan = CMICX_N_DMA_CHAN;
   7079     } else {
   7080         chan = N_DMA_CHAN;
   7081     }
   7082 
   7083     for (channel = 0; channel < chan; channel++) {
   7084         LOG_INFO(BSL_LS_APPL_TESTS,
   7085                  (BSL_META("PBMP(0) testing Tx channel %d\n"), channel));
   7086 
   7087         if (soc_dma_chan_config(lw->lw_unit, channel, DV_TX)) {
   7088             test_error(lw->lw_unit,
   7089                        "Unable to configure TX channel: %d\n",
   7090                        channel);
   7091             rv = -1;
   7092             continue;
   7093         }
   7094 
   7095         soc_dma_dv_reset(DV_TX, dv);
   7096 
   7097         dv->dv_flags |= DV_F_NOTIFY_CHN | DV_F_WAIT;
   7098 
   7099         DMAC_INIT(dmac, 64);
   7100         soc_dma_desc_add(dv, 0xdeadbeef, dmac, 0, 0, NULL);
   7101         soc_dma_desc_end_packet(dv);
   7102 
   7103         if (soc_dmaChainDone !=
   7104             (srv = soc_dma_start(lw->lw_unit, channel, dv))) {
   7105             test_error(lw->lw_unit, "Unexpected DMA status: %d\n", srv);
   7106             rv = -1;
   7107         } else {
   7108             dcb_get_dmas0(dt, dv->dv_dcb, &dmas0);
   7109             dcb_get_dmas1(dt, dv->dv_dcb, &dmas1);
   7110             if ((SOC_DCB_XFERCOUNT_GET(unit, dv->dv_dcb != 0) 
   7111                  || !SOC_DCB_DONE_GET(unit, dv->dv_dcb) {
   7112                 soc_dma_dump_dv(lw->lw_unit, "PBM: ", dv);
   7113                 test_error(lw->lw_unit,
   7114                            "PBM of 0 resulted in unexpected status\n");
   7115                 rv = -1;
   7116             }
   7117         }
   7118 
   7119         if (soc_dma_chan_config(lw->lw_unit, channel, DV_NONE)) {
   7120             test_error(lw->lw_unit,
   7121                        "Unable to de-configure TX channel: %d\n",
   7122                        channel);
   7123             rv = -1;
   7124             continue;
   7125         }
   7126     }
   7127 
   7128     lb_stats_done(lw);
   7129 
   7130     return(rv);
   7131 }
   7132 #endif /* LB_PBM_TEST */
   7133 
   7134 int
   7135 lb_reload_test(int unit, args_t *a, void *pa)
   7136 /*
   7137  * Function:    lb_reload_test
   7138  * Purpose:     Test RLD option is dma descriptor.
   7139  * Parameters:  unit - unit
   7140  *              a - pointer to args (ignored)
   7141  *              pa - parameter returned from lb_reload_init.
   7142  * Returns:     0 - success
   7143  *              -1 - failed
   7144  */
   7145 {
   7146     loopback_test_t     *lw = (loopback_test_t *)pa;
   7147     loopback_testdata_t *lp = lw->lw_lp;
   7148     int                 channel, rv, tx, d, chan;
   7149     int                 soc_dma_rv;
   7150     static sal_vaddr_t  reload_addr = (sal_vaddr_t) NULL;
   7151 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)
   7152     int cmc = SOC_PCI_CMC(unit);
   7153 #endif
   7154 
   7155     COMPILER_REFERENCE(a);
   7156     lb_stats_init(lw);
   7157     rv = 0;
   7158 
   7159     if(soc_feature(unit, soc_feature_cmicx)) {
   7160         chan = CMICX_N_DMA_CHAN;
   7161     } else {
   7162         chan = N_DMA_CHAN;
   7163     }
   7164 
   7165     if (lp->lp_seed) {
   7166         sal_srand(lp->lp_seed);
   7167     }
   7168 
   7169     if (reload_addr == (sal_vaddr_t) NULL) {
   7170         reload_addr = (sal_vaddr_t) soc_cm_salloc(unit, 1, "rld");
   7171     }
   7172 
   7173     lw->lw_tx_dcb_factor = 1;
   7174 
   7175     /*
   7176      * Create a simple dcb chain with only a RLD, verify descriptor
   7177      * address register is updated.  This tests RLD=1, CHN=0.
   7178      */
   7179 
   7180     for (tx = 0; tx <= 1; tx++) {
   7181         for (channel = 0; channel < chan; channel++) {
   7182             sal_vaddr_t dma_desc;
   7183             dv_t        **dv_array = tx ? lw->lw_tx_dv : lw->lw_rx_dv;
   7184 
   7185             LOG_INFO(BSL_LS_APPL_TESTS,
   7186                      (BSL_META_U(unit,
   7187                                  "Basic DCB Reload %s Channel %d\n"),
   7188                       tx ? "Tx" : "Rx", channel));
   7189 
   7190             if (soc_dma_chan_config(unit, channel,
   7191                                     tx ? DV_TX : DV_RX, 
   7192                                     SOC_DMA_F_INTR | SOC_DMA_F_DEFAULT)) {
   7193                 test_error(lw->lw_unit,
   7194                            "Unable to configure %s channel: %d\n",
   7195                            tx ? "Tx" : "Rx", channel);
   7196                 break;
   7197             }
   7198 
   7199 #ifdef BCM_CMICM_SUPPORT
   7200             /* Assign all COS to this channel
   7201              * Though this is added for CMICm, 
   7202              * it should be OK if we do this for CMICe as well */
   7203             if(soc_feature(lw->lw_unit, soc_feature_cmicm) && (!tx)) {
   7204                 LOG_INFO(BSL_LS_APPL_TESTS,
   7205                          (BSL_META_U(unit,
   7206                                      "Assign all COS to channel: 1\n")));
   7207                 SOC_IF_ERROR_RETURN(
   7208                     bcm_rx_queue_channel_set(unit, -1, channel));
   7209 
   7210 #if defined(BCM_KATANA2_SUPPORT)
   7211                 if(SOC_IS_KATANA2(unit)) {
   7212                     uint32 reg_val, reg_addr;
   7213 
   7214                     /* Including CPU L0 bitmap to support CMIC backpressure */
   7215                     reg_addr = CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(0, channel);
   7216                     reg_val = soc_pci_read(unit, reg_addr);
   7217                     reg_val |= (1 << 16);
   7218                     soc_pci_write(unit, reg_addr, reg_val);
   7219                 }
   7220 #endif
   7221 
   7222             }
   7223 #endif
   7224 #ifdef BCM_CMICX_SUPPORT
   7225             /* Assign all COS to this channel */
   7226             if(soc_feature(lw->lw_unit, soc_feature_cmicx) && (!tx)) {
   7227                 LOG_INFO(BSL_LS_APPL_TESTS,
   7228                          (BSL_META_U(unit,
   7229                                      "Assign all COS to channel: 1\n")));
   7230                 SOC_IF_ERROR_RETURN(
   7231                     bcm_rx_queue_channel_set(unit, -1, channel));
   7232             }
   7233 #endif
   7234 
   7235             for (d = lp->lp_dv_start; d <= lp->lp_dv_end; d += lp->lp_dv_inc) {
   7236                 int     i;
   7237 
   7238                 rv = 0;
   7239                 LOG_INFO(BSL_LS_APPL_TESTS,
   7240                          (BSL_META_U(unit,
   7241                                      "Testing %cx channel %d: %d independent chains\n"),
   7242                           tx ? 'T' : 'R', channel, d));
   7243 
   7244                 for (i = 0; i < d; i++) {
   7245                     dv_t        *dv = dv_array[i];
   7246 
   7247                     soc_dma_dv_reset(tx ? DV_TX : DV_RX, dv);
   7248                     if (i == 0) {
   7249                       SET_NOTIFY_CHN_ONLY(dv->dv_flags);
   7250                     } else {
   7251                         dv->dv_flags &= ~(DV_F_NOTIFY_CHN|DV_F_NOTIFY_DSC);
   7252                         soc_dma_dv_join(dv_array[i - 1], dv);
   7253                     }
   7254                 }
   7255 
   7256                 /* Add Reload DCB and End of Packet to last DV */
   7257                 /* coverity[check_return] */
   7258                 soc_dma_rld_desc_add(dv_array[d - 1], reload_addr);
   7259                 soc_dma_desc_end_packet(dv_array[d - 1]);
   7260 
   7261                 if (tx) {
   7262                     lw->lw_tx_dv_chain_done = dv_array[0];
   7263                 } else {
   7264                     lw->lw_rx_dv_chain_done = dv_array[0];
   7265                 }
   7266 
   7267                 if ((soc_dma_rv = soc_dma_start(unit, channel,
   7268                                                 dv_array[0])) < 0) {
   7269                     cli_out("%s Channel %d: Unexpected DMA start: %s\n",
   7270                             tx ? "Tx" : "Rx",
   7271                             channel, soc_errmsg(soc_dma_rv));
   7272                     rv = -1;
   7273                 }
   7274 
   7275                 while (!rv) {
   7276                     if (sal_sem_take(lw->lw_sema, lw->lw_timeout_usec)) {
   7277                         lb_dump_dv(lw->lw_unit, "Rld-TO:",
   7278                                    tx ? lw->lw_tx_dv : lw->lw_rx_dv, d);
   7279                         test_error(lw->lw_unit,
   7280                                    "Time-out waiting for completion: "
   7281                                    "%cx on channel %d\n",
   7282                                    tx ? 'T' : 'R', channel);
   7283                         rv = -1;
   7284                     } else {
   7285                         lw->lw_sema_woke = FALSE;
   7286                     }
   7287 
   7288                     if ((tx && lw->lw_eoc_tx) || (!tx && lw->lw_eoc_rx)) {
   7289                         break;          /* while */
   7290                     }
   7291 
   7292                     /* Verify DMA address register reloaded */
   7293 
   7294 #ifdef BCM_CMICM_SUPPORT
   7295                     if (soc_feature(unit, soc_feature_cmicm)) {
   7296                         dma_desc = (sal_vaddr_t) soc_cm_p2l(unit,
   7297                              soc_pci_read(unit,
   7298                                  CMIC_CMCx_DMA_DESCy_OFFSET(cmc, channel)));
   7299                     } else 
   7300 #endif /* CMICM Support */
   7301 #ifdef BCM_CMICX_SUPPORT
   7302                     if (soc_feature(unit, soc_feature_cmicx)) {
   7303                         dma_desc = soc_cmicx_pktdma_desc_addr_get(unit, cmc, channel);
   7304                     } else
   7305 #endif /* CMICX Support */
   7306                     {
   7307                         dma_desc = (sal_vaddr_t) soc_cm_p2l(unit,
   7308                             soc_pci_read(unit, CMIC_DMA_DESC(channel)));
   7309                     }
   7310 
   7311                     if (dma_desc != reload_addr) {
   7312                         cli_out("%s channel %d: Expected ADDR=%p "
   7313                                 "Received ADDR=%p\n",
   7314                                 tx ? "Tx" : "Rx", channel,
   7315                                 (void *)reload_addr, (void *)dma_desc);
   7316                         rv = -1;
   7317                     }
   7318                 }
   7319 
   7320                 /*
   7321                  * Check all the DCBs are marked correct.
   7322                  */
   7323 
   7324                 for (i = 0; !rv && (i < d); i++) {
   7325                     dcb_t       *dcb = dv_array[i]->dv_dcb;
   7326 
   7327                     if (!SOC_DCB_DONE_GET(unit, dcb)) {
   7328                         rv = -1;
   7329                         cli_out("DCB[%d] Done expected but not set\n", i);
   7330                     }
   7331 
   7332                     if (SOC_DCB_RX_START_GET(unit, dcb) ||
   7333                         SOC_DCB_RX_END_GET(unit, dcb)) {
   7334                         cli_out("DCB[%d] SW/EW set but not expected\n", i);
   7335                         rv = -1;
   7336                     }
   7337                 }
   7338 
   7339                 if (rv) {
   7340                     /* Fail test, but allow to continue if desired */
   7341 
   7342                     if (tx) {
   7343                         lb_dump_dv(unit, "Tx:", lw->lw_tx_dv, d);
   7344                     } else {
   7345                         lb_dump_dv(unit, "Rx:", lw->lw_rx_dv, d);
   7346                     }
   7347 
   7348                     test_error(unit, "Test Failed\n");
   7349                     /*
   7350                      * Abort active DMAs before reset_dv
   7351                      */
   7352                     soc_dma_abort(unit);
   7353                 }
   7354 
   7355                 /*
   7356                  * Reset DVs.
   7357                  */
   7358 
   7359                 lb_reset_dv(unit, dv_array, d);
   7360             }
   7361 
   7362             if ((rv |= soc_dma_chan_config(unit, channel,
   7363                                            DV_NONE, SOC_DMA_F_INTR))) {
   7364                 cli_out("%s Channel %d: unable to deconfigure\n",
   7365                         tx ? "Tx" : "Rx", channel);
   7366             }
   7367         }
   7368     }
   7369 
   7370 #ifdef LB_PBM_TEST
   7371     rv |= lb_pbm_test(lw, lp);
   7372 #endif
   7373 
   7374     return(rv);
   7375 }
   7376 #endif /* BCM_ESW_SUPPORT */