eyescan.c (87866B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * SOC EYESCAN 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <sal/types.h> 14 #include <soc/eyescan.h> 15 #include <soc/drv.h> 16 #include <soc/error.h> 17 #include <soc/mem.h> 18 #include <soc/phy/phyctrl.h> 19 20 #ifdef PHYMOD_SUPPORT 21 #include <phymod/phymod_diagnostics.h> 22 #include <phymod/phymod_diag.h> 23 #endif 24 25 #ifdef PORTMOD_SUPPORT 26 #include <soc/portmod/portmod.h> 27 #endif 28 29 #ifndef __KERNEL__ 30 #include <math.h> 31 #endif /* #ifndef __KERNEL__ */ 32 33 STATIC soc_port_phy_eyescan_counter_cb_t counter_func[SOC_MAX_NUM_DEVICES][socPortPhyEyescanNofCounters] = {{{0}}}; 34 35 int 36 soc_port_phy_eyescan_counter_register(int unit, soc_port_phy_eyscan_counter_t counter, soc_port_phy_eyescan_counter_cb_t* cf) 37 { 38 if (!SOC_UNIT_VALID(unit)) { 39 LOG_ERROR(BSL_LS_SOC_PHY, 40 (BSL_META_U(unit, 41 "Invalid unit\n"))); 42 return SOC_E_UNIT; 43 } 44 45 if(counter >= socPortPhyEyescanNofCounters || counter < 0) { 46 LOG_ERROR(BSL_LS_SOC_PHY, 47 (BSL_META_U(unit, 48 "Counter %d isn't supported\n"), counter)); 49 return SOC_E_PARAM; 50 } 51 52 if(NULL == cf) { /*clear callbacks*/ 53 counter_func[unit][counter].clear_func = NULL; 54 counter_func[unit][counter].get_func = NULL; 55 } else { 56 counter_func[unit][counter] = *cf; 57 } 58 59 return SOC_E_NONE; 60 } 61 62 STATIC int 63 soc_port_phy_eyescan_check_bounds(int unit, soc_port_t port, uint32 inst, int flags, soc_port_phy_eyscan_counter_t counter, soc_port_phy_eye_bounds_t* bounds) 64 { 65 int vmax, vmin, l_hmax, r_hmax; 66 int locked; 67 int rv = SOC_E_NONE; 68 69 if((socPortPhyEyescanCounterRelativePhy!=counter) && bounds->vertical_min<0) { 70 LOG_CLI((BSL_META_U(unit, 71 "Counter mode doesn't support negative vertical_min. Updated to 0.\n"))); 72 bounds->vertical_min = 0; 73 } 74 if(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY) { 75 bounds->horizontal_min = 0; 76 bounds->horizontal_max = 0; 77 } 78 79 MIIM_LOCK(unit); 80 locked = 1; 81 82 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){ 83 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 84 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MAX_LEFT_HOFFSET, (int *) (&l_hmax)); 85 if (SOC_FAILURE(rv)) { 86 LOG_ERROR(BSL_LS_SOC_PHY, 87 (BSL_META_U(unit, 88 "%s\n"), soc_errmsg(rv))); 89 goto exit; 90 } 91 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 92 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MAX_RIGHT_HOFFSET, (int *) (&r_hmax)); 93 if (SOC_FAILURE(rv)) { 94 LOG_ERROR(BSL_LS_SOC_PHY, 95 (BSL_META_U(unit, 96 "%s\n"), soc_errmsg(rv))); 97 goto exit; 98 } 99 } 100 101 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 102 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MIN_VOFFSET, (int *) (&vmin)); 103 if (SOC_FAILURE(rv)) { 104 LOG_ERROR(BSL_LS_SOC_PHY, 105 (BSL_META_U(unit, 106 "%s\n"), soc_errmsg(rv))); 107 goto exit; 108 } 109 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 110 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_MAX_VOFFSET, (int *) (&vmax)); 111 if (SOC_FAILURE(rv)) { 112 LOG_ERROR(BSL_LS_SOC_PHY, 113 (BSL_META_U(unit, 114 "%s\n"), soc_errmsg(rv))); 115 goto exit; 116 } 117 118 locked = 0; 119 MIIM_UNLOCK(unit); 120 121 if(bounds->vertical_min < vmin){ 122 LOG_CLI((BSL_META_U(unit, 123 "vertical_min smaller than min available. Updated to %d.\n"), vmin)); 124 bounds->vertical_min = vmin; 125 } 126 if (bounds->vertical_max > vmax) { 127 LOG_CLI((BSL_META_U(unit, 128 "vertical_max larger than max available. Updated to %d.\n"), vmax)); 129 bounds->vertical_max = vmax; 130 } 131 132 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){ 133 if(bounds->horizontal_min < l_hmax){ 134 LOG_CLI((BSL_META_U(unit, 135 "horizontal_min smaller than min available. Updated to %d.\n"), l_hmax)); 136 bounds->horizontal_min = l_hmax; 137 } 138 if (bounds->horizontal_max > r_hmax) { 139 LOG_CLI((BSL_META_U(unit, 140 "horizontal_max larger than max available. Updated to %d.\n"), r_hmax)); 141 bounds->horizontal_max = r_hmax; 142 } 143 } 144 145 if(bounds->vertical_min < -1*SOC_PORT_PHY_EYESCAN_V_INDEX){ 146 LOG_CLI((BSL_META_U(unit, 147 "vertical_min smaller than min available. Updated to %d.\n"), -1*SOC_PORT_PHY_EYESCAN_V_INDEX)); 148 bounds->vertical_min = -1*SOC_PORT_PHY_EYESCAN_V_INDEX; 149 } 150 if (bounds->vertical_max > SOC_PORT_PHY_EYESCAN_V_INDEX) { 151 LOG_CLI((BSL_META_U(unit, 152 "vertical_max larger than max available. Updated to %d.\n"), SOC_PORT_PHY_EYESCAN_V_INDEX)); 153 bounds->vertical_max = SOC_PORT_PHY_EYESCAN_V_INDEX; 154 } 155 156 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){ 157 if(bounds->horizontal_min < -1*SOC_PORT_PHY_EYESCAN_H_INDEX){ 158 LOG_CLI((BSL_META_U(unit, 159 "horizontal_min smaller than min available. Updated to %d.\n"), -1*SOC_PORT_PHY_EYESCAN_H_INDEX)); 160 bounds->horizontal_min = -1*SOC_PORT_PHY_EYESCAN_H_INDEX; 161 } 162 if (bounds->horizontal_max > SOC_PORT_PHY_EYESCAN_H_INDEX) { 163 LOG_CLI((BSL_META_U(unit, 164 "horizontal_max larger than max available. Updated to %d.\n"), SOC_PORT_PHY_EYESCAN_H_INDEX)); 165 bounds->horizontal_max = SOC_PORT_PHY_EYESCAN_H_INDEX; 166 } 167 } 168 169 exit: 170 if (locked) { 171 MIIM_UNLOCK(unit); 172 } 173 return rv; 174 } 175 176 177 STATIC int 178 soc_port_phy_eyescan_enable(int unit, uint32 inst, int flags, soc_port_t port, 179 soc_port_phy_eyscan_counter_t counter, int enable, int* voffset) 180 { 181 int data; 182 int p1_mapped[] = {0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14,16,17,19,18,20,21,23,22,24,25,27,26,28,29,31,30}; 183 int hoffset_init=0; 184 int rv = SOC_E_NONE; 185 186 MIIM_LOCK(unit); 187 188 switch(counter) { 189 case socPortPhyEyescanCounterRelativePhy: 190 if(enable) { 191 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 192 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_ENABLE_LIVELINK, (void *) (0)); 193 if (SOC_FAILURE(rv)) { 194 LOG_ERROR(BSL_LS_SOC_PHY, 195 (BSL_META_U(unit, 196 "%s\n"), soc_errmsg(rv))); 197 goto exit; 198 } 199 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 200 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_GET_INIT_VOFFSET, voffset); 201 if (SOC_FAILURE(rv)) { 202 LOG_ERROR(BSL_LS_SOC_PHY, 203 (BSL_META_U(unit, 204 "%s\n"), soc_errmsg(rv))); 205 goto exit; 206 } 207 208 /* use the mapped P1 value */ 209 data = *voffset & 0x1f; 210 data = p1_mapped[data]; 211 data |= (*voffset) & 0x20; 212 *voffset = data; 213 214 } else { 215 if(SRD_EYESCAN_INVALID_VOFFSET != *voffset) { 216 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)) { 217 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 218 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_HOFFSET, &hoffset_init); 219 if (SOC_FAILURE(rv)) { 220 LOG_ERROR(BSL_LS_SOC_PHY, 221 (BSL_META_U(unit, 222 "%s\n"), soc_errmsg(rv))); 223 goto exit; 224 } 225 } 226 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 227 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_VOFFSET, (int *) voffset); 228 if (SOC_FAILURE(rv)) { 229 LOG_ERROR(BSL_LS_SOC_PHY, 230 (BSL_META_U(unit, 231 "%s\n"), soc_errmsg(rv))); 232 goto exit; 233 } 234 } 235 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 236 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_DISABLE_LIVELINK, (void *) (0)); 237 if (SOC_FAILURE(rv)) { 238 LOG_ERROR(BSL_LS_SOC_PHY, 239 (BSL_META_U(unit, 240 "%s\n"), soc_errmsg(rv))); 241 goto exit; 242 } 243 } 244 break; 245 case socPortPhyEyescanCounterPrbsPhy: 246 case socPortPhyEyescanCounterPrbsMac: 247 case socPortPhyEyescanCounterCrcMac: 248 case socPortPhyEyescanCounterBerMac: 249 default: 250 if(enable) { 251 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 252 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_ENABLE_DEADLINK, (void *) (0)); 253 if (SOC_FAILURE(rv)) { 254 LOG_ERROR(BSL_LS_SOC_PHY, 255 (BSL_META_U(unit, 256 "%s\n"), soc_errmsg(rv))); 257 goto exit; 258 } 259 } else { 260 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 261 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_HOFFSET, &hoffset_init); 262 if (SOC_FAILURE(rv)) { 263 LOG_ERROR(BSL_LS_SOC_PHY, 264 (BSL_META_U(unit, 265 "%s\n"), soc_errmsg(rv))); 266 goto exit; 267 } 268 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 269 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_VOFFSET, &hoffset_init); 270 if (SOC_FAILURE(rv)) { 271 LOG_ERROR(BSL_LS_SOC_PHY, 272 (BSL_META_U(unit, 273 "%s\n"), soc_errmsg(rv))); 274 goto exit; 275 } 276 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 277 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_DISABLE_DEADLINK, (void *) (0)); 278 if (SOC_FAILURE(rv)) { 279 LOG_ERROR(BSL_LS_SOC_PHY, 280 (BSL_META_U(unit, 281 "%s\n"), soc_errmsg(rv))); 282 goto exit; 283 } 284 } 285 break; 286 } 287 288 exit: 289 MIIM_UNLOCK(unit); 290 return rv; 291 } 292 293 STATIC int 294 soc_port_phy_eyescan_counter_clear(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter, sal_usecs_t* start_time) 295 { 296 uint32 error; 297 int rv = SOC_E_NONE; 298 299 if(NULL != counter_func[unit][counter].get_func) { 300 counter_func[unit][counter].clear_func(unit, port); 301 } else { 302 switch(counter) { 303 case socPortPhyEyescanCounterRelativePhy: 304 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 305 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_CLEAR_LIVELINK, (void *) (0)); 306 if (SOC_FAILURE(rv)) { 307 LOG_ERROR(BSL_LS_SOC_PHY, 308 (BSL_META_U(unit, 309 "%s\n"), soc_errmsg(rv))); 310 return rv; 311 } 312 break; 313 case socPortPhyEyescanCounterPrbsPhy: 314 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 315 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_READ_DEADLINK, &error); 316 if (SOC_FAILURE(rv)) { 317 LOG_ERROR(BSL_LS_SOC_PHY, 318 (BSL_META_U(unit, 319 "%s\n"), soc_errmsg(rv))); 320 return rv; 321 } 322 break; 323 default: 324 LOG_ERROR(BSL_LS_SOC_PHY, 325 (BSL_META_U(unit, 326 "counter isn't supported by the device\n"))); 327 return SOC_E_PARAM; 328 break; 329 } 330 } 331 332 *start_time = sal_time_usecs(); 333 334 return rv; 335 } 336 337 STATIC int 338 soc_port_phy_eyescan_start(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter) 339 { 340 int rv = SOC_E_NONE; 341 342 switch(counter) { 343 case socPortPhyEyescanCounterRelativePhy: 344 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 345 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_START_LIVELINK, (void *) (0)); 346 if (SOC_FAILURE(rv)) { 347 LOG_ERROR(BSL_LS_SOC_PHY, 348 (BSL_META_U(unit, 349 "%s\n"), soc_errmsg(rv))); 350 } 351 break; 352 case socPortPhyEyescanCounterPrbsMac: 353 case socPortPhyEyescanCounterPrbsPhy: 354 case socPortPhyEyescanCounterCrcMac: 355 case socPortPhyEyescanCounterBerMac: 356 default: 357 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 358 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_START_DEADLINK, (void *) (0)); 359 if (SOC_FAILURE(rv)) { 360 LOG_ERROR(BSL_LS_SOC_PHY, 361 (BSL_META_U(unit, 362 "%s\n"), soc_errmsg(rv))); 363 } 364 break; 365 } 366 367 return rv; 368 } 369 370 STATIC int 371 soc_port_phy_eyescan_stop(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter, sal_usecs_t* end_time) 372 { 373 int rv = SOC_E_NONE; 374 375 switch(counter) { 376 case socPortPhyEyescanCounterRelativePhy: 377 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 378 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_STOP_LIVELINK, (void *) (0)); 379 if (SOC_FAILURE(rv)) { 380 LOG_ERROR(BSL_LS_SOC_PHY, 381 (BSL_META_U(unit, 382 "%s\n"), soc_errmsg(rv))); 383 return rv; 384 } 385 break; 386 default: 387 break; 388 } 389 390 *end_time = sal_time_usecs(); 391 392 return rv; 393 } 394 395 STATIC int 396 soc_port_phy_eyescan_counter_get(int unit, soc_port_t port, uint32 inst, soc_port_phy_eyscan_counter_t counter, uint32* err_count) 397 { 398 int rv = SOC_E_NONE; 399 400 if(NULL != counter_func[unit][counter].get_func) { 401 counter_func[unit][counter].get_func(unit, port, err_count); 402 } else { 403 404 switch(counter) { 405 case socPortPhyEyescanCounterRelativePhy: 406 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 407 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_READ_LIVELINK, err_count); 408 if (SOC_FAILURE(rv)) { 409 LOG_ERROR(BSL_LS_SOC_PHY, 410 (BSL_META_U(unit, 411 "%s\n"), soc_errmsg(rv))); 412 } 413 break; 414 case socPortPhyEyescanCounterPrbsPhy: 415 rv = soc_phyctrl_diag_ctrl(unit, port, inst, 416 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_READ_DEADLINK, err_count); 417 if (SOC_FAILURE(rv)) { 418 LOG_ERROR(BSL_LS_SOC_PHY, 419 (BSL_META_U(unit, 420 "%s\n"), soc_errmsg(rv))); 421 } 422 break; 423 default: 424 rv = SOC_E_PARAM; 425 LOG_ERROR(BSL_LS_SOC_PHY, 426 (BSL_META_U(unit, 427 "Counter isn't supported by the device\n"))); 428 break; 429 } 430 } 431 432 return rv; 433 } 434 435 #ifdef PHYMOD_SUPPORT 436 int _soc_port_phy_is_glue_driver(int unit, soc_port_t port) 437 { 438 phy_ctrl_t *pc; 439 440 pc = EXT_PHY_SW_STATE(unit, port); 441 if (!pc) { 442 return(0); 443 } 444 if (!pc->pd) { 445 return(0); 446 } 447 448 /* Checking id for Sesto */ 449 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5290)) { 450 return(1); 451 } 452 453 /* Checking id for furia */ 454 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5230)) { 455 return(1); 456 } 457 458 /* Checking id for madura */ 459 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x52b0)) { 460 return(1); 461 } 462 463 /* Checking id for Qudra28 */ 464 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5250)) { 465 return(1); 466 } 467 468 /* Checking id for Dino */ 469 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5390)) { 470 return(1); 471 } 472 473 return(0); 474 } 475 #endif 476 477 int _soc_port_phy_eyescan_run( 478 int unit, 479 uint32 inst, /* phy instance containing phy number and interface */ 480 int flags, 481 soc_port_phy_eyescan_params_t* params, 482 uint32 nof_ports, 483 soc_port_t* ports, 484 int* lane_num, 485 soc_port_phy_eyescan_results_t* results /*array of result per port*/) 486 { 487 #if 0 488 int port=0,index=0; 489 #endif 490 int h,v,j; 491 int under_threshold, first_run, default_sample_time; 492 int total_time, desired_time, time_before; 493 sal_usecs_t* start_time = NULL; 494 sal_usecs_t end_time = 0; 495 uint32 err_count; 496 int* v_init_offset = NULL; 497 soc_port_t* local_ports = NULL; 498 int* local_lane_num = NULL; 499 pbmp_t valid_ports_bitmap; 500 uint32 is_enable; 501 #ifdef PHYMOD_SUPPORT 502 uint32 done; 503 #endif 504 int dev, intf; 505 int rv = SOC_E_NONE; 506 507 /*validate input*/ 508 if (!SOC_UNIT_VALID(unit)) { 509 LOG_ERROR(BSL_LS_SOC_PHY, 510 (BSL_META_U(unit, 511 "Invalid unit\n"))); 512 return SOC_E_UNIT; 513 } 514 515 if (params == NULL || ports == NULL || results == NULL) { 516 LOG_ERROR(BSL_LS_SOC_PHY, 517 (BSL_META_U(unit, 518 "Null parameter\n"))); 519 return SOC_E_PARAM; 520 } 521 522 if(params->counter >= socPortPhyEyescanNofCounters || params->counter < 0) { 523 LOG_ERROR(BSL_LS_SOC_PHY, 524 (BSL_META_U(unit, 525 "Counter %d isn't supported\n"), params->counter)); 526 return SOC_E_PARAM; 527 } 528 529 /*allocate & initialize local_ports array*/ 530 local_ports = (soc_port_t*)sal_alloc(sizeof(soc_port_t)*nof_ports,"eyecan local ports"); 531 for (j = 0; j < nof_ports; j++) { 532 local_ports[j] = -1; 533 } 534 if(NULL == local_ports) { 535 rv = SOC_E_MEMORY; 536 LOG_ERROR(BSL_LS_SOC_PHY, 537 (BSL_META_U(unit, 538 "Failed to allocate local_ports array\n"))); 539 goto exit; 540 } 541 542 /*allocate & initialize local_lane_num array*/ 543 local_lane_num = (int*)sal_alloc(sizeof(int)*nof_ports,"eyecan local_lane_num"); 544 if(NULL == local_lane_num) { 545 rv = SOC_E_MEMORY; 546 LOG_ERROR(BSL_LS_SOC_PHY, 547 (BSL_META_U(unit, 548 "Failed to allocate local_lane_num array\n"))); 549 goto exit; 550 } 551 552 /*get valid ports*/ 553 SOC_PBMP_ASSIGN(valid_ports_bitmap, SOC_INFO(unit).port.bitmap); 554 555 intf = PHY_DIAG_INTF_DFLT; 556 dev = PHY_DIAG_INST_DEV(inst); 557 if (dev == PHY_DIAG_DEV_EXT) { 558 intf = PHY_DIAG_INST_INTF(inst); 559 } 560 561 for(j = 0 ; j < nof_ports ; j++) { 562 if (SOC_PBMP_MEMBER(valid_ports_bitmap, ports[j])) { 563 if (dev == PHY_DIAG_DEV_EXT) { 564 if (lane_num != NULL) { 565 rv = soc_phyctrl_redirect_control_get(unit, ports[j], dev, lane_num[j], 566 (intf == PHY_DIAG_INTF_SYS), SOC_PHY_CONTROL_RX_SEQ_DONE, 567 &is_enable); 568 } else { 569 rv = soc_phyctrl_redirect_control_get(unit, ports[j], dev, -1, 570 (intf == PHY_DIAG_INTF_SYS), 571 SOC_PHY_CONTROL_RX_SEQ_DONE, &is_enable); 572 } 573 if (SOC_FAILURE(rv)) { 574 LOG_ERROR(BSL_LS_SOC_PHY, 575 (BSL_META_U(unit, 576 "%s\n"), soc_errmsg(rv))); 577 goto exit; 578 } 579 } else { 580 rv = soc_phyctrl_control_get(unit, ports[j], 581 SOC_PHY_CONTROL_RX_SEQ_DONE, 582 &is_enable); 583 if (SOC_FAILURE(rv)) { 584 LOG_ERROR(BSL_LS_SOC_PHY, 585 (BSL_META_U(unit, 586 "%s\n"), soc_errmsg(rv))); 587 goto exit; 588 } 589 } 590 if(is_enable) { 591 local_ports[j] = ports[j]; 592 } else { 593 /*do not run eyescan*/ 594 local_ports[j] = -1; 595 } 596 } else { 597 rv = SOC_E_PORT; 598 LOG_ERROR(BSL_LS_SOC_PHY, 599 (BSL_META_U(unit, 600 "Invalid port %d\n"), ports[j])); 601 goto exit; 602 } 603 } 604 605 #ifdef PHYMOD_SUPPORT 606 /*enable BER proj*/ 607 for (j = 0; j < nof_ports; j++) { 608 /*if serdes is unlock continue*/ 609 if (local_ports[j] == -1) continue; 610 if(_soc_port_phy_is_glue_driver(unit, local_ports[j]) && (params->type == 4)) { 611 rv = soc_phyctrl_diag_ctrl(unit, local_ports[j], inst, 612 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_BER, (void *) (params)); 613 if (SOC_FAILURE(rv)) { 614 LOG_ERROR(BSL_LS_SOC_PHY, 615 (BSL_META_U(unit, 616 "%s\n"), soc_errmsg(rv))); 617 goto exit; 618 } 619 /* label this port has been handled */ 620 local_ports[j] = -1; 621 } 622 } 623 624 done = 1; 625 for (j = 0; j < nof_ports; j++) { 626 if(local_ports[j] != -1) { 627 done = 0; 628 break; 629 } 630 } 631 if(done == 1) { 632 goto exit; 633 } 634 #endif 635 636 /* check if the lane num is NULL */ 637 /* pc->lane_num used to indicate which lane to focus on */ 638 /* in the leagcy driver */ 639 if (lane_num != NULL) { 640 phy_ctrl_t *pc; 641 for(j = 0 ; j < nof_ports ; j++) { 642 if (local_ports[j] == -1) continue; 643 pc = INT_PHY_SW_STATE(unit, local_ports[j]); 644 local_lane_num[j] = pc->lane_num; 645 if (pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) { 646 pc->lane_num += lane_num[j]; 647 } else { 648 pc->lane_num = lane_num[j]; 649 } 650 } 651 } 652 653 /*allocate start_time array*/ 654 start_time = (uint32*)sal_alloc(sizeof(sal_usecs_t)*nof_ports,"eyecan start time"); 655 if(NULL == start_time) { 656 rv = SOC_E_MEMORY; 657 LOG_ERROR(BSL_LS_SOC_PHY, 658 (BSL_META_U(unit, 659 "Failed to allocate start_time array\n"))); 660 goto exit; 661 } 662 663 /*allocate v_init_offset array*/ 664 v_init_offset = (int*)sal_alloc(sizeof(int)*nof_ports,"eyecan v_init_offset"); 665 if(NULL == v_init_offset) { 666 rv = SOC_E_MEMORY; 667 LOG_ERROR(BSL_LS_SOC_PHY, 668 (BSL_META_U(unit, 669 "Failed to allocate v_init_offset array\n"))); 670 goto exit; 671 } 672 for(j = 0 ; j < nof_ports ; j++) { 673 v_init_offset[j] = SRD_EYESCAN_INVALID_VOFFSET; 674 } 675 676 /*enable eyescan*/ 677 for (j = 0; j < nof_ports; j++) { 678 /*if serdes is unlock continue*/ 679 if (local_ports[j] == -1) continue; 680 rv = soc_port_phy_eyescan_enable(unit, inst, flags, local_ports[j], params->counter, 1, &(v_init_offset[j])); 681 if (SOC_FAILURE(rv)) { 682 LOG_ERROR(BSL_LS_SOC_PHY, 683 (BSL_META_U(unit, 684 "%s\n"), soc_errmsg(rv))); 685 goto exit; 686 } 687 } 688 689 sal_usleep(100000); 690 /*check bounds*/ 691 for (j = 0; j < nof_ports; j++) { 692 /*if serdes is unlock continue*/ 693 if (local_ports[j] == -1) continue; 694 rv = soc_port_phy_eyescan_check_bounds(unit, local_ports[j], inst, flags, params->counter, &(params->bounds)); 695 if (SOC_FAILURE(rv)) { 696 LOG_ERROR(BSL_LS_SOC_PHY, 697 (BSL_META_U(unit, 698 "%s\n"), soc_errmsg(rv))); 699 goto exit; 700 } 701 } 702 703 default_sample_time = params->sample_time; 704 705 /*scan*/ 706 for(h = params->bounds.horizontal_min; h <= params->bounds.horizontal_max; h++) { 707 if(h % params->sample_resolution != 0) { 708 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){ 709 continue; 710 } 711 } 712 desired_time = 0; 713 params->sample_time = default_sample_time; 714 715 for(v = params->bounds.vertical_max; v >= params->bounds.vertical_min; v--) { 716 if(v % params->sample_resolution != 0) { 717 continue; 718 } 719 720 if (flags & SRD_EYESCAN_FLAG_DSC_PRINT) { 721 LOG_CLI((BSL_META_U(unit, 722 "\nStarting BER msmt at offset: v=%d h=%d\n"), v, h)); 723 } 724 725 under_threshold = params->nof_threshold_links; 726 first_run = 1; 727 total_time = 0; 728 for (j = 0; j < nof_ports; j++) { 729 /*if serdes is unlock continue*/ 730 if (local_ports[j] == -1) continue; 731 732 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0; 733 results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0; 734 } 735 736 while ((under_threshold >= params->nof_threshold_links) && (params->sample_time <= params->time_upper_bound)) { 737 under_threshold = 0; 738 if (first_run) { 739 desired_time = params->sample_time; 740 total_time = params->sample_time; 741 } else { 742 if ((desired_time >= params->time_upper_bound) || (total_time >= params->time_upper_bound)) { 743 params->sample_time = (params->time_upper_bound + 1); 744 break; 745 } 746 desired_time = desired_time * TIME_MULTIPLIER; 747 params->sample_time = desired_time - total_time; 748 if (params->sample_time > params->time_upper_bound) { 749 params->sample_time = params->time_upper_bound - total_time; 750 } 751 total_time += params->sample_time; 752 } 753 754 for (j = 0; (j < nof_ports); j++) { 755 /*if serdes is unlock continue*/ 756 if (local_ports[j] == -1) continue; 757 758 if (first_run) { 759 /*set vertical and horizinal*/ 760 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)) { 761 rv = soc_phyctrl_diag_ctrl(unit, local_ports[j], inst, 762 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_HOFFSET, (int*) (&h)); 763 if (SOC_FAILURE(rv)) { 764 LOG_ERROR(BSL_LS_SOC_PHY, 765 (BSL_META_U(unit, 766 "%s\n"), soc_errmsg(rv))); 767 goto exit; 768 } 769 } 770 rv = soc_phyctrl_diag_ctrl(unit, local_ports[j], inst, 771 PHY_DIAG_CTRL_CMD, PHY_DIAG_CTRL_EYE_SET_VOFFSET, (int *) (&v));/*start measure*/ 772 if (SOC_FAILURE(rv)) { 773 LOG_ERROR(BSL_LS_SOC_PHY, 774 (BSL_META_U(unit, 775 "%s\n"), soc_errmsg(rv))); 776 goto exit; 777 } 778 rv = soc_port_phy_eyescan_start(unit, local_ports[j], inst, params->counter); 779 if (SOC_FAILURE(rv)) { 780 LOG_ERROR(BSL_LS_SOC_PHY, 781 (BSL_META_U(unit, 782 "%s\n"), soc_errmsg(rv))); 783 goto exit; 784 } 785 786 if ((flags & SRD_EYESCAN_FLAG_DSC_PRINT)){ 787 soc_phyctrl_control_set(unit, local_ports[j], SOC_PHY_CONTROL_DUMP, 1); 788 } 789 } 790 791 /*clear counters*/ 792 rv = soc_port_phy_eyescan_counter_clear(unit, local_ports[j], inst, params->counter, &(start_time[j])); 793 if (SOC_FAILURE(rv)) { 794 LOG_ERROR(BSL_LS_SOC_PHY, 795 (BSL_META_U(unit, 796 "%s\n"), soc_errmsg(rv))); 797 goto exit; 798 } 799 } 800 sal_usleep(params->sample_time*1000); 801 802 for (j = 0; j < nof_ports; j++) { 803 804 /*if serdes is unlock continue*/ 805 if (local_ports[j] == -1) continue; 806 807 /*stop measure*/ 808 rv = soc_port_phy_eyescan_stop(unit, local_ports[j], inst, params->counter, &end_time); 809 if (SOC_FAILURE(rv)) { 810 LOG_ERROR(BSL_LS_SOC_PHY, 811 (BSL_META_U(unit, 812 "%s\n"), soc_errmsg(rv))); 813 goto exit; 814 } 815 rv = soc_port_phy_eyescan_counter_get(unit, local_ports[j], inst, params->counter, &err_count); 816 if (SOC_FAILURE(rv)) { 817 LOG_ERROR(BSL_LS_SOC_PHY, 818 (BSL_META_U(unit, 819 "%s\n"), soc_errmsg(rv))); 820 goto exit; 821 } 822 823 time_before = results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX]; 824 825 if(end_time > start_time[j]) { 826 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] += (end_time - start_time[j])/1000; 827 } else { 828 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] += ((SAL_USECS_TIMESTAMP_ROLLOVER - start_time[j]) + end_time)/1000; 829 } 830 results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] += (err_count); 831 832 if (results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] < params->error_threshold) { 833 under_threshold++; 834 } 835 836 if (flags & SRD_EYESCAN_FLAG_DSC_PRINT) { 837 LOG_CLI((BSL_META_U(unit, 838 "Added %d errors in %d miliseconds for port %d\n"), err_count, (results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] - time_before), local_ports[j])); 839 } 840 #if 0 841 port = local_ports[j]; 842 index = j; 843 #endif 844 } 845 846 first_run = 0; 847 if (params->counter == socPortPhyEyescanCounterRelativePhy) { 848 break; 849 } 850 } 851 if (first_run) { 852 for (j = 0; j < nof_ports; j++) { 853 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = (params->sample_time-1); 854 } 855 } 856 857 if ((params->counter != socPortPhyEyescanCounterRelativePhy) && (desired_time < params->time_upper_bound)) { 858 params->sample_time = total_time; 859 } 860 861 if ((params->sample_time < params->time_upper_bound) && (total_time >= params->time_upper_bound)) { 862 params->sample_time = params->time_upper_bound; 863 } 864 } 865 866 if(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY) { 867 break; 868 } 869 } 870 871 /*highest number of errors for unlock serdes*/ 872 for (j = 0; j < nof_ports; j++) { 873 /*if serdes is unlock continue*/ 874 if (local_ports[j] != -1) continue; 875 876 LOG_CLI((BSL_META_U(unit, 877 "ERROR: link %d is unlock.\n"), ports[j])); 878 /*error results*/ 879 for(h = params->bounds.horizontal_min ; h <= params->bounds.horizontal_max ; h++) { 880 if(h % params->sample_resolution != 0) { 881 if(!(flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY)){ 882 continue; 883 } 884 } 885 for (v = params->bounds.vertical_min ; v <= params->bounds.vertical_max ; v++) { 886 if(v % params->sample_resolution != 0) { 887 continue; 888 } 889 890 results[j].run_time[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0; 891 results[j].error_count[h + SOC_PORT_PHY_EYESCAN_H_INDEX][v + SOC_PORT_PHY_EYESCAN_V_INDEX] = 0; 892 893 } 894 } 895 } 896 897 exit: 898 if (start_time != NULL) { 899 sal_free(start_time); 900 } 901 902 if (v_init_offset) { 903 904 /*disable eyescan mode*/ 905 for (j = 0; j < nof_ports; j++) { 906 /*if serdes is unlock continue*/ 907 if (local_ports != NULL) { 908 if (local_ports[j] == -1) continue; 909 910 soc_port_phy_eyescan_enable(unit, inst, flags, local_ports[j], params->counter, 0, &(v_init_offset[j])); 911 } 912 } 913 if (v_init_offset != NULL) { 914 sal_free(v_init_offset); 915 } 916 } 917 918 /* check if the lane num needs to be recovered */ 919 if (lane_num != NULL) { 920 phy_ctrl_t *pc; 921 for (j = 0 ; j < nof_ports ; j++) { 922 if (local_ports != NULL) { 923 if (local_ports[j] == -1) continue; 924 pc = INT_PHY_SW_STATE(unit, local_ports[j]); 925 if (local_lane_num != NULL) { 926 pc->lane_num = local_lane_num[j]; 927 } 928 } 929 } 930 } 931 932 if (local_ports != NULL) { 933 sal_free(local_ports); 934 } 935 if (local_lane_num != NULL) { 936 sal_free(local_lane_num); 937 } 938 939 return rv; 940 } 941 942 #ifdef PHYMOD_SUPPORT 943 944 /* 945 * The term "legacy mode" here is referred to the code before TSCE/TSCF projects. 946 * TSCE/TSCE introduces the capability to use uC to assist eyescan, ber and etc. 947 * The legacy mode/method used pd_diag_ctrl channel. However, a phy glue logic 948 * could build the phy_diag_ctrl channel on the surface as well, but still 949 * deploy the uC assist deep down. 950 */ 951 int is_eyescan_algorithm_legacy_mode(int unit, uint32 nof_ports, soc_port_t* ports, uint32 inst) 952 { 953 int legacy; 954 phy_ctrl_t *pc; 955 soc_phymod_ctrl_t *pmc; 956 soc_phymod_phy_t *phy; 957 958 legacy = 1; /* 1 means to use phy_diag_ctrl legacy mode/method */ 959 960 if (!nof_ports) return (legacy); 961 962 if (!ext_phy_ctrl[unit]) { 963 return (0); 964 } 965 /* external phy */ 966 if (PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_EXT) { 967 pc = EXT_PHY_SW_STATE(unit, ports[0]); 968 969 if (soc_feature(unit, soc_feature_portmod)) { 970 /* some phymod device could use phy_diag mode 971 * currently a NULL under portmod is assigned for phymod 972 * and phymod is assumed to be all non phy_diag mode 973 */ 974 if (!pc) { 975 return (0); 976 } 977 if (!pc->pd) { 978 return (0); 979 } 980 } else { 981 if (!pc || !pc->pd) { 982 LOG_ERROR(BSL_LS_SOC_PHY, 983 (BSL_META_U(unit, 984 "Ext Phy ID0: non portmod mode has NULL extPHY\n"))); 985 return (0); 986 } 987 } 988 /* if pc is available, use the following check to figure 989 * out legacy mode or not 990 */ 991 LOG_INFO(BSL_LS_SOC_PHY, 992 (BSL_META_U(unit, 993 "Ext Phy ID0: 0x%X, Phy ID1: 0x%X Phy Model: 0x%X \n"), 994 pc->phy_id0, pc->phy_id1, pc->phy_model)); 995 996 /* Note: 997 * we should phase out the following code methods soon 998 * for accuracy and portability. 999 */ 1000 /* Checking id for furia */ 1001 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5230)) { 1002 legacy = 0; 1003 } 1004 /* Checking id for QSGMIIE and viper*/ 1005 if ((pc->phy_id0 == 0x0143) && (pc->phy_id1 == 0xbff0)) { 1006 legacy = 0; 1007 } 1008 /* Checking id for Qudra28 */ 1009 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5250)) { 1010 legacy = 0; 1011 } 1012 /* Checking id for Sesto */ 1013 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x5290)) { 1014 legacy = 0; 1015 } 1016 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x52b0)) { 1017 legacy = 0; 1018 } 1019 /* Checking id for PHY8806X */ 1020 if ((pc->phy_id0 == 0xae02) && (pc->phy_id1 == 0x52c0)) { 1021 legacy = 0; 1022 } 1023 } else { 1024 /* 1025 * internal phy 1026 */ 1027 if (soc_feature(unit, soc_feature_portmod)) { 1028 /* Under portmod, internal phymod is assumed to be non phy_diag_ctrl mode. 1029 * But the assumption could be wrong one day. 1030 */ 1031 return 0 ; 1032 } else { 1033 pc = INT_PHY_SW_STATE(unit, ports[0]); 1034 if (!pc) { 1035 return(0); 1036 } 1037 LOG_INFO(BSL_LS_SOC_PHY, 1038 (BSL_META_U(unit, 1039 "Int Phy ID0: 0x%X, Phy ID1: 0x%X Phy Model: 0x%X \n"), 1040 pc->phy_id0, pc->phy_id1, pc->phy_model)); 1041 1042 /* Note: 1043 * we should phase out the following code methods soon 1044 * for accuracy and portability. 1045 */ 1046 if ((pc->phy_id0 == 0x143) && (pc->phy_id1 == 0xbff0) && (pc->phy_model == 0x3f)) { 1047 return (legacy); 1048 } 1049 /* Checking id for TSC/WC family; check phymod object for TSCE/TSCF */ 1050 if ((pc->phy_id0 == 0x600d) && (pc->phy_id1 == 0x8770)) { 1051 pmc = &pc->phymod_ctrl; 1052 if (pmc != NULL) { 1053 phy = pmc->phy[0]; 1054 if (phy != NULL) { 1055 legacy = 0 ; 1056 } 1057 } 1058 } 1059 } 1060 } 1061 return (legacy); 1062 } 1063 1064 /* 1065 Some phyctrl_diag mode is using uC assist. Then it doesn't need to use the reporting code 1066 from the legacy method. 1067 */ 1068 int is_eyescan_algorithm_legacy_rpt_mode(int unit, uint32 nof_ports, soc_port_t* ports, uint32 inst) 1069 { 1070 /* need to expand more cases */ 1071 return is_eyescan_algorithm_legacy_mode(unit, nof_ports, ports, inst) ; 1072 } 1073 1074 const phymod_phy_access_t* _get_phymod_phy_access(soc_phymod_ctrl_t *pmc, int phy_idx) 1075 { 1076 if (!pmc) return (NULL); 1077 if (!pmc->phy[phy_idx]) return (NULL); 1078 return(&pmc->phy[phy_idx]->pm_phy); 1079 } 1080 1081 /* 1082 To find out what is the first lane position (0, 1, ...) 1083 for a given port. Retunr the lane postion value or -1. 1084 */ 1085 int first_lane_mask_position(uint32 lane_mask) { 1086 int lane_pos =0, found=0 ; 1087 1088 while(lane_mask) { 1089 if(lane_mask & 0x1) { 1090 found = 1 ; 1091 break ; 1092 } 1093 lane_pos +=1 ; 1094 lane_mask >>= 1 ; 1095 } 1096 if(found) { return lane_pos ; } 1097 else { return -1 ; } 1098 } 1099 1100 STATIC int 1101 _soc_port_generate_phy_array( 1102 int unit, 1103 uint32 inst, /* phy instance containing phy number and interface */ 1104 uint32 nof_ports, 1105 soc_port_t* ports, 1106 int* lane_num, /* array of lane index offset 0, 1, ... */ 1107 int lane, /* secondray lane offset indication */ 1108 int check_pmd_lock, 1109 int phy_acc_max_length, 1110 phymod_phy_access_t* phy_acc, /* out */ 1111 int* port_ids, /* out */ 1112 int* line_rates, /* out, optional */ 1113 int* phy_acc_length /* out */) 1114 1115 { 1116 int phy_acc_count, j, idx; 1117 int local_lane_num, rv; 1118 soc_phymod_ctrl_t *pmc = NULL; 1119 phy_ctrl_t *pc; 1120 const phymod_phy_access_t *pa; 1121 uint32 locked; 1122 int lane_pos=0; 1123 int is_legacy = 0; 1124 1125 /* Generate phys array */ 1126 phy_acc_count = 0; 1127 for(j = 0 ; j < nof_ports ; j++) { 1128 1129 if(!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), ports[j])){ 1130 LOG_ERROR(BSL_LS_SOC_PHY, 1131 (BSL_META_U(unit, "Port %d can't run eyescan \n"), ports[j])); 1132 continue; 1133 } 1134 if ((j == 0) && (PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_EXT)) { 1135 if ((ext_phy_ctrl[unit]) && (pc = EXT_PHY_SW_STATE(unit, ports[0])) && (pc->pd)) { 1136 is_legacy = 1; 1137 } 1138 } 1139 1140 if ((soc_feature(unit, soc_feature_portmod)) && !is_legacy) { 1141 #ifdef PORTMOD_SUPPORT 1142 uint32 saved_lane_mask[3]; 1143 int i; 1144 portmod_access_get_params_t params; 1145 phymod_phy_access_t access[PHYMOD_CONFIG_MAX_CORES_PER_PORT]; 1146 int nof_phys, dev, intf; 1147 portmod_port_interface_config_t if_config; 1148 1149 intf = PHY_DIAG_INTF_DFLT; 1150 portmod_access_get_params_t_init(unit, ¶ms); 1151 1152 params.lane = lane_num ? lane_num[j] : lane; 1153 params.phyn = 0; /* internal phy */ 1154 params.apply_lane_mask = 1; 1155 1156 dev = PHY_DIAG_INST_DEV(inst); 1157 if (dev == PHY_DIAG_DEV_EXT) { 1158 params.phyn = 1; /* external phy */ 1159 intf = PHY_DIAG_INST_INTF(inst); 1160 if(intf == PHY_DIAG_INTF_SYS) { 1161 params.sys_side = PORTMOD_SIDE_SYSTEM; 1162 } else { 1163 params.sys_side = PORTMOD_SIDE_LINE; 1164 } 1165 } 1166 1167 /* it picks one lane or all lane mask based on params.lane */ 1168 rv = portmod_port_phy_lane_access_get(unit, ports[j], ¶ms, PHYMOD_CONFIG_MAX_CORES_PER_PORT, 1169 access, &nof_phys, NULL); 1170 SOC_IF_ERROR_RETURN(rv); 1171 1172 1173 if ( nof_phys == 3 ){ 1174 for(i=0; i < nof_phys; i++) { 1175 saved_lane_mask[i] = access[i].access.lane_mask; 1176 access[i].access.lane_mask = 0; /* need this to do compare. */ 1177 } 1178 1179 if( !sal_memcmp( &access[0],&access[1], sizeof(phymod_phy_access_t)) && 1180 !sal_memcmp( &access[0],&access[2], sizeof(phymod_phy_access_t))){ 1181 access[0].access.lane_mask = ( saved_lane_mask[0]| saved_lane_mask[1]| saved_lane_mask[2]); 1182 phymod_access_t_init(&access[1].access); 1183 phymod_access_t_init(&access[2].access); 1184 /* cli_out("Consolidating entries.\n");*/ 1185 nof_phys = 1; 1186 } else { 1187 /* restore lane mask */ 1188 for(i=0; i < nof_phys; i++) { 1189 access[i].access.lane_mask = saved_lane_mask[i]; 1190 } 1191 } 1192 } 1193 1194 for(idx = 0 ; idx < nof_phys ; idx++) { 1195 pa = &(access[idx]); 1196 1197 if(check_pmd_lock) { 1198 rv = phymod_phy_rx_pmd_locked_get(pa, &locked); 1199 SOC_IF_ERROR_RETURN(rv); 1200 1201 if(!locked) { 1202 if(nof_phys > 1) { 1203 LOG_WARN(BSL_LS_SOC_PHY, 1204 (BSL_META_U(unit, "p=%d phy idx=%0d is skipped, phy rx isn't locked \n"), ports[j], idx)); 1205 } else { 1206 LOG_WARN(BSL_LS_SOC_PHY, 1207 (BSL_META_U(unit, "Port %d is skipped, Phy RX isn't locked \n"), ports[j])); 1208 } 1209 continue; 1210 } 1211 } 1212 1213 if(phy_acc_count >= phy_acc_max_length) { 1214 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1215 "ERROR: No space left for phy_acc\n"))); 1216 return SOC_E_INTERNAL; 1217 } 1218 1219 if(line_rates) { 1220 rv = portmod_port_interface_config_get(unit, ports[j], &if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 1221 SOC_IF_ERROR_RETURN(rv); 1222 line_rates[phy_acc_count] = if_config.speed; 1223 } 1224 1225 sal_memcpy(&(phy_acc[phy_acc_count]), pa, sizeof(phymod_phy_access_t)); 1226 port_ids[phy_acc_count] = ports[j] ; 1227 phy_acc_count++; 1228 } 1229 1230 #endif /*PORTMOD_SUPPORT*/ 1231 } else { 1232 int intf = PHY_DIAG_INTF_DFLT; 1233 int dev = PHY_DIAG_INST_DEV(inst); 1234 if (dev == PHY_DIAG_DEV_EXT) { 1235 pc = EXT_PHY_SW_STATE(unit, ports[j]); 1236 } else { 1237 pc = INT_PHY_SW_STATE(unit, ports[j]); 1238 } 1239 1240 if (pc == NULL) { 1241 LOG_ERROR(BSL_LS_SOC_PHY, 1242 (BSL_META_U(unit, "Err: port %d, pc is NULL \n"), ports[j])); 1243 continue; 1244 } 1245 1246 if (dev == PHY_DIAG_DEV_EXT) { 1247 intf = PHY_DIAG_INST_INTF(inst); 1248 if (intf == PHY_DIAG_INTF_SYS) { 1249 pc->flags |= PHYCTRL_SYS_SIDE_CTRL; 1250 } else { 1251 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL; 1252 } 1253 } 1254 1255 pmc = &pc->phymod_ctrl; 1256 if (pmc == NULL) { 1257 LOG_ERROR(BSL_LS_SOC_PHY, 1258 (BSL_META_U(unit, "Err: port %d, pmc is NULL \n"), ports[j])); 1259 continue; 1260 } 1261 1262 local_lane_num = pc->lane_num; /* pc->lane_num used to indicate which lane to focus on */ 1263 if (lane_num != NULL) { /* in the leagcy driver */ 1264 pc->lane_num = lane_num[j]; 1265 } 1266 #ifdef INCLUDE_FCMAP 1267 else if (pc->fcmap_enable && (intf == PHY_DIAG_INTF_LINE)) { 1268 pc->lane_num = 0; 1269 } 1270 #endif 1271 1272 for (idx = 0; idx < pmc->num_phys; idx++) { 1273 pa = _get_phymod_phy_access(pmc, idx); 1274 if (!pa) { 1275 if(pmc->num_phys>1) { 1276 LOG_ERROR(BSL_LS_SOC_PHY, 1277 (BSL_META_U(unit, 1278 "ERROR: p=%0d phymod idx=%0d access is NULL\n"), ports[j], idx)); 1279 } else { 1280 LOG_ERROR(BSL_LS_SOC_PHY, 1281 (BSL_META_U(unit, 1282 "ERROR: phymod Access on port%d is NULL\n"), ports[j])); 1283 } 1284 continue; 1285 } 1286 1287 if(check_pmd_lock) { 1288 rv = phymod_phy_rx_pmd_locked_get(pa, &locked); 1289 SOC_IF_ERROR_RETURN(rv); 1290 1291 if(!locked) { 1292 if(pmc->num_phys>1) { 1293 LOG_WARN(BSL_LS_SOC_PHY, 1294 (BSL_META_U(unit, "p=%d phy idx=%0d is skipped, phy rx isn't locked \n"), ports[j], idx)); 1295 } else { 1296 LOG_WARN(BSL_LS_SOC_PHY, 1297 (BSL_META_U(unit, "Port %d is skipped, Phy RX isn't locked \n"), ports[j])); 1298 } 1299 continue; 1300 } 1301 } 1302 1303 if(phy_acc_count >= phy_acc_max_length) { 1304 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1305 "ERROR: No space left for phy_acc\n"))); 1306 pc->lane_num = local_lane_num; 1307 return SOC_E_INTERNAL; 1308 } 1309 1310 if(line_rates) { 1311 rv = soc_phyctrl_speed_get(unit, ports[j], &(line_rates[phy_acc_count])); 1312 if(SOC_FAILURE(rv)) { 1313 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1314 "ERROR: Failed to retrive speed for port %d \n"), ports[j])); 1315 pc->lane_num = local_lane_num; 1316 return SOC_E_INTERNAL; 1317 } 1318 } 1319 port_ids[phy_acc_count] = ports[j] ; 1320 sal_memcpy(&(phy_acc[phy_acc_count]), pa, sizeof(phymod_phy_access_t)); 1321 /* fix the lane mask by lane_num */ 1322 if(lane_num != NULL) { 1323 lane_pos = first_lane_mask_position(phy_acc[phy_acc_count].access.lane_mask) ; 1324 if(lane_pos>=0) { 1325 phy_acc[phy_acc_count].access.lane_mask &= (1<< (lane_num[j]+lane_pos)) ; 1326 } 1327 /* lane_mask exception is handled later in the functions call this code */ 1328 } 1329 #ifdef INCLUDE_FCMAP 1330 else if (pc->fcmap_enable && (intf == PHY_DIAG_INTF_LINE)) { 1331 lane_pos = first_lane_mask_position(phy_acc[phy_acc_count].access.lane_mask) ; 1332 if(lane_pos>=0) { 1333 phy_acc[phy_acc_count].access.lane_mask &= (1<< lane_pos) ; 1334 } 1335 } 1336 #endif 1337 phy_acc_count++; 1338 } 1339 pc->lane_num = local_lane_num; 1340 } /* soc_feature_portmod else */ 1341 } 1342 1343 *phy_acc_length = phy_acc_count; 1344 return SOC_E_NONE; 1345 } 1346 1347 int _soc_port_phy_eyescan_run_lowber( 1348 int unit, 1349 uint32 inst, /* phy instance containing phy number and interface */ 1350 int flags, 1351 soc_port_phy_eyescan_params_t* params, 1352 uint32 nof_ports, 1353 soc_port_t* ports, 1354 int* lane_num, 1355 soc_port_phy_eyescan_results_t* results) /*array of result per port*/ 1356 { 1357 phymod_phy_access_t* phy_acc = NULL; 1358 phymod_phy_eyescan_options_t eyescan_options; 1359 int rv = SOC_E_NONE; 1360 int* line_rates; 1361 int* port_ids; 1362 int array_max_size, phy_acc_length; 1363 int i; 1364 /*validate input*/ 1365 if (params == NULL || ports == NULL || results == NULL) { 1366 LOG_ERROR(BSL_LS_SOC_PHY, 1367 (BSL_META_U(unit, 1368 "Null parameter\n"))); 1369 return SOC_E_PARAM; 1370 } 1371 1372 if(params->counter >= socPortPhyEyescanNofCounters || params->counter < 0) { 1373 LOG_ERROR(BSL_LS_SOC_PHY, 1374 (BSL_META_U(unit, 1375 "Counter %d isn't supported\n"), params->counter)); 1376 return SOC_E_PARAM; 1377 } 1378 1379 1380 /* default_sample_time = params->sample_time; */ 1381 eyescan_options.timeout_in_milliseconds = params->sample_time; 1382 eyescan_options.horz_max = params->bounds.horizontal_max; 1383 eyescan_options.horz_min = params->bounds.horizontal_min; 1384 eyescan_options.hstep = params->sample_resolution; 1385 eyescan_options.vert_max = params->bounds.vertical_max; 1386 eyescan_options.vert_min = params->bounds.vertical_min; 1387 eyescan_options.vstep = params->sample_resolution; 1388 eyescan_options.mode = (params->type == 3)? 1 << 2: 0; /*Mode should be DIAG_BER_INTR for type3*/ 1389 /* following param are used in BER projection */ 1390 eyescan_options.ber_proj_scan_mode = params->ber_proj_scan_mode; 1391 eyescan_options.ber_proj_timer_cnt = params->ber_proj_timer_cnt; 1392 eyescan_options.ber_proj_err_cnt = params->ber_proj_err_cnt; 1393 1394 /* Allocate Mem */ 1395 array_max_size = nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT; 1396 phy_acc = (phymod_phy_access_t*) sal_alloc(sizeof(phymod_phy_access_t)*array_max_size, "eyescan phymod_phy_access_t"); 1397 line_rates = (int*)sal_alloc(sizeof(int)*array_max_size, "eyescan line rates"); 1398 port_ids = (int*)sal_alloc(sizeof(int)*array_max_size, "eyescan port ids"); 1399 if(NULL == phy_acc || NULL == line_rates || NULL == port_ids) { 1400 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1401 "Failed to allocate Memory phy_acc=%d line_rates=%d\n"), phy_acc?1:0, line_rates?1:0)); 1402 rv = SOC_E_MEMORY; 1403 goto exit; 1404 } 1405 1406 sal_memset(phy_acc, 0, sizeof(phymod_phy_access_t)*array_max_size); 1407 1408 #if defined(BCM_TOMAHAWK3_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT) 1409 /* For TH3, only front panel ports support this eyescan mode. 1410 * For front panel ports (PM8x50), we do not need line_rates here. 1411 * So pass NULL as input for lint_rates. 1412 */ 1413 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) { 1414 rv = _soc_port_generate_phy_array(unit, 1415 inst, 1416 nof_ports, 1417 ports, 1418 lane_num, 1419 -1, 1420 1, 1421 array_max_size, 1422 phy_acc, 1423 port_ids, 1424 NULL, 1425 &phy_acc_length); 1426 } else 1427 #endif 1428 { 1429 /* Generate phys array */ 1430 rv = _soc_port_generate_phy_array(unit, 1431 inst, 1432 nof_ports, 1433 ports, 1434 lane_num, 1435 -1, 1436 1, 1437 array_max_size, 1438 phy_acc, 1439 port_ids, 1440 line_rates, 1441 &phy_acc_length); 1442 } 1443 if(SOC_FAILURE(rv)) { 1444 goto exit; 1445 } 1446 1447 for(i=0; i < phy_acc_length; i++) { 1448 if (phy_acc[i].access.lane_mask == 0) { 1449 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, "Illegal lane_mask of 0 on port %d, aborted.\n"), port_ids[i])); 1450 goto exit; 1451 } 1452 } 1453 1454 /*enable eyescan*/ 1455 if(params->type == 4) { 1456 rv = phymod_diag_eyescan_run(phy_acc, unit, port_ids, line_rates, phy_acc_length, phymodEyescanModeBERProj, &eyescan_options); 1457 } else if(params->type >4) { 1458 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1459 "Eyescan type %d is not supported (type should be <= 4)\n"), params->type)); 1460 goto exit; 1461 } else { 1462 rv = phymod_diag_eyescan_run(phy_acc, unit, port_ids, line_rates, phy_acc_length, phymodEyescanModeLowBER, &eyescan_options); 1463 } 1464 1465 1466 exit: 1467 if(phy_acc != NULL) { 1468 sal_free(phy_acc); 1469 } 1470 if(line_rates != NULL) { 1471 sal_free(line_rates); 1472 } 1473 if(port_ids != NULL) { 1474 sal_free(port_ids); 1475 } 1476 return rv; 1477 } 1478 1479 /* no eyescan params requred */ 1480 int _soc_port_phy_eyescan_run_fast_uc( 1481 int unit, 1482 uint32 inst, /* phy instance containing phy number and interface */ 1483 int flags, 1484 soc_port_phy_eyescan_params_t* params, 1485 uint32 nof_ports, 1486 soc_port_t* ports, 1487 int* lane_num, 1488 soc_port_phy_eyescan_results_t* results) /*array of result per port*/ 1489 { 1490 phymod_phy_access_t *phy_acc; 1491 1492 int phy_acc_length; 1493 int rv = SOC_E_NONE; 1494 int i; 1495 int *port_ids ; 1496 1497 /*validate input*/ 1498 if (!SOC_UNIT_VALID(unit)) { 1499 LOG_ERROR(BSL_LS_SOC_PHY, 1500 (BSL_META_U(unit, 1501 "Invalid unit\n"))); 1502 return SOC_E_UNIT; 1503 } 1504 1505 if (params == NULL || ports == NULL || results == NULL) { 1506 LOG_ERROR(BSL_LS_SOC_PHY, 1507 (BSL_META_U(unit, 1508 "Null parameter\n"))); 1509 return SOC_E_PARAM; 1510 } 1511 1512 /* Allocate Mem */ 1513 phy_acc = (phymod_phy_access_t*) sal_alloc(sizeof(phymod_phy_access_t)*nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT, "eyescan phymod_phy_access_t"); 1514 if(NULL == phy_acc) { 1515 LOG_ERROR(BSL_LS_SOC_PHY, 1516 (BSL_META_U(unit, 1517 "Failed to allocate Memory for phy_acc\n"))); 1518 return SOC_E_MEMORY; 1519 } 1520 port_ids = (int*)sal_alloc(sizeof(int)*nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT, "eyescan port ids"); 1521 if(NULL == port_ids) { 1522 sal_free(phy_acc); 1523 LOG_ERROR(BSL_LS_SOC_PHY, 1524 (BSL_META_U(unit, 1525 "Failed to allocate Memory for port_ids.\n"))); 1526 return SOC_E_MEMORY; 1527 } 1528 sal_memset(phy_acc, 0, sizeof(phymod_phy_access_t)*nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT); 1529 /* Generate phys array */ 1530 #if defined(BCM_MONTEREY_SUPPORT) 1531 if ((IS_CPRI_PORT(unit, ports[0])) && SOC_IS_MONTEREY(unit)) { 1532 rv = _soc_port_generate_phy_array(unit, 1533 inst, 1534 nof_ports, 1535 ports, 1536 lane_num, 1537 /* lane, */ 1538 -1, 1539 0, 1540 nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT, 1541 phy_acc, 1542 port_ids, 1543 NULL, 1544 &phy_acc_length); 1545 } else 1546 #endif 1547 { 1548 rv = _soc_port_generate_phy_array(unit, 1549 inst, 1550 nof_ports, 1551 ports, 1552 lane_num, 1553 /* lane, */ 1554 -1, 1555 1, 1556 nof_ports*PHYMOD_CONFIG_MAX_CORES_PER_PORT, 1557 phy_acc, 1558 port_ids, 1559 NULL, 1560 &phy_acc_length); 1561 } 1562 if(SOC_FAILURE(rv)) { 1563 goto exit; 1564 } 1565 1566 for(i=0; i < phy_acc_length; i++ ) { 1567 if ( phy_acc[i].access.lane_mask == 0 ) { 1568 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, "p=%0d lane_mask=0 causes to abort.\n"), port_ids[i])); 1569 goto exit; 1570 } 1571 } 1572 1573 /* Run fast eyescan: no eyescan options required */ 1574 rv = phymod_diag_eyescan_run(phy_acc, unit, port_ids, NULL, phy_acc_length, phymodEyescanModeFast, NULL); 1575 exit: 1576 if(phy_acc != NULL) { 1577 sal_free(phy_acc); 1578 } 1579 if(port_ids != NULL) { 1580 sal_free(port_ids); 1581 } 1582 return rv; 1583 } 1584 #endif 1585 1586 1587 /* Please consult thephymod team firt before modify this function or functions called inside */ 1588 /* this function. each port group in the function argument would be required to expect the */ 1589 /* same phy_diag call mode or phymod call mode. */ 1590 1591 int soc_port_phy_eyescan_run ( 1592 int unit, 1593 uint32 inst, /* phy instance containing phy number and interface */ 1594 int flags, 1595 soc_port_phy_eyescan_params_t* params, 1596 uint32 nof_ports, 1597 soc_port_t* ports, 1598 int* lane_num, 1599 soc_port_phy_eyescan_results_t* results /*array of result per port*/) 1600 { 1601 #ifdef PHYMOD_SUPPORT 1602 1603 if (is_eyescan_algorithm_legacy_mode(unit, nof_ports, ports,inst)) { 1604 return _soc_port_phy_eyescan_run(unit, inst, flags, params, nof_ports, 1605 ports, lane_num, results); 1606 } else { 1607 int rv, i; 1608 int *saved_intf = NULL; 1609 phy_ctrl_t *pc = NULL; 1610 int is_legacy = 0; 1611 1612 if (PHY_DIAG_INST_DEV(inst) == PHY_DIAG_DEV_EXT) { 1613 if ((ext_phy_ctrl[unit]) && (pc = EXT_PHY_SW_STATE(unit, ports[0])) && (pc->pd)) { 1614 is_legacy = 1; 1615 } 1616 } 1617 1618 if ((!soc_feature(unit, soc_feature_portmod)) || (is_legacy)) { 1619 /* First, Save the PhyCtrl SYS/LINE Flags */ 1620 saved_intf = sal_alloc((nof_ports) * sizeof(int), "eyescan saved intf"); 1621 if (saved_intf != NULL) { 1622 for(i=0; i<nof_ports; i++ ) { 1623 int dev = PHY_DIAG_INST_DEV(inst); 1624 if (dev == PHY_DIAG_DEV_EXT) { 1625 pc = EXT_PHY_SW_STATE(unit, ports[i]); 1626 } else { 1627 pc = INT_PHY_SW_STATE(unit, ports[i]); 1628 } 1629 if(pc == NULL) { 1630 LOG_ERROR(BSL_LS_SOC_PHY, (BSL_META_U(unit, "Can not find port INT/EXT phy\n"))); 1631 sal_free(saved_intf); 1632 return SOC_E_INTERNAL; 1633 } 1634 saved_intf[i] = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? 1 : 0; 1635 } 1636 } else { 1637 cli_out("Failed to allocate for saved_intf. Just using teh default"); 1638 } 1639 } 1640 if (params->type == 1) { 1641 rv = _soc_port_phy_eyescan_run_fast_uc( 1642 unit, inst, flags, params, nof_ports, 1643 ports, lane_num, results); 1644 } else { 1645 rv = _soc_port_phy_eyescan_run_lowber( 1646 unit, inst, flags, params, nof_ports, 1647 ports, lane_num, results); 1648 } 1649 1650 if ((!soc_feature(unit, soc_feature_portmod)) || (is_legacy)) { 1651 /* Restore the PhyCtrl SYS/LINE Flags */ 1652 if (saved_intf != NULL) { 1653 for(i=0; i<nof_ports; i++ ) { 1654 int dev = PHY_DIAG_INST_DEV(inst); 1655 if (dev == PHY_DIAG_DEV_EXT) { 1656 pc = EXT_PHY_SW_STATE(unit, ports[i]); 1657 } else { 1658 pc = INT_PHY_SW_STATE(unit, ports[i]); 1659 } 1660 if (saved_intf[i]) { 1661 pc->flags |= PHYCTRL_SYS_SIDE_CTRL; 1662 } else { 1663 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL; 1664 } 1665 } 1666 sal_free(saved_intf); 1667 } 1668 } 1669 return rv; 1670 } 1671 #else 1672 return (_soc_port_phy_eyescan_run(unit, inst, flags, params, nof_ports, ports, lane_num, results)); 1673 #endif 1674 } 1675 1676 1677 #ifndef __KERNEL__ 1678 1679 #ifdef COMPILER_HAS_DOUBLE 1680 STATIC COMPILER_DOUBLE 1681 _eyescan_util_round_real( COMPILER_DOUBLE original_value, int decimal_places ) 1682 { 1683 1684 COMPILER_DOUBLE shift_digits[EYESCAN_UTIL_MAX_ROUND_DIGITS+1] = { 0.0, 10.0, 100.0, 1000.0, 1685 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0 }; 1686 COMPILER_DOUBLE shifted; 1687 COMPILER_DOUBLE rounded; 1688 1689 if (decimal_places > EYESCAN_UTIL_MAX_ROUND_DIGITS ) { 1690 LOG_CLI((BSL_META("ERROR: Maximum digits to the right of decimal for rounding " 1691 "exceeded. Max %d, requested %d\n"), 1692 EYESCAN_UTIL_MAX_ROUND_DIGITS, decimal_places)); 1693 return 0.0; 1694 } 1695 /* shift to preserve the desired digits to the right of the decimal */ 1696 shifted = original_value * shift_digits[decimal_places]; 1697 1698 /* convert to integer and back to COMPILER_DOUBLE to truncate undesired precision */ 1699 shifted = (COMPILER_DOUBLE)(floor(shifted+0.5)); 1700 1701 /* shift back to place decimal point correctly */ 1702 rounded = shifted / shift_digits[decimal_places]; 1703 return rounded; 1704 } 1705 #endif /* COMPILER HAS DOUBLE */ 1706 1707 #ifdef COMPILER_HAS_DOUBLE 1708 STATIC int 1709 _eye_margin_diagram_cal(int unit, EYE_DIAG_INFOt *pInfo, soc_port_phy_eyescan_results_t* results) 1710 { 1711 COMPILER_DOUBLE lbers[MAX_EYE_LOOPS]={0}; /*Internal linear scale sqrt(-log(ber))*/ 1712 COMPILER_DOUBLE margins[MAX_EYE_LOOPS]={0}; /* Eye margin @ each measurement*/ 1713 COMPILER_DOUBLE bers[MAX_EYE_LOOPS]={0}; /* computed bit error rate */ 1714 int delta_n; 1715 COMPILER_DOUBLE Exy = 0.0; 1716 COMPILER_DOUBLE Eyy = 0.0; 1717 COMPILER_DOUBLE Exx = 0.0; 1718 COMPILER_DOUBLE Ey = 0.0; 1719 COMPILER_DOUBLE Ex = 0.0; 1720 COMPILER_DOUBLE alpha; 1721 COMPILER_DOUBLE beta; 1722 COMPILER_DOUBLE proj_ber; 1723 COMPILER_DOUBLE proj_margin_12; 1724 COMPILER_DOUBLE proj_margin_15; 1725 COMPILER_DOUBLE proj_margin_18; 1726 COMPILER_DOUBLE sq_err2; 1727 COMPILER_DOUBLE ierr; 1728 int beta_max=0; 1729 int ber_conf_scale[20]; 1730 int start_n; 1731 int stop_n; 1732 int low_confidence; 1733 int loop_index; 1734 COMPILER_DOUBLE outputs[4]; 1735 COMPILER_DOUBLE eye_unit; 1736 int n_mono; 1737 int loop_var, hi_confidence_cnt, veye_cnt, veye_cnt_orig ; 1738 1739 /* Initialize BER confidence scale */ 1740 ber_conf_scale[0] = 3.02; 1741 ber_conf_scale[1] = 4.7863; 1742 ber_conf_scale[2] = 3.1623; 1743 ber_conf_scale[3] = 2.6303; 1744 ber_conf_scale[4] = 2.2909; 1745 ber_conf_scale[5] = 2.138; 1746 ber_conf_scale[6] = 1.9953; 1747 ber_conf_scale[7] = 1.9055; 1748 ber_conf_scale[8] = 1.8197; 1749 ber_conf_scale[9] = 1.7783; 1750 ber_conf_scale[10] = 1.6982; 1751 ber_conf_scale[11] = 1.6596; 1752 ber_conf_scale[12] = 1.6218; 1753 ber_conf_scale[13] = 1.6218; 1754 ber_conf_scale[14] = 1.5849; 1755 ber_conf_scale[15] = 1.5488; 1756 ber_conf_scale[16] = 1.5488; 1757 ber_conf_scale[17] = 1.5136; 1758 ber_conf_scale[18] = 1.5136; 1759 ber_conf_scale[19] = 1.4791; 1760 1761 LOG_VERBOSE(BSL_LS_SOC_PHY, 1762 (BSL_META_U(unit, 1763 "first_good_ber_idx: %d, first_small_errcnt_idx: %d\n"), 1764 pInfo->first_good_ber_idx,pInfo->first_small_errcnt_idx)); 1765 1766 /* re-calculate the range selected for extroplation */ 1767 hi_confidence_cnt = 0; 1768 veye_cnt = 0; 1769 veye_cnt_orig = pInfo->veye_cnt ; 1770 for (loop_var = 0; loop_var < pInfo->offset_max; loop_var++) { 1771 veye_cnt += 1; 1772 if (pInfo->total_errs[loop_var] >= HI_CONFIDENCE_ERR_CNT) { 1773 hi_confidence_cnt = hi_confidence_cnt + 1; 1774 } 1775 1776 if (((hi_confidence_cnt >= 2) && (pInfo->total_errs[loop_var] < 1777 HI_CONFIDENCE_MIN_ERR_CNT)) || 1778 ((hi_confidence_cnt < 2) && 1779 (pInfo->total_errs[loop_var] < LO_CONFIDENCE_MIN_ERR_CNT)) ) { 1780 break; /* exit for loop */ 1781 } 1782 } 1783 pInfo->veye_cnt = veye_cnt ; 1784 1785 /* Find the highest data point to use, currently based on at least 1E-8 BER level */ 1786 if (pInfo->first_good_ber_idx == INDEX_UNINITIALIZED) { 1787 start_n = pInfo->veye_cnt; 1788 } else { 1789 start_n = pInfo->first_good_ber_idx; 1790 if(start_n > pInfo->veye_cnt) { 1791 start_n = pInfo->veye_cnt; 1792 } 1793 } 1794 stop_n = pInfo->veye_cnt; 1795 1796 /* Find the lowest data point to use */ 1797 if (pInfo->first_small_errcnt_idx == INDEX_UNINITIALIZED) { 1798 stop_n = pInfo->veye_cnt; 1799 } else { 1800 stop_n = pInfo->first_small_errcnt_idx; 1801 if(stop_n > pInfo->veye_cnt) { 1802 stop_n = pInfo->veye_cnt; 1803 } 1804 } 1805 1806 /* determine the number of non-monotonic outliers */ 1807 n_mono = 0; 1808 for (loop_index = start_n; loop_index < stop_n; loop_index++) { 1809 if (pInfo->mono_flags[loop_index] == 1) { 1810 n_mono = n_mono + 1; 1811 } 1812 } 1813 1814 eye_unit = VEYE_UNIT; 1815 1816 for (loop_index = 0; loop_index < pInfo->veye_cnt; loop_index++) { 1817 if (pInfo->total_errs[loop_index] == 0) { 1818 bers[loop_index] = (1000.0/(COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_index])/pInfo->rate; 1819 } else { 1820 bers[loop_index] = (COMPILER_DOUBLE)(1000.0*(COMPILER_DOUBLE)pInfo->total_errs[loop_index])/ 1821 (COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_index]/pInfo->rate; 1822 } 1823 bers[loop_index] /= 1000; 1824 margins[loop_index] = (pInfo->offset_max-loop_index)*eye_unit; 1825 } 1826 1827 if( start_n >= pInfo->veye_cnt ) { 1828 outputs[0] = -_eyescan_util_round_real(log(bers[pInfo->veye_cnt-1])/log(10), 1); 1829 outputs[1] = -100.0; 1830 outputs[2] = -100.0; 1831 outputs[3] = -100.0; 1832 /* No need to print out the decimal portion of the BER */ 1833 LOG_VERBOSE(BSL_LS_SOC_PHY, 1834 (BSL_META_U(unit, 1835 "BER *worse* than 1e-%d\n"), 1836 (int)outputs[0])); 1837 LOG_VERBOSE(BSL_LS_SOC_PHY, 1838 (BSL_META_U(unit, 1839 "Negative margin @ 1e-12, 1e-15 & 1e-18\n"))); 1840 results->ext_better = -1; 1841 results->ext_results_int = (int)outputs[0]; 1842 results->ext_results_remainder = 0; 1843 } else { 1844 low_confidence = 0; 1845 if( (stop_n-start_n - n_mono) < 2 ) { 1846 /* Code triggered when less than 2 statistically valid extrapolation points */ 1847 LOG_CLI((BSL_META_U(unit, 1848 "\nWARNING: less accurate extrapolation because of less than 2 statistically valid extrapolation points.\n"))); 1849 for( loop_index = stop_n; loop_index < pInfo->veye_cnt; loop_index++ ) { 1850 if( pInfo->total_errs[loop_index] < 20 ) { 1851 bers[loop_index] = ber_conf_scale[pInfo->total_errs[loop_index]] * bers[loop_index]; 1852 } else { 1853 bers[loop_index] = ber_conf_scale[19] * bers[loop_index]; 1854 } 1855 pInfo->mono_flags[loop_index] = 0; /* remove flags; or assess again */ 1856 } 1857 /* Add artificial point at 100% margin to enable interpolation */ 1858 margins[pInfo->veye_cnt] = 100.0; 1859 bers[pInfo->veye_cnt] = 0.1; 1860 low_confidence = 1; 1861 stop_n = pInfo->veye_cnt + 1; 1862 } 1863 1864 /* Below this point the code assumes statistically valid point available */ 1865 delta_n = stop_n - start_n - n_mono; 1866 1867 LOG_VERBOSE(BSL_LS_SOC_PHY, 1868 (BSL_META_U(unit, 1869 "start_n: %d, stop_n: %d, veye: %d, n_mono: %d\n"), 1870 start_n,stop_n,pInfo->veye_cnt,n_mono)); 1871 1872 /* Find all the correlations */ 1873 for (loop_index = start_n; loop_index < stop_n; loop_index++) { 1874 lbers[loop_index] = (COMPILER_DOUBLE)sqrt(-log(bers[loop_index])); 1875 } 1876 1877 LOG_VERBOSE(BSL_LS_SOC_PHY, 1878 (BSL_META_U(unit, 1879 "\tstart=%d, stop=%d, low_confidence=%d\n"), 1880 start_n, stop_n, low_confidence)); 1881 for (loop_index = start_n; loop_index < stop_n; loop_index++){ 1882 LOG_VERBOSE(BSL_LS_SOC_PHY, 1883 (BSL_META_U(unit, 1884 "\ttotal_errs[%d]=0x%08x\n"), 1885 loop_index,(int)pInfo->total_errs[loop_index])); 1886 LOG_VERBOSE(BSL_LS_SOC_PHY, 1887 (BSL_META_U(unit, 1888 "\tbers[%d]=%f\n"), 1889 loop_index,bers[loop_index])); 1890 LOG_VERBOSE(BSL_LS_SOC_PHY, 1891 (BSL_META_U(unit, 1892 "\tlbers[%d]=%f\n"), 1893 loop_index,lbers[loop_index])); 1894 } 1895 1896 LOG_VERBOSE(BSL_LS_SOC_PHY, 1897 (BSL_META_U(unit, 1898 "delta_n = %d\n"), 1899 delta_n)); 1900 1901 for( loop_index = start_n; loop_index < stop_n; loop_index++ ) { 1902 if (pInfo->mono_flags[loop_index] == 0) { 1903 Exy = Exy + margins[loop_index] * lbers[loop_index]/(COMPILER_DOUBLE)delta_n; 1904 Eyy = Eyy + lbers[loop_index]*lbers[loop_index]/(COMPILER_DOUBLE)delta_n; 1905 Exx = Exx + margins[loop_index]*margins[loop_index]/(COMPILER_DOUBLE)delta_n; 1906 Ey = Ey + lbers[loop_index]/(COMPILER_DOUBLE)delta_n; 1907 Ex = Ex + margins[loop_index]/(COMPILER_DOUBLE)delta_n; 1908 } 1909 } 1910 1911 /* Compute fit slope and offset */ 1912 alpha = (Exy - Ey * Ex)/(Exx - Ex * Ex); 1913 beta = Ey - Ex * alpha; 1914 1915 LOG_VERBOSE(BSL_LS_SOC_PHY, 1916 (BSL_META_U(unit, 1917 "Exy=%f, Eyy=%f, Exx=%f, Ey=%f,Ex=%f alpha=%f, beta=%f\n"), 1918 Exy,Eyy,Exx,Ey,Ex,alpha,beta)); 1919 1920 /* JPA> Due to the limit of floats, I need to test for a maximum Beta of 9.32 */ 1921 if(beta > 9.32){ 1922 beta_max=1; 1923 LOG_CLI((BSL_META_U(unit, 1924 "\n\tWARNING: intermediate float variable is maxed out, what this means is:\n"))); 1925 LOG_CLI((BSL_META_U(unit, 1926 "\t\t- The *extrapolated* minimum BER will be reported as 1E-37.\n"))); 1927 LOG_CLI((BSL_META_U(unit, 1928 "\t\t- This may occur if the channel is near ideal (e.g. test loopback)\n"))); 1929 LOG_CLI((BSL_META_U(unit, 1930 "\t\t- While not discrete, reporting an extrapolated BER < 1E-37 is numerically corect, and informative\n\n"))); 1931 } 1932 1933 1934 proj_ber = exp(-beta * beta); 1935 proj_margin_12 = (sqrt(-log(1e-12)) - beta)/alpha; 1936 proj_margin_15 = (sqrt(-log(1e-15)) - beta)/alpha; 1937 proj_margin_18 = (sqrt(-log(1e-18)) - beta)/alpha; 1938 1939 sq_err2 = 0; 1940 for (loop_index = start_n; loop_index < stop_n; loop_index++) { 1941 ierr = (lbers[loop_index] - (alpha*margins[loop_index] + beta)); 1942 sq_err2 = sq_err2 + ierr*ierr/(COMPILER_DOUBLE)delta_n; 1943 } 1944 1945 outputs[0] = -_eyescan_util_round_real(log(proj_ber)/log(10),1); 1946 outputs[1] = _eyescan_util_round_real(proj_margin_18,1); 1947 outputs[2] = _eyescan_util_round_real(proj_margin_12,1); 1948 outputs[3] = _eyescan_util_round_real(proj_margin_15,1); 1949 1950 LOG_VERBOSE(BSL_LS_SOC_PHY, 1951 (BSL_META_U(unit, 1952 "\t\tlog1e-12=%f, sq=%f\n"), 1953 (COMPILER_DOUBLE)log(1e-12),(COMPILER_DOUBLE)sqrt(-log(1e-12)))); 1954 LOG_VERBOSE(BSL_LS_SOC_PHY, 1955 (BSL_META_U(unit, 1956 "\t\talpha=%f\n"), 1957 alpha)); 1958 LOG_VERBOSE(BSL_LS_SOC_PHY, 1959 (BSL_META_U(unit, 1960 "\t\tbeta=%f\n"), 1961 beta)); 1962 LOG_VERBOSE(BSL_LS_SOC_PHY, 1963 (BSL_META_U(unit, 1964 "\t\tproj_ber=%f\n"), 1965 proj_ber)); 1966 LOG_VERBOSE(BSL_LS_SOC_PHY, 1967 (BSL_META_U(unit, 1968 "\t\tproj_margin12=%f\n"), 1969 proj_margin_12)); 1970 LOG_VERBOSE(BSL_LS_SOC_PHY, 1971 (BSL_META_U(unit, 1972 "\t\tproj_margin12=%f\n"), 1973 proj_margin_15)); 1974 LOG_VERBOSE(BSL_LS_SOC_PHY, 1975 (BSL_META_U(unit, 1976 "\t\tproj_margin18=%f\n"), 1977 proj_margin_18)); 1978 LOG_VERBOSE(BSL_LS_SOC_PHY, 1979 (BSL_META_U(unit, 1980 "\t\toutputs[0]=%f\n"), 1981 outputs[0])); 1982 LOG_VERBOSE(BSL_LS_SOC_PHY, 1983 (BSL_META_U(unit, 1984 "\t\toutputs[1]=%f\n"), 1985 outputs[1])); 1986 LOG_VERBOSE(BSL_LS_SOC_PHY, 1987 (BSL_META_U(unit, 1988 "\t\toutputs[2]=%f\n"), 1989 outputs[2])); 1990 1991 /* Extrapolated results, low confidence */ 1992 if( low_confidence == 1 ) { 1993 if(beta_max){ 1994 LOG_VERBOSE(BSL_LS_SOC_PHY, 1995 (BSL_META_U(unit, 1996 "BER(extrapolated) is *better* than 1e-37\n"))); 1997 LOG_VERBOSE(BSL_LS_SOC_PHY, 1998 (BSL_META_U(unit, 1999 "Margin @ 1e-12 is *better* than %f\n"), 2000 outputs[2])); 2001 LOG_VERBOSE(BSL_LS_SOC_PHY, 2002 (BSL_META_U(unit, 2003 "Margin @ 1e-15 is *better* than %f\n"), 2004 outputs[3])); 2005 LOG_VERBOSE(BSL_LS_SOC_PHY, 2006 (BSL_META_U(unit, 2007 "Margin @ 1e-18 is *better* than %f\n"), 2008 outputs[1])); 2009 results->ext_better = 1; 2010 results->ext_results_int = 37; 2011 results->ext_results_remainder = 0; 2012 } 2013 else{ 2014 LOG_VERBOSE(BSL_LS_SOC_PHY, 2015 (BSL_META_U(unit, 2016 "BER(extrapolated) is *better* than 1e-%f\n"), 2017 outputs[0])); 2018 LOG_VERBOSE(BSL_LS_SOC_PHY, 2019 (BSL_META_U(unit, 2020 "Margin @ 1e-12 is *better* than %f\n"), 2021 outputs[2])); 2022 LOG_VERBOSE(BSL_LS_SOC_PHY, 2023 (BSL_META_U(unit, 2024 "Margin @ 1e-15 is *better* than %f\n"), 2025 outputs[3])); 2026 LOG_VERBOSE(BSL_LS_SOC_PHY, 2027 (BSL_META_U(unit, 2028 "Margin @ 1e-18 is *better* than %f\n"), 2029 outputs[1])); 2030 results->ext_better = 1; 2031 results->ext_results_int = (int)outputs[0]; 2032 results->ext_results_remainder = (((int)(outputs[0]*100))%100); 2033 } 2034 2035 /* JPA> Extrapolated results, high confidence */ 2036 } else { 2037 if(beta_max){ 2038 LOG_VERBOSE(BSL_LS_SOC_PHY, 2039 (BSL_META_U(unit, 2040 "BER(extrapolated) = 1e-37\n"))); 2041 LOG_VERBOSE(BSL_LS_SOC_PHY, 2042 (BSL_META_U(unit, 2043 "Margin @ 1e-12 is *better* than %f\n"), 2044 outputs[2])); 2045 LOG_VERBOSE(BSL_LS_SOC_PHY, 2046 (BSL_META_U(unit, 2047 "Margin @ 1e-15 is *better* than %f\n"), 2048 outputs[3])); 2049 LOG_VERBOSE(BSL_LS_SOC_PHY, 2050 (BSL_META_U(unit, 2051 "Margin @ 1e-18 is *better* than %f\n"), 2052 outputs[1])); 2053 results->ext_better = 0; 2054 results->ext_results_int = 37; 2055 results->ext_results_remainder = 0; 2056 } 2057 else{ 2058 LOG_VERBOSE(BSL_LS_SOC_PHY, 2059 (BSL_META_U(unit, 2060 "BER(extrapolated) = 1e-%4.2f\n"), 2061 outputs[0])); 2062 LOG_VERBOSE(BSL_LS_SOC_PHY, 2063 (BSL_META_U(unit, 2064 "Margin @ 1e-12 = %4.2f%%\n"), 2065 outputs[2])); 2066 LOG_VERBOSE(BSL_LS_SOC_PHY, 2067 (BSL_META_U(unit, 2068 "Margin @ 1e-15 = %4.2f%%\n"), 2069 outputs[3])); 2070 LOG_VERBOSE(BSL_LS_SOC_PHY, 2071 (BSL_META_U(unit, 2072 "Margin @ 1e-18 = %4.2f%%\n"), 2073 outputs[1])); 2074 results->ext_better = 0; 2075 results->ext_results_int = (int)outputs[0]; 2076 results->ext_results_remainder = (((int)(outputs[0]*100))%100); 2077 } 2078 } 2079 } 2080 pInfo->veye_cnt = veye_cnt_orig ; 2081 return SOC_E_NONE; 2082 } 2083 #else 2084 STATIC int 2085 _eye_margin_diagram_cal(int unit, EYE_DIAG_INFOt *pInfo, soc_port_phy_eyescan_results_t* results) 2086 { 2087 LOG_ERROR(BSL_LS_SOC_PHY, 2088 (BSL_META_U(unit, 2089 "_eye_margin_diagram_cal unavailable with this compiler\n"))); 2090 2091 return SOC_E_UNAVAIL; 2092 } 2093 #endif 2094 2095 #ifdef COMPILER_HAS_DOUBLE 2096 STATIC int 2097 _eye_margin_ber_cal(int unit, EYE_DIAG_INFOt *pInfo) 2098 { 2099 COMPILER_DOUBLE bers[MAX_EYE_LOOPS]; /* computed bit error rate */ 2100 COMPILER_DOUBLE margins[MAX_EYE_LOOPS]; /* Eye margin @ each measurement*/ 2101 int loop_var; 2102 COMPILER_DOUBLE eye_unit; 2103 COMPILER_DOUBLE curr_ber_log; 2104 COMPILER_DOUBLE prev_ber_log = 0; 2105 COMPILER_DOUBLE good_ber_level = -7.8; 2106 2107 /* Initialize BER array */ 2108 for (loop_var = 0; loop_var < MAX_EYE_LOOPS; loop_var++) { 2109 bers[loop_var] = 0.0; 2110 } 2111 2112 eye_unit = VEYE_UNIT; 2113 2114 LOG_VERBOSE(BSL_LS_SOC_PHY, 2115 (BSL_META_U(unit, 2116 "\nBER measurement at each offset, num_data_points: %d\n"), 2117 pInfo->veye_cnt)); 2118 2119 for (loop_var = 0; loop_var < pInfo->veye_cnt; loop_var++) { 2120 margins[loop_var] = (pInfo->offset_max-loop_var)*eye_unit; 2121 LOG_VERBOSE(BSL_LS_SOC_PHY, 2122 (BSL_META_U(unit, 2123 "BER measurement at offset: %f\n"), 2124 margins[loop_var])); 2125 2126 /* Compute BER */ 2127 if (pInfo->total_errs[loop_var] == 0) { 2128 bers[loop_var] = 1000.0/(COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_var]/pInfo->rate; 2129 bers[loop_var] /= 1000; 2130 2131 LOG_VERBOSE(BSL_LS_SOC_PHY, 2132 (BSL_META_U(unit, 2133 "BER @ %04f %% = 1e%04f (%d errors in %d miliseconds)\n"), 2134 (COMPILER_DOUBLE)((pInfo->offset_max-loop_var)*eye_unit), 2135 1.0*(log10(bers[loop_var])), 2136 pInfo->total_errs[loop_var], 2137 pInfo->total_elapsed_time[loop_var])); 2138 } else { 2139 bers[loop_var] = ((COMPILER_DOUBLE)1000.0*((COMPILER_DOUBLE)(pInfo->total_errs[loop_var])))/ 2140 (COMPILER_DOUBLE)pInfo->total_elapsed_time[loop_var]/pInfo->rate; 2141 2142 /* the rate unit is KHZ, add -3(log10(1/1000)) for actual display */ 2143 bers[loop_var] /= 1000; 2144 LOG_VERBOSE(BSL_LS_SOC_PHY, 2145 (BSL_META_U(unit, 2146 "BER @ %2.2f%% = 1e%2.2f (%d errors in %d miliseconds)\n"), 2147 (pInfo->offset_max-loop_var)*eye_unit, 2148 log10(bers[loop_var]), 2149 pInfo->total_errs[loop_var], 2150 pInfo->total_elapsed_time[loop_var])); 2151 } 2152 curr_ber_log = log10(bers[loop_var]); 2153 2154 /* Detect and record nonmonotonic data points */ 2155 if ((loop_var > 0) && (curr_ber_log > prev_ber_log)) { 2156 pInfo->mono_flags[loop_var] = 1; 2157 } 2158 prev_ber_log = curr_ber_log; 2159 2160 LOG_VERBOSE(BSL_LS_SOC_PHY, 2161 (BSL_META_U(unit, 2162 "cur_be_log %2.2f\n"), 2163 curr_ber_log)); 2164 /* find the first data point with good BER */ 2165 if ((curr_ber_log <= good_ber_level) && 2166 (pInfo->first_good_ber_idx == INDEX_UNINITIALIZED)) { 2167 LOG_VERBOSE(BSL_LS_SOC_PHY, 2168 (BSL_META_U(unit, 2169 "cur_be_log %2.2f, loop_var %d\n"), 2170 curr_ber_log,loop_var)); 2171 pInfo->first_good_ber_idx = loop_var; 2172 } 2173 if ((pInfo->total_errs[loop_var] < HI_CONFIDENCE_MIN_ERR_CNT) && (pInfo->first_small_errcnt_idx == INDEX_UNINITIALIZED)) { 2174 /* find the first data point with small error count */ 2175 pInfo->first_small_errcnt_idx = loop_var; 2176 } 2177 2178 } /* for loop_var */ 2179 2180 return SOC_E_NONE; 2181 } 2182 #endif /* COMPILER_HAS_DOUBLE */ 2183 2184 int 2185 soc_port_phy_eyescan_extrapolate(int unit, 2186 int flags, 2187 soc_port_phy_eyescan_params_t* params, 2188 uint32 nof_ports, 2189 soc_port_t* ports, 2190 soc_port_phy_eyescan_results_t* results) 2191 { 2192 #ifdef COMPILER_HAS_DOUBLE 2193 int i, cnt, vertical_i; 2194 int rv = SOC_E_NONE, speed; 2195 EYE_DIAG_INFOt veye_info; 2196 2197 sal_memset(&veye_info, 0, sizeof(EYE_DIAG_INFOt)); 2198 /* extrapolate */ 2199 if (!(flags & SRD_EYESCAN_FLAG_AVOID_EXTRAPOLATION) && (flags & SRD_EYESCAN_FLAG_VERTICAL_ONLY) && 2200 (params->counter!=socPortPhyEyescanCounterRelativePhy)){ 2201 2202 for (i = 0 ; i < nof_ports; i++) { 2203 rv = soc_phyctrl_speed_get(unit, ports[i], &speed); 2204 if (SOC_FAILURE(rv)) { 2205 LOG_ERROR(BSL_LS_SOC_PHY, 2206 (BSL_META_U(unit, 2207 "soc_phyctrl_speed_get failed\n"))); 2208 return rv; 2209 } 2210 2211 veye_info.first_good_ber_idx = INDEX_UNINITIALIZED; 2212 veye_info.first_small_errcnt_idx = INDEX_UNINITIALIZED; 2213 veye_info.offset_max = params->bounds.vertical_max; 2214 veye_info.rate = speed*1000; 2215 2216 cnt = 0; 2217 for (vertical_i = params->bounds.vertical_min ; vertical_i <= params->bounds.vertical_max; vertical_i++){ 2218 if(vertical_i % params->sample_resolution != 0) { 2219 continue; 2220 } 2221 cnt++; 2222 if(cnt == MAX_EYE_LOOPS) { 2223 break; 2224 } 2225 } 2226 veye_info.veye_cnt = cnt; 2227 for (vertical_i = params->bounds.vertical_min ; vertical_i <= params->bounds.vertical_max; vertical_i++){ 2228 cnt--; 2229 if(vertical_i % params->sample_resolution != 0) { 2230 continue; 2231 } 2232 veye_info.total_errs[cnt] = results[i].error_count[SOC_PORT_PHY_EYESCAN_H_INDEX][vertical_i + SOC_PORT_PHY_EYESCAN_V_INDEX]; 2233 veye_info.total_elapsed_time[cnt] = results[i].run_time[SOC_PORT_PHY_EYESCAN_H_INDEX][vertical_i + SOC_PORT_PHY_EYESCAN_V_INDEX]; 2234 veye_info.mono_flags[cnt] = 0; 2235 } 2236 if (veye_info.veye_cnt > MAX_EYE_LOOPS) { 2237 rv = SOC_E_PARAM; 2238 LOG_ERROR(BSL_LS_SOC_PHY, 2239 (BSL_META_U(unit, 2240 "ERROR: veye_cnt > MAX_EYE_LOOPS\n"))); 2241 return rv; 2242 } 2243 _eye_margin_ber_cal(unit, &veye_info); 2244 _eye_margin_diagram_cal(unit, &veye_info, &(results[i])); 2245 results[i].ext_done = 1; 2246 } 2247 } 2248 2249 return rv; 2250 #else 2251 return SOC_E_NONE; 2252 #endif /* COMPILER_HAS_DOUBLE*/ 2253 } 2254 2255 #else /* #ifndef __KERNEL__ */ 2256 2257 int 2258 soc_port_phy_eyescan_extrapolate(int unit, 2259 int flags, 2260 soc_port_phy_eyescan_params_t* params, 2261 uint32 nof_ports, 2262 soc_port_t* ports, 2263 soc_port_phy_eyescan_results_t* results){ 2264 LOG_CLI((BSL_META_U(unit, 2265 "\nExtrapolation is not supported in Linux kernel mode\n"))); 2266 2267 return SOC_E_NONE; 2268 } 2269 2270 #endif /* #ifndef __KERNEL__ */