mem.c (117159B)
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 * socdiag memory commands 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <soc/mem.h> 14 #include <soc/debug.h> 15 #include <shared/bsl.h> 16 #include <soc/error.h> 17 #include <soc/l2x.h> 18 #include <soc/l3x.h> 19 #include <soc/soc_ser_log.h> 20 #ifdef BCM_ISM_SUPPORT 21 #include <soc/ism.h> 22 #endif 23 #include <appl/diag/system.h> 24 #ifdef BCM_TRIDENT2_SUPPORT 25 #include <soc/trident2.h> 26 #endif 27 #ifdef BCM_TOMAHAWK_SUPPORT 28 #include <soc/tomahawk.h> 29 #endif 30 #ifdef BCM_TOMAHAWK3_SUPPORT 31 #include <soc/tomahawk3.h> 32 #endif 33 34 #ifdef BCM_TRIDENT3_SUPPORT 35 #include <soc/esw/flow_db.h> 36 #include <soc/esw/flow_db_core.h> 37 #endif 38 #ifdef ALPM_ENABLE 39 #include <soc/alpm.h> 40 #endif 41 #ifdef __KERNEL__ 42 #define atoi _shr_ctoi 43 #endif 44 45 #ifdef INCLUDE_MEM_SCAN 46 static sal_usecs_t prev_memscan_interval[SOC_MAX_NUM_DEVICES]; 47 static int prev_memscan_rate[SOC_MAX_NUM_DEVICES]; 48 #endif 49 #ifdef BCM_SRAM_SCAN_SUPPORT 50 static sal_usecs_t prev_sramscan_interval[SOC_MAX_NUM_DEVICES]; 51 static int prev_sramscan_rate[SOC_MAX_NUM_DEVICES]; 52 #endif 53 54 /* Memory counter array */ 55 static mem_count_t *mem_count[SOC_MAX_NUM_DEVICES]; 56 57 /* local defines */ 58 #define FIELD_ID_ARRAY_SIZE 40 59 60 /* 61 * Utility routine to concatenate the first argument ("first"), with 62 * the remaining arguments, with commas separating them. 63 */ 64 65 static void 66 collect_comma_args(args_t *a, char *valstr, char *first) 67 { 68 char *s; 69 70 sal_strcpy(valstr, first); 71 72 while ((s = ARG_GET(a)) != 0) { 73 sal_strcat(valstr, ","); 74 sal_strcat(valstr, s); 75 } 76 } 77 78 static void 79 check_global(int unit, soc_mem_t mem, char *s, int *is_global) 80 { 81 soc_field_info_t *fld; 82 soc_mem_info_t *m = &SOC_MEM_INFO(unit, mem); 83 char *eqpos; 84 85 eqpos = strchr(s, '='); 86 if (eqpos != NULL) { 87 *eqpos++ = 0; 88 } 89 for (fld = &m->fields[0]; fld < &m->fields[m->nFields]; fld++) { 90 if (!sal_strcasecmp(s, SOC_FIELD_NAME(unit, fld->field)) && 91 (fld->flags & SOCF_GLOBAL)) { 92 break; 93 } 94 } 95 if (fld == &m->fields[m->nFields]) { 96 *is_global = 0; 97 } else { 98 *is_global = 1; 99 } 100 } 101 102 static int 103 collect_comma_args_with_view(args_t *a, char *valstr, char *first, 104 char *view, int unit, soc_mem_t mem) 105 { 106 char *s, *s_copy = NULL, *f_copy = NULL; 107 int is_global, rv = 0; 108 109 if ((f_copy = sal_alloc(sal_strlen(first) + 1, "first")) == NULL) { 110 cli_out("cmd_esw_mem_write : Out of memory\n"); 111 rv = -1; 112 goto done; 113 } 114 sal_memset(f_copy, 0, sal_strlen(first) + 1); 115 sal_strcpy(f_copy, first); 116 117 /* Check if field is global before applying view prefix */ 118 check_global(unit, mem, f_copy, &is_global); 119 if (!is_global) { 120 sal_strcpy(valstr, view); 121 sal_strcat(valstr, first); 122 } else { 123 sal_strcpy(valstr, first); 124 } 125 126 while ((s = ARG_GET(a)) != 0) { 127 if ((s_copy = sal_alloc(sal_strlen(s) + 1, "s_copy")) == NULL) { 128 cli_out("cmd_esw_mem_write : Out of memory\n"); 129 rv = -1; 130 goto done; 131 } 132 sal_memset(s_copy, 0, sal_strlen(s) + 1); 133 sal_strcpy(s_copy, s); 134 check_global(unit, mem, s_copy, &is_global); 135 sal_free(s_copy); 136 sal_strcat(valstr, ","); 137 if (!is_global) { 138 sal_strcat(valstr, view); 139 sal_strcat(valstr, s); 140 } else { 141 sal_strcat(valstr, s); 142 } 143 } 144 done: 145 if (f_copy != NULL) { 146 sal_free(f_copy); 147 } 148 return rv; 149 } 150 151 static int 152 _modify_flex_mem_fields(int unit, soc_mem_t mem, uint32 *entry, 153 uint32 *mask, char *mod, int incr) 154 { 155 #ifdef BCM_TRIDENT3_SUPPORT 156 int rv = CMD_NFND; 157 soc_field_info_t *fld; 158 char *fmod, *fval, *s; 159 char *modstr = NULL; 160 char *tokstr = NULL; 161 uint32 fvalue[SOC_MAX_MEM_FIELD_WORDS]; 162 uint32 fincr[SOC_MAX_MEM_FIELD_WORDS]; 163 int i, entry_dw; 164 soc_mem_info_t *m = &SOC_MEM_INFO(unit, mem); 165 char *mod_ptr = NULL; 166 soc_field_t key_type_fid = 0; 167 soc_field_t data_type_fid = 0; 168 int key_type = 0; 169 int data_type = 0; 170 int flex_view = FALSE; 171 soc_mem_t mem_view_id; 172 soc_flow_db_mem_view_field_info_t view_field; 173 int field_type; 174 uint32 cnt; 175 int ix = 0; 176 uint32 field_id[FIELD_ID_ARRAY_SIZE]; 177 int field_found; 178 soc_field_info_t soc_field; 179 char *field_name; 180 181 if (!soc_feature(unit, soc_feature_flex_flow)) { 182 return CMD_NFND; 183 } 184 /* check if flow_db is initialized */ 185 rv = soc_flow_db_status_get(unit); 186 187 if (SOC_FAILURE(rv)) { 188 return CMD_NFND; 189 } 190 191 entry_dw = BYTES2WORDS(m->bytes); 192 193 if ((modstr = sal_alloc(ARGS_BUFFER, "modify_mem")) == NULL) { 194 cli_out("modify_mem_fields: Out of memory\n"); 195 return CMD_FAIL; 196 } 197 198 sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */ 199 modstr[ARGS_BUFFER - 1] = 0; 200 201 /* For flex view entry modification, user should always specify the 202 * key_type if applicable and data_type. 203 */ 204 mod_ptr = modstr; 205 while ((fmod = sal_strtok_r(mod_ptr, ",", &tokstr)) != 0) { 206 mod_ptr = NULL; /* Pass strtok NULL next time */ 207 fval = strchr(fmod, '='); 208 if (fval != NULL) { /* Point fval to arg, NULL if none */ 209 *fval++ = 0; /* Now fmod holds only field name. */ 210 211 if (!sal_strcasecmp(fmod, "KEY_TYPE0")) { 212 key_type_fid = KEY_TYPE0f; 213 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval); 214 key_type = fvalue[0]; 215 } else if (!sal_strcasecmp(fmod, "KEY_TYPE")) { 216 key_type_fid = KEY_TYPEf; 217 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval); 218 key_type = fvalue[0]; 219 } else if (!sal_strcasecmp(fmod, "DATA_TYPE0")) { 220 data_type_fid = DATA_TYPE0f; 221 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval); 222 data_type = fvalue[0]; 223 } else if (!sal_strcasecmp(fmod, "DATA_TYPE")) { 224 data_type_fid = DATA_TYPEf; 225 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval); 226 data_type = fvalue[0]; 227 } 228 } 229 } 230 if (key_type_fid || data_type_fid) { 231 if (!key_type) { 232 rv = soc_flow_db_mem_to_view_id_get (unit, mem, 233 SOC_FLOW_DB_KEY_TYPE_INVALID, data_type, 234 0, NULL, (uint32 *)&mem_view_id); 235 } else { 236 rv = soc_flow_db_mem_to_view_id_get (unit, mem, 237 key_type, data_type, 0, NULL, (uint32 *)&mem_view_id); 238 } 239 /* if error, fall thru to try non-flex action */ 240 if (rv == SOC_E_NONE) { 241 flex_view = TRUE; 242 } 243 } 244 245 if (flex_view == FALSE) { 246 sal_free(modstr); 247 return CMD_NFND; 248 } 249 250 /* restore back modstr */ 251 sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */ 252 modstr[ARGS_BUFFER - 1] = 0; 253 mod = modstr; 254 255 if (mask) { 256 memset(mask, 0, entry_dw * 4); 257 } 258 259 while ((fmod = sal_strtok_r(mod, ",", &tokstr)) != 0) { 260 mod = NULL; /* Pass strtok NULL next time */ 261 fval = strchr(fmod, '='); 262 if (fval != NULL) { /* Point fval to arg, NULL if none */ 263 *fval++ = 0; /* Now fmod holds only field name. */ 264 } 265 if (fmod[0] == 0) { 266 cli_out("Null field name\n"); 267 sal_free(modstr); 268 return CMD_FAIL; 269 } 270 if (!sal_strcasecmp(fmod, "clear")) { 271 sal_memset(entry, 0, entry_dw * sizeof (*entry)); 272 if (mask) { 273 memset(mask, 0xff, entry_dw * sizeof (*entry)); 274 } 275 continue; 276 } 277 field_found= FALSE; 278 for (field_type = SOC_FLOW_DB_FIELD_TYPE_CONTROL; 279 field_type < SOC_FLOW_DB_FIELD_TYPE_MAX; field_type++) { 280 rv = soc_flow_db_mem_view_field_list_get(unit, mem_view_id, 281 field_type, FIELD_ID_ARRAY_SIZE, field_id, &cnt); 282 if (SOC_SUCCESS(rv)) { 283 for (ix = 0; ix < cnt; ix++) { 284 if (field_type == SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY || 285 field_type == 286 SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA) { 287 (void) soc_flow_db_mem_view_field_name_get(unit, 288 mem_view_id, field_id[ix], &field_name); 289 } 290 else { 291 field_name = SOC_FIELD_NAME(unit,field_id[ix]); 292 } 293 294 if (!sal_strcasecmp(fmod, field_name)) { 295 field_found=TRUE; 296 break; 297 } 298 } 299 } 300 301 if (field_found == TRUE) { 302 break; 303 } 304 } 305 if (field_found == TRUE) { 306 rv = soc_flow_db_mem_view_field_info_get(unit,mem_view_id, 307 field_id[ix], &view_field); 308 } 309 if ((field_found == FALSE) || SOC_FAILURE(rv)) { 310 sal_free(modstr); 311 return CMD_NFND; 312 } 313 soc_field.field = field_id[ix]; 314 soc_field.len = view_field.width; 315 soc_field.bp = view_field.offset; 316 soc_field.flags = view_field.flags; 317 fld = &soc_field; 318 mem = mem_view_id; 319 320 if (!fval) { 321 cli_out("Missing %d-bit value to assign to \"%s\" field \"%s\".\n", 322 fld->len, 323 SOC_MEM_UFNAME(unit, mem), field_name); 324 sal_free(modstr); 325 return -1; 326 } 327 s = strchr(fval, '+'); 328 if (s == NULL) { 329 s = strchr(fval, '-'); 330 } 331 if (s == fval) { 332 s = NULL; 333 } 334 if (incr) { 335 if (s != NULL) { 336 parse_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS, 337 s[1] ? &s[1] : "1"); 338 if (*s == '-') { 339 neg_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS); 340 } 341 if (fld->len & 31) { 342 /* Proper treatment of sign extension */ 343 fincr[fld->len / 32] &= ~(0xffffffff << (fld->len & 31)); 344 } 345 soc_mem_field_get(unit, mem, entry, fld->field, fvalue); 346 add_long_integer(fvalue, fincr, SOC_MAX_MEM_FIELD_WORDS); 347 if (fld->len & 31) { 348 /* Proper treatment of sign extension */ 349 fvalue[fld->len / 32] &= ~(0xffffffff << (fld->len & 31)); 350 } 351 soc_mem_field_set(unit, mem, entry, fld->field, fvalue); 352 } 353 } else { 354 if (s != NULL) { 355 *s = 0; 356 } 357 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval); 358 for (i = fld->len; i < SOC_MAX_MEM_FIELD_BITS; i++) { 359 if (fvalue[i / 32] & 1 << (i & 31)) { 360 cli_out("Value \"%s\" too large for " 361 "%d-bit field \"%s\".\n", 362 fval, fld->len, field_name); 363 sal_free(modstr); 364 return CMD_FAIL; 365 } 366 } 367 soc_mem_field_set(unit, mem, entry, fld->field, fvalue); 368 } 369 if (mask) { 370 sal_memset(fvalue, 0, sizeof (fvalue)); 371 for (i = 0; i < fld->len; i++) { 372 fvalue[i / 32] |= 1 << (i & 31); 373 } 374 soc_mem_field_set(unit, mem, mask, fld->field, fvalue); 375 } 376 } 377 378 sal_free(modstr); 379 return CMD_OK; 380 #else 381 return CMD_NFND; 382 #endif 383 } 384 /* 385 * modify_mem_fields 386 * 387 * Verify similar to modify_reg_fields (see reg.c) but works on 388 * memory table entries instead of register values. Handles fields 389 * of any length. 390 * 391 * If mask is non-NULL, it receives an entry which is a mask of all 392 * fields modified. 393 * 394 * Values may be specified with optional increment or decrement 395 * amounts; for example, a MAC address could be 0x1234+2 or 0x1234-1 396 * to specify an increment of +2 or -1, respectively. 397 * 398 * If incr is FALSE, the increment is ignored and the plain value is 399 * stored in the field (e.g. 0x1234). 400 * 401 * If incr is TRUE, the value portion is ignored. Instead, the 402 * increment value is added to the existing value of the field. The 403 * field value wraps around on overflow. 404 * 405 * Returns -1 on failure, 0 on success. 406 */ 407 408 static int 409 _modify_mem_fields(int unit, soc_mem_t mem, uint32 *entry, 410 uint32 *mask, char *mod, int incr) 411 { 412 soc_field_info_t *fld; 413 char *fmod, *fval, *s; 414 char *modstr = NULL; 415 char *tokstr = NULL; 416 uint32 fvalue[SOC_MAX_MEM_FIELD_WORDS]; 417 uint32 fincr[SOC_MAX_MEM_FIELD_WORDS]; 418 int i, entry_dw; 419 soc_mem_info_t *m = &SOC_MEM_INFO(unit, mem); 420 421 entry_dw = BYTES2WORDS(m->bytes); 422 423 if ((modstr = sal_alloc(ARGS_BUFFER, "modify_mem")) == NULL) { 424 cli_out("modify_mem_fields: Out of memory\n"); 425 return CMD_FAIL; 426 } 427 428 sal_strncpy(modstr, mod, ARGS_BUFFER);/* Don't destroy input string */ 429 modstr[ARGS_BUFFER - 1] = 0; 430 mod = modstr; 431 432 if (mask) { 433 memset(mask, 0, entry_dw * 4); 434 } 435 436 while ((fmod = sal_strtok_r(mod, ",", &tokstr)) != 0) { 437 mod = NULL; /* Pass strtok NULL next time */ 438 fval = strchr(fmod, '='); 439 if (fval != NULL) { /* Point fval to arg, NULL if none */ 440 *fval++ = 0; /* Now fmod holds only field name. */ 441 } 442 if (fmod[0] == 0) { 443 cli_out("Null field name\n"); 444 sal_free(modstr); 445 return -1; 446 } 447 if (!sal_strcasecmp(fmod, "clear")) { 448 sal_memset(entry, 0, entry_dw * sizeof (*entry)); 449 if (mask) { 450 memset(mask, 0xff, entry_dw * sizeof (*entry)); 451 } 452 continue; 453 } 454 for (fld = &m->fields[0]; fld < &m->fields[m->nFields]; fld++) { 455 if (!sal_strcasecmp(fmod, SOC_FIELD_NAME(unit, fld->field))) { 456 break; 457 } 458 } 459 if (fld == &m->fields[m->nFields]) { 460 cli_out("No such field \"%s\" in memory \"%s\".\n", 461 fmod, SOC_MEM_UFNAME(unit, mem)); 462 sal_free(modstr); 463 return -1; 464 } 465 if (!fval) { 466 cli_out("Missing %d-bit value to assign to \"%s\" field \"%s\".\n", 467 fld->len, 468 SOC_MEM_UFNAME(unit, mem), SOC_FIELD_NAME(unit, fld->field)); 469 sal_free(modstr); 470 return -1; 471 } 472 s = strchr(fval, '+'); 473 if (s == NULL) { 474 s = strchr(fval, '-'); 475 } 476 if (s == fval) { 477 s = NULL; 478 } 479 if (incr) { 480 if (s != NULL) { 481 parse_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS, 482 s[1] ? &s[1] : "1"); 483 if (*s == '-') { 484 neg_long_integer(fincr, SOC_MAX_MEM_FIELD_WORDS); 485 } 486 if (fld->len & 31) { 487 /* Proper treatment of sign extension */ 488 fincr[fld->len / 32] &= ~(0xffffffff << (fld->len & 31)); 489 } 490 soc_mem_field_get(unit, mem, entry, fld->field, fvalue); 491 add_long_integer(fvalue, fincr, SOC_MAX_MEM_FIELD_WORDS); 492 if (fld->len & 31) { 493 /* Proper treatment of sign extension */ 494 fvalue[fld->len / 32] &= ~(0xffffffff << (fld->len & 31)); 495 } 496 soc_mem_field_set(unit, mem, entry, fld->field, fvalue); 497 } 498 } else { 499 if (s != NULL) { 500 *s = 0; 501 } 502 parse_long_integer(fvalue, SOC_MAX_MEM_FIELD_WORDS, fval); 503 for (i = fld->len; i < SOC_MAX_MEM_FIELD_BITS; i++) { 504 if (fvalue[i / 32] & 1 << (i & 31)) { 505 cli_out("Value \"%s\" too large for " 506 "%d-bit field \"%s\".\n", 507 fval, fld->len, SOC_FIELD_NAME(unit, fld->field)); 508 sal_free(modstr); 509 return -1; 510 } 511 } 512 soc_mem_field_set(unit, mem, entry, fld->field, fvalue); 513 } 514 if (mask) { 515 sal_memset(fvalue, 0, sizeof (fvalue)); 516 for (i = 0; i < fld->len; i++) { 517 fvalue[i / 32] |= 1 << (i & 31); 518 } 519 soc_mem_field_set(unit, mem, mask, fld->field, fvalue); 520 } 521 } 522 523 sal_free(modstr); 524 return 0; 525 } 526 527 static int 528 modify_mem_fields(int unit, soc_mem_t mem, uint32 *entry, 529 uint32 *mask, char *mod, int incr) 530 { 531 int rv; 532 533 rv = _modify_flex_mem_fields(unit,mem,entry,mask,mod,incr); 534 if (rv == CMD_NFND) { 535 return _modify_mem_fields(unit,mem,entry,mask,mod,incr); 536 } else { 537 return rv; 538 } 539 } 540 541 /* 542 * mmudebug command 543 * No argument: print current state 544 * Argument is 1: enable 545 * Argument is 0: disable 546 */ 547 548 char mmudebug_usage[] = 549 "Parameters: [on | off]\n\t" 550 "Puts the MMU in debug mode (on) or normal mode (off).\n\t" 551 "With no parameter, displays the current mode.\n\t" 552 "MMU must be in debug mode to access CBP memories.\n"; 553 554 cmd_result_t 555 mem_mmudebug(int unit, args_t *a) 556 { 557 char *s = ARG_GET(a); 558 559 if (!sh_check_attached(ARG_CMD(a), unit)) { 560 return CMD_FAIL; 561 } 562 563 if (s) { 564 if (!sal_strcasecmp(s, "on")) { 565 cli_out("Entering debug mode ...\n"); 566 if (soc_mem_debug_set(unit, 1) < 0) { 567 return CMD_FAIL; 568 } 569 } else if (!sal_strcasecmp(s, "off")) { 570 cli_out("Leaving debug mode ...\n"); 571 if (soc_mem_debug_set(unit, 0) < 0) { 572 return CMD_FAIL; 573 } 574 } else 575 return CMD_USAGE; 576 } else { 577 int enable = 0; 578 soc_mem_debug_get(unit, &enable); 579 cli_out("MMU debug mode is %s\n", enable ? "on" : "off"); 580 } 581 582 return CMD_OK; 583 } 584 585 /* 586 * Initialize Cell Free Address pool. 587 */ 588 589 char cfapinit_usage[] = 590 "Parameters: none\n\t" 591 "Run diags on CFAP pool and initialize CFAP with good entries only\n"; 592 593 cmd_result_t 594 mem_cfapinit(int unit, args_t *a) 595 { 596 int r; 597 598 if (!sh_check_attached(ARG_CMD(a), unit)) { 599 return CMD_FAIL; 600 } 601 602 if ((r = soc_mem_cfap_init(unit)) < 0) { 603 cli_out("NOTICE: error initializing CFAP: %s\n", soc_errmsg(r)); 604 return CMD_FAIL; 605 } 606 607 return CMD_OK; 608 } 609 610 #ifdef BCM_HERCULES_SUPPORT 611 /* 612 * Initialize Cell Free Address pool. 613 */ 614 615 char llainit_usage[] = 616 "Parameters: [force]\n\t" 617 "Run diags on LLA and PP and initialize LLA with good entries only\n"; 618 619 cmd_result_t 620 mem_llainit(int unit, args_t *a) 621 { 622 char *argforce; 623 int force = FALSE; 624 625 if (!sh_check_attached(ARG_CMD(a), unit)) { 626 return CMD_FAIL; 627 } 628 629 if ((argforce = ARG_GET(a)) != NULL) { 630 if (!sal_strcasecmp(argforce, "force")) { 631 force = TRUE; 632 } else { 633 return CMD_USAGE; 634 } 635 } 636 637 if (force) { 638 if (SOC_CONTROL(unit)->lla_map != NULL) { 639 int i; 640 PBMP_PORT_ITER(unit, i) { 641 if (SOC_CONTROL(unit)->lla_map[i] != NULL) { 642 sal_free(SOC_CONTROL(unit)->lla_map[i]); 643 SOC_CONTROL(unit)->lla_map[i] = NULL; 644 } 645 } 646 } 647 } 648 649 return CMD_OK; 650 } 651 #endif 652 653 static int 654 parse_dwords(int count, uint32 *dw, args_t *a) 655 { 656 char *s; 657 int i; 658 659 for (i = 0; i < count; i++) { 660 if ((s = ARG_GET(a)) == NULL) { 661 cli_out("Not enough data values (have %d, need %d)\n", 662 i, count); 663 return -1; 664 } 665 666 dw[i] = parse_integer(s); 667 } 668 669 if (ARG_CNT(a) > 0) { 670 cli_out("Ignoring extra data on command line " 671 "(only %d words needed)\n", 672 count); 673 } 674 675 return 0; 676 } 677 678 cmd_result_t 679 cmd_esw_mem_write(int unit, args_t *a) 680 { 681 int i, index, start, count, copyno; 682 char *tab, *idx, *cnt, *s, *memname, *slam_buf = NULL; 683 soc_mem_t mem; 684 uint32 entry[SOC_MAX_MEM_WORDS]; 685 int entry_dw, view_len, entry_bytes; 686 char copyno_str[8]; 687 int r, update; 688 int rv = CMD_FAIL; 689 char *valstr = NULL, *view = NULL; 690 int no_cache = 0; 691 int use_slam = 0; 692 int acc_type = 0; 693 int specific_pipe = 0; 694 #ifdef BCM_KATANA2_SUPPORT 695 int port_index[15]= 696 {1,5,9,13,17,21,25,26,27,28,30,33,37,39,41}; 697 int matched = 0; 698 #endif /*BCM_KATANA2_SUPPORT */ 699 #if defined(BCM_TOMAHAWK_SUPPORT) 700 int enable_mem_mode_check = 1; 701 #endif /* BCM_TOMAHAWK_SUPPORT */ 702 int idx_phy = 0; 703 uint32 flags = SOC_MEM_NO_FLAGS; 704 705 if (!sh_check_attached(ARG_CMD(a), unit)) { 706 goto done; 707 } 708 709 tab = ARG_GET(a); 710 if (tab != NULL && sal_strcasecmp(tab, "idx_phy") == 0) { 711 idx_phy = 1; 712 tab = ARG_GET(a); 713 } 714 if (tab != NULL && sal_strcasecmp(tab, "nocache") == 0) { 715 no_cache = 1; 716 tab = ARG_GET(a); 717 } 718 if (tab != NULL && sal_strcasecmp(tab, "pipe_x") == 0) { 719 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X; 720 specific_pipe = 1; 721 tab = ARG_GET(a); 722 } 723 if (tab != NULL && sal_strcasecmp(tab, "pipe_y") == 0) { 724 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y; 725 specific_pipe = 1; 726 tab = ARG_GET(a); 727 } 728 if (tab != NULL && sal_strcasecmp(tab, "pipe0") == 0) { 729 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0; 730 specific_pipe = 1; 731 tab = ARG_GET(a); 732 } 733 if (tab != NULL && sal_strcasecmp(tab, "pipe1") == 0) { 734 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_1; 735 specific_pipe = 1; 736 tab = ARG_GET(a); 737 } 738 if (tab != NULL && sal_strcasecmp(tab, "pipe2") == 0) { 739 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_2; 740 specific_pipe = 1; 741 tab = ARG_GET(a); 742 } 743 if (tab != NULL && sal_strcasecmp(tab, "pipe3") == 0) { 744 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_3; 745 specific_pipe = 1; 746 tab = ARG_GET(a); 747 } 748 if (tab != NULL && sal_strcasecmp(tab, "pipe4") == 0) { 749 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_4; 750 specific_pipe = 1; 751 tab = ARG_GET(a); 752 } 753 if (tab != NULL && sal_strcasecmp(tab, "pipe5") == 0) { 754 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_5; 755 specific_pipe = 1; 756 tab = ARG_GET(a); 757 } 758 if (tab != NULL && sal_strcasecmp(tab, "pipe6") == 0) { 759 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_6; 760 specific_pipe = 1; 761 tab = ARG_GET(a); 762 } 763 if (tab != NULL && sal_strcasecmp(tab, "pipe7") == 0) { 764 acc_type = _SOC_MEM_ADDR_ACC_TYPE_PIPE_7; 765 specific_pipe = 1; 766 tab = ARG_GET(a); 767 } 768 #if defined(BCM_TOMAHAWK_SUPPORT) 769 if (tab != NULL && sal_strcasecmp(tab, "nocheck_mem_mode") == 0) { 770 enable_mem_mode_check = 0; 771 tab = ARG_GET(a); 772 } 773 #endif /* BCM_TOMAHAWK_SUPPORT */ 774 idx = ARG_GET(a); 775 cnt = ARG_GET(a); 776 s = ARG_GET(a); 777 778 /* you will need at least one value and all the args .. */ 779 if (!tab || !idx || !cnt || !s || !isint(cnt)) { 780 return CMD_USAGE; 781 } 782 783 /* Deal with VIEW:MEMORY if applicable */ 784 memname = sal_strstr(tab, ":"); 785 view_len = 0; 786 if (memname != NULL) { 787 memname++; 788 view_len = memname - tab; 789 } else { 790 memname = tab; 791 } 792 793 if (parse_memory_name(unit, &mem, memname, ©no, 0) < 0) { 794 cli_out("ERROR: unknown table \"%s\"\n",tab); 795 goto done; 796 } 797 798 if (!SOC_MEM_IS_VALID(unit, mem)) { 799 cli_out("Error: Memory %s not valid for chip %s.\n", 800 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 801 goto done; 802 } 803 804 #if defined(BCM_HAWKEYE_SUPPORT) 805 if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) { 806 cli_out("Error: Memory %s not valid for chip %s.\n", 807 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 808 goto done; 809 } 810 #endif /* BCM_HAWKEYE_SUPPORT */ 811 812 if (soc_mem_is_readonly(unit, mem)) { 813 cli_out("Error: Table %s is read-only\n", 814 SOC_MEM_UFNAME(unit, mem)); 815 goto done; 816 } 817 818 start = parse_memory_index(unit, mem, idx); 819 count = parse_integer(cnt); 820 821 if (copyno == COPYNO_ALL) { 822 copyno_str[0] = 0; 823 } else { 824 sal_sprintf(copyno_str, ".%d", copyno); 825 } 826 827 entry_dw = soc_mem_entry_words(unit, mem); 828 829 if ((valstr = sal_alloc(ARGS_BUFFER, "reg_set")) == NULL) { 830 cli_out("cmd_esw_mem_write : Out of memory\n"); 831 goto done; 832 } 833 834 /* 835 * If a list of fields were specified, generate the entry from them. 836 * Otherwise, generate it by reading raw dwords from command line. 837 */ 838 839 if (!isint(s)) { 840 /* List of fields */ 841 842 if (view_len == 0) { 843 collect_comma_args(a, valstr, s); 844 } else { 845 if ((view = sal_alloc(view_len + 1, "view_name")) == NULL) { 846 cli_out("cmd_esw_mem_write : Out of memory\n"); 847 goto done; 848 } 849 sal_memset(view, 0, view_len + 1); 850 sal_memcpy(view, tab, view_len); 851 if (collect_comma_args_with_view(a, valstr, s, view, unit, mem) < 0) { 852 cli_out("Out of memory: aborted\n"); 853 goto done; 854 } 855 } 856 857 memset(entry, 0, sizeof (entry)); 858 859 if (modify_mem_fields(unit, mem, entry, NULL, valstr, FALSE) < 0) { 860 cli_out("Syntax error: aborted\n"); 861 goto done; 862 } 863 864 update = TRUE; 865 } else { 866 /* List of numeric values */ 867 868 ARG_PREV(a); 869 870 if (parse_dwords(entry_dw, entry, a) < 0) { 871 goto done; 872 } 873 874 update = FALSE; 875 } 876 877 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 878 cli_out("WRITE[%s%s], DATA:", SOC_MEM_UFNAME(unit, mem), copyno_str); 879 for (i = 0; i < entry_dw; i++) { 880 cli_out(" 0x%x", entry[i]); 881 } 882 cli_out("\n"); 883 } 884 885 /* 886 * Created entry, now write it 887 */ 888 889 use_slam = soc_property_get(unit, spn_DIAG_SHELL_USE_SLAM, 0); 890 #if defined(BCM_TOMAHAWK_SUPPORT) 891 if (SOC_IS_TOMAHAWKX(unit)) { 892 if (enable_mem_mode_check && 893 soc_th_mem_is_dual_mode(unit, mem, NULL, NULL)) { 894 use_slam = 0; /* simplify */ 895 LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit, 896 "Write slam DISABLED for mem %s\n"), 897 SOC_MEM_NAME(unit, mem))); 898 } 899 } 900 #endif /* BCM_TOMAHAWK_SUPPORT */ 901 if (use_slam && count > 1) { 902 entry_bytes = WORDS2BYTES(soc_mem_entry_words(unit, mem)); 903 slam_buf = soc_cm_salloc(unit, count * entry_bytes, "slam_entry"); 904 if (slam_buf == NULL) { 905 cli_out("cmd_esw_mem_write : Out of memory\n"); 906 goto done; 907 } 908 for (i = 0; i < count; i++) { 909 sal_memcpy(slam_buf + i * entry_bytes, entry, entry_bytes); 910 } 911 r = soc_mem_write_range(unit, mem, copyno, start, start + count - 1, slam_buf); 912 soc_cm_sfree(unit, slam_buf); 913 if (r < 0) { 914 cli_out("Slam ERROR: table %s.%s: %s\n", 915 SOC_MEM_UFNAME(unit, mem), copyno_str, soc_errmsg(r)); 916 goto done; 917 } 918 for (index = start; index < start + count; index++) { 919 if (update) { 920 modify_mem_fields(unit, mem, entry, NULL, valstr, TRUE); 921 } 922 } 923 } else { 924 for (index = start; index < start + count; index++) { 925 #ifdef BCM_KATANA2_SUPPORT 926 if (SOC_IS_KATANA2(unit)) { 927 /* In case of SP memories, out of SP0, SP1, SP2 & SP3 928 only SP0 is valid. i.e only inidices 0,4,8. This check 929 is to avoid processing invalid indices. Issue is handled 930 for THDI memories alone. Has to be handled 931 for other SP memories in future */ 932 933 if ((mem == THDIEMA_THDI_PORT_SP_CONFIGm || 934 mem == THDIEXT_THDI_PORT_SP_CONFIGm || 935 mem == THDIQEN_THDI_PORT_SP_CONFIGm || 936 mem == THDIRQE_THDI_PORT_SP_CONFIGm || 937 mem == THDI_PORT_SP_CONFIGm) && (index % 4)) { 938 939 continue; 940 } 941 if(!SOC_IS_SABER2(unit)) { 942 matched = 0; 943 if ((mem == THDIEMA_THDI_PORT_PG_CONFIGm || 944 mem == THDIEXT_THDI_PORT_PG_CONFIGm || 945 mem == THDIQEN_THDI_PORT_PG_CONFIGm || 946 mem == THDIRQE_THDI_PORT_PG_CONFIGm || 947 mem == THDI_PORT_PG_CONFIGm )) { 948 for (i = 0; i < 15 ; i ++) { 949 if (port_index[i] == (index/8)) { 950 matched = 1; 951 break; 952 } 953 } 954 955 if (!matched && (index % 8)) { 956 continue; 957 } 958 } 959 960 } 961 } 962 963 #endif /*BCM_KATANA2_SUPPORT */ 964 965 #if defined(BCM_TOMAHAWK_SUPPORT) 966 if (SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TOMAHAWK3(unit)) { 967 if (enable_mem_mode_check) { 968 if (!soc_th_dual_tcam_index_valid(unit, mem, index)) { 969 LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit, 970 "Write IGNORED for mem %s, index %d\n"), 971 SOC_MEM_NAME(unit, mem), index)); 972 continue; 973 } 974 } 975 } 976 #endif /* BCM_TOMAHAWK_SUPPORT */ 977 978 if (idx_phy) { 979 flags |= SOC_MEM_DONT_MAP_INDEX; 980 } 981 if (no_cache) { 982 flags |= SOC_MEM_DONT_USE_CACHE; 983 } 984 if (specific_pipe) { 985 if ((r = soc_mem_pipe_select_write(unit, 986 flags, 987 mem, copyno, acc_type, index, 988 entry)) < 0) { 989 cli_out("Write ERROR: table %s(Y).%s[%d]: %s\n", 990 SOC_MEM_UFNAME(unit, mem), copyno_str, 991 index, soc_errmsg(r)); 992 goto done; 993 } 994 } else if ((r = soc_mem_write_extended(unit, 995 flags, 996 mem, 997 copyno, index, entry)) < 0) { 998 cli_out("Write ERROR: table %s.%s[%d]: %s\n", 999 SOC_MEM_UFNAME(unit, mem), copyno_str, 1000 index, soc_errmsg(r)); 1001 goto done; 1002 } 1003 1004 if (update) { 1005 modify_mem_fields(unit, mem, entry, NULL, valstr, TRUE); 1006 } 1007 } 1008 } 1009 rv = CMD_OK; 1010 1011 done: 1012 if (valstr != NULL) { 1013 sal_free(valstr); 1014 } 1015 if (view != NULL) { 1016 sal_free(view); 1017 } 1018 return rv; 1019 } 1020 1021 1022 /* 1023 * Modify the fields of a table entry 1024 */ 1025 cmd_result_t 1026 cmd_esw_mem_modify(int unit, args_t *a) 1027 { 1028 int index, start, count, copyno, i, view_len; 1029 char *tab, *idx, *cnt, *s, *memname; 1030 soc_mem_t mem; 1031 uint32 entry[SOC_MAX_MEM_WORDS], mask[SOC_MAX_MEM_WORDS]; 1032 uint32 changed[SOC_MAX_MEM_WORDS]; 1033 char *valstr = NULL, *view = NULL; 1034 int r, rv = CMD_FAIL; 1035 int blk; 1036 #ifdef BCM_TRIDENT2_SUPPORT 1037 int check_view = FALSE; 1038 soc_mem_t mview = INVALIDm; 1039 #endif /* BCM_TRIDENT2_SUPPORT */ 1040 #ifdef BCM_KATANA2_SUPPORT 1041 int port_index[15]= 1042 {1,5,9,13,17,21,25,26,27,28,30,33,37,39,41}; 1043 int matched = 0; 1044 #endif /*BCM_KATANA2_SUPPORT */ 1045 #if defined(BCM_TOMAHAWK_SUPPORT) 1046 int enable_mem_mode_check = 1; 1047 int check_lpm_view = FALSE; 1048 soc_mem_t lpm_view = INVALIDm; 1049 int pair_lpm = 0; 1050 #endif /* BCM_TOMAHAWK_SUPPORT */ 1051 uint32 flags = SOC_MEM_NO_FLAGS; 1052 1053 if (!sh_check_attached(ARG_CMD(a), unit)) { 1054 return CMD_FAIL; 1055 } 1056 1057 tab = ARG_GET(a); 1058 #if defined(BCM_TOMAHAWK_SUPPORT) 1059 if (tab != NULL && sal_strcasecmp(tab, "nocheck_mem_mode") == 0) { 1060 enable_mem_mode_check = 0; 1061 tab = ARG_GET(a); 1062 } 1063 #endif /* BCM_TOMAHAWK_SUPPORT */ 1064 if (tab != NULL && sal_strcasecmp(tab, "idx_phy") == 0) { 1065 flags = SOC_MEM_DONT_MAP_INDEX; 1066 tab = ARG_GET(a); 1067 } 1068 idx = ARG_GET(a); 1069 cnt = ARG_GET(a); 1070 s = ARG_GET(a); 1071 1072 /* you will need at least one dword and all the args .. */ 1073 if (!tab || !idx || !cnt || !s || !isint(cnt)) { 1074 return CMD_USAGE; 1075 } 1076 1077 if ((valstr = sal_alloc(ARGS_BUFFER, "mem_modify")) == NULL) { 1078 cli_out("cmd_esw_mem_modify : Out of memory\n"); 1079 goto done; 1080 } 1081 1082 memname = sal_strstr(tab, ":"); 1083 view_len = 0; 1084 if (memname != NULL) { 1085 memname++; 1086 view_len = memname - tab; 1087 } else { 1088 memname = tab; 1089 } 1090 1091 if (parse_memory_name(unit, &mem, memname, ©no, 0) < 0) { 1092 cli_out("ERROR: unknown table \"%s\"\n",tab); 1093 goto done; 1094 } 1095 1096 if (view_len == 0) { 1097 collect_comma_args(a, valstr, s); 1098 } else { 1099 if ((view = sal_alloc(view_len + 1, "view_name")) == NULL) { 1100 cli_out("cmd_esw_mem_modify : Out of memory\n"); 1101 goto done; 1102 } 1103 1104 sal_memcpy(view, tab, view_len); 1105 view[view_len] = 0; 1106 1107 if (collect_comma_args_with_view(a, valstr, s, view, unit, mem) < 0) { 1108 cli_out("Out of memory: aborted\n"); 1109 goto done; 1110 } 1111 } 1112 1113 if (!SOC_MEM_IS_VALID(unit, mem)) { 1114 cli_out("Error: Memory %s not valid for chip %s.\n", 1115 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 1116 goto done; 1117 } 1118 1119 #if defined(BCM_HAWKEYE_SUPPORT) 1120 if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) { 1121 cli_out("Error: Memory %s not valid for chip %s.\n", 1122 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 1123 goto done; 1124 } 1125 #endif /* BCM_HAWKEYE_SUPPORT */ 1126 1127 if (soc_mem_is_readonly(unit, mem)) { 1128 cli_out("ERROR: Table %s is read-only\n", SOC_MEM_UFNAME(unit, mem)); 1129 goto done; 1130 } 1131 1132 sal_memset(changed, 0, sizeof (changed)); 1133 1134 if (modify_mem_fields(unit, mem, changed, mask, valstr, FALSE) < 0) { 1135 cli_out("Syntax error: aborted\n"); 1136 goto done; 1137 } 1138 1139 start = parse_memory_index(unit, mem, idx); 1140 count = parse_integer(cnt); 1141 1142 #ifdef BCM_TRIDENT2_SUPPORT 1143 if (SOC_IS_TD2_TT2(unit) && 1144 (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 1145 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 1146 mem == L3_DEFIP_ALPM_IPV6_128m)) { 1147 check_view = TRUE; 1148 mview = mem; 1149 } 1150 #endif /* BCM_TRIDENT2_SUPPORT */ 1151 #ifdef BCM_TOMAHAWK_SUPPORT 1152 if (SOC_IS_TOMAHAWKX(unit) && (flags & SOC_MEM_DONT_MAP_INDEX)) { 1153 if (soc_feature(unit, soc_feature_l3_defip_map) && 1154 (mem == L3_DEFIPm || 1155 #ifdef BCM_TOMAHAWK3_SUPPORT 1156 mem == L3_DEFIP_LEVEL1m || 1157 #endif 1158 mem == L3_DEFIP_ONLYm || 1159 mem == L3_DEFIP_PAIR_128m || 1160 #ifdef BCM_TOMAHAWK3_SUPPORT 1161 mem == L3_DEFIP_PAIR_LEVEL1m || 1162 #endif 1163 mem == L3_DEFIP_PAIR_128_ONLYm)) { 1164 check_lpm_view = TRUE; 1165 lpm_view = mem; 1166 pair_lpm = (mem == L3_DEFIP_PAIR_128m || 1167 #ifdef BCM_TOMAHAWK3_SUPPORT 1168 mem == L3_DEFIP_PAIR_LEVEL1m || 1169 #endif 1170 mem == L3_DEFIP_PAIR_128_ONLYm) ? 1 : 0; 1171 } 1172 } 1173 #endif 1174 /* 1175 * Take lock to ensure atomic modification of memory. 1176 */ 1177 1178 soc_mem_lock(unit, mem); 1179 1180 rv = CMD_OK; 1181 1182 for (index = start; index < start + count; index++) { 1183 1184 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 1185 if (copyno != COPYNO_ALL && copyno != blk) { 1186 continue; 1187 } 1188 1189 #if defined(BCM_TOMAHAWK_SUPPORT) 1190 if (SOC_IS_TOMAHAWKX(unit)) { 1191 if (enable_mem_mode_check) { 1192 if (!soc_th_dual_tcam_index_valid(unit, mem, index)) { 1193 LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit, 1194 "Modify IGNORED for mem %s, index %d\n"), 1195 SOC_MEM_NAME(unit, mem), index)); 1196 continue; 1197 } 1198 } 1199 } 1200 #endif /* BCM_TOMAHAWK_SUPPORT */ 1201 1202 #ifdef BCM_TRIDENT2_SUPPORT 1203 if (check_view) { 1204 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 1205 mview = _soc_trident2_alpm_bkt_view_get(unit, index); 1206 } 1207 #if defined(ALPM_ENABLE) 1208 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 1209 else { 1210 mview = soc_alpm_cmn_bkt_view_get(unit, index); 1211 } 1212 #endif 1213 #endif 1214 if (!(mview == INVALIDm || mem == mview)) { 1215 continue; 1216 } 1217 } 1218 #endif /* BCM_TRIDENT2_SUPPORT */ 1219 #ifdef BCM_TOMAHAWK_SUPPORT 1220 if (check_lpm_view) { 1221 #ifdef BCM_TOMAHAWK3_SUPPORT 1222 if (SOC_IS_TOMAHAWK3(unit)) { 1223 lpm_view = _soc_th3_lpm_view_get(unit, index, pair_lpm); 1224 } else 1225 #endif 1226 if (SOC_IS_TOMAHAWKX(unit)) { 1227 lpm_view = _soc_th_lpm_view_get(unit, index, pair_lpm); 1228 } 1229 if (mem != lpm_view) { 1230 continue; 1231 } 1232 } 1233 #endif 1234 /* 1235 * Retrieve the current entry, set masked fields to changed 1236 * values, and write back. 1237 */ 1238 1239 r = soc_mem_read_physical_index(unit, flags, mem, blk, index, entry); 1240 1241 if (r < 0) { 1242 cli_out("ERROR: read from %s table copy %d failed: %s\n", 1243 SOC_MEM_UFNAME(unit, mem), blk, soc_errmsg(r)); 1244 rv = CMD_FAIL; 1245 break; 1246 } 1247 1248 for (i = 0; i < SOC_MAX_MEM_WORDS; i++) { 1249 entry[i] = (entry[i] & ~mask[i]) | changed[i]; 1250 } 1251 1252 #ifdef BCM_KATANA2_SUPPORT 1253 1254 if (SOC_IS_KATANA2(unit)) { 1255 /* In case of SP memories, out of SP0, SP1, SP2 & SP3 1256 only SP0 is valid i.e. only indices 0,4,8.This check 1257 is avoid processing invalid indices. Issue is handled 1258 for THDI memories alone. Has to be handled 1259 for other SP memories in future */ 1260 1261 if ((mem == THDIEMA_THDI_PORT_SP_CONFIGm || 1262 mem == THDIEXT_THDI_PORT_SP_CONFIGm || 1263 mem == THDIQEN_THDI_PORT_SP_CONFIGm || 1264 mem == THDIRQE_THDI_PORT_SP_CONFIGm || 1265 mem == THDI_PORT_SP_CONFIGm) && (index % 4)) { 1266 continue; 1267 } 1268 if (!SOC_IS_SABER2(unit)) { 1269 matched = 0; 1270 if ((mem == THDIEMA_THDI_PORT_PG_CONFIGm || 1271 mem == THDIEXT_THDI_PORT_PG_CONFIGm || 1272 mem == THDIQEN_THDI_PORT_PG_CONFIGm || 1273 mem == THDIRQE_THDI_PORT_PG_CONFIGm || 1274 mem == THDI_PORT_PG_CONFIGm )) { 1275 for (i = 0; i < 15 ; i ++) { 1276 if (port_index[i] == (index/8)) { 1277 matched = 1; 1278 break; 1279 } 1280 } 1281 1282 if (!matched && (index % 8)) { 1283 continue; 1284 } 1285 } 1286 } 1287 } 1288 1289 #endif /*BCM_KATANA2_SUPPORT */ 1290 1291 r = soc_mem_write_extended(unit, flags, mem, blk, index, entry); 1292 1293 if (r < 0) { 1294 cli_out("ERROR: write to %s table copy %d failed: %s\n", 1295 SOC_MEM_UFNAME(unit, mem), blk, soc_errmsg(r)); 1296 rv = CMD_FAIL; 1297 break; 1298 } 1299 } 1300 1301 if (rv != CMD_OK) { 1302 break; 1303 } 1304 modify_mem_fields(unit, mem, changed, NULL, valstr, TRUE); 1305 } 1306 1307 soc_mem_unlock(unit, mem); 1308 1309 done: 1310 if (view != NULL) { 1311 sal_free(view); 1312 } 1313 sal_free(valstr); 1314 return rv; 1315 } 1316 1317 /* 1318 * Auxiliary routine to perform either insert or delete 1319 */ 1320 1321 #define TBL_OP_INSERT 0 1322 #define TBL_OP_DELETE 1 1323 #define TBL_OP_LOOKUP 2 1324 1325 static cmd_result_t 1326 do_ins_del_lkup(int unit, args_t *a, int tbl_op) 1327 { 1328 soc_control_t *soc = SOC_CONTROL(unit); 1329 uint32 entry[SOC_MAX_MEM_WORDS]; 1330 uint32 result[SOC_MAX_MEM_WORDS]; 1331 int entry_dw = 0, index; 1332 char *ufname, *s; 1333 int rv = CMD_FAIL; 1334 char valstr[1024]; 1335 soc_mem_t mem; 1336 int copyno, update, view_len = 0; 1337 int swarl = 0; /* Indicates operating on 1338 software ARL/L2 table */ 1339 char *tab, *memname, *view = NULL; 1340 int count = 1; 1341 soc_mem_t arl_mem = INVALIDm; 1342 shr_avl_compare_fn arl_cmp = NULL; 1343 int quiet = 0; 1344 int32 banks = 0; 1345 int i=0; 1346 int8 banknum = SOC_MEM_HASH_BANK_ALL; 1347 1348 if (!sh_check_attached(ARG_CMD(a), unit)) { 1349 return CMD_FAIL; 1350 } 1351 1352 for (;;) { 1353 if ((tab = ARG_GET(a)) == NULL) { 1354 return CMD_USAGE; 1355 } 1356 1357 if (isint(tab)) { 1358 count = parse_integer(tab); 1359 continue; 1360 } 1361 1362 if (sal_strcasecmp(tab, "quiet") == 0) { 1363 quiet = 1; 1364 continue; 1365 } 1366 1367 if (soc_feature(unit, soc_feature_ism_memory) || 1368 soc_feature(unit, soc_feature_shared_hash_mem)) { 1369 char *bnum; 1370 int8 num = -1; 1371 bnum = sal_strstr(tab, "bank"); 1372 if (bnum != NULL) { 1373 num = sal_atoi(bnum+4); 1374 if (num >= 0 && num < 20) { 1375 banknum = num; 1376 } 1377 continue; 1378 } 1379 1380 } else { 1381 if (sal_strcasecmp(tab, "bank0") == 0) { 1382 banks = SOC_MEM_HASH_BANK0_ONLY; 1383 continue; 1384 } 1385 1386 if (sal_strcasecmp(tab, "bank1") == 0) { 1387 banks = SOC_MEM_HASH_BANK1_ONLY; 1388 continue; 1389 } 1390 } 1391 1392 break; 1393 } 1394 1395 #ifdef BCM_XGS_SWITCH_SUPPORT 1396 if (soc_feature(unit, soc_feature_arl_hashed)) { 1397 arl_mem = L2Xm; 1398 arl_cmp = soc_l2x_entry_compare_key; 1399 } 1400 #endif 1401 1402 if (!sal_strcasecmp(tab, "sa") || !sal_strcasecmp(tab, "sarl")) { 1403 if (soc->arlShadow == NULL) { 1404 cli_out("ERROR: No software ARL table\n"); 1405 goto done; 1406 } 1407 mem = arl_mem; 1408 if (mem != INVALIDm) { 1409 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 1410 } 1411 swarl = 1; 1412 } else { 1413 memname = sal_strstr(tab, ":"); 1414 if (memname != NULL) { 1415 memname++; 1416 view_len = memname - tab; 1417 } else { 1418 memname = tab; 1419 } 1420 if (parse_memory_name(unit, &mem, memname, ©no, 0) < 0) { 1421 cli_out("ERROR: unknown table \"%s\"\n", tab); 1422 goto done; 1423 } 1424 } 1425 1426 if (!SOC_MEM_IS_VALID(unit, mem)) { 1427 cli_out("Error: Memory %s not valid for chip %s.\n", 1428 (mem != INVALIDm) ? SOC_MEM_UFNAME(unit, mem) : "INVALID", 1429 SOC_UNIT_NAME(unit)); 1430 goto done; 1431 } 1432 1433 if (!soc_mem_is_sorted(unit, mem) && 1434 !soc_mem_is_hashed(unit, mem) && 1435 !soc_mem_is_cam(unit, mem) && 1436 !soc_mem_is_cmd(unit, mem)) { 1437 cli_out("ERROR: %s table is not sorted, hashed, CAM, or command\n", 1438 SOC_MEM_UFNAME(unit, mem)); 1439 goto done; 1440 } 1441 1442 if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) || 1443 (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) || 1444 (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) || 1445 (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) || 1446 (mem == L3_ENTRY_IPV6_MULTICASTm)))) { 1447 if (banknum != SOC_MEM_HASH_BANK_ALL) { 1448 banks |= ((int32)1 << banknum); 1449 } else if (banks == 0) { 1450 banks = SOC_MEM_HASH_BANK_ALL; 1451 } 1452 } 1453 /* All hash tables have multiple banks from TRX onwards only */ 1454 #ifndef BCM_TRX_SUPPORT 1455 if (soc_feature(unit, soc_feature_dual_hash) && !SOC_IS_TRX(unit)) { 1456 if (banks != 0) { 1457 switch (mem) { 1458 case L2Xm: 1459 case MPLS_ENTRYm: 1460 case VLAN_XLATEm: 1461 case EGR_VLAN_XLATEm: 1462 case L3_ENTRY_IPV4_UNICASTm: 1463 case L3_ENTRY_IPV4_MULTICASTm: 1464 case L3_ENTRY_IPV6_UNICASTm: 1465 case L3_ENTRY_IPV6_MULTICASTm: 1466 break; 1467 default: 1468 cli_out("ERROR: %s table does not have multiple banks\n", 1469 SOC_MEM_UFNAME(unit, mem)); 1470 goto done; 1471 } 1472 } 1473 } 1474 #endif 1475 1476 entry_dw = soc_mem_entry_words(unit, mem); 1477 ufname = (swarl ? "SARL" : SOC_MEM_UFNAME(unit, mem)); 1478 1479 if (tbl_op == TBL_OP_LOOKUP && copyno == COPYNO_ALL) { 1480 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 1481 } 1482 1483 /* 1484 * If a list of fields were specified, generate the entry from them. 1485 * Otherwise, generate it by reading raw dwords from command line. 1486 */ 1487 1488 if ((s = ARG_GET(a)) == 0) { 1489 cli_out("ERROR: missing data for entry to %s\n", 1490 tbl_op == TBL_OP_INSERT ? "insert" : 1491 tbl_op == TBL_OP_DELETE ? "delete" : "lookup"); 1492 goto done; 1493 } 1494 1495 if (!isint(s)) { 1496 /* List of fields */ 1497 sal_memset(valstr, 0, 1024); 1498 if (view_len == 0) { 1499 collect_comma_args(a, valstr, s); 1500 } else { 1501 if ((view = sal_alloc(view_len + 1, "view_name")) == NULL) { 1502 cli_out("cmd_esw_mem_modify : Out of memory\n"); 1503 goto done; 1504 } 1505 sal_memset(view, 0, view_len + 1); 1506 sal_memcpy(view, tab, view_len); 1507 if (collect_comma_args_with_view(a, valstr, s, view, unit, mem) < 0) { 1508 cli_out("Out of memory: aborted\n"); 1509 goto done; 1510 } 1511 } 1512 1513 memset(entry, 0, sizeof (entry)); 1514 1515 if (modify_mem_fields(unit, mem, entry, NULL, valstr, FALSE) < 0) { 1516 cli_out("Syntax error in field specification\n"); 1517 goto done; 1518 } 1519 1520 update = TRUE; 1521 } else { 1522 /* List of numeric values */ 1523 1524 ARG_PREV(a); 1525 1526 if (parse_dwords(entry_dw, entry, a) < 0) { 1527 goto done; 1528 } 1529 1530 update = FALSE; 1531 } 1532 1533 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 1534 cli_out("%s[%s], DATA:", 1535 tbl_op == TBL_OP_INSERT ? "INSERT" : 1536 tbl_op == TBL_OP_DELETE ? "DELETE" : "LOOKUP", ufname); 1537 for (i = 0; i < entry_dw; i++) { 1538 cli_out(" 0x%x", entry[i]); 1539 } 1540 cli_out("\n"); 1541 } 1542 1543 /* 1544 * Have entry data, now insert, delete, or lookup. 1545 * For delete and lookup, all fields except the key are ignored. 1546 * Software ARL/L2 table requires special processing. 1547 */ 1548 1549 while (count--) { 1550 switch (tbl_op) { 1551 case TBL_OP_INSERT: 1552 if (swarl) { 1553 if (soc->arlShadow != NULL) { 1554 sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER); 1555 i = shr_avl_insert(soc->arlShadow, 1556 arl_cmp, 1557 (shr_avl_datum_t *) entry); 1558 sal_mutex_give(soc->arlShadowMutex); 1559 } else { 1560 i = SOC_E_NONE; 1561 } 1562 #ifdef BCM_TRIUMPH_SUPPORT 1563 } else if (mem == EXT_L2_ENTRYm) { 1564 i = soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY, 0, 1565 entry, NULL, 0); 1566 #endif /* BCM_TRIUMPH_SUPPORT */ 1567 #ifdef BCM_ISM_SUPPORT 1568 } else if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) { 1569 if (banks == SOC_MEM_HASH_BANK_ALL) { 1570 /* coverity[stack_use_callee] */ 1571 /* coverity[stack_use_overflow] */ 1572 i = soc_mem_insert(unit, mem, copyno, entry); 1573 } else { 1574 i = soc_mem_bank_insert(unit, mem, banks, 1575 copyno, (void *)entry, NULL); 1576 } 1577 #endif 1578 #ifdef BCM_FIREBOLT2_SUPPORT 1579 } else if (banks != 0) { 1580 switch (mem) { 1581 case L2Xm: 1582 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1583 i = soc_mem_bank_insert(unit, mem, banks, 1584 copyno, (void *)entry, NULL); 1585 } else { 1586 i = soc_fb_l2x_bank_insert(unit, banks, 1587 (void *)entry); 1588 } 1589 break; 1590 #if defined(INCLUDE_L3) 1591 case L3_ENTRY_IPV4_UNICASTm: 1592 case L3_ENTRY_IPV4_MULTICASTm: 1593 case L3_ENTRY_IPV6_UNICASTm: 1594 case L3_ENTRY_IPV6_MULTICASTm: 1595 if (soc_feature(unit, soc_feature_shared_hash_mem)) { 1596 i = soc_mem_bank_insert(unit, mem, banks, 1597 copyno, (void *)entry, NULL); 1598 } else { 1599 i = soc_fb_l3x_bank_insert(unit, banks, 1600 (void *)entry); 1601 } 1602 break; 1603 #endif 1604 #if defined(BCM_TRIUMPH_SUPPORT) 1605 case MPLS_ENTRYm: 1606 #endif 1607 case VLAN_XLATEm: 1608 case VLAN_MACm: 1609 case AXP_WRX_WCDm: 1610 case AXP_WRX_SVP_ASSIGNMENTm: 1611 #if defined(BCM_TRIUMPH3_SUPPORT) 1612 case FT_SESSIONm: 1613 case FT_SESSION_IPV6m: 1614 #endif 1615 i = soc_mem_bank_insert(unit, mem, banks, 1616 copyno, (void *)entry, NULL); 1617 break; 1618 default: 1619 i = SOC_E_INTERNAL; 1620 goto done; 1621 } 1622 #endif /* BCM_FIREBOLT2_SUPPORT */ 1623 } else { 1624 i = soc_mem_insert(unit, mem, copyno, entry); 1625 } 1626 1627 if (i == SOC_E_EXISTS) { 1628 i = SOC_E_NONE; 1629 } 1630 1631 if (quiet && i == SOC_E_FULL) { 1632 i = SOC_E_NONE; 1633 } 1634 1635 if (i < 0) { 1636 cli_out("Insert ERROR: %s table insert failed: %s\n", 1637 ufname, soc_errmsg(i)); 1638 goto done; 1639 } 1640 1641 break; 1642 1643 case TBL_OP_DELETE: 1644 if (swarl) { 1645 if (soc->arlShadow != NULL) { 1646 sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER); 1647 i = shr_avl_delete(soc->arlShadow, 1648 arl_cmp, 1649 (shr_avl_datum_t *) entry); 1650 sal_mutex_give(soc->arlShadowMutex); 1651 } else { 1652 i = SOC_E_NONE; 1653 } 1654 #ifdef BCM_TRX_SUPPORT 1655 } else if (soc_feature(unit, soc_feature_generic_table_ops)) { 1656 i = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, 1657 banks, entry, NULL, 0); 1658 #endif /* BCM_TRX_SUPPORT */ 1659 #ifdef BCM_FIREBOLT2_SUPPORT 1660 } else if (banks != 0) { 1661 switch (mem) { 1662 case L2Xm: 1663 i = soc_fb_l2x_bank_delete(unit, banks, 1664 (void *)entry); 1665 break; 1666 #if defined(INCLUDE_L3) 1667 case L3_ENTRY_IPV4_UNICASTm: 1668 case L3_ENTRY_IPV4_MULTICASTm: 1669 case L3_ENTRY_IPV6_UNICASTm: 1670 case L3_ENTRY_IPV6_MULTICASTm: 1671 i = soc_fb_l3x_bank_delete(unit, banks, 1672 (void *)entry); 1673 break; 1674 #endif 1675 default: 1676 i = SOC_E_INTERNAL; 1677 goto done; 1678 } 1679 #endif 1680 } else { 1681 i = soc_mem_delete(unit, mem, copyno, entry); 1682 } 1683 1684 if (quiet && i == SOC_E_NOT_FOUND) { 1685 i = SOC_E_NONE; 1686 } 1687 1688 if (i < 0) { 1689 cli_out("Delete ERROR: %s table delete failed: %s\n", 1690 ufname, soc_errmsg(i)); 1691 goto done; 1692 } 1693 1694 break; 1695 1696 case TBL_OP_LOOKUP: 1697 if (swarl) { 1698 if (soc->arlShadow != NULL) { 1699 sal_mutex_take(soc->arlShadowMutex, sal_mutex_FOREVER); 1700 i = shr_avl_lookup(soc->arlShadow, 1701 arl_cmp, 1702 (shr_avl_datum_t *) entry); 1703 sal_mutex_give(soc->arlShadowMutex); 1704 if (i) { 1705 i = SOC_E_NONE; 1706 index = -1; 1707 sal_memcpy(result, entry, 1708 soc_mem_entry_words(unit, mem) * 4); 1709 } else { 1710 i = SOC_E_NOT_FOUND; 1711 } 1712 } else { 1713 i = SOC_E_NONE; 1714 goto done; 1715 } 1716 #ifdef BCM_TRX_SUPPORT 1717 } else if (soc_feature(unit, soc_feature_generic_table_ops)) { 1718 i = soc_mem_generic_lookup(unit, mem, MEM_BLOCK_ANY, 1719 banks, entry, result, &index); 1720 #endif /* BCM_TRX_SUPPORT */ 1721 #ifdef BCM_FIREBOLT2_SUPPORT 1722 } else if (banks != 0) { 1723 switch (mem) { 1724 case L2Xm: 1725 i = soc_fb_l2x_bank_lookup(unit, banks, 1726 (void *)entry, 1727 (void *)result, 1728 &index); 1729 break; 1730 #if defined(INCLUDE_L3) 1731 case L3_ENTRY_IPV4_UNICASTm: 1732 case L3_ENTRY_IPV4_MULTICASTm: 1733 case L3_ENTRY_IPV6_UNICASTm: 1734 case L3_ENTRY_IPV6_MULTICASTm: 1735 i = soc_fb_l3x_bank_lookup(unit, banks, 1736 (void *)entry, 1737 (void *)result, 1738 &index); 1739 break; 1740 #endif 1741 default: 1742 i = SOC_E_INTERNAL; 1743 goto done; 1744 } 1745 #endif /* BCM_FIREBOLT2_SUPPORT */ 1746 } else { 1747 i = soc_mem_search(unit, mem, copyno, 1748 &index, entry, result, 0); 1749 } 1750 1751 if (i < 0) { /* Error not fatal for lookup */ 1752 if (i == SOC_E_NOT_FOUND) { 1753 cli_out("Lookup: No matching entry found\n"); 1754 } else { 1755 cli_out("Lookup ERROR: read error during search: %s\n", 1756 soc_errmsg(i)); 1757 } 1758 } else { /* Entry found */ 1759 if (index < 0) { 1760 cli_out("Found in %s.%s: ", 1761 ufname, SOC_BLOCK_NAME(unit, copyno)); 1762 } else { 1763 cli_out("Found %s.%s[%d]: ", 1764 ufname, SOC_BLOCK_NAME(unit, copyno), index); 1765 } 1766 soc_mem_entry_dump(unit, mem, result, BSL_LSS_CLI); 1767 cli_out("\n"); 1768 } 1769 1770 break; 1771 1772 default: 1773 assert(0); 1774 break; 1775 } 1776 1777 if (update) { 1778 modify_mem_fields(unit, mem, entry, NULL, valstr, TRUE); 1779 } 1780 } 1781 1782 rv = CMD_OK; 1783 1784 done: 1785 if (view != NULL) { 1786 sal_free(view); 1787 } 1788 return rv; 1789 } 1790 1791 /* 1792 * Insert an entry by key into a sorted table 1793 */ 1794 1795 char insert_usage[] = 1796 "\nParameters 1: [quiet] [<COUNT>] [bank#] <TABLE> <DW0> .. <DWN>\n" 1797 "Parameters 2: [quiet] [<COUNT>] <TABLE> <FIELD>=<VALUE> ...\n\t" 1798 "Number of <DW> must be appropriate to table entry size.\n\t" 1799 "Entry is inserted in ascending sorted order by key field.\n\t" 1800 "The quiet option indicates not to complain on table/bucket full.\n\t" 1801 "Some tables allow restricting the insert to a single bank.\n"; 1802 1803 cmd_result_t 1804 mem_insert(int unit, args_t *a) 1805 { 1806 return do_ins_del_lkup(unit, a, TBL_OP_INSERT); 1807 } 1808 1809 1810 /* 1811 * Delete entries by key from a sorted table 1812 */ 1813 1814 char delete_usage[] = 1815 "\nParameters 1: [quiet] [<COUNT>] [bank#] <TABLE> <DW0> .. <DWN>\n" 1816 "Parameters 2: [quiet] [<COUNT>] <TABLE> <FIELD>=<VALUE> ...\n\t" 1817 "Number of <DW> must be appropriate to table entry size.\n\t" 1818 "The entry is deleted by key.\n\t" 1819 "All fields other than the key field(s) are ignored.\n\t" 1820 "The quiet option indicates not to complain on entry not found.\n\t" 1821 "Some tables allow restricting the delete to a single bank.\n"; 1822 1823 cmd_result_t 1824 mem_delete(int unit, args_t *a) 1825 { 1826 return do_ins_del_lkup(unit, a, TBL_OP_DELETE); 1827 } 1828 1829 /* 1830 * Lookup entry an key in a sorted table 1831 */ 1832 1833 char lookup_usage[] = 1834 "\nParameters 1: [<COUNT>] [bank#] <TABLE> <DW0> .. <DWN>\n" 1835 "Parameters 2: [<COUNT>] <TABLE> <FIELD>=<VALUE> ...\n\t" 1836 "Number of <DW> must be appropriate to table entry size.\n\t" 1837 "The entry is looked up by key.\n\t" 1838 "All fields other than the key field(s) are ignored.\n\t" 1839 "Some tables allow restricting the lookup to a single bank.\n"; 1840 1841 cmd_result_t 1842 mem_lookup(int unit, args_t *a) 1843 { 1844 return do_ins_del_lkup(unit, a, TBL_OP_LOOKUP); 1845 } 1846 1847 /* 1848 * Remove (delete) entries by index from a sorted table 1849 */ 1850 1851 char remove_usage[] = 1852 "Parameters: <TABLE> <INDEX> [COUNT]\n\t" 1853 "Deletes an entry from a table by index.\n\t" 1854 "(For the ARL, reads the table entry and deletes by key).\n"; 1855 1856 cmd_result_t 1857 mem_remove(int unit, args_t *a) 1858 { 1859 char *tab, *ind, *cnt, *ufname; 1860 soc_mem_t mem; 1861 int copyno; 1862 int r, rv = CMD_FAIL; 1863 int index, count; 1864 1865 if (!sh_check_attached(ARG_CMD(a), unit)) { 1866 goto done; 1867 } 1868 1869 tab = ARG_GET(a); 1870 ind = ARG_GET(a); 1871 cnt = ARG_GET(a); 1872 1873 if (!tab || !ind) { 1874 return CMD_USAGE; 1875 } 1876 1877 if (parse_memory_name(unit, &mem, tab, ©no, 0) < 0) { 1878 cli_out("ERROR: unknown table \"%s\"\n", tab); 1879 goto done; 1880 } 1881 1882 if (!SOC_MEM_IS_VALID(unit, mem)) { 1883 cli_out("Error: Memory %s not valid for chip %s.\n", 1884 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 1885 goto done; 1886 } 1887 1888 ufname = SOC_MEM_UFNAME(unit, mem); 1889 1890 if (!soc_mem_is_sorted(unit, mem) && 1891 !soc_mem_is_hashed(unit, mem) && 1892 !soc_mem_is_cam(unit, mem)) { 1893 cli_out("ERROR: %s table is not sorted, hashed, or CAM\n", 1894 ufname); 1895 goto done; 1896 } 1897 1898 count = cnt ? parse_integer(cnt) : 1; 1899 1900 index = parse_memory_index(unit, mem, ind); 1901 1902 while (count-- > 0) 1903 if ((r = soc_mem_delete_index(unit, mem, copyno, index)) < 0) { 1904 cli_out("ERROR: delete %s table index 0x%x failed: %s\n", 1905 ufname, index, soc_errmsg(r)); 1906 goto done; 1907 } 1908 1909 rv = CMD_OK; 1910 1911 done: 1912 return rv; 1913 } 1914 1915 /* 1916 * Pop an entry from a FIFO 1917 */ 1918 1919 char pop_usage[] = 1920 "\nParameters: [quiet] [<COUNT>] <TABLE>\n" 1921 "The quiet option indicates not to complain on FIFO empty.\n"; 1922 1923 cmd_result_t 1924 mem_pop(int unit, args_t *a) 1925 { 1926 uint32 result[SOC_MAX_MEM_WORDS]; 1927 char *ufname; 1928 int rv = CMD_FAIL; 1929 soc_mem_t mem; 1930 int copyno; 1931 char *tab; 1932 int count = 1; 1933 int quiet = 0; 1934 int i; 1935 1936 if (!sh_check_attached(ARG_CMD(a), unit)) { 1937 return CMD_FAIL; 1938 } 1939 1940 if (!soc_feature(unit, soc_feature_mem_push_pop)) { 1941 /* feature not supported */ 1942 return CMD_FAIL; 1943 } 1944 1945 for (;;) { 1946 if ((tab = ARG_GET(a)) == NULL) { 1947 return CMD_USAGE; 1948 } 1949 1950 if (isint(tab)) { 1951 count = parse_integer(tab); 1952 continue; 1953 } 1954 1955 if (sal_strcasecmp(tab, "quiet") == 0) { 1956 quiet = 1; 1957 continue; 1958 } 1959 break; 1960 } 1961 1962 if (parse_memory_name(unit, &mem, tab, ©no, 0) < 0) { 1963 cli_out("ERROR: unknown table \"%s\"\n", tab); 1964 goto done; 1965 } 1966 1967 if (!SOC_MEM_IS_VALID(unit, mem)) { 1968 cli_out("Error: Memory %s not valid for chip %s.\n", 1969 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 1970 goto done; 1971 } 1972 1973 switch (mem) { 1974 #if defined (BCM_TRIUMPH_SUPPORT) 1975 case ING_IPFIX_EXPORT_FIFOm: 1976 case EGR_IPFIX_EXPORT_FIFOm: 1977 case EXT_L2_MOD_FIFOm: 1978 #endif /* BCM_TRIUMPH_SUPPORT */ 1979 case L2_MOD_FIFOm: 1980 #ifdef BCM_TRIUMPH3_SUPPORT 1981 case ING_SER_FIFOm: 1982 case ING_SER_FIFO_Xm: 1983 case ING_SER_FIFO_Ym: 1984 case EGR_SER_FIFOm: 1985 case EGR_SER_FIFO_Xm: 1986 case EGR_SER_FIFO_Ym: 1987 case ISM_SER_FIFOm: 1988 #endif /* BCM_TRIUMPH3_SUPPORT */ 1989 #ifdef BCM_TOMAHAWK_SUPPORT 1990 case ING_SER_FIFO_PIPE0m: 1991 case ING_SER_FIFO_PIPE1m: 1992 case ING_SER_FIFO_PIPE2m: 1993 case ING_SER_FIFO_PIPE3m: 1994 case EGR_SER_FIFO_PIPE0m: 1995 case EGR_SER_FIFO_PIPE1m: 1996 case EGR_SER_FIFO_PIPE2m: 1997 case EGR_SER_FIFO_PIPE3m: 1998 case L2_MGMT_SER_FIFOm: 1999 case MMU_GCFG_MEM_FAIL_ADDR_64m: 2000 case MMU_XCFG_MEM_FAIL_ADDR_64m: 2001 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE0m: 2002 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE1m: 2003 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE2m: 2004 case MMU_XCFG_MEM_FAIL_ADDR_64_XPE3m: 2005 case MMU_SCFG_MEM_FAIL_ADDR_64m: 2006 case MMU_SCFG_MEM_FAIL_ADDR_64_SC0m: 2007 case MMU_SCFG_MEM_FAIL_ADDR_64_SC1m: 2008 case CENTRAL_CTR_EVICTION_FIFOm: 2009 #endif /* BCM_TOMAHAWK_SUPPORT */ 2010 #ifdef BCM_TOMAHAWK2_SUPPORT 2011 case MMU_SEDCFG_MEM_FAIL_ADDR_64m: 2012 case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC0m: 2013 case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC1m: 2014 #endif /* BCM_TOMAHAWK2_SUPPORT */ 2015 #ifdef BCM_56980_A0 2016 case ING_SER_FIFO_PIPE4m: 2017 case ING_SER_FIFO_PIPE5m: 2018 case ING_SER_FIFO_PIPE6m: 2019 case ING_SER_FIFO_PIPE7m: 2020 case EGR_SER_FIFO_PIPE4m: 2021 case EGR_SER_FIFO_PIPE5m: 2022 case EGR_SER_FIFO_PIPE6m: 2023 case EGR_SER_FIFO_PIPE7m: 2024 case EDB_SER_FIFOm: 2025 case EDB_SER_FIFO_PIPE0m: 2026 case EDB_SER_FIFO_PIPE1m: 2027 case EDB_SER_FIFO_PIPE2m: 2028 case EDB_SER_FIFO_PIPE3m: 2029 case EDB_SER_FIFO_PIPE4m: 2030 case EDB_SER_FIFO_PIPE5m: 2031 case EDB_SER_FIFO_PIPE6m: 2032 case EDB_SER_FIFO_PIPE7m: 2033 case EGR_SER_FIFO_2m: 2034 case EGR_SER_FIFO_2_PIPE0m: 2035 case EGR_SER_FIFO_2_PIPE1m: 2036 case EGR_SER_FIFO_2_PIPE2m: 2037 case EGR_SER_FIFO_2_PIPE3m: 2038 case EGR_SER_FIFO_2_PIPE4m: 2039 case EGR_SER_FIFO_2_PIPE5m: 2040 case EGR_SER_FIFO_2_PIPE6m: 2041 case EGR_SER_FIFO_2_PIPE7m: 2042 case MMU_GLBCFG_MEM_FAIL_ADDR_64m: 2043 case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM0m: 2044 case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM1m: 2045 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE0m: 2046 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE1m: 2047 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE2m: 2048 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE3m: 2049 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE4m: 2050 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE5m: 2051 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE6m: 2052 case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE7m: 2053 case DLB_ECMP_SER_FIFOm: 2054 #endif 2055 break; 2056 default: 2057 cli_out("ERROR: %s table does not support FIFO push/pop\n", 2058 SOC_MEM_UFNAME(unit, mem)); 2059 goto done; 2060 } 2061 2062 ufname = SOC_MEM_UFNAME(unit, mem); 2063 2064 if (copyno == COPYNO_ALL) { 2065 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 2066 } 2067 2068 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 2069 cli_out("POP[%s]", ufname); 2070 cli_out("\n"); 2071 } 2072 2073 while (count--) { 2074 i = soc_mem_pop(unit, mem, copyno, result); 2075 2076 if (i < 0) { /* Error not fatal for lookup */ 2077 if (i != SOC_E_NOT_FOUND) { 2078 cli_out("Pop ERROR: read error during pop: %s\n", 2079 soc_errmsg(i)); 2080 } else if (!quiet) { 2081 cli_out("Pop: Fifo empty\n"); 2082 } 2083 } else { /* Entry popped */ 2084 cli_out("Popped in %s.%s: ", 2085 ufname, SOC_BLOCK_NAME(unit, copyno)); 2086 soc_mem_entry_dump(unit, mem, result, BSL_LSS_CLI); 2087 cli_out("\n"); 2088 } 2089 } 2090 2091 rv = CMD_OK; 2092 2093 done: 2094 return rv; 2095 } 2096 2097 /* 2098 * Push an entry onto a FIFO 2099 */ 2100 2101 char push_usage[] = 2102 "\nParameters: [quiet] [<COUNT>] <TABLE>\n" 2103 "The quiet option indicates not to complain on FIFO full.\n"; 2104 2105 cmd_result_t 2106 mem_push(int unit, args_t *a) 2107 { 2108 uint32 entry[SOC_MAX_MEM_WORDS]; 2109 int entry_dw; 2110 char *ufname, *s; 2111 int rv = CMD_FAIL; 2112 char valstr[1024]; 2113 soc_mem_t mem; 2114 int copyno; 2115 char *tab; 2116 int count = 1; 2117 int quiet = 0; 2118 int i; 2119 2120 if (!sh_check_attached(ARG_CMD(a), unit)) { 2121 return CMD_FAIL; 2122 } 2123 2124 if (!soc_feature(unit, soc_feature_mem_push_pop)) { 2125 /* feature not supported */ 2126 return CMD_FAIL; 2127 } 2128 2129 for (;;) { 2130 if ((tab = ARG_GET(a)) == NULL) { 2131 return CMD_USAGE; 2132 } 2133 2134 if (isint(tab)) { 2135 count = parse_integer(tab); 2136 continue; 2137 } 2138 2139 if (sal_strcasecmp(tab, "quiet") == 0) { 2140 quiet = 1; 2141 continue; 2142 } 2143 break; 2144 } 2145 2146 if (parse_memory_name(unit, &mem, tab, ©no, 0) < 0) { 2147 cli_out("ERROR: unknown table \"%s\"\n", tab); 2148 goto done; 2149 } 2150 2151 if (!SOC_MEM_IS_VALID(unit, mem)) { 2152 cli_out("Error: Memory %s not valid for chip %s.\n", 2153 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 2154 goto done; 2155 } 2156 2157 switch (mem) { 2158 #if defined (BCM_TRIUMPH_SUPPORT) 2159 case ING_IPFIX_EXPORT_FIFOm: 2160 case EGR_IPFIX_EXPORT_FIFOm: 2161 case EXT_L2_MOD_FIFOm: 2162 #endif /* BCM_TRIUMPH_SUPPORT */ 2163 case L2_MOD_FIFOm: 2164 break; 2165 default: 2166 cli_out("ERROR: %s table does not support FIFO push/pop\n", 2167 SOC_MEM_UFNAME(unit, mem)); 2168 goto done; 2169 } 2170 2171 entry_dw = soc_mem_entry_words(unit, mem); 2172 ufname = SOC_MEM_UFNAME(unit, mem); 2173 2174 if (copyno == COPYNO_ALL) { 2175 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 2176 } 2177 2178 /* 2179 * If a list of fields were specified, generate the entry from them. 2180 * Otherwise, generate it by reading raw dwords from command line. 2181 */ 2182 2183 if ((s = ARG_GET(a)) == 0) { 2184 cli_out("ERROR: missing data for entry to push\n"); 2185 goto done; 2186 } 2187 2188 if (!isint(s)) { 2189 /* List of fields */ 2190 2191 collect_comma_args(a, valstr, s); 2192 2193 sal_memset(entry, 0, sizeof (entry)); 2194 2195 if (modify_mem_fields(unit, mem, entry, NULL, valstr, FALSE) < 0) { 2196 cli_out("Syntax error in field specification\n"); 2197 goto done; 2198 } 2199 } else { 2200 /* List of numeric values */ 2201 2202 ARG_PREV(a); 2203 2204 if (parse_dwords(entry_dw, entry, a) < 0) { 2205 goto done; 2206 } 2207 } 2208 2209 if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) { 2210 cli_out("PUSH[%s], DATA:", ufname); 2211 for (i = 0; i < entry_dw; i++) { 2212 cli_out(" 0x%x", entry[i]); 2213 } 2214 cli_out("\n"); 2215 } 2216 2217 /* 2218 * Have entry data, push entry. 2219 */ 2220 2221 while (count--) { 2222 i = soc_mem_push(unit, mem, copyno, entry); 2223 if (quiet && i == SOC_E_FULL) { 2224 i = SOC_E_NONE; 2225 } 2226 2227 if (i < 0) { 2228 cli_out("Push ERROR: %s table push failed: %s\n", 2229 ufname, soc_errmsg(i)); 2230 goto done; 2231 } 2232 } 2233 2234 rv = CMD_OK; 2235 2236 done: 2237 return rv; 2238 } 2239 2240 /* 2241 * do_search_entry 2242 * 2243 * Auxiliary routine for command_search() 2244 * Returns byte position within entry where pattern is found. 2245 * Returns -1 if not found. 2246 * Finds pattern in either big- or little-endian order. 2247 */ 2248 2249 static int 2250 do_search_entry(uint8 *entry, int entry_len, 2251 uint8 *pat, int pat_len) 2252 { 2253 int start, i; 2254 2255 for (start = 0; start <= entry_len - pat_len; start++) { 2256 for (i = 0; i < pat_len; i++) { 2257 if (entry[start + i] != pat[i]) { 2258 break; 2259 } 2260 } 2261 2262 if (i == pat_len) { 2263 return start; 2264 } 2265 2266 for (i = 0; i < pat_len; i++) { 2267 if (entry[start + i] != pat[pat_len - 1 - i]) { 2268 break; 2269 } 2270 } 2271 2272 if (i == pat_len) { 2273 return start; 2274 } 2275 } 2276 2277 return -1; 2278 } 2279 2280 /* 2281 * Search a table for a byte pattern 2282 */ 2283 2284 #define SRCH_MAX_PAT 16 2285 2286 char search_usage[] = 2287 "1. Parameters: [ALL | BIN | FBIN] <TABLE>[.<COPY>] 0x<PATTERN>\n" 2288 #ifndef COMPILER_STRING_CONST_LIMIT 2289 "\tDumps table entries containing the specified byte pattern\n\t" 2290 "anywhere in the entry in big- or little-endian order.\n\t" 2291 "Example: search arl 0x112233445566\n" 2292 #endif 2293 "2. Parameters: [ALL | BIN | FBIN] <TABLE>[.<COPY>]" 2294 "<FIELD>=<VALUE>[,...]\n" 2295 #ifndef COMPILER_STRING_CONST_LIMIT 2296 "\tDumps table entries where the specified fields are equal\n\t" 2297 "to the specified values.\n\t" 2298 "Example: search l3 ip_addr=0xf4000001,pnum=10\n\t" 2299 "The ALL flag indicates to search sorted tables in their\n\t" 2300 "entirety instead of only entries known to contain data.\n\t" 2301 "The BIN flag does a binary search of sorted tables in\n\t" 2302 "the portion known to contain data.\n\t" 2303 "The FBIN flag does a binary search, and guarantees if there\n\t" 2304 "are duplicates the lowest matching index will be returned.\n" 2305 #endif 2306 ; 2307 2308 cmd_result_t 2309 mem_search(int unit, args_t *a) 2310 { 2311 int t, rv = CMD_FAIL; 2312 char *tab, *patstr; 2313 soc_mem_t mem; 2314 uint32 pat_entry[SOC_MAX_MEM_WORDS]; 2315 uint32 pat_mask[SOC_MAX_MEM_WORDS]; 2316 uint32 entry[SOC_MAX_MEM_WORDS]; 2317 char valstr[1024]; 2318 uint8 pat[SRCH_MAX_PAT]; 2319 char *ufname; 2320 int patsize = 0, found_count = 0, entry_bytes, entry_dw; 2321 int copyno, index, min, max; 2322 int byte_search; 2323 int all_flag = 0, bin_flag = 0, lowest_match = 0; 2324 #ifdef BCM_TRIDENT2_SUPPORT 2325 int check_view = FALSE; 2326 soc_mem_t view = INVALIDm; 2327 #endif /* BCM_TRIDENT2_SUPPORT */ 2328 2329 if (!sh_check_attached(ARG_CMD(a), unit)) { 2330 goto done; 2331 } 2332 2333 tab = ARG_GET(a); 2334 2335 while (tab) { 2336 if (!sal_strcasecmp(tab, "all")) { 2337 all_flag = 1; 2338 } else if (!sal_strcasecmp(tab, "bin")) { 2339 bin_flag = 1; 2340 } else if (!sal_strcasecmp(tab, "fbin")) { 2341 bin_flag = 1; 2342 lowest_match = 1; 2343 } else { 2344 break; 2345 } 2346 tab = ARG_GET(a); 2347 } 2348 2349 patstr = ARG_GET(a); 2350 2351 if (!tab || !patstr) { 2352 return CMD_USAGE; 2353 } 2354 2355 if (parse_memory_name(unit, &mem, tab, ©no, 0) < 0) { 2356 cli_out("ERROR: unknown table \"%s\"\n", tab); 2357 goto done; 2358 } 2359 2360 if (!SOC_MEM_IS_VALID(unit, mem)) { 2361 cli_out("Error: Memory %s not valid for chip %s.\n", 2362 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 2363 goto done; 2364 } 2365 2366 if (copyno == COPYNO_ALL) { 2367 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 2368 } 2369 2370 entry_bytes = soc_mem_entry_bytes(unit, mem); 2371 entry_dw = BYTES2WORDS(entry_bytes); 2372 min = soc_mem_index_min(unit, mem); 2373 max = soc_mem_index_max(unit, mem); 2374 ufname = SOC_MEM_UFNAME(unit, mem); 2375 2376 byte_search = isint(patstr); 2377 2378 if (byte_search) { 2379 char *s; 2380 2381 /* 2382 * Search by pattern string. 2383 * Parse pattern string (long hex number) into array of bytes. 2384 */ 2385 2386 if (patstr[0] != '0' || 2387 (patstr[1] != 'x' && patstr[1] != 'X') || patstr[2] == 0) { 2388 cli_out("ERROR: illegal search pattern, need hex constant\n"); 2389 goto done; 2390 } 2391 2392 patstr += 2; 2393 2394 for (s = patstr; *s; s++) { 2395 if (!isxdigit((unsigned) *s)) { 2396 cli_out("ERROR: invalid hex digit in search pattern\n"); 2397 goto done; 2398 } 2399 } 2400 2401 while (s > patstr + 1) { 2402 s -= 2; 2403 pat[patsize++] = xdigit2i(s[0]) << 4 | xdigit2i(s[1]); 2404 } 2405 2406 if (s > patstr) { 2407 s--; 2408 pat[patsize++] = xdigit2i(s[0]); 2409 } 2410 2411 #if 0 2412 cli_out("PATTERN: "); 2413 for (index = 0; index < patsize; index++) { 2414 cli_out("%02x ", pat[index]); 2415 } 2416 cli_out("\n"); 2417 #endif 2418 } else { 2419 /* 2420 * Search by pat_entry and pat_mask. 2421 * Collect list of fields 2422 */ 2423 2424 collect_comma_args(a, valstr, patstr); 2425 2426 memset(pat_entry, 0, sizeof (pat_entry)); 2427 2428 if (modify_mem_fields(unit, mem, 2429 pat_entry, pat_mask, 2430 valstr, FALSE) < 0) { 2431 cli_out("Syntax error: aborted\n"); 2432 goto done; 2433 } 2434 } 2435 2436 if (bin_flag) { 2437 if (!soc_mem_is_sorted(unit, mem)) { 2438 cli_out("ERROR: can only binary search sorted tables\n"); 2439 goto done; 2440 } 2441 2442 if (byte_search) { 2443 cli_out("ERROR: can only binary search for " 2444 "<FIELD>=<VALUE>[,...]\n"); 2445 goto done; 2446 } 2447 2448 cli_out("Searching %s...\n", ufname); 2449 2450 t = soc_mem_search(unit, mem, copyno, &index, 2451 pat_entry, entry, lowest_match); 2452 if ((t < 0) && (t != SOC_E_NOT_FOUND)) { 2453 cli_out("Read ERROR: table[%s]: %s\n", ufname, soc_errmsg(t)); 2454 goto done; 2455 } 2456 2457 if (t == SOC_E_NONE) { 2458 cli_out("%s[%d]: ", ufname, index); 2459 soc_mem_entry_dump(unit, mem, entry, BSL_LSS_CLI); 2460 cli_out("\n"); 2461 } else { 2462 cli_out("Nothing found\n"); 2463 } 2464 2465 rv = CMD_OK; 2466 goto done; 2467 } 2468 2469 if (!all_flag && soc_mem_is_sorted(unit, mem)) { 2470 max = soc_mem_index_last(unit, mem, copyno); 2471 } 2472 2473 #ifdef BCM_TRIDENT2_SUPPORT 2474 if (SOC_IS_TD2_TT2(unit) && 2475 (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m || 2476 mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m || 2477 mem == L3_DEFIP_ALPM_IPV6_128m)) { 2478 check_view = TRUE; 2479 view = mem; 2480 } 2481 #endif /* BCM_TRIDENT2_SUPPORT */ 2482 2483 cli_out("Searching %s table indexes 0x%x through 0x%x...\n", 2484 ufname, min, max); 2485 2486 for (index = min; index <= max; index++) { 2487 int match; 2488 2489 #ifdef BCM_TRIDENT2_SUPPORT 2490 if (check_view) { 2491 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) { 2492 view = _soc_trident2_alpm_bkt_view_get(unit, index); 2493 } 2494 #if defined(ALPM_ENABLE) 2495 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) 2496 else { 2497 view = soc_alpm_cmn_bkt_view_get(unit, index); 2498 } 2499 #endif 2500 #endif 2501 if (!(view == INVALIDm || mem == view)) { 2502 continue; 2503 } 2504 } 2505 #endif /* BCM_TRIDENT2_SUPPORT */ 2506 2507 if ((t = soc_mem_read(unit, mem, copyno, index, entry)) < 0) { 2508 cli_out("Read ERROR: table %s.%s[%d]: %s\n", 2509 ufname, SOC_BLOCK_NAME(unit, copyno), index, soc_errmsg(t)); 2510 goto done; 2511 } 2512 2513 #ifdef BCM_XGS_SWITCH_SUPPORT 2514 if (!all_flag) { 2515 #ifdef BCM_XGS12_SWITCH_SUPPORT 2516 if SOC_IS_XGS12_SWITCH(unit) { 2517 if (mem == L2Xm && 2518 !soc_L2Xm_field32_get(unit, entry, VALID_BITf)) { 2519 continue; 2520 } 2521 2522 if (mem == L3Xm && 2523 !soc_L3Xm_field32_get(unit, entry, L3_VALIDf)) { 2524 continue; 2525 } 2526 } 2527 #endif /* BCM_XGS12_SWITCH_SUPPORT */ 2528 2529 #ifdef BCM_XGS3_SWITCH_SUPPORT 2530 #ifdef BCM_FIREBOLT_SUPPORT 2531 if (SOC_IS_FBX(unit) || SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) { 2532 switch (mem) { 2533 case L2Xm: 2534 { 2535 soc_field_t vld_fld; 2536 vld_fld = 2537 (SOC_IS_TOMAHAWK3(unit) || SOC_IS_TRIDENT3X(unit)) ? BASE_VALIDf : VALIDf; 2538 if (!soc_L2Xm_field32_get(unit, entry, vld_fld)) { 2539 continue; 2540 } 2541 } 2542 break; 2543 case L2_USER_ENTRYm: 2544 if (!soc_L2_USER_ENTRYm_field32_get(unit, 2545 entry, VALIDf)) { 2546 continue; 2547 } 2548 break; 2549 case L3_ENTRY_IPV4_UNICASTm: 2550 if (!soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 2551 entry, VALIDf)) { 2552 continue; 2553 } 2554 break; 2555 case L3_ENTRY_IPV4_MULTICASTm: 2556 if (soc_mem_field_valid(unit, mem, VALIDf)) { 2557 if (!soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 2558 entry, VALIDf)) { 2559 continue; 2560 } 2561 } 2562 2563 if (soc_mem_field_valid(unit, mem, VALID_0f) && 2564 soc_mem_field_valid(unit, mem, VALID_1f)) { 2565 if (!(soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 2566 entry, VALID_0f) && 2567 soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, 2568 entry, VALID_1f))) { 2569 continue; 2570 } 2571 } 2572 break; 2573 case L3_ENTRY_IPV6_UNICASTm: 2574 if (!(soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, 2575 entry, VALID_0f) && 2576 soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, 2577 entry, VALID_1f))) { 2578 continue; 2579 } 2580 break; 2581 case L3_ENTRY_IPV6_MULTICASTm: 2582 if (!(soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 2583 entry, VALID_0f) && 2584 soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 2585 entry, VALID_1f) && 2586 soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 2587 entry, VALID_2f) && 2588 soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, 2589 entry, VALID_3f))) { 2590 continue; 2591 } 2592 break; 2593 default: 2594 break; 2595 } 2596 } 2597 #endif /* BCM_FIREBOLT_SUPPORT */ 2598 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 2599 } 2600 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2601 2602 if (byte_search) { 2603 match = (do_search_entry((uint8 *) entry, entry_bytes, 2604 pat, patsize) >= 0); 2605 } else { 2606 int i; 2607 2608 for (i = 0; i < entry_dw; i++) 2609 if ((entry[i] & pat_mask[i]) != pat_entry[i]) 2610 break; 2611 2612 match = (i == entry_dw); 2613 } 2614 2615 if (match) { 2616 cli_out("%s.%s[%d]: ", 2617 ufname, SOC_BLOCK_NAME(unit, copyno), index); 2618 soc_mem_entry_dump(unit, mem, entry, BSL_LSS_CLI); 2619 cli_out("\n"); 2620 found_count++; 2621 } 2622 } 2623 2624 if (found_count == 0) { 2625 cli_out("Nothing found\n"); 2626 } 2627 2628 rv = CMD_OK; 2629 2630 done: 2631 return rv; 2632 } 2633 2634 /* 2635 * Print a one line summary for matching memories 2636 * If substr_match is NULL, match all memories. 2637 * If substr_match is non-NULL, match any memories whose name 2638 * or user-friendly name contains that substring. 2639 */ 2640 2641 static void 2642 mem_list_summary(int unit, char *substr_match) 2643 { 2644 soc_mem_t mem; 2645 int i, copies, dlen; 2646 int found = 0; 2647 char *dstr; 2648 int print_tr = 0; 2649 const char *soctr = "soc_tr"; 2650 2651 if(substr_match) { 2652 if(sal_strcmp(substr_match,soctr) == 0){ 2653 print_tr = 1; 2654 substr_match = NULL; 2655 } 2656 } 2657 2658 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 2659 if (!soc_mem_is_valid(unit, mem)) { 2660 continue; 2661 } 2662 2663 #if defined(BCM_HAWKEYE_SUPPORT) 2664 if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) { 2665 continue; 2666 } 2667 #endif /* BCM_HAWKEYE_SUPPORT */ 2668 2669 if (substr_match != NULL && 2670 strcaseindex(SOC_MEM_NAME(unit, mem), substr_match) == NULL && 2671 strcaseindex(SOC_MEM_UFNAME(unit, mem), substr_match) == NULL) { 2672 continue; 2673 } 2674 2675 copies = 0; 2676 SOC_MEM_BLOCK_ITER(unit, mem, i) { 2677 copies += 1; 2678 } 2679 2680 dlen = sal_strlen(SOC_MEM_DESC(unit, mem)); 2681 if (dlen > 30) { 2682 dlen = 26; 2683 dstr = "..."; 2684 } else { 2685 dstr = ""; 2686 } 2687 2688 if(print_tr) { 2689 if(!soc_mem_is_readonly(unit, mem)) { 2690 if(soc_mem_index_count(unit,mem) > 3) { 2691 cli_out("local mem '%s';\n", SOC_MEM_UFNAME(unit,mem)); 2692 cli_out("$name; $tr50; $tr51; $tr52;\n"); 2693 } else if(soc_mem_index_count(unit,mem) > 0) { 2694 cli_out("local mem '%s';\n", SOC_MEM_UFNAME(unit,mem)); 2695 cli_out("$name; $tr50;\n"); 2696 } 2697 } else { 2698 cli_out("#local mem '%s' Read Only Memory - Not tested\n", 2699 SOC_MEM_UFNAME(unit,mem)); 2700 } 2701 } else { 2702 if (!found) { 2703 cli_out(" %-6s %1s %-28s%6s/%-4s %s\n", 2704 "Flags", "C", "Name", "Entry", 2705 "Copy", "Description"); 2706 found = 1; 2707 } 2708 2709 cli_out(" %c%c%c%c%c%c %1s %-28s%6d", 2710 soc_mem_is_readonly(unit, mem) ? 'r' : '-', 2711 soc_mem_is_debug(unit, mem) ? 'd' : '-', 2712 soc_mem_is_sorted(unit, mem) ? 's' : 2713 soc_mem_is_hashed(unit, mem) ? 'h' : 2714 soc_mem_is_cam(unit, mem) ? 'A' : '-', 2715 soc_mem_is_cbp(unit, mem) ? 'c' : '-', 2716 (soc_mem_is_bistepic(unit, mem) || 2717 soc_mem_is_bistffp(unit, mem) || 2718 soc_mem_is_bistcbp(unit, mem)) ? 'b' : '-', 2719 soc_mem_is_cachable(unit, mem) ? 'C' : '-', 2720 soc_mem_cache_get(unit, mem, SOC_BLOCK_ANY) ? "*" : "", 2721 SOC_MEM_UFNAME(unit, mem), 2722 soc_mem_index_count(unit, mem)); 2723 if (copies == 1) { 2724 cli_out("%5s %*.*s%s\n", 2725 "", 2726 dlen, dlen, SOC_MEM_DESC(unit, mem), dstr); 2727 } else { 2728 cli_out("/%-4d %*.*s%s\n", 2729 copies, 2730 dlen, dlen, SOC_MEM_DESC(unit, mem), dstr); 2731 } 2732 } 2733 } 2734 2735 if (found) { 2736 cli_out("Flags: (r)eadonly, (d)ebug, (s)orted, (h)ashed\n" 2737 " C(A)M, (c)bp, (b)ist-able, (C)achable\n"); 2738 cli_out(" C: Cache state, * means cache is on\n"); 2739 } else if (substr_match != NULL) { 2740 cli_out("No memory found with the substring '%s' in its name.\n", 2741 substr_match); 2742 } 2743 } 2744 2745 /* 2746 * List the tables, or fields of a table entry 2747 */ 2748 2749 cmd_result_t 2750 cmd_esw_mem_list(int unit, args_t *a) 2751 { 2752 soc_mem_info_t *m; 2753 soc_field_info_t *fld; 2754 char *tab, *s; 2755 soc_mem_t mem; 2756 uint32 entry[SOC_MAX_MEM_WORDS]; 2757 uint32 mask[SOC_MAX_MEM_WORDS]; 2758 int have_entry, i, dw, copyno; 2759 int copies, disabled, dmaable, slamable; 2760 char *dmastr, *slamstr; 2761 uint32 flags; 2762 int minidx, maxidx; 2763 uint8 at; 2764 2765 if (!sh_check_attached(ARG_CMD(a), unit)) { 2766 return CMD_FAIL; 2767 } 2768 2769 if (!soc_property_get(unit, spn_MEMLIST_ENABLE, 1)) { 2770 return CMD_OK; 2771 } 2772 tab = ARG_GET(a); 2773 2774 if (!tab) { 2775 mem_list_summary(unit, NULL); 2776 return CMD_OK; 2777 } 2778 2779 if (parse_memory_name(unit, &mem, tab, ©no, 0) < 0) { 2780 if ((s = strchr(tab, '.')) != NULL) { 2781 *s = 0; 2782 } 2783 mem_list_summary(unit, tab); 2784 return CMD_OK; 2785 } 2786 2787 if (!SOC_MEM_IS_VALID(unit, mem)) { 2788 cli_out("ERROR: Memory \"%s\" not valid for this unit\n", tab); 2789 return CMD_FAIL; 2790 } 2791 2792 #if defined(BCM_HAWKEYE_SUPPORT) 2793 if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) { 2794 cli_out("ERROR: Memory \"%s\" not valid for this unit\n", tab); 2795 return CMD_FAIL; 2796 } 2797 #endif /* BCM_HAWKEYE_SUPPORT */ 2798 2799 if (copyno < 0) { 2800 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 2801 if (copyno < 0) { 2802 cli_out("ERROR: Memory \"%s\" has no instance on this unit\n", tab); 2803 return CMD_FAIL; 2804 } 2805 } else if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 2806 cli_out("ERROR: Invalid copy number %d for memory %s\n", copyno, tab); 2807 return CMD_FAIL; 2808 } 2809 2810 m = &SOC_MEM_INFO(unit, mem); 2811 flags = m->flags; 2812 2813 dw = BYTES2WORDS(m->bytes); 2814 2815 if ((s = ARG_GET(a)) == 0) { 2816 have_entry = 0; 2817 } else { 2818 for (i = 0; i < dw; i++) { 2819 if (s == 0) { 2820 cli_out("Not enough data specified (%d words needed)\n", dw); 2821 return CMD_FAIL; 2822 } 2823 entry[i] = parse_integer(s); 2824 s = ARG_GET(a); 2825 } 2826 if (s) { 2827 cli_out("Extra data specified (ignored)\n"); 2828 } 2829 have_entry = 1; 2830 } 2831 2832 cli_out("Memory: %s.%s", 2833 SOC_MEM_NAME(unit, mem), 2834 SOC_BLOCK_NAME(unit, copyno)); 2835 s = SOC_MEM_UFNAME(unit, mem); 2836 if (s && *s && sal_strcmp(SOC_MEM_NAME(unit, mem), s) != 0) { 2837 cli_out(" aka %s", s); 2838 } 2839 s = SOC_MEM_UFALIAS(unit, mem); 2840 if (s && *s && sal_strcmp(SOC_MEM_UFNAME(unit, mem), s) != 0) { 2841 cli_out(" alias %s", s); 2842 } 2843 cli_out(" address 0x%08x\n", soc_mem_addr_get(unit, mem, 0, copyno, 0, &at)); 2844 2845 cli_out("Flags:"); 2846 if (flags & SOC_MEM_FLAG_READONLY) { 2847 cli_out(" read-only"); 2848 } 2849 if (flags & SOC_MEM_FLAG_VALID) { 2850 cli_out(" valid"); 2851 } 2852 if (flags & SOC_MEM_FLAG_DEBUG) { 2853 cli_out(" debug"); 2854 } 2855 if (flags & SOC_MEM_FLAG_SORTED) { 2856 cli_out(" sorted"); 2857 } 2858 if (flags & SOC_MEM_FLAG_CBP) { 2859 cli_out(" cbp"); 2860 } 2861 if (flags & SOC_MEM_FLAG_CACHABLE) { 2862 cli_out(" cachable"); 2863 if (soc_mem_cache_get(unit, mem, SOC_BLOCK_ANY)) { 2864 cli_out("(on)"); 2865 } else { 2866 cli_out("(off)"); 2867 } 2868 } 2869 if (flags & SOC_MEM_FLAG_BISTCBP) { 2870 cli_out(" bist-cbp"); 2871 } 2872 if (flags & SOC_MEM_FLAG_BISTEPIC) { 2873 cli_out(" bist-epic"); 2874 } 2875 if (flags & SOC_MEM_FLAG_BISTFFP) { 2876 cli_out(" bist-ffp"); 2877 } 2878 if (flags & SOC_MEM_FLAG_UNIFIED) { 2879 cli_out(" unified"); 2880 } 2881 if (flags & SOC_MEM_FLAG_HASHED) { 2882 cli_out(" hashed"); 2883 } 2884 if (flags & SOC_MEM_FLAG_WORDADR) { 2885 cli_out(" word-addressed"); 2886 } 2887 if (flags & SOC_MEM_FLAG_BE) { 2888 cli_out(" big-endian"); 2889 } 2890 if (flags & SOC_MEM_FLAG_MULTIVIEW) { 2891 cli_out(" multiview"); 2892 } 2893 cli_out("\n"); 2894 2895 cli_out("Blocks: "); 2896 copies = disabled = dmaable = slamable = 0; 2897 SOC_MEM_BLOCK_ITER(unit, mem, i) { 2898 if (SOC_INFO(unit).block_valid[i]) { 2899 dmastr = ""; 2900 slamstr = ""; 2901 #ifdef BCM_XGS_SWITCH_SUPPORT 2902 if (soc_mem_dmaable(unit, mem, i)) { 2903 dmastr = "/dma"; 2904 dmaable += 1; 2905 } 2906 if (soc_mem_slamable(unit, mem, i)) { 2907 slamstr = "/slam"; 2908 slamable += 1; 2909 } 2910 #endif 2911 cli_out(" %s%s%s", SOC_BLOCK_NAME(unit, i), dmastr, slamstr); 2912 } else { 2913 cli_out(" [%s]", SOC_BLOCK_NAME(unit, i)); 2914 disabled += 1; 2915 } 2916 copies += 1; 2917 } 2918 cli_out(" (%d cop%s", copies, copies == 1 ? "y" : "ies"); 2919 if (disabled) { 2920 cli_out(", %d disabled", disabled); 2921 } 2922 #ifdef BCM_XGS_SWITCH_SUPPORT 2923 if (dmaable) { 2924 cli_out(", %d dmaable", dmaable); 2925 } 2926 if (slamable) { 2927 cli_out(", %d slamable", slamable); 2928 } 2929 #endif 2930 cli_out(")\n"); 2931 2932 minidx = soc_mem_index_min(unit, mem); 2933 maxidx = soc_mem_index_max(unit, mem); 2934 cli_out("Entries: %d with indices %d-%d (0x%x-0x%x)", 2935 maxidx - minidx + 1, 2936 minidx, 2937 maxidx, 2938 minidx, 2939 maxidx); 2940 cli_out(", each %d bytes %d words\n", m->bytes, dw); 2941 2942 cli_out("Entry mask:"); 2943 soc_mem_datamask_get(unit, mem, mask); 2944 for (i = 0; i < dw; i++) { 2945 if (mask[i] == 0xffffffff) { 2946 cli_out(" -1"); 2947 } else if (mask[i] == 0) { 2948 cli_out(" 0"); 2949 } else { 2950 cli_out(" 0x%08x", mask[i]); 2951 } 2952 } 2953 cli_out("\n"); 2954 2955 #ifdef BCM_ISM_SUPPORT 2956 if (soc_feature(unit, soc_feature_ism_memory)) { 2957 uint8 banks[_SOC_ISM_MAX_BANKS] = {0}; 2958 uint32 bank_size[_SOC_ISM_MAX_BANKS]; 2959 uint8 count; 2960 if (soc_ism_get_banks_for_mem(unit, mem, banks, bank_size, &count) 2961 == SOC_E_NONE) { 2962 if (count) { 2963 uint8 bc; 2964 uint32 bmask = 0; 2965 for (bc = 0; bc < count; bc++) { 2966 bmask |= 1 << banks[bc]; 2967 } 2968 cli_out("ISM bank mask: 0x%x\n", bmask); 2969 } 2970 } 2971 } 2972 #endif 2973 2974 s = SOC_MEM_DESC(unit, mem); 2975 if (s && *s) { 2976 cli_out("Description: %s\n", s); 2977 } 2978 2979 for (fld = &m->fields[m->nFields - 1]; fld >= &m->fields[0]; fld--) { 2980 cli_out(" %s<%d", SOC_FIELD_NAME(unit, fld->field), fld->bp + fld->len - 1); 2981 if (fld->len > 1) { 2982 cli_out(":%d", fld->bp); 2983 } 2984 if (have_entry) { 2985 uint32 fval[SOC_MAX_MEM_FIELD_WORDS]; 2986 char tmp[132]; 2987 2988 sal_memset(fval, 0, sizeof (fval)); 2989 soc_mem_field_get(unit, mem, entry, fld->field, fval); 2990 format_long_integer(tmp, fval, SOC_MAX_MEM_FIELD_WORDS); 2991 cli_out("> = %s\n", tmp); 2992 } else { 2993 cli_out(">\n"); 2994 } 2995 } 2996 2997 return CMD_OK; 2998 } 2999 3000 /* 3001 * Turn on/off software caching of hardware tables 3002 */ 3003 3004 cmd_result_t 3005 mem_esw_cache(int unit, args_t *a) 3006 { 3007 soc_mem_t mem; 3008 int copyno; 3009 char *c; 3010 int enable, r; 3011 3012 if (!sh_check_attached(ARG_CMD(a), unit)) { 3013 return CMD_FAIL; 3014 } 3015 3016 if (ARG_CNT(a) == 0) { 3017 for (enable = 0; enable < 2; enable++) { 3018 cli_out("Caching is %s for:\n", enable ? "on" : "off"); 3019 3020 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3021 int any_printed; 3022 3023 if ((!SOC_MEM_IS_VALID(unit, mem)) || 3024 (!soc_mem_is_cachable(unit, mem))) { 3025 continue; 3026 } 3027 3028 any_printed = 0; 3029 3030 SOC_MEM_BLOCK_ITER(unit, mem, copyno) { 3031 if ((!enable) == 3032 (!soc_mem_cache_get(unit, mem, copyno))) { 3033 if (!any_printed) { 3034 cli_out(" "); 3035 } 3036 cli_out(" %s.%s", 3037 SOC_MEM_UFNAME(unit, mem), 3038 SOC_BLOCK_NAME(unit, copyno)); 3039 any_printed = 1; 3040 } 3041 } 3042 3043 if (any_printed) { 3044 cli_out("\n"); 3045 } 3046 } 3047 } 3048 3049 return CMD_OK; 3050 } 3051 3052 while ((c = ARG_GET(a)) != 0) { 3053 switch (*c) { 3054 case '+': 3055 enable = 1; 3056 c++; 3057 break; 3058 case '-': 3059 enable = 0; 3060 c++; 3061 break; 3062 default: 3063 enable = 1; 3064 break; 3065 } 3066 3067 if (parse_memory_name(unit, &mem, c, ©no, 0) < 0) { 3068 cli_out("%s: Unknown table \"%s\"\n", ARG_CMD(a), c); 3069 return CMD_FAIL; 3070 } 3071 3072 if (!SOC_MEM_IS_VALID(unit, mem)) { 3073 cli_out("Error: Memory %s not valid for chip %s.\n", 3074 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 3075 continue; 3076 } 3077 3078 if (!soc_mem_is_cachable(unit, mem)) { 3079 cli_out("%s: Memory %s is not cachable\n", 3080 ARG_CMD(a), SOC_MEM_UFNAME(unit, mem)); 3081 return CMD_FAIL; 3082 } 3083 3084 if ((r = soc_mem_cache_set(unit, mem, copyno, enable)) < 0) { 3085 cli_out("%s: Error setting cachability for %s: %s\n", 3086 ARG_CMD(a), SOC_MEM_UFNAME(unit, mem), soc_errmsg(r)); 3087 return CMD_FAIL; 3088 } 3089 } 3090 3091 return CMD_OK; 3092 } 3093 3094 #ifdef INCLUDE_MEM_SCAN 3095 3096 /* 3097 * Turn on/off memory scan thread 3098 */ 3099 3100 char memscan_usage[] = 3101 "Parameters: [Interval=<USEC>] [Rate=<ENTRIES>] [on] [off]\n\t" 3102 "Interval specifies how often to run (0 to stop)\n\t" 3103 "Rate specifies the number of entries to process per interval\n\t" 3104 "Any memories that are cached will be scanned (see 'cache' command)\n"; 3105 3106 cmd_result_t 3107 mem_scan(int unit, args_t *a) 3108 { 3109 parse_table_t pt; 3110 int running, rv; 3111 sal_usecs_t interval = 0; 3112 int rate = SOC_MEMSCAN_RATE_DEFAULT; 3113 char *c; 3114 3115 if (!sh_check_attached(ARG_CMD(a), unit)) { 3116 return CMD_FAIL; 3117 } 3118 3119 if ((running = soc_mem_scan_running(unit, &rate, &interval)) < 0) { 3120 cli_out("soc_mem_scan_running %d: ERROR: %s\n", 3121 unit, soc_errmsg(running)); 3122 return CMD_FAIL; 3123 } 3124 3125 if (ARG_CNT(a) == 0) { 3126 cli_out("%s: %s on unit %d\n", 3127 ARG_CMD(a), running ? "Running" : "Not running", unit); 3128 cli_out("%s: Interval: %d usec\n", 3129 ARG_CMD(a), interval); 3130 cli_out("%s: Rate: %d\n", 3131 ARG_CMD(a), rate); 3132 3133 return CMD_OK; 3134 } 3135 3136 parse_table_init(unit, &pt); 3137 parse_table_add(&pt, "Interval", PQ_INT | PQ_DFL, 0, &interval, 0); 3138 parse_table_add(&pt, "Rate", PQ_INT | PQ_DFL, 0, &rate, 0); 3139 3140 if (parse_arg_eq(a, &pt) < 0) { 3141 cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a)); 3142 parse_arg_eq_done(&pt); 3143 return CMD_FAIL; 3144 } 3145 3146 parse_arg_eq_done(&pt); 3147 3148 if ((c = ARG_GET(a)) != NULL) { 3149 if (sal_strcasecmp(c, "off") == 0) { 3150 interval = 0; 3151 rate = 0; 3152 } else if (sal_strcasecmp(c, "on") == 0) { 3153 interval = prev_memscan_interval[unit]; 3154 rate = prev_memscan_rate[unit]; 3155 } else { 3156 return CMD_USAGE; 3157 } 3158 } 3159 3160 if (interval == 0) { 3161 sal_usecs_t prev_interval; 3162 int prev_rate; 3163 3164 rv = soc_mem_scan_running(unit, &prev_rate, &prev_interval); 3165 if (rv < 0 || prev_rate <= 0) { 3166 prev_rate = SOC_MEMSCAN_RATE_DEFAULT; 3167 } 3168 if (rv < 0 || prev_interval <= 0) { 3169 prev_interval = SOC_MEMSCAN_INTERVAL_DEFAULT; 3170 } 3171 prev_memscan_rate[unit] = prev_rate; 3172 prev_memscan_interval[unit] = prev_interval; 3173 3174 if ((rv = soc_mem_scan_stop(unit)) < 0) { 3175 cli_out("soc_mem_scan_stop %d: ERROR: %s\n", 3176 unit, soc_errmsg(rv)); 3177 return CMD_FAIL; 3178 } 3179 3180 cli_out("%s: Stopped on unit %d\n", ARG_CMD(a), unit); 3181 } else { 3182 if (0 == rate) { 3183 cli_out("%s: Start fails since rate 0 is not supported!\n", ARG_CMD(a)); 3184 return CMD_FAIL; 3185 } 3186 if ((rv = soc_mem_scan_start(unit, rate, interval)) < 0) { 3187 cli_out("soc_mem_scan_start %d: ERROR: %s\n", 3188 unit, soc_errmsg(rv)); 3189 return CMD_FAIL; 3190 } 3191 cli_out("%s: Started on unit %d\n", ARG_CMD(a), unit); 3192 } 3193 3194 return CMD_OK; 3195 } 3196 3197 #endif /* INCLUDE_MEM_SCAN */ 3198 3199 #ifdef BCM_SRAM_SCAN_SUPPORT 3200 3201 /* 3202 * Turn on/off sram scan thread 3203 */ 3204 3205 char sramscan_usage[] = 3206 "Parameters: [Interval=<USEC>] [Rate=<ENTRIES>] [on] [off]\n\t" 3207 "Interval specifies how often to run (0 to stop)\n\t" 3208 "Rate specifies the number of entries to process per interval\n\t" 3209 "Any srams that are cached will be scanned (see 'cache' command)\n"; 3210 3211 cmd_result_t 3212 sram_scan(int unit, args_t *a) 3213 { 3214 parse_table_t pt; 3215 int running, rv; 3216 sal_usecs_t interval = 0; 3217 int rate = SOC_SRAMSCAN_RATE_DEFAULT; 3218 char *c; 3219 3220 if (!sh_check_attached(ARG_CMD(a), unit)) { 3221 return CMD_FAIL; 3222 } 3223 3224 if ((running = soc_sram_scan_running(unit, &rate, &interval)) < 0) { 3225 cli_out("soc_sram_scan_running %d: ERROR: %s\n", 3226 unit, soc_errmsg(running)); 3227 return CMD_FAIL; 3228 } 3229 3230 if (ARG_CNT(a) == 0) { 3231 cli_out("%s: %s on unit %d\n", 3232 ARG_CMD(a), running ? "Running" : "Not running", unit); 3233 cli_out("%s: Interval: %d usec\n", 3234 ARG_CMD(a), interval); 3235 cli_out("%s: Rate: %d\n", 3236 ARG_CMD(a), rate); 3237 3238 return CMD_OK; 3239 } 3240 3241 parse_table_init(unit, &pt); 3242 parse_table_add(&pt, "Interval", PQ_INT | PQ_DFL, 0, &interval, 0); 3243 parse_table_add(&pt, "Rate", PQ_INT | PQ_DFL, 0, &rate, 0); 3244 3245 if (parse_arg_eq(a, &pt) < 0) { 3246 cli_out("%s: Invalid argument: %s\n", ARG_CMD(a), ARG_CUR(a)); 3247 parse_arg_eq_done(&pt); 3248 return CMD_FAIL; 3249 } 3250 3251 parse_arg_eq_done(&pt); 3252 3253 if ((c = ARG_GET(a)) != NULL) { 3254 if (sal_strcasecmp(c, "off") == 0) { 3255 interval = 0; 3256 rate = 0; 3257 } else if (sal_strcasecmp(c, "on") == 0) { 3258 interval = prev_sramscan_interval[unit]; 3259 rate = prev_sramscan_rate[unit]; 3260 } else { 3261 return CMD_USAGE; 3262 } 3263 } 3264 3265 if (interval == 0) { 3266 sal_usecs_t prev_interval; 3267 int prev_rate; 3268 3269 rv = soc_sram_scan_running(unit, &prev_rate, &prev_interval); 3270 if (rv < 0 || prev_rate <= 0) { 3271 prev_rate = SOC_SRAMSCAN_RATE_DEFAULT; 3272 } 3273 if (rv < 0 || prev_interval <= 0) { 3274 prev_interval = SOC_SRAMSCAN_INTERVAL_DEFAULT; 3275 } 3276 prev_sramscan_rate[unit] = prev_rate; 3277 prev_sramscan_interval[unit] = prev_interval; 3278 3279 if ((rv = soc_sram_scan_stop(unit)) < 0) { 3280 cli_out("soc_sram_scan_stop %d: ERROR: %s\n", 3281 unit, soc_errmsg(rv)); 3282 return CMD_FAIL; 3283 } 3284 3285 cli_out("%s: Stopped on unit %d\n", ARG_CMD(a), unit); 3286 } else { 3287 if (0 == rate) { 3288 cli_out("%s: Start fails since rate 0 is not supported!\n", ARG_CMD(a)); 3289 return CMD_FAIL; 3290 } 3291 if ((rv = soc_sram_scan_start(unit, rate, interval)) < 0) { 3292 cli_out("soc_sram_scan_start %d: ERROR: %s\n", 3293 unit, soc_errmsg(rv)); 3294 return CMD_FAIL; 3295 } 3296 cli_out("%s: Started on unit %d\n", ARG_CMD(a), unit); 3297 } 3298 return CMD_OK; 3299 } 3300 3301 #endif /* BCM_SRAM_SCAN_SUPPORT */ 3302 3303 3304 #if defined(SER_TR_TEST_SUPPORT) 3305 char cmd_esw_ser_usage[] = 3306 "Usages:\n" 3307 #ifdef COMPILER_STRING_CONST_LIMIT 3308 "SER [options]\t" 3309 #else 3310 " SER INFO (NOT YET IMPLEMENTED)\n" 3311 " SER SHOW (NOT YET IMPLEMENTED)\n" 3312 " SER LOG [ID=<id>]\n" 3313 "\tid argument is used to show specified SER log\n" 3314 " SER INJECT memory=<memID> [Index=<Index>] [Pipe=pipe_x|pipe_y|" 3315 "pipe0|pipe1|pipe2|pipe3|pipe4|pipe5|pipe6|pipe7] [Xor_bank=0|1]\n" 3316 "\tpipe argument is allowed only in multi-pipe devices\n" 3317 "\tXor_bank argument is used to insert error into XOR ram of XOR hash tables.\n" 3318 " SER INJECT register=<regID> port=<portNum> [Index=<Index>]" 3319 " [Pipe=pipe_x|pipe_y|pipe0|pipe1|pipe2|pipe3](NOT YET IMPLEMENTED\n" 3320 "\tWith no optional parameters, Index will default to 0, and Pipe to" 3321 " pipe_x(pipe0)\n" 3322 #endif 3323 ; 3324 3325 /* 3326 * Function: 3327 * cmd_esw_ser 3328 * Purpose: 3329 * Entry point and argument parser for SER diag shell utilities 3330 * Parameters: 3331 * unit - (IN) Device Number 3332 * a - (IN) A string of user input. Only the first parameter will 3333 * be used by this function. 3334 * Returns: 3335 * CMD_OK if injection succeeds, CMD_USAGE if there is a problem with user 3336 * input, and CMD_FAIL if preconditions are not met or injection fails for 3337 * a reason not related to incorrect input. 3338 */ 3339 cmd_result_t 3340 esw_ser_inject(int unit, args_t *a) { 3341 cmd_result_t rv = CMD_USAGE; 3342 char *mem_name = "", *pipe_name = ""; 3343 int index, tcam_mask, i, idx_phy, xor_bank = 0; 3344 uint32 flags = 0; 3345 soc_block_t block = MEM_BLOCK_ANY; 3346 soc_mem_t mem; 3347 soc_pipe_select_t pipe = 0; 3348 parse_table_t pt; 3349 const char *allowed_pipe_name[] = { 3350 "pipe_x", 3351 "pipe_y", 3352 "pipe0", 3353 "pipe1", 3354 "pipe2", 3355 "pipe3", 3356 "pipe4", 3357 "pipe5", 3358 "pipe6", 3359 "pipe7", 3360 }; 3361 const int pipe_num[] = { 3362 SOC_PIPE_SELECT_X_COMMON, 3363 SOC_PIPE_SELECT_Y_COMMON, 3364 SOC_PIPE_SELECT_0, 3365 SOC_PIPE_SELECT_1, 3366 SOC_PIPE_SELECT_2, 3367 SOC_PIPE_SELECT_3, 3368 SOC_PIPE_SELECT_4, 3369 SOC_PIPE_SELECT_5, 3370 SOC_PIPE_SELECT_6, 3371 SOC_PIPE_SELECT_7, 3372 }; 3373 parse_table_init(unit, &pt); 3374 parse_table_add(&pt, "Memory", PQ_STRING, 3375 SOC_MEM_NAME(unit,INVALIDm), &(mem_name), NULL); 3376 parse_table_add(&pt, "Index", PQ_INT, 3377 (void *)0, &index, NULL); 3378 parse_table_add(&pt, "Pipe", PQ_STRING, 3379 "pipe_x", &(pipe_name), NULL); 3380 parse_table_add(&pt, "TCAM", PQ_BOOL, 3381 FALSE, &(tcam_mask), NULL); 3382 parse_table_add(&pt, "idx_phy", PQ_BOOL, 3383 FALSE, &(idx_phy), NULL); 3384 parse_table_add(&pt, "Xor_bank", PQ_BOOL, 3385 FALSE, &(xor_bank), NULL); 3386 3387 if(parse_arg_eq(a, &pt) < 0) { 3388 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3389 parse_arg_eq_done(&pt); 3390 return rv; 3391 } 3392 3393 if (!(parse_memory_name(unit,&(mem),mem_name,&block,0) >=0)) { 3394 cli_out("Invalid memory selected.\n"); 3395 parse_arg_eq_done(&pt); 3396 return rv; 3397 } 3398 3399 for (i = 0; i < COUNTOF(pipe_num); i++) { 3400 if (!sal_strcasecmp(pipe_name, allowed_pipe_name[i])) { 3401 pipe = pipe_num[i]; 3402 break; 3403 } 3404 } 3405 3406 if (i == COUNTOF(pipe_num)) { 3407 cli_out("Invalid pipe selected. Valid entries are:" 3408 " pipe_x, pipe_y, pipe0, pipe1, pipe2, pipe3" 3409 " pipe4, pipe5, pipe6, pipe7\n"); 3410 parse_arg_eq_done(&pt); 3411 return rv; 3412 } 3413 if (!SOC_SUCCESS(soc_ser_inject_support(unit, mem, pipe))){ 3414 if (soc_ser_inject_support(unit,mem,pipe) == SOC_E_FAIL) { 3415 cli_out("Injection is not supported because miscellaneous" 3416 " initializations have not yet been performed.\n" 3417 "Type 'init misc' to do so and try again.\n"); 3418 } else { 3419 cli_out("The selected memory: %s is valid, but SER correction " 3420 "for it is not currently supported.\n", mem_name); 3421 } 3422 rv = CMD_FAIL; 3423 parse_arg_eq_done(&pt); 3424 return rv; 3425 } 3426 if (index < 0) { 3427 cli_out("Invalid index selected"); 3428 parse_arg_eq_done(&pt); 3429 return rv; 3430 } 3431 if(tcam_mask) { 3432 flags |= SOC_INJECT_ERROR_TCAM_FLAG; 3433 } 3434 if (idx_phy) { 3435 flags |= SOC_INJECT_ERROR_DONT_MAP_INDEX; 3436 } 3437 if (xor_bank) { 3438 flags |= SOC_INJECT_ERROR_XOR_BANK; 3439 } 3440 if (SOC_FAILURE(soc_ser_inject_error(unit, flags, mem, pipe, block, index))) { 3441 cli_out("Injection failed on %s at index %d %s.\n", mem_name, index, 3442 pipe_name); 3443 rv = CMD_FAIL; 3444 } else { 3445 cli_out("Error injected on %s at index %d %s\n", mem_name, index, 3446 pipe_name); 3447 rv = CMD_OK; 3448 } 3449 3450 parse_arg_eq_done(&pt); 3451 return rv; 3452 } 3453 3454 /* 3455 * Function: 3456 * cmd_esw_ser 3457 * Purpose: 3458 * Entry point and argument parser for SER diag shell utilities 3459 * Parameters: 3460 * unit - (IN) Device Number 3461 * a - (IN) A string of user input. Only the first parameter will 3462 * be used by this function. 3463 * Returns: 3464 * CMD_OK if the command succeeds, CMD_USAGE if there is a problem with the 3465 * input from the user. Other returns of type cmd_result_t are possible 3466 * depending on the implementation of each utility. 3467 */ 3468 cmd_result_t 3469 cmd_esw_ser(int unit, args_t *a){ 3470 char* arg1; 3471 int i, log_id = 1; 3472 cmd_result_t rv = CMD_USAGE; 3473 parse_table_t pt; 3474 /* pipe argument is allowed only in multi-pipe devices */ 3475 for (i = 0; i < a->a_argc; i++) { 3476 if (NUM_PIPE(unit) == 1) { 3477 if (sal_strstr(a->a_argv[i], "pipe") != NULL) { 3478 return rv; 3479 } 3480 } 3481 } 3482 arg1 = ARG_GET(a); 3483 if (arg1 != NULL && !sal_strcasecmp(arg1, "inject")) { 3484 rv = esw_ser_inject(unit, a); 3485 } else if (arg1 != NULL && !sal_strcasecmp(arg1, "info")) { 3486 cli_out("Info option not yet implemented\n"); 3487 rv = CMD_NOTIMPL; 3488 } else if (arg1 != NULL && !sal_strcasecmp(arg1, "show")) { 3489 cli_out("Show option not yet implemented\n"); 3490 rv = CMD_NOTIMPL; 3491 } else if (arg1 != NULL && !sal_strcasecmp(arg1, "log")) { 3492 if (ARG_CNT(a) == 0) { 3493 rv = soc_ser_log_print_all(unit); 3494 if (rv != 0) { 3495 cli_out("Error: getting SER log failed %d!\n", rv); 3496 return CMD_USAGE; 3497 } 3498 } else { 3499 parse_table_init(unit, &pt); 3500 parse_table_add(&pt, "ID", PQ_INT, (void *)0, &log_id, NULL); 3501 3502 if (parse_arg_eq(a, &pt) < 0) { 3503 cli_out("%s: Invalid option %s\n", ARG_CMD(a), ARG_CUR(a)); 3504 parse_arg_eq_done(&pt); 3505 return CMD_USAGE; 3506 } 3507 3508 if (log_id < 0) { 3509 cli_out("Invalid id selected!\n"); 3510 parse_arg_eq_done(&pt); 3511 return CMD_USAGE; 3512 } 3513 3514 parse_arg_eq_done(&pt); 3515 3516 rv = soc_ser_log_print_one(unit, log_id); 3517 if (rv != 0) { 3518 cli_out("Error: getting SER log failed %d!\n", rv); 3519 return CMD_USAGE; 3520 } 3521 } 3522 } else { 3523 cli_out("Invalid mode selected.\n"); 3524 } 3525 return rv; 3526 } 3527 3528 #endif /*defined(SER_TR_TEST_SUPPORT)*/ 3529 3530 void mem_watch_counter_init(int unit); 3531 /* 3532 * Function: 3533 * mem_watch_cb 3534 * Purpose: 3535 * Call back function for memory snooping 3536 * Parameters: 3537 * unit - (IN) BCM device number 3538 * mem - (IN) memory for snooping 3539 * flags - (IN) SOC_MEM_SNOOP_XXX flags 3540 * copyno - (IN) Memory block to read/write 3541 * index_min - (IN) First memory index to read/write 3542 * index_max - (IN) Last memory index to read/write 3543 * data_buffer - (IN) buffer of the entry to read/write 3544 * user_data - (IN) registered snooping user data 3545 * Returns: 3546 * No return value 3547 */ 3548 static void 3549 mem_watch_cb(int unit, soc_mem_t mem, uint32 flags, int copyno, int index_min, 3550 int index_max, void *data_buffer, void *user_data) 3551 { 3552 int i; 3553 3554 if (INVALIDm == mem) { 3555 cli_out("Invalid memory....\n"); 3556 return; 3557 } 3558 3559 if (index_max < index_min) { 3560 cli_out("Wrong indexes ....\n"); 3561 return; 3562 } 3563 if (mem_count[unit] == NULL) { 3564 mem_watch_counter_init(unit); 3565 } 3566 3567 if (SOC_MEM_SNOOP_WRITE_COUNT & flags) { 3568 mem_count[unit][mem].wr_count_cur += (index_max - index_min + 1); 3569 } 3570 3571 if (SOC_MEM_SNOOP_READ_COUNT & flags) { 3572 mem_count[unit][mem].rd_count_cur += (index_max - index_min + 1); 3573 } 3574 3575 if ((SOC_MEM_SNOOP_WRITE & flags) 3576 || (SOC_MEM_SNOOP_READ & flags)) { 3577 3578 if (NULL == data_buffer) { 3579 cli_out("Buffer is NULL .... \n"); 3580 return; 3581 } 3582 3583 for (i = 0; i <= (index_max - index_min); i++) { 3584 cli_out("Unit = %d, mem = %s (%d), copyno = %d index = %d, Entry - ", 3585 unit, SOC_MEM_NAME(unit, mem), mem, copyno, i + index_min); 3586 soc_mem_entry_dump(unit,mem, (char *)data_buffer + i, BSL_LSS_CLI); 3587 } 3588 cli_out("\n"); 3589 } 3590 3591 return; 3592 } 3593 3594 /* 3595 * Function: 3596 * mem_watch_counter_init 3597 * Purpose: 3598 * Allocates space and initializes memory counters 3599 * Parameters: 3600 * unit - (IN) BCM device number 3601 * Returns: 3602 * No return value 3603 */ 3604 void 3605 mem_watch_counter_init(int unit) 3606 { 3607 soc_mem_t mem; 3608 3609 mem_count[unit] = (mem_count_t*) sal_alloc(sizeof(mem_count_t) * NUM_SOC_MEM, "mem_count"); 3610 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3611 if (!SOC_MEM_IS_VALID(unit, mem)) { 3612 continue; 3613 } 3614 mem_count[unit][mem].rd_count_old = 0; 3615 mem_count[unit][mem].rd_count_cur = 0; 3616 mem_count[unit][mem].wr_count_old = 0; 3617 mem_count[unit][mem].wr_count_cur = 0; 3618 } 3619 return; 3620 } 3621 3622 /* 3623 * Function: 3624 * mem_watch_snoop_all 3625 * Purpose: 3626 * Registers or unregisters a snooping call back for all memories 3627 * with the specific SOC_MEM_SNOOP_* flags 3628 * Parameters: 3629 * unit - (IN) BCM device number 3630 * flags - (IN) SOC_MEM_SNOOP_* flags 3631 * regist - (IN) register or unregister 3632 * Returns: 3633 * No return value 3634 */ 3635 void 3636 mem_watch_snoop_all(int unit, uint32 flags, int regist) 3637 { 3638 soc_mem_t mem; 3639 3640 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3641 if (!SOC_MEM_IS_VALID(unit, mem)) { 3642 continue; 3643 } 3644 if (regist) { 3645 soc_mem_snoop_register(unit, mem, flags, mem_watch_cb, NULL); 3646 } else { 3647 soc_mem_snoop_unregister(unit, mem, flags); 3648 } 3649 } 3650 return; 3651 } 3652 3653 /* 3654 * Function: 3655 * mem_watch_start 3656 * Purpose: 3657 * Registers a snooping call back for all memories with 3658 * SOC_MEM_SNOOP_READ/WRITE_ALL flags 3659 * Parameters: 3660 * unit - (IN) BCM device number 3661 * Returns: 3662 * No return value 3663 */ 3664 void 3665 mem_watch_start(int unit) 3666 { 3667 soc_mem_t mem; 3668 3669 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3670 if (!SOC_MEM_IS_VALID(unit, mem)) { 3671 continue; 3672 } 3673 soc_mem_snoop_register(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT 3674 | SOC_MEM_SNOOP_READ_COUNT, 3675 mem_watch_cb, NULL); 3676 } 3677 return; 3678 } 3679 3680 /* 3681 * Function: 3682 * mem_watch_stop 3683 * Purpose: 3684 * Reset snooping flags SOC_MEM_SNOOP_READ/WRITE_ALL for all memories 3685 * 3686 * Parameters: 3687 * unit - (IN) BCM device number 3688 * clear - (IN) if TRUE, clear counters 3689 * Returns: 3690 * No return value 3691 */ 3692 static void 3693 mem_watch_stop(int unit, uint8 clear) { 3694 soc_mem_t mem; 3695 3696 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3697 if (!SOC_MEM_IS_VALID(unit, mem)) { 3698 continue; 3699 } 3700 soc_mem_snoop_unregister(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT 3701 | SOC_MEM_SNOOP_READ_COUNT); 3702 if (clear == TRUE) { 3703 mem_count[unit][mem].rd_count_old = 0; 3704 mem_count[unit][mem].rd_count_cur = 0; 3705 mem_count[unit][mem].wr_count_old = 0; 3706 mem_count[unit][mem].wr_count_cur = 0; 3707 } 3708 } 3709 return; 3710 } 3711 3712 /* 3713 * Function: 3714 * mem_watch_show 3715 * Purpose: 3716 * Show memories that have been read/written 3717 * Parameters: 3718 * unit - (IN) BCM device number 3719 * show_type - (IN) config for which type should be showed: 3720 * SOC_MEM_WATCH_SHOW_READ 3721 * SOC_MEM_WATCH_SHOW_WRITE 3722 * SOC_MEM_WATCH_SHOW_READ_WRITE 3723 * show_all - (IN) if TRUE: also show the memories where the delta of 3724 * read/writes is 0 between 2 invocations of the 3725 * command 3726 * Returns: 3727 * No return value 3728 * Notes: 3729 * mem_watch_start() should be called before calling this function 3730 */ 3731 static void 3732 mem_watch_show(int unit, uint32 show_type, uint8 show_all) 3733 { 3734 soc_mem_t mem; 3735 uint32 rd_delta, wr_delta; 3736 3737 mem = -1; 3738 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3739 if (!SOC_MEM_IS_VALID(unit, mem)) { 3740 continue; 3741 } 3742 3743 if (!(SOC_MEM_SNOOP_WRITE_COUNT 3744 & SOC_MEM_INFO(unit, mem).snoop_flags) 3745 || !(SOC_MEM_SNOOP_READ_COUNT 3746 & SOC_MEM_INFO(unit, mem).snoop_flags)) { 3747 cli_out("WARNING: Memory watch not started on %s\n", 3748 SOC_MEM_NAME(unit, mem)); 3749 continue; 3750 } 3751 3752 rd_delta = mem_count[unit][mem].rd_count_cur 3753 - mem_count[unit][mem].rd_count_old; 3754 3755 wr_delta = mem_count[unit][mem].wr_count_cur 3756 - mem_count[unit][mem].wr_count_old; 3757 3758 /* Only show momories that have counter update unless "show all" */ 3759 if (show_all == TRUE 3760 || ((SOC_MEM_WATCH_SHOW_READ & show_type) && (rd_delta != 0)) 3761 || ((SOC_MEM_WATCH_SHOW_WRITE & show_type) && (wr_delta != 0))) 3762 { 3763 cli_out("%s ", SOC_MEM_NAME(unit, mem)); 3764 } 3765 3766 if (SOC_MEM_WATCH_SHOW_READ & show_type) { 3767 if (rd_delta == 0) { 3768 if (show_all == TRUE) { 3769 cli_out("Read count: %u 0 ", 3770 mem_count[unit][mem].rd_count_cur); 3771 } 3772 } else { 3773 cli_out("Read count: %u +%u ", 3774 mem_count[unit][mem].rd_count_cur, rd_delta); 3775 if (mem_count[unit][mem].rd_count_cur 3776 < mem_count[unit][mem].rd_count_old) { 3777 cli_out("(wrap) "); 3778 } 3779 } 3780 3781 if (!(rd_delta == 0 && show_all == FALSE)) { 3782 mem_count[unit][mem].rd_count_old 3783 = mem_count[unit][mem].rd_count_cur; 3784 } 3785 } 3786 3787 if (SOC_MEM_WATCH_SHOW_WRITE & show_type) { 3788 if (wr_delta == 0) { 3789 if (show_all == TRUE) { 3790 cli_out("Write count: %u 0 ", 3791 mem_count[unit][mem].wr_count_cur); 3792 } 3793 } else { 3794 cli_out("Write count: %u +%u ", 3795 mem_count[unit][mem].wr_count_cur, wr_delta); 3796 if (mem_count[unit][mem].wr_count_cur 3797 < mem_count[unit][mem].wr_count_old) { 3798 cli_out("(wrap) "); 3799 } 3800 } 3801 3802 if (!(wr_delta == 0 && show_all == FALSE)) { 3803 mem_count[unit][mem].wr_count_old 3804 = mem_count[unit][mem].wr_count_cur; 3805 } 3806 } 3807 3808 if (show_all == TRUE 3809 || ((SOC_MEM_WATCH_SHOW_READ & show_type) && (rd_delta != 0)) 3810 || ((SOC_MEM_WATCH_SHOW_WRITE & show_type) && (wr_delta != 0))) 3811 { 3812 cli_out("\n"); 3813 } 3814 } 3815 return; 3816 } 3817 3818 static soc_mem_t mem_last=0; 3819 static 3820 int mem_skip(int unit, soc_mem_t mem) 3821 { 3822 if (!soc_mem_is_valid(unit, mem)) { 3823 return 1; 3824 } 3825 #ifdef SABER2_DEBUG 3826 if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_READONLY) != 0) { 3827 /*cli_out("skipping read only memory %s\n", SOC_MEM_NAME(unit,mem));*/ 3828 return 1; 3829 } 3830 if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_WRITEONLY) != 0) { 3831 /*cli_out("skipping write only memory %s\n", SOC_MEM_NAME(unit,mem));*/ 3832 return 1; 3833 } 3834 if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_DEBUG) != 0) { 3835 /*cli_out("skipping debug only memory %s\n", SOC_MEM_NAME(unit,mem));*/ 3836 return 1; 3837 } 3838 if ((soc_mem_flags(unit, mem) & SOC_MEM_FLAG_SIGNAL) != 0) { 3839 /*cli_out("skipping signal only memory %s\n", SOC_MEM_NAME(unit,mem));*/ 3840 return 1; 3841 } 3842 #endif 3843 /* People can add chip specifi memory here */ 3844 if (SOC_IS_SABER2(unit)) { 3845 #ifdef SABER2_DEBUG 3846 switch(mem) { 3847 case IARB_ING_PHYSICAL_PORTm: 3848 return 1; 3849 default: 3850 break; 3851 } 3852 #endif 3853 } 3854 return 0; 3855 } 3856 cmd_result_t 3857 mem_first(int unit, args_t *a) 3858 { 3859 int count=0; 3860 soc_mem_t mem; 3861 for (mem = 0; mem < NUM_SOC_MEM; mem++) { 3862 if (mem_skip(unit, mem)) { 3863 continue; 3864 } 3865 /* cli_out("First Memory: %s \n", SOC_MEM_NAME(unit, mem)); */ 3866 var_set("mem_name", SOC_MEM_NAME(unit,mem), FALSE, FALSE); 3867 var_set(SOC_MEM_NAME(unit,mem),"1", TRUE, FALSE); 3868 mem_last = mem; 3869 count++; 3870 break; 3871 } 3872 for (mem = mem + 1 ; mem < NUM_SOC_MEM; mem++) { 3873 if (mem_skip(unit, mem)) { 3874 continue; 3875 } 3876 /* if Any left !! */ 3877 var_unset(SOC_MEM_NAME(unit,mem),TRUE, FALSE,FALSE); 3878 count++; 3879 } 3880 var_set_integer("mem_count", count, FALSE, FALSE); 3881 return CMD_OK; 3882 } 3883 cmd_result_t 3884 mem_next(int unit, args_t *a) 3885 { 3886 soc_mem_t mem; 3887 3888 var_unset(SOC_MEM_NAME(unit,mem_last),TRUE, FALSE,FALSE); 3889 for (mem = mem_last + 1; mem < NUM_SOC_MEM; mem++) { 3890 if (mem_skip(unit, mem)) { 3891 continue; 3892 } 3893 /* cli_out("Next Memory: %s \n", SOC_MEM_NAME(unit, mem)); */ 3894 var_set("mem_name", SOC_MEM_NAME(unit,mem), FALSE, FALSE); 3895 var_set(SOC_MEM_NAME(unit,mem),"1", TRUE, FALSE); 3896 mem_last = mem; 3897 return CMD_OK; 3898 } 3899 /* Actuall Not Required but better to have it for boundary check */ 3900 var_set("mem_name", "LAST_INVALID_MEMORY", FALSE, FALSE); 3901 return CMD_OK; 3902 } 3903 3904 cmd_result_t 3905 mem_watch(int unit, args_t *a) 3906 { 3907 soc_mem_t mem; 3908 char *c, *memname, *subcmd; 3909 int copyno; 3910 int allmems = 0; 3911 uint32 show_type; 3912 uint8 show_all; 3913 3914 if (!sh_check_attached(ARG_CMD(a), unit)) { 3915 return CMD_FAIL; 3916 } 3917 3918 if (ARG_CNT(a) == 0) { 3919 return CMD_USAGE; 3920 } 3921 3922 if (NULL == (c = ARG_GET(a))) { 3923 return CMD_USAGE; 3924 } 3925 3926 subcmd = c; 3927 3928 if (sal_strcasecmp(subcmd, "start") == 0) { 3929 mem_watch_start(unit); 3930 return CMD_OK; 3931 } 3932 3933 if (sal_strcasecmp(subcmd, "stop") == 0) { 3934 if (NULL == (subcmd = ARG_GET(a))) { 3935 mem_watch_stop(unit, FALSE); 3936 } else if (sal_strcasecmp(subcmd, "clear") == 0) { 3937 mem_watch_stop(unit, TRUE); 3938 } 3939 return CMD_OK; 3940 } 3941 3942 if (sal_strcasecmp(subcmd, "show") == 0) { 3943 if (NULL == (subcmd = ARG_GET(a))) { 3944 /* memwatch show */ 3945 show_type = SOC_MEM_WATCH_SHOW_READ_WRITE; 3946 show_all = FALSE; 3947 } else if (sal_strcasecmp(subcmd, "read") == 0) { 3948 if (NULL == (subcmd = ARG_GET(a))) { 3949 /* memwatch show read */ 3950 show_type = SOC_MEM_WATCH_SHOW_READ; 3951 show_all = FALSE; 3952 } else if (sal_strcasecmp(subcmd, "all") == 0) { 3953 /* memwatch show read all */ 3954 show_type = SOC_MEM_WATCH_SHOW_READ; 3955 show_all = TRUE; 3956 } else { 3957 return CMD_FAIL; 3958 } 3959 } else if (sal_strcasecmp(subcmd, "write") == 0) { 3960 if (NULL == (subcmd = ARG_GET(a))) { 3961 /* memwatch show write */ 3962 show_type = SOC_MEM_WATCH_SHOW_WRITE; 3963 show_all = FALSE; 3964 } else if (sal_strcasecmp(subcmd, "all") == 0) { 3965 /* memwatch show write all */ 3966 show_type = SOC_MEM_WATCH_SHOW_WRITE; 3967 show_all = TRUE; 3968 } else { 3969 return CMD_FAIL; 3970 } 3971 } else if (sal_strcasecmp(subcmd, "all") == 0) { 3972 /* memwatch show all */ 3973 show_type = SOC_MEM_WATCH_SHOW_READ_WRITE; 3974 show_all = TRUE; 3975 } else { 3976 return CMD_FAIL; 3977 } 3978 3979 mem_watch_show(unit, show_type, show_all); 3980 return CMD_OK; 3981 } 3982 3983 if (sal_strcasecmp(c, "*") == 0) { 3984 allmems = 1; 3985 } else { 3986 /* Deal with VIEW:MEMORY if applicable */ 3987 memname = sal_strstr(c, ":"); 3988 if (memname != NULL) { 3989 memname++; 3990 } else { 3991 memname = c; 3992 } 3993 3994 if (sal_strcasecmp(memname, "delta") == 0) { 3995 c = ARG_GET(a); 3996 soc_mem_watch_set(unit, (c && (sal_strcasecmp(c, "on") == 0)) ? 1 : 0); 3997 return CMD_OK; 3998 } 3999 4000 if (parse_memory_name(unit, &mem, memname, ©no, 0) < 0) { 4001 cli_out("ERROR: unknown table \"%s\"\n", c); 4002 return CMD_FAIL; 4003 } 4004 } 4005 4006 if (NULL == (c = ARG_GET(a))) { 4007 return CMD_USAGE; 4008 } 4009 4010 if (sal_strcasecmp(c, "off") == 0) { 4011 /* unregister single read/write call back */ 4012 if (allmems) { 4013 mem_watch_snoop_all(unit, SOC_MEM_SNOOP_READ | SOC_MEM_SNOOP_WRITE, 4014 FALSE); 4015 } else { 4016 soc_mem_snoop_unregister(unit, mem, SOC_MEM_SNOOP_READ 4017 | SOC_MEM_SNOOP_WRITE); 4018 } 4019 } else if (sal_strcasecmp(c, "read") == 0) { 4020 /* register callback with read flag */ 4021 if (allmems) { 4022 mem_watch_snoop_all(unit, SOC_MEM_SNOOP_READ, TRUE); 4023 } else { 4024 soc_mem_snoop_register(unit, mem, SOC_MEM_SNOOP_READ, 4025 mem_watch_cb, NULL); 4026 } 4027 } else if (sal_strcasecmp(c, "write") == 0) { 4028 /* register callback with write flag */ 4029 if (allmems) { 4030 mem_watch_snoop_all(unit, SOC_MEM_SNOOP_WRITE, TRUE); 4031 } else { 4032 soc_mem_snoop_register(unit, mem, SOC_MEM_SNOOP_WRITE, 4033 mem_watch_cb, NULL); 4034 } 4035 } else { 4036 return CMD_USAGE; 4037 } 4038 4039 return CMD_OK; 4040 } 4041