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