tdm_td3_cmn.c (18547B)
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-specific common facility functions 9 */ 10 #ifdef _TDM_STANDALONE 11 #include <tdm_top.h> 12 #else 13 #include <soc/tdm/core/tdm_top.h> 14 #endif 15 16 17 /** 18 @name: tdm_td3_cmn_chk_port_is_fp 19 @param: 20 @desc: Return BOOL_TRUE if given port is a front panel port, 21 otherwise return BOOL_FALSE. 22 */ 23 int 24 tdm_td3_cmn_chk_port_is_fp(tdm_mod_t *_tdm, int port_token) 25 { 26 /* return (tdm_cmn_chk_port_is_fp(_tdm, port_token)); */ 27 return ((port_token >= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 28 port_token <= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) ? 29 BOOL_TRUE : BOOL_FALSE); 30 } 31 32 33 /** 34 @name: tdm_td3_cmn_chk_port_is_lr 35 @param: 36 @desc: Return BOOL_TRUE if given port is a linerate port, 37 otherwise return BOOL_FALSE. 38 */ 39 int 40 tdm_td3_cmn_chk_port_is_lr(tdm_mod_t *_tdm, int port_token) 41 { 42 /* return (tdm_cmn_chk_port_is_lr(_tdm, port_token)); */ 43 int port_state; 44 port_state = tdm_td3_cmn_get_port_state(_tdm, port_token); 45 return ((port_state == PORT_STATE__LINERATE || 46 port_state == PORT_STATE__LINERATE_HG) ? 47 BOOL_TRUE : BOOL_FALSE); 48 } 49 50 51 /** 52 @name: tdm_td3_cmn_chk_port_is_os 53 @param: 54 @desc: Return BOOL_TRUE if given port is an oversubscript port, 55 otherwise return BOOL_FALSE. 56 */ 57 int 58 tdm_td3_cmn_chk_port_is_os(tdm_mod_t *_tdm, int port_token) 59 { 60 /* return (tdm_cmn_chk_port_is_os(_tdm, port_token)); */ 61 int port_state; 62 port_state = tdm_td3_cmn_get_port_state(_tdm, port_token); 63 return ((port_state == PORT_STATE__OVERSUB || 64 port_state == PORT_STATE__OVERSUB_HG) ? 65 BOOL_TRUE : BOOL_FALSE); 66 } 67 68 69 /** 70 @name: tdm_td3_cmn_chk_port_is_mgmt 71 @param: 72 @desc: Return BOOL_TRUE if given port is a management port, 73 otherwise return BOOL_FALSE. 74 */ 75 int 76 tdm_td3_cmn_chk_port_is_mgmt(tdm_mod_t *_tdm, int port_token) 77 { 78 /* return (tdm_cmn_chk_port_is_os(_tdm, port_token)); */ 79 int port_state; 80 port_state = tdm_td3_cmn_get_port_state(_tdm, port_token); 81 return ((port_state == PORT_STATE__MANAGEMENT) ? 82 BOOL_TRUE : BOOL_FALSE); 83 } 84 85 86 /** 87 @name: tdm_td3_cmn_chk_port_is_hg 88 @param: 89 @desc: Return BOOL_TRUE if given port is a higig/higig2 port, 90 otherwise return BOOL_FALSE. 91 */ 92 int 93 tdm_td3_cmn_chk_port_is_hg(tdm_mod_t *_tdm, int port_token) 94 { 95 /* return (tdm_cmn_chk_port_is_hg(_tdm, port_token)); */ 96 int port_state; 97 port_state = tdm_td3_cmn_get_port_state(_tdm, port_token); 98 return ((port_state == PORT_STATE__LINERATE_HG || 99 port_state == PORT_STATE__OVERSUB_HG) ? 100 BOOL_TRUE : BOOL_FALSE); 101 } 102 103 104 /** 105 @name: tdm_td3_cmn_get_port_pm 106 @param: 107 108 Return Port Macro number of the given port 109 */ 110 int 111 tdm_td3_cmn_get_port_pm(tdm_mod_t *_tdm, int port_token) 112 { 113 int port_pm; 114 115 if (_tdm->_chip_data.soc_pkg.pmap_num_lanes > 0 && 116 port_token >=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 117 port_token <=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) { 118 port_pm = (port_token - 1) / _tdm->_chip_data.soc_pkg.pmap_num_lanes; 119 } else { 120 port_pm = _tdm->_chip_data.soc_pkg.pm_num_phy_modules; 121 } 122 123 return (port_pm % TD3_NUM_PM_MOD); 124 } 125 126 127 /** 128 @name: tdm_td3_cmn_get_port_speed 129 @param: 130 131 Return port speed of the given port 132 */ 133 int 134 tdm_td3_cmn_get_port_speed(tdm_mod_t *_tdm, int port_token) 135 { 136 /* return (tdm_cmn_get_port_speed(_tdm, port_token)); */ 137 if (tdm_td3_cmn_chk_port_is_fp(_tdm, port_token) == BOOL_TRUE) { 138 return (_tdm->_chip_data.soc_pkg.speed[port_token]); 139 } else { 140 return 0; 141 } 142 } 143 144 145 /** 146 @name: tdm_td3_cmn_get_port_speed_eth 147 @param: 148 149 Return port speed in ethernet mode. This converts HiGig speed to ethernet. 150 */ 151 int 152 tdm_td3_cmn_get_port_speed_eth(tdm_mod_t *_tdm, int port_token) 153 { 154 /* return (tdm_cmn_get_port_speed_eth(_tdm, port_token)); */ 155 int port_speed, port_speed_eth; 156 157 port_speed = tdm_td3_cmn_get_port_speed(_tdm, port_token); 158 switch(port_speed) { 159 case SPEED_1G: 160 case SPEED_1p25G: 161 case SPEED_2p5G: 162 case SPEED_5G: 163 port_speed_eth = port_speed; 164 break; 165 case SPEED_10G: 166 case SPEED_10G_DUAL: 167 case SPEED_10G_XAUI: 168 case SPEED_11G: 169 port_speed_eth = SPEED_10G; 170 break; 171 case SPEED_12p5G: 172 port_speed_eth = SPEED_12p5G; 173 break; 174 case SPEED_20G: 175 case SPEED_21G: 176 case SPEED_21G_DUAL: 177 port_speed_eth = SPEED_20G; 178 break; 179 case SPEED_25G: 180 case SPEED_27G: 181 port_speed_eth = SPEED_25G; 182 break; 183 case SPEED_40G: 184 case SPEED_42G: 185 case SPEED_42G_HG2: 186 port_speed_eth = SPEED_40G; 187 break; 188 case SPEED_50G: 189 case SPEED_53G: 190 port_speed_eth = SPEED_50G; 191 break; 192 case SPEED_100G: 193 case SPEED_106G: 194 port_speed_eth = SPEED_100G; 195 break; 196 case SPEED_120G: 197 case SPEED_127G: 198 port_speed_eth = SPEED_120G; 199 break; 200 case SPEED_200G: 201 port_speed_eth = SPEED_200G; 202 break; 203 case SPEED_400G: 204 port_speed_eth = SPEED_400G; 205 break; 206 default: 207 port_speed_eth = 0; 208 break; 209 } 210 211 return port_speed_eth; 212 } 213 214 215 /** 216 @name: tdm_td3_cmn_get_port_state 217 @param: 218 219 Return port state of the given port 220 */ 221 int 222 tdm_td3_cmn_get_port_state(tdm_mod_t *_tdm, int port_token) 223 { 224 if (port_token >= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 225 port_token <= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) { 226 return (_tdm->_chip_data.soc_pkg.state[port_token-1]); 227 } 228 229 return (PORT_STATE__DISABLED); 230 } 231 232 233 /** 234 @name: tdm_td3_cmn_get_speed_lanes 235 @param: 236 237 Return the number of lanes required by the given speed 238 (Chip-Specific) 239 */ 240 int 241 tdm_td3_cmn_get_speed_lanes(int port_speed) 242 { 243 int lanes = 0; 244 245 switch(port_speed){ 246 case SPEED_1G: case SPEED_2p5G: 247 case SPEED_10G: case SPEED_11G: 248 case SPEED_20G: case SPEED_21G: 249 case SPEED_25G: case SPEED_27G: 250 lanes = 1; 251 break; 252 case SPEED_40G: case SPEED_42G: case SPEED_42G_HG2: 253 case SPEED_50G: case SPEED_53G: 254 lanes = 2; 255 break; 256 case SPEED_100G: case SPEED_106G: 257 lanes = 4; 258 break; 259 default: 260 break; 261 } 262 263 return (lanes); 264 } 265 266 267 /** 268 @name: tdm_td3_cmn_get_speed_slots 269 @param: 270 271 Return the number of slots (2.5G per slot) of the given speed 272 (Chip-Specific) 273 */ 274 int 275 tdm_td3_cmn_get_speed_slots(int port_speed) 276 { 277 int slot_num=0; 278 279 switch (port_speed) { 280 case SPEED_1G: case SPEED_2p5G: 281 slot_num = 1; 282 break; 283 case SPEED_10G: case SPEED_11G: 284 slot_num = 4; 285 break; 286 case SPEED_20G: case SPEED_21G: 287 slot_num = 8; 288 break; 289 case SPEED_25G: case SPEED_27G: 290 slot_num = 10; 291 break; 292 case SPEED_40G: case SPEED_42G: case SPEED_42G_HG2: 293 slot_num = 16; 294 break; 295 case SPEED_50G: case SPEED_53G: 296 slot_num = 20; 297 break; 298 case SPEED_100G: case SPEED_106G: 299 slot_num = 40; 300 break; 301 default: 302 TDM_ERROR4("%s, %s -- %dM (%dG)\n", 303 "[Port Speed]", 304 "invalid port speed", 305 port_speed, port_speed/1000); 306 break; 307 } 308 309 return (slot_num); 310 } 311 312 313 /** 314 @name: tdm_td3_cmn_get_port_slots 315 @param: 316 */ 317 int 318 tdm_td3_cmn_get_port_slots(tdm_mod_t *_tdm, int port_token) 319 { 320 /* return (tdm_cmn_get_port_slots(_tdm, port_token)); */ 321 int port_slots, port_speed; 322 323 port_speed = tdm_td3_cmn_get_port_speed_eth(_tdm, port_token); 324 port_slots = tdm_td3_cmn_get_speed_slots(port_speed); 325 326 return port_slots; 327 } 328 329 330 /** 331 @name: tdm_td3_cmn_get_pipe_port_range 332 @param: 333 334 Return physical port number range of the given pipe 335 */ 336 void 337 tdm_td3_cmn_get_pipe_port_range(int cal_id, int *phy_lo, int *phy_hi) 338 { 339 int prt_lo = 0, prt_hi = 0; 340 341 switch(cal_id){ 342 case 0: prt_lo = TD3_CAL_0_PORT_LO; prt_hi = TD3_CAL_0_PORT_HI; break; 343 case 1: prt_lo = TD3_CAL_1_PORT_LO; prt_hi = TD3_CAL_1_PORT_HI; break; 344 case 2: prt_lo = TD3_CAL_2_PORT_LO; prt_hi = TD3_CAL_2_PORT_HI; break; 345 case 3: prt_lo = TD3_CAL_3_PORT_LO; prt_hi = TD3_CAL_3_PORT_HI; break; 346 case 4: prt_lo = TD3_CAL_4_PORT_LO; prt_hi = TD3_CAL_4_PORT_HI; break; 347 case 5: prt_lo = TD3_CAL_5_PORT_LO; prt_hi = TD3_CAL_5_PORT_HI; break; 348 case 6: prt_lo = TD3_CAL_6_PORT_LO; prt_hi = TD3_CAL_6_PORT_HI; break; 349 case 7: prt_lo = TD3_CAL_7_PORT_LO; prt_hi = TD3_CAL_7_PORT_HI; break; 350 default: break; 351 } 352 if (phy_lo != NULL && phy_hi != NULL) { 353 *phy_lo = prt_lo; 354 *phy_hi = prt_hi; 355 } 356 } 357 358 359 /** 360 @name: tdm_td3_cmn_get_pipe_port_lo_hi 361 @param: 362 363 Return physical port number range of the current pipe 364 */ 365 void 366 tdm_td3_cmn_get_pipe_port_lo_hi(tdm_mod_t *_tdm, int *phy_lo, int *phy_hi) 367 { 368 tdm_td3_cmn_get_pipe_port_range(_tdm->_core_data.vars_pkg.cal_id, 369 phy_lo, phy_hi); 370 } 371 372 373 /** 374 @name: tdm_td3_cmn_get_pipe_pm_lo_hi 375 @param: 376 377 Return physical port number range of the given pipe 378 */ 379 void 380 tdm_td3_cmn_get_pipe_pm_lo_hi(tdm_mod_t *_tdm, int *pm_lo, int *pm_hi) 381 { 382 int prt_lo = 0, prt_hi = 0; 383 384 if (pm_lo != NULL && pm_hi != NULL) { 385 tdm_td3_cmn_get_pipe_port_lo_hi(_tdm, &prt_lo, &prt_hi); 386 *pm_lo = tdm_td3_cmn_get_port_pm(_tdm, prt_lo); 387 *pm_hi = tdm_td3_cmn_get_port_pm(_tdm, prt_hi); 388 } 389 } 390 391 392 /** 393 @name: tdm_td3_cmn_get_pipe_ethernet 394 @param: 395 396 Return BOOL_TRUE if the given pipe has traffic entirely Ethernet; 397 otherwise, return BOOL_FALSE. 398 */ 399 int 400 tdm_td3_cmn_get_pipe_ethernet(tdm_mod_t *_tdm, int cal_id) 401 { 402 int port, phy_lo, phy_hi; 403 404 tdm_td3_cmn_get_pipe_port_range(cal_id, &phy_lo, &phy_hi); 405 for (port = phy_lo; port <= phy_hi; port++) { 406 if (BOOL_TRUE == tdm_td3_cmn_chk_port_is_hg(_tdm, port)) 407 return BOOL_FALSE; 408 } 409 410 return BOOL_TRUE; 411 } 412 413 414 /** 415 @name: tdm_td3_cmn_get_pipe_higig 416 @param: 417 418 Return BOOL_TRUE if the given pipe has HiGig traffic; 419 otherwise, return BOOL_FALSE. 420 (Chip-Specific) 421 */ 422 int 423 tdm_td3_cmn_get_pipe_higig(tdm_mod_t *_tdm, int cal_id) 424 { 425 int result = BOOL_FALSE; 426 427 /* check regular ports */ 428 if (tdm_td3_cmn_get_pipe_ethernet(_tdm, cal_id) == BOOL_FALSE) { 429 result = BOOL_TRUE; 430 } 431 /* check management ports */ 432 if (cal_id == TD3_IDB_PIPE_1_CAL_ID && 433 _tdm->_chip_data.soc_pkg.soc_vars.td3.mgmt_pm_hg == BOOL_TRUE) { 434 result = BOOL_TRUE; 435 } 436 437 return (result); 438 } 439 440 441 /** 442 @name: tdm_td3_cmn_get_pipe_cal_len_max 443 @param: 444 445 Return the size of selected calendar (regardless of frequency/higig) 446 */ 447 int 448 tdm_td3_cmn_get_pipe_cal_len_max(tdm_mod_t *_tdm, int cal_id) 449 { 450 int cal_len = 0; 451 452 switch (cal_id) { 453 case 0: cal_len = _tdm->_chip_data.cal_0.cal_len; break; 454 case 1: cal_len = _tdm->_chip_data.cal_1.cal_len; break; 455 case 2: cal_len = _tdm->_chip_data.cal_2.cal_len; break; 456 case 3: cal_len = _tdm->_chip_data.cal_3.cal_len; break; 457 case 4: cal_len = _tdm->_chip_data.cal_4.cal_len; break; 458 case 5: cal_len = _tdm->_chip_data.cal_5.cal_len; break; 459 case 6: cal_len = _tdm->_chip_data.cal_6.cal_len; break; 460 case 7: cal_len = _tdm->_chip_data.cal_7.cal_len; break; 461 default: break; 462 } 463 464 return (cal_len); 465 } 466 467 468 /** 469 @name: tdm_td3_cmn_get_pipe_cal_len 470 @param: 471 472 Return valid length of selected calendar under frequency/higig constraint 473 (Chip-Specific) 474 */ 475 int 476 tdm_td3_cmn_get_pipe_cal_len(tdm_mod_t *_tdm, int cal_id) 477 { 478 int cal_len = 0; 479 int param_freq; 480 481 param_freq = _tdm->_chip_data.soc_pkg.clk_freq; 482 483 /* get calendar length */ 484 if (tdm_td3_cmn_get_pipe_higig(_tdm, cal_id) == BOOL_FALSE) { 485 switch (param_freq) { 486 case TD3_CLK_1700MHZ: cal_len = TD3_LEN_1700MHZ_EN; break; 487 case TD3_CLK_1625MHZ: cal_len = TD3_LEN_1625MHZ_EN; break; 488 case TD3_CLK_1525MHZ: cal_len = TD3_LEN_1525MHZ_EN; break; 489 case TD3_CLK_1425MHZ: cal_len = TD3_LEN_1425MHZ_EN; break; 490 case TD3_CLK_1325MHZ: cal_len = TD3_LEN_1325MHZ_EN; break; 491 case TD3_CLK_1275MHZ: cal_len = TD3_LEN_1275MHZ_EN; break; 492 case TD3_CLK_1125MHZ: cal_len = TD3_LEN_1125MHZ_EN; break; 493 case TD3_CLK_1012MHZ: cal_len = TD3_LEN_1012MHZ_EN; break; 494 case TD3_CLK_850MHZ: cal_len = TD3_LEN_850MHZ_EN; break; 495 default: break; 496 } 497 } else { 498 switch (param_freq) { 499 case TD3_CLK_1700MHZ: cal_len = TD3_LEN_1700MHZ_HG; break; 500 case TD3_CLK_1625MHZ: cal_len = TD3_LEN_1625MHZ_HG; break; 501 case TD3_CLK_1525MHZ: cal_len = TD3_LEN_1525MHZ_HG; break; 502 case TD3_CLK_1425MHZ: cal_len = TD3_LEN_1425MHZ_HG; break; 503 case TD3_CLK_1325MHZ: cal_len = TD3_LEN_1325MHZ_HG; break; 504 case TD3_CLK_1275MHZ: cal_len = TD3_LEN_1275MHZ_HG; break; 505 case TD3_CLK_1125MHZ: cal_len = TD3_LEN_1125MHZ_HG; break; 506 case TD3_CLK_1012MHZ: cal_len = TD3_LEN_1012MHZ_HG; break; 507 case TD3_CLK_850MHZ: cal_len = TD3_LEN_850MHZ_HG; break; 508 default: break; 509 } 510 } 511 /* check validity of calendar length */ 512 if (cal_len == 0) { 513 TDM_ERROR1("Invalid core clock frequency %0d\n", param_freq); 514 } else if (cal_len > tdm_td3_cmn_get_pipe_cal_len_max(_tdm, cal_id)) { 515 cal_len = 0; 516 TDM_ERROR1("Invalid calendar length %0d (overflow)\n", cal_len); 517 } 518 519 return (cal_len); 520 } 521 522 523 /** 524 @name: tdm_td3_cmn_get_pipe_cal 525 @param: 526 527 Return calendar pointer of the current pipe. 528 */ 529 tdm_calendar_t *tdm_td3_cmn_get_pipe_cal(tdm_mod_t *_tdm) 530 { 531 /* return (tdm_cmn_get_pipe_cal(_tdm)); */ 532 tdm_calendar_t * cal = NULL; 533 534 if (_tdm != NULL) { 535 switch (_tdm->_core_data.vars_pkg.cal_id) { 536 case 0: cal=(&(_tdm->_chip_data.cal_0)); break; 537 case 1: cal=(&(_tdm->_chip_data.cal_1)); break; 538 case 2: cal=(&(_tdm->_chip_data.cal_2)); break; 539 case 3: cal=(&(_tdm->_chip_data.cal_3)); break; 540 case 4: cal=(&(_tdm->_chip_data.cal_4)); break; 541 case 5: cal=(&(_tdm->_chip_data.cal_5)); break; 542 case 6: cal=(&(_tdm->_chip_data.cal_6)); break; 543 case 7: cal=(&(_tdm->_chip_data.cal_7)); break; 544 default: 545 TDM_PRINT1("Invalid calendar ID - %0d\n", 546 _tdm->_core_data.vars_pkg.cal_id); 547 cal = NULL; 548 break; 549 } 550 } 551 552 return cal; 553 } 554 555 556 /** 557 @name: tdm_td3_cmn_get_pipe_cal_prev 558 @param: 559 560 Return calendar pointer of the previous pipe. 561 */ 562 tdm_calendar_t *tdm_td3_cmn_get_pipe_cal_prev(tdm_mod_t *_tdm) 563 { 564 /* return (tdm_cmn_get_pipe_cal_prev(_tdm)); */ 565 tdm_calendar_t * cal = NULL; 566 567 if (_tdm != NULL) { 568 switch (_tdm->_core_data.vars_pkg.cal_id) { 569 case 0: cal=(&(_tdm->_prev_chip_data.cal_0)); break; 570 case 1: cal=(&(_tdm->_prev_chip_data.cal_1)); break; 571 case 2: cal=(&(_tdm->_prev_chip_data.cal_2)); break; 572 case 3: cal=(&(_tdm->_prev_chip_data.cal_3)); break; 573 case 4: cal=(&(_tdm->_prev_chip_data.cal_4)); break; 574 case 5: cal=(&(_tdm->_prev_chip_data.cal_5)); break; 575 case 6: cal=(&(_tdm->_prev_chip_data.cal_6)); break; 576 case 7: cal=(&(_tdm->_prev_chip_data.cal_7)); break; 577 default: 578 TDM_PRINT1("Invalid calendar ID - %0d\n", 579 _tdm->_core_data.vars_pkg.cal_id); 580 cal = NULL; 581 break; 582 } 583 } 584 585 return cal; 586 } 587 588 589 /** 590 @name: tdm_td3_cmn_get_same_port_dist 591 @param: 592 */ 593 int 594 tdm_td3_cmn_get_same_port_dist(int slot, int dir, int *cal_main, int cal_len) 595 { 596 int n, k, dist = 0; 597 598 if (slot < cal_len && cal_len > 0) { 599 if (dir == TDM_DIR_UP) { /* UP direction */ 600 for (n = 1; n < cal_len; n++) { 601 k = (slot + cal_len - n) % cal_len; 602 if (cal_main[k] == cal_main[slot]) { 603 dist = n; 604 break; 605 } 606 } 607 } else { /* DOWN direction */ 608 for (n = 1; n < cal_len; n++) { 609 k = (slot + n) % cal_len; 610 if (cal_main[k] == cal_main[slot]) { 611 dist = n; 612 break; 613 } 614 } 615 } 616 } 617 618 return (dist); 619 } 620 621 622 /** 623 @name: tdm_td3_cmn_get_speed_jitter 624 @param: 625 */ 626 void 627 tdm_td3_cmn_get_speed_jitter(int port_speed, int cal_len, int *space_min, int *space_max) 628 { 629 int slot_req, space_frac, jitter_range, jitter_min=0, jitter_max=0; 630 631 if (port_speed<SPEED_10G) { 632 slot_req = (port_speed/100)/25; 633 } else { 634 slot_req = ((port_speed/10000)*100)/25; 635 } 636 if (slot_req>0) { 637 space_frac = ((cal_len*10)/slot_req)%10; 638 jitter_range= (2*cal_len)/(slot_req*5); 639 jitter_range= ((((2*cal_len*10)/(slot_req*5))%10)<5)? 640 (jitter_range): 641 (jitter_range+1); 642 643 if (space_frac<5){ 644 jitter_min = cal_len/slot_req - jitter_range/2; 645 jitter_max = cal_len/slot_req + jitter_range/2; 646 jitter_max = ((jitter_range%2)==0)? 647 (jitter_max): 648 (jitter_max+1); 649 } else { 650 jitter_min = cal_len/slot_req - jitter_range/2; 651 jitter_min = ((cal_len%slot_req)==0)? 652 (jitter_min): 653 (jitter_min+1); 654 jitter_min = ((jitter_range%2)==0)? 655 (jitter_min): 656 (jitter_min-1); 657 jitter_max = cal_len/slot_req + jitter_range/2; 658 jitter_max = ((cal_len%slot_req)==0)? 659 (jitter_max): 660 (jitter_max+1); 661 } 662 jitter_min = (jitter_min<1)? (1): (jitter_min); 663 jitter_max = (jitter_max<1)? (1): (jitter_max); 664 } 665 if (space_min != NULL && space_max != NULL) { 666 *space_min = jitter_min; 667 *space_max = jitter_max; 668 } 669 }