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 */