tdm_ap_scan.c (26616B)
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 * $All Rights Reserved.$ 7 * 8 * TDM chip data structure scanning functions 9 */ 10 #ifdef _TDM_STANDALONE 11 #include <tdm_top.h> 12 #else 13 #include <soc/tdm/core/tdm_top.h> 14 #endif 15 16 17 /** 18 @name: tdm_ap_which_tsc 19 @param: 20 21 Returns the TSC to which the input port belongs given pointer to transcribed pmap 22 */ 23 int 24 tdm_ap_which_tsc( tdm_mod_t *_tdm_s ) 25 { 26 AP_TOKEN_CHECK(_tdm_s->_core_data.vars_pkg.port) { 27 return tdm_find_pm( _tdm_s ); 28 } 29 30 return AP_NUM_EXT_PORTS; 31 32 } 33 34 35 /** 36 @name: tdm_ap_legacy_which_tsc 37 @param: 38 39 Returns the TSC to which the input port belongs given pointer to transcribed pmap 40 */ 41 int 42 tdm_ap_legacy_which_tsc(unsigned short port, int **tsc) 43 { 44 int i, j, which=AP_NUM_EXT_PORTS; 45 46 AP_TOKEN_CHECK(port) { 47 for (i=0; i<AP_NUM_PHY_PM; i++) { 48 for (j=0; j<AP_NUM_PM_LNS; j++) { 49 if (tsc[i][j]==port) { 50 which=i; 51 } 52 } 53 if (which!=AP_NUM_EXT_PORTS) { 54 break; 55 } 56 } 57 } 58 59 return which; 60 61 } 62 63 64 /** 65 @name: tdm_ap_check_ethernet 66 @param: 67 68 Returns BOOL_TRUE or BOOL_FALSE depending on if pipe of the given port has traffic entirely Ethernet 69 */ 70 int 71 tdm_ap_check_ethernet( tdm_mod_t *_tdm_s) 72 { 73 int i, j, port_tsc=AP_NUM_PHY_PM, type=BOOL_TRUE, tsc[AP_NUM_PHY_PM][AP_NUM_PM_LNS]; 74 75 for (i=0; i<AP_NUM_PHY_PM; i++) { 76 for (j=0; j<AP_NUM_PM_LNS; j++) { 77 tsc[i][j]=_tdm_s->_chip_data.soc_pkg.pmap[i][j]; 78 } 79 } 80 for (i=1; i<73; i++) { 81 port_tsc = tdm_ap_scan_which_tsc(i,tsc); 82 if (port_tsc<_tdm_s->_chip_data.soc_pkg.pm_num_phy_modules) { 83 /* 84 * COVERITY 85 * 86 * The value of the above variable "port_tsc" is guaranteed 87 * less than 18 once the program going into this block, because 88 * "_tdm_s->_chip_data.soc_pkg.pm_num_phy_modules" is 89 * initialized to 18 (AP_NUM_PHY_PM). 90 */ 91 /* coverity[overrun-local] */ 92 if (_tdm_s->_chip_data.soc_pkg.speed[i]!=SPEED_0 && _tdm_s->_chip_data.soc_pkg.soc_vars.ap.pm_encap_type[port_tsc]==PM_ENCAP__HIGIG2) { 93 type=BOOL_FALSE; 94 break; 95 } 96 } 97 } 98 99 return type; 100 101 } 102 103 104 /** 105 @name: tdm_ap_check_same_port_dist_dn 106 @param: 107 108 Returns distance to next index with same port number, in down direction 109 Wraparound without mirroring 110 */ 111 int 112 tdm_ap_check_same_port_dist_dn(int idx, int *tdm_tbl, int lim) 113 { 114 int j, dist=1, slot; 115 116 slot=idx; 117 for (j=1; j<lim; j++) { 118 if (++slot==lim) {slot=0;} 119 if (tdm_tbl[slot]==tdm_tbl[idx]) { 120 break; 121 } 122 dist++; 123 } 124 125 return dist; 126 127 } 128 129 130 /** 131 @name: tdm_ap_check_same_port_dist_up 132 @param: 133 134 Returns distance to next index with same port number, in down direction 135 Wraparound without mirroring 136 */ 137 int 138 tdm_ap_check_same_port_dist_up(int idx, int *tdm_tbl, int lim) 139 { 140 int j, dist=1, slot; 141 142 slot=idx; 143 for (j=1; j<lim; j++) { 144 if (--slot<=0) {slot=(lim-1);} 145 if (tdm_tbl[slot]==tdm_tbl[idx]) { 146 break; 147 } 148 dist++; 149 } 150 151 return dist; 152 153 } 154 155 156 /** 157 @name: tdm_ap_check_same_port_dist_dn_port 158 @param: 159 160 Returns distance to next index with same port number, in down direction 161 Wraparound without mirroring 162 */ 163 int 164 tdm_ap_check_same_port_dist_dn_port(int port, int idx, int *tdm_tbl, int lim) 165 { 166 int j, dist=1, slot; 167 168 slot=idx; 169 for (j=1; j<lim; j++) { 170 if (++slot==lim) {slot=0;} 171 if (tdm_tbl[slot]==port) { 172 break; 173 } 174 dist++; 175 } 176 177 return dist; 178 } 179 180 181 /** 182 @name: tdm_ap_check_same_port_dist_up_port 183 @param: 184 185 Returns distance to next index with same port number, in down direction 186 Wraparound without mirroring 187 */ 188 int 189 tdm_ap_check_same_port_dist_up_port(int port, int idx, int *tdm_tbl, int lim) 190 { 191 int j, dist=1, slot; 192 193 slot=idx; 194 for (j=1; j<lim; j++) { 195 if (--slot<=0) {slot=(lim-1);} 196 if (tdm_tbl[slot]==port) { 197 break; 198 } 199 dist++; 200 } 201 202 return dist; 203 } 204 205 206 /** 207 @name: tdm_ap_slice_size_local 208 @param: 209 210 Given index, returns size of largest contiguous slice 211 */ 212 int 213 tdm_ap_slice_size_local(unsigned short idx, int *tdm, int lim) 214 { 215 int i, slice_size=(-1); 216 if (tdm[idx]!=AP_OVSB_TOKEN && tdm[idx]!=AP_NUM_EXT_PORTS) { 217 for (i=idx; i>=0; i--) { 218 if (tdm[i]!=AP_OVSB_TOKEN && tdm[i]!=AP_NUM_EXT_PORTS) {slice_size++;} 219 else {break;} 220 } 221 for (i=idx; i<lim; i++) { 222 if (tdm[i]!=AP_OVSB_TOKEN && tdm[i]!=AP_NUM_EXT_PORTS) {slice_size++;} 223 else {break;} 224 } 225 } 226 else if (tdm[idx]==AP_OVSB_TOKEN) { 227 for (i=idx; i>=0; i--) { 228 if (tdm[i]==AP_OVSB_TOKEN) {slice_size++;} 229 else {break;} 230 } 231 for (i=idx; i<lim; i++) { 232 if (tdm[i]==AP_OVSB_TOKEN) {slice_size++;} 233 else {break;} 234 } 235 } 236 237 return slice_size; 238 } 239 240 241 /** 242 @name: tdm_ap_slice_size 243 @param: 244 245 Given port number, returns size of largest slice 246 */ 247 int 248 tdm_ap_slice_size(unsigned short port, int *tdm, int lim) 249 { 250 int i, j, k=0, slice_size=0; 251 252 AP_TOKEN_CHECK(port) { 253 for (i=0; i<lim; i++) { 254 AP_TOKEN_CHECK(tdm[i]) { 255 k=1; 256 for (j=(i+1); j<lim; j++) { 257 AP_TOKEN_CHECK(tdm[j]) {k++;} 258 else {break;} 259 } 260 slice_size = (k>slice_size)?(k):(slice_size); 261 } 262 } 263 } 264 else { 265 for (i=2; i<lim; i++) { 266 if (tdm[i]==port) { 267 k=1; 268 for (j=(i+1); j<lim; j++) { 269 if (tdm[j]==port) {k++;} 270 else {break;} 271 } 272 slice_size = (k>slice_size)?(k):(slice_size); 273 } 274 } 275 } 276 277 return slice_size; 278 } 279 280 281 /** 282 @name: tdm_ap_slice_idx 283 @param: 284 285 Given port number, returns index of largest slice 286 */ 287 int 288 tdm_ap_slice_idx(unsigned short port, int *tdm, int lim) 289 { 290 int i, j, k=0, slice_size=0, slice_idx=0; 291 292 if (port<=AP_NUM_PHY_PORTS && port>0) { 293 for (i=0; i<lim; i++) { 294 AP_TOKEN_CHECK(tdm[i]) { 295 k=1; 296 for (j=(i+1); j<lim; j++) { 297 AP_TOKEN_CHECK(tdm[j]) {k++;} 298 else {break;} 299 } 300 } 301 if (k>slice_size) { 302 slice_idx=i; 303 slice_size=k; 304 } 305 } 306 } 307 else { 308 for (i=2; i<lim; i++) { 309 if (tdm[i]==port) { 310 k=1; 311 for (j=(i+1); j<lim; j++) { 312 if (tdm[j]==port) {k++;} 313 else {break;} 314 } 315 } 316 if (k>slice_size) { 317 slice_idx=i; 318 slice_size=k; 319 } 320 } 321 } 322 323 return slice_idx; 324 } 325 326 327 /** 328 @name: tdm_ap_slice_prox_dn 329 @param: 330 331 Given port number, checks min spacing in a slice in down direction 332 */ 333 int 334 tdm_ap_slice_prox_dn(int slot, int *tdm, int lim, int **tsc, enum port_speed_e *speed) 335 { 336 int i, cnt=0, wc, idx=(slot+1), slice_prox=PASS; 337 338 if (slot < 0) { 339 return FAIL; 340 } 341 wc=(tdm[slot]==AP_ANCL_TOKEN)?(tdm[slot]):(tdm_ap_legacy_which_tsc(tdm[slot],tsc)); 342 if (slot<=(lim-5)) { 343 if ( wc==tdm_ap_legacy_which_tsc(tdm[slot+1],tsc) || 344 wc==tdm_ap_legacy_which_tsc(tdm[slot+2],tsc) || 345 wc==tdm_ap_legacy_which_tsc(tdm[slot+3],tsc) || 346 wc==tdm_ap_legacy_which_tsc(tdm[slot+4],tsc) ) { 347 slice_prox=FAIL; 348 } 349 } 350 else { 351 while (idx<lim) { 352 if (wc==tdm_ap_legacy_which_tsc(tdm[idx],tsc)) { 353 slice_prox=FAIL; 354 break; 355 } 356 idx++; cnt++; 357 } 358 for (i=(lim-slot-cnt-1); i>=0; i--) { 359 if (wc==tdm_ap_legacy_which_tsc(tdm[i],tsc)) { 360 slice_prox=FAIL; 361 break; 362 } 363 } 364 } 365 /* #ifdef _LLS_SCHEDULER */ 366 { 367 int i=slot, j; 368 AP_TOKEN_CHECK(tdm[i]){ 369 if (speed[tdm[i]]<=SPEED_42G_HG2) { 370 if (i<(AP_VMAP_MAX_LEN-1)) { 371 for (j=1; j<11; j++) { 372 if (tdm[i+j]==tdm[i]) { 373 slice_prox=FAIL; 374 break; 375 } 376 } 377 } 378 } 379 } 380 } 381 /* #endif */ 382 383 return slice_prox; 384 } 385 386 387 /** 388 @name: tdm_ap_slice_prox_up 389 @param: 390 391 Given port number, checks min spacing in a slice in up direction 392 */ 393 int 394 tdm_ap_slice_prox_up(int slot, int *tdm, int **tsc, enum port_speed_e *speed) 395 { 396 int wc, slice_prox=PASS; 397 398 wc=(tdm[slot]==AP_ANCL_TOKEN)?(tdm[slot]):(tdm_ap_legacy_which_tsc(tdm[slot],tsc)); 399 if (slot>=4) { 400 if ( wc==tdm_ap_legacy_which_tsc(tdm[slot-1],tsc) || 401 wc==tdm_ap_legacy_which_tsc(tdm[slot-2],tsc) || 402 wc==tdm_ap_legacy_which_tsc(tdm[slot-3],tsc) || 403 wc==tdm_ap_legacy_which_tsc(tdm[slot-4],tsc) ) { 404 slice_prox=FAIL; 405 } 406 } 407 /* #ifdef _LLS_SCHEDULER */ 408 { 409 int i=slot, j; 410 AP_TOKEN_CHECK(tdm[i]){ 411 if (speed[tdm[i]]<=SPEED_42G_HG2) { 412 if (i>=1) { 413 for (j=1; j<11; j++) { 414 if (tdm[i-j]==tdm[i]) { 415 slice_prox=FAIL; 416 break; 417 } 418 } 419 } 420 } 421 } 422 } 423 /* #endif */ 424 425 return slice_prox; 426 } 427 428 429 /** 430 @name: tdm_ap_check_fit_smooth 431 @param: 432 433 Inside of table array, returns number of nodes inside a port vector that clump with other nodes of the same type 434 */ 435 int 436 tdm_ap_check_fit_smooth(int *tdm_tbl, int port, int lr_idx_limit, int clump_thresh) 437 { 438 int i, cnt=0; 439 440 for (i=0; i<lr_idx_limit; i++) { 441 if ( (tdm_tbl[i]==port) && (tdm_ap_slice_size_local(i,tdm_tbl,lr_idx_limit)>=clump_thresh) ) { 442 cnt++; 443 } 444 } 445 446 return cnt; 447 448 } 449 450 451 /** 452 @name: tdm_ap_check_lls_flat_up 453 @param: 454 455 Checks LLS scheduler min spacing in tdm array, up direction only, returns dist 456 */ 457 int 458 tdm_ap_check_lls_flat_up(int idx, int *tdm_tbl, enum port_speed_e *speed) 459 { 460 int lls_prox=AP_VMAP_MAX_LEN; 461 462 /* #ifdef _LLS_SCHEDULER */ 463 { 464 int i=idx, j; 465 lls_prox=1; 466 if (i>=11 && tdm_tbl[idx]<=SPEED_42G_HG2) { 467 for (j=1; j<11; j++) { 468 if (tdm_tbl[i-j]==tdm_tbl[i]) { 469 break; 470 } 471 lls_prox++; 472 } 473 } 474 } 475 /* #endif */ 476 477 return lls_prox; 478 479 } 480 481 482 /** 483 @name: tdm_ap_slice_prox_local 484 @param: 485 486 Given index, checks min spacing of two nearest non-token ports 487 */ 488 int 489 tdm_ap_slice_prox_local(unsigned short idx, int *tdm, int lim, int **tsc) 490 { 491 int i, prox_len=0, wc=AP_NUM_EXT_PORTS; 492 493 /* Nearest non-token port */ 494 AP_TOKEN_CHECK(tdm[idx]) { 495 wc=tdm_ap_legacy_which_tsc(tdm[idx],tsc); 496 } 497 else { 498 for (i=1; (idx-i)>=0; i++) { 499 AP_TOKEN_CHECK(tdm[i]) { 500 wc=tdm_ap_legacy_which_tsc(tdm[idx-i],tsc); 501 break; 502 } 503 } 504 } 505 for (i=1; (idx+i)<lim; i++) { 506 if (tdm_ap_legacy_which_tsc(tdm[idx+i],tsc)!=wc) { 507 prox_len++; 508 } 509 else { 510 break; 511 } 512 } 513 514 return prox_len; 515 } 516 517 518 /** 519 @name: tdm_ap_num_lr_slots 520 @param: 521 */ 522 int 523 tdm_ap_num_lr_slots(int *tdm_tbl) 524 { 525 int i, cnt=0; 526 527 for (i=0; i<AP_VMAP_MAX_LEN; i++) { 528 AP_TOKEN_CHECK(tdm_tbl[i]) { 529 cnt++; 530 } 531 } 532 533 return cnt; 534 } 535 536 537 /** 538 @name: tdm_ap_scan_slice_min 539 @param: 540 541 Given port number, returns the MIN size of port slices in an array 542 */ 543 int 544 tdm_ap_scan_slice_min(unsigned short port, int *tdm, int lim, int *slice_start_idx, int pos) 545 { 546 int i, k=0, idx0, slice_size_min=256, slice_idx=-1 , idx_start; 547 548 if(pos>=0 && pos<lim){ 549 /* linerate */ 550 AP_TOKEN_CHECK(port) { 551 for (i=0; i<lim; i++) { 552 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 553 AP_TOKEN_CHECK(tdm[idx0]) { 554 k = tdm_ap_scan_slice_size_local(idx0, tdm, lim, &idx_start); 555 if(k>0 && k<slice_size_min){ 556 slice_size_min = k; 557 slice_idx = idx_start; 558 } 559 } 560 } 561 } 562 /* oversub */ 563 else if (port==AP_OVSB_TOKEN){ 564 for (i=0; i<lim; i++) { 565 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 566 if (tdm[idx0]==AP_OVSB_TOKEN) { 567 k = tdm_ap_scan_slice_size_local(idx0, tdm, lim, &idx_start); 568 if(k>0 && k<slice_size_min){ 569 slice_size_min = k; 570 slice_idx = idx_start; 571 } 572 } 573 } 574 } 575 /* idle */ 576 else if (port==AP_IDL1_TOKEN || port==AP_IDL2_TOKEN ){ 577 for (i=0; i<lim; i++) { 578 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 579 if (tdm[idx0]==AP_IDL1_TOKEN || tdm[idx0]==AP_IDL2_TOKEN) { 580 k = tdm_ap_scan_slice_size_local(idx0, tdm, lim, &idx_start); 581 if(k>0 && k<slice_size_min){ 582 slice_size_min = k; 583 slice_idx = idx_start; 584 } 585 } 586 } 587 } 588 } 589 590 (*slice_start_idx) = slice_idx; 591 return slice_size_min; 592 } 593 594 595 /** 596 @name: tdm_ap_scan_slice_max 597 @param: 598 599 Given port number, returns the MAX size of port slices in an array 600 */ 601 int 602 tdm_ap_scan_slice_max(unsigned short port, int *tdm, int lim, int *slice_start_idx, int pos) 603 { 604 int i, k=0, idx0, slice_size_max=0, slice_idx=-1 , idx_start; 605 606 if(pos>=0 && pos<lim){ 607 /* linerate */ 608 AP_TOKEN_CHECK(port) { 609 for (i=0; i<lim; i++) { 610 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 611 AP_TOKEN_CHECK(tdm[idx0]) { 612 k = tdm_ap_scan_slice_size_local(idx0, tdm, lim, &idx_start); 613 if(k>slice_size_max){ 614 slice_size_max = k; 615 slice_idx = idx_start; 616 } 617 } 618 } 619 } 620 /* oversub */ 621 else if (port==AP_OVSB_TOKEN){ 622 for (i=0; i<lim; i++) { 623 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 624 if (tdm[idx0]==AP_OVSB_TOKEN) { 625 k = tdm_ap_scan_slice_size_local(idx0, tdm, lim, &idx_start); 626 if(k>slice_size_max){ 627 slice_size_max = k; 628 slice_idx = idx_start; 629 } 630 } 631 } 632 } 633 /* idle */ 634 else if (port==AP_IDL1_TOKEN || port==AP_IDL2_TOKEN ){ 635 for (i=0; i<lim; i++) { 636 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 637 if (tdm[idx0]==AP_IDL1_TOKEN || tdm[idx0]==AP_IDL2_TOKEN) { 638 k = tdm_ap_scan_slice_size_local(idx0, tdm, lim, &idx_start); 639 if(k>slice_size_max){ 640 slice_size_max = k; 641 slice_idx = idx_start; 642 } 643 } 644 } 645 } 646 } 647 648 (*slice_start_idx) = slice_idx; 649 return slice_size_max; 650 } 651 652 653 /** 654 @name: tdm_ap_scan_slice_size_local 655 @param: 656 657 Given index, returns the largest size of local slice 658 */ 659 int 660 tdm_ap_scan_slice_size_local(unsigned short idx, int *tdm, int lim, int *slice_start_idx) 661 { 662 int i, slice_size=(-1), idx_start=(-1); 663 664 if(idx<lim){ 665 /* linerate */ 666 AP_TOKEN_CHECK(tdm[idx]){ 667 for (i=idx; i>=0; i--) { 668 AP_TOKEN_CHECK(tdm[i]) {slice_size++; idx_start=i;} 669 else {break;} 670 } 671 for (i=idx; i<lim; i++) { 672 AP_TOKEN_CHECK(tdm[i]) {slice_size++;} 673 else {break;} 674 } 675 } 676 /* ovsb */ 677 if (tdm[idx]==AP_OVSB_TOKEN) { 678 for (i=idx; i>=0; i--) { 679 if (tdm[i]==AP_OVSB_TOKEN) {slice_size++; idx_start=i;} 680 else {break;} 681 } 682 for (i=idx; i<lim; i++) { 683 if (tdm[i]==AP_OVSB_TOKEN) {slice_size++;} 684 else {break;} 685 } 686 } 687 /* idle */ 688 else if (tdm[idx]==AP_IDL1_TOKEN || tdm[idx]==AP_IDL2_TOKEN) { 689 for (i=idx; i>=0; i--) { 690 if (tdm[i]==AP_IDL1_TOKEN || tdm[i]==AP_IDL2_TOKEN) {slice_size++; idx_start=i;} 691 else {break;} 692 } 693 for (i=idx; i<lim; i++) { 694 if (tdm[i]==AP_IDL1_TOKEN || tdm[i]==AP_IDL2_TOKEN) {slice_size++;} 695 else {break;} 696 } 697 } 698 } 699 700 (*slice_start_idx) = idx_start; 701 return slice_size; 702 } 703 704 705 /** 706 @name: tdm_ap_slice_size_min 707 @param: 708 709 Given port number, returns the MIN size of port slices (mixed with ANCL) in an array 710 */ 711 int 712 tdm_ap_scan_mix_slice_min(unsigned short port, int *tdm, int lim, int *slice_start_idx, int pos) 713 { 714 int i, k=0, idx0, slice_size_min=256, slice_idx=-1 , idx_start; 715 if (pos>=0 && pos<lim) { 716 /* linerate */ 717 AP_TOKEN_CHECK(port) { 718 for (i=0; i<lim; i++) { 719 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 720 AP_TOKEN_CHECK(tdm[idx0]) { 721 k = tdm_ap_scan_mix_slice_size_local(idx0, tdm, lim, &idx_start); 722 if(k>0 && k<slice_size_min){ 723 slice_size_min = k; 724 slice_idx= idx_start; 725 } 726 } 727 } 728 } 729 /* oversub */ 730 else if (port==AP_OVSB_TOKEN){ 731 for (i=0; i<lim; i++) { 732 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 733 if (tdm[idx0]==AP_OVSB_TOKEN) { 734 k = tdm_ap_scan_mix_slice_size_local(idx0, tdm, lim, &idx_start); 735 if(k>0 && k<slice_size_min){ 736 slice_size_min = k; 737 slice_idx= idx_start; 738 } 739 } 740 } 741 } 742 /* idle */ 743 else if (port==AP_IDL1_TOKEN || port==AP_IDL2_TOKEN ){ 744 for (i=0; i<lim; i++) { 745 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 746 if (tdm[idx0]==AP_IDL1_TOKEN || tdm[idx0]==AP_IDL2_TOKEN) { 747 k = tdm_ap_scan_mix_slice_size_local(idx0, tdm, lim, &idx_start); 748 if(k>0 && k<slice_size_min){ 749 slice_size_min = k; 750 slice_idx= idx_start; 751 } 752 } 753 } 754 } 755 } 756 757 (*slice_start_idx) = slice_idx; 758 return slice_size_min; 759 } 760 761 762 /** 763 @name: tdm_ap_scan_mix_slice_max 764 @param: 765 766 Given port number, returns the MAX size of port slices (mixed with ANCL) in an array 767 */ 768 int 769 tdm_ap_scan_mix_slice_max(unsigned short port, int *tdm, int lim, int *slice_start_idx, int pos) 770 { 771 int i, k=0, idx0, slice_size_max=0, slice_idx=-1 , idx_start; 772 if (pos>=0 && pos<lim) { 773 /* linerate */ 774 AP_TOKEN_CHECK(port) { 775 for (i=0; i<lim; i++) { 776 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 777 AP_TOKEN_CHECK(tdm[idx0]) { 778 k = tdm_ap_scan_mix_slice_size_local(idx0, tdm, lim, &idx_start); 779 if(k>slice_size_max){ 780 slice_size_max = k; 781 slice_idx= idx_start; 782 } 783 } 784 } 785 } 786 /* oversub */ 787 else if (port==AP_OVSB_TOKEN){ 788 for (i=0; i<lim; i++) { 789 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 790 if (tdm[idx0]==AP_OVSB_TOKEN) { 791 k = tdm_ap_scan_mix_slice_size_local(idx0, tdm, lim, &idx_start); 792 if(k>slice_size_max){ 793 slice_size_max = k; 794 slice_idx= idx_start; 795 } 796 } 797 } 798 } 799 /* idle */ 800 else if (port==AP_IDL1_TOKEN || port==AP_IDL2_TOKEN ){ 801 for (i=0; i<lim; i++) { 802 idx0 = ((i+pos)<lim)?(i+pos):(i+pos-lim); 803 if (tdm[idx0]==AP_IDL1_TOKEN || tdm[idx0]==AP_IDL2_TOKEN) { 804 k = tdm_ap_scan_mix_slice_size_local(idx0, tdm, lim, &idx_start); 805 if(k>slice_size_max){ 806 slice_size_max = k; 807 slice_idx= idx_start; 808 } 809 } 810 } 811 } 812 } 813 814 (*slice_start_idx) = slice_idx; 815 return slice_size_max; 816 } 817 818 819 /** 820 @name: tdm_ap_scan_mix_slice_size_local 821 @param: 822 823 Given index, returns the largest size of local slice (mixed with ANCL) 824 */ 825 int 826 tdm_ap_scan_mix_slice_size_local(unsigned short idx, int *tdm, int lim, int *slice_start_idx) 827 { 828 int i, slice_size=(-1), idx_start=(-1); 829 830 if(idx<lim){ 831 /* linerate mix ancl */ 832 AP_TOKEN_CHECK(tdm[idx]){ 833 for (i=idx; i>=0; i--) { 834 AP_TOKEN_CHECK(tdm[i]) {slice_size++; idx_start=i;} 835 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++; idx_start=i;} 836 else {break;} 837 } 838 for (i=idx; i<lim; i++) { 839 AP_TOKEN_CHECK(tdm[i]) {slice_size++;} 840 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++;} 841 else {break;} 842 } 843 } 844 /* ancl mix linerate */ 845 else if (tdm[idx]==AP_ANCL_TOKEN){ 846 for (i=idx; i>=0; i--) { 847 AP_TOKEN_CHECK(tdm[i]) {slice_size++; idx_start=i;} 848 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++; idx_start=i;} 849 else {break;} 850 } 851 for (i=idx; i<lim; i++) { 852 AP_TOKEN_CHECK(tdm[i]) {slice_size++;} 853 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++;} 854 else {break;} 855 } 856 } 857 /* oversub mix ancl */ 858 else if (tdm[idx]==AP_OVSB_TOKEN) { 859 for (i=idx; i>=0; i--) { 860 if (tdm[i]==AP_OVSB_TOKEN) {slice_size++; idx_start=i;} 861 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++; idx_start=i;} 862 else {break;} 863 } 864 for (i=idx; i<lim; i++) { 865 if (tdm[i]==AP_OVSB_TOKEN) {slice_size++;} 866 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++;} 867 else {break;} 868 } 869 } 870 /* idle mix ancl */ 871 else if (tdm[idx]==AP_IDL1_TOKEN || tdm[idx]==AP_IDL2_TOKEN) { 872 for (i=idx; i>=0; i--) { 873 if (tdm[i]==AP_IDL1_TOKEN || tdm[i]==AP_IDL2_TOKEN) {slice_size++; idx_start=i;} 874 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++; idx_start=i;} 875 else {break;} 876 } 877 for (i=idx; i<lim; i++) { 878 if (tdm[i]==AP_IDL1_TOKEN || tdm[i]==AP_IDL2_TOKEN) {slice_size++;} 879 else if (tdm[i]==AP_ANCL_TOKEN) {slice_size++;} 880 else {break;} 881 } 882 } 883 } 884 885 (*slice_start_idx) = idx_start; 886 return slice_size; 887 } 888 889 890 /** 891 @name: tdm_ap_check_slot_swap_cond 892 @param: 893 894 Check if two consecutive slots can be swapped in an array 895 --- _X_Y_ -> _Y_X_ 896 --- [idx]=X 897 */ 898 int 899 tdm_ap_check_slot_swap_cond(int idx, int *tdm_tbl, int tdm_tbl_len, int **tsc, enum port_speed_e *speed) 900 { 901 int idx_x, idx_y, idx0, tsc0, idx1, tsc1, result, check_pass=BOOL_TRUE; 902 903 idx_x = idx; 904 idx_y = idx+1; 905 if( !(idx>=0 && idx<(tdm_tbl_len-1)) ) {check_pass = BOOL_FALSE;} 906 907 /* Check sister port spacing: x3_x2_x1_X_Y_y1_y2_y3 */ 908 if (check_pass==BOOL_TRUE){ 909 AP_TOKEN_CHECK(tdm_tbl[idx_x]){ 910 idx0 = idx_x; 911 idx1 = ((idx_x + VBS_MIN_SPACING)<tdm_tbl_len)? (idx_x + VBS_MIN_SPACING): (idx_x + VBS_MIN_SPACING - tdm_tbl_len); 912 tsc0 = tdm_ap_legacy_which_tsc(tdm_tbl[idx0],tsc); 913 tsc1 = tdm_ap_legacy_which_tsc(tdm_tbl[idx1],tsc); 914 if (tsc0==tsc1) {check_pass = BOOL_FALSE;} 915 } 916 AP_TOKEN_CHECK(tdm_tbl[idx_y]){ 917 idx0 = idx_y; 918 idx1 = ((idx_y - VBS_MIN_SPACING)>=0)? (idx_y - VBS_MIN_SPACING): (idx_y - VBS_MIN_SPACING + tdm_tbl_len); 919 tsc0 = tdm_ap_legacy_which_tsc(tdm_tbl[idx0],tsc); 920 tsc1 = tdm_ap_legacy_which_tsc(tdm_tbl[idx1],tsc); 921 if (tsc0==tsc1) {check_pass = BOOL_FALSE;} 922 } 923 } 924 /* Check same port spacing */ 925 if (check_pass==BOOL_TRUE){ 926 AP_TOKEN_CHECK(tdm_tbl[idx_x]){ 927 if (speed[tdm_tbl[idx_x]]<=SPEED_42G_HG2) { 928 idx0 = ((idx_x + LLS_MIN_SPACING)<tdm_tbl_len)? (idx_x + LLS_MIN_SPACING): (idx_x + LLS_MIN_SPACING - tdm_tbl_len); 929 if (tdm_tbl[idx0]==tdm_tbl[idx_x]){ 930 check_pass = BOOL_FALSE; 931 } 932 } 933 } 934 AP_TOKEN_CHECK(tdm_tbl[idx_y]){ 935 if (speed[tdm_tbl[idx_y]]<=SPEED_42G_HG2) { 936 idx0 = ((idx_y - LLS_MIN_SPACING)>=0)? (idx_y - LLS_MIN_SPACING): (idx_y - LLS_MIN_SPACING + tdm_tbl_len); 937 if (tdm_tbl[idx0]==tdm_tbl[idx_y]){ 938 check_pass = BOOL_FALSE; 939 } 940 } 941 } 942 } 943 944 result = (check_pass==BOOL_TRUE)? (PASS): (FAIL); 945 return result; 946 } 947 948 949 /** 950 @name: tdm_ap_check_shift_cond_pattern 951 @param: 952 953 Check if all slots of the given port can shift UP/DOWN in an array 954 --- shift pattern 955 --- sister port spacing 956 */ 957 int 958 tdm_ap_check_shift_cond_pattern(unsigned short port, int *tdm_tbl, int tdm_tbl_len, int **tsc, int dir) 959 { 960 int i, port_tsc, idx0, tsc0, result, shift_cond_pass=BOOL_FALSE; 961 962 /* Check port state */ 963 AP_TOKEN_CHECK(port) { 964 shift_cond_pass = BOOL_TRUE; 965 } 966 /* Check shift pattern */ 967 if (shift_cond_pass==BOOL_TRUE) { 968 /* Downward pattern: _x_ovsb_..._x_ovsb_..._x_ovsb_ */ 969 if (dir==DN) { 970 for (i=0; i<(tdm_tbl_len-1); i++) { 971 if (tdm_tbl[i]==port && tdm_tbl[i+1]!=AP_OVSB_TOKEN && tdm_tbl[i+1]!=AP_ANCL_TOKEN) { 972 shift_cond_pass=BOOL_FALSE; 973 break; 974 } 975 } 976 } 977 /* Upward pattern: _ovsb_x_..._ovsb_x_..._ovsb_x_ */ 978 else{ 979 for (i=1; i<tdm_tbl_len; i++) { 980 if (tdm_tbl[i]==port && tdm_tbl[i-1]!=AP_OVSB_TOKEN && tdm_tbl[i-1]!=AP_ANCL_TOKEN) { 981 shift_cond_pass=BOOL_FALSE; 982 break; 983 } 984 } 985 } 986 } 987 /* Check sister port spacing */ 988 if(shift_cond_pass==BOOL_TRUE){ 989 port_tsc = tdm_ap_legacy_which_tsc(port,tsc); 990 /* Downward pattern: _x_ovsb_..._x_ovsb_..._x_ovsb_ */ 991 if (dir==DN){ 992 for (i=0; i<(tdm_tbl_len-1); i++) { 993 if (tdm_tbl[i]==port) { 994 idx0 = ((i+VBS_MIN_SPACING)<tdm_tbl_len) ? (i+VBS_MIN_SPACING) : (i+VBS_MIN_SPACING-tdm_tbl_len); 995 tsc0 = tdm_ap_legacy_which_tsc(tdm_tbl[idx0],tsc); 996 if ( port_tsc==tsc0 ) { 997 shift_cond_pass = BOOL_FALSE; 998 break; 999 } 1000 } 1001 } 1002 } 1003 /* Upward pattern: _ovsb_x_..._ovsb_x_..._ovsb_x_ */ 1004 else { 1005 for (i=1; i<tdm_tbl_len; i++) { 1006 if (tdm_tbl[i]==port) { 1007 idx0 = ((i-VBS_MIN_SPACING)>=0) ? (i-VBS_MIN_SPACING) : (i-VBS_MIN_SPACING+tdm_tbl_len); 1008 tsc0 = tdm_ap_legacy_which_tsc(tdm_tbl[idx0],tsc); 1009 if ( port_tsc==tsc0 ) { 1010 shift_cond_pass = BOOL_FALSE; 1011 break; 1012 } 1013 } 1014 } 1015 } 1016 } 1017 1018 result = (shift_cond_pass==BOOL_TRUE)? (PASS): (FAIL); 1019 1020 return result; 1021 } 1022 1023 1024 /** 1025 @name: tdm_ap_check_shift_cond_local_slice 1026 @param: 1027 1028 Check if all slots of the given port can shift UP/DOWN in an array 1029 --- local OVSB slice compared with max OVSB slice 1030 --- local LINERATE slice compared with max LINERATE slice 1031 */ 1032 int 1033 tdm_ap_check_shift_cond_local_slice(unsigned short port, int *tdm_tbl, int tdm_tbl_len, int **tsc, int dir) 1034 { 1035 int i, j, slice_idx, ovsb_token, idx0, idx1, shift_cond_pass, result, shift_dir, 1036 os_clump_max_last, lr_clump_max_last, lr_clump_min_last, os_clump_local_above, os_clump_local_below, 1037 filter_port=0, lr_clump_local_last, lr_clump_local_curr; 1038 1039 ovsb_token = AP_OVSB_TOKEN; 1040 shift_dir = (dir==UP) ? (UP) : (DN); 1041 1042 os_clump_max_last = tdm_ap_scan_slice_max(ovsb_token,tdm_tbl,tdm_tbl_len, &slice_idx, 0); 1043 lr_clump_max_last = tdm_ap_scan_mix_slice_max(1,tdm_tbl,tdm_tbl_len, &slice_idx, 0); 1044 lr_clump_min_last = tdm_ap_scan_mix_slice_min(1,tdm_tbl,tdm_tbl_len, &slice_idx, 0); 1045 1046 if ( (lr_clump_max_last<=1) || (lr_clump_max_last==2 && lr_clump_min_last==1) ) { 1047 shift_cond_pass = BOOL_FALSE; 1048 } 1049 else { 1050 shift_cond_pass = BOOL_TRUE; 1051 for (i=0; i<tdm_tbl_len; i++) { 1052 filter_port = tdm_tbl[i]; 1053 if (filter_port!=port){continue;} 1054 1055 /* Check the above/below ovsb slices */ 1056 idx0 = i-1; 1057 idx1 = ((i+1)<tdm_tbl_len)? (i+1): (i+1-tdm_tbl_len); 1058 os_clump_local_above = 0; 1059 os_clump_local_below = 0; 1060 if (tdm_tbl[idx0]==ovsb_token){ 1061 os_clump_local_above = tdm_ap_scan_slice_size_local(idx0,tdm_tbl,tdm_tbl_len, &slice_idx); 1062 } 1063 if (tdm_tbl[idx1]==ovsb_token){ 1064 os_clump_local_below = tdm_ap_scan_slice_size_local(idx1,tdm_tbl,tdm_tbl_len, &slice_idx); 1065 } 1066 if ( (shift_dir==DN && (os_clump_local_above>os_clump_local_below || os_clump_local_above==os_clump_max_last)) || 1067 (shift_dir==UP && (os_clump_local_above<os_clump_local_below || os_clump_local_below==os_clump_max_last)) ){ 1068 shift_cond_pass = BOOL_FALSE; 1069 break; 1070 } 1071 1072 /* Check with max linerate size */ 1073 lr_clump_local_last = tdm_ap_scan_mix_slice_size_local(i,tdm_tbl,tdm_tbl_len, &slice_idx); 1074 lr_clump_local_curr = 1; 1075 if (dir==DN){ 1076 idx0 = ((i+2)<tdm_tbl_len)? (i+2): (i+2-tdm_tbl_len); 1077 if (tdm_tbl[idx0]!=ovsb_token){ 1078 for (j=0; j<(tdm_tbl_len-2); j++){ 1079 idx1 = ((idx0+j)<tdm_tbl_len)? (idx0+j): (idx0+j-tdm_tbl_len); 1080 if (tdm_tbl[idx1]==ovsb_token) { 1081 lr_clump_local_curr = 1 + tdm_ap_scan_mix_slice_size_local(idx0,tdm_tbl,tdm_tbl_len, &slice_idx); 1082 break; 1083 } 1084 else if (tdm_tbl[idx1]==filter_port) { 1085 lr_clump_local_curr = tdm_ap_scan_mix_slice_size_local(idx0,tdm_tbl,tdm_tbl_len, &slice_idx); 1086 break; 1087 } 1088 } 1089 } 1090 } 1091 else { 1092 idx0 = ((i-2)>=0)? (i-2): (i-2+tdm_tbl_len); 1093 if (tdm_tbl[idx0]!=ovsb_token){ 1094 for (j=0; j<(tdm_tbl_len-2); j++){ 1095 idx1 = ((idx0-j)>=0)? (idx0-j): (idx0-j+tdm_tbl_len); 1096 if (tdm_tbl[idx1]==ovsb_token) { 1097 lr_clump_local_curr = 1 + tdm_ap_scan_mix_slice_size_local(idx0,tdm_tbl,tdm_tbl_len, &slice_idx); 1098 break; 1099 } 1100 else if (tdm_tbl[idx1]==filter_port) { 1101 lr_clump_local_curr = tdm_ap_scan_mix_slice_size_local(idx0,tdm_tbl,tdm_tbl_len, &slice_idx); 1102 break; 1103 } 1104 } 1105 } 1106 } 1107 if (lr_clump_local_curr>=lr_clump_max_last){ 1108 shift_cond_pass = BOOL_FALSE; 1109 break; 1110 } 1111 else if (lr_clump_local_curr>lr_clump_local_last ){ 1112 shift_cond_pass = BOOL_FALSE; 1113 break; 1114 } 1115 } 1116 } 1117 1118 result = (shift_cond_pass==BOOL_TRUE)? (PASS): (FAIL); 1119 return result; 1120 } 1121 1122 /** 1123 @name: tdm_ap_scan_which_tsc 1124 @param: 1125 1126 Upward abstraction layer between TDM.4 and TDM.5 API 1127 Only returns enough of TDM.5 style struct to drive scan functions, do not use as class 1128 */ 1129 int 1130 tdm_ap_scan_which_tsc( int port, int tsc[AP_NUM_PHY_PM][AP_NUM_PM_LNS] ) 1131 { 1132 int result=AP_NUM_EXT_PORTS; 1133 tdm_mod_t *_tdm_s; 1134 1135 AP_TOKEN_CHECK(port){ 1136 _tdm_s = tdm_chip_ap_shim__which_tsc_alloc(port, tsc); 1137 if (_tdm_s != NULL) { 1138 result = tdm_ap_which_tsc(_tdm_s); 1139 tdm_chip_ap_shim__which_tsc_free(_tdm_s); 1140 } 1141 } 1142 1143 return result; 1144 1145 }