openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 }