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_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 }