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.
36 /* header include files -- defines (.h) */
37 #include "common_def.h"
42 #include "rg_sch_err.h"
43 #include "rg_sch_inf.h"
45 #include "rg_sch_cmn.h"
47 #include "rl_interface.h"
48 #include "rl_common.h"
50 /* header/extern include files (.x) */
51 #include "tfu.x" /* TFU types */
52 #include "lrg.x" /* layer management typedefs for MAC */
53 #include "rgr.x" /* layer management typedefs for MAC */
55 #include "rg_sch_inf.x" /* typedefs for Scheduler */
56 #include "rg_sch.x" /* typedefs for Scheduler */
57 #include "rg_sch_cmn.x" /* typedefs for Scheduler */
59 #include "rg_sch_emtc_ext.x"
64 uint32_t rgNumPrachRecvd =0; /* Num of Rach Req received including dedicated preambles */
65 uint32_t rgNumRarSched =0; /* Num of RARs sent */
66 uint32_t rgNumBI =0; /* Num of BackOff Ind sent */
67 uint32_t rgNumMsg3CrcPassed =0; /* Num of CRC success for Msg3 */
68 uint32_t rgNumMsg3CrcFailed =0; /* Num of CRC fail for Msg 3 */
69 uint32_t rgNumMsg3FailMaxRetx =0; /* Num of Msg3 fail after Max Retx attempts */
70 uint32_t rgNumMsg4Ack =0; /* Num of Acks for Msg4 Tx */
71 uint32_t rgNumMsg4Nack =0;
72 /* Num of Nacks for Msg4 Tx */
73 uint32_t rgNumMsg4FailMaxRetx =0; /* Num of Msg4 Tx failed after Max Retx attempts */
74 uint32_t rgNumSrRecvd =0; /* Num of Sched Req received */
75 uint32_t rgNumSrGrant =0; /* Num of Sched Req Grants sent */
76 uint32_t rgNumMsg3CrntiCE =0; /* Num of Msg 3 CRNTI CE received */
77 uint32_t rgNumDedPream =0; /* Num of Dedicated Preambles recvd */
78 uint32_t rgNumMsg3CCCHSdu =0; /* Num of Msg 3 CCCH Sdus recvd */
79 uint32_t rgNumCCCHSduCrntiNotFound =0; /*UE Ctx not found for CCCH SDU Msg 3 */
80 uint32_t rgNumCrntiCeCrntiNotFound =0; /*UE Ctx not found for CRNTI CE Msg 3 */
81 uint32_t rgNumMsg4WithCCCHSdu =0; /* Num of Msg4 with CCCH Sdu */
82 uint32_t rgNumMsg4WoCCCHSdu =0; /* Num of Msg4 without CCCH Sdu */
83 uint32_t rgNumMsg4Dtx =0; /* Num of DTX received for Msg 4 */
84 uint32_t rgNumMsg3AckSent =0; /* Num of PHICH Ack sent for Msg 3 */
85 uint32_t rgNumMsg3NackSent =0; /* Num of PHICH Nack sent for Msg 3 */
86 uint32_t rgNumMsg4PdcchWithCrnti =0; /* Num of PDCCH for CRNTI based contention resolution */
87 uint32_t rgNumRarFailDuetoRntiExhaustion =0; /* Num of RACH Failures due to RNTI pool exhaution */
88 uint32_t rgNumTAModified =0; /* Num of times TA received is different from prev value */
89 uint32_t rgNumTASent =0; /* Num of TA Command sent */
90 uint32_t rgNumMsg4ToBeTx =0; /* Num of times MSG4 that should be sent */
91 uint32_t rgNumMsg4Txed =0; /* Num of MSG4 actually sent *//* ysNumMsg4ToBeTx -ysNumMsg4Txed == Failed MSG4 TX */
92 uint32_t rgNumMsg3DtxRcvd =0; /* CRC Fail with SINR < 0 */
94 uint32_t rgNumDedPreamUECtxtFound =0; /* Num of Dedicated Preambles recvd */
96 static uint8_t rgSchDciAmbigSizeTbl[61] = {0,0,0,0,0,0,0,0,0,0,0,
97 0,1,0,1,0,1,0,0,0,1,
98 0,0,0,1,0,1,0,0,0,0,
99 0,1,0,0,0,0,0,0,0,1,
100 0,0,0,1,0,0,0,0,0,0,
101 0,0,0,0,0,1,0,0,0,0};
105 uint32_t rgSchCmnBetaCqiOffstTbl[16];
106 uint32_t rgSchCmnBetaRiOffstTbl[16];
107 RgSchdApis rgSchCmnApis;
108 S16 RgUiRgmSendPrbRprtInd ARGS((
111 RgmPrbRprtInd *prbRprtInd
114 S16 RgUiRgmSendTmModeChangeInd ARGS((
117 RgmTransModeInd *txModeChngInd
120 S16 rgSCHEmtcUtlGetSfAlloc ARGS((
123 S16 rgSCHEmtcUtlPutSfAlloc ARGS((
126 Void rgSCHEmtcUtlUpdUeDciSize ARGS((
130 Void rgSCHEmtcGetDciFrmt61ASize ARGS((
133 Void rgSCHEmtcGetDciFrmt60ASize ARGS((
136 S16 rgSCHEmtcUtlFillPdschDciInfo ARGS((
137 TfuPdschDciInfo *pdsch,
140 Void rgSCHEmtcUtlRlsRnti ARGS((
142 RgSchRntiLnk *rntiLnk,
145 S16 rgSCHEmtcPdcchAlloc ARGS((
149 Void rgSCHEmtcPdcchFree ARGS((
154 /* Functions specific to TM1/TM2/TM6/TM7 for PRB calculation*/
155 Void rgSchUtlDlCalc1CwPrb ARGS(( RgSchCellCb *cell,
158 uint32_t *prbReqrd));
160 /* Functions specific to TM3/TM4 for PRB calculation*/
161 Void rgSchUtlDlCalc2CwPrb ARGS(( RgSchCellCb *cell,
164 uint32_t *prbReqrd));
167 RgSchCellCb* rgSchUtlGetCellCb ARGS(( Inst inst,
172 typedef Void (*RgSchUtlDlCalcPrbFunc) ARGS((RgSchCellCb *cell, RgSchUeCb *ue,
173 uint32_t bo, uint32_t *prbRequrd));
175 /* Functions specific to each transmission mode for PRB calculation*/
176 RgSchUtlDlCalcPrbFunc dlCalcPrbFunc[7] = {rgSchUtlDlCalc1CwPrb,
177 rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc2CwPrb, rgSchUtlDlCalc2CwPrb,
178 NULLP, rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc1CwPrb};
181 /* Functions specific to each transmission mode for PRB calculation*/
182 RgSchUtlDlCalcPrbFunc dlCalcPrbFunc[9] = {rgSchUtlDlCalc1CwPrb,
183 rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc2CwPrb, rgSchUtlDlCalc2CwPrb,
184 NULLP, rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc1CwPrb, NULLP, NULLP};
189 /* The below table will be used to map the UL SF number in a TDD Cfg 0
190 frame to the ul Sf array maintained in cellCb */
191 static uint8_t rgSchTddCfg0UlSfTbl[] = {2, 3, 4, 7, 8, 9};
194 static S16 rgSCHUtlUlAllocDbInit ARGS((
199 static Void rgSCHUtlUlAllocDbDeinit ARGS((
203 static S16 rgSCHUtlUlHoleDbInit ARGS((
210 static Void rgSCHUtlUlHoleDbDeinit ARGS((
215 static S16 rgSCHChkBoUpdate ARGS((
217 RgInfCmnBoRpt *boUpdt
221 static uint8_t rgSCHUtlFetchPcqiBitSz ARGS((
228 /* sorted in ascending order of tbSz */
229 const struct rgSchUtlBcchPcchTbSz
231 uint8_t rbIndex; /* RB index {2,3} */
232 uint16_t tbSz; /* one of the Transport block size in bits of
234 /* Corrected allocation for common channels */
235 uint8_t mcs; /* imcs */
236 } rgSchUtlBcchPcchTbSzTbl[44] = {
237 { 2, 32, 0 }, { 2, 56, 1 }, { 2, 72, 2 }, { 3, 88, 1 },
238 { 2, 104, 3 }, { 2, 120, 4 }, { 2, 144, 5 }, { 2, 176, 6 },
239 { 3, 208, 4 }, { 2, 224, 7 }, { 2, 256, 8 }, { 2, 296, 9 },
240 { 2, 328, 10 }, { 2, 376, 11 }, { 3, 392, 8 }, { 2, 440, 12 },
241 { 3, 456, 9 }, { 2, 488, 13 }, { 3, 504, 10 }, { 2, 552, 14 },
242 { 3, 584, 11 }, { 2, 600, 15 }, { 2, 632, 16 }, { 3, 680, 12 },
243 { 2, 696, 17 }, { 3, 744, 13 }, { 2, 776, 18 }, { 2, 840, 19 },
244 { 2, 904, 20 }, { 3, 968, 16 }, { 2, 1000, 21 }, { 2, 1064, 22 },
245 { 2, 1128, 23 }, { 3, 1160, 18 }, { 2, 1192, 24 }, { 2, 1256, 25 },
246 { 3, 1288, 19 }, { 3, 1384, 20 }, { 2, 1480, 26 }, { 3, 1608, 22 },
247 { 3, 1736, 23 }, { 3, 1800, 24 }, { 3, 1864, 25 }, { 3, 2216, 26 }
254 /* forward references */
256 static Void rgSCHUtlUpdPrachOcc ARGS((
258 RgrTddPrachInfo *cellCfg));
261 #define RGSCH_NUM_PCFICH_REG 4
262 #define RGSCH_NUM_REG_PER_CCE 9
263 #define RGSCH_NUM_REG_PER_PHICH_GRP 3
266 #define RGSCH_INITPHICH(_phich, _hqFeedBack, _nDmrs, _rbStart, _iPhich) {\
267 (_phich)->hqFeedBack = _hqFeedBack; \
268 (_phich)->rbStart = _rbStart; \
269 (_phich)->nDmrs = _nDmrs; \
270 (_phich)->iPhich = _iPhich; \
271 (_phich)->lnk.next = NULLP; \
272 (_phich)->lnk.prev = NULLP; \
273 (_phich)->lnk.node = (PTR)(_phich); \
276 #define RGSCH_INITPHICH(_phich, _hqFeedBack, _nDmrs, _rbStart, _isForMsg3) {\
277 (_phich)->hqFeedBack = _hqFeedBack; \
278 (_phich)->rbStart = _rbStart; \
279 (_phich)->nDmrs = _nDmrs; \
280 (_phich)->isForMsg3 = _isForMsg3; \
281 (_phich)->lnk.next = NULLP; \
282 (_phich)->lnk.prev = NULLP; \
283 (_phich)->lnk.node = (PTR)(_phich); \
287 #define RGSCH_PHICH_ALLOC(_inst,_dataPtr, _size, _ret) {\
288 _ret = rgSCHUtlAllocSBuf(_inst, (Data **)&_dataPtr, _size); \
291 /* ccpu00117052 - MOD - Passing double pointer
292 for proper NULLP assignment*/
293 #define RGSCH_PHICH_FREE(_inst, _dataPtr, _size) {\
294 rgSCHUtlFreeSBuf(_inst, (Data **)(&(_dataPtr)), _size); \
298 #define RGSCH_GETBIT(a, b) ((((uint8_t*)a)[(b)>>3] >> ((7-((b)&7)))) & 1)
304 * Desc: This function finds of the Power of x raised to n
306 * Ret: value of x raised to n
313 F64 rgSCHUtlPower(F64 x,F64 n)
321 return ( x * rgSCHUtlPower( x, n-1 ) );
325 return ( (1/x) * rgSCHUtlPower( x, n+1 ) );
327 } /* end of rgSCHUtlPower*/
333 * Desc: This function parses bits x to y of an array and
334 * returns the integer value out of it.
336 * Ret: integer value of z bits
343 uint32_t rgSCHUtlParse(uint8_t *buff,uint8_t startPos,uint8_t endPos,uint8_t buffSize)
345 uint8_t pointToChar,pointToEnd, loop;
346 uint8_t size = endPos - startPos;
348 pointToEnd = (startPos)%8;
349 for ( loop=0; loop<size; loop++)
351 pointToChar = (((startPos)+loop)/8);
352 if (RGSCH_GETBIT(buff+pointToChar,pointToEnd%8)==1)
354 result=result+(rgSCHUtlPower(2,(size-loop-1)));
358 return ((uint32_t)result);
359 } /* end of rgSCHUtlParse*/
363 * Fun: rgSCHUtlFindDist
365 * Desc: This function calculates the iterations need to cover
366 * before the valid Index can be used for next possible Reception
368 * Ret: integer value of z bits
375 uint8_t rgSCHUtlFindDist(uint16_t crntTime,uint16_t tempIdx)
378 /* ccpu00137113- Distance is not estimated properly if the periodicity is
379 * equal to RG_SCH_PCQI_SRS_SR_TRINS_SIZE.
381 while(crntTime<=tempIdx)
383 crntTime += RG_SCH_PCQI_SRS_SR_TRINS_SIZE;
387 } /* end of rgSCHUtlFindDist*/
392 * @brief This function checks availability of a PDCCH
396 * Function: rgSCHUtlPdcchAvail
397 * Purpose: This function checks if a particular PDCCH is in use.
398 * map field of PDCCH is used to track the CCEs arleady
399 * allocated. Each bit of map represents one CCE and the
400 * LSBit of first byte represents CCE 0.
402 * 1. Locate the set of bits that represent the PDCCH for
403 * the provided location.
404 * 2. If the value of the bits is non-zero one or many CCEs
405 * for the PDCCH are in use and hence the PDCCH is not available.
406 * 3. If pdcch is available, assign it to [out]pdcch.
407 * 4. Set all of the bits to one. There is no check performed
408 * to see if the PDCCH is available.
410 * Invoked by: scheduler
412 * @param[in] RgSchCellCb* cell
413 * @param[in] RgSchPdcchInfo* pdcchInfo
414 * @param[in] uint8_t loc
415 * @param[in] uint8_t aggrLvl
416 * @param[out] RgSchPdcch** pdcch
418 * -# TRUE if available
422 Bool rgSCHUtlPdcchAvail
425 RgSchPdcchInfo *pdcchInfo,
426 CmLteAggrLvl aggrLvl,
434 Inst inst = cell->instIdx;
436 uint16_t offsetStepMask;
440 byte = &pdcchInfo->map[0];
441 initMask = (0xffff >> (16 - aggrLvl));
443 /* if N(symbol, xPDCCH) =2, then xPDCCH will be candidates in
444 * search space of index {0,1,2,3} and {8,9,..14}
446 if ((cell->cell5gtfCb.cfi == 2) && (aggrLvl == CM_LTE_AGGR_LVL2))
448 offsetStepMask = 0xc;
452 offsetStepMask = 0xc0;
455 /* Loop till the number of bytes available in the CCE map */
456 while (offset < ((pdcchInfo->nCce+ 7) >> 3))
458 byte = &pdcchInfo->map[offset];
459 /* Checking for available CCE */
460 if ((*byte & currMask) == 0)
464 /* if the number of CCEs required are not available, move to next offset */
465 if (currMask & offsetStepMask)
472 /* Move to the next available CCE index in the current byte(cce map) */
473 currMask = currMask << aggrLvl;
477 if ((offset >= ((pdcchInfo->nCce + 7) >> 3)) ||
478 ((aggrLvl == CM_LTE_AGGR_LVL16) && (offset > 0)))
483 byte = &pdcchInfo->map[offset];
485 if (cell->pdcchLst.first != NULLP)
487 *pdcch = (RgSchPdcch *)(cell->pdcchLst.first->node);
488 cmLListDelFrm(&cell->pdcchLst, cell->pdcchLst.first);
492 ret = rgSCHUtlAllocSBuf(inst, (Data **)pdcch, sizeof(RgSchPdcch));
502 /* ALL CCEs will be used in case of level 16 */
503 if (aggrLvl == CM_LTE_AGGR_LVL16)
505 *(byte+1) |= currMask;
507 (*pdcch)->aggrLvl = aggrLvl;
508 cmLListAdd2Tail(&pdcchInfo->pdcchs, &((*pdcch)->lnk));
509 (*pdcch)->lnk.node = (PTR)*pdcch;
510 (*pdcch)->nCce = aggrLvl;
511 (*pdcch)->ue = NULLP;
519 * @brief This function releases a PDCCH
523 * Function: rgSCHUtlPdcchPut
524 * Purpose: This function releases a PDCCH.
526 * 1. Locate the set of bits that represent the PDCCH for
527 * the provided location.
528 * 2. Set all of the bits to zero.
529 * 3. Release the memory of PDCCH to the cell free Q
531 * Invoked by: scheduler
533 * @param[in] RgSchPdcchInfo* pdcchInfo
534 * @param[in] uint8_t loc
535 * @param[in] uint8_t aggrLvl
539 Void rgSCHUtlPdcchPut(RgSchCellCb *cell,RgSchPdcchInfo *pdcchInfo,RgSchPdcch *pdcch)
545 switch(pdcch->aggrLvl)
547 case CM_LTE_AGGR_LVL2:
548 offset = (pdcch->nCce >> 1) & 3;
549 mask = 0x3 << (offset * 2); /*ccpu00128826 - Offset Correction */
551 case CM_LTE_AGGR_LVL4:
552 offset = (pdcch->nCce >> 2) & 1;
553 mask = 0xf << (offset * 4);/*ccpu00128826 - Offset Correction */
555 case CM_LTE_AGGR_LVL8:
558 case CM_LTE_AGGR_LVL16:
564 /* Placing common computation of byte from all the cases above here
566 byte = &pdcchInfo->map[pdcch->nCce >> 3];
568 cmLListDelFrm(&pdcchInfo->pdcchs, &pdcch->lnk);
569 cmLListAdd2Tail(&cell->pdcchLst, &pdcch->lnk);
570 pdcch->lnk.node = (PTR)pdcch;
579 * @brief This function initializes PDCCH information for frame
583 * Function: rgSCHUtlPdcchInit
584 * Purpose: This function initializes PDCCH information for
585 * a slot. It removes the list of PDCCHs allocated
586 * in the prior use of this slot structure.
588 * Invoked by: rgSCHUtlSubFrmPut
590 * @param[in] RgSchCellCb* cell
591 * @param[in] RgSubFrm* subFrm
595 Void rgSCHUtlPdcchInit(RgSchCellCb *cell,RgSchDlSf *subFrm,uint16_t nCce)
597 RgSchPdcchInfo *pdcchInfo;
599 Inst inst = cell->instIdx;
603 pdcchInfo = &subFrm->pdcchInfo;
604 while(pdcchInfo->pdcchs.first != NULLP)
606 pdcch = (RgSchPdcch *)pdcchInfo->pdcchs.first->node;
607 cmLListDelFrm(&pdcchInfo->pdcchs, pdcchInfo->pdcchs.first);
608 cmLListAdd2Tail(&cell->pdcchLst, &pdcch->lnk);
611 cmLListInit(&pdcchInfo->pdcchs);
614 subFrm->relPdcch = NULLP;
617 cceMapSz = ((pdcchInfo->nCce + 7) >> 3);
619 /* The bitMap array size is the number of ceiling(CCEs/8) */
620 /* If nCce received is not the same as the one stored in
621 * pdcchInfo, free the pdcchInfo map */
623 if(pdcchInfo->nCce != nCce)
627 rgSCHUtlFreeSBuf(inst, (Data **)(&(pdcchInfo->map)), cceMapSz);
629 pdcchInfo->nCce = nCce;
630 cceMapSz = ((pdcchInfo->nCce + 7) >> 3);
631 rgSCHUtlAllocSBuf(inst, (Data **)&pdcchInfo->map,
633 if (pdcchInfo->map == NULLP)
635 /* Generate log error here */
640 memset(subFrm->pdcchInfo.map, 0, cceMapSz);
641 /* If nCce is not exactly same as the bitMap size(no of bits allocated
642 * to represent the Cce's, then mark the extra bits as unavailable
643 extra bits = (((pdcchInfo->nCce + 7) >> 3)*8) - pdcchInfo->nCce
644 The last byte of bit map = subFrm->pdcchInfo.map[((pdcchInfo->nCce + 7) >> 3) - 1]
645 NOTE : extra bits are most significant of the last byte eg. */
646 extraBits = (cceMapSz)*8 - pdcchInfo->nCce;
647 subFrm->pdcchInfo.map[cceMapSz - 1] |=
648 ((1 << extraBits) - 1) << (8 - extraBits);
652 /* LTE_ADV_FLAG_REMOVED_START */
654 * @brief This function frees Pool
657 * Function: rgSchSFRTotalPoolFree
659 * Invoked by: rgSchSFRTotalPoolInit
661 * @param[in] RgSchCellCb* cell
662 * @param[in] RgSubFrm* subFrm
666 Void rgSchSFRTotalPoolFree(RgSchSFRTotalPoolInfo *sfrTotalPoolInfo,RgSchCellCb *cell)
671 /*Deinitialise if these cc pools and ce pools are already existent*/
672 l = &sfrTotalPoolInfo->ccPool;
676 /*REMOVING Cell Centred POOLS IF ANY*/
677 n = cmLListDelFrm(l, n);
679 /* Deallocate buffer */
680 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n->node)), sizeof(RgSchSFRPoolInfo));
682 /* Deallocate buffer */
683 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n)), sizeof(CmLList));
687 /*REMOVING Cell Edged POOLS IF ANY*/
688 l = &sfrTotalPoolInfo->cePool;
692 n = cmLListDelFrm(l, n);
694 /* Deallocate buffer */
695 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n->node)), sizeof(RgSchSFRPoolInfo));
697 /* Deallocate buffer */
698 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n)), sizeof(CmLList));
705 * @brief This function resets temporary variables in Pool
708 * Function: rgSchSFRResetPoolVariables
710 * Invoked by: rgSCHSFRUtlTotalPoolInit
712 * @param[in] RgSchCellCb* cell
713 * @param[in] RgSubFrm* subFrm
717 S16 rgSchSFRTotalPoolInit(RgSchCellCb *cell,RgSchDlSf *sf)
719 /* Initialise the variables */
720 RgSchSFRPoolInfo *sfrCCPool;
721 RgSchSFRPoolInfo *sfrCEPool;
724 CmLList *temp = NULLP;
727 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo, cell);
728 sf->sfrTotalPoolInfo.CCPool1BwAvlbl = 0;
729 sf->sfrTotalPoolInfo.CCPool2BwAvlbl = 0;
730 sf->sfrTotalPoolInfo.CEPoolBwAvlbl = 0;
731 sf->sfrTotalPoolInfo.CC1 = FALSE;
732 sf->sfrTotalPoolInfo.CC2 = FALSE;
733 /*Initialise the CE Pools*/
734 cmLListInit (&(sf->sfrTotalPoolInfo.cePool));
736 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
739 DU_LOG("\nERROR --> SCH : CE Pool memory allocation FAILED for cell");
740 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo, cell);
744 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
747 DU_LOG("\nERROR --> SCH : CE Pool memory allocation FAILED for cell ");
748 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
752 l = &sf->sfrTotalPoolInfo.cePool;
753 cmLListAdd2Tail(l, temp);
755 /*Initialise Bandwidth and startRB and endRB for each pool*/
758 /* Initialise the CE Pools */
759 sfrCEPool = (RgSchSFRPoolInfo*)n->node;
761 sfrCEPool->poolstartRB = cell->lteAdvCb.sfrCfg.cellEdgeRbRange.startRb;
762 sfrCEPool->poolendRB = cell->lteAdvCb.sfrCfg.cellEdgeRbRange.endRb;
763 sfrCEPool->bw = sfrCEPool->poolendRB - sfrCEPool->poolstartRB + 1;
764 sf->sfrTotalPoolInfo.CEPoolBwAvlbl = sfrCEPool->bw;
766 sfrCEPool->bwAlloced = 0;
767 sfrCEPool->type2Start = sfrCEPool->poolstartRB;
768 sfrCEPool->type2End = RGSCH_CEIL(sfrCEPool->poolstartRB, cell->rbgSize);
769 sfrCEPool->type0End = ((sfrCEPool->poolendRB + 1) / cell->rbgSize) - 1;
770 sfrCEPool->pwrHiCCRange.startRb = 0;
771 sfrCEPool->pwrHiCCRange.endRb = 0;
773 /*Initialise CC Pool*/
774 cmLListInit (&(sf->sfrTotalPoolInfo.ccPool));
776 /*Add memory and Update CCPool*/
777 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
780 DU_LOG("\nERROR --> SCH : CC Pool memory allocation FAILED for cell ");
781 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
785 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
788 DU_LOG("\nERROR --> SCH : CC Pool memory allocation FAILED for cell ");
789 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
793 l = &sf->sfrTotalPoolInfo.ccPool;
794 cmLListAdd2Tail(l, temp);
796 /*Initialise Bandwidth and startRB and endRB for each pool*/
797 if(sfrCEPool->poolstartRB)
800 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
802 sfrCCPool->poolstartRB = 0;
803 sfrCCPool->poolendRB = sfrCEPool->poolstartRB - 1;
804 sfrCCPool->bw = sfrCCPool->poolendRB - sfrCCPool->poolstartRB + 1;
805 sf->sfrTotalPoolInfo.CCPool1BwAvlbl = sfrCCPool->bw;
806 sfrCCPool->bwAlloced = 0;
807 sfrCCPool->type2Start = 0;
808 sfrCCPool->type2End = 0;
809 sfrCCPool->type0End = ((sfrCCPool->poolendRB + 1) / cell->rbgSize) - 1;
810 sf->sfrTotalPoolInfo.CC1 = TRUE;
811 sfrCCPool->pwrHiCCRange.startRb = 0;
812 sfrCCPool->pwrHiCCRange.endRb = 0;
817 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
819 sfrCCPool->poolstartRB = sfrCEPool->poolendRB + 1;
820 sfrCCPool->poolendRB = sf->bw - 1;
821 sfrCCPool->bw = sfrCCPool->poolendRB - sfrCCPool->poolstartRB + 1;
822 sf->sfrTotalPoolInfo.CCPool2BwAvlbl = sfrCCPool->bw;
823 sfrCCPool->CCPool2Exists = TRUE;
824 sfrCCPool->bwAlloced = 0;
825 sfrCCPool->type2Start = sfrCCPool->poolstartRB;
826 sfrCCPool->type2End = RGSCH_CEIL(sfrCCPool->poolstartRB, cell->rbgSize);
827 sfrCCPool->type0End = ((sfrCCPool->poolendRB + 1) / cell->rbgSize) - 1;
828 sf->sfrTotalPoolInfo.CC2 = TRUE;
829 sfrCEPool->adjCCPool = sfrCCPool; /* SFR_FIX */
830 sfrCCPool->pwrHiCCRange.startRb = 0;
831 sfrCCPool->pwrHiCCRange.endRb = 0;
834 if((sfrCEPool->poolendRB != sf->bw - 1) && (!sfrCCPool->poolstartRB))
836 /*Add memory and Update CCPool*/
837 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
840 DU_LOG("\nERROR --> SCH : CC Pool memory allocation FAILED for cell ");
841 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
845 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
848 DU_LOG("\nERROR --> SCH : CC Pool memory allocation FAILED for cell ");
849 rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
853 cmLListAdd2Tail(l, temp);
856 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
858 sfrCCPool->poolstartRB = sfrCEPool->poolendRB + 1;
859 sfrCCPool->poolendRB = sf->bw - 1;
860 sfrCCPool->bw = sfrCCPool->poolendRB - sfrCCPool->poolstartRB + 1;
861 sf->sfrTotalPoolInfo.CCPool2BwAvlbl = sfrCCPool->bw;
862 sfrCCPool->CCPool2Exists = TRUE;
863 sfrCCPool->bwAlloced = 0;
864 sfrCCPool->type2Start = sfrCCPool->poolstartRB;
865 sfrCCPool->type2End = RGSCH_CEIL(sfrCCPool->poolstartRB, cell->rbgSize);
866 sfrCCPool->type0End = ((sfrCCPool->poolendRB + 1) / cell->rbgSize) - 1;
867 sf->sfrTotalPoolInfo.CC2 = TRUE;
868 sfrCEPool->adjCCPool = sfrCCPool; /* SFR_FIX */
869 sfrCCPool->pwrHiCCRange.startRb = 0;
870 sfrCCPool->pwrHiCCRange.endRb = 0;
873 sf->sfrTotalPoolInfo.CCRetx = FALSE;
874 sf->sfrTotalPoolInfo.CERetx = FALSE;
876 sf->sfrTotalPoolInfo.ccBwFull = FALSE;
877 sf->sfrTotalPoolInfo.ceBwFull = FALSE;
878 sf->sfrTotalPoolInfo.isUeCellEdge = FALSE;
882 * @brief This function resets temporary variables in RNTP Prepration
885 * Function: rgSchDSFRRntpInfoInit
887 * Invoked by: rgSCHSFRUtlTotalPoolInit
889 * @param[in] TknStrOSXL* rntpPtr
890 * @param[in] RgSubFrm* subFrm
894 S16 rgSchDSFRRntpInfoInit(TknStrOSXL *rntpPtr,RgSchCellCb *cell,uint16_t bw)
896 Inst inst = cell->instIdx;
899 rntpPtr->pres = PRSNT_NODEF;
901 len = (bw % 8 == 0) ? (bw/8) : (bw/8 + 1);
905 /* Allocate memory for "scheduled UE" Info */
906 if((rgSCHUtlAllocSBuf(inst, (Data**)&(rntpPtr->val),
907 (len * sizeof(uint8_t)))) != ROK)
909 DU_LOG("\nERROR --> SCH : Memory allocation FAILED for RNTP Alloc");
917 * @brief This function release RNTP pattern from slot and Cell
920 * Function: rgSchDSFRRntpInfoFree
922 * Invoked by: rgSCHSFRUtlTotalPoolInit
924 * @param[in] TknStrOSXL* rntpPtr
925 * @param[in] RgSubFrm* subFrm
929 S16 rgSchDSFRRntpInfoFree(TknStrOSXL *rntpPtr,RgSchCellCb *cell,uint16_t bw)
931 Inst inst = cell->instIdx;
934 len = (bw % 8 == 0) ? (bw/8) : (bw/8 + 1);
936 if(rntpPtr->pres == PRSNT_NODEF)
938 rgSCHUtlFreeSBuf(inst, (Data **)(&(rntpPtr->val)),(len * sizeof(uint8_t)));
939 rntpPtr->pres = NOTPRSNT;
947 * @brief This function resets temporary variables in Pool
950 * Function: rgSchSFRResetPoolVariables
951 * Purpose: Initialise the dynamic variables in each pool.
952 * Reset bwAlloced, bwAssigned, type2End, type0End, type2Start
953 * Invoked by: rgSCHSFRUtlTotalPoolReset
955 * @param[in] RgSchCellCb* cell
956 * @param[in] RgSchSFRPoolInfo *pool
960 static Void rgSchSFRResetPoolVariables(RgSchCellCb *cell,RgSchSFRPoolInfo *pool)
965 /*type0end will be the last RBG in pool with all available RBs*/
966 pool->type0End = (((pool->poolendRB + 1)/cell->rbgSize) - 1);
968 /*type2end will be the first RBG in pool with all available RBs*/
969 pool->type2End = RGSCH_CEIL(pool->poolstartRB, cell->rbgSize);
970 pool->type2Start = pool->poolstartRB;
971 pool->bw = pool->poolendRB - pool->poolstartRB + 1;
976 * @brief This function resets SFR Pool information for frame
980 * Function: rgSCHSFRUtlTotalPooReset
981 * Purpose: Update the dynamic variables in each pool as they will be modified in each slot.
982 * Dont modify the static variables like startRB, endRB, BW
983 * Invoked by: rgSCHUtlSubFrmPut
985 * @param[in] RgSchCellCb* cell
986 * @param[in] RgSchDlSf* subFrm
990 static Void rgSCHSFRUtlTotalPoolReset(RgSchCellCb *cell,RgSchDlSf *subFrm)
992 RgSchSFRTotalPoolInfo *totalPoolInfo = &subFrm->sfrTotalPoolInfo;
993 CmLListCp *ccPool = &totalPoolInfo->ccPool;
994 CmLListCp *cePool = &totalPoolInfo->cePool;
995 CmLList *node = NULLP;
996 RgSchSFRPoolInfo *tempPool = NULLP;
998 totalPoolInfo->ccBwFull = FALSE;
999 totalPoolInfo->ceBwFull = FALSE;
1000 totalPoolInfo->isUeCellEdge = FALSE;
1001 totalPoolInfo->CCPool1BwAvlbl = 0;
1002 totalPoolInfo->CCPool2BwAvlbl = 0;
1003 totalPoolInfo->CEPoolBwAvlbl = 0;
1004 totalPoolInfo->CCRetx = FALSE;
1005 totalPoolInfo->CERetx = FALSE;
1007 node = ccPool->first;
1010 tempPool = (RgSchSFRPoolInfo *)(node->node);
1012 rgSchSFRResetPoolVariables(cell, tempPool);
1013 if(tempPool->poolstartRB == 0)
1014 totalPoolInfo->CCPool1BwAvlbl = tempPool->bw;
1016 totalPoolInfo->CCPool2BwAvlbl = tempPool->bw;
1019 node = cePool->first;
1022 tempPool = (RgSchSFRPoolInfo *)(node->node);
1024 rgSchSFRResetPoolVariables(cell, tempPool);
1025 totalPoolInfo->CEPoolBwAvlbl = tempPool->bw;
1030 /* LTE_ADV_FLAG_REMOVED_END */
1032 * @brief This function appends PHICH information for frame
1036 * Function: rgSCHUtlAddPhich
1037 * Purpose: This function appends PHICH information for
1042 * @param[in] RgSchCellCb* cell
1043 * @param[in] RgSubFrm* subFrm
1044 * @param[in] uint8_t hqFeedBack
1045 * @param[in] uint8_t nDmrs
1046 * @param[in] uint8_t rbStart
1052 S16 rgSCHUtlAddPhich
1055 CmLteTimingInfo frm,
1062 S16 rgSCHUtlAddPhich
1065 CmLteTimingInfo frm,
1076 Inst inst = cell->instIdx;
1078 dlSf = rgSCHUtlSubFrmGet(cell, frm);
1079 RGSCH_PHICH_ALLOC(inst, phich,sizeof(RgSchPhich), ret);
1083 DU_LOG("\nERROR --> SCH : rgSCHUtlAddPhich(): "
1084 "Allocation of RgSchPhich failed");
1088 RGSCH_INITPHICH(phich, hqFeedBack, nDmrs, rbStart, iPhich);
1090 RGSCH_INITPHICH(phich, hqFeedBack, nDmrs, rbStart, isForMsg3); /*SR_RACH_STATS */
1092 cmLListAdd2Tail(&dlSf->phichInfo.phichs, &phich->lnk);
1094 } /* rgSCHUtlAddPhich */
1097 * @brief This function resets PHICH information for frame
1101 * Function: rgSCHUtlPhichReset
1102 * Purpose: This function initializes PHICH information for
1103 * a slot. It removes the list of PHICHs allocated
1104 * in the prior use of this slot structure.
1106 * Invoked by: rgSCHUtlSubFrmPut
1108 * @param[in] RgSchCellCb* cell
1109 * @param[in] RgSubFrm* subFrm
1113 static Void rgSCHUtlPhichReset(RgSchCellCb *cell,RgSchDlSf *subFrm)
1115 RgSchPhichInfo *phichInfo;
1120 phichInfo = &subFrm->phichInfo;
1121 while(phichInfo->phichs.first != NULLP)
1123 phich = (RgSchPhich *)phichInfo->phichs.first->node;
1124 cmLListDelFrm(&phichInfo->phichs, phichInfo->phichs.first);
1125 RGSCH_PHICH_FREE(cell->instIdx, phich, sizeof(RgSchPhich));
1127 cmLListInit(&phichInfo->phichs);
1129 } /* rgSCHUtlPhichReset */
1133 * @brief This function returns slot data structure for a cell
1137 * Function: rgSCHUtlSubFrmGet
1138 * Purpose: This function resets the slot data structure
1139 * when the slot is released
1141 * Invoked by: scheduler
1143 * @param[in] RgSubFrm subFrm
1147 RgSchDlSf* rgSCHUtlSubFrmGet(RgSchCellCb *cell,CmLteTimingInfo frm)
1153 dlIdx = rgSCHUtlGetDlSfIdx(cell, &frm);
1154 //RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx);
1155 sf = cell->subFrms[dlIdx];
1157 /* Changing the idexing
1158 so that proper slot is selected */
1159 dlIdx = (((frm.sfn & 1) * RGSCH_NUM_SUB_FRAMES) + (frm.slot % RGSCH_NUM_SUB_FRAMES));
1160 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx);
1161 sf = cell->subFrms[dlIdx];
1171 * @brief This function returns slot data structure for a cell
1175 * Function: rgSCHUtlSubFrmPut
1176 * Purpose: This function resets the slot data structure
1177 * when the slot is released
1179 * Invoked by: scheduler
1181 * @param[in] RgSubFrm subFrm
1185 Void rgSCHUtlSubFrmPut(RgSchCellCb *cell,RgSchDlSf *sf)
1191 /* Release all the held PDCCH information */
1192 rgSCHUtlPdcchInit(cell, sf, sf->nCce);
1194 /* Release all the held PDCCH information */
1195 rgSCHUtlPdcchInit(cell, sf, cell->nCce);
1197 rgSCHUtlPhichReset(cell, sf);
1199 /* Reset the bw allocated. */
1202 /* Setting allocated bandwidth to SPS bandwidth for non-SPS RB allocator */
1203 sf->bwAlloced = ((cell->spsCellCfg.maxSpsDlBw +
1204 cell->rbgSize - 1)/cell->rbgSize) * cell->rbgSize;
1205 if (sf->bwAlloced > sf->bw)
1207 sf->bwAlloced = sf->bw;
1209 sf->spsAllocdBw = 0;
1210 sf->type2Start = sf->bwAlloced;
1211 memset( &sf->dlSfAllocInfo, 0, sizeof(RgSchDlSfAllocInfo));
1214 /* Fix for ccpu00123918*/
1216 /* LTE_ADV_FLAG_REMOVED_START */
1217 /* dsfr_pal_fixes ** 21-March-2013 ** SKS */
1218 if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
1220 memset(sf->rntpInfo.val, 0, sf->rntpInfo.len);
1222 /* LTE_ADV_FLAG_REMOVED_END */
1225 /*[ccpu00138609]-ADD-Reset the CCCH UE counter */
1228 /* Non DLFS scheduling using Type0 RA requires the following
1229 * parameter's tracking */
1230 /* Type 2 localized allocations start from 0th RBG and onwards */
1231 /* Type 0 allocations start from last RBG and backwards*/
1235 sf->type2End = RGSCH_CEIL(sf->bwAlloced,cell->rbgSize);
1237 sf->type0End = cell->noOfRbgs - 1;
1238 /* If last RBG is of incomplete size then special handling */
1239 (sf->bw % cell->rbgSize == 0)? (sf->lstRbgDfct = 0) :
1240 (sf->lstRbgDfct = cell->rbgSize - (sf->bw % cell->rbgSize));
1241 /* This resets the allocation for BCCH and PDCCH */
1243 /* TODO we need to move this reset for emtc functions */
1244 if(!(cell->emtcEnable))
1253 sf->bcch.pdcch = NULLP;
1254 sf->pcch.pdcch = NULLP;
1256 noRaRsps = RGSCH_MAX_TDD_RA_RSP_ALLOC;
1258 noRaRsps = RGSCH_MAX_RA_RSP_ALLOC;
1260 for (i = 0; i < noRaRsps; i++)
1262 sf->raRsp[i].pdcch = NULLP;
1263 cmLListInit(&(sf->raRsp[i].raRspLst));
1265 /* LTE_ADV_FLAG_REMOVED_START */
1266 if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE)
1268 rgSCHSFRUtlTotalPoolReset(cell, sf);
1270 /* LTE_ADV_FLAG_REMOVED_END */
1272 cmLListInit(&sf->n1PucchResLst);
1276 sf->isCceFailure = FALSE;
1277 sf->dlUlBothCmplt = 0;
1283 * @brief This function computes log N (32 bit Unsigned) to the base 2
1287 * Function: rgSCHUtlLog32bitNbase2
1288 * Purpose: This function computes log N (32 bit Unsigned) to the base 2.
1289 * For n= 0,1 ret = 0.
1291 * Invoked by: Scheduler
1293 * @param[in] uint32_t n
1297 uint8_t rgSCHUtlLog32bitNbase2(uint32_t n)
1299 uint32_t b[] = {0x2, 0xc, 0xf0, 0xff00, 0xffff0000};
1300 uint32_t s[] = {1, 2, 4, 8, 16};
1304 for (i=4; i >= 0; i--)
1318 * @brief This function is a wrapper to call scheduler specific API.
1322 * Function: rgSCHUtlDlRelPdcchFbk
1323 * Purpose: Calls scheduler's handler for SPS release PDCCH feedback
1328 * @param[in] RgSchCellCb *cell
1329 * @param[in] RgSchUeCb *ue
1330 * @param[in] uint8_t isAck
1334 Void rgSCHUtlDlRelPdcchFbk(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t isAck)
1336 cell->sc.apis->rgSCHDlRelPdcchFbk(cell, ue, isAck);
1343 * @brief This function is a wrapper to call scheduler specific API.
1347 * Function: rgSCHUtlDlProcAck
1348 * Purpose: Calls scheduler's handler to process Ack
1353 * @param[in] RgSchCellCb *cell
1354 * @param[in] RgSchDlHqProcCb *hqP
1358 Void rgSCHUtlDlProcAck(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
1360 cell->sc.apis->rgSCHDlProcAck(cell, hqP);
1365 * @brief CRNTI CE Handler
1369 * Function : rgSCHUtlHdlCrntiCE
1371 * - Call scheduler common API
1374 * @param[in] RgSchCellCb *cell
1375 * @param[in] RgSchUeCb *ue
1376 * @param[out] RgSchErrInfo *err
1379 Void rgSCHUtlHdlCrntiCE(RgSchCellCb *cell,RgSchUeCb *ue)
1382 cell->sc.apis->rgSCHHdlCrntiCE(cell, ue);
1384 } /* rgSCHUtlHdlCrntiCE */
1385 #endif /* LTEMAC_SPS */
1387 /***********************************************************
1389 * Func : rgSCHUtlCalcTotalRegs
1391 * Desc : Calculate total REGs, given a bandwidth, CFI
1392 * and number of antennas.
1394 * Ret : Total REGs (uint16_t)
1396 * Notes: Could optimise if bw values are limited
1397 * (taken from RRC spec) by indexing values from
1399 * Input values are not validated. CFI is assumed
1404 **********************************************************/
1405 static uint16_t rgSCHUtlCalcTotalRegs(uint8_t bw,uint8_t cfi,uint8_t numAntna,Bool isEcp)
1409 /*ccpu00116757- removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1415 /* Refer 36.211 section 6.10.1.2
1416 * For symbols 2 and 4, the REGs per RB will be based on cyclic prefix
1417 * and number of antenna ports.
1418 * For symbol 1, there are 2 REGs per RB always. Similarly symbol 3
1422 /*CR changes [ccpu00124416] - MOD*/
1425 regs = bw * RGSCH_NUM_REGS_4TH_SYM_EXT_CP;
1429 regs = bw * RGSCH_NUM_REGS_4TH_SYM_NOR_CP;
1432 regs += bw * RGSCH_NUM_REGS_3RD_SYM;
1434 /*CR changes [ccpu00124416] - MOD using number of antenna ports*/
1435 regs += (numAntna == RGSCH_NUM_ANT_PORT_FOUR) ? \
1436 (bw * RGSCH_NUM_REGS_2ND_SYM_FOUR_ANT_PORT) : \
1437 (bw * RGSCH_NUM_REGS_2ND_SYM_1OR2_ANT_PORT);
1438 default: /* case 1 */
1439 regs += bw * RGSCH_NUM_REGS_1ST_SYM;
1444 /***********************************************************
1446 * Func : rgSCHUtlCalcPhichRegs
1448 * Desc : Calculates number of PHICH REGs
1450 * Ret : Number of PHICH REGs (uint8_t)
1452 * Notes: ng6 is Ng multiplied by 6
1456 **********************************************************/
1457 static uint16_t rgSCHUtlCalcPhichRegs(uint8_t bw,uint8_t ng6)
1459 /* ccpu00115330: Corrected the calculation for number of PHICH groups*/
1460 return (RGSCH_CEIL((bw * ng6) ,(8 * 6)) * RGSCH_NUM_REG_PER_PHICH_GRP);
1465 * @brief Calculates total CCEs (N_cce)
1469 * Function: rgSCHUtlCalcNCce
1470 * Purpose: This function calculates and returns total CCEs for a
1471 * cell, given the following: bandwidth, Ng configuration
1472 * (multiplied by six), cfi (actual number of control
1473 * symbols), m factor for PHICH and number of antennas.
1475 * Invoked by: Scheduler
1477 * @param[in] uint8_t bw
1478 * @param[in] uint8_t ng6
1479 * @param[in] uint8_t cfi
1480 * @param[in] uint8_t mPhich
1481 * @param[in] uint8_t numAntna
1482 * @param[in] Bool isEcp
1483 * @return N_cce (uint8_t)
1486 uint8_t rgSCHUtlCalcNCce(uint8_t bw,RgrPhichNg ng,uint8_t cfi,uint8_t mPhich,uint8_t numAntna,Bool isEcp)
1493 /*ccpu00116757- removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1497 case RGR_NG_ONESIXTH:
1512 totalRegs = rgSCHUtlCalcTotalRegs(bw, cfi, numAntna, isEcp);
1513 phichRegs = rgSCHUtlCalcPhichRegs(bw, ng6);
1514 cceRegs = totalRegs - mPhich*phichRegs - RGSCH_NUM_PCFICH_REG;
1516 return ((uint8_t)(cceRegs/RGSCH_NUM_REG_PER_CCE));
1521 * @brief Calculates total CCEs (N_cce)
1525 * Function: rgSCHUtlCalcNCce
1526 * Purpose: This function calculates and returns total CCEs for a
1527 * cell, given the following: bandwidth, Ng configuration
1528 * (multiplied by six), cfi (actual number of control
1529 * symbols) and number of antennas.
1531 * Invoked by: Scheduler
1533 * @param[in] uint8_t bw
1534 * @param[in] uint8_t ng6
1535 * @param[in] uint8_t cfi
1536 * @param[in] uint8_t numAntna
1537 * @return N_cce (uint8_t)
1540 uint8_t rgSCHUtlCalcNCce(uint8_t bw,RgrPhichNg ng,uint8_t cfi,uint8_t numAntna,Bool isEcp)
1547 /*ccpu00116757- removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1551 case RGR_NG_ONESIXTH:
1566 totalRegs = rgSCHUtlCalcTotalRegs(bw, cfi, numAntna, isEcp);
1567 phichRegs = rgSCHUtlCalcPhichRegs(bw, ng6);
1568 cceRegs = totalRegs - phichRegs - RGSCH_NUM_PCFICH_REG;
1570 return ((uint8_t)(cceRegs/RGSCH_NUM_REG_PER_CCE));
1575 * @brief Returns PHICH info associated with an uplink
1576 * HARQ process allocation
1580 * Function: rgSCHUtlGetPhichInfo
1581 * Purpose: This function returns PHICH info associated with
1582 * an uplink HARQ process allocation. PHICH info
1583 * comprises RB start and N_dmrs.
1585 * @param[in] RgSchUlHqProcCb *hqProc
1586 * @param[out] uint8_t *rbStartRef
1587 * @param[out] uint8_t *nDmrsRef
1591 S16 rgSCHUtlGetPhichInfo(RgSchUlHqProcCb *hqProc,uint8_t *rbStartRef,uint8_t *nDmrsRef,uint8_t *iPhich)
1593 S16 rgSCHUtlGetPhichInfo(RgSchUlHqProcCb *hqProc,uint8_t *rbStartRef,uint8_t *nDmrsRef)
1599 if ((hqProc != NULLP) && (hqProc->alloc != NULLP))
1601 *rbStartRef = hqProc->alloc->grnt.rbStart;
1602 *nDmrsRef = hqProc->alloc->grnt.nDmrs;
1604 *iPhich = hqProc->iPhich;
1612 * @brief Returns uplink grant information required to permit
1613 * PHY to receive data
1617 * Function: rgSCHUtlAllocRcptInfo
1618 * Purpose: Given an uplink allocation, this function returns
1619 * uplink grant information which is needed by PHY to
1620 * decode data sent from UE. This information includes:
1625 * @param[in] RgSchUlAlloc *alloc
1626 * @param[out] uint8_t *rbStartRef
1627 * @param[out] uint8_t *numRbRef
1628 * @param[out] uint8_t *rvRef
1629 * @param[out] uint16_t *size
1630 * @param[out] TfuModScheme *modType
1631 * @param[out] Bool *isRtx
1632 * @param[out] uint8_t *nDmrs
1633 * @param[out] Bool *ndi
1634 * @param[out] uint8_t *hqPId
1637 S16 rgSCHUtlAllocRcptInfo
1639 RgSchUlAlloc *alloc,
1642 uint8_t *rbStartRef,
1646 TfuModScheme *modType,
1653 /* Modulation order for 16qam UEs would be
1654 * min(4,modulation order in grant). Please refer to 36.213-8.6.1*/
1655 CmLteUeCategory ueCtgy;
1657 #if (ERRCLASS & ERRCLS_DEBUG)
1658 if ((alloc == NULLP) || (alloc->hqProc == NULLP))
1664 if ( !alloc->forMsg3 )
1666 if ( ((alloc->ue) == NULLP) || (RG_SCH_CMN_GET_UE(alloc->ue, alloc->ue->cell) == NULLP))
1668 DU_LOG("\nERROR --> SCH : Failed: ue->sch is null RNTI:%d,isRetx=%d",
1669 alloc->rnti, alloc->grnt.isRtx);
1672 ueCtgy = (RG_SCH_CMN_GET_UE_CTGY(alloc->ue));
1675 *iMcsRef = alloc->grnt.iMcs;
1676 *rbStartRef = alloc->grnt.rbStart;
1677 *numRbRef = alloc->grnt.numRb;
1678 *rvRef = rgRvTable[alloc->hqProc->rvIdx];
1679 *rnti = alloc->rnti;
1680 *size = alloc->grnt.datSz;
1681 *modType = (alloc->forMsg3)? alloc->grnt.modOdr:
1682 ((ueCtgy == CM_LTE_UE_CAT_5)?
1684 (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr)));
1685 *isRtx = alloc->grnt.isRtx;
1686 *nDmrs = alloc->grnt.nDmrs;
1687 *ndi = alloc->hqProc->ndi;
1688 *hqPId = alloc->hqProc->procId;
1694 * @brief Returns uplink grant information required to permit
1695 * PHY to receive data
1699 * Function: rgSCHUtlAllocRcptInfo
1700 * Purpose: Given an uplink allocation, this function returns
1701 * uplink grant information which is needed by PHY to
1702 * decode data sent from UE. This information includes:
1707 * @param[in] RgSchUlAlloc *alloc
1708 * @param[out] uint8_t *rbStartRef
1709 * @param[out] uint8_t *numRbRef
1710 * @param[out] uint8_t *rvRef
1711 * @param[out] uint16_t *size
1712 * @param[out] TfuModScheme *modType
1715 S16 rgSCHUtlAllocRcptInfo(RgSchCellCb *cell,RgSchUlAlloc *alloc,CmLteTimingInfo *timeInfo,TfuUeUlSchRecpInfo *recpReq)
1717 #if (ERRCLASS & ERRCLS_DEBUG)
1718 if ((alloc == NULLP) || (alloc->hqProc == NULLP))
1723 recpReq->size = alloc->grnt.datSz;
1724 recpReq->rbStart = alloc->grnt.rbStart;
1725 recpReq->numRb = alloc->grnt.numRb;
1726 /* Modulation order min(4,mod in grant) for 16 qam UEs.
1727 * Please refer to 36.213-8.6.1*/
1728 #ifdef FOUR_TX_ANTENNA
1729 recpReq->modType = (TfuModScheme)((alloc->forMsg3)?alloc->grnt.modOdr:
1730 (/*(alloc->ue->ueCatEnum == CM_LTE_UE_CAT_5)?
1731 alloc->grnt.modOdr: *//* Chandra:TmpFx-TM500 Cat5 with Only16QAM */
1732 (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr))));
1734 recpReq->modType = (TfuModScheme)((alloc->forMsg3)?alloc->grnt.modOdr:
1735 ((alloc->ue->ueCatEnum == CM_LTE_UE_CAT_5)?
1737 (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr))));
1739 recpReq->nDmrs = alloc->grnt.nDmrs;
1740 recpReq->hoppingEnbld = FALSE;
1741 recpReq->hoppingBits = 0;
1742 recpReq->isRtx = alloc->grnt.isRtx;
1743 recpReq->ndi = alloc->hqProc->ndi;
1744 recpReq->rv = rgRvTable[alloc->hqProc->rvIdx];
1746 recpReq->harqProcId = alloc->hqProc->procId;
1748 recpReq->harqProcId = rgSCHCmnGetUlHqProcIdx(timeInfo, cell);
1750 /* Transmission mode is SISO till Uplink MIMO is implemented. */
1751 recpReq->txMode = 0;
1752 /* This value needs to filled in in the case of frequency hopping. */
1753 recpReq->crntTxNb = 0;
1755 recpReq->mcs = alloc->grnt.iMcs;
1757 recpReq->rbgStart = alloc->grnt.vrbgStart;
1758 recpReq->numRbg = alloc->grnt.numVrbg;
1759 recpReq->xPUSCHRange = alloc->grnt.xPUSCHRange;
1760 //TODO_SID Need to check
1761 recpReq->nAntPortLayer = 0;
1762 recpReq->SCID = alloc->grnt.SCID;
1763 recpReq->PMI = alloc->grnt.PMI;
1764 recpReq->uciWoTBFlag = alloc->grnt.uciOnxPUSCH;
1767 recpReq->beamIndex = alloc->ue->ue5gtfCb.BeamId;
1772 if (!alloc->forMsg3)
1774 if (alloc->grnt.isRtx)
1776 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulRetxOccns++;
1780 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulTxOccns++;
1781 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulSumiTbs += \
1782 rgSCHCmnUlGetITbsFrmIMcs(alloc->grnt.iMcs);
1783 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulNumiTbs ++;
1784 cell->tenbStats->sch.ulSumiTbs += \
1785 rgSCHCmnUlGetITbsFrmIMcs(alloc->grnt.iMcs);
1786 cell->tenbStats->sch.ulNumiTbs ++;
1788 alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulPrbUsg += alloc->grnt.numRb;
1789 cell->tenbStats->sch.ulPrbUsage[0] += alloc->grnt.numRb;
1792 /* ccpu00117050 - DEL - nSrs setting at rgSCHUtlAllocRcptInfo */
1799 * @brief This function initialises the PRACH slot occasions
1803 * Function: rgSCHUtlUpdPrachOcc
1804 * Purpose: This function updates the PRACH slots based on
1805 * RGR configuration.
1807 * Invoked by: Scheduler
1809 * @param[in] RgSchCellCb *cell
1810 * @param[in] RgrTddPrachInfo *cellCfg
1814 static Void rgSCHUtlUpdPrachOcc(RgSchCellCb *cell,RgrTddPrachInfo *cellCfg)
1822 /* In the 1st half frame */
1823 if(cellCfg->halfFrm == 0)
1828 /* In the 2nd half frame */
1834 for(idx = startIdx; idx < endIdx; idx++)
1836 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
1837 == RG_SCH_TDD_UL_slot)
1839 if(cellCfg->ulStartSfIdx == count)
1841 size = cell->rachCfg.raOccasion.size;
1842 cell->rachCfg.raOccasion.slotNum[size] = idx;
1843 cell->rachCfg.raOccasion.size++;
1853 * @brief This function initialises the PRACH occasions
1857 * Function: rgSCHUtlPrachCfgInit
1858 * Purpose: This function initialises the PRACH occasions based on
1859 * RGR configuration.
1861 * Invoked by: Scheduler
1863 * @param[in] RgSchCellCb *cell
1864 * @param[in] RgrCellCfg *cellCfg
1868 Void rgSCHUtlPrachCfgInit(RgSchCellCb *cell,RgrCellCfg *cellCfg)
1874 if(cellCfg->prachRscInfo.numRsc <= 0)
1876 DU_LOG("\nERROR --> SCH : Invalid"
1877 "PRACH resources Configuration ");
1881 /* Update SFN occasions */
1882 cell->rachCfg.raOccasion.sfnEnum =
1883 cellCfg->prachRscInfo.prachInfo[0].sfn;
1885 cell->rachCfg.raOccasion.size = 0;
1887 /* Update slot occasions */
1888 for(idx = 0; idx < cellCfg->prachRscInfo.numRsc; idx++)
1890 if(cellCfg->prachRscInfo.prachInfo[idx].freqIdx == 0)
1892 if(cellCfg->prachRscInfo.prachInfo[idx].halfFrm == 0)
1900 if(cellCfg->prachRscInfo.prachInfo[idx].ulStartSfIdx ==
1903 subfrmIdx = cell->rachCfg.raOccasion.size;
1904 cell->rachCfg.raOccasion.slotNum[subfrmIdx] = splFrm;
1905 cell->rachCfg.raOccasion.size++;
1909 rgSCHUtlUpdPrachOcc(cell,
1910 &cellCfg->prachRscInfo.prachInfo[idx]);
1918 * @brief This function performs RGR cell initialization
1922 * Function: rgSCHUtlRgrCellCfg
1923 * Purpose: This function initialises the cell with RGR configuration
1924 * and slot related initialization.
1926 * Invoked by: Scheduler
1928 * @param[in] RgSchCellCb *cell
1929 * @param[in] RgrCellCfg *cellCfg
1930 * @param[in] RgSchErrInfo *errInfo
1934 S16 rgSCHUtlRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *errInfo)
1940 CmLteTimingInfo frm;
1941 uint8_t ulDlCfgIdx = cellCfg->ulDlCfgIdx;
1945 uint16_t bw; /*!< Number of RBs in the cell */
1947 memset(&frm,0,sizeof(CmLteTimingInfo));
1949 /* ccpu00132657-MOD- Determining DLSF array size independent of DELTAS */
1950 maxDlslots = rgSchTddNumDlSubfrmTbl[ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1951 maxslots = 2 * maxDlslots;
1952 cell->numDlSubfrms = maxslots;
1953 /* ACC-TDD <ccpu00130639> */
1954 cell->tddHqSfnCycle = -1;
1955 cell->ulDlCfgIdx = ulDlCfgIdx;
1957 /* PRACH Occasions Initialization */
1958 rgSCHUtlPrachCfgInit(cell, cellCfg);
1960 /* ccpu00132658- Moved out of below for loop since the updating rbgSize and
1961 * bw are independent of sfNum*/
1962 /* determine the RBG size and no of RBGs for the configured
1964 if (cell->bwCfg.dlTotalBw > 63)
1968 else if (cell->bwCfg.dlTotalBw > 26)
1972 else if (cell->bwCfg.dlTotalBw > 10)
1980 cell->noOfRbgs = RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize);
1982 bw = cell->bwCfg.dlTotalBw;
1984 rgSCHUtlAllocSBuf(cell->instIdx,
1985 (Data **)&cell->subFrms, sizeof(RgSchDlSf *) * maxslots);
1986 if (cell->subFrms == NULLP)
1991 /* Create memory for each frame. */
1992 for(i = 0; i < maxslots; i++)
1994 while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] ==
1997 sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES;
2000 rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf, sizeof(RgSchDlSf));
2005 memset(sf, 0, sizeof(*sf));
2008 if (ROK != rgSCHLaaInitDlSfCb(cell, sf))
2016 /* Mark SPS bandwidth to be occupied */
2017 sf->bwAlloced = ((cellCfg->spsCfg.maxSpsDlBw +
2018 cell->rbgSize - 1)/cell->rbgSize) * cell->rbgSize;
2019 sf->spsAllocdBw = 0;
2020 sf->type2End = sf->bwAlloced/cell->rbgSize;
2023 /* Fix for ccpu00123918*/
2025 #endif /* LTEMAC_SPS */
2026 /* Initialize the ackNakRepQ here */
2027 #ifdef RG_MAC_MEASGAP
2028 cmLListInit (&(sf->ackNakRepQ));
2030 cell->subFrms[i] = sf;
2031 sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES;
2037 /* ccpu00117052 - MOD - Passing double pointer
2038 for proper NULLP assignment*/
2039 rgSCHUtlFreeSBuf(cell->instIdx,
2040 (Data **)(&(cell->subFrms[i-1])), sizeof(RgSchDlSf));
2042 rgSCHLaaDeInitDlSfCb(cell, sf);
2045 /* ccpu00117052 - MOD - Passing double pointer
2046 for proper NULLP assignment*/
2047 rgSCHUtlFreeSBuf(cell->instIdx,
2048 (Data **)(&(cell->subFrms)), sizeof(RgSchDlSf *) * maxslots);
2053 if (cell->sc.apis == NULLP)
2055 cell->sc.apis = &rgSchCmnApis;
2057 ret = cell->sc.apis->rgSCHRgrCellCfg(cell, cellCfg, errInfo);
2061 /* ccpu00132286- Removed deletion of sf nodes as the deletion will be
2062 * happening during CellDelete. Added return handling to provide negative
2067 /* Release the slots and thereby perform the initialization */
2068 for (i = 0; i < maxslots; i++)
2070 if((i > 0) && (i%maxDlslots == 0))
2075 frm.slot = cell->subFrms[i]->sfNum;
2076 rgSCHUtlDlRlsSubFrm(cell, frm);
2085 * @brief This function performs scheduler related cell creation
2089 * Function: rgSCHUtlRgrCellCfg
2090 * Purpose: This function creates the slots needed for the
2091 * cell. It then peforms init of the scheduler by calling
2092 * scheduler specific cell init function.
2094 * Invoked by: Scheduler
2096 * @param[in] RgSchCellCb *cell
2097 * @param[in] RgrCellCfg *cellCfg
2098 * @param[in] RgSchErrInfo *errInfo
2102 S16 rgSCHUtlRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *errInfo)
2106 CmLteTimingInfo frm;
2108 Inst inst = cell->instIdx;
2109 /* LTE_ADV_FLAG_REMOVED_START */
2111 len = (uint16_t)((cell->bwCfg.dlTotalBw % 8 == 0) ? (cell->bwCfg.dlTotalBw/8) : (cell->bwCfg.dlTotalBw/8 + 1)); /*KW fix for LTE_ADV */
2112 /* LTE_ADV_FLAG_REMOVED_END */
2114 memset(&frm,0,sizeof(CmLteTimingInfo));
2116 /* determine the RBG size and no of RBGs for the configured
2118 if (cell->bwCfg.dlTotalBw > 63)
2122 else if (cell->bwCfg.dlTotalBw > 26)
2126 else if (cell->bwCfg.dlTotalBw > 10)
2134 cell->noOfRbgs = RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize);
2135 /* Create memory for each frame. */
2136 /* Changing loop limit from
2137 RGSCH_NUM_SUB_FRAMES to RGSCH_NUM_DL_slotS */
2138 for(i = 0; i < RGSCH_NUM_DL_slotS; i++)
2140 rgSCHUtlAllocSBuf(inst, (Data **)&sf, sizeof(RgSchDlSf));
2145 memset(sf, 0, sizeof(*sf));
2148 if (ROK != rgSCHLaaInitDlSfCb(cell, sf))
2153 /* Doing MOD operation before assigning value of i */
2154 sf->sfNum = i % RGSCH_NUM_SUB_FRAMES;
2155 sf->bw = cell->bwCfg.dlTotalBw;
2156 /* Initialize the ackNakRepQ here */
2157 #ifdef RG_MAC_MEASGAP
2158 cmLListInit (&(sf->ackNakRepQ));
2160 cell->subFrms[i] = sf;
2161 /* LTE_ADV_FLAG_REMOVED_START */
2162 if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
2164 /*initialize the RNTP Buffer*/
2165 if(rgSchDSFRRntpInfoInit(&sf->rntpInfo, cell, sf->bw))
2171 if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE)
2173 /*initialise the pools of CC and CE*/
2174 if(rgSchSFRTotalPoolInit(cell, sf))
2179 /* LTE_ADV_FLAG_REMOVED_END */
2182 /* LTE_ADV_FLAG_REMOVED_START */
2183 /* Allocate memory for "scheduled UE" Info */
2184 if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
2186 if((rgSCHUtlAllocSBuf(inst, (Data**)&(cell->rntpAggrInfo.val),
2187 (len * sizeof(uint8_t)))) != ROK)
2189 DU_LOG("\nERROR --> SCH : Memory allocation FAILED for RNTP Alloc");
2192 cell->rntpAggrInfo.pres = PRSNT_NODEF;
2193 cell->rntpAggrInfo.len = len;
2195 /* LTE_ADV_FLAG_REMOVED_END */
2197 /* Changing loop limit from
2198 RGSCH_NUM_SUB_FRAMES to RGSCH_NUM_DL_slotS */
2199 if (i != RGSCH_NUM_DL_slotS)
2203 /* ccpu00117052 - MOD - Passing double pointer
2204 for proper NULLP assignment*/
2205 rgSCHUtlFreeSBuf(inst, (Data **)(&(cell->subFrms[i-1])),
2208 rgSCHLaaDeInitDlSfCb(cell, sf);
2214 if (cell->sc.apis == NULLP)
2216 cell->sc.apis = &rgSchCmnApis;
2219 /* Release the slots and thereby perform the initialization */
2220 for (i = 0; i < RGSCH_NUM_DL_slotS; i++)
2222 if (i >= RGSCH_NUM_SUB_FRAMES)
2224 /* [ccpu00123828]-MOD-The below statement sfn += 1incorrectly modified
2225 * the value of sfn for i>=10 thru 19. Correct way is to assign
2229 frm.slot = i % RGSCH_NUM_SUB_FRAMES;
2230 rgSCHUtlDlRlsSubFrm(cell, frm);
2233 ret = cell->sc.apis->rgSCHRgrCellCfg(cell, cellCfg, errInfo);
2236 errInfo->errCause = RGSCHERR_SCH_CFG;
2240 if(cell->emtcEnable)
2242 /* TODO: Repetition framework in RGR and APP */
2243 if (rgSCHUtlEmtcResMngmtInit(
2245 RGSCH_IOT_PDSCH_POOLSZ, RGSCH_IOT_PDSCH_DELTA, cellCfg->bwCfg.dlTotalBw,
2246 RGSCH_IOT_PUSCH_POOLSZ, RGSCH_IOT_PUSCH_DELTA, RGSCH_IOT_PUSCH_MAXFREQSZ,
2247 RGSCH_IOT_PUCCH_POOLSZ, RGSCH_IOT_PUCCH_DELTA, RGSCH_IOT_PUCCH_MAXFREQSZ) != ROK)
2249 errInfo->errCause = RGSCHERR_SCH_CFG;
2261 * @brief This function performs the cell reconfiguration at RGR interface
2265 * Function: rgSCHUtlRgrCellRecfg
2266 * Purpose: This function updates the reconfigurable parameters
2267 * on the cell control block for the scheduler.
2269 * Invoked by: Scheduler
2271 * @param[in] RgSchCellCb *cell
2272 * @param[in] RgrCellCfg *cellCfg
2273 * @param[in] RgSchErrInfo *errInfo
2277 S16 rgSCHUtlRgrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
2279 return (cell->sc.apis->rgSCHRgrCellRecfg(cell, recfg, err));
2285 * @brief This function returns the Y value of UE for a sub frame
2289 * Function: rgSCHUtlFreeCell
2290 * Purpose: This function updates the value of Y stored in the
2291 * UE control block. It uses the previously computed
2292 * value for computing for this slot.
2294 * Invoked by: Scheduler
2296 * @param[in] RgSchCellCb *cell
2300 S16 rgSCHUtlFreeCell(RgSchCellCb *cell)
2305 RgSchPdcchInfo *pdcchInfo;
2306 RgSchPhichInfo *phichInfo;
2308 Inst inst = cell->instIdx;
2311 RgSchRaReqInfo *raReqInfo;
2316 maxslots = cell->numDlSubfrms;
2318 maxslots = RGSCH_NUM_DL_slotS;
2322 /* Invoke the index for scheduler, cell deletion */
2323 cell->sc.apis->rgSCHFreeCell(cell);
2325 /* Release the slots allocated */
2326 for (i = 0; i < maxslots; i++)
2329 rgSCHLaaDeInitDlSfCb(cell, cell->subFrms[i]);
2331 pdcchInfo = &cell->subFrms[i]->pdcchInfo;
2332 /* ccpu00117052 - MOD - Passing double pointer
2333 for proper NULLP assignment*/
2334 rgSCHUtlFreeSBuf(inst, (Data **)(&(pdcchInfo->map)),
2335 (pdcchInfo->nCce + 7) >> 3);
2336 while (pdcchInfo->pdcchs.first != NULLP)
2338 pdcch = (RgSchPdcch *)pdcchInfo->pdcchs.first->node;
2339 cmLListDelFrm(&pdcchInfo->pdcchs, pdcchInfo->pdcchs.first);
2340 /* ccpu00117052 - MOD - Passing double pointer
2341 for proper NULLP assignment*/
2342 rgSCHUtlFreeSBuf(inst, (Data **)&pdcch, sizeof(RgSchPdcch));
2345 phichInfo = &cell->subFrms[i]->phichInfo;
2346 while(phichInfo->phichs.first != NULLP)
2348 phich = (RgSchPhich *)phichInfo->phichs.first->node;
2349 cmLListDelFrm(&phichInfo->phichs, phichInfo->phichs.first);
2350 RGSCH_PHICH_FREE(inst, phich, sizeof(RgSchPhich));
2353 /* LTE_ADV_FLAG_REMOVED_START */
2354 /*releasing SFR pool entries*/
2355 rgSchSFRTotalPoolFree(&cell->subFrms[i]->sfrTotalPoolInfo, cell);
2357 /*releasing dsfr rntp pattern info*/
2358 rgSchDSFRRntpInfoFree(&cell->subFrms[i]->rntpInfo, cell,
2359 cell->bwCfg.dlTotalBw);
2360 /* LTE_ADV_FLAG_REMOVED_END */
2362 /* ccpu00117052 - MOD - Passing double pointer
2363 for proper NULLP assignment*/
2364 rgSCHUtlFreeSBuf(inst, (Data **)(&(cell->subFrms[i])), sizeof(RgSchDlSf));
2367 /* Release the slot pointers */
2368 /* ccpu00117052 - MOD - Passing double pointer
2369 for proper NULLP assignment*/
2370 rgSCHUtlFreeSBuf(inst,
2371 (Data **) (&(cell->subFrms)), sizeof(RgSchDlSf *) * maxslots);
2373 for(idx=0; idx < cell->raInfo.lstSize; idx++)
2375 lst = &cell->raInfo.raReqLst[idx];
2376 while (lst->first != NULLP)
2378 raReqInfo = (RgSchRaReqInfo *)lst->first->node;
2379 cmLListDelFrm(lst, &raReqInfo->raReqLstEnt);
2380 /* ccpu00117052 - MOD - Passing double pointer
2381 for proper NULLP assignment*/
2382 rgSCHUtlFreeSBuf(inst,(Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
2385 /* ccpu00117052 - MOD - Passing double pointer
2386 for proper NULLP assignment*/
2387 rgSCHUtlFreeSBuf(inst,
2388 (Data **)(&(cell->raInfo.raReqLst)),
2389 sizeof(CmLListCp) * (cell->raInfo.lstSize));
2392 /* Release allocated pdcchs */
2393 lst = &cell->pdcchLst;
2394 while (lst->first != NULLP)
2396 pdcch = (RgSchPdcch *)lst->first->node;
2397 cmLListDelFrm(lst, &pdcch->lnk);
2399 if(cell->emtcEnable)
2401 rgSCHEmtcPdcchFree(cell, pdcch);
2402 rgSCHUtlEmtcResMngmtDeinit(cell);
2405 /* ccpu00117052 - MOD - Passing double pointer
2406 for proper NULLP assignment*/
2407 rgSCHUtlFreeSBuf(inst,(Data **)&pdcch, sizeof(RgSchPdcch));
2410 rgSCHLaaFreeLists(cell);
2413 /* LTE_ADV_FLAG_REMOVED_START */
2414 /* releasing RNTP Aggregation Info from CellCb*/
2415 rgSchDSFRRntpInfoFree(&cell->rntpAggrInfo, cell, cell->bwCfg.dlTotalBw);
2416 /* LTE_ADV_FLAG_REMOVED_END */
2423 * @brief This function adds the UE to scheduler
2427 * Function: rgSCHUtlRgrUeCfg
2428 * Purpose: This function performs addition of UE to scheduler
2429 * 1. First, it updates the Y table in the UE
2430 * 2. Then, it calls the scheduler's handler for UE addition
2432 * Invoked by: Scheduler
2434 * @param[in] RgSchCellCb *cell
2435 * @param[in] RgSchUeCb *ue
2436 * @param[in] RgrUeCfg *cfg
2437 * @param[in] RgSchErrInfo *err
2441 S16 rgSCHUtlRgrUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *cfg,RgSchErrInfo *err)
2444 /* Assign TM 1 as UE's default TM */
2445 ue->mimoInfo.txMode = RGR_UE_TM_1;
2446 ue->txModeTransCmplt = TRUE;
2447 cmInitTimers(&ue->txModeTransTmr, 1);
2448 if (cfg->txMode.pres == PRSNT_NODEF)
2450 /* DL MU-MIMO not supported */
2451 if (cfg->txMode.txModeEnum == RGR_UE_TM_5)
2453 err->errCause = RGSCHERR_SCH_CFG;
2456 ue->mimoInfo.txMode = cfg->txMode.txModeEnum;
2458 ue->ul.ulTxAntSel = cfg->ulTxAntSel;
2459 ue->mimoInfo.cdbkSbstRstrctn = cfg->ueCodeBookRstCfg;
2461 ue->ueCatEnum = cfg->ueCatEnum;
2462 if ((cfg->puschDedCfg.bACKIdx > 15) ||
2463 (cfg->puschDedCfg.bCQIIdx > 15) ||
2464 (cfg->puschDedCfg.bRIIdx > 15))
2466 err->errCause = RGSCHERR_SCH_CFG;
2469 ue->ul.betaHqOffst = cfg->puschDedCfg.bACKIdx;
2470 ue->ul.betaCqiOffst = cfg->puschDedCfg.bCQIIdx;
2471 ue->ul.betaRiOffst = cfg->puschDedCfg.bRIIdx;
2473 ue->csgMmbrSta = cfg->csgMmbrSta;
2475 memset(&ue->pfsStats, 0, sizeof(RgSchPfsStats));
2477 /* Call the handler of the scheduler based on cell configuration */
2478 return (cell->sc.apis->rgSCHRgrUeCfg(cell, ue, cfg, err));
2480 /* Start : LTEMAC_2.1_DEV_CFG */
2483 * @brief This function adds a service to scheduler
2487 * Function: rgSCHUtlRgrLcCfg
2488 * Purpose: This function performs addition of service to scheduler
2489 * The addition is performed for each direction based
2490 * the direction field of the configuration
2492 * Invoked by: Scheduler
2494 * @param[in] RgSchCellCb *cell
2495 * @param[in] RgSchUeCb *ue
2496 * @param[in] RgSchDlLcCb *dlLc
2497 * @param[in] RgrLchCfg *cfg
2498 * @param[in] RgSchErrInfo *err
2502 S16 rgSCHUtlRgrLcCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchCfg *cfg,RgSchErrInfo *errInfo)
2504 return (cell->sc.apis->rgSCHRgrLchCfg(cell, ue, dlLc, cfg, errInfo));
2509 * @brief This function modifies a service to scheduler
2513 * Function: rgSCHUtlRgrLcRecfg
2514 * Purpose: This function performs modification of a service in
2515 * scheduler. The modification is performed for each direction
2516 * based the direction field of the configuration
2518 * Invoked by: Scheduler
2520 * @param[in] RgSchCellCb *cell
2521 * @param[in] RgSchUeCb *ue
2522 * @param[in] RgSchDlLcCb *dlLc
2523 * @param[in] RgrLchRecfg *recfg
2524 * @param[in] RgSchErrInfo *err
2528 S16 rgSCHUtlRgrLcRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchRecfg *recfg,RgSchErrInfo *err)
2530 return (cell->sc.apis->rgSCHRgrLchRecfg(cell, ue, dlLc, recfg, err));
2534 * @brief This function deletes a Lc in scheduler
2538 * Function: rgSCHUtlRgrLcDel
2539 * Purpose: This function performs deletion of Lc in scheduler
2541 * Invoked by: Scheduler
2543 * @param[in] RgSchCellCb *cell
2544 * @param[in] RgSchUeCb *ue
2545 * @param[in] CmLteLcId lcId
2546 * @param[in] uint8_t lcgId
2550 S16 rgSCHUtlRgrLcDel(RgSchCellCb *cell,RgSchUeCb *ue,CmLteLcId lcId,uint8_t lcgId)
2552 cell->sc.apis->rgSCHRgrLchDel(cell, ue, lcId, lcgId);
2555 } /* rgSCHUtlRgrLcDel */
2558 * @brief This function adds a service to scheduler
2562 * Function: rgSCHUtlRgrLcgCfg
2563 * Purpose: This function performs addition of service to scheduler
2564 * The addition is performed for each direction based
2565 * the direction field of the configuration
2567 * Invoked by: Scheduler
2569 * @param[in] RgSchCellCb *cell
2570 * @param[in] RgSchUeCb *ue
2571 * @param[in] RgrLchCfg *cfg
2572 * @param[in] RgSchErrInfo *err
2576 S16 rgSCHUtlRgrLcgCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrLcgCfg *cfg,RgSchErrInfo *errInfo)
2578 return (cell->sc.apis->rgSCHRgrLcgCfg(cell, ue, &(ue->ul.lcgArr[cfg->ulInfo.lcgId]), cfg, errInfo));
2583 * @brief This function modifies a service to scheduler
2587 * Function: rgSCHUtlRgrLcgRecfg
2588 * Purpose: This function performs modification of a service in
2589 * scheduler. The modification is performed for each direction
2590 * based the direction field of the configuration
2592 * Invoked by: Scheduler
2594 * @param[in] RgSchCellCb *cell
2595 * @param[in] RgSchUeCb *ue
2596 * @param[in] RgrLcgRecfg *recfg
2597 * @param[in] RgSchErrInfo *err
2601 S16 rgSCHUtlRgrLcgRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrLcgRecfg *recfg,RgSchErrInfo *err)
2603 return (cell->sc.apis->rgSCHRgrLcgRecfg(cell, ue, &(ue->ul.lcgArr[recfg->ulRecfg.lcgId]), recfg, err));
2604 } /* rgSCHUtlRgrLcRecfg */
2607 * @brief This function modifies a service to scheduler
2611 * Function: rgSCHUtlRgrLcgDel
2612 * Purpose: This function performs modification of a service in
2613 * scheduler. The modification is performed for each direction
2614 * based the direction field of the configuration
2616 * Invoked by: Scheduler
2618 * @param[in] RgSchCellCb *cell
2619 * @param[in] RgSchUeCb *ue
2620 * @param[in] RgrDel *lcDelInfo
2624 Void rgSCHUtlRgrLcgDel(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId)
2626 cell->sc.apis->rgSCHFreeLcg(cell, ue, &ue->ul.lcgArr[lcgId]);
2628 /* Stack Crash problem for TRACE5 changes. added the return below . */
2631 } /* rgSCHUtlRgrLcgDel */
2634 /* End: LTEMAC_2.1_DEV_CFG */
2637 * @brief This function is a wrapper to call scheduler specific API.
2641 * Function: rgSCHUtlDoaInd
2642 * Purpose: Updates the DOA for the UE
2646 * @param[in] RgSchCellCb *cell
2647 * @param[in] RgSchUeCb *ue
2648 * @param[in] TfuDoaRpt *doaRpt
2652 Void rgSCHUtlDoaInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuDoaRpt *doaRpt)
2654 ue->mimoInfo.doa.pres = PRSNT_NODEF;
2655 ue->mimoInfo.doa.val = doaRpt->doa;
2660 * @brief This function is a wrapper to call scheduler specific API.
2664 * Function: rgSCHUtlDlCqiInd
2665 * Purpose: Updates the DL CQI for the UE
2669 * @param[in] RgSchCellCb *cell
2670 * @param[in] RgSchUeCb *ue
2671 * @param[in] TfuDlCqiRpt *dlCqiRpt
2672 * @param[in] CmLteTimingInfo timingInfo
2676 Void rgSCHUtlDlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuDlCqiRpt *dlCqiRpt,CmLteTimingInfo timingInfo)
2678 RgSchCellCb *sCellCb = NULLP;
2679 if (dlCqiRpt->isPucchInfo)
2681 sCellCb = ue->cellInfo[dlCqiRpt->dlCqiInfo.pucchCqi.cellIdx]->cell;
2682 sCellCb->sc.apis->rgSCHDlCqiInd(sCellCb, ue, dlCqiRpt->isPucchInfo, \
2683 (Void *)&dlCqiRpt->dlCqiInfo.pucchCqi, timingInfo);
2688 for (idx = 0; idx < dlCqiRpt->dlCqiInfo.pusch.numOfCells; idx++)
2690 sCellCb = ue->cellInfo[dlCqiRpt->dlCqiInfo.pusch.puschCqi[idx].cellIdx]->cell;
2691 sCellCb->sc.apis->rgSCHDlCqiInd(sCellCb, ue, dlCqiRpt->isPucchInfo, \
2692 (Void *)&dlCqiRpt->dlCqiInfo.pusch.puschCqi[idx], timingInfo);
2701 * @brief This function is a wrapper to call scheduler specific API.
2705 * Function: rgSCHUtlSrsInd
2706 * Purpose: Updates the UL SRS for the UE
2710 * @param[in] RgSchCellCb *cell
2711 * @param[in] RgSchUeCb *ue
2712 * @param[in] TfuSrsRpt* srsRpt
2713 * @param[in] CmLteTimingInfo timingInfo
2717 Void rgSCHUtlSrsInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuSrsRpt *srsRpt,CmLteTimingInfo timingInfo)
2719 cell->sc.apis->rgSCHSrsInd(cell, ue, srsRpt, timingInfo);
2725 * @brief This function is a wrapper to call scheduler specific API.
2729 * Function: rgSCHUtlDlTARpt
2730 * Purpose: Reports PHY TA for a UE.
2734 * @param[in] RgSchCellCb *cell
2735 * @param[in] RgSchUeCb *ue
2739 Void rgSCHUtlDlTARpt(RgSchCellCb *cell,RgSchUeCb *ue)
2741 cell->sc.apis->rgSCHDlTARpt(cell, ue);
2747 * @brief This function is a wrapper to call scheduler specific API.
2751 * Function: rgSCHUtlDlRlsSubFrm
2752 * Purpose: Releases scheduler Information from DL SubFrm.
2756 * @param[in] RgSchCellCb *cell
2757 * @param[out] CmLteTimingInfo subFrm
2761 Void rgSCHUtlDlRlsSubFrm(RgSchCellCb *cell,CmLteTimingInfo subFrm)
2763 cell->sc.apis->rgSCHDlRlsSubFrm(cell, subFrm);
2769 * @brief This API is invoked to update the AperCQI trigger
2774 * Function : rgSCHUtlUpdACqiTrigWt
2775 * - If HqFdbk is ACK then add up weight corresponding
2776 * to ACK to the AcqiTrigWt.
2777 * - If HqFdbk is NACK then add up weight corresponding
2778 * to NACK to the AcqiTrigWt.
2779 * - If AcqiTrigWt crosses threshold then trigger
2780 * grant req for APERCQI to SCH.
2782 * @param[in] RgSchUeCb *ue
2783 * @param[in] uint8_t isAck
2787 Void rgSCHUtlUpdACqiTrigWt(RgSchUeCb *ue,RgSchUeCellInfo *cellInfo,uint8_t isAck )
2790 uint8_t triggerSet = 0;
2794 if (isAck == TFU_HQFDB_ACK)
2796 cellInfo->acqiCb.aCqiTrigWt += RG_APER_CQI_ACK_WGT;
2800 cellInfo->acqiCb.aCqiTrigWt += RG_APER_CQI_NACK_WGT;
2803 if (cellInfo->acqiCb.aCqiTrigWt > RG_APER_CQI_THRESHOLD_WGT)
2805 RgSchCellCb *cell = ue->cell;
2806 RgSchErrInfo unUsed;
2808 if(ue->dl.reqForCqi)
2810 /* Already one ACQI trigger procedure is going on
2811 * which is not yet satisfied. Delaying this request till
2812 * the previous is getting satisfied*/
2816 ue->dl.reqForCqi = TRUE;
2818 rgSchCmnSetCqiReqField(cellInfo,ue,&ue->dl.reqForCqi);
2819 //Reset aCqiTrigWt for all the serving cells for which we have triggered ACQI
2820 rgSCHTomUtlGetTrigSet(cell, ue, ue->dl.reqForCqi, &triggerSet);
2821 for (sIdx = 0; sIdx < CM_LTE_MAX_CELLS; sIdx++)
2823 /* The Aperiodic requested for SCell index sIdx */
2824 if ((triggerSet >> (7 - sIdx)) & 0x01)
2826 /* The Aperiodic request for SCell index sIdx */
2827 ue->cellInfo[sIdx]->acqiCb.aCqiTrigWt = 0;
2832 /* Force SCH to send UL grant by indicating fake SR.
2833 * If this UE already in UL SCH Qs this SR Ind will
2835 rgSCHUtlSrRcvd(cell, ue, cell->crntTime, &unUsed);
2843 * @brief This API is invoked to indicate scheduler of a CRC indication.
2847 * Function : rgSCHUtlHdlUlTransInd
2848 * This API is invoked to indicate scheduler of a CRC indication.
2850 * @param[in] RgSchCellCb *cell
2851 * @param[in] RgSchUeCb *ue
2852 * @param[in] CmLteTimingInfo timingInfo
2856 Void rgSCHUtlHdlUlTransInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2858 cell->sc.apis->rgSCHHdlUlTransInd(cell, ue, timingInfo);
2863 * @brief This API is invoked to indicate scheduler of a CRC failure.
2867 * Function : rgSCHUtlHdlCrcInd
2868 * This API is invoked to indicate CRC to scheduler.
2870 * @param[in] RgSchCellCb *cell
2871 * @param[in] RgSchUeCb *ue
2872 * @param[in] CmLteTimingInfo timingInfo
2876 Void rgSCHUtlHdlCrcInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2878 cell->sc.apis->rgSCHUlCrcInd(cell, ue, timingInfo);
2880 } /* end of rgSCHUtlHdlCrcFailInd */
2883 * @brief This API is invoked to indicate scheduler of a CRC failure.
2887 * Function : rgSCHUtlHdlCrcFailInd
2888 * This API is invoked to indicate CRC failure to scheduler.
2890 * @param[in] RgSchCellCb *cell
2891 * @param[in] RgSchUeCb *ue
2892 * @param[in] CmLteTimingInfo timingInfo
2896 Void rgSCHUtlHdlCrcFailInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2898 cell->sc.apis->rgSCHUlCrcFailInd(cell, ue, timingInfo);
2900 } /* end of rgSCHUtlHdlCrcFailInd */
2901 #endif /* LTEMAC_SPS */
2905 * @brief This function is a wrapper to call scheduler specific API.
2909 * Function: rgSCHUtlDlProcAddToRetx
2910 * Purpose: This function adds a HARQ process to retransmission
2911 * queue. This may be performed when a HARQ ack is
2914 * Invoked by: HARQ feedback processing
2916 * @param[in] RgSchCellCb* cell
2917 * @param[in] RgSchDlHqProc* hqP
2921 Void rgSCHUtlDlProcAddToRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
2923 cell->sc.apis->rgSCHDlProcAddToRetx(cell, hqP);
2929 * @brief This function adds a HARQ process TB to transmission
2933 * Function: rgSCHUtlDlHqPTbAddToTx
2934 * Purpose: This function a HarqProcess TB to the slot
2937 * Invoked by: Scheduler
2939 * @param[in] RgSubFrm* subFrm
2940 * @param[in] RgDlHqProc* hqP
2941 * @param[in] uint8_t tbIdx
2945 Void rgSCHUtlDlHqPTbAddToTx(RgSchDlSf *subFrm,RgSchDlHqProcCb *hqP,uint8_t tbIdx)
2947 RgSchUeCb *ue = NULLP;
2948 RgSchCellCb *cell = hqP->hqE->cell;
2950 /* Addition of UE to dlSf->ueLst shall be done only to UE's PCell */
2951 /* ue->cell will always hold PCell information */
2952 if (NULLP == hqP->hqPSfLnk.node)
2957 if(NULLP == ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node)
2959 ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node = (PTR)ue;
2960 cmLListAdd2Tail(&cell->subFrms[subFrm->dlIdx]->ueLst,
2961 &ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk);
2963 ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].isPuschHarqRecpPres = FALSE;
2967 /* Add Hq proc in particular dlIdx List for this UE
2968 This list will be used while processing feedback*/
2969 hqP->hqPSfLnk.node = (PTR)hqP;
2970 cmLListAdd2Tail(&ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].hqPLst,&hqP->hqPSfLnk);
2973 uint32_t gSCellSchedCount,gPrimarySchedCount;
2974 if(RG_SCH_IS_CELL_SEC(hqP->hqE->ue,hqP->hqE->cell))
2978 gPrimarySchedCount++;
2982 else if (hqP->hqE->msg4Proc == hqP)
2984 /* Msg4 will be scheduled on PCELL only hence add directly to subFrm msg4HqpList */
2985 hqP->hqPSfLnk.node = (PTR)hqP;
2986 cmLListAdd2Tail(&subFrm->msg4HqPLst, &hqP->hqPSfLnk);
2993 if((ue) && (HQ_TB_WAITING == hqP->tbInfo[tbIdx].state))
2996 ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].totalTbCnt++;
2998 /*totalTbCnt will hold the total number of TBs across all harq Proc from all
3001 hqP->subFrm = subFrm;
3010 * @brief This function removes a HARQ process TB from transmission
3014 * Function: rgSCHUtlDlHqPTbRmvFrmTx
3015 * Purpose: This function removes a HarqProcess TB to the slot
3018 * Invoked by: Scheduler
3020 * @param[in] RgSubFrm* subFrm
3021 * @param[in] RgDlHqProc* hqP
3022 * @param[in] uint8_t tbIdx
3023 * @param[in] Bool isRepeting
3027 Void rgSCHUtlDlHqPTbRmvFrmTx(RgSchDlSf *subFrm,RgSchDlHqProcCb *hqP,uint8_t tbIdx,Bool isRepeting)
3029 RgSchCellCb *cell = NULLP;
3030 /* Check with TDD */
3032 (hqP->hqE->ue->ackNakRepCb.cfgRepCnt !=
3033 hqP->tbInfo[tbIdx].fbkRepCntr))
3035 cmLListDelFrm(&subFrm->ackNakRepQ,
3036 &hqP->tbInfo[tbIdx].anRepLnk[hqP->tbInfo[tbIdx].fbkRepCntr]);
3040 if (NULLP != hqP->hqPSfLnk.node)
3043 if (hqP->hqE->msg4Proc == hqP)
3045 /* Msg4 will be scheduled on PCELL only hence delete directly from subFrm msg4HqpList */
3046 cmLListDelFrm(&subFrm->msg4HqPLst, &hqP->hqPSfLnk);
3050 cell = hqP->hqE->cell;
3051 /* Addition of UE to dlSf->ueLst shall be done only to UE's PCell */
3052 /* ue->cell will always hold PCell information */
3053 cmLListDelFrm(&hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].hqPLst,&hqP->hqPSfLnk);
3054 if (0 == hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].hqPLst.count)
3057 cmLListDelFrm(&cell->subFrms[subFrm->dlIdx]->ueLst,
3058 &hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk);
3059 hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node = (PTR)NULLP;
3060 hqP->hqE->ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].totalTbCnt = 0;
3063 hqP->hqPSfLnk.node = NULLP;
3065 hqP->subFrm = NULLP;
3072 * @brief Handler for accessing the existing SCellCb identified by the key
3073 * SCellId under the CellCb.
3077 * Function : rgSchUtlGetCellCb
3080 * @param[in] *cellCb
3082 * @return RgSchUeCb*
3084 RgSchCellCb* rgSchUtlGetCellCb(Inst inst,uint16_t cellId)
3086 RgSchCellCb *cellCb = NULLP;
3088 strtCellId = rgSchCb[inst].genCfg.startCellId;
3089 cellCb = rgSchCb[inst].cells[cellId - strtCellId];
3093 } /* rgSchUtlGetCellCb */
3096 * @brief Handler for deriving the servCellidx
3100 * Function : rgSchUtlGetServCellIdx
3103 * @param[in] *cellId
3104 * @param[in] RgSchUeCb *ue
3105 * @return uint8_t servCellIdx
3107 uint8_t rgSchUtlGetServCellIdx(Inst inst, uint16_t cellId, RgSchUeCb *ue)
3109 uint8_t servCellIdx;
3110 uint16_t strtCellId;
3112 strtCellId = rgSchCb[inst].genCfg.startCellId;
3113 servCellIdx = ue->cellIdToCellIdxMap[cellId - strtCellId];
3114 return (servCellIdx);
3116 } /* rgSchUtlGetCellCb */
3119 * @brief Handler for validating the Cell Id received secondary Cell Addition
3123 * Function : rgSchUtlGetCellId
3126 * @param[in] *cellCb
3128 * @return RgSchUeCb*
3130 S16 rgSchUtlVldtCellId(Inst inst,uint16_t cellId)
3134 strtCellId = rgSchCb[inst].genCfg.startCellId;
3135 if((cellId >= strtCellId) && ((cellId - strtCellId) < CM_LTE_MAX_CELLS))
3140 } /* rgSchUtlVldtCellId */
3144 * @brief UE reconfiguration for scheduler
3148 * Function : rgSCHUtlRgrUeRecfg
3150 * This functions updates UE specific scheduler
3151 * information upon UE reconfiguration
3153 * @param[in] RgSchCellCb *cell
3154 * @param[in] RgSchUeCb *ue
3155 * @param[int] RgrUeRecfg *ueRecfg
3156 * @param[out] RgSchErrInfo *err
3161 S16 rgSCHUtlRgrUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
3163 /* Changes for UE Category Reconfiguration feature addition */
3164 RgSchCmnUe *ueSch = RG_SCH_CMN_GET_UE(ue, cell);
3166 /* Changes for UE Category Reconfiguration feature addition */
3167 if (ueRecfg->ueRecfgTypes & RGR_UE_UECAT_RECFG)
3169 ueSch->cmn.ueCat = ueRecfg->ueCatEnum-1;
3171 ue->ueCatEnum = ueRecfg->ueCatEnum;
3175 /* DL MU-MIMO not supported */
3176 if (ueRecfg->ueRecfgTypes & RGR_UE_TXMODE_RECFG)
3179 if (ueRecfg->txMode.pres == PRSNT_NODEF)
3181 if (ueRecfg->txMode.txModeEnum == RGR_UE_TM_5)
3183 err->errCause = RGSCHERR_SCH_CFG;
3187 if(ue->mimoInfo.txMode != ueRecfg->txMode.txModeEnum)
3189 /* Decremnt the previos A value for this cell */
3190 ue->f1bCsAVal -= rgSCHUtlGetMaxTbSupp(ue->mimoInfo.txMode);
3191 /* Update A value with the new TM Mode */
3192 ue->f1bCsAVal += rgSCHUtlGetMaxTbSupp(ueRecfg->txMode.txModeEnum);
3195 DU_LOG("\nINFO --> SCH : UeReCfg A valie is %d\n",ue->f1bCsAVal);
3198 ue->mimoInfo.txMode = ueRecfg->txMode.txModeEnum;
3202 /* [ccpu00123958]-ADD- Check for PUSCH related Reconfig from the bit mask */
3203 if(ueRecfg->ueRecfgTypes & RGR_UE_PUSCH_RECFG)
3205 /* Fix: ccpu00124012 */
3206 /* TODO:: Need to check if this is
3207 mandatory to be re-configured on UE category re-configuration */
3208 /* ue->ul.betaHqOffst = ueRecfg->puschDedCfg.bACKIdx;
3209 ue->ul.betaCqiOffst = ueRecfg->puschDedCfg.bCQIIdx;
3210 ue->ul.betaRiOffst = ueRecfg->puschDedCfg.bRIIdx;*/
3213 if (ueRecfg->ueRecfgTypes & RGR_UE_ULTXANTSEL_RECFG)
3215 ue->ul.ulTxAntSel = ueRecfg->ulTxAntSel;
3217 if (ueRecfg->ueRecfgTypes & RGR_UE_CDBKSBST_RECFG)
3219 ue->mimoInfo.cdbkSbstRstrctn = ueRecfg->ueCodeBookRstRecfg;
3222 /* Commenting here to assign garbage value when it is not set in APP. */
3223 //ue->accessStratumRls = ueRecfg->accessStratumRls;
3224 return (cell->sc.apis->rgSCHRgrUeRecfg(cell, ue, ueRecfg, err));
3225 } /* rgSCHUtlRgrUeRecfg */
3228 * @brief This function deletes a service from scheduler
3232 * Function: rgSCHUtlFreeDlLc
3233 * Purpose: This function is made available through a FP for
3234 * making scheduler aware of a service being deleted from UE
3236 * Invoked by: BO and Scheduler
3238 * @param[in] RgSchCellCb* cell
3239 * @param[in] RgSchUeCb* ue
3240 * @param[in] RgSchDlLcCb* svc
3243 Void rgSCHUtlFreeDlLc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3245 cell->sc.apis->rgSCHFreeDlLc(cell, ue, svc);
3247 /* Stack Crash problem for TRACE5 changes. added the return below . */
3253 * @brief UE deletion for scheduler
3257 * Function : rgSCHUtlFreeUe
3259 * This functions deletes all scheduler information
3260 * pertaining to a UE
3262 * @param[in] RgSchCellCb *cell
3263 * @param[in] RgSchUeCb *ue
3266 Void rgSCHUtlFreeUe(RgSchCellCb *cell,RgSchUeCb *ue)
3269 rgSCHUtlDelUeANFdbkInfo(ue,RGSCH_PCELL_INDEX);
3271 cell->sc.apis->rgSCHFreeUe(cell, ue);
3273 /* Stack Crash problem for TRACE5 changes. added the return below . */
3276 } /* rgSCHUtlFreeUe */
3279 * @brief This function updates the scheduler with service for a UE
3283 * Function: rgSCHUtlDlDedBoUpd
3284 * Purpose: This function should be called whenever there is a
3285 * change BO for a service.
3287 * Invoked by: BO and Scheduler
3289 * @param[in] RgSchCellCb* cell
3290 * @param[in] RgSchUeCb* ue
3291 * @param[in] RgSchDlLcCb* lc
3294 Void rgSCHUtlDlDedBoUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *lc)
3296 cell->sc.apis->rgSCHDlDedBoUpd(cell, ue, lc);
3300 * @brief Record MSG3 allocation into the UE
3304 * Function : rgSCHUtlRecMsg3Alloc
3306 * This function is invoked to update record msg3 allocation information
3307 * in the UE when UE is detected for RaCb
3309 * @param[in] RgSchCellCb *cell
3310 * @param[in] RgSchUeCb *ue
3311 * @param[in] RgSchRaCb *raCb
3314 Void rgSCHUtlRecMsg3Alloc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchRaCb *raCb)
3316 cell->sc.apis->rgSCHUlRecMsg3Alloc(cell, ue, raCb);
3319 } /* rgSCHRecMsg3Alloc */
3323 * @brief Update harq process for allocation
3327 * Function : rgSCHUtlUpdUlHqProc
3329 * This function is invoked when harq process
3330 * control block is now in a new memory location
3331 * thus requiring a pointer/reference update.
3333 * @param[in] RgSchCellCb *cell
3334 * @param[in] RgSchUlHqProcCb *curProc
3335 * @param[in] RgSchUlHqProcCb *oldProc
3340 S16 rgSCHUtlUpdUlHqProc(RgSchCellCb *cell,RgSchUlHqProcCb *curProc,RgSchUlHqProcCb *oldProc)
3342 return (cell->sc.apis->rgSCHUpdUlHqProc(cell, curProc, oldProc));
3343 } /* rgSCHUtlUpdUlHqProc */
3346 * @brief UL grant for contention resolution
3350 * Function : rgSCHUtlContResUlGrant
3352 * Add UE to another queue specifically for CRNTI based contention
3355 * @param[in] RgSchCellCb *cell
3356 * @param[in] RgSchUeCb *ue
3357 * @param[out] RgSchErrInfo *err
3362 S16 rgSCHUtlContResUlGrant(RgSchCellCb *cell,RgSchUeCb *ue,RgSchErrInfo *err)
3365 ue->isMsg4PdcchWithCrnti = TRUE;
3366 return (cell->sc.apis->rgSCHContResUlGrant(cell, ue, err));
3367 } /* rgSCHUtlContResUlGrant */
3370 * @brief SR reception handling
3374 * Function : rgSCHUtlSrRcvd
3376 * - Handles SR reception for UE
3378 * @param[in] RgSchCellCb *cell
3379 * @param[in] RgSchUeCb *ue
3380 * @param[out] RgSchErrInfo *err
3385 S16 rgSCHUtlSrRcvd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo frm,RgSchErrInfo *err)
3387 return (cell->sc.apis->rgSCHSrRcvd(cell, ue, frm, err));
3388 } /* rgSCHUtlSrRcvd */
3391 * @brief Short BSR update
3395 * Function : rgSCHUtlUpdBsrShort
3397 * This functions does requisite updates to handle short BSR reporting
3399 * @param[in] RgSchCellCb *cell
3400 * @param[in] RgSchUeCb *ue
3401 * @param[in] uint8_t lcgId
3402 * @param[in] uint8_t bsr
3403 * @param[out] RgSchErrInfo *err
3408 Void rgSCHUtlUpdBsrShort(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId,uint8_t bsr,RgSchErrInfo *err)
3410 cell->sc.apis->rgSCHUpdBsrShort(cell, ue, &ue->ul.lcgArr[lcgId], bsr, err);
3412 } /* rgSCHUtlUpdBsrShort */
3416 * @brief Truncated BSR update
3420 * Function : rgSCHUtlUpdBsrTrunc
3422 * This functions does required updates to handle truncated BSR report
3425 * @param[in] RgSchCellCb *cell
3426 * @param[in] RgSchUeCb *ue
3427 * @param[in] uint8_t lcgId
3428 * @param[in] uint8_t bsr
3429 * @param[out] RgSchErrInfo *err
3434 Void rgSCHUtlUpdBsrTrunc(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId,uint8_t bsr,RgSchErrInfo *err)
3436 cell->sc.apis->rgSCHUpdBsrTrunc(cell, ue, &ue->ul.lcgArr[lcgId], bsr, err);
3438 } /* rgSCHUtlUpdBsrTrunc */
3442 * @brief Long BSR update
3446 * Function : rgSCHUtlUpdBsrLong
3448 * - Update BSRs for all configured LCGs
3449 * - Update priority of LCGs if needed
3450 * - Update UE's position within/across uplink scheduling queues
3453 * @param[in] RgSchCellCb *cell
3454 * @param[in] RgSchUeCb *ue
3455 * @param[in] uint8_t bsr0
3456 * @param[in] uint8_t bsr1
3457 * @param[in] uint8_t bsr2
3458 * @param[in] uint8_t bsr3
3459 * @param[out] RgSchErrInfo *err
3464 Void rgSCHUtlUpdBsrLong(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t bsr0,uint8_t bsr1,uint8_t bsr2,uint8_t bsr3,RgSchErrInfo *err)
3471 cell->sc.apis->rgSCHUpdBsrLong(cell, ue, bsArr, err);
3473 } /* rgSCHUtlUpdBsrLong */
3476 * @brief EXT PHR update
3480 * Function : rgSCHUtlUpdExtPhr
3482 * Updates extended power headroom info for a UE
3484 * @param[in] RgSchCellCb *cell
3485 * @param[in] RgSchUeCb *ue
3486 * @param[in] uint8_t phr
3487 * @param[out] RgSchErrInfo *err
3492 S16 rgSCHUtlUpdExtPhr(RgSchCellCb *cell,RgSchUeCb *ue,RgInfExtPhrCEInfo *extPhr,RgSchErrInfo *err)
3494 return (cell->sc.apis->rgSCHUpdExtPhr(cell, ue, extPhr, err));
3495 } /* rgSCHUtlUpdExtPhr */
3504 * Function : rgSCHUtlUpdPhr
3506 * Updates power headroom info for a UE
3508 * @param[in] RgSchCellCb *cell
3509 * @param[in] RgSchUeCb *ue
3510 * @param[in] uint8_t phr
3511 * @param[out] RgSchErrInfo *err
3516 S16 rgSCHUtlUpdPhr(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t phr,RgSchErrInfo *err)
3518 return (cell->sc.apis->rgSCHUpdPhr(cell, ue, phr, err));
3519 } /* rgSCHUtlUpdPhr */
3523 * @brief Indication of UL CQI
3527 * Function : rgSCHUtlUlCqiInd
3529 * - Updates uplink CQI information for the UE. Computes and
3530 * stores the lowest CQI of CQIs reported in all subbands
3532 * @param[in] RgSchCellCb *cell
3533 * @param[in] RgSchUeCb *ue
3534 * @param[in] TfuUlCqiRpt *ulCqiInfo
3537 Void rgSCHUtlUlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuUlCqiRpt *ulCqiInfo)
3539 cell->sc.apis->rgSCHUlCqiInd(cell, ue, ulCqiInfo);
3541 } /* rgSCHUtlUlCqiInd */
3544 * @brief Indication of PUCCH power adjustment
3548 * Function : rgSCHUtlPucchDeltaPwrInd
3550 * - Updates uplink CQI information for the UE. Computes and
3551 * stores the lowest CQI of CQIs reported in all subbands
3553 * @param[in] RgSchCellCb *cell
3554 * @param[in] RgSchUeCb *ue
3555 * @param[in] uint8_t delta
3558 Void rgSCHUtlPucchDeltaPwrInd(RgSchCellCb *cell,RgSchUeCb *ue,S8 delta)
3560 cell->sc.apis->rgSCHPucchDeltaPwrInd(cell, ue, delta);
3562 } /* rgSCHUtlPucchDeltaPwrInd */
3564 /* Start: LTEMAC_2.1_DEV_CFG */
3566 * @brief Ue Reset Request
3570 * Function : rgSCHUtlUeReset
3573 * @param[in] RgSchCellCb *cell
3574 * @param[in] RgSchUeCb *ue
3577 Void rgSCHUtlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
3580 cell->sc.apis->rgSCHUeReset(cell, ue);
3582 } /* rgSCHUtlUeReset */
3583 /* End: LTEMAC_2.1_DEV_CFG */
3586 * @brief Returns HARQ proc for which data expected now
3590 * Function: rgSCHUtlUlHqProcForUe
3591 * Purpose: This function returns the harq process for
3592 * which data is expected in the current slot.
3593 * It does not validate if the HARQ process
3594 * has an allocation.
3598 * @param[in] RgSchCellCb *cell
3599 * @param[in] CmLteTimingInfo frm
3600 * @param[in] RgSchUeCb *ue
3601 * @param[out] RgSchUlHqProcCb **procRef
3604 Void rgSCHUtlUlHqProcForUe(RgSchCellCb *cell,CmLteTimingInfo frm,RgSchUeCb *ue,RgSchUlHqProcCb **procRef)
3606 cell->sc.apis->rgSCHUlHqProcForUe(cell, frm, ue, procRef);
3608 /* Stack Crash problems for TRACE5 changes. added the return below */
3614 * @brief Returns first uplink allocation to send reception
3619 * Function: rgSCHUtlFirstRcptnReq(cell)
3620 * Purpose: This function returns the first uplink allocation
3621 * (or NULLP if there is none) in the slot
3622 * in which is expected to prepare and send reception
3627 * @param[in] RgSchCellCb *cell
3628 * @return RgSchUlAlloc*
3630 RgSchUlAlloc *rgSCHUtlFirstRcptnReq(RgSchCellCb *cell)
3632 return (cell->sc.apis->rgSCHFirstRcptnReq(cell));
3636 * @brief Returns first uplink allocation to send reception
3641 * Function: rgSCHUtlNextRcptnReq(cell)
3642 * Purpose: This function returns the next uplink allocation
3643 * (or NULLP if there is none) in the slot
3644 * in which is expected to prepare and send reception
3649 * @param[in] RgSchCellCb *cell
3650 * @return RgSchUlAlloc*
3652 RgSchUlAlloc *rgSCHUtlNextRcptnReq(RgSchCellCb *cell,RgSchUlAlloc *alloc)
3654 return (cell->sc.apis->rgSCHNextRcptnReq(cell, alloc));
3658 * @brief Returns first uplink allocation to send HARQ feedback
3663 * Function: rgSCHUtlFirstHqFdbkAlloc
3664 * Purpose: This function returns the first uplink allocation
3665 * (or NULLP if there is none) in the slot
3666 * in which it is expected to prepare and send HARQ
3671 * @param[in] RgSchCellCb *cell
3672 * @param[in] uint8_t idx
3673 * @return RgSchUlAlloc*
3675 RgSchUlAlloc *rgSCHUtlFirstHqFdbkAlloc(RgSchCellCb *cell,uint8_t idx)
3677 return (cell->sc.apis->rgSCHFirstHqFdbkAlloc(cell, idx));
3682 * @brief Returns next allocation to send HARQ feedback for
3686 * Function: rgSCHUtlNextHqFdbkAlloc(cell)
3687 * Purpose: This function returns the next uplink allocation
3688 * (or NULLP if there is none) in the slot
3689 * for which HARQ feedback needs to be sent.
3693 * @param[in] RgSchCellCb *cell
3694 * @return RgSchUlAlloc*
3696 RgSchUlAlloc *rgSCHUtlNextHqFdbkAlloc(RgSchCellCb *cell,RgSchUlAlloc *alloc,uint8_t idx)
3698 return (cell->sc.apis->rgSCHNextHqFdbkAlloc(cell, alloc, idx));
3701 /***********************************************************
3703 * Func : rgSCHUtlResetSfAlloc
3705 * Desc : Utility Function to Reset slot allocation information.
3714 **********************************************************/
3715 S16 rgSCHUtlResetSfAlloc(RgInfSfAlloc *sfAlloc,Bool resetCmnLcInfo,Bool restAlloc)
3717 if(TRUE == restAlloc)
3719 if(sfAlloc->ueInfo.numUes)
3721 memset(sfAlloc->ueInfo.allocInfo,0x00,
3722 (sizeof(RgInfUeAlloc)*sfAlloc->ueInfo.numUes));
3724 sfAlloc->ueInfo.numUes = 0;
3725 sfAlloc->rarInfo.numRaRntis = 0;
3726 sfAlloc->flowCntrlInfo.numUes = 0;
3728 if(TRUE == resetCmnLcInfo)
3730 sfAlloc->cmnLcInfo.bitMask = 0;
3735 /***********************************************************
3737 * Func : rgSCHUtlGetRlsHqAlloc
3739 * Desc : Utility Function to Allocate slot allocation information.
3748 **********************************************************/
3749 S16 rgSCHUtlGetRlsHqAlloc(RgSchCellCb *cell)
3752 Inst inst = cell->instIdx;
3753 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3755 cell->rlsHqArr[idx].cellId = cell->cellId;
3757 /* Allocating with additional location, to accommodate
3758 TA scheduling along with maximum no of UEs per SF */
3760 /* Allocate memory for "scheduled UE" Info */
3761 if((rgSCHUtlAllocSBuf(inst,
3762 (Data**)&(cell->rlsHqArr[idx].ueHqInfo),
3763 (sizeof(RgInfUeHqInfo)*RGSCH_MAX_UE_PER_DL_SF))) != ROK)
3765 DU_LOG("\nERROR --> SCH : Memory allocation FAILED for "
3775 /***********************************************************
3777 * Func : rgSCHUtlPutRlsHqAlloc
3779 * Desc : Utility Function to deallocate slot allocation information.
3788 **********************************************************/
3789 S16 rgSCHUtlPutRlsHqAlloc(RgSchCellCb *cell)
3792 Inst inst = cell->instIdx;
3794 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3796 /* Deallocate memory for "scheduled UE" Info */
3797 if (cell->rlsHqArr[idx].ueHqInfo != NULLP)
3799 /* Freeing with additional location, to accommodate TA
3800 scheduling along with maximum no of UEs per SF */
3801 /* ccpu00117052 - MOD - Passing double pointer
3802 for proper NULLP assignment*/
3803 rgSCHUtlFreeSBuf(inst,
3804 (Data **)(&(cell->rlsHqArr[idx].ueHqInfo)),
3805 (sizeof(RgInfUeHqInfo)*RGSCH_MAX_UE_PER_DL_SF));
3814 /***********************************************************
3816 * Func : rgSCHUtlGetSfAlloc
3818 * Desc : Utility Function to Allocate slot allocation information.
3827 **********************************************************/
3828 S16 rgSCHUtlGetSfAlloc(RgSchCellCb *cell)
3832 Inst inst = cell->instIdx;
3833 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3836 for(idx=0; idx < RGSCH_SF_ALLOC_SIZE; idx++)
3838 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3841 cell->sfAllocArr[idx].cellId = cell->cellId;
3843 /* Allocating with additional location, to accommodate
3844 TA scheduling along with maximum no of UEs per SF */
3846 /* Allocate memory for "scheduled UE" Info */
3847 if((rgSCHUtlAllocSBuf(inst,
3848 (Data**)&(cell->sfAllocArr[idx].ueInfo.allocInfo),
3849 (sizeof(RgInfUeAlloc)*RGSCH_MAX_UE_PER_DL_SF))) != ROK)
3851 DU_LOG("\nERROR --> SCH : Memory allocation FAILED for "
3856 /* Allocate memory for "scheduled RAR" Info */
3857 if((rgSCHUtlAllocSBuf(inst,
3858 (Data**)&(cell->sfAllocArr[idx].rarInfo.raRntiInfo),
3859 (sizeof(RgInfRaRntiInfo)*RGSCH_MAX_RARNTI_PER_DL_SF))) != ROK)
3861 DU_LOG("\nERROR --> SCH : Memory allocation FAILED for "
3865 for(indx = 0; indx < RGSCH_MAX_RARNTI_PER_DL_SF; indx++)
3867 if((rgSCHUtlAllocSBuf(inst,
3868 (Data**)&(cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].crntiInfo),
3869 (sizeof(RgInfCrntiInfo)* (cellUl->maxMsg3PerUlSf)))) != ROK)
3871 DU_LOG("\nERROR --> SCH : Memory allocation FAILED for "
3880 rgSCHEmtcUtlGetSfAlloc(cell);
3887 /***********************************************************
3889 * Func : rgSCHUtlPutSfAlloc
3891 * Desc : Utility Function to deallocate slot allocation information.
3900 **********************************************************/
3901 S16 rgSCHUtlPutSfAlloc(RgSchCellCb *cell)
3905 Inst inst = cell->instIdx;
3906 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3909 for(idx=0; idx < RGSCH_SF_ALLOC_SIZE; idx++)
3911 for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3914 if (cell->sfAllocArr[idx].rarInfo.raRntiInfo != NULLP)
3916 for(indx = 0; indx < RGSCH_MAX_RARNTI_PER_DL_SF; indx++)
3918 if (cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].crntiInfo != NULLP)
3919 /* ccpu00117052 - MOD - Passing double pointer
3920 for proper NULLP assignment*/
3921 rgSCHUtlFreeSBuf(inst,
3922 (Data**)(&(cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].\
3924 (sizeof(RgInfCrntiInfo)* (cellUl->maxMsg3PerUlSf)));
3926 /* Deallocate memory for "scheduled RAR" Info */
3927 /* ccpu00117052 - MOD - Passing double pointer
3928 for proper NULLP assignment*/
3929 rgSCHUtlFreeSBuf(inst,
3930 (Data**)(&(cell->sfAllocArr[idx].rarInfo.raRntiInfo)),
3931 (sizeof(RgInfRaRntiInfo)*RGSCH_MAX_RARNTI_PER_DL_SF));
3933 /* Deallocate memory for "scheduled UE" Info */
3934 if (cell->sfAllocArr[idx].ueInfo.allocInfo != NULLP)
3936 /* Freeing with additional location, to accommodate TA
3937 scheduling along with maximum no of UEs per SF */
3938 /* ccpu00117052 - MOD - Passing double pointer
3939 for proper NULLP assignment*/
3940 rgSCHUtlFreeSBuf(inst,
3941 (Data**)(&(cell->sfAllocArr[idx].ueInfo.allocInfo)),
3942 (sizeof(RgInfUeAlloc)*RGSCH_MAX_UE_PER_DL_SF));
3947 rgSCHEmtcUtlPutSfAlloc(cell);
3953 /***********************************************************
3955 * Func : rgSCHUtlAllocSBuf
3957 * Desc : Utility Function to Allocate static buffer.
3958 * Memory allocated is assumed contiguous.
3964 * Notes: Caller doesnt need to raise the alarm in case of memory
3965 * allocation gets failed.
3969 **********************************************************/
3970 S16 rgSCHUtlAllocSBuf
3972 Inst inst, /* Instance of the invoking scheduler */
3973 Data **pData, /* Pointer of the data to be returned */
3974 Size size /* size */
3977 /* Moving alarm diagnostics to available scope */
3979 /* Initialize the param to NULLP */
3982 /* May not be necessary for data performance path */
3990 /* allocate buffer */
3991 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
3992 MS_BUF_ADD_ALLOC_CALLER();
3994 if (SGetSBuf(rgSchCb[inst].rgSchInit.region, rgSchCb[inst].rgSchInit.pool,
3995 pData, size) != ROK)
3997 RgUstaDgn dgn; /* Alarm diagnostics structure */
3998 dgn.type = LRG_USTA_DGNVAL_MEM;
3999 dgn.u.mem.region = rgSchCb[inst].rgSchInit.region;
4000 dgn.u.mem.pool = rgSchCb[inst].rgSchInit.pool;
4001 /* Send an alarm to Layer Manager */
4002 rgSCHLmmStaInd(inst, LCM_CATEGORY_RESOURCE, LCM_EVENT_SMEM_ALLOC_FAIL,
4003 LCM_CAUSE_MEM_ALLOC_FAIL, &dgn);
4004 DU_LOG("\nERROR --> SCH : Unable to Allocate the Buffer");
4009 /* zero out the allocated memory */
4010 memset(*pData, 0x00, size);
4014 } /* end of rgSCHUtlAllocSBuf */
4019 * Fun: rgSCHUtlFreeSBuf
4021 * Desc: The argument to rgSCHUtlFreeSBuf() is a pointer to a block
4022 * previously allocated by rgSCHUtlAllocSBuf() and size. It
4023 * deallocates the memory.
4030 Void rgSCHUtlFreeSBuf
4032 Inst inst, /* Instance of the invoking scheduler */
4033 Data **data, /* pointer to data */
4034 Size size /* size */
4040 if ((data == NULLP) || (*data == NULLP) || (size == 0))
4046 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
4047 MS_BUF_ADD_CALLER();
4049 /* Deallocate buffer */
4050 ret = SPutSBuf(rgSchCb[inst].rgSchInit.region,
4051 rgSchCb[inst].rgSchInit.pool, (*data), size);
4055 DU_LOG("\nERROR --> SCH : rgSCHUtlFreeSBuf failed");
4059 /* ccpu00117052 - ADD - Assigning the pointer to NULLP */
4063 } /* end of rgSCHUtlFreeSBuf */
4069 * Fun: rgSCHUtlFreeWarningSiSeg
4071 * Desc: This is used to deallocate Warning SI Seg.
4079 Void rgSCHUtlFreeWarningSiSeg(Region reg,Pool pool,CmLListCp *siPduLst)
4084 while (siPduLst->first != NULLP)
4086 node = siPduLst->first;
4087 pdu = (Buffer *)node->node;
4088 cmLListDelFrm(siPduLst, node);
4089 RGSCH_FREE_MSG(pdu);
4090 SPutSBuf(reg, pool, (Data *)node,sizeof(CmLList));
4095 } /* end of rgSCHUtlFreeWarningSiSeg */
4100 * Fun: rgSCHUtlFreeWarningSiPdu
4102 * Desc: This is used to deallocate Warning SI PDU.
4110 Void rgSCHUtlFreeWarningSiPdu(RgSchCellCb *cell)
4114 RgSchWarningSiInfo *warningSi;
4115 RgSchWarningSiPdu *warningSiPdu;
4117 warningSi = (RgSchWarningSiInfo *) cell->siCb.\
4118 siArray[cell->siCb.siCtx.siId-1].si;
4119 /* ccpu00136659: CMAS ETWS design changes */
4120 CM_LLIST_FIRST_NODE(&warningSi->warningSiMsg.segLstCp, node);
4126 warningSiPdu = (RgSchWarningSiPdu *)node->node;
4127 pdu = warningSiPdu->pdu;
4128 /* ccpu00136659: CMAS ETWS design changes */
4129 cmLListDelFrm(&warningSi->warningSiMsg.segLstCp, node);
4130 RGSCH_FREE_MSG(pdu);
4131 if(warningSi->warningSiMsg.segLstCp.count == 0)
4133 /* ccpu00136659: CMAS ETWS design changes */
4134 cell->siCb.siArray[cell->siCb.siCtx.siId-1].si = NULLP;
4135 rgSCHUtlRgrWarningSiCfgCfm(cell->instIdx,
4136 rgSchCb[cell->instIdx].rgrSap->sapCfg.spId,
4137 cell->siCb.warningSi[warningSi->idx].siId,
4138 warningSi->warningSiMsg.transId, RGR_CFG_CFM_TX_COMPLETE);
4143 } /* end of rgSCHUtlFreeWarningSiPdu */
4148 * Fun: rgSCHUtlGetWarningSiPdu
4150 * Desc: This is used to get Warning SI PDU for Scheduling.
4158 Buffer *rgSCHUtlGetWarningSiPdu(RgSchCellCb *cell)
4160 RgSchWarningSiInfo *warningSi;
4161 RgSchWarningSiPdu *warningSiPdu;
4165 warningSi = (RgSchWarningSiInfo *) cell->siCb.
4166 siArray[cell->siCb.siCtx.siId-1].si;
4167 /* ccpu00136659: CMAS ETWS design changes */
4168 CM_LLIST_FIRST_NODE(&warningSi->warningSiMsg.segLstCp, node);
4171 warningSiPdu = (RgSchWarningSiPdu *)node->node;
4172 pdu = warningSiPdu->pdu;
4179 } /* rgSCHUtlGetWarningSiPdu */
4184 * Fun: rgSCHUtlGetMcsAndNPrb
4186 * Desc: This is used to get mcs and nPrb value.
4194 S16 rgSCHUtlGetMcsAndNPrb(RgSchCellCb *cell,uint8_t *nPrb,uint8_t *mcs,MsgLen *msgLen)
4196 RgSchWarningSiInfo *warningSi;
4197 RgSchWarningSiPdu *warningSiPdu;
4200 if(cell->siCb.siCtx.warningSiFlag == FALSE)
4202 *mcs = cell->siCb.crntSiInfo.siInfo[cell->siCb.siCtx.siId-1].mcs;
4203 *nPrb = cell->siCb.crntSiInfo.siInfo[cell->siCb.siCtx.siId-1].nPrb;
4204 *msgLen = cell->siCb.crntSiInfo.siInfo[cell->siCb.siCtx.siId-1].msgLen;
4208 warningSi = (RgSchWarningSiInfo *) cell->siCb.
4209 siArray[cell->siCb.siCtx.siId-1].si;
4210 /* ccpu00136659: CMAS ETWS design changes */
4211 CM_LLIST_FIRST_NODE(&warningSi->warningSiMsg.segLstCp, node);
4217 warningSiPdu = (RgSchWarningSiPdu *)node->node;
4218 *mcs = warningSiPdu->mcs;
4219 *nPrb = warningSiPdu->nPrb;
4220 *msgLen = warningSiPdu->msgLen;
4225 } /* rgSCHUtlGetMcsAndNPrb */
4229 * Fun: rgSCHUtlCalMacAndPrb
4231 * Desc: This is used to Calculate mcs and nPrb value for SIB1 and SIs.
4239 S16 rgSCHUtlCalMcsAndNPrb(RgSchCellCb *cell,uint8_t cfgType,MsgLen msgLen,uint8_t siId)
4244 /*Get the nPrb and mcs parametr values */
4245 if (rgSCHUtlGetAllwdCchTbSz(msgLen*8, &nPrb, &mcs) != (msgLen*8))
4247 DU_LOG("\nERROR --> SCH : msgLen does "
4248 "not match any valid TB Size");
4253 if(cfgType == RGR_SI_CFG_TYPE_SIB1 || cfgType == RGR_SI_CFG_TYPE_SIB1_PWS)
4256 if(cell->siCb.crntSiInfo.sib1Info.sib1 == NULLP)
4258 cell->siCb.crntSiInfo.sib1Info.mcs = mcs;
4259 cell->siCb.crntSiInfo.sib1Info.nPrb = nPrb;
4260 cell->siCb.crntSiInfo.sib1Info.msgLen = msgLen;
4264 cell->siCb.newSiInfo.sib1Info.mcs = mcs;
4265 cell->siCb.newSiInfo.sib1Info.nPrb= nPrb;
4266 cell->siCb.newSiInfo.sib1Info.msgLen = msgLen;
4271 if(cfgType == RGR_SI_CFG_TYPE_SI)
4273 if(cell->siCb.crntSiInfo.siInfo[siId-1].si == NULLP &&
4274 !(cell->siCb.siBitMask & RGSCH_SI_SICFG_UPD))
4276 cell->siCb.crntSiInfo.siInfo[siId-1].mcs = mcs;
4277 cell->siCb.crntSiInfo.siInfo[siId-1].nPrb = nPrb;
4278 cell->siCb.crntSiInfo.siInfo[siId-1].msgLen = msgLen;
4282 cell->siCb.newSiInfo.siInfo[siId-1].mcs = mcs;
4283 cell->siCb.newSiInfo.siInfo[siId-1].nPrb= nPrb;
4284 cell->siCb.newSiInfo.siInfo[siId-1].msgLen = msgLen;
4288 if(cfgType == RGR_SI_CFG_TYPE_SIB8_CDMA)
4290 cell->siCb.crntSiInfo.siInfo[siId-1].mcs = mcs;
4291 cell->siCb.crntSiInfo.siInfo[siId-1].nPrb = nPrb;
4292 cell->siCb.crntSiInfo.siInfo[siId-1].msgLen = msgLen;
4299 /***********************************************************
4301 * Func : rgSCHUtlFillDgnParams
4303 * Desc : Utility Function to Fill Diagonostic params.
4311 **********************************************************/
4312 Void rgSCHUtlFillDgnParams(Inst inst,RgUstaDgn *dgn,uint8_t dgnType)
4317 case LRG_USTA_DGNVAL_MEM:
4318 dgn->type = (uint8_t) LRG_USTA_DGNVAL_MEM;
4319 dgn->u.mem.region = rgSchCb[inst].rgSchInit.region;
4320 dgn->u.mem.pool = rgSchCb[inst].rgSchInit.pool;
4328 } /* end of rgSCHUtlFillDgnParams */
4330 /***********************************************************
4332 * Func : rgSCHUtlGetPstToLyr
4334 * Desc : Utility Function to get the pst structure to post a message to MAC
4340 * Notes: This function should be called while sending a msg from
4341 * scheduler instance to MAC
4345 **********************************************************/
4346 Void rgSCHUtlGetPstToLyr(Pst *pst,RgSchCb *schCb,Inst macInst)
4349 /* Only the needed params are filled */
4350 pst->region = schCb->rgSchInit.region;
4351 pst->pool = schCb->rgSchInit.pool;
4352 pst->srcInst = schCb->rgSchInit.inst+SCH_INST_START;
4353 pst->srcProcId = schCb->rgSchInit.procId;
4354 pst->dstProcId = schCb->rgSchInit.procId;
4356 pst->dstInst = macInst;
4357 pst->dstEnt = ENTMAC;
4358 pst->srcEnt = ENTMAC;
4360 pst->prior = PRIOR0;
4362 pst->route = RTESPEC;
4365 } /* end of rgSCHUtlGetPstToLyr */
4367 /** @brief This function fills in the common lc information to be sent to MAC
4371 * Function: rgSCHUtlFillRgInfCmnLcInfo
4372 * @param RgSchDlSf *sf,
4373 * @param RgInfSfAlloc *sfAlloc,
4374 * @param CmLteLcId lcId,
4375 * @param Bool sendInd
4381 S16 rgSCHUtlFillRgInfCmnLcInfo(RgSchDlSf *sf,RgInfSfAlloc *sfAlloc,CmLteLcId lcId,Bool sendInd)
4384 if((sf->bch.tbSize)&&
4385 !(sfAlloc->cmnLcInfo.bitMask & RGINF_BCH_INFO))
4388 sfAlloc->cmnLcInfo.bchInfo.lcId = lcId;
4390 sfAlloc->cmnLcInfo.bitMask |= RGINF_BCH_INFO;
4392 else if((sf->bcch.pdcch != NULLP)&&
4393 !(sfAlloc->cmnLcInfo.bitMask & RGINF_BCCH_INFO))
4395 sfAlloc->cmnLcInfo.bcchInfo.rnti = RGSCH_SI_RNTI;
4396 rgSCHUtlFillPdschDciInfo(&(sfAlloc->cmnLcInfo.bcchInfo.dciInfo),
4397 &(sf->bcch.pdcch->dci));
4399 sfAlloc->cmnLcInfo.bcchInfo.lcId = lcId;
4400 sfAlloc->cmnLcInfo.bcchInfo.sndStatInd = sendInd;
4402 sfAlloc->cmnLcInfo.bitMask |= RGINF_BCCH_INFO;
4404 else if((sf->pcch.pdcch != NULLP) &&
4405 !(sfAlloc->cmnLcInfo.bitMask & RGINF_PCCH_INFO))
4407 sfAlloc->cmnLcInfo.pcchInfo.rnti = RGSCH_P_RNTI;
4408 rgSCHUtlFillPdschDciInfo(&(sfAlloc->cmnLcInfo.pcchInfo.dciInfo),
4409 &(sf->pcch.pdcch->dci));
4410 sfAlloc->cmnLcInfo.pcchInfo.lcId = lcId;
4411 sfAlloc->cmnLcInfo.bitMask |= RGINF_PCCH_INFO;
4416 /** @brief This function fills in the RAR information to be sent to MAC
4420 * Function: rgSCHUtlFillRgInfRarInfo
4422 * @param RgSchCellCb *cell
4423 * @param RgSchDlSf *sf
4424 * @param RgInfSfAlloc *sfAlloc
4429 S16 rgSCHUtlFillRgInfRarInfo(RgSchDlSf *sf,RgInfSfAlloc *sfAlloc,RgSchCellCb *cell)
4436 RgInfRaRntiInfo *raRntiAlloc;
4438 RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell);
4441 noRaRsps = RGSCH_MAX_TDD_RA_RSP_ALLOC;
4443 noRaRsps = RGSCH_MAX_RA_RSP_ALLOC;
4446 for(idx =0; idx < noRaRsps; idx++)
4448 if (sf->raRsp[idx].pdcch == NULLP)
4450 /* No further raResp Allocations. */
4453 /* Added Dl TB count for RACH Response transmission*/
4455 cell->dlUlTbCnt.tbTransDlTotalCnt++;
4457 raRntiAlloc = &(sfAlloc->rarInfo.raRntiInfo[idx]);
4458 raRntiAlloc->raRnti = sf->raRsp[idx].raRnti;
4459 raRntiAlloc->schdTbSz = sf->raRsp[idx].tbSz;
4460 raRntiAlloc->numCrnti = 0;
4461 rgSCHUtlFillPdschDciInfo(&(raRntiAlloc->dciInfo),
4462 &(sf->raRsp[idx].pdcch->dci));
4463 /* RACHO : fill backoff indicator information */
4464 raRntiAlloc->backOffInd = sf->raRsp[idx].backOffInd;
4466 /* Fill for contention free UEs*/
4467 lnkLst = &(sf->raRsp[idx].contFreeUeLst);
4468 CM_LLIST_FIRST_NODE(lnkLst, tmp);
4471 ue = (RgSchUeCb *)tmp->node;
4473 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].tmpCrnti = ue->ueId;
4474 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].isContFree = TRUE;
4475 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].rapId = ue->ul.rarGrnt.rapId;
4476 #ifndef MAC_5GTF_UPDATE
4477 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.hop =
4479 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.cqiBit =
4480 ue->ul.rarGrnt.cqiReqBit;
4482 /* SHASHAHNK ADD RIV CALC */
4483 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.rbStart =
4484 ue->ul.rarGrnt.rbStart;
4485 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.numRb =
4486 ue->ul.rarGrnt.numRb;
4487 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.tpc =
4489 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.iMcsCrnt =
4490 ue->ul.rarGrnt.iMcsCrnt;
4491 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].ta = ue->ul.rarGrnt.ta;
4492 raRntiAlloc->numCrnti++;
4493 cmLListDelFrm(lnkLst, &ue->ul.rarGrnt.raRspLnk);
4494 ue->ul.rarGrnt.raRspLnk.node = (PTR)NULLP;
4496 /* Fill for contention based UEs*/
4497 lnkLst = &(sf->raRsp[idx].raRspLst);
4499 CM_LLIST_FIRST_NODE(lnkLst, tmp);
4501 while((NULLP != tmp) && ((RgSchRaCb *)tmp->node != NULLP))
4503 raCb = (RgSchRaCb *)tmp->node;
4505 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].tmpCrnti = raCb->tmpCrnti;
4506 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].isContFree = FALSE;
4507 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].rapId = raCb->rapId;
4508 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].ta.pres = TRUE;
4509 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].ta.val = raCb->ta.val;
4510 #ifndef MAC_5GTF_UPDATE
4511 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.hop =
4513 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.cqiBit = FALSE;
4515 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.rbStart =
4516 raCb->msg3Grnt.rbStart;
4517 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.numRb =
4518 raCb->msg3Grnt.numRb;
4519 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.tpc =
4521 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.iMcsCrnt =
4522 raCb->msg3Grnt.iMcsCrnt;
4523 raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.delayBit =
4524 raCb->msg3Grnt.delayBit;
4525 /* For initial attaching UEs Aperiodic CQI need not be triggered */
4526 raRntiAlloc->numCrnti++;
4527 /* Search the next node */
4528 CM_LLIST_NEXT_NODE(lnkLst, tmp);
4531 sfAlloc->rarInfo.numRaRntis = idx;
4532 /* ccpu00132314-ADD-Update the tx power allocation info
4533 TODO-Need to add a check for max tx power per symbol */
4534 sfAlloc->rarInfo.txPwrOffset = cellDl->rarTxPwrOffset;
4537 } /* end of rgSCHUtlFillRgInfRarInfo */
4539 /** @brief This function fills in the pdsch data related allocation Info
4540 * from the pdcch DCI info.
4545 * Function: rgSCHUtlFillPdschDciInfo
4548 * - Depending upon the DCI Format, fill the appropriate fields.
4550 * @param [out] TfuPdschDciInfo *pdschDci
4551 * @param [in] TfuDciInfo *pdcchDci
4556 S16 rgSCHUtlFillPdschDciInfo(TfuPdschDciInfo *pdsch,TfuDciInfo *pdcchDci)
4562 pdsch->format = pdcchDci->dciFormat;
4563 switch(pdcchDci->dciFormat)
4565 case TFU_DCI_FORMAT_1:
4566 pdsch->u.format1AllocInfo = pdcchDci->u.format1Info.allocInfo;
4568 case TFU_DCI_FORMAT_1A:
4569 if (pdcchDci->u.format1aInfo.isPdcchOrder == FALSE)
4571 pdsch->u.format1aAllocInfo = pdcchDci->u.format1aInfo.t.pdschInfo.allocInfo;
4574 case TFU_DCI_FORMAT_1B:
4575 pdsch->u.format1bAllocInfo = pdcchDci->u.format1bInfo.allocInfo;
4577 case TFU_DCI_FORMAT_1C:
4578 pdsch->u.format1cAllocInfo = pdcchDci->u.format1cInfo;
4580 case TFU_DCI_FORMAT_1D:
4581 pdsch->u.format1dAllocInfo = pdcchDci->u.format1dInfo.allocInfo;
4583 case TFU_DCI_FORMAT_2:
4584 pdsch->u.format2AllocInfo = pdcchDci->u.format2Info.allocInfo;
4586 case TFU_DCI_FORMAT_2A:
4587 pdsch->u.format2AAllocInfo = pdcchDci->u.format2AInfo.allocInfo;
4590 case TFU_DCI_FORMAT_B1:
4591 pdsch->u.formatB1Info = pdcchDci->u.formatB1Info;
4593 case TFU_DCI_FORMAT_B2:
4594 pdsch->u.formatB2Info = pdcchDci->u.formatB2Info;
4599 ret = rgSCHEmtcUtlFillPdschDciInfo(pdsch, pdcchDci);
4611 /* LTE_ADV_FLAG_REMOVED_START */
4613 * @brief This function resets temporary variables in Pool
4616 * Function: rgSchSFRResetPoolVariables
4618 * Invoked by: rgSCHSFRUtlTotalPoolInit
4620 * @param[in] RgSchCellCb* cell
4621 * @param[in] RgSubFrm* subFrm
4625 Void rgSchDSFRPwrCheck(RgSchDlSf *sf,Bool *isAllUePwrHigh)
4627 RgSchSFRPoolInfo *sfrCCPool;
4632 l = &sf->sfrTotalPoolInfo.ccPool;
4633 n = cmLListFirst(l);
4636 sfrCCPool = (RgSchSFRPoolInfo*)n->node;
4637 if((sfrCCPool->poolstartRB == sfrCCPool->pwrHiCCRange.startRb) &&
4638 (sfrCCPool->poolendRB == sfrCCPool->pwrHiCCRange.endRb))
4645 *isAllUePwrHigh = TRUE;
4652 /* LTE_ADV_FLAG_REMOVED_END */
4653 /***********************************************************
4655 * Func : rgSCHUtlFillRgInfTbInfo
4657 * Desc : Utility Function to fill the allocation info of each Tb
4663 * Notes: This function should be called while sending a msg from
4664 * scheduler instance to MAC
4668 **********************************************************/
4669 static Void rgSCHUtlFillRgInfTbInfo(RgSchDlHqProcCb *hqP,RgInfUeAlloc *allocInfo,RgSchCellCb *cell)
4673 RgInfUeTbInfo *tbInfo;
4675 /* LTE_ADV_FLAG_REMOVED_START */
4677 static uint32_t tmpCnt = 0;
4678 Bool isAllUePwrHigh = FALSE;
4680 /* LTE_ADV_FLAG_REMOVED_END */
4681 RgSchDlLcCb *dlLcCb = NULLP;
4682 uint16_t rlcHdrEstmt;
4686 uint8_t prbUsed = 0;
4690 CmLteTimingInfo frm;
4692 /* Get Downlink slot */
4693 frm = cell->crntTime;
4694 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
4695 sf = rgSCHUtlSubFrmGet(cell, frm);
4696 /* Setting of fillCtrlPdu flag
4697 If both P-cell and S-cell are present,
4698 make TRUE for P-cell and FALSE for all s-cells
4699 For all other cases set TRUE */
4701 if ((rgSchCb[cell->instIdx].genCfg.forceCntrlSrbBoOnPCel) &&
4702 !RG_SCH_CMN_IS_PCELL_HQP(hqP))
4704 allocInfo->fillCtrlPdu = FALSE;
4708 allocInfo->fillCtrlPdu = TRUE;
4712 allocInfo->tbStrtIdx = -1;
4716 allocInfo->tbReqInfo.sCellHqPId = 0xff;
4717 rgSCHLaaHndlFillRgInfTbInfo(cell, hqP, allocInfo);
4720 /*TODO:REEMA: Check and fill the isRetx */
4721 for(tbCnt = 0; tbCnt < 2; tbCnt++)
4723 RgSchUeCb *ue = NULLP;
4724 /*Changed as a result of CR timer*/
4725 if ((hqP->hqE->ue != NULLP)/* &&
4726 ((hqP->tbInfo[tbCnt].lchSchdData[0].lcId != 0) || \
4727 (hqP->tbInfo[tbCnt].schdTa.pres == PRSNT_NODEF))*/)
4730 allocInfo->rnti = ue->ueId;
4731 allocInfo->doa = hqP->hqE->ue->mimoInfo.doa;
4732 allocInfo->txMode = (TfuTxMode)(hqP->hqE->ue->mimoInfo.txMode);
4733 allocInfo->puschRptUsd = hqP->hqE->ue->mimoInfo.puschFdbkVld;
4734 allocInfo->puschPmiInfo = hqP->hqE->ue->mimoInfo.puschPmiInfo;
4735 if(hqP->tbInfo[tbCnt].schdTa.pres == PRSNT_NODEF)
4737 hqP->tbInfo[tbCnt].taSnt = TRUE;
4740 if (RG_SCH_IS_PAPRSNT(ue,hqP->hqE->cell))
4742 /*update pA value */
4743 allocInfo->pa = (RG_SCH_CMN_GET_PA(ue,hqP->hqE->cell)).val;
4747 /* LTE_ADV_FLAG_REMOVED_START */
4748 /* If ABS is enabled, calculate resource used */
4749 if((0 == tbCnt) && (RGR_ENABLE == ue->cell->lteAdvCb.absCfg.status))
4751 /* For Macro count number resource used in Non-ABS SF */
4752 if(RGR_ABS_MUTE == ue->cell->lteAdvCb.absCfg.absPatternType)
4754 if(RG_SCH_ABS_ENABLED_NONABS_SF == ue->cell->lteAdvCb.absDlSfInfo)
4756 ue->cell->lteAdvCb.absLoadInfo[ue->cell->lteAdvCb.absPatternDlIdx]+=
4757 hqP->tbInfo[tbCnt].dlGrnt.numRb;
4760 /* For pico count number resource used in ABS SF for ABS UE */
4761 else if(RGR_ABS_TRANSMIT == ue->cell->lteAdvCb.absCfg.absPatternType)
4763 if(RG_SCH_ABS_ENABLED_ABS_SF == ue->cell->lteAdvCb.absDlSfInfo)
4765 if(TRUE == ue->lteAdvUeCb.rgrLteAdvUeCfg.isAbsUe)
4767 ue->cell->lteAdvCb.absLoadInfo[ue->cell->lteAdvCb.absPatternDlIdx]+=
4768 hqP->tbInfo[tbCnt].dlGrnt.numRb;
4775 /*if SFR is enabled*/
4776 allocInfo->isEnbSFR = (uint8_t)RG_SCH_CMN_IS_SFR_ENB(ue->cell); /* KW fix for LTE_ADV */
4777 if((ue->cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE) &&
4778 (ue->lteAdvUeCb.rgrLteAdvUeCfg.isUeCellEdge == FALSE))
4780 rgSchDSFRPwrCheck(sf, &isAllUePwrHigh);
4784 allocInfo->pa = (uint8_t)ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh; /* KW fix for LTE_ADV */
4785 if(tmpCnt++ == 100000)
4787 DU_LOG("\nDEBUG --> SCH : DSFR::ll UEs can go HIGH, PHigh(%d) for UE(%d)",allocInfo->pa, ue->ueId);
4793 if (allocInfo->isEnbSFR)
4795 /*Update pA to Plow if it is cell-centred ,else pA will be pHigh*/
4796 if (ue->lteAdvUeCb.rgrLteAdvUeCfg.isUeCellEdge == TRUE)
4798 allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;
4799 if(tmpCnt++ == 100000)
4801 DU_LOG("\nDEBUG --> SCH : SFR::UE is CELL EDGE, PHigh(%d) for UE(%d)",allocInfo->pa, ue->ueId);
4808 if(TRUE == ue->lteAdvUeCb.isCCUePHigh)
4810 allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;
4811 ue->lteAdvUeCb.isCCUePHigh = FALSE;
4815 allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pLow;
4816 if(tmpCnt++ == 100000)
4818 DU_LOG("\nDEBUG --> SCH : SFR::UE is CELL CENTRE, PLow(%d) for UE(%d)\n",allocInfo->pa, ue->ueId);
4825 /* LTE_ADV_FLAG_REMOVED_END */
4833 RgSchCmnDlCell *cellDl = RG_SCH_CMN_GET_DL_CELL(cell);
4836 allocInfo->pdcchRnti = hqP->hqE->raCb->tmpCrnti;
4838 allocInfo->rnti = hqP->hqE->raCb->tmpCrnti;
4840 /*ccpu00132314-ADD-Use a default pA value
4842 allocInfo->pa = cellDl->msg4pAVal;
4846 /* If TB Is scheduled for this SF */
4847 if(hqP->tbInfo[tbCnt].state == HQ_TB_WAITING)
4849 if (allocInfo->tbStrtIdx == -1){
4850 allocInfo->tbStrtIdx = tbCnt;
4852 rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4853 &(hqP->pdcch->dci));
4857 rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4858 &(hqP->pdcch->dci));
4860 else if ((ue) && (ue->dl.spsOccPdcch.rnti == ue->spsRnti))
4862 rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4863 &(ue->dl.spsOccPdcch.dci));
4865 #endif /* ifndef LTEMAC_SPS */
4870 allocInfo->pdcchRnti = hqP->pdcch->rnti;
4874 allocInfo->pdcchRnti = ue->spsRnti;
4877 tbInfo = &(allocInfo->tbInfo[tbCnt]);
4878 allocInfo->nmbOfTBs++;
4879 allocInfo->hqProcId = hqP->procId;
4880 allocInfo->tbInfo[tbCnt].schdTbSz = hqP->tbInfo[tbCnt].tbSz;
4882 tbInfo->disTb = FALSE;
4883 if(!(hqP->tbInfo[tbCnt].txCntr))
4886 if(!((rgSCHLaaCheckIfLAAProc(hqP)) && (TRUE ==
4887 rgSCHLaaSCellEnabled(cell))))
4890 hqP->tbInfo[tbCnt].txCntr++;
4892 for(idx = 0; idx < hqP->tbInfo[tbCnt].numLch; idx++)
4894 tbInfo->schdDat[idx].lcId =\
4895 hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
4896 tbInfo->schdDat[idx].numBytes =\
4897 hqP->tbInfo[tbCnt].lchSchdData[idx].schdData;
4900 lcId = hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
4903 dlLcCb = hqP->hqE->ue->dl.lcCb[lcId-1];
4906 RG_SCH_CMN_DL_GET_HDR_EST(dlLcCb, rlcHdrEstmt);
4907 /* Update the totalBo with the scheduled bo */
4908 (hqP->hqE->ue->totalBo <= tbInfo->schdDat[idx].numBytes - rlcHdrEstmt)?\
4909 (hqP->hqE->ue->totalBo = 0):\
4910 (hqP->hqE->ue->totalBo -= tbInfo->schdDat[idx].numBytes-rlcHdrEstmt);
4914 prbUsed = ((hqP->tbInfo[tbCnt].\
4915 lchSchdData[idx].schdData *
4916 hqP->tbInfo[tbCnt].dlGrnt.numRb) /
4917 (hqP->tbInfo[0].tbSz + hqP->tbInfo[1].tbSz));
4918 dlLcCb->qciCb->dlPrbCount += prbUsed;
4919 if(dlLcCb->qciCb->qci > 0)
4921 RG_SCH_CALC_GBR_UTILIZATION(cell, dlLcCb, prbUsed);
4923 #endif /* RRM_RBC_Y */
4926 //if(!(hqP->hqE->ue->pfsStats.lcStats[lcId-1].isLcCntSet))
4930 if (hqP->hqE->ue->cell == hqP->hqE->cell)
4932 idx = RGSCH_PCELL_INDEX;
4936 idx = RG_SCH_GET_SCELL_INDEX((hqP->hqE->ue), (hqP->hqE->cell));
4938 hqP->hqE->ue->pfsStats.lcStats[lcId-1].ueSchdOcc[idx]++;
4939 hqP->hqE->ue->pfsStats.lcStats[lcId-1].perRefresh[ue->pfsStats.lcStats[lcId-1].lastIdx].lcSchdOcc++;
4946 /* Added Dl TB count for SRB/DRB data transmission*/
4948 cell->dlUlTbCnt.tbTransDlTotalCnt++;
4950 tbInfo->ta.pres = hqP->tbInfo[tbCnt].schdTa.pres;
4951 tbInfo->ta.val = hqP->tbInfo[tbCnt].schdTa.val;
4953 tbInfo->sCellActCe = hqP->tbInfo[tbCnt].schdSCellActCe;
4955 tbInfo->numSchLch = hqP->tbInfo[tbCnt].numLch;
4956 if(!(hqP->tbInfo[tbCnt].numLch))
4958 tbInfo->schdDat[tbInfo->numSchLch].numBytes= hqP->tbInfo[tbCnt].tbSz;
4959 /* Fix: If only TA is scheduled, use some dummy LCID */
4960 if (tbInfo->ta.pres)
4961 tbInfo->schdDat[tbInfo->numSchLch].lcId = RG_TA_LCID;
4964 tbInfo->contResCe = hqP->tbInfo[tbCnt].contResCe;
4965 tbInfo->isReTx = FALSE;
4970 if(!((rgSCHLaaCheckIfLAAProc(hqP)) && (TRUE ==
4971 rgSCHLaaSCellEnabled(cell))))
4974 hqP->tbInfo[tbCnt].txCntr++;
4976 tbInfo->isReTx = TRUE;
4978 /* As per 36.314, harq retransmission also considered for
4979 * prb utilization calculation*/
4980 for(idx = 0; idx < hqP->tbInfo[tbCnt].numLch; idx++)
4985 lcId = hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
4988 dlLcCb = hqP->hqE->ue->dl.lcCb[lcId-1];
4991 prbUsed = ((hqP->tbInfo[tbCnt].\
4992 lchSchdData[idx].schdData *
4993 hqP->tbInfo[tbCnt].dlGrnt.numRb) /
4994 (hqP->tbInfo[0].tbSz + hqP->tbInfo[1].tbSz));
4995 if(dlLcCb->qciCb->qci > 0)
4997 RG_SCH_CALC_GBR_UTILIZATION(cell, dlLcCb, prbUsed);
5009 rgSCHLaaResetDlHqProcCb(hqP);
5014 /***********************************************************
5016 * Func : rgSCHUtlFillRgInfUeInfo
5018 * Desc : Utility Function to fill the allocation info of Ue
5019 * : MIMO : Filling 2TB's of each UE
5024 * Notes: This function should be called while sending a msg from
5025 * scheduler instance to MAC
5029 **********************************************************/
5031 Void rgSCHUtlFillRgInfUeInfo(RgSchDlSf *sf,RgSchCellCb *cell,CmLListCp *dlDrxInactvTmrLst,CmLListCp *dlInActvLst,CmLListCp *ulInActvLst)
5033 RgInfSfAlloc *sfAlloc;
5034 CmLListCp *lnkLst; /* lnkLst assignment */
5037 RgSchUeCb *ue = NULLP;
5038 RgInfUeInfo *ueInfo = NULLP;
5039 RgInfUeAlloc *ueAlloc = NULLP;
5040 RgSchDlHqProcCb *hqCb = NULLP;
5042 /* Since Msg4 is sched only on PCELL, use cell arg's sfAllocArr */
5043 sfAlloc = &(cell->sfAllocArr[cell->crntSfIdx]);
5044 ueInfo = &(sfAlloc->ueInfo);
5045 ueAlloc = sfAlloc->ueInfo.allocInfo;
5047 lnkLst = &(sf->msg4HqPLst);
5048 CM_LLIST_FIRST_NODE(lnkLst, tmp);
5051 DU_LOG("\nINFO --> SCH : 5GTF_ERROR MSG4 Consolidation\n");
5052 hqCb = (RgSchDlHqProcCb *)(tmp->node);
5053 CM_LLIST_NEXT_NODE(lnkLst, tmp);
5055 rgSCHUtlFillRgInfTbInfo(hqCb, &ueAlloc[ueInfo->numUes], cell);
5061 if((!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE)) && (ue->isDrxEnabled))
5063 rgSCHUtlGetDrxSchdUesInDl(cell, ue, hqCb, &ueAlloc[ueInfo->numUes],
5064 dlDrxInactvTmrLst, dlInActvLst, ulInActvLst);
5070 lnkLst = &(sf->ueLst);
5071 CM_LLIST_FIRST_NODE(lnkLst, tmp);
5074 #if defined (TENB_STATS) && defined (RG_5GTF)
5075 cell->tenbStats->sch.dl5gtfPdschCons++;
5077 ue = (RgSchUeCb *)(tmp->node);
5078 CM_LLIST_NEXT_NODE(lnkLst, tmp);
5080 hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
5083 hqCb = (RgSchDlHqProcCb *)hqPNode->node;
5084 hqPNode = hqPNode->next;
5086 sfAlloc = &(hqCb->hqE->cell->sfAllocArr[hqCb->hqE->cell->crntSfIdx]);
5087 ueInfo = &(sfAlloc->ueInfo);
5088 ueAlloc = sfAlloc->ueInfo.allocInfo;
5090 rgSCHUtlFillRgInfTbInfo(hqCb, &ueAlloc[ueInfo->numUes],
5093 if(ue->isDrxEnabled)
5095 rgSCHUtlGetDrxSchdUesInDl(cell, ue, hqCb, &ueAlloc[ueInfo->numUes],
5096 dlDrxInactvTmrLst, dlInActvLst, ulInActvLst);
5101 if (rgSchCb[cell->instIdx].genCfg.isSCellActDeactAlgoEnable == TRUE)
5103 /*If remaining BO is left then increment the count*/
5107 /* Check if trigger for Activation is met or not */
5108 if(rgSCHIsActvReqd(cell, ue))
5111 /*Passing primary cell*/
5112 rgSCHSCellSelectAndActDeAct(ue->cell, ue, RGR_SCELL_ACT);
5117 /*If remaining BO is 0 then reset the count*/
5125 } /* end of rgSCHUtlFillRgInfUeInfo */
5129 /** @brief This function shall update the scheduler with the CEs and data rcvd
5133 * Function: rgSCHUtlUpdSch
5136 * - Collate the information of all the SDUs received and inform the
5137 * scheduler rgSCHDataRcvd
5138 * - Send Data indication to the higher layer with the dedicated data
5139 * (rgUIMSndDedDatInd)
5140 * - Inform scheduler with any MAC CEs if present.
5142 * @param [in] RgCellCb *cellCb
5143 * @param [in] RgUeCb *ueCb
5144 * @param [in] RgMacPdu *pdu
5145 * @param [in] RgSchErrInfo *err
5150 S16 rgSCHUtlUpdSch(RgInfSfDatInd *subfrmInfo,RgSchCellCb *cellCb,RgSchUeCb *ueCb,RgInfUeDatInd *pdu,RgSchErrInfo *err)
5155 if (RGSCH_UL_SPS_ACT_PRSENT & pdu->ceInfo.bitMask)
5157 /* SPS to be activated due to data on SPS LCG ID*/
5158 rgSCHUtlSpsActInd(cellCb, ueCb, pdu->ceInfo.spsSduSize);
5161 /* TODO : Temp Fix for crash due to UL SDU corruption*/
5162 if (RGSCH_PHR_CE_PRSNT & pdu->ceInfo.bitMask)
5165 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5166 if ((ret = rgSCHUtlUpdPhr(cellCb, ueCb, pdu->ceInfo.ces.phr, err)) != ROK)
5169 /* Note: Order of indication to Sch now is
5170 * 1st Indicate the DataInd info for each LCG's
5171 * 2nd Update the BSR reports received along with data
5172 * this is to make sure the effBsr is updated to the latest BSR
5175 cellCb->sc.apis->rgSCHUpdUeDataIndLcg(cellCb, ueCb, pdu);
5177 #ifndef MAC_5GTF_UPDATE
5178 if (RGSCH_TRUNC_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5180 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5181 /*ccpu00129922 - MOD - Deleted return value
5182 * checking since it returns void*/
5183 rgSCHUtlUpdBsrTrunc (cellCb, ueCb,
5184 (uint8_t)(pdu->ceInfo.ces.bsr.truncBsr >> 6),
5185 (uint8_t)(pdu->ceInfo.ces.bsr.truncBsr & 0x3F), err);
5189 if (RGSCH_SHORT_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5191 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5192 /*ccpu00129922 - MOD - Deleted return value
5193 checking since it returns void*/
5194 rgSCHUtlUpdBsrShort (cellCb, ueCb,
5195 (uint8_t)(pdu->ceInfo.ces.bsr.shortBsr >> 6),
5196 (uint8_t)(pdu->ceInfo.ces.bsr.shortBsr & 0x3F), err);
5200 if (RGSCH_LONG_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5202 if (RGSCH_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5205 RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5206 /*ccpu00129922 - MOD - Deleted return value
5207 checking since it returns void*/
5208 rgSCHUtlUpdBsrLong (cellCb, ueCb,
5209 pdu->ceInfo.ces.bsr.longBsr.bs1,
5210 pdu->ceInfo.ces.bsr.longBsr.bs2,
5211 pdu->ceInfo.ces.bsr.longBsr.bs3,
5212 pdu->ceInfo.ces.bsr.longBsr.bs4,
5215 #ifndef MAC_5GTF_UPDATE
5222 } /* end of rgSCHUtlUpdSch */
5225 * @brief Handler for Updating Bo received in StaRsp
5229 * Function : rgSCHUtlAddUeToCcchSduLst
5231 * This function shall be invoked once it receives staRsp on CCCH
5233 * @param[in] RgSchCellCb *cell
5234 * @param[in] RgSchUeCb *ueCb
5238 S16 rgSCHUtlAddUeToCcchSduLst(RgSchCellCb *cell,RgSchUeCb *ueCb)
5240 RgSchCmnDlUe *ueDl = RG_SCH_CMN_GET_DL_UE(ueCb, cell);
5241 RgSchDlHqProcCb *hqP = (RgSchDlHqProcCb *)ueDl->proc;
5243 /* Temp Guard: For back to back CCCH SDU BO
5244 * twice. Hence an extra guard. If already added to scheduling
5245 * queue or if scheduled and waiting for HQ FDBK, ignore */
5246 if ((ueCb->ccchSduLnk.node) ||
5247 ((!(ueCb->dl.dlInactvMask & RG_HQENT_INACTIVE)) &&
5248 ((hqP != NULLP) && (hqP->hqE->ccchSduProc))))
5250 DU_LOG("\nINFO --> SCH : RNTI:%d Unexpected CCCH SDU BO",
5255 ueCb->ccchSduLnk.node = (PTR)(ueCb);
5256 cmLListAdd2Tail(&(cell->ccchSduUeLst), &(ueCb->ccchSduLnk));
5264 * Function : rgSCHUtlUpdtBo
5266 * This function shall be invoked once it receives staRsp on CCCH
5268 * @param[in] RgSchCellCb *cell
5269 * @param[in] RgRguCmnStaRsp *staRsp
5273 S16 rgSCHUtlUpdtBo(RgSchCellCb *cell,RgInfCmnBoRpt *staRsp)
5277 if ((ueCb = rgSCHDbmGetUeCb(cell, staRsp->u.rnti)) == NULLP)
5279 /* Handle Ue fetch failure */
5280 DU_LOG("\nERROR --> SCH : Invalid UEID:%d",staRsp->u.rnti);
5283 /* Update Bo in ueCb */
5284 ueCb->dlCcchInfo.bo = (uint32_t)(staRsp->bo);
5288 rgSCHUtlAddUeToEmtcCcchSduLst(cell,ueCb);
5293 rgSCHUtlAddUeToCcchSduLst(cell, ueCb);
5297 } /* rgSCHUtlUpdtBo */
5303 * Function : rgSCHUtlHndlCcchBoUpdt
5305 * This function shall fetch the raCb with the given rnti and ask RAM to
5309 * @param[in] RgSchCellCb *cell
5310 * @param[in] RgInfCmnBoRpt *boRpt
5315 S16 rgSCHUtlHndlCcchBoUpdt(RgSchCellCb *cell,RgInfCmnBoRpt *boRpt)
5320 if ((raCb = rgSCHDbmGetRaCb(cell, boRpt->u.rnti)) == NULLP)
5323 /* CR timer implementation changes*/
5324 /*If no raCb, schedule ueCb, ueCb is extracted in rgSCHUtlUpdtBo*/
5325 return (rgSCHUtlUpdtBo(cell, boRpt));
5327 /* Handle RaCb fetch failure */
5328 DU_LOG("\nERROR --> SCH : Invalid RNTI:%d to fetch raCb",boRpt->u.rnti);
5335 /*Fix: If RaCb exists, then MSG4 is not completed yet*/
5336 /*Check if guard timer has expired, if not CR CE + CCCH SDU will be scheduled*/
5337 if((raCb->contResTmrLnk.node != NULLP) && \
5338 (raCb->schdLnk.node == NULLP) && (raCb->dlHqE->msg4Proc == NULLP))
5341 /*if contention resolution timer left ,Stop the Contention Resolution Guard Timer ,
5342 add in toBeSchduled list and update the Bo */
5343 if(TRUE == raCb->isEmtcRaCb)
5345 rgSCHRamEmtcUpdtBo(cell, raCb, boRpt);
5350 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
5351 raCb->contResTmrLnk.node=NULLP;
5352 rgSCHRamUpdtBo(cell, raCb, boRpt);
5357 /*Fix:Guard timer has expired */
5358 /*Update the BO in UE CB but dont add it to the scheduling list.
5359 *Should be added to the list after MSG4 completion*/
5360 if ((ueCb = rgSCHDbmGetUeCb(cell, boRpt->u.rnti)) == NULLP)
5362 /* Handle Ue fetch failure */
5363 DU_LOG("\nERROR --> SCH : Invalid RNTI:%d",boRpt->u.rnti);
5366 /* Update Bo in ueCb */
5367 ueCb->dlCcchInfo.bo = (uint32_t)(boRpt->bo);
5371 rgSCHRamUpdtBo(cell, raCb, boRpt);
5375 } /* rgSCHUtlHndlCcchBoUpdt */
5378 * @brief Validates BO received for BCCH or PCCH.
5382 * Function : rgSCHUtlGetAllwdCchTbSz
5384 * This function shall return the tbSz equal to or
5385 * the nearest greater value for a given bo.
5386 * If no such value found return -1. The nPrb value is
5390 * @param[in] uint32_t bo
5391 * @param[out] uint8_t *nPrb
5396 S32 rgSCHUtlGetAllwdCchTbSz(uint32_t bo,uint8_t *nPrb,uint8_t *mcs)
5402 for (lt = 0, rt = 43; lt <= rt;)
5405 if (rgSchUtlBcchPcchTbSzTbl[cn].tbSz == bo)
5407 *nPrb = rgSchUtlBcchPcchTbSzTbl[cn].rbIndex;
5408 *mcs = rgSchUtlBcchPcchTbSzTbl[cn].mcs;
5409 return (rgSchUtlBcchPcchTbSzTbl[cn].tbSz);
5411 else if (rgSchUtlBcchPcchTbSzTbl[cn].tbSz < bo)
5420 *nPrb = rgSchUtlBcchPcchTbSzTbl[lt].rbIndex;
5421 *mcs = rgSchUtlBcchPcchTbSzTbl[lt].mcs;
5422 return (rgSchUtlBcchPcchTbSzTbl[lt].tbSz);
5426 * @brief Handler for BO Updt received for BCCH or PCCH.
5430 * Function : rgSCHUtlHndlBcchPcchBoUpdt
5432 * This function shall store the buffer and time to transmit in lcCb
5435 * @param[in] RgSchCellCb *cell
5436 * @param[in] RgInfCmnBoRpt *boRpt
5441 S16 rgSCHUtlHndlBcchPcchBoUpdt(RgSchCellCb *cell,RgInfCmnBoRpt *boUpdt)
5443 RgSchClcDlLcCb *dlLc;
5444 RgSchClcBoRpt *boRpt;
5445 Inst inst = cell->instIdx;
5449 dlLc = rgSCHDbmGetBcchOnBch(cell);
5452 DU_LOG("\nERROR --> SCH : No Logical Channel dlLc is NULLP for RNTI:%d LCID:%d",boUpdt->u.rnti,boUpdt->lcId);
5455 if (boUpdt->lcId != dlLc->lcId)
5457 /* Added for dropping paging Message*/
5459 if ((rgSCHChkBoUpdate(cell,boUpdt))== ROK) /* Checking if received BO falls within the window of 5120 slots*/
5461 if (rgSCHUtlGetAllwdCchTbSz(boUpdt->bo*8, &nPrb, &mcs)
5464 DU_LOG("\nERROR --> SCH : [%d]BO: does not match any "
5465 "valid TB Size RNTI:%d LCID:%d", boUpdt->bo,boUpdt->u.rnti,boUpdt->lcId);
5468 }/*end of rgSCHChkBoUpdate*/
5474 if ((dlLc = rgSCHDbmGetCmnLcCb(cell, boUpdt->lcId)) == NULLP)
5476 /* Handle lcCb fetch failure */
5477 DU_LOG("\nERROR --> SCH : LCID:%d Invalid for RNTI:%d",boUpdt->lcId,boUpdt->u.rnti);
5480 if (((rgSCHUtlAllocSBuf(inst, (Data **)(&boRpt), sizeof(RgSchClcBoRpt))) ==RFAILED) ||
5483 DU_LOG("\nERROR --> SCH : Allocation of common bo %dreport "
5484 "failed RNTI:%d LCID:%d", boUpdt->bo,boUpdt->u.rnti,boUpdt->lcId);
5488 boRpt->bo = boUpdt->bo;
5490 boRpt->timeToTx = boUpdt->u.timeToTx;
5493 if(cell->emtcEnable)
5495 boRpt->emtcDIReason = boUpdt->emtcDIReason;
5496 boRpt->pnb = boUpdt->pnb;
5499 RG_SCH_ADD_TO_CRNT_TIME(boRpt->timeToTx,
5500 boRpt->maxTimeToTx, cell->siCfg.siWinSize)
5501 if((NULLP != dlLc) && (dlLc->si))
5503 boRpt->retxCnt = cell->siCfg.retxCnt;
5509 rgSCHDbmInsCmnLcBoRpt(dlLc, boRpt);
5512 } /* rgSCHUtlHndlBcchPcchBoUpdt */
5515 * @brief API for sending bind confirm from Scheduler instance to RRM
5519 * Function: rgSCHUtlRgrBndCfm
5521 * This API is invoked to send bind confirm from Scheduler instance to RRM.
5522 * This API fills in Pst structure and SAP Ids and invokes
5523 * bind confirm API towards RRM.
5525 * @param[in] SuId suId
5526 * @param[in] uint8_t status
5531 S16 rgSCHUtlRgrBndCfm(Inst instId,SuId suId,uint8_t status)
5535 ret = RgUiRgrBndCfm(&rgSchCb[instId].rgrSap[suId].sapCfg.sapPst, rgSchCb[instId].rgrSap[suId].sapCfg.suId, status);
5538 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrBndCfm: RgUiRgrBndCfm Failed ");
5542 } /* rgSCHUtlRgrBndCfm*/
5545 * @brief API for sending bind confirm from Scheduler instance to RRM via RGM
5550 * Function: rgSCHUtlRgmBndCfm
5552 * This API is invoked to send bind confirm from Scheduler instance to RRM.
5553 * This API fills in Pst structure and SAP Ids and invokes
5555 * @param[in] SuId suId
5556 * @param[in] uint8_t status
5561 S16 rgSCHUtlRgmBndCfm(Inst instId,SuId suId,uint8_t status)
5565 ret = RgUiRgmBndCfm(&rgSchCb[instId].rgmSap[suId].sapCfg.sapPst, rgSchCb[instId].rgmSap[suId].sapCfg.suId, status);
5568 DU_LOG("\nERROR --> SCH : rgSCHUtlRgmBndCfm: RgUiRgrBndCfm Failed ");
5572 } /* rgSCHUtlRgmBndCfm*/
5577 * @brief API for sending configuration confirm from Scheduler to DU APP
5581 * Function: schSendCfgCfm
5583 * This API is invoked to send configuration confirm from Scheduler to DU
5586 * @param[in] Pst pst
5587 * @param[in] RgrCfgTransId transId
5588 * @param[in] uint8_t status
5593 S16 schSendCfgCfm(Region reg,Pool pool,RgrCfgTransId transId,uint8_t status)
5597 memset((&cfmPst), 0, sizeof(Pst));
5599 cfmPst.srcEnt = (Ent)ENTDUAPP;
5600 cfmPst.srcInst = (Inst) 0;
5601 cfmPst.srcProcId = SFndProcId();
5602 cfmPst.dstEnt = (Ent)ENTMAC;
5603 cfmPst.dstInst = (Inst) 0;
5604 cfmPst.dstProcId = SFndProcId();
5605 cfmPst.selector = ODU_SELECTOR_LC;
5606 cfmPst.region = reg;
5609 if(RgUiRgrCfgCfm(&cfmPst,transId, status) != ROK)
5611 DU_LOG("\nERROR --> SCH : schSendCfgCfm: RgUiRgrCfgCfm Failed ");
5615 } /* schSendCfgCfm*/
5618 * @brief API for sending TTI indication from Scheduler to RRM.
5622 * Function: rgSCHUtlRgrTtiInd
5624 * This API is invoked to send TTI indication from Scheduler instance to RRM.
5625 * This API fills in Pst structure and RgrTtiIndInfo
5627 * @param[in] cell RgSchCellCb
5628 * @param[in] CmLteTimingInfo status
5633 S16 rgSCHUtlRgrTtiInd(RgSchCellCb *cell,RgrTtiIndInfo *rgrTti)
5636 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
5639 Void mtTmrHdlrPublic(void);
5642 rgrSap = cell->rgrSap;
5643 if (rgrSap->sapSta.sapState != LRG_BND)
5645 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrTtiInd() Upper SAP not bound (%d) ",
5646 rgrSap->sapSta.sapState);
5649 RgUiRgrTtiInd(&(cell->rgrSap->sapCfg.sapPst),
5650 cell->rgrSap->sapCfg.suId, rgrTti);
5658 } /* rgSCHUtlRgrTtiInd*/
5660 /** @brief This function is called by rgMacSchSfRecpInd. This function invokes the
5661 * scheduler with the information of the received Data and any Control Elements
5669 * - Retrieves the RaCb with the rnti provided, if it doesnt exist
5671 * - If UE exists then update the Schduler with any MAC CEs if present.
5672 * - Invoke RAM module to do Msg3 related processing rgSCHRamProcMsg3
5674 * @param [in] RgSchCellCb *cellCb
5675 * @param [in] RgSchUeCb *ueCb
5676 * @param [in] CmLteRnti rnti
5677 * @param [in] RgMacPdu *pdu
5678 * @param [in] RgSchErrInfo *err
5684 S16 rgSCHUtlProcMsg3
5686 RgInfSfDatInd *subfrmInfo,
5687 RgSchCellCb *cellCb,
5697 /* must have an raCb for this case */
5698 raCb = rgSCHDbmGetRaCb (cellCb, rnti);
5701 DU_LOG("\nERROR --> SCH : RNTI:%d Received MSG3, unable to "
5706 /* ccpu00130982: Processing CRNTI MAC CE before Short BSR, if any, such that
5707 * effBsr of current case only will be considered in scheduling of ContResLst*/
5708 ret = rgSCHRamProcMsg3 (cellCb, ueCb, raCb, pdu, err);
5711 DU_LOG("\nERROR --> SCH : Processing failed in the RAM "
5715 /* if ueCb is present */
5718 rgSCHUtlUpdSch (subfrmInfo, cellCb, ueCb, pdu, err);
5724 /** @brief This function is called by RgMacSchSpsRelInd. This function invokes the
5725 * scheduler with the information of the received Data.
5729 * Function: rgSCHUtlSpsRelInd
5734 * @param [in] RgSchCellCb *cellCb
5735 * @param [in] RgSchUeCb *ueCb
5736 * @param [in] Bool *isExplRel
5742 S16 rgSCHUtlSpsRelInd(RgSchCellCb *cellCb,RgSchUeCb *ueCb,Bool isExplRel)
5744 cellCb->sc.apis->rgSCHUlSpsRelInd(cellCb, ueCb, isExplRel);
5746 } /* end of rgSCHUtlSpsRelInd */
5749 /** @brief This function is called by RgMacSchSpsRelInd. This function invokes the
5750 * scheduler with the information of the received Data.
5754 * Function: rgSCHUtlSpsActInd
5759 * @param [in] RgSchCellCb *cellCb
5760 * @param [in] RgSchUeCb *ueCb
5761 * @param [in] uint16_t spsSduSize
5767 S16 rgSCHUtlSpsActInd(RgSchCellCb *cellCb,RgSchUeCb *ueCb,uint16_t spsSduSize)
5769 cellCb->sc.apis->rgSCHUlSpsActInd(cellCb, ueCb, spsSduSize);
5771 } /* end of rgSCHUtlSpsActInd */
5774 #endif /* LTEMAC_SPS */
5778 * @brief This API is invoked to send uplink group power control request to PHY.
5782 * Function : rgSCHUtlTfuGrpPwrCntrlReq
5784 * This API is invoked to send uplink group power control request to PHY.
5785 * It fills in the Pst structure, spId value and invokes group power
5786 * control request primitive at TFU.
5788 * @param[in] TfuGrpPwrCntrlReqInfo *grpPwrCntrlReq
5793 S16 rgSCHUtlTfuGrpPwrCntrlReq(Inst inst,S16 sapId,TfuGrpPwrCntrlReqInfo *grpPwrCntrlReq)
5796 RgSchLowSapCb *tfuSap;
5799 /* Get the lower SAP control block from the layer control block. */
5800 tfuSap = &(rgSchCb[inst].tfuSap[sapId]);
5801 if (tfuSap->sapSta.sapState != LRG_BND)
5803 DU_LOG("\nERROR --> SCH : rgSCHUtlTfuGrpPwrCntrlReq() Lower SAP not bound (%d) ",tfuSap->sapSta.sapState);
5806 memcpy (&pst, &(tfuSap->sapCfg.sapPst), sizeof(Pst));
5807 if((ret = RgLiTfuGrpPwrCntrlReq (&pst, tfuSap->sapCfg.spId, grpPwrCntrlReq)) != ROK)
5809 DU_LOG("\nERROR --> SCH : rgSCHUtlTfuGrpPwrCntrlReq() Call to RgLiTfuGrpPwrCntrlReq() failed");
5812 } /* rgSCHUtlTfuGrpPwrCntrlReq */
5815 /* FOR ACK NACK REP */
5818 * @brief This API is invoked to tell the DL Scheduler to add the UE back into
5819 * its scheduling queues.
5823 * Function : rgSCHUtlDlActvtUe
5825 * This API is invoked from Measurement gap moduled.
5827 * @param[in] RgSchCellCb *cell
5828 * @param[in] RgSchUeCb *ueCb
5834 S16 rgSCHUtlDlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
5836 cell->sc.apis->rgSCHActvtDlUe(cell, ue);
5841 * @brief This API is invoked to tell the UL Scheduler to add the UE back into
5842 * its scheduling queues.
5846 * Function : rgSCHUtlUlActvtUe
5848 * This API is invoked from Measurement gap moduled.
5850 * @param[in] RgSchCellCb *cell
5851 * @param[in] RgSchUeCb *ueCb
5857 S16 rgSCHUtlUlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
5859 cell->sc.apis->rgSCHActvtUlUe(cell, ue);
5863 /** @brief This function Validates the SAP information received along with the
5864 * primitive from the lower layer.
5866 * Function: rgSCHUtlValidateTfuSap
5868 * Validates SAP information.
5869 * @param suId The SAP Id
5874 S16 rgSCHUtlValidateTfuSap(Inst inst,SuId suId)
5876 RgSchLowSapCb *tfuSap;
5878 if(suId >= rgSchCb[inst].numSaps)
5880 DU_LOG("\nERROR --> SCH : Incorrect SuId");
5883 tfuSap = &(rgSchCb[inst].tfuSap[suId]);
5885 /* First lets check the suId */
5886 if( suId != tfuSap->sapCfg.suId)
5888 DU_LOG("\nERROR --> SCH : Incorrect SuId. Configured (%d) Recieved (%d)",
5889 tfuSap->sapCfg.suId, suId);
5892 if (tfuSap->sapSta.sapState != LRG_BND)
5894 DU_LOG("\nERROR --> SCH : Lower SAP not enabled SuId (%d)",
5895 tfuSap->sapCfg.suId);
5899 } /* end of rgSCHUtlValidateTfuSap */
5903 * Fun: rgSCHUtlAllocEventMem
5905 * Desc: This function allocates event memory
5907 * Ret: ROK - on success
5908 * RFAILED - on failure
5915 S16 rgSCHUtlAllocEventMem(Inst inst,Ptr *memPtr,Size memSize)
5918 volatile uint32_t startTime=0;
5921 sMem.region = rgSchCb[inst].rgSchInit.region;
5922 sMem.pool = rgSchCb[inst].rgSchInit.pool;
5924 #if (ERRCLASS & ERRCLS_DEBUG)
5927 DU_LOG("\nERROR --> SCH : rgAllocEventMem(): memSize invalid\n");
5930 #endif /* ERRCLASS & ERRCLS_DEBUG */
5932 SStartTask(&startTime, PID_SCHUTL_CMALLCEVT);
5934 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
5935 MS_BUF_ADD_ALLOC_CALLER();
5937 #ifdef TFU_ALLOC_EVENT_NO_INIT
5938 if(ROK != cmAllocEvntNoInit(memSize, TFU_MAX_MEMBLK_SIZE, &sMem, memPtr))
5940 if(ROK != cmAllocEvnt(memSize, TFU_MAX_MEMBLK_SIZE, &sMem, memPtr))
5943 DU_LOG("\nERROR --> SCH : cmAllocEvnt Failed.");
5947 SStopTask(startTime, PID_SCHUTL_CMALLCEVT);
5949 } /* end of rgSCHUtlAllocEventMem*/
5953 * Fun: rgGetEventMem
5955 * Desc: This function allocates event memory
5957 * Ret: ROK - on success
5958 * RFAILED - on failure
5965 S16 rgSCHUtlGetEventMem(Ptr *ptr,Size len,Ptr memCp)
5969 #ifdef TFU_ALLOC_EVENT_NO_INIT
5970 ret = cmGetMemNoInit(memCp, len, (Ptr *)ptr);
5972 ret = cmGetMem(memCp, len, (Ptr *)ptr);
5975 } /* end of rgSCHUtlGetEventMem*/
5981 * @brief Handler to allocate memory for ACK/NACk feedback information
5985 * Function : rgSCHUtlAllocUeANFdbkInfo
5987 * It allocates memory for the UE related ACK NACK information.
5989 * @param[in] RgSchUeCb *ue
5992 S16 rgSCHUtlAllocUeANFdbkInfo(RgSchUeCb *ue,uint8_t servCellIdx)
5996 if (rgSCHUtlAllocSBuf(ue->cell->instIdx,
5997 (Data **) &(ue->cellInfo[servCellIdx]->anInfo), sizeof(RgSchTddANInfo) * \
5998 ue->cell->ackNackFdbkArrSize) != ROK)
6003 for(idx=0; idx < ue->cell->ackNackFdbkArrSize; idx++)
6005 rgSCHUtlInitUeANFdbkInfo(&ue->cellInfo[servCellIdx]->anInfo[idx]);
6008 /* Set it to the first index */
6009 ue->cellInfo[servCellIdx]->nextFreeANIdx = 0;
6011 } /* rgSCHUtlAllocUeANFdbkInfo */
6014 * @brief Handler to release memory for ACK/NACk feedback information
6018 * Function : rgSCHUtlDelUeANFdbkInfo
6020 * It releases memory for the UE related ACK NACK information.
6022 * @param[in] RgSchUeCb *ue
6025 Void rgSCHUtlDelUeANFdbkInfo(RgSchUeCb *ue,uint8_t servCellIdx)
6028 /* ccpu00117052 - MOD - Passing double pointer
6029 for proper NULLP assignment*/
6030 rgSCHUtlFreeSBuf(ue->cell->instIdx,
6031 (Data **)(&( ue->cellInfo[servCellIdx]->anInfo)), sizeof(RgSchTddANInfo) * \
6032 ue->cell->ackNackFdbkArrSize);
6035 } /* rgSCHUtlDelUeANFdbkInfo */
6038 * @brief Handler to initialise UE ACK/NACk feedback information
6042 * Function : rgSCHUtlInitUeANFdbkInfo
6044 * It initialises UE related ACK NACK information.
6046 * @param[in] RgSchTddANInfo *anFdInfo
6049 S16 rgSCHUtlInitUeANFdbkInfo(RgSchTddANInfo *anFdInfo)
6052 anFdInfo->sfn = RGSCH_MAX_SFN+1; /* defensively setting invalid sfn */
6054 anFdInfo->ulDai = RG_SCH_INVALID_DAI_VAL;
6055 anFdInfo->dlDai = RG_SCH_INVALID_DAI_VAL;
6056 anFdInfo->latestMIdx = RG_SCH_INVALID_M_VAL;
6059 } /* rgSCHUtlInitUeANFdbkInfo */
6062 * @brief Handler to get UE related ACK NACK feedback information
6066 * Function : rgSCHUtlGetUeANFdbkInfo
6068 * It gets the UE related ACK NACK information based on
6069 * SFN and slot number.
6071 * @param[in] RgSchUeCb *ueCb
6072 * @param[in] CmLteTimingInfo *time
6073 * @return RgSchTddANInfo*
6075 RgSchTddANInfo* rgSCHUtlGetUeANFdbkInfo(RgSchUeCb *ueCb,CmLteTimingInfo *timeInfo,uint8_t servCellIdx)
6079 for (idx = 0; idx < ueCb->cell->ackNackFdbkArrSize; ++idx)
6081 if( (timeInfo->sfn == ueCb->cellInfo[servCellIdx]->anInfo[idx].sfn) &&
6082 (timeInfo->slot == ueCb->cellInfo[servCellIdx]->anInfo[idx].slot))
6084 return (&ueCb->cellInfo[servCellIdx]->anInfo[idx]);
6089 } /* rgSCHUtlGetUeANFdbkInfo */
6092 * @brief To get downlink slot index
6096 * Function: rgSCHUtlGetDlSfIdx
6097 * Purpose: Gets downlink slot index based on SFN and slot no
6099 * @param[in] CmLteTimingInfo *timeInfo
6100 * @param[in] RgSchCellCb *cell
6104 uint8_t rgSCHUtlGetDlSfIdx(RgSchCellCb *cell,CmLteTimingInfo *timeInfo)
6108 idx = RGSCH_NUM_SUB_FRAMES - \
6109 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
6110 idx = ((idx * timeInfo->sfn) + \
6111 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][timeInfo->slot]) - 1;
6112 idx = idx % cell->numDlSubfrms;
6114 return ((uint8_t)idx);
6118 * @brief To get the next downlink slot
6122 * Function: rgSCHUtlGetNxtDlSfInfo
6123 * Purpose: Gets next downlink slot based on current DL slot
6125 * @param[in] CmLteTimingInfo curDlTime
6126 * @param[in] RgSchCellCb *cell
6127 * @param[in] RgSchDlSf *dlSf
6128 * @param[in] RgSchDlSf **nxtDlsf
6129 * @param[in] CmLteTimingInfo *nxtDlTime
6133 Void rgSCHUtlGetNxtDlSfInfo(CmLteTimingInfo curDlTime,RgSchCellCb *cell,RgSchDlSf *dlSf,RgSchDlSf **nxtDlsf,CmLteTimingInfo *nxtDlTime)
6135 uint16_t idx = curDlTime.slot;
6142 idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
6144 }while(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
6145 != RG_SCH_TDD_DL_slot);
6146 RG_SCH_ADD_TO_CRNT_TIME(curDlTime, (*nxtDlTime), count);
6147 *nxtDlsf = rgSCHUtlSubFrmGet(cell, *nxtDlTime);
6148 if(dlSf->dlFdbkInfo.slot != (*nxtDlsf)->dlFdbkInfo.slot)
6157 * @brief To get the previous downlink slot
6161 * Function: rgSCHUtlGetPrevDlSfInfo
6162 * Purpose: Gets previous downlink slot based on current DL slot
6164 * @param[in] RgSchCellCb *cell
6165 * @param[in] CmLteTimingInfo curDlTime
6166 * @param[in] CmLteTimingInfo *prevDlTime
6167 * @param[in] uint8_t *numSubfrm
6171 Void rgSCHUtlGetPrevDlSfInfo(RgSchCellCb *cell,CmLteTimingInfo curDlTime,CmLteTimingInfo *prevDlTime,uint8_t *numSubfrm)
6173 S16 idx = curDlTime.slot;
6181 idx = RGSCH_NUM_SUB_FRAMES-1;
6184 }while(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
6185 != RG_SCH_TDD_DL_slot);
6187 RGSCHDECRFRMCRNTTIME(curDlTime, (*prevDlTime), count);
6192 /* Added Holes Management functions for Adaptive Re transmission */
6193 /******* </AllocHolesMemMgmnt>: START *****/
6194 /***********************************************************
6196 * Func : rgSCHUtlUlSfInit
6198 * Desc : UL slot init.
6206 **********************************************************/
6207 S16 rgSCHUtlUlSfInit(RgSchCellCb *cell,RgSchUlSf *sf,uint8_t idx,uint8_t maxUePerSf)
6217 if(cell->ulDlCfgIdx == 0)
6219 /* Store the Uplink slot number corresponding to the idx */
6220 sf->ulSfIdx = rgSchTddCfg0UlSfTbl[idx%6];
6223 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf->allocDb,
6224 sizeof(RgSchUlAllocDb));
6229 ret = rgSCHUtlUlAllocDbInit(cell, sf->allocDb, maxUePerSf);
6232 /* ccpu00117052 - MOD - Passing double pointer
6233 for proper NULLP assignment*/
6234 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6235 sizeof(RgSchUlAllocDb));
6238 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf->holeDb,
6239 sizeof(RgSchUlHoleDb));
6242 rgSCHUtlUlAllocDbDeinit(cell, sf->allocDb);
6243 /* ccpu00117052 - MOD - Passing double pointer
6244 for proper NULLP assignment*/
6245 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6246 sizeof(RgSchUlAllocDb));
6249 /* Initialize the hole with CFI 1 Pusch Bw Info */
6250 ret = rgSCHUtlUlHoleDbInit(cell, sf->holeDb, (uint8_t)(maxUePerSf + 2), \
6251 0, cell->dynCfiCb.bwInfo[1].numSb);
6255 rgSCHUtlUlAllocDbDeinit(cell, sf->allocDb);
6256 /* ccpu00117052 - MOD - Passing double pointer
6257 for proper NULLP assignment*/
6258 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6259 sizeof(RgSchUlAllocDb));
6260 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->holeDb)),
6261 sizeof(RgSchUlHoleDb));
6264 cmLListInit(&sf->reTxLst);
6266 /* Fix ccpu00120610*/
6267 sf->allocCountRef = &sf->allocDb->count;
6269 /* initialize UL available subbands for current sub-frame */
6270 sf->availSubbands = cell->dynCfiCb.bwInfo[1].numSb;
6272 sf->numGrpPerTti = cell->cell5gtfCb.ueGrpPerTti;
6273 sf->numUePerGrp = cell->cell5gtfCb.uePerGrpPerTti;
6274 for(index = 0; index < MAX_5GTF_BEAMS; index++)
6276 sf->sfBeamInfo[index].totVrbgAllocated = 0;
6277 sf->sfBeamInfo[index].totVrbgRequired = 0;
6278 sf->sfBeamInfo[index].vrbgStart = 0;
6286 /***********************************************************
6288 * Func : rgSCHUtlUlSfDeinit
6290 * Desc : Deinitialises a slot
6298 **********************************************************/
6299 Void rgSCHUtlUlSfDeinit(RgSchCellCb *cell,RgSchUlSf *sf)
6303 rgSCHUtlUlAllocDbDeinit(cell, sf->allocDb);
6304 /* ccpu00117052 - MOD - Passing double pointer
6305 for proper NULLP assignment*/
6306 /* ccpu00117052 - MOD - Passing double pointer
6307 for proper NULLP assignment*/
6308 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6309 sizeof(RgSchUlAllocDb));
6313 rgSCHUtlUlHoleDbDeinit(cell, sf->holeDb);
6314 /* ccpu00117052 - MOD - Passing double pointer
6315 for proper NULLP assignment*/
6316 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->holeDb)),
6317 sizeof(RgSchUlHoleDb));
6322 /***********************************************************
6324 * Func : rgSCHUtlUlAllocDbInit
6326 * Desc : Initialise allocation DB
6328 * Ret : S16 (ROK/RFAILED)
6334 **********************************************************/
6335 static S16 rgSCHUtlUlAllocDbInit(RgSchCellCb *cell,RgSchUlAllocDb *allocDb,uint8_t maxAllocs)
6337 S16 ret = rgSCHUtlUlAllocMemInit(cell, &allocDb->mem, maxAllocs);
6343 allocDb->first = NULLP;
6347 /***********************************************************
6349 * Func : rgSCHUtlUlAllocDbDeinit
6351 * Desc : Deinitialises allocation DB
6352 * sent to UE, for a UE with accumulation disabled
6360 **********************************************************/
6361 static Void rgSCHUtlUlAllocDbDeinit(RgSchCellCb *cell,RgSchUlAllocDb *allocDb)
6363 rgSCHUtlUlAllocMemDeinit(cell, &allocDb->mem);
6365 allocDb->first = NULLP;
6369 /***********************************************************
6371 * Func : rgSCHUtlUlHoleDbInit
6373 * Desc : Initialise hole DB
6375 * Ret : S16 (ROK/RFAILED)
6381 **********************************************************/
6382 static S16 rgSCHUtlUlHoleDbInit(RgSchCellCb *cell,RgSchUlHoleDb *holeDb,uint8_t maxHoles,uint8_t start,uint8_t num)
6385 RgSchUlHole *hole = NULLP;
6387 ret = rgSCHUtlUlHoleMemInit(cell, &holeDb->mem, maxHoles, &hole);
6393 holeDb->first = hole;
6394 hole->start = start;
6396 hole->prv = hole->nxt = NULLP;
6400 /***********************************************************
6402 * Func : rgSCHUtlUlHoleDbDeinit
6404 * Desc : Deinitialises hole DB
6412 **********************************************************/
6413 static Void rgSCHUtlUlHoleDbDeinit(RgSchCellCb *cell,RgSchUlHoleDb *holeDb)
6415 rgSCHUtlUlHoleMemDeinit(cell, &holeDb->mem);
6417 holeDb->first = NULLP;
6422 /***********************************************************
6424 * Func : rgSCHUtlUlAllocGetHole
6426 * Desc : Get allocation from hole
6428 * Ret : RgSchUlAlloc *
6434 **********************************************************/
6435 RgSchUlAlloc *rgSCHUtlUlAllocGetHole(RgSchUlSf *sf,uint8_t numSb,RgSchUlHole *hole)
6437 if (numSb < hole->num)
6439 return (rgSCHUtlUlAllocGetPartHole(sf, numSb, hole));
6443 return (rgSCHUtlUlAllocGetCompHole(sf, hole));
6448 /***********************************************************
6450 * Func : rgSCHUtlUlAllocGetCompHole
6452 * Desc : Get an allocation corresponding to an entire hole
6454 * Ret : RgSchUlAlloc *
6460 **********************************************************/
6461 RgSchUlAlloc *rgSCHUtlUlAllocGetCompHole(RgSchUlSf *sf,RgSchUlHole *hole)
6463 RgSchUlAlloc *alloc;
6464 /* alloc = rgSCHUtlUlAllocGetAndIns(sf->allocDb, hole->prvAlloc, hole->nxtAlloc); */
6465 /* Calling rgSchCmnUlAllocGetAndIns is ok, but prv alloc needs to have nxtHole
6466 * updated, causing another check for prv */
6467 RgSchUlAlloc *prv = hole->prvAlloc;
6468 RgSchUlAlloc *nxt = hole->nxtAlloc;
6472 if (hole->start == prv->nxtHole->start)
6474 prv->nxtHole = NULLP;
6476 alloc = rgSCHUtlUlAllocGetAdjNxt(sf->allocDb, prv);
6480 alloc = rgSCHUtlUlAllocGetFirst(sf->allocDb);
6483 RGSCH_NULL_CHECK( 0, alloc);
6484 alloc->prvHole = NULLP;
6485 alloc->nxtHole = NULLP;
6487 alloc->sbStart = hole->start;
6488 alloc->numSb = hole->num;
6492 nxt->prvHole = NULLP;
6495 rgSCHUtlUlHoleRls(sf->holeDb, hole);
6497 /* UL_ALLOC_CHANGES*/
6498 alloc->allocDbRef = (void*)sf->allocDb;
6499 alloc->holeDbRef = (void*)sf->holeDb;
6503 /***********************************************************
6505 * Func : rgSCHUtlUlAllocGetPartHole
6507 * Desc : Get an allocation corresponding to a part of a hole.
6508 * The initial 'numSb' part of the hole shall be taken
6509 * away for this alloc.
6511 * Ret : RgSchUlAlloc *
6517 **********************************************************/
6518 RgSchUlAlloc *rgSCHUtlUlAllocGetPartHole(RgSchUlSf *sf,uint8_t numSb,RgSchUlHole *hole)
6520 RgSchUlAlloc *alloc;
6521 /* alloc = rgSCHUtlUlAllocGetAndIns(sf->allocDb, hole->prvAlloc, hole->nxtAlloc); */
6522 /* Calling rgSchCmnUlAllocGetAndIns is ok, but prv alloc needs to have nxtHole
6523 * updated, causing another check for prv */
6524 RgSchUlAlloc *prv = hole->prvAlloc;
6528 if (hole->start == prv->nxtHole->start)
6530 prv->nxtHole = NULLP;
6532 alloc = rgSCHUtlUlAllocGetAdjNxt(sf->allocDb, prv);
6536 alloc = rgSCHUtlUlAllocGetFirst(sf->allocDb);
6539 RGSCH_NULL_CHECK( 0, alloc);
6540 alloc->prvHole = NULLP;
6541 alloc->nxtHole = hole;
6542 hole->prvAlloc = alloc;
6544 alloc->sbStart = hole->start;
6545 alloc->numSb = numSb;
6546 hole->start += numSb;
6549 rgSCHUtlUlHoleDecr(sf->holeDb, hole);
6551 /* UL_ALLOC_CHANGES*/
6552 alloc->allocDbRef = (void*)sf->allocDb;
6553 alloc->holeDbRef = (void*)sf->holeDb;
6558 /***********************************************************
6560 * Func : rgSCHUtlUlAllocFirst
6562 * Desc : Get first alloc in slot
6564 * Ret : RgSchUlAlloc *
6570 **********************************************************/
6571 RgSchUlAlloc *rgSCHUtlUlAllocFirst(RgSchUlSf *sf)
6573 return (sf->allocDb->first);
6576 /***********************************************************
6578 * Func : rgSCHUtlUlAllocNxt
6580 * Desc : Get next alloc
6582 * Ret : RgSchUlAlloc *
6588 **********************************************************/
6589 RgSchUlAlloc *rgSCHUtlUlAllocNxt(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6592 return (alloc->nxt);
6595 /***********************************************************
6597 * Func : rgSCHUtlUlAllocGetAdjNxt
6599 * Desc : Get alloc which is immediately after the passed one.
6600 * 1. Gets alloc from mem.
6601 * 2. Inserts alloc into list (between prv and
6602 * prv->nxt, prv is not NULLP).
6603 * 3. Increments alloc count.
6604 * Note 1: Holes are not dealt with here.
6605 * Note 2: Assumes prv to be NULL.
6607 * Ret : RgSchUlAlloc *
6613 **********************************************************/
6614 RgSchUlAlloc *rgSCHUtlUlAllocGetAdjNxt(RgSchUlAllocDb *db,RgSchUlAlloc *prv)
6616 RgSchUlAlloc *alloc = rgSCHUtlUlAllocMemGet(&db->mem);
6617 RgSchUlAlloc *nxt = prv->nxt;
6619 #if (ERRCLASS & ERRCLS_DEBUG)
6620 if ( alloc == NULLP )
6638 /***********************************************************
6640 * Func : rgSCHUtlUlAllocGetFirst
6642 * Desc : Get alloc which is to be the first one in the alloc list
6643 * 1. Gets alloc from mem.
6644 * 2. Inserts alloc as first element into list.
6645 * 3. Increments alloc count.
6646 * Note 1: Holes are not dealt with here.
6647 * Note 2: prv to necessarily NULLP.
6649 * Ret : RgSchUlAlloc *
6655 **********************************************************/
6656 RgSchUlAlloc *rgSCHUtlUlAllocGetFirst(RgSchUlAllocDb *db)
6658 RgSchUlAlloc *alloc = rgSCHUtlUlAllocMemGet(&db->mem);
6659 RgSchUlAlloc *nxt = db->first;
6661 #if (ERRCLASS & ERRCLS_DEBUG)
6662 if ( alloc == NULLP )
6681 /* UL_ALLOC_ENHANCEMENT */
6682 /***********************************************************
6684 * Func : rgSCHUtlUlHoleAddAllocation
6686 * Desc : On freeing an alloc, add to hole
6694 **********************************************************/
6695 Void rgSCHUtlUlHoleAddAllocation(RgSchUlAlloc *alloc)
6697 /* Note: rgSchCmnUlHoleUpdAllocLnks function that is used should not exist as
6698 * one, if such excessive branching is done (AllocNone, AllocNoPrv etc).
6699 * The excessive branching is meant to utilise the knowledge of whether prv
6700 * and nxt allocs exist or not. Hence for each kind (none, noprv, nonxt,
6701 * both), there should be a rgSchCmnUlHoleUpdAllocLnks... function (such as
6702 * rgSchCmnUlHoleUpdAllocLnksNone/NoPrv etc. */
6703 RgSchUlHoleDb *db = alloc->holeDbRef;
6704 RgSchUlHole *prv = alloc->prvHole;
6705 RgSchUlHole *nxt = alloc->nxtHole;
6711 rgSCHUtlUlHoleJoin(db, prv, nxt, alloc);
6714 rgSCHUtlUlHoleExtndRight(db, prv, alloc);
6720 rgSCHUtlUlHoleExtndLeft(db, nxt, alloc);
6723 rgSCHUtlUlHoleNew(db, alloc);
6729 /***********************************************************
6731 * Func : rgSCHUtlUlAllocRelease
6733 * Desc : Releases an uplink allocation, only take alloc ptr
6741 **********************************************************/
6742 Void rgSCHUtlUlAllocRelease(RgSchUlAlloc *alloc)
6744 RgSchUlAllocDb *allocDb = alloc->allocDbRef;
6745 RgSchUlAlloc *prv = alloc->prv;
6746 RgSchUlAlloc *nxt = alloc->nxt;
6749 alloc->raCb = NULLP;
6750 alloc->isAdaptive = FALSE;
6755 if (nxt) /* general case: this allocation lies btw two */
6762 allocDb->first = nxt;
6769 rgSCHUtlUlHoleAddAllocation(alloc);
6770 rgSCHUtlUlAllocMemRls(&allocDb->mem, alloc);
6776 /***********************************************************
6778 * Func : rgSCHUtlUlAllocRls
6780 * Desc : Releases an uplink allocation
6788 **********************************************************/
6789 Void rgSCHUtlUlAllocRls(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6791 RgSchUlAllocDb *allocDb = sf->allocDb;
6792 RgSchUlAlloc *prv = alloc->prv;
6793 RgSchUlAlloc *nxt = alloc->nxt;
6796 alloc->raCb = NULLP;
6797 alloc->isAdaptive = FALSE;
6804 if (nxt) /* general case: this allocation lies btw two */
6811 allocDb->first = nxt;
6818 rgSCHUtlUlHoleAddAlloc(sf, alloc);
6819 rgSCHUtlUlAllocMemRls(&allocDb->mem, alloc);
6824 DU_LOG("\nERROR --> SCH : allocDb->count is ZERO ");
6827 //DU_LOG("\nallocDb->count:%u\n",allocDb->count);
6832 /***********************************************************
6834 * Func : rgSCHUtlUlHoleFirst
6836 * Desc : Get first (largest) hole
6838 * Ret : RgSchUlHole *
6844 **********************************************************/
6845 RgSchUlHole *rgSCHUtlUlHoleFirst(RgSchUlSf *sf)
6847 return (sf->holeDb->first);
6850 /***********************************************************
6852 * Func : rgSCHUtlUlHoleNxt
6854 * Desc : Get next largest hole
6856 * Ret : RgSchUlHole *
6862 **********************************************************/
6863 RgSchUlHole *rgSCHUtlUlHoleNxt(RgSchUlSf *sf,RgSchUlHole *hole)
6869 /***********************************************************
6871 * Func : rgSCHUtlUlHoleAddAlloc
6873 * Desc : On freeing an alloc, add to hole
6881 **********************************************************/
6882 Void rgSCHUtlUlHoleAddAlloc(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6884 /* Note: rgSchCmnUlHoleUpdAllocLnks function that is used should not exist as
6885 * one, if such excessive branching is done (AllocNone, AllocNoPrv etc).
6886 * The excessive branching is meant to utilise the knowledge of whether prv
6887 * and nxt allocs exist or not. Hence for each kind (none, noprv, nonxt,
6888 * both), there should be a rgSchCmnUlHoleUpdAllocLnks... function (such as
6889 * rgSchCmnUlHoleUpdAllocLnksNone/NoPrv etc. */
6890 RgSchUlHoleDb *db = sf->holeDb;
6891 RgSchUlHole *prv = alloc->prvHole;
6892 RgSchUlHole *nxt = alloc->nxtHole;
6898 rgSCHUtlUlHoleJoin(db, prv, nxt, alloc);
6901 rgSCHUtlUlHoleExtndRight(db, prv, alloc);
6907 rgSCHUtlUlHoleExtndLeft(db, nxt, alloc);
6910 rgSCHUtlUlHoleNew(db, alloc);
6913 /* increment the number of subbands getting freed to total available list */
6914 sf->availSubbands += alloc->numSb;
6919 /***********************************************************
6921 * Func : rgSCHUtlUlHoleJoin
6923 * Desc : Join two holes (due to alloc being deleted)
6931 **********************************************************/
6932 Void rgSCHUtlUlHoleJoin(RgSchUlHoleDb *db,RgSchUlHole *prv,RgSchUlHole *nxt,RgSchUlAlloc *alloc)
6934 prv->num += alloc->numSb + nxt->num;
6935 rgSCHUtlUlHoleRls(db, nxt);
6936 rgSCHUtlUlHoleIncr(db, prv);
6937 rgSCHUtlUlHoleUpdAllocLnks(prv, alloc->prv, alloc->nxt);
6942 /***********************************************************
6944 * Func : rgSCHUtlUlHoleExtndRight
6946 * Desc : Extend hole due to alloc coming 'after' the hole
6955 **********************************************************/
6956 Void rgSCHUtlUlHoleExtndRight(RgSchUlHoleDb *db,RgSchUlHole *prv,RgSchUlAlloc *alloc)
6958 prv->num += alloc->numSb;
6959 rgSCHUtlUlHoleIncr(db, prv);
6960 rgSCHUtlUlHoleUpdAllocLnks(prv, alloc->prv, alloc->nxt);
6964 /***********************************************************
6966 * Func : rgSCHUtlUlHoleExtndLeft
6968 * Desc : Extend hole due to alloc coming 'before' the hole
6977 **********************************************************/
6978 Void rgSCHUtlUlHoleExtndLeft(RgSchUlHoleDb *db,RgSchUlHole *nxt,RgSchUlAlloc *alloc)
6980 nxt->num += alloc->numSb;
6981 nxt->start = alloc->sbStart;
6982 rgSCHUtlUlHoleIncr(db, nxt);
6983 rgSCHUtlUlHoleUpdAllocLnks(nxt, alloc->prv, alloc->nxt);
6987 /***********************************************************
6989 * Func : rgSCHUtlUlHoleNew
6991 * Desc : Create new hole due to alloc being deleted
6999 **********************************************************/
7000 Void rgSCHUtlUlHoleNew(RgSchUlHoleDb *db,RgSchUlAlloc *alloc)
7002 RgSchUlHole *hole = rgSCHUtlUlHoleMemGet(&db->mem);
7003 #if (ERRCLASS & ERRCLS_DEBUG)
7004 if ( hole == NULLP )
7009 hole->start = alloc->sbStart;
7010 hole->num = alloc->numSb;
7012 rgSCHUtlUlHoleIns(db, hole);
7013 rgSCHUtlUlHoleUpdAllocLnks(hole, alloc->prv, alloc->nxt);
7017 /***********************************************************
7019 * Func : rgSCHUtlUlHoleUpdAllocLnks
7021 * Desc : Update alloc links in hole
7029 **********************************************************/
7030 Void rgSCHUtlUlHoleUpdAllocLnks(RgSchUlHole *hole,RgSchUlAlloc *prvAlloc,RgSchUlAlloc *nxtAlloc)
7034 prvAlloc->nxtHole = hole;
7038 nxtAlloc->prvHole = hole;
7040 hole->prvAlloc = prvAlloc;
7041 hole->nxtAlloc = nxtAlloc;
7046 /***********************************************************
7048 * Func : rgSCHUtlUlHoleIns
7050 * Desc : Insert (newly created) hole in sorted list of holes.
7051 * Searches linearly, beginning with the largest hole.
7059 **********************************************************/
7060 Void rgSCHUtlUlHoleIns(RgSchUlHoleDb *db,RgSchUlHole *hole)
7064 if ((cur = db->first) != NULLP)
7067 if (cur->num < hole->num)
7077 for (nxt = cur->nxt; nxt; cur = nxt, nxt = nxt->nxt)
7079 if (nxt->num < hole->num)
7081 /* Insert hole: cur <-> hole <-> nxt */
7097 /* This is the first hole */
7099 hole->prv = NULLP; /* may not be needed */
7105 /***********************************************************
7107 * Func : rgSCHUtlUlHoleIncr
7109 * Desc : hole->num has increeased, reposition in sorted
7118 **********************************************************/
7119 Void rgSCHUtlUlHoleIncr(RgSchUlHoleDb *db,RgSchUlHole *hole)
7123 if ((cur = hole->prv) != NULLP)
7127 if (cur->num > hole->num)
7132 /* Remove hole from current position */
7133 cur->nxt = hole->nxt;
7136 hole->nxt->prv = cur;
7139 for (prv = cur->prv; prv; cur = prv, prv = prv->prv)
7141 if (prv->num > hole->num)
7143 /* Insert hole: prv <-> hole <-> cur */
7162 /***********************************************************
7164 * Func : rgSCHUtlUlHoleDecr
7166 * Desc : hole->num has decreeased, reposition in sorted
7175 **********************************************************/
7176 Void rgSCHUtlUlHoleDecr(RgSchUlHoleDb *db,RgSchUlHole *hole)
7180 if ((cur = hole->nxt) != NULLP)
7184 if (cur->num < hole->num)
7189 /* Remove hole from current position */
7190 cur->prv = hole->prv;
7193 hole->prv->nxt = cur;
7195 else /* no prv, so cur to replace hole as first in list */
7200 for (nxt = cur->nxt; nxt; cur = nxt, nxt = nxt->nxt)
7202 if (nxt->num < hole->num)
7204 /* Insert hole: cur <-> hole <-> nxt */
7222 /***********************************************************
7224 * Func : rgSCHUtlUlHoleRls
7226 * Desc : Releases hole.
7227 * 1. Decrements hole count.
7228 * 2. Deletes hole from list.
7229 * 3. Frees hole (hole memory release).
7237 **********************************************************/
7238 Void rgSCHUtlUlHoleRls(RgSchUlHoleDb *db,RgSchUlHole *hole)
7240 RgSchUlHole *prv = hole->prv;
7241 RgSchUlHole *nxt = hole->nxt;
7261 rgSCHUtlUlHoleMemRls(&db->mem, hole);
7266 /***********************************************************
7268 * Func : rgSCHUtlUlAllocMemInit
7270 * Desc : Initialises alloc free pool
7272 * Ret : S16 (ROK/RFAILED)
7278 **********************************************************/
7279 S16 rgSCHUtlUlAllocMemInit(RgSchCellCb *cell,RgSchUlAllocMem *mem,uint8_t maxAllocs)
7282 RgSchUlAlloc *allocs;
7284 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&allocs,
7285 maxAllocs * sizeof(*allocs));
7290 mem->allocs = allocs;
7291 mem->maxAllocs = maxAllocs;
7292 if (mem->maxAllocs == 1)
7294 allocs[0].prv = NULLP;
7295 allocs[0].nxt = NULLP;
7300 allocs[0].prv = NULLP;
7301 allocs[0].nxt = &allocs[1];
7302 for (i = 1; i < mem->maxAllocs - 1; ++i)
7304 allocs[i].prv = &allocs[i-1];
7305 allocs[i].nxt = &allocs[i+1];
7307 allocs[i].prv = &allocs[i-1];
7308 allocs[i].nxt = NULLP;
7310 mem->firstFree = &allocs[0];
7314 /***********************************************************
7316 * Func : rgSCHUtlUlAllocMemDeinit
7318 * Desc : Deinitialises alloc free pool
7326 **********************************************************/
7327 Void rgSCHUtlUlAllocMemDeinit(RgSchCellCb *cell,RgSchUlAllocMem *mem)
7329 /* ccpu00117052 - MOD - Passing double pointer
7330 for proper NULLP assignment*/
7331 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(mem->allocs)),
7332 mem->maxAllocs * sizeof(*mem->allocs));
7334 mem->firstFree = NULLP;
7338 /***********************************************************
7340 * Func : rgSCHUtlUlHoleMemInit
7342 * Desc : Initialises hole free pool. Assumes maxHoles
7345 * Ret : S16 (ROK/RFAILED)
7351 **********************************************************/
7352 S16 rgSCHUtlUlHoleMemInit(RgSchCellCb *cell,RgSchUlHoleMem *mem,uint8_t maxHoles,RgSchUlHole **holeRef)
7357 ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&holes,
7358 maxHoles * sizeof(*holes));
7365 mem->maxHoles = maxHoles;
7367 /* first hole is taken up */
7368 holes[0].prv = NULLP; /* not needed */
7369 holes[0].nxt = NULLP; /* not needed */
7370 *holeRef = &holes[0];
7372 if (mem->maxHoles == 2)
7374 holes[1].prv = NULLP; /* may not be needed */
7375 holes[1].nxt = NULLP; /* may not be needed */
7380 holes[1].prv = NULLP;
7381 holes[0].nxt = &holes[1];
7382 for (i = 1; i < mem->maxHoles - 1; ++i)
7384 holes[i].prv = &holes[i-1];
7385 holes[i].nxt = &holes[i+1];
7387 holes[i].prv = &holes[i-1];
7388 holes[i].nxt = NULLP;
7390 mem->firstFree = &holes[1];
7395 /***********************************************************
7397 * Func : rgSCHUtlUlHoleMemDeinit
7399 * Desc : Deinitialises hole free pool
7407 **********************************************************/
7408 Void rgSCHUtlUlHoleMemDeinit(RgSchCellCb *cell,RgSchUlHoleMem *mem)
7410 /* ccpu00117052 - MOD - Passing double pointer
7411 for proper NULLP assignment*/
7412 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(mem->holes)),
7413 mem->maxHoles * sizeof(*mem->holes));
7415 mem->firstFree = NULLP;
7419 /***********************************************************
7421 * Func : rgSCHUtlUlAllocMemGet
7423 * Desc : Gets an 'alloc' from the free pool
7425 * Ret : RgSchUlAlloc *
7431 **********************************************************/
7432 RgSchUlAlloc *rgSCHUtlUlAllocMemGet(RgSchUlAllocMem *mem)
7434 RgSchUlAlloc *alloc;
7436 #if (ERRCLASS & ERRCLS_DEBUG)
7437 if (mem->firstFree == NULLP)
7443 alloc = mem->firstFree;
7444 mem->firstFree = alloc->nxt;
7445 alloc->nxt = NULLP; /* probably not needed */
7446 /* alloc->prv might already be NULLP, in case was needed to set it to NULLP */
7451 /***********************************************************
7453 * Func : rgSCHUtlUlAllocMemRls
7455 * Desc : Returns an 'alloc' to the free pool
7463 **********************************************************/
7464 Void rgSCHUtlUlAllocMemRls(RgSchUlAllocMem *mem,RgSchUlAlloc *alloc)
7468 alloc->nxt = mem->firstFree;
7469 if (mem->firstFree != NULLP)
7471 mem->firstFree->prv = alloc;
7473 mem->firstFree = alloc;
7477 /***********************************************************
7479 * Func : rgSCHUtlUlHoleMemGet
7481 * Desc : Gets a 'hole' from the free pool
7483 * Ret : RgSchUlHole *
7489 **********************************************************/
7490 RgSchUlHole *rgSCHUtlUlHoleMemGet(RgSchUlHoleMem *mem)
7494 #if (ERRCLASS & ERRCLS_DEBUG)
7495 if (mem->firstFree == NULLP)
7501 hole = mem->firstFree;
7502 mem->firstFree = hole->nxt;
7503 mem->firstFree->prv = NULLP; /* may not be needed, under error class */
7504 hole->nxt = NULLP; /* probably not needed */
7505 /* hole->prv is might already be NULLP, in case was needed to set it to NULLP */
7510 /***********************************************************
7512 * Func : rgSCHUtlUlHoleMemRls
7514 * Desc : Returns a 'hole' to the free pool
7522 **********************************************************/
7523 Void rgSCHUtlUlHoleMemRls(RgSchUlHoleMem *mem,RgSchUlHole *hole)
7527 hole->nxt = mem->firstFree;
7528 if (mem->firstFree != NULLP)
7530 mem->firstFree->prv = hole;
7532 mem->firstFree = hole;
7537 * @brief Get an alloc from the specified position in the BW.
7541 * Function : rgSCHUtlUlGetSpfcAlloc
7543 * - Return an alloc from the specified position in the BW.
7544 * Note: This function assumes there is always a hole
7545 * Existing which completely has the specified
7546 * allocation. The reason for such an assumption is
7547 * the function's usage as of now guarantees that there
7548 * will always be such hole. And also for efficiency.
7550 * @param[in] RgSchUlSf *sf
7551 * @param[in] uint8_t startSb
7552 * @param[in] uint8_t numSb
7553 * @return RgSchUlAlloc*
7555 RgSchUlAlloc *rgSCHUtlUlGetSpfcAlloc(RgSchUlSf *sf,uint8_t startSb,uint8_t numSb)
7557 RgSchUlHole *hole, *nxtHole;
7558 RgSchUlAlloc *alloc = NULLP;
7560 if ((hole = rgSCHUtlUlHoleFirst(sf)) == NULLP)
7566 nxtHole = rgSCHUtlUlHoleNxt(sf, hole);
7567 if ((startSb >= hole->start) &&
7568 (startSb+numSb <= hole->start+hole->num))
7570 if (startSb != hole->start)
7572 /* Create a new hole to accomodate Subbands between
7573 * hole start and req alloc start */
7574 RgSchUlHole *newHole = rgSCHUtlUlHoleMemGet(&(sf->holeDb->mem));
7576 #if (ERRCLASS & ERRCLS_DEBUG)
7577 if ( newHole == NULLP )
7582 newHole->start = hole->start;
7583 newHole->num = startSb - hole->start;
7584 hole->start = startSb;
7585 /* [ccpu00122847]-MOD- Correctly updating the hole->num */
7586 hole->num -= newHole->num;
7587 ++(sf->holeDb->count);
7588 rgSCHUtlUlHoleIns(sf->holeDb, newHole);
7589 newHole->prvAlloc = hole->prvAlloc;
7590 if (newHole->prvAlloc)
7592 newHole->prvAlloc->nxtHole = newHole;
7594 if (numSb == hole->num)
7596 alloc = rgSCHUtlUlAllocGetCompHole(sf, hole);
7600 alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole);
7602 alloc->prvHole = newHole;
7603 newHole->nxtAlloc = alloc;
7605 else /* Hole start and req alloc start are same */
7607 if (numSb == hole->num)
7609 alloc = rgSCHUtlUlAllocGetCompHole(sf, hole);
7613 alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole);
7618 } while ((hole = nxtHole) != NULLP);
7623 * @brief Validates the qci values
7627 * Function :rgSCHUtlValidateQci
7629 * @param[in] RgSchCellCb *cellCb
7630 * @param[in] uint8_t numQci
7631 * @param[out] uint8_t *qci
7636 static S16 rgSCHUtlValidateQci(RgSchCellCb *cellCb,uint8_t numQci,uint8_t *qci)
7641 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
7643 qciVal = qci[qciIdx];
7644 if(qciVal == 0 || qciVal > 9)
7648 if(qciVal != cellCb->qciArray[qciVal].qci)
7655 }/* rgSCHUtlValidateQci */
7657 * @brief Validates the measurement request parameters.
7661 * Function :rgSCHUtlValidateMeasReq
7663 * @param[in] RgSchCellCb *cellCb
7664 * @param[in] LrgSchMeasReqInfo *schL2MeasInfo
7665 * @param[out] RgSchErrInfo *err
7666 * @return RgSchUlAlloc*
7668 S16 rgSCHUtlValidateMeasReq(RgSchCellCb *cellCb, LrgSchMeasReqInfo *schL2MeasInfo,RgSchErrInfo *err)
7673 measType = schL2MeasInfo->measType;
7674 if((measType == 0) ||
7677 err->errType = RGSCHERR_SCH_INVALID_MEAS_TYPE;
7678 err->errCause = RGSCHERR_SCH_L2MEAS;
7681 if((schL2MeasInfo->timePrd !=0) &&
7682 (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL) &&
7683 ((schL2MeasInfo->avgPrbQciDl.numQci > LRG_MAX_QCI_PER_REQ)||
7684 (schL2MeasInfo->avgPrbQciDl.numQci == 0)))
7686 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7687 err->errCause = RGSCHERR_SCH_L2MEAS;
7690 if((schL2MeasInfo->timePrd !=0) &&
7691 (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_UL) &&
7692 (schL2MeasInfo->avgPrbQciUl.numQci > LRG_MAX_QCI_PER_REQ))
7694 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7695 err->errCause = RGSCHERR_SCH_L2MEAS;
7698 if((measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_DL) &&
7699 ((schL2MeasInfo->nmbActvUeQciDl.numQci > LRG_MAX_QCI_PER_REQ) ||
7700 (schL2MeasInfo->nmbActvUeQciDl.sampPrd == 0)||
7701 ((schL2MeasInfo->timePrd !=0)&&
7702 (schL2MeasInfo->timePrd < schL2MeasInfo->nmbActvUeQciDl.sampPrd)) ||
7703 (schL2MeasInfo->nmbActvUeQciDl.sampPrd > LRG_MAX_SAMP_PRD)))
7705 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7706 err->errCause = RGSCHERR_SCH_L2MEAS;
7709 if((measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_UL) &&
7710 ((schL2MeasInfo->nmbActvUeQciUl.numQci > LRG_MAX_QCI_PER_REQ) ||
7711 (schL2MeasInfo->nmbActvUeQciUl.sampPrd == 0)||
7712 ((schL2MeasInfo->timePrd !=0) &&
7713 (schL2MeasInfo->timePrd < schL2MeasInfo->nmbActvUeQciUl.sampPrd)) ||
7714 (schL2MeasInfo->nmbActvUeQciUl.sampPrd > LRG_MAX_SAMP_PRD)))
7716 err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7717 err->errCause = RGSCHERR_SCH_L2MEAS;
7720 if((schL2MeasInfo->timePrd !=0) &&
7721 (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL))
7723 RGSCH_ARRAY_BOUND_CHECK(cellCb->instIdx, schL2MeasInfo->avgPrbQciDl.qci, \
7724 (schL2MeasInfo->avgPrbQciDl.numQci));
7725 ret = rgSCHUtlValidateQci(cellCb, schL2MeasInfo->avgPrbQciDl.numQci,
7726 schL2MeasInfo->avgPrbQciDl.qci);
7729 err->errType = RGSCHERR_SCH_INVALID_QCI_VAL;
7730 err->errCause = RGSCHERR_SCH_L2MEAS;
7735 }/* rgSCHUtlValidateMeasReq */
7736 #endif /* LTE_L2_MEAS */
7737 /******* </AllocHolesMemMgmnt>: END *****/
7740 * @brief API for sending SI configuration confirm from Scheduler to RRM
7744 * Function: rgSCHUtlRgrSiCfgCfm
7746 * This API is invoked to send SI configuration confirm from Scheduler
7748 * This API fills in Pst structure and SAP Ids and invokes
7749 * config confirm API towards RRM.
7751 * @param[in] RgrCfgTransId transId
7752 * @param[in] uint8_t status
7757 S16 rgSCHUtlRgrSiCfgCfm(Inst instId,SpId spId,RgrCfgTransId transId,uint8_t status)
7759 uint8_t prntTrans[RGR_CFG_TRANSID_SIZE+1];
7761 memcpy(prntTrans, transId.trans, RGR_CFG_TRANSID_SIZE);
7762 prntTrans[RGR_CFG_TRANSID_SIZE] = '\0';
7763 if(RgUiRgrSiCfgCfm(&rgSchCb[instId].rgrSap[spId].sapCfg.sapPst,
7764 rgSchCb[instId].rgrSap[spId].sapCfg.suId,
7765 transId, status) != ROK)
7767 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrSiCfgCfm: "
7768 "RgUiRgrSiCfgCfm Failed ");
7773 } /* rgSCHUtlRgrSiCfgCfm */
7777 * @brief API for sending Warning SI configuration confirm from
7783 * This API is invoked to send Warning SI configuration confirm
7784 * from Scheduler to RRM.
7785 * This API fills in Pst structure and SAP Ids and invokes
7786 * config confirm API towards RRM.
7788 * @param[in] RgrCfgTransId transId
7789 * @param[in] uint8_t status
7794 S16 rgSCHUtlRgrWarningSiCfgCfm(Inst instId,SpId spId,uint8_t siId,RgrCfgTransId transId,uint8_t status)
7796 uint8_t prntTrans[RGR_CFG_TRANSID_SIZE+1];
7798 memcpy(prntTrans, transId.trans, RGR_CFG_TRANSID_SIZE);
7799 prntTrans[RGR_CFG_TRANSID_SIZE] = '\0';
7801 if(RgUiRgrWarningSiCfgCfm(&rgSchCb[instId].rgrSap[spId].sapCfg.sapPst,
7802 rgSchCb[instId].rgrSap[spId].sapCfg.suId,
7803 transId, siId, status) != ROK)
7805 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrSiCfgCfm: "
7806 "RgUiRgrSiCfgCfm Failed ");
7811 } /* rgSCHUtlRgrWarningSiCfgCfm */
7813 /***********************************************************
7815 * Func : rgSCHUtlPutSiInfo
7817 * Desc : Utility Function to deallocate SI information
7825 **********************************************************/
7826 Void rgSCHUtlPutSiInfo(RgSchCellCb *cell)
7829 uint32_t sizeOfSiInfo = 0;
7830 /*Free the buffers in crntSiInfo*/
7831 RGSCH_FREE_MSG(cell->siCb.crntSiInfo.mib)
7832 RGSCH_FREE_MSG(cell->siCb.crntSiInfo.sib1Info.sib1)
7834 sizeOfSiInfo = sizeof(cell->siCb.crntSiInfo.siInfo)/sizeof(cell->siCb.crntSiInfo.siInfo[0]);
7836 for(idx=0; idx < sizeOfSiInfo; idx++)
7838 RGSCH_FREE_MSG(cell->siCb.crntSiInfo.siInfo[idx].si)
7841 /*Free the buffers in newSiInfo */
7842 RGSCH_FREE_MSG(cell->siCb.newSiInfo.mib)
7843 RGSCH_FREE_MSG(cell->siCb.newSiInfo.sib1Info.sib1)
7845 sizeOfSiInfo = sizeof(cell->siCb.newSiInfo.siInfo)/sizeof(cell->siCb.newSiInfo.siInfo[0]);
7847 for(idx=0; idx < sizeOfSiInfo; idx++)
7849 RGSCH_FREE_MSG(cell->siCb.newSiInfo.siInfo[idx].si)
7854 #endif /*RGR_SI_SCH */
7858 /***********************************************************
7860 * Func : rgSCHUtlGetDrxSchdUesInDl
7862 * Desc : Utility Function to fill the get the list of
7863 * scheduled UEs. On these UE's, drx-inactivity
7864 * timer will be started/restarted.
7873 **********************************************************/
7874 S16 rgSCHUtlGetDrxSchdUesInDl
7876 RgSchCellCb *cellCb,
7878 RgSchDlHqProcCb *dlHq,
7879 RgInfUeAlloc *allocInfo,
7880 CmLListCp *dlDrxInactvTmrLst,
7881 CmLListCp *dlInActvLst,
7882 CmLListCp *ulInActvLst
7885 Bool isNewTx = FALSE;
7887 RgSchDrxDlHqProcCb *drxHq;
7888 RgSchDRXCellCb *drxCell = cellCb->drxCb;
7889 RgSchDrxUeCb *drxUe;
7890 uint8_t cellIdx = ueCb->cellIdToCellIdxMap[RG_SCH_CELLINDEX(dlHq->hqE->cell)];
7891 uint32_t dlInactvMask;
7892 uint32_t ulInactvMask;
7894 for(idx = 0; idx < allocInfo->nmbOfTBs; idx++)
7896 if(allocInfo->tbInfo[idx].isReTx == FALSE)
7899 /* Removing break here, since in 2 TB case if 2nd TB is proceeding with
7900 retx then drxretx timer should be stopped.*/
7904 /*Stop the DRX retransmission timer as UE scheduled for retx. Here
7905 * we stop the timer and inactivate the UE for both UL and DL.
7906 * This may result in loss of one slot for UL but this trade
7907 * off is taken to avoid the overhead of maintaining a list of UEs
7908 * to be inactivated in the next slot.*/
7909 drxHq = RG_SCH_DRX_GET_DL_HQ(dlHq);
7910 drxUe = RG_SCH_DRX_GET_UE(ueCb);
7911 if(drxHq->reTxIndx != DRX_INVALID)
7913 /* This condition should never occur */
7914 if(drxHq->reTxIndx >= RG_SCH_MAX_DRXQ_SIZE)
7916 DU_LOG("\nERROR --> SCH : [%d]UE:DRXUE RETX IDX[%d]"
7917 "is out of bound,dlInactvMask %d,procId %d\n", ueCb->ueId,
7918 drxHq->reTxIndx,ueCb->dl.dlInactvMask, dlHq->procId);
7921 drxUe->drxDlInactvMaskPerCell[cellIdx] |= (RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId);
7922 drxUe->drxUlInactvMaskPerCell[cellIdx] |= (RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId);
7924 dlInactvMask = RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId;
7925 ulInactvMask = RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId;
7927 for(cellIdx = 0; cellIdx < CM_LTE_MAX_CELLS; cellIdx++)
7929 dlInactvMask &= drxUe->drxDlInactvMaskPerCell[cellIdx];
7930 ulInactvMask &= drxUe->drxUlInactvMaskPerCell[cellIdx];
7933 drxUe->drxDlInactvMask |= dlInactvMask;
7934 drxUe->drxUlInactvMask |= ulInactvMask;
7936 /* if no other condition is keeping ue active,
7939 if(!RG_SCH_DRX_DL_IS_UE_ACTIVE(drxUe))
7941 /* BUG 2 : HARQ_RTT, changed for consistency */
7942 ueCb->dl.dlInactvMask |= (RG_DRX_INACTIVE);
7944 /* Add to DL inactive list */
7945 cmLListAdd2Tail(dlInActvLst,&(ueCb->dlDrxInactvLnk));
7946 ueCb->dlDrxInactvLnk.node = (PTR)ueCb;
7949 if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
7951 /*BUG 2: HARQ_RTT changed for consistency */
7952 ueCb->ul.ulInactvMask |= (RG_DRX_INACTIVE);
7954 cmLListAdd2Tail(ulInActvLst,&(ueCb->ulDrxInactvLnk));
7955 ueCb->ulDrxInactvLnk.node = (PTR)ueCb;
7958 /* Deleting entry from HARQ RTT queue for the same HARQ proc,
7959 * if exist. This is the special case which can happen iF UL
7960 * scheduling is done later. */
7961 if(drxHq->rttIndx != DRX_INVALID)
7963 cmLListDelFrm (&(cellCb->drxCb->drxQ[drxHq->rttIndx].harqRTTQ),
7964 &(drxHq->harqRTTEnt));
7966 drxHq->rttIndx = DRX_INVALID;
7969 cmLListDelFrm (&(drxCell->drxQ[drxHq->reTxIndx].harqRetxQ),
7970 &(drxHq->harqRetxEnt));
7971 drxHq->reTxIndx = DRX_INVALID;
7978 if(ueCb->drxCb->raRcvd == TRUE)
7980 ueCb->drxCb->raRcvd = FALSE;
7982 /* mark the ra bit */
7983 ueCb->drxCb->drxUlInactvMask |= RG_SCH_DRX_RA_BITMASK;
7984 ueCb->drxCb->drxDlInactvMask |= RG_SCH_DRX_RA_BITMASK;
7986 }/*if(ra->rcvd) == TRUE */
7988 if(ueCb->dlDrxInactvTmrLnk.node == NULLP)
7990 cmLListAdd2Tail(dlDrxInactvTmrLst,&(ueCb->dlDrxInactvTmrLnk));
7991 ueCb->dlDrxInactvTmrLnk.node = (PTR)ueCb;
7993 }/*if(isNewTx == TRUE) */
7996 }/* rgSCHUtlGetSchdUes*/
7998 /* ccpu00117452 - MOD - Changed macro name from
7999 RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */
8002 * @brief This function fills StaInd struct
8006 * Function: rgSCHUtlFillSndStaInd
8007 * Purpose: Fills StaInd struct and sends the
8010 * @param[in] RgSchCellCb *cell pointer to Cell Control block
8011 * @param[in] RgSchUeCb *ue pointer to Ue Control block
8012 * @param[in] RgrStaIndInfo *staInfo Sta Ind struct to be filled
8013 * @param[in] uint8_t numCqiRept NUmber of reports to be filled
8017 S16 rgSCHUtlFillSndStaInd(RgSchCellCb *cell,RgSchUeCb *ue,RgrStaIndInfo *staInfo,uint8_t numCqiRept)
8021 /* Fill StaInd for sending collated Latest N CQI rpeorts */
8022 /* Find index in the array from where Latest N
8023 reports needs to be fetched. Use this value to index in the array
8024 and copy the reports into staInfo */
8026 /* Fill the Cell Id of PCC of the UE */
8027 staInfo->cellId = ue->cell->cellId;
8028 staInfo->crnti = ue->ueId;
8030 idxStart = ue->schCqiInfo.cqiCount - numCqiRept;
8032 memcpy (&(staInfo->ueCqiInfo.cqiRept),
8033 &(ue->schCqiInfo.cqiRept[idxStart]),
8034 numCqiRept * sizeof(RgrUeCqiRept));
8036 staInfo->ueCqiInfo.numCqiRept = numCqiRept;
8038 ue->schCqiInfo.cqiCount = 0;
8040 /* Call utility function (rgSCHUtlRgrStaInd) to send rpts to RRM */
8041 if(rgSCHUtlRgrStaInd(cell, staInfo) != ROK)
8043 DU_LOG("\nERROR --> SCH : Could not send "
8044 "CQI reports for RNTI:%d",ue->ueId);
8050 }/* End of rgSCHUtlFillSndStaInd */
8055 * @brief API for sending STA indication from Scheduler to RRM.
8059 * Function: rgSCHUtlRgrStaInd
8061 * This API is invoked to send STA indication from Scheduler instance to RRM.
8062 * This API fills in Pst structure and RgrStaIndInfo
8063 * and calls the Sta primitive API towards RRM.
8065 * @param[in] cell RgSchCellCb
8066 * @param[in] RgrStsIndInfo *rgrSta
8071 S16 rgSCHUtlRgrStaInd(RgSchCellCb *cell,RgrStaIndInfo *rgrSta)
8074 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
8076 rgrSap = cell->rgrSap;
8077 if (rgrSap->sapSta.sapState != LRG_BND)
8079 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrStaInd() Upper SAP not bound (%d) ",
8080 rgrSap->sapSta.sapState);
8083 RgUiRgrStaInd(&(cell->rgrSap->sapCfg.sapPst),
8084 cell->rgrSap->sapCfg.suId, rgrSta);
8086 } /* rgSCHUtlRgrStaInd*/
8087 #endif /* End of RGR_CQI_REPT */
8089 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
8091 * @brief Indicates MAC to release any rnti context it has.
8094 * Function : rgSCHUtlIndRntiRls2Mac
8095 * This function indicates MAC for this rnti release.
8096 * In case of ueId change it will indicate MAC
8097 * about the new rnti to be updated.
8098 * It will post a release RNTI indication to MAC.
8102 * @param[in] RgSchCellCb *cell
8103 * @param[in] CmLteRnti rnti
8104 * @param[in] Bool ueIdChng
8105 * @param[in] CmLteRnti newRnti
8109 Void rgSCHUtlIndRntiRls2Mac(RgSchCellCb *cell,CmLteRnti rnti,Bool ueIdChng,CmLteRnti newRnti)
8112 Inst inst = cell->instIdx;
8113 RgInfRlsRnti rntiInfo;
8116 /* Copy the info to rntiInfo */
8117 rntiInfo.cellId = cell->cellId;
8118 rntiInfo.rnti = rnti;
8119 /* Fix : syed ueId change as part of reestablishment.
8120 * Now SCH to trigger this. CRG ueRecfg for ueId change
8122 rntiInfo.ueIdChng = ueIdChng;
8123 rntiInfo.newRnti = newRnti;
8125 rntiInfo.isUeSCellDel = FALSE;
8127 /* Invoke MAC to release the rnti */
8128 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[inst], cell->macInst);
8129 RgSchMacRlsRnti(&pst, &rntiInfo);
8133 /* LTE_ADV_FLAG_REMOVED_START */
8135 * @brief API for sending LOAD INF indication from Scheduler to RRM.
8138 * Function: rgSCHUtlRgrLoadInfInd
8140 * This API is invoked to send LOAD INF indication from Scheduler instance to RRM.
8141 * This API fills in Pst structure and RgrLoadInfIndInfo
8142 * and calls the Sta primitive API towards RRM.
8144 * @param[in] cell RgSchCellCb
8145 * @param[in] RgrLoadInfIndInfo *rgrLoadInf
8150 S16 rgSCHUtlRgrLoadInfInd(RgSchCellCb *cell,RgrLoadInfIndInfo *rgrLoadInf)
8153 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
8155 rgrSap = cell->rgrSap;
8156 if (rgrSap->sapSta.sapState != LRG_BND)
8158 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrLoadInfInd() Upper SAP not bound (%d) ",
8159 rgrSap->sapSta.sapState);
8162 RgUiRgrLoadInfInd(&(cell->rgrSap->sapCfg.sapPst),
8163 cell->rgrSap->sapCfg.suId, rgrLoadInf);
8165 } /* rgSCHUtlRgrLoadInfInd*/
8166 /* LTE_ADV_FLAG_REMOVED_END */
8168 /* MS_FIX : syed SCH to act as MASTER in maintaining
8169 * rnti related context. Trigger to rnti del/Chng at SCH
8170 * will result in a Indication to MAC to release its
8171 * RNTI context. MAC inturn indicates the context cleared
8172 * indication to SCH, upon which SCH would set this
8174 * @brief API for sending STA indication from Scheduler to RRM.
8178 * Function: rgSCHUtlRlsRnti
8180 * This API is invoked to indicate MAC to release rnti
8182 * @param[in] RgSchCellCb *cellCb
8183 * @param[in] RgSchRntiLnk *rntiLnk,
8184 * @param[in] Bool ueIdChngd,
8185 * @param[in] CmLteRnti newRnti
8189 Void rgSCHUtlRlsRnti(RgSchCellCb *cell,RgSchRntiLnk *rntiLnk,Bool ueIdChngd,CmLteRnti newRnti)
8192 uint8_t isLegacy = 0;
8194 if(cell->emtcEnable)
8196 rgSCHEmtcUtlRlsRnti(cell, rntiLnk, &isLegacy);
8201 /*Add to Guard Pool*/
8202 cmLListAdd2Tail(&cell->rntiDb.rntiGuardPool, &rntiLnk->rntiGrdPoolLnk);
8203 rntiLnk->rntiGrdPoolLnk.node = (PTR)rntiLnk;
8205 /* Fix: syed Explicitly Inidcate MAC to release RNTI */
8206 rgSCHUtlIndRntiRls2Mac(cell, rntiLnk->rnti, ueIdChngd, newRnti);
8213 * @brief This function fills StaInd struct
8217 * Function: rgSCHUtlFillSndUeStaInd
8218 * Purpose: Fills StaInd struct and sends the
8221 * @param[in] RgSchCellCb *cell pointer to Cell Control block
8222 * @param[in] RgSchUeCb *ue pointer to Ue Control block
8223 * @param[in] uint8_t numCqiRept NUmber of reports to be filled
8227 S16 rgSCHUtlFillSndUeStaInd(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeStaIndInfo *ueStaInfo)
8230 ueStaInfo->cellId = cell->cellId;
8231 ueStaInfo->crnti = ue->ueId;
8233 /* Call utility function (rgSCHUtlRgrUeStaInd) to send rpts to RRM */
8234 if(rgSCHUtlRgrUeStaInd(cell, ueStaInfo) != ROK)
8236 DU_LOG("\nERROR --> SCH : Could not send "
8237 "UE Sta reports CRNTI:%d",ue->ueId);
8243 }/* End of rgSCHUtlFillSndStaInd */
8248 * @brief API for sending STA indication from Scheduler to RRM.
8252 * Function: rgSCHUtlRgrStaInd
8254 * This API is invoked to send STA indication from Scheduler instance to RRM.
8255 * This API fills in Pst structure and RgrStaIndInfo
8256 * and calls the Sta primitive API towards RRM.
8258 * @param[in] cell RgSchCellCb
8259 * @param[in] RgrStsIndInfo *rgrSta
8264 S16 rgSCHUtlRgrUeStaInd(RgSchCellCb *cell,RgrUeStaIndInfo *rgrUeSta)
8267 RgSchUpSapCb *rgrSap; /*!< RGR SAP Control Block */
8269 rgrSap = cell->rgrSap;
8270 if (rgrSap->sapSta.sapState != LRG_BND)
8272 DU_LOG("\nERROR --> SCH : rgSCHUtlRgrUeStaInd() Upper SAP not bound (%d) ",
8273 rgrSap->sapSta.sapState);
8276 RgUiRgrUeStaInd(&(cell->rgrSap->sapCfg.sapPst),
8277 cell->rgrSap->sapCfg.suId, rgrUeSta);
8279 } /* rgSCHUtlRgrStaInd*/
8283 * @brief function to report DL and UL PRB usage to RRM.
8286 * Function: rgSCHUtlUpdAvgPrbUsage
8287 * This function sends the PRB usage report to
8288 * RRM with the interval configured by RRM.
8290 * @param[in] cell *RgSchCellCb
8295 S16 rgSCHUtlUpdAvgPrbUsage(RgSchCellCb *cell)
8297 CmLteTimingInfo frm;
8298 RgmPrbRprtInd *prbRprtInd;
8301 #ifdef DBG_MAC_RRM_PRB_PRINT
8302 static uint32_t count = 0;
8303 const uint32_t reprotForEvery20Sec = 20000/cell->prbUsage.rprtPeriod;
8308 frm = cell->crntTime;
8309 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
8315 if(cell->prbUsage.rprtPeriod >= RGSCH_NUM_SUB_FRAMES)
8317 /* Get the total number of DL and UL slots within the reporting period*/
8318 numDlSf = (cell->prbUsage.rprtPeriod *
8319 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1])
8320 / RGSCH_NUM_SUB_FRAMES;
8321 numUlSf = (cell->prbUsage.rprtPeriod *
8322 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1])
8323 / RGSCH_NUM_SUB_FRAMES;
8327 /* Get the total number of DL and UL slots < 10 ms interval */
8328 numDlSf = rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][frm.slot];
8329 numUlSf = rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][frm.slot];
8332 numDlSf = cell->prbUsage.rprtPeriod;
8333 numUlSf = cell->prbUsage.rprtPeriod;
8336 if(SGetSBuf(cell->rgmSap->sapCfg.sapPst.region,
8337 cell->rgmSap->sapCfg.sapPst.pool, (Data**)&prbRprtInd,
8338 sizeof(RgmPrbRprtInd)) != ROK)
8343 memset(&prbRprtInd->stQciPrbRpts[0],
8345 (RGM_MAX_QCI_REPORTS * sizeof(RgmPrbRptPerQci)));
8347 prbRprtInd->bCellId = cell->cellId;
8351 prbRprtInd->bPrbUsageMask |= RGM_PRB_USAGE_DL;
8352 for (idx = 0; idx < RGM_MAX_QCI_REPORTS; idx++ )
8354 prbRprtInd->stQciPrbRpts[idx].bAvgPrbDlUsage =
8355 RGSCH_DIV_ROUND((cell->prbUsage.qciPrbRpts[idx].dlTotPrbUsed*100),
8356 (numDlSf * cell->bwCfg.dlTotalBw));
8357 prbRprtInd->stQciPrbRpts[idx].bQci = cell->prbUsage.qciPrbRpts[idx].qci;
8358 cell->prbUsage.qciPrbRpts[idx].dlTotPrbUsed = 0;
8364 prbRprtInd->bPrbUsageMask |= RGM_PRB_USAGE_UL;
8365 for (idx = 0; idx < RGM_MAX_QCI_REPORTS; idx++ )
8367 prbRprtInd->stQciPrbRpts[idx].bAvgPrbUlUsage =
8368 RGSCH_DIV_ROUND((cell->prbUsage.qciPrbRpts[idx].ulTotPrbUsed*100),
8369 (numUlSf * cell->ulAvailBw));
8370 prbRprtInd->stQciPrbRpts[idx].bQci = cell->prbUsage.qciPrbRpts[idx].qci;
8371 cell->prbUsage.qciPrbRpts[idx].ulTotPrbUsed = 0;
8375 #ifdef DBG_MAC_RRM_PRB_PRINT
8376 if((count % reprotForEvery20Sec) == 0 )
8378 DU_LOG("\n====================================================================");
8379 DU_LOG("\nINFO --> SCH : QCI-1[DL:UL] | QCI-2[DL:UL] | QCI-3[DL:UL] | QCI-4[DL:UL] \n");
8380 DU_LOG("======================================================================\n");
8381 DU_LOG(" [%d: %d]\t | [%d: %d]\t | [%d: %d]\t| [%d: %d]\t\n",
8382 prbRprtInd->stQciPrbRpts[0].bAvgPrbDlUsage,
8383 prbRprtInd->stQciPrbRpts[0].bAvgPrbUlUsage,
8384 prbRprtInd->stQciPrbRpts[1].bAvgPrbDlUsage,
8385 prbRprtInd->stQciPrbRpts[1].bAvgPrbUlUsage,
8386 prbRprtInd->stQciPrbRpts[2].bAvgPrbDlUsage,
8387 prbRprtInd->stQciPrbRpts[2].bAvgPrbUlUsage,
8388 prbRprtInd->stQciPrbRpts[3].bAvgPrbDlUsage,
8389 prbRprtInd->stQciPrbRpts[3].bAvgPrbUlUsage);
8392 RgUiRgmSendPrbRprtInd(&(cell->rgmSap->sapCfg.sapPst),
8393 cell->rgmSap->sapCfg.suId, prbRprtInd);
8401 * @brief This function resends the Ta in case of
8402 * max retx failure or DTX for the Ta transmitted
8406 * Function: rgSCHUtlReTxTa
8409 * @param[in] RgSchCellCb *cell
8410 * @param[in] RgSchUeCb *ue
8414 Void rgSCHUtlReTxTa(RgSchCellCb *cellCb,RgSchUeCb *ueCb)
8417 /* If TA Timer is running. Stop it */
8418 if (ueCb->taTmr.tmrEvnt != TMR_NONE)
8420 rgSCHTmrStopTmr(cellCb, ueCb->taTmr.tmrEvnt, ueCb);
8422 /*[ccpu00121813]-ADD-If maxretx is reached then
8423 * use outstanding TA val for scheduling again */
8424 if(ueCb->dl.taCb.outStndngTa == TRUE)
8426 ueCb->dl.taCb.ta = ueCb->dl.taCb.outStndngTaval;
8427 ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
8428 ueCb->dl.taCb.outStndngTa = FALSE;
8431 /* Fix : syed TA state updation missing */
8432 ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
8433 rgSCHUtlDlTARpt(cellCb, ueCb);
8438 /* Added function for dropping Paging Message*/
8440 * @brief Handler for BO Updt received for BCCH or PCCH.
8444 * Function : rgSCHChkBoUpdate
8446 * This function shall check for BO received falls within the scheduling window or not
8449 * @param[in] RgSchCellCb *cell
8454 static S16 rgSCHChkBoUpdate(RgSchCellCb *cell,RgInfCmnBoRpt *boUpdt)
8457 uint32_t crntTimeInSubFrms = 0;
8458 uint32_t boUpdTimeInSubFrms = 0;
8459 uint32_t distance = 0;
8461 crntTimeInSubFrms = (cell->crntTime.sfn * RGSCH_NUM_SUB_FRAMES_5G) + cell->crntTime.slot +
8462 RG_SCH_CMN_DL_DELTA + 2; /* As bo received will scheduled in next TTI
8463 so incrementing with +1 more */
8464 boUpdTimeInSubFrms = (boUpdt->u.timeToTx.sfn * RGSCH_NUM_SUB_FRAMES_5G)+ boUpdt->u.timeToTx.slot;
8467 distance = boUpdTimeInSubFrms > crntTimeInSubFrms ? \
8468 boUpdTimeInSubFrms - crntTimeInSubFrms : \
8469 (RGSCH_MAX_SUBFRM_5G - crntTimeInSubFrms + boUpdTimeInSubFrms);
8471 if (distance > RGSCH_PCCHBCCH_WIN)
8477 }/*rgSCHChkBoUpdate*/
8482 * @brief Utility function to calculate the UL reTxIdx in TDD cfg0
8486 * Function : rgSchUtlCfg0ReTxIdx
8488 * Update the reTxIdx according to the rules mentioned
8489 * in 3GPP TS 36.213 section 8 for TDD Cfg0
8491 * @param[in] RgSchCellCb *cell
8492 * @param[in] CmLteTimingInfo phichTime
8493 * @param[in] uint8_t hqFdbkIdx
8496 uint8_t rgSchUtlCfg0ReTxIdx(RgSchCellCb *cell,CmLteTimingInfo phichTime,uint8_t hqFdbkIdx)
8498 uint8_t reTxIdx = RGSCH_INVALID_INFO;
8500 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
8502 uint8_t ulSF; /* UL SF in the TDD frame */
8504 ulSf = &cellUl->ulSfArr[hqFdbkIdx];
8505 ulSF = ulSf->ulSfIdx;
8507 /* Check for the UL SF 4 or 9 */
8508 if(ulSF == 9 || ulSF == 4)
8512 if(phichTime.slot == 0 || phichTime.slot == 5)
8516 /* Retx will happen according to the Pusch k table */
8517 reTxIdx = cellUl->schdIdx;
8521 /* Retx will happen at n+7 */
8522 RGSCHCMNADDTOCRNTTIME(phichTime, phichTime, 7);
8523 /* Fetch the corresponding UL slot Idx in UL sf array */
8524 reTxIdx = rgSCHCmnGetUlSfIdx(&phichTime, cell);
8527 else if(phichTime.slot == 1 || phichTime.slot == 6)
8529 /* Retx will happen at n+7 */
8530 RGSCHCMNADDTOCRNTTIME(phichTime, phichTime, 7);
8531 /* Fetch the corresponding UL slot Idx in UL sf array */
8532 reTxIdx = rgSCHCmnGetUlSfIdx(&phichTime, cell);
8539 * @brief Utility function to calculate total num of PRBs required to
8540 * satisfy DL BO for TM1/TM2/TM6/TM7
8544 * Function : rgSchUtlDlCalc1CwPrb
8546 * Calculate PRBs required for UE to satisfy BO in DL
8548 * Note : Total calculated PRBs will be assigned to *prbReqrd
8551 * @param[in] RgSchCellCb *cell
8552 * @param[in] RgSchUeCb *ue
8553 * @param[in] uint32_t bo
8554 * @param[out] uint32_t *prbReqrd
8557 Void rgSchUtlDlCalc1CwPrb(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8559 RgSchCmnDlCell *dlCell = RG_SCH_CMN_GET_DL_CELL(cell);
8560 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ue, cell);
8564 uint8_t cfi = dlCell->currCfi;
8566 iTbs = dlUe->mimoInfo.cwInfo[0].iTbs[0];
8567 eff = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[0][cfi]))[iTbs];
8569 /* Optimization to convert totalBo (which is in-terms of bytes) to bits
8570 * i.e, << 3 and multiply with 1024 i.e, << 10 */
8571 noRes = ((uint64_t)((bo << 3) << 10)) / (eff);
8572 /* Get the number of RBs needed for this transmission */
8573 /* Number of RBs = No of REs / No of REs per RB */
8574 *prbReqrd = RGSCH_CEIL(noRes, dlCell->noResPerRb[cfi]);
8577 } /* rgSchUtlDlCalc1CwPrb*/
8580 * @brief Utility function to calculate total num of PRBs required to
8581 * satisfy DL BO(BO sum of all logical channels for that UE or an LC BO)
8586 * Function : rgSchUtlDlCalc2CwPrb
8588 * Calculate PRBs required for UE to satisfy BO in DL
8590 * Note : Total calculated PRBs will be assigned to *prbReqrd
8593 * @param[in] RgSchCellCb *cell
8594 * @param[in] RgSchUeCb *ue
8595 * @param[in] uint32_t bo
8596 * @param[out] uint32_t *prbReqrd
8599 Void rgSchUtlDlCalc2CwPrb(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8601 RgSchCmnDlCell *dlCell = RG_SCH_CMN_GET_DL_CELL(cell);
8602 RgSchCmnDlUe *dlUe = RG_SCH_CMN_GET_DL_UE(ue, cell);
8603 uint32_t eff1, eff2;
8605 uint8_t noLyr1, noLyr2;
8606 uint8_t iTbs1, iTbs2;
8607 uint8_t cfi = dlCell->currCfi;
8609 if ((dlUe->mimoInfo.forceTD) ||/* Transmit Diversity (TD) */
8610 (dlUe->mimoInfo.ri < 2))/* 1 layer precoding */
8612 iTbs1 = dlUe->mimoInfo.cwInfo[0].iTbs[0];
8613 eff1 = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[0][cfi]))[iTbs1];
8615 /* Optimization to convert totalBo (which is in-terms of bytes) to bits
8616 * i.e, << 3 and multiply with 1024 i.e, << 10 */
8617 noRes = ((uint64_t)((bo << 3) << 10)) / (eff1);
8618 /* Get the number of RBs needed for this transmission */
8619 /* Number of RBs = No of REs / No of REs per RB */
8620 *prbReqrd = RGSCH_CEIL(noRes, dlCell->noResPerRb[cfi]);
8624 noLyr1 = dlUe->mimoInfo.cwInfo[0].noLyr;
8625 noLyr2 = dlUe->mimoInfo.cwInfo[1].noLyr;
8626 iTbs1 = dlUe->mimoInfo.cwInfo[0].iTbs[noLyr1 - 1];
8627 iTbs2 = dlUe->mimoInfo.cwInfo[1].iTbs[noLyr2 - 1];
8628 eff1 = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[noLyr1 - 1][cfi]))[iTbs1];
8629 eff2 = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[noLyr2 - 1][cfi]))[iTbs2];
8631 /* Optimization to convert totalBo (which is in-terms of bytes) to bits
8632 * i.e, << 3 and multiply with 1024 i.e, << 10 */
8633 noRes = ((uint64_t)((bo << 3) << 10)) / (eff1 + eff2);
8634 /* Get the number of RBs needed for this transmission */
8635 /* Number of RBs = No of REs / No of REs per RB */
8636 *prbReqrd = RGSCH_CEIL(noRes, dlCell->noResPerRb[cfi]);
8639 } /* rgSchUtlDlCalc2CwPrb */
8642 * @brief Utility function to calculate total num of PRBs required to
8643 * satisfy DL BO(BO sum of all logical channels for that UE or an LC BO)
8647 * Function : rgSchUtlCalcTotalPrbReq
8649 * This function calls TM specific routine to calculate PRB
8652 * @param[in] RgSchCellCb *cell
8653 * @param[in] RgSchUeCb *ue
8654 * @param[in] uint32_t bo
8655 * @param[out] uint32_t *prbReqrd
8658 Void rgSchUtlCalcTotalPrbReq(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8660 /* Call TM specific Prb calculation routine */
8661 (dlCalcPrbFunc[ue->mimoInfo.txMode - 1])(cell, ue, bo, prbReqrd);
8664 } /* rgSchUtlCalcTotalPrbReq */
8667 /***********************************************************
8669 * Func : rgSCHUtlFetchPcqiBitSz
8672 * Desc : Fetch the CQI/PMI bits for a UE based on the mode, periodicity.
8681 **********************************************************/
8682 static uint8_t rgSCHUtlFetchPcqiBitSz(RgSchCellCb *cell, RgSchUeCb *ueCb,uint8_t numTxAnt)
8684 uint8_t confRepMode;
8687 RgSchUePCqiCb *cqiCb = RG_SCH_GET_UE_CELL_CQI_CB(ueCb,cell);
8689 confRepMode = cqiCb->cqiCfg.cqiSetup.prdModeEnum;
8690 if((ueCb->mimoInfo.txMode != RGR_UE_TM_3) &&
8691 (ueCb->mimoInfo.txMode != RGR_UE_TM_4))
8697 ri = cqiCb->perRiVal;
8701 case RGR_PRD_CQI_MOD10:
8707 case RGR_PRD_CQI_MOD11:
8720 else if(numTxAnt == 4)
8733 /* This is number of antenna case 1.
8734 * This is not applicable for Mode 1-1.
8735 * So setting it to invalid value */
8741 case RGR_PRD_CQI_MOD20:
8749 pcqiSz = 4 + cqiCb->label;
8754 case RGR_PRD_CQI_MOD21:
8769 else if(numTxAnt == 4)
8782 /* This might be number of antenna case 1.
8783 * For mode 2-1 wideband case only antenna port 2 or 4 is supported.
8784 * So setting invalid value.*/
8792 pcqiSz = 4 + cqiCb->label;
8796 pcqiSz = 7 + cqiCb->label;
8812 * @brief Utility function to returns the number of subbands based on the
8817 * Function : rgSchUtlGetNumSbs
8819 * Calculate the number of PRBs
8820 * Update the subbandRequired based on the nPrbs and subband size
8822 * @param[in] RgSchCellCb *cell
8823 * @param[in] RgSchUeCb *ue
8824 * @param[in] uint32_t *numSbs
8827 uint8_t rgSchUtlGetNumSbs(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t *numSbs)
8830 //Currently hardcoding MAX prb for each UE
8831 nPrb = ue->ue5gtfCb.maxPrb;
8832 (*numSbs) = RGSCH_CEIL(nPrb, MAX_5GTF_VRBG_SIZE);
8837 * @brief Utility function to insert the UE node into UE Lst based on the
8838 * number of subbands allocated for the UE for the current TTI.
8842 * Function : rgSchUtlSortInsUeLst
8844 * If subbandRequired < Min, then insert at head
8845 * Else If subbandRequired > Max, then insert at tail
8846 * Else, traverse the list and place the node at the appropriate place
8848 * @param[in] RgSchCellCb *cell
8849 * @param[in] RgSchUeCb *ue
8852 uint8_t rgSchUtlSortInsUeLst(RgSchCellCb *cell,CmLListCp *ueLst,CmLList *node,uint8_t vrbgRequired)
8855 CmLList *firstUeInLst;
8856 CmLList *lastUeInLst;
8860 //firstUeInLst = cmLListFirst(ueLst);
8861 CM_LLIST_FIRST_NODE(ueLst,firstUeInLst);
8862 if(NULLP == firstUeInLst)
8864 /* first node to be added to the list */
8865 cmLListAdd2Tail(ueLst, node);
8869 /* Sb Required for the UE is less than the first node in the list */
8870 tempUe = (RgSchUeCb *)(firstUeInLst->node);
8871 ueUl = RG_SCH_CMN_GET_UL_UE(tempUe, cell);
8873 if(vrbgRequired <= ueUl->vrbgRequired)
8875 cmLListInsCrnt(ueLst, (node));
8879 /* Sb Required for this UE is higher than the UEs in the list */
8880 lastUeInLst = cmLListLast(ueLst);
8881 tempUe = (RgSchUeCb *)(lastUeInLst->node);
8882 if(vrbgRequired >= ueUl->vrbgRequired)
8884 cmLListAdd2Tail(ueLst, (node));
8888 /* This UE needs to be in the middle. Search and insert the UE */
8889 ueInLst = cmLListFirst(ueLst);
8892 tempUe = (RgSchUeCb *)(ueInLst->node);
8894 if(vrbgRequired <= ueUl->vrbgRequired)
8896 cmLListInsCrnt(ueLst, (node));
8900 ueInLst = cmLListNext(ueLst);
8902 } while(NULLP != ueInLst && ueInLst != firstUeInLst);
8911 * @brief Function to Send LCG GBR register to MAC
8915 * Function: rgSCHUtlBuildNSendLcgReg
8917 * Handler for sending LCG GBR registration
8924 * @param[in] RgSchCellCb *cell
8925 * @param[in] CmLteRnti crnti
8926 * @param[in] uint8_t lcgId
8927 * @param[in] Bool isGbr
8931 S16 rgSCHUtlBuildNSendLcgReg(RgSchCellCb *cell,CmLteRnti crnti,uint8_t lcgId,Bool isGbr)
8934 RgInfLcgRegReq lcgRegReq;
8936 memset(&pst, 0, sizeof(Pst));
8937 lcgRegReq.isGbr = isGbr;
8938 lcgRegReq.cellId = cell->cellId;
8939 lcgRegReq.crnti = crnti;
8940 lcgRegReq.lcgId = lcgId;
8941 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
8942 /* code Coverage portion of the test case */
8943 RgSchMacLcgReg(&pst, &lcgRegReq);
8952 * @brief Function to map RGR pucch type to TFU type
8956 * Function: rgSchUtlGetFdbkMode
8964 * @param[in] RgrSchFrmt1b3TypEnum
8965 * @return TfuAckNackMode
8968 TfuAckNackMode rgSchUtlGetFdbkMode(RgrSchFrmt1b3TypEnum fdbkType)
8971 TfuAckNackMode mode = TFU_UCI_FORMAT_1A_1B;
8975 case RG_SCH_UCI_FORMAT_NON_CA:
8976 case RG_SCH_UCI_FORMAT1A_1B:
8978 mode = TFU_UCI_FORMAT_1A_1B;
8981 case RG_SCH_UCI_FORMAT1B_CS:
8983 mode = TFU_UCI_FORMAT_1B_CS;
8986 case RG_SCH_UCI_FORMAT3:
8988 mode = TFU_UCI_FORMAT_3;
8994 #endif /* TFU_TDD */
8995 #endif /* LTE_ADV */
8996 #endif /*TFU_UPGRADE */
9000 * @brief Send Ue SCell delete to SMAC.
9004 * Function : rgSCHUtlSndUeSCellDel2Mac
9005 * This function populates the struct RgInfRlsRnti and
9006 * get the pst for SMac and mark field isUeSCellDel to TRUE which
9007 * indicates that it is a Ue SCell delete.
9011 * @param[in] RgSchCellCb *cell
9012 * @param[in] CmLteRnti rnti
9016 Void rgSCHUtlSndUeSCellDel2Mac(RgSchCellCb *cell,CmLteRnti rnti)
9019 Inst inst = cell->instIdx;
9020 RgInfRlsRnti rntiInfo;
9022 DU_LOG("\nINFO --> SCH : RNTI Release IND for UE(%d)\n", rnti);
9023 /* Copy the info to rntiInfo */
9024 rntiInfo.cellId = cell->cellId;
9025 rntiInfo.rnti = rnti;
9026 /* Fix : syed ueId change as part of reestablishment.
9027 * Now SCH to trigger this. CRG ueRecfg for ueId change
9029 rntiInfo.ueIdChng = FALSE;
9030 rntiInfo.newRnti = rnti;
9031 rntiInfo.isUeSCellDel = TRUE;
9032 /* Invoke MAC to release the rnti */
9033 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[inst], cell->macInst);
9034 RgSchMacRlsRnti(&pst, &rntiInfo);
9039 * @brief Returns max TB supported by a given txMode
9043 * Function : rgSCHUtlGetMaxTbSupp
9044 * Max TB supported for TM Modes (1,2,5,6 and 7) is 1
9048 * @param[in] RgrTxMode txMode
9049 * @return uint8_t maxTbCount;
9052 uint8_t rgSCHUtlGetMaxTbSupp(RgrTxMode txMode)
9078 return (maxTbCount);
9082 * @brief Send Ue SCell delete to SMAC.
9086 * Function : rgSCHTomUtlGetTrigSet
9087 * This function gets the triggerset based on cqiReq
9089 * @param[in] RgSchCellCb *cell
9090 * @param[in] RgSchUeCb ueCb
9091 * @param[in] uint8_t cqiReq,
9092 * @param[out] uint8_t *triggerSet
9097 Void rgSCHTomUtlGetTrigSet(RgSchCellCb *cell,RgSchUeCb *ueCb,uint8_t cqiReq,uint8_t *triggerSet)
9099 RgSchUeCellInfo *pCellInfo = RG_SCH_CMN_GET_PCELL_INFO(ueCb);
9102 case RG_SCH_APCQI_SERVING_CC:
9104 /* APeriodic CQI request for Current Carrier.*/
9105 uint8_t sCellIdx = ueCb->cellIdToCellIdxMap[RG_SCH_CELLINDEX(cell)];
9106 *triggerSet = 1 << (7 - sCellIdx);
9109 case RG_SCH_APCQI_1ST_SERVING_CCS_SET:
9111 *triggerSet = pCellInfo->acqiCb.aCqiCfg.triggerSet1;
9114 case RG_SCH_APCQI_2ND_SERVING_CCS_SET:
9116 *triggerSet = pCellInfo->acqiCb.aCqiCfg.triggerSet2;
9129 * @brief This function updates the value of UE specific DCI sizes
9133 * Function: rgSCHUtlUpdUeDciSize
9134 * Purpose: This function calculates and updates DCI Sizes in bits.
9136 * Invoked by: Scheduler
9138 * @param[in] RgSchCellCb *cell
9139 * @param[in] RgSchUeCb *ueCb
9140 * @param[in] isCsi2Bit *isCsi2Bit: is 1 bit or 2 bit CSI
9144 Void rgSCHUtlUpdUeDciSize(RgSchCellCb *cell,RgSchUeCb *ueCb,Bool isCsi2Bit)
9146 uint8_t dci01aCmnSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0];
9147 uint8_t dci01aDedSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0];
9148 if ((ueCb->accessStratumRls >= RGR_REL_10) && (cell->bwCfg.dlTotalBw >= cell->bwCfg.ulTotalBw))
9150 dci01aCmnSize += 1; /* Resource Allocation Type DCI 0 */
9151 dci01aDedSize += 1; /* Resource Allocation Type DCI 0 */
9153 if (isCsi2Bit == TRUE)
9155 dci01aDedSize += 2; /* 2 bit CSI DCI 0 */
9159 dci01aDedSize += 1; /* 1 bit CSI DCI 0 */
9162 /* Common CSI is always 1 bit DCI 0 */
9163 dci01aCmnSize += 1; /* 1 bit CSI DCI 0 */
9165 /* Compare the sizes of DCI 0 with DCI 1A and consider the greater */
9166 if (dci01aCmnSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9168 dci01aCmnSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9170 if (dci01aDedSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9172 dci01aDedSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9175 /* 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 */
9176 dci01aCmnSize += rgSchDciAmbigSizeTbl[dci01aCmnSize];
9177 dci01aDedSize += rgSchDciAmbigSizeTbl[dci01aDedSize];
9179 ueCb->dciSize.cmnSize[TFU_DCI_FORMAT_0] = dci01aCmnSize;
9180 ueCb->dciSize.cmnSize[TFU_DCI_FORMAT_1A] = dci01aCmnSize;
9182 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_0] = dci01aDedSize;
9183 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A] = dci01aDedSize;
9185 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1];
9187 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the UE is configured to decode PDCCH with CRC scrambled
9188 * by the C-RNTI and the number of information bits in format 1 is equal to that for format 0/1A
9189 * for scheduling the same serving cell and mapped onto the UE specific search space given by the
9190 * C-RNTI as defined in [3], one bit of value zero shall be appended to format 1. */
9191 if (ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A])
9193 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] += 1;
9196 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the number of information bits in format 1 belongs
9197 * to one of the sizes in Table 5.3.3.1.2-1, one or more zero bit(s) shall be appended
9198 * to format 1 until the payload size of format 1 does not belong to one of the sizes in
9199 * Table 5.3.3.1.2-1 and is not equal to that of format 0/1A mapped onto the same search space. */
9200 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] += rgSchDciAmbigSizeTbl[ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1]];
9201 } while (ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A]);
9203 /* Just copying the value of 2/2A to avoid multiple checks at PDCCH allocations. This values never change.*/
9204 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_2] = cell->dciSize.size[TFU_DCI_FORMAT_2];
9205 ueCb->dciSize.dedSize[TFU_DCI_FORMAT_2A] = cell->dciSize.size[TFU_DCI_FORMAT_2A];
9206 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_2] = cell->dciSize.size[TFU_DCI_FORMAT_2];
9207 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_2A] = cell->dciSize.size[TFU_DCI_FORMAT_2A];
9209 /* Spec 36.212-a80 Sec 5.3.3.1.3: except when format 1A assigns downlink resource
9210 * on a secondary cell without an uplink configuration associated with the secondary cell */
9211 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9212 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A] += rgSchDciAmbigSizeTbl[ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A]];
9213 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1];
9215 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the UE is configured to decode PDCCH with CRC scrambled
9216 * by the C-RNTI and the number of information bits in format 1 is equal to that for format 0/1A
9217 * for scheduling the same serving cell and mapped onto the UE specific search space given by the
9218 * C-RNTI as defined in [3], one bit of value zero shall be appended to format 1. */
9219 if (ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A])
9221 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] += 1;
9224 /* Spec 36.212-a80 Sec 5.3.3.1.2: If the number of information bits in format 1 belongs
9225 * to one of the sizes in Table 5.3.3.1.2-1, one or more zero bit(s) shall be appended
9226 * to format 1 until the payload size of format 1 does not belong to one of the sizes in
9227 * Table 5.3.3.1.2-1 and is not equal to that of format 0/1A mapped onto the same search space. */
9228 ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] += rgSchDciAmbigSizeTbl[ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1]];
9229 } while (ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] == ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1A]);
9231 rgSCHEmtcUtlUpdUeDciSize(cell, ueCb);
9236 * @brief This function initialises the DCI Size table
9240 * Function: rgSCHUtlCalcDciSizes
9241 * Purpose: This function calculates and initialises DCI Sizes in bits.
9243 * Invoked by: Scheduler
9245 * @param[in] RgSchCellCb *cell
9249 Void rgSCHUtlCalcDciSizes(RgSchCellCb *cell)
9251 uint8_t dciSize = 0;
9252 uint8_t dci01aSize = 0;
9253 uint32_t bits = 0, idx = 0;
9255 switch(TFU_DCI_FORMAT_0) /* Switch case for the purpose of readability */
9257 case TFU_DCI_FORMAT_0:
9259 /* DCI 0: Spec 36.212 Section 5.3.3.1.1 */
9261 /*-- Calculate resource block assignment bits need to be set
9262 Which is ln(N(N+1)/2) 36.212 5.3.3.1 --*/
9263 bits = (cell->bwCfg.ulTotalBw * (cell->bwCfg.ulTotalBw + 1) / 2);
9264 while ((bits & 0x8000) == 0)
9271 dciSize = 1 /* DCI 0 bit indicator */ + \
9272 1 /* Frequency hoping enable bit field */ + \
9273 (uint8_t)bits /* For frequency Hopping */ + \
9280 2 /* UL Index Config 0 or DAI Config 1-6 */
9284 cell->dciSize.baseSize[TFU_DCI_FORMAT_0] = dciSize;
9286 /* If hoping flag is enabled */
9287 if (cell->bwCfg.ulTotalBw <= 49) /* Spec 36.213 Table 8.4-1, N UL_hop, if hopping is enabled */
9289 cell->dciSize.dci0HopSize = 1;
9293 cell->dciSize.dci0HopSize = 2;
9296 /* Update common non-CRNTI scrambled DCI 0/1A flag */
9297 dci01aSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0] + 1; /* 1 bit CSI */
9299 case TFU_DCI_FORMAT_1A:
9301 /* DCI 1A: Spec 36.212 Section 5.3.3.1.3 */
9304 /* Calculate resource block assignment bits need to be set
9305 Which is ln(N(N+1)/2) */
9306 bits = (cell->bwCfg.dlTotalBw * (cell->bwCfg.dlTotalBw + 1) / 2);
9307 while ((bits & 0x8000) == 0)
9314 dciSize += 1 /* Format 1A */ + \
9315 1 /* Local or Distributed */ + \
9316 (uint8_t)bits /* Resource block Assignment */ + \
9319 4 /* HARQ Proc Id */ +
9321 3 /* HARQ Proc Id */ +
9331 cell->dciSize.baseSize[TFU_DCI_FORMAT_1A] = dciSize;
9333 /* If the UE is not configured to decode PDCCH with CRC scrambled by the C-RNTI,
9334 * and the number of information bits in format 1A is less than that of format 0,
9335 * zeros shall be appended to format 1A until the payload size equals that of format 0. */
9336 /* Compare the size with DCI 1A and DCI 0 and consider the greater one */
9337 if (dci01aSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9339 dci01aSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9341 /* If the number of information bits in format 1A belongs to one of the sizes in
9342 * Table 5.3.3.1.2-1, one zero bit shall be appended to format 1A. */
9343 dci01aSize += rgSchDciAmbigSizeTbl[dci01aSize];
9344 cell->dciSize.size[TFU_DCI_FORMAT_1A] = cell->dciSize.size[TFU_DCI_FORMAT_0] = dci01aSize;
9346 case TFU_DCI_FORMAT_1:
9348 /* DCI 1: Spec 36.212 Section 5.3.3.1.2 */
9350 if (cell->bwCfg.dlTotalBw > 10)
9352 dciSize = 1; /* Resource Allocation header bit */
9355 /* Resouce allocation bits Type 0 and Type 1 */
9356 bits = (cell->bwCfg.dlTotalBw/cell->rbgSize);
9357 if ((cell->bwCfg.dlTotalBw % cell->rbgSize) != 0)
9362 dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9370 2 /* Redunancy Version */ + \
9379 cell->dciSize.baseSize[TFU_DCI_FORMAT_1] = dciSize;
9381 cell->dciSize.size[TFU_DCI_FORMAT_1] = dciSize;
9384 /* If the UE is not configured to decode PDCCH with CRC
9385 * scrambled by the C-RNTI and the number of information bits in format 1
9386 * is equal to that for format 0/1A, one bit of value zero shall be appended
9388 if (dci01aSize == cell->dciSize.size[TFU_DCI_FORMAT_1])
9390 cell->dciSize.size[TFU_DCI_FORMAT_1] += 1;
9393 /* If the number of information bits in format 1 belongs to one of the sizes in
9394 * Table 5.3.3.1.2-1, one or more zero bit(s) shall be appended to format 1 until
9395 * the payload size of format 1 does not belong to one of the sizes in Table 5.3.3.1.2-1
9396 * and is not equal to that of format 0/1A mapped onto the same search space. */
9397 cell->dciSize.size[TFU_DCI_FORMAT_1] += rgSchDciAmbigSizeTbl[cell->dciSize.size[TFU_DCI_FORMAT_1]];
9398 } while (cell->dciSize.size[TFU_DCI_FORMAT_1] == dci01aSize);
9400 case TFU_DCI_FORMAT_2:
9402 /* DCI 2: Spec 36.212 Section 5.3.3.1.5 */
9404 if (cell->bwCfg.dlTotalBw > 10)
9406 dciSize = 1; /* Resource Allocation bit */
9409 dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9417 1 /* CW Swap Flag */ + \
9418 5 /* MCS for TB1 */+ \
9419 1 /* NDI for TB1 */+ \
9420 2 /* RV for TB1 */ + \
9421 5 /* MCS for TB2 */+ \
9422 1 /* NDI for TB2 */+ \
9424 if (cell->numTxAntPorts == 2)
9428 else if (cell->numTxAntPorts == 4)
9432 cell->dciSize.size[TFU_DCI_FORMAT_2] = dciSize;
9433 cell->dciSize.size[TFU_DCI_FORMAT_2] += rgSchDciAmbigSizeTbl[cell->dciSize.size[TFU_DCI_FORMAT_2]];
9435 case TFU_DCI_FORMAT_2A:
9437 /* DCI 2A: Spec 36.212 Section 5.3.3.1.5A */
9439 if (cell->bwCfg.dlTotalBw > 10)
9441 dciSize = 1; /* Resource Allocation bit */
9444 dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9452 1 /* CW Swap Flag */ + \
9453 5 /* MCS for TB1 */+ \
9454 1 /* NDI for TB1 */+ \
9455 2 /* RV for TB1 */ + \
9456 5 /* MCS for TB2 */+ \
9457 1 /* NDI for TB2 */+ \
9459 if (cell->numTxAntPorts == 4)
9463 cell->dciSize.size[TFU_DCI_FORMAT_2A] = dciSize;
9464 cell->dciSize.size[TFU_DCI_FORMAT_2A] += \
9465 rgSchDciAmbigSizeTbl[cell->dciSize.size[TFU_DCI_FORMAT_2A]]; /* Spec 39.212 Table 5.3.3.1.2-1 */
9467 case TFU_DCI_FORMAT_3:
9469 /* DCI 3: Spec 36.212 Section 5.3.3.1.6 */
9470 cell->dciSize.size[TFU_DCI_FORMAT_3] = cell->dciSize.size[TFU_DCI_FORMAT_1A] / 2;
9471 if (cell->dciSize.size[TFU_DCI_FORMAT_3] % 2)
9473 cell->dciSize.size[TFU_DCI_FORMAT_3]++;
9476 case TFU_DCI_FORMAT_3A:
9478 /* DCI 3A: Spec 36.212 Section 5.3.3.1.7 */
9479 cell->dciSize.size[TFU_DCI_FORMAT_3A] = cell->dciSize.size[TFU_DCI_FORMAT_1A];
9482 case TFU_DCI_FORMAT_6_0A:
9484 rgSCHEmtcGetDciFrmt60ASize(cell);
9486 case TFU_DCI_FORMAT_6_1A:
9488 rgSCHEmtcGetDciFrmt61ASize(cell);
9493 /* DCI format not supported */
9500 * @brief Handler for the CPU OvrLd related state adjustment.
9504 * Function : rgSCHUtlCpuOvrLdAdjItbsCap
9507 * - Record dl/ulTpts
9508 * - Adjust maxItbs to acheive target throughputs
9510 * @param[in] RgSchCellCb *cell
9513 Void rgSCHUtlCpuOvrLdAdjItbsCap( RgSchCellCb *cell)
9517 if ((cell->cpuOvrLdCntrl.cpuOvrLdIns) & (RGR_CPU_OVRLD_DL_TPT_UP |
9518 RGR_CPU_OVRLD_DL_TPT_DOWN))
9520 /* Regulate DL Tpt for CPU overload */
9521 if (cell->measurements.dlTpt > cell->cpuOvrLdCntrl.tgtDlTpt)
9523 tptDelta = cell->measurements.dlTpt - cell->cpuOvrLdCntrl.tgtDlTpt;
9524 /* Upto 0.5% drift in measured vs target tpt is ignored */
9525 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtDlTpt) > 5)
9527 cell->thresholds.maxDlItbs = RGSCH_MAX((cell->thresholds.maxDlItbs-1), 1);
9532 tptDelta = cell->cpuOvrLdCntrl.tgtDlTpt - cell->measurements.dlTpt;
9533 /* Upto 0.5% drift in measured vs target tpt is ignored */
9534 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtDlTpt) > 5)
9536 cell->thresholds.maxDlItbs = RGSCH_MIN((cell->thresholds.maxDlItbs+1), RG_SCH_DL_MAX_ITBS);
9539 #ifdef CPU_OL_DBG_PRINTS
9540 DU_LOG("\nINFO --> SCH : DL CPU OL ADJ = %lu, %lu, %d\n", cell->measurements.dlTpt, cell->cpuOvrLdCntrl.tgtDlTpt,
9541 cell->thresholds.maxDlItbs);
9545 if ((cell->cpuOvrLdCntrl.cpuOvrLdIns) & (RGR_CPU_OVRLD_UL_TPT_UP |
9546 RGR_CPU_OVRLD_UL_TPT_DOWN))
9548 /* Regualte DL Tpt for CPU overload */
9549 if (cell->measurements.ulTpt > cell->cpuOvrLdCntrl.tgtUlTpt)
9551 tptDelta = cell->measurements.ulTpt - cell->cpuOvrLdCntrl.tgtUlTpt;
9552 /* Upto 1% drift in measured vs target tpt is ignored */
9553 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtUlTpt) > 10)
9555 cell->thresholds.maxUlItbs = RGSCH_MAX((cell->thresholds.maxUlItbs-1), 1);
9560 tptDelta = cell->cpuOvrLdCntrl.tgtUlTpt - cell->measurements.ulTpt;
9561 /* Upto 1% drift in measured vs target tpt is ignored */
9562 if (((tptDelta*1000)/cell->cpuOvrLdCntrl.tgtUlTpt) > 10)
9564 cell->thresholds.maxUlItbs = RGSCH_MIN((cell->thresholds.maxUlItbs+1), RG_SCH_UL_MAX_ITBS);
9567 #ifdef CPU_OL_DBG_PRINTS
9568 DU_LOG("\nDEBUG --> SCH : UL CPU OL ADJ = %lu, %lu, %d\n", cell->measurements.ulTpt, cell->cpuOvrLdCntrl.tgtUlTpt,
9569 cell->thresholds.maxUlItbs);
9576 * @brief Handler for the num UE per TTI based CPU OvrLd instr updating
9580 * Function : rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr
9583 * - Validate the config params.
9584 * - Update numUEperTTi CPU OL related information.
9585 * - If successful, return ROK else RFAILED.
9587 * @param[in] RgSchCellCb *cell
9588 * @param[in] uint8_t cnrtCpuOvrLdIns
9591 static Void rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr(RgSchCellCb *cell,uint8_t crntCpuOvrLdIns)
9593 RgSchCpuOvrLdCntrlCb *cpuInstr = &(cell->cpuOvrLdCntrl);
9594 RgSchCmnCell *cellSch;
9595 uint8_t maxUeNewDlTxPerTti;
9596 uint8_t maxUeNewUlTxPerTti;
9597 uint8_t tmpslot = 0;
9598 #ifdef CPU_OL_DBG_PRINTS
9601 uint8_t maxDlDecCnt;
9602 uint8_t maxUlDecCnt;
9604 cellSch = RG_SCH_CMN_GET_CELL(cell);
9606 maxUeNewDlTxPerTti = cellSch->dl.maxUeNewTxPerTti;
9607 maxUeNewUlTxPerTti = cellSch->ul.maxUeNewTxPerTti;
9609 /* Calculate Maximum Decremen */
9610 maxDlDecCnt = (10*(maxUeNewDlTxPerTti - 1))-(10-RGR_MAX_PERC_NUM_UE_PER_TTI_RED);
9611 maxUlDecCnt = (10*(maxUeNewUlTxPerTti - 1))-(10-RGR_MAX_PERC_NUM_UE_PER_TTI_RED);
9613 /* Check for DL CPU Commands */
9614 if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_DEC_NUM_UE_PER_TTI )
9616 /* Decrement till 90% of maxUeNewDlTxPerTti */
9617 if ( cpuInstr->dlNxtIndxDecNumUeTti < maxDlDecCnt )
9619 tmpslot = (cpuInstr->dlNxtIndxDecNumUeTti) % 10;
9620 cpuInstr->dlNxtIndxDecNumUeTti++;
9621 if ( cpuInstr->maxUeNewTxPerTti[tmpslot] > 1 )
9623 cpuInstr->maxUeNewTxPerTti[tmpslot]--;
9627 #ifdef CPU_OL_DBG_PRINTS
9628 DU_LOG("\nERROR --> SCH : CPU_OL_TTI__ERROR\n");
9630 DU_LOG("\nERROR --> SCH : Invalid CPU OL");
9633 #ifdef CPU_OL_DBG_PRINTS
9634 DU_LOG("\nDEBUG --> SCH : dlNxtIndxDecNumUeTti = %d\n", cpuInstr->dlNxtIndxDecNumUeTti);
9636 DU_LOG("\nDEBUG --> SCH : dlNxtIndxDecNumUeTti = %d",
9637 cpuInstr->dlNxtIndxDecNumUeTti);
9639 else if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_INC_NUM_UE_PER_TTI )
9641 if ( cpuInstr->dlNxtIndxDecNumUeTti > 0)
9643 cpuInstr->dlNxtIndxDecNumUeTti--;
9644 tmpslot = (cpuInstr->dlNxtIndxDecNumUeTti) % 10;
9645 if ( cpuInstr->maxUeNewTxPerTti[tmpslot] < maxUeNewDlTxPerTti )
9647 cpuInstr->maxUeNewTxPerTti[tmpslot]++;
9651 #ifdef CPU_OL_DBG_PRINTS
9652 DU_LOG("\nERROR --> SCH : CPU_OL_TTI__ERROR\n");
9654 DU_LOG("\nERROR --> SCH : Invalid CPU OL");
9657 #ifdef CPU_OL_DBG_PRINTS
9658 DU_LOG("\nDEBUG --> SCH : dlNxtIndxDecNumUeTti = %d\n", cpuInstr->dlNxtIndxDecNumUeTti);
9660 DU_LOG("\nERROR --> SCH : dlNxtIndxDecNumUeTti = %d",
9661 cpuInstr->dlNxtIndxDecNumUeTti);
9663 /* Check for UL CPU commands */
9664 if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_DEC_NUM_UE_PER_TTI )
9666 /* Decrement till 90% of maxUeNewDlTxPerTti */
9667 if ( cpuInstr->ulNxtIndxDecNumUeTti < maxUlDecCnt )
9669 tmpslot = (cpuInstr->ulNxtIndxDecNumUeTti) % 10;
9670 cpuInstr->ulNxtIndxDecNumUeTti++;
9671 if ( cpuInstr->maxUeNewRxPerTti[tmpslot] > 1 )
9673 cpuInstr->maxUeNewRxPerTti[tmpslot]--;
9677 #ifdef CPU_OL_DBG_PRINTS
9678 DU_LOG("\nERROR --> SCH : CPU_OL_TTI__ERROR\n");
9680 DU_LOG("\nERROR --> SCH : Invalid CPU OL");
9683 #ifdef CPU_OL_DBG_PRINTS
9684 DU_LOG("\nDEBUG --> SCH : ulNxtIndxDecNumUeTti = %d\n", cpuInstr->ulNxtIndxDecNumUeTti);
9686 DU_LOG("\nDEBUG --> SCH : dlNxtIndxDecNumUeTti = %d",
9687 cpuInstr->dlNxtIndxDecNumUeTti);
9689 else if ( crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_INC_NUM_UE_PER_TTI )
9691 if ( cpuInstr->ulNxtIndxDecNumUeTti > 0)
9693 cpuInstr->ulNxtIndxDecNumUeTti--;
9694 tmpslot = (cpuInstr->ulNxtIndxDecNumUeTti) % 10;
9695 if ( cpuInstr->maxUeNewRxPerTti[tmpslot] < maxUeNewUlTxPerTti )
9697 cpuInstr->maxUeNewRxPerTti[tmpslot]++;
9701 #ifdef CPU_OL_DBG_PRINTS
9702 DU_LOG("\nERROR --> SCH : CPU_OL_TTI__ERROR\n");
9704 DU_LOG("\nERROR --> SCH : Invalid CPU OL");
9707 #ifdef CPU_OL_DBG_PRINTS
9708 DU_LOG("\nDEBUG --> SCH : ulNxtIndxDecNumUeTti = %d\n", cpuInstr->ulNxtIndxDecNumUeTti);
9710 DU_LOG("\nDEBUG --> SCH : dlNxtIndxDecNumUeTti = %d",
9711 cpuInstr->dlNxtIndxDecNumUeTti);
9713 #ifdef CPU_OL_DBG_PRINTS
9714 /* TODO: Debug Information - Shall be moved under CPU_OL_DBG_PRINTS */
9715 DU_LOG("\nDEBUG --> SCH : maxUeNewDlTxPerTti = %d, maxUeNewUlTxPerTti = %d\n", maxUeNewDlTxPerTti, maxUeNewUlTxPerTti);
9716 DU_LOG("\nINFO --> SCH : DL Sf numUePerTti:");
9717 for ( idx = 0; idx < 10 ; idx ++ )
9719 DU_LOG(" %d", cpuInstr->maxUeNewTxPerTti[idx]);
9721 DU_LOG("\nINFO --> SCH : UL Sf numUePerTti:");
9722 for ( idx = 0; idx < 10 ; idx ++ )
9724 DU_LOG(" %d", cpuInstr->maxUeNewRxPerTti[idx]);
9730 } /* rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr */
9733 * @brief Handler for the CPU OvrLd related cell Recfg.
9737 * Function : rgSCHUtlResetCpuOvrLdState
9740 * - Validate the config params.
9741 * - Update CPU OL related state information.
9742 * - If successful, return ROK else RFAILED.
9744 * @param[in] RgSchCellCb *cell
9745 * @param[in] uint8_t cnrtCpuOvrLdIns
9750 S16 rgSCHUtlResetCpuOvrLdState(RgSchCellCb *cell,uint8_t crntCpuOvrLdIns)
9752 uint8_t crntDlCpuOL=0;
9753 uint8_t crntUlCpuOL=0;
9754 RgSchCmnCell *schCmnCell = (RgSchCmnCell *)(cell->sc.sch);
9757 #ifdef CPU_OL_DBG_PRINTS
9758 DU_LOG("\nDEBUG --> SCH : CPU OVR LD Ins Rcvd = %d\n", (int)crntCpuOvrLdIns);
9760 DU_LOG("\nINFO --> SCH : CPU OVR LD Ins Rcvd");
9762 if ( RGR_CPU_OVRLD_RESET == crntCpuOvrLdIns )
9764 /* The CPU OL instruction received with RESET (0), hence reset it */
9765 #ifdef CPU_OL_DBG_PRINTS
9766 DU_LOG("\nDEBUG --> SCH : rgSCHUtlResetCpuOvrLdState: RESET CPU OL instr\n");
9768 DU_LOG("\nINFO --> SCH : RESET CPU OVR LD");
9769 cell->cpuOvrLdCntrl.cpuOvrLdIns = 0;
9770 /* Reset the max UL and DL itbs to 26 */
9771 cell->thresholds.maxUlItbs = RG_SCH_UL_MAX_ITBS;
9772 cell->thresholds.maxDlItbs = RG_SCH_DL_MAX_ITBS;
9773 /* Reset the num UE per TTI intructions */
9774 cell->cpuOvrLdCntrl.dlNxtIndxDecNumUeTti = 0;
9775 cell->cpuOvrLdCntrl.ulNxtIndxDecNumUeTti = 0;
9776 for ( idx = 0; idx < 10; idx++ )
9778 cell->cpuOvrLdCntrl.maxUeNewTxPerTti[idx] =
9779 schCmnCell->dl.maxUeNewTxPerTti;
9780 cell->cpuOvrLdCntrl.maxUeNewRxPerTti[idx] =
9781 schCmnCell->ul.maxUeNewTxPerTti;
9786 /* Check and Update numUEPer TTI based CPU overload instruction before
9787 * going for TP based CPU OL
9788 * TTI based intrcuctions shall be > 0xF */
9789 if ( crntCpuOvrLdIns > 0xF )
9791 rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr(cell, crntCpuOvrLdIns);
9792 /* If need to have both TP and numUePerTti instrcution together in
9793 * one command then dont return from here */
9797 crntDlCpuOL = (crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_TPT_UP) +\
9798 (crntCpuOvrLdIns & RGR_CPU_OVRLD_DL_TPT_DOWN);
9799 if ((crntDlCpuOL) && (crntDlCpuOL != RGR_CPU_OVRLD_DL_TPT_UP) &&
9800 (crntDlCpuOL != RGR_CPU_OVRLD_DL_TPT_DOWN))
9802 /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9805 crntUlCpuOL = (crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_TPT_UP) +\
9806 (crntCpuOvrLdIns & RGR_CPU_OVRLD_UL_TPT_DOWN);
9807 if ((crntUlCpuOL) && (crntUlCpuOL != RGR_CPU_OVRLD_UL_TPT_UP) &&
9808 (crntUlCpuOL != RGR_CPU_OVRLD_UL_TPT_DOWN))
9810 /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9813 if ((crntDlCpuOL == 0) && (crntUlCpuOL == 0))
9815 /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9819 cell->cpuOvrLdCntrl.cpuOvrLdIns = crntCpuOvrLdIns;
9823 if (crntUlCpuOL == RGR_CPU_OVRLD_UL_TPT_DOWN)
9825 cell->cpuOvrLdCntrl.tgtUlTpt = cell->measurements.ulTpt - \
9826 (cell->measurements.ulTpt * 3 )/100;
9830 cell->cpuOvrLdCntrl.tgtUlTpt = cell->measurements.ulTpt + \
9831 (cell->measurements.ulTpt * 2 )/100;
9833 DU_LOG("\nDEBUG --> SCH : CPU OVR LD UL Reset to "
9834 "%d, %u, %u", (int)crntUlCpuOL, cell->cpuOvrLdCntrl.tgtUlTpt,cell->measurements.ulTpt);
9835 #ifdef CPU_OL_DBG_PRINTS
9836 DU_LOG("\nDEBUG --> SCH : CPU OVR LD UL Reset to= %d, %u, %u\n", (int)crntUlCpuOL, cell->cpuOvrLdCntrl.tgtUlTpt,
9837 cell->measurements.ulTpt);
9843 if (crntDlCpuOL == RGR_CPU_OVRLD_DL_TPT_DOWN)
9845 cell->cpuOvrLdCntrl.tgtDlTpt = cell->measurements.dlTpt - \
9846 (cell->measurements.dlTpt * 1 )/100;
9850 cell->cpuOvrLdCntrl.tgtDlTpt = cell->measurements.dlTpt + \
9851 (cell->measurements.dlTpt * 1 )/100;
9853 DU_LOG("\nDEBUG --> SCH : CPU OVR LD DL Reset to "
9854 "%d, %u, %u", (int)crntDlCpuOL, cell->cpuOvrLdCntrl.tgtDlTpt,cell->measurements.dlTpt);
9856 #ifdef CPU_OL_DBG_PRINTS
9857 DU_LOG("\nDEBUG --> SCH : CPU OVR LD DL Reset to= %d, %lu, %lu\n", (int)crntDlCpuOL, cell->cpuOvrLdCntrl.tgtDlTpt,
9858 cell->measurements.dlTpt);
9861 rgSCHUtlCpuOvrLdAdjItbsCap(cell);
9865 S16 rgSCHUtlAddToResLst
9871 cmLListAdd2Tail(cp, &iotRes->resLnk);
9872 iotRes->resLnk.node = (PTR)iotRes;
9875 S16 rgSCHUtlDelFrmResLst
9881 CmLListCp *cp = NULLP;
9882 RgSchEmtcUeInfo *emtcUe = NULLP;
9883 emtcUe = RG_GET_EMTC_UE_CB(ue);
9884 if(iotRes->resType == RG_SCH_EMTC_PUCCH_RES)
9886 cp = &emtcUe->ulResLst;
9887 }else if(iotRes->resType == RG_SCH_EMTC_PDSCH_RES)
9889 cp = &emtcUe->dlResLst;
9892 DU_LOG("\nINFO --> SCH : *****restype mismatch");
9898 DU_LOG("\nINFO --> SCH : ****error count*****\n");
9902 cmLListDelFrm(cp, &iotRes->resLnk);
9903 iotRes->resLnk.node = NULLP;
9907 /**********************************************************************
9910 **********************************************************************/