randaddr.c (38864B)
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 * Random index memory test implemented via S-Channel table read/write. 8 * 9 * This test function is a variation on memrand for random memory 10 * testing. It was requested by Govind to do the following: 11 * 12 * Write every word in the memory each pass. 13 * Write all then read all 14 * Vary the pattern each write, for example, from all 1s to all 0s. 15 * For different seeds, to order of writes to the memory should vary. 16 * 17 * Randomizing algorithm: 18 * Inputs: current value, original seed. 19 */ 20 21 #include <shared/bsl.h> 22 23 #include <sal/types.h> 24 25 #include <sal/appl/pci.h> 26 #include <shared/bsl.h> 27 #include <appl/diag/system.h> 28 #include <appl/diag/parse.h> 29 #include <appl/diag/progress.h> 30 31 #include <soc/mem.h> 32 #include <soc/debug.h> 33 #include <soc/l2x.h> 34 #include <soc/memory.h> 35 36 #ifdef BCM_PETRA_SUPPORT 37 #include <soc/dpp/drv.h> 38 #endif /* BCM_PETRA_SUPPORT */ 39 #ifdef BCM_DFE_SUPPORT 40 #include <soc/dfe/cmn/dfe_drv.h> 41 #endif /* BCM_DFE_SUPPORT */ 42 #ifdef BCM_DNXF_SUPPORT 43 #include <soc/dnxf/cmn/dnxf_drv.h> 44 #endif /* BCM_DNXF_SUPPORT */ 45 46 #include "testlist.h" 47 48 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 49 /* 50 * Return true if a and b are relatively prime 51 * Bad O(n) algorithm 52 */ 53 static uint32 54 relprime(uint32 a, uint32 b) 55 { 56 uint32 i; 57 uint32 min = a < b ? a : b; 58 uint32 max = a < b ? b : a; 59 60 if (max % min == 0) { 61 return 0; 62 } 63 64 if ((a % 2 == 0) && (b % 2 == 0)) { 65 return 0; 66 } 67 68 for (i = 3; i <= min / 2; i += 2) { 69 if ((a % i == 0) && (b % i == 0)) { 70 return 0; 71 } 72 } 73 74 return 1; 75 } 76 77 /* 78 * Return the first value greater than or equal to start that is 79 * relatively prime to val. 80 */ 81 static uint32 82 get_rel_prime(uint32 val, uint32 start) 83 { 84 while (!relprime(val, start)) { 85 start++; 86 } 87 88 return start; 89 } 90 91 92 /* 93 * Memory test status structure 94 */ 95 96 typedef struct rand_work_s { 97 int was_debug_mode; 98 int orig_enable; 99 int saved_tcam_protect_write; 100 int mem_scan; 101 int scan_rate; 102 sal_usecs_t scan_interval; 103 int sram_scan; 104 int sram_scan_rate; 105 sal_usecs_t sram_scan_interval; 106 int iters; /* Total iterations to perform */ 107 108 soc_mem_t mem; /* Memory to test */ 109 110 int copyno; /* copy to test (or COPYNO_ALL) */ 111 int copyno_total; /* Number of copies */ 112 113 int index_min; /* Lowest index in range to test */ 114 int index_max; /* Last index in range to test */ 115 int index_total; /* Size of index range (max-min+1-holes) */ 116 int array_index_start; /* Lowest array index in range to test */ 117 int array_index_end; /* Last array index in range to test */ 118 119 uint32 data_start; /* initial data value */ 120 uint32 data; /* current data value */ 121 uint32 seed; /* seed */ 122 int ecc_as_data; /* treat ecc field as regular field */ 123 int report_progress; 124 uint32 addr_incr; /* for internal random */ 125 uint32 first_addr; 126 uint32 cur_addr; 127 } rand_work_t; 128 129 static rand_work_t *rand_work[SOC_MAX_NUM_DEVICES]; 130 131 132 #if defined (BCM_ESW_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) 133 STATIC int 134 addr_rand_common_clear(int unit, soc_mem_t mem, int copyno) 135 { 136 #if defined(INCLUDE_MEM_SCAN) || defined(BCM_SRAM_SCAN_SUPPORT) 137 rand_work_t *rw = rand_work[unit]; 138 #endif 139 int rv; 140 141 SOC_MEM_TEST_SKIP_CACHE_SET(unit, 1); 142 if ((rv = soc_mem_parity_control(unit, mem, copyno, FALSE)) < 0) { 143 test_error(unit, "Could not disable parity warnings on memory %s\n", 144 SOC_MEM_UFNAME(unit, mem)); 145 return -1; 146 } 147 #ifdef INCLUDE_MEM_SCAN 148 if(!SOC_IS_DNX(unit)) { 149 if ((rw->mem_scan = soc_mem_scan_running(unit, &rw->scan_rate, 150 &rw->scan_interval)) > 0) { 151 if (soc_mem_scan_stop(unit)) { 152 return -1; 153 } 154 } 155 } 156 #endif /* INCLUDE_MEM_SCAN */ 157 #ifdef BCM_SRAM_SCAN_SUPPORT 158 if(!SOC_IS_DNX(unit)) { 159 if ((rw->sram_scan = soc_sram_scan_running(unit, &rw->sram_scan_rate, 160 &rw->sram_scan_interval)) > 0) { 161 if (soc_sram_scan_stop(unit)) { 162 return -1; 163 } 164 } 165 } 166 #endif /* BCM_SRAM_SCAN_SUPPORT */ 167 return 0; 168 } 169 170 STATIC int 171 addr_rand_common_restore(int unit, soc_mem_t mem, int copyno) 172 { 173 #if defined(INCLUDE_MEM_SCAN) || defined(BCM_SRAM_SCAN_SUPPORT) 174 rand_work_t *rw = rand_work[unit]; 175 #endif 176 177 SOC_MEM_TEST_SKIP_CACHE_SET(unit, 0); 178 if (soc_mem_parity_restore(unit, mem, copyno) < 0) { 179 test_error(unit, "Could not enable parity warnings on memory %s\n", 180 SOC_MEM_UFNAME(unit, mem)); 181 return -1; 182 } 183 #ifdef INCLUDE_MEM_SCAN 184 if (rw->mem_scan) { 185 if (soc_mem_scan_start(unit, rw->scan_rate, rw->scan_interval)) { 186 return -1; 187 } 188 } 189 #endif /* INCLUDE_MEM_SCAN */ 190 #ifdef BCM_SRAM_SCAN_SUPPORT 191 if (rw->sram_scan) { 192 if (soc_sram_scan_start(unit, rw->sram_scan_rate, rw->sram_scan_interval)) { 193 return -1; 194 } 195 } 196 #endif /* BCM_SRAM_SCAN_SUPPORT */ 197 return 0; 198 } 199 #endif /* BCM_ESW_SUPPORT || BCM_PETRA_SUPPORT */ 200 201 202 203 char tr52_test_usage[] = 204 "TR52 (single memory test write repeatedly to all indices of the given memory as many times as requested) usage:\n" 205 " \n" 206 #ifdef COMPILER_STRING_CONST_LIMIT 207 "\nFull documentation cannot be displayed with -pedantic compiler\n"; 208 #else 209 210 "M=<value> Memory - The memory to be checked\n" 211 "IS=<value> IndexStart - Starting index\n" 212 "IE=<value> IndexEnd - Ending index\n" 213 "AIS=<value> ArrayIndexStart - Array starting index (in case of array memory)\n" 214 "AIE=<value> ArrayIndexEnd - Array ending index (in case of array memory)\n" 215 "ITER=<value> ITERations - number of iterations to repeat TR\n" 216 "ID=<value> InitialData - the basic data to be written in the test \n" 217 "SEED=<value> SEED - the seed to use in the random function\n" 218 "EAD=<value> EccAsData - treat ECC field as regular field\n" 219 "RP=<value> ReportProgress - \n" 220 "Help=<1/0> - Specifies if tr 7 help is on and exit or off (off by default)\n" 221 "To enable printing values (write/read) of each memory proceed: debug +test +verb\n" 222 "\n"; 223 #endif 224 225 226 227 int 228 addr_rand_init(int unit, args_t *a, void **p) 229 { 230 rand_work_t *rw; 231 char *mem_name; 232 char *idx_start_str, *idx_end_str; 233 char *array_idx_start_str, *array_idx_end_str; 234 int blk; 235 int rv = -1; 236 uint32 help_status_default = 0; 237 uint32 help_status=0; 238 parse_table_t pt; 239 240 rw = rand_work[unit]; 241 if (rw == NULL) { 242 rw = sal_alloc(sizeof(rand_work_t), "randaddr"); 243 if (rw == NULL) { 244 cli_out("%s: cannot allocate memory test data\n", ARG_CMD(a)); 245 return -1; 246 } 247 sal_memset(rw, 0, sizeof(rand_work_t)); 248 rand_work[unit] = rw; 249 } 250 251 parse_table_init(unit, &pt); 252 parse_table_add(&pt, "Memory", PQ_STRING, "", 253 &mem_name, NULL); 254 parse_table_add(&pt, "IndexStart", PQ_STRING, (void *) "min", 255 &idx_start_str, NULL); 256 parse_table_add(&pt, "IndexEnd", PQ_STRING, (void *) "max", 257 &idx_end_str, NULL); 258 parse_table_add(&pt, "ArrayIndexStart", PQ_STRING, (void *) "min", &array_idx_start_str, NULL); 259 parse_table_add(&pt, "ArrayIndexEnd", PQ_STRING, (void *) "max", &array_idx_end_str, NULL); 260 parse_table_add(&pt, "ITERations", PQ_INT, (void *) 10, 261 &rw->iters, NULL); 262 parse_table_add(&pt, "SEED", PQ_INT, (void *) 0xdecade, 263 &rw->seed, NULL ); 264 parse_table_add(&pt, "EccAsData", PQ_BOOL, (void *)1, 265 &rw->ecc_as_data, NULL ); 266 parse_table_add(&pt, "InitialData", PQ_INT, (void *) 0xffffffff, 267 &rw->data_start, NULL ); 268 parse_table_add(&pt, "ReportProgress", PQ_BOOL, (void *)1, 269 &rw->report_progress, NULL); 270 parse_table_add(&pt, "Help", PQ_DFL|PQ_INT, &help_status_default, &help_status, NULL); 271 272 if (parse_arg_eq(a, &pt) < 0) { 273 cli_out("%s: Invalid option: %s\n", 274 ARG_CMD(a), ARG_CUR(a)); 275 goto done; 276 } 277 278 if (ARG_CNT(a) != 0) { 279 cli_out("%s: extra options starting with \"%s\"\n", 280 ARG_CMD(a), ARG_CUR(a)); 281 goto done; 282 } 283 if (help_status == 1) { 284 rv=-1; 285 cli_out("%s\n",tr52_test_usage); 286 goto done; 287 } 288 289 if (mem_name == 0 || *mem_name == 0 || 290 parse_memory_name(unit, 291 &rw->mem, 292 mem_name, 293 &rw->copyno, 294 0) < 0) { 295 test_error(unit, 296 "Missing or unknown memory name " 297 "(use listmem for list)\n"); 298 goto done; 299 } 300 301 { 302 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 303 if (!soc_mem_is_valid(unit, rw->mem) || 304 soc_mem_is_readonly(unit, rw->mem) || 305 soc_mem_index_max(unit, rw->mem) < 3) { 306 if (soc_feature(unit,soc_feature_esm_support)) { 307 if ((rw->mem == L3_DEFIPm && SOC_MEM_IS_ENABLED(unit, L3_DEFIPm)) || 308 (rw->mem == L3_DEFIP_ONLYm && SOC_MEM_IS_ENABLED(unit, L3_DEFIP_ONLYm)) || 309 (rw->mem == L3_DEFIP_DATA_ONLYm && SOC_MEM_IS_ENABLED(unit, L3_DEFIP_DATA_ONLYm)) || 310 (rw->mem == L3_DEFIP_HIT_ONLYm && SOC_MEM_IS_ENABLED(unit, L3_DEFIP_DATA_ONLYm)) || 311 (rw->mem == L3_DEFIP_PAIR_128_DATA_ONLYm && SOC_MEM_IS_ENABLED(unit, L3_DEFIP_PAIR_128_DATA_ONLYm)) || 312 (rw->mem == L3_DEFIP_PAIR_128_HIT_ONLYm && SOC_MEM_IS_ENABLED(unit, L3_DEFIP_PAIR_128_HIT_ONLYm))) { 313 /* The above internal memories will not be supported if External TCAM is present. 314 These internal memories are set to 0 and hence can not run the test on these memories.*/ 315 return BCM_E_UNAVAIL; 316 } else { 317 test_error(unit, 318 "Cannot test memory %s with this command\n", 319 SOC_MEM_UFNAME(unit, rw->mem)); 320 goto done; 321 } 322 } else { 323 test_error(unit, 324 "Cannot test memory %s with this command\n", 325 SOC_MEM_UFNAME(unit, rw->mem)); 326 goto done; 327 } 328 } 329 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 330 } 331 #if defined (BCM_TOMAHAWK2_SUPPORT) 332 if (soc_feature(unit,soc_feature_no_vfp) && 333 ((rw->mem >= VFP_TCAMm && rw->mem <= VFP_TCAM_PIPE3m) || 334 (rw->mem >= VFP_POLICY_TABLEm && rw->mem <= VFP_POLICY_TABLE_PIPE3m))) { 335 test_msg("VFP is not supported.Cannot test memory %s \n", SOC_MEM_UFNAME(unit, rw->mem)); 336 rv = SOC_E_UNAVAIL; 337 goto done; 338 } 339 #endif /*BCM_TOMAHAWK2_SUPPORT*/ 340 #if defined(BCM_DFE_SUPPORT) || defined(BCM_PETRA_SUPPORT) || defined (BCM_DNXF_SUPPORT) 341 if (SOC_IS_SAND(unit) && (soc_mem_is_writeonly(unit, rw->mem) || soc_mem_is_signal(unit, rw->mem))) { 342 test_error(unit, "Memory %s is writeonly/signal \n", 343 SOC_MEM_UFNAME(unit, rw->mem)); 344 goto done; 345 } 346 #endif 347 #ifdef BCM_PETRA_SUPPORT 348 if(SOC_IS_ARAD(unit)) { 349 switch(rw->mem) { 350 case BRDC_FSRD_FSRD_WL_EXT_MEMm: 351 case IQM_MEM_8000000m: 352 case NBI_TBINS_MEMm: 353 case NBI_RBINS_MEMm: 354 case PORT_WC_UCMEM_DATAm: 355 case ECI_MBU_MEMm: 356 case EGQ_CBMm: 357 case EGQ_RDMUCm: 358 359 test_error(unit, "Memory %s is invalid/readonly/writeonly/signal \n", 360 SOC_MEM_UFNAME(unit, rw->mem)); 361 362 goto done; 363 default: 364 break; 365 } 366 } 367 #endif 368 #ifdef BCM_DNXF_SUPPORT 369 if (SOC_IS_DNXF(unit)) 370 { 371 if (!SOC_MEM_IS_VALID(unit, rw->mem) 372 || (soc_mem_flags(unit, rw->mem) & (SOC_MEM_FLAG_READONLY | SOC_MEM_FLAG_WRITEONLY | SOC_MEM_FLAG_SIGNAL)) != 0) 373 { 374 return 1; 375 } 376 switch (rw->mem) 377 { 378 case BRDC_QRH_FFLBm: 379 case BRDC_QRH_MCLBTm: 380 case BRDC_QRH_MCSFFm: 381 case BRDC_QRH_MNOLm: 382 case FSRD_FSRD_PROM_MEMm: 383 case QRH_FFLBm: 384 case QRH_MCLBTm: 385 case QRH_MCSFFm: 386 case QRH_MNOLm: 387 test_error(unit, "Memory %s is invalid/readonly/writeonly/signal \n", 388 SOC_MEM_UFNAME(unit, rw->mem)); 389 goto done; /* Skip these tables */ 390 default: 391 break; 392 } 393 } 394 #endif 395 #if defined (BCM_DFE_SUPPORT) 396 if(SOC_IS_DFE(unit)) 397 { 398 int rv; 399 int is_filtered = 0; 400 401 rv = MBCM_DFE_DRIVER_CALL(unit, mbcm_dfe_drv_test_mem_filter, (unit, rw->mem, &is_filtered)); 402 if (rv != SOC_E_NONE) 403 { 404 return rv; 405 } 406 if (is_filtered) 407 { 408 test_error(unit, "Memory %s is invalid/readonly/writeonly/signal \n", 409 SOC_MEM_UFNAME(unit,rw->mem)); 410 goto done; 411 } 412 } 413 #endif /*BCM_DFE_SUPPORT*/ 414 415 if (rw->copyno == COPYNO_ALL) { 416 rw->copyno_total = 0; 417 SOC_MEM_BLOCK_ITER(unit, rw->mem, blk) { 418 rw->copyno_total += 1; 419 } 420 } else { 421 rw->copyno_total = 1; 422 if (!SOC_MEM_BLOCK_VALID(unit, rw->mem, rw->copyno)) { 423 { 424 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 425 test_error(unit, 426 "Copy number out of range for memory %s\n", 427 SOC_MEM_UFNAME(unit, rw->mem)); 428 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 429 } 430 goto done; 431 } 432 } 433 434 rw->index_min = parse_memory_index(unit, rw->mem, idx_start_str); 435 rw->index_max = parse_memory_index(unit, rw->mem, idx_end_str); 436 rw->array_index_start = parse_memory_array_index(unit, rw->mem, array_idx_start_str); 437 rw->array_index_end = parse_memory_array_index(unit, rw->mem, array_idx_end_str); 438 if (rw->array_index_start > rw->array_index_end ) { 439 unsigned temp_ai = rw->array_index_start; 440 rw->array_index_start = rw->array_index_end; 441 rw->array_index_end = temp_ai; 442 cli_out("WARNING: switching start and end array indices to %u-%u\n", rw->array_index_start, rw->array_index_end); 443 } 444 #ifdef BCM_FIREBOLT_SUPPORT 445 if (SOC_IS_FB_FX_HX(unit)) { 446 if (rw->index_min < soc_mem_index_min(unit, rw->mem)) { 447 rw->index_min = soc_mem_index_min(unit, rw->mem); 448 } 449 } 450 #endif /* BCM_FIREBOLT_SUPPORT */ 451 rw->index_total = rw->index_max - rw->index_min + 1; 452 453 if (rw->index_total <= 1 || rw->copyno_total < 1) { 454 test_error(unit, 455 "Min copyno/index must be less than max copyno/index\n"); 456 goto done; 457 } 458 459 /* Place MMU in debug mode if testing a CBP memory */ 460 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNXF_SUPPORT) 461 if (soc_mem_is_debug(unit, rw->mem) && 462 (rw->was_debug_mode = soc_mem_debug_set(unit, 0)) < 0) { 463 test_error(unit, "Could not put MMU in debug mode\n"); 464 goto done; 465 } 466 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 467 468 /* Disable non-atomic TCAM write handling */ 469 rw->saved_tcam_protect_write = SOC_CONTROL(unit)->tcam_protect_write; 470 SOC_CONTROL(unit)->tcam_protect_write = FALSE; 471 472 #if defined (BCM_DFE_SUPPORT) || defined(BCM_DNXF_SUPPORT) 473 if(SOC_IS_DFE(unit) || SOC_IS_DNXF(unit)) { 474 SOC_MEM_TEST_SKIP_CACHE_SET(unit, 1); 475 /* Disable any parity control (herc) */ 476 if (soc_mem_parity_control(unit, rw->mem, rw->copyno, FALSE) < 0) { 477 test_error(unit, "Could not disable parity warnings on memory %s\n", 478 SOC_MEM_UFNAME(unit, rw->mem)); 479 goto done; 480 } 481 } else 482 #endif /* BCM_DFE_SUPPORT */ 483 { 484 #if defined (BCM_ESW_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) 485 if (addr_rand_common_clear(unit, rw->mem, rw->copyno)) { 486 goto done; 487 } 488 #endif /* BCM_ESW_SUPPORT || BCM_PETRA_SUPPORT */ 489 } 490 491 { 492 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 493 if (soc_mem_cache_get(unit, rw->mem, 494 rw->copyno == COPYNO_ALL ? 495 MEM_BLOCK_ALL : rw->copyno)) { 496 cli_out("WARNING: Caching is enabled on memory %s.%s\n", 497 SOC_MEM_UFNAME(unit, rw->mem), 498 SOC_BLOCK_NAME(unit, rw->copyno)); 499 } 500 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 501 } 502 503 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 504 if (soc_mem_cpu_write_control(unit, rw->mem, rw->copyno, TRUE, 505 &rw->orig_enable) < 0) { 506 test_error(unit, "Could not enable exclusive cpu write on memory %s\n", 507 SOC_MEM_UFNAME(unit, rw->mem)); 508 goto done; 509 } 510 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 511 512 /* 513 * Turn off L2 task to keep it from going crazy if L2 memory is 514 * being tested. 515 */ 516 517 #ifdef BCM_XGS_SWITCH_SUPPORT 518 if (soc_feature(unit, soc_feature_arl_hashed)) { 519 (void)soc_l2x_stop(unit); 520 } 521 #endif /* BCM_XGS_SWITCH_SUPPORT */ 522 #ifdef BCM_SHADOW_SUPPORT 523 if (SOC_IS_SHADOW(unit) && (rw->mem == EGR_PERQ_XMT_COUNTERSm)) { 524 rv = soc_reg_field32_modify(unit, EGR_EDB_HW_CONTROLr, REG_PORT_ANY, 525 XGS_COUNTER_COMPAT_MODEf, 1); 526 if (rv != SOC_E_NONE) { 527 goto done; 528 } 529 } 530 if (SOC_IS_SHADOW(unit) && SOC_BLOCK_IS_CMP(unit, 531 SOC_MEM_BLOCK_MIN(unit, rw->mem), SOC_BLK_MS_ISEC)) { 532 rv = soc_reg_field32_modify(unit, ISEC_MASTER_CTRLr, 1, 533 XGS_COUNTER_COMPAT_MODEf, 1); 534 if (rv != SOC_E_NONE) { 535 return -1; 536 } 537 rv = soc_reg_field32_modify(unit, ISEC_MASTER_CTRLr, 5, 538 XGS_COUNTER_COMPAT_MODEf, 1); 539 if (rv != SOC_E_NONE) { 540 return -1; 541 } 542 } 543 if (SOC_IS_SHADOW(unit) && SOC_BLOCK_IS_CMP(unit, 544 SOC_MEM_BLOCK_MIN(unit, rw->mem), SOC_BLK_MS_ESEC)) { 545 rv = soc_reg_field32_modify(unit, ESEC_MASTER_CTRLr, 1, 546 XGS_COUNTER_COMPAT_MODEf, 1); 547 if (rv != SOC_E_NONE) { 548 return -1; 549 } 550 rv = soc_reg_field32_modify(unit, ESEC_MASTER_CTRLr, 5, 551 XGS_COUNTER_COMPAT_MODEf, 1); 552 if (rv != SOC_E_NONE) { 553 return -1; 554 } 555 } 556 #endif 557 558 /* 559 * Turn off FP. 560 * Required when testing FP and METERING memories or tests will fail. 561 * We don't care about the return value as the BCM layer may not have 562 * been initialized at all. 563 */ 564 (void)bcm_field_detach(unit); 565 566 #ifdef BCM_TRIUMPH_SUPPORT 567 if (soc_feature(unit, soc_feature_esm_support)) { 568 /* Some tables have dependency on the content of other table */ 569 switch (rw->mem) { 570 case EXT_ACL360_TCAM_DATAm: 571 case EXT_ACL360_TCAM_DATA_IPV6_SHORTm: 572 rv = soc_mem_clear(unit, EXT_ACL360_TCAM_MASKm, 573 MEM_BLOCK_ALL, TRUE); 574 if (rv < 0) { 575 test_error(unit, "Could not clear EXT_ACL360_TCAM_MASK\n"); 576 goto done; 577 } 578 break; 579 case EXT_ACL432_TCAM_DATAm: 580 case EXT_ACL432_TCAM_DATA_IPV6_LONGm: 581 case EXT_ACL432_TCAM_DATA_L2_IPV4m: 582 case EXT_ACL432_TCAM_DATA_L2_IPV6m: 583 rv = soc_mem_clear(unit, EXT_ACL432_TCAM_MASKm, 584 MEM_BLOCK_ALL, TRUE); 585 if (rv < 0) { 586 test_error(unit, "Could not clear EXT_ACL432_TCAM_MASK\n"); 587 goto done; 588 } 589 break; 590 default: 591 break; 592 } 593 } 594 #endif /* BCM_TRIUMPH_SUPPORT */ 595 #ifdef BCM_TRIUMPH3_SUPPORT 596 if (soc_feature(unit, soc_feature_etu_support)) { 597 /* Some tables have dependency on the content of other table */ 598 switch (rw->mem) { 599 case EXT_ACL480_TCAM_DATAm: 600 if (SOC_FAILURE(soc_mem_clear(unit, EXT_ACL480_TCAM_MASKm, 601 MEM_BLOCK_ALL, TRUE))) 602 { 603 test_error(unit, "Failed to clear EXT_ACL360_TCAM_MASKm\n"); 604 parse_arg_eq_done(&pt); 605 return -1; 606 } 607 break; 608 default: 609 break; 610 } 611 } 612 #endif /* BCM_TRIUMPH3_SUPPORT */ 613 614 /* Choose a value for increment that is 615 relatively prime to total index. */ 616 rw->addr_incr = get_rel_prime(rw->index_total, rw->seed * 617 rw->index_total); 618 rw->first_addr = (rw->addr_incr % rw->index_total) + rw->index_min; 619 LOG_INFO(BSL_LS_APPL_TESTS, 620 (BSL_META_U(unit, 621 "Running with simple seed. Incr: %d. First 0x%x.\n"), 622 rw->addr_incr, rw->first_addr)); 623 624 *p = rw; 625 626 rv = 0; 627 628 done: 629 parse_arg_eq_done(&pt); 630 return rv; 631 } 632 633 #define NEXT_ADDR(cur) \ 634 ((((cur) - rw->index_min + rw->addr_incr) % rw->index_total) + rw->index_min) 635 636 637 int 638 addr_rand(int unit, args_t *a, void *p) 639 { 640 rand_work_t *rw = p; 641 uint32 mask[SOC_MAX_MEM_WORDS]; 642 uint32 tcammask[SOC_MAX_MEM_WORDS]; 643 uint32 eccmask[SOC_MAX_MEM_WORDS]; 644 uint32 forcemask[SOC_MAX_MEM_WORDS]; 645 uint32 forcedata[SOC_MAX_MEM_WORDS]; 646 uint32 accum_tcammask, accum_forcemask; 647 int iter, i, dw, word, copyno; 648 unsigned array_index; 649 uint32 data[SOC_MAX_MEM_WORDS]; 650 char status[160]; 651 int count; 652 int skip_count; 653 uint32 miscomp; 654 655 COMPILER_REFERENCE(a); 656 657 if (rw->index_total <= 0) { 658 return -1; 659 } 660 sal_memset(data, 0, SOC_MAX_MEM_WORDS * sizeof(uint32)); 661 662 dw = soc_mem_entry_words(unit, rw->mem); 663 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) ||\ 664 defined(BCM_GREYHOUND2_SUPPORT) || defined(BCM_DNXF_SUPPORT) ||\ 665 defined(BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 666 if(SOC_IS_DPP(unit) || SOC_IS_DFE(unit) || SOC_IS_GREYHOUND2(unit) || SOC_IS_DNXF(unit) || SOC_IS_DNX(unit)) { 667 soc_mem_datamask_rw_get(unit, rw->mem, mask); 668 } else 669 #endif 670 { 671 soc_mem_datamask_get(unit, rw->mem, mask); 672 } 673 soc_mem_tcammask_get(unit, rw->mem, tcammask); 674 soc_mem_eccmask_get(unit, rw->mem, eccmask); 675 soc_mem_forcedata_get(unit, rw->mem, forcemask, forcedata); 676 accum_tcammask = 0; 677 for (i = 0; i < dw; i++) { 678 accum_tcammask |= tcammask[i]; 679 } 680 accum_forcemask = 0; 681 for (i = 0; i < dw; i++) { 682 accum_forcemask |= forcemask[i]; 683 } 684 if (!rw->ecc_as_data) { 685 for (i = 0; i < dw; i++) { 686 mask[i] &= ~eccmask[i]; 687 } 688 } 689 soc_mem_datamask_memtest(unit, rw->mem, mask); 690 691 progress_init(rw->copyno_total * rw->iters * rw->index_total * (rw->array_index_end - rw->array_index_start + 1) * 2, 3, 0); 692 693 SOC_MEM_BLOCK_ITER(unit, rw->mem, copyno) { 694 if (rw->copyno != COPYNO_ALL && rw->copyno != copyno) { 695 continue; 696 } 697 698 for (array_index = rw->array_index_start; array_index <= rw->array_index_end; ++array_index) { 699 700 if (rw->array_index_start != 0 || rw->array_index_end != rw->array_index_start) { 701 { 702 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 703 sal_sprintf(status, 704 "Running %d iterations on %s[%u].%s[%d-%d]", 705 rw->iters, 706 SOC_MEM_UFNAME(unit, rw->mem), 707 array_index, 708 SOC_BLOCK_NAME(unit, copyno), 709 rw->index_min, rw->index_max); 710 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 711 } 712 } else { 713 { 714 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 715 sal_sprintf(status, 716 "Running %d iterations on %s.%s[%d-%d]", 717 rw->iters, 718 SOC_MEM_UFNAME(unit, rw->mem), 719 SOC_BLOCK_NAME(unit, copyno), 720 rw->index_min, rw->index_max); 721 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 722 } 723 } 724 725 progress_status(status); 726 727 for (iter = 0; iter < rw->iters; iter++) { 728 /* Set up addr and data and write to all memory addresses */ 729 730 rw->cur_addr = rw->first_addr; 731 rw->data = rw->data_start; 732 733 count = 0; 734 skip_count = 0; 735 do { 736 count++; 737 do { 738 if (soc_mem_test_skip(unit, rw->mem, rw->cur_addr)) { 739 rw->cur_addr = NEXT_ADDR(rw->cur_addr); 740 skip_count++; 741 } else { 742 break; 743 } 744 } while (rw->cur_addr != rw->first_addr); 745 746 if (rw->cur_addr == rw->first_addr) { 747 if ((count == 1 && skip_count == rw->index_total) || (count != 1)) { 748 break; 749 } 750 } 751 752 if (soc_mem_entry_words(unit, rw->mem) % 2 == 0) { 753 rw->data = ~rw->data; 754 } 755 for (word = 0; word < dw; word++) { 756 data[word] = rw->data & mask[word]; 757 rw->data = ~rw->data; 758 } 759 if (accum_tcammask) { 760 /* data read back has dependency on mask */ 761 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) || 762 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU)) { 763 for (word = 0; word < dw; word++) { 764 data[word] &= ~tcammask[word]; 765 } 766 } else if (soc_feature(unit, soc_feature_xy_tcam)) { 767 for (word = 0; word < dw; word++) { 768 data[word] |= tcammask[word]; 769 } 770 } 771 } 772 if (accum_forcemask) { 773 for (word = 0; word < dw; word++) { 774 data[word] &= ~forcemask[word]; 775 data[word] |= forcedata[word]; 776 } 777 } 778 779 #ifdef BCM_TOMAHAWK3_SUPPORT 780 if (rw->mem == CDMIB_MEMm && array_index == 12) { 781 data[14] = 0x00000000; 782 data[15] = 0x00000000; 783 } 784 #endif 785 786 { 787 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 788 /* coverity[NEGATIVE_RETURNS: FALSE] */ 789 if (soc_mem_array_write(unit, rw->mem, array_index, copyno, 790 rw->cur_addr, data) < 0) { 791 cli_out("Write ERROR: table %s.%s[%d] iteration %d\n", 792 SOC_MEM_UFNAME(unit, rw->mem), 793 SOC_BLOCK_NAME(unit, copyno), 794 rw->cur_addr, iter); 795 if (rw->array_index_start != 0 || rw->array_index_end != rw->array_index_start) { 796 cli_out("At array index %u.\n", array_index); 797 } 798 goto break_all; 799 } 800 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 801 } 802 803 rw->cur_addr = NEXT_ADDR(rw->cur_addr); 804 if (rw->report_progress) { 805 progress_report(1); 806 } 807 } while (rw->cur_addr != rw->first_addr); 808 809 /* Reset addr and data and Verify values written */ 810 811 rw->cur_addr = rw->first_addr; 812 rw->data = rw->data_start; 813 814 miscomp = 0; 815 816 if ((count + skip_count) != rw->index_total) { 817 cli_out("WARNING: number of writes != index total\n"); 818 } 819 820 count = 0; 821 skip_count = 0; 822 do { 823 count++; 824 do { 825 if (soc_mem_test_skip(unit, rw->mem, rw->cur_addr)) { 826 rw->cur_addr = NEXT_ADDR(rw->cur_addr); 827 skip_count++; 828 } else { 829 break; 830 } 831 } while (rw->cur_addr != rw->first_addr); 832 833 if (rw->cur_addr == rw->first_addr) { 834 if ((count == 1 && skip_count == rw->index_total) || (count != 1)) { 835 break; 836 } 837 } 838 if (soc_mem_entry_words(unit, rw->mem) % 2 == 0) { 839 rw->data = ~rw->data; 840 } 841 { 842 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 843 if (soc_mem_array_read(unit, rw->mem, array_index, copyno, 844 rw->cur_addr, data) < 0) { 845 cli_out("Read ERROR: table %s.%s[%d] iteration %d\n", 846 SOC_MEM_UFNAME(unit, rw->mem), 847 SOC_BLOCK_NAME(unit, copyno), 848 rw->cur_addr, iter); 849 if (rw->array_index_start != 0 || rw->array_index_end != rw->array_index_start) { 850 cli_out("At array index %u.\n", array_index); 851 } 852 goto break_all; 853 } 854 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 855 } 856 857 for (word = 0; word < dw; word++) { 858 uint32 comp_word = rw->data & mask[word]; 859 if (accum_tcammask) { 860 /* data read back has dependency on mask */ 861 if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM)|| 862 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU)) { 863 comp_word &= ~tcammask[word]; 864 } else if (soc_feature(unit, soc_feature_xy_tcam)) { 865 comp_word |= tcammask[word]; 866 } 867 } 868 if (accum_forcemask) { 869 comp_word &= ~forcemask[word]; 870 comp_word |= forcedata[word]; 871 } 872 #ifdef BCM_TOMAHAWK3_SUPPORT 873 if (rw->mem == CDMIB_MEMm) { 874 comp_word &= data[word]; 875 } 876 #endif 877 if ((data[word] ^ comp_word) & mask[word]) { 878 soc_pci_analyzer_trigger(unit); 879 880 if (rw->array_index_start != 0 || rw->array_index_end != rw->array_index_start) { 881 { 882 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 883 cli_out("Compare ERROR: table %s[%u].%s iteration %d\n", 884 SOC_MEM_UFNAME(unit, rw->mem), array_index, 885 SOC_BLOCK_NAME(unit, copyno), iter+1); 886 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 887 } 888 } else { 889 { 890 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) || defined (BCM_DNXF_SUPPORT) 891 cli_out("Compare ERROR: table %s.%s iteration %d\n", 892 SOC_MEM_UFNAME(unit, rw->mem), 893 SOC_BLOCK_NAME(unit, copyno), iter+1); 894 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 895 } 896 } 897 cli_out("Wrote word %d: 0x%08x.\n", word, comp_word); 898 cli_out("Read word %d: 0x%08x.\n", word, data[word]); 899 cli_out("Difference: 0x%08x.\n", 900 comp_word ^ data[word]); 901 miscomp = 1; 902 } 903 rw->data = ~rw->data; 904 } 905 906 rw->cur_addr = NEXT_ADDR(rw->cur_addr); 907 908 if (rw->report_progress) { 909 progress_report(1); 910 } 911 } while ((rw->cur_addr != rw->first_addr) && (!miscomp)); 912 913 if (miscomp) { 914 cli_out("Cycle aborted due to error\n"); 915 test_error(unit, "\n"); 916 } 917 } 918 } 919 } 920 921 break_all: 922 progress_done(); 923 924 return 0; 925 } 926 927 int 928 addr_rand_done(int unit, void *p) 929 { 930 rand_work_t *rw = p; 931 #ifdef BCM_SHADOW_SUPPORT 932 int rv = SOC_E_NONE; 933 #endif 934 935 if (rw) { 936 /* Take MMU out of debug mode if testing a CBP memory */ 937 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNXF_SUPPORT) 938 if (soc_mem_is_debug(unit,rw->mem) && 939 rw->was_debug_mode >= 0 && 940 soc_mem_debug_set(unit, rw->was_debug_mode) < 0) { 941 test_error(unit, "Could not restore previous MMU debug state\n"); 942 return -1; 943 } 944 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 945 946 /* Restore non-atomic TCAM write handling status */ 947 SOC_CONTROL(unit)->tcam_protect_write = rw->saved_tcam_protect_write; 948 949 #if defined (BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)|| defined (BCM_PETRA_SUPPORT) || defined (BCM_DNXF_SUPPORT) 950 if (soc_mem_cpu_write_control(unit, rw->mem, rw->copyno, 951 rw->orig_enable, &rw->orig_enable) < 0) { 952 test_error(unit, "Could not disable exclusive cpu write on memory " 953 "%s\n", 954 SOC_MEM_UFNAME(unit, rw->mem)); 955 return -1; 956 } 957 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */ 958 959 #if defined (BCM_DFE_SUPPORT) || defined(BCM_DNXF_SUPPORT) 960 if(SOC_IS_DFE(unit) || SOC_IS_DNXF(unit)) { 961 SOC_MEM_TEST_SKIP_CACHE_SET(unit, 0); 962 if (soc_mem_parity_restore(unit, rw->mem, rw->copyno) < 0) { 963 test_error(unit, "Could not enable parity warnings on memory %s\n", 964 SOC_MEM_UFNAME(unit, rw->mem)); 965 return -1; 966 } 967 } else 968 #endif /* BCM_DFE_SUPPORT */ 969 { 970 #if defined (BCM_ESW_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined (BCM_DNX_SUPPORT) 971 if (addr_rand_common_restore(unit, rw->mem, rw->copyno)) { 972 return -1; 973 } 974 #endif /* BCM_ESW_SUPPORT || BCM_PETRA_SUPPORT */ 975 } 976 977 #ifdef BCM_SHADOW_SUPPORT 978 if (SOC_IS_SHADOW(unit) && (rw->mem == EGR_PERQ_XMT_COUNTERSm)) { 979 rv = soc_reg_field32_modify(unit, EGR_EDB_HW_CONTROLr, REG_PORT_ANY, 980 XGS_COUNTER_COMPAT_MODEf, 0); 981 if (rv != SOC_E_NONE) { 982 return -1; 983 } 984 } 985 if (SOC_IS_SHADOW(unit) && SOC_BLOCK_IS_CMP(unit, 986 SOC_MEM_BLOCK_MIN(unit, rw->mem), SOC_BLK_MS_ISEC)) { 987 rv = soc_reg_field32_modify(unit, ISEC_MASTER_CTRLr, 1, 988 XGS_COUNTER_COMPAT_MODEf, 0); 989 if (rv != SOC_E_NONE) { 990 return -1; 991 } 992 rv = soc_reg_field32_modify(unit, ISEC_MASTER_CTRLr, 5, 993 XGS_COUNTER_COMPAT_MODEf, 0); 994 if (rv != SOC_E_NONE) { 995 return -1; 996 } 997 } 998 if (SOC_IS_SHADOW(unit) && SOC_BLOCK_IS_CMP(unit, 999 SOC_MEM_BLOCK_MIN(unit, rw->mem), SOC_BLK_MS_ESEC)) { 1000 rv = soc_reg_field32_modify(unit, ESEC_MASTER_CTRLr, 1, 1001 XGS_COUNTER_COMPAT_MODEf, 0); 1002 if (rv != SOC_E_NONE) { 1003 return -1; 1004 } 1005 rv = soc_reg_field32_modify(unit, ESEC_MASTER_CTRLr, 5, 1006 XGS_COUNTER_COMPAT_MODEf, 0); 1007 if (rv != SOC_E_NONE) { 1008 return -1; 1009 } 1010 } 1011 #endif 1012 } 1013 1014 return 0; 1015 } 1016 1017 #endif /* BCM_ESW_SUPPORT || BCM_DFE_SUPPORT || BCM_PETRA_SUPPORT */