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