ctrtest.c (26146B)
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 * Counter Tests 8 */ 9 #ifdef BSL_LOG_MODULE 10 #error "BSL_LOG_MODULE redefined" 11 #endif 12 #define BSL_LOG_MODULE BSL_LS_SOCDNX_COUNTER 13 14 #include <sal/types.h> 15 16 #include <appl/diag/system.h> 17 #include <appl/diag/parse.h> 18 19 20 #include <soc/debug.h> 21 #include <soc/counter.h> 22 23 #include "testlist.h" 24 25 #if defined(BCM_DNX_SUPPORT) 26 #include <soc/dnx/stat/jer2_stat.h> 27 #include <soc/dnx/dbal/dbal.h> 28 #include <src/bcm/dnx/stat/mib/mib_stat_dbal.h> 29 #endif 30 31 32 #if defined BCM_PETRA_SUPPORT 33 /* 34 * Get counter type for input port 35 */ 36 static soc_ctr_type_t 37 get_port_ctype(int unit, soc_port_t port) { 38 int blk = -1; 39 int bindex = -1; 40 int blktype = -1; 41 int phy_port; 42 soc_ctr_type_t ctype = -1; 43 44 if (soc_feature(unit, soc_feature_logical_port_num)) { 45 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 46 } else { 47 phy_port = port; 48 } 49 blk = SOC_PORT_BLOCK(unit, phy_port); 50 bindex = SOC_PORT_BINDEX(unit, phy_port); 51 52 if (blk < 0 && bindex < 0) { 53 return ctype; 54 } 55 56 blktype = SOC_BLOCK_INFO(unit, blk).type; 57 58 switch (blktype) { 59 case SOC_BLK_EPIC: 60 ctype = SOC_CTR_TYPE_FE; 61 break; 62 case SOC_BLK_GPIC: 63 case SOC_BLK_GPORT: 64 case SOC_BLK_QGPORT: 65 case SOC_BLK_SPORT: 66 ctype = SOC_CTR_TYPE_GE; 67 break; 68 case SOC_BLK_XQPORT: 69 case SOC_BLK_XGPORT: 70 if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) { 71 ctype = SOC_CTR_TYPE_XE; 72 } else { 73 ctype = SOC_CTR_TYPE_GE; 74 } 75 break; 76 case SOC_BLK_IPIC: 77 case SOC_BLK_HPIC: 78 ctype = SOC_CTR_TYPE_HG; 79 break; 80 case SOC_BLK_XPIC: 81 case SOC_BLK_XPORT: 82 case SOC_BLK_GXPORT: 83 case SOC_BLK_XLPORT: 84 case SOC_BLK_XLPORTB0: 85 case SOC_BLK_XTPORT: 86 case SOC_BLK_CLPORT: 87 case SOC_BLK_MXQPORT: 88 case SOC_BLK_XWPORT: 89 if (SOC_IS_GREYHOUND(unit) && blktype == SOC_BLK_GXPORT){ 90 if (SOC_BLOCK_PORT(unit, blk) < 0){ 91 ctype = SOC_CTR_TYPE_XE; 92 } else { 93 /* Greyhound GE port with SOC_BLK_GXPORT case*/ 94 ctype = SOC_CTR_TYPE_GE; 95 } 96 } else { 97 ctype = SOC_CTR_TYPE_XE; 98 } 99 break; 100 case SOC_BLK_CLG2PORT: 101 ctype = SOC_CTR_TYPE_CE; 102 break; 103 case SOC_BLK_CLP: 104 case SOC_BLK_XLP: 105 if (IS_IL_PORT(unit, port)) { 106 } else if (IS_CE_PORT(unit, port)) { 107 ctype = SOC_CTR_TYPE_CE; 108 } else if (IS_QSGMII_PORT(unit,port)) { 109 ctype = SOC_CTR_TYPE_GE; 110 } else { 111 ctype = SOC_CTR_TYPE_XE; 112 } 113 break; 114 case SOC_BLK_MXQ: 115 ctype = SOC_CTR_TYPE_GE; 116 break; 117 case SOC_BLK_CMIC: 118 if (soc_feature(unit, soc_feature_cpuport_stat_dma)) { 119 ctype = SOC_CTR_TYPE_CPU; 120 break; 121 } 122 case SOC_BLK_CPIC: 123 default: 124 break; 125 } 126 127 return ctype; 128 } 129 #endif 130 131 #if defined BCM_DNX_SUPPORT 132 133 /** 134 * brief - Test counter rw. 135 */ 136 static int 137 test_dnx_ctr_rw( 138 int unit, 139 int port, 140 int counter_id) 141 { 142 int rv; 143 uint64 val, incr; 144 uint64 mask, pattern,tmp; 145 int length; 146 dbal_fields_e field_id; 147 int loop; 148 int res = 0; /* test result - assume pass */ 149 150 rv = dnx_cdmib_counter_id_to_dbal_field_id_get(unit, port, counter_id, &field_id); 151 if (rv != 0) 152 { 153 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - counter type %d is not supported for port %d"), counter_id, port)); 154 res = 1; 155 } 156 157 rv = soc_jer2_stat_counter_length_get(unit, counter_id, &length); 158 if (rv != 0) 159 { 160 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get length failed for counter type %d"), counter_id)); 161 res = 1; 162 } 163 164 COMPILER_64_MASK_CREATE(mask, length, 0); 165 COMPILER_64_SET(incr, 0x55555555, 0x55555555); 166 /* 167 * The following loop sets pattern to: 168 * 169 * 0x00000000 170 * 0x55555555 171 * 0xaaaaaaaa 172 * 0xffffffff 173 */ 174 175 COMPILER_64_ZERO(pattern); 176 for (loop = 0; loop < 4; loop++) 177 { 178 tmp = pattern; 179 180 rv = dnx_cdmib_stat_dbal_set(unit, port, field_id, tmp); 181 if (rv != 0) 182 { 183 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - set value %08x%08x for counter type %d failed"), 184 COMPILER_64_HI(tmp),COMPILER_64_LO(tmp), counter_id)); 185 res = 1; 186 } 187 COMPILER_64_ZERO(val); 188 rv = dnx_cdmib_stat_dbal_get(unit, port, field_id, &val); 189 if (rv != 0) 190 { 191 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get value failed for counter type %d"), counter_id)); 192 res = 1; 193 } 194 195 tmp = val; 196 COMPILER_64_XOR(tmp, pattern); 197 COMPILER_64_AND(tmp, mask); 198 199 if (!COMPILER_64_IS_ZERO(tmp)) 200 { 201 COMPILER_64_AND(pattern, mask); 202 COMPILER_64_AND(val, mask); 203 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, 204 "Counter type %d miscompare:\n" 205 " wrote 0x%08x%08x\n" 206 " read 0x%08x%08x\n"), 207 counter_id, 208 COMPILER_64_HI(pattern), 209 COMPILER_64_LO(pattern), 210 COMPILER_64_HI(val), 211 COMPILER_64_LO(val))); 212 res = 1; 213 } 214 215 COMPILER_64_ADD_64(pattern, incr); 216 } 217 218 return res; 219 } 220 221 int ctr_dnx_test_rw(int unit, args_t *a, void *pa) 222 { 223 bcm_pbmp_t pbmp; 224 int port; 225 int counter_id; 226 int rv; 227 int res = 0; /* test result - assume pass */ 228 229 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 230 BCM_PBMP_REMOVE(pbmp, PBMP_SFI_ALL(unit)); 231 BCM_PBMP_REMOVE(pbmp, PBMP_IL_ALL(unit)); 232 /* 233 * Get first cdmib port 234 */ 235 _SHR_PBMP_FIRST(pbmp, port); 236 237 /* 238 * Test Counter read/wirte 239 */ 240 cli_out("Counter read/wirte test - Start\n"); 241 242 if (port == -1) 243 { 244 LOG_ERROR(BSL_LOG_MODULE, 245 (BSL_META_U(unit, "Error - Expecting one eth port at least\n"))); 246 res = 1; 247 } 248 else 249 { 250 for (counter_id = soc_jer2_counters_cdmib_r64; counter_id <= soc_jer2_counters_cdmib_tbyt; counter_id++) 251 { 252 rv = test_dnx_ctr_rw(unit, port, counter_id); 253 if (rv != 0) 254 { 255 res = 1; /*set failed flag*/ 256 } 257 } 258 } 259 cli_out("Counter read/wirte test - Done\n"); 260 /* 261 * Final Result 262 */ 263 if (res == 0) 264 { 265 cli_out("Counter read/wirte test- Pass\n"); 266 } 267 return res; 268 269 } 270 271 /** 272 * brief - Test counter width. 273 */ 274 static int 275 test_dnx_ctr_width( 276 int unit, 277 int port, 278 int counter_id) 279 { 280 int rv; 281 int res = 0; /* test result - assume pass */ 282 uint64 val; 283 dbal_fields_e field_id; 284 int defined_width, actual_width; 285 286 COMPILER_64_SET(val, 0xffffffff, 0xffffffff); 287 288 rv = dnx_cdmib_counter_id_to_dbal_field_id_get(unit, port, counter_id, &field_id); 289 if (rv != 0) 290 { 291 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - counter type %d is not supported for port %d"), counter_id, port)); 292 res = 1; 293 } 294 295 rv = dnx_cdmib_stat_dbal_set(unit, port, field_id, val); 296 if (rv != 0) 297 { 298 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - set value %08x%08x for counter type %d failed"), 299 COMPILER_64_HI(val),COMPILER_64_LO(val), counter_id)); 300 res = 1; 301 } 302 303 COMPILER_64_ZERO(val); 304 rv = dnx_cdmib_stat_dbal_get(unit, port, field_id, &val); 305 if (rv != 0) 306 { 307 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get value failed for counter type %d"), counter_id)); 308 res = 1; 309 } 310 311 rv = soc_jer2_stat_counter_length_get(unit, counter_id, &defined_width); 312 if (rv != 0) 313 { 314 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get length failed for counter type %d"), counter_id)); 315 res = 1; 316 } 317 318 actual_width = (_shr_popcount(COMPILER_64_LO(val)) + _shr_popcount(COMPILER_64_HI(val))); 319 if (defined_width != actual_width) 320 { 321 LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, 322 "Counter type %d width mismatch" 323 "defined width: %d bits, actual: %d bits\n"), 324 counter_id, defined_width, actual_width)); 325 res = 1; 326 } 327 328 return res; 329 } 330 331 int ctr_dnx_test_width(int unit, args_t *a, void *pa) 332 { 333 334 bcm_pbmp_t pbmp; 335 int port; 336 int counter_id; 337 int rv; 338 int res = 0; /* test result - assume pass */ 339 340 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit)); 341 BCM_PBMP_REMOVE(pbmp, PBMP_SFI_ALL(unit)); 342 BCM_PBMP_REMOVE(pbmp, PBMP_IL_ALL(unit)); 343 /* 344 * Get first cdmib port 345 */ 346 _SHR_PBMP_FIRST(pbmp, port); 347 348 /* 349 * Test Counter widths 350 */ 351 cli_out("Counter widths test - Start\n"); 352 353 if (port == -1) 354 { 355 LOG_ERROR(BSL_LOG_MODULE, 356 (BSL_META_U(unit, "Error - Expecting one eth port at least\n"))); 357 res = 1; 358 } 359 else 360 { 361 for (counter_id = soc_jer2_counters_cdmib_r64; counter_id <= soc_jer2_counters_cdmib_tbyt; counter_id++) 362 { 363 rv = test_dnx_ctr_width(unit, port, counter_id); 364 if (rv != 0) 365 { 366 res = 1; /*set failed flag*/ 367 } 368 } 369 } 370 cli_out("Counter widths test - Done\n"); 371 /* 372 * Final Result 373 */ 374 if (res == 0) 375 { 376 cli_out("Counter widths test- Pass\n"); 377 } 378 return res; 379 } 380 381 #endif 382 383 /* 384 * Given a counter type, return a port that can be used for it. 385 * Actually returns the first port of the appropriate type 386 */ 387 static soc_port_t 388 find_ctype_port(int unit, soc_ctr_type_t ctype) 389 { 390 switch (ctype) { 391 case SOC_CTR_TYPE_FE: 392 if (SOC_PORT_NUM(unit, fe) < 1) { 393 return -1; 394 } 395 return SOC_PORT(unit, fe, 0); 396 case SOC_CTR_TYPE_GE: 397 case SOC_CTR_TYPE_GFE: 398 if (SOC_PORT_NUM(unit, ge) < 1) { 399 return -1; 400 } 401 #ifdef BCM_GREYHOUND_SUPPORT 402 if (SOC_IS_GREYHOUND(unit) && IS_XL_PORT(unit, SOC_PORT(unit, ge, 0))) { 403 return -1; 404 } 405 #endif /* BCM_GREYHOUND_SUPPORT */ 406 return SOC_PORT(unit, ge, 0); 407 case SOC_CTR_TYPE_XE: 408 if (SOC_PORT_NUM(unit, xe) < 1) { 409 return -1; 410 } 411 #if defined BCM_PETRA_SUPPORT 412 /*For QUX,XE ports in Viper core use ge counter type*/ 413 if (SOC_IS_QUX(unit)) { 414 int i, port; 415 for (i=0;i<SOC_PORT_NUM(unit, xe);i++) { 416 port = SOC_PORT(unit, xe, i); 417 if (SOC_CTR_TYPE_XE == get_port_ctype(unit,port)) { 418 return port; 419 } 420 } 421 if (SOC_PORT_NUM(unit, xe) == i) { 422 return -1; 423 } 424 } else 425 #endif 426 { 427 return SOC_PORT(unit, xe, 0); 428 } 429 case SOC_CTR_TYPE_HG: 430 if (SOC_PORT_NUM(unit, hg) < 1) { 431 return -1; 432 } 433 return SOC_PORT(unit, hg, 0); 434 default: 435 return -1; 436 } 437 } 438 439 /* 440 * Routine to test the width of a counter in bits, as verified against 441 * the width listed in the regsfile, for counters up to 32 bits. 442 */ 443 444 static int 445 test_width32(int unit, soc_reg_t ctr_reg, soc_port_t port) 446 { 447 uint32 val = 0; 448 char *name; 449 int regsfile_width, actual_width; 450 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 451 int r; 452 #endif /* BCM_ESW_SUPPORT */ 453 454 name = NULL; 455 regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[0].len; 456 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 457 if (soc_feature(unit, soc_feature_counter_parity) || 458 soc_reg_field_valid(unit, ctr_reg, PARITYf) ) { 459 int i = 0; 460 while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 461 if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) { 462 regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[i].len; 463 break; 464 } 465 i++; 466 } 467 } 468 #endif 469 470 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 471 name = SOC_REG_NAME(unit, ctr_reg); 472 473 if (soc_feature(unit, soc_feature_prime_ctr_writes)) { 474 r = soc_counter_set32(unit, port, ctr_reg, 0, ~0); 475 } else { 476 r = soc_reg32_set(unit, ctr_reg, port, 0, ~0); 477 } 478 479 if ((r < 0) || 480 (r = soc_reg32_get(unit, ctr_reg, port, 0, &val)) < 0) { 481 test_error(unit, 482 "Can't access counter %s.%s: %s\n", 483 name, SOC_PORT_NAME(unit, port), soc_errmsg(r)); 484 return -1; 485 } 486 if (soc_feature(unit, soc_feature_counter_parity) || 487 soc_reg_field_valid(unit, ctr_reg, PARITYf) ) { 488 int bits; 489 bits = soc_reg_field_length(unit, ctr_reg, COUNTf); 490 val &= ((bits == 32 ? 0 : 1 << bits) - 1); 491 } 492 #endif 493 494 actual_width = _shr_popcount(val); 495 496 if (regsfile_width != actual_width) { 497 test_error(unit, 498 "Counter %s.%s width mismatch: " 499 "regsfile: %d bits, actual: %d bits\n", 500 name, SOC_PORT_NAME(unit, port), regsfile_width, 501 actual_width); 502 return -1; 503 } 504 return 0; 505 } 506 507 /* 508 * Routine to test the width of a counter in bits, as verified against 509 * the width listed in the regsfile, for counters over 32 bits. 510 */ 511 512 static int 513 test_width64(int unit, soc_reg_t ctr_reg, soc_port_t port) 514 { 515 uint64 val; 516 char *name; 517 int regsfile_width, actual_width; 518 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 519 int r; 520 #endif 521 522 name = NULL; 523 regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[0].len; 524 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 525 if (soc_feature(unit, soc_feature_counter_parity) || 526 soc_reg_field_valid(unit, ctr_reg, PARITYf)) { 527 int i = 0; 528 while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 529 if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) { 530 regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[i].len; 531 break; 532 } 533 i++; 534 } 535 } 536 #endif 537 538 COMPILER_64_SET(val, 0xffffffff, 0xffffffff); 539 540 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 541 name = SOC_REG_NAME(unit, ctr_reg); 542 if ((r = soc_reg64_set(unit, ctr_reg, port, 0, val)) < 0 || 543 (r = soc_reg64_get(unit, ctr_reg, port, 0, &val)) < 0) { 544 test_error(unit, 545 "Can't access counter %s.%s: %s\n", 546 name, SOC_PORT_NAME(unit, port), soc_errmsg(r)); 547 return -1; 548 } 549 val = soc_reg64_field_get(unit, ctr_reg, val, 550 SOC_REG_INFO(unit, ctr_reg).fields[0].field); 551 #endif 552 actual_width = (_shr_popcount(COMPILER_64_LO(val)) + 553 _shr_popcount(COMPILER_64_HI(val))); 554 555 if (regsfile_width != actual_width) { 556 test_error(unit, 557 "Counter %s.%s width mismatch: " 558 "regsfile: %d bits, actual: %d bits\n", 559 name, SOC_PORT_NAME(unit, port), 560 regsfile_width, actual_width); 561 return -1; 562 } 563 return 0; 564 } 565 566 int 567 ctr_test_width(int unit, args_t *a, void *pa) 568 /* 569 * Function: ctr_test_width 570 * Purpose: Test the widths of all counters as compared to regsfile 571 * Parameters: u - unit #. 572 * a - pointer to arguments. 573 * pa - ignored cookie. 574 * Returns: 0 575 */ 576 { 577 int i; 578 soc_ctr_type_t ctype; 579 soc_reg_t reg; 580 soc_port_t port; 581 582 COMPILER_REFERENCE(a); 583 COMPILER_REFERENCE(pa); 584 585 #if defined BCM_DNX_SUPPORT 586 return ctr_dnx_test_width(unit, a, pa); 587 #endif 588 589 #ifdef BCM_SHADOW_SUPPORT 590 /* coverity[dead_error_line] */ 591 if (SOC_IS_SHADOW(unit)) { 592 if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY, 593 XGS_COUNTER_COMPAT_MODEf, 1) < 0) { 594 return -1; 595 } 596 } 597 #endif 598 for (ctype = SOC_CTR_TYPE_FE; ctype < SOC_CTR_NUM_TYPES; ctype++) { 599 if (SOC_HAS_CTR_TYPE(unit, ctype)) { 600 port = find_ctype_port(unit, ctype); 601 if (port < 0) { 602 continue; 603 } 604 for (i = 0; i < SOC_CTR_MAP_SIZE(unit, ctype); i++) { 605 reg = SOC_CTR_TO_REG(unit, ctype, i); 606 if (!SOC_COUNTER_INVALID(unit, reg) && 607 !(SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_RO)) { 608 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 609 soc_regaddrinfo_t ainfo; 610 uint64 mask; 611 uint32 addr; 612 int block; 613 uint8 at; 614 615 if (!SOC_REG_PORT_VALID(unit, reg, port)) { 616 continue; 617 } 618 addr = soc_reg_addr_get(unit, reg, port, 0, 619 SOC_REG_ADDR_OPTION_NONE, 620 &block, &at); 621 soc_regaddrinfo_extended_get(unit, &ainfo, block, at, addr); 622 if (SOC_COUNTER_INVALID(unit, ainfo.reg)) { 623 continue; 624 } 625 if (reg_mask_subset(unit, &ainfo, &mask)) { 626 /* Unimplemented in HW, skip */ 627 continue; 628 } 629 #endif 630 631 if (SOC_REG_IS_COUNTER_TABLE(unit, reg) || 632 SOC_REG_IS_64(unit, reg)) { 633 test_width64(unit, reg, port); 634 } else { 635 test_width32(unit, reg, port); 636 } 637 } 638 } 639 } 640 } 641 #ifdef BCM_SHADOW_SUPPORT 642 if (SOC_IS_SHADOW(unit)) { 643 if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY, 644 XGS_COUNTER_COMPAT_MODEf, 0) < 0) { 645 return -1; 646 } 647 } 648 #endif 649 650 return 0; 651 } 652 653 /* 654 * Routine to write a counter with several patterns and compare. 655 * Works on counters <= 32 bits. 656 */ 657 658 static int 659 test_rw32(int unit, soc_reg_t ctr_reg, soc_port_t port) 660 { 661 char *name; 662 volatile uint32 pattern; /* SiByte1250 workaround */ 663 uint32 mask, val; 664 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 665 uint32 pattern_mask; 666 int r; 667 #endif 668 int bits, patno; 669 670 name = NULL; 671 bits = SOC_REG_INFO(unit, ctr_reg).fields[0].len; 672 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 673 if (soc_feature(unit, soc_feature_counter_parity) || 674 soc_reg_field_valid(unit, ctr_reg, PARITYf)) { 675 int i = 0; 676 while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 677 if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) { 678 bits = SOC_REG_INFO(unit, ctr_reg).fields[i].len; 679 break; 680 } 681 i++; 682 } 683 } 684 #endif 685 mask = (bits == 32 ? 0 : 1 << bits) - 1; 686 687 /* 688 * The following loop sets pattern to: 689 * 690 * 0x00000000 691 * 0x55555555 692 * 0xaaaaaaaa 693 * 0xffffffff 694 */ 695 696 pattern = 0x00000000; 697 val = 0; 698 699 for (patno = 0; patno < 4; patno++) { 700 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 701 name = SOC_REG_NAME(unit, ctr_reg); 702 pattern_mask = pattern & mask; 703 if (soc_feature(unit, soc_feature_prime_ctr_writes)) { 704 r = soc_counter_set32(unit, port, ctr_reg, 0, pattern_mask); 705 } else { 706 r = soc_reg32_set(unit, ctr_reg, port, 0, pattern_mask); 707 } 708 if (r < 0) { 709 val = pattern_mask; 710 test_error(unit, 711 "Can't write counter %s.%s: %s\n", 712 name, SOC_PORT_NAME(unit, port), soc_errmsg(r)); 713 } else if ((r = soc_reg32_get(unit, ctr_reg, port, 0, &val)) < 0) { 714 test_error(unit, 715 "Can't access counter %s.%s: %s\n", 716 name, SOC_PORT_NAME(unit, port), soc_errmsg(r)); 717 } 718 #endif 719 if (((val ^ pattern) & mask) != 0) { 720 uint32 reread = 0; 721 722 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 723 (void) soc_reg32_get(unit, ctr_reg, port, 0, &reread); 724 #endif 725 726 test_error(unit, 727 "Counter %s.%s miscompare: \n" 728 " wrote 0x%08x\n" 729 " read 0x%08x\n" 730 " re-read 0x%08x\n", 731 name, SOC_PORT_NAME(unit, port), 732 pattern & mask, 733 val & mask, 734 reread & mask); 735 } 736 737 pattern += 0x55555555; 738 } 739 return 0; 740 } 741 742 /* 743 * Routine to write a counter with several patterns and compare. 744 * Works on counters over 32 bits. 745 */ 746 747 static int 748 test_rw64(int unit, soc_reg_t ctr_reg, soc_port_t port) 749 { 750 char *name; 751 uint64 mask, pattern, tmp; 752 uint64 val, incr; 753 int bits, patno; 754 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 755 int r; 756 #endif /* BCM_ESW_SUPPORT */ 757 758 name = NULL; 759 bits = SOC_REG_INFO(unit, ctr_reg).fields[0].len; 760 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 761 if (soc_feature(unit, soc_feature_counter_parity) || 762 soc_reg_field_valid(unit, ctr_reg, PARITYf) ) { 763 int i = 0; 764 while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 765 if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) { 766 bits = SOC_REG_INFO(unit, ctr_reg).fields[i].len; 767 break; 768 } 769 i++; 770 } 771 } 772 #endif 773 774 COMPILER_64_MASK_CREATE(mask, bits, 0); 775 COMPILER_64_SET(incr, 0x55555555, 0x55555555); 776 COMPILER_64_SET(val, 0x0, 0x0); 777 778 /* 779 * The following loop sets pattern to: 780 * 781 * 0x00000000 782 * 0x55555555 783 * 0xaaaaaaaa 784 * 0xffffffff 785 */ 786 787 COMPILER_64_ZERO(pattern); 788 789 for (patno = 0; patno < 4; patno++) { 790 tmp = pattern; 791 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 792 name = SOC_REG_NAME(unit, ctr_reg); 793 if ((r = soc_reg64_set(unit, ctr_reg, port, 0, tmp)) < 0) { 794 val = tmp; 795 test_error(unit, 796 "Can't write counter %s.%s: %s\n", 797 name, SOC_PORT_NAME(unit, port), soc_errmsg(r)); 798 } else if ((r = soc_reg64_get(unit, ctr_reg, port, 0, &val)) < 0) { 799 test_error(unit, 800 "Can't access counter %s.%s: %s\n", 801 name, SOC_PORT_NAME(unit, port), soc_errmsg(r)); 802 } 803 #endif 804 tmp = val; 805 COMPILER_64_XOR(tmp, pattern); 806 COMPILER_64_AND(tmp, mask); 807 808 if (!COMPILER_64_IS_ZERO(tmp)) { 809 uint64 reread; 810 811 COMPILER_64_ZERO(reread); 812 813 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 814 (void) soc_reg64_get(unit, ctr_reg, port, 0, &reread); 815 #endif 816 817 COMPILER_64_AND(pattern, mask); 818 COMPILER_64_AND(val, mask); 819 820 test_error(unit, 821 "Counter %s.%s miscompare:\n" 822 " wrote 0x%08x%08x\n" 823 " read 0x%08x%08x\n" 824 " re-read 0x%08x%08x\n", 825 name, SOC_PORT_NAME(unit, port), 826 COMPILER_64_HI(pattern), 827 COMPILER_64_LO(pattern), 828 COMPILER_64_HI(val), 829 COMPILER_64_LO(val), 830 COMPILER_64_HI(reread), 831 COMPILER_64_LO(reread)); 832 } 833 834 COMPILER_64_ADD_64(pattern, incr); 835 } 836 return 0; 837 } 838 839 int 840 ctr_test_rw(int unit, args_t *a, void *pa) 841 /* 842 * Function: ctr_test_rw 843 * Purpose: Run test values through all counter registers 844 * Parameters: u - unit #. 845 * a - pointer to arguments. 846 * pa - ignored cookie. 847 * Returns: 0 848 */ 849 { 850 int i; 851 soc_reg_t reg; 852 soc_ctr_type_t ctype; 853 soc_port_t port; 854 855 COMPILER_REFERENCE(a); 856 COMPILER_REFERENCE(pa); 857 858 #if defined BCM_DNX_SUPPORT 859 return ctr_dnx_test_rw(unit, a, pa); 860 #endif 861 862 #ifdef BCM_SHADOW_SUPPORT 863 /* coverity[dead_error_line] */ 864 if (SOC_IS_SHADOW(unit)) { 865 if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY, 866 XGS_COUNTER_COMPAT_MODEf, 1) < 0) { 867 return -1; 868 } 869 } 870 #endif 871 872 for (ctype = SOC_CTR_TYPE_FE; ctype < SOC_CTR_NUM_TYPES; ctype++) { 873 if (SOC_HAS_CTR_TYPE(unit, ctype)) { 874 port = find_ctype_port(unit, ctype); 875 if (port < 0) { 876 continue; 877 } 878 for (i = 0; i < SOC_CTR_MAP_SIZE(unit, ctype); i++) { 879 reg = SOC_CTR_TO_REG(unit, ctype, i); 880 if (!SOC_COUNTER_INVALID(unit, reg) && 881 !(SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_RO)) { 882 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT) 883 soc_regaddrinfo_t ainfo; 884 uint64 mask; 885 uint32 addr; 886 int block; 887 uint8 at; 888 889 if (!SOC_REG_PORT_VALID(unit, reg, port)) { 890 continue; 891 } 892 addr = soc_reg_addr_get(unit, reg, port, 0, 893 SOC_REG_ADDR_OPTION_NONE, 894 &block, &at); 895 soc_regaddrinfo_extended_get(unit, &ainfo, block, at, addr); 896 if (SOC_COUNTER_INVALID(unit, ainfo.reg)) { 897 continue; 898 } 899 if (reg_mask_subset(unit, &ainfo, &mask)) { 900 /* Unimplemented in HW, skip */ 901 continue; 902 } 903 #endif 904 if (SOC_REG_IS_COUNTER_TABLE(unit, reg) || 905 SOC_REG_IS_64(unit, reg)) { 906 test_rw64(unit, reg, port); 907 } else { 908 test_rw32(unit, reg, port); 909 } 910 } 911 } 912 } 913 } 914 #ifdef BCM_SHADOW_SUPPORT 915 if (SOC_IS_SHADOW(unit)) { 916 if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY, 917 XGS_COUNTER_COMPAT_MODEf, 0) < 0) { 918 return -1; 919 } 920 } 921 #endif 922 923 return 0; 924 }