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