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_td2p_scan.c (27168B)


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