1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for Entry point fucntions
29 **********************************************************************/
31 /** @file rg_sch_utl.c
32 @brief This file implements the schedulers main access to MAC layer code.
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_MODULE_ID=4096;
37 static int RLOG_FILE_ID=177;
39 /* header include files -- defines (.h) */
40 #include "common_def.h"
45 #include "rg_sch_err.h"
46 #include "rg_sch_inf.h"
48 #include "rg_sch_cmn.h"
50 #include "rl_interface.h"
51 #include "rl_common.h"
53 /* header/extern include files (.x) */
54 #include "tfu.x" /* TFU types */
55 #include "lrg.x" /* layer management typedefs for MAC */
56 #include "rgr.x" /* layer management typedefs for MAC */
58 #include "rg_sch_inf.x" /* typedefs for Scheduler */
59 #include "rg_sch.x" /* typedefs for Scheduler */
60 #include "rg_sch_cmn.x" /* typedefs for Scheduler */
62 #include "rg_sch_emtc_ext.x"
67 uint32_t rgNumPrachRecvd =0; /* Num of Rach Req received including dedicated preambles */
68 uint32_t rgNumRarSched =0; /* Num of RARs sent */
69 uint32_t rgNumBI =0; /* Num of BackOff Ind sent */
70 uint32_t rgNumMsg3CrcPassed =0; /* Num of CRC success for Msg3 */
71 uint32_t rgNumMsg3CrcFailed =0; /* Num of CRC fail for Msg 3 */
72 uint32_t rgNumMsg3FailMaxRetx =0; /* Num of Msg3 fail after Max Retx attempts */
73 uint32_t rgNumMsg4Ack =0; /* Num of Acks for Msg4 Tx */
74 uint32_t rgNumMsg4Nack =0;
75 /* Num of Nacks for Msg4 Tx */
76 uint32_t rgNumMsg4FailMaxRetx =0; /* Num of Msg4 Tx failed after Max Retx attempts */
77 uint32_t rgNumSrRecvd =0; /* Num of Sched Req received */
78 uint32_t rgNumSrGrant =0; /* Num of Sched Req Grants sent */
79 uint32_t rgNumMsg3CrntiCE =0; /* Num of Msg 3 CRNTI CE received */
80 uint32_t rgNumDedPream =0; /* Num of Dedicated Preambles recvd */
81 uint32_t rgNumMsg3CCCHSdu =0; /* Num of Msg 3 CCCH Sdus recvd */
82 uint32_t rgNumCCCHSduCrntiNotFound =0; /*UE Ctx not found for CCCH SDU Msg 3 */
83 uint32_t rgNumCrntiCeCrntiNotFound =0; /*UE Ctx not found for CRNTI CE Msg 3 */
84 uint32_t rgNumMsg4WithCCCHSdu =0; /* Num of Msg4 with CCCH Sdu */
85 uint32_t rgNumMsg4WoCCCHSdu =0; /* Num of Msg4 without CCCH Sdu */
86 uint32_t rgNumMsg4Dtx =0; /* Num of DTX received for Msg 4 */
87 uint32_t rgNumMsg3AckSent =0; /* Num of PHICH Ack sent for Msg 3 */
88 uint32_t rgNumMsg3NackSent =0; /* Num of PHICH Nack sent for Msg 3 */
89 uint32_t rgNumMsg4PdcchWithCrnti =0; /* Num of PDCCH for CRNTI based contention resolution */
90 uint32_t rgNumRarFailDuetoRntiExhaustion =0; /* Num of RACH Failures due to RNTI pool exhaution */
91 uint32_t rgNumTAModified =0; /* Num of times TA received is different from prev value */
92 uint32_t rgNumTASent =0; /* Num of TA Command sent */
93 uint32_t rgNumMsg4ToBeTx =0; /* Num of times MSG4 that should be sent */
94 uint32_t rgNumMsg4Txed =0; /* Num of MSG4 actually sent *//* ysNumMsg4ToBeTx -ysNumMsg4Txed == Failed MSG4 TX */
95 uint32_t rgNumMsg3DtxRcvd =0; /* CRC Fail with SINR < 0 */
97 uint32_t rgNumDedPreamUECtxtFound =0; /* Num of Dedicated Preambles recvd */
99 static uint8_t rgSchDciAmbigSizeTbl[61] = {0,0,0,0,0,0,0,0,0,0,0,
100 0,1,0,1,0,1,0,0,0,1,
101 0,0,0,1,0,1,0,0,0,0,
102 0,1,0,0,0,0,0,0,0,1,
103 0,0,0,1,0,0,0,0,0,0,
104 0,0,0,0,0,1,0,0,0,0};
108 uint32_t rgSchCmnBetaCqiOffstTbl[16];
109 uint32_t rgSchCmnBetaRiOffstTbl[16];
110 RgSchdApis rgSchCmnApis;
111 S16 RgUiRgmSendPrbRprtInd ARGS((
114 RgmPrbRprtInd *prbRprtInd
117 S16 RgUiRgmSendTmModeChangeInd ARGS((
120 RgmTransModeInd *txModeChngInd
123 S16 rgSCHEmtcUtlGetSfAlloc ARGS((
126 S16 rgSCHEmtcUtlPutSfAlloc ARGS((
129 Void rgSCHEmtcUtlUpdUeDciSize ARGS((
133 Void rgSCHEmtcGetDciFrmt61ASize ARGS((
136 Void rgSCHEmtcGetDciFrmt60ASize ARGS((
139 S16 rgSCHEmtcUtlFillPdschDciInfo ARGS((
140 TfuPdschDciInfo *pdsch,
143 Void rgSCHEmtcUtlRlsRnti ARGS((
145 RgSchRntiLnk *rntiLnk,
148 S16 rgSCHEmtcPdcchAlloc ARGS((
152 Void rgSCHEmtcPdcchFree ARGS((
157 /* Functions specific to TM1/TM2/TM6/TM7 for PRB calculation*/
158 Void rgSchUtlDlCalc1CwPrb ARGS(( RgSchCellCb *cell,
161 uint32_t *prbReqrd));
163 /* Functions specific to TM3/TM4 for PRB calculation*/
164 Void rgSchUtlDlCalc2CwPrb ARGS(( RgSchCellCb *cell,
167 uint32_t *prbReqrd));
170 RgSchCellCb* rgSchUtlGetCellCb ARGS(( Inst inst,
175 typedef Void (*RgSchUtlDlCalcPrbFunc) ARGS((RgSchCellCb *cell, RgSchUeCb *ue,
176 uint32_t bo, uint32_t *prbRequrd));
178 /* Functions specific to each transmission mode for PRB calculation*/
179 RgSchUtlDlCalcPrbFunc dlCalcPrbFunc[7] = {rgSchUtlDlCalc1CwPrb,
180 rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc2CwPrb, rgSchUtlDlCalc2CwPrb,
181 NULLP, rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc1CwPrb};
184 /* Functions specific to each transmission mode for PRB calculation*/
185 RgSchUtlDlCalcPrbFunc dlCalcPrbFunc[9] = {rgSchUtlDlCalc1CwPrb,
186 rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc2CwPrb, rgSchUtlDlCalc2CwPrb,
187 NULLP, rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc1CwPrb, NULLP, NULLP};
192 /* The below table will be used to map the UL SF number in a TDD Cfg 0
193 frame to the ul Sf array maintained in cellCb */
194 static uint8_t rgSchTddCfg0UlSfTbl[] = {2, 3, 4, 7, 8, 9};
197 static S16 rgSCHUtlUlAllocDbInit ARGS((
202 static Void rgSCHUtlUlAllocDbDeinit ARGS((
206 static S16 rgSCHUtlUlHoleDbInit ARGS((
213 static Void rgSCHUtlUlHoleDbDeinit ARGS((
218 static S16 rgSCHChkBoUpdate ARGS((
220 RgInfCmnBoRpt *boUpdt
224 static uint8_t rgSCHUtlFetchPcqiBitSz ARGS((
231 /* sorted in ascending order of tbSz */
232 const struct rgSchUtlBcchPcchTbSz
234 uint8_t rbIndex; /* RB index {2,3} */
235 uint16_t tbSz; /* one of the Transport block size in bits of
237 /* Corrected allocation for common channels */
238 uint8_t mcs; /* imcs */
239 } rgSchUtlBcchPcchTbSzTbl[44] = {
240 { 2, 32, 0 }, { 2, 56, 1 }, { 2, 72, 2 }, { 3, 88, 1 },
241 { 2, 104, 3 }, { 2, 120, 4 }, { 2, 144, 5 }, { 2, 176, 6 },
242 { 3, 208, 4 }, { 2, 224, 7 }, { 2, 256, 8 }, { 2, 296, 9 },
243 { 2, 328, 10 }, { 2, 376, 11 }, { 3, 392, 8 }, { 2, 440, 12 },
244 { 3, 456, 9 }, { 2, 488, 13 }, { 3, 504, 10 }, { 2, 552, 14 },
245 { 3, 584, 11 }, { 2, 600, 15 }, { 2, 632, 16 }, { 3, 680, 12 },
246 { 2, 696, 17 }, { 3, 744, 13 }, { 2, 776, 18 }, { 2, 840, 19 },
247 { 2, 904, 20 }, { 3, 968, 16 }, { 2, 1000, 21 }, { 2, 1064, 22 },
248 { 2, 1128, 23 }, { 3, 1160, 18 }, { 2, 1192, 24 }, { 2, 1256, 25 },
249 { 3, 1288, 19 }, { 3, 1384, 20 }, { 2, 1480, 26 }, { 3, 1608, 22 },
250 { 3, 1736, 23 }, { 3, 1800, 24 }, { 3, 1864, 25 }, { 3, 2216, 26 }
257 /* forward references */
259 static Void rgSCHUtlUpdPrachOcc ARGS((
261 RgrTddPrachInfo *cellCfg));
264 #define RGSCH_NUM_PCFICH_REG 4
265 #define RGSCH_NUM_REG_PER_CCE 9
266 #define RGSCH_NUM_REG_PER_PHICH_GRP 3
269 #define RGSCH_INITPHICH(_phich, _hqFeedBack, _nDmrs, _rbStart, _iPhich) {\
270 (_phich)->hqFeedBack = _hqFeedBack; \
271 (_phich)->rbStart = _rbStart; \
272 (_phich)->nDmrs = _nDmrs; \
273 (_phich)->iPhich = _iPhich; \
274 (_phich)->lnk.next = NULLP; \
275 (_phich)->lnk.prev = NULLP; \
276 (_phich)->lnk.node = (PTR)(_phich); \
279 #define RGSCH_INITPHICH(_phich, _hqFeedBack, _nDmrs, _rbStart, _isForMsg3) {\
280 (_phich)->hqFeedBack = _hqFeedBack; \
281 (_phich)->rbStart = _rbStart; \
282 (_phich)->nDmrs = _nDmrs; \
283 (_phich)->isForMsg3 = _isForMsg3; \
284 (_phich)->lnk.next = NULLP; \
285 (_phich)->lnk.prev = NULLP; \
286 (_phich)->lnk.node = (PTR)(_phich); \
290 #define RGSCH_PHICH_ALLOC(_inst,_dataPtr, _size, _ret) {\
291 _ret = rgSCHUtlAllocSBuf(_inst, (Data **)&_dataPtr, _size); \
294 /* ccpu00117052 - MOD - Passing double pointer
295 for proper NULLP assignment*/
296 #define RGSCH_PHICH_FREE(_inst, _dataPtr, _size) {\
297 rgSCHUtlFreeSBuf(_inst, (Data **)(&(_dataPtr)), _size); \
301 #define RGSCH_GETBIT(a, b) ((((uint8_t*)a)[(b)>>3] >> ((7-((b)&7)))) & 1)
307 * Desc: This function finds of the Power of x raised to n
309 * Ret: value of x raised to n
316 F64 rgSCHUtlPower(F64 x,F64 n)
324 return ( x * rgSCHUtlPower( x, n-1 ) );
328 return ( (1/x) * rgSCHUtlPower( x, n+1 ) );
330 } /* end of rgSCHUtlPower*/
336 * Desc: This function parses bits x to y of an array and
337 * returns the integer value out of it.
339 * Ret: integer value of z bits
346 uint32_t rgSCHUtlParse(uint8_t *buff,uint8_t startPos,uint8_t endPos,uint8_t buffSize)
348 uint8_t pointToChar,pointToEnd, loop;
349 uint8_t size = endPos - startPos;
351 pointToEnd = (startPos)%8;
352 for ( loop=0; loop<size; loop++)
354 pointToChar = (((startPos)+loop)/8);
355 if (RGSCH_GETBIT(buff+pointToChar,pointToEnd%8)==1)
357 result=result+(rgSCHUtlPower(2,(size-loop-1)));
361 return ((uint32_t)result);
362 } /* end of rgSCHUtlParse*/
366 * Fun: rgSCHUtlFindDist
368 * Desc: This function calculates the iterations need to cover
369 * before the valid Index can be used for next possible Reception
371 * Ret: integer value of z bits
378 uint8_t rgSCHUtlFindDist(uint16_t crntTime,uint16_t tempIdx)
381 /* ccpu00137113- Distance is not estimated properly if the periodicity is
382 * equal to RG_SCH_PCQI_SRS_SR_TRINS_SIZE.
384 while(crntTime<=tempIdx)
386 crntTime += RG_SCH_PCQI_SRS_SR_TRINS_SIZE;
390 } /* end of rgSCHUtlFindDist*/
395 * @brief This function checks availability of a PDCCH
399 * Function: rgSCHUtlPdcchAvail
400 * Purpose: This function checks if a particular PDCCH is in use.
401 * map field of PDCCH is used to track the CCEs arleady
402 * allocated. Each bit of map represents one CCE and the
403 * LSBit of first byte represents CCE 0.
405 * 1. Locate the set of bits that represent the PDCCH for
406 * the provided location.
407 * 2. If the value of the bits is non-zero one or many CCEs
408 * for the PDCCH are in use and hence the PDCCH is not available.
409 * 3. If pdcch is available, assign it to [out]pdcch.
410 * 4. Set all of the bits to one. There is no check performed
411 * to see if the PDCCH is available.
413 * Invoked by: scheduler
415 * @param[in] RgSchCellCb* cell
416 * @param[in] RgSchPdcchInfo* pdcchInfo
417 * @param[in] uint8_t loc
418 * @param[in] uint8_t aggrLvl
419 * @param[out] RgSchPdcch** pdcch
421 * -# TRUE if available
425 Bool rgSCHUtlPdcchAvail
428 RgSchPdcchInfo *pdcchInfo,
429 CmLteAggrLvl aggrLvl,
437 Inst inst = cell->instIdx;
439 uint16_t offsetStepMask;
443 byte = &pdcchInfo->map[0];
444 initMask = (0xffff >> (16 - aggrLvl));
446 /* if N(symbol, xPDCCH) =2, then xPDCCH will be candidates in
447 * search space of index {0,1,2,3} and {8,9,..14}
449 if ((cell->cell5gtfCb.cfi == 2) && (aggrLvl == CM_LTE_AGGR_LVL2))
451 offsetStepMask = 0xc;
455 offsetStepMask = 0xc0;
458 /* Loop till the number of bytes available in the CCE map */
459 while (offset < ((pdcchInfo->nCce+ 7) >> 3))
461 byte = &pdcchInfo->map[offset];
462 /* Checking for available CCE */
463 if ((*byte & currMask) == 0)
467 /* if the number of CCEs required are not available, move to next offset */
468 if (currMask & offsetStepMask)
475 /* Move to the next available CCE index in the current byte(cce map) */
476 currMask = currMask << aggrLvl;
480 if ((offset >= ((pdcchInfo->nCce + 7) >> 3)) ||
481 ((aggrLvl == CM_LTE_AGGR_LVL16) && (offset > 0)))
486 byte = &pdcchInfo->map[offset];
488 if (cell->pdcchLst.first != NULLP)
490 *pdcch = (RgSchPdcch *)(cell->pdcchLst.first->node);
491 cmLListDelFrm(&cell->pdcchLst, cell->pdcchLst.first);
495 ret = rgSCHUtlAllocSBuf(inst, (Data **)pdcch, sizeof(RgSchPdcch));
505 /* ALL CCEs will be used in case of level 16 */
506 if (aggrLvl == CM_LTE_AGGR_LVL16)
508 *(byte+1) |= currMask;
510 (*pdcch)->aggrLvl = aggrLvl;
511 cmLListAdd2Tail(&pdcchInfo->pdcchs, &((*pdcch)->lnk));
512 (*pdcch)->lnk.node = (PTR)*pdcch;
513 (*pdcch)->nCce = aggrLvl;
514 (*pdcch)->ue = NULLP;
522 * @brief This function releases a PDCCH
526 * Function: rgSCHUtlPdcchPut
527 * Purpose: This function releases a PDCCH.
529 * 1. Locate the set of bits that represent the PDCCH for
530 * the provided location.
531 * 2. Set all of the bits to zero.
532 * 3. Release the memory of PDCCH to the cell free Q
534 * Invoked by: scheduler
536 * @param[in] RgSchPdcchInfo* pdcchInfo
537 * @param[in] uint8_t loc
538 * @param[in] uint8_t aggrLvl
542 Void rgSCHUtlPdcchPut(RgSchCellCb *cell,RgSchPdcchInfo *pdcchInfo,RgSchPdcch *pdcch)
548 switch(pdcch->aggrLvl)
550 case CM_LTE_AGGR_LVL2:
551 offset = (pdcch->nCce >> 1) & 3;
552 mask = 0x3 << (offset * 2); /*ccpu00128826 - Offset Correction */
554 case CM_LTE_AGGR_LVL4:
555 offset = (pdcch->nCce >> 2) & 1;
556 mask = 0xf << (offset * 4);/*ccpu00128826 - Offset Correction */
558 case CM_LTE_AGGR_LVL8:
561 case CM_LTE_AGGR_LVL16:
567 /* Placing common computation of byte from all the cases above here
569 byte = &pdcchInfo->map[pdcch->nCce >> 3];
571 cmLListDelFrm(&pdcchInfo->pdcchs, &pdcch->lnk);
572 cmLListAdd2Tail(&cell->pdcchLst, &pdcch->lnk);
573 pdcch->lnk.node = (PTR)pdcch;
582 * @brief This function initializes PDCCH information for frame
586 * Function: rgSCHUtlPdcchInit
587 * Purpose: This function initializes PDCCH information for
588 * a slot. It removes the list of PDCCHs allocated
589 * in the prior use of this slot structure.
591 * Invoked by: rgSCHUtlSubFrmPut
593 * @param[in] RgSchCellCb* cell
594 * @param[in] RgSubFrm* subFrm
598 Void rgSCHUtlPdcchInit(RgSchCellCb *cell,RgSchDlSf *subFrm,uint16_t nCce)
600 RgSchPdcchInfo *pdcchInfo;
602 Inst inst = cell->instIdx;
606 pdcchInfo = &subFrm->pdcchInfo;
607 while(pdcchInfo->pdcchs.first != NULLP)
609 pdcch = (RgSchPdcch *)pdcchInfo->pdcchs.first->node;
610 cmLListDelFrm(&pdcchInfo->pdcchs, pdcchInfo->pdcchs.first);
611 cmLListAdd2Tail(&cell->pdcchLst, &pdcch->lnk);
614 cmLListInit(&pdcchInfo->pdcchs);
617 subFrm->relPdcch = NULLP;
620 cceMapSz = ((pdcchInfo->nCce + 7) >> 3);
622 /* The bitMap array size is the number of ceiling(CCEs/8) */
623 /* If nCce received is not the same as the one stored in
624 * pdcchInfo, free the pdcchInfo map */
626 if(pdcchInfo->nCce != nCce)
630 rgSCHUtlFreeSBuf(inst, (Data **)(&(pdcchInfo->map)), cceMapSz);
632 pdcchInfo->nCce = nCce;
633 cceMapSz = ((pdcchInfo->nCce + 7) >> 3);
634 rgSCHUtlAllocSBuf(inst, (Data **)&pdcchInfo->map,
636 if (pdcchInfo->map == NULLP)
638 /* Generate log error here */
643 memset(subFrm->pdcchInfo.map, 0, cceMapSz);
644 /* If nCce is not exactly same as the bitMap size(no of bits allocated
645 * to represent the Cce's, then mark the extra bits as unavailable
646 extra bits = (((pdcchInfo->nCce + 7) >> 3)*8) - pdcchInfo->nCce
647 The last byte of bit map = subFrm->pdcchInfo.map[((pdcchInfo->nCce + 7) >> 3) - 1]
648 NOTE : extra bits are most significant of the last byte eg. */
649 extraBits = (cceMapSz)*8 - pdcchInfo->nCce;
650 subFrm->pdcchInfo.map[cceMapSz - 1] |=
651 ((1 << extraBits) - 1) << (8 - extraBits);
655 /* LTE_ADV_FLAG_REMOVED_START */
657 * @brief This function frees Pool
660 * Function: rgSchSFRTotalPoolFree
662 * Invoked by: rgSchSFRTotalPoolInit
664 * @param[in] RgSchCellCb* cell
665 * @param[in] RgSubFrm* subFrm
669 Void rgSchSFRTotalPoolFree(RgSchSFRTotalPoolInfo *sfrTotalPoolInfo,RgSchCellCb *cell)
674 /*Deinitialise if these cc pools and ce pools are already existent*/
675 l = &sfrTotalPoolInfo->ccPool;
679 /*REMOVING Cell Centred POOLS IF ANY*/
680 n = cmLListDelFrm(l, n);
682 /* Deallocate buffer */
683 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n->node)), sizeof(RgSchSFRPoolInfo));
685 /* Deallocate buffer */
686 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n)), sizeof(CmLList));
690 /*REMOVING Cell Edged POOLS IF ANY*/
691 l = &sfrTotalPoolInfo->cePool;
695 n = cmLListDelFrm(l, n);
697 /* Deallocate buffer */
698 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n->node)), sizeof(RgSchSFRPoolInfo));
700 /* Deallocate buffer */
701 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n)), sizeof(CmLList));
708 * @brief This function resets temporary variables in Pool
711 * Function: rgSchSFRResetPoolVariables
713 * Invoked by: rgSCHSFRUtlTotalPoolInit
715 * @param[in] RgSchCellCb* cell
716 * @param[in] RgSubFrm* subFrm
720 S16 rgSchSFRTotalPoolInit(RgSchCellCb *cell,RgSchDlSf *sf)
722 /* Initialise the variables */
723 RgSchSFRPoolInfo *sfrCCPool;
724 RgSchSFRPoolInfo *sfrCEPool;
727 CmLList *temp = NULLP;
730 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo, cell);
731 sf->sfrTotalPoolInfo.CCPool1BwAvlbl = 0;
732 sf->sfrTotalPoolInfo.CCPool2BwAvlbl = 0;
733 sf->sfrTotalPoolInfo.CEPoolBwAvlbl = 0;
734 sf->sfrTotalPoolInfo.CC1 = FALSE;
735 sf->sfrTotalPoolInfo.CC2 = FALSE;
736 /*Initialise the CE Pools*/
737 cmLListInit (&(sf->sfrTotalPoolInfo.cePool));
739 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
742 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
743 "CE Pool memory allocation FAILED for cell");
744 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo, cell);
748 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
751 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
752 "CE Pool memory allocation FAILED for cell ");
753 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
757 l = &sf->sfrTotalPoolInfo.cePool;
758 cmLListAdd2Tail(l, temp);
760 /*Initialise Bandwidth and startRB and endRB for each pool*/
763 /* Initialise the CE Pools */
764 sfrCEPool = (RgSchSFRPoolInfo*)n->node;
766 sfrCEPool->poolstartRB = cell->lteAdvCb.sfrCfg.cellEdgeRbRange.startRb;
767 sfrCEPool->poolendRB = cell->lteAdvCb.sfrCfg.cellEdgeRbRange.endRb;
768 sfrCEPool->bw = sfrCEPool->poolendRB - sfrCEPool->poolstartRB + 1;
769 sf->sfrTotalPoolInfo.CEPoolBwAvlbl = sfrCEPool->bw;
771 sfrCEPool->bwAlloced = 0;
772 sfrCEPool->type2Start = sfrCEPool->poolstartRB;
773 sfrCEPool->type2End = RGSCH_CEIL(sfrCEPool->poolstartRB, cell->rbgSize);
774 sfrCEPool->type0End = ((sfrCEPool->poolendRB + 1) / cell->rbgSize) - 1;
775 sfrCEPool->pwrHiCCRange.startRb = 0;
776 sfrCEPool->pwrHiCCRange.endRb = 0;
778 /*Initialise CC Pool*/
779 cmLListInit (&(sf->sfrTotalPoolInfo.ccPool));
781 /*Add memory and Update CCPool*/
782 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
785 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
786 "CC Pool memory allocation FAILED for cell ");
787 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
791 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
794 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
795 "CC Pool memory allocation FAILED for cell ");
796 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
800 l = &sf->sfrTotalPoolInfo.ccPool;
801 cmLListAdd2Tail(l, temp);
803 /*Initialise Bandwidth and startRB and endRB for each pool*/
804 if(sfrCEPool->poolstartRB)
807 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
809 sfrCCPool->poolstartRB = 0;
810 sfrCCPool->poolendRB = sfrCEPool->poolstartRB - 1;
811 sfrCCPool->bw = sfrCCPool->poolendRB - sfrCCPool->poolstartRB + 1;
812 sf->sfrTotalPoolInfo.CCPool1BwAvlbl = sfrCCPool->bw;
813 sfrCCPool->bwAlloced = 0;
814 sfrCCPool->type2Start = 0;
815 sfrCCPool->type2End = 0;
816 sfrCCPool->type0End = ((sfrCCPool->poolendRB + 1) / cell->rbgSize) - 1;
817 sf->sfrTotalPoolInfo.CC1 = TRUE;
818 sfrCCPool->pwrHiCCRange.startRb = 0;
819 sfrCCPool->pwrHiCCRange.endRb = 0;
824 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
826 sfrCCPool->poolstartRB = sfrCEPool->poolendRB + 1;
827 sfrCCPool->poolendRB = sf->bw - 1;
828 sfrCCPool->bw = sfrCCPool->poolendRB - sfrCCPool->poolstartRB + 1;
829 sf->sfrTotalPoolInfo.CCPool2BwAvlbl = sfrCCPool->bw;
830 sfrCCPool->CCPool2Exists = TRUE;
831 sfrCCPool->bwAlloced = 0;
832 sfrCCPool->type2Start = sfrCCPool->poolstartRB;
833 sfrCCPool->type2End = RGSCH_CEIL(sfrCCPool->poolstartRB, cell->rbgSize);
834 sfrCCPool->type0End = ((sfrCCPool->poolendRB + 1) / cell->rbgSize) - 1;
835 sf->sfrTotalPoolInfo.CC2 = TRUE;
836 sfrCEPool->adjCCPool = sfrCCPool; /* SFR_FIX */
837 sfrCCPool->pwrHiCCRange.startRb = 0;
838 sfrCCPool->pwrHiCCRange.endRb = 0;
841 if((sfrCEPool->poolendRB != sf->bw - 1) && (!sfrCCPool->poolstartRB))
843 /*Add memory and Update CCPool*/
844 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
847 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
848 "CC Pool memory allocation FAILED for cell ");
849 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
853 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
856 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
857 "CC Pool memory allocation FAILED for cell ");
858 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
862 cmLListAdd2Tail(l, temp);
865 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
867 sfrCCPool->poolstartRB = sfrCEPool->poolendRB + 1;
868 sfrCCPool->poolendRB = sf->bw - 1;
869 sfrCCPool->bw = sfrCCPool->poolendRB - sfrCCPool->poolstartRB + 1;
870 sf->sfrTotalPoolInfo.CCPool2BwAvlbl = sfrCCPool->bw;
871 sfrCCPool->CCPool2Exists = TRUE;
872 sfrCCPool->bwAlloced = 0;
873 sfrCCPool->type2Start = sfrCCPool->poolstartRB;
874 sfrCCPool->type2End = RGSCH_CEIL(sfrCCPool->poolstartRB, cell->rbgSize);
875 sfrCCPool->type0End = ((sfrCCPool->poolendRB + 1) / cell->rbgSize) - 1;
876 sf->sfrTotalPoolInfo.CC2 = TRUE;
877 sfrCEPool->adjCCPool = sfrCCPool; /* SFR_FIX */
878 sfrCCPool->pwrHiCCRange.startRb = 0;
879 sfrCCPool->pwrHiCCRange.endRb = 0;
882 sf->sfrTotalPoolInfo.CCRetx = FALSE;
883 sf->sfrTotalPoolInfo.CERetx = FALSE;
885 sf->sfrTotalPoolInfo.ccBwFull = FALSE;
886 sf->sfrTotalPoolInfo.ceBwFull = FALSE;
887 sf->sfrTotalPoolInfo.isUeCellEdge = FALSE;
891 * @brief This function resets temporary variables in RNTP Prepration
894 * Function: rgSchDSFRRntpInfoInit
896 * Invoked by: rgSCHSFRUtlTotalPoolInit
898 * @param[in] TknStrOSXL* rntpPtr
899 * @param[in] RgSubFrm* subFrm
903 S16 rgSchDSFRRntpInfoInit(TknStrOSXL *rntpPtr,RgSchCellCb *cell,uint16_t bw)
905 Inst inst = cell->instIdx;
908 rntpPtr->pres = PRSNT_NODEF;
910 len = (bw % 8 == 0) ? (bw/8) : (bw/8 + 1);
914 /* Allocate memory for "scheduled UE" Info */
915 if((rgSCHUtlAllocSBuf(inst, (Data**)&(rntpPtr->val),
916 (len * sizeof(uint8_t)))) != ROK)
918 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED for RNTP Alloc");
926 * @brief This function release RNTP pattern from slot and Cell
929 * Function: rgSchDSFRRntpInfoFree
931 * Invoked by: rgSCHSFRUtlTotalPoolInit
933 * @param[in] TknStrOSXL* rntpPtr
934 * @param[in] RgSubFrm* subFrm
938 S16 rgSchDSFRRntpInfoFree(TknStrOSXL *rntpPtr,RgSchCellCb *cell,uint16_t bw)
940 Inst inst = cell->instIdx;
943 len = (bw % 8 == 0) ? (bw/8) : (bw/8 + 1);
945 if(rntpPtr->pres == PRSNT_NODEF)
947 rgSCHUtlFreeSBuf(inst, (Data **)(&(rntpPtr->val)),(len * sizeof(uint8_t)));
948 rntpPtr->pres = NOTPRSNT;
956 * @brief This function resets temporary variables in Pool
959 * Function: rgSchSFRResetPoolVariables
960 * Purpose: Initialise the dynamic variables in each pool.
961 * Reset bwAlloced, bwAssigned, type2End, type0End, type2Start
962 * Invoked by: rgSCHSFRUtlTotalPoolReset
964 * @param[in] RgSchCellCb* cell
965 * @param[in] RgSchSFRPoolInfo *pool
969 static Void rgSchSFRResetPoolVariables(RgSchCellCb *cell,RgSchSFRPoolInfo *pool)
974 /*type0end will be the last RBG in pool with all available RBs*/
975 pool->type0End = (((pool->poolendRB + 1)/cell->rbgSize) - 1);
977 /*type2end will be the first RBG in pool with all available RBs*/
978 pool->type2End = RGSCH_CEIL(pool->poolstartRB, cell->rbgSize);
979 pool->type2Start = pool->poolstartRB;
980 pool->bw = pool->poolendRB - pool->poolstartRB + 1;
985 * @brief This function resets SFR Pool information for frame
989 * Function: rgSCHSFRUtlTotalPooReset
990 * Purpose: Update the dynamic variables in each pool as they will be modified in each slot.
991 * Dont modify the static variables like startRB, endRB, BW
992 * Invoked by: rgSCHUtlSubFrmPut
994 * @param[in] RgSchCellCb* cell
995 * @param[in] RgSchDlSf* subFrm
999 static Void rgSCHSFRUtlTotalPoolReset(RgSchCellCb *cell,RgSchDlSf *subFrm)
1001 RgSchSFRTotalPoolInfo *totalPoolInfo = &subFrm->sfrTotalPoolInfo;
1002 CmLListCp *ccPool = &totalPoolInfo->ccPool;
1003 CmLListCp *cePool = &totalPoolInfo->cePool;
1004 CmLList *node = NULLP;
1005 RgSchSFRPoolInfo *tempPool = NULLP;
1007 totalPoolInfo->ccBwFull = FALSE;
1008 totalPoolInfo->ceBwFull = FALSE;
1009 totalPoolInfo->isUeCellEdge = FALSE;
1010 totalPoolInfo->CCPool1BwAvlbl = 0;
1011 totalPoolInfo->CCPool2BwAvlbl = 0;
1012 totalPoolInfo->CEPoolBwAvlbl = 0;
1013 totalPoolInfo->CCRetx = FALSE;
1014 totalPoolInfo->CERetx = FALSE;
1016 node = ccPool->first;
1019 tempPool = (RgSchSFRPoolInfo *)(node->node);
1021 rgSchSFRResetPoolVariables(cell, tempPool);
1022 if(tempPool->poolstartRB == 0)
1023 totalPoolInfo->CCPool1BwAvlbl = tempPool->bw;
1025 totalPoolInfo->CCPool2BwAvlbl = tempPool->bw;
1028 node = cePool->first;
1031 tempPool = (RgSchSFRPoolInfo *)(node->node);
1033 rgSchSFRResetPoolVariables(cell, tempPool);
1034 totalPoolInfo->CEPoolBwAvlbl = tempPool->bw;
1039 /* LTE_ADV_FLAG_REMOVED_END */
1041 * @brief This function appends PHICH information for frame
1045 * Function: rgSCHUtlAddPhich
1046 * Purpose: This function appends PHICH information for
1051 * @param[in] RgSchCellCb* cell
1052 * @param[in] RgSubFrm* subFrm
1053 * @param[in] uint8_t hqFeedBack
1054 * @param[in] uint8_t nDmrs
1055 * @param[in] uint8_t rbStart
1061 S16 rgSCHUtlAddPhich
1064 CmLteTimingInfo frm,
1071 S16 rgSCHUtlAddPhich
1074 CmLteTimingInfo frm,
1085 Inst inst = cell->instIdx;
1087 dlSf = rgSCHUtlSubFrmGet(cell, frm);
1088 RGSCH_PHICH_ALLOC(inst, phich,sizeof(RgSchPhich), ret);
1092 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, " rgSCHUtlAddPhich(): "
1093 "Allocation of RgSchPhich failed");
1097 RGSCH_INITPHICH(phich, hqFeedBack, nDmrs, rbStart, iPhich);
1099 RGSCH_INITPHICH(phich, hqFeedBack, nDmrs, rbStart, isForMsg3); /*SR_RACH_STATS */
1101 cmLListAdd2Tail(&dlSf->phichInfo.phichs, &phich->lnk);
1103 } /* rgSCHUtlAddPhich */
1106 * @brief This function resets PHICH information for frame
1110 * Function: rgSCHUtlPhichReset
1111 * Purpose: This function initializes PHICH information for
1112 * a slot. It removes the list of PHICHs allocated
1113 * in the prior use of this slot structure.
1115 * Invoked by: rgSCHUtlSubFrmPut
1117 * @param[in] RgSchCellCb* cell
1118 * @param[in] RgSubFrm* subFrm
1122 static Void rgSCHUtlPhichReset(RgSchCellCb *cell,RgSchDlSf *subFrm)
1124 RgSchPhichInfo *phichInfo;
1129 phichInfo = &subFrm->phichInfo;
1130 while(phichInfo->phichs.first != NULLP)
1132 phich = (RgSchPhich *)phichInfo->phichs.first->node;
1133 cmLListDelFrm(&phichInfo->phichs, phichInfo->phichs.first);
1134 RGSCH_PHICH_FREE(cell->instIdx, phich, sizeof(RgSchPhich));
1136 cmLListInit(&phichInfo->phichs);
1138 } /* rgSCHUtlPhichReset */
1142 * @brief This function returns slot data structure for a cell
1146 * Function: rgSCHUtlSubFrmGet
1147 * Purpose: This function resets the slot data structure
1148 * when the slot is released
1150 * Invoked by: scheduler
1152 * @param[in] RgSubFrm subFrm
1156 RgSchDlSf* rgSCHUtlSubFrmGet(RgSchCellCb *cell,CmLteTimingInfo frm)
1162 dlIdx = rgSCHUtlGetDlSfIdx(cell, &frm);
1163 //RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx);
1164 sf = cell->subFrms[dlIdx];
1166 /* Changing the idexing
1167 so that proper slot is selected */
1168 dlIdx = (((frm.sfn & 1) * RGSCH_NUM_SUB_FRAMES) + (frm.slot % RGSCH_NUM_SUB_FRAMES));
1169 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx);
1170 sf = cell->subFrms[dlIdx];
1180 * @brief This function returns slot data structure for a cell
1184 * Function: rgSCHUtlSubFrmPut
1185 * Purpose: This function resets the slot data structure
1186 * when the slot is released
1188 * Invoked by: scheduler
1190 * @param[in] RgSubFrm subFrm
1194 Void rgSCHUtlSubFrmPut(RgSchCellCb *cell,RgSchDlSf *sf)
1200 /* Release all the held PDCCH information */
1201 rgSCHUtlPdcchInit(cell, sf, sf->nCce);
1203 /* Release all the held PDCCH information */
1204 rgSCHUtlPdcchInit(cell, sf, cell->nCce);
1206 rgSCHUtlPhichReset(cell, sf);
1208 /* Reset the bw allocated. */
1211 /* Setting allocated bandwidth to SPS bandwidth for non-SPS RB allocator */
1212 sf->bwAlloced = ((cell->spsCellCfg.maxSpsDlBw +
1213 cell->rbgSize - 1)/cell->rbgSize) * cell->rbgSize;
1214 if (sf->bwAlloced > sf->bw)
1216 sf->bwAlloced = sf->bw;
1218 sf->spsAllocdBw = 0;
1219 sf->type2Start = sf->bwAlloced;
1220 memset( &sf->dlSfAllocInfo, 0, sizeof(RgSchDlSfAllocInfo));
1223 /* Fix for ccpu00123918*/
1225 /* LTE_ADV_FLAG_REMOVED_START */
1226 /* dsfr_pal_fixes ** 21-March-2013 ** SKS */
1227 if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
1229 memset(sf->rntpInfo.val, 0, sf->rntpInfo.len);
1231 /* LTE_ADV_FLAG_REMOVED_END */
1234 /*[ccpu00138609]-ADD-Reset the CCCH UE counter */
1237 /* Non DLFS scheduling using Type0 RA requires the following
1238 * parameter's tracking */
1239 /* Type 2 localized allocations start from 0th RBG and onwards */
1240 /* Type 0 allocations start from last RBG and backwards*/
1244 sf->type2End = RGSCH_CEIL(sf->bwAlloced,cell->rbgSize);
1246 sf->type0End = cell->noOfRbgs - 1;
1247 /* If last RBG is of incomplete size then special handling */
1248 (sf->bw % cell->rbgSize == 0)? (sf->lstRbgDfct = 0) :
1249 (sf->lstRbgDfct = cell->rbgSize - (sf->bw % cell->rbgSize));
1250 /* This resets the allocation for BCCH and PDCCH */
1252 /* TODO we need to move this reset for emtc functions */
1253 if(!(cell->emtcEnable))
1262 sf->bcch.pdcch = NULLP;
1263 sf->pcch.pdcch = NULLP;
1265 noRaRsps = RGSCH_MAX_TDD_RA_RSP_ALLOC;
1267 noRaRsps = RGSCH_MAX_RA_RSP_ALLOC;
1269 for (i = 0; i < noRaRsps; i++)
1271 sf->raRsp[i].pdcch = NULLP;
1272 cmLListInit(&(sf->raRsp[i].raRspLst));
1274 /* LTE_ADV_FLAG_REMOVED_START */
1275 if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE)
1277 rgSCHSFRUtlTotalPoolReset(cell, sf);
1279 /* LTE_ADV_FLAG_REMOVED_END */
1281 cmLListInit(&sf->n1PucchResLst);
1285 sf->isCceFailure = FALSE;
1286 sf->dlUlBothCmplt = 0;
1292 * @brief This function computes log N (32 bit Unsigned) to the base 2
1296 * Function: rgSCHUtlLog32bitNbase2
1297 * Purpose: This function computes log N (32 bit Unsigned) to the base 2.
1298 * For n= 0,1 ret = 0.
1300 * Invoked by: Scheduler
1302 * @param[in] uint32_t n
1306 uint8_t rgSCHUtlLog32bitNbase2(uint32_t n)
1308 uint32_t b[] = {0x2, 0xc, 0xf0, 0xff00, 0xffff0000};
1309 uint32_t s[] = {1, 2, 4, 8, 16};
1313 for (i=4; i >= 0; i--)
1327 * @brief This function is a wrapper to call scheduler specific API.
1331 * Function: rgSCHUtlDlRelPdcchFbk
1332 * Purpose: Calls scheduler's handler for SPS release PDCCH feedback
1337 * @param[in] RgSchCellCb *cell
1338 * @param[in] RgSchUeCb *ue
1339 * @param[in] uint8_t isAck
1343 Void rgSCHUtlDlRelPdcchFbk(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t isAck)
1345 cell->sc.apis->rgSCHDlRelPdcchFbk(cell, ue, isAck);
1352 * @brief This function is a wrapper to call scheduler specific API.
1356 * Function: rgSCHUtlDlProcAck
1357 * Purpose: Calls scheduler's handler to process Ack
1362 * @param[in] RgSchCellCb *cell
1363 * @param[in] RgSchDlHqProcCb *hqP
1367 Void rgSCHUtlDlProcAck(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
1369 cell->sc.apis->rgSCHDlProcAck(cell, hqP);
1374 * @brief CRNTI CE Handler
1378 * Function : rgSCHUtlHdlCrntiCE
1380 * - Call scheduler common API
1383 * @param[in] RgSchCellCb *cell
1384 * @param[in] RgSchUeCb *ue
1385 * @param[out] RgSchErrInfo *err
1388 Void rgSCHUtlHdlCrntiCE(RgSchCellCb *cell,RgSchUeCb *ue)
1391 cell->sc.apis->rgSCHHdlCrntiCE(cell, ue);
1393 } /* rgSCHUtlHdlCrntiCE */
1394 #endif /* LTEMAC_SPS */
1396 /***********************************************************
1398 * Func : rgSCHUtlCalcTotalRegs
1400 * Desc : Calculate total REGs, given a bandwidth, CFI
1401 * and number of antennas.
1403 * Ret : Total REGs (uint16_t)
1405 * Notes: Could optimise if bw values are limited
1406 * (taken from RRC spec) by indexing values from
1408 * Input values are not validated. CFI is assumed
1413 **********************************************************/
1414 static uint16_t rgSCHUtlCalcTotalRegs(uint8_t bw,uint8_t cfi,uint8_t numAntna,Bool isEcp)
1418 /*ccpu00116757- removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1424 /* Refer 36.211 section 6.10.1.2
1425 * For symbols 2 and 4, the REGs per RB will be based on cyclic prefix
1426 * and number of antenna ports.
1427 * For symbol 1, there are 2 REGs per RB always. Similarly symbol 3
1431 /*CR changes [ccpu00124416] - MOD*/
1434 regs = bw * RGSCH_NUM_REGS_4TH_SYM_EXT_CP;
1438 regs = bw * RGSCH_NUM_REGS_4TH_SYM_NOR_CP;
1441 regs += bw * RGSCH_NUM_REGS_3RD_SYM;
1443 /*CR changes [ccpu00124416] - MOD using number of antenna ports*/
1444 regs += (numAntna == RGSCH_NUM_ANT_PORT_FOUR) ? \
1445 (bw * RGSCH_NUM_REGS_2ND_SYM_FOUR_ANT_PORT) : \
1446 (bw * RGSCH_NUM_REGS_2ND_SYM_1OR2_ANT_PORT);
1447 default: /* case 1 */
1448 regs += bw * RGSCH_NUM_REGS_1ST_SYM;
1453 /***********************************************************
1455 * Func : rgSCHUtlCalcPhichRegs
1457 * Desc : Calculates number of PHICH REGs
1459 * Ret : Number of PHICH REGs (uint8_t)
1461 * Notes: ng6 is Ng multiplied by 6
1465 **********************************************************/
1466 static uint16_t rgSCHUtlCalcPhichRegs(uint8_t bw,uint8_t ng6)
1468 /* ccpu00115330: Corrected the calculation for number of PHICH groups*/
1469 return (RGSCH_CEIL((bw * ng6) ,(8 * 6)) * RGSCH_NUM_REG_PER_PHICH_GRP);
1474 * @brief Calculates total CCEs (N_cce)
1478 * Function: rgSCHUtlCalcNCce
1479 * Purpose: This function calculates and returns total CCEs for a
1480 * cell, given the following: bandwidth, Ng configuration
1481 * (multiplied by six), cfi (actual number of control
1482 * symbols), m factor for PHICH and number of antennas.
1484 * Invoked by: Scheduler
1486 * @param[in] uint8_t bw
1487 * @param[in] uint8_t ng6
1488 * @param[in] uint8_t cfi
1489 * @param[in] uint8_t mPhich
1490 * @param[in] uint8_t numAntna
1491 * @param[in] Bool isEcp
1492 * @return N_cce (uint8_t)
1495 uint8_t rgSCHUtlCalcNCce(uint8_t bw,RgrPhichNg ng,uint8_t cfi,uint8_t mPhich,uint8_t numAntna,Bool isEcp)
1502 /*ccpu00116757- removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1506 case RGR_NG_ONESIXTH:
1521 totalRegs = rgSCHUtlCalcTotalRegs(bw, cfi, numAntna, isEcp);
1522 phichRegs = rgSCHUtlCalcPhichRegs(bw, ng6);
1523 cceRegs = totalRegs - mPhich*phichRegs - RGSCH_NUM_PCFICH_REG;
1525 return ((uint8_t)(cceRegs/RGSCH_NUM_REG_PER_CCE));
1530 * @brief Calculates total CCEs (N_cce)
1534 * Function: rgSCHUtlCalcNCce
1535 * Purpose: This function calculates and returns total CCEs for a
1536 * cell, given the following: bandwidth, Ng configuration
1537 * (multiplied by six), cfi (actual number of control
1538 * symbols) and number of antennas.
1540 * Invoked by: Scheduler
1542 * @param[in] uint8_t bw
1543 * @param[in] uint8_t ng6
1544 * @param[in] uint8_t cfi
1545 * @param[in] uint8_t numAntna
1546 * @return N_cce (uint8_t)
1549 uint8_t rgSCHUtlCalcNCce(uint8_t bw,RgrPhichNg ng,uint8_t cfi,uint8_t numAntna,Bool isEcp)
1556 /*ccpu00116757- removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1560 case RGR_NG_ONESIXTH:
1575 totalRegs = rgSCHUtlCalcTotalRegs(bw, cfi, numAntna, isEcp);
1576 phichRegs = rgSCHUtlCalcPhichRegs(bw, ng6);
1577 cceRegs = totalRegs - phichRegs - RGSCH_NUM_PCFICH_REG;
1579 return ((uint8_t)(cceRegs/RGSCH_NUM_REG_PER_CCE));
1584 * @brief Returns PHICH info associated with an uplink
1585 * HARQ process allocation
1589 * Function: rgSCHUtlGetPhichInfo
1590 * Purpose: This function returns PHICH info associated with
1591 * an uplink HARQ process allocation. PHICH info
1592 * comprises RB start and N_dmrs.
1594 * @param[in] RgSchUlHqProcCb *hqProc
1595 * @param[out] uint8_t *rbStartRef
1596 * @param[out] uint8_t *nDmrsRef
1600 S16 rgSCHUtlGetPhichInfo(RgSchUlHqProcCb *hqProc,uint8_t *rbStartRef,uint8_t *nDmrsRef,uint8_t *iPhich)
1602 S16 rgSCHUtlGetPhichInfo(RgSchUlHqProcCb *hqProc,uint8_t *rbStartRef,uint8_t *nDmrsRef)
1608 if ((hqProc != NULLP) && (hqProc->alloc != NULLP))
1610 *rbStartRef = hqProc->alloc->grnt.rbStart;
1611 *nDmrsRef = hqProc->alloc->grnt.nDmrs;
1613 *iPhich = hqProc->iPhich;
1621 * @brief Returns uplink grant information required to permit
1622 * PHY to receive data
1626 * Function: rgSCHUtlAllocRcptInfo
1627 * Purpose: Given an uplink allocation, this function returns
1628 * uplink grant information which is needed by PHY to
1629 * decode data sent from UE. This information includes:
1634 * @param[in] RgSchUlAlloc *alloc
1635 * @param[out] uint8_t *rbStartRef
1636 * @param[out] uint8_t *numRbRef
1637 * @param[out] uint8_t *rvRef
1638 * @param[out] uint16_t *size
1639 * @param[out] TfuModScheme *modType
1640 * @param[out] Bool *isRtx
1641 * @param[out] uint8_t *nDmrs
1642 * @param[out] Bool *ndi
1643 * @param[out] uint8_t *hqPId
1646 S16 rgSCHUtlAllocRcptInfo
1648 RgSchUlAlloc *alloc,
1651 uint8_t *rbStartRef,
1655 TfuModScheme *modType,
1662 /* Modulation order for 16qam UEs would be
1663 * min(4,modulation order in grant). Please refer to 36.213-8.6.1*/
1664 CmLteUeCategory ueCtgy;
1666 #if (ERRCLASS & ERRCLS_DEBUG)
1667 if ((alloc == NULLP) || (alloc->hqProc == NULLP))
1673 if ( !alloc->forMsg3 )
1675 if ( ((alloc->ue) == NULLP) || (RG_SCH_CMN_GET_UE(alloc->ue, alloc->ue->cell) == NULLP))
1677 RLOG_ARG2(L_ERROR,DBG_CELLID,alloc->ue->cell->cellId,
1678 "Failed: ue->sch is null RNTI:%d,isRetx=%d",
1679 alloc->rnti, alloc->grnt.isRtx);
1682 ueCtgy = (RG_SCH_CMN_GET_UE_CTGY(alloc->ue));
1685 *iMcsRef = alloc->grnt.iMcs;
1686 *rbStartRef = alloc->grnt.rbStart;
1687 *numRbRef = alloc->grnt.numRb;
1688 *rvRef = rgRvTable[alloc->hqProc->rvIdx];
1689 *rnti = alloc->rnti;
1690 *size = alloc->grnt.datSz;
1691 *modType = (alloc->forMsg3)? alloc->grnt.modOdr:
1692 ((ueCtgy == CM_LTE_UE_CAT_5)?
1694 (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr)));
1695 *isRtx = alloc->grnt.isRtx;
1696 *nDmrs = alloc->grnt.nDmrs;
1697 *ndi = alloc->hqProc->ndi;
1698 *hqPId = alloc->hqProc->procId;
1704 * @brief Returns uplink grant information required to permit
1705 * PHY to receive data
1709 * Function: rgSCHUtlAllocRcptInfo
1710 * Purpose: Given an uplink allocation, this function returns
1711 * uplink grant information which is needed by PHY to
1712 * decode data sent from UE. This information includes:
1717 * @param[in] RgSchUlAlloc *alloc
1718 * @param[out] uint8_t *rbStartRef
1719 * @param[out] uint8_t *numRbRef
1720 * @param[out] uint8_t *rvRef
1721 * @param[out] uint16_t *size
1722 * @param[out] TfuModScheme *modType
1725 S16 rgSCHUtlAllocRcptInfo(RgSchCellCb *cell,RgSchUlAlloc *alloc,CmLteTimingInfo *timeInfo,TfuUeUlSchRecpInfo *recpReq)
1727 #if (ERRCLASS & ERRCLS_DEBUG)
1728 if ((alloc == NULLP) || (alloc->hqProc == NULLP))
1733 recpReq->size = alloc->grnt.datSz;
1734 recpReq->rbStart = alloc->grnt.rbStart;
1735 recpReq->numRb = alloc->grnt.numRb;
1736 /* Modulation order min(4,mod in grant) for 16 qam UEs.
1737 * Please refer to 36.213-8.6.1*/
1738 #ifdef FOUR_TX_ANTENNA
1739 recpReq->modType = (TfuModScheme)((alloc->forMsg3)?alloc->grnt.modOdr:
1740 (/*(alloc->ue->ueCatEnum == CM_LTE_UE_CAT_5)?
1741 alloc->grnt.modOdr: *//* Chandra:TmpFx-TM500 Cat5 with Only16QAM */
1742 (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr))));
1744 recpReq->modType = (TfuModScheme)((alloc->forMsg3)?alloc->grnt.modOdr:
1745 ((alloc->ue->ueCatEnum == CM_LTE_UE_CAT_5)?
1747 (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr))));
1749 recpReq->nDmrs = alloc->grnt.nDmrs;
1750 recpReq->hoppingEnbld = FALSE;
1751 recpReq->hoppingBits = 0;
1752 recpReq->isRtx = alloc->grnt.isRtx;
1753 recpReq->ndi = alloc->hqProc->ndi;
1754 recpReq->rv = rgRvTable[alloc->hqProc->rvIdx];
1756 recpReq->harqProcId = alloc->hqProc->procId;
1758 recpReq->harqProcId = rgSCHCmnGetUlHqProcIdx(timeInfo, cell);
1760 /* Transmission mode is SISO till Uplink MIMO is implemented. */
1761 recpReq->txMode = 0;
1762 /* This value needs to filled in in the case of frequency hopping. */
1763 recpReq->crntTxNb = 0;
1765 recpReq->mcs = alloc->grnt.iMcs;
1767 recpReq->rbgStart = alloc->grnt.vrbgStart;
1768 recpReq->numRbg = alloc->grnt.numVrbg;
1769 recpReq->xPUSCHRange = alloc->grnt.xPUSCHRange;
1770 //TODO_SID Need to check
1771 recpReq->nAntPortLayer = 0;
1772 recpReq->SCID = alloc->grnt.SCID;
1773 recpReq->PMI = alloc->grnt.PMI;
1774 recpReq->uciWoTBFlag = alloc->grnt.uciOnxPUSCH;
1777 recpReq->beamIndex = alloc->ue->ue5gtfCb.BeamId;
1782 if (!alloc->forMsg3)
1784 if (alloc->grnt.isRtx)
1786 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulRetxOccns++;
1790 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulTxOccns++;
1791 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulSumiTbs += \
1792 rgSCHCmnUlGetITbsFrmIMcs(alloc->grnt.iMcs);
1793 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulNumiTbs ++;
1794 cell->tenbStats->sch.ulSumiTbs += \
1795 rgSCHCmnUlGetITbsFrmIMcs(alloc->grnt.iMcs);
1796 cell->tenbStats->sch.ulNumiTbs ++;
1798 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulPrbUsg += alloc->grnt.numRb;
1799 cell->tenbStats->sch.ulPrbUsage[0] += alloc->grnt.numRb;
1802 /* ccpu00117050 - DEL - nSrs setting at rgSCHUtlAllocRcptInfo */
1809 * @brief This function initialises the PRACH slot occasions
1813 * Function: rgSCHUtlUpdPrachOcc
1814 * Purpose: This function updates the PRACH slots based on
1815 * RGR configuration.
1817 * Invoked by: Scheduler
1819 * @param[in] RgSchCellCb *cell
1820 * @param[in] RgrTddPrachInfo *cellCfg
1824 static Void rgSCHUtlUpdPrachOcc(RgSchCellCb *cell,RgrTddPrachInfo *cellCfg)
1832 /* In the 1st half frame */
1833 if(cellCfg->halfFrm == 0)
1838 /* In the 2nd half frame */
1844 for(idx = startIdx; idx < endIdx; idx++)
1846 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
1847 == RG_SCH_TDD_UL_slot)
1849 if(cellCfg->ulStartSfIdx == count)
1851 size = cell->rachCfg.raOccasion.size;
1852 cell->rachCfg.raOccasion.slotNum[size] = idx;
1853 cell->rachCfg.raOccasion.size++;
1863 * @brief This function initialises the PRACH occasions
1867 * Function: rgSCHUtlPrachCfgInit
1868 * Purpose: This function initialises the PRACH occasions based on
1869 * RGR configuration.
1871 * Invoked by: Scheduler
1873 * @param[in] RgSchCellCb *cell
1874 * @param[in] RgrCellCfg *cellCfg
1878 Void rgSCHUtlPrachCfgInit(RgSchCellCb *cell,RgrCellCfg *cellCfg)
1884 if(cellCfg->prachRscInfo.numRsc <= 0)
1886 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "Invalid"
1887 "PRACH resources Configuration ");
1891 /* Update SFN occasions */
1892 cell->rachCfg.raOccasion.sfnEnum =
1893 cellCfg->prachRscInfo.prachInfo[0].sfn;
1895 cell->rachCfg.raOccasion.size = 0;
1897 /* Update slot occasions */
1898 for(idx = 0; idx < cellCfg->prachRscInfo.numRsc; idx++)
1900 if(cellCfg->prachRscInfo.prachInfo[idx].freqIdx == 0)
1902 if(cellCfg->prachRscInfo.prachInfo[idx].halfFrm == 0)
1910 if(cellCfg->prachRscInfo.prachInfo[idx].ulStartSfIdx ==
1913 subfrmIdx = cell->rachCfg.raOccasion.size;
1914 cell->rachCfg.raOccasion.slotNum[subfrmIdx] = splFrm;
1915 cell->rachCfg.raOccasion.size++;
1919 rgSCHUtlUpdPrachOcc(cell,
1920 &cellCfg->prachRscInfo.prachInfo[idx]);
1928 * @brief This function performs RGR cell initialization
1932 * Function: rgSCHUtlRgrCellCfg
1933 * Purpose: This function initialises the cell with RGR configuration
1934 * and slot related initialization.
1936 * Invoked by: Scheduler
1938 * @param[in] RgSchCellCb *cell
1939 * @param[in] RgrCellCfg *cellCfg
1940 * @param[in] RgSchErrInfo *errInfo
1944 S16 rgSCHUtlRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *errInfo)
1950 CmLteTimingInfo frm;
1951 uint8_t ulDlCfgIdx = cellCfg->ulDlCfgIdx;
1955 uint16_t bw; /*!< Number of RBs in the cell */
1957 memset(&frm,0,sizeof(CmLteTimingInfo));
1959 /* ccpu00132657-MOD- Determining DLSF array size independent of DELTAS */
1960 maxDlslots = rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1961 maxslots = 2 * maxDlslots;
1962 cell->numDlSubfrms = maxslots;
1963 /* ACC-TDD <ccpu00130639> */
1964 cell->tddHqSfnCycle = -1;
1965 cell->ulDlCfgIdx = ulDlCfgIdx;
1967 /* PRACH Occasions Initialization */
1968 rgSCHUtlPrachCfgInit(cell, cellCfg);
1970 /* ccpu00132658- Moved out of below for loop since the updating rbgSize and
1971 * bw are independent of sfNum*/
1972 /* determine the RBG size and no of RBGs for the configured
1974 if (cell->bwCfg.dlTotalBw > 63)
1978 else if (cell->bwCfg.dlTotalBw > 26)
1982 else if (cell->bwCfg.dlTotalBw > 10)
1990 cell->noOfRbgs = RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize);
1992 bw = cell->bwCfg.dlTotalBw;
1994 rgSCHUtlAllocSBuf(cell->instIdx,
1995 (Data **)&cell->subFrms, sizeof(RgSchDlSf *) * maxslots);
1996 if (cell->subFrms == NULLP)
2001 /* Create memory for each frame. */
2002 for(i = 0; i < maxslots; i++)
2004 while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] ==
2007 sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES;
2010 rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf, sizeof(RgSchDlSf));
2015 memset(sf, 0, sizeof(*sf));
2018 if (ROK != rgSCHLaaInitDlSfCb(cell, sf))
2026 /* Mark SPS bandwidth to be occupied */
2027 sf->bwAlloced = ((cellCfg->spsCfg.maxSpsDlBw +
2028 cell->rbgSize - 1)/cell->rbgSize) * cell->rbgSize;
2029 sf->spsAllocdBw = 0;
2030 sf->type2End = sf->bwAlloced/cell->rbgSize;
2033 /* Fix for ccpu00123918*/
2035 #endif /* LTEMAC_SPS */
2036 /* Initialize the ackNakRepQ here */
2037 #ifdef RG_MAC_MEASGAP
2038 cmLListInit (&(sf->ackNakRepQ));
2040 cell->subFrms[i] = sf;
2041 sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES;
2047 /* ccpu00117052 - MOD - Passing double pointer
2048 for proper NULLP assignment*/
2049 rgSCHUtlFreeSBuf(cell->instIdx,
2050 (Data **)(&(cell->subFrms[i-1])), sizeof(RgSchDlSf));
2052 rgSCHLaaDeInitDlSfCb(cell, sf);
2055 /* ccpu00117052 - MOD - Passing double pointer
2056 for proper NULLP assignment*/
2057 rgSCHUtlFreeSBuf(cell->instIdx,
2058 (Data **)(&(cell->subFrms)), sizeof(RgSchDlSf *) * maxslots);
2063 if (cell->sc.apis == NULLP)
2065 cell->sc.apis = &rgSchCmnApis;
2067 ret = cell->sc.apis->rgSCHRgrCellCfg(cell, cellCfg, errInfo);
2071 /* ccpu00132286- Removed deletion of sf nodes as the deletion will be
2072 * happening during CellDelete. Added return handling to provide negative
2077 /* Release the slots and thereby perform the initialization */
2078 for (i = 0; i < maxslots; i++)
2080 if((i > 0) && (i%maxDlslots == 0))
2085 frm.slot = cell->subFrms[i]->sfNum;
2086 rgSCHUtlDlRlsSubFrm(cell, frm);
2095 * @brief This function performs scheduler related cell creation
2099 * Function: rgSCHUtlRgrCellCfg
2100 * Purpose: This function creates the slots needed for the
2101 * cell. It then peforms init of the scheduler by calling
2102 * scheduler specific cell init function.
2104 * Invoked by: Scheduler
2106 * @param[in] RgSchCellCb *cell
2107 * @param[in] RgrCellCfg *cellCfg
2108 * @param[in] RgSchErrInfo *errInfo
2112 S16 rgSCHUtlRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *errInfo)
2116 CmLteTimingInfo frm;
2118 Inst inst = cell->instIdx;
2119 /* LTE_ADV_FLAG_REMOVED_START */
2121 len = (uint16_t)((cell->bwCfg.dlTotalBw % 8 == 0) ? (cell->bwCfg.dlTotalBw/8) : (cell->bwCfg.dlTotalBw/8 + 1)); /*KW fix for LTE_ADV */
2122 /* LTE_ADV_FLAG_REMOVED_END */
2124 memset(&frm,0,sizeof(CmLteTimingInfo));
2126 /* determine the RBG size and no of RBGs for the configured
2128 if (cell->bwCfg.dlTotalBw > 63)
2132 else if (cell->bwCfg.dlTotalBw > 26)
2136 else if (cell->bwCfg.dlTotalBw > 10)
2144 cell->noOfRbgs = RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize);
2145 /* Create memory for each frame. */
2146 /* Changing loop limit from
2147 RGSCH_NUM_SUB_FRAMES to RGSCH_NUM_DL_slotS */
2148 for(i = 0; i < RGSCH_NUM_DL_slotS; i++)
2150 rgSCHUtlAllocSBuf(inst, (Data **)&sf, sizeof(RgSchDlSf));
2155 memset(sf, 0, sizeof(*sf));
2158 if (ROK != rgSCHLaaInitDlSfCb(cell, sf))
2163 /* Doing MOD operation before assigning value of i */
2164 sf->sfNum = i % RGSCH_NUM_SUB_FRAMES;
2165 sf->bw = cell->bwCfg.dlTotalBw;
2166 /* Initialize the ackNakRepQ here */
2167 #ifdef RG_MAC_MEASGAP
2168 cmLListInit (&(sf->ackNakRepQ));
2170 cell->subFrms[i] = sf;
2171 /* LTE_ADV_FLAG_REMOVED_START */
2172 if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
2174 /*initialize the RNTP Buffer*/
2175 if(rgSchDSFRRntpInfoInit(&sf->rntpInfo, cell, sf->bw))
2181 if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE)
2183 /*initialise the pools of CC and CE*/
2184 if(rgSchSFRTotalPoolInit(cell, sf))
2189 /* LTE_ADV_FLAG_REMOVED_END */
2192 /* LTE_ADV_FLAG_REMOVED_START */
2193 /* Allocate memory for "scheduled UE" Info */
2194 if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
2196 if((rgSCHUtlAllocSBuf(inst, (Data**)&(cell->rntpAggrInfo.val),
2197 (len * sizeof(uint8_t)))) != ROK)
2199 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED for RNTP Alloc");
2202 cell->rntpAggrInfo.pres = PRSNT_NODEF;
2203 cell->rntpAggrInfo.len = len;
2205 /* LTE_ADV_FLAG_REMOVED_END */
2207 /* Changing loop limit from
2208 RGSCH_NUM_SUB_FRAMES to RGSCH_NUM_DL_slotS */
2209 if (i != RGSCH_NUM_DL_slotS)
2213 /* ccpu00117052 - MOD - Passing double pointer
2214 for proper NULLP assignment*/
2215 rgSCHUtlFreeSBuf(inst, (Data **)(&(cell->subFrms[i-1])),
2218 rgSCHLaaDeInitDlSfCb(cell, sf);
2224 if (cell->sc.apis == NULLP)
2226 cell->sc.apis = &rgSchCmnApis;
2229 /* Release the slots and thereby perform the initialization */
2230 for (i = 0; i < RGSCH_NUM_DL_slotS; i++)
2232 if (i >= RGSCH_NUM_SUB_FRAMES)
2234 /* [ccpu00123828]-MOD-The below statement sfn += 1incorrectly modified
2235 * the value of sfn for i>=10 thru 19. Correct way is to assign
2239 frm.slot = i % RGSCH_NUM_SUB_FRAMES;
2240 rgSCHUtlDlRlsSubFrm(cell, frm);
2243 ret = cell->sc.apis->rgSCHRgrCellCfg(cell, cellCfg, errInfo);
2246 errInfo->errCause = RGSCHERR_SCH_CFG;
2250 if(cell->emtcEnable)
2252 /* TODO: Repetition framework in RGR and APP */
2253 if (rgSCHUtlEmtcResMngmtInit(
2255 RGSCH_IOT_PDSCH_POOLSZ, RGSCH_IOT_PDSCH_DELTA, cellCfg->bwCfg.dlTotalBw,
2256 RGSCH_IOT_PUSCH_POOLSZ, RGSCH_IOT_PUSCH_DELTA, RGSCH_IOT_PUSCH_MAXFREQSZ,
2257 RGSCH_IOT_PUCCH_POOLSZ, RGSCH_IOT_PUCCH_DELTA, RGSCH_IOT_PUCCH_MAXFREQSZ) != ROK)
2259 errInfo->errCause = RGSCHERR_SCH_CFG;
2271 * @brief This function performs the cell reconfiguration at RGR interface
2275 * Function: rgSCHUtlRgrCellRecfg
2276 * Purpose: This function updates the reconfigurable parameters
2277 * on the cell control block for the scheduler.
2279 * Invoked by: Scheduler
2281 * @param[in] RgSchCellCb *cell
2282 * @param[in] RgrCellCfg *cellCfg
2283 * @param[in] RgSchErrInfo *errInfo
2287 S16 rgSCHUtlRgrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
2289 return (cell->sc.apis->rgSCHRgrCellRecfg(cell, recfg, err));
2295 * @brief This function returns the Y value of UE for a sub frame
2299 * Function: rgSCHUtlFreeCell
2300 * Purpose: This function updates the value of Y stored in the
2301 * UE control block. It uses the previously computed
2302 * value for computing for this slot.
2304 * Invoked by: Scheduler
2306 * @param[in] RgSchCellCb *cell
2310 S16 rgSCHUtlFreeCell(RgSchCellCb *cell)
2315 RgSchPdcchInfo *pdcchInfo;
2316 RgSchPhichInfo *phichInfo;
2318 Inst inst = cell->instIdx;
2321 RgSchRaReqInfo *raReqInfo;
2326 maxslots = cell->numDlSubfrms;
2328 maxslots = RGSCH_NUM_DL_slotS;
2332 /* Invoke the index for scheduler, cell deletion */
2333 cell->sc.apis->rgSCHFreeCell(cell);
2335 /* Release the slots allocated */
2336 for (i = 0; i < maxslots; i++)
2339 rgSCHLaaDeInitDlSfCb(cell, cell->subFrms[i]);
2341 pdcchInfo = &cell->subFrms[i]->pdcchInfo;
2342 /* ccpu00117052 - MOD - Passing double pointer
2343 for proper NULLP assignment*/
2344 rgSCHUtlFreeSBuf(inst, (Data **)(&(pdcchInfo->map)),
2345 (pdcchInfo->nCce + 7) >> 3);
2346 while (pdcchInfo->pdcchs.first != NULLP)
2348 pdcch = (RgSchPdcch *)pdcchInfo->pdcchs.first->node;
2349 cmLListDelFrm(&pdcchInfo->pdcchs, pdcchInfo->pdcchs.first);
2350 /* ccpu00117052 - MOD - Passing double pointer
2351 for proper NULLP assignment*/
2352 rgSCHUtlFreeSBuf(inst, (Data **)&pdcch, sizeof(RgSchPdcch));
2355 phichInfo = &cell->subFrms[i]->phichInfo;
2356 while(phichInfo->phichs.first != NULLP)
2358 phich = (RgSchPhich *)phichInfo->phichs.first->node;
2359 cmLListDelFrm(&phichInfo->phichs, phichInfo->phichs.first);
2360 RGSCH_PHICH_FREE(inst, phich, sizeof(RgSchPhich));
2363 /* LTE_ADV_FLAG_REMOVED_START */
2364 /*releasing SFR pool entries*/
2365 rgSchSFRTotalPoolFree(&cell->subFrms[i]->sfrTotalPoolInfo, cell);
2367 /*releasing dsfr rntp pattern info*/
2368 rgSchDSFRRntpInfoFree(&cell->subFrms[i]->rntpInfo, cell,
2369 cell->bwCfg.dlTotalBw);
2370 /* LTE_ADV_FLAG_REMOVED_END */
2372 /* ccpu00117052 - MOD - Passing double pointer
2373 for proper NULLP assignment*/
2374 rgSCHUtlFreeSBuf(inst, (Data **)(&(cell->subFrms[i])), sizeof(RgSchDlSf));
2377 /* Release the slot pointers */
2378 /* ccpu00117052 - MOD - Passing double pointer
2379 for proper NULLP assignment*/
2380 rgSCHUtlFreeSBuf(inst,
2381 (Data **) (&(cell->subFrms)), sizeof(RgSchDlSf *) * maxslots);
2383 for(idx=0; idx < cell->raInfo.lstSize; idx++)
2385 lst = &cell->raInfo.raReqLst[idx];
2386 while (lst->first != NULLP)
2388 raReqInfo = (RgSchRaReqInfo *)lst->first->node;
2389 cmLListDelFrm(lst, &raReqInfo->raReqLstEnt);
2390 /* ccpu00117052 - MOD - Passing double pointer
2391 for proper NULLP assignment*/
2392 rgSCHUtlFreeSBuf(inst,(Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
2395 /* ccpu00117052 - MOD - Passing double pointer
2396 for proper NULLP assignment*/
2397 rgSCHUtlFreeSBuf(inst,
2398 (Data **)(&(cell->raInfo.raReqLst)),
2399 sizeof(CmLListCp) * (cell->raInfo.lstSize));
2402 /* Release allocated pdcchs */
2403 lst = &cell->pdcchLst;
2404 while (lst->first != NULLP)
2406 pdcch = (RgSchPdcch *)lst->first->node;
2407 cmLListDelFrm(lst, &pdcch->lnk);
2409 if(cell->emtcEnable)
2411 rgSCHEmtcPdcchFree(cell, pdcch);
2412 rgSCHUtlEmtcResMngmtDeinit(cell);
2415 /* ccpu00117052 - MOD - Passing double pointer
2416 for proper NULLP assignment*/
2417 rgSCHUtlFreeSBuf(inst,(Data **)&pdcch, sizeof(RgSchPdcch));
2420 rgSCHLaaFreeLists(cell);
2423 /* LTE_ADV_FLAG_REMOVED_START */
2424 /* releasing RNTP Aggregation Info from CellCb*/
2425 rgSchDSFRRntpInfoFree(&cell->rntpAggrInfo, cell, cell->bwCfg.dlTotalBw);
2426 /* LTE_ADV_FLAG_REMOVED_END */
2433 * @brief This function adds the UE to scheduler
2437 * Function: rgSCHUtlRgrUeCfg
2438 * Purpose: This function performs addition of UE to scheduler
2439 * 1. First, it updates the Y table in the UE
2440 * 2. Then, it calls the scheduler's handler for UE addition
2442 * Invoked by: Scheduler
2444 * @param[in] RgSchCellCb *cell
2445 * @param[in] RgSchUeCb *ue
2446 * @param[in] RgrUeCfg *cfg
2447 * @param[in] RgSchErrInfo *err
2451 S16 rgSCHUtlRgrUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *cfg,RgSchErrInfo *err)
2454 /* Assign TM 1 as UE's default TM */
2455 ue->mimoInfo.txMode = RGR_UE_TM_1;
2456 ue->txModeTransCmplt = TRUE;
2457 cmInitTimers(&ue->txModeTransTmr, 1);
2458 if (cfg->txMode.pres == PRSNT_NODEF)
2460 /* DL MU-MIMO not supported */
2461 if (cfg->txMode.txModeEnum == RGR_UE_TM_5)
2463 err->errCause = RGSCHERR_SCH_CFG;
2466 ue->mimoInfo.txMode = cfg->txMode.txModeEnum;
2468 ue->ul.ulTxAntSel = cfg->ulTxAntSel;
2469 ue->mimoInfo.cdbkSbstRstrctn = cfg->ueCodeBookRstCfg;
2471 ue->ueCatEnum = cfg->ueCatEnum;
2472 if ((cfg->puschDedCfg.bACKIdx > 15) ||
2473 (cfg->puschDedCfg.bCQIIdx > 15) ||
2474 (cfg->puschDedCfg.bRIIdx > 15))
2476 err->errCause = RGSCHERR_SCH_CFG;
2479 ue->ul.betaHqOffst = cfg->puschDedCfg.bACKIdx;
2480 ue->ul.betaCqiOffst = cfg->puschDedCfg.bCQIIdx;
2481 ue->ul.betaRiOffst = cfg->puschDedCfg.bRIIdx;
2483 ue->csgMmbrSta = cfg->csgMmbrSta;
2485 memset(&ue->pfsStats, 0, sizeof(RgSchPfsStats));
2487 /* Call the handler of the scheduler based on cell configuration */
2488 return (cell->sc.apis->rgSCHRgrUeCfg(cell, ue, cfg, err));
2490 /* Start : LTEMAC_2.1_DEV_CFG */
2493 * @brief This function adds a service to scheduler
2497 * Function: rgSCHUtlRgrLcCfg
2498 * Purpose: This function performs addition of service to scheduler
2499 * The addition is performed for each direction based
2500 * the direction field of the configuration
2502 * Invoked by: Scheduler
2504 * @param[in] RgSchCellCb *cell
2505 * @param[in] RgSchUeCb *ue
2506 * @param[in] RgSchDlLcCb *dlLc
2507 * @param[in] RgrLchCfg *cfg
2508 * @param[in] RgSchErrInfo *err
2512 S16 rgSCHUtlRgrLcCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchCfg *cfg,RgSchErrInfo *errInfo)
2514 return (cell->sc.apis->rgSCHRgrLchCfg(cell, ue, dlLc, cfg, errInfo));
2519 * @brief This function modifies a service to scheduler
2523 * Function: rgSCHUtlRgrLcRecfg
2524 * Purpose: This function performs modification of a service in
2525 * scheduler. The modification is performed for each direction
2526 * based the direction field of the configuration
2528 * Invoked by: Scheduler
2530 * @param[in] RgSchCellCb *cell
2531 * @param[in] RgSchUeCb *ue
2532 * @param[in] RgSchDlLcCb *dlLc
2533 * @param[in] RgrLchRecfg *recfg
2534 * @param[in] RgSchErrInfo *err
2538 S16 rgSCHUtlRgrLcRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchRecfg *recfg,RgSchErrInfo *err)
2540 return (cell->sc.apis->rgSCHRgrLchRecfg(cell, ue, dlLc, recfg, err));
2544 * @brief This function deletes a Lc in scheduler
2548 * Function: rgSCHUtlRgrLcDel
2549 * Purpose: This function performs deletion of Lc in scheduler
2551 * Invoked by: Scheduler
2553 * @param[in] RgSchCellCb *cell
2554 * @param[in] RgSchUeCb *ue
2555 * @param[in] CmLteLcId lcId
2556 * @param[in] uint8_t lcgId
2560 S16 rgSCHUtlRgrLcDel(RgSchCellCb *cell,RgSchUeCb *ue,CmLteLcId lcId,uint8_t lcgId)
2562 cell->sc.apis->rgSCHRgrLchDel(cell, ue, lcId, lcgId);
2565 } /* rgSCHUtlRgrLcDel */
2568 * @brief This function adds a service to scheduler
2572 * Function: rgSCHUtlRgrLcgCfg
2573 * Purpose: This function performs addition of service to scheduler
2574 * The addition is performed for each direction based
2575 * the direction field of the configuration
2577 * Invoked by: Scheduler
2579 * @param[in] RgSchCellCb *cell
2580 * @param[in] RgSchUeCb *ue
2581 * @param[in] RgrLchCfg *cfg
2582 * @param[in] RgSchErrInfo *err
2586 S16 rgSCHUtlRgrLcgCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrLcgCfg *cfg,RgSchErrInfo *errInfo)
2588 return (cell->sc.apis->rgSCHRgrLcgCfg(cell, ue, &(ue->ul.lcgArr[cfg->ulInfo.lcgId]), cfg, errInfo));
2593 * @brief This function modifies a service to scheduler
2597 * Function: rgSCHUtlRgrLcgRecfg
2598 * Purpose: This function performs modification of a service in
2599 * scheduler. The modification is performed for each direction
2600 * based the direction field of the configuration
2602 * Invoked by: Scheduler
2604 * @param[in] RgSchCellCb *cell
2605 * @param[in] RgSchUeCb *ue
2606 * @param[in] RgrLcgRecfg *recfg
2607 * @param[in] RgSchErrInfo *err
2611 S16 rgSCHUtlRgrLcgRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrLcgRecfg *recfg,RgSchErrInfo *err)
2613 return (cell->sc.apis->rgSCHRgrLcgRecfg(cell, ue, &(ue->ul.lcgArr[recfg->ulRecfg.lcgId]), recfg, err));
2614 } /* rgSCHUtlRgrLcRecfg */
2617 * @brief This function modifies a service to scheduler
2621 * Function: rgSCHUtlRgrLcgDel
2622 * Purpose: This function performs modification of a service in
2623 * scheduler. The modification is performed for each direction
2624 * based the direction field of the configuration
2626 * Invoked by: Scheduler
2628 * @param[in] RgSchCellCb *cell
2629 * @param[in] RgSchUeCb *ue
2630 * @param[in] RgrDel *lcDelInfo
2634 Void rgSCHUtlRgrLcgDel(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId)
2636 cell->sc.apis->rgSCHFreeLcg(cell, ue, &ue->ul.lcgArr[lcgId]);
2638 /* Stack Crash problem for TRACE5 changes. added the return below . */
2641 } /* rgSCHUtlRgrLcgDel */
2644 /* End: LTEMAC_2.1_DEV_CFG */
2647 * @brief This function is a wrapper to call scheduler specific API.
2651 * Function: rgSCHUtlDoaInd
2652 * Purpose: Updates the DOA for the UE
2656 * @param[in] RgSchCellCb *cell
2657 * @param[in] RgSchUeCb *ue
2658 * @param[in] TfuDoaRpt *doaRpt
2662 Void rgSCHUtlDoaInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuDoaRpt *doaRpt)
2664 ue->mimoInfo.doa.pres = PRSNT_NODEF;
2665 ue->mimoInfo.doa.val = doaRpt->doa;
2670 * @brief This function is a wrapper to call scheduler specific API.
2674 * Function: rgSCHUtlDlCqiInd
2675 * Purpose: Updates the DL CQI for the UE
2679 * @param[in] RgSchCellCb *cell
2680 * @param[in] RgSchUeCb *ue
2681 * @param[in] TfuDlCqiRpt *dlCqiRpt
2682 * @param[in] CmLteTimingInfo timingInfo
2686 Void rgSCHUtlDlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuDlCqiRpt *dlCqiRpt,CmLteTimingInfo timingInfo)
2688 RgSchCellCb *sCellCb = NULLP;
2689 if (dlCqiRpt->isPucchInfo)
2691 sCellCb = ue->cellInfo[dlCqiRpt->dlCqiInfo.pucchCqi.cellIdx]->cell;
2692 sCellCb->sc.apis->rgSCHDlCqiInd(sCellCb, ue, dlCqiRpt->isPucchInfo, \
2693 (Void *)&dlCqiRpt->dlCqiInfo.pucchCqi, timingInfo);
2698 for (idx = 0; idx < dlCqiRpt->dlCqiInfo.pusch.numOfCells; idx++)
2700 sCellCb = ue->cellInfo[dlCqiRpt->dlCqiInfo.pusch.puschCqi[idx].cellIdx]->cell;
2701 sCellCb->sc.apis->rgSCHDlCqiInd(sCellCb, ue, dlCqiRpt->isPucchInfo, \
2702 (Void *)&dlCqiRpt->dlCqiInfo.pusch.puschCqi[idx], timingInfo);
2711 * @brief This function is a wrapper to call scheduler specific API.
2715 * Function: rgSCHUtlSrsInd
2716 * Purpose: Updates the UL SRS for the UE
2720 * @param[in] RgSchCellCb *cell
2721 * @param[in] RgSchUeCb *ue
2722 * @param[in] TfuSrsRpt* srsRpt
2723 * @param[in] CmLteTimingInfo timingInfo
2727 Void rgSCHUtlSrsInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuSrsRpt *srsRpt,CmLteTimingInfo timingInfo)
2729 cell->sc.apis->rgSCHSrsInd(cell, ue, srsRpt, timingInfo);
2735 * @brief This function is a wrapper to call scheduler specific API.
2739 * Function: rgSCHUtlDlTARpt
2740 * Purpose: Reports PHY TA for a UE.
2744 * @param[in] RgSchCellCb *cell
2745 * @param[in] RgSchUeCb *ue
2749 Void rgSCHUtlDlTARpt(RgSchCellCb *cell,RgSchUeCb *ue)
2751 cell->sc.apis->rgSCHDlTARpt(cell, ue);
2757 * @brief This function is a wrapper to call scheduler specific API.
2761 * Function: rgSCHUtlDlRlsSubFrm
2762 * Purpose: Releases scheduler Information from DL SubFrm.
2766 * @param[in] RgSchCellCb *cell
2767 * @param[out] CmLteTimingInfo subFrm
2771 Void rgSCHUtlDlRlsSubFrm(RgSchCellCb *cell,CmLteTimingInfo subFrm)
2773 cell->sc.apis->rgSCHDlRlsSubFrm(cell, subFrm);
2779 * @brief This API is invoked to update the AperCQI trigger
2784 * Function : rgSCHUtlUpdACqiTrigWt
2785 * - If HqFdbk is ACK then add up weight corresponding
2786 * to ACK to the AcqiTrigWt.
2787 * - If HqFdbk is NACK then add up weight corresponding
2788 * to NACK to the AcqiTrigWt.
2789 * - If AcqiTrigWt crosses threshold then trigger
2790 * grant req for APERCQI to SCH.
2792 * @param[in] RgSchUeCb *ue
2793 * @param[in] uint8_t isAck
2797 Void rgSCHUtlUpdACqiTrigWt(RgSchUeCb *ue,RgSchUeCellInfo *cellInfo,uint8_t isAck )
2800 uint8_t triggerSet = 0;
2804 if (isAck == TFU_HQFDB_ACK)
2806 cellInfo->acqiCb.aCqiTrigWt += RG_APER_CQI_ACK_WGT;
2810 cellInfo->acqiCb.aCqiTrigWt += RG_APER_CQI_NACK_WGT;
2813 if (cellInfo->acqiCb.aCqiTrigWt > RG_APER_CQI_THRESHOLD_WGT)
2815 RgSchCellCb *cell = ue->cell;
2816 RgSchErrInfo unUsed;
2818 if(ue->dl.reqForCqi)
2820 /* Already one ACQI trigger procedure is going on
2821 * which is not yet satisfied. Delaying this request till
2822 * the previous is getting satisfied*/
2826 ue->dl.reqForCqi = TRUE;
2828 rgSchCmnSetCqiReqField(cellInfo,ue,&ue->dl.reqForCqi);
2829 //Reset aCqiTrigWt for all the serving cells for which we have triggered ACQI
2830 rgSCHTomUtlGetTrigSet(cell, ue, ue->dl.reqForCqi, &triggerSet);
2831 for (sIdx = 0; sIdx < CM_LTE_MAX_CELLS; sIdx++)
2833 /* The Aperiodic requested for SCell index sIdx */
2834 if ((triggerSet >> (7 - sIdx)) & 0x01)
2836 /* The Aperiodic request for SCell index sIdx */
2837 ue->cellInfo[sIdx]->acqiCb.aCqiTrigWt = 0;
2842 /* Force SCH to send UL grant by indicating fake SR.
2843 * If this UE already in UL SCH Qs this SR Ind will
2845 rgSCHUtlSrRcvd(cell, ue, cell->crntTime, &unUsed);
2853 * @brief This API is invoked to indicate scheduler of a CRC indication.
2857 * Function : rgSCHUtlHdlUlTransInd
2858 * This API is invoked to indicate scheduler of a CRC indication.
2860 * @param[in] RgSchCellCb *cell
2861 * @param[in] RgSchUeCb *ue
2862 * @param[in] CmLteTimingInfo timingInfo
2866 Void rgSCHUtlHdlUlTransInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2868 cell->sc.apis->rgSCHHdlUlTransInd(cell, ue, timingInfo);
2873 * @brief This API is invoked to indicate scheduler of a CRC failure.
2877 * Function : rgSCHUtlHdlCrcInd
2878 * This API is invoked to indicate CRC to scheduler.
2880 * @param[in] RgSchCellCb *cell
2881 * @param[in] RgSchUeCb *ue
2882 * @param[in] CmLteTimingInfo timingInfo
2886 Void rgSCHUtlHdlCrcInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2888 cell->sc.apis->rgSCHUlCrcInd(cell, ue, timingInfo);
2890 } /* end of rgSCHUtlHdlCrcFailInd */
2893 * @brief This API is invoked to indicate scheduler of a CRC failure.
2897 * Function : rgSCHUtlHdlCrcFailInd
2898 * This API is invoked to indicate CRC failure to scheduler.
2900 * @param[in] RgSchCellCb *cell
2901 * @param[in] RgSchUeCb *ue
2902 * @param[in] CmLteTimingInfo timingInfo
2906 Void rgSCHUtlHdlCrcFailInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2908 cell->sc.apis->rgSCHUlCrcFailInd(cell, ue, timingInfo);
2910 } /* end of rgSCHUtlHdlCrcFailInd */
2911 #endif /* LTEMAC_SPS */
2915 * @brief This function is a wrapper to call scheduler specific API.
2919 * Function: rgSCHUtlDlProcAddToRetx
2920 * Purpose: This function adds a HARQ process to retransmission
2921 * queue. This may be performed when a HARQ ack is
2924 * Invoked by: HARQ feedback processing
2926 * @param[in] RgSchCellCb* cell
2927 * @param[in] RgSchDlHqProc* hqP
2931 Void rgSCHUtlDlProcAddToRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
2933 cell->sc.apis->rgSCHDlProcAddToRetx(cell, hqP);
2939 * @brief This function adds a HARQ process TB to transmission
2943 * Function: rgSCHUtlDlHqPTbAddToTx
2944 * Purpose: This function a HarqProcess TB to the slot
2947 * Invoked by: Scheduler
2949 * @param[in] RgSubFrm* subFrm
2950 * @param[in] RgDlHqProc* hqP
2951 * @param[in] uint8_t tbIdx
2955 Void rgSCHUtlDlHqPTbAddToTx(RgSchDlSf *subFrm,RgSchDlHqProcCb *hqP,uint8_t tbIdx)
2957 RgSchUeCb *ue = NULLP;
2958 RgSchCellCb *cell = hqP->hqE->cell;
2960 /* Addition of UE to dlSf->ueLst shall be done only to UE's PCell */
2961 /* ue->cell will always hold PCell information */
2962 if (NULLP == hqP->hqPSfLnk.node)
2967 if(NULLP == ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node)
2969 ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node = (PTR)ue;
2970 cmLListAdd2Tail(&cell->subFrms[subFrm->dlIdx]->ueLst,
2971 &ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk);
2973 ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].isPuschHarqRecpPres = FALSE;
2977 /* Add Hq proc in particular dlIdx List for this UE
2978 This list will be used while processing feedback*/
2979 hqP->hqPSfLnk.node = (PTR)hqP;
2980 cmLListAdd2Tail(&ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].hqPLst,&hqP->hqPSfLnk);
2983 uint32_t gSCellSchedCount,gPrimarySchedCount;
2984 if(RG_SCH_IS_CELL_SEC(hqP->hqE->ue,hqP->hqE->cell))
2988 gPrimarySchedCount++;
2992 else if (hqP->hqE->msg4Proc == hqP)
2994 /* Msg4 will be scheduled on PCELL only hence add directly to subFrm msg4HqpList */
2995 hqP->hqPSfLnk.node = (PTR)hqP;
2996 cmLListAdd2Tail(&subFrm->msg4HqPLst, &hqP->hqPSfLnk);
3003 if((ue) && (HQ_TB_WAITING == hqP->tbInfo[tbIdx].state))
3006 ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].totalTbCnt++;
3008 /*totalTbCnt will hold the total number of TBs across all harq Proc from all
3011 hqP->subFrm = subFrm;
3020 * @brief This function removes a HARQ process TB from transmission
3024 * Function: rgSCHUtlDlHqPTbRmvFrmTx
3025 * Purpose: This function removes a HarqProcess TB to the slot
3028 * Invoked by: Scheduler
3030 * @param[in] RgSubFrm* subFrm
3031 * @param[in] RgDlHqProc* hqP
3032 * @param[in] uint8_t tbIdx
3033 * @param[in] Bool isRepeting
3037 Void rgSCHUtlDlHqPTbRmvFrmTx(RgSchDlSf *subFrm,RgSchDlHqProcCb *hqP,uint8_t tbIdx,Bool isRepeting)
3039 RgSchCellCb *cell = NULLP;
3040 /* Check with TDD */
3042 (hqP->hqE->ue->ackNakRepCb.cfgRepCnt !=
3043 hqP->tbInfo[tbIdx].fbkRepCntr))
3045 cmLListDelFrm(&subFrm->ackNakRepQ,
3046 &hqP->tbInfo[tbIdx].anRepLnk[hqP->tbInfo[tbIdx].fbkRepCntr]);
3050 if (NULLP != hqP->hqPSfLnk.node)
3053 if (hqP->hqE->msg4Proc == hqP)
3055 /* Msg4 will be scheduled on PCELL only hence delete directly from subFrm msg4HqpList */
3056 cmLListDelFrm(&subFrm->msg4HqPLst, &hqP->hqPSfLnk);
3060 cell = hqP->hqE->cell;
3061 /* Addition of UE to dlSf->ueLst shall be done only to UE's PCell */
3062 /* ue->cell will always hold PCell information */
3063 cmLListDelFrm(&hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].hqPLst,&hqP->hqPSfLnk);
3064 if (0 == hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].hqPLst.count)
3067 cmLListDelFrm(&cell->subFrms[subFrm->dlIdx]->ueLst,
3068 &hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk);
3069 hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node = (PTR)NULLP;
3070 hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].totalTbCnt = 0;
3073 hqP->hqPSfLnk.node = NULLP;
3075 hqP->subFrm = NULLP;
3082 * @brief Handler for accessing the existing SCellCb identified by the key
3083 * SCellId under the CellCb.
3087 * Function : rgSchUtlGetCellCb
3090 * @param[in] *cellCb
3092 * @return RgSchUeCb*
3094 RgSchCellCb* rgSchUtlGetCellCb(Inst inst,uint16_t cellId)
3096 RgSchCellCb *cellCb = NULLP;
3098 strtCellId = rgSchCb[inst].genCfg.startCellId;
3099 cellCb = rgSchCb[inst].cells[cellId - strtCellId];
3103 } /* rgSchUtlGetCellCb */
3106 * @brief Handler for deriving the servCellidx
3110 * Function : rgSchUtlGetServCellIdx
3113 * @param[in] *cellId
3114 * @param[in] RgSchUeCb *ue
3115 * @return uint8_t servCellIdx
3117 uint8_t rgSchUtlGetServCellIdx(Inst inst, uint16_t cellId, RgSchUeCb *ue)
3119 uint8_t servCellIdx;
3120 uint16_t strtCellId;
3122 strtCellId = rgSchCb[inst].genCfg.startCellId;
3123 servCellIdx = ue->cellIdToCellIdxMap[cellId - strtCellId];
3124 return (servCellIdx);
3126 } /* rgSchUtlGetCellCb */
3129 * @brief Handler for validating the Cell Id received secondary Cell Addition
3133 * Function : rgSchUtlGetCellId
3136 * @param[in] *cellCb
3138 * @return RgSchUeCb*
3140 S16 rgSchUtlVldtCellId(Inst inst,uint16_t cellId)
3144 strtCellId = rgSchCb[inst].genCfg.startCellId;
3145 if((cellId >= strtCellId) && ((cellId - strtCellId) < CM_LTE_MAX_CELLS))
3150 } /* rgSchUtlVldtCellId */
3154 * @brief UE reconfiguration for scheduler
3158 * Function : rgSCHUtlRgrUeRecfg
3160 * This functions updates UE specific scheduler
3161 * information upon UE reconfiguration
3163 * @param[in] RgSchCellCb *cell
3164 * @param[in] RgSchUeCb *ue
3165 * @param[int] RgrUeRecfg *ueRecfg
3166 * @param[out] RgSchErrInfo *err
3171 S16 rgSCHUtlRgrUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
3173 /* Changes for UE Category Reconfiguration feature addition */
3174 RgSchCmnUe *ueSch = RG_SCH_CMN_GET_UE(ue, cell);
3176 /* Changes for UE Category Reconfiguration feature addition */
3177 if (ueRecfg->ueRecfgTypes & RGR_UE_UECAT_RECFG)
3179 ueSch->cmn.ueCat = ueRecfg->ueCatEnum-1;
3181 ue->ueCatEnum = ueRecfg->ueCatEnum;
3185 /* DL MU-MIMO not supported */
3186 if (ueRecfg->ueRecfgTypes & RGR_UE_TXMODE_RECFG)
3189 if (ueRecfg->txMode.pres == PRSNT_NODEF)
3191 if (ueRecfg->txMode.txModeEnum == RGR_UE_TM_5)
3193 err->errCause = RGSCHERR_SCH_CFG;
3197 if(ue->mimoInfo.txMode != ueRecfg->txMode.txModeEnum)
3199 /* Decremnt the previos A value for this cell */
3200 ue->f1bCsAVal -= rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode);
3201 /* Update A value with the new TM Mode */
3202 ue->f1bCsAVal += rgSCHUtlGetMaxTbSupp(ueRecfg->txMode.txModeEnum);
3205 RLOG1(L_INFO,"UeReCfg A valie is %d\n",ue->f1bCsAVal);
3208 ue->mimoInfo.txMode = ueRecfg->txMode.txModeEnum;
3212 /* [ccpu00123958]-ADD- Check for PUSCH related Reconfig from the bit mask */
3213 if(ueRecfg->ueRecfgTypes & RGR_UE_PUSCH_RECFG)
3215 /* Fix: ccpu00124012 */
3216 /* TODO:: Need to check if this is
3217 mandatory to be re-configured on UE category re-configuration */
3218 /* ue->ul.betaHqOffst = ueRecfg->puschDedCfg.bACKIdx;
3219 ue->ul.betaCqiOffst = ueRecfg->puschDedCfg.bCQIIdx;
3220 ue->ul.betaRiOffst = ueRecfg->puschDedCfg.bRIIdx;*/
3223 if (ueRecfg->ueRecfgTypes & RGR_UE_ULTXANTSEL_RECFG)
3225 ue->ul.ulTxAntSel = ueRecfg->ulTxAntSel;
3227 if (ueRecfg->ueRecfgTypes & RGR_UE_CDBKSBST_RECFG)
3229 ue->mimoInfo.cdbkSbstRstrctn = ueRecfg->ueCodeBookRstRecfg;
3232 /* Commenting here to assign garbage value when it is not set in APP. */
3233 //ue->accessStratumRls = ueRecfg->accessStratumRls;
3234 return (cell->sc.apis->rgSCHRgrUeRecfg(cell, ue, ueRecfg, err));
3235 } /* rgSCHUtlRgrUeRecfg */
3238 * @brief This function deletes a service from scheduler
3242 * Function: rgSCHUtlFreeDlLc
3243 * Purpose: This function is made available through a FP for
3244 * making scheduler aware of a service being deleted from UE
3246 * Invoked by: BO and Scheduler
3248 * @param[in] RgSchCellCb* cell
3249 * @param[in] RgSchUeCb* ue
3250 * @param[in] RgSchDlLcCb* svc
3253 Void rgSCHUtlFreeDlLc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3255 cell->sc.apis->rgSCHFreeDlLc(cell, ue, svc);
3257 /* Stack Crash problem for TRACE5 changes. added the return below . */
3263 * @brief UE deletion for scheduler
3267 * Function : rgSCHUtlFreeUe
3269 * This functions deletes all scheduler information
3270 * pertaining to a UE
3272 * @param[in] RgSchCellCb *cell
3273 * @param[in] RgSchUeCb *ue
3276 Void rgSCHUtlFreeUe(RgSchCellCb *cell,RgSchUeCb *ue)
3279 rgSCHUtlDelUeANFdbkInfo(ue,RGSCH_PCELL_INDEX);
3281 cell->sc.apis->rgSCHFreeUe(cell, ue);
3283 /* Stack Crash problem for TRACE5 changes. added the return below . */
3286 } /* rgSCHUtlFreeUe */
3289 * @brief This function updates the scheduler with service for a UE
3293 * Function: rgSCHUtlDlDedBoUpd
3294 * Purpose: This function should be called whenever there is a
3295 * change BO for a service.
3297 * Invoked by: BO and Scheduler
3299 * @param[in] RgSchCellCb* cell
3300 * @param[in] RgSchUeCb* ue
3301 * @param[in] RgSchDlLcCb* lc
3304 Void rgSCHUtlDlDedBoUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *lc)
3306 cell->sc.apis->rgSCHDlDedBoUpd(cell, ue, lc);
3310 * @brief Record MSG3 allocation into the UE
3314 * Function : rgSCHUtlRecMsg3Alloc
3316 * This function is invoked to update record msg3 allocation information
3317 * in the UE when UE is detected for RaCb
3319 * @param[in] RgSchCellCb *cell
3320 * @param[in] RgSchUeCb *ue
3321 * @param[in] RgSchRaCb *raCb
3324 Void rgSCHUtlRecMsg3Alloc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchRaCb *raCb)
3326 cell->sc.apis->rgSCHUlRecMsg3Alloc(cell, ue, raCb);
3329 } /* rgSCHRecMsg3Alloc */
3333 * @brief Update harq process for allocation
3337 * Function : rgSCHUtlUpdUlHqProc
3339 * This function is invoked when harq process
3340 * control block is now in a new memory location
3341 * thus requiring a pointer/reference update.
3343 * @param[in] RgSchCellCb *cell
3344 * @param[in] RgSchUlHqProcCb *curProc
3345 * @param[in] RgSchUlHqProcCb *oldProc
3350 S16 rgSCHUtlUpdUlHqProc(RgSchCellCb *cell,RgSchUlHqProcCb *curProc,RgSchUlHqProcCb *oldProc)
3352 return (cell->sc.apis->rgSCHUpdUlHqProc(cell, curProc, oldProc));
3353 } /* rgSCHUtlUpdUlHqProc */
3356 * @brief UL grant for contention resolution
3360 * Function : rgSCHUtlContResUlGrant
3362 * Add UE to another queue specifically for CRNTI based contention
3365 * @param[in] RgSchCellCb *cell
3366 * @param[in] RgSchUeCb *ue
3367 * @param[out] RgSchErrInfo *err
3372 S16 rgSCHUtlContResUlGrant(RgSchCellCb *cell,RgSchUeCb *ue,RgSchErrInfo *err)
3375 ue->isMsg4PdcchWithCrnti = TRUE;
3376 return (cell->sc.apis->rgSCHContResUlGrant(cell, ue, err));
3377 } /* rgSCHUtlContResUlGrant */
3380 * @brief SR reception handling
3384 * Function : rgSCHUtlSrRcvd
3386 * - Handles SR reception for UE
3388 * @param[in] RgSchCellCb *cell
3389 * @param[in] RgSchUeCb *ue
3390 * @param[out] RgSchErrInfo *err
3395 S16 rgSCHUtlSrRcvd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo frm,RgSchErrInfo *err)
3397 return (cell->sc.apis->rgSCHSrRcvd(cell, ue, frm, err));
3398 } /* rgSCHUtlSrRcvd */
3401 * @brief Short BSR update
3405 * Function : rgSCHUtlUpdBsrShort
3407 * This functions does requisite updates to handle short BSR reporting
3409 * @param[in] RgSchCellCb *cell
3410 * @param[in] RgSchUeCb *ue
3411 * @param[in] uint8_t lcgId
3412 * @param[in] uint8_t bsr
3413 * @param[out] RgSchErrInfo *err
3418 Void rgSCHUtlUpdBsrShort(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId,uint8_t bsr,RgSchErrInfo *err)
3420 cell->sc.apis->rgSCHUpdBsrShort(cell, ue, &ue->ul.lcgArr[lcgId], bsr, err);
3422 } /* rgSCHUtlUpdBsrShort */
3426 * @brief Truncated BSR update
3430 * Function : rgSCHUtlUpdBsrTrunc
3432 * This functions does required updates to handle truncated BSR report
3435 * @param[in] RgSchCellCb *cell
3436 * @param[in] RgSchUeCb *ue
3437 * @param[in] uint8_t lcgId
3438 * @param[in] uint8_t bsr
3439 * @param[out] RgSchErrInfo *err
3444 Void rgSCHUtlUpdBsrTrunc(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId,uint8_t bsr,RgSchErrInfo *err)
3446 cell->sc.apis->rgSCHUpdBsrTrunc(cell, ue, &ue->ul.lcgArr[lcgId], bsr, err);
3448 } /* rgSCHUtlUpdBsrTrunc */
3452 * @brief Long BSR update
3456 * Function : rgSCHUtlUpdBsrLong
3458 * - Update BSRs for all configured LCGs
3459 * - Update priority of LCGs if needed
3460 * - Update UE's position within/across uplink scheduling queues
3463 * @param[in] RgSchCellCb *cell
3464 * @param[in] RgSchUeCb *ue
3465 * @param[in] uint8_t bsr0
3466 * @param[in] uint8_t bsr1
3467 * @param[in] uint8_t bsr2
3468 * @param[in] uint8_t bsr3
3469 * @param[out] RgSchErrInfo *err
3474 Void rgSCHUtlUpdBsrLong(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t bsr0,uint8_t bsr1,uint8_t bsr2,uint8_t bsr3,RgSchErrInfo *err)
3481 cell->sc.apis->rgSCHUpdBsrLong(cell, ue, bsArr, err);
3483 } /* rgSCHUtlUpdBsrLong */
3486 * @brief EXT PHR update
3490 * Function : rgSCHUtlUpdExtPhr
3492 * Updates extended power headroom info for a UE
3494 * @param[in] RgSchCellCb *cell
3495 * @param[in] RgSchUeCb *ue
3496 * @param[in] uint8_t phr
3497 * @param[out] RgSchErrInfo *err
3502 S16 rgSCHUtlUpdExtPhr(RgSchCellCb *cell,RgSchUeCb *ue,RgInfExtPhrCEInfo *extPhr,RgSchErrInfo *err)
3504 return (cell->sc.apis->rgSCHUpdExtPhr(cell, ue, extPhr, err));
3505 } /* rgSCHUtlUpdExtPhr */
3514 * Function : rgSCHUtlUpdPhr
3516 * Updates power headroom info for a UE
3518 * @param[in] RgSchCellCb *cell
3519 * @param[in] RgSchUeCb *ue
3520 * @param[in] uint8_t phr
3521 * @param[out] RgSchErrInfo *err
3526 S16 rgSCHUtlUpdPhr(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t phr,RgSchErrInfo *err)
3528 return (cell->sc.apis->rgSCHUpdPhr(cell, ue, phr, err));
3529 } /* rgSCHUtlUpdPhr */
3533 * @brief Indication of UL CQI
3537 * Function : rgSCHUtlUlCqiInd
3539 * - Updates uplink CQI information for the UE. Computes and
3540 * stores the lowest CQI of CQIs reported in all subbands
3542 * @param[in] RgSchCellCb *cell
3543 * @param[in] RgSchUeCb *ue
3544 * @param[in] TfuUlCqiRpt *ulCqiInfo
3547 Void rgSCHUtlUlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuUlCqiRpt *ulCqiInfo)
3549 cell->sc.apis->rgSCHUlCqiInd(cell, ue, ulCqiInfo);
3551 } /* rgSCHUtlUlCqiInd */
3554 * @brief Indication of PUCCH power adjustment
3558 * Function : rgSCHUtlPucchDeltaPwrInd
3560 * - Updates uplink CQI information for the UE. Computes and
3561 * stores the lowest CQI of CQIs reported in all subbands
3563 * @param[in] RgSchCellCb *cell
3564 * @param[in] RgSchUeCb *ue
3565 * @param[in] uint8_t delta
3568 Void rgSCHUtlPucchDeltaPwrInd(RgSchCellCb *cell,RgSchUeCb *ue,S8 delta)
3570 cell->sc.apis->rgSCHPucchDeltaPwrInd(cell, ue, delta);
3572 } /* rgSCHUtlPucchDeltaPwrInd */
3574 /* Start: LTEMAC_2.1_DEV_CFG */
3576 * @brief Ue Reset Request
3580 * Function : rgSCHUtlUeReset
3583 * @param[in] RgSchCellCb *cell
3584 * @param[in] RgSchUeCb *ue
3587 Void rgSCHUtlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
3590 cell->sc.apis->rgSCHUeReset(cell, ue);
3592 } /* rgSCHUtlUeReset */
3593 /* End: LTEMAC_2.1_DEV_CFG */
3596 * @brief Returns HARQ proc for which data expected now
3600 * Function: rgSCHUtlUlHqProcForUe
3601 * Purpose: This function returns the harq process for
3602 * which data is expected in the current slot.
3603 * It does not validate if the HARQ process
3604 * has an allocation.
3608 * @param[in] RgSchCellCb *cell
3609 * @param[in] CmLteTimingInfo frm
3610 * @param[in] RgSchUeCb *ue
3611 * @param[out] RgSchUlHqProcCb **procRef
3614 Void rgSCHUtlUlHqProcForUe(RgSchCellCb *cell,CmLteTimingInfo frm,RgSchUeCb *ue,RgSchUlHqProcCb **procRef)
3616 cell->sc.apis->rgSCHUlHqProcForUe(cell, frm, ue, procRef);
3618 /* Stack Crash problems for TRACE5 changes. added the return below */
3624 * @brief Returns first uplink allocation to send reception
3629 * Function: rgSCHUtlFirstRcptnReq(cell)
3630 * Purpose: This function returns the first uplink allocation
3631 * (or NULLP if there is none) in the slot
3632 * in which is expected to prepare and send reception
3637 * @param[in] RgSchCellCb *cell
3638 * @return RgSchUlAlloc*
3640 RgSchUlAlloc *rgSCHUtlFirstRcptnReq(RgSchCellCb *cell)
3642 return (cell->sc.apis->rgSCHFirstRcptnReq(cell));
3646 * @brief Returns first uplink allocation to send reception
3651 * Function: rgSCHUtlNextRcptnReq(cell)
3652 * Purpose: This function returns the next uplink allocation
3653 * (or NULLP if there is none) in the slot
3654 * in which is expected to prepare and send reception
3659 * @param[in] RgSchCellCb *cell
3660 * @return RgSchUlAlloc*
3662 RgSchUlAlloc *rgSCHUtlNextRcptnReq(RgSchCellCb *cell,RgSchUlAlloc *alloc)
3664 return (cell->sc.apis->rgSCHNextRcptnReq(cell, alloc));
3668 * @brief Returns first uplink allocation to send HARQ feedback
3673 * Function: rgSCHUtlFirstHqFdbkAlloc
3674 * Purpose: This function returns the first uplink allocation
3675 * (or NULLP if there is none) in the slot
3676 * in which it is expected to prepare and send HARQ
3681 * @param[in] RgSchCellCb *cell
3682 * @param[in] uint8_t idx
3683 * @return RgSchUlAlloc*
3685 RgSchUlAlloc *rgSCHUtlFirstHqFdbkAlloc(RgSchCellCb *cell,uint8_t idx)
3687 return (cell->sc.apis->rgSCHFirstHqFdbkAlloc(cell, idx));
3692 * @brief Returns next allocation to send HARQ feedback for
3696 * Function: rgSCHUtlNextHqFdbkAlloc(cell)
3697 * Purpose: This function returns the next uplink allocation
3698 * (or NULLP if there is none) in the slot
3699 * for which HARQ feedback needs to be sent.
3703 * @param[in] RgSchCellCb *cell
3704 * @return RgSchUlAlloc*
3706 RgSchUlAlloc *rgSCHUtlNextHqFdbkAlloc(RgSchCellCb *cell,RgSchUlAlloc *alloc,uint8_t idx)
3708 return (cell->sc.apis->rgSCHNextHqFdbkAlloc(cell, alloc, idx));
3711 /***********************************************************
3713 * Func : rgSCHUtlResetSfAlloc
3715 * Desc : Utility Function to Reset slot allocation information.
3724 **********************************************************/
3725 S16 rgSCHUtlResetSfAlloc(RgInfSfAlloc *sfAlloc,Bool resetCmnLcInfo,Bool restAlloc)
3727 if(TRUE == restAlloc)
3729 if(sfAlloc->ueInfo.numUes)
3731 memset(sfAlloc->ueInfo.allocInfo,0x00,
3732 (sizeof(RgInfUeAlloc)*sfAlloc->ueInfo.numUes));
3734 sfAlloc->ueInfo.numUes = 0;
3735 sfAlloc->rarInfo.numRaRntis = 0;
3736 sfAlloc->flowCntrlInfo.numUes = 0;
3738 if(TRUE == resetCmnLcInfo)
3740 sfAlloc->cmnLcInfo.bitMask = 0;
3745 /***********************************************************
3747 * Func : rgSCHUtlGetRlsHqAlloc
3749 * Desc : Utility Function to Allocate slot allocation information.
3758 **********************************************************/
3759 S16 rgSCHUtlGetRlsHqAlloc(RgSchCellCb *cell)
3762 Inst inst = cell->instIdx;
3763 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3765 cell->rlsHqArr[idx].cellId = cell->cellId;
3767 /* Allocating with additional location, to accommodate
3768 TA scheduling along with maximum no of UEs per SF */
3770 /* Allocate memory for "scheduled UE" Info */
3771 if((rgSCHUtlAllocSBuf(inst,
3772 (Data**)&(cell->rlsHqArr[idx].ueHqInfo),
3773 (sizeof(RgInfUeHqInfo)*RGSCH_MAX_UE_PER_DL_SF))) != ROK)
3775 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED for "
3785 /***********************************************************
3787 * Func : rgSCHUtlPutRlsHqAlloc
3789 * Desc : Utility Function to deallocate slot allocation information.
3798 **********************************************************/
3799 S16 rgSCHUtlPutRlsHqAlloc(RgSchCellCb *cell)
3802 Inst inst = cell->instIdx;
3804 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3806 /* Deallocate memory for "scheduled UE" Info */
3807 if (cell->rlsHqArr[idx].ueHqInfo != NULLP)
3809 /* Freeing with additional location, to accommodate TA
3810 scheduling along with maximum no of UEs per SF */
3811 /* ccpu00117052 - MOD - Passing double pointer
3812 for proper NULLP assignment*/
3813 rgSCHUtlFreeSBuf(inst,
3814 (Data **)(&(cell->rlsHqArr[idx].ueHqInfo)),
3815 (sizeof(RgInfUeHqInfo)*RGSCH_MAX_UE_PER_DL_SF));
3824 /***********************************************************
3826 * Func : rgSCHUtlGetSfAlloc
3828 * Desc : Utility Function to Allocate slot allocation information.
3837 **********************************************************/
3838 S16 rgSCHUtlGetSfAlloc(RgSchCellCb *cell)
3842 Inst inst = cell->instIdx;
3843 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3846 for(idx=0; idx < RGSCH_SF_ALLOC_SIZE; idx++)
3848 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3851 cell->sfAllocArr[idx].cellId = cell->cellId;
3853 /* Allocating with additional location, to accommodate
3854 TA scheduling along with maximum no of UEs per SF */
3856 /* Allocate memory for "scheduled UE" Info */
3857 if((rgSCHUtlAllocSBuf(inst,
3858 (Data**)&(cell->sfAllocArr[idx].ueInfo.allocInfo),
3859 (sizeof(RgInfUeAlloc)*RGSCH_MAX_UE_PER_DL_SF))) != ROK)
3861 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED for "
3866 /* Allocate memory for "scheduled RAR" Info */
3867 if((rgSCHUtlAllocSBuf(inst,
3868 (Data**)&(cell->sfAllocArr[idx].rarInfo.raRntiInfo),
3869 (sizeof(RgInfRaRntiInfo)*RGSCH_MAX_RARNTI_PER_DL_SF))) != ROK)
3871 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED for "
3875 for(indx = 0; indx < RGSCH_MAX_RARNTI_PER_DL_SF; indx++)
3877 if((rgSCHUtlAllocSBuf(inst,
3878 (Data**)&(cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].crntiInfo),
3879 (sizeof(RgInfCrntiInfo)* (cellUl->maxMsg3PerUlSf)))) != ROK)
3881 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Memory allocation FAILED for "
3890 rgSCHEmtcUtlGetSfAlloc(cell);
3897 /***********************************************************
3899 * Func : rgSCHUtlPutSfAlloc
3901 * Desc : Utility Function to deallocate slot allocation information.
3910 **********************************************************/
3911 S16 rgSCHUtlPutSfAlloc(RgSchCellCb *cell)
3915 Inst inst = cell->instIdx;
3916 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3919 for(idx=0; idx < RGSCH_SF_ALLOC_SIZE; idx++)
3921 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3924 if (cell->sfAllocArr[idx].rarInfo.raRntiInfo != NULLP)
3926 for(indx = 0; indx < RGSCH_MAX_RARNTI_PER_DL_SF; indx++)
3928 if (cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].crntiInfo != NULLP)
3929 /* ccpu00117052 - MOD - Passing double pointer
3930 for proper NULLP assignment*/
3931 rgSCHUtlFreeSBuf(inst,
3932 (Data**)(&(cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].\
3934 (sizeof(RgInfCrntiInfo)* (cellUl->maxMsg3PerUlSf)));
3936 /* Deallocate memory for "scheduled RAR" Info */
3937 /* ccpu00117052 - MOD - Passing double pointer
3938 for proper NULLP assignment*/
3939 rgSCHUtlFreeSBuf(inst,
3940 (Data**)(&(cell->sfAllocArr[idx].rarInfo.raRntiInfo)),
3941 (sizeof(RgInfRaRntiInfo)*RGSCH_MAX_RARNTI_PER_DL_SF));
3943 /* Deallocate memory for "scheduled UE" Info */
3944 if (cell->sfAllocArr[idx].ueInfo.allocInfo != NULLP)
3946 /* Freeing with additional location, to accommodate TA
3947 scheduling along with maximum no of UEs per SF */
3948 /* ccpu00117052 - MOD - Passing double pointer
3949 for proper NULLP assignment*/
3950 rgSCHUtlFreeSBuf(inst,
3951 (Data**)(&(cell->sfAllocArr[idx].ueInfo.allocInfo)),
3952 (sizeof(RgInfUeAlloc)*RGSCH_MAX_UE_PER_DL_SF));
3957 rgSCHEmtcUtlPutSfAlloc(cell);
3963 /***********************************************************
3965 * Func : rgSCHUtlAllocSBuf
3967 * Desc : Utility Function to Allocate static buffer.
3968 * Memory allocated is assumed contiguous.
3974 * Notes: Caller doesnt need to raise the alarm in case of memory
3975 * allocation gets failed.
3979 **********************************************************/
3980 S16 rgSCHUtlAllocSBuf
3982 Inst inst, /* Instance of the invoking scheduler */
3983 Data **pData, /* Pointer of the data to be returned */
3984 Size size /* size */
3987 /* Moving alarm diagnostics to available scope */
3989 /* Initialize the param to NULLP */
3992 /* May not be necessary for data performance path */
4000 /* allocate buffer */
4001 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
4002 MS_BUF_ADD_ALLOC_CALLER();
4004 if (SGetSBuf(rgSchCb[inst].rgSchInit.region, rgSchCb[inst].rgSchInit.pool,
4005 pData, size) != ROK)
4007 RgUstaDgn dgn; /* Alarm diagnostics structure */
4008 dgn.type = LRG_USTA_DGNVAL_MEM;
4009 dgn.u.mem.region = rgSchCb[inst].rgSchInit.region;
4010 dgn.u.mem.pool = rgSchCb[inst].rgSchInit.pool;
4011 /* Send an alarm to Layer Manager */
4012 rgSCHLmmStaInd(inst, LCM_CATEGORY_RESOURCE, LCM_EVENT_SMEM_ALLOC_FAIL,
4013 LCM_CAUSE_MEM_ALLOC_FAIL, &dgn);
4014 RGSCHLOGERROR(inst, ERRCLS_DEBUG, ERG015, 0, "Unable to Allocate Buffer");
4015 RLOG_ARG0(L_ERROR,DBG_INSTID,inst, "Unable to Allocate the Buffer");
4020 /* zero out the allocated memory */
4021 memset(*pData, 0x00, size);
4025 } /* end of rgSCHUtlAllocSBuf */
4030 * Fun: rgSCHUtlFreeSBuf
4032 * Desc: The argument to rgSCHUtlFreeSBuf() is a pointer to a block
4033 * previously allocated by rgSCHUtlAllocSBuf() and size. It
4034 * deallocates the memory.
4041 Void rgSCHUtlFreeSBuf
4043 Inst inst, /* Instance of the invoking scheduler */
4044 Data **data, /* pointer to data */
4045 Size size /* size */
4051 if ((data == NULLP) || (*data == NULLP) || (size == 0))
4057 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
4058 MS_BUF_ADD_CALLER();
4060 /* Deallocate buffer */
4061 ret = SPutSBuf(rgSchCb[inst].rgSchInit.region,
4062 rgSchCb[inst].rgSchInit.pool, (*data), size);
4066 RGSCHLOGERROR(inst, ERRCLS_DEBUG, ERG016, (ErrVal) 0,
4067 "rgSCHUtlFreeSBuf failed.\n");
4068 RLOG_ARG0(L_ERROR,DBG_INSTID,inst, "rgSCHUtlFreeSBuf failed");
4072 /* ccpu00117052 - ADD - Assigning the pointer to NULLP */
4076 } /* end of rgSCHUtlFreeSBuf */
4082 * Fun: rgSCHUtlFreeWarningSiSeg
4084 * Desc: This is used to deallocate Warning SI Seg.
4092 Void rgSCHUtlFreeWarningSiSeg(Region reg,Pool pool,CmLListCp *siPduLst)
4097 while (siPduLst->first != NULLP)
4099 node = siPduLst->first;
4100 pdu = (Buffer *)node->node;
4101 cmLListDelFrm(siPduLst, node);
4102 RGSCH_FREE_MSG(pdu);
4103 SPutSBuf(reg, pool, (Data *)node,sizeof(CmLList));
4108 } /* end of rgSCHUtlFreeWarningSiSeg */
4113 * Fun: rgSCHUtlFreeWarningSiPdu
4115 * Desc: This is used to deallocate Warning SI PDU.
4123 Void rgSCHUtlFreeWarningSiPdu(RgSchCellCb *cell)
4127 RgSchWarningSiInfo *warningSi;
4128 RgSchWarningSiPdu *warningSiPdu;
4130 warningSi = (RgSchWarningSiInfo *) cell->siCb.\
4131 siArray[cell->siCb.siCtx.siId-1].si;
4132 /* ccpu00136659: CMAS ETWS design changes */
4133 CM_LLIST_FIRST_NODE(&warningSi->warningSiMsg.segLstCp, node);
4139 warningSiPdu = (RgSchWarningSiPdu *)node->node;
4140 pdu = warningSiPdu->pdu;
4141 /* ccpu00136659: CMAS ETWS design changes */
4142 cmLListDelFrm(&warningSi->warningSiMsg.segLstCp, node);
4143 RGSCH_FREE_MSG(pdu);
4144 if(warningSi->warningSiMsg.segLstCp.count == 0)
4146 /* ccpu00136659: CMAS ETWS design changes */
4147 cell->siCb.siArray[cell->siCb.siCtx.siId-1].si = NULLP;
4148 rgSCHUtlRgrWarningSiCfgCfm(cell->instIdx,
4149 rgSchCb[cell->instIdx].rgrSap->sapCfg.spId,
4150 cell->siCb.warningSi[warningSi->idx].siId,
4151 warningSi->warningSiMsg.transId, RGR_CFG_CFM_TX_COMPLETE);
4156 } /* end of rgSCHUtlFreeWarningSiPdu */
4161 * Fun: rgSCHUtlGetWarningSiPdu
4163 * Desc: This is used to get Warning SI PDU for Scheduling.
4171 Buffer *rgSCHUtlGetWarningSiPdu(RgSchCellCb *cell)
4173 RgSchWarningSiInfo *warningSi;
4174 RgSchWarningSiPdu *warningSiPdu;
4178 warningSi = (RgSchWarningSiInfo *) cell->siCb.
4179 siArray[cell->siCb.siCtx.siId-1].si;
4180 /* ccpu00136659: CMAS ETWS design changes */
4181 CM_LLIST_FIRST_NODE(&warningSi->warningSiMsg.segLstCp, node);
4184 warningSiPdu = (RgSchWarningSiPdu *)node->node;
4185 pdu = warningSiPdu->pdu;
4192 } /* rgSCHUtlGetWarningSiPdu */
4197 * Fun: rgSCHUtlGetMcsAndNPrb
4199 * Desc: This is used to get mcs and nPrb value.
4207 S16 rgSCHUtlGetMcsAndNPrb(RgSchCellCb *cell,uint8_t *nPrb,uint8_t *mcs,MsgLen *msgLen)
4209 RgSchWarningSiInfo *warningSi;
4210 RgSchWarningSiPdu *warningSiPdu;
4213 if(cell->siCb.siCtx.warningSiFlag == FALSE)
4215 *mcs = cell->siCb.crntSiInfo.siInfo[cell->siCb.siCtx.siId-1].mcs;
4216 *nPrb = cell->siCb.crntSiInfo.siInfo[cell->siCb.siCtx.siId-1].nPrb;
4217 *msgLen = cell->siCb.crntSiInfo.siInfo[cell->siCb.siCtx.siId-1].msgLen;
4221 warningSi = (RgSchWarningSiInfo *) cell->siCb.
4222 siArray[cell->siCb.siCtx.siId-1].si;
4223 /* ccpu00136659: CMAS ETWS design changes */
4224 CM_LLIST_FIRST_NODE(&warningSi->warningSiMsg.segLstCp, node);
4230 warningSiPdu = (RgSchWarningSiPdu *)node->node;
4231 *mcs = warningSiPdu->mcs;
4232 *nPrb = warningSiPdu->nPrb;
4233 *msgLen = warningSiPdu->msgLen;
4238 } /* rgSCHUtlGetMcsAndNPrb */
4242 * Fun: rgSCHUtlCalMacAndPrb
4244 * Desc: This is used to Calculate mcs and nPrb value for SIB1 and SIs.
4252 S16 rgSCHUtlCalMcsAndNPrb(RgSchCellCb *cell,uint8_t cfgType,MsgLen msgLen,uint8_t siId)
4257 /*Get the nPrb and mcs parametr values */
4258 if (rgSCHUtlGetAllwdCchTbSz(msgLen*8, &nPrb, &mcs) != (msgLen*8))
4260 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, "msgLen does "
4261 "not match any valid TB Size");
4266 if(cfgType == RGR_SI_CFG_TYPE_SIB1 || cfgType == RGR_SI_CFG_TYPE_SIB1_PWS)
4269 if(cell->siCb.crntSiInfo.sib1Info.sib1 == NULLP)
4271 cell->siCb.crntSiInfo.sib1Info.mcs = mcs;
4272 cell->siCb.crntSiInfo.sib1Info.nPrb = nPrb;
4273 cell->siCb.crntSiInfo.sib1Info.msgLen = msgLen;
4277 cell->siCb.newSiInfo.sib1Info.mcs = mcs;
4278 cell->siCb.newSiInfo.sib1Info.nPrb= nPrb;
4279 cell->siCb.newSiInfo.sib1Info.msgLen = msgLen;
4284 if(cfgType == RGR_SI_CFG_TYPE_SI)
4286 if(cell->siCb.crntSiInfo.siInfo[siId-1].si == NULLP &&
4287 !(cell->siCb.siBitMask & RGSCH_SI_SICFG_UPD))
4289 cell->siCb.crntSiInfo.siInfo[siId-1].mcs = mcs;
4290 cell->siCb.crntSiInfo.siInfo[siId-1].nPrb = nPrb;
4291 cell->siCb.crntSiInfo.siInfo[siId-1].msgLen = msgLen;
4295 cell->siCb.newSiInfo.siInfo[siId-1].mcs = mcs;
4296 cell->siCb.newSiInfo.siInfo[siId-1].nPrb= nPrb;
4297 cell->siCb.newSiInfo.siInfo[siId-1].msgLen = msgLen;
4301 if(cfgType == RGR_SI_CFG_TYPE_SIB8_CDMA)
4303 cell->siCb.crntSiInfo.siInfo[siId-1].mcs = mcs;
4304 cell->siCb.crntSiInfo.siInfo[siId-1].nPrb = nPrb;
4305 cell->siCb.crntSiInfo.siInfo[siId-1].msgLen = msgLen;
4312 /***********************************************************
4314 * Func : rgSCHUtlFillDgnParams
4316 * Desc : Utility Function to Fill Diagonostic params.
4324 **********************************************************/
4325 Void rgSCHUtlFillDgnParams(Inst inst,RgUstaDgn *dgn,uint8_t dgnType)
4330 case LRG_USTA_DGNVAL_MEM:
4331 dgn->type = (uint8_t) LRG_USTA_DGNVAL_MEM;
4332 dgn->u.mem.region = rgSchCb[inst].rgSchInit.region;
4333 dgn->u.mem.pool = rgSchCb[inst].rgSchInit.pool;
4341 } /* end of rgSCHUtlFillDgnParams */
4343 /***********************************************************
4345 * Func : rgSCHUtlGetPstToLyr
4347 * Desc : Utility Function to get the pst structure to post a message to MAC
4353 * Notes: This function should be called while sending a msg from
4354 * scheduler instance to MAC
4358 **********************************************************/
4359 Void rgSCHUtlGetPstToLyr(Pst *pst,RgSchCb *schCb,Inst macInst)
4362 /* Only the needed params are filled */
4363 pst->region = schCb->rgSchInit.region;
4364 pst->pool = schCb->rgSchInit.pool;
4365 pst->srcInst = schCb->rgSchInit.inst+SCH_INST_START;
4366 pst->srcProcId = schCb->rgSchInit.procId;
4367 pst->dstProcId = schCb->rgSchInit.procId;
4369 pst->dstInst = macInst;
4370 pst->dstEnt = ENTMAC;
4371 pst->srcEnt = ENTMAC;
4373 pst->prior = PRIOR0;
4375 pst->route = RTESPEC;
4378 } /* end of rgSCHUtlGetPstToLyr */
4380 /** @brief This function fills in the common lc information to be sent to MAC
4384 * Function: rgSCHUtlFillRgInfCmnLcInfo
4385 * @param RgSchDlSf *sf,
4386 * @param RgInfSfAlloc *sfAlloc,
4387 * @param CmLteLcId lcId,
4388 * @param Bool sendInd
4394 S16 rgSCHUtlFillRgInfCmnLcInfo(RgSchDlSf *sf,RgInfSfAlloc *sfAlloc,CmLteLcId lcId,Bool sendInd)
4397 if((sf->bch.tbSize)&&
4398 !(sfAlloc->cmnLcInfo.bitMask & RGINF_BCH_INFO))
4401 sfAlloc->cmnLcInfo.bchInfo.lcId = lcId;
4403 sfAlloc->cmnLcInfo.bitMask |= RGINF_BCH_INFO;
4405 else if((sf->bcch.pdcch != NULLP)&&
4406 !(sfAlloc->cmnLcInfo.bitMask & RGINF_BCCH_INFO))
4408 sfAlloc->cmnLcInfo.bcchInfo.rnti = RGSCH_SI_RNTI;
4409 rgSCHUtlFillPdschDciInfo(&(sfAlloc->cmnLcInfo.bcchInfo.dciInfo),
4410 &(sf->bcch.pdcch->dci));
4412 sfAlloc->cmnLcInfo.bcchInfo.lcId = lcId;
4413 sfAlloc->cmnLcInfo.bcchInfo.sndStatInd = sendInd;
4415 sfAlloc->cmnLcInfo.bitMask |= RGINF_BCCH_INFO;
4417 else if((sf->pcch.pdcch != NULLP) &&
4418 !(sfAlloc->cmnLcInfo.bitMask & RGINF_PCCH_INFO))
4420 sfAlloc->cmnLcInfo.pcchInfo.rnti = RGSCH_P_RNTI;
4421 rgSCHUtlFillPdschDciInfo(&(sfAlloc->cmnLcInfo.pcchInfo.dciInfo),
4422 &(sf->pcch.pdcch->dci));
4423 sfAlloc->cmnLcInfo.pcchInfo.lcId = lcId;
4424 sfAlloc->cmnLcInfo.bitMask |= RGINF_PCCH_INFO;
4429 /** @brief This function fills in the RAR information to be sent to MAC
4433 * Function: rgSCHUtlFillRgInfRarInfo
4435 * @param RgSchCellCb *cell
4436 * @param RgSchDlSf *sf
4437 * @param RgInfSfAlloc *sfAlloc
4442 S16 rgSCHUtlFillRgInfRarInfo(RgSchDlSf *sf,RgInfSfAlloc *sfAlloc,RgSchCellCb *cell)
4449 RgInfRaRntiInfo *raRntiAlloc;
4451 RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell);
4454 noRaRsps = RGSCH_MAX_TDD_RA_RSP_ALLOC;
4456 noRaRsps = RGSCH_MAX_RA_RSP_ALLOC;
4459 for(idx =0; idx < noRaRsps; idx++)
4461 if (sf->raRsp[idx].pdcch == NULLP)
4463 /* No further raResp Allocations. */
4466 /* Added Dl TB count for RACH Response transmission*/
4468 cell->dlUlTbCnt.tbTransDlTotalCnt++;
4470 raRntiAlloc = &(sfAlloc->rarInfo.raRntiInfo[idx]);
4471 raRntiAlloc->raRnti = sf->raRsp[idx].raRnti;
4472 raRntiAlloc->schdTbSz = sf->raRsp[idx].tbSz;
4473 raRntiAlloc->numCrnti = 0;
4474 rgSCHUtlFillPdschDciInfo(&(raRntiAlloc->dciInfo),
4475 &(sf->raRsp[idx].pdcch->dci));
4476 /* RACHO : fill backoff indicator information */
4477 raRntiAlloc->backOffInd = sf->raRsp[idx].backOffInd;
4479 /* Fill for contention free UEs*/
4480 lnkLst = &(sf->raRsp[idx].contFreeUeLst);
4481 CM_LLIST_FIRST_NODE(lnkLst, tmp);
4484 ue = (RgSchUeCb *)tmp->node;
4486 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].tmpCrnti = ue->ueId;
4487 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].isContFree = TRUE;
4488 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].rapId = ue->ul.rarGrnt.rapId;
4489 #ifndef MAC_5GTF_UPDATE
4490 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.hop =
4492 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.cqiBit =
4493 ue->ul.rarGrnt.cqiReqBit;
4495 /* SHASHAHNK ADD RIV CALC */
4496 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.rbStart =
4497 ue->ul.rarGrnt.rbStart;
4498 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.numRb =
4499 ue->ul.rarGrnt.numRb;
4500 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.tpc =
4502 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.iMcsCrnt =
4503 ue->ul.rarGrnt.iMcsCrnt;
4504 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].ta = ue->ul.rarGrnt.ta;
4505 raRntiAlloc->numCrnti++;
4506 cmLListDelFrm(lnkLst, &ue->ul.rarGrnt.raRspLnk);
4507 ue->ul.rarGrnt.raRspLnk.node = (PTR)NULLP;
4509 /* Fill for contention based UEs*/
4510 lnkLst = &(sf->raRsp[idx].raRspLst);
4512 CM_LLIST_FIRST_NODE(lnkLst, tmp);
4514 while((NULLP != tmp) && ((RgSchRaCb *)tmp->node != NULLP))
4516 raCb = (RgSchRaCb *)tmp->node;
4518 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].tmpCrnti = raCb->tmpCrnti;
4519 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].isContFree = FALSE;
4520 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].rapId = raCb->rapId;
4521 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].ta.pres = TRUE;
4522 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].ta.val = raCb->ta.val;
4523 #ifndef MAC_5GTF_UPDATE
4524 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.hop =
4526 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.cqiBit = FALSE;
4528 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.rbStart =
4529 raCb->msg3Grnt.rbStart;
4530 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.numRb =
4531 raCb->msg3Grnt.numRb;
4532 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.tpc =
4534 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.iMcsCrnt =
4535 raCb->msg3Grnt.iMcsCrnt;
4536 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.delayBit =
4537 raCb->msg3Grnt.delayBit;
4538 /* For initial attaching UEs Aperiodic CQI need not be triggered */
4539 raRntiAlloc->numCrnti++;
4540 /* Search the next node */
4541 CM_LLIST_NEXT_NODE(lnkLst, tmp);
4544 sfAlloc->rarInfo.numRaRntis = idx;
4545 /* ccpu00132314-ADD-Update the tx power allocation info
4546 TODO-Need to add a check for max tx power per symbol */
4547 sfAlloc->rarInfo.txPwrOffset = cellDl->rarTxPwrOffset;
4550 } /* end of rgSCHUtlFillRgInfRarInfo */
4552 /** @brief This function fills in the pdsch data related allocation Info
4553 * from the pdcch DCI info.
4558 * Function: rgSCHUtlFillPdschDciInfo
4561 * - Depending upon the DCI Format, fill the appropriate fields.
4563 * @param [out] TfuPdschDciInfo *pdschDci
4564 * @param [in] TfuDciInfo *pdcchDci
4569 S16 rgSCHUtlFillPdschDciInfo(TfuPdschDciInfo *pdsch,TfuDciInfo *pdcchDci)
4575 pdsch->format = pdcchDci->dciFormat;
4576 switch(pdcchDci->dciFormat)
4578 case TFU_DCI_FORMAT_1:
4579 pdsch->u.format1AllocInfo = pdcchDci->u.format1Info.allocInfo;
4581 case TFU_DCI_FORMAT_1A:
4582 if (pdcchDci->u.format1aInfo.isPdcchOrder == FALSE)
4584 pdsch->u.format1aAllocInfo = pdcchDci->u.format1aInfo.t.pdschInfo.allocInfo;
4587 case TFU_DCI_FORMAT_1B:
4588 pdsch->u.format1bAllocInfo = pdcchDci->u.format1bInfo.allocInfo;
4590 case TFU_DCI_FORMAT_1C:
4591 pdsch->u.format1cAllocInfo = pdcchDci->u.format1cInfo;
4593 case TFU_DCI_FORMAT_1D:
4594 pdsch->u.format1dAllocInfo = pdcchDci->u.format1dInfo.allocInfo;
4596 case TFU_DCI_FORMAT_2:
4597 pdsch->u.format2AllocInfo = pdcchDci->u.format2Info.allocInfo;
4599 case TFU_DCI_FORMAT_2A:
4600 pdsch->u.format2AAllocInfo = pdcchDci->u.format2AInfo.allocInfo;
4603 case TFU_DCI_FORMAT_B1:
4604 pdsch->u.formatB1Info = pdcchDci->u.formatB1Info;
4606 case TFU_DCI_FORMAT_B2:
4607 pdsch->u.formatB2Info = pdcchDci->u.formatB2Info;
4612 ret = rgSCHEmtcUtlFillPdschDciInfo(pdsch, pdcchDci);
4624 /* LTE_ADV_FLAG_REMOVED_START */
4626 * @brief This function resets temporary variables in Pool
4629 * Function: rgSchSFRResetPoolVariables
4631 * Invoked by: rgSCHSFRUtlTotalPoolInit
4633 * @param[in] RgSchCellCb* cell
4634 * @param[in] RgSubFrm* subFrm
4638 Void rgSchDSFRPwrCheck(RgSchDlSf *sf,Bool *isAllUePwrHigh)
4640 RgSchSFRPoolInfo *sfrCCPool;
4645 l = &sf->sfrTotalPoolInfo.ccPool;
4646 n = cmLListFirst(l);
4649 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
4650 if((sfrCCPool->poolstartRB == sfrCCPool->pwrHiCCRange.startRb) &&
4651 (sfrCCPool->poolendRB == sfrCCPool->pwrHiCCRange.endRb))
4658 *isAllUePwrHigh = TRUE;
4665 /* LTE_ADV_FLAG_REMOVED_END */
4666 /***********************************************************
4668 * Func : rgSCHUtlFillRgInfTbInfo
4670 * Desc : Utility Function to fill the allocation info of each Tb
4676 * Notes: This function should be called while sending a msg from
4677 * scheduler instance to MAC
4681 **********************************************************/
4682 static Void rgSCHUtlFillRgInfTbInfo(RgSchDlHqProcCb *hqP,RgInfUeAlloc *allocInfo,RgSchCellCb *cell)
4686 RgInfUeTbInfo *tbInfo;
4688 /* LTE_ADV_FLAG_REMOVED_START */
4690 static uint32_t tmpCnt = 0;
4691 Bool isAllUePwrHigh = FALSE;
4693 /* LTE_ADV_FLAG_REMOVED_END */
4694 RgSchDlLcCb *dlLcCb = NULLP;
4695 uint16_t rlcHdrEstmt;
4699 uint8_t prbUsed = 0;
4703 CmLteTimingInfo frm;
4705 /* Get Downlink slot */
4706 frm = cell->crntTime;
4707 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
4708 sf = rgSCHUtlSubFrmGet(cell, frm);
4709 /* Setting of fillCtrlPdu flag
4710 If both P-cell and S-cell are present,
4711 make TRUE for P-cell and FALSE for all s-cells
4712 For all other cases set TRUE */
4714 if ((rgSchCb[cell->instIdx].genCfg.forceCntrlSrbBoOnPCel) &&
4715 !RG_SCH_CMN_IS_PCELL_HQP(hqP))
4717 allocInfo->fillCtrlPdu = FALSE;
4721 allocInfo->fillCtrlPdu = TRUE;
4725 allocInfo->tbStrtIdx = -1;
4729 allocInfo->tbReqInfo.sCellHqPId = 0xff;
4730 rgSCHLaaHndlFillRgInfTbInfo(cell, hqP, allocInfo);
4733 /*TODO:REEMA: Check and fill the isRetx */
4734 for(tbCnt = 0; tbCnt < 2; tbCnt++)
4736 RgSchUeCb *ue = NULLP;
4737 /*Changed as a result of CR timer*/
4738 if ((hqP->hqE->ue != NULLP)/* &&
4739 ((hqP->tbInfo[tbCnt].lchSchdData[0].lcId != 0) || \
4740 (hqP->tbInfo[tbCnt].schdTa.pres == PRSNT_NODEF))*/)
4743 allocInfo->rnti = ue->ueId;
4744 allocInfo->doa = hqP->hqE->ue->mimoInfo.doa;
4745 allocInfo->txMode = (TfuTxMode)(hqP->hqE->ue->mimoInfo.txMode);
4746 allocInfo->puschRptUsd = hqP->hqE->ue->mimoInfo.puschFdbkVld;
4747 allocInfo->puschPmiInfo = hqP->hqE->ue->mimoInfo.puschPmiInfo;
4748 if(hqP->tbInfo[tbCnt].schdTa.pres == PRSNT_NODEF)
4750 hqP->tbInfo[tbCnt].taSnt = TRUE;
4753 if (RG_SCH_IS_PAPRSNT(ue,hqP->hqE->cell))
4755 /*update pA value */
4756 allocInfo->pa = (RG_SCH_CMN_GET_PA(ue,hqP->hqE->cell)).val;
4760 /* LTE_ADV_FLAG_REMOVED_START */
4761 /* If ABS is enabled, calculate resource used */
4762 if((0 == tbCnt) && (RGR_ENABLE == ue->cell->lteAdvCb.absCfg.status))
4764 /* For Macro count number resource used in Non-ABS SF */
4765 if(RGR_ABS_MUTE == ue->cell->lteAdvCb.absCfg.absPatternType)
4767 if(RG_SCH_ABS_ENABLED_NONABS_SF == ue->cell->lteAdvCb.absDlSfInfo)
4769 ue->cell->lteAdvCb.absLoadInfo[ue->cell->lteAdvCb.absPatternDlIdx]+=
4770 hqP->tbInfo[tbCnt].dlGrnt.numRb;
4773 /* For pico count number resource used in ABS SF for ABS UE */
4774 else if(RGR_ABS_TRANSMIT == ue->cell->lteAdvCb.absCfg.absPatternType)
4776 if(RG_SCH_ABS_ENABLED_ABS_SF == ue->cell->lteAdvCb.absDlSfInfo)
4778 if(TRUE == ue->lteAdvUeCb.rgrLteAdvUeCfg.isAbsUe)
4780 ue->cell->lteAdvCb.absLoadInfo[ue->cell->lteAdvCb.absPatternDlIdx]+=
4781 hqP->tbInfo[tbCnt].dlGrnt.numRb;
4788 /*if SFR is enabled*/
4789 allocInfo->isEnbSFR = (uint8_t)RG_SCH_CMN_IS_SFR_ENB(ue->cell); /* KW fix for LTE_ADV */
4790 if((ue->cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE) &&
4791 (ue->lteAdvUeCb.rgrLteAdvUeCfg.isUeCellEdge == FALSE))
4793 rgSchDSFRPwrCheck(sf, &isAllUePwrHigh);
4797 allocInfo->pa = (uint8_t)ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh; /* KW fix for LTE_ADV */
4798 if(tmpCnt++ == 100000)
4800 RLOG_ARG2(L_DEBUG,DBG_CELLID,ue->cell->cellId,
4801 "DSFR::ll UEs can go HIGH, PHigh(%d) for UE(%d)",allocInfo->pa, ue->ueId);
4807 if (allocInfo->isEnbSFR)
4809 /*Update pA to Plow if it is cell-centred ,else pA will be pHigh*/
4810 if (ue->lteAdvUeCb.rgrLteAdvUeCfg.isUeCellEdge == TRUE)
4812 allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;
4813 if(tmpCnt++ == 100000)
4815 RLOG_ARG2(L_DEBUG,DBG_CELLID,ue->cell->cellId,
4816 "SFR::UE is CELL EDGE, PHigh(%d) for UE(%d)",allocInfo->pa, ue->ueId);
4823 if(TRUE == ue->lteAdvUeCb.isCCUePHigh)
4825 allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;
4826 ue->lteAdvUeCb.isCCUePHigh = FALSE;
4830 allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pLow;
4831 if(tmpCnt++ == 100000)
4833 RLOG_ARG2(L_DEBUG,DBG_CELLID,ue->cell->cellId,
4834 "SFR::UE is CELL CENTRE, PLow(%d) for UE(%d)\n",allocInfo->pa, ue->ueId);
4841 /* LTE_ADV_FLAG_REMOVED_END */
4849 RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell);
4852 allocInfo->pdcchRnti = hqP->hqE->raCb->tmpCrnti;
4854 allocInfo->rnti = hqP->hqE->raCb->tmpCrnti;
4856 /*ccpu00132314-ADD-Use a default pA value
4858 allocInfo->pa = cellDl->msg4pAVal;
4862 /* If TB Is scheduled for this SF */
4863 if(hqP->tbInfo[tbCnt].state == HQ_TB_WAITING)
4865 if (allocInfo->tbStrtIdx == -1){
4866 allocInfo->tbStrtIdx = tbCnt;
4868 rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4869 &(hqP->pdcch->dci));
4873 rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4874 &(hqP->pdcch->dci));
4876 else if ((ue) && (ue->dl.spsOccPdcch.rnti == ue->spsRnti))
4878 rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4879 &(ue->dl.spsOccPdcch.dci));
4881 #endif /* ifndef LTEMAC_SPS */
4886 allocInfo->pdcchRnti = hqP->pdcch->rnti;
4890 allocInfo->pdcchRnti = ue->spsRnti;
4893 tbInfo = &(allocInfo->tbInfo[tbCnt]);
4894 allocInfo->nmbOfTBs++;
4895 allocInfo->hqProcId = hqP->procId;
4896 allocInfo->tbInfo[tbCnt].schdTbSz = hqP->tbInfo[tbCnt].tbSz;
4898 tbInfo->disTb = FALSE;
4899 if(!(hqP->tbInfo[tbCnt].txCntr))
4902 if(!((rgSCHLaaCheckIfLAAProc(hqP)) && (TRUE ==
4903 rgSCHLaaSCellEnabled(cell))))
4906 hqP->tbInfo[tbCnt].txCntr++;
4908 for(idx = 0; idx < hqP->tbInfo[tbCnt].numLch; idx++)
4910 tbInfo->schdDat[idx].lcId =\
4911 hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
4912 tbInfo->schdDat[idx].numBytes =\
4913 hqP->tbInfo[tbCnt].lchSchdData[idx].schdData;
4916 lcId = hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
4919 dlLcCb = hqP->hqE->ue->dl.lcCb[lcId-1];
4922 RG_SCH_CMN_DL_GET_HDR_EST(dlLcCb, rlcHdrEstmt);
4923 /* Update the totalBo with the scheduled bo */
4924 (hqP->hqE->ue->totalBo <= tbInfo->schdDat[idx].numBytes - rlcHdrEstmt)?\
4925 (hqP->hqE->ue->totalBo = 0):\
4926 (hqP->hqE->ue->totalBo -= tbInfo->schdDat[idx].numBytes-rlcHdrEstmt);
4930 prbUsed = ((hqP->tbInfo[tbCnt].\
4931 lchSchdData[idx].schdData *
4932 hqP->tbInfo[tbCnt].dlGrnt.numRb) /
4933 (hqP->tbInfo[0].tbSz + hqP->tbInfo[1].tbSz));
4934 dlLcCb->qciCb->dlPrbCount += prbUsed;
4935 if(dlLcCb->qciCb->qci > 0)
4937 RG_SCH_CALC_GBR_UTILIZATION(cell, dlLcCb, prbUsed);
4939 #endif /* RRM_RBC_Y */
4942 //if(!(hqP->hqE->ue->pfsStats.lcStats[lcId-1].isLcCntSet))
4946 if (hqP->hqE->ue->cell == hqP->hqE->cell)
4948 idx = RGSCH_PCELL_INDEX;
4952 idx = RG_SCH_GET_SCELL_INDEX((hqP->hqE->ue), (hqP->hqE->cell));
4954 hqP->hqE->ue->pfsStats.lcStats[lcId-1].ueSchdOcc[idx]++;
4955 hqP->hqE->ue->pfsStats.lcStats[lcId-1].perRefresh[ue->pfsStats.lcStats[lcId-1].lastIdx].lcSchdOcc++;
4962 /* Added Dl TB count for SRB/DRB data transmission*/
4964 cell->dlUlTbCnt.tbTransDlTotalCnt++;
4966 tbInfo->ta.pres = hqP->tbInfo[tbCnt].schdTa.pres;
4967 tbInfo->ta.val = hqP->tbInfo[tbCnt].schdTa.val;
4969 tbInfo->sCellActCe = hqP->tbInfo[tbCnt].schdSCellActCe;
4971 tbInfo->numSchLch = hqP->tbInfo[tbCnt].numLch;
4972 if(!(hqP->tbInfo[tbCnt].numLch))
4974 tbInfo->schdDat[tbInfo->numSchLch].numBytes= hqP->tbInfo[tbCnt].tbSz;
4975 /* Fix: If only TA is scheduled, use some dummy LCID */
4976 if (tbInfo->ta.pres)
4977 tbInfo->schdDat[tbInfo->numSchLch].lcId = RG_TA_LCID;
4980 tbInfo->contResCe = hqP->tbInfo[tbCnt].contResCe;
4981 tbInfo->isReTx = FALSE;
4986 if(!((rgSCHLaaCheckIfLAAProc(hqP)) && (TRUE ==
4987 rgSCHLaaSCellEnabled(cell))))
4990 hqP->tbInfo[tbCnt].txCntr++;
4992 tbInfo->isReTx = TRUE;
4994 /* As per 36.314, harq retransmission also considered for
4995 * prb utilization calculation*/
4996 for(idx = 0; idx < hqP->tbInfo[tbCnt].numLch; idx++)
5001 lcId = hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
5004 dlLcCb = hqP->hqE->ue->dl.lcCb[lcId-1];
5007 prbUsed = ((hqP->tbInfo[tbCnt].\
5008 lchSchdData[idx].schdData *
5009 hqP->tbInfo[tbCnt].dlGrnt.numRb) /
5010 (hqP->tbInfo[0].tbSz + hqP->tbInfo[1].tbSz));
5011 if(dlLcCb->qciCb->qci > 0)
5013 RG_SCH_CALC_GBR_UTILIZATION(cell, dlLcCb, prbUsed);
5025 rgSCHLaaResetDlHqProcCb(hqP);
5030 /***********************************************************
5032 * Func : rgSCHUtlFillRgInfUeInfo
5034 * Desc : Utility Function to fill the allocation info of Ue
5035 * : MIMO : Filling 2TB's of each UE
5040 * Notes: This function should be called while sending a msg from
5041 * scheduler instance to MAC
5045 **********************************************************/
5047 Void rgSCHUtlFillRgInfUeInfo(RgSchDlSf *sf,RgSchCellCb *cell,CmLListCp *dlDrxInactvTmrLst,CmLListCp *dlInActvLst,CmLListCp *ulInActvLst)
5049 RgInfSfAlloc *sfAlloc;
5050 CmLListCp *lnkLst; /* lnkLst assignment */
5053 RgSchUeCb *ue = NULLP;
5054 RgInfUeInfo *ueInfo = NULLP;
5055 RgInfUeAlloc *ueAlloc = NULLP;
5056 RgSchDlHqProcCb *hqCb = NULLP;
5058 /* Since Msg4 is sched only on PCELL, use cell arg's sfAllocArr */
5059 sfAlloc = &(cell->sfAllocArr[cell->crntSfIdx]);
5060 ueInfo = &(sfAlloc->ueInfo);
5061 ueAlloc = sfAlloc->ueInfo.allocInfo;
5063 lnkLst = &(sf->msg4HqPLst);
5064 CM_LLIST_FIRST_NODE(lnkLst, tmp);
5067 printf("5GTF_ERROR MSG4 Consolidation\n");
5068 hqCb = (RgSchDlHqProcCb *)(tmp->node);
5069 CM_LLIST_NEXT_NODE(lnkLst, tmp);
5071 rgSCHUtlFillRgInfTbInfo(hqCb, &ueAlloc[ueInfo->numUes], cell);
5077 if((!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE)) && (ue->isDrxEnabled))
5079 rgSCHUtlGetDrxSchdUesInDl(cell, ue, hqCb, &ueAlloc[ueInfo->numUes],
5080 dlDrxInactvTmrLst, dlInActvLst, ulInActvLst);
5086 lnkLst = &(sf->ueLst);
5087 CM_LLIST_FIRST_NODE(lnkLst, tmp);
5090 #if defined (TENB_STATS) && defined (RG_5GTF)
5091 cell->tenbStats->sch.dl5gtfPdschCons++;
5093 ue = (RgSchUeCb *)(tmp->node);
5094 CM_LLIST_NEXT_NODE(lnkLst, tmp);
5096 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
5099 hqCb = (RgSchDlHqProcCb *)hqPNode->node;
5100 hqPNode = hqPNode->next;
5102 sfAlloc = &(hqCb->hqE->cell->sfAllocArr[hqCb->hqE->cell->crntSfIdx]);
5103 ueInfo = &(sfAlloc->ueInfo);
5104 ueAlloc = sfAlloc->ueInfo.allocInfo;
5106 rgSCHUtlFillRgInfTbInfo(hqCb, &ueAlloc[ueInfo->numUes],
5109 if(ue->isDrxEnabled)
5111 rgSCHUtlGetDrxSchdUesInDl(cell, ue, hqCb, &ueAlloc[ueInfo->numUes],
5112 dlDrxInactvTmrLst, dlInActvLst, ulInActvLst);
5117 if (rgSchCb[cell->instIdx].genCfg.isSCellActDeactAlgoEnable == TRUE)
5119 /*If remaining BO is left then increment the count*/
5123 /* Check if trigger for Activation is met or not */
5124 if(rgSCHIsActvReqd(cell, ue))
5127 /*Passing primary cell*/
5128 rgSCHSCellSelectAndActDeAct(ue->cell, ue, RGR_SCELL_ACT);
5133 /*If remaining BO is 0 then reset the count*/
5141 } /* end of rgSCHUtlFillRgInfUeInfo */
5145 /** @brief This function shall update the scheduler with the CEs and data rcvd
5149 * Function: rgSCHUtlUpdSch
5152 * - Collate the information of all the SDUs received and inform the
5153 * scheduler rgSCHDataRcvd
5154 * - Send Data indication to the higher layer with the dedicated data
5155 * (rgUIMSndDedDatInd)
5156 * - Inform scheduler with any MAC CEs if present.
5158 * @param [in] RgCellCb *cellCb
5159 * @param [in] RgUeCb *ueCb
5160 * @param [in] RgMacPdu *pdu
5161 * @param [in] RgSchErrInfo *err
5166 S16 rgSCHUtlUpdSch(RgInfSfDatInd *subfrmInfo,RgSchCellCb *cellCb,RgSchUeCb *ueCb,RgInfUeDatInd *pdu,RgSchErrInfo *err)
5171 if (RGSCH_UL_SPS_ACT_PRSENT & pdu->ceInfo.bitMask)
5173 /* SPS to be activated due to data on SPS LCG ID*/
5174 rgSCHUtlSpsActInd(cellCb, ueCb, pdu->ceInfo.spsSduSize);
5177 /* TODO : Temp Fix for crash due to UL SDU corruption*/
5178 if (RGSCH_PHR_CE_PRSNT & pdu->ceInfo.bitMask)
5181 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5182 if ((ret = rgSCHUtlUpdPhr(cellCb, ueCb, pdu->ceInfo.ces.phr, err)) != ROK)
5185 /* Note: Order of indication to Sch now is
5186 * 1st Indicate the DataInd info for each LCG's
5187 * 2nd Update the BSR reports received along with data
5188 * this is to make sure the effBsr is updated to the latest BSR
5191 cellCb->sc.apis->rgSCHUpdUeDataIndLcg(cellCb, ueCb, pdu);
5193 #ifndef MAC_5GTF_UPDATE
5194 if (RGSCH_TRUNC_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5196 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5197 /*ccpu00129922 - MOD - Deleted return value
5198 * checking since it returns void*/
5199 rgSCHUtlUpdBsrTrunc (cellCb, ueCb,
5200 (uint8_t)(pdu->ceInfo.ces.bsr.truncBsr >> 6),
5201 (uint8_t)(pdu->ceInfo.ces.bsr.truncBsr & 0x3F), err);
5205 if (RGSCH_SHORT_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5207 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5208 /*ccpu00129922 - MOD - Deleted return value
5209 checking since it returns void*/
5210 rgSCHUtlUpdBsrShort (cellCb, ueCb,
5211 (uint8_t)(pdu->ceInfo.ces.bsr.shortBsr >> 6),
5212 (uint8_t)(pdu->ceInfo.ces.bsr.shortBsr & 0x3F), err);
5216 if (RGSCH_LONG_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5218 if (RGSCH_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5221 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5222 /*ccpu00129922 - MOD - Deleted return value
5223 checking since it returns void*/
5224 rgSCHUtlUpdBsrLong (cellCb, ueCb,
5225 pdu->ceInfo.ces.bsr.longBsr.bs1,
5226 pdu->ceInfo.ces.bsr.longBsr.bs2,
5227 pdu->ceInfo.ces.bsr.longBsr.bs3,
5228 pdu->ceInfo.ces.bsr.longBsr.bs4,
5231 #ifndef MAC_5GTF_UPDATE
5238 } /* end of rgSCHUtlUpdSch */
5241 * @brief Handler for Updating Bo received in StaRsp
5245 * Function : rgSCHUtlAddUeToCcchSduLst
5247 * This function shall be invoked once it receives staRsp on CCCH
5249 * @param[in] RgSchCellCb *cell
5250 * @param[in] RgSchUeCb *ueCb
5254 S16 rgSCHUtlAddUeToCcchSduLst(RgSchCellCb *cell,RgSchUeCb *ueCb)
5256 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ueCb, cell);
5257 RgSchDlHqProcCb *hqP = (RgSchDlHqProcCb *)ueDl->proc;
5259 /* Temp Guard: For back to back CCCH SDU BO
5260 * twice. Hence an extra guard. If already added to scheduling
5261 * queue or if scheduled and waiting for HQ FDBK, ignore */
5262 if ((ueCb->ccchSduLnk.node) ||
5263 ((!(ueCb->dl.dlInactvMask & RG_HQENT_INACTIVE)) &&
5264 ((hqP != NULLP) && (hqP->hqE->ccchSduProc))))
5266 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"RNTI:%d Unexpected CCCH SDU BO",
5271 ueCb->ccchSduLnk.node = (PTR)(ueCb);
5272 cmLListAdd2Tail(&(cell->ccchSduUeLst), &(ueCb->ccchSduLnk));
5280 * Function : rgSCHUtlUpdtBo
5282 * This function shall be invoked once it receives staRsp on CCCH
5284 * @param[in] RgSchCellCb *cell
5285 * @param[in] RgRguCmnStaRsp *staRsp
5289 S16 rgSCHUtlUpdtBo(RgSchCellCb *cell,RgInfCmnBoRpt *staRsp)
5293 if ((ueCb = rgSCHDbmGetUeCb(cell, staRsp->u.rnti)) == NULLP)
5295 /* Handle Ue fetch failure */
5296 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Invalid UEID:%d",staRsp->u.rnti);
5299 /* Update Bo in ueCb */
5300 ueCb->dlCcchInfo.bo = (uint32_t)(staRsp->bo);
5304 rgSCHUtlAddUeToEmtcCcchSduLst(cell,ueCb);
5309 rgSCHUtlAddUeToCcchSduLst(cell, ueCb);
5313 } /* rgSCHUtlUpdtBo */
5319 * Function : rgSCHUtlHndlCcchBoUpdt
5321 * This function shall fetch the raCb with the given rnti and ask RAM to
5325 * @param[in] RgSchCellCb *cell
5326 * @param[in] RgInfCmnBoRpt *boRpt
5331 S16 rgSCHUtlHndlCcchBoUpdt(RgSchCellCb *cell,RgInfCmnBoRpt *boRpt)
5336 if ((raCb = rgSCHDbmGetRaCb(cell, boRpt->u.rnti)) == NULLP)
5339 /* CR timer implementation changes*/
5340 /*If no raCb, schedule ueCb, ueCb is extracted in rgSCHUtlUpdtBo*/
5341 return (rgSCHUtlUpdtBo(cell, boRpt));
5343 /* Handle RaCb fetch failure */
5344 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
5345 "Invalid RNTI:%d to fetch raCb",boRpt->u.rnti);
5352 /*Fix: If RaCb exists, then MSG4 is not completed yet*/
5353 /*Check if guard timer has expired, if not CR CE + CCCH SDU will be scheduled*/
5354 if((raCb->contResTmrLnk.node != NULLP) && \
5355 (raCb->schdLnk.node == NULLP) && (raCb->dlHqE->msg4Proc == NULLP))
5358 /*if contention resolution timer left ,Stop the Contention Resolution Guard Timer ,
5359 add in toBeSchduled list and update the Bo */
5360 if(TRUE == raCb->isEmtcRaCb)
5362 rgSCHRamEmtcUpdtBo(cell, raCb, boRpt);
5367 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
5368 raCb->contResTmrLnk.node=NULLP;
5369 rgSCHRamUpdtBo(cell, raCb, boRpt);
5374 /*Fix:Guard timer has expired */
5375 /*Update the BO in UE CB but dont add it to the scheduling list.
5376 *Should be added to the list after MSG4 completion*/
5377 if ((ueCb = rgSCHDbmGetUeCb(cell, boRpt->u.rnti)) == NULLP)
5379 /* Handle Ue fetch failure */
5380 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Invalid RNTI:%d",boRpt->u.rnti);
5383 /* Update Bo in ueCb */
5384 ueCb->dlCcchInfo.bo = (uint32_t)(boRpt->bo);
5388 rgSCHRamUpdtBo(cell, raCb, boRpt);
5392 } /* rgSCHUtlHndlCcchBoUpdt */
5395 * @brief Validates BO received for BCCH or PCCH.
5399 * Function : rgSCHUtlGetAllwdCchTbSz
5401 * This function shall return the tbSz equal to or
5402 * the nearest greater value for a given bo.
5403 * If no such value found return -1. The nPrb value is
5407 * @param[in] uint32_t bo
5408 * @param[out] uint8_t *nPrb
5413 S32 rgSCHUtlGetAllwdCchTbSz(uint32_t bo,uint8_t *nPrb,uint8_t *mcs)
5419 for (lt = 0, rt = 43; lt <= rt;)
5422 if (rgSchUtlBcchPcchTbSzTbl[cn].tbSz == bo)
5424 *nPrb = rgSchUtlBcchPcchTbSzTbl[cn].rbIndex;
5425 *mcs = rgSchUtlBcchPcchTbSzTbl[cn].mcs;
5426 return (rgSchUtlBcchPcchTbSzTbl[cn].tbSz);
5428 else if (rgSchUtlBcchPcchTbSzTbl[cn].tbSz < bo)
5437 *nPrb = rgSchUtlBcchPcchTbSzTbl[lt].rbIndex;
5438 *mcs = rgSchUtlBcchPcchTbSzTbl[lt].mcs;
5439 return (rgSchUtlBcchPcchTbSzTbl[lt].tbSz);
5443 * @brief Handler for BO Updt received for BCCH or PCCH.
5447 * Function : rgSCHUtlHndlBcchPcchBoUpdt
5449 * This function shall store the buffer and time to transmit in lcCb
5452 * @param[in] RgSchCellCb *cell
5453 * @param[in] RgInfCmnBoRpt *boRpt
5458 S16 rgSCHUtlHndlBcchPcchBoUpdt(RgSchCellCb *cell,RgInfCmnBoRpt *boUpdt)
5460 RgSchClcDlLcCb *dlLc;
5461 RgSchClcBoRpt *boRpt;
5462 Inst inst = cell->instIdx;
5466 dlLc = rgSCHDbmGetBcchOnBch(cell);
5469 RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,
5470 "No Logical Channel dlLc is NULLP for RNTI:%d LCID:%d",boUpdt->u.rnti,boUpdt->lcId);
5473 if (boUpdt->lcId != dlLc->lcId)
5475 /* Added for dropping paging Message*/
5477 if ((rgSCHChkBoUpdate(cell,boUpdt))== ROK) /* Checking if received BO falls within the window of 5120 slots*/
5479 if (rgSCHUtlGetAllwdCchTbSz(boUpdt->bo*8, &nPrb, &mcs)
5482 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId,"[%ld]BO: does not match any "
5483 "valid TB Size RNTI:%d LCID:%d", boUpdt->bo,boUpdt->u.rnti,boUpdt->lcId);
5486 }/*end of rgSCHChkBoUpdate*/
5492 if ((dlLc = rgSCHDbmGetCmnLcCb(cell, boUpdt->lcId)) == NULLP)
5494 /* Handle lcCb fetch failure */
5495 RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId,
5496 "LCID:%d Invalid for RNTI:%d",boUpdt->lcId,boUpdt->u.rnti);
5499 if (((rgSCHUtlAllocSBuf(inst, (Data **)(&boRpt), sizeof(RgSchClcBoRpt))) ==RFAILED) ||
5502 RLOG_ARG3(L_ERROR,DBG_CELLID,cell->cellId, "Allocation of common bo %dreport "
5503 "failed RNTI:%d LCID:%d", boUpdt->bo,boUpdt->u.rnti,boUpdt->lcId);
5507 boRpt->bo = boUpdt->bo;
5509 boRpt->timeToTx = boUpdt->u.timeToTx;
5512 if(cell->emtcEnable)
5514 boRpt->emtcDIReason = boUpdt->emtcDIReason;
5515 boRpt->pnb = boUpdt->pnb;
5518 RG_SCH_ADD_TO_CRNT_TIME(boRpt->timeToTx,
5519 boRpt->maxTimeToTx, cell->siCfg.siWinSize)
5520 if((NULLP != dlLc) && (dlLc->si))
5522 boRpt->retxCnt = cell->siCfg.retxCnt;
5528 rgSCHDbmInsCmnLcBoRpt(dlLc, boRpt);
5531 } /* rgSCHUtlHndlBcchPcchBoUpdt */
5534 * @brief API for sending bind confirm from Scheduler instance to RRM
5538 * Function: rgSCHUtlRgrBndCfm
5540 * This API is invoked to send bind confirm from Scheduler instance to RRM.
5541 * This API fills in Pst structure and SAP Ids and invokes
5542 * bind confirm API towards RRM.
5544 * @param[in] SuId suId
5545 * @param[in] uint8_t status
5550 S16 rgSCHUtlRgrBndCfm(Inst instId,SuId suId,uint8_t status)
5554 ret = RgUiRgrBndCfm(&rgSchCb[instId].rgrSap[suId].sapCfg.sapPst, rgSchCb[instId].rgrSap[suId].sapCfg.suId, status);
5557 RLOG_ARG0(L_ERROR,DBG_INSTID,instId,"rgSCHUtlRgrBndCfm: RgUiRgrBndCfm Failed ");
5561 } /* rgSCHUtlRgrBndCfm*/
5564 * @brief API for sending bind confirm from Scheduler instance to RRM via RGM
5569 * Function: rgSCHUtlRgmBndCfm
5571 * This API is invoked to send bind confirm from Scheduler instance to RRM.
5572 * This API fills in Pst structure and SAP Ids and invokes
5574 * @param[in] SuId suId
5575 * @param[in] uint8_t status
5580 S16 rgSCHUtlRgmBndCfm(Inst instId,SuId suId,uint8_t status)
5584 ret = RgUiRgmBndCfm(&rgSchCb[instId].rgmSap[suId].sapCfg.sapPst, rgSchCb[instId].rgmSap[suId].sapCfg.suId, status);
5587 RLOG_ARG0(L_ERROR,DBG_INSTID,instId,"rgSCHUtlRgmBndCfm: RgUiRgrBndCfm Failed ");
5591 } /* rgSCHUtlRgmBndCfm*/
5596 * @brief API for sending configuration confirm from Scheduler to DU APP
5600 * Function: schSendCfgCfm
5602 * This API is invoked to send configuration confirm from Scheduler to DU
5605 * @param[in] Pst pst
5606 * @param[in] RgrCfgTransId transId
5607 * @param[in] uint8_t status
5612 S16 schSendCfgCfm(Region reg,Pool pool,RgrCfgTransId transId,uint8_t status)
5617 memset((&cfmPst), 0, sizeof(Pst));
5619 cfmPst.srcEnt = (Ent)ENTDUAPP;
5620 cfmPst.srcInst = (Inst) 0;
5621 cfmPst.srcProcId = SFndProcId();
5622 cfmPst.dstEnt = (Ent)ENTMAC;
5623 cfmPst.dstInst = (Inst) 0;
5624 cfmPst.dstProcId = SFndProcId();
5625 cfmPst.selector = ODU_SELECTOR_LC;
5626 cfmPst.region = reg;
5629 if(RgUiRgrCfgCfm(&cfmPst,transId, status) != ROK)
5631 RLOG_ARG0(L_ERROR,DBG_INSTID,inst,"schSendCfgCfm: RgUiRgrCfgCfm Failed");
5632 printf("\nschSendCfgCfm: RgUiRgrCfgCfm Failed ");
5636 } /* schSendCfgCfm*/
5639 * @brief API for sending TTI indication from Scheduler to RRM.
5643 * Function: rgSCHUtlRgrTtiInd
5645 * This API is invoked to send TTI indication from Scheduler instance to RRM.
5646 * This API fills in Pst structure and RgrTtiIndInfo
5648 * @param[in] cell RgSchCellCb
5649 * @param[in] CmLteTimingInfo status
5654 S16 rgSCHUtlRgrTtiInd(RgSchCellCb *cell,RgrTtiIndInfo *rgrTti)
5657 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
5660 Void mtTmrHdlrPublic(void);
5663 rgrSap = cell->rgrSap;
5664 if (rgrSap->sapSta.sapState != LRG_BND)
5666 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
5667 "rgSCHUtlRgrTtiInd() Upper SAP not bound (%d) ",
5668 rgrSap->sapSta.sapState);
5671 RgUiRgrTtiInd(&(cell->rgrSap->sapCfg.sapPst),
5672 cell->rgrSap->sapCfg.suId, rgrTti);
5680 } /* rgSCHUtlRgrTtiInd*/
5682 /** @brief This function is called by rgMacSchSfRecpInd. This function invokes the
5683 * scheduler with the information of the received Data and any Control Elements
5691 * - Retrieves the RaCb with the rnti provided, if it doesnt exist
5693 * - If UE exists then update the Schduler with any MAC CEs if present.
5694 * - Invoke RAM module to do Msg3 related processing rgSCHRamProcMsg3
5696 * @param [in] RgSchCellCb *cellCb
5697 * @param [in] RgSchUeCb *ueCb
5698 * @param [in] CmLteRnti rnti
5699 * @param [in] RgMacPdu *pdu
5700 * @param [in] RgSchErrInfo *err
5706 S16 rgSCHUtlProcMsg3
5708 RgInfSfDatInd *subfrmInfo,
5709 RgSchCellCb *cellCb,
5719 /* must have an raCb for this case */
5720 raCb = rgSCHDbmGetRaCb (cellCb, rnti);
5723 RLOG_ARG1(L_ERROR,DBG_CELLID,cellCb->cellId, "RNTI:%d Received MSG3, unable to "
5728 /* ccpu00130982: Processing CRNTI MAC CE before Short BSR, if any, such that
5729 * effBsr of current case only will be considered in scheduling of ContResLst*/
5730 ret = rgSCHRamProcMsg3 (cellCb, ueCb, raCb, pdu, err);
5733 RLOG_ARG1(L_ERROR,DBG_CELLID,cellCb->cellId,"Processing failed in the RAM "
5737 /* if ueCb is present */
5740 rgSCHUtlUpdSch (subfrmInfo, cellCb, ueCb, pdu, err);
5746 /** @brief This function is called by RgMacSchSpsRelInd. This function invokes the
5747 * scheduler with the information of the received Data.
5751 * Function: rgSCHUtlSpsRelInd
5756 * @param [in] RgSchCellCb *cellCb
5757 * @param [in] RgSchUeCb *ueCb
5758 * @param [in] Bool *isExplRel
5764 S16 rgSCHUtlSpsRelInd(RgSchCellCb *cellCb,RgSchUeCb *ueCb,Bool isExplRel)
5766 cellCb->sc.apis->rgSCHUlSpsRelInd(cellCb, ueCb, isExplRel);
5768 } /* end of rgSCHUtlSpsRelInd */
5771 /** @brief This function is called by RgMacSchSpsRelInd. This function invokes the
5772 * scheduler with the information of the received Data.
5776 * Function: rgSCHUtlSpsActInd
5781 * @param [in] RgSchCellCb *cellCb
5782 * @param [in] RgSchUeCb *ueCb
5783 * @param [in] uint16_t spsSduSize
5789 S16 rgSCHUtlSpsActInd(RgSchCellCb *cellCb,RgSchUeCb *ueCb,uint16_t spsSduSize)
5791 cellCb->sc.apis->rgSCHUlSpsActInd(cellCb, ueCb, spsSduSize);
5793 } /* end of rgSCHUtlSpsActInd */
5796 #endif /* LTEMAC_SPS */
5800 * @brief This API is invoked to send uplink group power control request to PHY.
5804 * Function : rgSCHUtlTfuGrpPwrCntrlReq
5806 * This API is invoked to send uplink group power control request to PHY.
5807 * It fills in the Pst structure, spId value and invokes group power
5808 * control request primitive at TFU.
5810 * @param[in] TfuGrpPwrCntrlReqInfo *grpPwrCntrlReq
5815 S16 rgSCHUtlTfuGrpPwrCntrlReq(Inst inst,S16 sapId,TfuGrpPwrCntrlReqInfo *grpPwrCntrlReq)
5818 RgSchLowSapCb *tfuSap;
5821 /* Get the lower SAP control block from the layer control block. */
5822 tfuSap = &(rgSchCb[inst].tfuSap[sapId]);
5823 if (tfuSap->sapSta.sapState != LRG_BND)
5825 RLOG_ARG1(L_ERROR,DBG_CELLID,grpPwrCntrlReq->cellId,
5826 "rgSCHUtlTfuGrpPwrCntrlReq() Lower SAP not bound (%d) ",tfuSap->sapSta.sapState);
5829 memcpy (&pst, &(tfuSap->sapCfg.sapPst), sizeof(Pst));
5830 if((ret = RgLiTfuGrpPwrCntrlReq (&pst, tfuSap->sapCfg.spId, grpPwrCntrlReq)) != ROK)
5832 RLOG_ARG0(L_ERROR,DBG_CELLID,grpPwrCntrlReq->cellId,
5833 "rgSCHUtlTfuGrpPwrCntrlReq() Call to RgLiTfuGrpPwrCntrlReq() failed");
5836 } /* rgSCHUtlTfuGrpPwrCntrlReq */
5839 /* FOR ACK NACK REP */
5842 * @brief This API is invoked to tell the DL Scheduler to add the UE back into
5843 * its scheduling queues.
5847 * Function : rgSCHUtlDlActvtUe
5849 * This API is invoked from Measurement gap moduled.
5851 * @param[in] RgSchCellCb *cell
5852 * @param[in] RgSchUeCb *ueCb
5858 S16 rgSCHUtlDlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
5860 cell->sc.apis->rgSCHActvtDlUe(cell, ue);
5865 * @brief This API is invoked to tell the UL Scheduler to add the UE back into
5866 * its scheduling queues.
5870 * Function : rgSCHUtlUlActvtUe
5872 * This API is invoked from Measurement gap moduled.
5874 * @param[in] RgSchCellCb *cell
5875 * @param[in] RgSchUeCb *ueCb
5881 S16 rgSCHUtlUlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
5883 cell->sc.apis->rgSCHActvtUlUe(cell, ue);
5887 /** @brief This function Validates the SAP information received along with the
5888 * primitive from the lower layer.
5890 * Function: rgSCHUtlValidateTfuSap
5892 * Validates SAP information.
5893 * @param suId The SAP Id
5898 S16 rgSCHUtlValidateTfuSap(Inst inst,SuId suId)
5900 RgSchLowSapCb *tfuSap;
5902 if(suId >= rgSchCb[inst].numSaps)
5904 RLOG_ARG0(L_ERROR,DBG_INSTID,inst, "Incorrect SuId");
5907 tfuSap = &(rgSchCb[inst].tfuSap[suId]);
5909 /* First lets check the suId */
5910 if( suId != tfuSap->sapCfg.suId)
5912 RLOG_ARG2(L_ERROR,DBG_INSTID,inst,"Incorrect SuId. Configured (%d) Recieved (%d)",
5913 tfuSap->sapCfg.suId, suId);
5916 if (tfuSap->sapSta.sapState != LRG_BND)
5918 RLOG_ARG1(L_ERROR,DBG_INSTID,inst,"Lower SAP not enabled SuId (%d)",
5919 tfuSap->sapCfg.suId);
5923 } /* end of rgSCHUtlValidateTfuSap */
5927 * Fun: rgSCHUtlAllocEventMem
5929 * Desc: This function allocates event memory
5931 * Ret: ROK - on success
5932 * RFAILED - on failure
5939 S16 rgSCHUtlAllocEventMem(Inst inst,Ptr *memPtr,Size memSize)
5942 volatile uint32_t startTime=0;
5945 sMem.region = rgSchCb[inst].rgSchInit.region;
5946 sMem.pool = rgSchCb[inst].rgSchInit.pool;
5948 #if (ERRCLASS & ERRCLS_DEBUG)
5951 RGSCHLOGERROR(inst, ERRCLS_INT_PAR, ERG022, memSize,
5952 "rgAllocEventMem(): memSize invalid\n");
5955 #endif /* ERRCLASS & ERRCLS_DEBUG */
5957 SStartTask(&startTime, PID_SCHUTL_CMALLCEVT);
5959 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
5960 MS_BUF_ADD_ALLOC_CALLER();
5962 #ifdef TFU_ALLOC_EVENT_NO_INIT
5963 if(ROK != cmAllocEvntNoInit(memSize, TFU_MAX_MEMBLK_SIZE, &sMem, memPtr))
5965 if(ROK != cmAllocEvnt(memSize, TFU_MAX_MEMBLK_SIZE, &sMem, memPtr))
5968 RLOG_ARG0(L_ERROR,DBG_INSTID,inst,"cmAllocEvnt Failed.");
5972 SStopTask(startTime, PID_SCHUTL_CMALLCEVT);
5974 } /* end of rgSCHUtlAllocEventMem*/
5978 * Fun: rgGetEventMem
5980 * Desc: This function allocates event memory
5982 * Ret: ROK - on success
5983 * RFAILED - on failure
5990 S16 rgSCHUtlGetEventMem(Ptr *ptr,Size len,Ptr memCp)
5994 #ifdef TFU_ALLOC_EVENT_NO_INIT
5995 ret = cmGetMemNoInit(memCp, len, (Ptr *)ptr);
5997 ret = cmGetMem(memCp, len, (Ptr *)ptr);
6000 } /* end of rgSCHUtlGetEventMem*/
6006 * @brief Handler to allocate memory for ACK/NACk feedback information
6010 * Function : rgSCHUtlAllocUeANFdbkInfo
6012 * It allocates memory for the UE related ACK NACK information.
6014 * @param[in] RgSchUeCb *ue
6017 S16 rgSCHUtlAllocUeANFdbkInfo(RgSchUeCb *ue,uint8_t servCellIdx)
6021 if (rgSCHUtlAllocSBuf(ue->cell->instIdx,
6022 (Data **) &(ue->cellInfo[servCellIdx]->anInfo), sizeof(RgSchTddANInfo) * \
6023 ue->cell->ackNackFdbkArrSize) != ROK)
6028 for(idx=0; idx < ue->cell->ackNackFdbkArrSize; idx++)
6030 rgSCHUtlInitUeANFdbkInfo(&ue->cellInfo[servCellIdx]->anInfo[idx]);
6033 /* Set it to the first index */
6034 ue->cellInfo[servCellIdx]->nextFreeANIdx = 0;
6036 } /* rgSCHUtlAllocUeANFdbkInfo */
6039 * @brief Handler to release memory for ACK/NACk feedback information
6043 * Function : rgSCHUtlDelUeANFdbkInfo
6045 * It releases memory for the UE related ACK NACK information.
6047 * @param[in] RgSchUeCb *ue
6050 Void rgSCHUtlDelUeANFdbkInfo(RgSchUeCb *ue,uint8_t servCellIdx)
6053 /* ccpu00117052 - MOD - Passing double pointer
6054 for proper NULLP assignment*/
6055 rgSCHUtlFreeSBuf(ue->cell->instIdx,
6056 (Data **)(&( ue->cellInfo[servCellIdx]->anInfo)), sizeof(RgSchTddANInfo) * \
6057 ue->cell->ackNackFdbkArrSize);
6060 } /* rgSCHUtlDelUeANFdbkInfo */
6063 * @brief Handler to initialise UE ACK/NACk feedback information
6067 * Function : rgSCHUtlInitUeANFdbkInfo
6069 * It initialises UE related ACK NACK information.
6071 * @param[in] RgSchTddANInfo *anFdInfo
6074 S16 rgSCHUtlInitUeANFdbkInfo(RgSchTddANInfo *anFdInfo)
6077 anFdInfo->sfn = RGSCH_MAX_SFN+1; /* defensively setting invalid sfn */
6079 anFdInfo->ulDai = RG_SCH_INVALID_DAI_VAL;
6080 anFdInfo->dlDai = RG_SCH_INVALID_DAI_VAL;
6081 anFdInfo->latestMIdx = RG_SCH_INVALID_M_VAL;
6084 } /* rgSCHUtlInitUeANFdbkInfo */
6087 * @brief Handler to get UE related ACK NACK feedback information
6091 * Function : rgSCHUtlGetUeANFdbkInfo
6093 * It gets the UE related ACK NACK information based on
6094 * SFN and slot number.
6096 * @param[in] RgSchUeCb *ueCb
6097 * @param[in] CmLteTimingInfo *time
6098 * @return RgSchTddANInfo*
6100 RgSchTddANInfo* rgSCHUtlGetUeANFdbkInfo(RgSchUeCb *ueCb,CmLteTimingInfo *timeInfo,uint8_t servCellIdx)
6104 for (idx = 0; idx < ueCb->cell->ackNackFdbkArrSize; ++idx)
6106 if( (timeInfo->sfn == ueCb->cellInfo[servCellIdx]->anInfo[idx].sfn) &&
6107 (timeInfo->slot == ueCb->cellInfo[servCellIdx]->anInfo[idx].slot))
6109 return (&ueCb->cellInfo[servCellIdx]->anInfo[idx]);
6114 } /* rgSCHUtlGetUeANFdbkInfo */
6117 * @brief To get downlink slot index
6121 * Function: rgSCHUtlGetDlSfIdx
6122 * Purpose: Gets downlink slot index based on SFN and slot no
6124 * @param[in] CmLteTimingInfo *timeInfo
6125 * @param[in] RgSchCellCb *cell
6129 uint8_t rgSCHUtlGetDlSfIdx(RgSchCellCb *cell,CmLteTimingInfo *timeInfo)
6133 idx = RGSCH_NUM_SUB_FRAMES - \
6134 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
6135 idx = ((idx * timeInfo->sfn) + \
6136 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][timeInfo->slot]) - 1;
6137 idx = idx % cell->numDlSubfrms;
6139 return ((uint8_t)idx);
6143 * @brief To get the next downlink slot
6147 * Function: rgSCHUtlGetNxtDlSfInfo
6148 * Purpose: Gets next downlink slot based on current DL slot
6150 * @param[in] CmLteTimingInfo curDlTime
6151 * @param[in] RgSchCellCb *cell
6152 * @param[in] RgSchDlSf *dlSf
6153 * @param[in] RgSchDlSf **nxtDlsf
6154 * @param[in] CmLteTimingInfo *nxtDlTime
6158 Void rgSCHUtlGetNxtDlSfInfo(CmLteTimingInfo curDlTime,RgSchCellCb *cell,RgSchDlSf *dlSf,RgSchDlSf **nxtDlsf,CmLteTimingInfo *nxtDlTime)
6160 uint16_t idx = curDlTime.slot;
6167 idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
6169 }while(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
6170 != RG_SCH_TDD_DL_slot);
6171 RG_SCH_ADD_TO_CRNT_TIME(curDlTime, (*nxtDlTime), count);
6172 *nxtDlsf = rgSCHUtlSubFrmGet(cell, *nxtDlTime);
6173 if(dlSf->dlFdbkInfo.slot != (*nxtDlsf)->dlFdbkInfo.slot)
6182 * @brief To get the previous downlink slot
6186 * Function: rgSCHUtlGetPrevDlSfInfo
6187 * Purpose: Gets previous downlink slot based on current DL slot
6189 * @param[in] RgSchCellCb *cell
6190 * @param[in] CmLteTimingInfo curDlTime
6191 * @param[in] CmLteTimingInfo *prevDlTime
6192 * @param[in] uint8_t *numSubfrm
6196 Void rgSCHUtlGetPrevDlSfInfo(RgSchCellCb *cell,CmLteTimingInfo curDlTime,CmLteTimingInfo *prevDlTime,uint8_t *numSubfrm)
6198 S16 idx = curDlTime.slot;
6206 idx = RGSCH_NUM_SUB_FRAMES-1;
6209 }while(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
6210 != RG_SCH_TDD_DL_slot);
6212 RGSCHDECRFRMCRNTTIME(curDlTime, (*prevDlTime), count);
6217 /* Added Holes Management functions for Adaptive Re transmission */
6218 /******* </AllocHolesMemMgmnt>: START *****/
6219 /***********************************************************
6221 * Func : rgSCHUtlUlSfInit
6223 * Desc : UL slot init.
6231 **********************************************************/
6232 S16 rgSCHUtlUlSfInit(RgSchCellCb *cell,RgSchUlSf *sf,uint8_t idx,uint8_t maxUePerSf)
6242 if(cell->ulDlCfgIdx == 0)
6244 /* Store the Uplink slot number corresponding to the idx */
6245 sf->ulSfIdx = rgSchTddCfg0UlSfTbl[idx%6];
6248 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf->allocDb,
6249 sizeof(RgSchUlAllocDb));
6254 ret = rgSCHUtlUlAllocDbInit(cell, sf->allocDb, maxUePerSf);
6257 /* ccpu00117052 - MOD - Passing double pointer
6258 for proper NULLP assignment*/
6259 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6260 sizeof(RgSchUlAllocDb));
6263 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf->holeDb,
6264 sizeof(RgSchUlHoleDb));
6267 rgSCHUtlUlAllocDbDeinit(cell, sf->allocDb);
6268 /* ccpu00117052 - MOD - Passing double pointer
6269 for proper NULLP assignment*/
6270 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6271 sizeof(RgSchUlAllocDb));
6274 /* Initialize the hole with CFI 1 Pusch Bw Info */
6275 ret = rgSCHUtlUlHoleDbInit(cell, sf->holeDb, (uint8_t)(maxUePerSf + 2), \
6276 0, cell->dynCfiCb.bwInfo[1].numSb);
6280 rgSCHUtlUlAllocDbDeinit(cell, sf->allocDb);
6281 /* ccpu00117052 - MOD - Passing double pointer
6282 for proper NULLP assignment*/
6283 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6284 sizeof(RgSchUlAllocDb));
6285 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->holeDb)),
6286 sizeof(RgSchUlHoleDb));
6289 cmLListInit(&sf->reTxLst);
6291 /* Fix ccpu00120610*/
6292 sf->allocCountRef = &sf->allocDb->count;
6294 /* initialize UL available subbands for current sub-frame */
6295 sf->availSubbands = cell->dynCfiCb.bwInfo[1].numSb;
6297 sf->numGrpPerTti = cell->cell5gtfCb.ueGrpPerTti;
6298 sf->numUePerGrp = cell->cell5gtfCb.uePerGrpPerTti;
6299 for(index = 0; index < MAX_5GTF_BEAMS; index++)
6301 sf->sfBeamInfo[index].totVrbgAllocated = 0;
6302 sf->sfBeamInfo[index].totVrbgRequired = 0;
6303 sf->sfBeamInfo[index].vrbgStart = 0;
6311 /***********************************************************
6313 * Func : rgSCHUtlUlSfDeinit
6315 * Desc : Deinitialises a slot
6323 **********************************************************/
6324 Void rgSCHUtlUlSfDeinit(RgSchCellCb *cell,RgSchUlSf *sf)
6328 rgSCHUtlUlAllocDbDeinit(cell, sf->allocDb);
6329 /* ccpu00117052 - MOD - Passing double pointer
6330 for proper NULLP assignment*/
6331 /* ccpu00117052 - MOD - Passing double pointer
6332 for proper NULLP assignment*/
6333 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6334 sizeof(RgSchUlAllocDb));
6338 rgSCHUtlUlHoleDbDeinit(cell, sf->holeDb);
6339 /* ccpu00117052 - MOD - Passing double pointer
6340 for proper NULLP assignment*/
6341 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->holeDb)),
6342 sizeof(RgSchUlHoleDb));
6347 /***********************************************************
6349 * Func : rgSCHUtlUlAllocDbInit
6351 * Desc : Initialise allocation DB
6353 * Ret : S16 (ROK/RFAILED)
6359 **********************************************************/
6360 static S16 rgSCHUtlUlAllocDbInit(RgSchCellCb *cell,RgSchUlAllocDb *allocDb,uint8_t maxAllocs)
6362 S16 ret = rgSCHUtlUlAllocMemInit(cell, &allocDb->mem, maxAllocs);
6368 allocDb->first = NULLP;
6372 /***********************************************************
6374 * Func : rgSCHUtlUlAllocDbDeinit
6376 * Desc : Deinitialises allocation DB
6377 * sent to UE, for a UE with accumulation disabled
6385 **********************************************************/
6386 static Void rgSCHUtlUlAllocDbDeinit(RgSchCellCb *cell,RgSchUlAllocDb *allocDb)
6388 rgSCHUtlUlAllocMemDeinit(cell, &allocDb->mem);
6390 allocDb->first = NULLP;
6394 /***********************************************************
6396 * Func : rgSCHUtlUlHoleDbInit
6398 * Desc : Initialise hole DB
6400 * Ret : S16 (ROK/RFAILED)
6406 **********************************************************/
6407 static S16 rgSCHUtlUlHoleDbInit(RgSchCellCb *cell,RgSchUlHoleDb *holeDb,uint8_t maxHoles,uint8_t start,uint8_t num)
6410 RgSchUlHole *hole = NULLP;
6412 ret = rgSCHUtlUlHoleMemInit(cell, &holeDb->mem, maxHoles, &hole);
6418 holeDb->first = hole;
6419 hole->start = start;
6421 hole->prv = hole->nxt = NULLP;
6425 /***********************************************************
6427 * Func : rgSCHUtlUlHoleDbDeinit
6429 * Desc : Deinitialises hole DB
6437 **********************************************************/
6438 static Void rgSCHUtlUlHoleDbDeinit(RgSchCellCb *cell,RgSchUlHoleDb *holeDb)
6440 rgSCHUtlUlHoleMemDeinit(cell, &holeDb->mem);
6442 holeDb->first = NULLP;
6447 /***********************************************************
6449 * Func : rgSCHUtlUlAllocGetHole
6451 * Desc : Get allocation from hole
6453 * Ret : RgSchUlAlloc *
6459 **********************************************************/
6460 RgSchUlAlloc *rgSCHUtlUlAllocGetHole(RgSchUlSf *sf,uint8_t numSb,RgSchUlHole *hole)
6462 if (numSb < hole->num)
6464 return (rgSCHUtlUlAllocGetPartHole(sf, numSb, hole));
6468 return (rgSCHUtlUlAllocGetCompHole(sf, hole));
6473 /***********************************************************
6475 * Func : rgSCHUtlUlAllocGetCompHole
6477 * Desc : Get an allocation corresponding to an entire hole
6479 * Ret : RgSchUlAlloc *
6485 **********************************************************/
6486 RgSchUlAlloc *rgSCHUtlUlAllocGetCompHole(RgSchUlSf *sf,RgSchUlHole *hole)
6488 RgSchUlAlloc *alloc;
6489 /* alloc = rgSCHUtlUlAllocGetAndIns(sf->allocDb, hole->prvAlloc, hole->nxtAlloc); */
6490 /* Calling rgSchCmnUlAllocGetAndIns is ok, but prv alloc needs to have nxtHole
6491 * updated, causing another check for prv */
6492 RgSchUlAlloc *prv = hole->prvAlloc;
6493 RgSchUlAlloc *nxt = hole->nxtAlloc;
6497 if (hole->start == prv->nxtHole->start)
6499 prv->nxtHole = NULLP;
6501 alloc = rgSCHUtlUlAllocGetAdjNxt(sf->allocDb, prv);
6505 alloc = rgSCHUtlUlAllocGetFirst(sf->allocDb);
6508 RGSCH_NULL_CHECK( 0, alloc);
6509 alloc->prvHole = NULLP;
6510 alloc->nxtHole = NULLP;
6512 alloc->sbStart = hole->start;
6513 alloc->numSb = hole->num;
6517 nxt->prvHole = NULLP;
6520 rgSCHUtlUlHoleRls(sf->holeDb, hole);
6522 /* UL_ALLOC_CHANGES*/
6523 alloc->allocDbRef = (void*)sf->allocDb;
6524 alloc->holeDbRef = (void*)sf->holeDb;
6528 /***********************************************************
6530 * Func : rgSCHUtlUlAllocGetPartHole
6532 * Desc : Get an allocation corresponding to a part of a hole.
6533 * The initial 'numSb' part of the hole shall be taken
6534 * away for this alloc.
6536 * Ret : RgSchUlAlloc *
6542 **********************************************************/
6543 RgSchUlAlloc *rgSCHUtlUlAllocGetPartHole(RgSchUlSf *sf,uint8_t numSb,RgSchUlHole *hole)
6545 RgSchUlAlloc *alloc;
6546 /* alloc = rgSCHUtlUlAllocGetAndIns(sf->allocDb, hole->prvAlloc, hole->nxtAlloc); */
6547 /* Calling rgSchCmnUlAllocGetAndIns is ok, but prv alloc needs to have nxtHole
6548 * updated, causing another check for prv */
6549 RgSchUlAlloc *prv = hole->prvAlloc;
6553 if (hole->start == prv->nxtHole->start)
6555 prv->nxtHole = NULLP;
6557 alloc = rgSCHUtlUlAllocGetAdjNxt(sf->allocDb, prv);
6561 alloc = rgSCHUtlUlAllocGetFirst(sf->allocDb);
6564 RGSCH_NULL_CHECK( 0, alloc);
6565 alloc->prvHole = NULLP;
6566 alloc->nxtHole = hole;
6567 hole->prvAlloc = alloc;
6569 alloc->sbStart = hole->start;
6570 alloc->numSb = numSb;
6571 hole->start += numSb;
6574 rgSCHUtlUlHoleDecr(sf->holeDb, hole);
6576 /* UL_ALLOC_CHANGES*/
6577 alloc->allocDbRef = (void*)sf->allocDb;
6578 alloc->holeDbRef = (void*)sf->holeDb;
6583 /***********************************************************
6585 * Func : rgSCHUtlUlAllocFirst
6587 * Desc : Get first alloc in slot
6589 * Ret : RgSchUlAlloc *
6595 **********************************************************/
6596 RgSchUlAlloc *rgSCHUtlUlAllocFirst(RgSchUlSf *sf)
6598 return (sf->allocDb->first);
6601 /***********************************************************
6603 * Func : rgSCHUtlUlAllocNxt
6605 * Desc : Get next alloc
6607 * Ret : RgSchUlAlloc *
6613 **********************************************************/
6614 RgSchUlAlloc *rgSCHUtlUlAllocNxt(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6617 return (alloc->nxt);
6620 /***********************************************************
6622 * Func : rgSCHUtlUlAllocGetAdjNxt
6624 * Desc : Get alloc which is immediately after the passed one.
6625 * 1. Gets alloc from mem.
6626 * 2. Inserts alloc into list (between prv and
6627 * prv->nxt, prv is not NULLP).
6628 * 3. Increments alloc count.
6629 * Note 1: Holes are not dealt with here.
6630 * Note 2: Assumes prv to be NULL.
6632 * Ret : RgSchUlAlloc *
6638 **********************************************************/
6639 RgSchUlAlloc *rgSCHUtlUlAllocGetAdjNxt(RgSchUlAllocDb *db,RgSchUlAlloc *prv)
6641 RgSchUlAlloc *alloc = rgSCHUtlUlAllocMemGet(&db->mem);
6642 RgSchUlAlloc *nxt = prv->nxt;
6644 #if (ERRCLASS & ERRCLS_DEBUG)
6645 if ( alloc == NULLP )
6663 /***********************************************************
6665 * Func : rgSCHUtlUlAllocGetFirst
6667 * Desc : Get alloc which is to be the first one in the alloc list
6668 * 1. Gets alloc from mem.
6669 * 2. Inserts alloc as first element into list.
6670 * 3. Increments alloc count.
6671 * Note 1: Holes are not dealt with here.
6672 * Note 2: prv to necessarily NULLP.
6674 * Ret : RgSchUlAlloc *
6680 **********************************************************/
6681 RgSchUlAlloc *rgSCHUtlUlAllocGetFirst(RgSchUlAllocDb *db)
6683 RgSchUlAlloc *alloc = rgSCHUtlUlAllocMemGet(&db->mem);
6684 RgSchUlAlloc *nxt = db->first;
6686 #if (ERRCLASS & ERRCLS_DEBUG)
6687 if ( alloc == NULLP )
6706 /* UL_ALLOC_ENHANCEMENT */
6707 /***********************************************************
6709 * Func : rgSCHUtlUlHoleAddAllocation
6711 * Desc : On freeing an alloc, add to hole
6719 **********************************************************/
6720 Void rgSCHUtlUlHoleAddAllocation(RgSchUlAlloc *alloc)
6722 /* Note: rgSchCmnUlHoleUpdAllocLnks function that is used should not exist as
6723 * one, if such excessive branching is done (AllocNone, AllocNoPrv etc).
6724 * The excessive branching is meant to utilise the knowledge of whether prv
6725 * and nxt allocs exist or not. Hence for each kind (none, noprv, nonxt,
6726 * both), there should be a rgSchCmnUlHoleUpdAllocLnks... function (such as
6727 * rgSchCmnUlHoleUpdAllocLnksNone/NoPrv etc. */
6728 RgSchUlHoleDb *db = alloc->holeDbRef;
6729 RgSchUlHole *prv = alloc->prvHole;
6730 RgSchUlHole *nxt = alloc->nxtHole;
6736 rgSCHUtlUlHoleJoin(db, prv, nxt, alloc);
6739 rgSCHUtlUlHoleExtndRight(db, prv, alloc);
6745 rgSCHUtlUlHoleExtndLeft(db, nxt, alloc);
6748 rgSCHUtlUlHoleNew(db, alloc);
6754 /***********************************************************
6756 * Func : rgSCHUtlUlAllocRelease
6758 * Desc : Releases an uplink allocation, only take alloc ptr
6766 **********************************************************/
6767 Void rgSCHUtlUlAllocRelease(RgSchUlAlloc *alloc)
6769 RgSchUlAllocDb *allocDb = alloc->allocDbRef;
6770 RgSchUlAlloc *prv = alloc->prv;
6771 RgSchUlAlloc *nxt = alloc->nxt;
6774 alloc->raCb = NULLP;
6775 alloc->isAdaptive = FALSE;
6780 if (nxt) /* general case: this allocation lies btw two */
6787 allocDb->first = nxt;
6794 rgSCHUtlUlHoleAddAllocation(alloc);
6795 rgSCHUtlUlAllocMemRls(&allocDb->mem, alloc);
6801 /***********************************************************
6803 * Func : rgSCHUtlUlAllocRls
6805 * Desc : Releases an uplink allocation
6813 **********************************************************/
6814 Void rgSCHUtlUlAllocRls(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6816 RgSchUlAllocDb *allocDb = sf->allocDb;
6817 RgSchUlAlloc *prv = alloc->prv;
6818 RgSchUlAlloc *nxt = alloc->nxt;
6821 alloc->raCb = NULLP;
6822 alloc->isAdaptive = FALSE;
6829 if (nxt) /* general case: this allocation lies btw two */
6836 allocDb->first = nxt;
6843 rgSCHUtlUlHoleAddAlloc(sf, alloc);
6844 rgSCHUtlUlAllocMemRls(&allocDb->mem, alloc);
6849 printf("\nError: allocDb->count is ZERO ====\n");
6852 //printf("\nallocDb->count:%u\n",allocDb->count);
6857 /***********************************************************
6859 * Func : rgSCHUtlUlHoleFirst
6861 * Desc : Get first (largest) hole
6863 * Ret : RgSchUlHole *
6869 **********************************************************/
6870 RgSchUlHole *rgSCHUtlUlHoleFirst(RgSchUlSf *sf)
6872 return (sf->holeDb->first);
6875 /***********************************************************
6877 * Func : rgSCHUtlUlHoleNxt
6879 * Desc : Get next largest hole
6881 * Ret : RgSchUlHole *
6887 **********************************************************/
6888 RgSchUlHole *rgSCHUtlUlHoleNxt(RgSchUlSf *sf,RgSchUlHole *hole)
6894 /***********************************************************
6896 * Func : rgSCHUtlUlHoleAddAlloc
6898 * Desc : On freeing an alloc, add to hole
6906 **********************************************************/
6907 Void rgSCHUtlUlHoleAddAlloc(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6909 /* Note: rgSchCmnUlHoleUpdAllocLnks function that is used should not exist as
6910 * one, if such excessive branching is done (AllocNone, AllocNoPrv etc).
6911 * The excessive branching is meant to utilise the knowledge of whether prv
6912 * and nxt allocs exist or not. Hence for each kind (none, noprv, nonxt,
6913 * both), there should be a rgSchCmnUlHoleUpdAllocLnks... function (such as
6914 * rgSchCmnUlHoleUpdAllocLnksNone/NoPrv etc. */
6915 RgSchUlHoleDb *db = sf->holeDb;
6916 RgSchUlHole *prv = alloc->prvHole;
6917 RgSchUlHole *nxt = alloc->nxtHole;
6923 rgSCHUtlUlHoleJoin(db, prv, nxt, alloc);
6926 rgSCHUtlUlHoleExtndRight(db, prv, alloc);
6932 rgSCHUtlUlHoleExtndLeft(db, nxt, alloc);
6935 rgSCHUtlUlHoleNew(db, alloc);
6938 /* increment the number of subbands getting freed to total available list */
6939 sf->availSubbands += alloc->numSb;
6944 /***********************************************************
6946 * Func : rgSCHUtlUlHoleJoin
6948 * Desc : Join two holes (due to alloc being deleted)
6956 **********************************************************/
6957 Void rgSCHUtlUlHoleJoin(RgSchUlHoleDb *db,RgSchUlHole *prv,RgSchUlHole *nxt,RgSchUlAlloc *alloc)
6959 prv->num += alloc->numSb + nxt->num;
6960 rgSCHUtlUlHoleRls(db, nxt);
6961 rgSCHUtlUlHoleIncr(db, prv);
6962 rgSCHUtlUlHoleUpdAllocLnks(prv, alloc->prv, alloc->nxt);
6967 /***********************************************************
6969 * Func : rgSCHUtlUlHoleExtndRight
6971 * Desc : Extend hole due to alloc coming 'after' the hole
6980 **********************************************************/
6981 Void rgSCHUtlUlHoleExtndRight(RgSchUlHoleDb *db,RgSchUlHole *prv,RgSchUlAlloc *alloc)
6983 prv->num += alloc->numSb;
6984 rgSCHUtlUlHoleIncr(db, prv);
6985 rgSCHUtlUlHoleUpdAllocLnks(prv, alloc->prv, alloc->nxt);
6989 /***********************************************************
6991 * Func : rgSCHUtlUlHoleExtndLeft
6993 * Desc : Extend hole due to alloc coming 'before' the hole
7002 **********************************************************/
7003 Void rgSCHUtlUlHoleExtndLeft(RgSchUlHoleDb *db,RgSchUlHole *nxt,RgSchUlAlloc *alloc)
7005 nxt->num += alloc->numSb;
7006 nxt->start = alloc->sbStart;
7007 rgSCHUtlUlHoleIncr(db, nxt);
7008 rgSCHUtlUlHoleUpdAllocLnks(nxt, alloc->prv, alloc->nxt);
7012 /***********************************************************
7014 * Func : rgSCHUtlUlHoleNew
7016 * Desc : Create new hole due to alloc being deleted
7024 **********************************************************/
7025 Void rgSCHUtlUlHoleNew(RgSchUlHoleDb *db,RgSchUlAlloc *alloc)
7027 RgSchUlHole *hole = rgSCHUtlUlHoleMemGet(&db->mem);
7028 #if (ERRCLASS & ERRCLS_DEBUG)
7029 if ( hole == NULLP )
7034 hole->start = alloc->sbStart;
7035 hole->num = alloc->numSb;
7037 rgSCHUtlUlHoleIns(db, hole);
7038 rgSCHUtlUlHoleUpdAllocLnks(hole, alloc->prv, alloc->nxt);
7042 /***********************************************************
7044 * Func : rgSCHUtlUlHoleUpdAllocLnks
7046 * Desc : Update alloc links in hole
7054 **********************************************************/
7055 Void rgSCHUtlUlHoleUpdAllocLnks(RgSchUlHole *hole,RgSchUlAlloc *prvAlloc,RgSchUlAlloc *nxtAlloc)
7059 prvAlloc->nxtHole = hole;
7063 nxtAlloc->prvHole = hole;
7065 hole->prvAlloc = prvAlloc;
7066 hole->nxtAlloc = nxtAlloc;
7071 /***********************************************************
7073 * Func : rgSCHUtlUlHoleIns
7075 * Desc : Insert (newly created) hole in sorted list of holes.
7076 * Searches linearly, beginning with the largest hole.
7084 **********************************************************/
7085 Void rgSCHUtlUlHoleIns(RgSchUlHoleDb *db,RgSchUlHole *hole)
7089 if ((cur = db->first) != NULLP)
7092 if (cur->num < hole->num)
7102 for (nxt = cur->nxt; nxt; cur = nxt, nxt = nxt->nxt)
7104 if (nxt->num < hole->num)
7106 /* Insert hole: cur <-> hole <-> nxt */
7122 /* This is the first hole */
7124 hole->prv = NULLP; /* may not be needed */
7130 /***********************************************************
7132 * Func : rgSCHUtlUlHoleIncr
7134 * Desc : hole->num has increeased, reposition in sorted
7143 **********************************************************/
7144 Void rgSCHUtlUlHoleIncr(RgSchUlHoleDb *db,RgSchUlHole *hole)
7148 if ((cur = hole->prv) != NULLP)
7152 if (cur->num > hole->num)
7157 /* Remove hole from current position */
7158 cur->nxt = hole->nxt;
7161 hole->nxt->prv = cur;
7164 for (prv = cur->prv; prv; cur = prv, prv = prv->prv)
7166 if (prv->num > hole->num)
7168 /* Insert hole: prv <-> hole <-> cur */
7187 /***********************************************************
7189 * Func : rgSCHUtlUlHoleDecr
7191 * Desc : hole->num has decreeased, reposition in sorted
7200 **********************************************************/
7201 Void rgSCHUtlUlHoleDecr(RgSchUlHoleDb *db,RgSchUlHole *hole)
7205 if ((cur = hole->nxt) != NULLP)
7209 if (cur->num < hole->num)
7214 /* Remove hole from current position */
7215 cur->prv = hole->prv;
7218 hole->prv->nxt = cur;
7220 else /* no prv, so cur to replace hole as first in list */
7225 for (nxt = cur->nxt; nxt; cur = nxt, nxt = nxt->nxt)
7227 if (nxt->num < hole->num)
7229 /* Insert hole: cur <-> hole <-> nxt */
7247 /***********************************************************
7249 * Func : rgSCHUtlUlHoleRls
7251 * Desc : Releases hole.
7252 * 1. Decrements hole count.
7253 * 2. Deletes hole from list.
7254 * 3. Frees hole (hole memory release).
7262 **********************************************************/
7263 Void rgSCHUtlUlHoleRls(RgSchUlHoleDb *db,RgSchUlHole *hole)
7265 RgSchUlHole *prv = hole->prv;
7266 RgSchUlHole *nxt = hole->nxt;
7286 rgSCHUtlUlHoleMemRls(&db->mem, hole);
7291 /***********************************************************
7293 * Func : rgSCHUtlUlAllocMemInit
7295 * Desc : Initialises alloc free pool
7297 * Ret : S16 (ROK/RFAILED)
7303 **********************************************************/
7304 S16 rgSCHUtlUlAllocMemInit(RgSchCellCb *cell,RgSchUlAllocMem *mem,uint8_t maxAllocs)
7307 RgSchUlAlloc *allocs;
7309 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&allocs,
7310 maxAllocs * sizeof(*allocs));
7315 mem->allocs = allocs;
7316 mem->maxAllocs = maxAllocs;
7317 if (mem->maxAllocs == 1)
7319 allocs[0].prv = NULLP;
7320 allocs[0].nxt = NULLP;
7325 allocs[0].prv = NULLP;
7326 allocs[0].nxt = &allocs[1];
7327 for (i = 1; i < mem->maxAllocs - 1; ++i)
7329 allocs[i].prv = &allocs[i-1];
7330 allocs[i].nxt = &allocs[i+1];
7332 allocs[i].prv = &allocs[i-1];
7333 allocs[i].nxt = NULLP;
7335 mem->firstFree = &allocs[0];
7339 /***********************************************************
7341 * Func : rgSCHUtlUlAllocMemDeinit
7343 * Desc : Deinitialises alloc free pool
7351 **********************************************************/
7352 Void rgSCHUtlUlAllocMemDeinit(RgSchCellCb *cell,RgSchUlAllocMem *mem)
7354 /* ccpu00117052 - MOD - Passing double pointer
7355 for proper NULLP assignment*/
7356 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(mem->allocs)),
7357 mem->maxAllocs * sizeof(*mem->allocs));
7359 mem->firstFree = NULLP;
7363 /***********************************************************
7365 * Func : rgSCHUtlUlHoleMemInit
7367 * Desc : Initialises hole free pool. Assumes maxHoles
7370 * Ret : S16 (ROK/RFAILED)
7376 **********************************************************/
7377 S16 rgSCHUtlUlHoleMemInit(RgSchCellCb *cell,RgSchUlHoleMem *mem,uint8_t maxHoles,RgSchUlHole **holeRef)
7382 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&holes,
7383 maxHoles * sizeof(*holes));
7390 mem->maxHoles = maxHoles;
7392 /* first hole is taken up */
7393 holes[0].prv = NULLP; /* not needed */
7394 holes[0].nxt = NULLP; /* not needed */
7395 *holeRef = &holes[0];
7397 if (mem->maxHoles == 2)
7399 holes[1].prv = NULLP; /* may not be needed */
7400 holes[1].nxt = NULLP; /* may not be needed */
7405 holes[1].prv = NULLP;
7406 holes[0].nxt = &holes[1];
7407 for (i = 1; i < mem->maxHoles - 1; ++i)
7409 holes[i].prv = &holes[i-1];
7410 holes[i].nxt = &holes[i+1];
7412 holes[i].prv = &holes[i-1];
7413 holes[i].nxt = NULLP;
7415 mem->firstFree = &holes[1];
7420 /***********************************************************
7422 * Func : rgSCHUtlUlHoleMemDeinit
7424 * Desc : Deinitialises hole free pool
7432 **********************************************************/
7433 Void rgSCHUtlUlHoleMemDeinit(RgSchCellCb *cell,RgSchUlHoleMem *mem)
7435 /* ccpu00117052 - MOD - Passing double pointer
7436 for proper NULLP assignment*/
7437 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(mem->holes)),
7438 mem->maxHoles * sizeof(*mem->holes));
7440 mem->firstFree = NULLP;
7444 /***********************************************************
7446 * Func : rgSCHUtlUlAllocMemGet
7448 * Desc : Gets an 'alloc' from the free pool
7450 * Ret : RgSchUlAlloc *
7456 **********************************************************/
7457 RgSchUlAlloc *rgSCHUtlUlAllocMemGet(RgSchUlAllocMem *mem)
7459 RgSchUlAlloc *alloc;
7461 #if (ERRCLASS & ERRCLS_DEBUG)
7462 if (mem->firstFree == NULLP)
7468 alloc = mem->firstFree;
7469 mem->firstFree = alloc->nxt;
7470 alloc->nxt = NULLP; /* probably not needed */
7471 /* alloc->prv might already be NULLP, in case was needed to set it to NULLP */
7476 /***********************************************************
7478 * Func : rgSCHUtlUlAllocMemRls
7480 * Desc : Returns an 'alloc' to the free pool
7488 **********************************************************/
7489 Void rgSCHUtlUlAllocMemRls(RgSchUlAllocMem *mem,RgSchUlAlloc *alloc)
7493 alloc->nxt = mem->firstFree;
7494 if (mem->firstFree != NULLP)
7496 mem->firstFree->prv = alloc;
7498 mem->firstFree = alloc;
7502 /***********************************************************
7504 * Func : rgSCHUtlUlHoleMemGet
7506 * Desc : Gets a 'hole' from the free pool
7508 * Ret : RgSchUlHole *
7514 **********************************************************/
7515 RgSchUlHole *rgSCHUtlUlHoleMemGet(RgSchUlHoleMem *mem)
7519 #if (ERRCLASS & ERRCLS_DEBUG)
7520 if (mem->firstFree == NULLP)
7526 hole = mem->firstFree;
7527 mem->firstFree = hole->nxt;
7528 mem->firstFree->prv = NULLP; /* may not be needed, under error class */
7529 hole->nxt = NULLP; /* probably not needed */
7530 /* hole->prv is might already be NULLP, in case was needed to set it to NULLP */
7535 /***********************************************************
7537 * Func : rgSCHUtlUlHoleMemRls
7539 * Desc : Returns a 'hole' to the free pool
7547 **********************************************************/
7548 Void rgSCHUtlUlHoleMemRls(RgSchUlHoleMem *mem,RgSchUlHole *hole)
7552 hole->nxt = mem->firstFree;
7553 if (mem->firstFree != NULLP)
7555 mem->firstFree->prv = hole;
7557 mem->firstFree = hole;
7562 * @brief Get an alloc from the specified position in the BW.
7566 * Function : rgSCHUtlUlGetSpfcAlloc
7568 * - Return an alloc from the specified position in the BW.
7569 * Note: This function assumes there is always a hole
7570 * Existing which completely has the specified
7571 * allocation. The reason for such an assumption is
7572 * the function's usage as of now guarantees that there
7573 * will always be such hole. And also for efficiency.
7575 * @param[in] RgSchUlSf *sf
7576 * @param[in] uint8_t startSb
7577 * @param[in] uint8_t numSb
7578 * @return RgSchUlAlloc*
7580 RgSchUlAlloc *rgSCHUtlUlGetSpfcAlloc(RgSchUlSf *sf,uint8_t startSb,uint8_t numSb)
7582 RgSchUlHole *hole, *nxtHole;
7583 RgSchUlAlloc *alloc = NULLP;
7585 if ((hole = rgSCHUtlUlHoleFirst(sf)) == NULLP)
7591 nxtHole = rgSCHUtlUlHoleNxt(sf, hole);
7592 if ((startSb >= hole->start) &&
7593 (startSb+numSb <= hole->start+hole->num))
7595 if (startSb != hole->start)
7597 /* Create a new hole to accomodate Subbands between
7598 * hole start and req alloc start */
7599 RgSchUlHole *newHole = rgSCHUtlUlHoleMemGet(&(sf->holeDb->mem));
7601 #if (ERRCLASS & ERRCLS_DEBUG)
7602 if ( newHole == NULLP )
7607 newHole->start = hole->start;
7608 newHole->num = startSb - hole->start;
7609 hole->start = startSb;
7610 /* [ccpu00122847]-MOD- Correctly updating the hole->num */
7611 hole->num -= newHole->num;
7612 ++(sf->holeDb->count);
7613 rgSCHUtlUlHoleIns(sf->holeDb, newHole);
7614 newHole->prvAlloc = hole->prvAlloc;
7615 if (newHole->prvAlloc)
7617 newHole->prvAlloc->nxtHole = newHole;
7619 if (numSb == hole->num)
7621 alloc = rgSCHUtlUlAllocGetCompHole(sf, hole);
7625 alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole);
7627 alloc->prvHole = newHole;
7628 newHole->nxtAlloc = alloc;
7630 else /* Hole start and req alloc start are same */
7632 if (numSb == hole->num)
7634 alloc = rgSCHUtlUlAllocGetCompHole(sf, hole);
7638 alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole);
7643 } while ((hole = nxtHole) != NULLP);
7648 * @brief Validates the qci values
7652 * Function :rgSCHUtlValidateQci
7654 * @param[in] RgSchCellCb *cellCb
7655 * @param[in] uint8_t numQci
7656 * @param[out] uint8_t *qci
7661 static S16 rgSCHUtlValidateQci(RgSchCellCb *cellCb,uint8_t numQci,uint8_t *qci)
7666 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
7668 qciVal = qci[qciIdx];
7669 if(qciVal == 0 || qciVal > 9)
7673 if(qciVal != cellCb->qciArray[qciVal].qci)
7680 }/* rgSCHUtlValidateQci */
7682 * @brief Validates the measurement request parameters.
7686 * Function :rgSCHUtlValidateMeasReq
7688 * @param[in] RgSchCellCb *cellCb
7689 * @param[in] LrgSchMeasReqInfo *schL2MeasInfo
7690 * @param[out] RgSchErrInfo *err
7691 * @return RgSchUlAlloc*
7693 S16 rgSCHUtlValidateMeasReq(RgSchCellCb *cellCb, LrgSchMeasReqInfo *schL2MeasInfo,RgSchErrInfo *err)
7698 measType = schL2MeasInfo->measType;
7699 if((measType == 0) ||
7702 err->errType = RGSCHERR_SCH_INVALID_MEAS_TYPE;
7703 err->errCause = RGSCHERR_SCH_L2MEAS;
7706 if((schL2MeasInfo->timePrd !=0) &&
7707 (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL) &&
7708 ((schL2MeasInfo->avgPrbQciDl.numQci > LRG_MAX_QCI_PER_REQ)||
7709 (schL2MeasInfo->avgPrbQciDl.numQci == 0)))
7711 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7712 err->errCause = RGSCHERR_SCH_L2MEAS;
7715 if((schL2MeasInfo->timePrd !=0) &&
7716 (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_UL) &&
7717 (schL2MeasInfo->avgPrbQciUl.numQci > LRG_MAX_QCI_PER_REQ))
7719 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7720 err->errCause = RGSCHERR_SCH_L2MEAS;
7723 if((measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_DL) &&
7724 ((schL2MeasInfo->nmbActvUeQciDl.numQci > LRG_MAX_QCI_PER_REQ) ||
7725 (schL2MeasInfo->nmbActvUeQciDl.sampPrd == 0)||
7726 ((schL2MeasInfo->timePrd !=0)&&
7727 (schL2MeasInfo->timePrd < schL2MeasInfo->nmbActvUeQciDl.sampPrd)) ||
7728 (schL2MeasInfo->nmbActvUeQciDl.sampPrd > LRG_MAX_SAMP_PRD)))
7730 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7731 err->errCause = RGSCHERR_SCH_L2MEAS;
7734 if((measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_UL) &&
7735 ((schL2MeasInfo->nmbActvUeQciUl.numQci > LRG_MAX_QCI_PER_REQ) ||
7736 (schL2MeasInfo->nmbActvUeQciUl.sampPrd == 0)||
7737 ((schL2MeasInfo->timePrd !=0) &&
7738 (schL2MeasInfo->timePrd < schL2MeasInfo->nmbActvUeQciUl.sampPrd)) ||
7739 (schL2MeasInfo->nmbActvUeQciUl.sampPrd > LRG_MAX_SAMP_PRD)))
7741 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7742 err->errCause = RGSCHERR_SCH_L2MEAS;
7745 if((schL2MeasInfo->timePrd !=0) &&
7746 (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL))
7748 RGSCH_ARRAY_BOUND_CHECK(cellCb->instIdx, schL2MeasInfo->avgPrbQciDl.qci, \
7749 (schL2MeasInfo->avgPrbQciDl.numQci));
7750 ret = rgSCHUtlValidateQci(cellCb, schL2MeasInfo->avgPrbQciDl.numQci,
7751 schL2MeasInfo->avgPrbQciDl.qci);
7754 err->errType = RGSCHERR_SCH_INVALID_QCI_VAL;
7755 err->errCause = RGSCHERR_SCH_L2MEAS;
7760 }/* rgSCHUtlValidateMeasReq */
7761 #endif /* LTE_L2_MEAS */
7762 /******* </AllocHolesMemMgmnt>: END *****/
7765 * @brief API for sending SI configuration confirm from Scheduler to RRM
7769 * Function: rgSCHUtlRgrSiCfgCfm
7771 * This API is invoked to send SI configuration confirm from Scheduler
7773 * This API fills in Pst structure and SAP Ids and invokes
7774 * config confirm API towards RRM.
7776 * @param[in] RgrCfgTransId transId
7777 * @param[in] uint8_t status
7782 S16 rgSCHUtlRgrSiCfgCfm(Inst instId,SpId spId,RgrCfgTransId transId,uint8_t status)
7784 uint8_t prntTrans[RGR_CFG_TRANSID_SIZE+1];
7786 memcpy(prntTrans, transId.trans, RGR_CFG_TRANSID_SIZE);
7787 prntTrans[RGR_CFG_TRANSID_SIZE] = '\0';
7788 if(RgUiRgrSiCfgCfm(&rgSchCb[instId].rgrSap[spId].sapCfg.sapPst,
7789 rgSchCb[instId].rgrSap[spId].sapCfg.suId,
7790 transId, status) != ROK)
7792 RLOG_ARG0(L_ERROR,DBG_INSTID,instId,"rgSCHUtlRgrSiCfgCfm: "
7793 "RgUiRgrSiCfgCfm Failed ");
7798 } /* rgSCHUtlRgrSiCfgCfm */
7802 * @brief API for sending Warning SI configuration confirm from
7808 * This API is invoked to send Warning SI configuration confirm
7809 * from Scheduler to RRM.
7810 * This API fills in Pst structure and SAP Ids and invokes
7811 * config confirm API towards RRM.
7813 * @param[in] RgrCfgTransId transId
7814 * @param[in] uint8_t status
7819 S16 rgSCHUtlRgrWarningSiCfgCfm(Inst instId,SpId spId,uint8_t siId,RgrCfgTransId transId,uint8_t status)
7821 uint8_t prntTrans[RGR_CFG_TRANSID_SIZE+1];
7823 memcpy(prntTrans, transId.trans, RGR_CFG_TRANSID_SIZE);
7824 prntTrans[RGR_CFG_TRANSID_SIZE] = '\0';
7826 if(RgUiRgrWarningSiCfgCfm(&rgSchCb[instId].rgrSap[spId].sapCfg.sapPst,
7827 rgSchCb[instId].rgrSap[spId].sapCfg.suId,
7828 transId, siId, status) != ROK)
7830 RLOG_ARG0(L_ERROR,DBG_INSTID,instId,"rgSCHUtlRgrSiCfgCfm: "
7831 "RgUiRgrSiCfgCfm Failed ");
7836 } /* rgSCHUtlRgrWarningSiCfgCfm */
7838 /***********************************************************
7840 * Func : rgSCHUtlPutSiInfo
7842 * Desc : Utility Function to deallocate SI information
7850 **********************************************************/
7851 Void rgSCHUtlPutSiInfo(RgSchCellCb *cell)
7854 uint32_t sizeOfSiInfo = 0;
7855 /*Free the buffers in crntSiInfo*/
7856 RGSCH_FREE_MSG(cell->siCb.crntSiInfo.mib)
7857 RGSCH_FREE_MSG(cell->siCb.crntSiInfo.sib1Info.sib1)
7859 sizeOfSiInfo = sizeof(cell->siCb.crntSiInfo.siInfo)/sizeof(cell->siCb.crntSiInfo.siInfo[0]);
7861 for(idx=0; idx < sizeOfSiInfo; idx++)
7863 RGSCH_FREE_MSG(cell->siCb.crntSiInfo.siInfo[idx].si)
7866 /*Free the buffers in newSiInfo */
7867 RGSCH_FREE_MSG(cell->siCb.newSiInfo.mib)
7868 RGSCH_FREE_MSG(cell->siCb.newSiInfo.sib1Info.sib1)
7870 sizeOfSiInfo = sizeof(cell->siCb.newSiInfo.siInfo)/sizeof(cell->siCb.newSiInfo.siInfo[0]);
7872 for(idx=0; idx < sizeOfSiInfo; idx++)
7874 RGSCH_FREE_MSG(cell->siCb.newSiInfo.siInfo[idx].si)
7879 #endif /*RGR_SI_SCH */
7883 /***********************************************************
7885 * Func : rgSCHUtlGetDrxSchdUesInDl
7887 * Desc : Utility Function to fill the get the list of
7888 * scheduled UEs. On these UE's, drx-inactivity
7889 * timer will be started/restarted.
7898 **********************************************************/
7899 S16 rgSCHUtlGetDrxSchdUesInDl
7901 RgSchCellCb *cellCb,
7903 RgSchDlHqProcCb *dlHq,
7904 RgInfUeAlloc *allocInfo,
7905 CmLListCp *dlDrxInactvTmrLst,
7906 CmLListCp *dlInActvLst,
7907 CmLListCp *ulInActvLst
7910 Bool isNewTx = FALSE;
7912 RgSchDrxDlHqProcCb *drxHq;
7913 RgSchDRXCellCb *drxCell = cellCb->drxCb;
7914 RgSchDrxUeCb *drxUe;
7916 Inst inst = cellCb->instIdx;
7918 uint8_t cellIdx = ueCb->cellIdToCellIdxMap[RG_SCH_CELLINDEX(dlHq->hqE->cell)];
7919 uint32_t dlInactvMask;
7920 uint32_t ulInactvMask;
7922 for(idx = 0; idx < allocInfo->nmbOfTBs; idx++)
7924 if(allocInfo->tbInfo[idx].isReTx == FALSE)
7927 /* Removing break here, since in 2 TB case if 2nd TB is proceeding with
7928 retx then drxretx timer should be stopped.*/
7932 /*Stop the DRX retransmission timer as UE scheduled for retx. Here
7933 * we stop the timer and inactivate the UE for both UL and DL.
7934 * This may result in loss of one slot for UL but this trade
7935 * off is taken to avoid the overhead of maintaining a list of UEs
7936 * to be inactivated in the next slot.*/
7937 drxHq = RG_SCH_DRX_GET_DL_HQ(dlHq);
7938 drxUe = RG_SCH_DRX_GET_UE(ueCb);
7939 if(drxHq->reTxIndx != DRX_INVALID)
7941 /* This condition should never occur */
7942 if(drxHq->reTxIndx >= RG_SCH_MAX_DRXQ_SIZE)
7944 RGSCHDBGERRNEW(inst,(rgSchPBuf(inst),"[%d]UE:DRXUE RETX IDX[%d]"
7945 "is out of bound,dlInactvMask %d,procId %d\n", ueCb->ueId,
7946 drxHq->reTxIndx,ueCb->dl.dlInactvMask, dlHq->procId));
7949 drxUe->drxDlInactvMaskPerCell[cellIdx] |= (RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId);
7950 drxUe->drxUlInactvMaskPerCell[cellIdx] |= (RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId);
7952 dlInactvMask = RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId;
7953 ulInactvMask = RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId;
7955 for(cellIdx = 0; cellIdx < CM_LTE_MAX_CELLS; cellIdx++)
7957 dlInactvMask &= drxUe->drxDlInactvMaskPerCell[cellIdx];
7958 ulInactvMask &= drxUe->drxUlInactvMaskPerCell[cellIdx];
7961 drxUe->drxDlInactvMask |= dlInactvMask;
7962 drxUe->drxUlInactvMask |= ulInactvMask;
7964 /* if no other condition is keeping ue active,
7967 if(!RG_SCH_DRX_DL_IS_UE_ACTIVE(drxUe))
7969 /* BUG 2 : HARQ_RTT, changed for consistency */
7970 ueCb->dl.dlInactvMask |= (RG_DRX_INACTIVE);
7972 /* Add to DL inactive list */
7973 cmLListAdd2Tail(dlInActvLst,&(ueCb->dlDrxInactvLnk));
7974 ueCb->dlDrxInactvLnk.node = (PTR)ueCb;
7977 if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
7979 /*BUG 2: HARQ_RTT changed for consistency */
7980 ueCb->ul.ulInactvMask |= (RG_DRX_INACTIVE);
7982 cmLListAdd2Tail(ulInActvLst,&(ueCb->ulDrxInactvLnk));
7983 ueCb->ulDrxInactvLnk.node = (PTR)ueCb;
7986 /* Deleting entry from HARQ RTT queue for the same HARQ proc,
7987 * if exist. This is the special case which can happen iF UL
7988 * scheduling is done later. */
7989 if(drxHq->rttIndx != DRX_INVALID)
7991 cmLListDelFrm (&(cellCb->drxCb->drxQ[drxHq->rttIndx].harqRTTQ),
7992 &(drxHq->harqRTTEnt));
7994 drxHq->rttIndx = DRX_INVALID;
7997 cmLListDelFrm (&(drxCell->drxQ[drxHq->reTxIndx].harqRetxQ),
7998 &(drxHq->harqRetxEnt));
7999 drxHq->reTxIndx = DRX_INVALID;
8006 if(ueCb->drxCb->raRcvd == TRUE)
8008 ueCb->drxCb->raRcvd = FALSE;
8010 /* mark the ra bit */
8011 ueCb->drxCb->drxUlInactvMask |= RG_SCH_DRX_RA_BITMASK;
8012 ueCb->drxCb->drxDlInactvMask |= RG_SCH_DRX_RA_BITMASK;
8014 }/*if(ra->rcvd) == TRUE */
8016 if(ueCb->dlDrxInactvTmrLnk.node == NULLP)
8018 cmLListAdd2Tail(dlDrxInactvTmrLst,&(ueCb->dlDrxInactvTmrLnk));
8019 ueCb->dlDrxInactvTmrLnk.node = (PTR)ueCb;
8021 }/*if(isNewTx == TRUE) */
8024 }/* rgSCHUtlGetSchdUes*/
8026 /* ccpu00117452 - MOD - Changed macro name from
8027 RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */
8030 * @brief This function fills StaInd struct
8034 * Function: rgSCHUtlFillSndStaInd
8035 * Purpose: Fills StaInd struct and sends the
8038 * @param[in] RgSchCellCb *cell pointer to Cell Control block
8039 * @param[in] RgSchUeCb *ue pointer to Ue Control block
8040 * @param[in] RgrStaIndInfo *staInfo Sta Ind struct to be filled
8041 * @param[in] uint8_t numCqiRept NUmber of reports to be filled
8045 S16 rgSCHUtlFillSndStaInd(RgSchCellCb *cell,RgSchUeCb *ue,RgrStaIndInfo *staInfo,uint8_t numCqiRept)
8049 /* Fill StaInd for sending collated Latest N CQI rpeorts */
8050 /* Find index in the array from where Latest N
8051 reports needs to be fetched. Use this value to index in the array
8052 and copy the reports into staInfo */
8054 /* Fill the Cell Id of PCC of the UE */
8055 staInfo->cellId = ue->cell->cellId;
8056 staInfo->crnti = ue->ueId;
8058 idxStart = ue->schCqiInfo.cqiCount - numCqiRept;
8060 memcpy (&(staInfo->ueCqiInfo.cqiRept),
8061 &(ue->schCqiInfo.cqiRept[idxStart]),
8062 numCqiRept * sizeof(RgrUeCqiRept));
8064 staInfo->ueCqiInfo.numCqiRept = numCqiRept;
8066 ue->schCqiInfo.cqiCount = 0;
8068 /* Call utility function (rgSCHUtlRgrStaInd) to send rpts to RRM */
8069 if(rgSCHUtlRgrStaInd(cell, staInfo) != ROK)
8071 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Could not send "
8072 "CQI reports for RNTI:%d",ue->ueId);
8078 }/* End of rgSCHUtlFillSndStaInd */
8083 * @brief API for sending STA indication from Scheduler to RRM.
8087 * Function: rgSCHUtlRgrStaInd
8089 * This API is invoked to send STA indication from Scheduler instance to RRM.
8090 * This API fills in Pst structure and RgrStaIndInfo
8091 * and calls the Sta primitive API towards RRM.
8093 * @param[in] cell RgSchCellCb
8094 * @param[in] RgrStsIndInfo *rgrSta
8099 S16 rgSCHUtlRgrStaInd(RgSchCellCb *cell,RgrStaIndInfo *rgrSta)
8102 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
8104 rgrSap = cell->rgrSap;
8105 if (rgrSap->sapSta.sapState != LRG_BND)
8107 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
8108 "rgSCHUtlRgrStaInd() Upper SAP not bound (%d) ",
8109 rgrSap->sapSta.sapState);
8112 RgUiRgrStaInd(&(cell->rgrSap->sapCfg.sapPst),
8113 cell->rgrSap->sapCfg.suId, rgrSta);
8115 } /* rgSCHUtlRgrStaInd*/
8116 #endif /* End of RGR_CQI_REPT */
8118 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
8120 * @brief Indicates MAC to release any rnti context it has.
8123 * Function : rgSCHUtlIndRntiRls2Mac
8124 * This function indicates MAC for this rnti release.
8125 * In case of ueId change it will indicate MAC
8126 * about the new rnti to be updated.
8127 * It will post a release RNTI indication to MAC.
8131 * @param[in] RgSchCellCb *cell
8132 * @param[in] CmLteRnti rnti
8133 * @param[in] Bool ueIdChng
8134 * @param[in] CmLteRnti newRnti
8138 Void rgSCHUtlIndRntiRls2Mac(RgSchCellCb *cell,CmLteRnti rnti,Bool ueIdChng,CmLteRnti newRnti)
8141 Inst inst = cell->instIdx;
8142 RgInfRlsRnti rntiInfo;
8145 /* Copy the info to rntiInfo */
8146 rntiInfo.cellId = cell->cellId;
8147 rntiInfo.rnti = rnti;
8148 /* Fix : syed ueId change as part of reestablishment.
8149 * Now SCH to trigger this. CRG ueRecfg for ueId change
8151 rntiInfo.ueIdChng = ueIdChng;
8152 rntiInfo.newRnti = newRnti;
8154 rntiInfo.isUeSCellDel = FALSE;
8156 /* Invoke MAC to release the rnti */
8157 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[inst], cell->macInst);
8158 RgSchMacRlsRnti(&pst, &rntiInfo);
8162 /* LTE_ADV_FLAG_REMOVED_START */
8164 * @brief API for sending LOAD INF indication from Scheduler to RRM.
8167 * Function: rgSCHUtlRgrLoadInfInd
8169 * This API is invoked to send LOAD INF indication from Scheduler instance to RRM.
8170 * This API fills in Pst structure and RgrLoadInfIndInfo
8171 * and calls the Sta primitive API towards RRM.
8173 * @param[in] cell RgSchCellCb
8174 * @param[in] RgrLoadInfIndInfo *rgrLoadInf
8179 S16 rgSCHUtlRgrLoadInfInd(RgSchCellCb *cell,RgrLoadInfIndInfo *rgrLoadInf)
8182 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
8184 rgrSap = cell->rgrSap;
8185 if (rgrSap->sapSta.sapState != LRG_BND)
8187 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
8188 "rgSCHUtlRgrLoadInfInd() Upper SAP not bound (%d) ",
8189 rgrSap->sapSta.sapState);
8192 RgUiRgrLoadInfInd(&(cell->rgrSap->sapCfg.sapPst),
8193 cell->rgrSap->sapCfg.suId, rgrLoadInf);
8195 } /* rgSCHUtlRgrLoadInfInd*/
8196 /* LTE_ADV_FLAG_REMOVED_END */
8198 /* MS_FIX : syed SCH to act as MASTER in maintaining
8199 * rnti related context. Trigger to rnti del/Chng at SCH
8200 * will result in a Indication to MAC to release its
8201 * RNTI context. MAC inturn indicates the context cleared
8202 * indication to SCH, upon which SCH would set this
8204 * @brief API for sending STA indication from Scheduler to RRM.
8208 * Function: rgSCHUtlRlsRnti
8210 * This API is invoked to indicate MAC to release rnti
8212 * @param[in] RgSchCellCb *cellCb
8213 * @param[in] RgSchRntiLnk *rntiLnk,
8214 * @param[in] Bool ueIdChngd,
8215 * @param[in] CmLteRnti newRnti
8219 Void rgSCHUtlRlsRnti(RgSchCellCb *cell,RgSchRntiLnk *rntiLnk,Bool ueIdChngd,CmLteRnti newRnti)
8222 uint8_t isLegacy = 0;
8224 if(cell->emtcEnable)
8226 rgSCHEmtcUtlRlsRnti(cell, rntiLnk, &isLegacy);
8231 /*Add to Guard Pool*/
8232 cmLListAdd2Tail(&cell->rntiDb.rntiGuardPool, &rntiLnk->rntiGrdPoolLnk);
8233 rntiLnk->rntiGrdPoolLnk.node = (PTR)rntiLnk;
8235 /* Fix: syed Explicitly Inidcate MAC to release RNTI */
8236 rgSCHUtlIndRntiRls2Mac(cell, rntiLnk->rnti, ueIdChngd, newRnti);
8243 * @brief This function fills StaInd struct
8247 * Function: rgSCHUtlFillSndUeStaInd
8248 * Purpose: Fills StaInd struct and sends the
8251 * @param[in] RgSchCellCb *cell pointer to Cell Control block
8252 * @param[in] RgSchUeCb *ue pointer to Ue Control block
8253 * @param[in] uint8_t numCqiRept NUmber of reports to be filled
8257 S16 rgSCHUtlFillSndUeStaInd(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeStaIndInfo *ueStaInfo)
8260 ueStaInfo->cellId = cell->cellId;
8261 ueStaInfo->crnti = ue->ueId;
8263 /* Call utility function (rgSCHUtlRgrUeStaInd) to send rpts to RRM */
8264 if(rgSCHUtlRgrUeStaInd(cell, ueStaInfo) != ROK)
8266 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"Could not send "
8267 "UE Sta reports CRNTI:%d",ue->ueId);
8273 }/* End of rgSCHUtlFillSndStaInd */
8278 * @brief API for sending STA indication from Scheduler to RRM.
8282 * Function: rgSCHUtlRgrStaInd
8284 * This API is invoked to send STA indication from Scheduler instance to RRM.
8285 * This API fills in Pst structure and RgrStaIndInfo
8286 * and calls the Sta primitive API towards RRM.
8288 * @param[in] cell RgSchCellCb
8289 * @param[in] RgrStsIndInfo *rgrSta
8294 S16 rgSCHUtlRgrUeStaInd(RgSchCellCb *cell,RgrUeStaIndInfo *rgrUeSta)
8297 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
8299 rgrSap = cell->rgrSap;
8300 if (rgrSap->sapSta.sapState != LRG_BND)
8302 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
8303 "rgSCHUtlRgrUeStaInd() Upper SAP not bound (%d) ",
8304 rgrSap->sapSta.sapState);
8307 RgUiRgrUeStaInd(&(cell->rgrSap->sapCfg.sapPst),
8308 cell->rgrSap->sapCfg.suId, rgrUeSta);
8310 } /* rgSCHUtlRgrStaInd*/
8314 * @brief function to report DL and UL PRB usage to RRM.
8317 * Function: rgSCHUtlUpdAvgPrbUsage
8318 * This function sends the PRB usage report to
8319 * RRM with the interval configured by RRM.
8321 * @param[in] cell *RgSchCellCb
8326 S16 rgSCHUtlUpdAvgPrbUsage(RgSchCellCb *cell)
8328 CmLteTimingInfo frm;
8329 RgmPrbRprtInd *prbRprtInd;
8332 #ifdef DBG_MAC_RRM_PRB_PRINT
8333 static uint32_t count = 0;
8334 const uint32_t reprotForEvery20Sec = 20000/cell->prbUsage.rprtPeriod;
8339 frm = cell->crntTime;
8340 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
8346 if(cell->prbUsage.rprtPeriod >= RGSCH_NUM_SUB_FRAMES)
8348 /* Get the total number of DL and UL slots within the reporting period*/
8349 numDlSf = (cell->prbUsage.rprtPeriod *
8350 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1])
8351 / RGSCH_NUM_SUB_FRAMES;
8352 numUlSf = (cell->prbUsage.rprtPeriod *
8353 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1])
8354 / RGSCH_NUM_SUB_FRAMES;
8358 /* Get the total number of DL and UL slots < 10 ms interval */
8359 numDlSf = rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][frm.slot];
8360 numUlSf = rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][frm.slot];
8363 numDlSf = cell->prbUsage.rprtPeriod;
8364 numUlSf = cell->prbUsage.rprtPeriod;
8367 if(SGetSBuf(cell->rgmSap->sapCfg.sapPst.region,
8368 cell->rgmSap->sapCfg.sapPst.pool, (Data**)&prbRprtInd,
8369 sizeof(RgmPrbRprtInd)) != ROK)
8374 memset(&prbRprtInd->stQciPrbRpts[0],
8376 (RGM_MAX_QCI_REPORTS * sizeof(RgmPrbRptPerQci)));
8378 prbRprtInd->bCellId = cell->cellId;
8382 prbRprtInd->bPrbUsageMask |= RGM_PRB_USAGE_DL;
8383 for (idx = 0; idx < RGM_MAX_QCI_REPORTS; idx++ )
8385 prbRprtInd->stQciPrbRpts[idx].bAvgPrbDlUsage =
8386 RGSCH_DIV_ROUND((cell->prbUsage.qciPrbRpts[idx].dlTotPrbUsed*100),
8387 (numDlSf * cell->bwCfg.dlTotalBw));
8388 prbRprtInd->stQciPrbRpts[idx].bQci = cell->prbUsage.qciPrbRpts[idx].qci;
8389 cell->prbUsage.qciPrbRpts[idx].dlTotPrbUsed = 0;
8395 prbRprtInd->bPrbUsageMask |= RGM_PRB_USAGE_UL;
8396 for (idx = 0; idx < RGM_MAX_QCI_REPORTS; idx++ )
8398 prbRprtInd->stQciPrbRpts[idx].bAvgPrbUlUsage =
8399 RGSCH_DIV_ROUND((cell->prbUsage.qciPrbRpts[idx].ulTotPrbUsed*100),
8400 (numUlSf * cell->ulAvailBw));
8401 prbRprtInd->stQciPrbRpts[idx].bQci = cell->prbUsage.qciPrbRpts[idx].qci;
8402 cell->prbUsage.qciPrbRpts[idx].ulTotPrbUsed = 0;
8406 #ifdef DBG_MAC_RRM_PRB_PRINT
8407 if((count % reprotForEvery20Sec) == 0 )
8409 printf("\n====================================================================");
8410 printf("\nMAC: QCI-1[DL:UL] | QCI-2[DL:UL] | QCI-3[DL:UL] | QCI-4[DL:UL] \n");
8411 printf("======================================================================\n");
8412 printf(" [%d: %d]\t | [%d: %d]\t | [%d: %d]\t| [%d: %d]\t\n",
8413 prbRprtInd->stQciPrbRpts[0].bAvgPrbDlUsage,
8414 prbRprtInd->stQciPrbRpts[0].bAvgPrbUlUsage,
8415 prbRprtInd->stQciPrbRpts[1].bAvgPrbDlUsage,
8416 prbRprtInd->stQciPrbRpts[1].bAvgPrbUlUsage,
8417 prbRprtInd->stQciPrbRpts[2].bAvgPrbDlUsage,
8418 prbRprtInd->stQciPrbRpts[2].bAvgPrbUlUsage,
8419 prbRprtInd->stQciPrbRpts[3].bAvgPrbDlUsage,
8420 prbRprtInd->stQciPrbRpts[3].bAvgPrbUlUsage);
8423 RgUiRgmSendPrbRprtInd(&(cell->rgmSap->sapCfg.sapPst),
8424 cell->rgmSap->sapCfg.suId, prbRprtInd);
8432 * @brief This function resends the Ta in case of
8433 * max retx failure or DTX for the Ta transmitted
8437 * Function: rgSCHUtlReTxTa
8440 * @param[in] RgSchCellCb *cell
8441 * @param[in] RgSchUeCb *ue
8445 Void rgSCHUtlReTxTa(RgSchCellCb *cellCb,RgSchUeCb *ueCb)
8448 /* If TA Timer is running. Stop it */
8449 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
8451 rgSCHTmrStopTmr(cellCb, ueCb->taTmr.tmrEvnt, ueCb);
8453 /*[ccpu00121813]-ADD-If maxretx is reached then
8454 * use outstanding TA val for scheduling again */
8455 if(ueCb->dl.taCb.outStndngTa == TRUE)
8457 ueCb->dl.taCb.ta = ueCb->dl.taCb.outStndngTaval;
8458 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
8459 ueCb->dl.taCb.outStndngTa = FALSE;
8462 /* Fix : syed TA state updation missing */
8463 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
8464 rgSCHUtlDlTARpt(cellCb, ueCb);
8469 /* Added function for dropping Paging Message*/
8471 * @brief Handler for BO Updt received for BCCH or PCCH.
8475 * Function : rgSCHChkBoUpdate
8477 * This function shall check for BO received falls within the scheduling window or not
8480 * @param[in] RgSchCellCb *cell
8485 static S16 rgSCHChkBoUpdate(RgSchCellCb *cell,RgInfCmnBoRpt *boUpdt)
8488 uint32_t crntTimeInSubFrms = 0;
8489 uint32_t boUpdTimeInSubFrms = 0;
8490 uint32_t distance = 0;
8492 crntTimeInSubFrms = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G) + cell->crntTime.slot +
8493 RG_SCH_CMN_DL_DELTA + 2; /* As bo received will scheduled in next TTI
8494 so incrementing with +1 more */
8495 boUpdTimeInSubFrms = (boUpdt->u.timeToTx.sfn * RGSCH_NUM_SUB_FRAMES_5G)+ boUpdt->u.timeToTx.slot;
8498 distance = boUpdTimeInSubFrms > crntTimeInSubFrms ? \
8499 boUpdTimeInSubFrms - crntTimeInSubFrms : \
8500 (RGSCH_MAX_SUBFRM_5G - crntTimeInSubFrms + boUpdTimeInSubFrms);
8502 if (distance > RGSCH_PCCHBCCH_WIN)
8508 }/*rgSCHChkBoUpdate*/
8513 * @brief Utility function to calculate the UL reTxIdx in TDD cfg0
8517 * Function : rgSchUtlCfg0ReTxIdx
8519 * Update the reTxIdx according to the rules mentioned
8520 * in 3GPP TS 36.213 section 8 for TDD Cfg0
8522 * @param[in] RgSchCellCb *cell
8523 * @param[in] CmLteTimingInfo phichTime
8524 * @param[in] uint8_t hqFdbkIdx
8527 uint8_t rgSchUtlCfg0ReTxIdx(RgSchCellCb *cell,CmLteTimingInfo phichTime,uint8_t hqFdbkIdx)
8529 uint8_t reTxIdx = RGSCH_INVALID_INFO;
8531 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
8533 uint8_t ulSF; /* UL SF in the TDD frame */
8535 ulSf = &cellUl->ulSfArr[hqFdbkIdx];
8536 ulSF = ulSf->ulSfIdx;
8538 /* Check for the UL SF 4 or 9 */
8539 if(ulSF == 9 || ulSF == 4)
8543 if(phichTime.slot == 0 || phichTime.slot == 5)
8547 /* Retx will happen according to the Pusch k table */
8548 reTxIdx = cellUl->schdIdx;
8552 /* Retx will happen at n+7 */
8553 RGSCHCMNADDTOCRNTTIME(phichTime, phichTime, 7);
8554 /* Fetch the corresponding UL slot Idx in UL sf array */
8555 reTxIdx = rgSCHCmnGetUlSfIdx(&phichTime, cell);
8558 else if(phichTime.slot == 1 || phichTime.slot == 6)
8560 /* Retx will happen at n+7 */
8561 RGSCHCMNADDTOCRNTTIME(phichTime, phichTime, 7);
8562 /* Fetch the corresponding UL slot Idx in UL sf array */
8563 reTxIdx = rgSCHCmnGetUlSfIdx(&phichTime, cell);
8570 * @brief Utility function to calculate total num of PRBs required to
8571 * satisfy DL BO for TM1/TM2/TM6/TM7
8575 * Function : rgSchUtlDlCalc1CwPrb
8577 * Calculate PRBs required for UE to satisfy BO in DL
8579 * Note : Total calculated PRBs will be assigned to *prbReqrd
8582 * @param[in] RgSchCellCb *cell
8583 * @param[in] RgSchUeCb *ue
8584 * @param[in] uint32_t bo
8585 * @param[out] uint32_t *prbReqrd
8588 Void rgSchUtlDlCalc1CwPrb(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8590 RgSchCmnDlCell *dlCell = RG_SCH_CMN_GET_DL_CELL(cell);
8591 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ue, cell);
8595 uint8_t cfi = dlCell->currCfi;
8597 iTbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
8598 eff = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[0][cfi]))[iTbs];
8600 /* Optimization to convert totalBo (which is in-terms of bytes) to bits
8601 * i.e, << 3 and multiply with 1024 i.e, << 10 */
8602 noRes = ((uint64_t)((bo << 3) << 10)) / (eff);
8603 /* Get the number of RBs needed for this transmission */
8604 /* Number of RBs = No of REs / No of REs per RB */
8605 *prbReqrd = RGSCH_CEIL(noRes, dlCell->noResPerRb[cfi]);
8608 } /* rgSchUtlDlCalc1CwPrb*/
8611 * @brief Utility function to calculate total num of PRBs required to
8612 * satisfy DL BO(BO sum of all logical channels for that UE or an LC BO)
8617 * Function : rgSchUtlDlCalc2CwPrb
8619 * Calculate PRBs required for UE to satisfy BO in DL
8621 * Note : Total calculated PRBs will be assigned to *prbReqrd
8624 * @param[in] RgSchCellCb *cell
8625 * @param[in] RgSchUeCb *ue
8626 * @param[in] uint32_t bo
8627 * @param[out] uint32_t *prbReqrd
8630 Void rgSchUtlDlCalc2CwPrb(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8632 RgSchCmnDlCell *dlCell = RG_SCH_CMN_GET_DL_CELL(cell);
8633 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ue, cell);
8634 uint32_t eff1, eff2;
8636 uint8_t noLyr1, noLyr2;
8637 uint8_t iTbs1, iTbs2;
8638 uint8_t cfi = dlCell->currCfi;
8640 if ((dlUe->mimoInfo.forceTD) ||/* Transmit Diversity (TD) */
8641 (dlUe->mimoInfo.ri < 2))/* 1 layer precoding */
8643 iTbs1 = dlUe->mimoInfo.cwInfo[0].iTbs[0];
8644 eff1 = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[0][cfi]))[iTbs1];
8646 /* Optimization to convert totalBo (which is in-terms of bytes) to bits
8647 * i.e, << 3 and multiply with 1024 i.e, << 10 */
8648 noRes = ((uint64_t)((bo << 3) << 10)) / (eff1);
8649 /* Get the number of RBs needed for this transmission */
8650 /* Number of RBs = No of REs / No of REs per RB */
8651 *prbReqrd = RGSCH_CEIL(noRes, dlCell->noResPerRb[cfi]);
8655 noLyr1 = dlUe->mimoInfo.cwInfo[0].noLyr;
8656 noLyr2 = dlUe->mimoInfo.cwInfo[1].noLyr;
8657 iTbs1 = dlUe->mimoInfo.cwInfo[0].iTbs[noLyr1 - 1];
8658 iTbs2 = dlUe->mimoInfo.cwInfo[1].iTbs[noLyr2 - 1];
8659 eff1 = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[noLyr1 - 1][cfi]))[iTbs1];
8660 eff2 = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[noLyr2 - 1][cfi]))[iTbs2];
8662 /* Optimization to convert totalBo (which is in-terms of bytes) to bits
8663 * i.e, << 3 and multiply with 1024 i.e, << 10 */
8664 noRes = ((uint64_t)((bo << 3) << 10)) / (eff1 + eff2);
8665 /* Get the number of RBs needed for this transmission */
8666 /* Number of RBs = No of REs / No of REs per RB */
8667 *prbReqrd = RGSCH_CEIL(noRes, dlCell->noResPerRb[cfi]);
8670 } /* rgSchUtlDlCalc2CwPrb */
8673 * @brief Utility function to calculate total num of PRBs required to
8674 * satisfy DL BO(BO sum of all logical channels for that UE or an LC BO)
8678 * Function : rgSchUtlCalcTotalPrbReq
8680 * This function calls TM specific routine to calculate PRB
8683 * @param[in] RgSchCellCb *cell
8684 * @param[in] RgSchUeCb *ue
8685 * @param[in] uint32_t bo
8686 * @param[out] uint32_t *prbReqrd
8689 Void rgSchUtlCalcTotalPrbReq(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8691 /* Call TM specific Prb calculation routine */
8692 (dlCalcPrbFunc[ue->mimoInfo.txMode - 1])(cell, ue, bo, prbReqrd);
8695 } /* rgSchUtlCalcTotalPrbReq */
8698 /***********************************************************
8700 * Func : rgSCHUtlFetchPcqiBitSz
8703 * Desc : Fetch the CQI/PMI bits for a UE based on the mode, periodicity.
8712 **********************************************************/
8713 static uint8_t rgSCHUtlFetchPcqiBitSz(RgSchCellCb *cell, RgSchUeCb *ueCb,uint8_t numTxAnt)
8715 uint8_t confRepMode;
8718 RgSchUePCqiCb *cqiCb = RG_SCH_GET_UE_CELL_CQI_CB(ueCb,cell);
8720 confRepMode = cqiCb->cqiCfg.cqiSetup.prdModeEnum;
8721 if((ueCb->mimoInfo.txMode != RGR_UE_TM_3) &&
8722 (ueCb->mimoInfo.txMode != RGR_UE_TM_4))
8728 ri = cqiCb->perRiVal;
8732 case RGR_PRD_CQI_MOD10:
8738 case RGR_PRD_CQI_MOD11:
8751 else if(numTxAnt == 4)
8764 /* This is number of antenna case 1.
8765 * This is not applicable for Mode 1-1.
8766 * So setting it to invalid value */
8772 case RGR_PRD_CQI_MOD20:
8780 pcqiSz = 4 + cqiCb->label;
8785 case RGR_PRD_CQI_MOD21:
8800 else if(numTxAnt == 4)
8813 /* This might be number of antenna case 1.
8814 * For mode 2-1 wideband case only antenna port 2 or 4 is supported.
8815 * So setting invalid value.*/
8823 pcqiSz = 4 + cqiCb->label;
8827 pcqiSz = 7 + cqiCb->label;
8843 * @brief Utility function to returns the number of subbands based on the
8848 * Function : rgSchUtlGetNumSbs
8850 * Calculate the number of PRBs
8851 * Update the subbandRequired based on the nPrbs and subband size
8853 * @param[in] RgSchCellCb *cell
8854 * @param[in] RgSchUeCb *ue
8855 * @param[in] uint32_t *numSbs
8858 uint8_t rgSchUtlGetNumSbs(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t *numSbs)
8861 //Currently hardcoding MAX prb for each UE
8862 nPrb = ue->ue5gtfCb.maxPrb;
8863 (*numSbs) = RGSCH_CEIL(nPrb, MAX_5GTF_VRBG_SIZE);
8868 * @brief Utility function to insert the UE node into UE Lst based on the
8869 * number of subbands allocated for the UE for the current TTI.
8873 * Function : rgSchUtlSortInsUeLst
8875 * If subbandRequired < Min, then insert at head
8876 * Else If subbandRequired > Max, then insert at tail
8877 * Else, traverse the list and place the node at the appropriate place
8879 * @param[in] RgSchCellCb *cell
8880 * @param[in] RgSchUeCb *ue
8883 uint8_t rgSchUtlSortInsUeLst(RgSchCellCb *cell,CmLListCp *ueLst,CmLList *node,uint8_t vrbgRequired)
8886 CmLList *firstUeInLst;
8887 CmLList *lastUeInLst;
8891 //firstUeInLst = cmLListFirst(ueLst);
8892 CM_LLIST_FIRST_NODE(ueLst,firstUeInLst);
8893 if(NULLP == firstUeInLst)
8895 /* first node to be added to the list */
8896 cmLListAdd2Tail(ueLst, node);
8900 /* Sb Required for the UE is less than the first node in the list */
8901 tempUe = (RgSchUeCb *)(firstUeInLst->node);
8902 ueUl = RG_SCH_CMN_GET_UL_UE(tempUe, cell);
8904 if(vrbgRequired <= ueUl->vrbgRequired)
8906 cmLListInsCrnt(ueLst, (node));
8910 /* Sb Required for this UE is higher than the UEs in the list */
8911 lastUeInLst = cmLListLast(ueLst);
8912 tempUe = (RgSchUeCb *)(lastUeInLst->node);
8913 if(vrbgRequired >= ueUl->vrbgRequired)
8915 cmLListAdd2Tail(ueLst, (node));
8919 /* This UE needs to be in the middle. Search and insert the UE */
8920 ueInLst = cmLListFirst(ueLst);
8923 tempUe = (RgSchUeCb *)(ueInLst->node);
8925 if(vrbgRequired <= ueUl->vrbgRequired)
8927 cmLListInsCrnt(ueLst, (node));
8931 ueInLst = cmLListNext(ueLst);
8933 } while(NULLP != ueInLst && ueInLst != firstUeInLst);
8942 * @brief Function to Send LCG GBR register to MAC
8946 * Function: rgSCHUtlBuildNSendLcgReg
8948 * Handler for sending LCG GBR registration
8955 * @param[in] RgSchCellCb *cell
8956 * @param[in] CmLteRnti crnti
8957 * @param[in] uint8_t lcgId
8958 * @param[in] Bool isGbr
8962 S16 rgSCHUtlBuildNSendLcgReg(RgSchCellCb *cell,CmLteRnti crnti,uint8_t lcgId,Bool isGbr)
8965 RgInfLcgRegReq lcgRegReq;
8967 memset(&pst, 0, sizeof(Pst));
8968 lcgRegReq.isGbr = isGbr;
8969 lcgRegReq.cellId = cell->cellId;
8970 lcgRegReq.crnti = crnti;
8971 lcgRegReq.lcgId = lcgId;
8972 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
8973 /* code Coverage portion of the test case */
8974 RgSchMacLcgReg(&pst, &lcgRegReq);
8983 * @brief Function to map RGR pucch type to TFU type
8987 * Function: rgSchUtlGetFdbkMode
8995 * @param[in] RgrSchFrmt1b3TypEnum
8996 * @return TfuAckNackMode
8999 TfuAckNackMode rgSchUtlGetFdbkMode(RgrSchFrmt1b3TypEnum fdbkType)
9002 TfuAckNackMode mode = TFU_UCI_FORMAT_1A_1B;
9006 case RG_SCH_UCI_FORMAT_NON_CA:
9007 case RG_SCH_UCI_FORMAT1A_1B:
9009 mode = TFU_UCI_FORMAT_1A_1B;
9012 case RG_SCH_UCI_FORMAT1B_CS:
9014 mode = TFU_UCI_FORMAT_1B_CS;
9017 case RG_SCH_UCI_FORMAT3:
9019 mode = TFU_UCI_FORMAT_3;
9025 #endif /* TFU_TDD */
9026 #endif /* LTE_ADV */
9027 #endif /*TFU_UPGRADE */
9031 * @brief Send Ue SCell delete to SMAC.
9035 * Function : rgSCHUtlSndUeSCellDel2Mac
9036 * This function populates the struct RgInfRlsRnti and
9037 * get the pst for SMac and mark field isUeSCellDel to TRUE which
9038 * indicates that it is a Ue SCell delete.
9042 * @param[in] RgSchCellCb *cell
9043 * @param[in] CmLteRnti rnti
9047 Void rgSCHUtlSndUeSCellDel2Mac(RgSchCellCb *cell,CmLteRnti rnti)
9050 Inst inst = cell->instIdx;
9051 RgInfRlsRnti rntiInfo;
9053 RGSCHDBGINFONEW(inst,(rgSchPBuf(inst),"RNTI Release IND for UE(%d)\n", rnti));
9054 /* Copy the info to rntiInfo */
9055 rntiInfo.cellId = cell->cellId;
9056 rntiInfo.rnti = rnti;
9057 /* Fix : syed ueId change as part of reestablishment.
9058 * Now SCH to trigger this. CRG ueRecfg for ueId change
9060 rntiInfo.ueIdChng = FALSE;
9061 rntiInfo.newRnti = rnti;
9062 rntiInfo.isUeSCellDel = TRUE;
9063 /* Invoke MAC to release the rnti */
9064 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[inst], cell->macInst);
9065 RgSchMacRlsRnti(&pst, &rntiInfo);
9070 * @brief Returns max TB supported by a given txMode
9074 * Function : rgSCHUtlGetMaxTbSupp
9075 * Max TB supported for TM Modes (1,2,5,6 and 7) is 1
9079 * @param[in] RgrTxMode txMode
9080 * @return uint8_t maxTbCount;
9083 uint8_t rgSCHUtlGetMaxTbSupp(RgrTxMode txMode)
9109 return (maxTbCount);
9113 * @brief Send Ue SCell delete to SMAC.
9117 * Function : rgSCHTomUtlGetTrigSet
9118 * This function gets the triggerset based on cqiReq
9120 * @param[in] RgSchCellCb *cell
9121 * @param[in] RgSchUeCb ueCb
9122 * @param[in] uint8_t cqiReq,
9123 * @param[out] uint8_t *triggerSet
9128 Void rgSCHTomUtlGetTrigSet(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t cqiReq,uint8_t *triggerSet)
9130 RgSchUeCellInfo *pCellInfo = RG_SCH_CMN_GET_PCELL_INFO(ueCb);
9133 case RG_SCH_APCQI_SERVING_CC:
9135 /* APeriodic CQI request for Current Carrier.*/
9136 uint8_t sCellIdx = ueCb->cellIdToCellIdxMap[RG_SCH_CELLINDEX(cell)];
9137 *triggerSet = 1 << (7 - sCellIdx);
9140 case RG_SCH_APCQI_1ST_SERVING_CCS_SET:
9142 *triggerSet = pCellInfo->acqiCb.aCqiCfg.triggerSet1;
9145 case RG_SCH_APCQI_2ND_SERVING_CCS_SET:
9147 *triggerSet = pCellInfo->acqiCb.aCqiCfg.triggerSet2;
9160 * @brief This function updates the value of UE specific DCI sizes
9164 * Function: rgSCHUtlUpdUeDciSize
9165 * Purpose: This function calculates and updates DCI Sizes in bits.
9167 * Invoked by: Scheduler
9169 * @param[in] RgSchCellCb *cell
9170 * @param[in] RgSchUeCb *ueCb
9171 * @param[in] isCsi2Bit *isCsi2Bit: is 1 bit or 2 bit CSI
9175 Void rgSCHUtlUpdUeDciSize(RgSchCellCb *cell,RgSchUeCb *ueCb,Bool isCsi2Bit)
9177 uint8_t dci01aCmnSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0];
9178 uint8_t dci01aDedSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0];
9179 if ((ueCb->accessStratumRls >= RGR_REL_10) && (cell->bwCfg.dlTotalBw >= cell->bwCfg.ulTotalBw))
9181 dci01aCmnSize += 1; /* Resource Allocation Type DCI 0 */
9182 dci01aDedSize += 1; /* Resource Allocation Type DCI 0 */
9184 if (isCsi2Bit == TRUE)
9186 dci01aDedSize += 2; /* 2 bit CSI DCI 0 */
9190 dci01aDedSize += 1; /* 1 bit CSI DCI 0 */
9193 /* Common CSI is always 1 bit DCI 0 */
9194 dci01aCmnSize += 1; /* 1 bit CSI DCI 0 */
9196 /* Compare the sizes of DCI 0 with DCI 1A and consider the greater */
9197 if (dci01aCmnSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9199 dci01aCmnSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9201 if (dci01aDedSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9203 dci01aDedSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9206 /* Remove the Ambiguous Sizes as mentioned in table Table 5.3.3.1.2-1 Spec 36.212-a80 Sec 5.3.3.1.3 */
9207 dci01aCmnSize += rgSchDciAmbigSizeTbl[dci01aCmnSize];
9208 dci01aDedSize += rgSchDciAmbigSizeTbl[dci01aDedSize];
9210 ueCb->dciSize.cmnSize[TFU_DCI_FORMAT_0] = dci01aCmnSize;
9211 ueCb->dciSize.cmnSize[TFU_DCI_FORMAT_1A] = dci01aCmnSize;
9213 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_0] = dci01aDedSize;
9214 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A] = dci01aDedSize;
9216 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1];
9218 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the UE is configured to decode PDCCH with CRC scrambled
9219 * by the C-RNTI and the number of information bits in format 1 is equal to that for format 0/1A
9220 * for scheduling the same serving cell and mapped onto the UE specific search space given by the
9221 * C-RNTI as defined in [3], one bit of value zero shall be appended to format 1. */
9222 if (ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A])
9224 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] += 1;
9227 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the number of information bits in format 1 belongs
9228 * to one of the sizes in Table 5.3.3.1.2-1, one or more zero bit(s) shall be appended
9229 * to format 1 until the payload size of format 1 does not belong to one of the sizes in
9230 * Table 5.3.3.1.2-1 and is not equal to that of format 0/1A mapped onto the same search space. */
9231 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] += rgSchDciAmbigSizeTbl[ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1]];
9232 } while (ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A]);
9234 /* Just copying the value of 2/2A to avoid multiple checks at PDCCH allocations. This values never change.*/
9235 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_2] = cell->dciSize.size[TFU_DCI_FORMAT_2];
9236 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_2A] = cell->dciSize.size[TFU_DCI_FORMAT_2A];
9237 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_2] = cell->dciSize.size[TFU_DCI_FORMAT_2];
9238 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_2A] = cell->dciSize.size[TFU_DCI_FORMAT_2A];
9240 /* Spec 36.212-a80 Sec 5.3.3.1.3: except when format 1A assigns downlink resource
9241 * on a secondary cell without an uplink configuration associated with the secondary cell */
9242 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9243 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A] += rgSchDciAmbigSizeTbl[ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A]];
9244 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1];
9246 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the UE is configured to decode PDCCH with CRC scrambled
9247 * by the C-RNTI and the number of information bits in format 1 is equal to that for format 0/1A
9248 * for scheduling the same serving cell and mapped onto the UE specific search space given by the
9249 * C-RNTI as defined in [3], one bit of value zero shall be appended to format 1. */
9250 if (ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A])
9252 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] += 1;
9255 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the number of information bits in format 1 belongs
9256 * to one of the sizes in Table 5.3.3.1.2-1, one or more zero bit(s) shall be appended
9257 * to format 1 until the payload size of format 1 does not belong to one of the sizes in
9258 * Table 5.3.3.1.2-1 and is not equal to that of format 0/1A mapped onto the same search space. */
9259 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] += rgSchDciAmbigSizeTbl[ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1]];
9260 } while (ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A]);
9262 rgSCHEmtcUtlUpdUeDciSize(cell, ueCb);
9267 * @brief This function initialises the DCI Size table
9271 * Function: rgSCHUtlCalcDciSizes
9272 * Purpose: This function calculates and initialises DCI Sizes in bits.
9274 * Invoked by: Scheduler
9276 * @param[in] RgSchCellCb *cell
9280 Void rgSCHUtlCalcDciSizes(RgSchCellCb *cell)
9282 uint8_t dciSize = 0;
9283 uint8_t dci01aSize = 0;
9284 uint32_t bits = 0, idx = 0;
9286 switch(TFU_DCI_FORMAT_0) /* Switch case for the purpose of readability */
9288 case TFU_DCI_FORMAT_0:
9290 /* DCI 0: Spec 36.212 Section 5.3.3.1.1 */
9292 /*-- Calculate resource block assignment bits need to be set
9293 Which is ln(N(N+1)/2) 36.212 5.3.3.1 --*/
9294 bits = (cell->bwCfg.ulTotalBw * (cell->bwCfg.ulTotalBw + 1) / 2);
9295 while ((bits & 0x8000) == 0)
9302 dciSize = 1 /* DCI 0 bit indicator */ + \
9303 1 /* Frequency hoping enable bit field */ + \
9304 (uint8_t)bits /* For frequency Hopping */ + \
9311 2 /* UL Index Config 0 or DAI Config 1-6 */
9315 cell->dciSize.baseSize[TFU_DCI_FORMAT_0] = dciSize;
9317 /* If hoping flag is enabled */
9318 if (cell->bwCfg.ulTotalBw <= 49) /* Spec 36.213 Table 8.4-1, N UL_hop, if hopping is enabled */
9320 cell->dciSize.dci0HopSize = 1;
9324 cell->dciSize.dci0HopSize = 2;
9327 /* Update common non-CRNTI scrambled DCI 0/1A flag */
9328 dci01aSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0] + 1; /* 1 bit CSI */
9330 case TFU_DCI_FORMAT_1A:
9332 /* DCI 1A: Spec 36.212 Section 5.3.3.1.3 */
9335 /* Calculate resource block assignment bits need to be set
9336 Which is ln(N(N+1)/2) */
9337 bits = (cell->bwCfg.dlTotalBw * (cell->bwCfg.dlTotalBw + 1) / 2);
9338 while ((bits & 0x8000) == 0)
9345 dciSize += 1 /* Format 1A */ + \
9346 1 /* Local or Distributed */ + \
9347 (uint8_t)bits /* Resource block Assignment */ + \
9350 4 /* HARQ Proc Id */ +
9352 3 /* HARQ Proc Id */ +
9362 cell->dciSize.baseSize[TFU_DCI_FORMAT_1A] = dciSize;
9364 /* If the UE is not configured to decode PDCCH with CRC scrambled by the C-RNTI,
9365 * and the number of information bits in format 1A is less than that of format 0,
9366 * zeros shall be appended to format 1A until the payload size equals that of format 0. */
9367 /* Compare the size with DCI 1A and DCI 0 and consider the greater one */
9368 if (dci01aSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9370 dci01aSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9372 /* If the number of information bits in format 1A belongs to one of the sizes in
9373 * Table 5.3.3.1.2-1, one zero bit shall be appended to format 1A. */
9374 dci01aSize += rgSchDciAmbigSizeTbl[dci01aSize];
9375 cell->dciSize.size[TFU_DCI_FORMAT_1A] = cell->dciSize.size[TFU_DCI_FORMAT_0] = dci01aSize;
9377 case TFU_DCI_FORMAT_1:
9379 /* DCI 1: Spec 36.212 Section 5.3.3.1.2 */
9381 if (cell->bwCfg.dlTotalBw > 10)
9383 dciSize = 1; /* Resource Allocation header bit */
9386 /* Resouce allocation bits Type 0 and Type 1 */
9387 bits = (cell->bwCfg.dlTotalBw/cell->rbgSize);
9388 if ((cell->bwCfg.dlTotalBw % cell->rbgSize) != 0)
9393 dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9401 2 /* Redunancy Version */ + \
9410 cell->dciSize.baseSize[TFU_DCI_FORMAT_1] = dciSize;
9412 cell->dciSize.size[TFU_DCI_FORMAT_1] = dciSize;
9415 /* If the UE is not configured to decode PDCCH with CRC
9416 * scrambled by the C-RNTI and the number of information bits in format 1
9417 * is equal to that for format 0/1A, one bit of value zero shall be appended
9419 if (dci01aSize == cell->dciSize.size[TFU_DCI_FORMAT_1])
9421 cell->dciSize.size[TFU_DCI_FORMAT_1] += 1;
9424 /* If the number of information bits in format 1 belongs to one of the sizes in
9425 * Table 5.3.3.1.2-1, one or more zero bit(s) shall be appended to format 1 until
9426 * the payload size of format 1 does not belong to one of the sizes in Table 5.3.3.1.2-1
9427 * and is not equal to that of format 0/1A mapped onto the same search space. */
9428 cell->dciSize.size[TFU_DCI_FORMAT_1] += rgSchDciAmbigSizeTbl[cell->dciSize.size[TFU_DCI_FORMAT_1]];
9429 } while (cell->dciSize.size[TFU_DCI_FORMAT_1] == dci01aSize);
9431 case TFU_DCI_FORMAT_2:
9433 /* DCI 2: Spec 36.212 Section 5.3.3.1.5 */
9435 if (cell->bwCfg.dlTotalBw > 10)
9437 dciSize = 1; /* Resource Allocation bit */
9440 dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9448 1 /* CW Swap Flag */ + \
9449 5 /* MCS for TB1 */+ \
9450 1 /* NDI for TB1 */+ \
9451 2 /* RV for TB1 */ + \
9452 5 /* MCS for TB2 */+ \
9453 1 /* NDI for TB2 */+ \
9455 if (cell->numTxAntPorts == 2)
9459 else if (cell->numTxAntPorts == 4)
9463 cell->dciSize.size[TFU_DCI_FORMAT_2] = dciSize;
9464 cell->dciSize.size[TFU_DCI_FORMAT_2] += rgSchDciAmbigSizeTbl[cell->dciSize.size[TFU_DCI_FORMAT_2]];
9466 case TFU_DCI_FORMAT_2A:
9468 /* DCI 2A: Spec 36.212 Section 5.3.3.1.5A */
9470 if (cell->bwCfg.dlTotalBw > 10)
9472 dciSize = 1; /* Resource Allocation bit */
9475 dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9483 1 /* CW Swap Flag */ + \
9484 5 /* MCS for TB1 */+ \
9485 1 /* NDI for TB1 */+ \
9486 2 /* RV for TB1 */ + \
9487 5 /* MCS for TB2 */+ \
9488 1 /* NDI for TB2 */+ \
9490 if (cell->numTxAntPorts == 4)
9494 cell->dciSize.size[TFU_DCI_FORMAT_2A] = dciSize;
9495 cell->dciSize.size[TFU_DCI_FORMAT_2A] += \
9496 rgSchDciAmbigSizeTbl[cell->dciSize.size[TFU_DCI_FORMAT_2A]]; /* Spec 39.212 Table 5.3.3.1.2-1 */
9498 case TFU_DCI_FORMAT_3:
9500 /* DCI 3: Spec 36.212 Section 5.3.3.1.6 */
9501 cell->dciSize.size[TFU_DCI_FORMAT_3] = cell->dciSize.size[TFU_DCI_FORMAT_1A] / 2;
9502 if (cell->dciSize.size[TFU_DCI_FORMAT_3] % 2)
9504 cell->dciSize.size[TFU_DCI_FORMAT_3]++;
9507 case TFU_DCI_FORMAT_3A:
9509 /* DCI 3A: Spec 36.212 Section 5.3.3.1.7 */
9510 cell->dciSize.size[TFU_DCI_FORMAT_3A] = cell->dciSize.size[TFU_DCI_FORMAT_1A];
9513 case TFU_DCI_FORMAT_6_0A:
9515 rgSCHEmtcGetDciFrmt60ASize(cell);
9517 case TFU_DCI_FORMAT_6_1A:
9519 rgSCHEmtcGetDciFrmt61ASize(cell);
9524 /* DCI format not supported */
9531 * @brief Handler for the CPU OvrLd related state adjustment.
9535 * Function : rgSCHUtlCpuOvrLdAdjItbsCap
9538 * - Record dl/ulTpts
9539 * - Adjust maxItbs to acheive target throughputs
9541 * @param[in] RgSchCellCb *cell
9544 Void rgSCHUtlCpuOvrLdAdjItbsCap( RgSchCellCb *cell)
9548 if ((cell->cpuOvrLdCntrl.cpuOvrLdIns) & (RGR_CPU_OVRLD_DL_TPT_UP |
9549 RGR_CPU_OVRLD_DL_TPT_DOWN))
9551 /* Regulate DL Tpt for CPU overload */
9552 if (cell->measurements.dlTpt > cell->cpuOvrLdCntrl.tgtDlTpt)
9554 tptDelta = cell->measurements.dlTpt - cell->cpuOvrLdCntrl.tgtDlTpt;
9555 /* Upto 0.5% drift in measured vs target tpt is ignored */
9556 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtDlTpt) > 5)
9558 cell->thresholds.maxDlItbs = RGSCH_MAX((cell->thresholds.maxDlItbs-1), 1);
9563 tptDelta = cell->cpuOvrLdCntrl.tgtDlTpt - cell->measurements.dlTpt;
9564 /* Upto 0.5% drift in measured vs target tpt is ignored */
9565 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtDlTpt) > 5)
9567 cell->thresholds.maxDlItbs = RGSCH_MIN((cell->thresholds.maxDlItbs+1), RG_SCH_DL_MAX_ITBS);
9570 #ifdef CPU_OL_DBG_PRINTS
9571 printf("\n DL CPU OL ADJ = %lu, %lu, %d\n", cell->measurements.dlTpt, cell->cpuOvrLdCntrl.tgtDlTpt,
9572 cell->thresholds.maxDlItbs);
9576 if ((cell->cpuOvrLdCntrl.cpuOvrLdIns) & (RGR_CPU_OVRLD_UL_TPT_UP |
9577 RGR_CPU_OVRLD_UL_TPT_DOWN))
9579 /* Regualte DL Tpt for CPU overload */
9580 if (cell->measurements.ulTpt > cell->cpuOvrLdCntrl.tgtUlTpt)
9582 tptDelta = cell->measurements.ulTpt - cell->cpuOvrLdCntrl.tgtUlTpt;
9583 /* Upto 1% drift in measured vs target tpt is ignored */
9584 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtUlTpt) > 10)
9586 cell->thresholds.maxUlItbs = RGSCH_MAX((cell->thresholds.maxUlItbs-1), 1);
9591 tptDelta = cell->cpuOvrLdCntrl.tgtUlTpt - cell->measurements.ulTpt;
9592 /* Upto 1% drift in measured vs target tpt is ignored */
9593 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtUlTpt) > 10)
9595 cell->thresholds.maxUlItbs = RGSCH_MIN((cell->thresholds.maxUlItbs+1), RG_SCH_UL_MAX_ITBS);
9598 #ifdef CPU_OL_DBG_PRINTS
9599 printf("\n UL CPU OL ADJ = %lu, %lu, %d\n", cell->measurements.ulTpt, cell->cpuOvrLdCntrl.tgtUlTpt,
9600 cell->thresholds.maxUlItbs);
9607 * @brief Handler for the num UE per TTI based CPU OvrLd instr updating
9611 * Function : rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr
9614 * - Validate the config params.
9615 * - Update numUEperTTi CPU OL related information.
9616 * - If successful, return ROK else RFAILED.
9618 * @param[in] RgSchCellCb *cell
9619 * @param[in] uint8_t cnrtCpuOvrLdIns
9622 static Void rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr(RgSchCellCb *cell,uint8_t crntCpuOvrLdIns)
9624 RgSchCpuOvrLdCntrlCb *cpuInstr = &(cell->cpuOvrLdCntrl);
9625 RgSchCmnCell *cellSch;
9626 uint8_t maxUeNewDlTxPerTti;
9627 uint8_t maxUeNewUlTxPerTti;
9628 uint8_t tmpslot = 0;
9629 #ifdef CPU_OL_DBG_PRINTS
9632 uint8_t maxDlDecCnt;
9633 uint8_t maxUlDecCnt;
9635 cellSch = RG_SCH_CMN_GET_CELL(cell);
9637 maxUeNewDlTxPerTti = cellSch->dl.maxUeNewTxPerTti;
9638 maxUeNewUlTxPerTti = cellSch->ul.maxUeNewTxPerTti;
9640 /* Calculate Maximum Decremen */
9641 maxDlDecCnt = (10*(maxUeNewDlTxPerTti - 1))-(10-RGR_MAX_PERC_NUM_UE_PER_TTI_RED);
9642 maxUlDecCnt = (10*(maxUeNewUlTxPerTti - 1))-(10-RGR_MAX_PERC_NUM_UE_PER_TTI_RED);
9644 /* Check for DL CPU Commands */
9645 if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_DEC_NUM_UE_PER_TTI )
9647 /* Decrement till 90% of maxUeNewDlTxPerTti */
9648 if ( cpuInstr->dlNxtIndxDecNumUeTti < maxDlDecCnt )
9650 tmpslot = (cpuInstr->dlNxtIndxDecNumUeTti) % 10;
9651 cpuInstr->dlNxtIndxDecNumUeTti++;
9652 if ( cpuInstr->maxUeNewTxPerTti[tmpslot] > 1 )
9654 cpuInstr->maxUeNewTxPerTti[tmpslot]--;
9658 #ifdef CPU_OL_DBG_PRINTS
9659 printf("CPU_OL_TTI__ERROR\n");
9661 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Invalid CPU OL");
9664 #ifdef CPU_OL_DBG_PRINTS
9665 printf("dlNxtIndxDecNumUeTti = %d\n", cpuInstr->dlNxtIndxDecNumUeTti);
9667 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,"dlNxtIndxDecNumUeTti = %d",
9668 cpuInstr->dlNxtIndxDecNumUeTti);
9670 else if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_INC_NUM_UE_PER_TTI )
9672 if ( cpuInstr->dlNxtIndxDecNumUeTti > 0)
9674 cpuInstr->dlNxtIndxDecNumUeTti--;
9675 tmpslot = (cpuInstr->dlNxtIndxDecNumUeTti) % 10;
9676 if ( cpuInstr->maxUeNewTxPerTti[tmpslot] < maxUeNewDlTxPerTti )
9678 cpuInstr->maxUeNewTxPerTti[tmpslot]++;
9682 #ifdef CPU_OL_DBG_PRINTS
9683 printf("CPU_OL_TTI__ERROR\n");
9685 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Invalid CPU OL");
9688 #ifdef CPU_OL_DBG_PRINTS
9689 printf("dlNxtIndxDecNumUeTti = %d\n", cpuInstr->dlNxtIndxDecNumUeTti);
9691 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,"dlNxtIndxDecNumUeTti = %d",
9692 cpuInstr->dlNxtIndxDecNumUeTti);
9694 /* Check for UL CPU commands */
9695 if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_DEC_NUM_UE_PER_TTI )
9697 /* Decrement till 90% of maxUeNewDlTxPerTti */
9698 if ( cpuInstr->ulNxtIndxDecNumUeTti < maxUlDecCnt )
9700 tmpslot = (cpuInstr->ulNxtIndxDecNumUeTti) % 10;
9701 cpuInstr->ulNxtIndxDecNumUeTti++;
9702 if ( cpuInstr->maxUeNewRxPerTti[tmpslot] > 1 )
9704 cpuInstr->maxUeNewRxPerTti[tmpslot]--;
9708 #ifdef CPU_OL_DBG_PRINTS
9709 printf("CPU_OL_TTI__ERROR\n");
9711 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Invalid CPU OL");
9714 #ifdef CPU_OL_DBG_PRINTS
9715 printf("ulNxtIndxDecNumUeTti = %d\n", cpuInstr->ulNxtIndxDecNumUeTti);
9717 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,"dlNxtIndxDecNumUeTti = %d",
9718 cpuInstr->dlNxtIndxDecNumUeTti);
9720 else if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_INC_NUM_UE_PER_TTI )
9722 if ( cpuInstr->ulNxtIndxDecNumUeTti > 0)
9724 cpuInstr->ulNxtIndxDecNumUeTti--;
9725 tmpslot = (cpuInstr->ulNxtIndxDecNumUeTti) % 10;
9726 if ( cpuInstr->maxUeNewRxPerTti[tmpslot] < maxUeNewUlTxPerTti )
9728 cpuInstr->maxUeNewRxPerTti[tmpslot]++;
9732 #ifdef CPU_OL_DBG_PRINTS
9733 printf("CPU_OL_TTI__ERROR\n");
9735 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Invalid CPU OL");
9738 #ifdef CPU_OL_DBG_PRINTS
9739 printf("ulNxtIndxDecNumUeTti = %d\n", cpuInstr->ulNxtIndxDecNumUeTti);
9741 RLOG_ARG1(L_DEBUG,DBG_CELLID,cell->cellId,"dlNxtIndxDecNumUeTti = %d",
9742 cpuInstr->dlNxtIndxDecNumUeTti);
9744 #ifdef CPU_OL_DBG_PRINTS
9745 /* TODO: Debug Information - Shall be moved under CPU_OL_DBG_PRINTS */
9746 printf("maxUeNewDlTxPerTti = %d, maxUeNewUlTxPerTti = %d\n", maxUeNewDlTxPerTti, maxUeNewUlTxPerTti);
9747 printf("DL Sf numUePerTti:");
9748 for ( idx = 0; idx < 10 ; idx ++ )
9750 printf(" %d", cpuInstr->maxUeNewTxPerTti[idx]);
9752 printf("\nUL Sf numUePerTti:");
9753 for ( idx = 0; idx < 10 ; idx ++ )
9755 printf(" %d", cpuInstr->maxUeNewRxPerTti[idx]);
9761 } /* rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr */
9764 * @brief Handler for the CPU OvrLd related cell Recfg.
9768 * Function : rgSCHUtlResetCpuOvrLdState
9771 * - Validate the config params.
9772 * - Update CPU OL related state information.
9773 * - If successful, return ROK else RFAILED.
9775 * @param[in] RgSchCellCb *cell
9776 * @param[in] uint8_t cnrtCpuOvrLdIns
9781 S16 rgSCHUtlResetCpuOvrLdState(RgSchCellCb *cell,uint8_t crntCpuOvrLdIns)
9783 uint8_t crntDlCpuOL=0;
9784 uint8_t crntUlCpuOL=0;
9785 RgSchCmnCell *schCmnCell = (RgSchCmnCell *)(cell->sc.sch);
9788 #ifdef CPU_OL_DBG_PRINTS
9789 printf("\n CPU OVR LD Ins Rcvd = %d\n", (int)crntCpuOvrLdIns);
9791 RLOG_ARG0(L_INFO,DBG_CELLID,cell->cellId,"CPU OVR LD Ins Rcvd");
9793 if ( RGR_CPU_OVRLD_RESET == crntCpuOvrLdIns )
9795 /* The CPU OL instruction received with RESET (0), hence reset it */
9796 #ifdef CPU_OL_DBG_PRINTS
9797 printf("rgSCHUtlResetCpuOvrLdState: RESET CPU OL instr\n");
9799 RLOG_ARG0(L_INFO,DBG_CELLID,cell->cellId,"RESET CPU OVR LD");
9800 cell->cpuOvrLdCntrl.cpuOvrLdIns = 0;
9801 /* Reset the max UL and DL itbs to 26 */
9802 cell->thresholds.maxUlItbs = RG_SCH_UL_MAX_ITBS;
9803 cell->thresholds.maxDlItbs = RG_SCH_DL_MAX_ITBS;
9804 /* Reset the num UE per TTI intructions */
9805 cell->cpuOvrLdCntrl.dlNxtIndxDecNumUeTti = 0;
9806 cell->cpuOvrLdCntrl.ulNxtIndxDecNumUeTti = 0;
9807 for ( idx = 0; idx < 10; idx++ )
9809 cell->cpuOvrLdCntrl.maxUeNewTxPerTti[idx] =
9810 schCmnCell->dl.maxUeNewTxPerTti;
9811 cell->cpuOvrLdCntrl.maxUeNewRxPerTti[idx] =
9812 schCmnCell->ul.maxUeNewTxPerTti;
9817 /* Check and Update numUEPer TTI based CPU overload instruction before
9818 * going for TP based CPU OL
9819 * TTI based intrcuctions shall be > 0xF */
9820 if ( crntCpuOvrLdIns > 0xF )
9822 rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr(cell, crntCpuOvrLdIns);
9823 /* If need to have both TP and numUePerTti instrcution together in
9824 * one command then dont return from here */
9828 crntDlCpuOL = (crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_TPT_UP) +\
9829 (crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_TPT_DOWN);
9830 if ((crntDlCpuOL) && (crntDlCpuOL != RGR_CPU_OVRLD_DL_TPT_UP) &&
9831 (crntDlCpuOL != RGR_CPU_OVRLD_DL_TPT_DOWN))
9833 /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9836 crntUlCpuOL = (crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_TPT_UP) +\
9837 (crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_TPT_DOWN);
9838 if ((crntUlCpuOL) && (crntUlCpuOL != RGR_CPU_OVRLD_UL_TPT_UP) &&
9839 (crntUlCpuOL != RGR_CPU_OVRLD_UL_TPT_DOWN))
9841 /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9844 if ((crntDlCpuOL == 0) && (crntUlCpuOL == 0))
9846 /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9850 cell->cpuOvrLdCntrl.cpuOvrLdIns = crntCpuOvrLdIns;
9854 if (crntUlCpuOL == RGR_CPU_OVRLD_UL_TPT_DOWN)
9856 cell->cpuOvrLdCntrl.tgtUlTpt = cell->measurements.ulTpt - \
9857 (cell->measurements.ulTpt * 3 )/100;
9861 cell->cpuOvrLdCntrl.tgtUlTpt = cell->measurements.ulTpt + \
9862 (cell->measurements.ulTpt * 2 )/100;
9864 RLOG_ARG3(L_DEBUG,DBG_CELLID,cell->cellId,"CPU OVR LD UL Reset to "
9865 "%d, %lu, %lu", (int)crntUlCpuOL, cell->cpuOvrLdCntrl.tgtUlTpt,cell->measurements.ulTpt);
9866 #ifdef CPU_OL_DBG_PRINTS
9867 printf("\n CPU OVR LD UL Reset to= %d, %lu, %lu\n", (int)crntUlCpuOL, cell->cpuOvrLdCntrl.tgtUlTpt,
9868 cell->measurements.ulTpt);
9874 if (crntDlCpuOL == RGR_CPU_OVRLD_DL_TPT_DOWN)
9876 cell->cpuOvrLdCntrl.tgtDlTpt = cell->measurements.dlTpt - \
9877 (cell->measurements.dlTpt * 1 )/100;
9881 cell->cpuOvrLdCntrl.tgtDlTpt = cell->measurements.dlTpt + \
9882 (cell->measurements.dlTpt * 1 )/100;
9884 RLOG_ARG3(L_DEBUG,DBG_CELLID,cell->cellId,"CPU OVR LD DL Reset to "
9885 "%d, %lu, %lu", (int)crntDlCpuOL, cell->cpuOvrLdCntrl.tgtDlTpt,cell->measurements.dlTpt);
9887 #ifdef CPU_OL_DBG_PRINTS
9888 printf("\n CPU OVR LD DL Reset to= %d, %lu, %lu\n", (int)crntDlCpuOL, cell->cpuOvrLdCntrl.tgtDlTpt,
9889 cell->measurements.dlTpt);
9892 rgSCHUtlCpuOvrLdAdjItbsCap(cell);
9896 S16 rgSCHUtlAddToResLst
9902 cmLListAdd2Tail(cp, &iotRes->resLnk);
9903 iotRes->resLnk.node = (PTR)iotRes;
9906 S16 rgSCHUtlDelFrmResLst
9912 CmLListCp *cp = NULLP;
9913 RgSchEmtcUeInfo *emtcUe = NULLP;
9914 emtcUe = RG_GET_EMTC_UE_CB(ue);
9915 if(iotRes->resType == RG_SCH_EMTC_PUCCH_RES)
9917 cp = &emtcUe->ulResLst;
9918 }else if(iotRes->resType == RG_SCH_EMTC_PDSCH_RES)
9920 cp = &emtcUe->dlResLst;
9923 RLOG0(L_INFO, "*****restype mismatch");
9929 RLOG0(L_INFO,"****error count*****\n");
9933 cmLListDelFrm(cp, &iotRes->resLnk);
9934 iotRes->resLnk.node = NULLP;
9938 /**********************************************************************
9941 **********************************************************************/