phy.c (405702B)
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 * File: phy.c 8 * Purpose: Functions to support CLI port commands 9 * Requires: 10 */ 11 #include <sal/core/libc.h> 12 #include <sal/types.h> 13 #include <sal/appl/sal.h> 14 #include <sal/appl/io.h> 15 #include <sal/core/libc.h> 16 #include <shared/bsl.h> 17 18 #include <soc/phy.h> 19 #include <soc/phy/phymod_sim.h> 20 #include <soc/eyescan.h> 21 #include <soc/phy/phyctrl.h> 22 23 #include <appl/diag/shell.h> 24 #include <appl/diag/system.h> 25 #include <appl/diag/diag.h> 26 #include <appl/diag/dport.h> 27 28 #ifdef PHYMOD_LINKCAT_SUPPORT 29 #include "include/Blackhawk_LinkCAT_lib.h" 30 #endif /* PHYMOD_LINKCAT_SUPPORT */ 31 32 #if defined(BCM_ESW_SUPPORT) 33 #include <bcm_int/esw/port.h> 34 #endif 35 36 #if defined(PHYMOD_SUPPORT) 37 #include <appl/diag/phymod/phymod_symop.h> 38 #include <soc/phyreg.h> 39 #include <soc/phy/phymod_ctrl.h> 40 #include <phymod/phymod_reg.h> 41 #include <phymod/phymod_debug.h> 42 #include <phymod/phymod_diag.h> 43 #if defined(PORTMOD_SUPPORT) 44 #include <soc/portmod/portmod.h> 45 #include <soc/portmod/portmod_internal.h> 46 #endif 47 #endif 48 #if defined(PORTMOD_SUPPORT) 49 #include <soc/portmod/portmod_common.h> 50 #include <soc/portmod/portmod_chain.h> 51 #endif 52 53 #ifdef SW_AUTONEG_SUPPORT 54 #include <bcm_int/common/sw_an.h> 55 #endif 56 57 #ifdef INCLUDE_PHY_SYM_DBG 58 /* For timebeing adding the headers for socket calls directly */ 59 #include<sys/types.h> 60 #include<sys/socket.h> 61 #include<netinet/in.h> 62 #include<unistd.h> 63 #ifdef VXWORKS 64 #include <vxWorks.h> 65 #include <sockLib.h> 66 #include <selectLib.h> 67 #else 68 #include<sys/select.h> 69 #endif 70 #endif 71 72 #if defined(INCLUDE_PHY_8806X) 73 #include <phy8806x_funcs.h> 74 #include <phy8806x_ctr.h> 75 extern int phy_is_8806x(phy_ctrl_t *pc); 76 #endif 77 78 #if defined(INCLUDE_FCMAP) 79 /* BFCMAP TEST */ 80 #include <bcm/fcmap.h> 81 extern int bfcmap_pcfg_set_get(int port); 82 extern int bfcmap88060_xmod_debug_cmd(int unit, int port, int cmd); 83 int bfcmap88060_show_fc_config(int unit, int port); 84 #endif 85 extern int phy8806x_xmod_debug_cmd(int unit, int port); 86 87 #include <bcm/port.h> 88 #include <bcm/error.h> 89 #include <bcm_int/control.h> 90 91 #if defined(BCM_ESW_SUPPORT) 92 #include <soc/xaui.h> 93 #endif 94 95 #define DUMP_PHY_COLS 4 96 #define PHY_UPDATE(_flags, _control) ((_flags) & (1 << (_control))) 97 #define IS_LONGREACH(_type) (((_type)>=BCM_PORT_PHY_CONTROL_LONGREACH_SPEED) && \ 98 ((_type)<=BCM_PORT_PHY_CONTROL_LONGREACH_ENABLE)) 99 100 /* Note: See port.h, bcm_port_phy_control_t */ 101 char *phy_control[] = { 102 "WAN ", 103 "Preemphasis ", 104 "DriverCurrent ", 105 "PreDriverCurrent ", 106 "EqualizerBoost ", 107 "Interface ", 108 "InterfaceMAX ", 109 "MacsecSwitchFixed ", 110 "MacsecSwitchFixedSpeed ", 111 "MacsecSwitchFixedDuplex ", 112 "MacsecSwitchFixedPause ", 113 "MacsecPauseRxForward ", 114 "MacsecPauseTxForward ", 115 "MacsecLineIPG ", 116 "MacsecSwitchIPG ", 117 "SPeed ", 118 "PAirs ", 119 "GAin ", 120 "AutoNeg ", 121 "LocalAbility ", 122 "RemoteAbility (RO) ", 123 "CurrentAbility (RO) ", 124 "MAster ", 125 "Active (RO) ", 126 "ENable ", 127 "PrePremphasis ", 128 "Encoding ", 129 "Scrambler ", 130 "PrbsPolynomial ", 131 "PrbsTxInvertData ", 132 "PrbsTxEnable ", 133 "PrbsRxEnable ", 134 "PrbsRxStatus ", 135 "SerdesDriverTune ", 136 "SerdesDriverEqualTuneStatus", 137 "8b10b ", 138 NULL 139 }; 140 141 /* Note: See eyescan.h soc_stat_eyscan_counter_e */ 142 char *eyescan_counter[] = { 143 "RelativePhy", "PrbsPhy", "PrbsMac", "CrcMac", "BerMac", "Custom", NULL 144 }; 145 146 147 cmd_result_t 148 port_phy_control_update(int u, bcm_port_t p, bcm_port_phy_control_t type, 149 uint32 val, uint32 flags, int *print_header) 150 { 151 int rv; 152 uint32 oval, flag_bit; 153 char buffer[100]; 154 155 oval = 0; 156 rv = bcm_port_phy_control_get(u, p, type, &oval); 157 if (BCM_FAILURE(rv) && BCM_E_UNAVAIL != rv) { 158 cli_out("%s\n", bcm_errmsg(rv)); 159 return CMD_FAIL; 160 } else if (BCM_SUCCESS(rv)) { 161 switch ( type ) { /* for "phy clock" command */ 162 case BCM_PORT_PHY_CONTROL_CLOCK_ENABLE: 163 flag_bit = 0; 164 break; 165 case BCM_PORT_PHY_CONTROL_CLOCK_SECONDARY_ENABLE: 166 flag_bit = 1; 167 break; 168 case BCM_PORT_PHY_CONTROL_CLOCK_MODE_AUTO: 169 flag_bit = 3; 170 break; 171 case BCM_PORT_PHY_CONTROL_CLOCK_AUTO_SECONDARY: 172 flag_bit = 4; 173 break; 174 case BCM_PORT_PHY_CONTROL_FIRMWARE_DFE_ENABLE: 175 flag_bit = 8; 176 break; 177 case BCM_PORT_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE: 178 flag_bit = 9; 179 break; 180 case BCM_PORT_PHY_CONTROL_FIRMWARE_BR_DFE_ENABLE: 181 flag_bit = 10; 182 break; 183 case BCM_PORT_PHY_CONTROL_CL72: 184 flag_bit = 11; 185 break; 186 default: 187 flag_bit = type; 188 } 189 if ((val != oval) && PHY_UPDATE(flags, flag_bit)) { 190 if (BCM_FAILURE(bcm_port_phy_control_set(u, p, type, val))) { 191 cli_out("%s\n", bcm_errmsg(rv)); 192 return CMD_FAIL; 193 } 194 oval = val; 195 } 196 if (*print_header) { 197 cli_out("Current PHY control settings of %s ->\n", 198 BCM_PORT_NAME(u, p)); 199 *print_header = FALSE; 200 } 201 if (IS_LONGREACH(type)) { 202 switch (type) { 203 case BCM_PORT_PHY_CONTROL_LONGREACH_SPEED: 204 case BCM_PORT_PHY_CONTROL_LONGREACH_PAIRS: 205 case BCM_PORT_PHY_CONTROL_LONGREACH_GAIN: 206 sal_sprintf(buffer, "%d", oval); 207 break; 208 case BCM_PORT_PHY_CONTROL_LONGREACH_LOCAL_ABILITY: 209 case BCM_PORT_PHY_CONTROL_LONGREACH_REMOTE_ABILITY: 210 case BCM_PORT_PHY_CONTROL_LONGREACH_CURRENT_ABILITY: 211 format_phy_control_longreach_ability(buffer, sizeof(buffer), 212 (soc_phy_control_longreach_ability_t) 213 oval); 214 break; 215 case BCM_PORT_PHY_CONTROL_LONGREACH_AUTONEG: 216 case BCM_PORT_PHY_CONTROL_LONGREACH_MASTER: 217 case BCM_PORT_PHY_CONTROL_LONGREACH_ACTIVE: 218 case BCM_PORT_PHY_CONTROL_LONGREACH_ENABLE: 219 sal_sprintf(buffer, "%s", (oval == 1) ? "True" : "False"); 220 break; 221 222 /* coverity[dead_error_begin] */ 223 default: 224 buffer[0] = 0; 225 break; 226 227 } 228 cli_out("%s = %s\n", phy_control[type], buffer); 229 } else if (type == BCM_PORT_PHY_CONTROL_LOOPBACK_EXTERNAL) { 230 cli_out(" ENable = %s\n", (oval == 1) ? "True" : "False"); 231 } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_ENABLE) { 232 cli_out("Extraction to clock out (PRImary) = %s\n", 233 (oval == 1) ? "Enabled" : "Disabled"); 234 } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_SECONDARY_ENABLE) { 235 cli_out("Extraction to clock out (SECondary) = %s\n", 236 (oval == 1) ? "Enabled" : "Disabled"); 237 } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_MODE_AUTO) { 238 cli_out("Recovered clock auto Disable (AutoDisable) = %s\n", 239 (oval == 1) ? "Yes" : "No"); 240 } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_AUTO_SECONDARY) { 241 cli_out("Auto switch to Secondary (AutoSECondary) = %s\n", 242 (oval == 1) ? "Yes" : "No"); 243 } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_SOURCE) { 244 cli_out("Recovery clock is being derived from = %s\n", 245 (oval == bcmPortPhyClockSourcePrimary) ? "PRImary" : "SECondary"); 246 } else if (type == BCM_PORT_PHY_CONTROL_CLOCK_FREQUENCY) { 247 cli_out("Extraction / Input (FR)equency = %d KHz\n", oval); 248 } else if (type == BCM_PORT_PHY_CONTROL_PORT_PRIMARY) { 249 cli_out("(BA)se port of chip = %d\n", oval); 250 } else if (type == BCM_PORT_PHY_CONTROL_PORT_OFFSET) { 251 cli_out("Port (OF)fset within the chip = %d\n", oval); 252 } else if (type == BCM_PORT_PHY_CONTROL_FIRMWARE_DFE_ENABLE) { 253 cli_out("DFE ENable = %s\n", (oval == 1) ? "True" : "False"); 254 } else if (type == BCM_PORT_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE) { 255 cli_out("LP DFE ENable = %s\n", (oval == 1) ? "True" : "False"); 256 } else if (type == BCM_PORT_PHY_CONTROL_FIRMWARE_BR_DFE_ENABLE) { 257 cli_out("BR DFE ENable = %s\n", (oval == 1) ? "True" : "False"); 258 } else if (type == BCM_PORT_PHY_CONTROL_CL72) { 259 cli_out("LinkTraining Enable = %s\n", (oval == 1) ? "True" : "False"); 260 } else { 261 cli_out("%s = 0x%0x\n", phy_control[type], oval); 262 } 263 } 264 return CMD_OK; 265 } 266 267 int 268 port_diag_ctrl(int unit, soc_port_t port, 269 uint32 inst, int op_type, int op_cmd, void *arg) 270 { 271 int rv; 272 #if defined(BCM_ESW_SUPPORT) 273 if(SOC_IS_ESW(unit)) { 274 PORT_LOCK(unit); 275 } 276 #endif 277 { 278 #ifdef PORTMOD_SUPPORT 279 int is_legacy_phy = 0; 280 int dev, is_internal = 0; 281 if (soc_feature(unit, soc_feature_portmod)) { 282 rv = portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_phy); 283 if (rv < 0) { 284 #if defined(BCM_ESW_SUPPORT) 285 if(SOC_IS_ESW(unit)) { 286 PORT_UNLOCK(unit); 287 } 288 #endif 289 return rv; 290 } 291 dev = PHY_DIAG_INST_DEV(inst); 292 if (dev == PHY_DIAG_DEV_DFLT) { 293 is_internal = is_legacy_phy ? 0 : 1; 294 } else if (dev == PHY_DIAG_DEV_INT) { 295 is_internal = 1; 296 } else { 297 is_internal = 0; 298 } 299 300 if (is_internal) { 301 rv = portmod_port_diag_ctrl(unit, port, inst, op_type, op_cmd, arg); 302 } else { 303 if (!is_legacy_phy) { 304 rv = portmod_port_diag_ctrl(unit, port, inst, op_type, op_cmd, arg); 305 } else { 306 rv = soc_phyctrl_diag_ctrl(unit, port, inst, op_type, op_cmd, arg); 307 } 308 } 309 } else 310 #endif 311 { 312 rv = soc_phyctrl_diag_ctrl(unit, port, inst, op_type, op_cmd, arg); 313 } 314 } 315 #if defined(BCM_ESW_SUPPORT) 316 if(SOC_IS_ESW(unit)) { 317 PORT_UNLOCK(unit); 318 } 319 #endif 320 return rv; 321 } 322 323 /* definition for phy low power control command */ 324 typedef struct { 325 bcm_pbmp_t pbm; 326 int registered; 327 } phy_power_ctrl_t; 328 329 static phy_power_ctrl_t phy_pctrl_desc[SOC_MAX_NUM_DEVICES]; 330 331 STATIC void 332 _phy_power_linkscan_cb(int unit, soc_port_t port, bcm_port_info_t *info) 333 { 334 int found = FALSE; 335 soc_port_t p, dport; 336 phy_power_ctrl_t *pDesc; 337 bcm_port_cable_diag_t cds; 338 int rv; 339 340 pDesc = &phy_pctrl_desc[unit]; 341 342 /* coverity[overrun-local] */ 343 DPORT_BCM_PBMP_ITER(unit, pDesc->pbm, dport, p) { 344 if (p == port) { 345 found = TRUE; 346 break; 347 } 348 } 349 350 if (found == TRUE) { 351 if (info->linkstatus == BCM_PORT_LINK_STATUS_UP) { 352 /* link down->up transition */ 353 354 /* Check if giga link */ 355 if (info->speed != 1000) { 356 return; 357 } 358 359 /* Run cable diag if giga link */ 360 sal_memset(&cds, 0, sizeof(bcm_port_cable_diag_t)); 361 rv = bcm_port_cable_diag(unit, p, &cds); 362 if (SOC_FAILURE(rv)) { 363 return; 364 } 365 366 if (cds.pair_len[0] >= 0 && cds.pair_len[0] < 10) { 367 /* Enable low power mode */ 368 (void)bcm_port_phy_control_set(unit, p, 369 BCM_PORT_PHY_CONTROL_POWER, 370 BCM_PORT_PHY_CONTROL_POWER_LOW); 371 } 372 } else { 373 /* link up->down transition */ 374 /* disable low-power mode */ 375 (void)bcm_port_phy_control_set(unit, p, 376 BCM_PORT_PHY_CONTROL_POWER, 377 BCM_PORT_PHY_CONTROL_POWER_FULL); 378 379 } 380 } 381 } 382 383 STATIC int 384 _phy_auto_low_start(int unit, bcm_pbmp_t pbm, int enable) 385 { 386 soc_port_t p, dport; 387 phy_power_ctrl_t *pDesc; 388 389 pDesc = &phy_pctrl_desc[unit]; 390 391 if (enable) { 392 if (!pDesc->registered) { 393 pDesc->pbm = pbm; 394 (void)bcm_linkscan_register(unit, _phy_power_linkscan_cb); 395 pDesc->registered = TRUE; 396 } 397 } else { 398 if (pDesc->registered) { 399 (void)bcm_linkscan_unregister(unit, _phy_power_linkscan_cb); 400 pDesc->registered = FALSE; 401 /* coverity[overrun-local] */ 402 DPORT_BCM_PBMP_ITER(unit, pbm, dport, p) { 403 (void)bcm_port_phy_control_set(unit, p, 404 BCM_PORT_PHY_CONTROL_POWER, 405 BCM_PORT_PHY_CONTROL_POWER_FULL); 406 } 407 } 408 } 409 return SOC_E_NONE; 410 } 411 412 STATIC cmd_result_t 413 _phy_diag_phy_unit_get(int unit_value, int *phy_dev) 414 { 415 *phy_dev = PHY_DIAG_DEV_DFLT; 416 if (unit_value == 0) { /* internal PHY */ 417 *phy_dev = PHY_DIAG_DEV_INT; 418 } else if ((unit_value > 0) && (unit_value < 4)) { 419 *phy_dev = PHY_DIAG_DEV_EXT; 420 } else if (unit_value != -1) { 421 cli_out("unit is numeric value: 0,1,2, ...\n"); 422 return CMD_FAIL; 423 } 424 return CMD_OK; 425 } 426 427 STATIC cmd_result_t 428 _phy_diag_phy_if_get(char *if_str, int *dev_if) 429 { 430 *dev_if = PHY_DIAG_INTF_DFLT; 431 if (if_str) { 432 if (sal_strcasecmp(if_str, "sys") == 0) { 433 *dev_if = PHY_DIAG_INTF_SYS; 434 } else if (sal_strcasecmp(if_str, "line") == 0) { 435 *dev_if = PHY_DIAG_INTF_LINE; 436 } else if (if_str[0] != 0) { 437 cli_out("InterFace must be sys or line.\n"); 438 return CMD_FAIL; 439 } 440 } else { 441 cli_out("Invalid Interface string\n"); 442 return CMD_FAIL; 443 } 444 return CMD_OK; 445 } 446 447 STATIC cmd_result_t 448 _phy_diag_loopback(int unit, bcm_pbmp_t pbmp, args_t *args) 449 { 450 parse_table_t pt; 451 bcm_port_t port, dport; 452 int rv=0; 453 bcm_error_t bcm_res = BCM_E_NONE; 454 cmd_result_t cmd_res = CMD_OK; 455 char *if_str = NULL, *mode_str = NULL; 456 int phy_unit = 0, phy_unit_value = -1, phy_unit_if; 457 int pmd_status = 0, remote_status = 0, internal_status = 0; 458 int mode = 0; 459 uint32 inst; 460 461 parse_table_init(unit, &pt); 462 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 463 &phy_unit_value, NULL); 464 parse_table_add(&pt, "InterFace", PQ_STRING, 0, &if_str, NULL); 465 parse_table_add(&pt, "mode", PQ_STRING, 0, &mode_str, NULL); 466 467 if (parse_arg_eq(args, &pt) < 0) { 468 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 469 parse_arg_eq_done(&pt); 470 return CMD_USAGE; 471 } 472 473 cmd_res = _phy_diag_phy_if_get(if_str, &phy_unit_if); 474 if (cmd_res == CMD_OK) { 475 cmd_res = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 476 } 477 478 if (mode_str && sal_strlen(mode_str)) { 479 if (sal_strcasecmp(mode_str, "remote") == 0) { 480 mode = 1; /* remote loopback */ 481 } else if (sal_strcasecmp(mode_str, "local") == 0) { 482 mode = 2; /* internal loopback */ 483 } else if (sal_strcasecmp(mode_str, "global") == 0) { 484 mode = 3; /* global loopback */ 485 } else if (sal_strcasecmp(mode_str, "none") == 0) { 486 mode = 0; /* no loopback */ 487 } else { 488 cli_out("valid modes: remote,local,global and none\n"); 489 cmd_res = CMD_FAIL; 490 } 491 } else { 492 mode = -1; 493 } 494 /* Now free allocated strings */ 495 parse_arg_eq_done(&pt); 496 497 if (cmd_res != CMD_OK) { 498 return cmd_res; 499 } 500 501 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT); 502 503 /* coverity[overrun-local] */ 504 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 505 506 if (mode > 0) { 507 bcm_res = bcm_port_loopback_set(unit, port, 2); /* PHY */ 508 509 if (bcm_res != BCM_E_NONE) break; 510 511 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT) , 512 PHY_DIAG_CTRL_SET, 513 SOC_PHY_CONTROL_LOOPBACK_INTERNAL, 514 (void *)FALSE); 515 if (bcm_res != BCM_E_NONE) break; 516 } 517 518 switch (mode) { 519 case 3: 520 bcm_res = port_diag_ctrl(unit, port, inst, 521 PHY_DIAG_CTRL_SET, 522 SOC_PHY_CONTROL_LOOPBACK_INTERNAL, 523 (void *)TRUE); 524 break; 525 case 2: 526 bcm_res = port_diag_ctrl(unit, port, inst, 527 PHY_DIAG_CTRL_SET, 528 SOC_PHY_CONTROL_LOOPBACK_PMD, 529 (void *)TRUE); 530 break; 531 case 1: 532 bcm_res = port_diag_ctrl(unit, port, inst, 533 PHY_DIAG_CTRL_SET, 534 SOC_PHY_CONTROL_LOOPBACK_REMOTE, 535 (void *)TRUE); 536 break; 537 538 case 0: 539 bcm_res = bcm_port_loopback_set(unit, port, 0); 540 541 if (bcm_res != BCM_E_NONE) break; 542 543 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT), 544 PHY_DIAG_CTRL_SET, 545 SOC_PHY_CONTROL_LOOPBACK_PMD, 546 (void *)FALSE); 547 if (bcm_res!= BCM_E_NONE) break; 548 549 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT), 550 PHY_DIAG_CTRL_SET, 551 SOC_PHY_CONTROL_LOOPBACK_REMOTE, 552 (void *)FALSE); 553 if (bcm_res != BCM_E_NONE) break; 554 555 556 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT), 557 PHY_DIAG_CTRL_SET, 558 SOC_PHY_CONTROL_LOOPBACK_INTERNAL, 559 (void *)FALSE); 560 if (bcm_res != BCM_E_NONE) break; 561 562 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_SYS, PHY_DIAG_LN_DFLT), 563 PHY_DIAG_CTRL_SET, 564 SOC_PHY_CONTROL_LOOPBACK_PMD, 565 (void *)FALSE); 566 if (bcm_res != BCM_E_NONE) break; 567 568 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_SYS, PHY_DIAG_LN_DFLT), 569 PHY_DIAG_CTRL_SET, 570 SOC_PHY_CONTROL_LOOPBACK_REMOTE, 571 (void *)FALSE); 572 if (bcm_res != BCM_E_NONE) break; 573 574 bcm_res = port_diag_ctrl(unit, port, PHY_DIAG_INSTANCE(phy_unit, PHY_DIAG_INTF_SYS, PHY_DIAG_LN_DFLT), 575 PHY_DIAG_CTRL_SET, 576 SOC_PHY_CONTROL_LOOPBACK_INTERNAL, 577 (void *)FALSE); 578 break; 579 580 581 case -1: 582 default: 583 584 bcm_res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET, 585 SOC_PHY_CONTROL_LOOPBACK_PMD, 586 (void *)&pmd_status); 587 if (bcm_res != BCM_E_NONE) break; 588 589 bcm_res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET, 590 SOC_PHY_CONTROL_LOOPBACK_REMOTE, 591 (void *)&remote_status); 592 if (bcm_res != (int)BCM_E_NONE) break; 593 594 bcm_res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET, 595 SOC_PHY_CONTROL_LOOPBACK_INTERNAL, 596 (void *)&internal_status); 597 if (bcm_res != (int)BCM_E_NONE) break; 598 cli_out("Loopback Status: u=%d p=%d if=%s PMD=%d, PMD_REMOTE=%d, MAC=%d\n", unit, port, 599 (phy_unit_if & 0x1) ? "L" : "S", pmd_status, remote_status, internal_status); 600 } 601 602 } 603 604 if (bcm_res != BCM_E_NONE) { 605 cli_out("Setting loopback failed: %s\n", bcm_errmsg(rv)); 606 return CMD_FAIL; 607 } 608 609 return CMD_OK; 610 } 611 612 STATIC cmd_result_t 613 _phy_diag_dsc(int unit, bcm_pbmp_t pbmp, args_t *args) 614 { 615 parse_table_t pt; 616 bcm_port_t port, dport; 617 bcm_error_t rv = BCM_E_NONE; 618 cmd_result_t cmd_result; 619 620 char *if_str; 621 int phy_unit, phy_unit_value = 0, phy_unit_if; 622 uint32 inst; 623 char *cmd_str = NULL; 624 625 parse_table_init(unit, &pt); 626 627 /* 628 * unit: phy_unit_value: phy chain number 629 * if : if_str="sys"|"line" 630 * 631 * in cases like phy diag xe0 dsc u=1 the string is not specified 632 * Need to handle this case too. 633 */ 634 635 if (args->a_argc > 4) { 636 if (args->a_argv[4] && args->a_argv[4][0] != 'u') { 637 cmd_str = ARG_GET(args); 638 } 639 } 640 641 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 642 &phy_unit_value, NULL); 643 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 644 if (parse_arg_eq(args, &pt) < 0) { 645 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 646 parse_arg_eq_done(&pt); 647 return CMD_USAGE; 648 } 649 650 cmd_result = _phy_diag_phy_if_get(if_str, &phy_unit_if); 651 if (cmd_result == CMD_OK) { 652 cmd_result = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 653 } 654 655 /* Now free allocated strings */ 656 parse_arg_eq_done(&pt); 657 658 if (cmd_result != CMD_OK) { 659 return cmd_result; 660 } 661 662 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT); 663 664 /* coverity[overrun-local] */ 665 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 666 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 667 PHY_DIAG_CTRL_DSC, (void *)cmd_str); 668 if (rv != BCM_E_NONE) { 669 return CMD_FAIL; 670 } 671 } 672 return CMD_OK; 673 } 674 675 cmd_result_t 676 _phy_diag_pcs(int unit, bcm_pbmp_t pbmp, args_t *args) 677 { 678 parse_table_t pt; 679 bcm_port_t port, dport; 680 char *if_str; 681 int phy_unit, phy_unit_value = 0, phy_unit_if; 682 uint32 inst; 683 char *cmd_str; 684 bcm_error_t rv = BCM_E_NONE; 685 cmd_result_t cmd_result; 686 687 cmd_str = ARG_GET(args); 688 689 parse_table_init(unit, &pt); 690 691 /* 692 * unit: phy_unit_value: phy chain number 693 * if : if_str="sys"|"line" 694 */ 695 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 696 &phy_unit_value, NULL); 697 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 698 if (parse_arg_eq(args, &pt) < 0) { 699 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 700 parse_arg_eq_done(&pt); 701 return CMD_USAGE; 702 } 703 704 cmd_result = _phy_diag_phy_if_get(if_str, &phy_unit_if); 705 if (cmd_result == CMD_OK) { 706 cmd_result = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 707 } 708 709 710 /* Now free allocated strings */ 711 parse_arg_eq_done(&pt); 712 713 if (cmd_result != CMD_OK) { 714 return cmd_result; 715 } 716 717 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT); 718 719 /* coverity[overrun-local] */ 720 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 721 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 722 PHY_DIAG_CTRL_PCS, (void *)cmd_str); 723 /* coverity[mixed_enums] */ 724 if (rv != BCM_E_NONE) { 725 return CMD_FAIL; 726 } 727 } 728 return CMD_OK; 729 } 730 731 #ifdef PHYMOD_LINKCAT_SUPPORT 732 STATIC cmd_result_t 733 _phy_diag_linkcat(int unit, bcm_pbmp_t pbmp, args_t *args) 734 { 735 parse_table_t pt; 736 bcm_port_t port, dport; 737 int lane; /* lane number specified on command line */ 738 char *mode = NULL; 739 int mode_val = LINKCAT_LPBK_MODE; /* mode specified on command line. Default to lpbk */ 740 phymod_dispatch_type_t type = phymodDispatchTypeCount; 741 phymod_access_t phy_acc; 742 int num_lanes; 743 int first_bit, mask; 744 linkcat_config linkcat_config; 745 linkcat_returns linkcat_status; 746 char *prefix = NULL; 747 char prefix_str[50]; 748 749 750 if ( args->a_argc < 5) { 751 return CMD_USAGE; 752 } 753 parse_table_init(unit, &pt); 754 parse_table_add(&pt, "lane", PQ_INT, 755 (void *)(0), &lane, NULL); 756 parse_table_add(&pt, "mode", PQ_DFL | PQ_STRING, 757 (void *)(0), &mode, NULL); 758 parse_table_add(&pt, "prefix", PQ_DFL | PQ_STRING, 759 (void *)(0), &prefix, NULL); 760 if ( parse_arg_eq(args, &pt) < 0) { 761 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 762 parse_arg_eq_done(&pt); 763 return CMD_USAGE; 764 } 765 766 if ( mode != NULL ) { 767 if ( !sal_strcasecmp(mode, "tx") ) { 768 mode_val = LINKCAT_LPTX_MODE; 769 } else if ( !sal_strcasecmp(mode, "rx") ) { 770 mode_val = LINKCAT_RX_MODE; 771 } else if ( !sal_strcasecmp(mode, "lpbk") ) { 772 mode_val = LINKCAT_LPBK_MODE; 773 } else { 774 cli_out("Invalid mode parameter %s\n", mode); 775 return CMD_OK; 776 } 777 } 778 sal_memset(prefix_str, 0, 50); 779 if ( prefix != NULL ) { 780 sal_strncpy(prefix_str, prefix, 49); 781 } 782 783 parse_arg_eq_done(&pt); 784 785 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 786 sal_memset(&phy_acc, 0, sizeof(phymod_access_t)); 787 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 788 789 if(soc_feature(unit, soc_feature_portmod)) { 790 #ifdef PORTMOD_SUPPORT 791 portmod_access_get_params_t params; 792 phymod_core_access_t internal_core; 793 phymod_phy_access_t access; 794 int nof_phys, is_most_ext, max_phys = 1, nof_cores = 0; 795 796 phymod_core_access_t_init(&internal_core); 797 portmod_port_main_core_access_get(unit, port, 0, &internal_core, &nof_cores); 798 if(nof_cores == 0) { 799 continue; 800 } 801 sal_memcpy(&phy_acc, &internal_core.access, sizeof(phymod_access_t)); 802 type = internal_core.type; 803 804 params.phyn = 0; /* internal PHY */ 805 params.sys_side = PORTMOD_SIDE_LINE; 806 params.lane = -1; /* request all lanes */ 807 params.apply_lane_mask = 0; 808 809 portmod_port_phy_lane_access_get(unit, port, ¶ms, max_phys, &access, &nof_phys, &is_most_ext); 810 phy_acc.lane_mask = access.access.lane_mask; 811 812 } else 813 #endif /* PORTMOD_SUPPORT */ 814 { 815 phy_ctrl_t *pc; 816 pc = INT_PHY_SW_STATE(unit, port); 817 if (pc == NULL) { 818 continue; 819 } 820 sal_memcpy(&phy_acc, &pc->phymod_ctrl.phy[0]->pm_phy.access, sizeof(phymod_access_t)); 821 type = pc->phymod_ctrl.phy[0]->pm_phy.type; 822 } 823 824 if ( phy_acc.bus == NULL || !phy_acc.addr || !phy_acc.lane_mask ) { 825 cli_out("\nERROR: Unable to obtain PM core information for port %d\n. Command terminated", port); 826 return CMD_OK; 827 } 828 829 if ( lane >= num_lanes ) { 830 cli_out("\nInvalid lane number %d. Port %d has only %d lanes (0x%x)\n", lane, port, num_lanes, phy_acc.lane_mask); 831 return CMD_OK; 832 } 833 834 mask = 0x1; 835 for(first_bit = 0; first_bit < 32; first_bit++) { 836 if ( (phy_acc.lane_mask & mask) ) { 837 phy_acc.lane_mask = 1 << ( first_bit + lane ); 838 break; 839 } 840 mask = mask << 1; 841 } 842 linkcat_status.insertion_loss = 0.0; 843 linkcat_status.fit_factor = 0.0; 844 linkcat_config.mode = mode_val; 845 linkcat_config.portaddress = phy_acc.addr; 846 linkcat_config.dir_name = NULL; 847 linkcat_config.file_prefix = prefix_str; 848 849 switch(type) { 850 case phymodDispatchTypeBlackhawk: 851 case phymodDispatchTypeTscbh: 852 cli_out("Running linkCAT on addr=0x%x lane_mask=0x%x mode=%d\n", phy_acc.addr, phy_acc.lane_mask, mode_val); 853 blackhawk_tsc_LinkCat(&phy_acc, &linkcat_config, &linkcat_status); 854 break; 855 default: 856 cli_out("\nThis utility supports only PM8x50\n"); 857 return CMD_OK; 858 } 859 } 860 return CMD_OK; 861 } 862 #endif /* PHYMOD_LINKCAT_SUPPORT */ 863 864 STATIC cmd_result_t 865 _phy_diag_prbs(int unit, bcm_pbmp_t pbmp, args_t *args) 866 { 867 parse_table_t pt; 868 bcm_port_t port, dport; 869 int rv, cmd, enable; 870 char *cmd_str, *if_str, *poly_str=NULL; 871 int poly = 0, invert = 0, max_poly_index = 0; 872 int phy_unit, phy_unit_value = -1, phy_unit_if; 873 uint32 inst; 874 875 enum { _PHY_PRBS_SET_CMD, _PHY_PRBS_GET_CMD, _PHY_PRBS_CLEAR_CMD }; 876 enum { _PHY_PRBS_SI_MODE, _PHY_PRBS_HC_MODE }; 877 878 if ((cmd_str = ARG_GET(args)) == NULL) { 879 return CMD_USAGE; 880 } 881 if (sal_strcasecmp(cmd_str, "set") == 0) { 882 cmd = _PHY_PRBS_SET_CMD; 883 enable = 1; 884 } else if (sal_strcasecmp(cmd_str, "get") == 0) { 885 cmd = _PHY_PRBS_GET_CMD; 886 enable = 0; 887 } else if (sal_strcasecmp(cmd_str, "clear") == 0) { 888 cmd = _PHY_PRBS_CLEAR_CMD; 889 enable = 0; 890 } else 891 return CMD_USAGE; 892 893 parse_table_init(unit, &pt); 894 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 895 &phy_unit_value, NULL); 896 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 897 if (cmd == _PHY_PRBS_SET_CMD) { 898 parse_table_add(&pt, "Polynomial", PQ_DFL | PQ_STRING, 899 (void *)(0), &poly_str, NULL); 900 parse_table_add(&pt, "Invert", PQ_DFL | PQ_INT, 901 (void *)(0), &invert, NULL); 902 } 903 if (parse_arg_eq(args, &pt) < 0) { 904 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 905 parse_arg_eq_done(&pt); 906 return CMD_USAGE; 907 } 908 909 if ( poly_str ) { 910 if ( !sal_strcasecmp(poly_str, "P7") || !sal_strcasecmp(poly_str, "0")) { 911 poly = 0; 912 } else if (!sal_strcasecmp(poly_str, "P15") || !sal_strcasecmp(poly_str, "1") ) { 913 poly = 1; 914 } else if (!sal_strcasecmp(poly_str, "P23") || !sal_strcasecmp(poly_str, "2") ) { 915 poly = 2; 916 } else if (!sal_strcasecmp(poly_str, "P31") || !sal_strcasecmp(poly_str, "3") ) { 917 poly = 3; 918 } else if (!sal_strcasecmp(poly_str, "P9") || !sal_strcasecmp(poly_str, "4")) { 919 poly = 4; 920 } else if (!sal_strcasecmp(poly_str, "P11") || !sal_strcasecmp(poly_str, "5") ) { 921 poly = 5; 922 } else if (!sal_strcasecmp(poly_str, "P58") || !sal_strcasecmp(poly_str, "6")) { 923 poly = 6; 924 #ifdef BCM_TOMAHAWK3_SUPPORT 925 } else if (SOC_IS_TOMAHAWK3(unit)) { 926 if (!sal_strcasecmp(poly_str, "P49") || !sal_strcasecmp(poly_str, "7")) { 927 poly = 7; 928 } else if (!sal_strcasecmp(poly_str, "P20") || !sal_strcasecmp(poly_str, "8")) { 929 poly = 8; 930 } else if (!sal_strcasecmp(poly_str, "P13") || !sal_strcasecmp(poly_str, "9")) { 931 poly = 9; 932 } else if (!sal_strcasecmp(poly_str, "P10") || !sal_strcasecmp(poly_str, "10")) { 933 poly = 10; 934 } else { 935 cli_out("Prbs p must be P7(0), P15(1), P23(2), P31(3), P9(4), P11(5), P58(6), P49(7), P20(8), P13(9), or P10(10)\n"); 936 return CMD_FAIL; 937 } 938 #endif /* BCM_TOMAHAWK3_SUPPORT */ 939 } else { 940 cli_out("Prbs p must be P7(0), P15(1), P23(2), P31(3), P9(4), P11(5), or P58(6).\n"); 941 return CMD_FAIL; 942 } 943 } 944 945 rv = (int)_phy_diag_phy_if_get(if_str, &phy_unit_if); 946 if (rv == ((int)CMD_OK)) { 947 rv = (int)_phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 948 } 949 950 /* Now free allocated strings */ 951 parse_arg_eq_done(&pt); 952 953 if (rv != CMD_OK) { 954 return rv; 955 } 956 957 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT); 958 959 /* coverity[overrun-local] */ 960 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 961 if (cmd == _PHY_PRBS_SET_CMD || cmd == _PHY_PRBS_CLEAR_CMD) { 962 max_poly_index = 6; 963 #ifdef BCM_TOMAHAWK3_SUPPORT 964 if (SOC_IS_TOMAHAWK3(unit)) { 965 max_poly_index = 10; 966 } 967 #endif /* BCM_TOMAHAWK3_SUPPORT */ 968 if (poly >= 0 && poly <= max_poly_index) { 969 /* Set polynomial */ 970 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET, 971 SOC_PHY_CONTROL_PRBS_POLYNOMIAL, 972 INT_TO_PTR(poly)); 973 if (rv != ((int)BCM_E_NONE)) { 974 cli_out("Setting prbs polynomial failed: %s\n", 975 bcm_errmsg(rv)); 976 return CMD_FAIL; 977 } 978 } else { 979 cli_out("Polynomial must be 0..%d.\n", max_poly_index); 980 return CMD_FAIL; 981 } 982 983 /* Set invert */ 984 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET, 985 SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA, 986 INT_TO_PTR(invert)); 987 if (rv != ((int)BCM_E_NONE)) { 988 cli_out("Setting prbs invertion failed: %s\n", bcm_errmsg(rv)); 989 return CMD_FAIL; 990 } 991 992 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET, 993 SOC_PHY_CONTROL_PRBS_TX_ENABLE, 994 INT_TO_PTR(enable)); 995 if (rv != ((int)BCM_E_NONE)) { 996 cli_out("Setting prbs tx enable failed: %s\n", bcm_errmsg(rv)); 997 return CMD_FAIL; 998 } 999 1000 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_SET, 1001 SOC_PHY_CONTROL_PRBS_RX_ENABLE, 1002 INT_TO_PTR(enable)); 1003 if (rv != ((int)BCM_E_NONE)) { 1004 cli_out("Setting prbs rx enable failed: %s\n", bcm_errmsg(rv)); 1005 return CMD_FAIL; 1006 } 1007 } else { /* _PHY_PRBS_GET_CMD */ 1008 int status; 1009 1010 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_GET, 1011 SOC_PHY_CONTROL_PRBS_RX_STATUS, 1012 (void *)&status); 1013 if (rv != ((int)BCM_E_NONE)) { 1014 cli_out("Getting prbs rx status failed: %s\n", bcm_errmsg(rv)); 1015 return CMD_FAIL; 1016 } 1017 1018 switch (status) { 1019 case 0: 1020 cli_out("%s (%2d): PRBS OK!\n", BCM_PORT_NAME(unit, port), 1021 port); 1022 break; 1023 case -1: 1024 cli_out("%s (%2d): PRBS Failed!\n", 1025 BCM_PORT_NAME(unit, port), port); 1026 break; 1027 default: 1028 cli_out("%s (%2d): PRBS has %d errors!\n", 1029 BCM_PORT_NAME(unit, port), port, status); 1030 break; 1031 } 1032 } 1033 } 1034 return CMD_OK; 1035 } 1036 1037 STATIC cmd_result_t 1038 _phy_diag_mfg(int unit, bcm_pbmp_t pbmp, args_t *args) 1039 { 1040 #ifndef NO_FILEIO 1041 parse_table_t pt; 1042 bcm_port_t port, dport; 1043 int rv, i, data_len = 0; 1044 char *file_name = NULL, *buffer = NULL, *buf_ptr = NULL, *dptr; 1045 int test, test_cmd = 0, num_ports, data; 1046 FILE *ofp = NULL; 1047 1048 parse_table_init(unit, &pt); 1049 parse_table_add(&pt, "Test", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &test, 0); 1050 parse_table_add(&pt, "Data", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &data, 0); 1051 parse_table_add(&pt, "File", PQ_STRING, 0, &file_name, NULL); 1052 1053 if (parse_arg_eq(args, &pt) < 0) { 1054 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 1055 parse_arg_eq_done(&pt); 1056 return CMD_USAGE; 1057 } 1058 1059 switch (test) { 1060 case 1: 1061 test_cmd = PHY_DIAG_CTRL_MFG_HYB_CANC; 1062 data_len = 770 * 4; 1063 break; 1064 case 2: 1065 test_cmd = PHY_DIAG_CTRL_MFG_DENC; 1066 data_len = 44 * 4; 1067 break; 1068 case 3: 1069 test_cmd = PHY_DIAG_CTRL_MFG_TX_ON; 1070 break; 1071 case 0: 1072 test_cmd = PHY_DIAG_CTRL_MFG_EXIT; 1073 break; 1074 default: 1075 cli_out("Test should be : 1 (HYB_CANC), 2 (DENC), " 1076 "3 (TX_ON) or 0 (EXIT)\n"); 1077 parse_arg_eq_done(&pt); 1078 return CMD_FAIL; 1079 break; 1080 } 1081 1082 if (data_len) { 1083 if ((ofp = sal_fopen(file_name, "w")) == NULL) { 1084 cli_out("ERROR: Can't open the file : %s (for write)\n", file_name); 1085 parse_arg_eq_done(&pt); 1086 return CMD_FAIL; 1087 } 1088 switch (test) { 1089 case 1: 1090 sal_fprintf(ofp, "PHY_DIAG_CTRL_MFG_HYB_CANC\n"); 1091 break; 1092 case 2: 1093 sal_fprintf(ofp, "PHY_DIAG_CTRL_MFG_DENC\n"); 1094 break; 1095 } 1096 } 1097 1098 /* Now free allocated strings */ 1099 parse_arg_eq_done(&pt); 1100 1101 num_ports = 0; 1102 /* coverity[overrun-local] */ 1103 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1104 rv = port_diag_ctrl(unit, port, 0, 1105 PHY_DIAG_CTRL_SET, test_cmd, 1106 INT_TO_PTR(data)); 1107 if (rv != SOC_E_NONE) { 1108 cli_out("Error: PHY_DIAG_CTRL_SET u=%d p=%d test_cmd=%d\n", unit, 1109 port, test_cmd); 1110 } 1111 num_ports++; 1112 } 1113 1114 /* every port has an extra 32 bit scratch pad */ 1115 buffer = sal_alloc(num_ports * (data_len + 32), "mfg_test_results"); 1116 if (buffer == NULL) { 1117 cli_out("Insufficient memory.\n"); 1118 if (ofp) { 1119 sal_fclose(ofp); 1120 } 1121 return CMD_FAIL; 1122 } 1123 buf_ptr = buffer; 1124 1125 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1126 buf_ptr[0] = 0; 1127 rv = port_diag_ctrl(unit, port, 0, 1128 PHY_DIAG_CTRL_GET, test_cmd, 1129 (void *)(buf_ptr + 32)); 1130 if (rv != SOC_E_NONE) { 1131 cli_out("Error: PHY_DIAG_CTRL_GET u=%d p=%d test_cmd=%d\n", unit, 1132 port, test_cmd); 1133 } else { 1134 buf_ptr[0] = -1; /* indicates that the test result is valid */ 1135 } 1136 buf_ptr += (data_len + 32); 1137 } 1138 1139 if (data_len) { 1140 buf_ptr = buffer; 1141 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1142 i = 0; 1143 dptr = buf_ptr + 32; 1144 if (buf_ptr[0]) { 1145 sal_fprintf(ofp, "\n\nOutput data for port %s\n", 1146 BCM_PORT_NAME(unit, port)); 1147 while (i < data_len) { 1148 if ((i & 0x1f) == 0) { /* i % 32 */ 1149 sal_fprintf(ofp, "\n"); 1150 } 1151 /* data in ARM memory is big endian (network byte order) */ 1152 sal_fprintf(ofp, "0x%08x", soc_ntohl_load(dptr)); 1153 dptr += 4; 1154 i += 4; 1155 if (i >= data_len) { 1156 sal_fprintf(ofp, "\n"); 1157 break; 1158 } else { 1159 sal_fprintf(ofp, ", "); 1160 } 1161 } 1162 } else { 1163 sal_fprintf(ofp, "\n\nTest failed for port %s\n", 1164 BCM_PORT_NAME(unit, port)); 1165 } 1166 buf_ptr += (data_len + 32); 1167 } 1168 } 1169 1170 if (ofp) { 1171 sal_fclose(ofp); 1172 } 1173 sal_free(buffer); 1174 1175 return CMD_OK; 1176 #else 1177 cli_out("This command is not supported without file I/O\n"); 1178 return CMD_FAIL; 1179 #endif 1180 } 1181 1182 STATIC cmd_result_t 1183 _phy_diag_state(int unit, bcm_pbmp_t pbmp, args_t *args) 1184 { 1185 #ifndef NO_FILEIO 1186 parse_table_t pt; 1187 bcm_port_t port, dport; 1188 int rv, i, data_len = 0; 1189 char *file_name = NULL, *buffer = NULL, *buf_ptr = NULL, *dptr; 1190 XGPHY_DIAG_DATA_t *diag_dptr; 1191 int test, test_cmd = 0, num_ports, data; 1192 FILE *ofp = NULL; 1193 1194 parse_table_init(unit, &pt); 1195 parse_table_add(&pt, "Test", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &test, 0); 1196 parse_table_add(&pt, "Data", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 0, &data, 0); 1197 parse_table_add(&pt, "File", PQ_STRING, 0, &file_name, NULL); 1198 1199 if (parse_arg_eq(args, &pt) < 0) { 1200 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 1201 parse_arg_eq_done(&pt); 1202 return CMD_USAGE; 1203 } 1204 1205 switch (test) { 1206 case 1: 1207 test_cmd = PHY_DIAG_CTRL_STATE_TRACE1; 1208 data_len = 2048 * 4; 1209 break; 1210 case 2: 1211 test_cmd = PHY_DIAG_CTRL_STATE_TRACE2; 1212 data_len = 1024 * 4; 1213 break; 1214 case 3: 1215 test_cmd = PHY_DIAG_CTRL_STATE_WHEREAMI; 1216 data_len = sizeof(XGPHY_DIAG_DATA_t); 1217 break; 1218 case 4: 1219 test_cmd = PHY_DIAG_CTRL_STATE_TEMP; 1220 data_len = sizeof(XGPHY_DIAG_DATA_t); 1221 break; 1222 case 5: 1223 test_cmd = PHY_DIAG_CTRL_STATE_GENERIC; 1224 break; 1225 default: 1226 cli_out("Test should be : 1 (STATE_TRACE1), 2 (STATE_TRACE2), " 1227 "3 (WHERE_AM_I), 4 (TEMP)\n"); 1228 parse_arg_eq_done(&pt); 1229 return CMD_FAIL; 1230 break; 1231 } 1232 1233 if (data_len) { 1234 if ((ofp = sal_fopen(file_name, "a+")) == NULL) { 1235 cli_out("ERROR: Can't open the file : %s\n", file_name); 1236 parse_arg_eq_done(&pt); 1237 return CMD_FAIL; 1238 } 1239 sal_fprintf(ofp, 1240 "\n-------------------------------------------------------" 1241 "------------------------------------------------------\n"); 1242 switch (test) { 1243 case 1: 1244 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_TRACE1\n"); 1245 break; 1246 case 2: 1247 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_TRACE2\n"); 1248 break; 1249 case 3: 1250 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_WHERE_AM_I\n"); 1251 break; 1252 case 4: 1253 sal_fprintf(ofp, "PHY_DIAG_CTRL_STATE_TEMP\n"); 1254 break; 1255 } 1256 } 1257 1258 /* Now free allocated strings */ 1259 parse_arg_eq_done(&pt); 1260 1261 num_ports = 0; 1262 /* coverity[overrun-local] */ 1263 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1264 rv = port_diag_ctrl(unit, port, 0, 1265 PHY_DIAG_CTRL_SET, test_cmd, 1266 INT_TO_PTR(data)); 1267 if (rv != SOC_E_NONE) { 1268 cli_out("Error: PHY_DIAG_CTRL_SET u=%d p=%d test_cmd=%d\n", unit, 1269 port, test_cmd); 1270 } 1271 num_ports++; 1272 } 1273 1274 /* every port has an extra 32 bit scratch pad */ 1275 buffer = sal_alloc(num_ports * (data_len + 32), "state_test_results"); 1276 if (buffer == NULL) { 1277 cli_out("Insufficient memory.\n"); 1278 if (ofp) { 1279 sal_fclose(ofp); 1280 } 1281 return CMD_FAIL; 1282 } 1283 buf_ptr = buffer; 1284 1285 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1286 buf_ptr[0] = 0; 1287 rv = port_diag_ctrl(unit, port, 0, 1288 PHY_DIAG_CTRL_GET, test_cmd, 1289 (void *)(buf_ptr + 32)); 1290 if (rv != SOC_E_NONE) { 1291 cli_out("Error: PHY_DIAG_CTRL_GET u=%d p=%d test_cmd=%d\n", unit, 1292 port, test_cmd); 1293 } else { 1294 buf_ptr[0] = -1; /* indicates that the test result is valid */ 1295 } 1296 buf_ptr += (data_len + 32); 1297 } 1298 1299 if (data_len) { 1300 buf_ptr = buffer; 1301 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1302 i = 0; 1303 dptr = buf_ptr + 32; 1304 diag_dptr = (XGPHY_DIAG_DATA_t *) dptr; 1305 1306 if (buf_ptr[0]) { 1307 sal_fprintf(ofp, "\n\nOutput data for port %s\n", 1308 BCM_PORT_NAME(unit, port)); 1309 if (test_cmd == PHY_DIAG_CTRL_STATE_WHEREAMI) { 1310 int32 valA, valB, valC, valD, statA, statB, statC, statD; 1311 1312 if (diag_dptr->flags & PHY_DIAG_FULL_SNR_SUPPORT) { 1313 valA = 1314 soc_letohl_load(&diag_dptr->snr_block[16]) - 32768; 1315 valB = 1316 soc_letohl_load(&diag_dptr->snr_block[20]) - 32768; 1317 valC = 1318 soc_letohl_load(&diag_dptr->snr_block[24]) - 32768; 1319 valD = 1320 soc_letohl_load(&diag_dptr->snr_block[28]) - 32768; 1321 1322 statA = soc_letohl_load(&diag_dptr->snr_block[0]); 1323 statB = soc_letohl_load(&diag_dptr->snr_block[4]); 1324 statC = soc_letohl_load(&diag_dptr->snr_block[8]); 1325 statD = soc_letohl_load(&diag_dptr->snr_block[12]); 1326 1327 sal_fprintf(ofp, 1328 "\nsnrA = %d.%d (%s) snrB = %d.%d (%s) " 1329 "snrC = %d.%d (%s) snrD = %d.%d (%s) " 1330 "serr = %d cerr = %d block_lock = %d " 1331 "block_point_id = %d\n", 1332 valA / 10, valA % 10, 1333 statA ? "OK" : "Not OK", valB / 10, 1334 valB % 10, statB ? "OK" : "Not OK", 1335 valC / 10, valC % 10, 1336 statC ? "OK" : "Not OK", valD / 10, 1337 valD % 10, statD ? "OK" : "Not OK", 1338 diag_dptr->serr, diag_dptr->cerr, 1339 diag_dptr->block_lock, 1340 diag_dptr->block_point_id); 1341 1342 } else { 1343 valA = soc_letohl_load(&diag_dptr->snr_block[0]); 1344 valB = soc_letohl_load(&diag_dptr->snr_block[4]); 1345 valC = soc_letohl_load(&diag_dptr->snr_block[8]); 1346 valD = soc_letohl_load(&diag_dptr->snr_block[12]); 1347 1348 sal_fprintf(ofp, 1349 "\nmseA = %d mseB = %d mseC = %d mseD = %d " 1350 "serr = %d cerr = %d block_lock = 0x%x " 1351 "block_point_id = 0x%x\n", 1352 valA, valB, valC, valD, diag_dptr->serr, 1353 diag_dptr->cerr, diag_dptr->block_lock, 1354 diag_dptr->block_point_id); 1355 } 1356 } else if (test_cmd == PHY_DIAG_CTRL_STATE_TEMP) { 1357 sal_fprintf(ofp, "\nTemperature = %d C, %d F\n", 1358 diag_dptr->digital_temp, 1359 (diag_dptr->digital_temp * 9) / 5 + 32); 1360 } else { 1361 while (i < data_len) { 1362 if ((i & 0x1f) == 0) { /* i % 32 */ 1363 sal_fprintf(ofp, "\n"); 1364 } 1365 sal_fprintf(ofp, "0x%08x", soc_letohl_load(&dptr[0])); 1366 dptr += 4; 1367 i += 4; 1368 if (i >= data_len) { 1369 sal_fprintf(ofp, "\n"); 1370 break; 1371 } else { 1372 sal_fprintf(ofp, ", "); 1373 } 1374 } 1375 } 1376 } else { 1377 sal_fprintf(ofp, "\n\nTest failed for port %s\n", 1378 BCM_PORT_NAME(unit, port)); 1379 } 1380 buf_ptr += (data_len + 32); 1381 } 1382 } 1383 1384 if (ofp) { 1385 sal_fclose(ofp); 1386 } 1387 sal_free(buffer); 1388 1389 return CMD_OK; 1390 #else 1391 cli_out("This command is not supported without file I/O\n"); 1392 return CMD_FAIL; 1393 #endif 1394 } 1395 1396 STATIC cmd_result_t 1397 _phy_diag_fast_eyescan(int unit, bcm_pbmp_t pbmp, args_t *args) 1398 { 1399 parse_table_t pt; 1400 bcm_port_t port, dport; 1401 int rv=0,res=0; 1402 char *if_str; 1403 int phy_unit = 0, phy_unit_value = 0, phy_unit_if = 0; 1404 int lane_num = 0; 1405 uint32 inst; 1406 1407 parse_table_init(unit, &pt); 1408 1409 /* 1410 * unit: phy_unit_value: phy chain number 1411 * if : if_str="sys"|"line" 1412 */ 1413 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 1414 &phy_unit_value, NULL); 1415 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 1416 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), &lane_num, NULL); 1417 1418 if (parse_arg_eq(args, &pt) < 0) { 1419 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 1420 parse_arg_eq_done(&pt); 1421 return CMD_USAGE; 1422 } 1423 1424 rv = _phy_diag_phy_if_get(if_str, &phy_unit_if); 1425 if (rv == CMD_OK) { 1426 rv = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 1427 } 1428 1429 /* Now free allocated strings */ 1430 parse_arg_eq_done(&pt); 1431 1432 if (rv != CMD_OK) { 1433 return rv; 1434 } 1435 1436 inst = 1437 PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, 1438 (lane_num == 0xff) ? PHY_DIAG_LN_DFLT : lane_num); 1439 1440 /* coverity[overrun-local] */ 1441 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1442 res = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 1443 PHY_DIAG_CTRL_START_FAST_EYESCAN, (void *)0); 1444 if (res != BCM_E_NONE) { 1445 return CMD_FAIL; 1446 } 1447 } 1448 return CMD_OK; 1449 } 1450 1451 STATIC cmd_result_t 1452 _phy_diag_link_mon(int unit, bcm_pbmp_t pbmp, args_t *args) 1453 { 1454 parse_table_t pt; 1455 bcm_port_t port, dport; 1456 int rv; 1457 char *cmd_str, *if_str; 1458 int phy_unit = 0, phy_unit_value = 0, phy_unit_if = 0; 1459 int lane_num = 0; 1460 uint32 link_mon_mode = 0, cmd; 1461 uint32 inst; 1462 1463 enum { _PHY_LINKMON_SET_CMD, _PHY_LINKMON_GET_CMD}; 1464 parse_table_init(unit, &pt); 1465 1466 if ((cmd_str = ARG_GET(args)) == NULL) { 1467 return CMD_USAGE; 1468 } 1469 if (sal_strcasecmp(cmd_str, "set") == 0) { 1470 cmd = _PHY_LINKMON_SET_CMD; 1471 } else if (sal_strcasecmp(cmd_str, "get") == 0) { 1472 cmd = _PHY_LINKMON_GET_CMD; 1473 } else { 1474 return CMD_USAGE; 1475 } 1476 1477 /* 1478 * unit: phy_unit_value: phy chain number 1479 * if : if_str="sys"|"line" 1480 */ 1481 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 1482 &phy_unit_value, NULL); 1483 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 1484 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), &lane_num, NULL); 1485 if (cmd == _PHY_LINKMON_SET_CMD) { 1486 parse_table_add(&pt, "mode", PQ_DFL | PQ_INT, (void *)(0), &link_mon_mode, NULL); 1487 } 1488 1489 if (parse_arg_eq(args, &pt) < 0) { 1490 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 1491 parse_arg_eq_done(&pt); 1492 return CMD_USAGE; 1493 } 1494 1495 rv = (int)_phy_diag_phy_if_get(if_str, &phy_unit_if); 1496 if (rv == ((int)CMD_OK)) { 1497 rv = (int)_phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 1498 } 1499 1500 /* Now free allocated strings */ 1501 parse_arg_eq_done(&pt); 1502 1503 if (rv != ((int)CMD_OK)) { 1504 return rv; 1505 } 1506 1507 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, lane_num); 1508 1509 /* coverity[overrun-local] */ 1510 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1511 1512 #ifdef PORTMOD_SUPPORT 1513 if (soc_feature(unit, soc_feature_portmod)) { 1514 if (cmd == _PHY_LINKMON_SET_CMD) { 1515 rv = portmod_port_diag_ctrl( unit, port, inst, PHY_DIAG_CTRL_CMD, 1516 PHY_DIAG_CTRL_LINKMON_MODE, INT_TO_PTR(link_mon_mode)); 1517 } else { 1518 rv = portmod_port_diag_ctrl( unit, port, inst, PHY_DIAG_CTRL_CMD, 1519 PHY_DIAG_CTRL_LINKMON_STATUS,(void *)0); 1520 } 1521 } else 1522 #endif 1523 { 1524 1525 if (cmd == _PHY_LINKMON_SET_CMD) { 1526 rv = soc_phyctrl_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 1527 PHY_DIAG_CTRL_LINKMON_MODE, INT_TO_PTR(link_mon_mode)); 1528 } else { 1529 rv = soc_phyctrl_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 1530 PHY_DIAG_CTRL_LINKMON_STATUS, (void *)0); 1531 } 1532 } 1533 1534 if (rv != ((int)BCM_E_NONE)) { 1535 return CMD_FAIL; 1536 } 1537 } 1538 return CMD_OK; 1539 } 1540 1541 STATIC int 1542 _phy_diag_eyescan_res_print(int unit, 1543 int speed, 1544 soc_port_t port, 1545 int sample_res, 1546 soc_port_phy_eye_bounds_t *bounds, 1547 soc_port_phy_eyescan_results_t *res) 1548 { 1549 1550 int vt_i, hz_i, legend_ndx = 0, legend_ndx_offset = 0; 1551 int hz_min, hz_max, vt_min, vt_max; 1552 const char legend[] = { ' ', '.', 'o', 'b', 'P', 'D', 'B', 'M', 'W', 'X' }; 1553 const char legend_low_ber[] = 1554 { ' ', 'X', 'W', 'M', 'B', 'D', 'P', 'b', 'o', '.', 'Y', 'Z', 'A' }; 1555 const char error_char = '!'; 1556 const char invalid_char = '?'; 1557 int desc_idx = 0; 1558 unsigned int error_cnt; 1559 unsigned int time_tot; 1560 cmd_result_t ret = CMD_OK; 1561 phy_ctrl_t *pc; 1562 1563 #if defined(BROADCOM_DEBUG) /*required for compilation */ 1564 char *description[] = { 1565 " Description:", 1566 " =============", 1567 " '+' Latch", 1568 " '?' No data" 1569 }; 1570 #endif /*BROADCOM_DEBUG */ 1571 int desc_size = 4; 1572 1573 #if defined(BROADCOM_DEBUG) /*required for compilation */ 1574 char *desc_ber[] = { 1575 " '%c' BER <10-9", 1576 " '%c' BER ~10-9", 1577 " '%c' BER ~10-8", 1578 " '%c' BER ~10-7", 1579 " '%c' BER ~10-6", 1580 " '%c' BER ~10-5", 1581 " '%c' BER ~10-4", 1582 " '%c' BER ~10-3", 1583 " '%c' BER ~10-2", 1584 " '%c' BER >10-2" 1585 }; 1586 char *desc_low_ber[] = { 1587 " '%c' BER <10-12", 1588 " '%c' BER >10-2", 1589 " '%c' BER ~10-2", 1590 " '%c' BER ~10-3", 1591 " '%c' BER ~10-4", 1592 " '%c' BER ~10-5", 1593 " '%c' BER ~10-6", 1594 " '%c' BER ~10-7", 1595 " '%c' BER ~10-8", 1596 " '%c' BER ~10-9", 1597 " '%c' BER ~10-10", 1598 " '%c' BER ~10-11", 1599 " '%c' BER ~10-12" 1600 }; 1601 #endif /*BROADCOM_DEBUG */ 1602 int desc_ber_size = 10; 1603 int desc_low_ber_size = 13; 1604 1605 1606 const unsigned int nof_legend_chars = sizeof(legend) / sizeof(char); 1607 const unsigned int nof_legend_low_ber_chars = 1608 sizeof(legend_low_ber) / sizeof(char); 1609 char print_char; 1610 unsigned int ber; 1611 char buf[5]; 1612 unsigned int rev_ber = 0; 1613 unsigned int bits_xferred = 0; 1614 unsigned int gspeed = 0; /* Speed in Gbps */ 1615 unsigned int speed_n = 0; /* Normalized speed */ 1616 unsigned int time_n = 0; /* Normalized time */ 1617 1618 pc = EXT_PHY_SW_STATE(unit, port); 1619 1620 if (!BCM_UNIT_VALID(unit)) { 1621 ret = CMD_FAIL; 1622 goto exit; 1623 } 1624 1625 /*psrsmeters verification */ 1626 if (0 == bounds) { 1627 ret = CMD_FAIL; 1628 goto exit; 1629 } 1630 1631 hz_min = bounds->horizontal_min; 1632 hz_max = bounds->horizontal_max; 1633 vt_min = bounds->vertical_min; 1634 vt_max = bounds->vertical_max; 1635 1636 if (hz_max < hz_min) { 1637 ret = CMD_FAIL; 1638 goto exit; 1639 } 1640 if (vt_max < vt_min) { 1641 ret = CMD_FAIL; 1642 goto exit; 1643 } 1644 1645 if (0 == res) { 1646 ret = CMD_FAIL; 1647 goto exit; 1648 } 1649 1650 /*Print results log */ 1651 for (vt_i = vt_min; vt_i <= vt_max; vt_i++) { 1652 if (vt_i % sample_res != 0) { 1653 continue; 1654 } 1655 for (hz_i = hz_min; hz_i <= hz_max; hz_i++) { 1656 if (hz_i % sample_res != 0) { 1657 continue; 1658 } 1659 1660 cli_out("[H=%d, V=%d] %u errors in %d milisec \r\n", hz_i, vt_i, 1661 res->error_count[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX] 1662 [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX], 1663 res->run_time[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX] 1664 [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX]); 1665 } 1666 } 1667 1668 if (res->ext_done) { 1669 switch (res->ext_better) { 1670 case -1: 1671 cli_out("BER(extrapolated) is *worse* than 1e-%d.%d\n", 1672 res->ext_results_int, res->ext_results_remainder); 1673 break; 1674 case 1: 1675 cli_out("BER(extrapolated) is *better* than 1e-%d.%d\n", 1676 res->ext_results_int, res->ext_results_remainder); 1677 break; 1678 default: 1679 cli_out("BER(extrapolated) = 1e-%d.%d\n", res->ext_results_int, 1680 res->ext_results_remainder); 1681 break; 1682 } 1683 } 1684 1685 if (hz_max != hz_min) { 1686 cli_out("\r\n[VERTICAL]-------------------------------" 1687 "------------------------\r\n"); 1688 for (vt_i = vt_max; vt_i >= vt_min; vt_i--) { 1689 if (vt_i % sample_res != 0) { 1690 continue; 1691 } 1692 1693 /* Print Y axis and values */ 1694 if ((((vt_i - vt_min) / sample_res) % 5 == 0)) { 1695 cli_out("%3d-+", vt_i); 1696 } else { 1697 cli_out(" |"); 1698 } 1699 1700 for (hz_i = hz_min; hz_i <= hz_max; hz_i++) { 1701 1702 if (hz_i % sample_res != 0) { 1703 continue; 1704 } 1705 1706 print_char = error_char; 1707 error_cnt = 1708 res->error_count[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX] 1709 [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX]; 1710 time_tot = 1711 res->run_time[hz_i + SOC_PORT_PHY_EYESCAN_H_INDEX] 1712 [vt_i + SOC_PORT_PHY_EYESCAN_V_INDEX]; 1713 1714 if (time_tot == 0 && error_cnt == 0) { 1715 print_char = invalid_char; 1716 } else { 1717 /* 1718 * Eyescan calculation for Low BER 1719 * ------------------------------- 1720 * Standard/Existing eyescan plot function was supporting 1721 * upto BER 10^-9 below logic is implemented for plotting 1722 * eyescan for BER 10^-10, 10^-11, 10^-12 for satisfying 1723 * low BER requirements. Currently this logic is implemented 1724 * for Gallardo40 to fix the JIRA PHY-1156. 1725 * BER = #bit errors/#bit transferred 1726 * For testing low BER we need to run eyescan for long 1727 * sample time. For Ex: We may have to run eyescan for 10E5 1728 * milli sec with 10G traffic to see BER 10^-12 1729 * i.e., #bits transferred in 10^5 millisec = 10^12 1730 * if #bit errors = 1, BER = 1 / 10^12 = 10^-12 1731 * The below logic is implemented using uint32 so as to 1732 * avoid the usage of uint64, Float, math library functions 1733 * such as log, abs, ceil, floor these have performance 1734 * issues and prone to introduce build issues in our SDK 1735 * environment. uint32 can store max 2^32 1736 * (cannot store 10^12), and actual BER requires 1737 * Float (#biterrors/#bits transferred, We calculate 1738 * Reverse BER, calculating index of legend_low_ber by 1739 * calculating no of digits present in reverse BER to print 1740 * the char for plotting eyescan 1741 * rev_ber = bits_xferred / error_cnt; 1742 * legend_ndx = #digits(rev_ber); 1743 * print_char = legend_low_ber[legend_ndx]; 1744 * Below is the map between print_char and BER 1745 * ============= 1746 * '+' Latch 1747 * '?' No data 1748 * ' ' BER <10-12 1749 * 'X' BER >10-2 1750 * 'W' BER ~10-2 1751 * 'M' BER ~10-3 1752 * 'B' BER ~10-4 1753 * 'D' BER ~10-5 1754 * 'P' BER ~10-6 1755 * 'b' BER ~10-7 1756 * 'o' BER ~10-8 1757 * '.' BER ~10-9 1758 * 'Y' BER ~10-10 1759 * 'Z' BER ~10-11 1760 * 'A' BER ~10-12 1761 */ 1762 if (pc && pc->phy_id0 == 0x600d && pc->phy_id1 == 0x8500) { 1763 if (time_tot == 0) { 1764 legend_ndx = 0; 1765 } else { 1766 time_n = 1; 1767 while (time_n <= 1000000) { 1768 if (time_tot <= time_n) { 1769 break; 1770 } 1771 time_n *= 10; 1772 } 1773 1774 gspeed = speed / 1000; 1775 speed_n = 1; 1776 while (speed_n <= 100) { 1777 if (gspeed <= speed_n) { 1778 break; 1779 } 1780 speed_n *= 10; 1781 } 1782 1783 switch (time_n * speed_n) { 1784 case 1: 1785 case 10: 1786 case 100: 1787 case 1000: 1788 bits_xferred = gspeed * 1000000 * time_tot; 1789 legend_ndx_offset = 0; 1790 break; 1791 case 10000: 1792 bits_xferred = gspeed * 100000 * time_tot; 1793 legend_ndx_offset = 1; 1794 break; 1795 case 100000: 1796 bits_xferred = gspeed * 10000 * time_tot; 1797 legend_ndx_offset = 2; 1798 break; 1799 case 1000000: 1800 bits_xferred = gspeed * 1000 * time_tot; 1801 legend_ndx_offset = 3; 1802 break; 1803 default: 1804 bits_xferred = gspeed * 100 * time_tot; 1805 legend_ndx_offset = 4; 1806 break; 1807 } 1808 1809 if (error_cnt == 0) { 1810 legend_ndx = 0; 1811 } else { 1812 rev_ber = bits_xferred / error_cnt; 1813 if (rev_ber == 0) { 1814 legend_ndx = 1; 1815 } else { 1816 legend_ndx = 0; 1817 while (rev_ber > 0) { 1818 rev_ber /= 10; 1819 legend_ndx++; 1820 } 1821 if (legend_ndx > 1) { 1822 legend_ndx = 1823 legend_ndx + legend_ndx_offset - 1; 1824 } 1825 } 1826 } 1827 } 1828 1829 /* If exceeds legend size, round legend_ndx down */ 1830 if (legend_ndx >= nof_legend_low_ber_chars) { 1831 legend_ndx = 0; 1832 } 1833 print_char = legend_low_ber[legend_ndx]; 1834 } else { 1835 if (time_tot == 0) { 1836 ber = 0; 1837 } else if (error_cnt < (0xffffffff / 1000)) { 1838 /* multiplying by 1000 won't cause an overflow */ 1839 ber = (error_cnt * 1000 / time_tot); 1840 } else { 1841 /* number is big enough, 1842 so can first divide by time and than multiply */ 1843 ber = (error_cnt / time_tot * 1000); 1844 } 1845 1846 /* Print matrix entries */ 1847 if (ber == SRD_EYESCAN_INVALID) { 1848 /* print_char = invalid_char; */ 1849 } else { 1850 1851 legend_ndx = 0; 1852 while (ber > 0) { 1853 ber /= 10; 1854 legend_ndx++; 1855 } 1856 1857 /* If exceeds legend size, round legend_ndx down */ 1858 if (legend_ndx >= nof_legend_chars) { 1859 legend_ndx = (nof_legend_chars - 1); 1860 } 1861 } 1862 1863 print_char = legend[legend_ndx]; 1864 } 1865 } 1866 1867 cli_out("%c", print_char); 1868 } 1869 1870 cli_out("|"); 1871 1872 /* print description on relevant lines */ 1873 if (pc && pc->phy_id0 == 0x600d && pc->phy_id1 == 0x8500) { 1874 if (desc_idx < desc_low_ber_size + desc_size) { 1875 #if defined(BROADCOM_DEBUG) 1876 if (desc_idx < desc_size) { 1877 cli_out("%s", description[desc_idx]); 1878 } else { 1879 cli_out(desc_low_ber[desc_idx - desc_size], 1880 legend_low_ber[desc_idx - desc_size]); 1881 } 1882 #endif 1883 desc_idx++; 1884 } 1885 } else { 1886 if (desc_idx < desc_ber_size + desc_size) { 1887 #if defined(BROADCOM_DEBUG) 1888 if (desc_idx < desc_size) { 1889 cli_out("%s", description[desc_idx]); 1890 } else { 1891 cli_out(desc_ber[desc_idx - desc_size], 1892 legend[desc_idx - desc_size]); 1893 } 1894 #endif 1895 desc_idx++; 1896 } 1897 } 1898 cli_out("\r\n"); 1899 } 1900 1901 /* print x axis */ 1902 cli_out(" -"); 1903 1904 for (hz_i = hz_min; hz_i < hz_max - 9 * sample_res; hz_i++) { 1905 if (hz_i % sample_res != 0) { 1906 continue; 1907 } 1908 cli_out("%c", 1909 ((((hz_i - hz_min) / sample_res) % 5) ? '-' : '+')); 1910 } 1911 1912 cli_out("[HORIZONTAL]\r\n"); 1913 cli_out(" "); 1914 1915 for (hz_i = hz_min; hz_i <= hz_max; hz_i++) { 1916 if (hz_i % sample_res != 0) { 1917 continue; 1918 } 1919 cli_out("%c", 1920 ((((hz_i - hz_min) / sample_res) % 5) ? ' ' : '|')); 1921 } 1922 1923 cli_out("\r\n"); 1924 cli_out(" "); 1925 for (hz_i = hz_min; hz_i <= hz_max; hz_i++) { 1926 if (hz_i % sample_res != 0) { 1927 continue; 1928 } 1929 if (((hz_i - hz_min) / sample_res) % 5) { 1930 cli_out(" "); 1931 } else { 1932 cli_out("%2d", hz_i); 1933 sal_sprintf(buf, "%2d", hz_i); 1934 hz_i += ((sal_strlen(buf) - 1) * sample_res); 1935 } 1936 } 1937 cli_out("\r\n"); 1938 } 1939 exit: 1940 return ret; 1941 } 1942 1943 cmd_result_t 1944 _phy_diag_reg(int unit, bcm_pbmp_t pbmp, args_t *args) 1945 { 1946 bcm_port_t port, dport; 1947 int cmd; 1948 char *cmd_str/*, *core_str*/; 1949 uint32 *pData, par[5]; 1950 1951 par[0] = 0; 1952 par[1] = 0; 1953 par[2] = 0; 1954 par[3] = 0; 1955 par[4] = 0; 1956 pData = &par[0]; 1957 1958 cmd = PHY_DIAG_CTRL_REG_READ; 1959 1960 if ((cmd_str = ARG_GET(args)) == NULL) { 1961 return CMD_USAGE; 1962 } 1963 if (cmd_str) { 1964 if (sal_strcasecmp(cmd_str, "core0") == 0) { 1965 *pData++ = 0; 1966 } else if (sal_strcasecmp(cmd_str, "core1") == 0) { 1967 *pData++ = 1; 1968 } else if (sal_strcasecmp(cmd_str, "core2") == 0) { 1969 *pData++ = 2; 1970 } else if (sal_strcasecmp(cmd_str, "mld") == 0) { 1971 *pData++ = 3; 1972 } 1973 } 1974 if ((cmd_str = ARG_GET(args)) == NULL) { /* Get aer number */ 1975 return CMD_USAGE; 1976 } 1977 *pData++ = sal_strtoul(cmd_str, NULL, 0); 1978 1979 if ((cmd_str = ARG_GET(args)) == NULL) { /* Get reg number */ 1980 return CMD_USAGE; 1981 } 1982 *pData++ = sal_strtoul(cmd_str, NULL, 0); 1983 1984 if ((cmd_str = ARG_GET(args)) != NULL) { /* Get write data */ 1985 cmd = PHY_DIAG_CTRL_REG_WRITE; 1986 *pData++ = sal_strtoul(cmd_str, NULL, 0); 1987 } 1988 1989 /* command targets to Internal serdes device for now */ 1990 /* coverity[overrun-local] */ 1991 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1992 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 1993 PHY_DIAG_CTRL_CMD, cmd, 1994 &par) != SOC_E_NONE) { 1995 return CMD_FAIL; 1996 } 1997 } 1998 return CMD_OK; 1999 } 2000 2001 cmd_result_t 2002 _phy_diag_eyescan(int unit, bcm_pbmp_t pbmp, args_t *args) 2003 { 2004 int i, speed, port_count; 2005 cmd_result_t ret = CMD_OK; 2006 soc_port_phy_eyescan_params_t params; 2007 soc_port_phy_eyescan_results_t *results; 2008 int phy_unit, phy_unit_if, phy_unit_value = 0; 2009 parse_table_t pt; 2010 int rv, flags = 0; 2011 uint32 nof_ports; 2012 uint32 inst; 2013 char *if_str; 2014 soc_port_t *ports, port, dport; 2015 int *local_lane_num, lane_num = 0xff; 2016 char *eyescan_counters_strs[socPortPhyEyescanNofCounters * 2 + 1]; 2017 char numbers_strs[socPortPhyEyescanNofCounters][3]; 2018 2019 for (i = 0; i < socPortPhyEyescanNofCounters; i++) { 2020 sal_sprintf(numbers_strs[i], "%d", i); 2021 eyescan_counters_strs[i] = eyescan_counter[i]; 2022 eyescan_counters_strs[socPortPhyEyescanNofCounters + i] = 2023 numbers_strs[i]; 2024 } 2025 eyescan_counters_strs[socPortPhyEyescanNofCounters * 2] = NULL; 2026 2027 BCM_PBMP_COUNT(pbmp, port_count); 2028 if (port_count == 0) { 2029 return CMD_OK; 2030 } 2031 2032 results = sal_alloc((port_count) * sizeof(soc_port_phy_eyescan_results_t), 2033 "eyescan results array"); 2034 /*array of result per port */ 2035 if (results == NULL) { 2036 cli_out("ERROR, in phy_diag_eyescan: failed to allocate results"); 2037 return CMD_FAIL; 2038 } 2039 ports = sal_alloc((port_count) * sizeof(soc_port_t), "eyescan ports"); 2040 if (ports == NULL) { 2041 cli_out("ERROR, in phy_diag_eyescan: failed to allocate ports"); 2042 sal_free(results); 2043 return CMD_FAIL; 2044 } 2045 local_lane_num = 2046 sal_alloc((port_count) * sizeof(int), "eyescan lane_num array"); 2047 if (local_lane_num == NULL) { 2048 cli_out("ERROR, in phy_diag_eyescan: failed to allocate local_lane_num"); 2049 sal_free(results); 2050 sal_free(ports); 2051 return CMD_FAIL; 2052 } 2053 2054 /*default values */ 2055 params.sample_time = 1000; 2056 params.sample_resolution = 1; 2057 params.bounds.horizontal_max = 31; 2058 params.bounds.horizontal_min = -31; 2059 params.bounds.vertical_max = 31; 2060 params.bounds.vertical_min = -31; 2061 params.counter = socPortPhyEyescanCounterRelativePhy; 2062 params.error_threshold = 20; 2063 params.time_upper_bound = 256000; 2064 params.type = -1; 2065 /* defaults for BER projection */ 2066 params.ber_proj_scan_mode = 0; /* DIAG_BER_VERT DIAG_BER_POS */ 2067 params.ber_proj_timer_cnt = 96; 2068 params.ber_proj_err_cnt = 8; 2069 2070 sal_memset(results, 0, sizeof(soc_port_phy_eyescan_results_t) * port_count); 2071 2072 nof_ports = 0; 2073 /* coverity[overrun-local] */ 2074 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2075 ports[nof_ports] = port; 2076 nof_ports++; 2077 } 2078 2079 params.nof_threshold_links = nof_ports / 2; 2080 if (params.nof_threshold_links < 1) { 2081 params.nof_threshold_links = 1; 2082 } 2083 2084 parse_table_init(unit, &pt); 2085 parse_table_add(&pt, "type", PQ_DFL | PQ_INT, (void *)(0), 2086 &(params.type), NULL); 2087 parse_table_add(&pt, "vertical_max", PQ_DFL | PQ_INT, (void *)(0), 2088 &(params.bounds.vertical_max), NULL); 2089 parse_table_add(&pt, "vertical_min", PQ_DFL | PQ_INT, (void *)(0), 2090 &(params.bounds.vertical_min), NULL); 2091 parse_table_add(&pt, "horizontal_max", PQ_DFL | PQ_INT, (void *)(0), 2092 &(params.bounds.horizontal_max), NULL); 2093 parse_table_add(&pt, "horizontal_min", PQ_DFL | PQ_INT, (void *)(0), 2094 &(params.bounds.horizontal_min), NULL); 2095 parse_table_add(&pt, "sample_resolution", PQ_DFL | PQ_INT, (void *)(0), 2096 &(params.sample_resolution), NULL); 2097 parse_table_add(&pt, "sample_time", PQ_DFL | PQ_INT, (void *)(0), 2098 &(params.sample_time), NULL); 2099 parse_table_add(&pt, "counter", PQ_MULTI | PQ_DFL | PQ_NO_EQ_OPT, 2100 (void *)(0), &(params.counter), &eyescan_counters_strs); 2101 parse_table_add(&pt, "flags", PQ_DFL | PQ_INT, (void *)(0), &flags, NULL); 2102 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), &lane_num, NULL); 2103 parse_table_add(&pt, "error_threshold", PQ_DFL | PQ_INT, (void *)(0), 2104 &(params.error_threshold), NULL); 2105 parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0), 2106 &(params.time_upper_bound), NULL); 2107 parse_table_add(&pt, "nof_threshold_links", PQ_DFL | PQ_INT, (void *)(0), 2108 &(params.nof_threshold_links), NULL); 2109 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 2110 &phy_unit_value, NULL); 2111 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 2112 /* BER projection related parameter */ 2113 parse_table_add(&pt, "ber_scan_mode", PQ_DFL | PQ_INT, (void *)(0), 2114 &(params.ber_proj_scan_mode), NULL); 2115 parse_table_add(&pt, "timer_control", PQ_DFL | PQ_INT, (void *)(0), 2116 &(params.ber_proj_timer_cnt), NULL); 2117 parse_table_add(&pt, "max_err_control", PQ_DFL | PQ_INT, (void *)(0), 2118 &(params.ber_proj_err_cnt), NULL); 2119 2120 if (parse_arg_eq(args, &pt) < 0) { 2121 cli_out("ERROR: could not parse parameters\n"); 2122 parse_arg_eq_done(&pt); 2123 ret = CMD_FAIL; 2124 goto exit; 2125 } 2126 2127 if (ARG_CNT(args) > 0) { 2128 cli_out("%s: Unknown argument %s\n", ARG_CMD(args), ARG_CUR(args)); 2129 parse_arg_eq_done(&pt); 2130 ret = CMD_FAIL; 2131 goto exit; 2132 } 2133 params.counter = params.counter % socPortPhyEyescanNofCounters; 2134 if(params.type == -1) { /* -1 is un-specified, so set to 1 as default */ 2135 params.type = 1 ; 2136 } /* params.type !=0 means phymod eyescan */ 2137 2138 phy_unit = 0; 2139 rv = _phy_diag_phy_if_get(if_str, &phy_unit_if); 2140 if (rv != ((int)CMD_OK)) { 2141 parse_arg_eq_done(&pt); 2142 ret = CMD_FAIL; 2143 goto exit; 2144 } 2145 rv = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 2146 if (rv != ((int)CMD_OK)) { 2147 parse_arg_eq_done(&pt); 2148 ret = CMD_FAIL; 2149 goto exit; 2150 } 2151 2152 /* inst has unit, intf, lane */ 2153 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, 2154 lane_num == 0xff ? PHY_DIAG_LN_DFLT : lane_num); 2155 2156 for (i = 0; i < nof_ports; i++) { 2157 results[i].ext_done = 0; 2158 } 2159 2160 if (lane_num == 0xff) { 2161 if (local_lane_num != NULL) { 2162 sal_free(local_lane_num); 2163 } 2164 local_lane_num = NULL; 2165 } else { 2166 /*now check the correct lane num input for each port */ 2167 #ifndef PORTMOD_SUPPORT 2168 for (i = 0; i < nof_ports; i++) { 2169 if (lane_num > SOC_INFO(unit).port_num_lanes[ports[i]]) { 2170 cli_out("ERROR, in phy_diag_eyescan: lane num is wrong \n"); 2171 return CMD_FAIL; 2172 } 2173 } 2174 #endif 2175 2176 for(i = 0; i < port_count; i++) { 2177 sal_memcpy(&local_lane_num[i], &lane_num, sizeof(int)); 2178 } 2179 } 2180 2181 if ((params.sample_time < 0) || (params.sample_time > params.time_upper_bound)) { 2182 cli_out("ERROR, in phy_diag_eyescan: sample time %d" 2183 " out of range ( 0 ~ %d )\n", 2184 params.sample_time, params.time_upper_bound); 2185 ret = CMD_FAIL; 2186 goto exit; 2187 } 2188 2189 rv = soc_port_phy_eyescan_run(unit, inst, flags, ¶ms, nof_ports, ports, 2190 local_lane_num, results); 2191 #ifdef PHYMOD_SUPPORT 2192 if (!(is_eyescan_algorithm_legacy_mode(unit, nof_ports, ports, inst)) || rv){ 2193 ret = (rv == SOC_E_NONE)? CMD_OK : CMD_FAIL; 2194 goto exit; 2195 } 2196 #endif 2197 2198 #ifdef PHYMOD_SUPPORT 2199 if(is_eyescan_algorithm_legacy_rpt_mode(unit, nof_ports, ports, inst)) 2200 #endif 2201 { 2202 rv = soc_port_phy_eyescan_extrapolate(unit, flags, ¶ms, nof_ports, 2203 ports, results); 2204 2205 if (rv != SOC_E_NONE) { 2206 ret = CMD_FAIL; 2207 goto exit; 2208 } 2209 2210 for (i = 0; i < nof_ports; i++) { 2211 2212 rv = bcm_port_speed_get(unit, ports[i], &speed); 2213 if (rv != SOC_E_NONE) { 2214 ret = CMD_FAIL; 2215 goto exit; 2216 } 2217 2218 cli_out("Eye\\Cross-section Results For Port %d (with rate %d):\n", 2219 ports[i], speed); 2220 2221 rv = _phy_diag_eyescan_res_print(unit, speed, ports[i], 2222 params.sample_resolution, 2223 &(params.bounds), &(results[i])); 2224 2225 if (rv != SOC_E_NONE) { 2226 ret = CMD_FAIL; 2227 goto exit; 2228 } 2229 } 2230 } 2231 ret = CMD_OK; 2232 2233 exit: 2234 if (results != NULL) { 2235 sal_free(results); 2236 } 2237 if (ports != NULL) { 2238 sal_free(ports); 2239 } 2240 if (local_lane_num != NULL) { 2241 sal_free(local_lane_num); 2242 } 2243 return ret; 2244 } 2245 2246 cmd_result_t 2247 _phy_diag_berproj(int unit, bcm_pbmp_t pbmp, args_t *args) 2248 { 2249 parse_table_t pt; 2250 bcm_port_t port, dport; 2251 int num_ports, i, num_lanes; 2252 cmd_result_t res = CMD_OK; 2253 bcm_error_t rv = BCM_E_NONE; 2254 char *if_str; 2255 int phy_unit, phy_unit_value = 0, phy_unit_if; 2256 uint32 inst; 2257 soc_port_phy_ber_proj_params_t params; 2258 soc_phy_prbs_errcnt_t** prbs_errcnt = NULL; 2259 uint32 time_remaining; 2260 2261 params.ber_proj_fec_type = _SHR_PORT_PHY_FEC_RS_544; 2262 params.ber_proj_hist_errcnt_thresh = 0; 2263 params.ber_proj_timeout_s = 60; 2264 2265 /* 2266 * unit: phy_unit_value: phy chain number 2267 * if : if_str="sys"|"line" 2268 */ 2269 parse_table_init(unit, &pt); 2270 2271 parse_table_add(&pt, "unit", PQ_DFL | PQ_INT, (void *)(0), 2272 &phy_unit_value, NULL); 2273 parse_table_add(&pt, "if", PQ_STRING, 0, &if_str, NULL); 2274 parse_table_add(&pt, "hist_errcnt_threshold", PQ_DFL | PQ_INT, (void *)(0), 2275 ¶ms.ber_proj_hist_errcnt_thresh, NULL); 2276 parse_table_add(&pt, "sample_time", PQ_DFL | PQ_INT, (void *)(0), 2277 ¶ms.ber_proj_timeout_s, NULL); 2278 2279 if (parse_arg_eq(args, &pt) < 0) { 2280 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 2281 parse_arg_eq_done(&pt); 2282 return CMD_USAGE; 2283 } 2284 2285 res = _phy_diag_phy_if_get(if_str, &phy_unit_if); 2286 if (res == CMD_OK) { 2287 res = _phy_diag_phy_unit_get(phy_unit_value, &phy_unit); 2288 } 2289 2290 /* Now free allocated strings */ 2291 parse_arg_eq_done(&pt); 2292 2293 if (res != CMD_OK) { 2294 return res; 2295 } 2296 2297 inst = PHY_DIAG_INSTANCE(phy_unit, phy_unit_if, PHY_DIAG_LN_DFLT); 2298 2299 /* Here we parallelize the ber proj for all the ports 2300 * Here're the steps for ber proj: 2301 * 1. Pre: allocate memory to store err count. 2302 * 2. Pre config analyzer. (Only needed when hist_errcnt_threshold == 0.) 2303 * 3. Config: Configure BER analyzer. 2304 * 4. Start: Start accumulating errors. 2305 * 5. Collect: Collect error count. 2306 * 6. Proj: Project BER. 2307 * 7. Print output. 2308 */ 2309 2310 /* Verify input */ 2311 if (params.ber_proj_timeout_s <= 0) { 2312 cli_out("Error: invalid timeout value: %d\n", params.ber_proj_timeout_s); 2313 return CMD_USAGE; 2314 } 2315 2316 num_ports = 0; 2317 /* coverity[overrun-local] */ 2318 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2319 num_ports++; 2320 } 2321 2322 /* Allocate memories to collect error count */ 2323 prbs_errcnt = sal_alloc(sizeof(soc_phy_prbs_errcnt_t*)*num_ports, "BER error cnt array"); 2324 if (prbs_errcnt == NULL) { 2325 cli_out("Insufficient memory.\n"); 2326 res = CMD_FAIL; 2327 goto exit; 2328 } 2329 /* Initialize memory space */ 2330 for (i = 0; i < num_ports; i++) { 2331 prbs_errcnt[i] = NULL; 2332 } 2333 2334 i = 0; 2335 /* coverity[overrun-local] */ 2336 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2337 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 2338 prbs_errcnt[i] = sal_alloc(sizeof(soc_phy_prbs_errcnt_t)*num_lanes, "BER error cnt"); 2339 if (prbs_errcnt[i] == NULL) { 2340 cli_out("Insufficient memory.\n"); 2341 res = CMD_FAIL; 2342 goto exit; 2343 } 2344 sal_memset(prbs_errcnt[i], 0, sizeof(soc_phy_prbs_errcnt_t)*num_lanes); 2345 i++; 2346 } 2347 2348 if (params.ber_proj_hist_errcnt_thresh == 0) { 2349 /* Pre-stage, only needed when using optimized errcnt threshold. */ 2350 cli_out("Getting optimized threshold for all the lanes...\n"); 2351 i = 0; 2352 /* coverity[overrun-local] */ 2353 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2354 params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_PRE; 2355 params.ber_proj_prbs_errcnt = prbs_errcnt[i]; 2356 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 2357 PHY_DIAG_CTRL_BER_PROJ, (void *)¶ms); 2358 if (rv != BCM_E_NONE) { 2359 res = CMD_FAIL; 2360 goto exit; 2361 } 2362 i++; 2363 } 2364 /* 99 is used to generate CEIL function of 5% of timeout_s */ 2365 time_remaining = (params.ber_proj_timeout_s * 5 + 99)/ 100; 2366 sal_sleep(time_remaining); 2367 } 2368 2369 i = 0; 2370 /* coverity[overrun-local] */ 2371 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2372 /* Stage 1: Config PRBS checker */ 2373 params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_CONFIG; 2374 params.ber_proj_prbs_errcnt = prbs_errcnt[i]; 2375 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 2376 PHY_DIAG_CTRL_BER_PROJ, (void *)¶ms); 2377 if (rv != BCM_E_NONE) { 2378 res = CMD_FAIL; 2379 goto exit; 2380 } 2381 i++; 2382 } 2383 2384 i = 0; 2385 /* coverity[overrun-local] */ 2386 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2387 /* Stage 2: Start Error accumulation */ 2388 params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_START; 2389 params.ber_proj_prbs_errcnt = prbs_errcnt[i]; 2390 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 2391 PHY_DIAG_CTRL_BER_PROJ, (void *)¶ms); 2392 if (rv != BCM_E_NONE) { 2393 res = CMD_FAIL; 2394 goto exit; 2395 } 2396 i++; 2397 } 2398 2399 /* Stage 3: Collect PRBS error count */ 2400 time_remaining = params.ber_proj_timeout_s; 2401 while (time_remaining > 0) { 2402 if (time_remaining > 5) { 2403 sal_sleep(5); 2404 time_remaining = time_remaining - 5; 2405 cli_out("."); 2406 } else { 2407 sal_sleep(time_remaining); 2408 time_remaining = 0; 2409 cli_out(".\n"); 2410 } 2411 i = 0; 2412 /* coverity[overrun-local] */ 2413 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2414 params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_COLLECT; 2415 params.ber_proj_prbs_errcnt = prbs_errcnt[i]; 2416 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 2417 PHY_DIAG_CTRL_BER_PROJ, (void *)¶ms); 2418 if (rv != BCM_E_NONE) { 2419 res = CMD_FAIL; 2420 goto exit; 2421 } 2422 i++; 2423 } 2424 } 2425 2426 /* Stage 4: BER Calculate */ 2427 i = 0; 2428 /* coverity[overrun-local] */ 2429 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2430 params.ber_proj_phase = SOC_PORT_PHY_BER_PROJ_P_CALC; 2431 params.ber_proj_prbs_errcnt = prbs_errcnt[i]; 2432 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 2433 PHY_DIAG_CTRL_BER_PROJ, (void *)¶ms); 2434 if (rv != BCM_E_NONE) { 2435 res = CMD_FAIL; 2436 goto exit; 2437 } 2438 i++; 2439 } 2440 2441 exit: 2442 if (prbs_errcnt != NULL) { 2443 i = 0; 2444 /* coverity[overrun-local] */ 2445 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2446 if (prbs_errcnt[i] != NULL) { 2447 sal_free(prbs_errcnt[i]); 2448 } 2449 i++; 2450 } 2451 sal_free(prbs_errcnt); 2452 } 2453 2454 return res; 2455 } 2456 2457 #ifdef PORTMOD_SUPPORT 2458 2459 int portmod_port_num_phys_get(int unit, int port, int *nof_phys) 2460 { 2461 int is_most_ext = 0; 2462 int phyn, nof_cores; 2463 phymod_core_access_t core_access[7]; 2464 int rv; 2465 phyn = 0; 2466 2467 while (!is_most_ext) { 2468 rv = portmod_port_core_access_get(unit, port, phyn, MAX_PHYN, core_access, &nof_cores, &is_most_ext); 2469 if (BCM_FAILURE(rv)){ 2470 return CMD_FAIL; 2471 } 2472 phyn++; 2473 } 2474 *nof_phys = phyn; 2475 return CMD_OK; 2476 2477 } 2478 #endif 2479 2480 int 2481 port_to_phyaddr(int unit, int port) 2482 { 2483 int phy_id; 2484 #ifdef PORTMOD_SUPPORT 2485 if (soc_feature(unit, soc_feature_portmod)) { 2486 phy_id = portmod_port_to_phyaddr(unit, port); 2487 } else 2488 #endif 2489 { 2490 phy_id = PORT_TO_PHY_ADDR(unit, port); 2491 } 2492 return phy_id; 2493 } 2494 2495 int 2496 port_to_phyaddr_int(int unit, int port) 2497 { 2498 int phy_id; 2499 #ifdef PORTMOD_SUPPORT 2500 if (soc_feature(unit, soc_feature_portmod)) { 2501 phy_id = portmod_port_to_phyaddr_int(unit, port); 2502 } else 2503 #endif 2504 { 2505 phy_id = PORT_TO_PHY_ADDR_INT(unit, port); 2506 } 2507 return phy_id; 2508 } 2509 2510 void 2511 _print_timesync_egress_message_mode(char *message, 2512 bcm_port_phy_timesync_event_message_egress_mode_t 2513 mode) 2514 { 2515 2516 cli_out("%s (no,uc,rc,ct) - ", message); 2517 2518 switch (mode) { 2519 case bcmPortPhyTimesyncEventMessageEgressModeNone: 2520 cli_out("NOne\n"); 2521 break; 2522 case bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField: 2523 cli_out("Update_Correctionfield\n"); 2524 break; 2525 case bcmPortPhyTimesyncEventMessageEgressModeReplaceCorrectionFieldOrigin: 2526 cli_out("Replace_Correctionfield_origin\n"); 2527 break; 2528 case bcmPortPhyTimesyncEventMessageEgressModeCaptureTimestamp: 2529 cli_out("Capture_Timestamp\n"); 2530 break; 2531 default: 2532 cli_out("\n"); 2533 break; 2534 } 2535 2536 } 2537 2538 void 2539 _print_inband_timesync_matching_criterion(uint32 flags) 2540 { 2541 uint8 delimit = 0; 2542 cli_out("InBand timesync MATch (none, ip, mac, pnum, vlid) - "); 2543 2544 if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR) { 2545 cli_out("ip"); 2546 delimit = 1; 2547 } 2548 if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR) { 2549 cli_out("%s", delimit ? ", mac" : "mac"); 2550 delimit = 1; 2551 } 2552 if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM) { 2553 cli_out("%s", delimit ? ", pnum" : "pnum"); 2554 delimit = 1; 2555 } 2556 if (flags & BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID) { 2557 cli_out("%s", delimit ? ", vlid" : "vlid"); 2558 } 2559 cli_out("\n"); 2560 } 2561 2562 bcm_port_phy_timesync_event_message_egress_mode_t 2563 _convert_timesync_egress_message_str(char *str, 2564 bcm_port_phy_timesync_event_message_egress_mode_t 2565 def) 2566 { 2567 int i; 2568 struct s_array { 2569 char *s; 2570 bcm_port_phy_timesync_event_message_egress_mode_t value; 2571 } data[] = { 2572 { 2573 "no", bcmPortPhyTimesyncEventMessageEgressModeNone}, { 2574 "uc", bcmPortPhyTimesyncEventMessageEgressModeUpdateCorrectionField}, { 2575 "rc", 2576 bcmPortPhyTimesyncEventMessageEgressModeReplaceCorrectionFieldOrigin}, 2577 { 2578 "ct", bcmPortPhyTimesyncEventMessageEgressModeCaptureTimestamp}}; 2579 2580 for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) { 2581 if (!sal_strncmp(str, data[i].s, 2)) { 2582 return data[i].value; 2583 } 2584 } 2585 return def; 2586 } 2587 2588 void 2589 _print_timesync_ingress_message_mode(char *message, 2590 bcm_port_phy_timesync_event_message_ingress_mode_t 2591 mode) 2592 { 2593 2594 cli_out("%s (no,uc,it,id) - ", message); 2595 2596 switch (mode) { 2597 case bcmPortPhyTimesyncEventMessageIngressModeNone: 2598 cli_out("NOne\n"); 2599 break; 2600 case bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField: 2601 cli_out("Update_Correctionfield\n"); 2602 break; 2603 case bcmPortPhyTimesyncEventMessageIngressModeInsertTimestamp: 2604 cli_out("Insert_Timestamp\n"); 2605 break; 2606 case bcmPortPhyTimesyncEventMessageIngressModeInsertDelaytime: 2607 cli_out("Insert_Delaytime\n"); 2608 break; 2609 default: 2610 cli_out("\n"); 2611 break; 2612 } 2613 2614 } 2615 2616 bcm_port_phy_timesync_event_message_ingress_mode_t 2617 _convert_timesync_ingress_message_str(char *str, 2618 bcm_port_phy_timesync_event_message_ingress_mode_t 2619 def) 2620 { 2621 int i; 2622 struct s_array { 2623 char *s; 2624 bcm_port_phy_timesync_event_message_ingress_mode_t value; 2625 } data[] = { 2626 { 2627 "no", bcmPortPhyTimesyncEventMessageIngressModeNone}, { 2628 "uc", bcmPortPhyTimesyncEventMessageIngressModeUpdateCorrectionField}, { 2629 "it", bcmPortPhyTimesyncEventMessageIngressModeInsertTimestamp}, { 2630 "id", bcmPortPhyTimesyncEventMessageIngressModeInsertDelaytime}}; 2631 2632 for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) { 2633 if (!sal_strncmp(str, data[i].s, 2)) { 2634 return data[i].value; 2635 } 2636 } 2637 return def; 2638 } 2639 2640 void 2641 _print_timesync_gmode(char *message, 2642 bcm_port_phy_timesync_global_mode_t mode) 2643 { 2644 2645 cli_out("%s (fr,si,cp) - ", message); 2646 2647 switch (mode) { 2648 case bcmPortPhyTimesyncModeFree: 2649 cli_out("FRee\n"); 2650 break; 2651 case bcmPortPhyTimesyncModeSyncin: 2652 cli_out("SyncIn\n"); 2653 break; 2654 case bcmPortPhyTimesyncModeCpu: 2655 cli_out("CPu\n"); 2656 break; 2657 default: 2658 cli_out("\n"); 2659 break; 2660 } 2661 2662 } 2663 2664 bcm_port_phy_timesync_global_mode_t 2665 _convert_timesync_gmode_str(char *str, 2666 bcm_port_phy_timesync_global_mode_t def) 2667 { 2668 int i; 2669 struct s_array { 2670 char *s; 2671 bcm_port_phy_timesync_global_mode_t value; 2672 } data[] = { 2673 { 2674 "fr", bcmPortPhyTimesyncModeFree}, { 2675 "si", bcmPortPhyTimesyncModeSyncin}, { 2676 "cp", bcmPortPhyTimesyncModeCpu}}; 2677 2678 for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) { 2679 if (!sal_strncmp(str, data[i].s, 2)) { 2680 return data[i].value; 2681 } 2682 } 2683 return def; 2684 } 2685 2686 void 2687 _print_framesync_mode(char *message, 2688 bcm_port_phy_timesync_framesync_mode_t mode) 2689 { 2690 2691 cli_out("%s (fno,fs0,fs1,fss,fsc) - ", message); 2692 2693 switch (mode) { 2694 case bcmPortPhyTimesyncFramesyncNone: 2695 cli_out("FramesyncNOne\n"); 2696 break; 2697 case bcmPortPhyTimesyncFramesyncSyncin0: 2698 cli_out("FramesyncSyncIn0\n"); 2699 break; 2700 case bcmPortPhyTimesyncFramesyncSyncin1: 2701 cli_out("FramesyncSyncIn1\n"); 2702 break; 2703 case bcmPortPhyTimesyncFramesyncSyncout: 2704 cli_out("FrameSyncSyncout\n"); 2705 break; 2706 case bcmPortPhyTimesyncFramesyncCpu: 2707 cli_out("FrameSyncCpu\n"); 2708 break; 2709 default: 2710 cli_out("\n"); 2711 break; 2712 } 2713 2714 } 2715 2716 bcm_port_phy_timesync_framesync_mode_t 2717 _convert_framesync_mode_str(char *str, 2718 bcm_port_phy_timesync_framesync_mode_t def) 2719 { 2720 int i; 2721 struct s_array { 2722 char *s; 2723 bcm_port_phy_timesync_framesync_mode_t value; 2724 } data[] = { 2725 { 2726 "fno", bcmPortPhyTimesyncFramesyncNone}, { 2727 "fs0", bcmPortPhyTimesyncFramesyncSyncin0}, { 2728 "fs1", bcmPortPhyTimesyncFramesyncSyncin1}, { 2729 "fss", bcmPortPhyTimesyncFramesyncSyncout}, { 2730 "fsc", bcmPortPhyTimesyncFramesyncCpu}}; 2731 2732 for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) { 2733 if (!sal_strncmp(str, data[i].s, 3)) { 2734 return data[i].value; 2735 } 2736 } 2737 return def; 2738 } 2739 2740 void 2741 _print_syncout_mode(char *message, 2742 bcm_port_phy_timesync_syncout_mode_t mode) 2743 { 2744 2745 cli_out("%s (sod,sot,spt,sps) - ", message); 2746 2747 switch (mode) { 2748 case bcmPortPhyTimesyncSyncoutDisable: 2749 cli_out("SyncOutDisable\n"); 2750 break; 2751 case bcmPortPhyTimesyncSyncoutOneTime: 2752 cli_out("SyncoutOneTime\n"); 2753 break; 2754 case bcmPortPhyTimesyncSyncoutPulseTrain: 2755 cli_out("SyncoutPulseTrain\n"); 2756 break; 2757 case bcmPortPhyTimesyncSyncoutPulseTrainWithSync: 2758 cli_out("SyncoutPulsetrainSync\n"); 2759 break; 2760 default: 2761 cli_out("\n"); 2762 break; 2763 } 2764 2765 } 2766 2767 bcm_port_phy_timesync_syncout_mode_t 2768 _convert_syncout_mode_str(char *str, 2769 bcm_port_phy_timesync_syncout_mode_t def) 2770 { 2771 int i; 2772 struct s_array { 2773 char *s; 2774 bcm_port_phy_timesync_syncout_mode_t value; 2775 } data[] = { 2776 { 2777 "sod", bcmPortPhyTimesyncSyncoutDisable}, { 2778 "sot", bcmPortPhyTimesyncSyncoutOneTime}, { 2779 "spt", bcmPortPhyTimesyncSyncoutPulseTrain}, { 2780 "sps", bcmPortPhyTimesyncSyncoutPulseTrainWithSync}}; 2781 2782 for (i = 0; i < (sizeof(data) / sizeof(data[0])); i++) { 2783 if (!sal_strncmp(str, data[i].s, 3)) { 2784 return data[i].value; 2785 } 2786 } 2787 return def; 2788 } 2789 2790 void 2791 _set_inband_timesync_matching_criterion(char *str, 2792 uint32 * inband_ctrl_flags) 2793 { 2794 int i; 2795 struct s_array { 2796 char *s; 2797 uint32 flag; 2798 } data[] = { 2799 {"ip" , BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR}, 2800 {"mac" , BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR}, 2801 {"pnum", BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM}, 2802 {"vlid", BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID}, 2803 {"none", 0} 2804 }; 2805 2806 *inband_ctrl_flags &= 2807 ~(BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR | 2808 BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR | 2809 BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM | 2810 BCM_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID); 2811 for ( i = 0; i < (sizeof(data) / sizeof(data[0])); i++ ) { 2812 if ( ! sal_strcmp(str, data[i].s) ) { 2813 *inband_ctrl_flags |= data[i].flag; 2814 } 2815 } 2816 2817 } 2818 2819 void 2820 _print_timesync_config(bcm_port_phy_timesync_config_t *conf) 2821 { 2822 2823 cli_out("ENable (Y or N) - %s\n", 2824 conf->flags & BCM_PORT_PHY_TIMESYNC_ENABLE ? "Yes" : "No"); 2825 2826 cli_out("CaptureTS (Y or N) - %s\n", 2827 conf-> 2828 flags & BCM_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE ? "Yes" : "No"); 2829 2830 cli_out("HeartbeatTS (Y or N) - %s\n", 2831 conf-> 2832 flags & BCM_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE ? "Yes" : "No"); 2833 2834 cli_out("RxCrc (Y or N) - %s\n", 2835 conf->flags & BCM_PORT_PHY_TIMESYNC_RX_CRC_ENABLE ? "Yes" : "No"); 2836 2837 cli_out("AS (Y or N) - %s\n", 2838 conf->flags & BCM_PORT_PHY_TIMESYNC_8021AS_ENABLE ? "Yes" : "No"); 2839 2840 cli_out("L2 (Y or N) - %s\n", 2841 conf->flags & BCM_PORT_PHY_TIMESYNC_L2_ENABLE ? "Yes" : "No"); 2842 2843 cli_out("IP4 (Y or N) - %s\n", 2844 conf->flags & BCM_PORT_PHY_TIMESYNC_IP4_ENABLE ? "Yes" : "No"); 2845 2846 cli_out("IP6 (Y or N) - %s\n", 2847 conf->flags & BCM_PORT_PHY_TIMESYNC_IP6_ENABLE ? "Yes" : "No"); 2848 2849 cli_out("ExtClock (Y or N) - %s\n", 2850 conf->flags & BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT ? "Yes" : "No"); 2851 2852 cli_out("ITpid = 0x%04x\n", conf->itpid); 2853 2854 cli_out("OTpid = 0x%04x\n", conf->otpid); 2855 2856 cli_out("OriginalTimecodeSeconds = 0x%08x%08x\n", 2857 COMPILER_64_HI(conf->original_timecode.seconds), 2858 COMPILER_64_LO(conf->original_timecode.seconds)); 2859 2860 cli_out("OriginalTimecodeNanoseconds = 0x%08x\n", 2861 conf->original_timecode.nanoseconds); 2862 2863 _print_timesync_gmode("GMode", conf->gmode); 2864 2865 _print_framesync_mode("FramesyncMode", conf->framesync.mode); 2866 2867 _print_syncout_mode("SyncoutMode", conf->syncout.mode); 2868 2869 cli_out("TxOffset = %d\n", conf->tx_timestamp_offset); 2870 2871 cli_out("RxOffset = %d\n", conf->rx_timestamp_offset); 2872 2873 _print_timesync_egress_message_mode("TxSync", conf->tx_sync_mode); 2874 _print_timesync_egress_message_mode("TxDelayReq", 2875 conf->tx_delay_request_mode); 2876 _print_timesync_egress_message_mode("TxPdelayReq", 2877 conf->tx_pdelay_request_mode); 2878 _print_timesync_egress_message_mode("TxPdelayreS", 2879 conf->tx_pdelay_response_mode); 2880 2881 _print_timesync_ingress_message_mode("RxSync", conf->rx_sync_mode); 2882 _print_timesync_ingress_message_mode("RxDelayReq", 2883 conf->rx_delay_request_mode); 2884 _print_timesync_ingress_message_mode("RxPdelayReq", 2885 conf->rx_pdelay_request_mode); 2886 _print_timesync_ingress_message_mode("RxPdelayreS", 2887 conf->rx_pdelay_response_mode); 2888 2889 } 2890 2891 void 2892 _print_inband_timesync_config(bcm_port_phy_timesync_config_t *conf) 2893 { 2894 cli_out("InBand timesync message Sync (Y or N) - %s\n", 2895 ( conf->inband_control.flags 2896 & BCM_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE ) 2897 ? "Yes" : "No"); 2898 cli_out("InBand timesync Delay Request (Y or N) - %s\n", 2899 ( conf->inband_control.flags 2900 & BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE ) 2901 ? "Yes" : "No"); 2902 cli_out("InBand timesync Pdelay Request (Y or N) - %s\n", 2903 ( conf->inband_control.flags 2904 & BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE ) 2905 ? "Yes" : "No"); 2906 cli_out("InBand timesync Pdelay reSponse (Y or N) - %s\n", 2907 ( conf->inband_control.flags 2908 & BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE ) 2909 ? "Yes" : "No"); 2910 cli_out("InBand timesync ID (Resv_0) - 0x%X\n", 2911 conf->inband_control.resv0_id); 2912 cli_out("InBand timesync ID ChecK (Y or N) - %s\n", 2913 ( conf->inband_control.flags 2914 & BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK ) 2915 ? "Yes" : "No"); 2916 cli_out("InBand timesync ID Update (Y or N) - %s\n", 2917 ( conf->inband_control.flags 2918 & BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE ) 2919 ? "Yes" : "No"); 2920 _print_inband_timesync_matching_criterion(conf->inband_control.flags); 2921 2922 cli_out("InBand timesync Follow Up Assist (Y or N) - %s\n", 2923 ( conf->inband_control.flags 2924 & BCM_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST ) 2925 ? "Yes" : "No"); 2926 cli_out("InBand timesync Delay Response Assist (Y or N) - %s\n", 2927 ( conf->inband_control.flags 2928 & BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST ) 2929 ? "Yes" : "No"); 2930 cli_out("InBand timesync Long TimeStamp (Y or N) - %s\n", 2931 ( conf->inband_control.timer_mode 2932 & bcmPortPhyTimesyncTimerMode80bit ) 2933 ? "Yes" : "No"); 2934 } 2935 2936 void 2937 _print_heartbeat_ts(int unit, bcm_port_t port) 2938 { 2939 int rv; 2940 uint64 time; 2941 2942 rv = bcm_port_control_phy_timesync_get(unit, port, 2943 bcmPortControlPhyTimesyncHeartbeatTimestamp, 2944 &time); 2945 2946 if (rv != BCM_E_NONE) { 2947 cli_out("bcm_port_control_phy_timesync_get " 2948 "failed with error u=%d p=%d %s\n", 2949 unit, port, bcm_errmsg(rv)); 2950 } 2951 2952 cli_out("Heartbeat TS = %08x%08x\n", 2953 COMPILER_64_HI(time), COMPILER_64_LO(time)); 2954 } 2955 2956 void 2957 _print_capture_ts(int unit, bcm_port_t port) 2958 { 2959 int rv; 2960 uint64 time; 2961 2962 rv = bcm_port_control_phy_timesync_get(unit, port, 2963 bcmPortControlPhyTimesyncCaptureTimestamp, 2964 &time); 2965 2966 if (rv != BCM_E_NONE) { 2967 cli_out("bcm_port_control_phy_timesync_get " 2968 "failed with error u=%d p=%d %s\n", 2969 unit, port, bcm_errmsg(rv)); 2970 } 2971 2972 cli_out("Capture TS = %08x%08x\n", 2973 COMPILER_64_HI(time), COMPILER_64_LO(time)); 2974 } 2975 2976 2977 2978 2979 2980 2981 #if defined(PHYMOD_SUPPORT) 2982 2983 int 2984 phymod_sym_access(int u, args_t *a, int intermediate, soc_pbmp_t *pbm) 2985 { 2986 phymod_symbols_iter_t iter; 2987 phymod_symbols_t *symbols; 2988 phymod_phy_access_t pm_acc; 2989 int rv, p, dport; 2990 char hdr[32]; 2991 2992 rv = phymod_symop_init(&iter, a); 2993 if (rv != CMD_OK) { 2994 return rv; 2995 } 2996 2997 /* coverity[overrun-local] */ 2998 DPORT_SOC_PBMP_ITER(u, *pbm, dport, p) { 2999 if (phymod_sym_info(u, p, intermediate, &iter, &pm_acc) < 0) { 3000 continue; 3001 } 3002 /* coverity[overrun-local] */ 3003 if (IS_CPRI_PORT(u, p)) { 3004 pm_acc.type = phymodDispatchTypeTscf_gen3; 3005 } 3006 if (phymod_diag_symbols_table_get(&pm_acc, &symbols) < 0) { 3007 continue; 3008 } 3009 /* coverity[illegal_address] */ 3010 rv = sal_snprintf(hdr, sizeof(hdr), "Port %s%s:\n", 3011 SOC_PORT_NAME(u, p), 3012 intermediate ? " (int)" : ""); 3013 if (rv >= sizeof(hdr)) { 3014 continue; 3015 } 3016 rv = phymod_symop_exec(&iter, symbols, &pm_acc, hdr); 3017 if (rv != CMD_OK) { 3018 return rv; 3019 } 3020 } 3021 3022 return phymod_symop_cleanup(&iter); 3023 } 3024 3025 #endif /* defined(PHYMOD_SUPPORT) */ 3026 3027 /* #define INCLUDE_TIMESYNC_DVT_TESTS */ 3028 #ifdef INCLUDE_TIMESYNC_DVT_TESTS 3029 cmd_result_t phy_test1588(int unit, args_t *args, soc_pbmp_t *pbm); 3030 #endif 3031 3032 STATIC cmd_result_t 3033 _if_esw_phy_info(int u, args_t *a) 3034 { 3035 soc_pbmp_t pbm; 3036 soc_port_t p, p1, dport; 3037 char remark[40]; 3038 #if defined(BCM_KATANA2_SUPPORT) 3039 soc_field_t wc_xfi_mode_sel_fld[] = 3040 { WC0_8_XFI_MODE_SELf, WC1_8_XFI_MODE_SELf }; 3041 uint32 wc_xfi_mode_sel_val[2] = { 0 }; 3042 uint32 top_misc_control_1_val = 0; 3043 #endif 3044 3045 remark[0] = '\0'; 3046 #if defined(BCM_KATANA2_SUPPORT) 3047 if (SOC_IS_KATANA2(u) && !SOC_IS_SABER2(u)) { 3048 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r 3049 (u, &top_misc_control_1_val)); 3050 wc_xfi_mode_sel_val[0] = 3051 soc_reg_field_get(u, TOP_MISC_CONTROL_1r, 3052 top_misc_control_1_val, 3053 wc_xfi_mode_sel_fld[0]); 3054 wc_xfi_mode_sel_val[1] = 3055 soc_reg_field_get(u, TOP_MISC_CONTROL_1r, 3056 top_misc_control_1_val, 3057 wc_xfi_mode_sel_fld[1]); 3058 } 3059 #endif 3060 SOC_PBMP_ASSIGN(pbm, PBMP_PORT_ALL(u)); 3061 SOC_PBMP_REMOVE(pbm, PBMP_HG_SUBPORT_ALL(u)); 3062 SOC_PBMP_REMOVE(pbm, PBMP_REQ_ALL(u)); 3063 cli_out("Phy mapping dump:\n"); 3064 cli_out("%10s %5s %5s %5s %5s %23s %17s\n", 3065 "port", "id0", "id1", "addr", "iaddr", "name", "timeout"); 3066 /* Coverity 3067 * DPORT_SOC_PBMP_ITER checks that dport is valid. 3068 */ 3069 /* coverity[overrun-local] */ 3070 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 3071 if (phy_port_info[u] == NULL) { 3072 continue; 3073 } 3074 p1 = p; 3075 #if defined(BCM_KATANA2_SUPPORT) 3076 if (SOC_IS_KATANA2(u) && !SOC_IS_SABER2(u)) { 3077 switch (p) { 3078 case 25: 3079 case 36: 3080 if (wc_xfi_mode_sel_val[0]) { 3081 p1 = (p == 25) ? 32 : 34; 3082 sal_sprintf(remark, "XFI#Int:%d:==>Ext:%d:", p, p1); 3083 } 3084 break; 3085 case 26: 3086 case 39: 3087 if (wc_xfi_mode_sel_val[1]) { 3088 p1 = (p == 26) ? 29 : 31; 3089 sal_sprintf(remark, "XFI#Int:%d:==>Ext:%d:", p, p1); 3090 } 3091 break; 3092 default: 3093 remark[0] = '\0'; 3094 break; 3095 } 3096 } 3097 #endif 3098 3099 #ifdef PORTMOD_SUPPORT 3100 if(soc_feature(u, soc_feature_portmod)) { 3101 phymod_core_access_t core_acc, internal_core; 3102 phymod_core_info_t core_info; 3103 int nof_cores = 0 , an_timeout = -1; 3104 int phy = 0, core_num = 0, is_legacy =0; 3105 int range_start = 0; 3106 int is_first_range; 3107 portmod_port_diag_info_t diag_info; 3108 int diag_rv; 3109 uint8 pcount=0; 3110 char lnstr[32], *pname, namelen; 3111 pm_info_t pm_info; 3112 int mod = 4; 3113 3114 phymod_core_access_t_init(&core_acc); 3115 phymod_core_access_t_init(&internal_core); 3116 phymod_core_info_t_init(&core_info); 3117 sal_memset(&diag_info, 0, sizeof(portmod_port_diag_info_t)); 3118 3119 portmod_port_main_core_access_get(u, p, -1, &core_acc, &nof_cores); 3120 if(nof_cores == 0) { 3121 continue; 3122 } 3123 /* check if the external phy is a legacy phy */ 3124 diag_rv = portmod_port_check_legacy_phy(u, p, &is_legacy); 3125 if (diag_rv) { 3126 continue; 3127 } 3128 3129 portmod_port_main_core_access_get(u, p, 0, &internal_core, &nof_cores); 3130 if(nof_cores == 0) { 3131 continue; 3132 } 3133 3134 diag_rv = portmod_port_diag_info_get(u, p, &diag_info); 3135 if(diag_rv){ 3136 continue; 3137 } 3138 3139 diag_rv = portmod_port_core_num_get(u, p, &core_num); 3140 if (diag_rv){ 3141 continue; 3142 } 3143 3144 diag_rv = portmod_pm_info_get(u, p, &pm_info); 3145 if (diag_rv) { 3146 continue; 3147 } 3148 3149 #ifdef PORTMOD_PM8X50_SUPPORT 3150 if (pm_info->type == portmodDispatchTypePm8x50) { 3151 mod = 8; 3152 } 3153 #endif 3154 is_first_range = TRUE; 3155 PORTMOD_PBMP_ITER(diag_info.phys, phy){ 3156 if( is_first_range ){ 3157 range_start = phy ; 3158 is_first_range = FALSE; 3159 } 3160 } 3161 3162 if (IS_QSGMII_PORT(u, p)) { 3163 range_start = (range_start - 1)/4 + 1; 3164 } 3165 3166 an_timeout = soc_property_port_get(u, p, 3167 spn_PHY_AUTONEG_TIMEOUT, 250000); 3168 #ifdef PORTMOD_CPM4X25_SUPPORT 3169 if (pm_info->type == portmodDispatchTypeCpm4x25) { 3170 pname = "CPRIFA0"; 3171 if (IS_E_PORT(u, p)) { 3172 SOC_IF_ERROR_RETURN 3173 (phymod_core_info_get(&core_acc, &core_info)); 3174 } 3175 } else 3176 #endif 3177 { 3178 if ( !is_legacy ) { 3179 SOC_IF_ERROR_RETURN 3180 (phymod_core_info_get(&core_acc, &core_info)); 3181 } 3182 3183 PORTMOD_PBMP_COUNT(diag_info.phys, pcount); 3184 3185 pname = phymod_core_version_t_mapping[core_info.core_version].key; 3186 } 3187 namelen = strlen(pname); 3188 3189 sal_snprintf(lnstr, sizeof(lnstr), "%s", pname); 3190 sal_snprintf(lnstr+namelen-2, sizeof(lnstr)-(namelen-2), "-%s/%02d/", pname+namelen-2, core_num); 3191 3192 pname = lnstr; 3193 while (*pname != '-') { 3194 *pname = sal_toupper(*pname); 3195 pname++; 3196 } 3197 3198 pname = lnstr+strlen(lnstr); 3199 if (pcount == 8) { 3200 sal_snprintf(pname,sizeof(lnstr), "%d", pcount); 3201 } else if (pcount == 4) { 3202 if (mod == 8) { 3203 sal_snprintf(pname,sizeof(lnstr), "%d-%d", (range_start-1)%mod, ((range_start-1)%mod)+3); 3204 } else { 3205 sal_snprintf(pname,sizeof(lnstr), "%d", pcount); 3206 } 3207 } else if (pcount == 2) { 3208 sal_snprintf(pname,sizeof(lnstr), "%d-%d", (range_start-1)%mod, ((range_start-1)%mod)+1); 3209 } else { 3210 sal_snprintf(pname,sizeof(lnstr), "%d", (range_start-1)%mod); 3211 } 3212 3213 if ( !is_legacy ) { 3214 cli_out("%5s(%3d) %5x %5x %5x %5x %23s %10d %s \n", 3215 SOC_PORT_NAME(u, p), p1, 3216 core_info.phy_id0, 3217 core_info.phy_id1, 3218 core_acc.access.addr, 3219 internal_core.access.addr, 3220 lnstr, an_timeout, 3221 /*soc_phy_an_timeout_get(u, p), */ 3222 remark); 3223 } else { 3224 cli_out("%5s(%3d) %5x %5x %5x %5x %23s %10d %s \n", 3225 SOC_PORT_NAME(u, p), p1, 3226 soc_phy_id0reg_get(u, p), 3227 soc_phy_id1reg_get(u, p), 3228 soc_phy_addr_of_port(u, p), 3229 internal_core.access.addr, 3230 soc_phy_name_get(u, p), 3231 soc_phy_an_timeout_get(u, p), remark); 3232 } 3233 } else 3234 #endif 3235 { 3236 cli_out("%5s(%3d) %5x %5x %5x %5x %23s %10d %s \n", 3237 SOC_PORT_NAME(u, p), p1, 3238 soc_phy_id0reg_get(u, p), 3239 soc_phy_id1reg_get(u, p), 3240 soc_phy_addr_of_port(u, p), 3241 soc_phy_addr_int_of_port(u, p), 3242 soc_phy_name_get(u, p), 3243 soc_phy_an_timeout_get(u, p), remark); 3244 } 3245 } 3246 3247 return CMD_OK; 3248 } 3249 3250 #if defined(PHYMOD_SUPPORT) 3251 STATIC cmd_result_t 3252 _if_esw_phy_phymod(int u, args_t *a) 3253 { 3254 soc_pbmp_t pbm; 3255 soc_port_t p, dport; 3256 char *c; 3257 int rv = 0; 3258 3259 if ((c = ARG_GET(a)) != NULL) { 3260 soc_phymod_ctrl_t *pmc; 3261 soc_phymod_phy_t *phy; 3262 phy_ctrl_t *pc; 3263 int phy_id = sal_ctoi(c, NULL); 3264 #ifdef PORTMOD_SUPPORT 3265 if( sal_strcasecmp(c, "addr") == 0 ) { 3266 if (soc_feature(u, soc_feature_portmod)) { 3267 if ((c = ARG_GET(a)) != NULL) { 3268 phymod_dbg_addr = sal_ctoi(c, NULL); 3269 if ((c = ARG_GET(a)) != NULL) { 3270 phymod_dbg_mask = sal_ctoi(c, NULL); 3271 if ((c = ARG_GET(a)) != NULL) { 3272 phymod_dbg_lane = sal_ctoi(c, NULL); 3273 } else { 3274 phymod_dbg_lane = 0; 3275 } 3276 } 3277 } 3278 cli_out("addr=0x%0x mask=0x%08x lane=%0x", 3279 phymod_dbg_addr, phymod_dbg_mask, phymod_dbg_lane) ; 3280 cli_out("\n"); 3281 } 3282 return CMD_OK; 3283 } 3284 #endif 3285 if (parse_bcm_pbmp(u, c, &pbm) == 0) { 3286 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 3287 if (phy_port_info[u] == NULL) { 3288 continue; 3289 } 3290 #ifdef PORTMOD_SUPPORT 3291 if (soc_feature(u, soc_feature_portmod)) { 3292 if ((c = ARG_GET(a)) != NULL) { 3293 uint16 phyad = 0; 3294 phyad = portmod_port_to_phyaddr(u, p); 3295 phymod_dbg_addr = phyad; 3296 phymod_dbg_mask = sal_ctoi(c, NULL); 3297 if ((c = ARG_GET(a)) != NULL) { 3298 phymod_dbg_lane = sal_ctoi(c, NULL); 3299 } else { 3300 phymod_dbg_lane = 0; 3301 } 3302 } 3303 cli_out("%5s(%3d) %d ", 3304 SOC_PORT_NAME(u, p), p, 3305 SOC_PORT_BINDEX(u, p)); 3306 cli_out("addr=0x%0x mask=0x%08x lane=0x%0x", 3307 phymod_dbg_addr, phymod_dbg_mask, phymod_dbg_lane) ; 3308 } else 3309 #endif 3310 { 3311 pc = INT_PHY_SW_STATE(u, p); 3312 if (pc == NULL) { 3313 continue; 3314 } 3315 if ((c = ARG_GET(a)) != NULL) { 3316 uint16 phyad = 0; 3317 soc_phy_cfg_addr_get(u, p, SOC_PHY_INTERNAL, &phyad); 3318 phymod_dbg_addr = phyad; 3319 phymod_dbg_mask = sal_ctoi(c, NULL); 3320 if ((c = ARG_GET(a)) != NULL) { 3321 phymod_dbg_lane = sal_ctoi(c, NULL); 3322 } else { 3323 phymod_dbg_lane = 0; 3324 } 3325 continue; 3326 } 3327 pmc = &pc->phymod_ctrl; 3328 cli_out("%5s(%3d) %d ", 3329 SOC_PORT_NAME(u, p), p, 3330 SOC_PORT_BINDEX(u, p)); 3331 phy = pmc->phy[0]; 3332 if (phy) { 3333 cli_out("phy(0x%08x)->core(0x%08x) ", 3334 phy->obj.obj_id, 3335 phy->core->obj.obj_id); 3336 } 3337 } 3338 cli_out("\n"); 3339 } 3340 } else { 3341 rv = soc_phymod_phy_create(u, -1, &phy); 3342 if (SOC_SUCCESS(rv)) { 3343 cli_out("phymod ID %d created\n", phy->obj.obj_id); 3344 } 3345 rv = soc_phymod_phy_find_by_id(u, phy_id, &phy); 3346 cli_out("phymod ID %d%s found\n", phy_id, (rv < 0) ? " not" : ""); 3347 } 3348 } 3349 return CMD_OK; 3350 } 3351 #endif /* defined(PHYMOD_SUPPORT) */ 3352 3353 STATIC cmd_result_t 3354 _if_esw_phy_eee(int u, args_t *a) 3355 { 3356 soc_pbmp_t pbm; 3357 soc_port_t p, dport; 3358 char *c; 3359 int rv = 0; 3360 char *str, *latency_str; 3361 uint32 eee_mode_value, eee_auto_mode_value; 3362 uint32 latency, idle = 0, tx_events, tx_duration, rx_events, rx_duration; 3363 uint32 flags; 3364 int i; 3365 parse_table_t pt; 3366 char *mode_type = NULL, *lstr = NULL, *stats = NULL; 3367 int idle_th = -1; 3368 3369 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 3370 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 3371 return CMD_FAIL; 3372 } 3373 3374 if ((c = ARG_CUR(a)) != NULL) { 3375 3376 parse_table_init(u, &pt); 3377 parse_table_add(&pt, "MOde", PQ_DFL | PQ_STRING, 0, &mode_type, 0); 3378 3379 parse_table_add(&pt, "LAtency", PQ_DFL | PQ_STRING, 0, &lstr, 0); 3380 3381 parse_table_add(&pt, "IDle_th", PQ_DFL | PQ_INT, 0, &idle_th, 0); 3382 3383 parse_table_add(&pt, "STats", PQ_DFL | PQ_STRING, 0, &stats, 0); 3384 3385 if (parse_arg_eq(a, &pt) < 0) { 3386 parse_arg_eq_done(&pt); 3387 return CMD_USAGE; 3388 } 3389 if (ARG_CNT(a) > 0) { 3390 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 3391 parse_arg_eq_done(&pt); 3392 return CMD_USAGE; 3393 } 3394 3395 flags = 0; 3396 3397 for (i = 0; i < pt.pt_cnt; i++) { 3398 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 3399 flags |= (1 << i); 3400 } 3401 } 3402 3403 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 3404 3405 if (flags & 0x1) { 3406 3407 if (sal_strcasecmp(mode_type, "native") == 0) { 3408 rv = bcm_port_phy_control_set(u, p, 3409 BCM_PORT_PHY_CONTROL_EEE, 3410 1); 3411 } 3412 if (sal_strcasecmp(mode_type, "auto") == 0) { 3413 rv = bcm_port_phy_control_set(u, p, 3414 BCM_PORT_PHY_CONTROL_EEE_AUTO, 3415 1); 3416 } 3417 if (sal_strcasecmp(mode_type, "none") == 0) { 3418 rv = bcm_port_phy_control_set(u, p, 3419 BCM_PORT_PHY_CONTROL_EEE_AUTO, 3420 0); 3421 rv = bcm_port_phy_control_set(u, p, 3422 BCM_PORT_PHY_CONTROL_EEE, 3423 0); 3424 } 3425 3426 if (rv == BCM_E_NONE) { 3427 cli_out("Port %s EEE mode set to %s EEE mode\n", 3428 SOC_PORT_NAME(u, p), mode_type); 3429 } else { 3430 if (rv == BCM_E_UNAVAIL) { 3431 cli_out("Port %s EEE %s mode not available\n", 3432 SOC_PORT_NAME(u, p), mode_type); 3433 } else { 3434 cli_out("Port %s EEE %s mode set unsuccessful\n", 3435 SOC_PORT_NAME(u, p), mode_type); 3436 } 3437 } 3438 rv = bcm_port_phy_control_get(u, p, 3439 BCM_PORT_PHY_CONTROL_EEE_AUTO, 3440 &eee_auto_mode_value); 3441 if ((rv == BCM_E_NONE) && (eee_auto_mode_value == 1)) { 3442 str = "auto"; 3443 } else { 3444 rv = bcm_port_phy_control_get(u, p, 3445 BCM_PORT_PHY_CONTROL_EEE, 3446 &eee_mode_value); 3447 if (rv == BCM_E_NONE) { 3448 if (eee_mode_value == 0 && eee_auto_mode_value == 0) { 3449 str = "none"; 3450 } else { 3451 str = "native"; 3452 } 3453 } else { 3454 str = "NA"; 3455 } 3456 } 3457 cli_out("Port %s EEE mode = %s\n", SOC_PORT_NAME(u, p), str); 3458 } 3459 3460 if (flags & 0x2) { 3461 if (sal_strcasecmp(lstr, "fixed") == 0) { 3462 rv = bcm_port_phy_control_set(u, p, 3463 BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY, 3464 1); 3465 if (rv != BCM_E_NONE) { 3466 return CMD_FAIL; 3467 } 3468 } 3469 if (sal_strcasecmp(lstr, "variable") == 0) { 3470 rv = bcm_port_phy_control_set(u, p, 3471 BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY, 3472 0); 3473 if (rv != BCM_E_NONE) { 3474 return CMD_FAIL; 3475 } 3476 } 3477 rv = bcm_port_phy_control_get(u, p, 3478 BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY, 3479 &latency); 3480 if (rv == BCM_E_NONE) { 3481 if (latency == 1) { /* AutogrEEEn Ctrl Reg. */ 3482 str = "fixed"; /* bit_2 == 0 */ 3483 } else { 3484 str = "variable"; /* bit_2 == 1 */ 3485 } 3486 cli_out("Port %s EEE Auto mode Latency = %s\n", 3487 SOC_PORT_NAME(u, p), str); 3488 } 3489 } 3490 3491 if (flags & 0x4) { 3492 if ((rv = 3493 bcm_port_phy_control_set(u, p, 3494 BCM_PORT_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD, 3495 idle_th)) != BCM_E_NONE) { 3496 return CMD_FAIL; 3497 } 3498 if ((rv = bcm_port_phy_control_get(u, p, 3499 BCM_PORT_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD, 3500 &idle)) != BCM_E_NONE) { 3501 return CMD_FAIL; 3502 } 3503 cli_out("Port %s EEE Auto mode IDLE Threshold = %d\n", 3504 SOC_PORT_NAME(u, p), idle); 3505 } 3506 3507 if (flags & 0x8) { 3508 if (sal_strcasecmp(stats, "get") == 0) { 3509 (void)bcm_port_phy_control_get(u, p, 3510 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_EVENTS, 3511 &tx_events); 3512 (void)bcm_port_phy_control_get(u, p, 3513 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_DURATION, 3514 &tx_duration); 3515 (void)bcm_port_phy_control_get(u, p, 3516 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_EVENTS, 3517 &rx_events); 3518 (void)bcm_port_phy_control_get(u, p, 3519 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_DURATION, 3520 &rx_duration); 3521 cli_out("Port %s Tx events = %u TX Duration = %u " 3522 "RX events = %u RX Duration = %u\n", 3523 SOC_PORT_NAME(u, p), tx_events, 3524 tx_duration, rx_events, rx_duration); 3525 } 3526 if (sal_strcasecmp(stats, "clear") == 0) { 3527 (void)bcm_port_phy_control_set(u, p, 3528 BCM_PORT_PHY_CONTROL_EEE_STATISTICS_CLEAR, 3529 1); 3530 cli_out("Port %s Statistics Cleared \n", 3531 SOC_PORT_NAME(u, p)); 3532 } 3533 3534 if (sal_strcasecmp(stats, "all") == 0) { 3535 (void)bcm_port_phy_control_get(u, p, 3536 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_EVENTS, 3537 &tx_events); 3538 (void)bcm_port_phy_control_get(u, p, 3539 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_DURATION, 3540 &tx_duration); 3541 (void)bcm_port_phy_control_get(u, p, 3542 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_EVENTS, 3543 &rx_events); 3544 rv = bcm_port_phy_control_get(u, p, 3545 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_DURATION, 3546 &rx_duration); 3547 if (rv == BCM_E_NONE) { 3548 cli_out("Port %s EEE Statistics\n", 3549 SOC_PORT_NAME(u, p)); 3550 cli_out("\tEEE Transmit Events\t%u\n" , tx_events); 3551 cli_out("\tEEE Transmit Duration\t%u\n", tx_duration); 3552 cli_out("\tEEE Receive Events\t%u\n" , rx_events); 3553 cli_out("\tEEE Receive Duration\t%u\n", rx_duration); 3554 } 3555 } 3556 } 3557 } 3558 /* free allocated memory from arg parsing */ 3559 parse_arg_eq_done(&pt); 3560 } else { 3561 3562 cli_out("EEE Details:\n"); 3563 cli_out("%10s %16s %16s %14s %14s\n", 3564 "port", "name", "eee mode", "latency mode", 3565 "Idle Threshold(ms)"); 3566 /* coverity[overrun-local] */ 3567 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 3568 latency_str = "NA"; 3569 idle = 0; 3570 3571 if ((rv = 3572 bcm_port_phy_control_get(u, p, 3573 BCM_PORT_PHY_CONTROL_EEE_AUTO, 3574 &eee_auto_mode_value)) == 3575 BCM_E_FAIL) { 3576 cli_out("Phy control get: " 3577 "BCM_PORT_PHY_CONTROL_EEE_AUTO failed\n"); 3578 return BCM_E_FAIL; 3579 } 3580 if ((rv == BCM_E_NONE) && (eee_auto_mode_value == 1)) { 3581 str = "auto"; 3582 rv = bcm_port_phy_control_get(u, p, 3583 BCM_PORT_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY, 3584 &latency); 3585 if (rv == BCM_E_NONE) { 3586 if (latency == 1) { /* AutogrEEEn Ctrl Reg. */ 3587 latency_str = "fixed"; /* bit_2 == 0 */ 3588 } else { 3589 latency_str = "variable"; /* bit_2 == 1 */ 3590 } 3591 } else { 3592 latency_str = "NA"; 3593 } 3594 rv = bcm_port_phy_control_get(u, p, 3595 BCM_PORT_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD, 3596 &idle); 3597 if (rv != BCM_E_NONE) { 3598 idle = 0; 3599 } 3600 } else { 3601 if ((rv = 3602 bcm_port_phy_control_get(u, p, 3603 BCM_PORT_PHY_CONTROL_EEE, 3604 &eee_mode_value)) == 3605 BCM_E_FAIL) { 3606 cli_out("Phy control get: " 3607 "BCM_PORT_PHY_CONTROL_EEE failed\n"); 3608 return BCM_E_FAIL; 3609 } 3610 if (eee_mode_value == 1) { 3611 str = "native"; 3612 } else { 3613 str = "none"; 3614 } 3615 } 3616 /* coverity[illegal_address] */ 3617 cli_out("%5s(%3d) %16s %14s %14s %10d\n", 3618 SOC_PORT_NAME(u, p), p, 3619 soc_phy_name_get(u, p), str, latency_str, idle); 3620 } 3621 } 3622 return CMD_OK; 3623 } 3624 3625 STATIC cmd_result_t 3626 _if_esw_phy_timesync(int u, args_t *a) 3627 { 3628 soc_pbmp_t pbm; 3629 soc_port_t p, dport; 3630 char *c; 3631 int i, rv = 0; 3632 bcm_port_phy_timesync_config_t conf; 3633 uint64 val64; 3634 3635 sal_memset(&conf, 0, sizeof(conf)); 3636 3637 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 3638 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 3639 return CMD_FAIL; 3640 } 3641 if ((c = ARG_CUR(a)) != NULL) { 3642 parse_table_t pt; 3643 uint32 enable, capture_ts, heartbeat_ts, rx_crc, as, l2, ip4, ip6, ec, /* bool */ 3644 itpid, otpid, tx_offset, rx_offset, original_timecode_seconds, 3645 original_timecode_nanoseconds, load_all, frame_sync, flags, 3646 flags_2, ibts_sync = 0; 3647 uint32 ibts_dreq = 0, ibts_pdreq = 0, ibts_pdrsp = 0, 3648 ibts_resv_id_chk = 0, ibts_resv_id_upd = 0, ibts_resv_id = 0, 3649 ibts_upd_fu = 0, ibts_upd_drsp = 0, ibts_longts = 0; 3650 char *gmode_str = NULL, *tx_sync_mode_str = NULL, 3651 *tx_delay_request_mode_str = NULL, 3652 *tx_pdelay_request_mode_str = NULL, 3653 *tx_pdelay_response_mode_str = NULL, *rx_sync_mode_str = NULL, 3654 *rx_delay_request_mode_str = NULL, 3655 *rx_pdelay_request_mode_str = NULL, 3656 *rx_pdelay_response_mode_str = NULL, *framesync_mode_str = NULL, 3657 *syncout_mode_str = NULL, *ibts_match = NULL; 3658 3659 parse_table_init(u, &pt); 3660 parse_table_add(&pt, "ENable", 3661 PQ_BOOL | PQ_DFL | 3662 PQ_NO_EQ_OPT, 0, 3663 &enable, 0); /* index 0 */ 3664 parse_table_add(&pt, "CaptureTS", 3665 PQ_BOOL | PQ_DFL | 3666 PQ_NO_EQ_OPT, 0, 3667 &capture_ts, 0); /* index 1 */ 3668 parse_table_add(&pt, "HeartbeatTS", 3669 PQ_BOOL | PQ_DFL | 3670 PQ_NO_EQ_OPT, 0, 3671 &heartbeat_ts, 0); /* index 2 */ 3672 parse_table_add(&pt, "RxCrc", 3673 PQ_BOOL | PQ_DFL | 3674 PQ_NO_EQ_OPT, 0, 3675 &rx_crc, 0); /* index 3 */ 3676 parse_table_add(&pt, "AS", 3677 PQ_BOOL | PQ_DFL | 3678 PQ_NO_EQ_OPT, 0, 3679 &as, 0); /* index 4 */ 3680 parse_table_add(&pt, "L2", 3681 PQ_BOOL | PQ_DFL | 3682 PQ_NO_EQ_OPT, 0, 3683 &l2, 0); /* index 5 */ 3684 parse_table_add(&pt, "IP4", 3685 PQ_BOOL | PQ_DFL | 3686 PQ_NO_EQ_OPT, 0, 3687 &ip4, 0); /* index 6 */ 3688 parse_table_add(&pt, "IP6", 3689 PQ_BOOL | PQ_DFL | 3690 PQ_NO_EQ_OPT, 0, 3691 &ip6, 0); /* index 7 */ 3692 parse_table_add(&pt, "ExtClock", 3693 PQ_BOOL | PQ_DFL | 3694 PQ_NO_EQ_OPT, 0, 3695 &ec, 0); /* index 8 */ 3696 parse_table_add(&pt, "ITpid", 3697 PQ_DFL | PQ_INT, 0, 3698 &itpid, 0); /* index 9 */ 3699 parse_table_add(&pt, "OTpid", 3700 PQ_DFL | PQ_INT, 3701 0, &otpid, 0); /* index 10 */ 3702 parse_table_add(&pt, "GMode", 3703 PQ_DFL | PQ_STRING, 3704 0, &gmode_str, 0); /* index 11 */ 3705 parse_table_add(&pt, "TxOffset", 3706 PQ_DFL | PQ_INT, 3707 0, &tx_offset, 0); /* index 12 */ 3708 parse_table_add(&pt, "RxOffset", 3709 PQ_DFL | PQ_INT, 3710 0, &rx_offset, 0); /* index 13 */ 3711 parse_table_add(&pt, "TxSync", 3712 PQ_DFL | PQ_STRING, 3713 0, &tx_sync_mode_str, 0); /* index 14 */ 3714 parse_table_add(&pt, "TxDelayReq", 3715 PQ_DFL | PQ_STRING, 3716 0, &tx_delay_request_mode_str, 3717 0); /* index 15 */ 3718 parse_table_add(&pt, "TxPdelayReq", 3719 PQ_DFL | PQ_STRING, 3720 0, &tx_pdelay_request_mode_str, 3721 0); /* index 16 */ 3722 parse_table_add(&pt, "TxPdelayreS", 3723 PQ_DFL | PQ_STRING, 3724 0, &tx_pdelay_response_mode_str, 3725 0); /* index 17 */ 3726 parse_table_add(&pt, "RxSync", 3727 PQ_DFL | PQ_STRING, 3728 0, &rx_sync_mode_str, 0); /* index 18 */ 3729 parse_table_add(&pt, "RxDelayReq", 3730 PQ_DFL | PQ_STRING, 3731 0, &rx_delay_request_mode_str, 3732 0); /* index 19 */ 3733 parse_table_add(&pt, "RxPdelayReq", 3734 PQ_DFL | PQ_STRING, 3735 0, &rx_pdelay_request_mode_str, 3736 0); /* index 20 */ 3737 parse_table_add(&pt, "RxPdelayreS", 3738 PQ_DFL | PQ_STRING, 3739 0, &rx_pdelay_response_mode_str, 3740 0); /* index 21 */ 3741 parse_table_add(&pt, "OriginalTimecodeSeconds", 3742 PQ_DFL | PQ_INT, 3743 0, &original_timecode_seconds, 3744 0); /* index 22 */ 3745 parse_table_add(&pt, "OriginalTimecodeNanoseconds", 3746 PQ_DFL | PQ_INT, 3747 0, &original_timecode_nanoseconds, 3748 0); /* index 23 */ 3749 parse_table_add(&pt, "FramesyncMode", 3750 PQ_DFL | PQ_STRING, 3751 0, &framesync_mode_str, 0); /* index 24 */ 3752 parse_table_add(&pt, "SyncoutMode", 3753 PQ_DFL | PQ_STRING, 3754 0, &syncout_mode_str, 0); /* index 25 */ 3755 parse_table_add(&pt, "LoadAll", 3756 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3757 0, &load_all, 0); /* index 26 */ 3758 parse_table_add(&pt, "FrameSync", 3759 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3760 0, &frame_sync, 0); /* index 27 */ 3761 parse_table_add(&pt, "InBandSync", 3762 PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, 3763 0, &ibts_sync, 0); /* index 28 */ 3764 parse_table_add(&pt, "InBandDelayRequest", 3765 PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, 3766 0, &ibts_dreq, 0); /* index 29 */ 3767 parse_table_add(&pt, "InBandPdelayRequest", 3768 PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, 3769 0, &ibts_pdreq, 0); /* index 30 */ 3770 parse_table_add(&pt, "InBandPdelayreSponse", 3771 PQ_DFL | PQ_BOOL | PQ_NO_EQ_OPT, 3772 0, &ibts_pdrsp, 0); /* index 31 */ 3773 parse_table_add(&pt, "InBandID", 3774 PQ_DFL | PQ_INT, 0, &ibts_resv_id, 3775 0); /* flag_2 index 0 */ 3776 parse_table_add(&pt, "InBandIDCheck", 3777 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3778 0, &ibts_resv_id_chk, 0); /* flag_2 index 1 */ 3779 parse_table_add(&pt, "InBandIDUpdate", 3780 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3781 0, &ibts_resv_id_upd, 0); /* flag_2 index 2 */ 3782 parse_table_add(&pt, "InBandMATch", 3783 PQ_DFL | PQ_STRING, "none", 3784 &ibts_match, 0); /* flag_2 index 3 */ 3785 parse_table_add(&pt, "InBandFollowUpAssist", 3786 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3787 0, &ibts_upd_fu, 0); 3788 parse_table_add(&pt, "InBandDelayRespAssist", 3789 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3790 0, &ibts_upd_drsp, 0); 3791 parse_table_add(&pt, "InBandLongTimeStamp", 3792 PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 3793 0, &ibts_longts, 0); 3794 3795 if (parse_arg_eq(a, &pt) < 0) { 3796 parse_arg_eq_done(&pt); 3797 return CMD_USAGE; 3798 } 3799 if (ARG_CNT(a) > 0) { 3800 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 3801 parse_arg_eq_done(&pt); 3802 return CMD_USAGE; 3803 } 3804 3805 flags = 0; 3806 flags_2 = 0; 3807 3808 for (i = 0; i < pt.pt_cnt; i++) { 3809 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 3810 if (i >= (sizeof(flags) * 8)) { 3811 flags_2 |= (1 << (i - (sizeof(flags) * 8))); 3812 } else { 3813 flags |= (1 << i); 3814 } 3815 3816 } 3817 } 3818 3819 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 3820 conf.validity_mask = 3821 0xffffffff & (~(BCM_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL)); 3822 if ((rv = 3823 bcm_port_phy_timesync_config_get(u, p, 3824 &conf)) == BCM_E_FAIL) { 3825 cli_out("bcm_port_phy_timesync_config_get() " 3826 "failed, u=%d, p=%d\n", u, p); 3827 parse_arg_eq_done(&pt); 3828 return BCM_E_FAIL; 3829 } 3830 3831 conf.validity_mask &= 3832 ~BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 3833 3834 if (flags & (1U << 0)) { 3835 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_ENABLE; 3836 conf.flags |= enable ? BCM_PORT_PHY_TIMESYNC_ENABLE : 0; 3837 } 3838 3839 if (flags & (1U << 1)) { 3840 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 3841 conf.flags |= 3842 capture_ts ? BCM_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE : 3843 0; 3844 } 3845 3846 if (flags & (1U << 2)) { 3847 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 3848 conf.flags |= 3849 heartbeat_ts ? BCM_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE 3850 : 0; 3851 } 3852 3853 if (flags & (1U << 3)) { 3854 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 3855 conf.flags |= 3856 rx_crc ? BCM_PORT_PHY_TIMESYNC_RX_CRC_ENABLE : 0; 3857 } 3858 3859 if (flags & (1U << 4)) { 3860 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_8021AS_ENABLE; 3861 conf.flags |= as ? BCM_PORT_PHY_TIMESYNC_8021AS_ENABLE : 0; 3862 } 3863 3864 if (flags & (1U << 5)) { 3865 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_L2_ENABLE; 3866 conf.flags |= l2 ? BCM_PORT_PHY_TIMESYNC_L2_ENABLE : 0; 3867 } 3868 3869 if (flags & (1U << 6)) { 3870 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_IP4_ENABLE; 3871 conf.flags |= ip4 ? BCM_PORT_PHY_TIMESYNC_IP4_ENABLE : 0; 3872 } 3873 3874 if (flags & (1U << 7)) { 3875 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_IP6_ENABLE; 3876 conf.flags |= ip6 ? BCM_PORT_PHY_TIMESYNC_IP6_ENABLE : 0; 3877 } 3878 3879 if (flags & (1U << 8)) { 3880 conf.flags &= ~BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 3881 conf.flags |= ec ? BCM_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT : 0; 3882 } 3883 3884 if (flags & (1U << 9)) { 3885 conf.itpid = itpid; 3886 } 3887 3888 if (flags & (1U << 10)) { 3889 conf.otpid = otpid; 3890 } 3891 3892 if (flags & (1U << 11)) { 3893 conf.gmode = 3894 _convert_timesync_gmode_str(gmode_str, conf.gmode); 3895 } 3896 3897 if (flags & (1U << 12)) { 3898 conf.tx_timestamp_offset = tx_offset; 3899 } 3900 3901 if (flags & (1U << 13)) { 3902 conf.rx_timestamp_offset = rx_offset; 3903 } 3904 3905 if (flags & (1U << 14)) { 3906 conf.tx_sync_mode = 3907 _convert_timesync_egress_message_str(tx_sync_mode_str, 3908 conf.tx_sync_mode); 3909 } 3910 3911 if (flags & (1U << 15)) { 3912 conf.tx_delay_request_mode = 3913 _convert_timesync_egress_message_str 3914 (tx_delay_request_mode_str, conf.tx_delay_request_mode); 3915 } 3916 3917 if (flags & (1U << 16)) { 3918 conf.tx_pdelay_request_mode = 3919 _convert_timesync_egress_message_str 3920 (tx_pdelay_request_mode_str, 3921 conf.tx_pdelay_request_mode); 3922 } 3923 3924 if (flags & (1U << 17)) { 3925 conf.tx_pdelay_response_mode = 3926 _convert_timesync_egress_message_str 3927 (tx_pdelay_response_mode_str, 3928 conf.tx_pdelay_response_mode); 3929 } 3930 3931 if (flags & (1U << 18)) { 3932 conf.rx_sync_mode = 3933 _convert_timesync_ingress_message_str(rx_sync_mode_str, 3934 conf. 3935 rx_sync_mode); 3936 } 3937 3938 if (flags & (1U << 19)) { 3939 conf.rx_delay_request_mode = 3940 _convert_timesync_ingress_message_str 3941 (rx_delay_request_mode_str, conf.rx_delay_request_mode); 3942 } 3943 3944 if (flags & (1U << 20)) { 3945 conf.rx_pdelay_request_mode = 3946 _convert_timesync_ingress_message_str 3947 (rx_pdelay_request_mode_str, 3948 conf.rx_pdelay_request_mode); 3949 } 3950 3951 if (flags & (1U << 21)) { 3952 conf.rx_pdelay_response_mode = 3953 _convert_timesync_ingress_message_str 3954 (rx_pdelay_response_mode_str, 3955 conf.rx_pdelay_response_mode); 3956 } 3957 3958 if (flags & (1U << 22)) { 3959 3960 COMPILER_64_SET(conf.original_timecode.seconds, 0, 3961 original_timecode_seconds); 3962 } 3963 3964 if (flags & (1U << 23)) { 3965 conf.original_timecode.nanoseconds = 3966 original_timecode_nanoseconds; 3967 } 3968 3969 if (flags & (1U << 24)) { 3970 conf.framesync.mode = 3971 _convert_framesync_mode_str(framesync_mode_str, 3972 conf.framesync.mode); 3973 } 3974 3975 if (flags & (1U << 25)) { 3976 conf.syncout.mode = 3977 _convert_syncout_mode_str(syncout_mode_str, 3978 conf.syncout.mode); 3979 } 3980 if (flags & (1U << 28)) { 3981 conf.validity_mask |= 3982 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 3983 conf.inband_control.flags &= 3984 ~BCM_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE; 3985 conf.inband_control.flags |= 3986 ibts_sync ? BCM_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE 3987 : 0; 3988 } 3989 if (flags & (1U << 29)) { 3990 conf.validity_mask |= 3991 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 3992 conf.inband_control.flags &= 3993 ~BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE; 3994 conf.inband_control.flags |= 3995 ibts_dreq ? 3996 BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE : 0; 3997 } 3998 if (flags & (1U << 30)) { 3999 conf.validity_mask |= 4000 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4001 conf.inband_control.flags &= 4002 ~BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE; 4003 conf.inband_control.flags |= 4004 ibts_pdreq ? 4005 BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE : 0; 4006 } 4007 if (flags & (1U << 31)) { 4008 conf.validity_mask |= 4009 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4010 conf.inband_control.flags &= 4011 ~BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE; 4012 conf.inband_control.flags |= 4013 ibts_pdrsp ? 4014 BCM_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE : 0; 4015 } 4016 if (flags_2 & (1U << 0)) { 4017 conf.validity_mask |= 4018 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4019 conf.inband_control.resv0_id = ibts_resv_id; 4020 } 4021 if (flags_2 & (1U << 1)) { 4022 conf.validity_mask |= 4023 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4024 conf.inband_control.flags &= 4025 ~BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK; 4026 conf.inband_control.flags |= 4027 ibts_resv_id_chk ? 4028 BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK : 0; 4029 } 4030 if (flags_2 & (1U << 2)) { 4031 conf.validity_mask |= 4032 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4033 conf.inband_control.flags &= 4034 ~BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE; 4035 conf.inband_control.flags |= 4036 ibts_resv_id_upd ? 4037 BCM_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE : 0; 4038 } 4039 if (flags_2 & (1U << 3)) { 4040 conf.validity_mask |= 4041 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4042 _set_inband_timesync_matching_criterion(ibts_match, 4043 &conf.inband_control.flags); 4044 } 4045 if (flags_2 & (1U << 4)) { 4046 conf.validity_mask |= 4047 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4048 conf.inband_control.flags &= 4049 (~BCM_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST); 4050 conf.inband_control.flags |= ( ibts_upd_fu ) ? 4051 BCM_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST : 0; 4052 } 4053 if (flags_2 & (1U << 5)) { 4054 conf.validity_mask |= 4055 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4056 conf.inband_control.flags &= 4057 (~BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST); 4058 conf.inband_control.flags |= ( ibts_upd_drsp ) ? 4059 BCM_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST : 0; 4060 } 4061 if (flags_2 & (1U << 6)) { 4062 conf.validity_mask |= 4063 BCM_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL; 4064 conf.inband_control.timer_mode &= 4065 (~bcmPortPhyTimesyncTimerMode80bit); 4066 conf.inband_control.timer_mode |= ( ibts_longts ) ? 4067 bcmPortPhyTimesyncTimerMode80bit : 0; 4068 } 4069 4070 conf.validity_mask = 4071 0xffffffff & ~BCM_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL; 4072 4073 if ((rv = 4074 bcm_port_phy_timesync_config_set(u, p, 4075 &conf)) == BCM_E_FAIL) { 4076 cli_out("bcm_port_phy_timesync_config_set() " 4077 "failed, u=%d, p=%d\n", u, p); 4078 parse_arg_eq_done(&pt); 4079 return BCM_E_FAIL; 4080 } 4081 if (flags & (1U << 26)) { 4082 COMPILER_64_SET(val64, 0, 0xaaaaaaaa); 4083 rv = bcm_port_control_phy_timesync_set(u, p, 4084 bcmPortControlPhyTimesyncLoadControl, 4085 val64); 4086 if (rv != BCM_E_NONE) { 4087 cli_out("bcm_port_control_phy_timesync_set failed " 4088 "with error u=%d p=%d %s\n", 4089 u, p, bcm_errmsg(rv)); 4090 } 4091 } 4092 if (flags & (1U << 27)) { 4093 COMPILER_64_SET(val64, 0, 1); 4094 rv = bcm_port_control_phy_timesync_set(u, p, 4095 bcmPortControlPhyTimesyncFrameSync, 4096 val64); 4097 if (rv != BCM_E_NONE) { 4098 cli_out("bcm_port_control_phy_timesync_set failed " 4099 "with error u=%d p=%d %s\n", 4100 u, p, bcm_errmsg(rv)); 4101 } 4102 } 4103 4104 } 4105 4106 /* free allocated memory from arg parsing */ 4107 parse_arg_eq_done(&pt); 4108 4109 } else { 4110 4111 /* coverity[overrun-local] */ 4112 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 4113 int offset; 4114 4115 /* coverity[unchecked_value] */ 4116 soc_phyctrl_offset_get(u, p, &offset); /* return value not checked on purpose */ 4117 4118 cli_out("IEEE-1588 settings for %s(%03d) %s, offset=%d\n", 4119 SOC_PORT_NAME(u, p), p, soc_phy_name_get(u, p), offset); 4120 4121 conf.validity_mask = 4122 0xffffffff & ~BCM_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL; 4123 if ((rv = 4124 bcm_port_phy_timesync_config_get(u, p, 4125 &conf)) == BCM_E_FAIL) { 4126 cli_out("bcm_port_phy_timesync_config_get() " 4127 "failed, u=%d, p=%d\n", u, p); 4128 return BCM_E_FAIL; 4129 } 4130 _print_timesync_config(&conf); 4131 _print_inband_timesync_config(&conf); 4132 _print_heartbeat_ts(u, p); 4133 _print_capture_ts(u, p); 4134 /*_print_enhanced_capture(u, p);*/ 4135 } 4136 4137 } 4138 return CMD_OK; 4139 } 4140 4141 #ifdef INCLUDE_PHY_SYM_DBG 4142 /* 4143 * Interface to PHY GUI for debugging 4144 */ 4145 /* 4146 * MDIO Message format 4147 */ 4148 typedef struct phy_sym_dbg_mdio_msg_s { 4149 uint8 op; 4150 uint8 port_id; 4151 uint8 device; 4152 uint8 c45; 4153 uint16 reg_addr; 4154 uint16 data; 4155 } phy_sym_dbg_mdio_msg_t; 4156 4157 enum phy_sum_dbg_mdio_op { 4158 MDIO_HANDSHAKE, 4159 MDIO_WRITE, 4160 MDIO_READ, 4161 MDIO_RESP, 4162 MDIO_ERROR, 4163 MDIO_CLOSE 4164 }; 4165 #define PHY_SYM_DBG_MDIO_MSG_LEN sizeof(phy_sym_dbg_mdio_msg_t) 4166 4167 typedef struct sym_dbg_s { 4168 int unit; 4169 int tcpportnum; 4170 sal_mutex_t sym_dbg_lock; 4171 int flags; 4172 } sym_dbg_t; 4173 4174 sym_dbg_t sym_dbg_arg; 4175 4176 #define SYM_DBG_LOCK(sym_dbg_arg) sal_mutex_take(sym_dbg_arg.sym_dbg_lock, \ 4177 sal_mutex_FOREVER) 4178 #define SYM_DBG_UNLOCK(sym_dbg_arg) sal_mutex_give(sym_dbg_arg.sym_dbg_lock) 4179 4180 #define SYM_DBG_THREAD_START 1 4181 #define SYM_DBG_THREAD_STOP 2 4182 4183 #define PHY_SYM_DBG_DEBUG_PRINT 0 4184 4185 static void 4186 _phy_sym_debug_server(void *unit) 4187 { 4188 int sockfd, newsockfd, clilen; 4189 struct sockaddr_in serv_addr, client_addr; 4190 phy_sym_dbg_mdio_msg_t buffer, mdio_rsp; 4191 uint16 phy_data, reg_addr, data; 4192 int n, rv = 0; 4193 int u, tcpportno; 4194 int flags = 0; 4195 struct timeval tout; 4196 fd_set sock_fdset; 4197 int i; 4198 4199 /* Not yet initialized */ 4200 SYM_DBG_LOCK(sym_dbg_arg); 4201 flags = sym_dbg_arg.flags; 4202 SYM_DBG_UNLOCK(sym_dbg_arg); 4203 4204 if (!(flags & SYM_DBG_THREAD_START)) { 4205 sal_thread_exit(-1); 4206 } 4207 4208 u = sym_dbg_arg.unit; 4209 tcpportno = sym_dbg_arg.tcpportnum; 4210 4211 sockfd = socket(AF_INET, SOCK_STREAM, 0); 4212 if (sockfd < 0) { 4213 cli_out("Error opeing a socket\n"); 4214 sal_thread_exit(-1); 4215 } 4216 bzero((char *)&serv_addr, sizeof(serv_addr)); 4217 serv_addr.sin_family = AF_INET; 4218 serv_addr.sin_addr.s_addr = INADDR_ANY; 4219 serv_addr.sin_port = htons(tcpportno); 4220 4221 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { 4222 cli_out("Error: socket bind falied\n"); 4223 close(sockfd); 4224 sal_thread_exit(-1); 4225 } 4226 cli_out("Listening on the port %d for client connection\n", tcpportno); 4227 4228 listen(sockfd, 1); 4229 clilen = sizeof(client_addr); 4230 cli_out("accepting on the socket %d for client connection\n", sockfd); 4231 4232 while (1) { 4233 FD_ZERO(&sock_fdset); 4234 FD_SET(sockfd, &sock_fdset); 4235 newsockfd = -1; 4236 do { 4237 #if PHY_SYM_DBG_DEBUG_PRINT 4238 cli_out("Calling select\n"); 4239 #endif 4240 4241 tout.tv_sec = 20; /* 5 seconds */ 4242 tout.tv_usec = 0; 4243 newsockfd = select(FD_SETSIZE, 4244 &sock_fdset, &sock_fdset, NULL, &tout); 4245 4246 #if PHY_SYM_DBG_DEBUG_PRINT 4247 cli_out("Returned from select %d\n", newsockfd); 4248 #endif 4249 SYM_DBG_LOCK(sym_dbg_arg); 4250 if (sym_dbg_arg.flags & SYM_DBG_THREAD_STOP) { 4251 cli_out("Closing Socket, user aborted\n"); 4252 close(sockfd); 4253 sal_thread_exit(-1); 4254 } 4255 SYM_DBG_UNLOCK(sym_dbg_arg); 4256 } while (newsockfd <= 0); 4257 4258 #if PHY_SYM_DBG_DEBUG_PRINT 4259 cli_out("Select returned \n"); 4260 #endif 4261 newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, 4262 (socklen_t *) & clilen); 4263 if (newsockfd < 0) { 4264 cli_out("Error in socket accept \n"); 4265 close(sockfd); 4266 sal_thread_exit(-1); 4267 } 4268 #if PHY_SYM_DBG_DEBUG_PRINT 4269 cli_out("Accepted Client connection %d\n", newsockfd); 4270 #endif 4271 4272 #if 0 4273 bzero(&buffer, PHY_SYM_DBG_MDIO_MSG_LEN); 4274 n = recv(newsockfd, &buffer, PHY_SYM_DBG_MDIO_MSG_LEN, 0); 4275 if ((n < 0) || (n < PHY_SYM_DBG_MDIO_MSG_LEN)) { 4276 cli_out("Error reading from socket \n"); 4277 rv = -1; 4278 goto sock_close; 4279 } 4280 if (buffer.op != MDIO_HANDSHAKE) { 4281 cli_out("Unknown connection, Handshake not " 4282 "received: Closing Socket\n"); 4283 rv = -1; 4284 goto sock_close; 4285 } 4286 4287 /* Sending back the handshake */ 4288 bzero(&mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN); 4289 mdio_rsp.op = MDIO_HANDSHAKE; 4290 n = send(newsockfd, &mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN, 0); 4291 if (n < 0) { 4292 cli_out("Handshake:Error writing to socket\n"); 4293 rv = -1; 4294 goto sock_close; 4295 } 4296 cli_out("Handshake with client completed\n"); 4297 #endif 4298 while (1) { 4299 /* Check if the thread needs to be aborted */ 4300 SYM_DBG_LOCK(sym_dbg_arg); 4301 if (sym_dbg_arg.flags & SYM_DBG_THREAD_STOP) { 4302 break; 4303 } 4304 SYM_DBG_UNLOCK(sym_dbg_arg); 4305 bzero((char *)&buffer, PHY_SYM_DBG_MDIO_MSG_LEN); 4306 n = recv(newsockfd, (void *)&buffer, PHY_SYM_DBG_MDIO_MSG_LEN, 0); 4307 #if PHY_SYM_DBG_DEBUG_PRINT 4308 cli_out("Size read %d %d\n", n, PHY_SYM_DBG_MDIO_MSG_LEN); 4309 #endif 4310 if (n > 0) { 4311 for (i = 0; i < n; i++) { 4312 #if PHY_SYM_DBG_DEBUG_PRINT 4313 cli_out("%x ", *(((char *)&buffer) + i)); 4314 #endif 4315 } 4316 } 4317 if ((n < 0) || (n < PHY_SYM_DBG_MDIO_MSG_LEN)) { 4318 cli_out("MDIO message corrupted or garbage read" 4319 " from socket: Closing socket\n"); 4320 break; 4321 } 4322 reg_addr = ntohs(buffer.reg_addr); 4323 data = ntohs(buffer.data); 4324 4325 bzero((char *)&mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN); 4326 if (buffer.op == MDIO_WRITE) { 4327 #if PHY_SYM_DBG_DEBUG_PRINT 4328 cli_out("MDIO WRITE operation\n"); 4329 cli_out("%x %x %x %x %x\n", buffer.port_id, buffer.device, 4330 reg_addr, buffer.c45, data); 4331 #endif 4332 if (buffer.c45) { 4333 rv = soc_miimc45_write(u, buffer.port_id, buffer.device, 4334 reg_addr, data); 4335 /* Read the register */ 4336 if (rv >= 0) { 4337 rv = soc_miimc45_read(u, buffer.port_id, buffer.device, 4338 reg_addr, &phy_data); 4339 } 4340 } else { 4341 rv = soc_miim_write(u, buffer.port_id, reg_addr, data); 4342 /* Read the register */ 4343 if (rv >= 0) { 4344 rv = soc_miim_read(u, buffer.port_id, reg_addr, 4345 &phy_data); 4346 #if PHY_SYM_DBG_DEBUG_PRINT 4347 cli_out("read data = %x\n", phy_data); 4348 #endif 4349 } 4350 } 4351 if (rv < 0) { 4352 cli_out("ERROR: MII Addr %d: soc_miim_write failed: %s\n", 4353 buffer.port_id, soc_errmsg(rv)); 4354 rv = -1; 4355 break; 4356 } 4357 mdio_rsp.data = htons(phy_data); 4358 mdio_rsp.op = MDIO_RESP; 4359 } else { 4360 if (buffer.op == MDIO_READ) { 4361 #if PHY_SYM_DBG_DEBUG_PRINT 4362 cli_out("MDIO READ operation\n"); 4363 cli_out("%x %x %x %x %x\n", buffer.port_id, buffer.device, 4364 reg_addr, buffer.c45, data); 4365 #endif 4366 4367 if (buffer.c45) { 4368 rv = soc_miimc45_read(u, buffer.port_id, buffer.device, 4369 reg_addr, &phy_data); 4370 } else { 4371 rv = soc_miim_read(u, buffer.port_id, reg_addr, 4372 &phy_data); 4373 } 4374 if (rv < 0) { 4375 cli_out("ERROR: MII Addr %d: soc_miim_read failed: %s\n", 4376 buffer.port_id, soc_errmsg(rv)); 4377 rv = -1; 4378 break; 4379 } 4380 mdio_rsp.data = htons(phy_data); 4381 mdio_rsp.op = MDIO_RESP; 4382 #if PHY_SYM_DBG_DEBUG_PRINT 4383 cli_out("READ data = %x %x\n", mdio_rsp.data, phy_data); 4384 #endif 4385 } else { 4386 if (buffer.op == MDIO_CLOSE) { 4387 cli_out("Closing connection\n"); 4388 break; 4389 } else { 4390 cli_out("Unknown MDIO operation\n"); 4391 mdio_rsp.op = MDIO_ERROR; 4392 } 4393 } 4394 } 4395 #if PHY_SYM_DBG_DEBUG_PRINT 4396 cli_out("sending response:\n"); 4397 for (i = 0; i < n; i++) { 4398 cli_out("%x ", *(((char *)&mdio_rsp) + i)); 4399 } 4400 #endif 4401 n = send(newsockfd, (void *)&mdio_rsp, PHY_SYM_DBG_MDIO_MSG_LEN, 0); 4402 if (n < 0) { 4403 #if PHY_SYM_DBG_DEBUG_PRINT 4404 cli_out("Error writing to socket\n"); 4405 #endif 4406 rv = -1; 4407 break; 4408 } 4409 } 4410 } 4411 /*sock_close:*/ 4412 close(newsockfd); 4413 close(sockfd); 4414 sal_thread_exit(rv); 4415 } 4416 4417 STATIC cmd_result_t 4418 _if_esw_phy_symdebug(int u, args_t *a) 4419 { 4420 int portnum; 4421 sal_thread_t sym_dbg_thread; 4422 char *c; 4423 4424 if (sym_dbg_arg.flags == SYM_DBG_THREAD_START) { 4425 cli_out("Thread already running\n"); 4426 return CMD_OK; 4427 } 4428 4429 /* Get TCP port number to listen on */ 4430 if ((c = ARG_GET(a)) == NULL) { 4431 return CMD_USAGE; 4432 } 4433 portnum = sal_ctoi(c, 0); 4434 4435 cli_out("Entering PHY Symbolic Debug mode. In this mode the link scan " 4436 "is DISABLED\n"); 4437 cli_out("Listening on TCP port %d\n", portnum); 4438 4439 sym_dbg_arg.unit = u; 4440 sym_dbg_arg.tcpportnum = portnum; 4441 sym_dbg_arg.flags = SYM_DBG_THREAD_START; 4442 sym_dbg_arg.sym_dbg_lock = sal_mutex_create("sym_dbg_lock"); 4443 4444 /* Create a thread to execute the sock functions */ 4445 sym_dbg_thread = sal_thread_create("phy_sym_dbg", 0, SAL_THREAD_STKSZ, 4446 _phy_sym_debug_server, (void *)&u); 4447 if (sym_dbg_thread == NULL) { 4448 cli_out("Unable to create thread\n"); 4449 return CMD_FAIL; 4450 } 4451 return CMD_OK; 4452 } 4453 4454 STATIC cmd_result_t 4455 _if_esw_phy_symdebug_off(int u, args_t *a) 4456 { 4457 cli_out("Stopping server thread\n"); 4458 SYM_DBG_LOCK(sym_dbg_arg); 4459 sym_dbg_arg.flags = SYM_DBG_THREAD_STOP; 4460 SYM_DBG_UNLOCK(sym_dbg_arg); 4461 return CMD_OK; 4462 } 4463 #endif 4464 4465 STATIC cmd_result_t 4466 _if_esw_phy_firmware(int u, args_t *a) 4467 { 4468 #ifdef NO_FILEIO 4469 cli_out("This command is not supported without file I/O\n"); 4470 return CMD_FAIL; 4471 #else 4472 soc_pbmp_t pbm; 4473 soc_port_t p, dport; 4474 char *c; 4475 int rv = 0; 4476 parse_table_t pt; 4477 int count; 4478 FILE *fp = NULL; 4479 uint8 *buf; 4480 int buf_len; 4481 int len; 4482 uint32 flags; 4483 char input[32]; 4484 int no_confirm = FALSE; 4485 int internal = 0; 4486 int raw = 0; 4487 char *filename = NULL; 4488 4489 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 4490 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", 4491 ARG_CMD(a), c ? c : ""); 4492 return CMD_FAIL; 4493 } 4494 4495 SOC_PBMP_COUNT(pbm, count); 4496 4497 if (count > 1) { 4498 cli_out("ERROR: too many ports specified : %d\n", 4499 count); 4500 return CMD_FAIL; 4501 } 4502 parse_table_init(u, &pt); 4503 if ((c = ARG_CUR(a)) != NULL) { 4504 4505 if (c[0] == '=') { 4506 return CMD_USAGE; /* '=' unsupported */ 4507 } 4508 4509 parse_table_add(&pt, "set", PQ_DFL | PQ_STRING, 0, 4510 &filename, NULL); 4511 parse_table_add(&pt, "-y", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0, 4512 &no_confirm, NULL); 4513 parse_table_add(&pt, "int", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0, 4514 &internal, NULL); 4515 parse_table_add(&pt, "raw", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0, 4516 &raw, NULL); 4517 4518 if (parse_arg_eq(a, &pt) < 0) { 4519 parse_arg_eq_done(&pt); 4520 return CMD_USAGE; 4521 } 4522 if (ARG_CNT(a) > 0) { 4523 cli_out("%s: Unknown argument %s\n", 4524 ARG_CMD(a), ARG_CUR(a)); 4525 parse_arg_eq_done(&pt); 4526 return CMD_USAGE; 4527 } 4528 } 4529 4530 if (!filename) { 4531 cli_out("ERROR: file name missing\n"); 4532 parse_arg_eq_done(&pt); 4533 return CMD_USAGE; 4534 } 4535 4536 if (raw && !internal) { 4537 cli_out("ERROR: raw mode supported for internal PHYs only\n"); 4538 parse_arg_eq_done(&pt); 4539 return CMD_FAIL; 4540 } 4541 4542 if ((fp = sal_fopen(filename, "rb")) == NULL) { 4543 cli_out("ERROR: Can't open the file : %s\n", 4544 filename); 4545 parse_arg_eq_done(&pt); 4546 return CMD_FAIL; 4547 } 4548 4549 ; 4550 if ((buf_len = sal_fsize(fp)) <= 0) { 4551 cli_out("ERROR: Could not determine file size\n"); 4552 parse_arg_eq_done(&pt); 4553 sal_fclose(fp); 4554 return CMD_FAIL; 4555 } 4556 4557 /* 4558 * filename points to memory allocated by arg parsing. 4559 * Calling parse_arg_eq_done frees this memory. 4560 */ 4561 parse_arg_eq_done(&pt); 4562 4563 if (!raw && !no_confirm) { 4564 /* prompt user for confirmation */ 4565 cli_out("Warning!!!\n" 4566 "The PHY device may become un-usable if the power is off\n" 4567 "during this process or a wrong file is given. The file must\n" 4568 "be in BINARY format. The only way to recover is to program\n" 4569 "the non-volatile storage device with a rom burner\n"); 4570 4571 if ((NULL == 4572 sal_readline("Are you sure you want to continue (yes/[no])?", 4573 input, sizeof(input), "no")) || 4574 (sal_strlen(input) != sal_strlen("yes")) || 4575 (sal_strncasecmp("yes", input, sal_strlen(input)))) { 4576 sal_fclose(fp); 4577 cli_out("Firmware update aborted. No writes to the " 4578 "PHY device's non-volatile storage\n"); 4579 return CMD_FAIL; 4580 } 4581 } 4582 4583 buf = sal_alloc(buf_len, "temp_buf"); 4584 if (buf == NULL) { 4585 sal_fclose(fp); 4586 cli_out("ERROR: Cannot allocate enough buffer space: %d\n", 4587 buf_len); 4588 return CMD_FAIL; 4589 } 4590 4591 /* coverity[overrun-local] */ 4592 DPORT_BCM_PBMP_ITER(u, pbm, dport, p) { 4593 /* coverity[tainted_data_argument] */ 4594 len = sal_fread(buf, 1, buf_len, fp); 4595 if (len != buf_len) { 4596 sal_fclose(fp); 4597 /* coverity[tainted_data] */ 4598 sal_free(buf); 4599 cli_out("ERROR: Could only read %d bytes (out of %d)\n", 4600 len, buf_len); 4601 return CMD_FAIL; 4602 } 4603 cli_out("Downloading %d bytes...\n", len); 4604 flags = internal ? BCM_PORT_PHY_INTERNAL : 0; 4605 if (raw) { 4606 rv = soc_phy_firmware_load(u, p, buf, len); 4607 } else { 4608 rv = bcm_port_phy_firmware_set(u, p, flags, 0, buf, len); 4609 } 4610 break; 4611 } 4612 sal_fclose(fp); 4613 /* coverity[tainted_data] */ 4614 sal_free(buf); 4615 if (rv == SOC_E_NONE) { 4616 cli_out("Successfully done!!!\n"); 4617 } else if (rv == SOC_E_UNAVAIL) { 4618 cli_out("Aborted.\n" 4619 "Feature is not available for this PHY device.\n"); 4620 } else { 4621 cli_out("Failed (%s).\n", 4622 bcm_errmsg(rv)); 4623 if (!raw) { 4624 cli_out("PHY device may not be usable.\n"); 4625 } 4626 } 4627 return CMD_OK; 4628 #endif 4629 } 4630 4631 STATIC cmd_result_t 4632 _if_esw_phy_oam(int u, args_t *a) 4633 { 4634 soc_pbmp_t pbm; 4635 soc_port_t p, dport; 4636 char *c; 4637 int i, rv = 0; 4638 bcm_port_config_phy_oam_t conf; 4639 uint64 val64; 4640 4641 sal_memset(&conf, 0, sizeof(bcm_port_config_phy_oam_t)); 4642 COMPILER_64_SET(val64, 0, 0); 4643 4644 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 4645 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 4646 return CMD_FAIL; 4647 } 4648 if ((c = ARG_CUR(a)) != NULL) { 4649 parse_table_t pt; 4650 uint32 mac_addr_hi = 0, mac_addr_low = 0, flags; 4651 uint32 mac_addr_hi_1 = 0, mac_addr_low_1 = 0; 4652 uint32 mac_addr_hi_2 = 0, mac_addr_low_2 = 0; 4653 uint32 mac_addr_hi_3 = 0, mac_addr_low_3 = 0; 4654 uint32 eth_type = 0; 4655 uint32 mac_check_en = 0, cw_en = 0, entropy_en = 0, 4656 mac_index = 0, timestamp = 0; 4657 char *mode, *dir, *ts_format; 4658 uint8 tx = 0, rx = 0, oam_mode; 4659 uint32 type; 4660 4661 parse_table_init(u, &pt); 4662 parse_table_add(&pt, "MODE", PQ_DFL | PQ_STRING, 0, &mode, 0); 4663 parse_table_add(&pt, "DIR", PQ_DFL | PQ_STRING, 0, &dir, 0); 4664 parse_table_add(&pt, "MacCheck", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 4665 0, &mac_check_en, 0); 4666 parse_table_add(&pt, "ControlWord", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 4667 0, &cw_en, 0); 4668 parse_table_add(&pt, "ENTROPY", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 4669 0, &entropy_en, 0); 4670 parse_table_add(&pt, "TimeStampFormat", PQ_DFL | PQ_STRING, 4671 0, &ts_format, 0); 4672 parse_table_add(&pt, "ETHerType", PQ_INT | PQ_DFL, 0, ð_type, 0); 4673 parse_table_add(&pt, "MACIndex", PQ_INT | PQ_DFL, 0, &mac_index, 0); 4674 parse_table_add(&pt, "MACAddrHi", PQ_INT | PQ_DFL, 4675 0, &mac_addr_hi, 0); 4676 parse_table_add(&pt, "MACAddrLow", PQ_INT | PQ_DFL, 4677 0, &mac_addr_low, 0); 4678 parse_table_add(&pt, "MACAddrHi1", PQ_INT | PQ_DFL, 4679 0, &mac_addr_hi_1, 0); 4680 parse_table_add(&pt, "MACAddrLow1", PQ_INT | PQ_DFL, 4681 0, &mac_addr_low_1, 0); 4682 parse_table_add(&pt, "MACAddrHi2", PQ_INT | PQ_DFL, 4683 0, &mac_addr_hi_2, 0); 4684 parse_table_add(&pt, "MACAddrLow2", PQ_INT | PQ_DFL, 4685 0, &mac_addr_low_2, 0); 4686 parse_table_add(&pt, "MACAddrHi3", PQ_INT | PQ_DFL, 4687 0, &mac_addr_hi_3, 0); 4688 parse_table_add(&pt, "MACAddrLow3", PQ_INT | PQ_DFL, 4689 0, &mac_addr_low_3, 0); 4690 4691 if (parse_arg_eq(a, &pt) < 0) { 4692 parse_arg_eq_done(&pt); 4693 return CMD_USAGE; 4694 } 4695 if (ARG_CNT(a) > 0) { 4696 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 4697 parse_arg_eq_done(&pt); 4698 return CMD_USAGE; 4699 } 4700 4701 flags = 0; 4702 4703 for (i = 0; i < pt.pt_cnt; i++) { 4704 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 4705 flags |= (1 << i); 4706 } 4707 } 4708 4709 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 4710 if ((rv = 4711 bcm_port_config_phy_oam_get(u, p, &conf)) == BCM_E_FAIL) { 4712 cli_out("bcm_port_config_phy_oam_get() failed, u=%d, p=%d\n", 4713 u, p); 4714 parse_arg_eq_done(&pt); 4715 return CMD_FAIL; 4716 } 4717 4718 if (flags & (1U << 1)) { 4719 if (!sal_strcmp(dir, "tx")) { 4720 tx = 1; 4721 } else if (!sal_strcmp(dir, "rx")) { 4722 rx = 1; 4723 } else { 4724 parse_arg_eq_done(&pt); 4725 return CMD_USAGE; 4726 } 4727 } else { 4728 tx = 1; 4729 rx = 1; 4730 } 4731 4732 if (flags & (1U << 0)) { 4733 if (!sal_strcmp(mode, "y1731")) { 4734 oam_mode = bcmPortConfigPhyOamDmModeY1731; 4735 } else if (!sal_strcmp(mode, "bhh")) { 4736 oam_mode = bcmPortConfigPhyOamDmModeBhh; 4737 } else if (!sal_strcmp(mode, "ietf")) { 4738 oam_mode = bcmPortConfigPhyOamDmModeIetf; 4739 } else { 4740 parse_arg_eq_done(&pt); 4741 return CMD_USAGE; 4742 } 4743 4744 if (tx) { 4745 conf.tx_dm_config.mode = oam_mode; 4746 } 4747 if (rx) { 4748 conf.rx_dm_config.mode = oam_mode; 4749 } 4750 } 4751 4752 if (flags & (1U << 2)) { 4753 if (tx) { 4754 conf.tx_dm_config.flags &= 4755 ~BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE; 4756 conf.tx_dm_config.flags |= 4757 mac_check_en ? BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE 4758 : 0; 4759 } 4760 if (rx) { 4761 conf.rx_dm_config.flags &= 4762 ~BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE; 4763 conf.rx_dm_config.flags |= 4764 mac_check_en ? BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE 4765 : 0; 4766 } 4767 } 4768 if (flags & (1U << 3)) { 4769 if (tx) { 4770 conf.tx_dm_config.flags &= 4771 ~BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE; 4772 conf.tx_dm_config.flags |= 4773 cw_en ? BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE : 0; 4774 } 4775 if (rx) { 4776 conf.rx_dm_config.flags &= 4777 ~BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE; 4778 conf.rx_dm_config.flags |= 4779 cw_en ? BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE : 0; 4780 } 4781 } 4782 if (flags & (1U << 4)) { 4783 if (tx) { 4784 conf.tx_dm_config.flags &= 4785 ~BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE; 4786 conf.tx_dm_config.flags |= 4787 entropy_en ? BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE : 0; 4788 } 4789 if (rx) { 4790 conf.rx_dm_config.flags &= 4791 ~BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE; 4792 conf.rx_dm_config.flags |= 4793 entropy_en ? BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE : 0; 4794 } 4795 } 4796 if (flags & (1U << 5)) { 4797 if (!sal_strcmp(ts_format, "ntp")) { 4798 timestamp = 1; 4799 } else if (!sal_strcmp(ts_format, "ptp")) { 4800 timestamp = 0; 4801 } else { 4802 parse_arg_eq_done(&pt); 4803 return CMD_USAGE; 4804 } 4805 4806 if (tx) { 4807 conf.tx_dm_config.flags &= 4808 ~BCM_PORT_PHY_OAM_DM_TS_FORMAT; 4809 conf.tx_dm_config.flags |= 4810 timestamp ? BCM_PORT_PHY_OAM_DM_TS_FORMAT : 0; 4811 } 4812 if (rx) { 4813 conf.rx_dm_config.flags &= 4814 ~BCM_PORT_PHY_OAM_DM_TS_FORMAT; 4815 conf.rx_dm_config.flags |= 4816 timestamp ? BCM_PORT_PHY_OAM_DM_TS_FORMAT : 0; 4817 } 4818 } 4819 4820 /* CONFIG SET */ 4821 if ((rv = 4822 bcm_port_config_phy_oam_set(u, p, &conf)) == BCM_E_FAIL) { 4823 cli_out("bcm_port_config_phy_oam_set() failed, u=%d, p=%d\n", 4824 u, p); 4825 parse_arg_eq_done(&pt); 4826 return CMD_FAIL; 4827 } 4828 4829 if (flags & (1U << 6)) { 4830 COMPILER_64_SET(val64, 0, eth_type); 4831 if (tx) { 4832 rv = bcm_port_control_phy_oam_set(u, p, 4833 bcmPortControlPhyOamDmTxEthertype, 4834 val64); 4835 if (rv != BCM_E_NONE) { 4836 cli_out("bcm_port_control_phy_oam_set failed with error \ 4837 u=%d p=%d %s\n", u, p, 4838 bcm_errmsg(rv)); 4839 parse_arg_eq_done(&pt); 4840 return CMD_FAIL; 4841 } 4842 } 4843 if (rx) { 4844 rv = bcm_port_control_phy_oam_set(u, p, 4845 bcmPortControlPhyOamDmRxEthertype, 4846 val64); 4847 if (rv != BCM_E_NONE) { 4848 cli_out("bcm_port_control_phy_oam_set failed with error \ 4849 u=%d p=%d %s\n", u, p, 4850 bcm_errmsg(rv)); 4851 parse_arg_eq_done(&pt); 4852 return CMD_FAIL; 4853 } 4854 } 4855 } 4856 4857 if (flags & (1U << 7)) { 4858 if (mac_index == 0) { 4859 parse_arg_eq_done(&pt); 4860 return CMD_USAGE; 4861 } 4862 COMPILER_64_SET(val64, 0, mac_index); 4863 if (tx) { 4864 rv = bcm_port_control_phy_oam_set(u, p, 4865 bcmPortControlPhyOamDmTxPortMacAddressIndex, 4866 val64); 4867 if (rv != BCM_E_NONE) { 4868 cli_out("bcm_port_control_phy_oam_set failed with error \ 4869 u=%d p=%d %s\n", u, p, 4870 bcm_errmsg(rv)); 4871 parse_arg_eq_done(&pt); 4872 return CMD_FAIL; 4873 } 4874 } 4875 if (rx) { 4876 rv = bcm_port_control_phy_oam_set(u, p, 4877 bcmPortControlPhyOamDmRxPortMacAddressIndex, 4878 val64); 4879 if (rv != BCM_E_NONE) { 4880 cli_out("bcm_port_control_phy_oam_set failed with error \ 4881 u=%d p=%d %s\n", u, p, 4882 bcm_errmsg(rv)); 4883 parse_arg_eq_done(&pt); 4884 return CMD_FAIL; 4885 } 4886 } 4887 } 4888 /* If mac_index is not provided and mac_addr needs to be set 4889 use mac_addr_1/2/3 instead. 4890 */ 4891 if (!(flags & (1U << 7)) && 4892 ((flags & (1U << 8)) || (flags & (1U << 9)))) { 4893 cli_out(" MACAddrHi/MACAddrLow cannot be used without 'MACIndex. " 4894 "Please use MACAddrHi1/2/3 for updating MAC address\n"); 4895 parse_arg_eq_done(&pt); 4896 return CMD_FAIL; 4897 } 4898 if ((flags & (1U << 8)) || (flags & (1U << 9))) { 4899 switch (mac_index) { 4900 case 1: 4901 type = bcmPortControlPhyOamDmMacAddress1; 4902 break; 4903 case 2: 4904 type = bcmPortControlPhyOamDmMacAddress2; 4905 break; 4906 case 3: 4907 type = bcmPortControlPhyOamDmMacAddress3; 4908 break; 4909 default: 4910 parse_arg_eq_done(&pt); 4911 return CMD_FAIL; 4912 } 4913 4914 COMPILER_64_SET(val64, mac_addr_hi, mac_addr_low); 4915 4916 rv = bcm_port_control_phy_oam_set(u, p, type, val64); 4917 if (rv != BCM_E_NONE) { 4918 cli_out("bcm_port_control_phy_oam_set failed with error \ 4919 u=%d p=%d %s\n", u, p, 4920 bcm_errmsg(rv)); 4921 parse_arg_eq_done(&pt); 4922 return CMD_FAIL; 4923 } 4924 } 4925 if ((flags & (1U << 10)) || (flags & (1U << 11))) { 4926 COMPILER_64_SET(val64, mac_addr_hi_1, mac_addr_low_1); 4927 4928 rv = bcm_port_control_phy_oam_set(u, p, 4929 bcmPortControlPhyOamDmMacAddress1, 4930 val64); 4931 if (rv != BCM_E_NONE) { 4932 cli_out("bcm_port_control_phy_oam_set failed with error \ 4933 u=%d p=%d %s\n", u, p, 4934 bcm_errmsg(rv)); 4935 parse_arg_eq_done(&pt); 4936 return CMD_FAIL; 4937 } 4938 } 4939 if ((flags & (1U << 12)) || (flags & (1U << 13))) { 4940 COMPILER_64_SET(val64, mac_addr_hi_2, mac_addr_low_2); 4941 4942 rv = bcm_port_control_phy_oam_set(u, p, 4943 bcmPortControlPhyOamDmMacAddress2, 4944 val64); 4945 if (rv != BCM_E_NONE) { 4946 cli_out("bcm_port_control_phy_oam_set failed with error \ 4947 u=%d p=%d %s\n", u, p, 4948 bcm_errmsg(rv)); 4949 parse_arg_eq_done(&pt); 4950 return CMD_FAIL; 4951 } 4952 } 4953 if ((flags & (1U << 14)) || (flags & (1U << 15))) { 4954 COMPILER_64_SET(val64, mac_addr_hi_3, mac_addr_low_3); 4955 4956 rv = bcm_port_control_phy_oam_set(u, p, 4957 bcmPortControlPhyOamDmMacAddress3, 4958 val64); 4959 if (rv != BCM_E_NONE) { 4960 cli_out("bcm_port_control_phy_oam_set failed with error \ 4961 u=%d p=%d %s\n", u, p, 4962 bcm_errmsg(rv)); 4963 parse_arg_eq_done(&pt); 4964 return CMD_FAIL; 4965 } 4966 } 4967 4968 } 4969 /* free allocated memory from arg parsing */ 4970 parse_arg_eq_done(&pt); 4971 4972 } else { 4973 4974 /* coverity[overrun-local] */ 4975 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 4976 int offset; 4977 uint64 tx_ethtype, rx_ethtype; 4978 uint64 mac1, mac2, mac3; 4979 uint64 tx_mac_index, rx_mac_index; 4980 4981 COMPILER_64_SET(tx_ethtype, 0, 0); 4982 COMPILER_64_SET(rx_ethtype, 0, 0); 4983 COMPILER_64_SET(mac1, 0, 0); 4984 COMPILER_64_SET(mac2, 0, 0); 4985 COMPILER_64_SET(mac3, 0, 0); 4986 COMPILER_64_SET(tx_mac_index, 0, 0); 4987 COMPILER_64_SET(rx_mac_index, 0, 0); 4988 /* coverity[unchecked_value] */ 4989 soc_phyctrl_offset_get(u, p, &offset); /* return value not checked on purpose */ 4990 4991 cli_out("\n\nOAM settings for %s(%3d) %s, offset = %d\n\n", 4992 SOC_PORT_NAME(u, p), p, soc_phy_name_get(u, p), offset); 4993 4994 if ((rv = 4995 bcm_port_config_phy_oam_get(u, p, &conf)) == BCM_E_FAIL) { 4996 cli_out("bcm_port_config_phy_oam_get() failed, u=%d, p=%d\n", 4997 u, p); 4998 return CMD_FAIL; 4999 } 5000 5001 rv = bcm_port_control_phy_oam_get(u, p, 5002 bcmPortControlPhyOamDmTxEthertype, 5003 &tx_ethtype); 5004 if (rv != BCM_E_NONE) { 5005 cli_out("bcm_port_control_phy_oam_get (TxEthertype) failed with error \ 5006 u=%d p=%d %s\n", u, p, 5007 bcm_errmsg(rv)); 5008 return CMD_FAIL; 5009 } 5010 rv = bcm_port_control_phy_oam_get(u, p, 5011 bcmPortControlPhyOamDmRxEthertype, 5012 &rx_ethtype); 5013 if (rv != BCM_E_NONE) { 5014 cli_out("bcm_port_control_phy_oam_get (RxEthertype) failed with error \ 5015 u=%d p=%d %s\n", u, p, 5016 bcm_errmsg(rv)); 5017 return CMD_FAIL; 5018 } 5019 rv = bcm_port_control_phy_oam_get(u, p, 5020 bcmPortControlPhyOamDmTxPortMacAddressIndex, 5021 &tx_mac_index); 5022 if (rv != BCM_E_NONE) { 5023 cli_out("bcm_port_control_phy_oam_get (TxMACIndex)failed with error \ 5024 u=%d p=%d %s\n", u, p, 5025 bcm_errmsg(rv)); 5026 return CMD_FAIL; 5027 } 5028 rv = bcm_port_control_phy_oam_get(u, p, 5029 bcmPortControlPhyOamDmRxPortMacAddressIndex, 5030 &rx_mac_index); 5031 if (rv != BCM_E_NONE) { 5032 cli_out("bcm_port_control_phy_oam_get (RxMACIndex)failed with error \ 5033 u=%d p=%d %s\n", u, p, 5034 bcm_errmsg(rv)); 5035 return CMD_FAIL; 5036 } 5037 5038 rv = bcm_port_control_phy_oam_get(u, p, 5039 bcmPortControlPhyOamDmMacAddress1, 5040 &mac1); 5041 if (rv != BCM_E_NONE) { 5042 cli_out("bcm_port_control_phy_oam_get (MacAddr1)failed with error \ 5043 u=%d p=%d %s\n", u, p, 5044 bcm_errmsg(rv)); 5045 return CMD_FAIL; 5046 } 5047 rv = bcm_port_control_phy_oam_get(u, p, 5048 bcmPortControlPhyOamDmMacAddress2, 5049 &mac2); 5050 if (rv != BCM_E_NONE) { 5051 cli_out("bcm_port_control_phy_oam_get (MacAddr2)failed with error \ 5052 u=%d p=%d %s\n", u, p, 5053 bcm_errmsg(rv)); 5054 return CMD_FAIL; 5055 } 5056 rv = bcm_port_control_phy_oam_get(u, p, 5057 bcmPortControlPhyOamDmMacAddress3, 5058 &mac3); 5059 if (rv != BCM_E_NONE) { 5060 cli_out("bcm_port_control_phy_oam_get (MacAddr3)failed with error \ 5061 u=%d p=%d %s\n", u, p, 5062 bcm_errmsg(rv)); 5063 return CMD_FAIL; 5064 } 5065 5066 cli_out("\nPHY OAM TX Config Settings:\n"); 5067 cli_out("=============================\n"); 5068 cli_out("MODE (Y1731, BHH or IETF) - %s\n", 5069 (conf.tx_dm_config.mode == 5070 bcmPortConfigPhyOamDmModeY1731) ? "Y.1731" : (conf. 5071 tx_dm_config. 5072 mode == 5073 bcmPortConfigPhyOamDmModeBhh) 5074 ? "BHH" : (conf.tx_dm_config.mode == 5075 bcmPortConfigPhyOamDmModeIetf) ? "IETF" : 5076 "NONE"); 5077 cli_out("MacCheck (Y or N) - %s\n", 5078 conf.tx_dm_config. 5079 flags & BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ? "Y" : 5080 "N"); 5081 cli_out("ControlWord (Y or N) - %s\n", 5082 conf.tx_dm_config. 5083 flags & BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ? "Y" : 5084 "N"); 5085 cli_out("ENTROPY (Y or N) - %s\n", 5086 conf.tx_dm_config. 5087 flags & BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE ? "Y" : "N"); 5088 cli_out("TimeStampFormat (PTP or NTP) - %s\n", 5089 conf.tx_dm_config. 5090 flags & BCM_PORT_PHY_OAM_DM_TS_FORMAT ? "NTP" : "PTP"); 5091 cli_out("EtherType- 0x%x\n", COMPILER_64_LO(tx_ethtype)); 5092 cli_out("MacIndex- %d\n", COMPILER_64_LO(tx_mac_index)); 5093 5094 cli_out("\nPHY OAM RX Config Settings:\n"); 5095 cli_out("=============================\n"); 5096 cli_out("MODE (Y1731, BHH or IETF) - %s\n", 5097 (conf.rx_dm_config.mode == 5098 bcmPortConfigPhyOamDmModeY1731) ? "Y.1731" : (conf. 5099 rx_dm_config. 5100 mode == 5101 bcmPortConfigPhyOamDmModeBhh) 5102 ? "BHH" : (conf.rx_dm_config.mode == 5103 bcmPortConfigPhyOamDmModeIetf) ? "IETF" : 5104 "NONE"); 5105 cli_out("MacCheck (Y or N) - %s\n", 5106 conf.rx_dm_config. 5107 flags & BCM_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ? "Y" : 5108 "N"); 5109 cli_out("ControlWord (Y or N) - %s\n", 5110 conf.rx_dm_config. 5111 flags & BCM_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ? "Y" : 5112 "N"); 5113 cli_out("ENTROPY (Y or N) - %s\n", 5114 conf.rx_dm_config. 5115 flags & BCM_PORT_PHY_OAM_DM_ENTROPY_ENABLE ? "Y" : "N"); 5116 cli_out("TimeStampFormat (PTP or NTP) - %s\n", 5117 conf.rx_dm_config. 5118 flags & BCM_PORT_PHY_OAM_DM_TS_FORMAT ? "NTP" : "PTP"); 5119 cli_out("EtherType- 0x%x\n", COMPILER_64_LO(rx_ethtype)); 5120 cli_out("MacIndex- %d\n", COMPILER_64_LO(rx_mac_index)); 5121 5122 cli_out("\nOther Settings:\n"); 5123 cli_out("=============================\n"); 5124 cli_out("MAC Address 1 - 0x%08x%08x\n", COMPILER_64_HI(mac1), 5125 COMPILER_64_LO(mac1)); 5126 cli_out("MAC Address 2 - 0x%08x%08x\n", COMPILER_64_HI(mac2), 5127 COMPILER_64_LO(mac2)); 5128 cli_out("MAC Address 3 - 0x%08x%08x\n", COMPILER_64_HI(mac3), 5129 COMPILER_64_LO(mac3)); 5130 5131 } 5132 5133 } 5134 return CMD_OK; 5135 } 5136 5137 STATIC cmd_result_t 5138 _if_esw_phy_power(int u, args_t *a) 5139 { 5140 soc_pbmp_t pbm; 5141 soc_port_t p, dport; 5142 char *c; 5143 int rv = 0; 5144 parse_table_t pt; 5145 char *mode_type = 0; 5146 uint32 mode_value; 5147 int sleep_time = -1; 5148 int wake_time = -1; 5149 5150 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 5151 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 5152 return CMD_FAIL; 5153 } 5154 5155 if ((c = ARG_CUR(a)) != NULL) { 5156 5157 if (c[0] == '=') { 5158 return CMD_USAGE; /* '=' unsupported */ 5159 } 5160 5161 parse_table_init(u, &pt); 5162 parse_table_add(&pt, "mode", PQ_DFL | PQ_STRING, 0, 5163 &mode_type, NULL); 5164 5165 parse_table_add(&pt, "Sleep_Time", PQ_DFL | PQ_INT, 5166 0, &sleep_time, NULL); 5167 5168 parse_table_add(&pt, "Wake_Time", PQ_DFL | PQ_INT, 5169 0, &wake_time, NULL); 5170 5171 if (parse_arg_eq(a, &pt) < 0) { 5172 parse_arg_eq_done(&pt); 5173 return CMD_USAGE; 5174 } 5175 if (ARG_CNT(a) > 0) { 5176 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 5177 parse_arg_eq_done(&pt); 5178 return CMD_USAGE; 5179 } 5180 } else { 5181 char *str; 5182 cli_out("Phy Power Mode dump:\n"); 5183 cli_out("%10s %16s %14s %14s %14s\n", 5184 "port", "name", "power_mode", "sleep_time(ms)", 5185 "wake_time(ms)"); 5186 /* coverity[overrun-local] */ 5187 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 5188 mode_value = 0; 5189 sleep_time = 0; 5190 wake_time = 0; 5191 rv = bcm_port_phy_control_get(u, p, BCM_PORT_PHY_CONTROL_POWER, 5192 &mode_value); 5193 if (rv == SOC_E_NONE) { 5194 if (mode_value == BCM_PORT_PHY_CONTROL_POWER_AUTO) { 5195 str = "auto_down"; 5196 if ((rv = bcm_port_phy_control_get(u, p, 5197 BCM_PORT_PHY_CONTROL_POWER_AUTO_SLEEP_TIME, 5198 (uint32 *) & 5199 sleep_time)) != 5200 SOC_E_NONE) { 5201 sleep_time = 0; 5202 } 5203 if ((rv = bcm_port_phy_control_get(u, p, 5204 BCM_PORT_PHY_CONTROL_POWER_AUTO_WAKE_TIME, 5205 (uint32 *) & 5206 wake_time)) != 5207 SOC_E_NONE) { 5208 wake_time = 0; 5209 } 5210 5211 } else if (mode_value == BCM_PORT_PHY_CONTROL_POWER_LOW) { 5212 str = "low"; 5213 } else { 5214 str = "full"; 5215 } 5216 } else { 5217 str = "unavail"; 5218 } 5219 /* coverity[illegal_address] */ 5220 cli_out("%5s(%3d) %16s %14s ", 5221 SOC_PORT_NAME(u, p), p, soc_phy_name_get(u, p), str); 5222 if (sleep_time && wake_time) { 5223 cli_out("%10d %14d\n", sleep_time, wake_time); 5224 } else { 5225 cli_out("%10s %14s\n", "N/A", "N/A"); 5226 } 5227 } 5228 return CMD_OK; 5229 } 5230 5231 if (sal_strcasecmp(mode_type, "auto_low") == 0) { 5232 (void)_phy_auto_low_start(u, pbm, 1); 5233 } else if (sal_strcasecmp(mode_type, "auto_off") == 0) { 5234 (void)_phy_auto_low_start(u, pbm, 0); 5235 } else if (sal_strcasecmp(mode_type, "low") == 0) { 5236 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 5237 (void)bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_POWER, 5238 BCM_PORT_PHY_CONTROL_POWER_LOW); 5239 } 5240 } else if (sal_strcasecmp(mode_type, "full") == 0) { 5241 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 5242 (void)bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_POWER, 5243 BCM_PORT_PHY_CONTROL_POWER_FULL); 5244 } 5245 } else if (sal_strcasecmp(mode_type, "auto_down") == 0) { 5246 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 5247 (void)bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_POWER, 5248 BCM_PORT_PHY_CONTROL_POWER_AUTO); 5249 if (sleep_time >= 0) { 5250 (void)bcm_port_phy_control_set(u, p, 5251 BCM_PORT_PHY_CONTROL_POWER_AUTO_SLEEP_TIME, 5252 sleep_time); 5253 } 5254 if (wake_time >= 0) { 5255 (void)bcm_port_phy_control_set(u, p, 5256 BCM_PORT_PHY_CONTROL_POWER_AUTO_WAKE_TIME, 5257 wake_time); 5258 } 5259 } 5260 } 5261 5262 /* free allocated memory from arg parsing */ 5263 parse_arg_eq_done(&pt); 5264 return CMD_OK; 5265 } 5266 5267 STATIC cmd_result_t 5268 _if_esw_phy_margin(int unit, args_t *args) 5269 { 5270 parse_table_t pt; 5271 bcm_port_t port, dport; 5272 bcm_pbmp_t pbmp; 5273 int rv, cmd, enable; 5274 char *cmd_str, *port_str; 5275 int marginval = 0; 5276 5277 enum { _PHY_MARGIN_MAX_GET_CMD, 5278 _PHY_MARGIN_SET_CMD, 5279 _PHY_MARGIN_VALUE_SET_CMD, 5280 _PHY_MARGIN_VALUE_GET_CMD, 5281 _PHY_MARGIN_CLEAR_CMD 5282 }; 5283 5284 if ((port_str = ARG_GET(args)) == NULL) { 5285 return CMD_USAGE; 5286 } 5287 5288 BCM_PBMP_CLEAR(pbmp); 5289 if (parse_bcm_pbmp(unit, port_str, &pbmp) < 0) { 5290 cli_out("Error: unrecognized port bitmap: %s\n", port_str); 5291 return CMD_FAIL; 5292 } 5293 5294 if ((cmd_str = ARG_GET(args)) == NULL) { 5295 return CMD_USAGE; 5296 } 5297 if (sal_strcasecmp(cmd_str, "maxget") == 0) { 5298 cmd = _PHY_MARGIN_MAX_GET_CMD; 5299 enable = 0; 5300 } else if (sal_strcasecmp(cmd_str, "set") == 0) { 5301 cmd = _PHY_MARGIN_SET_CMD; 5302 enable = 1; 5303 } else if (sal_strcasecmp(cmd_str, "valueset") == 0) { 5304 cmd = _PHY_MARGIN_VALUE_SET_CMD; 5305 enable = 0; 5306 } else if (sal_strcasecmp(cmd_str, "valueget") == 0) { 5307 cmd = _PHY_MARGIN_VALUE_GET_CMD; 5308 enable = 0; 5309 } else if (sal_strcasecmp(cmd_str, "clear") == 0) { 5310 cmd = _PHY_MARGIN_CLEAR_CMD; 5311 enable = 0; 5312 } else 5313 return CMD_USAGE; 5314 5315 parse_table_init(unit, &pt); 5316 if (cmd == _PHY_MARGIN_VALUE_SET_CMD) { 5317 parse_table_add(&pt, "marginval", PQ_DFL | PQ_INT, 5318 (void *)(0), &marginval, NULL); 5319 } 5320 if (parse_arg_eq(args, &pt) < 0) { 5321 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 5322 parse_arg_eq_done(&pt); 5323 return CMD_USAGE; 5324 } 5325 5326 /* Now free allocated strings */ 5327 parse_arg_eq_done(&pt); 5328 5329 /* coverity[overrun-local] */ 5330 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 5331 5332 switch (cmd) { 5333 5334 case _PHY_MARGIN_SET_CMD: 5335 case _PHY_MARGIN_CLEAR_CMD: 5336 5337 rv = bcm_port_control_set(unit, port, 5338 bcmPortControlSerdesTuneMarginMode, 5339 enable); 5340 if (rv != BCM_E_NONE) { 5341 cli_out("Setting margin enable failed: %s\n", 5342 bcm_errmsg(rv)); 5343 return CMD_FAIL; 5344 } 5345 5346 break; 5347 5348 case _PHY_MARGIN_VALUE_SET_CMD: 5349 5350 rv = bcm_port_control_set(unit, port, 5351 bcmPortControlSerdesTuneMarginValue, 5352 marginval); 5353 if (rv != BCM_E_NONE) { 5354 cli_out("Getting margin value failed: %s\n", bcm_errmsg(rv)); 5355 return CMD_FAIL; 5356 } 5357 cli_out("margin value(%d)\n", marginval); 5358 break; 5359 case _PHY_MARGIN_MAX_GET_CMD: 5360 5361 rv = bcm_port_control_get(unit, port, 5362 bcmPortControlSerdesTuneMarginMax, 5363 &marginval); 5364 if (rv != BCM_E_NONE) { 5365 cli_out("Getting margin max value failed: %s\n", 5366 bcm_errmsg(rv)); 5367 return CMD_FAIL; 5368 } 5369 cli_out("margin max value(%d)\n", marginval); 5370 break; 5371 5372 case _PHY_MARGIN_VALUE_GET_CMD: 5373 5374 rv = bcm_port_control_get(unit, port, 5375 bcmPortControlSerdesTuneMarginValue, 5376 &marginval); 5377 if (rv != BCM_E_NONE) { 5378 cli_out("Getting margin value failed: %s\n", bcm_errmsg(rv)); 5379 return CMD_FAIL; 5380 } 5381 cli_out("margin value(%d)\n", marginval); 5382 break; 5383 5384 default: 5385 break; 5386 } 5387 } 5388 5389 return CMD_OK; 5390 } 5391 5392 STATIC cmd_result_t 5393 _if_esw_phy_prbs(int unit, args_t *args) 5394 { 5395 parse_table_t pt; 5396 bcm_port_t port, dport; 5397 bcm_pbmp_t pbmp; 5398 int rv, cmd, enable, mode = 0; 5399 char *cmd_str, *port_str, *mode_str, *poly_str = NULL; 5400 int poly = 0, lb = 0; 5401 5402 enum { _PHY_PRBS_SET_CMD, _PHY_PRBS_GET_CMD, _PHY_PRBS_CLEAR_CMD }; 5403 enum { _PHY_PRBS_SI_MODE, _PHY_PRBS_HC_MODE }; 5404 5405 if ((port_str = ARG_GET(args)) == NULL) { 5406 return CMD_USAGE; 5407 } 5408 5409 BCM_PBMP_CLEAR(pbmp); 5410 if (parse_bcm_pbmp(unit, port_str, &pbmp) < 0) { 5411 cli_out("Error: unrecognized port bitmap: %s\n", port_str); 5412 return CMD_FAIL; 5413 } 5414 5415 if ((cmd_str = ARG_GET(args)) == NULL) { 5416 return CMD_USAGE; 5417 } 5418 if (sal_strcasecmp(cmd_str, "set") == 0) { 5419 cmd = _PHY_PRBS_SET_CMD; 5420 enable = 1; 5421 } else if (sal_strcasecmp(cmd_str, "get") == 0) { 5422 cmd = _PHY_PRBS_GET_CMD; 5423 enable = 0; 5424 } else if (sal_strcasecmp(cmd_str, "clear") == 0) { 5425 cmd = _PHY_PRBS_CLEAR_CMD; 5426 enable = 0; 5427 } else 5428 return CMD_USAGE; 5429 5430 parse_table_init(unit, &pt); 5431 parse_table_add(&pt, "Mode", PQ_STRING, 0, &mode_str, NULL); 5432 if (cmd == _PHY_PRBS_SET_CMD) { 5433 parse_table_add(&pt, "Polynomial", PQ_DFL | PQ_STRING, 5434 (void *)(0), &poly_str, NULL); 5435 parse_table_add(&pt, "LoopBack", PQ_DFL | PQ_BOOL, 5436 (void *)(0), &lb, NULL); 5437 } 5438 if (parse_arg_eq(args, &pt) < 0) { 5439 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 5440 parse_arg_eq_done(&pt); 5441 return CMD_USAGE; 5442 } 5443 5444 if ( poly_str ) { 5445 if ( !sal_strcasecmp(poly_str, "P7") || !sal_strcasecmp(poly_str, "0")) { 5446 poly = 0; 5447 } else if (!sal_strcasecmp(poly_str, "P15") || !sal_strcasecmp(poly_str, "1") ) { 5448 poly = 1; 5449 } else if (!sal_strcasecmp(poly_str, "P23") || !sal_strcasecmp(poly_str, "2") ) { 5450 poly = 2; 5451 } else if (!sal_strcasecmp(poly_str, "P31") || !sal_strcasecmp(poly_str, "3") ) { 5452 poly = 3; 5453 } else if (!sal_strcasecmp(poly_str, "P9") || !sal_strcasecmp(poly_str, "4")) { 5454 poly = 4; 5455 } else if (!sal_strcasecmp(poly_str, "P11") || !sal_strcasecmp(poly_str, "5") ) { 5456 poly = 5; 5457 } else if (!sal_strcasecmp(poly_str, "P58") || !sal_strcasecmp(poly_str, "6")) { 5458 poly = 6; 5459 }else { 5460 cli_out("Prbs p must be P7(0), P15(1), P23(2), P31(3), P9(4), P11(5), or P58(6).\n"); 5461 parse_arg_eq_done(&pt); 5462 return CMD_FAIL; 5463 } 5464 } 5465 5466 if (mode_str) { 5467 if (sal_strcasecmp(mode_str, "si") == 0) { 5468 mode = 1; 5469 } else if (sal_strcasecmp(mode_str, "hc") == 0) { 5470 mode = 0; 5471 } else { 5472 cli_out("Prbs mode must be si, mac, phy or hc.\n"); 5473 parse_arg_eq_done(&pt); 5474 return CMD_FAIL; 5475 } 5476 } 5477 5478 /* Now free allocated strings */ 5479 parse_arg_eq_done(&pt); 5480 5481 /* coverity[overrun-local] */ 5482 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 5483 5484 /* First set prbs mode */ 5485 rv = bcm_port_control_set(unit, port, bcmPortControlPrbsMode, mode); 5486 if (rv != BCM_E_NONE) { 5487 cli_out("Setting prbs mode failed: %s\n", bcm_errmsg(rv)); 5488 return CMD_FAIL; 5489 } 5490 if (cmd == _PHY_PRBS_SET_CMD || cmd == _PHY_PRBS_CLEAR_CMD) { 5491 if (poly >= 0 && poly <= 6) { 5492 /* Set polynomial */ 5493 rv = bcm_port_control_set(unit, port, 5494 bcmPortControlPrbsPolynomial, poly); 5495 if (rv != BCM_E_NONE) { 5496 cli_out("Setting prbs polynomial failed: %s\n", 5497 bcm_errmsg(rv)); 5498 return CMD_FAIL; 5499 } 5500 } else { 5501 cli_out("Polynomial must be 0..6.\n"); 5502 return CMD_FAIL; 5503 } 5504 5505 /* 5506 * Set tx/rx enable. If clear, enable == 0 5507 * Note that the order of enabling is important. The following 5508 * steps are listed in the SI Block description in the uArch Spec. 5509 * - Disable the normal receive path at the receive end. This is done 5510 * via SI_CONFIG0.enable; 5511 * - Enable the PRBS generator at the transmit end, 5512 * SI_CONFIG0.prbs_generator_en; 5513 * - Allow enough time for the PRBS stream to be received at the 5514 * monitor end 5515 * - Enable the PRBS monitor, SI_CONFIG0.prbs_monitor_en 5516 * - Read the PRBS error register to clear the error counter 5517 */ 5518 if (lb) { 5519 enable |= 0x8000; 5520 } 5521 rv = bcm_port_control_set(unit, port, 5522 bcmPortControlPrbsTxEnable, enable); 5523 if (rv != BCM_E_NONE) { 5524 cli_out("Setting prbs tx enable failed: %s\n", bcm_errmsg(rv)); 5525 return CMD_FAIL; 5526 } 5527 5528 rv = bcm_port_control_set(unit, port, 5529 bcmPortControlPrbsRxEnable, enable); 5530 if (rv != BCM_E_NONE) { 5531 cli_out("Setting prbs rx enable failed: %s\n", bcm_errmsg(rv)); 5532 return CMD_FAIL; 5533 } 5534 } else { /* _PHY_PRBS_GET_CMD */ 5535 int status; 5536 5537 /*If reading twice the error count will be missed.*/ 5538 rv = bcm_port_control_get(unit, port, 5539 bcmPortControlPrbsRxStatus, &status); 5540 if (rv != BCM_E_NONE) { 5541 cli_out("Getting prbs rx status failed: %s\n", 5542 bcm_errmsg(rv)); 5543 return CMD_FAIL; 5544 } 5545 5546 switch (status) { 5547 case 0: 5548 cli_out("%s (%2d): PRBS OK!\n", BCM_PORT_NAME(unit, port), 5549 port); 5550 break; 5551 case -1: 5552 cli_out("%s (%2d): PRBS Failed!\n", 5553 BCM_PORT_NAME(unit, port), port); 5554 break; 5555 default: 5556 cli_out("%s (%2d): PRBS has %d errors!\n", 5557 BCM_PORT_NAME(unit, port), port, status); 5558 break; 5559 } 5560 } 5561 } 5562 return CMD_OK; 5563 } 5564 5565 #ifdef BCM_TOMAHAWK3_SUPPORT 5566 /* PRBSStat is a command to periodically collect PRBS error counters and 5567 * compute BER based on the port configuration and the observed errorr 5568 * counters. The command processes and displays counters and BER calculation 5569 * for all lanes on a given port. 5570 */ 5571 5572 #define PRBS_STAT_F_INIT (1 << 0) 5573 #define PRBS_STAT_F_RUNNING (1 << 1) 5574 5575 #define PRBS_STAT_INIT(f) (f & PRBS_STAT_F_INIT) 5576 #define PRBS_STAT_RUNNING(f) (f & PRBS_STAT_F_RUNNING) 5577 5578 #define PM_MAX_LANES 8 5579 5580 #define PRBS_STAT_LOCK(lock) \ 5581 if (lock) { \ 5582 sal_mutex_take(lock, sal_mutex_FOREVER); \ 5583 } 5584 5585 #define PRBS_STAT_UNLOCK(lock) \ 5586 if (lock) { \ 5587 sal_mutex_give(lock); \ 5588 } 5589 5590 typedef struct prbs_stat_subcounter_s { 5591 uint64 errors; /* PRBS errors */ 5592 uint64 losslock; /* Loss of lock */ 5593 } prbs_stat_subcounter_t; 5594 5595 /* 5596 * Callback function - 5597 */ 5598 typedef void (*prbs_stat_handler_func_t)(int unit, bcm_port_t port, 5599 int lane, uint32 errors, 5600 int losslock); 5601 int 5602 prbs_stat_ber_get(int unit, bcm_port_t port, int lane, double *ber, 5603 int *interval); 5604 int 5605 prbs_stat_handler_register(int unit, prbs_stat_handler_func_t func); 5606 5607 int 5608 prbs_stat_handler_unregister(int unit, prbs_stat_handler_func_t func); 5609 5610 /* 5611 * Acc: accummulated from beginning/last clear 5612 * Cur: count since last time shown 5613 */ 5614 typedef struct prbs_stat_counter_s { 5615 prbs_stat_subcounter_t acc; 5616 prbs_stat_subcounter_t cur; 5617 } prbs_stat_counter_t; 5618 5619 /* 5620 * Per port info 5621 */ 5622 typedef struct prbs_stat_pinfo_s { 5623 int speed; 5624 int lanes; 5625 bcm_port_phy_fec_t fec_type; 5626 int intervals[PM_MAX_LANES]; /* Intervals expired since last show */ 5627 int prbs_lock[PM_MAX_LANES]; 5628 prbs_stat_counter_t counters[PM_MAX_LANES]; /* Counters per port/lane */ 5629 double ber[PM_MAX_LANES]; /* BER updated every interval */ 5630 } prbs_stat_pinfo_t; 5631 5632 typedef struct prbs_stat_handler_s { 5633 struct prbs_stat_handler_s *next; 5634 prbs_stat_handler_func_t func; 5635 } prbs_stat_handler_t; 5636 5637 5638 /* 5639 * The main control block 5640 * 5641 * The hardware polling interval is stored in secs. Due to the latched 5642 * clear-on-read hardware register behavior, the interval determines 5643 * how fast new data is available to be examined with show counters / show 5644 * ber. If show commands are called before an interval has transpired, 5645 * there will be no new errors or ber computation available. 5646 * 5647 * Loss of lock events are recorded. For counters, there are lossoflock 5648 * counters that get displayed. For BER computation, once there is a 5649 * loss of lock, the BER computation will not be updated until the 5650 * next show ber is called. This ensures loss of lock events are 5651 * noticed in the show ber output. 5652 */ 5653 typedef struct prbs_stat_cb_ { 5654 uint32 flags; 5655 int secs; 5656 bcm_pbmp_t pbmp; 5657 prbs_stat_pinfo_t pinfo[BCM_PBMP_PORT_MAX]; 5658 sal_sem_t sem; 5659 sal_thread_t thread_id; 5660 sal_mutex_t lock; 5661 sal_mutex_t handler_lock; 5662 prbs_stat_handler_t *handlers; /* Registered callback list */ 5663 } prbs_stat_cb_t; 5664 5665 /* Lookup table to determine VCO, base rate */ 5666 typedef struct stat_speed_entry_ { 5667 uint32 speed; /* port speed in Mbps */ 5668 uint32 num_lanes; /* number of lanes */ 5669 bcm_port_phy_fec_t fec_type; /* FEC type */ 5670 int vco; /* associated VCO rate of the ability */ 5671 double rate; /* base rate for speed */ 5672 } stat_speed_entry_t; 5673 5674 /* List of speed, lane, fec, VCO, and rate */ 5675 stat_speed_entry_t stat_speed_table[] = 5676 { 5677 /* speed lane fec_type vco base rate(Gbps) */ 5678 {10000, 1, bcmPortPhyFecNone, 20, 10.3125}, 5679 {10000, 1, bcmPortPhyFecBaseR, 20, 10.3125}, 5680 {20000, 1, bcmPortPhyFecNone, 20, 10.3125}, 5681 {20000, 1, bcmPortPhyFecBaseR, 20, 10.3125}, 5682 {40000, 4, bcmPortPhyFecNone, 20, 10.3125}, 5683 {40000, 4, bcmPortPhyFecBaseR, 20, 10.3125}, 5684 {40000, 2, bcmPortPhyFecNone, 20, 10.3125}, 5685 {25000, 1, bcmPortPhyFecNone, 25, 25.78125}, 5686 {25000, 1, bcmPortPhyFecBaseR, 25, 25.78125}, 5687 {25000, 1, bcmPortPhyFecRsFec, 25, 25.7812}, 5688 {50000, 1, bcmPortPhyFecNone, 25, 51.5625}, 5689 {50000, 1, bcmPortPhyFecRsFec, 25, 51.5625}, 5690 {50000, 1, bcmPortPhyFecRs544, 26, 53.125}, 5691 {50000, 1, bcmPortPhyFecRs272, 26, 53.125}, 5692 {50000, 2, bcmPortPhyFecNone, 25, 25.78125}, 5693 {50000, 2, bcmPortPhyFecRsFec, 25, 25.78125}, 5694 {50000, 2, bcmPortPhyFecRs544, 26, 26.5625}, 5695 {100000, 2, bcmPortPhyFecNone, 25, 51.5625}, 5696 {100000, 2, bcmPortPhyFecRsFec, 25, 51.5625}, 5697 {100000, 2, bcmPortPhyFecRs544, 26, 53.125}, 5698 {100000, 2, bcmPortPhyFecRs272, 26, 53.125}, 5699 {100000, 4, bcmPortPhyFecNone, 25, 25.78125}, 5700 {100000, 4, bcmPortPhyFecRsFec, 25, 25.78125}, 5701 {100000, 4, bcmPortPhyFecRs544, 26, 26.5625}, 5702 {200000, 4, bcmPortPhyFecNone, 25, 51.5625}, 5703 {200000, 4, bcmPortPhyFecRs272, 26, 53.125}, 5704 {200000, 4, bcmPortPhyFecRs544, 26, 53.125}, 5705 {200000, 4, bcmPortPhyFecRs544_2xN, 26, 53.125}, 5706 {400000, 8, bcmPortPhyFecRs544_2xN, 26, 53.125} 5707 }; 5708 5709 prbs_stat_cb_t prbs_stat_cb[BCM_MAX_NUM_UNITS]; 5710 5711 /* 5712 * Get base rate in Gbps for port based on port speed, lanes, and FEC 5713 */ 5714 STATIC int 5715 stat_speed_rate_get(int speed, int num_lanes, bcm_port_phy_fec_t fec_type, 5716 double *rate) 5717 { 5718 int i; 5719 int entries; 5720 5721 *rate = 0.; 5722 entries = sizeof(stat_speed_table) / sizeof(stat_speed_entry_t); 5723 for (i = 0; i < entries; i++) { 5724 if (stat_speed_table[i].speed == speed && 5725 stat_speed_table[i].num_lanes == num_lanes && 5726 stat_speed_table[i].fec_type == fec_type) 5727 { 5728 *rate = stat_speed_table[i].rate; 5729 break; 5730 } 5731 } 5732 return BCM_E_NONE; 5733 } 5734 5735 STATIC int 5736 prbs_stat_ber_compute(int unit, bcm_port_t port, int lanes, 5737 uint32 delta, sal_time_t secs, 5738 double *ber) 5739 { 5740 double rate; 5741 double nbits; 5742 prbs_stat_pinfo_t *psp; 5743 5744 if (secs < 1) { 5745 return 0; 5746 } 5747 5748 /* Make sure BER is computed at max if no errors */ 5749 if ( delta == 0){ 5750 delta = 1; 5751 } 5752 psp = &(prbs_stat_cb[unit].pinfo[port]); 5753 stat_speed_rate_get(psp->speed, psp->lanes, psp->fec_type, &rate); 5754 5755 /* Rate needs to be adjusted from Gbps to bps */ 5756 rate = rate * 1024. * 1024. * 1024.; 5757 nbits = rate * lanes; 5758 *ber = delta / (nbits * secs); 5759 5760 return 1; 5761 } 5762 5763 STATIC void 5764 prbs_stat_handler_notify(int unit, bcm_port_t port, int lane, uint32 errors, 5765 int losslock) 5766 { 5767 prbs_stat_cb_t *pscb; 5768 prbs_stat_handler_t *h, *next; 5769 5770 pscb = &(prbs_stat_cb[unit]); 5771 /* Notify all registered callbacks */ 5772 PRBS_STAT_LOCK(pscb->handler_lock); 5773 for (h = pscb->handlers; h != NULL; h = next) { 5774 next = h->next; 5775 h->func(unit, port, lane, errors, losslock); 5776 } 5777 PRBS_STAT_UNLOCK(pscb->handler_lock); 5778 } 5779 5780 STATIC void 5781 prbs_stat_counter_show(char *cname, char *pname, int lane, 5782 uint64 acc_counter, uint64 cur_counter, 5783 sal_time_t secs, int show_rate) 5784 { 5785 char chdr[32]; 5786 char buf[64]; 5787 uint64 delta; 5788 5789 sal_sprintf(chdr, "%s.%s[%d]", cname, pname, lane); 5790 COMPILER_64_COPY(delta, acc_counter); 5791 COMPILER_64_SUB_64(delta, cur_counter); 5792 if (!COMPILER_64_IS_ZERO(delta)) { 5793 /* Show couters since beginning */ 5794 format_uint64_decimal(buf, acc_counter, ','); 5795 LOG_CLI(("%-20s: %20s", chdr, buf)); 5796 5797 /* Show counters since last show */ 5798 format_uint64_decimal(buf, delta, ','); 5799 LOG_CLI((" %20s",buf)); 5800 5801 if (show_rate) { 5802 /* Show counters per second */ 5803 COMPILER_64_UDIV_32(delta, (uint32)secs); 5804 format_uint64_decimal(buf, delta, ','); 5805 LOG_CLI((" %12s/s",buf)); 5806 } 5807 LOG_CLI(("\n")); 5808 } 5809 } 5810 5811 5812 STATIC int 5813 prbs_stat_port_counter(int unit, bcm_port_t port) 5814 { 5815 int lane; 5816 int unlocked = 0; 5817 prbs_stat_cb_t *pscb; 5818 prbs_stat_pinfo_t *pspi; 5819 prbs_stat_counter_t *psco; 5820 5821 pscb = &(prbs_stat_cb[unit]); 5822 pspi = &(pscb->pinfo[port]); 5823 psco = pspi->counters; 5824 5825 for (lane = 0; lane < pspi->lanes; lane++) { 5826 if (!pspi->prbs_lock[lane]) { 5827 unlocked++; 5828 } 5829 } 5830 if (unlocked == pspi->lanes) { 5831 LOG_CLI(("%s: no PRBS lock\n", BCM_PORT_NAME(unit, port))); 5832 } 5833 5834 for (lane = 0; lane < pspi->lanes; lane++) { 5835 prbs_stat_counter_show("ERRORS", BCM_PORT_NAME(unit, port), 5836 lane, psco[lane].acc.errors, 5837 psco[lane].cur.errors, 5838 pscb->secs * pspi->intervals[lane], TRUE); 5839 pspi->intervals[lane] = 0; 5840 psco[lane].cur.errors = psco[lane].acc.errors; 5841 } 5842 5843 for (lane = 0; lane < pspi->lanes; lane++) { 5844 prbs_stat_counter_show("LOSSLOCK", BCM_PORT_NAME(unit, port), 5845 lane, psco[lane].acc.losslock, 5846 psco[lane].cur.losslock, 0, FALSE); 5847 psco[lane].cur.losslock = psco[lane].acc.losslock; 5848 } 5849 5850 5851 return 1; 5852 } 5853 5854 STATIC void 5855 prbs_stat_ber_update(int unit, bcm_port_t port, int lane, uint32 delta) 5856 { 5857 double ber; 5858 prbs_stat_cb_t *pscb; 5859 prbs_stat_pinfo_t *pspi; 5860 5861 pscb = &(prbs_stat_cb[unit]); 5862 pspi = &(pscb->pinfo[port]); 5863 5864 if (delta >= 0) { 5865 if (!prbs_stat_ber_compute(unit, port, 1, delta, pscb->secs, &ber)) { 5866 LOG_ERROR(BSL_LS_APPL_PHY, 5867 (BSL_META_U(unit, 5868 "%s[%d]: could not compute BER\n"), 5869 BCM_PORT_NAME(unit, port), lane)); 5870 return; 5871 } 5872 pspi->ber[lane] = ber; 5873 LOG_DEBUG(BSL_LS_APPL_PHY, 5874 (BSL_META_U(unit, "Updated BER for port %d: %8.2e (delta=%d)\n"), 5875 port, ber, delta)); 5876 } else { 5877 pspi->ber[lane] = 0; 5878 } 5879 } 5880 5881 /* 5882 * If there is a port configuration change, update the new configuration 5883 * and clear counters, BER 5884 */ 5885 STATIC int 5886 prbs_stat_pinfo_update(int unit, bcm_port_t port) 5887 { 5888 prbs_stat_pinfo_t *pspi; 5889 prbs_stat_counter_t *psco; 5890 bcm_port_resource_t rsrc; 5891 5892 pspi = &(prbs_stat_cb[unit].pinfo[port]); 5893 5894 BCM_IF_ERROR_RETURN(bcm_port_resource_speed_get(unit, port, &rsrc)); 5895 if ((pspi->speed == rsrc.speed) && 5896 (pspi->lanes == rsrc.lanes) && 5897 (pspi->fec_type == rsrc.fec_type)) { 5898 return 1; 5899 } 5900 5901 LOG_DEBUG(BSL_LS_APPL_PHY, 5902 (BSL_META_U(unit, "Updating %s config\n"), 5903 BCM_PORT_NAME(unit, port))); 5904 5905 PRBS_STAT_LOCK(prbs_stat_cb[unit].lock); 5906 pspi->speed = rsrc.speed; 5907 pspi->lanes = rsrc.lanes; 5908 pspi->fec_type = rsrc.fec_type; 5909 5910 psco = pspi->counters; 5911 sal_memset(psco, 0, sizeof(prbs_stat_counter_t) * PM_MAX_LANES); 5912 sal_memset(&(pspi->ber), 0, sizeof(double) * PM_MAX_LANES); 5913 PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock); 5914 5915 return 1; 5916 } 5917 5918 5919 STATIC int 5920 prbs_stat_collect(int unit, bcm_port_t port) 5921 { 5922 int rv; 5923 int lane; 5924 uint32 status; 5925 uint64 lcount; 5926 bcm_gport_t gport; 5927 prbs_stat_pinfo_t *pspi; 5928 prbs_stat_counter_t *psco; 5929 5930 prbs_stat_pinfo_update(unit, port); 5931 pspi = &(prbs_stat_cb[unit].pinfo[port]); 5932 psco = pspi->counters; 5933 5934 PRBS_STAT_LOCK(prbs_stat_cb[unit].lock); 5935 for (lane = 0; lane < pspi->lanes; lane++) { 5936 COMPILER_64_SET(lcount, 0, 0); 5937 BCM_PHY_GPORT_LANE_PORT_SET(gport, lane, port); 5938 rv = bcm_port_phy_control_get(0, gport, 5939 BCM_PORT_PHY_CONTROL_PRBS_RX_STATUS, 5940 &status); 5941 if (BCM_FAILURE(rv)) { 5942 PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock); 5943 return 0; 5944 } 5945 LOG_DEBUG(BSL_LS_APPL_PHY, 5946 (BSL_META_U(unit, "%s: collecting status %d\n"), 5947 BCM_PORT_NAME(unit, port), status)); 5948 5949 switch (status) { 5950 case -1: 5951 pspi->prbs_lock[lane] = 0; 5952 pspi->ber[lane] = 0; 5953 break; 5954 case -2: 5955 pspi->prbs_lock[lane] = 1; 5956 COMPILER_64_ADD_32(psco[lane].acc.losslock, 1); 5957 pspi->ber[lane] = -2; 5958 prbs_stat_handler_notify(unit, port, lane, 0, 1); 5959 break; 5960 default: 5961 pspi->prbs_lock[lane] = 1; 5962 COMPILER_64_SET(lcount, 0, status); 5963 COMPILER_64_ADD_64(psco[lane].acc.errors, lcount); 5964 pspi->intervals[lane]++; 5965 if (pspi->ber[lane] != -2) { 5966 /* 5967 * Do not update BER to preserve the loss of lock event. 5968 * The next show BER will 'unlatch' the loss of lock event 5969 * and restart BER calculation. Without this, the loss 5970 * of lock event will be lost if multiple intervals 5971 * transpire between show ber calls. 5972 */ 5973 prbs_stat_ber_update(unit, port, lane, status); 5974 } 5975 prbs_stat_handler_notify(unit, port, lane, status, 0); 5976 } 5977 } 5978 PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock); 5979 5980 return 1; 5981 } 5982 5983 STATIC void 5984 prbs_stat_thread(int unit) 5985 { 5986 int u_interval; 5987 bcm_port_t port; 5988 prbs_stat_cb_t *pscb; 5989 5990 pscb = &(prbs_stat_cb[unit]); 5991 u_interval = pscb->secs * 1000000; /* Adjust to usec */ 5992 5993 while (pscb->secs) { 5994 BCM_PBMP_ITER(pscb->pbmp, port) { 5995 LOG_DEBUG(BSL_LS_APPL_PHY, 5996 (BSL_META_U(unit, "Collecting PRBS for port %d\n"), port)); 5997 if (!prbs_stat_collect(unit, port)) { 5998 LOG_ERROR(BSL_LS_APPL_PHY, 5999 (BSL_META_U( 6000 unit, 6001 "Failed collecting PRBS stats for port %d\n"), port)); 6002 } 6003 } 6004 sal_sem_take(pscb->sem, u_interval); 6005 } 6006 6007 PRBS_STAT_LOCK(pscb->lock); 6008 BCM_PBMP_ITER(pscb->pbmp, port) { 6009 sal_memset(&(prbs_stat_cb[unit].pinfo[port].counters), 6010 0, sizeof(prbs_stat_counter_t) * PM_MAX_LANES); 6011 } 6012 pscb->flags &= ~PRBS_STAT_F_RUNNING; 6013 PRBS_STAT_UNLOCK(pscb->lock); 6014 6015 pscb->thread_id = NULL; 6016 LOG_DEBUG(BSL_LS_APPL_PHY, ("PRBS stat thread exiting...\n")); 6017 sal_thread_exit(0); 6018 } 6019 6020 6021 STATIC int 6022 prbs_stat_init(int unit) 6023 { 6024 prbs_stat_cb_t *pscb; 6025 6026 pscb = &(prbs_stat_cb[unit]); 6027 if (PRBS_STAT_INIT(pscb->flags)) { 6028 return 1; 6029 } 6030 sal_memset(pscb, 0, sizeof(prbs_stat_cb_t)); 6031 pscb->flags = PRBS_STAT_F_INIT; 6032 pscb->handlers = NULL; 6033 if ((pscb->lock = sal_mutex_create("PRBSStat lock")) == NULL) 6034 return 0; 6035 if ((pscb->handler_lock = sal_mutex_create("PRBSStat handler lock")) == NULL) 6036 return 0; 6037 if ((pscb->sem = sal_sem_create("PRBSStat sleep", sal_sem_BINARY, 0)) == NULL) 6038 return 0; 6039 6040 return 1; 6041 } 6042 6043 STATIC int 6044 prbs_stat_clear(int unit, bcm_pbmp_t pbmp, args_t *a) 6045 { 6046 bcm_port_t port; 6047 /* 6048 bcm_pbmp_t pbmp; 6049 6050 if (!prbs_stat_pbmp_parse(unit, a, &pbmp)) { 6051 return CMD_USAGE; 6052 } 6053 */ 6054 PRBS_STAT_LOCK(prbs_stat_cb[unit].lock); 6055 BCM_PBMP_ITER(pbmp, port) { 6056 sal_memset(&(prbs_stat_cb[unit].pinfo[port].counters), 6057 0, sizeof(prbs_stat_counter_t) * PM_MAX_LANES); 6058 } 6059 PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock); 6060 return CMD_OK; 6061 } 6062 6063 6064 STATIC int 6065 prbs_stat_counter(int unit, bcm_pbmp_t pbmp, args_t *a) 6066 { 6067 int rv = 1; 6068 bcm_port_t port; 6069 /* 6070 bcm_pbmp_t pbmp; 6071 6072 if (!prbs_stat_pbmp_parse(unit, a, &pbmp)) { 6073 return CMD_USAGE; 6074 } 6075 */ 6076 if (!PRBS_STAT_RUNNING(prbs_stat_cb[unit].flags)) { 6077 LOG_CLI(("PRBSStat not running\n")); 6078 return CMD_FAIL; 6079 } 6080 6081 PRBS_STAT_LOCK(prbs_stat_cb[unit].lock); 6082 LOG_CLI(("%-20s %20s %20s %12s", 6083 "port", "accumulated count", "last count", "count per sec\n")); 6084 BCM_PBMP_ITER(pbmp, port) { 6085 rv = prbs_stat_port_counter(unit, port); 6086 if (!rv) { 6087 break; 6088 } 6089 } 6090 6091 PRBS_STAT_UNLOCK(prbs_stat_cb[unit].lock); 6092 return rv ? CMD_OK : CMD_FAIL; 6093 } 6094 6095 6096 STATIC int 6097 prbs_stat_ber(int unit, bcm_pbmp_t pbmp, args_t *a) 6098 { 6099 int lane; 6100 bcm_port_t port; 6101 /* 6102 bcm_pbmp_t pbmp; 6103 */ 6104 prbs_stat_cb_t *pscb; 6105 prbs_stat_pinfo_t *pspi; 6106 6107 /* 6108 if (!prbs_stat_pbmp_parse(unit, a, &pbmp)) { 6109 return CMD_USAGE; 6110 } 6111 */ 6112 6113 pscb = &(prbs_stat_cb[unit]); 6114 if (!PRBS_STAT_RUNNING(pscb->flags)) { 6115 LOG_CLI(("PRBSStat not running\n")); 6116 return CMD_FAIL; 6117 } 6118 6119 LOG_CLI(("%-6s %s", "port", "BER\n")); 6120 LOG_CLI(("====\n")); 6121 PRBS_STAT_LOCK(pscb->lock); 6122 BCM_PBMP_ITER(pbmp, port) { 6123 pspi = &(pscb->pinfo[port]); 6124 for (lane = 0; lane < pspi->lanes; lane++) { 6125 if (pspi->ber[lane] == -2) { 6126 LOG_CLI(("%s[%d] : LossOfLock\n", BCM_PORT_NAME(unit, port), lane)); 6127 pspi->ber[lane] = 0; /* Clear it here now that has been displayed */ 6128 } else if (pspi->ber[lane]) { 6129 LOG_CLI(("%s[%d] : %4.2e\n", BCM_PORT_NAME(unit, port), 6130 lane, pspi->ber[lane])); 6131 } else { 6132 LOG_CLI(("%s[%d] : NoLock\n", BCM_PORT_NAME(unit, port), lane)); 6133 } 6134 } 6135 LOG_CLI(("====\n")); 6136 } 6137 PRBS_STAT_UNLOCK(pscb->lock); 6138 return CMD_OK; 6139 } 6140 6141 6142 STATIC int 6143 prbs_stat_stop(int unit) 6144 { 6145 prbs_stat_cb_t *pscb; 6146 6147 pscb = &(prbs_stat_cb[unit]); 6148 if (PRBS_STAT_RUNNING(pscb->flags)) { 6149 /* Signal thread to stop running */ 6150 pscb->secs = 0; 6151 LOG_CLI(("Stopping PRBSStat thread\n")); 6152 sal_sem_give(pscb->sem); 6153 /* Cleared when thread exit -- pscb->flags &= ~PRBS_STAT_F_RUNNING; */ 6154 } else { 6155 LOG_CLI(("PRBSStat already stopped\n")); 6156 } 6157 6158 return CMD_OK; 6159 } 6160 6161 6162 STATIC void 6163 prbs_stat_counter_init(int unit)/*, bcm_pbmp_t pbmp)*/ 6164 { 6165 int lane; 6166 uint32 status; 6167 bcm_port_t port; 6168 bcm_gport_t gport; 6169 prbs_stat_cb_t *pscb; 6170 prbs_stat_pinfo_t *pspi; 6171 prbs_stat_counter_t *psco; 6172 6173 pscb = &(prbs_stat_cb[unit]); 6174 6175 BCM_PBMP_ITER(pscb->pbmp, port) { 6176 pspi = &(pscb->pinfo[port]); 6177 psco = pspi->counters; 6178 6179 sal_memset(psco, 0,sizeof(prbs_stat_counter_t) * PM_MAX_LANES); 6180 sal_memset(&(pspi->ber), 0, sizeof(double) * PM_MAX_LANES); 6181 6182 /* Prime PRBS once to clear hardware counters */ 6183 for (lane = 0; lane < pspi->lanes; lane++) { 6184 BCM_PHY_GPORT_LANE_PORT_SET(gport, lane, port); 6185 bcm_port_phy_control_get(unit, gport, 6186 BCM_PORT_PHY_CONTROL_PRBS_RX_STATUS, 6187 &status); 6188 pspi->intervals[lane] = 0; 6189 } 6190 } 6191 } 6192 6193 STATIC int 6194 prbs_stat_start(int unit, bcm_pbmp_t pbmp, args_t *a) 6195 { 6196 int secs; 6197 /*bcm_pbmp_t pbmp;*/ 6198 parse_table_t pt; 6199 prbs_stat_cb_t *pscb; 6200 6201 pscb = &(prbs_stat_cb[unit]); 6202 6203 if (ARG_CNT(a) == 0) { 6204 if (!(pscb->flags & PRBS_STAT_F_RUNNING)) { 6205 LOG_CLI(("PRBSStat: not running\n")); 6206 } else { 6207 char pbmp_str[SOC_PBMP_FMT_LEN]; 6208 SOC_PBMP_FMT(pscb->pbmp, pbmp_str); 6209 LOG_CLI(("PRBSStat: interval=%ds\n", pscb->secs)); 6210 LOG_CLI(("PRBSStat: pbmp=%s\n", pbmp_str)); 6211 } 6212 return CMD_OK; 6213 } 6214 6215 /*BCM_PBMP_ASSIGN(pbmp, pscb->pbmp);*/ 6216 secs = pscb->secs; 6217 6218 parse_table_init(unit, &pt); 6219 parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 0, &secs, NULL); 6220 /*parse_table_add(&pt, "PortBitMap",PQ_DFL|PQ_PBMP, 0, &pbmp, NULL);*/ 6221 6222 if (parse_arg_eq(a, &pt) < 0) { 6223 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 6224 parse_arg_eq_done(&pt); 6225 return CMD_USAGE; 6226 } 6227 parse_arg_eq_done(&pt); 6228 6229 if (secs == 0 || secs > 180) { 6230 LOG_CLI(("Interval must be between 1 and 180 seconds\n")); 6231 return CMD_USAGE; 6232 } 6233 6234 /* 6235 * Allow start to be called while already running to update 6236 * interval and pbmp 6237 */ 6238 if (pscb->flags & PRBS_STAT_F_RUNNING) { 6239 PRBS_STAT_LOCK(pscb->lock); 6240 } 6241 6242 pscb->secs = secs; 6243 BCM_PBMP_ASSIGN(pscb->pbmp, pbmp); 6244 6245 prbs_stat_counter_init(unit); 6246 6247 if (pscb->flags & PRBS_STAT_F_RUNNING) { 6248 PRBS_STAT_UNLOCK(pscb->lock); 6249 /* Must return without starting new thread */ 6250 return CMD_OK; 6251 } 6252 6253 /* Thread should not be running */ 6254 if (pscb->thread_id != NULL) { 6255 LOG_CLI(("PRBSStat thread already running\n")); 6256 return CMD_FAIL; 6257 } 6258 6259 pscb->thread_id = sal_thread_create("PRBSstat", 6260 SAL_THREAD_STKSZ, 6261 100, /* thread priority */ 6262 (void (*)(void*))prbs_stat_thread, 6263 INT_TO_PTR(unit)); 6264 if (pscb->thread_id == SAL_THREAD_ERROR) { 6265 LOG_ERROR(BSL_LS_APPL_PHY, 6266 (BSL_META_U(unit, "Could not create PRBSstat thread\n"))); 6267 pscb->flags &= ~PRBS_STAT_F_RUNNING; 6268 return CMD_FAIL; 6269 } 6270 LOG_CLI(("PRBSStat thread started...\n")); 6271 pscb->flags |= PRBS_STAT_F_RUNNING; 6272 6273 return CMD_OK; 6274 } 6275 6276 6277 /* 6278 * Callback testing 6279 */ 6280 6281 STATIC void 6282 prbs_stat_test_callback(int unit, bcm_port_t port, int lane, uint32 errors, int losslock) 6283 { 6284 if (losslock) { 6285 LOG_CLI(("%s[%d]: locklock=%d\n", BCM_PORT_NAME(unit, port), 6286 lane, losslock)); 6287 } else if (errors) { 6288 LOG_CLI(("%s[%d]: errors=%-8d\n", BCM_PORT_NAME(unit, port), 6289 lane, errors)); 6290 } 6291 } 6292 6293 6294 /* 6295 * Match input with key. Allows abbreviated matches based on 6296 * the minimum initial capital letters in key. For example, 6297 * key = ABCdef will be matched with the input 6298 * abc, abcd, abcde, abcdef. Any other input is a mismatch. 6299 */ 6300 STATIC int 6301 prbs_stat_cmd_match(char *inp, char *key) 6302 { 6303 while (*key && isupper(*key)) { 6304 if (!*inp || (toupper(*inp) != *key)) { 6305 return 0; 6306 } 6307 key++; 6308 inp++; 6309 } 6310 while (*inp) { 6311 if (toupper(*inp) != toupper(*key)) { 6312 return 0; 6313 } 6314 key++; 6315 inp++; 6316 } 6317 return 1; 6318 } 6319 6320 6321 STATIC int 6322 prbs_stat_callback_test(int unit, args_t *a) 6323 { 6324 int rv; 6325 char *option; 6326 6327 if (ARG_CNT(a) == 0) { 6328 LOG_ERROR(BSL_LS_APPL_PHY, 6329 (BSL_META_U(unit, "Must specify REGister or UNREGister\n"))); 6330 return CMD_USAGE; 6331 } 6332 option = ARG_GET(a); 6333 if (option == NULL) { 6334 return CMD_USAGE; 6335 } 6336 if (prbs_stat_cmd_match(option, "REGister")) { 6337 rv = prbs_stat_handler_register(unit, prbs_stat_test_callback); 6338 } else if (prbs_stat_cmd_match(option, "UNREGister")) { 6339 rv = prbs_stat_handler_unregister(unit, prbs_stat_test_callback); 6340 } else { 6341 LOG_ERROR(BSL_LS_APPL_PHY, 6342 (BSL_META_U(unit, "Must specify REGister or UNREGister\n"))); 6343 return CMD_USAGE; 6344 } 6345 return (rv == BCM_E_NONE) ? CMD_OK : CMD_FAIL; 6346 } 6347 6348 STATIC cmd_result_t 6349 prbs_stat_cfg(int unit) 6350 { 6351 prbs_stat_cb_t *pscb; 6352 6353 pscb = &(prbs_stat_cb[unit]); 6354 6355 if (!PRBS_STAT_RUNNING(prbs_stat_cb[unit].flags)) { 6356 LOG_CLI(("PRBSStat not started\n")); 6357 } else { 6358 char buf[512]; 6359 char pfmt[SOC_PBMP_FMT_LEN]; 6360 6361 format_bcm_pbmp(unit, buf, sizeof(buf), pscb->pbmp); 6362 LOG_CLI(("PRBSStat: Polling interval: %d sec\n", pscb->secs)); 6363 LOG_CLI(("PRBSStat: Port bitmap: %s: %s\n", 6364 SOC_PBMP_FMT(pscb->pbmp, pfmt), buf)); 6365 } 6366 return CMD_OK; 6367 } 6368 6369 /*** APIs ***/ 6370 /* 6371 * Get computed BER for the last interval 6372 * 6373 * If the port is not configured with FEC or the BER cannot be computed, 6374 * the BER is 0 6375 * 6376 * If successful, return 1; otherwise 0 6377 */ 6378 int 6379 prbs_stat_ber_get(int unit, bcm_port_t port, int lane, double *ber, 6380 int *interval) 6381 { 6382 prbs_stat_cb_t *pscb = &(prbs_stat_cb[unit]); 6383 prbs_stat_pinfo_t *pspi = &(pscb->pinfo[port]); 6384 6385 PRBS_STAT_LOCK(pscb->lock); 6386 *ber = pspi->ber[lane]; 6387 *interval = pscb->secs; 6388 PRBS_STAT_UNLOCK(pscb->lock); 6389 6390 return 1; 6391 } 6392 6393 6394 /* 6395 * Register handler function from the caller 6396 */ 6397 int 6398 prbs_stat_handler_register(int unit, prbs_stat_handler_func_t func) 6399 { 6400 int found = 0; 6401 prbs_stat_cb_t *pscb = &(prbs_stat_cb[unit]); 6402 prbs_stat_handler_t *h; 6403 6404 if (!PRBS_STAT_INIT(pscb->flags)) { 6405 LOG_CLI(("PRBSStat not initialized\n")); 6406 return BCM_E_DISABLED; 6407 } 6408 6409 PRBS_STAT_LOCK(pscb->handler_lock); 6410 for (h = pscb->handlers; h != NULL; h = h->next) { 6411 if (h->func == func) { 6412 found = TRUE; 6413 } 6414 } 6415 /* Already registered */ 6416 if (found) { 6417 PRBS_STAT_UNLOCK(pscb->handler_lock); 6418 return BCM_E_NONE; 6419 } 6420 6421 h = sal_alloc(sizeof(prbs_stat_handler_t), "PRBSStat handler"); 6422 if (h == NULL) { 6423 PRBS_STAT_UNLOCK(pscb->handler_lock); 6424 return BCM_E_MEMORY; 6425 } 6426 /* Move current first node to second node */ 6427 h->next = pscb->handlers; 6428 h->func = func; 6429 /* Put the newly created node in the front of the list */ 6430 pscb->handlers = h; 6431 PRBS_STAT_UNLOCK(pscb->handler_lock); 6432 6433 return BCM_E_NONE; 6434 } 6435 6436 /* 6437 * Unregister handler function from the caller 6438 */ 6439 int 6440 prbs_stat_handler_unregister(int unit, prbs_stat_handler_func_t func) 6441 { 6442 prbs_stat_cb_t *pscb = &(prbs_stat_cb[unit]); 6443 prbs_stat_handler_t *h, *prev; 6444 6445 if (!PRBS_STAT_INIT(pscb->flags)) { 6446 LOG_CLI(("PRBSStat not initialized\n")); 6447 return BCM_E_DISABLED; 6448 } 6449 6450 PRBS_STAT_LOCK(pscb->handler_lock); 6451 for (prev = NULL, h = pscb->handlers; h != NULL; prev = h, h = h->next) { 6452 if (h->func == func) { 6453 if (prev == NULL) { 6454 pscb->handlers = h->next; 6455 } else { 6456 prev->next = h->next; 6457 } 6458 break; 6459 } 6460 } 6461 PRBS_STAT_UNLOCK(pscb->handler_lock); 6462 6463 if (h != NULL) { 6464 sal_free(h); 6465 return BCM_E_NONE; 6466 } 6467 return BCM_E_NOT_FOUND; 6468 } 6469 6470 static char prbs_stat_usage[] = 6471 "\nParameters: [STArt [Interval=<secs>]]\n" 6472 " [STOp] [Counters] [Ber] [CLear]\n"; 6473 6474 STATIC cmd_result_t 6475 _phy_diag_prbsstat(int unit, bcm_pbmp_t pbmp, args_t *a) 6476 { 6477 char *sc; 6478 6479 /* Check if a unit is attached */ 6480 if (!sh_check_attached(ARG_CMD(a), unit)) { 6481 return CMD_FAIL; 6482 } 6483 6484 if (!SOC_IS_TOMAHAWK3(unit)) { 6485 return CMD_NOTIMPL; 6486 } 6487 6488 sc = ARG_GET(a); 6489 /* check and display current configuration */ 6490 if (sc == NULL) { 6491 return prbs_stat_cfg(unit); 6492 } 6493 6494 /* initialize */ 6495 if (!prbs_stat_init(unit)) { 6496 return CMD_FAIL; 6497 } 6498 6499 if (prbs_stat_cmd_match(sc, "?")) { 6500 LOG_CLI(("%s\n", prbs_stat_usage)); 6501 } else if (prbs_stat_cmd_match(sc, "STArt")) { 6502 return prbs_stat_start(unit, pbmp, a); 6503 } else if (prbs_stat_cmd_match(sc, "STOp")) { 6504 return prbs_stat_stop(unit); 6505 } else if (prbs_stat_cmd_match(sc, "Counters")) { 6506 return prbs_stat_counter(unit, pbmp, a); 6507 } else if (prbs_stat_cmd_match(sc, "Ber")) { 6508 return prbs_stat_ber(unit, pbmp, a); 6509 } else if (prbs_stat_cmd_match(sc, "CLear")) { 6510 return prbs_stat_clear(unit, pbmp, a); 6511 } else if (prbs_stat_cmd_match(sc, "Testcb")) { 6512 return prbs_stat_callback_test(unit, a); 6513 } else { 6514 return CMD_USAGE; 6515 } 6516 6517 return CMD_OK; 6518 } 6519 6520 /* end of prbs_stat */ 6521 6522 /* start of fec_stat */ 6523 /* FECStat is a command that periodically collects FEC status counters such as 6524 * corrected and uncorrected FEC codewords for a given port. The command then 6525 * uses the corrected codewords to compute the pre-FEC bit error rate for the 6526 * channel. FECStat can be used to collect FEC status counters anytime there is 6527 * FEC traffic so there is no need to stop real traffic and dedicate the channel 6528 * for diagnostics purposes. 6529 */ 6530 #define FEC_STAT_F_INIT (1 << 0) 6531 #define FEC_STAT_F_RUNNING (1 << 1) 6532 6533 #define FEC_STAT_INIT(f) (f & FEC_STAT_F_INIT) 6534 #define FEC_STAT_RUNNING(f) (f & FEC_STAT_F_RUNNING) 6535 6536 #define FEC_STAT_LOCK(unit) \ 6537 if (fec_stat_cb[unit].lock) { \ 6538 sal_mutex_take(fec_stat_cb[unit].lock, sal_mutex_FOREVER); \ 6539 } 6540 6541 #define FEC_STAT_UNLOCK(unit) \ 6542 if (fec_stat_cb[unit].lock) { \ 6543 sal_mutex_give(fec_stat_cb[unit].lock); \ 6544 } 6545 6546 typedef struct fec_stat_subcounter_s { 6547 uint64 corrected; 6548 uint64 uncorrected; 6549 uint64 symbol_error[PM_MAX_LANES]; /* Per-lane based symbol error count. RS FEC only.*/ 6550 } fec_stat_subcounter_t; 6551 6552 /* 6553 * Acc: accummulated from beginning/last clear 6554 * Cur: count since last time shown 6555 */ 6556 typedef struct fec_stat_counter_s { 6557 fec_stat_subcounter_t acc; 6558 fec_stat_subcounter_t cur; 6559 } fec_stat_counter_t; 6560 6561 /* 6562 * Per port info 6563 */ 6564 typedef struct fec_stat_pinfo_s { 6565 int speed; 6566 int lanes; 6567 bcm_port_phy_fec_t fec_type; 6568 int intervals; 6569 fec_stat_counter_t counters;/* Counters per port for this FEC */ 6570 double ber[PM_MAX_LANES]; /* updated every interval */ 6571 } fec_stat_pinfo_t; 6572 6573 typedef struct fec_stat_cb_ { 6574 uint32 flags; 6575 int secs; 6576 int cfg_secs; 6577 bcm_pbmp_t pbmp; 6578 fec_stat_pinfo_t pinfo[BCM_PBMP_PORT_MAX]; 6579 sal_thread_t thread_id; 6580 sal_mutex_t lock; 6581 sal_sem_t sem; 6582 } fec_stat_cb_t; 6583 6584 fec_stat_cb_t fec_stat_cb[BCM_MAX_NUM_UNITS]; 6585 6586 /* 6587 * Get FEC that is then used to key off which port phy control to issue 6588 * to get FEC corrected/uncorrected counters 6589 * 6590 * Note that the counters are based on either BASE_R or RS FEC. RS FEC 6591 * includes RS528, RS544, RS272 FEC 6592 */ 6593 STATIC void 6594 fec_stat_fec_type_get(int unit, bcm_port_t port, bcm_port_phy_fec_t *fec_type) 6595 { 6596 fec_stat_pinfo_t *fspi; 6597 6598 fspi = &(fec_stat_cb[unit].pinfo[port]); 6599 6600 *fec_type = fspi->fec_type; 6601 6602 if ((fspi->fec_type == bcmPortPhyFecRs544) || 6603 (fspi->fec_type == bcmPortPhyFecRs272) || 6604 (fspi->fec_type == bcmPortPhyFecRs544_2xN) || 6605 (fspi->fec_type == bcmPortPhyFecRs272_2xN)) { 6606 *fec_type = bcmPortPhyFecRsFec; 6607 } 6608 } 6609 6610 /* This function will compute per-lane based BER for 1xN RS FEC and 6611 * per-port based BER for BaseR FEC and 2xN RS FEC. 6612 */ 6613 STATIC int 6614 fec_stat_ber_compute(int unit, bcm_port_t port, uint32 delta, uint32* symb_delta, 6615 sal_time_t secs, double *ber) 6616 { 6617 int i; 6618 double rate; 6619 double nbits; 6620 uint32 sum_symb_delta = 0; 6621 fec_stat_pinfo_t *fspi; 6622 bcm_port_phy_fec_t fec_type; 6623 6624 if (secs < 1) { 6625 return BCM_E_PARAM; 6626 } 6627 6628 fspi = &(fec_stat_cb[unit].pinfo[port]); 6629 BCM_IF_ERROR_RETURN 6630 (stat_speed_rate_get(fspi->speed, fspi->lanes, fspi->fec_type, &rate)); 6631 if (rate == 0) { 6632 cli_out("Error: Unsupported speed mode: %d\n", port); 6633 return BCM_E_UNAVAIL; 6634 } 6635 fec_stat_fec_type_get(unit, port, &fec_type); 6636 6637 /* Rate needs to be adjusted from Gbps to bps */ 6638 rate = rate * 1024. * 1024. * 1024.; 6639 /* Calculate per port BER for 2xN RS FEC based on sum of symbol error delta. 6640 * Calculate per lane BER for other RS FEC based on symbol error delta. 6641 * Calculate per port BER for other FEC types based on block error delta. 6642 */ 6643 if ((fspi->fec_type == bcmPortPhyFecRs544_2xN) || 6644 (fspi->fec_type == bcmPortPhyFecRs272_2xN)) { 6645 nbits = rate * fspi->lanes; 6646 for (i = 0; i < fspi->lanes; i++) { 6647 sum_symb_delta += symb_delta[i]; 6648 } 6649 /* Per port BER stored in ber[0]. */ 6650 ber[0] = sum_symb_delta / (nbits * secs); 6651 LOG_DEBUG(BSL_LS_APPL_PHY, 6652 (BSL_META_U(unit, "Updated BER for port %d: %8.2e\n"), 6653 port, ber[0])); 6654 } else if (fec_type == bcmPortPhyFecRsFec) { 6655 nbits = rate; 6656 for (i = 0; i < fspi->lanes; i++) { 6657 ber[i] = symb_delta[i] / (nbits * secs); 6658 LOG_DEBUG(BSL_LS_APPL_PHY, 6659 (BSL_META_U(unit, "Updated BER for port %d lane %d: %8.2e\n"), 6660 port, i, ber[i])); 6661 6662 } 6663 } else { 6664 /* Per port BER stored in ber[0]. */ 6665 nbits = rate * fspi->lanes; 6666 ber[0] = delta / (nbits * secs); 6667 LOG_DEBUG(BSL_LS_APPL_PHY, 6668 (BSL_META_U(unit, "Updated BER for port %d: %8.2e\n"), 6669 port, ber[0])); 6670 6671 } 6672 6673 return BCM_E_NONE; 6674 } 6675 6676 STATIC void 6677 fec_stat_counter_show(char *cname, char *pname, int* lane, 6678 uint64 acc_counter, uint64 cur_counter, sal_time_t secs) 6679 { 6680 char chdr[32]; 6681 char buf[64]; 6682 uint64 delta; 6683 6684 if (lane != NULL) { 6685 sal_sprintf(chdr, "%s.%s[%d]", cname, pname, *lane); 6686 } else { 6687 sal_sprintf(chdr, "%s.%s", cname, pname); 6688 } 6689 6690 delta = acc_counter; 6691 COMPILER_64_SUB_64(delta, cur_counter); 6692 if (!COMPILER_64_IS_ZERO(delta)) { 6693 format_uint64_decimal(buf, acc_counter, ','); 6694 LOG_CLI(("%-25s: %20s", chdr, buf)); 6695 6696 /* Show counters since last show */ 6697 format_uint64_decimal(buf, delta, ','); 6698 LOG_CLI((" %20s",buf)); 6699 6700 /* Show counters per second */ 6701 COMPILER_64_UDIV_32(delta, (uint32)secs); 6702 format_uint64_decimal(buf, delta, ','); 6703 LOG_CLI((" %12s/s\n",buf)); 6704 } 6705 } 6706 6707 STATIC int 6708 fec_stat_port_counter(int unit, bcm_port_t port) 6709 { 6710 int secs, lane, symb_err_valid = 0; 6711 bcm_port_phy_fec_t fec_type; 6712 fec_stat_cb_t *fscb; 6713 fec_stat_pinfo_t *fspi; 6714 fec_stat_counter_t *fsco; 6715 char *corrected_name; 6716 char *uncorrected_name; 6717 char *symbol_error_name = "RS_SYMBOL_ERR"; 6718 fscb = &(fec_stat_cb[unit]); 6719 fspi = &(fscb->pinfo[port]); 6720 fsco = &(fspi->counters); 6721 6722 fec_stat_fec_type_get(unit, port, &fec_type); 6723 if (fec_type == bcmPortPhyFecRsFec) { 6724 corrected_name = "CORREC_RS_CW"; 6725 uncorrected_name = "UNCORREC_RS_CW"; 6726 if ((fspi->fec_type != bcmPortPhyFecRs544_2xN) && 6727 (fspi->fec_type != bcmPortPhyFecRs272_2xN)) { 6728 symb_err_valid = 1; 6729 } 6730 } else { 6731 corrected_name = "CORREC_BASER"; 6732 uncorrected_name = "UNCORREC_BASER"; 6733 } 6734 6735 secs = fscb->secs * fspi->intervals; 6736 fec_stat_counter_show(corrected_name, BCM_PORT_NAME(unit, port), NULL, 6737 fsco->acc.corrected, fsco->cur.corrected, 6738 secs); 6739 fec_stat_counter_show(uncorrected_name, BCM_PORT_NAME(unit, port), NULL, 6740 fsco->acc.uncorrected, fsco->cur.uncorrected, 6741 secs); 6742 if (symb_err_valid) { 6743 for (lane = 0; lane < fspi->lanes; lane++) { 6744 fec_stat_counter_show(symbol_error_name, BCM_PORT_NAME(unit, port), &lane, 6745 fsco->acc.symbol_error[lane], fsco->cur.symbol_error[lane], 6746 secs); 6747 fsco->cur.symbol_error[lane] = fsco->acc.symbol_error[lane]; 6748 } 6749 } 6750 fspi->intervals = 0; 6751 fsco->cur.corrected = fsco->acc.corrected; 6752 fsco->cur.uncorrected = fsco->acc.uncorrected; 6753 6754 return BCM_E_NONE; 6755 } 6756 6757 6758 STATIC void 6759 fec_stat_accumulate(int unit, bcm_port_t port, bcm_port_phy_control_t type, 6760 uint64 *subc, uint32 *out_count) 6761 { 6762 int rv; 6763 uint32 count; 6764 6765 rv = bcm_port_phy_control_get(unit, port, type, &count); 6766 if (BCM_FAILURE(rv)) { 6767 count = 0; 6768 } 6769 if (count) { 6770 COMPILER_64_ADD_32(*subc, count); 6771 } 6772 *out_count = count; 6773 } 6774 6775 6776 STATIC int 6777 fec_stat_ber_update(int unit, bcm_port_t port, uint32 delta, uint32* symb_delta) 6778 { 6779 int rv = 0; 6780 fec_stat_cb_t *fscb; 6781 fec_stat_pinfo_t *fspi; 6782 6783 fscb = &(fec_stat_cb[unit]); 6784 fspi = &(fscb->pinfo[port]); 6785 6786 rv = fec_stat_ber_compute(unit, port, delta, symb_delta, fscb->secs, fspi->ber); 6787 6788 return rv; 6789 } 6790 6791 /* 6792 * If there is a port configuration change, update the new configuration 6793 * and clear counters, BER 6794 */ 6795 STATIC int 6796 fec_stat_pinfo_update(int unit, bcm_port_t port) 6797 { 6798 fec_stat_pinfo_t *fspi; 6799 fec_stat_counter_t *fsco; 6800 bcm_port_resource_t rsrc; 6801 6802 fspi = &(fec_stat_cb[unit].pinfo[port]); 6803 6804 BCM_IF_ERROR_RETURN(bcm_port_resource_speed_get(unit, port, &rsrc)); 6805 if ((fspi->speed == rsrc.speed) && 6806 (fspi->lanes == rsrc.lanes) && 6807 (fspi->fec_type == rsrc.fec_type)) { 6808 return BCM_E_NONE; 6809 } 6810 6811 LOG_DEBUG(BSL_LS_APPL_PHY, 6812 (BSL_META_U(unit, "Updating %s config\n"), 6813 BCM_PORT_NAME(unit, port))); 6814 6815 fspi->speed = rsrc.speed; 6816 fspi->lanes = rsrc.lanes; 6817 fspi->fec_type = rsrc.fec_type; 6818 6819 sal_memset(fspi->ber, 0, PM_MAX_LANES * sizeof(double)); 6820 6821 fsco = &(fspi->counters); 6822 sal_memset(&(fsco->acc), 0, sizeof(fec_stat_subcounter_t)); 6823 sal_memset(&(fsco->cur), 0, sizeof(fec_stat_subcounter_t)); 6824 6825 return BCM_E_NONE; 6826 } 6827 6828 6829 STATIC cmd_result_t 6830 fec_stat_collect(int unit, bcm_port_t port) 6831 { 6832 bcm_error_t rv = BCM_E_NONE; 6833 uint32 count, corrected_count, error_count[PM_MAX_LANES]; 6834 soc_port_phy_rsfec_symb_errcnt_t symbol_error_count; 6835 uint32 inst; 6836 int i, corrected_ctrl, uncorrected_ctrl, symbol_err_valid = 0; 6837 bcm_port_phy_fec_t fec_type; 6838 fec_stat_pinfo_t *fspi; 6839 fec_stat_counter_t *fsco; 6840 6841 FEC_STAT_LOCK(unit); 6842 6843 rv = fec_stat_pinfo_update(unit, port); 6844 if (rv != BCM_E_NONE) { 6845 FEC_STAT_UNLOCK(unit); 6846 return CMD_FAIL; 6847 } 6848 6849 fspi = &(fec_stat_cb[unit].pinfo[port]); 6850 fsco = &(fspi->counters); 6851 6852 fec_stat_fec_type_get(unit, port, &fec_type); 6853 6854 if (fec_type == bcmPortPhyFecRsFec) { 6855 corrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_CORRECTED_CODEWORD_COUNT; 6856 uncorrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_CODEWORD_COUNT; 6857 symbol_err_valid = 1; 6858 } else { /* Assume other FEC is BaseR */ 6859 corrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_CORRECTED_BLOCK_COUNT; 6860 uncorrected_ctrl = BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_BLOCK_COUNT; 6861 } 6862 6863 fec_stat_accumulate(unit, port, uncorrected_ctrl, &(fsco->acc.uncorrected), 6864 &count); 6865 fec_stat_accumulate(unit, port, corrected_ctrl, &(fsco->acc.corrected), 6866 &corrected_count); 6867 if (symbol_err_valid) { 6868 symbol_error_count.max_count = PM_MAX_LANES; 6869 symbol_error_count.symbol_errcnt = error_count; 6870 inst = PHY_DIAG_INSTANCE(PHY_DIAG_DEV_INT , PHY_DIAG_INTF_DFLT, PHY_DIAG_LN_DFLT); 6871 rv = port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 6872 PHY_DIAG_CTRL_RSFEC_SYMB_ERR, (void *)&symbol_error_count); 6873 if (rv != BCM_E_NONE) { 6874 FEC_STAT_UNLOCK(unit); 6875 return CMD_FAIL; 6876 } 6877 if (symbol_error_count.actual_count != fspi->lanes) { 6878 /* If actual_count returned by the API does not equal to 6879 * number of lanes stored in DB, it means the speed configs in 6880 * DB is not up-to-date. 6881 */ 6882 FEC_STAT_UNLOCK(unit); 6883 return CMD_FAIL; 6884 } 6885 for (i = 0; i < fspi->lanes; i++) { 6886 COMPILER_64_ADD_32(fsco->acc.symbol_error[i], error_count[i]); 6887 } 6888 } 6889 6890 rv = fec_stat_ber_update(unit, port, corrected_count, error_count); 6891 6892 fspi->intervals++; 6893 6894 FEC_STAT_UNLOCK(unit); 6895 return CMD_OK; 6896 } 6897 6898 STATIC void 6899 fec_stat_thread(int unit) 6900 { 6901 int u_interval; 6902 bcm_port_t port; 6903 fec_stat_cb_t *fscb; 6904 6905 fscb = &(fec_stat_cb[unit]); 6906 u_interval = fscb->secs * 1000000; 6907 6908 LOG_CLI(("FEC stat thread started...\n")); 6909 while (fscb->secs) { 6910 BCM_PBMP_ITER(fscb->pbmp, port) { 6911 LOG_DEBUG(BSL_LS_APPL_PHY, 6912 (BSL_META_U(unit, "Collect FEC for port %d\n"), port)); 6913 if (fec_stat_collect(unit, port)) { 6914 LOG_ERROR(BSL_LS_APPL_PHY, 6915 (BSL_META_U( 6916 unit, 6917 "Failed collect FEC stats for port %d\n"), port)); 6918 } 6919 } 6920 sal_sem_take(fscb->sem, u_interval); 6921 } 6922 6923 LOG_DEBUG(BSL_LS_APPL_PHY, ("FEC stat thread exiting...\n")); 6924 sal_memset(fscb, 0, sizeof(fec_stat_cb_t)); 6925 fscb->thread_id = NULL; 6926 sal_thread_exit(0); 6927 } 6928 6929 6930 STATIC int 6931 fec_stat_init(int unit) 6932 { 6933 fec_stat_cb_t *fscb; 6934 6935 fscb = &(fec_stat_cb[unit]); 6936 if (FEC_STAT_INIT(fscb->flags)) { 6937 return BCM_E_NONE; 6938 } 6939 sal_memset(fscb, 0, sizeof(fec_stat_cb_t)); 6940 fscb->flags = FEC_STAT_F_INIT; 6941 6942 if ((fscb->lock = sal_mutex_create("FECStat lock")) == NULL) 6943 return BCM_E_INTERNAL; 6944 6945 if ((fscb->sem = sal_sem_create("FECStat sleep", sal_sem_BINARY, 0)) == NULL) 6946 return BCM_E_INTERNAL; 6947 6948 return BCM_E_NONE; 6949 } 6950 6951 STATIC int 6952 fec_stat_clear(int unit, bcm_pbmp_t pbmp, args_t *a) 6953 { 6954 bcm_port_t port; 6955 6956 FEC_STAT_LOCK(unit); 6957 BCM_PBMP_ITER(pbmp, port) { 6958 sal_memset(&(fec_stat_cb[unit].pinfo[port].counters), 6959 0, sizeof(fec_stat_counter_t)); 6960 } 6961 FEC_STAT_UNLOCK(unit); 6962 return CMD_OK; 6963 } 6964 6965 STATIC int 6966 fec_stat_counters(int unit, bcm_pbmp_t pbmp, args_t *a) 6967 { 6968 int rv = 0; 6969 bcm_port_t port; 6970 6971 FEC_STAT_LOCK(unit); 6972 LOG_CLI(("%-20s\t\t%20s\t%20s\t%12s", 6973 "port", "accumulated count", "last count", "count per sec\n")); 6974 BCM_PBMP_ITER(pbmp, port) { 6975 rv = fec_stat_port_counter(unit, port); 6976 if (rv) { 6977 break; 6978 } 6979 } 6980 FEC_STAT_UNLOCK(unit); 6981 6982 return rv ? CMD_FAIL : CMD_OK; 6983 } 6984 6985 STATIC int 6986 fec_stat_ber(int unit, bcm_pbmp_t pbmp, args_t *a) 6987 { 6988 bcm_port_t port; 6989 fec_stat_pinfo_t *fspi; 6990 bcm_port_phy_fec_t fec_type; 6991 int lane; 6992 6993 FEC_STAT_LOCK(unit); 6994 /* Show BER computed during last interval */ 6995 LOG_CLI(("%-10s %s", "port", "BER\n")); 6996 LOG_CLI(("====\n")); 6997 BCM_PBMP_ITER(pbmp, port) { 6998 fspi = &(fec_stat_cb[unit].pinfo[port]); 6999 fec_stat_fec_type_get(unit, port, &fec_type); 7000 if ((fspi->fec_type == bcmPortPhyFecRs544_2xN) || 7001 (fspi->fec_type == bcmPortPhyFecRs272_2xN)) { 7002 if (fspi->ber[0]) { 7003 LOG_CLI(("%-10s: %4.2e\n", BCM_PORT_NAME(unit, port), fspi->ber[0])); 7004 } else { 7005 LOG_CLI(("%-10s: N/A\n", BCM_PORT_NAME(unit, port))); 7006 } 7007 } else if (fec_type == bcmPortPhyFecRsFec) { 7008 for (lane = 0; lane < fspi->lanes; lane++) { 7009 if (fspi->ber[lane]) { 7010 LOG_CLI(("%-s[%d]: %4.2e\n", BCM_PORT_NAME(unit, port), lane, fspi->ber[lane])); 7011 } else { 7012 LOG_CLI(("%-s[%d]: N/A\n", BCM_PORT_NAME(unit, port), lane)); 7013 } 7014 } 7015 } else { 7016 if (fspi->ber[0]) { 7017 LOG_CLI(("%-10s: %4.2e\n", BCM_PORT_NAME(unit, port), fspi->ber[0])); 7018 } else { 7019 LOG_CLI(("%-10s: N/A\n", BCM_PORT_NAME(unit, port))); 7020 } 7021 } 7022 } 7023 FEC_STAT_UNLOCK(unit); 7024 return CMD_OK; 7025 } 7026 7027 7028 STATIC int 7029 fec_stat_stop(int unit) 7030 { 7031 fec_stat_cb_t *fscb; 7032 7033 fscb = &(fec_stat_cb[unit]); 7034 if (FEC_STAT_RUNNING(fscb->flags)) { 7035 fscb->secs = 0; 7036 fscb->flags &= ~FEC_STAT_F_RUNNING; 7037 LOG_CLI(("Stopping FECStat thread\n")); 7038 sal_sem_give(fscb->sem); 7039 } 7040 return CMD_OK; 7041 } 7042 7043 STATIC int 7044 fec_stat_counter_init(int unit) 7045 { 7046 uint32 inst, value, error_count[PM_MAX_LANES]; 7047 soc_port_phy_rsfec_symb_errcnt_t symbol_error_count; 7048 bcm_port_phy_fec_t fec_type; 7049 bcm_port_t port; 7050 fec_stat_pinfo_t *fspi; 7051 fec_stat_cb_t *fscb; 7052 7053 fscb = &(fec_stat_cb[unit]); 7054 7055 BCM_PBMP_ITER(fscb->pbmp, port) { 7056 fspi = &(fec_stat_cb[unit].pinfo[port]); 7057 sal_memset(&(fspi->counters), 0, sizeof(fec_stat_counter_t)); 7058 BCM_IF_ERROR_RETURN(fec_stat_pinfo_update(unit, port)); 7059 7060 /* Prime counters to avoid first read to get all values since reboot */ 7061 fec_stat_fec_type_get(unit, port, &fec_type); 7062 if (fec_type == bcmPortPhyFecRsFec) { 7063 symbol_error_count.max_count = PM_MAX_LANES; 7064 symbol_error_count.symbol_errcnt = error_count; 7065 inst = PHY_DIAG_INSTANCE(PHY_DIAG_DEV_INT , PHY_DIAG_INTF_DFLT, PHY_DIAG_LN_DFLT); 7066 BCM_IF_ERROR_RETURN(port_diag_ctrl(unit, port, inst, PHY_DIAG_CTRL_CMD, 7067 PHY_DIAG_CTRL_RSFEC_SYMB_ERR, (void *)&symbol_error_count)); 7068 7069 BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port, 7070 BCM_PORT_PHY_CONTROL_FEC_CORRECTED_CODEWORD_COUNT, 7071 &value)); 7072 BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port, 7073 BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_CODEWORD_COUNT, 7074 &value)); 7075 } else { 7076 BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port, 7077 BCM_PORT_PHY_CONTROL_FEC_CORRECTED_BLOCK_COUNT, 7078 &value)); 7079 BCM_IF_ERROR_RETURN(bcm_port_phy_control_get(unit, port, 7080 BCM_PORT_PHY_CONTROL_FEC_UNCORRECTED_BLOCK_COUNT, 7081 &value)); 7082 } 7083 } 7084 return BCM_E_NONE; 7085 } 7086 7087 STATIC int 7088 fec_stat_start(int unit, bcm_pbmp_t pbmp, args_t *a) 7089 { 7090 int secs, rv; 7091 parse_table_t pt; 7092 fec_stat_cb_t *fscb; 7093 7094 fscb = &(fec_stat_cb[unit]); 7095 7096 if (ARG_CNT(a) == 0) { 7097 if (!(fscb->flags & FEC_STAT_F_RUNNING)) { 7098 LOG_CLI(("FECStat: not running\n")); 7099 } else { 7100 char pbmp_str[SOC_PBMP_FMT_LEN]; 7101 SOC_PBMP_FMT(fscb->pbmp, pbmp_str); 7102 LOG_CLI(("FECStat: interval=%ds\n", fscb->secs)); 7103 LOG_CLI(("FECStat: pbmp=%s\n", pbmp_str)); 7104 } 7105 return CMD_OK; 7106 } 7107 7108 /*SOC_PBMP_ASSIGN(pbmp, fscb->pbmp);*/ 7109 secs = fscb->secs; 7110 7111 parse_table_init(unit, &pt); 7112 parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 0, &secs, NULL); 7113 /*parse_table_add(&pt, "PortBitMap",PQ_DFL|PQ_PBMP, 0, &pbmp, NULL);*/ 7114 7115 if (parse_arg_eq(a, &pt) < 0) { 7116 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 7117 parse_arg_eq_done(&pt); 7118 return CMD_FAIL; 7119 } 7120 parse_arg_eq_done(&pt); 7121 7122 if (secs == 0 || secs > 180) { 7123 LOG_CLI(("Interval must be between 1 and 180 seconds\n")); 7124 return CMD_FAIL; 7125 } 7126 7127 /* 7128 * Allow start to be called while already running to update 7129 * interval and pbmp 7130 */ 7131 if (fscb->flags & FEC_STAT_F_RUNNING) { 7132 FEC_STAT_LOCK(unit); 7133 } 7134 7135 fscb->secs = secs; 7136 SOC_PBMP_ASSIGN(fscb->pbmp, pbmp); 7137 7138 rv = fec_stat_counter_init(unit); 7139 7140 if (fscb->flags & FEC_STAT_F_RUNNING) { 7141 /* 7142 * If fec_stat is already running, 7143 * need to return without starting new thread. 7144 */ 7145 FEC_STAT_UNLOCK(unit); 7146 return (rv == BCM_E_NONE) ? CMD_OK : CMD_FAIL; 7147 } 7148 7149 if (rv != BCM_E_NONE) { 7150 return CMD_FAIL; 7151 } 7152 7153 fscb->thread_id = sal_thread_create("FECstat", 7154 SAL_THREAD_STKSZ, 7155 100, /* thread priority */ 7156 (void (*)(void*))fec_stat_thread, 7157 INT_TO_PTR(unit)); 7158 if (fscb->thread_id == SAL_THREAD_ERROR) { 7159 LOG_ERROR( 7160 BSL_LS_APPL_PHY, 7161 (BSL_META_U(unit, "Could not create FECstat thread\n"))); 7162 fscb->flags &= ~FEC_STAT_F_RUNNING; 7163 return CMD_FAIL; 7164 } 7165 fscb->flags |= FEC_STAT_F_RUNNING; 7166 7167 return CMD_OK; 7168 } 7169 7170 /* 7171 * Match input with key. Allows abbreviated matches based on 7172 * the minimum initial capital letters in key. For example, 7173 * key = ABCdef will be matched with the input 7174 * abc, abcd, abcde, abcdef. Any other input is a mismatch. 7175 */ 7176 STATIC int 7177 fec_stat_cmd_match(char *inp, char *key) 7178 { 7179 while (*key && isupper(*key)) { 7180 if (!*inp || (toupper(*inp) != *key)) { 7181 return 0; 7182 } 7183 key++; 7184 inp++; 7185 } 7186 while (*inp) { 7187 if (toupper(*inp) != toupper(*key)) { 7188 return 0; 7189 } 7190 key++; 7191 inp++; 7192 } 7193 return 1; 7194 } 7195 7196 STATIC cmd_result_t 7197 fec_stat_cfg(int unit) 7198 { 7199 fec_stat_cb_t *fscb; 7200 7201 fscb = &(fec_stat_cb[unit]); 7202 7203 if (!FEC_STAT_RUNNING(fec_stat_cb[unit].flags)) { 7204 LOG_CLI(("FECStat not started\n")); 7205 } else { 7206 char buf[512]; 7207 char pfmt[SOC_PBMP_FMT_LEN]; 7208 7209 format_bcm_pbmp(unit, buf, sizeof(buf), fscb->pbmp); 7210 LOG_CLI(("FECStat: Polling interval: %d sec\n", fscb->secs)); 7211 LOG_CLI(("FECStat: Port bitmap: %s: %s\n", 7212 SOC_PBMP_FMT(fscb->pbmp, pfmt), buf)); 7213 } 7214 return CMD_OK; 7215 } 7216 7217 /*** API ***/ 7218 /* 7219 * Get computed BER for the last <secs> 7220 * 7221 * If the port is not configured with FEC or the BER cannot be computed, 7222 * the BER is 0 7223 * 7224 * If successful, return 1; otherwise 0 7225 */ 7226 int 7227 fec_stat_ber_get(int unit, bcm_port_t port, int *lane, double *ber) 7228 { 7229 fec_stat_pinfo_t *fscb = &(fec_stat_cb[unit].pinfo[port]); 7230 7231 FEC_STAT_LOCK(unit); 7232 if (lane == NULL) { 7233 *ber = fscb->ber[0]; 7234 } else if ((*lane >= 0) && (*lane < PM_MAX_LANES)) { 7235 *ber = fscb->ber[*lane]; 7236 } else { 7237 return 0; 7238 } 7239 7240 FEC_STAT_UNLOCK(unit); 7241 7242 return 1; 7243 7244 } 7245 7246 static char fec_stat_usage[] = 7247 "\nParameters: [STArt [Interval=<secs>]]\n" 7248 " [STOp] [Counters] [Ber] [CLear]\n"; 7249 7250 STATIC cmd_result_t 7251 _phy_diag_fecstat(int unit, bcm_pbmp_t pbmp, args_t *a) 7252 { 7253 char *sc; 7254 7255 if (!sh_check_attached(ARG_CMD(a), unit)) { 7256 return CMD_FAIL; 7257 } 7258 7259 if (!SOC_IS_TOMAHAWK3(unit)) { 7260 return CMD_NOTIMPL; 7261 } 7262 7263 sc = ARG_GET(a); 7264 if (sc == NULL) { 7265 return fec_stat_cfg(unit); 7266 } 7267 7268 if (fec_stat_init(unit)) { 7269 return CMD_FAIL; 7270 } 7271 if (fec_stat_cmd_match(sc, "?")) { 7272 LOG_CLI(("%s\n", fec_stat_usage)); 7273 } 7274 else if (fec_stat_cmd_match(sc, "STArt")) { 7275 return fec_stat_start(unit, pbmp, a); 7276 } else if (fec_stat_cmd_match(sc, "STOp")) { 7277 return fec_stat_stop(unit); 7278 } else if (fec_stat_cmd_match(sc, "Counters")) { 7279 return fec_stat_counters(unit, pbmp, a); 7280 } else if (fec_stat_cmd_match(sc, "Ber")) { 7281 return fec_stat_ber(unit, pbmp, a); 7282 } else if (fec_stat_cmd_match(sc, "CLear")) { 7283 return fec_stat_clear(unit, pbmp, a); 7284 } else { 7285 return CMD_USAGE; 7286 } 7287 7288 return CMD_OK; 7289 } 7290 7291 /* end of fec_stat */ 7292 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7293 7294 /* 7295 * Diagnostic utilities for serdes and PHY devices. 7296 * 7297 * Command format used in BCM diag shell: 7298 * phy diag <pbm> <sub_cmd> [sub cmd parameters] 7299 * All sub commands take two general parameters: unit and if. This identifies 7300 * the instance the command targets to. 7301 * unit = 0,1, .... 7302 * unit takes numeric values identifying the instance of the PHY devices 7303 * associated with the given port. A value 0 indicates the internal 7304 * PHY(serdes) the one directly connected to the MAC. A value 1 indicates 7305 * the first external PHY. 7306 * if(interface) = [sys | line] 7307 * interface identifies the system side interface or line side interface of 7308 * PHY device. 7309 * The list of sub commands: 7310 * dsc - display tx/rx equalization information. Warpcore(WC) only. 7311 * veye - vertical eye margin mesurement. WC only. All eye margin functions 7312 * are used in conjunction with PRBS utility in the configed speed mode 7313 * heye_r - right horizontal eye margin mesurement. WC only 7314 * heye_l - right horizontal eye margin mesurement. WC only 7315 * for the WarpLite, there are three additional parameters, live link or not, par1 for the target BER value for example: -18 stands for 10^(-18) 7316 * par2 will be percentage range for example, 5 means checxk for +-%5 of the target BER 7317 * loopback - put the device in the given loopback mode 7318 * parameter: mode=[remote | local | none] 7319 * prbs - perform various PRBS functions. Takes all parameters of the 7320 * "phy prbs" command except the mode parameter. 7321 * Example: 7322 * A port has a WC serdes and 84740 PHY connected. A typical usage 7323 * is to use the PRBS to check the link between WC and the system 7324 * side of the 84740. Use port xe0 as an example: 7325 * BCM.0> phy diag xe0 prbs set unit=0 p=3 7326 * BCM.0> phy diag xe0 prbs set unit=1 if=sys p=3 7327 * BCM.0> phy diag xe0 prbs get unit=1 if=sys 7328 * BCM.0> phy diag xe0 prbs get unit=0 7329 * 7330 * prbsstat - periodically collect PRBS error counters an 7331 * compute BER based on the port configuration an 7332 * the observed error counters. 7333 * Parameters: 7334 * [STArt [Interval=<secs>]] 7335 * [STOp] 7336 * [Counters] 7337 * [Ber] 7338 * [Clear] 7339 * Example: 7340 * BCM.0> phy diag cd0-cd3 prbsstat 7341 * BCM.0> phy diag cd0-cd3 prbsstat start i=60 7342 * BCM.0> phy diag cd0-cd3 prbsstat counters 7343 * BCM.0> phy diag cd0-cd3 prbsstat ber 7344 * BCM.0> phy diag cd0-cd3 prbsstat clear 7345 * pcs - display Diag information 7346 * BCM.0> phy diag xe0 pcs 7347 * BCM.0> phy diag xe0 pcs topology 7348 * BCM.0> phy diag xe0 pcs link 7349 * BCM.0> phy diag xe0 pcs aneg 7350 * BCM.0> phy diag xe0 pcs state 7351 * BCM.0> phy diag xe0 pcs tfc 7352 * BCM.0> phy diag xe0 pcs antimers 7353 * 7354 * dsc - display Diag information 7355 * BCM.0> phy diag xe0 dsc 7356 * BCM.0> phy diag xe0 dsc config 7357 * BCM.0> phy diag xe0 dsc cl72 7358 * BCM.0> phy diag xe0 dsc debug 7359 * 7360 * mfg - run manufacturing test on PHY BCM8483X 7361 * parameter: (t)est=num (d)ata=<val> (f)ile=filename 7362 * Test should be : 7363 * 1 (HYB_CANC), needs (f)ile=filename 7364 * 2 (DENC), needs (f)ile=filename 7365 * 3 (TX_ON) needs (d)ata = bit map for turning TX off on pairs DCBA 7366 * 0 (EXIT) 7367 */ 7368 STATIC cmd_result_t 7369 _if_esw_phy_diag(int unit, args_t *args) 7370 { 7371 bcm_port_t port, dport; 7372 bcm_pbmp_t pbmp; 7373 int rv, cmd; 7374 int par[5]; 7375 int *pData; 7376 int lscan_time; 7377 char *cmd_str, *port_str; 7378 parse_table_t pt; 7379 bcm_port_t p; 7380 int lnk_mode[BCM_PBMP_PORT_MAX]; 7381 7382 rv = CMD_OK; 7383 par[0] = 0; 7384 par[1] = 0; 7385 par[2] = 0; 7386 par[3] = 0; 7387 par[4] = 0; 7388 pData = &par[0]; 7389 7390 sal_memset(&lnk_mode, -1, sizeof(lnk_mode)); 7391 7392 if ((port_str = ARG_GET(args)) == NULL) { 7393 return CMD_USAGE; 7394 } 7395 7396 BCM_PBMP_CLEAR(pbmp); 7397 if (parse_bcm_pbmp(unit, port_str, &pbmp) < 0) { 7398 cli_out("Error: unrecognized port bitmap: %s\n", port_str); 7399 return CMD_FAIL; 7400 } 7401 7402 if ((cmd_str = ARG_GET(args)) == NULL) { 7403 return CMD_USAGE; 7404 } 7405 7406 /* linkscan should be disabled. soc_phyctrl_diag_ctrl() doesn't 7407 * assume exclusive access to the device. 7408 */ 7409 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_get(unit, &lscan_time)); 7410 if (lscan_time != 0) { 7411 BCM_PBMP_ITER(pbmp, p) { 7412 BCM_IF_ERROR_RETURN(bcm_linkscan_mode_get(unit, p, &lnk_mode[p])); 7413 if (lnk_mode[p] != BCM_LINKSCAN_MODE_NONE) { 7414 BCM_IF_ERROR_RETURN(bcm_linkscan_mode_set(unit, p, BCM_LINKSCAN_MODE_NONE)); 7415 } 7416 } 7417 } 7418 if (sal_strcasecmp(cmd_str, "peek") == 0) { 7419 cmd = PHY_DIAG_CTRL_PEEK; 7420 parse_table_init(unit, &pt); 7421 parse_table_add(&pt, "fb", PQ_DFL | PQ_INT, (void *)(0), pData++, NULL); 7422 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), 7423 pData++, NULL); 7424 if (parse_arg_eq(args, &pt) < 0) { 7425 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7426 parse_arg_eq_done(&pt); 7427 return CMD_USAGE; 7428 } 7429 /* command targets to Internal serdes device for now */ 7430 /* coverity[overrun-local] */ 7431 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7432 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7433 PHY_DIAG_CTRL_CMD, cmd, 7434 &par) != SOC_E_NONE) { 7435 rv = CMD_FAIL; 7436 } 7437 } 7438 } else if (sal_strcasecmp(cmd_str, "poke") == 0) { 7439 cmd = PHY_DIAG_CTRL_POKE; 7440 parse_table_init(unit, &pt); 7441 parse_table_add(&pt, "fb", PQ_DFL | PQ_INT, (void *)(0), pData++, NULL); 7442 parse_table_add(&pt, "val", PQ_DFL | PQ_INT, (void *)(0), 7443 pData++, NULL); 7444 if (parse_arg_eq(args, &pt) < 0) { 7445 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7446 parse_arg_eq_done(&pt); 7447 return CMD_USAGE; 7448 } 7449 /* command targets to Internal serdes device for now */ 7450 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7451 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7452 PHY_DIAG_CTRL_CMD, cmd, 7453 &par) != SOC_E_NONE) { 7454 rv = CMD_FAIL; 7455 } 7456 } 7457 } else if (sal_strcasecmp(cmd_str, "load_uc") == 0) { 7458 cmd = PHY_DIAG_CTRL_LOAD_UC; 7459 parse_table_init(unit, &pt); 7460 parse_table_add(&pt, "crc", PQ_DFL | PQ_INT, (void *)(0), 7461 pData++, NULL); 7462 parse_table_add(&pt, "debug", PQ_DFL | PQ_INT, (void *)(0), 7463 pData++, NULL); 7464 if (parse_arg_eq(args, &pt) < 0) { 7465 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7466 parse_arg_eq_done(&pt); 7467 return CMD_USAGE; 7468 } 7469 /* command targets to Internal serdes device for now */ 7470 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7471 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7472 PHY_DIAG_CTRL_CMD, cmd, 7473 &par) != SOC_E_NONE) { 7474 rv = CMD_FAIL; 7475 } 7476 } 7477 } else if (sal_strcasecmp(cmd_str, "veye") == 0) { 7478 cmd = PHY_DIAG_CTRL_EYE_MARGIN_VEYE; 7479 parse_table_init(unit, &pt); 7480 parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0), 7481 pData++, NULL); 7482 parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0), 7483 pData++, NULL); 7484 parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0), 7485 pData++, NULL); 7486 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), 7487 pData++, NULL); 7488 parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0), 7489 pData, NULL); 7490 if (parse_arg_eq(args, &pt) < 0) { 7491 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7492 parse_arg_eq_done(&pt); 7493 return CMD_USAGE; 7494 } 7495 /* command targets to Internal serdes device for now */ 7496 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7497 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7498 PHY_DIAG_CTRL_CMD, cmd, 7499 &par) != SOC_E_NONE) { 7500 rv = CMD_FAIL; 7501 } 7502 } 7503 } else if (sal_strcasecmp(cmd_str, "veye_u") == 0) { 7504 cmd = PHY_DIAG_CTRL_EYE_MARGIN_VEYE_UP; 7505 parse_table_init(unit, &pt); 7506 parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0), 7507 pData++, NULL); 7508 parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0), 7509 pData++, NULL); 7510 parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0), 7511 pData++, NULL); 7512 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), 7513 pData++, NULL); 7514 parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0), 7515 pData, NULL); 7516 if (parse_arg_eq(args, &pt) < 0) { 7517 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7518 parse_arg_eq_done(&pt); 7519 return CMD_USAGE; 7520 } 7521 /* command targets to Internal serdes device for now */ 7522 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7523 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7524 PHY_DIAG_CTRL_CMD, cmd, 7525 &par) != SOC_E_NONE) { 7526 rv = CMD_FAIL; 7527 } 7528 } 7529 } else if (sal_strcasecmp(cmd_str, "veye_d") == 0) { 7530 cmd = PHY_DIAG_CTRL_EYE_MARGIN_VEYE_DOWN; 7531 parse_table_init(unit, &pt); 7532 parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0), 7533 pData++, NULL); 7534 parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0), 7535 pData++, NULL); 7536 parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0), 7537 pData, NULL); 7538 if (parse_arg_eq(args, &pt) < 0) { 7539 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7540 parse_arg_eq_done(&pt); 7541 return CMD_USAGE; 7542 } 7543 /* command targets to Internal serdes device for now */ 7544 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7545 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7546 PHY_DIAG_CTRL_CMD, cmd, 7547 &par) != SOC_E_NONE) { 7548 rv = CMD_FAIL; 7549 } 7550 } 7551 } else if (sal_strcasecmp(cmd_str, "heye_r") == 0) { 7552 cmd = PHY_DIAG_CTRL_EYE_MARGIN_HEYE_RIGHT; 7553 parse_table_init(unit, &pt); 7554 parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0), 7555 pData++, NULL); 7556 parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0), 7557 pData++, NULL); 7558 parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0), 7559 pData++, NULL); 7560 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), 7561 pData++, NULL); 7562 parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0), 7563 pData, NULL); 7564 if (parse_arg_eq(args, &pt) < 0) { 7565 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7566 parse_arg_eq_done(&pt); 7567 return CMD_USAGE; 7568 } 7569 /* command targets to Internal serdes device for now */ 7570 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7571 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7572 PHY_DIAG_CTRL_CMD, cmd, 7573 &par) != SOC_E_NONE) { 7574 rv = CMD_FAIL; 7575 } 7576 } 7577 } else if (sal_strcasecmp(cmd_str, "heye_l") == 0) { 7578 cmd = PHY_DIAG_CTRL_EYE_MARGIN_HEYE_LEFT; 7579 parse_table_init(unit, &pt); 7580 parse_table_add(&pt, "live", PQ_DFL | PQ_INT, (void *)(0), 7581 pData++, NULL); 7582 parse_table_add(&pt, "BER", PQ_DFL | PQ_INT, (void *)(0), 7583 pData++, NULL); 7584 parse_table_add(&pt, "range", PQ_DFL | PQ_INT, (void *)(0), 7585 pData++, NULL); 7586 parse_table_add(&pt, "lane", PQ_DFL | PQ_INT, (void *)(0), 7587 pData++, NULL); 7588 parse_table_add(&pt, "time_upper_bound", PQ_DFL | PQ_INT, (void *)(0), 7589 pData, NULL); 7590 if (parse_arg_eq(args, &pt) < 0) { 7591 cli_out("Error: invalid option: %s\n", ARG_CUR(args)); 7592 parse_arg_eq_done(&pt); 7593 return CMD_USAGE; 7594 } 7595 /* command targets to Internal serdes device for now */ 7596 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7597 if (port_diag_ctrl(unit, port, PHY_DIAG_INT, 7598 PHY_DIAG_CTRL_CMD, cmd, 7599 &par) != SOC_E_NONE) { 7600 rv = CMD_FAIL; 7601 } 7602 } 7603 7604 } else if (sal_strcasecmp(cmd_str, "dsc") == 0) { 7605 rv = _phy_diag_dsc(unit, pbmp, args); 7606 } else if (sal_strcasecmp(cmd_str, "pcs") == 0) { 7607 rv = _phy_diag_pcs(unit, pbmp, args); 7608 } else if (sal_strcasecmp(cmd_str, "reg") == 0) { 7609 rv = _phy_diag_reg(unit, pbmp, args); 7610 } else if (sal_strcasecmp(cmd_str, "eyescan") == 0) { 7611 rv = _phy_diag_eyescan(unit, pbmp, args); 7612 } else if (sal_strcasecmp(cmd_str, "LoopBack") == 0) { 7613 rv = _phy_diag_loopback(unit, pbmp, args); 7614 #ifdef BCM_TOMAHAWK3_SUPPORT 7615 } else if (sal_strcasecmp(cmd_str, "prbsstat") == 0) { 7616 rv = _phy_diag_prbsstat(unit, pbmp, args); 7617 } else if (sal_strcasecmp(cmd_str, "fecstat") == 0) { 7618 rv = _phy_diag_fecstat(unit, pbmp, args); 7619 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7620 } else if (sal_strcasecmp(cmd_str, "prbs") == 0) { 7621 rv = _phy_diag_prbs(unit, pbmp, args); 7622 } else if (sal_strcasecmp(cmd_str, "mfg") == 0) { 7623 rv = _phy_diag_mfg(unit, pbmp, args); 7624 } else if (sal_strcasecmp(cmd_str, "state") == 0) { 7625 rv = _phy_diag_state(unit, pbmp, args); 7626 } else if (sal_strcasecmp(cmd_str, "feyescan") == 0) { 7627 rv = _phy_diag_fast_eyescan(unit, pbmp, args); 7628 } else if (sal_strcasecmp(cmd_str, "linkmon") == 0) { 7629 rv = _phy_diag_link_mon(unit, pbmp, args); 7630 } else if (sal_strcasecmp(cmd_str, "berproj") == 0) { 7631 rv = _phy_diag_berproj(unit, pbmp, args); 7632 #ifdef PHYMOD_LINKCAT_SUPPORT 7633 } else if (sal_strcasecmp(cmd_str, "linkcat") == 0) { 7634 rv = _phy_diag_linkcat(unit, pbmp, args); 7635 #endif /* PHYMOD_LINKCAT_SUPPORT */ 7636 } 7637 7638 #ifdef SW_AUTONEG_SUPPORT 7639 else if (sal_strcasecmp(cmd_str, "sw_an") == 0) { 7640 7641 if (soc_feature(unit, soc_feature_sw_autoneg)) { 7642 7643 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 7644 if (bcm_sw_an_port_diag(unit, port)) { 7645 rv = CMD_FAIL; 7646 } 7647 } 7648 } else { 7649 cli_out("Error: SW AUTONEG Not supported on this platform: \n"); 7650 rv = CMD_FAIL; 7651 } 7652 } 7653 #endif 7654 else { 7655 cli_out("Error: unrecognized PHY DIAG command: %s\n", cmd_str); 7656 rv = CMD_FAIL; 7657 } 7658 7659 if (lscan_time != 0) { 7660 BCM_PBMP_ITER(pbmp, p) { 7661 BCM_IF_ERROR_RETURN(bcm_linkscan_mode_set(unit, p, lnk_mode[p])); 7662 } 7663 } 7664 7665 return rv; 7666 } 7667 7668 7669 STATIC cmd_result_t 7670 _if_esw_phy_longreach(int u, args_t *a) 7671 { 7672 soc_pbmp_t pbm; 7673 soc_port_t p, dport; 7674 char *c; 7675 int i; 7676 cmd_result_t cmd_rv; 7677 parse_table_t pt; 7678 int print_header; 7679 uint32 flags; 7680 uint32 longreach_speed, longreach_pairs; 7681 uint32 longreach_gain, longreach_autoneg; 7682 uint32 longreach_local_ability, longreach_remote_ability; 7683 uint32 longreach_current_ability, longreach_master; 7684 uint32 longreach_active, longreach_enable; 7685 7686 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 7687 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 7688 return CMD_FAIL; 7689 } 7690 7691 { 7692 7693 if (c[0] == '=') { 7694 return CMD_USAGE; /* '=' unsupported */ 7695 } 7696 7697 parse_table_init(u, &pt); 7698 7699 parse_table_add(&pt, "SPeed", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7700 0, &longreach_speed, 0); 7701 parse_table_add(&pt, "PAirs", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7702 0, &longreach_pairs, 0); 7703 parse_table_add(&pt, "GAin", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7704 0, &longreach_gain, 0); 7705 parse_table_add(&pt, "AutoNeg", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 7706 0, &longreach_autoneg, 0); 7707 parse_table_add(&pt, "LocalAbility", 7708 PQ_LR_PHYAB | PQ_DFL | PQ_NO_EQ_OPT, 0, 7709 &longreach_local_ability, 0); 7710 parse_table_add(&pt, "RemoteAbility", 7711 PQ_LR_PHYAB | PQ_DFL | PQ_NO_EQ_OPT, 0, 7712 &longreach_remote_ability, 0); 7713 parse_table_add(&pt, "CurrentAbility", 7714 PQ_LR_PHYAB | PQ_DFL | PQ_NO_EQ_OPT, 0, 7715 &longreach_current_ability, 0); 7716 parse_table_add(&pt, "MAster", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0, 7717 &longreach_master, 0); 7718 parse_table_add(&pt, "Active", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0, 7719 &longreach_active, 0); 7720 parse_table_add(&pt, "ENable", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 0, 7721 &longreach_enable, 0); 7722 7723 if (parse_arg_eq(a, &pt) < 0) { 7724 parse_arg_eq_done(&pt); 7725 return CMD_USAGE; 7726 } 7727 if (ARG_CNT(a) > 0) { 7728 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 7729 parse_arg_eq_done(&pt); 7730 return CMD_USAGE; 7731 } 7732 7733 flags = 0; 7734 7735 for (i = 0; i < pt.pt_cnt; i++) { 7736 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 7737 flags |= (1 << (SOC_PHY_CONTROL_LONGREACH_SPEED + i)); 7738 } 7739 } 7740 /* free allocated memory from arg parsing */ 7741 parse_arg_eq_done(&pt); 7742 7743 /* coverity[overrun-local] */ 7744 DPORT_BCM_PBMP_ITER(u, pbm, dport, p) { 7745 print_header = FALSE; 7746 7747 cli_out("\nCurrent Longreach settings of %s ->\n", 7748 BCM_PORT_NAME(u, p)); 7749 7750 /* Read and set the longreach speed */ 7751 cmd_rv = port_phy_control_update(u, p, 7752 BCM_PORT_PHY_CONTROL_LONGREACH_SPEED, 7753 longreach_speed, 7754 flags, &print_header); 7755 if (cmd_rv != CMD_OK) { 7756 return cmd_rv; 7757 } 7758 7759 /* Read and set the longreach pairs */ 7760 cmd_rv = port_phy_control_update(u, p, 7761 BCM_PORT_PHY_CONTROL_LONGREACH_PAIRS, 7762 longreach_pairs, 7763 flags, &print_header); 7764 if (cmd_rv != CMD_OK) { 7765 return cmd_rv; 7766 } 7767 7768 /* Read and set the longreach gain */ 7769 cmd_rv = port_phy_control_update(u, p, 7770 BCM_PORT_PHY_CONTROL_LONGREACH_GAIN, 7771 longreach_gain, 7772 flags, &print_header); 7773 if (cmd_rv != CMD_OK) { 7774 return cmd_rv; 7775 } 7776 7777 /* Read and set the longreach autoneg (LDS) */ 7778 cmd_rv = port_phy_control_update(u, p, 7779 BCM_PORT_PHY_CONTROL_LONGREACH_AUTONEG, 7780 longreach_autoneg, 7781 flags, &print_header); 7782 if (cmd_rv != CMD_OK) { 7783 return cmd_rv; 7784 } 7785 7786 /* Read and set the longreach local ability */ 7787 cmd_rv = port_phy_control_update(u, p, 7788 BCM_PORT_PHY_CONTROL_LONGREACH_LOCAL_ABILITY, 7789 longreach_local_ability, 7790 flags, &print_header); 7791 if (cmd_rv != CMD_OK) { 7792 return cmd_rv; 7793 } 7794 /* Read the longreach remote ability */ 7795 cmd_rv = port_phy_control_update(u, p, 7796 BCM_PORT_PHY_CONTROL_LONGREACH_REMOTE_ABILITY, 7797 longreach_remote_ability, 7798 flags, &print_header); 7799 if (cmd_rv != CMD_OK) { 7800 return cmd_rv; 7801 } 7802 7803 /* Read the longreach current ability (GCD - read only) */ 7804 cmd_rv = port_phy_control_update(u, p, 7805 BCM_PORT_PHY_CONTROL_LONGREACH_CURRENT_ABILITY, 7806 longreach_current_ability, 7807 flags, &print_header); 7808 if (cmd_rv != CMD_OK) { 7809 return cmd_rv; 7810 } 7811 7812 /* Read and set the longreach master (when no LDS) */ 7813 cmd_rv = port_phy_control_update(u, p, 7814 BCM_PORT_PHY_CONTROL_LONGREACH_MASTER, 7815 longreach_master, 7816 flags, &print_header); 7817 if (cmd_rv != CMD_OK) { 7818 return cmd_rv; 7819 } 7820 /* Read and set the longreach active (LR is active - read only) */ 7821 cmd_rv = port_phy_control_update(u, p, 7822 BCM_PORT_PHY_CONTROL_LONGREACH_ACTIVE, 7823 longreach_active, 7824 flags, &print_header); 7825 if (cmd_rv != CMD_OK) { 7826 return cmd_rv; 7827 } 7828 /* Read and set the longreach active (Enable LR) */ 7829 cmd_rv = port_phy_control_update(u, p, 7830 BCM_PORT_PHY_CONTROL_LONGREACH_ENABLE, 7831 longreach_enable, 7832 flags, &print_header); 7833 if (cmd_rv != CMD_OK) { 7834 return cmd_rv; 7835 } 7836 7837 } 7838 7839 } 7840 7841 return CMD_OK; 7842 } 7843 7844 STATIC cmd_result_t 7845 _if_esw_phy_extlb(int u, args_t *a) 7846 { 7847 soc_pbmp_t pbm; 7848 soc_port_t p, dport; 7849 char *c; 7850 int i; 7851 cmd_result_t cmd_rv; 7852 parse_table_t pt; 7853 int print_header; 7854 uint32 flags; 7855 uint32 enable; 7856 7857 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 7858 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 7859 return CMD_FAIL; 7860 } 7861 7862 { 7863 7864 if (c[0] == '=') { 7865 return CMD_USAGE; /* '=' unsupported */ 7866 } 7867 7868 parse_table_init(u, &pt); 7869 7870 parse_table_add(&pt, "ENable", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 7871 0, &enable, 0); 7872 7873 if (parse_arg_eq(a, &pt) < 0) { 7874 parse_arg_eq_done(&pt); 7875 return CMD_USAGE; 7876 } 7877 7878 if (ARG_CNT(a) > 0) { 7879 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 7880 parse_arg_eq_done(&pt); 7881 return CMD_USAGE; 7882 } 7883 7884 flags = 0; 7885 7886 for (i = 0; i < pt.pt_cnt; i++) { 7887 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 7888 flags |= (1 << (SOC_PHY_CONTROL_LOOPBACK_EXTERNAL + i)); 7889 } 7890 } 7891 /* free allocated memory from arg parsing */ 7892 parse_arg_eq_done(&pt); 7893 7894 /* coverity[overrun-local] */ 7895 DPORT_BCM_PBMP_ITER(u, pbm, dport, p) { 7896 print_header = FALSE; 7897 7898 cli_out("\nExternal loopback plug mode setting of %s ->\n", 7899 BCM_PORT_NAME(u, p)); 7900 7901 /* Get and set the external loopback plug mode */ 7902 cmd_rv = port_phy_control_update(u, p, 7903 BCM_PORT_PHY_CONTROL_LOOPBACK_EXTERNAL, 7904 enable, flags, &print_header); 7905 if (cmd_rv != CMD_OK) { 7906 return cmd_rv; 7907 } 7908 7909 } 7910 7911 } 7912 7913 return CMD_OK; 7914 } 7915 7916 STATIC cmd_result_t 7917 _if_esw_phy_clock(int u, args_t *a) 7918 { 7919 soc_pbmp_t pbm; 7920 soc_port_t p, dport; 7921 char *c; 7922 int i; 7923 cmd_result_t cmd_rv; 7924 parse_table_t pt; 7925 int print_header; 7926 uint32 flags; 7927 uint32 pri_enable, sec_enable, frequency, mode_auto, auto_sec, source, base, offset; 7928 7929 if (((c = ARG_GET(a)) == NULL) || (parse_bcm_pbmp(u, c, &pbm) < 0)) { 7930 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 7931 return CMD_FAIL; 7932 } 7933 7934 { 7935 7936 if (c[0] == '=') { 7937 return CMD_USAGE; /* '=' unsupported */ 7938 } 7939 7940 parse_table_init(u, &pt); 7941 7942 parse_table_add(&pt, "PRImary", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 7943 0, &pri_enable, 0); 7944 parse_table_add(&pt, "SECondary", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 7945 0, &sec_enable, 0); 7946 parse_table_add(&pt, "FRequency", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7947 0, &frequency, 0); 7948 parse_table_add(&pt, "AutoDisable", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 7949 0, &mode_auto, 0); 7950 parse_table_add(&pt, "AutoSECondary", PQ_BOOL | PQ_DFL | PQ_NO_EQ_OPT, 7951 0, &auto_sec, 0); 7952 parse_table_add(&pt, "ClockSource", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7953 0, &source, 0); 7954 7955 parse_table_add(&pt, "BAse", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7956 0, &base, 0); 7957 parse_table_add(&pt, "OFfset", PQ_INT | PQ_DFL | PQ_NO_EQ_OPT, 7958 0, &offset, 0); 7959 7960 if (parse_arg_eq(a, &pt) < 0) { 7961 parse_arg_eq_done(&pt); 7962 return CMD_USAGE; 7963 } 7964 7965 if (ARG_CNT(a) > 0) { 7966 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 7967 parse_arg_eq_done(&pt); 7968 return CMD_USAGE; 7969 } 7970 7971 flags = 0; 7972 7973 for (i = 0; i < pt.pt_cnt; i++) { 7974 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 7975 /* flags |= (1 << (SOC_PHY_CONTROL_CLOCK_ENABLE + i)); */ 7976 flags |= (1 << i); 7977 } 7978 } 7979 /* free allocated memory from arg parsing */ 7980 parse_arg_eq_done(&pt); 7981 7982 /* coverity[overrun-local] */ 7983 DPORT_BCM_PBMP_ITER(u, pbm, dport, p) { 7984 print_header = FALSE; 7985 7986 cli_out("Clock extraction setting of %s ->\n", 7987 BCM_PORT_NAME(u, p)); 7988 7989 cmd_rv = port_phy_control_update(u, p, 7990 BCM_PORT_PHY_CONTROL_CLOCK_ENABLE, 7991 pri_enable, 7992 flags, &print_header); 7993 if (cmd_rv != CMD_OK) { 7994 return cmd_rv; 7995 } 7996 cmd_rv = port_phy_control_update(u, p, 7997 BCM_PORT_PHY_CONTROL_CLOCK_SECONDARY_ENABLE, 7998 sec_enable, 7999 flags, &print_header); 8000 if (cmd_rv != CMD_OK) { 8001 return cmd_rv; 8002 } 8003 cmd_rv = port_phy_control_update(u, p, 8004 BCM_PORT_PHY_CONTROL_CLOCK_FREQUENCY, 8005 frequency, 8006 flags, &print_header); 8007 if (cmd_rv != CMD_OK) { 8008 return cmd_rv; 8009 } 8010 cmd_rv = port_phy_control_update(u, p, 8011 BCM_PORT_PHY_CONTROL_CLOCK_MODE_AUTO, 8012 mode_auto, 8013 flags, &print_header); 8014 if (cmd_rv != CMD_OK) { 8015 return cmd_rv; 8016 } 8017 cmd_rv = port_phy_control_update(u, p, 8018 BCM_PORT_PHY_CONTROL_CLOCK_AUTO_SECONDARY, 8019 auto_sec, 8020 flags, &print_header); 8021 if (cmd_rv != CMD_OK) { 8022 return cmd_rv; 8023 } 8024 cmd_rv = port_phy_control_update(u, p, 8025 BCM_PORT_PHY_CONTROL_CLOCK_SOURCE, 8026 source, 8027 flags, &print_header); 8028 if (cmd_rv != CMD_OK) { 8029 return cmd_rv; 8030 } 8031 cmd_rv = port_phy_control_update(u, p, 8032 BCM_PORT_PHY_CONTROL_PORT_PRIMARY, 8033 base, flags, &print_header); 8034 if (cmd_rv != CMD_OK) { 8035 return cmd_rv; 8036 } 8037 cmd_rv = port_phy_control_update(u, p, 8038 BCM_PORT_PHY_CONTROL_PORT_OFFSET, 8039 offset, flags, &print_header); 8040 if (cmd_rv != CMD_OK) { 8041 return cmd_rv; 8042 } 8043 } /* DPORT_BCM_PBMP_ITER( ) */ 8044 } 8045 return CMD_OK; 8046 } 8047 8048 STATIC cmd_result_t 8049 _if_esw_phy_wr(int u, args_t *a) 8050 { 8051 char *c; 8052 cmd_result_t cmd_rv; 8053 bcm_port_t port; 8054 uint32 block; 8055 uint32 address; 8056 uint32 value; 8057 8058 /* Get port */ 8059 if ((c = ARG_GET(a)) == NULL) { 8060 return CMD_USAGE; 8061 } 8062 port = sal_ctoi(c, 0); 8063 if (!SOC_PORT_VALID(u, port)) { 8064 cli_out("%s: Invalid port\n", ARG_CMD(a)); 8065 return CMD_FAIL; 8066 } 8067 8068 /* Get block */ 8069 if ((c = ARG_GET(a)) == NULL) { 8070 return CMD_USAGE; 8071 } 8072 block = sal_ctoi(c, 0); 8073 8074 /* Get address */ 8075 if ((c = ARG_GET(a)) == NULL) { 8076 return CMD_USAGE; 8077 } 8078 address = sal_ctoi(c, 0); 8079 8080 /* Get value */ 8081 if ((c = ARG_GET(a)) == NULL) { 8082 return CMD_USAGE; 8083 } 8084 value = sal_ctoi(c, 0); 8085 8086 /* Write the phy register */ 8087 cmd_rv = bcm_port_phy_set(u, port, BCM_PORT_PHY_INTERNAL, 8088 BCM_PORT_PHY_REG_INDIRECT_ADDR 8089 (0, block, address), value); 8090 return cmd_rv; 8091 } 8092 8093 STATIC cmd_result_t 8094 _if_esw_phy_rd_cp(int u, args_t *a) 8095 { 8096 char *c; 8097 cmd_result_t cmd_rv; 8098 bcm_port_t port; 8099 uint32 block; 8100 uint32 address; 8101 uint32 value; 8102 uint32 rval; 8103 8104 /* Get port */ 8105 c = ARG_GET(a); 8106 port = sal_ctoi(c, 0); 8107 if (!SOC_PORT_VALID(u, port)) { 8108 cli_out("%s: Invalid port\n", ARG_CMD(a)); 8109 return CMD_FAIL; 8110 } 8111 8112 /* Get block */ 8113 if ((c = ARG_GET(a)) == NULL) { 8114 return CMD_USAGE; 8115 } 8116 block = sal_ctoi(c, 0); 8117 8118 /* Get address */ 8119 if ((c = ARG_GET(a)) == NULL) { 8120 return CMD_USAGE; 8121 } 8122 address = sal_ctoi(c, 0); 8123 8124 /* Get compare value */ 8125 if ((c = ARG_GET(a)) == NULL) { 8126 return CMD_USAGE; 8127 } 8128 value = sal_ctoi(c, 0); 8129 8130 /* Read the phy register */ 8131 cmd_rv = bcm_port_phy_get(u, port, BCM_PORT_PHY_INTERNAL, 8132 BCM_PORT_PHY_REG_INDIRECT_ADDR 8133 (0, block, address), &rval); 8134 8135 if (value != rval) { 8136 cli_out("Error: block %x, register %x expected %x, got %x\n", 8137 block, address, value, rval); 8138 } else { 8139 cli_out("Pass\n"); 8140 } 8141 return cmd_rv; 8142 } 8143 8144 STATIC cmd_result_t 8145 _if_esw_phy_rd_cp2(int u, args_t *a) 8146 { 8147 char *c; 8148 cmd_result_t cmd_rv; 8149 bcm_port_t port; 8150 uint32 block; 8151 uint32 address; 8152 uint32 value; 8153 uint32 mask; 8154 uint32 rval; 8155 8156 /* Get port */ 8157 c = ARG_GET(a); 8158 port = sal_ctoi(c, 0); 8159 if (!SOC_PORT_VALID(u, port)) { 8160 cli_out("%s: Invalid port\n", ARG_CMD(a)); 8161 return CMD_FAIL; 8162 } 8163 8164 /* Get block */ 8165 if ((c = ARG_GET(a)) == NULL) { 8166 return CMD_USAGE; 8167 } 8168 block = sal_ctoi(c, 0); 8169 8170 /* Get address */ 8171 if ((c = ARG_GET(a)) == NULL) { 8172 return CMD_USAGE; 8173 } 8174 address = sal_ctoi(c, 0); 8175 8176 /* Get compare value */ 8177 if ((c = ARG_GET(a)) == NULL) { 8178 return CMD_USAGE; 8179 } 8180 value = sal_ctoi(c, 0); 8181 8182 /* Get mask */ 8183 if ((c = ARG_GET(a)) == NULL) { 8184 return CMD_USAGE; 8185 } 8186 mask = sal_ctoi(c, 0); 8187 8188 /* Read the phy register */ 8189 cmd_rv = bcm_port_phy_get(u, port, BCM_PORT_PHY_INTERNAL, 8190 BCM_PORT_PHY_REG_INDIRECT_ADDR 8191 (0, block, address), &rval); 8192 8193 if ((value & mask) != (rval & mask)) { 8194 cli_out("Error: block %x, register %x expected %x, got %x\n", 8195 block, address, (value & mask), (rval & mask)); 8196 } else { 8197 cli_out("Pass\n"); 8198 } 8199 return cmd_rv; 8200 } 8201 8202 STATIC cmd_result_t 8203 _if_esw_phy_mod(int u, args_t *a) 8204 { 8205 char *c; 8206 cmd_result_t cmd_rv; 8207 bcm_port_t port; 8208 int block; 8209 uint32 flags; 8210 uint32 address; 8211 uint32 value; 8212 uint32 mask; 8213 8214 /* Get port */ 8215 if ((c = ARG_GET(a)) == NULL) { 8216 return CMD_USAGE; 8217 } 8218 port = sal_ctoi(c, 0); 8219 if (!SOC_PORT_VALID(u, port)) { 8220 cli_out("%s: Invalid port\n", ARG_CMD(a)); 8221 return CMD_FAIL; 8222 } 8223 8224 /* Get block */ 8225 if ((c = ARG_GET(a)) == NULL) { 8226 return CMD_USAGE; 8227 } 8228 block = sal_ctoi(c, 0); 8229 8230 /* Get address */ 8231 if ((c = ARG_GET(a)) == NULL) { 8232 return CMD_USAGE; 8233 } 8234 address = sal_ctoi(c, 0); 8235 8236 /* Get value */ 8237 if ((c = ARG_GET(a)) == NULL) { 8238 return CMD_USAGE; 8239 } 8240 value = sal_ctoi(c, 0); 8241 8242 /* Get mask */ 8243 if ((c = ARG_GET(a)) == NULL) { 8244 return CMD_USAGE; 8245 } 8246 mask = sal_ctoi(c, 0); 8247 8248 /* Modify the phy register */ 8249 flags = 0; 8250 if (block >= 0) { 8251 flags = BCM_PORT_PHY_INTERNAL; 8252 address = BCM_PORT_PHY_REG_INDIRECT_ADDR(0, block, address); 8253 } 8254 cmd_rv = bcm_port_phy_modify(u, port, flags, address, value, mask); 8255 8256 return cmd_rv; 8257 } 8258 8259 STATIC cmd_result_t 8260 _if_esw_phy_control(int u, args_t *a) 8261 { 8262 soc_pbmp_t pbm; 8263 soc_port_t p, dport; 8264 char *c; 8265 uint32 wan_mode, preemphasis, predriver_current, driver_current, dfe, lp_dfe, br_dfe, linkTraining; 8266 uint32 sw_rx_los_nval = 0, sw_rx_los_oval; 8267 uint32 eq_boost; 8268 uint32 interface; 8269 uint32 interfacemax; 8270 uint32 flags; 8271 int print_header; 8272 cmd_result_t cmd_rv; 8273 bcm_error_t bcm_rv; 8274 bcm_port_config_t pcfg; 8275 int eq_tune = FALSE; 8276 int eq_status = FALSE; 8277 int dump = FALSE; 8278 int farEndEqValue = 0; 8279 #ifdef INCLUDE_MACSEC 8280 uint32 macsec_switch_fixed, macsec_switch_fixed_speed; 8281 uint32 macsec_switch_fixed_duplex, macsec_switch_fixed_pause; 8282 uint32 macsec_pause_rx_fwd, macsec_pause_tx_fwd; 8283 uint32 macsec_line_ipg, macsec_switch_ipg; 8284 8285 macsec_switch_fixed = 0; 8286 macsec_switch_fixed_speed = 0; 8287 macsec_switch_fixed_duplex = 0; 8288 macsec_switch_fixed_pause = 0; 8289 macsec_pause_rx_fwd = 0; 8290 macsec_pause_tx_fwd = 0; 8291 macsec_line_ipg = 0; 8292 macsec_switch_ipg = 0; 8293 #endif 8294 8295 if (bcm_port_config_get(u, &pcfg) != BCM_E_NONE) { 8296 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 8297 return CMD_FAIL; 8298 } 8299 8300 wan_mode = 0; 8301 preemphasis = 0; 8302 predriver_current = 0; 8303 driver_current = 0; 8304 interface = 0; 8305 interfacemax = 0; 8306 eq_boost = 0; 8307 8308 dfe = 0; 8309 lp_dfe = 0; 8310 br_dfe = 0; 8311 linkTraining = 0; 8312 8313 if ((c = ARG_GET(a)) == NULL) { 8314 SOC_PBMP_ASSIGN(pbm, pcfg.port); 8315 } else if (parse_bcm_pbmp(u, c, &pbm) < 0) { 8316 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 8317 return CMD_FAIL; 8318 } 8319 8320 BCM_PBMP_AND(pbm, pcfg.port); 8321 8322 flags = 0; 8323 if ((c = ARG_CUR(a)) != NULL) { 8324 parse_table_t pt; 8325 int i; 8326 8327 if (c[0] == '=') { 8328 return CMD_USAGE; /* '=' unsupported */ 8329 } 8330 if (sal_strcasecmp(c, "RxTune") == 0) { 8331 if (ARG_CNT(a) <= 1) { /*Current counter is at RxTune */ 8332 ARG_NEXT(a); 8333 farEndEqValue = 0; 8334 cli_out("far end equalization value not input, using 0\n"); 8335 } else { 8336 /* go to next argument */ 8337 ARG_NEXT(a); 8338 /* Get far end equalization value */ 8339 if ((c = ARG_GET(a)) != NULL) { 8340 farEndEqValue = sal_ctoi(c, 0); 8341 cli_out("far end equalization value input (%d)\n", 8342 farEndEqValue); 8343 } 8344 } 8345 eq_tune = TRUE; 8346 } 8347 if (sal_strcasecmp(c, "Dump") == 0) { 8348 c = ARG_GET(a); 8349 dump = TRUE; 8350 } 8351 8352 if ((eq_tune == FALSE) && (dump == FALSE)) { 8353 parse_table_init(u, &pt); 8354 parse_table_add(&pt, "WanMode", PQ_DFL | PQ_BOOL, 8355 0, &wan_mode, 0); 8356 parse_table_add(&pt, "Preemphasis", PQ_DFL | PQ_INT, 8357 0, &preemphasis, 0); 8358 parse_table_add(&pt, "DriverCurrent", PQ_DFL | PQ_INT, 8359 0, &driver_current, 0); 8360 parse_table_add(&pt, "PreDriverCurrent", PQ_DFL | PQ_INT, 8361 0, &predriver_current, 0); 8362 parse_table_add(&pt, "EqualizerBoost", PQ_DFL | PQ_INT, 8363 0, &eq_boost, 0); 8364 parse_table_add(&pt, "Interface", PQ_DFL | PQ_INT, 8365 0, &interface, 0); 8366 parse_table_add(&pt, "InterfaceMax", PQ_DFL | PQ_INT, 8367 0, &interfacemax, 0); 8368 parse_table_add(&pt, "SwRxLos", PQ_DFL | PQ_INT, 8369 0, &sw_rx_los_nval, 0); 8370 parse_table_add(&pt, "Dfe", PQ_DFL | PQ_INT, 8371 0, &dfe, 0); 8372 parse_table_add(&pt, "LpDfe", PQ_DFL | PQ_INT, 8373 0, &lp_dfe, 0); 8374 parse_table_add(&pt, "BrDfe", PQ_DFL | PQ_INT, 8375 0, &br_dfe, 0); 8376 parse_table_add(&pt, "LT", PQ_DFL | PQ_INT, 8377 0, &linkTraining, 0); 8378 8379 #ifdef INCLUDE_MACSEC 8380 parse_table_add(&pt, "MacsecSwitchFixed", PQ_DFL | PQ_BOOL, 8381 0, &macsec_switch_fixed, 0); 8382 parse_table_add(&pt, "MacsecSwitchFixedSpeed", PQ_DFL | PQ_INT, 8383 0, &macsec_switch_fixed_speed, 0); 8384 parse_table_add(&pt, "MacsecSwitchFixedDuplex", 8385 PQ_DFL | PQ_BOOL, 0, 8386 &macsec_switch_fixed_duplex, 0); 8387 parse_table_add(&pt, "MacsecSwitchFixedPause", PQ_DFL | PQ_BOOL, 8388 0, &macsec_switch_fixed_pause, 0); 8389 parse_table_add(&pt, "MacsecPauseRXForward", PQ_DFL | PQ_BOOL, 8390 0, &macsec_pause_rx_fwd, 0); 8391 parse_table_add(&pt, "MacsecPauseTXForward", PQ_DFL | PQ_BOOL, 8392 0, &macsec_pause_tx_fwd, 0); 8393 parse_table_add(&pt, "MacsecLineIPG", PQ_DFL | PQ_INT, 0, 8394 &macsec_line_ipg, 0); 8395 parse_table_add(&pt, "MacsecSwitchIPG", PQ_DFL | PQ_INT, 0, 8396 &macsec_switch_ipg, 0); 8397 #endif 8398 8399 if (parse_arg_eq(a, &pt) < 0) { 8400 parse_arg_eq_done(&pt); 8401 return CMD_USAGE; 8402 } 8403 if (ARG_CNT(a) > 0) { 8404 cli_out("%s: Unknown argument %s\n", ARG_CMD(a), ARG_CUR(a)); 8405 parse_arg_eq_done(&pt); 8406 return CMD_USAGE; 8407 } 8408 8409 for (i = 0; i < pt.pt_cnt; i++) { 8410 if (pt.pt_entries[i].pq_type & PQ_PARSED) { 8411 flags |= (1 << i); 8412 } 8413 } 8414 parse_arg_eq_done(&pt); 8415 } 8416 } 8417 /* coverity[overrun-local] */ 8418 DPORT_BCM_PBMP_ITER(u, pbm, dport, p) { 8419 print_header = TRUE; 8420 8421 if (eq_tune == TRUE) { 8422 8423 cmd_rv = 8424 bcm_port_control_set(u, p, 8425 bcmPortControlSerdesDriverEqualizationFarEnd, 8426 farEndEqValue); 8427 8428 cmd_rv = bcm_port_control_set(u, p, 8429 bcmPortControlSerdesDriverTune, 8430 1); 8431 if (cmd_rv != CMD_OK) { 8432 cli_out("unit %d port %d Tuning function not available\n", 8433 u, p); 8434 continue; 8435 } 8436 cli_out("Rx Equalization Tuning start\n"); 8437 sal_usleep(1000000); 8438 cmd_rv = bcm_port_control_get(u, p, 8439 bcmPortControlSerdesDriverEqualizationTuneStatusFarEnd, 8440 &eq_status); 8441 8442 cli_out("unit %d port %d Tuning done, Status: %s\n", 8443 u, p, ((cmd_rv == CMD_OK) && eq_status) ? "OK" : "FAIL"); 8444 continue; 8445 } 8446 if (dump == TRUE) { 8447 /* coverity[returned_value] */ 8448 cmd_rv = 8449 bcm_port_phy_control_set(u, p, BCM_PORT_PHY_CONTROL_DUMP, 8450 1); 8451 continue; 8452 } 8453 8454 cmd_rv = port_phy_control_update(u, p, BCM_PORT_PHY_CONTROL_WAN, 8455 wan_mode, flags, &print_header); 8456 if (cmd_rv != CMD_OK) { 8457 return cmd_rv; 8458 } 8459 8460 /* Read and set WAN mode */ 8461 cmd_rv = port_phy_control_update(u, p, BCM_PORT_PHY_CONTROL_WAN, 8462 wan_mode, flags, &print_header); 8463 if (cmd_rv != CMD_OK) { 8464 return cmd_rv; 8465 } 8466 8467 /* Read and set Preemphasis */ 8468 cmd_rv = port_phy_control_update(u, p, 8469 BCM_PORT_PHY_CONTROL_PREEMPHASIS, 8470 preemphasis, flags, &print_header); 8471 if (cmd_rv != CMD_OK) { 8472 return cmd_rv; 8473 } 8474 8475 /* Read and set Driver Current */ 8476 cmd_rv = port_phy_control_update(u, p, 8477 BCM_PORT_PHY_CONTROL_DRIVER_CURRENT, 8478 driver_current, flags, 8479 &print_header); 8480 if (cmd_rv != CMD_OK) { 8481 return cmd_rv; 8482 } 8483 8484 /* Read and set Pre-driver Current */ 8485 cmd_rv = port_phy_control_update(u, p, 8486 BCM_PORT_PHY_CONTROL_PRE_DRIVER_CURRENT, 8487 predriver_current, flags, 8488 &print_header); 8489 if (cmd_rv != CMD_OK) { 8490 return cmd_rv; 8491 } 8492 8493 /* Read and set DFE */ 8494 cmd_rv = port_phy_control_update(u, p, 8495 BCM_PORT_PHY_CONTROL_FIRMWARE_DFE_ENABLE, 8496 dfe, flags, &print_header); 8497 if (cmd_rv != CMD_OK) { 8498 return cmd_rv; 8499 } 8500 8501 /* Read and set LP_DFE */ 8502 cmd_rv = port_phy_control_update(u, p, 8503 BCM_PORT_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE, 8504 lp_dfe, flags, &print_header); 8505 if (cmd_rv != CMD_OK) { 8506 return cmd_rv; 8507 } 8508 8509 /* Read and set BR_DFE */ 8510 cmd_rv = port_phy_control_update(u, p, 8511 BCM_PORT_PHY_CONTROL_FIRMWARE_BR_DFE_ENABLE, 8512 br_dfe, flags, &print_header); 8513 if (cmd_rv != CMD_OK) { 8514 return cmd_rv; 8515 } 8516 8517 /* Read and set forced cl72/93 */ 8518 cmd_rv = port_phy_control_update(u, p, 8519 BCM_PORT_PHY_CONTROL_CL72, 8520 linkTraining, flags, &print_header); 8521 if (cmd_rv != CMD_OK) { 8522 return cmd_rv; 8523 } 8524 8525 /* Read and set Equalizer Boost */ 8526 cmd_rv = port_phy_control_update(u, p, 8527 BCM_PORT_PHY_CONTROL_EQUALIZER_BOOST, 8528 eq_boost, flags, &print_header); 8529 if (cmd_rv != CMD_OK) { 8530 return cmd_rv; 8531 } 8532 8533 /* Read and set the interface */ 8534 cmd_rv = port_phy_control_update(u, p, 8535 BCM_PORT_PHY_CONTROL_INTERFACE, 8536 interface, flags, &print_header); 8537 if (cmd_rv != CMD_OK) { 8538 return cmd_rv; 8539 } 8540 /* Read and set(is noop) the interface */ 8541 cmd_rv = port_phy_control_update(u, p, 8542 SOC_PHY_CONTROL_INTERFACE_MAX, 8543 interfacemax, flags, 8544 &print_header); 8545 if (cmd_rv != CMD_OK) { 8546 return cmd_rv; 8547 } 8548 8549 /* Read and set(is noop) the interface */ 8550 bcm_rv = bcm_port_phy_control_get(u, p, 8551 BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS, 8552 &sw_rx_los_oval); 8553 if (BCM_FAILURE(bcm_rv) && BCM_E_UNAVAIL != bcm_rv) { 8554 cli_out("%s\n", bcm_errmsg(bcm_rv)); 8555 return CMD_FAIL; 8556 } else if (BCM_SUCCESS(bcm_rv)) { 8557 if ((sw_rx_los_nval != sw_rx_los_oval) && (flags & (1 << 7))) { 8558 bcm_rv = bcm_port_phy_control_set(u, p, 8559 BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS, 8560 sw_rx_los_nval); 8561 if (BCM_FAILURE(bcm_rv)) { 8562 cli_out("%s\n", bcm_errmsg(bcm_rv)); 8563 return CMD_FAIL; 8564 } 8565 sw_rx_los_oval = sw_rx_los_nval; 8566 } 8567 cmd_rv = CMD_OK; 8568 cli_out("Rx LOS (s/w) enable - %d\n", sw_rx_los_oval); 8569 } 8570 #ifdef INCLUDE_MACSEC 8571 8572 /* Read and set the Switch fixed */ 8573 cmd_rv = port_phy_control_update(u, p, 8574 BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED, 8575 macsec_switch_fixed, 8576 flags, &print_header); 8577 if (cmd_rv != CMD_OK) { 8578 return cmd_rv; 8579 } 8580 8581 /* Read and set the Switch fixed Speed */ 8582 cmd_rv = port_phy_control_update(u, p, 8583 BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED, 8584 macsec_switch_fixed_speed, 8585 flags, &print_header); 8586 if (cmd_rv != CMD_OK) { 8587 return cmd_rv; 8588 } 8589 8590 /* Read and set the Switch fixed Duplex */ 8591 cmd_rv = port_phy_control_update(u, p, 8592 BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX, 8593 macsec_switch_fixed_duplex, 8594 flags, &print_header); 8595 if (cmd_rv != CMD_OK) { 8596 return cmd_rv; 8597 } 8598 8599 /* Read and set the Switch fixed Pause */ 8600 cmd_rv = port_phy_control_update(u, p, 8601 BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE, 8602 macsec_switch_fixed_pause, 8603 flags, &print_header); 8604 if (cmd_rv != CMD_OK) { 8605 return cmd_rv; 8606 } 8607 8608 /* Read and set Pause Receive Forward */ 8609 cmd_rv = port_phy_control_update(u, p, 8610 BCM_PORT_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD, 8611 macsec_pause_rx_fwd, 8612 flags, &print_header); 8613 if (cmd_rv != CMD_OK) { 8614 return cmd_rv; 8615 } 8616 8617 /* Read and set Pause transmit Forward */ 8618 cmd_rv = port_phy_control_update(u, p, 8619 BCM_PORT_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD, 8620 macsec_pause_tx_fwd, 8621 flags, &print_header); 8622 if (cmd_rv != CMD_OK) { 8623 return cmd_rv; 8624 } 8625 8626 /* Read and set Line Side IPG */ 8627 cmd_rv = port_phy_control_update(u, p, 8628 BCM_PORT_PHY_CONTROL_MACSEC_LINE_IPG, 8629 macsec_line_ipg, 8630 flags, &print_header); 8631 if (cmd_rv != CMD_OK) { 8632 return cmd_rv; 8633 } 8634 8635 /* Read and set Switch Side IPG */ 8636 cmd_rv = port_phy_control_update(u, p, 8637 BCM_PORT_PHY_CONTROL_MACSEC_SWITCH_IPG, 8638 macsec_switch_ipg, 8639 flags, &print_header); 8640 if (cmd_rv != CMD_OK) { 8641 return cmd_rv; 8642 } 8643 #endif 8644 } 8645 return CMD_OK; 8646 } 8647 8648 STATIC cmd_result_t 8649 _if_esw_phy_dumpall(int u, args_t *a) 8650 { 8651 char *c; 8652 uint16 phy_data, phy_devad = 0; 8653 uint16 phy_addr; 8654 uint32 phy_reg; 8655 uint16 phy_addr_start = 0; 8656 uint16 phy_addr_end = 0xFF; 8657 int is_c45 = 0; 8658 int rv = 0; 8659 8660 if ((c = ARG_GET(a)) == NULL) { 8661 cli_out("%s: Error: expecting \"c45\" or \"c22\"\n", ARG_CMD(a)); 8662 return CMD_USAGE; 8663 } 8664 is_c45 = 0; 8665 if (sal_strcasecmp(c, "c45") == 0) { 8666 is_c45 = 1; 8667 if (!soc_feature(u, soc_feature_phy_cl45)) { 8668 cli_out("%s: Error: Device does not support clause 45\n", 8669 ARG_CMD(a)); 8670 return CMD_USAGE; 8671 } 8672 } else if (sal_strcasecmp(c, "c22") != 0) { 8673 cli_out("%s: Error: expecting \"c45\" or \"c22\"\n", ARG_CMD(a)); 8674 return CMD_USAGE; 8675 } 8676 if ((c = ARG_GET(a)) != NULL) { 8677 char *end; 8678 8679 phy_addr_start = sal_strtoul(c, &end, 0); 8680 if (*end) { 8681 cli_out("%s: Error: Expecting PHY start address [%s]\n", 8682 ARG_CMD(a), c); 8683 return CMD_USAGE; 8684 } 8685 if ((c = ARG_GET(a)) != NULL) { 8686 phy_addr_end = sal_strtoul(c, &end, 0); 8687 if (*end) { 8688 cli_out("%s: Error: Expecting PHY end address [%s]\n", 8689 ARG_CMD(a), c); 8690 return CMD_USAGE; 8691 } 8692 } else { 8693 /* If start specified but no end, just print one phy address */ 8694 phy_addr_end = phy_addr_start; 8695 } 8696 } else { 8697 /* phy addr start and end are not specified */ 8698 if (SOC_IS_TRIDENT3(u) || SOC_IS_TOMAHAWK(u)) { 8699 phy_addr_end = 0x1FF; 8700 } else if (SOC_IS_TOMAHAWK3(u)) { 8701 phy_addr_end = 0x2FF; 8702 } 8703 } 8704 8705 if (is_c45) { 8706 cli_out("%4s%5s %5s %3s: %-6s\n", "", "PRTAD", "DEVAD", "REG", 8707 "VALUE"); 8708 for (phy_addr = phy_addr_start; phy_addr <= phy_addr_end; 8709 phy_addr++) { 8710 /* Clause 45 supports 32 devices per phy. */ 8711 for (phy_devad = 0; phy_devad <= 0x1f; phy_devad++) { 8712 /* Device ID is in registers 2 and 3 */ 8713 for (phy_reg = 2; phy_reg <= 3; phy_reg++) { 8714 rv = soc_miimc45_read(u, phy_addr, phy_devad, 8715 phy_reg, &phy_data); 8716 if (rv < 0) { 8717 cli_out("ERROR: MII Addr %d: " 8718 "soc_miim_read failed: %s\n", 8719 phy_addr, soc_errmsg(rv)); 8720 return CMD_FAIL; 8721 } 8722 /* Assume device doesn't exist in phy if 8723 read back is all 0/1 */ 8724 if ((phy_data != 0xFFFF) && (phy_data != 0x0000) && 8725 (phy_data != 0x7FFF)&& (phy_data != 0x3FFF)) { 8726 cli_out("%4s 0x%02X 0x%02X 0x%02X: 0x%04X\n", 8727 "", phy_addr, phy_devad, phy_reg, phy_data); 8728 } 8729 } 8730 } 8731 } 8732 } else { 8733 cli_out("%4s%5s %3s: %-6s\n", "", "PRTAD", "REG", "VALUE"); 8734 for (phy_addr = phy_addr_start; phy_addr <= phy_addr_end; 8735 phy_addr++) { 8736 /* Device ID is in registers 2 and 3 */ 8737 for (phy_reg = 2; phy_reg <= 3; phy_reg++) { 8738 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data); 8739 if (rv < 0) { 8740 cli_out("ERROR: MII Addr %d: soc_miim_read failed: %s\n", 8741 phy_addr, soc_errmsg(rv)); 8742 return CMD_FAIL; 8743 } 8744 if ((phy_data != 0xFFFF) && (phy_data != 0x0000)) { 8745 cli_out("%4s0x%02X 0x%02x: 0x%04x\n", 8746 "", phy_addr, phy_reg, phy_data); 8747 } 8748 } 8749 } 8750 } 8751 return CMD_OK; 8752 } 8753 8754 STATIC cmd_result_t 8755 _if_esw_phy_raw(int u, args_t *a) 8756 { 8757 char *c, *bus_name; 8758 int is_c45 = 0; 8759 int is_sbus = 0; 8760 int is_sim = 0; 8761 int is_mpp1 = 0; 8762 uint16 phy_data, phy_devad = 0; 8763 uint16 phy_addr, phy_lane = 0, phy_pindex = 0; 8764 uint32 phy_reg, phy_wrmask; 8765 uint32 phy_data32, phy_aer = 0; 8766 int rv = 0; 8767 8768 if ((c = ARG_GET(a)) == NULL) { 8769 return CMD_USAGE; 8770 } 8771 8772 bus_name = "miim"; 8773 if (sal_strcasecmp(c, "sbus") == 0) { 8774 is_sbus = 1; 8775 bus_name = "sbus_mdio"; 8776 if ((c = ARG_GET(a)) == NULL) { 8777 return CMD_USAGE; 8778 } 8779 } else if (sal_strcasecmp(c, "sim") == 0) { 8780 is_sim = 1; 8781 bus_name = "physim"; 8782 if ((c = ARG_GET(a)) == NULL) { 8783 return CMD_USAGE; 8784 } 8785 } else if (soc_feature(u, soc_feature_phy_cl45)) { 8786 if (sal_strcasecmp(c, "c45") == 0) { 8787 bus_name = "miimc45"; 8788 is_c45 = 1; 8789 if ((c = ARG_GET(a)) == NULL) { 8790 return CMD_USAGE; 8791 } 8792 } 8793 } 8794 phy_addr = sal_strtoul(c, NULL, 0); 8795 if ((c = ARG_GET(a)) == NULL) { /* Get register number */ 8796 return CMD_USAGE; 8797 } 8798 if (is_sbus || is_sim) { 8799 phy_devad = sal_strtoul(c, NULL, 0); 8800 if (phy_devad > 0x1f) { 8801 cli_out("ERROR: Invalid devad 0x%x, max=0x%x\n", 8802 phy_devad, 0x1f); 8803 return CMD_FAIL; 8804 } 8805 /* 8806 * If DEVAD is specified as X.Y then X is the DEVAD and Y 8807 * is the lane number. For example DEVAD=1 and lane=2 is 8808 * specified as 1.2 and encoded in phy_aer as 0x0802. 8809 */ 8810 if ((c = sal_strchr(c, '.')) != NULL) { 8811 c++; 8812 phy_lane = sal_strtoul(c, NULL, 0); 8813 /*next check lane number is greater than 7 for TSCBH */ 8814 if (phy_lane > 7) { 8815 cli_out("ERROR: Invalid phy_lane 0x%x, max=0x%x\n", 8816 phy_lane, 0x7); 8817 return CMD_FAIL; 8818 } else { 8819 if (phy_lane > 3) { 8820 is_mpp1 = 1; 8821 } 8822 } 8823 if((c = sal_strchr(c, '.')) != NULL) { 8824 c++; 8825 phy_pindex = sal_strtoul(c, NULL, 0); 8826 } 8827 } 8828 8829 /* need to check if TSCBH 8 lane, for pcs register lane 0-lane3 using MPP0 8830 and lane 4-7 using MPP1, the bit location for MPP0 is 24 and MPP1 is 25 */ 8831 if (phy_devad == 0) { 8832 if (is_mpp1) { 8833 phy_aer = 1 << 9; 8834 } else { 8835 phy_aer = 1 << 8; 8836 } 8837 phy_aer |= (phy_devad << 11) | (phy_lane % 4); 8838 } else { 8839 phy_aer = (phy_devad << 11) | phy_lane | (phy_pindex << 8); 8840 } 8841 if ((c = ARG_GET(a)) == NULL) { /* Get register number */ 8842 return CMD_USAGE; 8843 } 8844 } else if (is_c45) { 8845 phy_devad = sal_strtoul(c, NULL, 0); 8846 if (phy_devad > 0x1f) { 8847 cli_out("ERROR: Invalid devad 0x%x, max=0x%x\n", 8848 phy_devad, 0x1f); 8849 return CMD_FAIL; 8850 } 8851 if ((c = ARG_GET(a)) == NULL) { /* Get register number */ 8852 return CMD_USAGE; 8853 } 8854 } 8855 phy_reg = sal_strtoul(c, NULL, 0); 8856 if ((c = ARG_GET(a)) == NULL) { /* Read register */ 8857 if (is_sbus) { 8858 phy_reg = (phy_aer << 16) | phy_reg; 8859 rv = soc_sbus_mdio_read(u, phy_addr, phy_reg, &phy_data32); 8860 phy_data = (uint16)phy_data32; 8861 } else if (is_sim) { 8862 phy_reg = (phy_aer << 16) | phy_reg; 8863 rv = soc_physim_read(u, phy_addr, phy_reg, &phy_data); 8864 } else if (is_c45) { 8865 rv = soc_miimc45_read(u, phy_addr, phy_devad, 8866 phy_reg, &phy_data); 8867 } else { 8868 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data); 8869 } 8870 if (rv < 0) { 8871 cli_out("ERROR: MII Addr %d: soc_%s_read failed: %s\n", 8872 phy_addr, bus_name, soc_errmsg(rv)); 8873 return CMD_FAIL; 8874 } 8875 var_set_hex("phy_reg_data", phy_data, TRUE, FALSE); 8876 cli_out("%s\t0x%02x: 0x%04x\n", "", phy_reg, phy_data); 8877 } else { /* write */ 8878 phy_data = sal_strtoul(c, NULL, 0); 8879 if (is_sbus || is_sim) { 8880 /* 8881 * If register data is specified as X/Y then X is the 8882 * data value and Y is the data mask. For example 8883 * data=0x50 and mask=0xf0 is specified as 0x50/0xf0 8884 * and encoded in phy_data32 as 0x0f000500. Note that 8885 * if the mask is not specified (or zero) then it is 8886 * implicitly assumed to be 0xffff (all bits valid). 8887 */ 8888 phy_data32 = phy_data; 8889 phy_wrmask = 0; 8890 if ((c = sal_strchr(c, '/')) != NULL) { 8891 c++; 8892 phy_wrmask = sal_strtoul(c, NULL, 0); 8893 phy_data32 |= (phy_wrmask << 16); 8894 } 8895 phy_reg = (phy_aer << 16) | phy_reg; 8896 if (is_sbus) { 8897 rv = soc_sbus_mdio_write(u, phy_addr, phy_reg, phy_data32); 8898 } else { /* is_sim */ 8899 rv = soc_physim_wrmask(u, phy_addr, 8900 phy_reg, phy_data, phy_wrmask); 8901 } 8902 } else if (is_c45) { 8903 rv = soc_miimc45_write(u, phy_addr, phy_devad, phy_reg, 8904 phy_data); 8905 } else { 8906 rv = soc_miim_write(u, phy_addr, phy_reg, phy_data); 8907 } 8908 if (rv < 0) { 8909 cli_out("ERROR: MII Addr %d: soc_%s_write failed: %s\n", 8910 phy_addr, bus_name, soc_errmsg(rv)); 8911 return CMD_FAIL; 8912 } 8913 } 8914 return CMD_OK; 8915 } 8916 8917 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X) 8918 STATIC cmd_result_t 8919 _phy_mt2(int unit, args_t *args) 8920 { 8921 mt2_sym_t *phy8806xsymbs = NULL; 8922 parse_table_t pt; 8923 bcm_pbmp_t pbm; 8924 soc_port_t p, dport; 8925 phy_ctrl_t *pc; 8926 uint16 phy_addr; 8927 char *port_str, *cmd_str, *regname, *regval, *fldname, *fldval; 8928 #if defined(INCLUDE_FCMAP) 8929 char *fc_oper; 8930 uint8 cmd = 0, show = 0; 8931 #endif 8932 char temp_char[2]; 8933 uint32 testno; 8934 uint32 val1 = 0; 8935 uint32 mt2_addr; 8936 uint32 mt2_data[4]; 8937 uint32 mt2_field; 8938 uint32 mt2_field_data[4]; 8939 uint32 flags = 0; 8940 int i, j, tem, sbit, ebit, cnt, blkno = -1, min_idx = -1, max_idx = -1; 8941 parse_pm_t ctr_options[] = { 8942 {"All", MT2_CTR_ALL}, 8943 {"SYs", MT2_CTR_SYS}, 8944 {"LiNe", MT2_CTR_LINE}, 8945 {"CHanged", MT2_CTR_CHANGED}, 8946 {"Same", MT2_CTR_SAME}, 8947 {"Zero", MT2_CTR_ZERO}, 8948 {"NonZero", MT2_CTR_NONZERO}, 8949 {"heX", MT2_CTR_HEX}, 8950 {NULL, 0} 8951 }; 8952 8953 BCM_PBMP_CLEAR(pbm); 8954 port_str = NULL; 8955 8956 if ((cmd_str = ARG_GET(args)) == NULL) { 8957 cli_out ("Specify Operation.. getreg, setreg, getmem, setmem, gettotsc, settotsc, counter, dump or testrun\n"); 8958 return CMD_FAIL; 8959 } 8960 8961 if ((sal_strcasecmp(cmd_str, "counter") == 0) || (sal_strcasecmp(cmd_str, "ctr") == 0)) { 8962 if ((cmd_str = ARG_GET(args)) == NULL) { 8963 cli_out ("Specify subcommand.. start, stop, show , interval\n"); 8964 return CMD_FAIL; 8965 } 8966 if (sal_strcasecmp(cmd_str, "start") == 0) { 8967 phy8806x_ctr_start(unit); 8968 return CMD_OK; 8969 } else if (sal_strcasecmp(cmd_str, "stop") == 0) { 8970 phy8806x_ctr_stop(unit); 8971 return CMD_OK; 8972 } else if ((sal_strcasecmp(cmd_str, "show") == 0) || (sal_strcasecmp(cmd_str, "interval") == 0) || 8973 (sal_strcasecmp(cmd_str, "fcevt") == 0)) { 8974 if ((port_str = ARG_GET(args)) == NULL) { 8975 cli_out ("Specify port bitmap\n"); 8976 return CMD_FAIL; 8977 } 8978 if (parse_bcm_pbmp(unit, port_str, &pbm) < 0) { 8979 cli_out("ERROR: unrecognized port bitmap: %s\n", port_str); 8980 return CMD_FAIL; 8981 } 8982 } else { 8983 cli_out ("Invalid subcommand.. start, stop, show, interval\n"); 8984 return CMD_FAIL; 8985 } 8986 if (sal_strcasecmp(cmd_str, "interval") == 0) { 8987 if ((regval = ARG_GET(args)) == NULL) { 8988 cli_out ("Specify the ctr task interval\n"); 8989 return CMD_FAIL; 8990 } 8991 val1 = sal_ctoi(regval, 0); 8992 /* coverity[overrun-local] */ 8993 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 8994 pc = EXT_PHY_SW_STATE(unit, p); 8995 if ((pc == NULL) || (phy_is_8806x(pc) != SOC_E_NONE)) { 8996 continue; 8997 } 8998 phy8806x_ctr_interval_set(pc, val1); 8999 } 9000 #if defined(INCLUDE_FCMAP) 9001 } else if (sal_strcasecmp(cmd_str, "fcevt") == 0) { 9002 if ((regval = ARG_GET(args)) == NULL) { 9003 cli_out ("Specify FC event 0 - disable; 1 - enable\n"); 9004 return CMD_FAIL; 9005 } 9006 9007 val1 = sal_ctoi(regval, 0); 9008 if (val1 == 0) { 9009 cmd = 0xc; 9010 } else if (val1 == 1) { 9011 cmd = 0xd; 9012 } 9013 9014 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9015 cli_out("FC Evt: u 0x%x, p 0x%x, cmd 0x%x\n", unit, p, cmd); 9016 bfcmap88060_xmod_debug_cmd(unit, p, cmd); 9017 } 9018 #endif 9019 } else if (sal_strcasecmp(cmd_str, "show") == 0) { 9020 while ((cmd_str = ARG_GET(args)) != NULL) { 9021 if (parse_mask(cmd_str, ctr_options, &flags)) { 9022 cli_out("Error: invalid option ignored: %s\n", cmd_str); 9023 } 9024 } 9025 9026 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9027 pc = EXT_PHY_SW_STATE(unit, p); 9028 if ((pc == NULL) || (phy_is_8806x(pc) != SOC_E_NONE)) { 9029 continue; 9030 } 9031 phy8806x_ctr_show(pc, flags); 9032 } 9033 } 9034 return CMD_OK; 9035 } 9036 9037 if (!(sal_strcasecmp(cmd_str, "listreg") == 0)) { 9038 if ((port_str = ARG_GET(args)) == NULL) { 9039 cli_out("%s: ERROR: missing port bitmap\n", ARG_CMD(args)); 9040 return CMD_FAIL; 9041 } 9042 if (parse_bcm_pbmp(unit, port_str, &pbm) < 0) { 9043 cli_out("ERROR: unrecognized port bitmap: %s\n", port_str); 9044 return CMD_FAIL; 9045 } 9046 } 9047 9048 if (sal_strcasecmp(cmd_str, "listreg") == 0) { 9049 if ((regname = ARG_GET(args)) == NULL) { 9050 cli_out ("Specify Partial register Name\n"); 9051 return CMD_FAIL; 9052 } 9053 i = 0; 9054 while (i >= 0) { 9055 i = mt2_syms_find_next_name(regname, &phy8806xsymbs, i); 9056 if (i >= 0) 9057 { 9058 cli_out("%s\n", phy8806xsymbs->name); 9059 } 9060 } 9061 return CMD_OK; 9062 } else if (sal_strcasecmp(cmd_str, "dump") == 0) { 9063 if ((regname = ARG_GET(args)) == NULL) { 9064 cli_out ("Specify AXI Address\n"); 9065 return CMD_FAIL; 9066 } 9067 mt2_addr = sal_ctoi(regname, 0); 9068 9069 if ((regval = ARG_GET(args)) == NULL) { 9070 val1 = 1; 9071 } else { 9072 val1 = sal_ctoi(regval, 0); 9073 } 9074 9075 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9076 phy_addr = port_to_phyaddr(unit,p); 9077 for (i = 0; i < val1; i++) { 9078 mt2_axi_read(unit, phy_addr, (mt2_addr + (i * 4)), mt2_data); 9079 /* To Do: Format Dump printout */ 9080 cli_out("Reading at 0x%08x at phy addr 0x%02x = 0x%08x\n", (mt2_addr + (i * 4)), phy_addr, mt2_data[0]); 9081 } 9082 } 9083 } else if ((sal_strcasecmp(cmd_str, "getreg") == 0) || (sal_strcasecmp(cmd_str, "setreg") == 0) || (sal_strcasecmp(cmd_str, "modreg") == 0)) { 9084 parse_table_init(unit, &pt); 9085 parse_table_add(&pt, "BLocK", PQ_DFL | PQ_INT, (void *)(-1), &blkno, 0); 9086 if (parse_arg_eq(args, &pt) < 0) { 9087 /* No Arguments. Don't have to do anything */ 9088 } 9089 parse_arg_eq_done(&pt); 9090 9091 if ((regname = ARG_GET(args)) == NULL) { 9092 /* Display All Registers */ 9093 regname = &temp_char[0]; /* use a local char array to avoid memory leak */ 9094 sal_strcpy(regname, "r"); 9095 } 9096 if (isint(regname)) { 9097 cli_out("Reg operation by Address Not Implemented"); 9098 /* Display All Registers */ 9099 regname = &temp_char[0]; 9100 sal_strcpy(regname, "r"); 9101 } 9102 9103 if ((phy8806xsymbs = mt2_syms_find_name(regname)) != NULL) 9104 { 9105 if (sal_strcasecmp(cmd_str, "setreg") == 0) { /* Set Reg */ 9106 if ((regval = ARG_GET(args)) == NULL) { 9107 cli_out ("Specify Value to Write\n"); 9108 return CMD_FAIL; 9109 } 9110 if (sal_strcmp(regval, "POR") == 0) { 9111 mt2_data[0] = phy8806xsymbs->rstval; 9112 mt2_data[1] = phy8806xsymbs->rstval_hi; 9113 } else { 9114 if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_R64) { 9115 mt2_data[1] = sal_ctoi(regval, 0); 9116 if ((regval = ARG_GET(args)) == NULL) { 9117 cli_out ("Value Size Mismatch(64 bits) - Provide 2 words\n"); 9118 return CMD_FAIL; 9119 } 9120 } else { 9121 mt2_data[1] = 0; 9122 } 9123 mt2_data[0] = sal_ctoi(regval, 0); 9124 } 9125 9126 while (((fldname = ARG_GET(args)) != NULL) && ((fldval = ARG_GET(args)) != NULL)) { 9127 /* Search Fields */ 9128 i = 0; 9129 while (1) { 9130 mt2_field = phy8806xsymbs->fields[i]; 9131 j = (mt2_field >> 16) & 0x7fff; 9132 if (sal_strcasecmp(fldname, phy8806x_fields[j]) == 0) { 9133 sbit = (mt2_field & 0xff); 9134 ebit = ((mt2_field >> 8) & 0xff); 9135 if ((ebit - sbit) <= 31) { 9136 j = sal_ctoi(fldval, 0); 9137 mt2_field32_set(mt2_data, sbit, ebit, j); 9138 cli_out ("Setting Field %s at %d - %d to %d\n", fldname, sbit, ebit, j); 9139 } 9140 break; 9141 } 9142 if (mt2_field & CDK_SYMBOL_FIELD_FLAG_LAST) { 9143 break; 9144 } 9145 i++; 9146 } 9147 } 9148 9149 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9150 phy_addr = port_to_phyaddr(unit,p); 9151 mt2_sbus_reg_write(unit, phy_addr, blkno, phy8806xsymbs, mt2_data); 9152 if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_R64) { 9153 cli_out("Writing 0x%08x_%08x to reg %s at phy addr 0x%02x\n", mt2_data[1], mt2_data[0], regname, phy_addr); 9154 } else { 9155 cli_out("Writing 0x%08x to reg %s at phy addr 0x%02x\n", mt2_data[0], regname, phy_addr); 9156 } 9157 } 9158 } else if (sal_strcasecmp(cmd_str, "modreg") == 0) { /* Modify Reg */ 9159 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9160 phy_addr = port_to_phyaddr(unit,p); 9161 cli_out("Modify Register %s at phy addr 0x%02x\n", regname, phy_addr); 9162 mt2_sbus_reg_read(unit, phy_addr, blkno, phy8806xsymbs, mt2_data); 9163 tem = 0; 9164 while (((fldname = ARG_GET(args)) != NULL) && ((fldval = ARG_GET(args)) != NULL)) { 9165 /* Search Fields */ 9166 i = 0; 9167 while (1) { 9168 mt2_field = phy8806xsymbs->fields[i]; 9169 j = (mt2_field >> 16) & 0x7fff; 9170 if (sal_strcasecmp(fldname, phy8806x_fields[j]) == 0) { 9171 sbit = (mt2_field & 0xff); 9172 ebit = ((mt2_field >> 8) & 0xff); 9173 if ((ebit - sbit) > 31) { 9174 cli_out("Skipping 64-bit field %s\n", fldname); 9175 } else { 9176 j = sal_ctoi(fldval, 0); 9177 mt2_field32_set(mt2_data, sbit, ebit, j); 9178 tem = 1; 9179 cli_out ("Setting Field %s at %d - %d to %d\n", fldname, sbit, ebit, j); 9180 } 9181 break; 9182 } 9183 9184 if (mt2_field & CDK_SYMBOL_FIELD_FLAG_LAST) { 9185 cli_out ("Not Found Field %s\n", fldname); 9186 break; 9187 } 9188 i++; 9189 } 9190 } 9191 if (tem) { /* At least one field had changed.. */ 9192 mt2_sbus_reg_write(unit, phy_addr, blkno, phy8806xsymbs, mt2_data); 9193 } 9194 } 9195 } else { /* Get Reg */ 9196 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9197 phy_addr = port_to_phyaddr(unit,p); 9198 mt2_sbus_reg_read(unit, phy_addr, blkno, phy8806xsymbs, mt2_data); 9199 if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_R64) { 9200 cli_out("%s.%s[0x%08x]= 0x%08x_%08x: <", phy8806xsymbs->name, port_str, phy8806xsymbs->addr, mt2_data[1], mt2_data[0]); 9201 } else { 9202 cli_out("%s.%s[0x%08x]= 0x%08x: <", phy8806xsymbs->name, port_str, phy8806xsymbs->addr, mt2_data[0]); 9203 } 9204 9205 /* Print Fields */ 9206 i = 0; 9207 while (1) { 9208 if (!phy8806xsymbs->fields) { 9209 cli_out(" field info unavailable >\n"); 9210 break; 9211 } 9212 mt2_field = phy8806xsymbs->fields[i]; 9213 j = (mt2_field >> 16) & 0x7fff; 9214 sbit = (mt2_field & 0xff); 9215 ebit = ((mt2_field >> 8) & 0xff); 9216 mt2_field_get(mt2_data, sbit, ebit, mt2_field_data); 9217 if ((ebit - sbit) > 31) { 9218 cli_out("%s=0x%08x_%08x", phy8806x_fields[j], mt2_field_data[1], mt2_field_data[0]); 9219 } else { 9220 cli_out("%s=%d", phy8806x_fields[j], mt2_field_data[0]); 9221 } 9222 if (mt2_field & CDK_SYMBOL_FIELD_FLAG_LAST) { 9223 cli_out(">\n"); 9224 break; 9225 } else { 9226 cli_out(", "); 9227 } 9228 i++; 9229 } 9230 } 9231 } 9232 } else { 9233 cli_out("Reg Not Found. Possible registers are:\n"); 9234 i = 0; 9235 while (i >= 0) { 9236 i = mt2_syms_find_next_name(regname, &phy8806xsymbs, i); 9237 if (i >= 0) 9238 { 9239 if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_REGISTER) { 9240 cli_out("%s\n", phy8806xsymbs->name); 9241 } 9242 } 9243 } 9244 } 9245 } else if ((sal_strcasecmp(cmd_str, "getmem") == 0) || (sal_strcasecmp(cmd_str, "setmem") == 0)) { 9246 parse_table_init(unit, &pt); 9247 parse_table_add(&pt, "MINIdx", PQ_DFL | PQ_INT, (void *)(-1), &min_idx, 0); 9248 parse_table_add(&pt, "MAXIdx", PQ_DFL | PQ_INT, (void *)(-1), &max_idx, 0); 9249 parse_table_add(&pt, "BLocK", PQ_DFL | PQ_INT, (void *)(-1), &blkno, 0); 9250 9251 if (parse_arg_eq(args, &pt) < 0) { 9252 /* No Arguments. Don't have to do anything */ 9253 } 9254 parse_arg_eq_done(&pt); 9255 9256 if ((regname = ARG_GET(args)) == NULL) { 9257 /* Display All Memories */ 9258 regname = &temp_char[0]; /* use local char array to avoid memory leak */ 9259 sal_strcpy(regname, "m"); 9260 } 9261 9262 if (isint(regname)) { 9263 cli_out("Mem operation by Address Not Implemented\n"); 9264 /* Display All Memories */ 9265 regname = &temp_char[0]; 9266 sal_strcpy(regname, "m"); 9267 } 9268 9269 if ((phy8806xsymbs = mt2_syms_find_name(regname)) != NULL) 9270 { 9271 cnt = (phy8806xsymbs->index & 0xff) / 4; /* Number of 32-bit words */ 9272 if (min_idx == -1) { 9273 min_idx = MT2_SYMBOL_INDEX_MIN_DECODE(phy8806xsymbs->index); 9274 } 9275 if (max_idx == -1) { 9276 max_idx = MT2_SYMBOL_INDEX_MAX_DECODE(phy8806xsymbs->index); 9277 } 9278 9279 if (sal_strcasecmp(cmd_str, "setmem") == 0) { /* Set Mem */ 9280 for (i = 1; i <= cnt; i++) { 9281 if ((regval = ARG_GET(args)) == NULL) { 9282 cli_out ("Value Size Mismatch(%d bits) - Provide %d words\n", (cnt*32), cnt); 9283 return CMD_FAIL; 9284 } 9285 mt2_data[cnt-i] = sal_ctoi(regval, 0); 9286 } 9287 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9288 phy_addr = port_to_phyaddr(unit,p); 9289 for (i = min_idx; i <= max_idx; i++) { 9290 mt2_sbus_mem_write(unit, phy_addr, blkno, phy8806xsymbs, i, mt2_data); 9291 cli_out("Writing %d words to mem %s[%d] at phy addr 0x%02x\n", cnt, regname, i, phy_addr); 9292 } 9293 } 9294 } else { /* Get Mem */ 9295 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9296 phy_addr = port_to_phyaddr(unit,p); 9297 for (i = min_idx; i <= max_idx; i++) { 9298 mt2_sbus_mem_read(unit, phy_addr, blkno, phy8806xsymbs, i, mt2_data); 9299 cli_out("Reading mem %s[%d] at phy addr 0x%02x = 0x", regname, i, phy_addr); 9300 for (j = 1; j <= cnt; j++) { 9301 cli_out("%08x%s", mt2_data[cnt-j], (j == cnt) ? "\n" : "_"); 9302 } 9303 } 9304 } 9305 } 9306 } else { 9307 cli_out("memory Not Found. Possible memories are:\n"); 9308 i = 0; 9309 while (i >= 0) { 9310 i = mt2_syms_find_next_name(regname, &phy8806xsymbs, i); 9311 if (i >= 0) 9312 { 9313 if (phy8806xsymbs->flags & MT2_SYMBOL_FLAG_MEMORY) { 9314 cli_out("%s\n", phy8806xsymbs->name); 9315 } 9316 } 9317 } 9318 } 9319 return CMD_OK; 9320 } else if ((sal_strcasecmp(cmd_str, "gettotsc") == 0) || (sal_strcasecmp(cmd_str, "settotsc") == 0)) { 9321 if ((regname = ARG_GET(args)) == NULL) { 9322 cli_out("Specify Address\n"); 9323 return CMD_FAIL; 9324 } 9325 if (!isint(regname)) { 9326 cli_out("To-TSC Symbolic Name Not Implemented. Give Address\n"); 9327 return CMD_FAIL; 9328 } 9329 mt2_addr = sal_ctoi(regname, 0); 9330 if (sal_strcasecmp(cmd_str, "settotsc") == 0) { /* Set To-Tsc Reg */ 9331 if ((regval = ARG_GET(args)) == NULL) { 9332 cli_out ("Specify Value to Write\n"); 9333 return CMD_FAIL; 9334 } 9335 tem = 0; 9336 parse_table_init(unit, &pt); 9337 parse_table_add(&pt, "Mask", PQ_DFL | PQ_INT, 0, &tem, 0); 9338 if (parse_arg_eq(args, &pt) < 0) { 9339 /* No Arguments. Mask is 0 */ 9340 } 9341 parse_arg_eq_done(&pt); 9342 mt2_data[0] = sal_ctoi(regval, 0) << 16; 9343 mt2_data[0] |= (tem & 0xffff); 9344 9345 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9346 phy_addr = port_to_phyaddr(unit,p); 9347 mt2_sbus_to_tsc_write(unit, phy_addr, mt2_addr, mt2_data); 9348 cli_out("Writing 0x%08x to to_tsc reg 0x%08x at phy addr 0x%02x\n", mt2_data[0], mt2_addr, phy_addr); 9349 } 9350 } else { /* Set To-Tsc Reg */ 9351 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9352 phy_addr = port_to_phyaddr(unit,p); 9353 mt2_sbus_to_tsc_read(unit, phy_addr, mt2_addr, mt2_data); 9354 cli_out("Reading to_tsc reg 0x%08x at phy addr 0x%02x = 0x%08x\n", mt2_addr, phy_addr, mt2_data[0]); 9355 } 9356 } 9357 9358 return CMD_OK; 9359 } else if ((sal_strcasecmp(cmd_str, "testrun") == 0) || (sal_strcasecmp(cmd_str, "tr") == 0)) { 9360 if ((regname = ARG_GET(args)) == NULL) { 9361 cli_out ("Specify Test Number\n"); 9362 return CMD_FAIL; 9363 } 9364 i = 0; 9365 if (sal_strcasecmp(regname, "-s") == 0) { 9366 i = 1; /* Silent / Summary Only */ 9367 if ((regname = ARG_GET(args)) == NULL) { 9368 cli_out ("Specify Test Number\n"); 9369 return CMD_FAIL; 9370 } 9371 } 9372 testno = sal_ctoi(regname, 0); 9373 9374 /* PORT_LOCK(unit); */ 9375 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9376 phy_addr = port_to_phyaddr(unit,p); 9377 mt2_test_run(unit, phy_addr, testno, i); 9378 } 9379 } else if (sal_strcasecmp(cmd_str, "ether") == 0) { 9380 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9381 if (phy8806x_xmod_debug_cmd(unit, p) == SOC_E_UNAVAIL) 9382 bsl_printf("Command not supported in FC mode \n"); 9383 } 9384 /* PORT_UNLOCK(unit); */ 9385 #if defined(INCLUDE_FCMAP) 9386 } else if (sal_strcasecmp(cmd_str, "fc") == 0) { 9387 if ((fc_oper = ARG_GET(args)) == NULL) { 9388 cli_out ("Specify FC operation..\n"); 9389 return CMD_FAIL; 9390 } 9391 9392 if (sal_strcasecmp(fc_oper, "dmpstat") == 0) { 9393 cmd = 0x5; 9394 } 9395 9396 if (sal_strcasecmp(fc_oper, "clrstat") == 0) { 9397 cmd = 0x6; 9398 } 9399 9400 if (sal_strcasecmp(fc_oper, "dmpdbg") == 0) { 9401 cmd = 0x7; 9402 } 9403 9404 if (sal_strcasecmp(fc_oper, "disable") == 0) { 9405 cmd = 0x8; 9406 } 9407 9408 if (sal_strcasecmp(fc_oper, "syslnk") == 0) { 9409 cmd = 0x9; 9410 } 9411 if (sal_strcasecmp(fc_oper, "admn") == 0) { 9412 cmd = 0xa; 9413 } 9414 if (sal_strcasecmp(fc_oper, "clkvld") == 0) { 9415 cmd = 0xb; 9416 } 9417 if (sal_strcasecmp(fc_oper, "speed") == 0) { 9418 cmd = 0x4; 9419 } 9420 9421 if (sal_strcasecmp(fc_oper, "showcfg") == 0) { 9422 show = 0x1; 9423 } 9424 9425 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9426 if (show == 0x1) { 9427 cli_out("FC CFG for port %d\n", p); 9428 bfcmap88060_show_fc_config(unit, p); 9429 } else { 9430 cli_out("FC OPER: u 0x%x, p 0x%x, oper %s cmd 0x%x\n", unit, p, fc_oper, cmd); 9431 bfcmap88060_xmod_debug_cmd(unit, p, cmd); 9432 } 9433 } 9434 #endif 9435 } else if (sal_strcasecmp(cmd_str, "diag") == 0) { 9436 if ((cmd_str = ARG_GET(args)) == NULL) { 9437 cli_out ("Specify Diag Command\n"); 9438 return CMD_FAIL; 9439 } 9440 regname = ARG_GET(args); /* recycle regname for Optional Parameter */ 9441 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9442 pc = EXT_PHY_SW_STATE(unit, p); 9443 if ((pc == NULL) || (phy_is_8806x(pc) != SOC_E_NONE)) { 9444 continue; 9445 } 9446 phy_addr = port_to_phyaddr(unit,p); 9447 mt2_diag_run(unit, phy_addr, cmd_str, regname); 9448 } 9449 } else if (sal_strcasecmp(cmd_str, "uart") == 0) { 9450 void *buffer, *buf; 9451 char *fn = NULL, file_name[81]; 9452 unsigned char *cbuf; 9453 parse_table_t pt; 9454 int lscan_time; 9455 unsigned int buf_size = 4096; /* NULL termination taken care of internally */ 9456 9457 parse_table_init(unit, &pt); 9458 parse_table_add(&pt, "File", PQ_STRING, 0, &fn, NULL); 9459 parse_table_add(&pt, "BufSize", PQ_DFL | PQ_INT, 0, &buf_size, 0); 9460 9461 if (parse_arg_eq(args, &pt) < 0) { 9462 cli_out("Dumping to the screen: %s\n", ARG_CUR(args)); 9463 file_name[0] = 0; 9464 } else { 9465 sal_strncpy(file_name, fn, 80); 9466 } 9467 parse_arg_eq_done(&pt); 9468 9469 buffer = (void*) sal_alloc(buf_size, "mt2 uart buffer"); 9470 9471 if (buffer == NULL) { 9472 cli_out("Insufficient memory.\n"); 9473 return CMD_FAIL; 9474 } 9475 /* rounding up to the next 4 byte boundary */ 9476 buf = UINTPTR_TO_PTR(((PTR_TO_UINTPTR(buffer) + 0x3) & ~0x3)); 9477 9478 cbuf = (unsigned char *) buf; 9479 buf_size -= (PTR_TO_UINTPTR(buffer) & 0x3) + 4; 9480 cbuf[0] = buf_size & 0xff; 9481 cbuf[1] = (buf_size >> 8) & 0xff; 9482 cbuf[2] = (buf_size >> 16) & 0xff; 9483 cbuf[3] = (buf_size >> 24) & 0xff; 9484 buf = UINTPTR_TO_PTR(PTR_TO_UINTPTR(buf) + 0x4); 9485 9486 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_get(unit, &lscan_time)); 9487 if (lscan_time != 0) { 9488 cli_out("Stopping Linkscan.\n"); 9489 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0)); 9490 /* Give enough time for linkscan task to exit. */ 9491 sal_usleep(lscan_time * 2); 9492 } 9493 9494 { 9495 #ifndef NO_FILEIO 9496 FILE *ofp = NULL; 9497 if ((ofp = sal_fopen(file_name, "w")) != NULL) { 9498 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9499 sal_fprintf(ofp, "-------------- Start Port %s --------------\n", SOC_PORT_NAME(unit, p)); 9500 do { 9501 if (port_diag_ctrl(unit, p, 0, 9502 PHY_DIAG_CTRL_GET, PHY_DIAG_CTRL_STATE_GENERIC, buf) == BCM_E_NONE) { 9503 sal_fprintf(ofp, "%s", (char*) buf); 9504 } else { 9505 sal_fprintf(ofp, "PHY_DIAG_CTRL_GET (PHY_DIAG_CTRL_STATE_GENERIC) failed for %s !.\n", SOC_PORT_NAME(unit, p)); 9506 cli_out("PHY_DIAG_CTRL_GET (PHY_DIAG_CTRL_STATE_GENERIC) failed for %s !.\n", SOC_PORT_NAME(unit, p)); 9507 break; 9508 } 9509 /* cli_out("available_size =%d sal_strlen = %d\n", buf_size, sal_strlen((char*) buf)); */ 9510 } while (sal_strlen((char*) buf) >= (buf_size - 8)); /* full buffer returned */ 9511 sal_fprintf(ofp, "\n-------------- End Port %s ----------------\n", SOC_PORT_NAME(unit, p)); 9512 } 9513 sal_fclose(ofp); 9514 } else 9515 #endif 9516 { 9517 DPORT_SOC_PBMP_ITER(unit, pbm, dport, p) { 9518 cli_out("-------------- Start Port %s --------------\n", SOC_PORT_NAME(unit, p)); 9519 do { 9520 if (port_diag_ctrl(unit, p, 0, 9521 PHY_DIAG_CTRL_GET, PHY_DIAG_CTRL_STATE_GENERIC, buf) == BCM_E_NONE) { 9522 cli_out("%s", (char*) buf); 9523 } else { 9524 cli_out("PHY_DIAG_CTRL_GET (PHY_DIAG_CTRL_STATE_GENERIC) failed for %s !.\n", SOC_PORT_NAME(unit, p)); 9525 break; 9526 } 9527 /* cli_out("available_size =%d sal_strlen = %d\n", buf_size, sal_strlen((char*) buf)); */ 9528 } while (sal_strlen((char*) buf) >= (buf_size - 8)); /* full buffer returned */ 9529 cli_out("\n-------------- End Port %s ----------------\n", SOC_PORT_NAME(unit, p)); 9530 } 9531 } 9532 } 9533 if (lscan_time != 0) { 9534 cli_out("Restarting Linkscan.\n"); 9535 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, lscan_time)); 9536 } 9537 sal_free(buffer); 9538 } else { 9539 cli_out ("Unknown Operation : %s\n", cmd_str); 9540 return CMD_FAIL; 9541 } 9542 9543 return CMD_OK; 9544 } 9545 #endif /* defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X) */ 9546 9547 /* 9548 * Function: if_phy 9549 * Purpose: Show/configure phy registers. 9550 * Parameters: u - SOC unit # 9551 * a - pointer to args 9552 * Returns: CMD_OK/CMD_FAIL/ 9553 */ 9554 cmd_result_t if_esw_phy(int u, args_t *a) 9555 { 9556 soc_pbmp_t pbm, pbm_phys, pbm_temp; 9557 soc_port_t p, dport; 9558 char *c, drv_name[64]; 9559 uint16 phy_data, phy_devad = 0; 9560 uint16 phy_addr; 9561 uint32 phy_reg; 9562 uint32 phy_data32; 9563 int int_ovrride; /* Set if no external PHY is present */ 9564 int intermediate = 0; 9565 int is_c45 = 0; 9566 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 9567 int is_rcpu = 0; 9568 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 9569 int rv = 0; 9570 char pfmt[SOC_PBMP_FMT_LEN]; 9571 int i; 9572 int p_devad[] = { PHY_C45_DEV_PMA_PMD, 9573 PHY_C45_DEV_WIS, 9574 PHY_C45_DEV_PCS, 9575 PHY_C45_DEV_PHYXS, 9576 PHY_C45_DEV_DTEXS, 9577 PHY_C45_DEV_AN, 9578 PHY_C45_DEV_USER 9579 }; 9580 char *p_devad_str[] = { "DEV_PMA_PMD", 9581 "DEV_WIS", 9582 "DEV_PCS", 9583 "DEV_PHYXS", 9584 "DEV_DTEXS", 9585 "DEV_AN", 9586 "DEV_USER" 9587 }; 9588 #ifdef PORTMOD_SUPPORT 9589 int nof_phys =0; 9590 #endif 9591 9592 if (!sh_check_attached(ARG_CMD(a), u)) { 9593 return CMD_FAIL; 9594 } 9595 9596 c = ARG_GET(a); 9597 9598 if (c != NULL && sal_strcasecmp(c, "info") == 0) { 9599 return _if_esw_phy_info(u, a); 9600 } 9601 9602 #if defined(PHYMOD_SUPPORT) 9603 if (c != NULL && sal_strcasecmp(c, "phymod") == 0) { 9604 return _if_esw_phy_phymod(u, a); 9605 } 9606 #endif /* defined(PHYMOD_SUPPORT) */ 9607 9608 if (c != NULL && sal_strcasecmp(c, "eee") == 0) { 9609 return _if_esw_phy_eee(u, a); 9610 } 9611 9612 #ifdef INCLUDE_TIMESYNC_DVT_TESTS /* test IEEE1588 TimeSync */ 9613 if (c != NULL && sal_strncasecmp(c, "tst", 3) == 0) { 9614 return phy_test1588(u, a, &pbm); 9615 } 9616 #endif 9617 9618 if ( c != NULL && 9619 ((sal_strcasecmp(c, "TS") == 0) || 9620 (sal_strcasecmp(c, "TimeSync") == 0)) ) { 9621 return _if_esw_phy_timesync(u, a); 9622 } 9623 9624 #ifdef INCLUDE_PHY_SYM_DBG 9625 if (c != NULL && sal_strcasecmp(c, "SymDebug") == 0) { 9626 return _if_esw_phy_symdebug(u, a); 9627 } 9628 9629 if (c != NULL && sal_strcasecmp(c, "SymDebugOff") == 0) { 9630 return _if_esw_phy_symdebug_off(u, a); 9631 } 9632 #endif 9633 9634 if (c != NULL && sal_strcasecmp(c, "firmware") == 0) { 9635 return _if_esw_phy_firmware(u, a); 9636 } 9637 9638 if (c != NULL && sal_strcasecmp(c, "oam") == 0) { 9639 return _if_esw_phy_oam(u, a); 9640 } 9641 9642 if (c != NULL && sal_strcasecmp(c, "power") == 0) { 9643 return _if_esw_phy_power(u, a); 9644 } 9645 9646 if (c != NULL && sal_strcasecmp(c, "margin") == 0) { 9647 return _if_esw_phy_margin(u, a); 9648 } 9649 9650 if (c != NULL && sal_strcasecmp(c, "prbs") == 0) { 9651 return _if_esw_phy_prbs(u, a); 9652 } 9653 9654 if (c != NULL && sal_strcasecmp(c, "diag") == 0) { 9655 return _if_esw_phy_diag(u, a); 9656 } 9657 9658 if (c != NULL && sal_strcasecmp(c, "longreach") == 0) { 9659 return _if_esw_phy_longreach(u, a); 9660 } 9661 9662 if (c != NULL && sal_strcasecmp(c, "extlb") == 0) { 9663 return _if_esw_phy_extlb(u, a); 9664 } 9665 9666 if (c != NULL && sal_strcasecmp(c, "clock") == 0) { 9667 return _if_esw_phy_clock(u, a); 9668 } 9669 9670 if (c != NULL && sal_strcasecmp(c, "wr") == 0) { 9671 return _if_esw_phy_wr(u, a); 9672 } 9673 9674 if (c != NULL && sal_strcasecmp(c, "rd_cp") == 0) { 9675 return _if_esw_phy_rd_cp(u, a); 9676 } 9677 9678 if (c != NULL && sal_strcasecmp(c, "rd_cp2") == 0) { 9679 return _if_esw_phy_rd_cp2(u, a); 9680 } 9681 9682 if (c != NULL && sal_strcasecmp(c, "mod") == 0) { 9683 return _if_esw_phy_mod(u, a); 9684 } 9685 9686 if (c != NULL && sal_strcasecmp(c, "control") == 0) { 9687 return _if_esw_phy_control(u, a); 9688 } 9689 9690 /* All access to an MII register */ 9691 if (c != NULL && sal_strcasecmp(c, "dumpall") == 0) { 9692 return _if_esw_phy_dumpall(u, a); 9693 } 9694 9695 /* Raw access to an MII register */ 9696 if (c != NULL && sal_strcasecmp(c, "raw") == 0) { 9697 return _if_esw_phy_raw(u, a); 9698 } 9699 9700 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 9701 if (c != NULL && sal_strcasecmp(c, "rcpu") == 0) { 9702 is_rcpu = 1; 9703 c = ARG_GET(a); 9704 } 9705 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 9706 9707 if (c != NULL && sal_strcasecmp(c, "int") == 0) { 9708 intermediate = 1; 9709 c = ARG_GET(a); 9710 } 9711 9712 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X) 9713 if (c != NULL && sal_strcasecmp(c, "mt2") == 0) { 9714 return _phy_mt2(u, a); 9715 } 9716 #endif /* defined(BCM_ESW_SUPPORT) && defined(INCLUDE_PHY_8806X) */ 9717 9718 9719 if (c == NULL) { 9720 return (CMD_USAGE); 9721 } 9722 9723 /* Parse the bitmap. */ 9724 if (parse_pbmp(u, c, &pbm) < 0) { 9725 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 9726 return CMD_FAIL; 9727 } 9728 9729 SOC_PBMP_ASSIGN(pbm_phys, pbm); 9730 SOC_PBMP_AND(pbm_phys, PBMP_PORT_ALL(u)); 9731 if (SOC_PBMP_IS_NULL(pbm_phys)) { 9732 cli_out("Ports specified do not have PHY drivers.\n"); 9733 } else { 9734 SOC_PBMP_ASSIGN(pbm_temp, pbm); 9735 SOC_PBMP_REMOVE(pbm_temp, PBMP_PORT_ALL(u)); 9736 if (SOC_PBMP_NOT_NULL(pbm_temp)) { 9737 cli_out("Not all ports given have PHY drivers. Using %s\n", 9738 SOC_PBMP_FMT(pbm_phys, pfmt)); 9739 } 9740 } 9741 SOC_PBMP_ASSIGN(pbm, pbm_phys); 9742 9743 if (ARG_CNT(a) == 0) { /* show information for all registers */ 9744 #if defined(BCM_TOMAHAWK3_SUPPORT) 9745 if (SOC_IS_TOMAHAWK3(u)) { 9746 cli_out("Tomahawk 3 does not support MDIO. Please use phy <pbm> *\n\n\n"); 9747 return (CMD_USAGE); 9748 } 9749 9750 #endif 9751 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 9752 phy_addr = (intermediate ? 9753 port_to_phyaddr_int(u, p) : port_to_phyaddr(u, p)); 9754 int_ovrride = (EXT_PHY_SW_STATE(u, p) == NULL) ? 1 : 0; 9755 if (phy_addr == 0xff) { 9756 cli_out("Port %s: No %sPHY address assigned\n", 9757 SOC_PORT_NAME(u, p), 9758 intermediate ? "intermediate " : ""); 9759 continue; 9760 } 9761 #ifdef PORTMOD_SUPPORT 9762 if (soc_feature(u, soc_feature_portmod)) { 9763 portmod_port_num_phys_get(u, p, &nof_phys); 9764 int_ovrride = 0; 9765 if (nof_phys == 1) { 9766 is_c45 = 0; 9767 } else { 9768 is_c45 = portmod_port_flags_test(u, p, PHY_FLAGS_C45); 9769 } 9770 } else 9771 #endif 9772 { 9773 is_c45 = soc_phy_is_c45_miim(u, p); 9774 } 9775 9776 if (intermediate) { 9777 cli_out("Port %s (intermediate PHY addr 0x%02x):", 9778 SOC_PORT_NAME(u, p), phy_addr); 9779 } else { 9780 int ap = p; 9781 char lnstr[32]; 9782 9783 #ifdef PORTMOD_SUPPORT 9784 if(soc_feature(u, soc_feature_portmod)) { 9785 phymod_core_access_t core_acc; 9786 phymod_core_info_t core_info; 9787 int nof_cores = 0; 9788 int phy = 0, core_num = 0, is_legacy =0; 9789 int range_start = 0; 9790 int is_first_range; 9791 portmod_port_diag_info_t diag_info; 9792 int diag_rv; 9793 uint8 pcount=0; 9794 char *pname, namelen; 9795 9796 phymod_core_access_t_init(&core_acc); 9797 phymod_core_info_t_init(&core_info); 9798 sal_memset(&diag_info, 0, sizeof(portmod_port_diag_info_t)); 9799 9800 portmod_port_main_core_access_get(u, p, -1, &core_acc, &nof_cores); 9801 if(nof_cores == 0) { 9802 continue; 9803 } 9804 /* check if the phy is a legacy phy */ 9805 diag_rv = portmod_port_check_legacy_phy(u, p, &is_legacy); 9806 if (diag_rv) { 9807 continue; 9808 } 9809 if ( !is_legacy ) { 9810 diag_rv = portmod_port_diag_info_get(u, p, &diag_info); 9811 if(diag_rv){ 9812 continue; 9813 } 9814 9815 diag_rv = portmod_port_core_num_get(u, p, &core_num); 9816 if (diag_rv){ 9817 continue; 9818 } 9819 9820 is_first_range = TRUE; 9821 BCM_PBMP_ITER(diag_info.phys, phy){ 9822 if( is_first_range ){ 9823 range_start = phy ; 9824 is_first_range = FALSE; 9825 } 9826 } 9827 9828 SOC_IF_ERROR_RETURN 9829 (phymod_core_info_get(&core_acc, &core_info)); 9830 9831 SOC_PBMP_COUNT(diag_info.phys, pcount); 9832 9833 pname = phymod_core_version_t_mapping[core_info.core_version].key; 9834 namelen = strlen(pname); 9835 9836 sal_snprintf(lnstr, sizeof(lnstr), "%s", pname); 9837 sal_snprintf(lnstr+namelen-2, sizeof(lnstr)-(namelen-2), "-%s/%02d/", pname+namelen-2, core_num); 9838 9839 pname = lnstr; 9840 while (*pname != '-') { 9841 *pname = sal_toupper(*pname); 9842 pname++; 9843 } 9844 9845 pname = lnstr+strlen(lnstr); 9846 if (pcount == 4) 9847 sal_snprintf(pname,sizeof(lnstr), "%d", pcount); 9848 else if (pcount == 2) 9849 sal_snprintf(pname,sizeof(lnstr), "%d-%d", (range_start-1)%4, ((range_start-1)%4)+1); 9850 else 9851 sal_snprintf(pname,sizeof(lnstr), "%d", (range_start-1)%4); 9852 }else { 9853 sal_snprintf(lnstr, sizeof(lnstr), "%s", soc_phy_name_get(u, p)); 9854 } 9855 }else 9856 #endif 9857 { 9858 sal_snprintf(lnstr, sizeof(lnstr), "%s", soc_phy_name_get(u, p)); 9859 } 9860 9861 BCM_API_XLATE_PORT_P2A(u, &ap); /* Use BCM API port */ 9862 BCM_IF_ERROR_RETURN(bcm_port_phy_drv_name_get 9863 (u, ap, drv_name, 64)); 9864 cli_out("Port %s (PHY addr 0x%02x): %s (%s)", 9865 (SOC_PORT_VALID_RANGE(u, p) ? SOC_PORT_NAME(u, p):"unknown"), 9866 phy_addr, lnstr, 9867 drv_name); 9868 } 9869 if (is_c45 && !intermediate && !int_ovrride) { 9870 for (i = 0; i < COUNTOF(p_devad); i++) { 9871 phy_devad = p_devad[i]; 9872 cli_out("\nDevAd = %d(%s)", phy_devad, p_devad_str[i]); 9873 for (phy_reg = PHY_MIN_REG; phy_reg <= PHY_MAX_REG; 9874 phy_reg++) { 9875 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 9876 if (1 == is_rcpu) { 9877 rv = soc_rcpu_miimc45_read(u, phy_addr, 9878 phy_devad, phy_reg, 9879 &phy_data); 9880 } else 9881 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 9882 if (EXT_PHY_SW_STATE(u, p) && 9883 (EXT_PHY_SW_STATE(u, p)->read)) { 9884 rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr, 9885 BCM_PORT_PHY_CLAUSE45_ADDR 9886 (phy_devad, 9887 phy_reg), 9888 &phy_data); 9889 } else if(soc_feature(u, soc_feature_portmod)) { 9890 rv = soc_miimc45_read(u, phy_addr, 9891 phy_devad, phy_reg, 9892 &phy_data); 9893 } else { 9894 rv = soc_miimc45_read(u, phy_addr, 9895 phy_devad, phy_reg, 9896 &phy_data); 9897 } 9898 9899 if (rv < 0) { 9900 cli_out("\nERROR: Port %s: " 9901 "soc_miim_read failed: %s\n", 9902 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 9903 return CMD_FAIL; 9904 } 9905 cli_out("%s\t0x%04x: 0x%04x", 9906 ((phy_reg % DUMP_PHY_COLS) == 0) ? "\n" : "", 9907 phy_reg, phy_data); 9908 } 9909 } 9910 } else { 9911 for (phy_reg = PHY_MIN_REG; phy_reg <= PHY_MAX_REG; phy_reg++) { 9912 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 9913 if (1 == is_rcpu) { 9914 rv = soc_rcpu_miim_read(u, phy_addr, phy_reg, 9915 &phy_data); 9916 } else 9917 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 9918 if (!intermediate && !int_ovrride) { 9919 if (EXT_PHY_SW_STATE(u, p) && 9920 (EXT_PHY_SW_STATE(u, p)->read)) { 9921 rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr, 9922 phy_reg, 9923 &phy_data); 9924 } else if(soc_feature(u, soc_feature_portmod)) { 9925 rv = soc_sbus_mdio_read(u, phy_addr, phy_reg, &phy_data32); 9926 phy_data = (uint16)phy_data32; 9927 } else { 9928 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data); 9929 } 9930 } else { 9931 if (INT_PHY_SW_STATE(u, p) && 9932 (INT_PHY_SW_STATE(u, p)->read)) { 9933 rv = INT_PHY_SW_STATE(u, p)->read(u, phy_addr, 9934 phy_reg, 9935 &phy_data); 9936 } else if(soc_feature(u, soc_feature_portmod)) { 9937 rv = soc_sbus_mdio_read(u, phy_addr, phy_reg, &phy_data32); 9938 phy_data = (uint16)phy_data32; 9939 } else { 9940 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data); 9941 } 9942 } 9943 if (rv < 0) { 9944 cli_out("\nERROR: Port %s: soc_miim_read failed: %s\n", 9945 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 9946 return CMD_FAIL; 9947 } 9948 cli_out("%s\t0x%02x: 0x%04x", 9949 ((phy_reg % DUMP_PHY_COLS) == 0) ? "\n" : "", 9950 phy_reg, phy_data); 9951 } 9952 } 9953 cli_out("\n"); 9954 } 9955 } else { /* get register argument */ 9956 9957 #if defined(PHYMOD_SUPPORT) 9958 if (!isint(ARG_CUR(a))) { 9959 return phymod_sym_access(u, a, intermediate, &pbm); 9960 } 9961 #endif /* defined(PHYMOD_SUPPORT) */ 9962 9963 c = ARG_GET(a); 9964 phy_reg = sal_ctoi(c, 0); 9965 9966 if (ARG_CNT(a) == 0) { /* no more args; show this register */ 9967 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 9968 phy_addr = (intermediate ? 9969 port_to_phyaddr_int(u, p) : port_to_phyaddr(u, p)); 9970 int_ovrride = (EXT_PHY_SW_STATE(u, p) == NULL) ? 1 : 0; 9971 if (phy_addr == 0xff) { 9972 cli_out("Port %s: No %sPHY address assigned\n", 9973 SOC_PORT_NAME(u, p), 9974 intermediate ? "intermediate " : ""); 9975 continue; 9976 } 9977 #ifdef PORTMOD_SUPPORT 9978 if (soc_feature(u, soc_feature_portmod)) { 9979 portmod_port_num_phys_get(u, p, &nof_phys); 9980 int_ovrride = 0; 9981 if (nof_phys == 1) { 9982 is_c45 = 0; 9983 } else { 9984 is_c45 = portmod_port_flags_test(u, p, PHY_FLAGS_C45); 9985 } 9986 } else 9987 #endif 9988 { 9989 is_c45 = soc_phy_is_c45_miim(u, p); 9990 } 9991 if ( is_c45 && !intermediate && !int_ovrride) { 9992 for (i = 0; i < COUNTOF(p_devad); i++) { 9993 phy_devad = p_devad[i]; 9994 cli_out("Port %s (PHY addr 0x%02x) " 9995 "DevAd %d(%s) Reg 0x%04x: ", 9996 SOC_PORT_NAME(u, p), phy_addr, phy_devad, 9997 p_devad_str[i], phy_reg); 9998 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 9999 if (1 == is_rcpu) { 10000 rv = soc_rcpu_miimc45_read(u, phy_addr, 10001 phy_devad, phy_reg, 10002 &phy_data); 10003 } else 10004 #endif /* defined(BCM_RCPU_SUPPORT) && 10005 defined(BCM_CMICM_SUPPORT) */ 10006 if (EXT_PHY_SW_STATE(u, p) && 10007 (EXT_PHY_SW_STATE(u, p)->read)) { 10008 rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr, 10009 BCM_PORT_PHY_CLAUSE45_ADDR 10010 (phy_devad, 10011 phy_reg), 10012 &phy_data); 10013 } else if(soc_feature(u, soc_feature_portmod)) { 10014 rv = soc_miimc45_read(u, phy_addr,phy_devad, phy_reg, &phy_data); 10015 } else { 10016 rv = soc_miimc45_read(u, phy_addr, 10017 phy_devad, phy_reg, 10018 &phy_data); 10019 } 10020 10021 if (rv < 0) { 10022 cli_out("\nERROR: Port %s: " 10023 "soc_miim_read failed: %s\n", 10024 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 10025 return CMD_FAIL; 10026 } 10027 var_set_hex("phy_reg_data", phy_data, TRUE, FALSE); 10028 cli_out("0x%04x\n", phy_data); 10029 } 10030 } else { 10031 cli_out("Port %s (PHY addr 0x%02x) Reg 0x%04x: ", 10032 SOC_PORT_NAME(u, p), phy_addr, phy_reg); 10033 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 10034 if (1 == is_rcpu) { 10035 rv = soc_rcpu_miim_read(u, phy_addr, phy_reg, 10036 &phy_data); 10037 } else 10038 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 10039 if (!intermediate && !int_ovrride) { 10040 if (EXT_PHY_SW_STATE(u, p) && 10041 (EXT_PHY_SW_STATE(u, p)->read)) { 10042 rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr, 10043 phy_reg, 10044 &phy_data); 10045 } else if(soc_feature(u, soc_feature_portmod)) { 10046 #ifdef PORTMOD_SUPPORT 10047 rv = portmod_port_phy_reg_read(u,p, -1, 0,phy_reg,&phy_data32); 10048 phy_data = (uint16)phy_data32; 10049 #endif 10050 } else { 10051 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data); 10052 } 10053 } else { 10054 if (INT_PHY_SW_STATE(u, p) && 10055 (INT_PHY_SW_STATE(u, p)->read)) { 10056 rv = INT_PHY_SW_STATE(u, p)->read(u, phy_addr, 10057 phy_reg, 10058 &phy_data); 10059 } else if(soc_feature(u, soc_feature_portmod)) { 10060 #ifdef PORTMOD_SUPPORT 10061 rv = portmod_port_phy_reg_read(u,p, -1, 0,phy_reg,&phy_data32); 10062 phy_data = (uint16)phy_data32; 10063 #endif 10064 } else { 10065 rv = soc_miim_read(u, phy_addr, phy_reg, &phy_data); 10066 } 10067 } 10068 10069 if (rv < 0) { 10070 cli_out("\nERROR: Port %s: soc_miim_read failed: %s\n", 10071 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 10072 return CMD_FAIL; 10073 } 10074 var_set_hex("phy_reg_data", phy_data, TRUE, FALSE); 10075 cli_out("0x%04x\n", phy_data); 10076 } 10077 } 10078 } else { /* set the reg to given value for the indicated phys */ 10079 c = ARG_GET(a); 10080 phy_data = phy_devad = sal_ctoi(c, 0); 10081 10082 DPORT_SOC_PBMP_ITER(u, pbm, dport, p) { 10083 phy_addr = (intermediate ? 10084 port_to_phyaddr_int(u, p) : port_to_phyaddr(u, p)); 10085 int_ovrride = (EXT_PHY_SW_STATE(u, p) == NULL) ? 1 : 0; 10086 if (phy_addr == 0xff) { 10087 cli_out("Port %s: No %sPHY address assigned\n", 10088 SOC_PORT_NAME(u, p), 10089 intermediate ? "intermediate " : ""); 10090 return CMD_FAIL; 10091 } 10092 #ifdef PORTMOD_SUPPORT 10093 if (soc_feature(u, soc_feature_portmod)) { 10094 portmod_port_num_phys_get(u, p, &nof_phys); 10095 int_ovrride = 0; 10096 if (nof_phys == 1) { 10097 is_c45 = 0; 10098 } else { 10099 is_c45 = portmod_port_flags_test(u, p, PHY_FLAGS_C45); 10100 } 10101 } else 10102 #endif 10103 { 10104 is_c45 = soc_phy_is_c45_miim(u, p); 10105 } 10106 if ( is_c45 && !intermediate && !int_ovrride) { 10107 for (i = 0; i < COUNTOF(p_devad); i++) { 10108 if (phy_devad == p_devad[i]) { 10109 break; 10110 } 10111 } 10112 if (i >= COUNTOF(p_devad)) { 10113 cli_out("\nERROR: Port %s: Invalid DevAd %d\n", 10114 SOC_PORT_NAME(u, p), phy_devad); 10115 return CMD_FAIL; 10116 } 10117 if (ARG_CNT(a) == 0) {/* no more args; show this register */ 10118 cli_out("Port %s (PHY addr 0x%02x) " 10119 "DevAd %d(%s) Reg 0x%04x: ", 10120 SOC_PORT_NAME(u, p), phy_addr, phy_devad, 10121 p_devad_str[i], phy_reg); 10122 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 10123 if (1 == is_rcpu) { 10124 rv = soc_rcpu_miimc45_read(u, phy_addr, 10125 phy_devad, phy_reg, 10126 &phy_data); 10127 } else 10128 #endif /* defined(BCM_RCPU_SUPPORT) && 10129 defined(BCM_CMICM_SUPPORT) */ 10130 if (EXT_PHY_SW_STATE(u, p) && 10131 (EXT_PHY_SW_STATE(u, p)->read)) { 10132 rv = EXT_PHY_SW_STATE(u, p)->read(u, phy_addr, 10133 BCM_PORT_PHY_CLAUSE45_ADDR 10134 (phy_devad, 10135 phy_reg), 10136 &phy_data); 10137 } else if(soc_feature(u, soc_feature_portmod)) { 10138 rv = soc_miimc45_read(u, phy_addr, 10139 phy_devad, phy_reg, 10140 &phy_data); 10141 10142 } else { 10143 rv = soc_miimc45_read(u, phy_addr, 10144 phy_devad, phy_reg, 10145 &phy_data); 10146 } 10147 10148 if (rv < 0) { 10149 cli_out("\nERROR: Port %s: " 10150 "soc_miim_read failed: %s\n", 10151 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 10152 return CMD_FAIL; 10153 } 10154 var_set_hex("phy_reg_data", phy_data, TRUE, FALSE); 10155 cli_out("0x%04x\n", phy_data); 10156 } else { /* write */ 10157 c = ARG_GET(a); 10158 phy_data = sal_ctoi(c, 0); 10159 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 10160 if (1 == is_rcpu) { 10161 rv = soc_rcpu_miimc45_write(u, phy_addr, 10162 phy_devad, phy_reg, 10163 phy_data); 10164 } else 10165 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 10166 if (EXT_PHY_SW_STATE(u, p) && 10167 (EXT_PHY_SW_STATE(u, p)->write)) { 10168 rv = EXT_PHY_SW_STATE(u, p)->write(u, phy_addr, 10169 BCM_PORT_PHY_CLAUSE45_ADDR 10170 (phy_devad, 10171 phy_reg), 10172 phy_data); 10173 } else if(soc_feature(u, soc_feature_portmod)) { 10174 #ifdef PORTMOD_SUPPORT 10175 portmod_port_num_phys_get(u, p, &nof_phys); 10176 if(nof_phys > 1 ){ 10177 rv = soc_miimc45_write(u, phy_addr, 10178 phy_devad, phy_reg, 10179 phy_data); 10180 } else 10181 #endif 10182 { 10183 rv = soc_sbus_mdio_write(u, phy_addr, phy_reg, phy_data); 10184 } 10185 } else { 10186 rv = soc_miimc45_write(u, phy_addr, 10187 phy_devad, phy_reg, 10188 phy_data); 10189 } 10190 10191 if (rv < 0) { 10192 cli_out("ERROR: Port %s: " 10193 "soc_miim_write failed: %s\n", 10194 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 10195 return CMD_FAIL; 10196 } 10197 } 10198 } else { 10199 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) 10200 if (1 == is_rcpu) { 10201 rv = soc_rcpu_miim_write(u, phy_addr, phy_reg, 10202 phy_data); 10203 } else 10204 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */ 10205 if (!intermediate && !int_ovrride) { 10206 if (EXT_PHY_SW_STATE(u, p) && 10207 (EXT_PHY_SW_STATE(u, p)->write)) { 10208 rv = EXT_PHY_SW_STATE(u, p)->write(u, phy_addr, 10209 phy_reg, 10210 phy_data); 10211 } else if(soc_feature(u, soc_feature_portmod)) { 10212 #ifdef PORTMOD_SUPPORT 10213 portmod_port_num_phys_get(u, p, &nof_phys); 10214 if(nof_phys > 1 ){ 10215 rv = soc_miimc45_write(u, phy_addr, 10216 phy_devad, phy_reg, 10217 phy_data); 10218 } else { 10219 rv = portmod_port_phy_reg_write(u, p, -1, 0, phy_reg, phy_data); 10220 } 10221 #endif 10222 } else { 10223 rv = soc_miim_write(u, phy_addr, phy_reg, phy_data); 10224 } 10225 } else { 10226 if (INT_PHY_SW_STATE(u, p) && 10227 (INT_PHY_SW_STATE(u, p)->write)) { 10228 rv = INT_PHY_SW_STATE(u, p)->write(u, phy_addr, 10229 phy_reg, 10230 phy_data); 10231 } else if(soc_feature(u, soc_feature_portmod)) { 10232 #ifdef PORTMOD_SUPPORT 10233 rv = portmod_port_phy_reg_write(u, p, -1, 0, phy_reg, phy_data); 10234 #endif 10235 } else { 10236 rv = soc_miim_write(u, phy_addr, phy_reg, phy_data); 10237 } 10238 } 10239 if (rv < 0) { 10240 cli_out("ERROR: Port %s: soc_miim_write failed: %s\n", 10241 SOC_PORT_NAME(u, p), soc_errmsg(rv)); 10242 return CMD_FAIL; 10243 } 10244 } 10245 } 10246 } 10247 } 10248 10249 if (BCM_FAILURE(rv)) { 10250 cli_out("%s\n", bcm_errmsg(rv)); 10251 return CMD_FAIL; 10252 } 10253 return CMD_OK; 10254 } 10255 10256 /*********************************************************************** 10257 * 10258 * Combo port support 10259 */ 10260 10261 /* 10262 * Function: if_combo_dump 10263 * Purpose: Dump the contents of a bcm_phy_config_t 10264 */ 10265 10266 STATIC int 10267 if_combo_dump(args_t *a, int u, int p, int medium) 10268 { 10269 char pm_str[80]; 10270 bcm_port_medium_t active_medium; 10271 int r; 10272 bcm_phy_config_t cfg; 10273 10274 /* 10275 * Get active medium so we can put an asterisk next to the status if 10276 * it is active. 10277 */ 10278 10279 if ((r = bcm_port_medium_get(u, p, &active_medium)) < 0) { 10280 return r; 10281 } 10282 if ((r = bcm_port_medium_config_get(u, p, medium, &cfg)) < 0) { 10283 return r; 10284 } 10285 10286 cli_out("%s:\t%s medium%s\n", 10287 BCM_PORT_NAME(u, p), 10288 MEDIUM_STATUS(medium), (medium == active_medium) ? " (active)" : ""); 10289 10290 format_port_mode(pm_str, sizeof(pm_str), cfg.autoneg_advert, TRUE); 10291 10292 cli_out("\tenable=%d preferred=%d " 10293 "force_speed=%d force_duplex=%d master=%s\n", 10294 cfg.enable, cfg.preferred, 10295 cfg.force_speed, cfg.force_duplex, PHYMASTER_MODE(cfg.master)); 10296 cli_out("\tautoneg_enable=%d autoneg_advert=%s(0x%x)\n", 10297 cfg.autoneg_enable, pm_str, cfg.autoneg_advert); 10298 cli_out("\tMDIX=%s\n", MDIX_MODE(cfg.mdix)); 10299 10300 return BCM_E_NONE; 10301 } 10302 10303 static int combo_watch[SOC_MAX_NUM_DEVICES][SOC_MAX_NUM_PORTS]; 10304 10305 static void 10306 if_combo_watch(int unit, bcm_port_t port, bcm_port_medium_t medium, void *arg) 10307 { 10308 cli_out("Unit %d: %s: Active medium switched to %s\n", 10309 unit, BCM_PORT_NAME(unit, port), MEDIUM_STATUS(medium)); 10310 10311 /* 10312 * Increment the number of medium changes. Remember, that we pass the 10313 * address of combo_watch[unit][port] when we register this callback 10314 */ 10315 (*((int *)arg))++; 10316 } 10317 10318 /* 10319 * Function: if_combo 10320 * Purpose: Control combo ports 10321 * Parameters: u - SOC unit # 10322 * a - pointer to args 10323 * Returns: CMD_OK/CMD_FAIL/ 10324 */ 10325 cmd_result_t 10326 if_esw_combo(int u, args_t *a) 10327 { 10328 pbmp_t pbm; 10329 soc_port_t p, dport; 10330 int specified_medium = BCM_PORT_MEDIUM_COUNT; 10331 int r, rc, rf; 10332 char *c; 10333 parse_table_t pt; 10334 bcm_phy_config_t cfg, cfg_opt; 10335 10336 enum if_combo_cmd_e { 10337 COMBO_CMD_DUMP, 10338 COMBO_CMD_SET, 10339 COMBO_CMD_WATCH, 10340 CONBO_CMD_COUNT 10341 } cmd; 10342 10343 enum if_combo_watch_arg_e { 10344 COMBO_CMD_WATCH_SHOW, 10345 COMBO_CMD_WATCH_ON, 10346 COMBO_CMD_WATCH_OFF, 10347 COMBO_CMD_WATCH_COUNT 10348 } watch_arg = COMBO_CMD_WATCH_SHOW; 10349 10350 cfg_opt.enable = -1; 10351 cfg_opt.preferred = -1; 10352 cfg_opt.autoneg_enable = -1; 10353 cfg_opt.autoneg_advert = 0xffffffff; 10354 cfg_opt.force_speed = -1; 10355 cfg_opt.force_duplex = -1; 10356 cfg_opt.master = -1; 10357 cfg_opt.mdix = -1; 10358 10359 if (!sh_check_attached(ARG_CMD(a), u)) { 10360 return CMD_FAIL; 10361 } 10362 10363 if ((c = ARG_GET(a)) == NULL) { 10364 return CMD_USAGE; 10365 } 10366 10367 if (parse_bcm_pbmp(u, c, &pbm) < 0) { 10368 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), c); 10369 return CMD_FAIL; 10370 } 10371 10372 SOC_PBMP_AND(pbm, PBMP_PORT_ALL(u)); 10373 10374 c = ARG_GET(a); /* NULL or media type or command */ 10375 10376 if (c == NULL) { 10377 cmd = COMBO_CMD_DUMP; 10378 specified_medium = BCM_PORT_MEDIUM_COUNT; 10379 } else if (sal_strcasecmp(c, "copper") == 0 || sal_strcasecmp(c, "c") == 0) { 10380 cmd = COMBO_CMD_SET; 10381 specified_medium = BCM_PORT_MEDIUM_COPPER; 10382 } else if (sal_strcasecmp(c, "fiber") == 0 || sal_strcasecmp(c, "f") == 0) { 10383 cmd = COMBO_CMD_SET; 10384 specified_medium = BCM_PORT_MEDIUM_FIBER; 10385 } else if (sal_strcasecmp(c, "watch") == 0 || sal_strcasecmp(c, "w") == 0) { 10386 cmd = COMBO_CMD_WATCH; 10387 } else { 10388 return CMD_USAGE; 10389 } 10390 10391 switch (cmd) { 10392 case COMBO_CMD_SET: 10393 if ((c = ARG_CUR(a)) != NULL) { 10394 if (c[0] == '=') { 10395 return CMD_USAGE; /* '=' unsupported */ 10396 } 10397 10398 parse_table_init(u, &pt); 10399 parse_table_add(&pt, "Enable", PQ_DFL | PQ_BOOL, 0, 10400 &cfg_opt.enable, 0); 10401 parse_table_add(&pt, "PREFerred", PQ_DFL | PQ_BOOL, 0, 10402 &cfg_opt.preferred, 0); 10403 parse_table_add(&pt, "Autoneg_Enable", PQ_DFL | PQ_BOOL, 0, 10404 &cfg_opt.autoneg_enable, 0); 10405 parse_table_add(&pt, "Autoneg_Advert", PQ_DFL | PQ_PORTMODE, 0, 10406 &cfg_opt.autoneg_advert, 0); 10407 parse_table_add(&pt, "Force_Speed", PQ_DFL | PQ_INT, 0, 10408 &cfg_opt.force_speed, 0); 10409 parse_table_add(&pt, "Force_Duplex", PQ_DFL | PQ_BOOL, 0, 10410 &cfg_opt.force_duplex, 0); 10411 parse_table_add(&pt, "MAster", PQ_DFL | PQ_BOOL, 0, 10412 &cfg_opt.master, 0); 10413 parse_table_add(&pt, "MDIX", PQ_DFL | PQ_MULTI, 0, 10414 &cfg_opt.mdix, mdix_mode); 10415 10416 if (parse_arg_eq(a, &pt) < 0) { 10417 parse_arg_eq_done(&pt); 10418 return CMD_USAGE; 10419 } 10420 parse_arg_eq_done(&pt); 10421 10422 if (ARG_CUR(a) != NULL) { 10423 return CMD_USAGE; 10424 } 10425 } else { 10426 cmd = COMBO_CMD_DUMP; 10427 } 10428 10429 break; 10430 10431 case COMBO_CMD_WATCH: 10432 c = ARG_GET(a); 10433 10434 if (c == NULL) { 10435 watch_arg = COMBO_CMD_WATCH_SHOW; 10436 } else if (sal_strcasecmp(c, "on") == 0) { 10437 watch_arg = COMBO_CMD_WATCH_ON; 10438 } else if (sal_strcasecmp(c, "off") == 0) { 10439 watch_arg = COMBO_CMD_WATCH_OFF; 10440 } else { 10441 return CMD_USAGE; 10442 } 10443 break; 10444 10445 default: 10446 break; 10447 } 10448 10449 /* coverity[overrun-local] */ 10450 DPORT_BCM_PBMP_ITER(u, pbm, dport, p) { 10451 switch (cmd) { 10452 case COMBO_CMD_DUMP: 10453 cli_out("Port %s:\n", BCM_PORT_NAME(u, p)); 10454 10455 rc = rf = BCM_E_UNAVAIL; 10456 if (specified_medium == BCM_PORT_MEDIUM_COPPER || 10457 specified_medium == BCM_PORT_MEDIUM_COUNT) { 10458 rc = if_combo_dump(a, u, p, BCM_PORT_MEDIUM_COPPER); 10459 if (rc != BCM_E_NONE && rc != BCM_E_UNAVAIL) { 10460 cli_out("%s:\tERROR(copper): %s\n", 10461 BCM_PORT_NAME(u, p), bcm_errmsg(rc)); 10462 } 10463 } 10464 10465 if (specified_medium == BCM_PORT_MEDIUM_FIBER || 10466 specified_medium == BCM_PORT_MEDIUM_COUNT) { 10467 rf = if_combo_dump(a, u, p, BCM_PORT_MEDIUM_FIBER); 10468 if (rf != BCM_E_NONE && rf != BCM_E_UNAVAIL) { 10469 cli_out("%s:\tERROR(fiber): %s\n", 10470 BCM_PORT_NAME(u, p), bcm_errmsg(rf)); 10471 } 10472 } 10473 10474 /* 10475 * If there were problems getting medium-specific info on 10476 * individual mediums, then they will be printed above. However, 10477 * if BCM_E_UNAVAIL is returned for both copper and fiber mediums 10478 * we'll print only one error message 10479 */ 10480 if (rc == BCM_E_UNAVAIL && rf == BCM_E_UNAVAIL) { 10481 cli_out("%s:\tmedium info unavailable\n", 10482 BCM_PORT_NAME(u, p)); 10483 } 10484 break; 10485 10486 case COMBO_CMD_SET: 10487 /* 10488 * Update the medium operating mode. 10489 */ 10490 r = bcm_port_medium_config_get(u, p, specified_medium, &cfg); 10491 10492 if (r < 0) { 10493 cli_out("%s: port %s: Error getting medium config: %s\n", 10494 ARG_CMD(a), BCM_PORT_NAME(u, p), bcm_errmsg(r)); 10495 return CMD_FAIL; 10496 } 10497 10498 if (cfg_opt.enable != -1) { 10499 cfg.enable = cfg_opt.enable; 10500 } 10501 10502 if (cfg_opt.preferred != -1) { 10503 cfg.preferred = cfg_opt.preferred; 10504 } 10505 10506 if (cfg_opt.autoneg_enable != -1) { 10507 cfg.autoneg_enable = cfg_opt.autoneg_enable; 10508 } 10509 10510 if (cfg_opt.autoneg_advert != 0xffffffff) { 10511 cfg.autoneg_advert = cfg_opt.autoneg_advert; 10512 } 10513 10514 if (cfg_opt.force_speed != -1) { 10515 cfg.force_speed = cfg_opt.force_speed; 10516 } 10517 10518 if (cfg_opt.force_duplex != -1) { 10519 cfg.force_duplex = cfg_opt.force_duplex; 10520 } 10521 10522 if (cfg_opt.master != -1) { 10523 cfg.master = cfg_opt.master; 10524 } 10525 10526 if (cfg_opt.mdix != -1) { 10527 cfg.mdix = cfg_opt.mdix; 10528 } 10529 10530 r = bcm_port_medium_config_set(u, p, specified_medium, &cfg); 10531 10532 if (r < 0) { 10533 cli_out("%s: port %s: Error setting medium config: %s\n", 10534 ARG_CMD(a), BCM_PORT_NAME(u, p), bcm_errmsg(r)); 10535 return CMD_FAIL; 10536 } 10537 10538 break; 10539 10540 case COMBO_CMD_WATCH: 10541 switch (watch_arg) { 10542 case COMBO_CMD_WATCH_SHOW: 10543 if (combo_watch[u][p]) { 10544 cli_out("Port %s: Medium status " 10545 "change watch is ON. " 10546 "Medim changed %d times\n", 10547 BCM_PORT_NAME(u, p), 10548 combo_watch[u][p] - 1); 10549 } else { 10550 cli_out("Port %s: Medium status " 10551 "change watch is OFF.\n", 10552 BCM_PORT_NAME(u, p)); 10553 } 10554 break; 10555 10556 case COMBO_CMD_WATCH_ON: 10557 if (!combo_watch[u][p]) { 10558 r = bcm_port_medium_status_register(u, p, 10559 if_combo_watch, 10560 &combo_watch[u] 10561 [p]); 10562 if (r < 0) { 10563 cli_out("Error registerinig medium " 10564 "status change callback for %s: %s\n", 10565 BCM_PORT_NAME(u, p), 10566 soc_errmsg(r)); 10567 return (CMD_FAIL); 10568 } 10569 10570 combo_watch[u][p] = 1; 10571 } 10572 10573 cli_out("Port %s: Medium change watch is ON\n", 10574 BCM_PORT_NAME(u, p)); 10575 10576 break; 10577 10578 case COMBO_CMD_WATCH_OFF: 10579 if (combo_watch[u][p]) { 10580 r = bcm_port_medium_status_unregister(u, p, 10581 if_combo_watch, 10582 &combo_watch 10583 [u][p]); 10584 if (r < 0) { 10585 cli_out("Error unregisterinig medium " 10586 "status change callback for %s: %s\n", 10587 BCM_PORT_NAME(u, p), 10588 soc_errmsg(r)); 10589 return (CMD_FAIL); 10590 } 10591 10592 combo_watch[u][p] = 0; 10593 } 10594 10595 cli_out("Port %s: Medium change watch is OFF\n", 10596 BCM_PORT_NAME(u, p)); 10597 10598 break; 10599 10600 default: 10601 return CMD_FAIL; 10602 } /* switch ( watch_arg ) */ 10603 10604 break; 10605 10606 /* must default. for covering all the cases of 'enum if_combo_cmd_e' */ 10607 /* coverity[dead_error_begin : FALSE] */ 10608 default: 10609 return CMD_FAIL; 10610 } /* switch ( cmd ) */ 10611 } 10612 10613 return CMD_OK; 10614 } 10615 10616 /* 10617 * Function: 10618 * cmd_cablediag 10619 * Purpose: 10620 * Run cable diagnostics (if available) 10621 */ 10622 10623 cmd_result_t 10624 cmd_esw_cablediag(int unit, args_t *a) 10625 { 10626 char *s; 10627 bcm_pbmp_t pbm; 10628 bcm_port_t port, dport; 10629 int rv, i; 10630 bcm_port_cable_diag_t cd; 10631 char *statename[] = _SHR_PORT_CABLE_STATE_NAMES_INITIALIZER; 10632 10633 if (!sh_check_attached(ARG_CMD(a), unit)) { 10634 return CMD_FAIL; 10635 } 10636 10637 if ((s = ARG_GET(a)) == NULL) { 10638 return CMD_USAGE; 10639 } 10640 10641 if (parse_bcm_pbmp(unit, s, &pbm) < 0) { 10642 cli_out("%s: ERROR: unrecognized port bitmap: %s\n", ARG_CMD(a), s); 10643 return CMD_FAIL; 10644 } 10645 10646 sal_memset(&cd, 0, sizeof(bcm_port_cable_diag_t)); 10647 10648 /* Coverity 10649 * DPORT_BCM_PBMP_ITER checks that dport is valid. 10650 */ 10651 /* coverity[overrun-local] */ 10652 DPORT_BCM_PBMP_ITER(unit, pbm, dport, port) { 10653 rv = bcm_port_cable_diag(unit, port, &cd); 10654 if (rv < 0) { 10655 cli_out("%s: ERROR: port %s: %s\n", 10656 ARG_CMD(a), BCM_PORT_NAME(unit, port), bcm_errmsg(rv)); 10657 continue; 10658 } 10659 if (cd.fuzz_len == 0) { 10660 cli_out("port %s: cable (%d pairs)\n", 10661 BCM_PORT_NAME(unit, port), cd.npairs); 10662 } else { 10663 cli_out("port %s: cable (%d pairs, length +/- %d meters)\n", 10664 BCM_PORT_NAME(unit, port), cd.npairs, cd.fuzz_len); 10665 } 10666 for (i = 0; i < cd.npairs; i++) { 10667 cli_out("\tpair %c %s, length %d meters\n", 10668 'A' + i, statename[cd.pair_state[i]], cd.pair_len[i]); 10669 } 10670 } 10671 10672 return CMD_OK; 10673 } 10674 10675 #ifdef BCM_XGS3_SWITCH_SUPPORT 10676 /* XAUI BERT Test */ 10677 10678 char cmd_xaui_usage[] = 10679 "Run XAUI BERT.\n" 10680 "Usages:\n\t" 10681 " xaui bert SrcPort=<port> DestPort=<port> Duration=<usec> Verb=0/1\n"; 10682 10683 #define XAUI_PREEMPHASIS_MIN (0) 10684 #define XAUI_PREEMPHASIS_MAX (15) 10685 #define XAUI_IDRIVER_MIN (0) 10686 #define XAUI_IDRIVER_MAX (15) 10687 #define XAUI_EQUALIZER_MIN (0) 10688 #define XAUI_EQUALIZER_MAX (7) 10689 10690 typedef struct _xaui_bert_info_s { 10691 bcm_port_t src_port; 10692 bcm_port_t dst_port; 10693 soc_xaui_config_t src_config; 10694 soc_xaui_config_t dst_config; 10695 soc_xaui_config_t test_config; 10696 bcm_port_info_t src_info; 10697 bcm_port_info_t dst_info; 10698 int duration; 10699 int linkscan_us; 10700 int verbose; 10701 } _xaui_bert_info_t; 10702 10703 /* 10704 * Function: 10705 * _xaui_bert_counter_check 10706 * Purpose: 10707 * Check BERT counters after the test. 10708 * Parameters: 10709 * (IN) unit - BCM unit number 10710 * (IN) test_info - Test configuration 10711 * Returns: 10712 * BCM_E_NONE - success 10713 * BCM_E_XXXX - failed. 10714 * Notes: 10715 */ 10716 static int 10717 _xaui_bert_counter_check(int unit, _xaui_bert_info_t *test_info) 10718 { 10719 bcm_port_t src_port, dst_port; 10720 uint32 tx_pkt, tx_byte, rx_pkt, rx_byte, bit_err, byte_err, pkt_err; 10721 int prbs_lock, lock; 10722 10723 src_port = test_info->src_port; 10724 dst_port = test_info->dst_port; 10725 10726 /* Read Tx counters */ 10727 SOC_IF_ERROR_RETURN(soc_xaui_txbert_pkt_count_get(unit, src_port, &tx_pkt)); 10728 SOC_IF_ERROR_RETURN 10729 (soc_xaui_txbert_byte_count_get(unit, src_port, &tx_byte)); 10730 10731 lock = 1; 10732 /* Read Rx counters */ 10733 SOC_IF_ERROR_RETURN 10734 (soc_xaui_rxbert_pkt_count_get(unit, dst_port, &rx_pkt, &prbs_lock)); 10735 lock &= prbs_lock; 10736 10737 SOC_IF_ERROR_RETURN 10738 (soc_xaui_rxbert_byte_count_get(unit, dst_port, &rx_byte, &prbs_lock)); 10739 lock &= prbs_lock; 10740 10741 SOC_IF_ERROR_RETURN 10742 (soc_xaui_rxbert_bit_err_count_get(unit, dst_port, 10743 &bit_err, &prbs_lock)); 10744 lock &= prbs_lock; 10745 10746 SOC_IF_ERROR_RETURN 10747 (soc_xaui_rxbert_byte_err_count_get(unit, dst_port, 10748 &byte_err, &prbs_lock)); 10749 lock &= prbs_lock; 10750 10751 SOC_IF_ERROR_RETURN 10752 (soc_xaui_rxbert_pkt_err_count_get(unit, dst_port, 10753 &pkt_err, &prbs_lock)); 10754 lock &= prbs_lock; 10755 10756 if (test_info->verbose) { 10757 cli_out(" %4s->%4s, 0x%08x, 0x%08x, 0x%08x, %s, ", 10758 BCM_PORT_NAME(unit, src_port), BCM_PORT_NAME(unit, dst_port), 10759 tx_byte, rx_byte, bit_err, lock ? " OK" : " !OK"); 10760 } 10761 10762 /* Check TX/RX counters */ 10763 if ((tx_byte == 0) || (tx_pkt == 0) || 10764 (tx_byte != rx_byte) || (tx_pkt != rx_pkt) || !lock) { 10765 return BCM_E_FAIL; 10766 } 10767 10768 /* Check error counters */ 10769 if ((bit_err != 0) || (byte_err != 0) || (pkt_err != 0)) { 10770 return BCM_E_FAIL; 10771 } 10772 10773 return BCM_E_NONE; 10774 } 10775 10776 /* 10777 * Function: 10778 * _xaui_bert_test 10779 * Purpose: 10780 * Run BERT test with requested port configuration. 10781 * Parameters: 10782 * (IN) unit - BCM unit number 10783 * (IN) test_info - Test configuration 10784 * Returns: 10785 * BCM_E_NONE - success 10786 * BCM_E_XXXX - failed. 10787 * Notes: 10788 */ 10789 static int 10790 _xaui_bert_test(int unit, _xaui_bert_info_t *test_info) 10791 { 10792 int result1, result2; 10793 bcm_port_t src_port, dst_port; 10794 10795 src_port = test_info->src_port; 10796 dst_port = test_info->dst_port; 10797 10798 BCM_IF_ERROR_RETURN(bcm_port_speed_set(unit, src_port, 10000)); 10799 BCM_IF_ERROR_RETURN(bcm_port_speed_set(unit, dst_port, 10000)); 10800 10801 BCM_IF_ERROR_RETURN 10802 (soc_xaui_config_set(unit, src_port, &test_info->test_config)); 10803 BCM_IF_ERROR_RETURN 10804 (soc_xaui_config_set(unit, dst_port, &test_info->test_config)); 10805 10806 /* Wait up to 0.1 sec for TX PLL lock */ 10807 sal_usleep(100000); 10808 10809 /* Enable RX BERT on both ports first */ 10810 BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, dst_port, TRUE)); 10811 if (src_port != dst_port) { 10812 BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, src_port, TRUE)); 10813 } 10814 10815 /* Enable TX BERT on both ports */ 10816 BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, src_port, TRUE)); 10817 if (src_port != dst_port) { 10818 BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, dst_port, TRUE)); 10819 } 10820 10821 /* Run test for requested duration */ 10822 sal_usleep(test_info->duration); 10823 10824 /* Disable TX BERT */ 10825 BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, src_port, FALSE)); 10826 if (src_port != dst_port) { 10827 BCM_IF_ERROR_RETURN(soc_xaui_txbert_enable(unit, dst_port, FALSE)); 10828 } 10829 10830 /* Give enough time to complete tx/rx */ 10831 sal_usleep(500); 10832 result1 = _xaui_bert_counter_check(unit, test_info); 10833 result2 = _xaui_bert_counter_check(unit, test_info); 10834 if (BCM_SUCCESS(result1) && BCM_SUCCESS(result2)) { 10835 cli_out(" ( P ) "); 10836 } else { 10837 cli_out(" ( F ) "); 10838 } 10839 10840 if (test_info->verbose) { 10841 cli_out("\n"); 10842 } 10843 10844 /* Disable RX BERT only after reading the counter. 10845 * Otherwise, counters always read zero. 10846 */ 10847 BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, src_port, FALSE)); 10848 if (src_port != dst_port) { 10849 BCM_IF_ERROR_RETURN(soc_xaui_rxbert_enable(unit, dst_port, FALSE)); 10850 } 10851 10852 if ((BCM_E_NONE != result1) && (BCM_E_FAIL != result1)) { 10853 return result1; 10854 } 10855 if ((BCM_E_NONE != result2) && (BCM_E_FAIL != result2)) { 10856 return result2; 10857 } 10858 return BCM_E_NONE; 10859 } 10860 10861 /* 10862 * Function: 10863 * _xaui_bert_save_config 10864 * Purpose: 10865 * Disable linkscan and save current port configuration. 10866 * Parameters: 10867 * (IN) unit - BCM unit number 10868 * (OUT) test_info - Current port configuration 10869 * Returns: 10870 * BCM_E_NONE - success 10871 * BCM_E_XXXX - failed. 10872 * Notes: 10873 */ 10874 static int 10875 _xaui_bert_save_config(int unit, _xaui_bert_info_t *test_info) 10876 { 10877 10878 /* If linkscan is enabled, disable linkscan */ 10879 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_get(unit, &test_info->linkscan_us)); 10880 if (test_info->linkscan_us != 0) { 10881 BCM_IF_ERROR_RETURN(bcm_linkscan_enable_set(unit, 0)); 10882 /* Give enough time for linkscan task to exit. */ 10883 sal_usleep(test_info->linkscan_us * 5); 10884 } 10885 10886 /* Save current settings */ 10887 BCM_IF_ERROR_RETURN 10888 (soc_xaui_config_get(unit, test_info->src_port, 10889 &test_info->src_config)); 10890 BCM_IF_ERROR_RETURN 10891 (soc_xaui_config_get(unit, test_info->dst_port, 10892 &test_info->dst_config)); 10893 10894 /* Save original speed settings */ 10895 BCM_IF_ERROR_RETURN 10896 (bcm_port_info_save(unit, test_info->src_port, &test_info->src_info)); 10897 BCM_IF_ERROR_RETURN 10898 (bcm_port_info_save(unit, test_info->dst_port, &test_info->dst_info)); 10899 10900 return BCM_E_NONE; 10901 } 10902 10903 /* 10904 * Function: 10905 * _xaui_bert_restore_config 10906 * Purpose: 10907 * Restore original port configuration. 10908 * Parameters: 10909 * (IN) unit - BCM unit number 10910 * (IN) test_info - Port configuration to be restored 10911 * Returns: 10912 * BCM_E_NONE - success 10913 * BCM_E_XXXX - failed. 10914 * Notes: 10915 */ 10916 static int 10917 _xaui_bert_restore_config(int unit, _xaui_bert_info_t *test_info) 10918 { 10919 10920 BCM_IF_ERROR_RETURN 10921 (bcm_port_info_restore(unit, test_info->src_port, 10922 &test_info->src_info)); 10923 BCM_IF_ERROR_RETURN 10924 (bcm_port_info_restore(unit, test_info->dst_port, 10925 &test_info->dst_info)); 10926 10927 #if 0 10928 /* Restore original configuration */ 10929 BCM_IF_ERROR_RETURN 10930 (soc_xaui_config_set(unit, test_info->src_port, 10931 &test_info->src_config)); 10932 BCM_IF_ERROR_RETURN 10933 (soc_xaui_config_set(unit, test_info->dst_port, 10934 &test_info->dst_config)); 10935 #endif 10936 10937 if (test_info->linkscan_us != 0) { 10938 BCM_IF_ERROR_RETURN 10939 (bcm_linkscan_enable_set(unit, test_info->linkscan_us)); 10940 } 10941 10942 return BCM_E_NONE; 10943 } 10944 10945 char bert_header[] = 10946 " Equalizer\n" 10947 "I_Driver 0 1 2 3 4 5 6 7\n"; 10948 10949 char bert_header_v[] = 10950 "\n Preemph, I_Driver, Equalizer, Src->Des," 10951 " tx_byte, rx_byte, bit_err, PRBS Lock," 10952 " Des->Src, tx_byte, rx_byte, bit_err," " PRBS Lock\n"; 10953 10954 /* 10955 * Function: 10956 * cmd_xaui 10957 * Purpose: 10958 * Entry point to XAUI related CLI commands. 10959 * Parameters: 10960 * (IN) unit - BCM unit number 10961 * (IN) a - Arguments for the command 10962 * Returns: 10963 * BCM_E_NONE - success 10964 * BCM_E_XXXX - failed. 10965 * Notes: 10966 */ 10967 cmd_result_t 10968 cmd_xaui(int unit, args_t *a) 10969 { 10970 char *subcmd; 10971 parse_table_t pt; 10972 int rv; 10973 cmd_result_t retCode; 10974 10975 if (!sh_check_attached(ARG_CMD(a), unit)) { 10976 return CMD_FAIL; 10977 } 10978 10979 if ((subcmd = ARG_GET(a)) == NULL) { 10980 return CMD_USAGE; 10981 } 10982 10983 rv = BCM_E_NONE; 10984 if (sal_strcasecmp(subcmd, "bert") == 0) { 10985 uint32 preemphasis, idriver, equalizer; 10986 _xaui_bert_info_t test_info; 10987 10988 sal_memset(&test_info, 0, sizeof(test_info)); 10989 test_info.duration = 10; 10990 10991 parse_table_init(unit, &pt); 10992 parse_table_add(&pt, "SrcPort", PQ_DFL | PQ_PORT, 0, 10993 &test_info.src_port, NULL); 10994 parse_table_add(&pt, "DestPort", PQ_DFL | PQ_PORT, 0, 10995 &test_info.dst_port, NULL); 10996 parse_table_add(&pt, "Duration", PQ_INT | PQ_DFL, 0, 10997 &test_info.duration, NULL); 10998 parse_table_add(&pt, "Verbose", PQ_BOOL | PQ_DFL, 0, 10999 &test_info.verbose, NULL); 11000 11001 if (!parseEndOk(a, &pt, &retCode)) { 11002 return retCode; 11003 } 11004 11005 /* Run only on HG and XE port */ 11006 if ((!IS_HG_PORT(unit, test_info.src_port) && 11007 !IS_XE_PORT(unit, test_info.src_port)) || 11008 (!IS_HG_PORT(unit, test_info.dst_port) && 11009 !IS_XE_PORT(unit, test_info.dst_port))) { 11010 cli_out("%s: ERROR: Invalid port selection %d, %d\n", 11011 ARG_CMD(a), test_info.src_port, test_info.dst_port); 11012 return CMD_FAIL; 11013 } 11014 11015 if ((rv = _xaui_bert_save_config(unit, &test_info)) < 0) { 11016 goto cmd_xaui_err; 11017 } 11018 11019 test_info.test_config = test_info.src_config; 11020 for (preemphasis = XAUI_PREEMPHASIS_MIN; 11021 preemphasis <= XAUI_PREEMPHASIS_MAX; preemphasis++) { 11022 test_info.test_config.preemphasis = preemphasis; 11023 11024 if (!test_info.verbose) { 11025 cli_out("\nPreemphasis = %d\n", preemphasis); 11026 } 11027 11028 cli_out("%s", test_info.verbose ? bert_header_v : bert_header); 11029 11030 for (idriver = XAUI_IDRIVER_MIN; 11031 idriver <= XAUI_IDRIVER_MAX; idriver++) { 11032 test_info.test_config.idriver = idriver; 11033 if (!test_info.verbose) { 11034 cli_out("%8d ", idriver); 11035 } 11036 for (equalizer = XAUI_EQUALIZER_MIN; 11037 equalizer <= XAUI_EQUALIZER_MAX; equalizer++) { 11038 11039 if (test_info.verbose) { 11040 cli_out("%8d, %8d, %9d,", preemphasis, idriver, 11041 equalizer); 11042 } 11043 11044 test_info.test_config.equalizer_ctrl = equalizer; 11045 if ((rv = _xaui_bert_test(unit, &test_info)) < 0) { 11046 _xaui_bert_restore_config(unit, &test_info); 11047 goto cmd_xaui_err; 11048 } 11049 } 11050 cli_out("\n"); 11051 } 11052 } 11053 11054 if ((rv = _xaui_bert_restore_config(unit, &test_info)) < 0) { 11055 goto cmd_xaui_err; 11056 } 11057 return CMD_OK; 11058 } 11059 cli_out("%s: ERROR: Unknown xaui subcommand: %s\n", ARG_CMD(a), subcmd); 11060 return CMD_USAGE; 11061 11062 cmd_xaui_err: 11063 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 11064 return CMD_FAIL; 11065 } 11066 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 11067 11068 #if defined(INCLUDE_FCMAP) 11069 /* BFCMAP TEST */ 11070 int 11071 diag_bfcmap_pcfg_set_get(int port) 11072 { 11073 int rc = CMD_OK; 11074 11075 rc = bfcmap_pcfg_set_get(port); 11076 11077 return (rc == BFCMAP_E_NONE) ? CMD_OK : CMD_FAIL; 11078 } 11079 11080 int bfcmap88060_show_fc_config(int unit, int port) 11081 { 11082 int rv = CMD_OK; 11083 bcm_fcmap_port_config_t pCfg; 11084 11085 /* Setting cos to invalid COS value to 11086 * get current configured cos and priority value 11087 */ 11088 pCfg.cos_to_pri.cos = 0xFFFF; 11089 11090 rv = bcm_fcmap_port_config_get(unit, port, &pCfg); 11091 11092 if (rv != BCM_E_NONE) { 11093 cli_out("Error in getting FC port config!!\n"); 11094 return CMD_FAIL; 11095 } 11096 11097 cli_out(" XMOD_FCMAP_ATTR_xxx. | action_mask : %#x\n", pCfg.action_mask); 11098 cli_out(" XMOD_FCMAP_ATTR2_xxx. | action_mask2 : %#x\n", pCfg.action_mask2); 11099 cli_out(" FC port Mode, FCoE mode | port_mode : %#x\n", pCfg.port_mode); 11100 cli_out(" Speed, AN/2/4/8/16/32/AN2/AN4/AN8/AN16/AN3 | speed : %#x\n", pCfg.speed); 11101 cli_out(" Transit B2B credits | tx_buffer_to_buffer_credits : %#x\n", pCfg.tx_buffer_to_buffer_credits); 11102 cli_out(" Receive B2B Credits (read only), computed based on max_frame_length | rx_buffer_to_buffer_credits : %#x\n", pCfg.rx_buffer_to_buffer_credits); 11103 cli_out(" maximum FC frame length for ingress and egress (in unit of 32-bit word) | max_frame_length : %#x\n", pCfg.max_frame_length); 11104 cli_out(" bb credit recovery parameter | bb_sc_n : %#x\n", pCfg.bb_sc_n); 11105 cli_out(" Port state, INIT, Reset, Link Up, Link down, disabled (read only) | port_state : %#x\n", pCfg.port_state); 11106 cli_out(" Receive, transmit Timeout, default 100ms | r_t_tov : %#x\n", pCfg.r_t_tov); 11107 cli_out(" Interrupt enable | interrupt_enable : %#x\n", pCfg.interrupt_enable); 11108 cli_out(" fillword on 8G active state | fw_on_active_8g : %#x\n", pCfg.fw_on_active_8g); 11109 cli_out(" Encap Source MAC construct mode | src_mac_construct : %#x\n", pCfg.src_mac_construct); 11110 cli_out(" Src MAC Addr for encapsulated frame | src_mac_addr : %02x:%02x:%02x:%02x:%02x:%02x\n", 11111 pCfg.src_mac_addr[0], pCfg.src_mac_addr[1], pCfg.src_mac_addr[2], 11112 pCfg.src_mac_addr[3], pCfg.src_mac_addr[4], pCfg.src_mac_addr[5]); 11113 cli_out(" Source FCMAP prefix for the FPMA | src_fcmap_prefix : %#x\n", pCfg.src_fcmap_prefix); 11114 cli_out(" Encap Dest MAC construct mode | dst_mac_construct : %#x\n", pCfg.dst_mac_construct); 11115 cli_out(" Dest MAC Addr for encapsulated frame | dst_mac_addr : %02x:%02x:%02x:%02x:%02x:%02x\n", 11116 pCfg.dst_mac_addr[0], pCfg.dst_mac_addr[1], pCfg.dst_mac_addr[2], 11117 pCfg.dst_mac_addr[3], pCfg.dst_mac_addr[4], pCfg.dst_mac_addr[5]); 11118 cli_out(" Destination FCMAP prefix for the FPMA | dst_fcmap_prefix : %#x\n", pCfg.dst_fcmap_prefix); 11119 cli_out(" default vlan for the mapper | vlan_tag : %#x\n", pCfg.vlan_tag); 11120 cli_out(" default VFT tag for the mapper | vft_tag : %#x\n", pCfg.vft_tag); 11121 cli_out(" Size of VLAN-VSAN Mapper table (read only) | mapper_len : %#x\n", pCfg.mapper_len); 11122 cli_out(" Bypass Mapper | ingress_mapper_bypass : %#x\n", pCfg.ingress_mapper_bypass); 11123 cli_out(" Bypass Mapper | egress_mapper_bypass : %#x\n", pCfg.egress_mapper_bypass); 11124 cli_out(" VID or VFID | ingress_map_table_input : %#x\n", pCfg.ingress_map_table_input); 11125 cli_out(" VID or VFID | egress_map_table_input : %#x\n", pCfg.egress_map_table_input); 11126 cli_out(" Mapper FC-CRC handling | ingress_fc_crc_mode : %#x\n", pCfg.ingress_fc_crc_mode); 11127 cli_out(" Mapper FC-CRC handling | egress_fc_crc_mode : %#x\n", pCfg.egress_fc_crc_mode); 11128 cli_out(" VFT header processing mode | ingress_vfthdr_proc_mode : %#x\n", pCfg.ingress_vfthdr_proc_mode); 11129 cli_out(" VFT header processing mode | egress_vfthdr_proc_mode : %#x\n", pCfg.egress_vfthdr_proc_mode); 11130 cli_out(" VLAN header processing mode | ingress_vlantag_proc_mode : %#x\n", pCfg.ingress_vlantag_proc_mode); 11131 cli_out(" VLAN header processing mode | egress_vlantag_proc_mode : %#x\n", pCfg.egress_vlantag_proc_mode); 11132 cli_out(" source of VFID | ingress_vfid_mapsrc : %#x\n", pCfg.ingress_vfid_mapsrc); 11133 cli_out(" source of VFID | egress_vfid_mapsrc : %#x\n", pCfg.egress_vfid_mapsrc); 11134 cli_out(" source of VID | ingress_vid_mapsrc : %#x\n", pCfg.ingress_vid_mapsrc); 11135 cli_out(" processing mode for priority field of vlan tag | ingress_vlan_pri_map_mode : %#x\n", pCfg.ingress_vlan_pri_map_mode); 11136 cli_out(" processing mode for priority field of vlan tag | egress_vlan_pri_map_mode : %#x\n", pCfg.egress_vlan_pri_map_mode); 11137 cli_out(" mode of VFT hopCnt check on ingress | ingress_hopCnt_check_mode : %#x\n", pCfg.ingress_hopCnt_check_mode); 11138 cli_out(" enable VFT hopCnt decrement on egress | egress_hopCnt_dec_enable : %#x\n", pCfg.egress_hopCnt_dec_enable); 11139 cli_out(" during 16G speed negotiation, 0 -- Use TTS, 1 -- Use PCS | use_tts_pcs_16G : %#x\n", pCfg.use_tts_pcs_16G); 11140 cli_out(" during 32G speed negotiation, 0 -- Use TTS, 1 -- Use PCS | use_tts_pcs_32G : %#x\n", pCfg.use_tts_pcs_32G); 11141 cli_out(" enable/disable link training for 16G | training_enable_16G : %#x\n", pCfg.training_enable_16G); 11142 cli_out(" enable/disable link training for 32G | training_enable_32G : %#x\n", pCfg.training_enable_32G); 11143 cli_out(" enable/disable FEC for 16G | fec_enable_16G : %#x\n", pCfg.fec_enable_16G); 11144 cli_out(" enable/disable FEC for 32G | fec_enable_32G : %#x\n", pCfg.fec_enable_32G); 11145 cli_out(" Enable FCS corruption on if FCoE pkt has EOFni or EOFa on ingress | ingress_fcs_crrpt_eof_enable : %#x\n", pCfg.ingress_fcs_crrpt_eof_enable); 11146 cli_out(" VLAN header insert enable | ingress_vlantag_presence_enable : %#x\n", pCfg.ingress_vlantag_presence_enable); 11147 cli_out(" mode of VFT hopCnt check on egress | egress_hopcnt_check_mode : %#x\n", pCfg.egress_hopcnt_check_mode); 11148 cli_out(" enable VFT hopCnt decrement on ingress | ingress_hopcnt_dec_enable : %#x\n", pCfg.ingress_hopcnt_dec_enable); 11149 cli_out(" enable passing control frame on egress when mapper is in bypass mode | egress_pass_ctrl_frame_enable : %#x\n", pCfg.egress_pass_ctrl_frame_enable); 11150 cli_out(" enable passing pfc frame on egress when mapper is in bypass mode | egress_pass_pfc_frame_enable : %#x\n", pCfg.egress_pass_pfc_frame_enable); 11151 cli_out(" enable passing pause frame on egress when mapper is in bypass mode | egress_pass_pause_frame_enable : %#x\n", pCfg.egress_pass_pause_frame_enable); 11152 cli_out(" disable FCOE header version field check on egress | egress_fcoe_version_chk_disable : %#x\n", pCfg.egress_fcoe_version_chk_disable); 11153 cli_out(" specify default CoS value to use on egress | egress_default_cos_value : %#x\n", pCfg.egress_default_cos_value); 11154 cli_out(" use IP CoS map values on egress | egress_use_ip_cos_map : %#x\n", pCfg.egress_use_ip_cos_map); 11155 cli_out(" bitmap to enable/disable scrambling for 2/4/8/16/32G FC speed | scrambling_enable_mask : %#x\n", pCfg.scrambling_enable_mask); 11156 cli_out(" 0 - disable, 1 - enable: bitmap value for corresponding speed | scrambling_enable_value : %#x\n", pCfg.scrambling_enable_value); 11157 cli_out(" 0 - disable, 1 - enable); legacy pause on egress | egress_pause_enable : %#x\n", pCfg.egress_pause_enable); 11158 cli_out(" 0 - disable, 1 - enable); PFC on egress | egress_pfc_enable : %#x\n", pCfg.egress_pfc_enable); 11159 cli_out(" stats collection interval in milliseconds | stat_interval : %#x\n", pCfg.stat_interval); 11160 cli_out(" current COS value | cos_to_pri.cos : %#x\n", pCfg.cos_to_pri.cos); 11161 cli_out(" current priority value | cos_to_pri.pri : %#x\n", pCfg.cos_to_pri.pri); 11162 11163 return CMD_OK; 11164 } 11165 11166 #endif