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_th2_proc.c (44268B)


      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 operations
      9  */
     10 #ifdef _TDM_STANDALONE
     11 	#include <tdm_top.h>
     12 	#include <tdm_th2_vec.h>
     13 #else
     14 	#include <soc/tdm/core/tdm_top.h>
     15 	#include <soc/tdm/tomahawk2/tdm_th2_vec.h>
     16 #endif
     17 
     18 
     19 /**
     20 @name: tdm_th2_div_round_up
     21 @param:
     22  Works only for positive integer numbers
     23  */
     24 int tdm_th2_div_round_up(int nominator, int denominator)
     25 {
     26 	int round_up;
     27 
     28 	if (denominator == 0) return 1;
     29 	round_up = (nominator+denominator-1)/denominator;
     30 	return round_up;
     31 }
     32 
     33 /**
     34 @name: tdm_th2_div_round_down
     35 @param:
     36  Works only for positive integer numbers
     37  */
     38 int tdm_th2_div_round_down(int nominator, int denominator)
     39 {
     40 	int round_down;
     41 
     42 	if (denominator == 0) return 1;
     43 	round_down = nominator/denominator;
     44 	return round_down;
     45 }
     46 
     47 /**
     48 @name: tdm_th2_div_round
     49 @param:
     50  Works only for positive integer numbers
     51  */
     52 int tdm_th2_div_round(int nominator, int denominator)
     53 {
     54 	int modulo;
     55 
     56 	if (denominator == 0) return 1;
     57 	
     58 	modulo = nominator % denominator;
     59 	
     60 	if (modulo >=((denominator+1)/2)) {
     61 		return (tdm_th2_div_round_up(nominator,denominator));
     62 	} else {
     63 		return (tdm_th2_div_round_down(nominator,denominator));
     64 	}
     65 }
     66 
     67 
     68 /**
     69 @name: tdm_th2_vmap_alloc
     70 @param:
     71  */
     72 int
     73 tdm_th2_vmap_alloc( tdm_mod_t *_tdm )
     74 {
     75 int iter;
     76 int indx_start, indx_end;
     77 
     78     _tdm->_core_data.vars_pkg.os_enable = 1;
     79     _tdm->_core_data.vars_pkg.lr_enable = 0;
     80 
     81     if (_tdm->_chip_data.soc_pkg.flex_port_en == 0) { /* Init time */
     82         /* check if the pipe is in LR or OS */
     83         indx_start = _tdm->_chip_data.soc_pkg.soc_vars.th2.pipe_start - 1;
     84         indx_end = _tdm->_chip_data.soc_pkg.soc_vars.th2.pipe_end;
     85     } else { /* FlexPort */
     86         /* check if the whole device is in LR or OS; 
     87          * covers cases where the whole pipe flexes down 
     88          */
     89         indx_start = 0;
     90         indx_end = TH2_NUM_EXT_PORTS - 8;
     91     }
     92 
     93     for (iter = indx_start; iter < indx_end; iter++) {
     94         if ( (_tdm->_chip_data.soc_pkg.state[iter] == PORT_STATE__LINERATE) ||
     95              (_tdm->_chip_data.soc_pkg.state[iter] == PORT_STATE__LINERATE_HG)) {
     96             _tdm->_core_data.vars_pkg.os_enable = 0;
     97             _tdm->_core_data.vars_pkg.lr_enable = 1;
     98         } else if ( (_tdm->_chip_data.soc_pkg.state[iter] == PORT_STATE__OVERSUB) ||
     99                     (_tdm->_chip_data.soc_pkg.state[iter] == PORT_STATE__OVERSUB_HG) ) {
    100             _tdm->_core_data.vars_pkg.os_enable = 1;
    101             _tdm->_core_data.vars_pkg.lr_enable = 0;
    102         }
    103     }
    104 
    105 	return ( _tdm->_core_exec[TDM_CORE_EXEC__SCHEDULER]( _tdm ) );
    106 }
    107 
    108 
    109 /**
    110 @name: tdm_th2_vbs_scheduler
    111 @param:
    112 
    113 Scheduler for the main TDM calendar (LR ports and OVS tokens)
    114  */
    115 int
    116 tdm_th2_vbs_scheduler( tdm_mod_t *_tdm )
    117 {
    118 	int i,j, k, s, token;
    119 	int tdm_cal_length;
    120 	int *tdm_pipe_main;
    121 	int req_slots=0;
    122 	int first_slot_pos;
    123 	
    124 	
    125 	tdm_th2_vmap_alloc_v2(_tdm);
    126 	
    127 	TDM_PRINT3("tdm_th2_vbs_scheduler() PIPE=%d lr_enable=%d os_enable=%d\n", _tdm->_core_data.vars_pkg.cal_id, _tdm->_core_data.vars_pkg.lr_enable,_tdm->_core_data.vars_pkg.os_enable);
    128 	
    129 	tdm_cal_length = _tdm->_chip_data.soc_pkg.lr_idx_limit + _tdm->_chip_data.soc_pkg.tvec_size;	
    130 
    131 	TDM_SEL_CAL(_tdm->_core_data.vars_pkg.cal_id,tdm_pipe_main);
    132 
    133 
    134 	/* If lr_enable place LR ports and AUX tokens
    135 	   If os_enable place AUX tokens only
    136 	*/
    137 	if (_tdm->_core_data.vars_pkg.lr_enable || _tdm->_core_data.vars_pkg.os_enable) {
    138 		for (i=0; i<(_tdm->_core_data.vmap_max_wid); i++) {
    139 			int distinct_ports[8]; /* all distinct ports in this line*/
    140 			int no_distinct_ports, match;
    141 			
    142 			/* Count the number of slots needed to be placed for this Port Group*/
    143 			for (j=0; j<_tdm->_core_data.vmap_max_len; j++) {
    144 				req_slots = j;
    145 				if (_tdm->_core_data.vmap[i][j] == _tdm->_chip_data.soc_pkg.num_ext_ports) {
    146 					break;
    147 				}
    148 			}
    149 			
    150 			if (req_slots == 0) continue; /* Nothing to be placed from this line */
    151 
    152 			/*	STEP 4.3 Find the first available slot in the calendar PM<i>_first_slot;
    153 				NOTE1: Also, the first slot could be found by randomly searching for an available slot in the range [0:PM<i>_distance-1];
    154 				NOTE2: OR, to avoid clumping of unallocated ports, the first slot could be found in the middle of the biggest clump of unallocated ports in the range [0:PM<i>_distance-1];
    155 				This will be good for mixed LR and OVS pipelines to spread OVS tokens as uniformly as possible.
    156 			*/			
    157 			first_slot_pos = tdm_th2_find_first_avail_slot(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports);
    158 			
    159 			no_distinct_ports = 1;
    160 			distinct_ports[0] = _tdm->_core_data.vmap[i][0];
    161 			for (j=0; j<req_slots; j++) {
    162 				match = 0;
    163 				for (k=0; k<no_distinct_ports;k++) {
    164 					if ( (_tdm->_core_data.vmap[i][j] == distinct_ports[k]) || (_tdm->_core_data.vmap[i][j] == 555) ) {
    165 						match=1;
    166 					}
    167 				}
    168 				if (match==0) {
    169 					distinct_ports[no_distinct_ports] = _tdm->_core_data.vmap[i][j];
    170 					no_distinct_ports++;
    171 				}
    172 			}
    173 			
    174 			for (k=0; k<no_distinct_ports;k++) {
    175 				TDM_PRINT2("tdm_th2_vbs_scheduler() Need to place in this line k=%d PhyPort=%d\n", k, distinct_ports[k]);
    176 			}
    177 			
    178 		   for (k=0; k<no_distinct_ports;k++) {
    179 			
    180 			/*
    181 			STEP4.3 for s=0: PM_num_slots-1 DO
    182 			*/
    183 			for (s=0; s < req_slots; s++) {
    184 				int ideal_pos, port_req_slots, port_jitter;
    185 				token = _tdm->_core_data.vmap[i][s];
    186 				if (token == 555) continue; /* nothing to place here */
    187 				if (token != distinct_ports[k]) continue; /* nothing to place here for now*/
    188 			/*
    189 				4.3.1 Pick the phy port to be placed based on subport placement table
    190 				Skip steps 4.3.2/4.3.3/4.3.4 if Pl_Tbl[s%Pl_Tbl_Length]==N		
    191 				PhyPort=PM_Phy_Port_Base + Pl_Tbl[s%Pl_Tbl_Length] (% - modulo)
    192 				NOTE: PM_Phy_Port_Base is first physical port in PM<i> (subport 0)
    193 				4.3.2 Compute the ideal position in the calendar where PhyPort needs to be placed
    194 				Ideal_Pos = PM<i>_first_slot + floor((s* CAL_LENGTH)/PM_num_slots)
    195 				4.3.3 Compute the jitter (tolerance from Ideal_Pos, PhyPort_Jitter)
    196 				PhyPort_Jitter = rount((JITTER_PCT*CAL_LENGTH)/PM_num_slots/2/100)
    197 				NOTE_1: uses floor to be more restrictive
    198 				NOTE_2: to be even more restrictive use JITTER_PCT/2; mathematically this is the correct percentage to get 
    199 				less then max jitter within JITTER_PCT between any two consecutive same port slots.
    200 			*/
    201 				ideal_pos = (first_slot_pos + tdm_th2_div_round(s*tdm_cal_length, req_slots)) % tdm_cal_length;  /* that is  round((s*tdm_cal_length)/pm_req_slots) */
    202 				if (token < _tdm->_chip_data.soc_pkg.num_ext_ports) {
    203 					port_req_slots = _tdm->_chip_data.soc_pkg.speed[token]/(BW_QUANTA*100);
    204 					port_jitter = tdm_th2_div_round( (TH2_LR_JITTER_PCT*tdm_cal_length), (port_req_slots*100*2)); 
    205 					port_jitter = (port_jitter == 0) ? 1 : port_jitter;
    206 				} else {
    207 					port_jitter = tdm_cal_length - 1;  /*  For AUX Ports use max possible jitter;  don't allow shifts */
    208 				}
    209 			/*	4.3.4 Place PhyPort in the calendar at Ideal_Pos with tolerance PhyPort_Jitter
    210 			*/
    211 				if (tdm_th2_place_lr_port(_tdm, tdm_pipe_main, token, ideal_pos, port_jitter, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports) == PASS) {
    212 					/*TDM_PRINT3("tdm_th2_vbs_scheduler() Placing PhyPort=%d at Ideal_Pos=%d with Jitter=%d\n",phy_port, ideal_pos, port_jitter);*/
    213 				} else {
    214 					port_jitter = port_jitter / 2;
    215 					port_jitter = (port_jitter == 0) ? 1 : port_jitter;
    216 					TDM_PRINT3("tdm_th2_vbs_scheduler() 1st iter failed: Trying to place PhyPort=%d at Ideal_Pos=%d with Jitter=%d\n",token, ideal_pos, port_jitter);
    217 					if (tdm_th2_place_lr_port(_tdm, tdm_pipe_main, token, ideal_pos, port_jitter, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports) == FAIL) {
    218 						TDM_ERROR3("tdm_th2_vbs_scheduler() 2nd iter FAILED in Placing PhyPort=%d at Ideal_Pos=%d with Jitter=%d\n",token, ideal_pos, port_jitter);
    219 					}
    220 				}
    221 			}
    222 		   }
    223 
    224 	TDM_PRINT2("tdm_th2_vbs_scheduler() AFter placing pm_num=%d pm_req_slots=%d\n", i, req_slots);
    225 	for (s=0; s<tdm_cal_length; s++) {
    226 		if (s%32==0) {
    227 			TDM_PRINT0("\n");
    228 			TDM_PRINT2("%3d : %3d\t",s, s+31);
    229 		}
    230 		
    231 		if (tdm_pipe_main[s] != _tdm->_chip_data.soc_pkg.num_ext_ports)
    232 			TDM_PRINT1("%5d",tdm_pipe_main[s]);
    233 		else
    234 			TDM_PRINT0("  ---");
    235 	}
    236 	TDM_PRINT0("\n\n");
    237 
    238 
    239 
    240 		}
    241 	}
    242 
    243 
    244 
    245    /* If PIPE is active then place AUX ports & OVS or IDLE tokens */
    246    if (_tdm->_core_data.vars_pkg.os_enable || _tdm->_core_data.vars_pkg.lr_enable) {
    247 
    248 
    249 	/* Place AUX ports*/
    250 	/*if (_tdm->_core_exec[TDM_CORE_EXEC__ACCESSORIZE]( _tdm )==FAIL) {*/
    251 	if (tdm_th2_acc_alloc(_tdm)==FAIL) {
    252 		return (TDM_EXEC_CORE_SIZE+1);
    253 	}
    254 	
    255 	/* OVS pipe: Place the OVS token for all unallocated slots */
    256 	if (_tdm->_core_data.vars_pkg.os_enable && (!_tdm->_core_data.vars_pkg.lr_enable)) {
    257 		for (j=0; j<tdm_cal_length; j++) {
    258 			if (tdm_pipe_main[j]==_tdm->_chip_data.soc_pkg.num_ext_ports) {
    259 				tdm_pipe_main[j] = _tdm->_chip_data.soc_pkg.soc_vars.ovsb_token;
    260 			}
    261 		}
    262 	} else {
    263 	/* LR pipe: Place IDLE tokens for all unallocated slots */
    264 		for (j=0; j<tdm_cal_length; j++) {
    265 			if (tdm_pipe_main[j]==_tdm->_chip_data.soc_pkg.num_ext_ports) {
    266 				tdm_pipe_main[j] = _tdm->_chip_data.soc_pkg.soc_vars.idl2_token; /* Uncallocated slots in LR pipes get IDLE token */
    267 			}
    268 		}
    269 	}
    270    }
    271 	
    272 	/* OVS grouping */
    273 	if (_tdm->_core_exec[TDM_CORE_EXEC__SCHEDULER_OVS](_tdm)==FAIL) {
    274 		return (TDM_EXEC_CORE_SIZE+1);
    275 	}
    276 	
    277 	return ( _tdm->_chip_exec[TDM_CHIP_EXEC__FILTER]( _tdm ) );
    278 }
    279 
    280 
    281 
    282 /**
    283 @name: tdm_th2_get_place_table
    284 @param:
    285  */
    286 int
    287 tdm_th2_get_pm_speed_and_place_table( enum port_speed_e *_pm_speeds, int num_lanes, int *place_tbl,  int *place_table_length)
    288 {
    289 	int is_100G=0, is_80G=0, is_40G=0;
    290 	int i;
    291 	int pm_sum=0;
    292 	
    293 	for (i=0; i<num_lanes; i++) {
    294 		if (_pm_speeds[i] == SPEED_0) continue;
    295 		if (_pm_speeds[i] % SPEED_25G == 0) {
    296 			is_100G=1;
    297 		}
    298 		if ((_pm_speeds[i]==SPEED_40G) || (_pm_speeds[i]==SPEED_20G) || (_pm_speeds[i]==SPEED_10G)) {
    299 			is_40G=1;
    300 		}
    301 		pm_sum += _pm_speeds[i];
    302 	}
    303 	
    304 	if (is_40G && ((pm_sum > SPEED_40G) || (_pm_speeds[2]==SPEED_40G))) { /* Could be 0, 0, 40G, 0 */
    305 		is_80G=1;
    306 		is_40G=0;
    307 	}
    308 	
    309 	
    310 	if (is_100G) {
    311 		(*place_table_length) = 4;
    312 		if (_pm_speeds[0]==SPEED_100G) { place_tbl[0]=0; place_tbl[1]=0; place_tbl[2]=0; place_tbl[3]=0;} /* SINGLE */
    313 		else {
    314 			if (_pm_speeds[0]==SPEED_50G) {
    315 				if (_pm_speeds[2]==SPEED_50G) {place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=2; }  /* DUAL */
    316 				else { place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=3;}   /* TRI_0 */
    317 			} else {
    318 				if (_pm_speeds[2]==SPEED_50G) {place_tbl[0]=2; place_tbl[1]=0; place_tbl[2]=2; place_tbl[3]=1; }    /* TRI_1 */
    319 				else { place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=1; place_tbl[3]=3;}    /* QUAD */
    320 			}
    321 		}
    322 		return (SPEED_100G);
    323 	} else if (is_40G) {
    324 		(*place_table_length) = 4;
    325 		if (_pm_speeds[0]==SPEED_40G) { place_tbl[0]=0; place_tbl[1]=0; place_tbl[2]=0; place_tbl[3]=0;} /* SINGLE */
    326 		else {
    327 			if (_pm_speeds[0]==SPEED_20G) {
    328 				if (_pm_speeds[2]==SPEED_20G) {place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=2; }  /* DUAL */
    329 				else { place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=3;}   /* TRI_0 */
    330 			} else {
    331 				if (_pm_speeds[2]==SPEED_20G) {place_tbl[0]=2; place_tbl[1]=0; place_tbl[2]=2; place_tbl[3]=1; }    /* TRI_1 */
    332 				else { place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=1; place_tbl[3]=3;}    /* QUAD */
    333 			}
    334 		}
    335 		return (SPEED_40G);
    336 	} else if (is_80G){ /* is_80G */
    337 		if ((_pm_speeds[0]==SPEED_40G) && (_pm_speeds[2]==SPEED_40G)) {
    338 			(*place_table_length) = 4;
    339 			place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=2;  /* DUAL 40/40 */
    340 		} else if (_pm_speeds[0]==SPEED_20G) {                                   /* DUAL 20/40 */
    341 			(*place_table_length) = 4;
    342 			place_tbl[0]=2; place_tbl[1]=0; place_tbl[2]=2; place_tbl[3]=5;
    343 		} else if (_pm_speeds[2]==SPEED_20G) {                                   /* DUAL 40/20 */
    344 			(*place_table_length) = 4;
    345 			place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=5;
    346 		} else { /* TRI cases */
    347 			(*place_table_length) = 8;
    348 			if (_pm_speeds[0]==SPEED_40G) {
    349 				place_tbl[0]=0; place_tbl[1]=2; place_tbl[2]=0; place_tbl[3]=5;    /* TRI_0 4:1:1;  5 - means don't place anything*/
    350 				place_tbl[4]=0; place_tbl[5]=3; place_tbl[6]=0; place_tbl[7]=5;
    351 			} else {
    352 				place_tbl[0]=2; place_tbl[1]=0; place_tbl[2]=2; place_tbl[3]=5;    /* TRI_0 1:1:4 */
    353 				place_tbl[4]=2; place_tbl[5]=1; place_tbl[6]=2; place_tbl[7]=5;
    354 			}
    355 		}
    356 		return (2*SPEED_40G);
    357 	} else {
    358 		return (SPEED_0);
    359 	}
    360 }
    361 
    362 
    363 
    364 /**
    365 @name: tdm_th2_find_first_avail_slot
    366 @param:
    367  */
    368 int
    369 tdm_th2_find_first_avail_slot(int *tdm_pipe_main, int tdm_cal_length, int avail_token)
    370 {
    371 	int i, j, max_clump_start, max_clump_slots, clump_start, clump_slots;
    372 	int first_avail;
    373 
    374 	/* Just return the first available token starting with index 0 */
    375 /*
    376 	for (i=0; i<tdm_cal_length; i++) {
    377 		if (tdm_pipe_main[i] == avail_token) {
    378 			return i;
    379 		}
    380 	}
    381 	return -1;
    382 */
    383 
    384 	/* Return the middle of the biggest clump in the calendar (including wraps) */
    385 	max_clump_start=0;
    386 	max_clump_slots=0;
    387 	for (i=0; i<tdm_cal_length; i++) {
    388 		if (tdm_pipe_main[i] != avail_token) {
    389 			continue; 
    390 		} else {
    391 			clump_start= i;
    392 			clump_slots=0;
    393 			for (j=0; j<tdm_cal_length; j++) {
    394 				if (tdm_pipe_main[(i+j)%tdm_cal_length] == avail_token) {
    395 					clump_slots++;
    396 				} else {
    397 					break;
    398 				}
    399 			}
    400 			if (clump_slots > max_clump_slots){
    401 				max_clump_start = clump_start;
    402 				max_clump_slots = clump_slots;
    403 			}
    404 			
    405 		}
    406 	}
    407 	
    408 	if (max_clump_slots==tdm_cal_length) {
    409 		first_avail=0;
    410 	} else {
    411 		first_avail = (max_clump_start + (max_clump_slots/2)) % tdm_cal_length;
    412 	}
    413 	
    414 	TDM_PRINT3("tdm_th2_find_first_avail_slot() finding at %d max_clump_start=%d max_clump_slots=%d\n", first_avail, max_clump_start, max_clump_slots);
    415 	
    416 	return (first_avail);
    417 
    418 
    419 }
    420 
    421 
    422 
    423 /**
    424 @name: tdm_th2_find_first_avail_slot_w_start
    425 @param:
    426  */
    427 int
    428 tdm_th2_find_first_avail_slot_w_start(int *tdm_pipe_main, int tdm_cal_length, int avail_token, int start_pos)
    429 {
    430 	int i, pos;
    431 
    432 	/* Just return the first available token starting with index start_pos */
    433 	for (i=0; i<tdm_cal_length; i++) {
    434 		pos= (start_pos+i) % tdm_cal_length;
    435 		if (tdm_pipe_main[pos] == avail_token) {
    436 			return pos;
    437 		}
    438 	}
    439 	return -1;
    440 }
    441 
    442 
    443 
    444 
    445 /**
    446 @name: tdm_th2_vmap_alloc_v2
    447 @param:
    448  */
    449 int
    450 tdm_th2_vmap_alloc_v2( tdm_mod_t *_tdm )
    451 {
    452 	int i,j, s, ln_num;
    453 	int pipe_id, pms_per_pipe, pm_indx, pm_num, phy_base_port, phy_port;
    454 	int pm_max_slots[TH2_NUM_PHY_PM/TH2_NUM_QUAD];
    455 	int pm_total_slots[TH2_NUM_PHY_PM/TH2_NUM_QUAD];
    456 	int pm_num_sort[TH2_NUM_PHY_PM/TH2_NUM_QUAD];
    457 	int pm_max_speed, pm_req_slots;
    458 	/*enum port_speed_e pm_max_speed=SPEED_0;*/
    459 
    460 	for (i=0; i<(_tdm->_core_data.vmap_max_wid); i++) {
    461 		TDM_MSET(_tdm->_core_data.vmap[i],_tdm->_chip_data.soc_pkg.num_ext_ports,_tdm->_core_data.vmap_max_len);
    462 	}
    463 
    464 	pipe_id = _tdm->_core_data.vars_pkg.cal_id;
    465 
    466    if (_tdm->_core_data.vars_pkg.lr_enable) {
    467 	pms_per_pipe  = _tdm->_chip_data.soc_pkg.pm_num_phy_modules/TH2_NUM_QUAD;
    468 	
    469 	/* STEP 1. Group ports by their corresponding PMs (PM<n>).*/
    470 	/* STEP 2. Find the biggest speed port in each PM and compute the jitter for this port (PM<n>_min_jitter).
    471 		PM_num_slots=PM_speed/QUANTA_BW
    472 		PhyPort_Jitter = floor((20*CAL_LENGTH)/PM_num_slots/100)
    473 	*/
    474 	pm_indx=0;
    475 	for (pm_num=pipe_id*pms_per_pipe; pm_num<(pipe_id+1)*pms_per_pipe; pm_num++) {
    476 		pm_max_speed = 0;
    477 		pm_total_slots[pm_indx] = 0;
    478 		phy_base_port = _tdm->_chip_data.soc_pkg.pmap_num_lanes*pm_num+1;
    479 		for (ln_num=0; ln_num<_tdm->_chip_data.soc_pkg.pmap_num_lanes; ln_num++) {
    480 			phy_port = phy_base_port+ln_num;
    481 
    482 			if( (_tdm->_chip_data.soc_pkg.speed[phy_port] != SPEED_0) &&
    483 				((_tdm->_chip_data.soc_pkg.state[phy_port-1] == PORT_STATE__LINERATE   ) ||
    484 				 (_tdm->_chip_data.soc_pkg.state[phy_port-1] == PORT_STATE__LINERATE_HG) ) ) {
    485 				if (_tdm->_chip_data.soc_pkg.speed[phy_port] > pm_max_speed) {
    486 					pm_max_speed = _tdm->_chip_data.soc_pkg.speed[phy_port];
    487 				}
    488 				pm_total_slots[pm_indx] += _tdm->_chip_data.soc_pkg.speed[phy_port]/BW_QUANTA/100;
    489 			}
    490 		}
    491 		pm_max_slots[pm_indx] = pm_max_speed/BW_QUANTA/100;
    492 		pm_num_sort[pm_indx]  = pm_num;
    493 		/*TDM_PRINT4("tdm_th2_avs_part_halfpipe2() pm_indx=%d pm_num=%d pm_speed=%d pm_num_subports=%d\n",pm_indx, pm_num_sort[pm_indx], pm_speed[pm_indx], pm_num_subports[pm_indx]);*/
    494 		pm_indx++;
    495 	}
    496 
    497 
    498 	for (i=0; i<pms_per_pipe; i++)
    499 	{
    500 		TDM_PRINT3("tdm_th2_vmap_alloc_v2() pm_num=%d pm_max_slots=%d pm_num_sort=%d\n",i, pm_max_slots[i], pm_num_sort[i]);
    501 	}
    502 
    503 	/* STEP3. Sort PMs by their PM<n>_min_jitter in descending order (PM_min_jitter_sort_list). */
    504 	/* This is equvalent with sorting pm_max_slots in descending order - bubble sort*/
    505 	for (i=0; i<pms_per_pipe-1; i++)
    506 	{
    507 		for (j=pms_per_pipe-1; j>i; j--)
    508 		{
    509 			if ( (pm_max_slots[j] > pm_max_slots[j-1]) || 
    510 			     ((pm_max_slots[j] == pm_max_slots[j-1]) && (pm_total_slots[j] > pm_total_slots[j-1]) ) ) /* swap j with j-1*/
    511 			{
    512 				int tmp;
    513 				tmp = pm_num_sort[j];
    514 				pm_num_sort[j] = pm_num_sort[j-1];
    515 				pm_num_sort[j-1] = tmp;
    516 				tmp = pm_max_slots[j];
    517 				pm_max_slots[j] = pm_max_slots[j-1];
    518 				pm_max_slots[j-1] = tmp;
    519 				tmp = pm_total_slots[j];
    520 				pm_total_slots[j] = pm_total_slots[j-1];
    521 				pm_total_slots[j-1] = tmp;
    522 			}
    523 		}
    524 	}
    525 
    526 	for (i=0; i<pms_per_pipe; i++)
    527 	{
    528 		TDM_PRINT4("tdm_th2_vmap_alloc_v2() pm_num=%d pm_max_slots=%d pm_num_sort=%d pm_total_slots=%0d\n",i, pm_max_slots[i], pm_num_sort[i], pm_total_slots[i]);
    529 	}
    530 
    531 
    532 	
    533 	/* STEP4. Foreach PM<i> in PM_min_jitter_sort_list DO: */
    534 	for (i=0; i<pms_per_pipe; i++)
    535 	{
    536 		enum port_speed_e pm_speeds[TH2_NUM_PM_LNS];
    537 		int place_tbl[8], place_table_length;
    538 
    539 		TDM_PRINT3("tdm_th2_vmap_alloc_v2() pm_indx=%d pm_num=%d pm_max_slots=%d\n",i, pm_num_sort[i], pm_max_slots[i]);
    540 		if (pm_max_slots[i] > 0) {
    541 			pm_num = pm_num_sort[i];
    542 			phy_base_port = _tdm->_chip_data.soc_pkg.pmap_num_lanes*pm_num+1;
    543 			_tdm->_core_data.vars_pkg.port = phy_base_port; /* Pass to _tdm which PM needs to be placed */
    544 
    545 		/*	STEP 4.1 Compute number of slots needed by PM 
    546 			PM_num_slots=PM<i>_speed/QUANTA_BW
    547 			(NOTE: for PM 40/10/10 configurations, PM_speed will be 80G and not 60G; thus, some slots will be left unoccupied)
    548 		*/
    549 		/* 	STEP 4.2 Generate a subport placement table (Pl_Tbl) based on port_mode and subport speeds; See table 1.1.
    550 		*/
    551 			
    552 			for (ln_num=0; ln_num<_tdm->_chip_data.soc_pkg.pmap_num_lanes; ln_num++) {
    553 				phy_port = phy_base_port+ln_num;
    554 				pm_speeds[ln_num] = _tdm->_chip_data.soc_pkg.speed[phy_port];
    555 			}
    556 			
    557 			pm_max_speed = tdm_th2_get_pm_speed_and_place_table(pm_speeds, _tdm->_chip_data.soc_pkg.pmap_num_lanes, place_tbl, &place_table_length);
    558 			pm_req_slots = pm_max_speed/(BW_QUANTA*100);
    559 			
    560 			TDM_PRINT3("tdm_th2_vmap_alloc_v2() pm_num=%d pm_max_speed=%dG pm_req_slots=%d\n",pm_num, pm_max_speed/1000, pm_req_slots);
    561 			
    562 			TDM_PRINT1("tdm_th2_vmap_alloc_v2() pm_num=%d Placing table is\n",pm_num);
    563 			for (s=0; s<place_table_length; s++){
    564 				TDM_PRINT1("%5d",place_tbl[s]);
    565 			}
    566 			TDM_PRINT0("\n\n");
    567 
    568 		/*
    569 			STEP4.3 for s=0: PM_num_slots-1 DO
    570 		*/
    571 			for (s=0; s<pm_req_slots; s++) {
    572 				ln_num = place_tbl[s % place_table_length];
    573 				if ((ln_num == 5)) {
    574 					_tdm->_core_data.vmap[i][s]=555;
    575 				} else {
    576 					phy_port = phy_base_port+ln_num;
    577 					if  (_tdm->_chip_data.soc_pkg.speed[phy_port] == SPEED_0) {
    578 						_tdm->_core_data.vmap[i][s]=555;
    579 					} else {
    580 						_tdm->_core_data.vmap[i][s]=phy_port;					
    581 					}
    582 				}
    583 			}
    584 		}
    585 	}
    586 	
    587 
    588    }	
    589 
    590    /* If PIPE is active then place AUX ports & OVS or IDLE tokens */
    591    if (_tdm->_core_data.vars_pkg.os_enable || _tdm->_core_data.vars_pkg.lr_enable) {
    592    
    593 	/* Find first available line */
    594 	for (i=0; i<(_tdm->_core_data.vmap_max_wid); i++) {
    595 		if (_tdm->_core_data.vmap[i][0] == _tdm->_chip_data.soc_pkg.num_ext_ports) {
    596 			break;
    597 		}
    598 	}
    599 	/* Place AUX tokens */
    600 	
    601 	/* CPU/MGM slots */
    602 /*
    603 	for (j=0; j<TH2_CPU_SLOTS; j++) {
    604 		_tdm->_core_data.vmap[i][j] = TH2_ANCL_TOKEN;
    605 	}
    606 */
    607 	/* LBK slots */
    608 /*
    609 	i++;
    610 	for (j=0; j<TH2_LBK_SLOTS; j++) {
    611 		_tdm->_core_data.vmap[i][j] = TH2_ANCL_TOKEN+1;
    612 	}
    613 */
    614 	/* LBK slots */
    615 /*
    616 	i++;
    617 	for (j=0; j<TH2_ANC_SLOTS; j++) {
    618 		_tdm->_core_data.vmap[i][j] = TH2_ANCL_TOKEN+2;
    619 	}
    620 */
    621    }
    622 /*
    623 	TDM_PRINT0("\n\n");
    624 	TDM_SML_BAR
    625 	TDM_PRINT1("\tdm_th2_vmap_alloc_v2() ALLOCATION Solution vmap pipe %0d:\n\n           ",((_tdm->_core_data.vmap[0][0])/64));
    626 	tdm_print_vmap_vector(_tdm);
    627 	TDM_PRINT0("\n\n\n");
    628 	TDM_SML_BAR
    629 */
    630 
    631 
    632 
    633 /*	return ( _tdm->_core_exec[TDM_CORE_EXEC__SCHEDULER]( _tdm ) );*/
    634 	return PASS;
    635 }
    636 
    637 
    638 
    639 
    640 /**
    641 @name: tdm_th2_get_min_max_jitter
    642 @param:
    643  */
    644 int
    645 tdm_th2_get_min_max_jitter(int tbl_len, int port_slots, int lr_jitter_pct, int *min_spacing, int *max_spacing)
    646 {
    647 	int rem, jitter_range;
    648 
    649 	if (port_slots == 0) {
    650 		(*min_spacing) = 0;
    651 		(*max_spacing) = 0;
    652 		return FAIL;
    653 	}
    654 
    655 	rem = tbl_len % port_slots;
    656 	jitter_range = tdm_th2_div_round( (2*tbl_len*lr_jitter_pct), (port_slots*100) ); /* 20% from ideal_spacing */
    657 	
    658 	if(rem >= ((port_slots+1)/2)) {
    659 		(*min_spacing) = tdm_th2_div_round_up(tbl_len,port_slots)   - tdm_th2_div_round_up(jitter_range,2);       /*ROUNDUP(ideal_spacing[port_speed],0) - ROUNDUP(range[port_speed]/2, 0);*/
    660 		(*max_spacing) = tdm_th2_div_round_up(tbl_len,port_slots)   + tdm_th2_div_round_down(jitter_range,2);     /*ROUNDUP(ideal_spacing[port_speed],0) + ROUNDDOWN(range[port_speed]/2, 0);*/
    661 	} else {
    662 		(*min_spacing) = tdm_th2_div_round_down(tbl_len,port_slots) - tdm_th2_div_round_down(jitter_range,2);	  /*ROUNDDOWN(ideal_spacing[port_speed],0) - ROUNDDOWN(range[port_speed]/2, 0);*/
    663 		(*max_spacing) = tdm_th2_div_round_down(tbl_len,port_slots) + tdm_th2_div_round_up(jitter_range,2);	  /*ROUNDDOWN(ideal_spacing[port_speed],0) + ROUNDUP(range[port_speed]/2, 0);*/
    664 	}
    665 
    666 	return PASS;
    667 }
    668 
    669 
    670 
    671 
    672 /**
    673 @name: tdm_th2_check_lr_placement
    674 @param:
    675 
    676 Checks if placement of phy_port in position pos will violate any sister port spacing or min/max jitter
    677  */
    678 int
    679 tdm_th2_check_lr_placement(tdm_mod_t *_tdm, int *tdm_pipe_main, int tbl_len, int phy_port, int pos, int lr_jitter_pct, int avail_token)
    680 {
    681 
    682 	int i, left_distance;
    683 	int no_occur;
    684 	int first_slot;
    685 	int port_slots;
    686 	int min_spacing, max_spacing;
    687 	int pos_t, tsc_pos, tsc_pos_t;
    688 	
    689 	/* Check only regular port */
    690 	if (phy_port < avail_token) {
    691 
    692 		/* Check sister spacing */
    693 		/* Sister port spacing for regular ports only */
    694 		_tdm->_core_data.vars_pkg.port = phy_port;
    695 		tsc_pos = tdm_find_pm(_tdm);
    696 		for (i=1; i< 4; i++) {
    697 			/* check sister port at left */
    698 			pos_t = (tbl_len+pos-i)%tbl_len;
    699 			if ( tdm_pipe_main[pos_t] < avail_token) {
    700 				_tdm->_core_data.vars_pkg.port = tdm_pipe_main[pos_t];
    701 				tsc_pos_t = tdm_find_pm(_tdm);
    702 				if ((tsc_pos_t == tsc_pos)) {
    703 					TDM_PRINT4("tdm_th2_check_lr_placement() ___WARNING RIGHT - Port=%d is violating sister spacing if placed in pos=%d; sister port is in pos=%d sis_port=%d \n", phy_port, pos, pos_t, tdm_pipe_main[pos_t]);
    704 					return FAIL;
    705 				}
    706 			}
    707 			/* check sister port at right */
    708 			pos_t = (pos+i)%tbl_len;
    709 			if ( tdm_pipe_main[pos_t] < avail_token) {
    710 				_tdm->_core_data.vars_pkg.port = tdm_pipe_main[pos_t];
    711 				tsc_pos_t = tdm_find_pm(_tdm);
    712 				if ((tsc_pos_t == tsc_pos)) {
    713 					TDM_PRINT3("tdm_th2_check_lr_placement() ___WARNING RIGHT - Port=%d is violating sister spacing if placed in pos=%d; sister port is in pos=%d\n", phy_port , pos, pos_t);
    714 					return FAIL;
    715 				}
    716 			}
    717 		}
    718 		
    719 		/* compute the distance from the same port located on the left side to ideal_pos;  If first slot to be placed ignore distance*/
    720 		no_occur = 0 ;
    721 		for (i=0; i < tbl_len; i++) {
    722 			if (phy_port == tdm_pipe_main[i]) {
    723 				no_occur++;
    724 			}
    725 		}
    726 		first_slot = (no_occur==0) ? 1 : 0;
    727 	
    728 		if (first_slot==1) { /* just put something there to pass */
    729 			return PASS;
    730 		} else {
    731 			/* compute min & max jitter */	
    732 			port_slots = _tdm->_chip_data.soc_pkg.speed[phy_port]/(BW_QUANTA*100);
    733 			tdm_th2_get_min_max_jitter(tbl_len, port_slots, TH2_LR_JITTER_PCT, &min_spacing, &max_spacing);
    734 			/* compute the distance */
    735 			left_distance=0;
    736 			for (i=1; i < tbl_len; i++) {
    737 				left_distance++;
    738 				if (tdm_pipe_main[(tbl_len+pos-i)%tbl_len] == phy_port) { break; }
    739 			}
    740 			if ( (left_distance < min_spacing)  ||  (left_distance > max_spacing)  ||  (left_distance < _tdm->_core_data.rule__prox_port_min) ) {
    741 				TDM_PRINT4("tdm_th2_check_lr_placement() ___WARNING Port=%d placed at pos=%d will be out of the jitter range min_spacing=%d max_spacing=%d\n", phy_port, pos, min_spacing, max_spacing);
    742 				return FAIL;
    743 			}
    744 		}
    745 	}
    746 	
    747 	return PASS;
    748 }
    749 
    750 
    751 
    752 
    753 
    754 /**
    755 @name: tdm_th2_place_lr_port
    756 
    757 @param:
    758  */
    759 int
    760 tdm_th2_place_lr_port(tdm_mod_t *_tdm, int *tdm_pipe_main, int phy_port, int ideal_pos, int port_jitter, int tdm_cal_length, int avail_token)
    761 {
    762 	int t, pos;
    763 	int avail_pos_left=0, avail_pos_right=0;
    764 	int left_slice_length, right_slice_length, i;
    765 	int shift_jitter;
    766 	int result, result_left, result_right;
    767 	int is_sist_fail_left, is_sist_fail_right;
    768 	int execute_left, execute_right;
    769 	
    770 /*	Try to place PhyPort in Ideal_Pos; if slot unavailable continue, else place & exit 4.3.4
    771 */
    772 	if (tdm_pipe_main[ideal_pos] == avail_token &&
    773 		(tdm_th2_check_lr_placement(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, ideal_pos, TH2_LR_JITTER_PCT, avail_token)==PASS) )
    774 	{
    775 		tdm_pipe_main[ideal_pos] = phy_port;
    776 		TDM_PRINT4("tdm_th2_place_lr_port() Placing PhyPort=%d at position %d; IdealPos=%d t=%d\n", phy_port, ideal_pos, ideal_pos, 0);
    777 		return PASS;
    778 	}
    779 	
    780 
    781 /*
    782 	for t= 1:PhyPort_Jitter DO {
    783 try to place in Ideal_Pos-t; if slot unavailable continue, else place & exit 4.3.4
    784 try to place in Ideal_Pos+t; if slot unavailable continue or (Ideal_Pos+t)>= CAL_LENGTH, else place & exit 4.3.4
    785 }
    786 */
    787 	for (t=1; t<= port_jitter; t++) {
    788 		pos = (tdm_cal_length+ideal_pos-t) % tdm_cal_length;
    789 		if ((tdm_pipe_main[pos] == avail_token) &&
    790 			(tdm_th2_check_lr_placement(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, pos, TH2_LR_JITTER_PCT, avail_token)==PASS) )
    791 		{
    792 			tdm_pipe_main[pos] = phy_port;
    793 			TDM_PRINT4("tdm_th2_place_lr_port() Placing PhyPort=%d at position %d; IdealPos=%d t=%d\n", phy_port, pos, ideal_pos, -t);
    794 			return PASS;
    795 		}
    796 		pos = (ideal_pos+t) % tdm_cal_length;
    797 		if ( (tdm_pipe_main[pos] == avail_token) &&
    798 			(tdm_th2_check_lr_placement(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, pos, TH2_LR_JITTER_PCT, avail_token)==PASS) )
    799 		{
    800 			tdm_pipe_main[pos] = phy_port;
    801 			TDM_PRINT4("tdm_th2_place_lr_port() Placing PhyPort=%d at position %d; IdealPos=%d t=%d\n", phy_port, pos, ideal_pos, t);
    802 			return PASS;
    803 		}
    804 	}
    805 
    806 	TDM_PRINT3("tdm_th2_place_lr_port() ___WARNING Failing to place PhyPort=%d at Ideal_Pos=%d with Jitter=%d; Try shifting slices\n",phy_port, ideal_pos, port_jitter);
    807 
    808 /* If not placed in [ideal_pos-port_jitter ideal_pos+port_jitter] range the shift a slice of ports and place it within that range*/
    809 /* First search for the smallest slice at left or right of the ideal_pos*/
    810 			
    811 	for (i=port_jitter; i<tdm_cal_length; i++) {
    812 		avail_pos_left = (tdm_cal_length+ideal_pos-i) % tdm_cal_length;
    813 		if (tdm_pipe_main[avail_pos_left] == avail_token) {
    814 			break;
    815 		}
    816 	}
    817 	for (i=port_jitter; i<tdm_cal_length; i++) {
    818 		avail_pos_right = (ideal_pos+i) % tdm_cal_length;
    819 		if (tdm_pipe_main[avail_pos_right] == avail_token) {
    820 			break;
    821 		}
    822 	}
    823 	
    824 	shift_jitter=port_jitter-1;
    825 	shift_jitter = (shift_jitter==0) ? 1: shift_jitter;
    826 
    827 	left_slice_length  = (tdm_cal_length + ideal_pos - avail_pos_left) % tdm_cal_length;
    828 	right_slice_length = (tdm_cal_length + avail_pos_right - ideal_pos) % tdm_cal_length;
    829 
    830 	/* Try left and righ shift (its more of a swap) */
    831 	is_sist_fail_left = 0; is_sist_fail_right = 0;
    832 	result_left  = tdm_th2_shift_left(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, ideal_pos, shift_jitter, left_slice_length, avail_token, TH2_LR_JITTER_PCT, 1, &is_sist_fail_left); /* 1 means try */
    833 	result_right = tdm_th2_shift_right(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, ideal_pos, shift_jitter, right_slice_length, avail_token, TH2_LR_JITTER_PCT, 1, &is_sist_fail_right);
    834 	
    835 	/* Take decision to shift and how to shift */
    836 	execute_left=0;
    837 	execute_right=0;
    838 	if ( left_slice_length <= right_slice_length ) {
    839 		if (result_left == PASS) {
    840 			execute_left = 1;
    841 		} else if (result_right == PASS) {
    842 			execute_right = 1;
    843 		} else {
    844 			if (is_sist_fail_left == 0) {
    845 				execute_left = 1;
    846 			} else if (is_sist_fail_right == 0) {
    847 				execute_right = 1;
    848 			}
    849 		}
    850 	} else {
    851 		if (result_right == PASS) {
    852 			execute_right = 1;
    853 		} else if (result_left == PASS) {
    854 			execute_left = 1;
    855 		} else {
    856 			if (is_sist_fail_right == 0) {
    857 				execute_right = 1;
    858 			} else if (is_sist_fail_left == 0) {
    859 				execute_left = 1;
    860 			}
    861 		}
    862 	}
    863 
    864 	if (execute_left == 1) {
    865 		tdm_th2_shift_left(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, ideal_pos, shift_jitter, left_slice_length, avail_token, TH2_LR_JITTER_PCT, 0, &is_sist_fail_left);
    866 	} else if (execute_right == 1){
    867 		tdm_th2_shift_right(_tdm, tdm_pipe_main, tdm_cal_length, phy_port, ideal_pos, shift_jitter, right_slice_length, avail_token, TH2_LR_JITTER_PCT, 0, &is_sist_fail_right);
    868 	}
    869 	
    870 
    871 	if ((execute_left == 1) || (execute_right == 1)) {
    872 		result = PASS;
    873 	} else {
    874 		TDM_ERROR3("tdm_th2_place_lr_port() Unable to shift RIGHT/LEFT properly port=%d at ideal_pos=%d within jitter=%d\n", phy_port, ideal_pos, shift_jitter);
    875 		result = FAIL;
    876 	}
    877 
    878 	return result;
    879 }
    880 
    881 
    882 
    883 
    884 /**
    885 @name: tdm_th2_shift_left
    886 @param:
    887  */
    888 int
    889 tdm_th2_shift_left(tdm_mod_t *_tdm, int *tdm_pipe_main, int tdm_cal_length, int phy_port, int ideal_pos, int shift_jitter, int left_slice_length, int avail_token, int lr_jitter_pct, int try, int *is_sist_fail)
    890 {
    891 	int i, pos1, pos2, pos;
    892 	int *tdm_pipe_main_tmp;
    893 	int result;
    894 	int tsc_for_phy_port, tsc_pos;
    895 	
    896 	if (try==1) { /* create a copy of the tdm_pipe_main */
    897 		tdm_pipe_main_tmp=(int *) TDM_ALLOC(tdm_cal_length*sizeof(int), "temp main calendar");
    898 		for (i=0; i<tdm_cal_length; i++) {
    899 			tdm_pipe_main_tmp[i] = tdm_pipe_main[i];
    900 		}
    901 	} else { /* make actual change on tdm_pipe_main */
    902 		tdm_pipe_main_tmp = tdm_pipe_main;
    903 	}
    904 	
    905 	*is_sist_fail = 0;
    906 	result=PASS;
    907 	
    908 	pos1 = (tdm_cal_length+ideal_pos-left_slice_length) % tdm_cal_length;
    909 	pos2 = (tdm_cal_length+ideal_pos-left_slice_length+1) % tdm_cal_length;
    910 	TDM_PRINT2("tdm_th2_shift_left() ___WARNING Shifting LEFT initial pos_1=%d with pos_2=%d\n", pos1, pos2);
    911 	for (i=left_slice_length; i > shift_jitter ; i--) {
    912 		if (tdm_th2_check_swap(_tdm, tdm_pipe_main_tmp, tdm_cal_length, pos1, pos2, avail_token, lr_jitter_pct)==PASS) {
    913 			int tmp;
    914 			tmp = tdm_pipe_main_tmp[pos1];
    915 			tdm_pipe_main_tmp[pos1] = tdm_pipe_main_tmp[pos2];
    916 			tdm_pipe_main_tmp[pos2] = tmp;
    917 			TDM_PRINT2("tdm_th2_shift_left() ___WARNING Shifting LEFT swap pos_1=%d with pos_2=%d\n", pos1, pos2);
    918 			pos1=pos2; /*pos1 = (pos1+1) % tdm_cal_length;*/
    919 			pos2 = (pos2+1) % tdm_cal_length;
    920 			result = PASS;
    921 		} else { /* don't swap; just advance to another token */
    922 			pos2 = (pos2+1) % tdm_cal_length;
    923 			result = FAIL;
    924 		}
    925 	}
    926 	
    927 	if (result==FAIL) {
    928 		TDM_PRINT4("tdm_th2_shift_left() ___WARNING Unable to swap LEFT and place properly port=%d at ideal_pos=%d pos1=%d pos2=%d\n", phy_port, ideal_pos, pos1, pos2);
    929 		tdm_pipe_main_tmp[pos1] = phy_port; /* place it on unallocated position*/
    930 		pos = pos1;
    931 	} else {
    932 		pos = (tdm_cal_length+ideal_pos-shift_jitter) % tdm_cal_length;
    933 		tdm_pipe_main_tmp[pos] = phy_port;
    934 		TDM_PRINT5("tdm_th2_shift_left() ___WARNING Shifting LEFT slice (left_slice_length=%d) pos [%d - %d] and placing PhyPort=%d at pos=%d\n",
    935 			left_slice_length, (tdm_cal_length+ideal_pos-left_slice_length+1)%tdm_cal_length, pos2, phy_port, (tdm_cal_length+ideal_pos-shift_jitter)%tdm_cal_length );
    936 	}
    937 	
    938 	
    939 	if (try==1) {
    940 		/* Sister spacing violation for the port to be placed */
    941 		_tdm->_core_data.vars_pkg.port = phy_port;
    942 		tsc_for_phy_port = tdm_find_pm(_tdm);
    943 		for (i=-3; i< 4; i++) {
    944 			if (i == 0) continue;
    945 			_tdm->_core_data.vars_pkg.port = tdm_pipe_main_tmp[(tdm_cal_length+pos+i) % tdm_cal_length];
    946 			tsc_pos = tdm_find_pm(_tdm);
    947 			if ((tsc_for_phy_port == tsc_pos)) {
    948 				TDM_PRINT2("tdm_th2_shift_left() ___WARNING LEFT NEW - Port=%d is violating sister spacing if moved in pos=%d\n", phy_port, pos);
    949 				result = FAIL;
    950 				*is_sist_fail = 1;
    951 			}
    952 		}
    953 		/* if just try then deallocate the copy of the tdm_pipe_main */
    954 		TDM_FREE(tdm_pipe_main_tmp);
    955 	}
    956 	
    957 	return result;
    958 }
    959 
    960 
    961 
    962 /**
    963 @name: tdm_th2_shift_right
    964 @param:
    965  */
    966 int
    967 tdm_th2_shift_right(tdm_mod_t *_tdm, int *tdm_pipe_main, int tdm_cal_length, int phy_port, int ideal_pos, int shift_jitter, int right_slice_length, int avail_token, int lr_jitter_pct, int try, int *is_sist_fail)
    968 {
    969 	int i, pos1, pos2, pos;
    970 	int *tdm_pipe_main_tmp;
    971 	int result;
    972 	int tsc_for_phy_port, tsc_pos;
    973 	
    974 	if (try==1) { /* create a copy of the tdm_pipe_main */
    975 		tdm_pipe_main_tmp=(int *) TDM_ALLOC(tdm_cal_length*sizeof(int), "temp main calendar");
    976 		for (i=0; i<tdm_cal_length; i++) {
    977 			tdm_pipe_main_tmp[i] = tdm_pipe_main[i];
    978 		}
    979 	} else { /* make actual change on tdm_pipe_main */
    980 		tdm_pipe_main_tmp = tdm_pipe_main;
    981 	}
    982 	
    983 	*is_sist_fail = 0;
    984 	result=PASS;
    985 	
    986 	pos2 = (ideal_pos+right_slice_length) % tdm_cal_length;
    987 	pos1 = (ideal_pos+right_slice_length-1) % tdm_cal_length;
    988 	for (i=right_slice_length; i > shift_jitter ; i--) {
    989 		if (tdm_th2_check_swap(_tdm, tdm_pipe_main_tmp, tdm_cal_length, pos1, pos2, avail_token, lr_jitter_pct)==PASS) {
    990 			int tmp;
    991 			tmp = tdm_pipe_main_tmp[pos1];
    992 			tdm_pipe_main_tmp[pos1] = tdm_pipe_main_tmp[pos2];
    993 			tdm_pipe_main_tmp[pos2] = tmp;
    994 			TDM_PRINT2("tdm_th2_shift_right() ___WARNING Shifting RIGHT swap pos_1=%d with pos_2=%d\n", pos1, pos2);
    995 			pos2=pos1; /*pos2 = (tdm_cal_length+pos2-1) % tdm_cal_length;*/
    996 			pos1 = (tdm_cal_length+pos1-1) % tdm_cal_length;				
    997 			result = PASS;
    998 		} else { /* don't swap; just advance to another token */
    999 			pos1 = (tdm_cal_length+pos1-1) % tdm_cal_length;
   1000 			result = FAIL;
   1001 		}
   1002 	}
   1003 	if (result==FAIL) {
   1004 		TDM_PRINT4("tdm_th2_shift_right() ___WARNING Unable to swap RIGHT and place properly port=%d at ideal_pos=%d pos1=%d pos2=%d\n", phy_port, ideal_pos, pos1, pos2);
   1005 		tdm_pipe_main_tmp[pos2] = phy_port; /* place it on unallocated position*/
   1006 		pos = pos2;
   1007 	} else {
   1008 		pos = (ideal_pos+shift_jitter) % tdm_cal_length;
   1009 		tdm_pipe_main_tmp[pos] = phy_port;
   1010 		TDM_PRINT5("tdm_th2_shift_right() ___WARNING Shifting RIGHT slice (right_slice_length=%d) pos [%d - %d] and placing PhyPort=%d at pos=%d\n",
   1011 			right_slice_length, pos1, (ideal_pos+right_slice_length-1)%tdm_cal_length, phy_port, (ideal_pos+shift_jitter)%tdm_cal_length );
   1012 	}
   1013 	
   1014 	if (try==1) {
   1015 		/* Sister spacing violation for the port to be placed */
   1016 		_tdm->_core_data.vars_pkg.port = phy_port;
   1017 		tsc_for_phy_port = tdm_find_pm(_tdm);
   1018 		for (i=-3; i< 4; i++) {
   1019 			if (i == 0) continue;
   1020 			_tdm->_core_data.vars_pkg.port = tdm_pipe_main_tmp[(tdm_cal_length+pos+i) % tdm_cal_length];
   1021 			tsc_pos = tdm_find_pm(_tdm);
   1022 			if ((tsc_for_phy_port == tsc_pos)) {
   1023 				TDM_PRINT2("tdm_th2_shift_right() ___WARNING LEFT NEW - Port=%d is violating sister spacing if moved in pos=%d\n", phy_port, pos);
   1024 				result = FAIL;
   1025 				*is_sist_fail = 1;
   1026 			}
   1027 		}
   1028 		/* if just try then deallocate the copy of the tdm_pipe_main */
   1029 		TDM_FREE(tdm_pipe_main_tmp);
   1030 	}
   1031 	
   1032 	return result;
   1033 }
   1034 
   1035 
   1036 
   1037 /**
   1038 @name: tdm_th2_check_swap
   1039 @param:
   1040 
   1041 Checks if swapping pos_1 with pos_2 will violate any min_spacing or jitter
   1042 Assumes that all tokens from pos_1 & pos_2 are placed in the table
   1043 Assumes that pos_2 is at the right of pos_1 in the table;
   1044 Thus, swap assumes that token in pos_1 is moving towards right and token in pos_2 is moving towards left
   1045 
   1046 Before:
   1047  - - - - pos_1 - - pos_2 - - 
   1048 After:
   1049  - - - - pos_2 - - pos_1 - - 
   1050  */
   1051 int
   1052 tdm_th2_check_swap(tdm_mod_t *_tdm, int *tdm_pipe_main, int tbl_len, int pos_1, int pos_2, int avail_token, int lr_jitter_pct)
   1053 {
   1054 	int i, pos, gap;
   1055 	int port_slots_1;
   1056 	int port_slots_2;
   1057 	
   1058 	int min_spacing_1, max_spacing_1, left_space_1, right_space_1;
   1059 	int min_spacing_2, max_spacing_2, left_space_2, right_space_2;
   1060 	
   1061 	int tsc_pos_1, tsc_pos_2, tsc_pos;
   1062 	
   1063 	int result=PASS;
   1064 
   1065 
   1066 	gap = (tbl_len+pos_2-pos_1) % tbl_len;
   1067 	
   1068 	if (tdm_pipe_main[pos_1] != avail_token) {
   1069 		port_slots_1 = 0;
   1070 		for (i=0; i< tbl_len; i++) {
   1071 			if (tdm_pipe_main[pos_1] == tdm_pipe_main[i]) {  port_slots_1++; }
   1072 		}
   1073 
   1074 		tdm_th2_get_min_max_jitter(tbl_len, port_slots_1, lr_jitter_pct, &min_spacing_1, &max_spacing_1);
   1075 
   1076 		right_space_1 = 0;
   1077 		for (i=1; i< tbl_len; i++) {
   1078 			pos = (pos_1+i) % tbl_len;
   1079 			right_space_1++;
   1080 			if(tdm_pipe_main[pos] ==  tdm_pipe_main[pos_1]) {
   1081 				break;
   1082 			}
   1083 		}
   1084 		left_space_1 = 0;
   1085 		for (i=1; i< tbl_len; i++) {
   1086 			pos = (tbl_len+pos_1-i) % tbl_len;
   1087 			left_space_1++;
   1088 			if(tdm_pipe_main[pos] ==  tdm_pipe_main[pos_1]) {
   1089 				break;
   1090 			}
   1091 		}
   1092 
   1093 		/* If, by swapping, the distance to adjacent same tokens is outside jitter range, then return FAIL*/
   1094 		if ( ((left_space_1+gap) < min_spacing_1)  ||  ((left_space_1+gap) > max_spacing_1) || ((left_space_1+gap) < _tdm->_core_data.rule__prox_port_min) ) {
   1095 			TDM_PRINT4("tdm_th2_check_swap() ___WARNING LEFT + Port=%d at pos=%d  is out of jitter range min_spacing=%d max_spacing=%d\n", tdm_pipe_main[pos_1], pos_1, min_spacing_1, max_spacing_1);
   1096 			result = FAIL;
   1097 		}
   1098 		if ( ((right_space_1-gap) < min_spacing_1)  ||  ((right_space_1-gap) > max_spacing_1) || ((right_space_1-gap) < _tdm->_core_data.rule__prox_port_min) ) {
   1099 			TDM_PRINT4("tdm_th2_check_swap() ___WARNING LEFT - Port=%d at pos=%d  is out of jitter range min_spacing=%d max_spacing=%d\n", tdm_pipe_main[pos_1], pos_1, min_spacing_1, max_spacing_1);
   1100 			result = FAIL;
   1101 		}
   1102 		
   1103 		/* Sister port spacing for regular ports only */
   1104 		if (tdm_pipe_main[pos_1] < avail_token) {
   1105 			_tdm->_core_data.vars_pkg.port = tdm_pipe_main[pos_1];
   1106 			tsc_pos_1 = tdm_find_pm(_tdm);
   1107 			for (i=1; i< 4; i++) {
   1108 				_tdm->_core_data.vars_pkg.port = tdm_pipe_main[(pos_2+i)%tbl_len];
   1109 				tsc_pos = tdm_find_pm(_tdm);
   1110 				if ((tsc_pos_1 == tsc_pos)) {
   1111 					TDM_PRINT3("tdm_th2_check_swap() ___WARNING LEFT - Port=%d at pos=%d  is violating sister spacing if moved in pos=%d\n", tdm_pipe_main[pos_1], pos_1, pos_2);
   1112 					result = FAIL;
   1113 				}
   1114 			}
   1115 			
   1116 		}
   1117 	}
   1118 	
   1119 	if (tdm_pipe_main[pos_2] != avail_token) {
   1120 		port_slots_2 = 0;
   1121 		for (i=0; i< tbl_len; i++) {
   1122 			if (tdm_pipe_main[pos_2] == tdm_pipe_main[i]) {  port_slots_2++; }
   1123 		}
   1124 
   1125 		tdm_th2_get_min_max_jitter(tbl_len, port_slots_2, lr_jitter_pct, &min_spacing_2, &max_spacing_2);
   1126 		right_space_2 = 0;
   1127 		for (i=1; i< tbl_len; i++) {
   1128 			pos = (pos_2+i) % tbl_len;
   1129 			right_space_2++;
   1130 			if(tdm_pipe_main[pos] ==  tdm_pipe_main[pos_2]) {
   1131 				break;
   1132 			}
   1133 		}
   1134 		left_space_2 = 0;
   1135 		for (i=1; i< tbl_len; i++) {
   1136 			pos = (tbl_len+pos_2-i) % tbl_len;
   1137 			left_space_2++;
   1138 			if(tdm_pipe_main[pos] ==  tdm_pipe_main[pos_2]) {
   1139 				break;
   1140 			}
   1141 		}
   1142 		if ( ((left_space_2-gap) < min_spacing_2)  ||  ((left_space_2-gap) > max_spacing_2) || ((left_space_2-gap) < _tdm->_core_data.rule__prox_port_min) ) {
   1143 			TDM_PRINT4("tdm_th2_check_swap() ___WARNING RIGHT - Port=%d at pos=%d  is out of jitter range min_spacing=%d max_spacing=%d\n", tdm_pipe_main[pos_2], pos_2, min_spacing_2, max_spacing_2);
   1144 			result = FAIL;
   1145 		}
   1146 		if ( ((right_space_2+gap) < min_spacing_2)  ||  ((right_space_2+gap) > max_spacing_2)  ||  ((right_space_2+gap) < _tdm->_core_data.rule__prox_port_min) ) {
   1147 			TDM_PRINT4("tdm_th2_check_swap() ___WARNING RIGHT + Port=%d at pos=%d  is out of jitter range min_spacing=%d max_spacing=%d\n", tdm_pipe_main[pos_2], pos_2, min_spacing_2, max_spacing_2);
   1148 			result = FAIL;
   1149 		}
   1150 
   1151 		/* Sister port spacing for regular ports only */
   1152 		if (tdm_pipe_main[pos_2] < avail_token) {
   1153 			_tdm->_core_data.vars_pkg.port = tdm_pipe_main[pos_2];
   1154 			tsc_pos_2 = tdm_find_pm(_tdm);
   1155 			for (i=1; i< 4; i++) {
   1156 				_tdm->_core_data.vars_pkg.port = tdm_pipe_main[(tbl_len+pos_1-i)%tbl_len];
   1157 				tsc_pos = tdm_find_pm(_tdm);
   1158 				if ((tsc_pos_2 == tsc_pos)) {
   1159 					TDM_PRINT3("tdm_th2_check_swap() ___WARNING RIGHT - Port=%d at pos=%d  is violating sister spacing if moved in pos=%d\n", tdm_pipe_main[pos_2], pos_2, pos_1);
   1160 					result = FAIL;
   1161 				}
   1162 			}
   1163 			
   1164 		}
   1165 
   1166 	}
   1167 	
   1168 	return result;
   1169 }
   1170 
   1171 
   1172 
   1173 
   1174 /**
   1175 @name: tdm_th2_acc_alloc
   1176 @param:
   1177  */
   1178 int
   1179 tdm_th2_acc_alloc( tdm_mod_t *_tdm )
   1180 {
   1181 	int s, j, existing_avail_tokens;
   1182 	int tdm_cal_length, req_slots, first_slot_pos, ideal_pos;
   1183 	int *tdm_pipe_main;
   1184 	int round_aux_tokens;
   1185 	int port_jitter;
   1186 	
   1187 	tdm_cal_length = _tdm->_chip_data.soc_pkg.lr_idx_limit + _tdm->_chip_data.soc_pkg.tvec_size;
   1188 	round_aux_tokens = _tdm->_chip_data.soc_pkg.tvec_size+2; /* in TH2 is 12*/
   1189 	
   1190 	TDM_SEL_CAL(_tdm->_core_data.vars_pkg.cal_id,tdm_pipe_main);
   1191 	
   1192 	existing_avail_tokens=0;
   1193 	for (j=0; j<tdm_cal_length; j++) {
   1194 		if (tdm_pipe_main[j] == _tdm->_chip_data.soc_pkg.num_ext_ports) {
   1195 			existing_avail_tokens++;
   1196 		}
   1197 	}
   1198 	
   1199 	if (existing_avail_tokens < _tdm->_chip_data.soc_pkg.tvec_size) {
   1200 		TDM_ERROR2("tdm_th2_acc_alloc() Not enough available tokens for AUX ports Required=%d Actual%d\n",_tdm->_chip_data.soc_pkg.tvec_size, existing_avail_tokens);
   1201 		return FAIL;
   1202 	}
   1203 	
   1204 	/* Place TOKEN (TH2_ANCL_TOKEN) for CMIC/MGM; the actual token will be placed in parse function */
   1205 	req_slots = TH2_CPU_SLOTS; /* in TH2 is same as TH2_MGM_SLOTS */
   1206 	if (existing_avail_tokens < round_aux_tokens) {
   1207 		first_slot_pos = tdm_th2_find_first_avail_slot(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports);
   1208 	} else {
   1209 		first_slot_pos = tdm_th2_find_first_avail_slot_w_start(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports, 0 );
   1210 	}
   1211 	for (s=0; s<req_slots; s++) {
   1212 		/*ideal_pos = (first_slot_pos + (( (s*tdm_cal_length) + req_slots-1) / req_slots)) % tdm_cal_length;*/ /* that is  round((s*tdm_cal_length)/req_slots) */
   1213 		ideal_pos = (first_slot_pos + tdm_th2_div_round(s*tdm_cal_length, req_slots)) % tdm_cal_length; /* that is  round((s*tdm_cal_length)/req_slots) */
   1214 		port_jitter = tdm_th2_div_round( (TH2_LR_JITTER_PCT*tdm_cal_length), (req_slots*100*2));
   1215 		if (tdm_th2_place_lr_port(_tdm, tdm_pipe_main, TH2_ANCL_TOKEN, ideal_pos, port_jitter, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports))
   1216 			TDM_PRINT2("tdm_th2_acc_alloc() Placing CMIC/MGM token at Ideal_Pos=%d with Jitter=%d\n", ideal_pos, tdm_cal_length-1);		
   1217 	}
   1218 	
   1219 	
   1220 	/* Place TOKEN (TH2_ANCL_TOKEN+1) for LBK; the actual token will be placed in parse function */
   1221 	req_slots = TH2_LBK_SLOTS;
   1222 	if (existing_avail_tokens < round_aux_tokens) {
   1223 		first_slot_pos = tdm_th2_find_first_avail_slot(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports);
   1224 	} else {
   1225 		first_slot_pos = tdm_th2_find_first_avail_slot_w_start(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports, (tdm_cal_length/round_aux_tokens) );
   1226 	}	
   1227 	for (s=0; s<req_slots; s++) {
   1228 		/*ideal_pos = (first_slot_pos + (( (s*tdm_cal_length) + req_slots-1) / req_slots)) % tdm_cal_length;*/ /* that is  round((s*tdm_cal_length)/req_slots) */
   1229 		ideal_pos = (first_slot_pos + tdm_th2_div_round(s*tdm_cal_length, req_slots)) % tdm_cal_length; /* that is  round((s*tdm_cal_length)/req_slots) */
   1230 		if (tdm_th2_place_lr_port(_tdm, tdm_pipe_main, TH2_ANCL_TOKEN+1, ideal_pos, tdm_cal_length-1, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports))
   1231 			TDM_PRINT2("tdm_th2_acc_alloc() Placing LBK token at Ideal_Pos=%d with Jitter=%d\n", ideal_pos, tdm_cal_length-1);		
   1232 	}
   1233 	
   1234 	/* Place TOKEN (TH2_ANCL_TOKEN+2) for OPPORTUNISTIC, IDLE, NUL slots;  the actual token will be placed in parse function  */
   1235 	req_slots = TH2_ANC_SLOTS; /* OPPT + IDLE + NULL */
   1236 	if (existing_avail_tokens < round_aux_tokens) {
   1237 		first_slot_pos = tdm_th2_find_first_avail_slot(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports);
   1238 	} else {
   1239 		first_slot_pos = tdm_th2_find_first_avail_slot_w_start(tdm_pipe_main, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports, ((2*tdm_cal_length)/round_aux_tokens) );
   1240 	}
   1241 	for (s=0; s<req_slots; s++) {
   1242 		/*ideal_pos = (first_slot_pos + (( (s*tdm_cal_length) + req_slots-1) / req_slots)) % tdm_cal_length;*/ /* that is  round((s*tdm_cal_length)/req_slots) */
   1243 		ideal_pos = (first_slot_pos + tdm_th2_div_round(s*tdm_cal_length, req_slots)) % tdm_cal_length; /* that is  round((s*tdm_cal_length)/req_slots) */
   1244 		if (tdm_th2_place_lr_port(_tdm, tdm_pipe_main, TH2_ANCL_TOKEN+2, ideal_pos, tdm_cal_length-1, tdm_cal_length, _tdm->_chip_data.soc_pkg.num_ext_ports))
   1245 			TDM_PRINT2("tdm_th2_acc_alloc() Placing OPPT/IDLE/NULL token at Ideal_Pos=%d with Jitter=%d\n", ideal_pos, tdm_cal_length-1);		
   1246 	}
   1247 	
   1248 	
   1249 	return PASS;
   1250 }
   1251