Merge "RLC DL UMD PDU changes [Issue-ID: ODUHIGH-271]"
[o-du/l2.git] / src / 5gnrsch / rg_sch_utl.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
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                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
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 *******************************************************************************/
18
19 /************************************************************************
20
21      Name:     LTE-MAC layer
22
23      Type:     C source file
24
25      Desc:     C source code for Entry point fucntions
26
27      File:     rg_sch_utl.c
28
29 **********************************************************************/
30
31 /** @file rg_sch_utl.c
32 @brief This file implements the schedulers main access to MAC layer code.
33 */
34
35
36 /* header include files -- defines (.h) */
37 #include "common_def.h"
38 #include "lrg.h"
39 #include "rgr.h"
40 #include "tfu.h"
41 #include "rg_env.h"
42 #include "rg_sch_err.h"
43 #include "rg_sch_inf.h"
44 #include "rg_sch.h"
45 #include "rg_sch_cmn.h"
46 #include "rgm.h"
47 #include "rl_interface.h"
48 #include "rl_common.h"
49
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 */
54 #include "rgm.x"
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 */
58 #ifdef EMTC_ENABLE
59 #include "rg_sch_emtc_ext.x"
60 #endif
61
62
63 /* SR_RACH_STATS */
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 */
93
94 uint32_t rgNumDedPreamUECtxtFound =0;         /* Num of Dedicated Preambles recvd */
95
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};
102
103 /* local defines */
104
105 uint32_t rgSchCmnBetaCqiOffstTbl[16];
106 uint32_t rgSchCmnBetaRiOffstTbl[16]; 
107 RgSchdApis rgSchCmnApis;
108 S16 RgUiRgmSendPrbRprtInd ARGS((
109 Pst* pst, 
110 SuId suId, 
111 RgmPrbRprtInd *prbRprtInd
112 ));
113
114 S16 RgUiRgmSendTmModeChangeInd ARGS((
115 Pst* pst, 
116 SuId suId, 
117 RgmTransModeInd *txModeChngInd
118 ));
119 #ifdef EMTC_ENABLE
120 S16 rgSCHEmtcUtlGetSfAlloc ARGS((
121 RgSchCellCb *cell
122 ));
123 S16 rgSCHEmtcUtlPutSfAlloc ARGS((
124 RgSchCellCb *cell
125 ));
126 Void rgSCHEmtcUtlUpdUeDciSize ARGS((
127 RgSchCellCb *cell,
128 RgSchUeCb *ueCb
129 ));
130 Void rgSCHEmtcGetDciFrmt61ASize ARGS((
131 RgSchCellCb *cell
132 ));
133 Void rgSCHEmtcGetDciFrmt60ASize ARGS((
134 RgSchCellCb *cell
135 ));
136 S16 rgSCHEmtcUtlFillPdschDciInfo ARGS((
137 TfuPdschDciInfo *pdsch,
138 TfuDciInfo      *pdcchDci
139 ));
140 Void rgSCHEmtcUtlRlsRnti ARGS((
141 RgSchCellCb *cell,
142 RgSchRntiLnk   *rntiLnk,
143 uint8_t             *isLegacy
144 ));
145 S16 rgSCHEmtcPdcchAlloc ARGS((
146 RgSchCellCb *cell,
147 RgSchPdcch  *pdcch
148 ));
149 Void rgSCHEmtcPdcchFree ARGS((
150 RgSchCellCb *cell,
151 RgSchPdcch  *pdcch
152 ));
153 #endif
154 /* Functions specific to TM1/TM2/TM6/TM7 for PRB calculation*/
155 Void rgSchUtlDlCalc1CwPrb ARGS(( RgSchCellCb    *cell,
156                                         RgSchUeCb      *ue,
157                                         uint32_t             bo,
158                                         uint32_t            *prbReqrd));
159
160 /* Functions specific to TM3/TM4 for PRB calculation*/
161 Void rgSchUtlDlCalc2CwPrb ARGS(( RgSchCellCb    *cell,
162                                         RgSchUeCb      *ue,
163                                         uint32_t             bo,
164                                         uint32_t            *prbReqrd));
165
166 #ifdef LTE_ADV
167 RgSchCellCb* rgSchUtlGetCellCb ARGS(( Inst       inst,
168                                              uint16_t        cellId
169 ));
170 #endif
171
172 typedef Void (*RgSchUtlDlCalcPrbFunc) ARGS((RgSchCellCb *cell, RgSchUeCb *ue,
173                                             uint32_t bo, uint32_t *prbRequrd));
174 #ifndef LTE_ADV
175 /* Functions specific to each transmission mode for PRB calculation*/
176 RgSchUtlDlCalcPrbFunc  dlCalcPrbFunc[7] = {rgSchUtlDlCalc1CwPrb,
177 rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc2CwPrb, rgSchUtlDlCalc2CwPrb,
178 NULLP, rgSchUtlDlCalc1CwPrb, rgSchUtlDlCalc1CwPrb};
179
180 #else
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};
185
186 #endif
187
188 #ifdef LTE_TDD
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};
192 #endif
193
194 static S16 rgSCHUtlUlAllocDbInit ARGS((
195          RgSchCellCb    *cell,
196          RgSchUlAllocDb *db,
197          uint8_t maxAllocs
198          ));
199 static Void rgSCHUtlUlAllocDbDeinit ARGS((
200          RgSchCellCb    *cell,
201          RgSchUlAllocDb *db
202          ));
203 static S16 rgSCHUtlUlHoleDbInit ARGS((
204          RgSchCellCb    *cell,
205          RgSchUlHoleDb *db,
206          uint8_t maxHoles,
207          uint8_t start,
208          uint8_t num
209          ));
210 static Void rgSCHUtlUlHoleDbDeinit ARGS((
211          RgSchCellCb   *cell,
212          RgSchUlHoleDb *db
213          ));
214
215 static S16 rgSCHChkBoUpdate ARGS((
216          RgSchCellCb    *cell,
217          RgInfCmnBoRpt  *boUpdt
218          ));
219 #ifdef UNUSE_FUN
220 #ifdef TFU_UPGRADE
221 static uint8_t rgSCHUtlFetchPcqiBitSz ARGS((
222  RgSchCellCb    *cell,
223  RgSchUeCb      *ueCb, 
224  uint8_t        numTxAnt
225  ));
226 #endif
227 #endif
228 /* sorted in ascending order of tbSz */
229 const struct rgSchUtlBcchPcchTbSz
230 {
231    uint8_t   rbIndex;    /* RB index {2,3} */
232    uint16_t  tbSz;       /* one of the Transport block size in bits of
233                      * rbIndex 2 or 3 */
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 }
248 };
249
250 /* local typedefs */
251
252 /* local externs */
253
254 /* forward references */
255 #ifdef LTE_TDD
256 static Void rgSCHUtlUpdPrachOcc ARGS((
257 RgSchCellCb *cell,
258 RgrTddPrachInfo *cellCfg));
259 #endif
260
261 #define RGSCH_NUM_PCFICH_REG 4
262 #define RGSCH_NUM_REG_PER_CCE 9
263 #define RGSCH_NUM_REG_PER_PHICH_GRP 3
264
265 #ifdef LTE_TDD
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); \
274 }
275 #else
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); \
284 }
285 #endif
286
287 #define RGSCH_PHICH_ALLOC(_inst,_dataPtr, _size, _ret) {\
288    _ret = rgSCHUtlAllocSBuf(_inst, (Data **)&_dataPtr, _size); \
289 }
290
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); \
295 }
296
297 #ifdef TFU_UPGRADE
298 #define RGSCH_GETBIT(a, b)     ((((uint8_t*)a)[(b)>>3] >> ((7-((b)&7)))) & 1)
299
300 /*
301 *
302 *       Fun:   rgSCHUtlPower
303 *
304 *       Desc:  This function finds of the Power of x raised to n
305 *
306 *       Ret:   value of x raised to n
307 *
308 *       Notes: None
309 *
310 *       File:  rg_sch_utl.c
311 *
312 */
313 F64 rgSCHUtlPower(F64 x,F64 n)
314 {
315  if( n==0 )
316  {
317    return ( 1 );
318  }
319  else if ( n>0 )
320  {
321    return ( x * rgSCHUtlPower( x, n-1 ) );
322  }
323  else
324  {
325    return ( (1/x) * rgSCHUtlPower( x, n+1 ) );
326  }
327 } /* end of rgSCHUtlPower*/
328
329 /*
330 *
331 *       Fun:   rgSCHUtlParse
332 *
333 *       Desc:  This function parses bits x to y of an array and
334 *                  returns the integer value  out of it.
335 *
336 *       Ret:   integer value of z bits
337 *
338 *       Notes: None
339 *
340 *       File:  rg_sch_utl.c
341 *
342 */
343 uint32_t rgSCHUtlParse(uint8_t *buff,uint8_t startPos,uint8_t endPos,uint8_t buffSize)
344 {
345  uint8_t pointToChar,pointToEnd, loop;
346  uint8_t size =  endPos - startPos;
347  F64 result = 0;
348  pointToEnd = (startPos)%8;
349    for ( loop=0; loop<size; loop++)
350    {
351       pointToChar = (((startPos)+loop)/8);
352       if (RGSCH_GETBIT(buff+pointToChar,pointToEnd%8)==1)
353       {
354          result=result+(rgSCHUtlPower(2,(size-loop-1)));
355       }
356       pointToEnd++;
357    }
358    return ((uint32_t)result);
359 } /* end of rgSCHUtlParse*/
360
361 /*
362 *
363 *       Fun:   rgSCHUtlFindDist
364 *
365 *       Desc:  This function calculates the iterations need to cover
366 *                  before the valid Index can be used for next possible Reception
367 *
368 *       Ret:   integer value of z bits
369 *
370 *       Notes: None
371 *
372 *       File:  rg_sch_utl.c
373 *
374 */
375 uint8_t rgSCHUtlFindDist(uint16_t crntTime,uint16_t tempIdx)
376 {
377  uint8_t  dist =0;
378  /* ccpu00137113- Distance is not estimated properly if the periodicity is 
379   * equal to RG_SCH_PCQI_SRS_SR_TRINS_SIZE.
380   */
381  while(crntTime<=tempIdx)
382  {
383     crntTime += RG_SCH_PCQI_SRS_SR_TRINS_SIZE;
384     dist+=1;
385  }
386  return (dist-1);
387 } /* end of rgSCHUtlFindDist*/
388 #endif
389
390 \f
391 /**
392  * @brief This function checks availability of a PDCCH
393  *
394  * @details
395  *
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.
401  *               steps:
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.
409  *
410  *     Invoked by: scheduler
411  *
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
417  *  @return  Boolean
418  *         -#   TRUE  if available
419  *         -#   FALSE otherwise
420  *
421  **/
422 Bool rgSCHUtlPdcchAvail
423 (
424 RgSchCellCb    *cell,
425 RgSchPdcchInfo *pdcchInfo,
426 CmLteAggrLvl   aggrLvl,
427 RgSchPdcch     **pdcch
428 )
429 {
430    uint8_t             *byte;
431    uint16_t             offset;
432    uint16_t             initMask;
433    uint16_t             currMask;
434    Inst                 inst = cell->instIdx;
435    S16                  ret;
436    uint16_t             offsetStepMask;
437
438    /* V5G_213 : 10.1 */
439         offset = 0;
440         byte = &pdcchInfo->map[0];
441         initMask = (0xffff >> (16 - aggrLvl));
442         currMask = initMask;
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}
445           */
446         if ((cell->cell5gtfCb.cfi == 2) && (aggrLvl == CM_LTE_AGGR_LVL2))
447         {
448                 offsetStepMask = 0xc;
449         }
450         else
451         {
452                 offsetStepMask = 0xc0;
453         }
454
455         /* Loop till the number of bytes available in the CCE map */
456         while (offset < ((pdcchInfo->nCce+ 7) >> 3))
457         {
458            byte = &pdcchInfo->map[offset];
459                 /* Checking for available CCE */
460                 if ((*byte & currMask) == 0)
461            {
462               break;
463            }
464                 /* if the number of CCEs required are not available, move to next offset */
465                 if (currMask & offsetStepMask)
466                 {
467                         offset++;
468                         currMask = initMask;
469                 }
470                 else
471                 {
472                    /* Move to the next available CCE index in the current byte(cce map) */
473                         currMask = currMask << aggrLvl;
474                 }
475         }
476
477         if ((offset >= ((pdcchInfo->nCce + 7) >> 3)) || 
478                   ((aggrLvl == CM_LTE_AGGR_LVL16) && (offset > 0)))
479         {
480                 return (FALSE);
481         }
482
483         byte = &pdcchInfo->map[offset];
484    
485    if (cell->pdcchLst.first != NULLP)
486    {
487       *pdcch = (RgSchPdcch *)(cell->pdcchLst.first->node);
488       cmLListDelFrm(&cell->pdcchLst, cell->pdcchLst.first);
489    }
490    else
491    {
492       ret = rgSCHUtlAllocSBuf(inst, (Data **)pdcch, sizeof(RgSchPdcch));
493       if(ROK != ret)
494       {
495          return (FALSE);
496       }
497    }
498
499    if (*pdcch)
500    {
501       (*byte) |= currMask;
502                 /* ALL CCEs will be used in case of level 16 */
503                 if (aggrLvl == CM_LTE_AGGR_LVL16)
504                 {
505                         *(byte+1) |= currMask;
506                 }
507       (*pdcch)->aggrLvl = aggrLvl;
508       cmLListAdd2Tail(&pdcchInfo->pdcchs, &((*pdcch)->lnk));
509       (*pdcch)->lnk.node = (PTR)*pdcch;
510       (*pdcch)->nCce = aggrLvl;
511       (*pdcch)->ue = NULLP;
512    }
513    return (TRUE);
514 }
515
516
517 \f
518 /**
519  * @brief This function releases a PDCCH
520  *
521  * @details
522  *
523  *     Function: rgSCHUtlPdcchPut
524  *     Purpose:  This function releases a PDCCH.
525  *               steps:
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
530  *
531  *     Invoked by: scheduler
532  *
533  *  @param[in]  RgSchPdcchInfo*  pdcchInfo
534  *  @param[in]  uint8_t            loc
535  *  @param[in]  uint8_t            aggrLvl
536  *  @return     Void
537  *
538  **/
539 Void rgSCHUtlPdcchPut(RgSchCellCb *cell,RgSchPdcchInfo *pdcchInfo,RgSchPdcch *pdcch)
540 {
541    uint8_t              *byte;
542    uint8_t              offset;
543    uint16_t             mask;
544
545    switch(pdcch->aggrLvl)
546    {
547       case CM_LTE_AGGR_LVL2:
548          offset = (pdcch->nCce >> 1) & 3;
549          mask = 0x3 << (offset * 2); /*ccpu00128826 - Offset Correction */
550          break;
551       case CM_LTE_AGGR_LVL4:
552          offset = (pdcch->nCce >> 2) & 1;
553          mask = 0xf << (offset * 4);/*ccpu00128826 - Offset Correction */
554          break;
555       case CM_LTE_AGGR_LVL8:
556          mask = 0xff;
557          break;
558                 case CM_LTE_AGGR_LVL16:
559          mask = 0xffff;
560          break;
561       default:
562          return;
563    }
564    /* Placing common computation of byte from all the cases above here
565       for optimization */
566    byte = &pdcchInfo->map[pdcch->nCce >> 3];
567
568    cmLListDelFrm(&pdcchInfo->pdcchs, &pdcch->lnk);
569    cmLListAdd2Tail(&cell->pdcchLst, &pdcch->lnk);
570    pdcch->lnk.node = (PTR)pdcch;
571    pdcch->ue = NULLP;
572    (*byte) &= ~mask;
573
574   return;
575 }
576
577 \f
578 /**
579  * @brief This function initializes PDCCH information for frame
580  *
581  * @details
582  *
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.
587  *
588  *     Invoked by: rgSCHUtlSubFrmPut
589  *
590  *  @param[in]  RgSchCellCb*     cell
591  *  @param[in]  RgSubFrm*     subFrm
592  *  @return  Void
593  *
594  **/
595 Void rgSCHUtlPdcchInit(RgSchCellCb *cell,RgSchDlSf *subFrm,uint16_t nCce)
596 {
597    RgSchPdcchInfo       *pdcchInfo;
598    RgSchPdcch           *pdcch;
599    Inst                 inst = cell->instIdx;
600    uint8_t              extraBits;
601    uint32_t             cceMapSz;
602
603    pdcchInfo = &subFrm->pdcchInfo;
604    while(pdcchInfo->pdcchs.first != NULLP)
605    {
606       pdcch = (RgSchPdcch *)pdcchInfo->pdcchs.first->node;
607       cmLListDelFrm(&pdcchInfo->pdcchs, pdcchInfo->pdcchs.first);
608       cmLListAdd2Tail(&cell->pdcchLst, &pdcch->lnk);
609       pdcch->ue = NULLP;
610    }
611    cmLListInit(&pdcchInfo->pdcchs);
612    
613 #ifdef LTEMAC_SPS
614    subFrm->relPdcch = NULLP;
615 #endif
616    
617    cceMapSz = ((pdcchInfo->nCce + 7) >> 3);
618
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                      */
622
623    if(pdcchInfo->nCce != nCce)
624    {
625       if(pdcchInfo->nCce)
626       {
627         rgSCHUtlFreeSBuf(inst, (Data **)(&(pdcchInfo->map)), cceMapSz);
628       }
629       pdcchInfo->nCce = nCce;
630       cceMapSz = ((pdcchInfo->nCce + 7) >> 3);
631       rgSCHUtlAllocSBuf(inst, (Data **)&pdcchInfo->map,  
632       cceMapSz);
633       if (pdcchInfo->map == NULLP)
634       {
635          /* Generate log error here */
636          return;
637       }    
638    }
639
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);
649    return;
650 }
651
652 /* LTE_ADV_FLAG_REMOVED_START */
653 /**
654  * @brief This function frees Pool
655  * @details
656  *
657  *     Function: rgSchSFRTotalPoolFree
658  *
659  *     Invoked by: rgSchSFRTotalPoolInit
660  *
661  *  @param[in]  RgSchCellCb*     cell
662  *  @param[in]  RgSubFrm*     subFrm
663  *  @return  Void
664  *
665  **/
666 Void rgSchSFRTotalPoolFree(RgSchSFRTotalPoolInfo *sfrTotalPoolInfo,RgSchCellCb *cell)
667 {
668    CmLListCp   *l;
669    CmLList     *n;
670
671    /*Deinitialise if  these cc pools and ce pools are already existent*/
672    l = &sfrTotalPoolInfo->ccPool;
673    n = cmLListFirst(l);
674    while (n != NULL)
675    {
676       /*REMOVING Cell Centred POOLS IF ANY*/
677       n = cmLListDelFrm(l, n);
678
679       /* Deallocate buffer */
680       rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n->node)), sizeof(RgSchSFRPoolInfo));
681
682       /* Deallocate buffer */
683       rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n)), sizeof(CmLList));   
684       n = cmLListNext(l);
685    }
686
687    /*REMOVING Cell Edged POOLS IF ANY*/
688    l = &sfrTotalPoolInfo->cePool;
689    n = cmLListFirst(l);
690    while (n != NULL)
691    {
692       n = cmLListDelFrm(l, n);
693
694       /* Deallocate buffer */
695       rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n->node)), sizeof(RgSchSFRPoolInfo));
696
697       /* Deallocate buffer */
698       rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(n)), sizeof(CmLList));   
699       n = cmLListNext(l);
700    } 
701
702 }
703
704 /**
705  * @brief This function resets temporary variables in Pool
706  * @details
707  *
708  *     Function: rgSchSFRResetPoolVariables
709  *
710  *     Invoked by: rgSCHSFRUtlTotalPoolInit
711  *
712  *  @param[in]  RgSchCellCb*     cell
713  *  @param[in]  RgSubFrm*     subFrm
714  *  @return  Void
715  *
716  **/
717 S16 rgSchSFRTotalPoolInit(RgSchCellCb *cell,RgSchDlSf *sf)
718 {      
719    /*  Initialise the variables */
720    RgSchSFRPoolInfo *sfrCCPool;
721    RgSchSFRPoolInfo *sfrCEPool;
722    CmLListCp   *l;
723    CmLList     *n;
724    CmLList *temp = NULLP;
725    S16 ret = 0;
726
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));
735
736    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
737    if (ret != ROK)
738    {
739       DU_LOG("\nERROR  -->  SCH : CE Pool memory allocation FAILED for cell");       
740       rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo, cell);
741       return RFAILED;
742    }
743
744    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
745    if (ret != ROK)
746    {
747       DU_LOG("\nERROR  -->  SCH : CE Pool memory allocation FAILED for cell ");       
748       rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
749       return RFAILED;
750    }
751
752    l = &sf->sfrTotalPoolInfo.cePool;
753    cmLListAdd2Tail(l, temp);
754
755    /*Initialise Bandwidth and startRB and endRB for each pool*/
756    n = cmLListFirst(l);
757
758    /* Initialise the CE Pools */
759    sfrCEPool = (RgSchSFRPoolInfo*)n->node;
760
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;
765
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;
772
773    /*Initialise CC Pool*/
774    cmLListInit (&(sf->sfrTotalPoolInfo.ccPool));
775
776    /*Add memory and Update CCPool*/
777    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
778    if (ret != ROK)
779    {
780       DU_LOG("\nERROR  -->  SCH : CC Pool memory allocation FAILED for cell ");       
781       rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
782       return RFAILED;
783    }
784
785    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
786    if (ret != ROK)
787    {
788       DU_LOG("\nERROR  -->  SCH : CC Pool memory allocation FAILED for cell ");       
789       rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
790       return RFAILED;
791    }
792
793    l = &sf->sfrTotalPoolInfo.ccPool;
794    cmLListAdd2Tail(l, temp);
795
796    /*Initialise Bandwidth and startRB and endRB for each pool*/
797    if(sfrCEPool->poolstartRB)
798    {
799       n = cmLListFirst(l);
800       sfrCCPool = (RgSchSFRPoolInfo*)n->node;
801
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;
813    }
814    else
815    {
816       n = cmLListFirst(l);
817       sfrCCPool = (RgSchSFRPoolInfo*)n->node;
818
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;
832    }
833
834    if((sfrCEPool->poolendRB != sf->bw - 1) && (!sfrCCPool->poolstartRB))
835    {    
836       /*Add memory and Update CCPool*/
837       ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp, sizeof(CmLList));
838       if (ret != ROK)
839       {
840          DU_LOG("\nERROR  -->  SCH : CC Pool memory allocation FAILED for cell ");       
841          rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
842          return RFAILED;
843       }
844
845       ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&temp->node, sizeof(RgSchSFRPoolInfo));
846       if (ret != ROK)
847       {
848          DU_LOG("\nERROR  -->  SCH : CC Pool memory allocation FAILED for cell ");       
849          rgSchSFRTotalPoolFree(&sf->sfrTotalPoolInfo,cell);
850          return RFAILED;
851       }
852
853       cmLListAdd2Tail(l, temp);
854
855       n = cmLListCrnt(l);
856       sfrCCPool = (RgSchSFRPoolInfo*)n->node;
857
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;
871    }   
872
873    sf->sfrTotalPoolInfo.CCRetx            = FALSE;
874    sf->sfrTotalPoolInfo.CERetx            = FALSE;
875
876    sf->sfrTotalPoolInfo.ccBwFull          = FALSE;
877    sf->sfrTotalPoolInfo.ceBwFull          = FALSE;
878    sf->sfrTotalPoolInfo.isUeCellEdge      = FALSE;
879    return ROK;
880 }
881 /**
882  * @brief This function resets temporary variables in RNTP Prepration
883  * @details
884  *
885  *     Function:   rgSchDSFRRntpInfoInit 
886  *
887  *     Invoked by: rgSCHSFRUtlTotalPoolInit
888  *
889  *  @param[in]  TknStrOSXL*     rntpPtr
890  *  @param[in]  RgSubFrm*        subFrm
891  *  @return  S16
892  *
893  **/
894 S16   rgSchDSFRRntpInfoInit(TknStrOSXL  *rntpPtr,RgSchCellCb *cell,uint16_t bw)
895 {   
896    Inst inst = cell->instIdx;
897    uint16_t len;
898
899    rntpPtr->pres = PRSNT_NODEF;
900
901    len = (bw % 8 == 0) ? (bw/8) : (bw/8 + 1);
902
903    rntpPtr->len  = len;   
904
905    /* Allocate memory for "scheduled UE" Info */
906    if((rgSCHUtlAllocSBuf(inst, (Data**)&(rntpPtr->val),
907                (len * sizeof(uint8_t)))) != ROK)
908    {
909       DU_LOG("\nERROR  -->  SCH : Memory allocation FAILED for RNTP Alloc");
910       return RFAILED;
911    }
912
913    return ROK;
914 }
915
916 /**
917  * @brief This function release RNTP pattern from slot and Cell 
918  * @details
919  *
920  *     Function:   rgSchDSFRRntpInfoFree 
921  *
922  *     Invoked by: rgSCHSFRUtlTotalPoolInit
923  *
924  *  @param[in]  TknStrOSXL*     rntpPtr
925  *  @param[in]  RgSubFrm*        subFrm
926  *  @return  S16
927  *
928  **/
929 S16   rgSchDSFRRntpInfoFree(TknStrOSXL *rntpPtr,RgSchCellCb *cell,uint16_t bw)
930 {   
931    Inst inst = cell->instIdx;
932    uint16_t len;
933
934    len = (bw % 8 == 0) ? (bw/8) : (bw/8 + 1);
935
936    if(rntpPtr->pres == PRSNT_NODEF)
937    {   
938       rgSCHUtlFreeSBuf(inst, (Data **)(&(rntpPtr->val)),(len * sizeof(uint8_t)));
939       rntpPtr->pres = NOTPRSNT;
940       rntpPtr->len  = 0;   
941    }
942
943    return ROK;
944 }
945
946 /**
947  * @brief This function resets temporary variables in Pool
948  * @details
949  *
950  *     Function: rgSchSFRResetPoolVariables
951  *     Purpose:  Initialise the dynamic variables in each pool.
952  *                    Reset bwAlloced, bwAssigned, type2End, type0End, type2Start
953  *     Invoked by: rgSCHSFRUtlTotalPoolReset
954  *
955  *  @param[in]  RgSchCellCb*     cell
956  *  @param[in]  RgSchSFRPoolInfo *pool
957  *  @return  Void
958  *
959  **/
960 static Void rgSchSFRResetPoolVariables(RgSchCellCb *cell,RgSchSFRPoolInfo *pool)
961 {
962
963    pool->bwAlloced  = 0;
964
965    /*type0end will be the last RBG in pool with all available RBs*/
966    pool->type0End = (((pool->poolendRB + 1)/cell->rbgSize) - 1);
967
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;
972
973       return;
974 }
975 /**
976  * @brief This function resets SFR Pool information for frame
977  *
978  * @details
979  *
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
984  *
985  *  @param[in]  RgSchCellCb*     cell
986  *  @param[in]  RgSchDlSf*     subFrm
987  *  @return  Void
988  *
989  **/
990 static Void rgSCHSFRUtlTotalPoolReset(RgSchCellCb *cell,RgSchDlSf *subFrm)
991 {
992    RgSchSFRTotalPoolInfo *totalPoolInfo = &subFrm->sfrTotalPoolInfo;
993    CmLListCp    *ccPool = &totalPoolInfo->ccPool;
994    CmLListCp    *cePool = &totalPoolInfo->cePool;
995    CmLList *node = NULLP;
996    RgSchSFRPoolInfo *tempPool = NULLP;
997
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;
1006
1007    node = ccPool->first;
1008    while(node)
1009    {
1010       tempPool = (RgSchSFRPoolInfo *)(node->node);
1011       node = node->next;
1012       rgSchSFRResetPoolVariables(cell, tempPool);
1013       if(tempPool->poolstartRB == 0)
1014          totalPoolInfo->CCPool1BwAvlbl = tempPool->bw;
1015       else
1016          totalPoolInfo->CCPool2BwAvlbl = tempPool->bw;
1017    }
1018
1019    node = cePool->first;
1020    while(node)
1021    {
1022       tempPool = (RgSchSFRPoolInfo *)(node->node);
1023       node = node->next;
1024       rgSchSFRResetPoolVariables(cell, tempPool);
1025       totalPoolInfo->CEPoolBwAvlbl = tempPool->bw;    
1026    }
1027
1028    return;
1029 }
1030 /* LTE_ADV_FLAG_REMOVED_END */
1031 /**
1032  * @brief This function appends PHICH information for frame
1033  *
1034  * @details
1035  *
1036  *     Function: rgSCHUtlAddPhich
1037  *     Purpose:  This function appends PHICH information for
1038  *               a slot.
1039  *
1040  *     Invoked by: TOM
1041  *
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
1047  *  @return  S16
1048  *      -# ROK
1049  *      -# RFAILED
1050  **/
1051 #ifdef LTE_TDD
1052 S16 rgSCHUtlAddPhich
1053 (
1054 RgSchCellCb     *cell,
1055 CmLteTimingInfo frm,
1056 uint8_t         hqFeedBack,
1057 uint8_t         nDmrs,
1058 uint8_t         rbStart,
1059 uint8_t         iPhich
1060 )
1061 #else
1062 S16 rgSCHUtlAddPhich
1063 (
1064 RgSchCellCb     *cell,
1065 CmLteTimingInfo frm,
1066 uint8_t         hqFeedBack,
1067 uint8_t         nDmrs,
1068 uint8_t         rbStart,
1069 Bool            isForMsg3
1070 )
1071 #endif
1072 {
1073    S16                ret;
1074    RgSchPhich         *phich;
1075    RgSchDlSf          *dlSf;
1076    Inst               inst = cell->instIdx;
1077
1078    dlSf = rgSCHUtlSubFrmGet(cell, frm);
1079    RGSCH_PHICH_ALLOC(inst, phich,sizeof(RgSchPhich), ret);
1080
1081    if(ret != ROK)
1082    {
1083       DU_LOG("\nERROR  -->  SCH : rgSCHUtlAddPhich(): "
1084                "Allocation of RgSchPhich failed");
1085       return RFAILED;
1086    }
1087 #ifdef LTE_TDD
1088    RGSCH_INITPHICH(phich, hqFeedBack, nDmrs, rbStart, iPhich);
1089 #else
1090    RGSCH_INITPHICH(phich, hqFeedBack, nDmrs, rbStart, isForMsg3); /*SR_RACH_STATS */
1091 #endif
1092    cmLListAdd2Tail(&dlSf->phichInfo.phichs, &phich->lnk);
1093    return ROK;
1094 } /* rgSCHUtlAddPhich */
1095
1096 /**
1097  * @brief This function resets PHICH information for frame
1098  *
1099  * @details
1100  *
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.
1105  *
1106  *     Invoked by: rgSCHUtlSubFrmPut
1107  *
1108  *  @param[in]  RgSchCellCb*     cell
1109  *  @param[in]  RgSubFrm*     subFrm
1110  *  @return  Void
1111  *
1112  **/
1113 static Void rgSCHUtlPhichReset(RgSchCellCb *cell,RgSchDlSf *subFrm)
1114 {
1115    RgSchPhichInfo          *phichInfo;
1116    RgSchPhich              *phich;
1117
1118    UNUSED(cell);
1119
1120    phichInfo = &subFrm->phichInfo;
1121    while(phichInfo->phichs.first != NULLP)
1122    {
1123       phich = (RgSchPhich *)phichInfo->phichs.first->node;
1124       cmLListDelFrm(&phichInfo->phichs, phichInfo->phichs.first);
1125       RGSCH_PHICH_FREE(cell->instIdx, phich, sizeof(RgSchPhich));
1126    }
1127    cmLListInit(&phichInfo->phichs);
1128    return;
1129 } /* rgSCHUtlPhichReset */
1130
1131 \f
1132 /**
1133  * @brief This function returns slot data structure for a cell
1134  *
1135  * @details
1136  *
1137  *     Function: rgSCHUtlSubFrmGet
1138  *     Purpose:  This function resets the slot data structure
1139  *               when the slot is released
1140  *
1141  *     Invoked by: scheduler
1142  *
1143  *  @param[in]  RgSubFrm  subFrm
1144  *  @return  Void
1145  *
1146  **/
1147 RgSchDlSf* rgSCHUtlSubFrmGet(RgSchCellCb *cell,CmLteTimingInfo frm)
1148 {
1149    RgSchDlSf            *sf;
1150    uint8_t               dlIdx;
1151
1152 #ifdef LTE_TDD
1153    dlIdx = rgSCHUtlGetDlSfIdx(cell, &frm);
1154    //RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->subFrms, dlIdx);
1155    sf = cell->subFrms[dlIdx];
1156 #else
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];
1162 #endif
1163   /* CA dev Start */
1164    sf->dlIdx    = dlIdx;
1165   /* CA dev End */
1166    return (sf);
1167 }
1168
1169 \f
1170 /**
1171  * @brief This function returns slot data structure for a cell
1172  *
1173  * @details
1174  *
1175  *     Function: rgSCHUtlSubFrmPut
1176  *     Purpose:  This function resets the slot data structure
1177  *               when the slot is released
1178  *
1179  *     Invoked by: scheduler
1180  *
1181  *  @param[in]  RgSubFrm  subFrm
1182  *  @return  Void
1183  *
1184  **/
1185 Void rgSCHUtlSubFrmPut(RgSchCellCb *cell,RgSchDlSf *sf)
1186 {
1187    uint8_t                  i;
1188    uint8_t                  noRaRsps;
1189
1190 #ifdef LTE_TDD
1191    /* Release all the held PDCCH information */
1192    rgSCHUtlPdcchInit(cell, sf, sf->nCce);
1193 #else
1194    /* Release all the held PDCCH information */
1195    rgSCHUtlPdcchInit(cell, sf, cell->nCce);
1196 #endif
1197    rgSCHUtlPhichReset(cell, sf);
1198
1199    /* Reset the bw allocated. */
1200    sf->bwAssigned = 0;
1201 #ifdef LTEMAC_SPS
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)
1206    {
1207       sf->bwAlloced = sf->bw;
1208    }
1209    sf->spsAllocdBw = 0;
1210    sf->type2Start = sf->bwAlloced;
1211    memset( &sf->dlSfAllocInfo, 0, sizeof(RgSchDlSfAllocInfo));
1212 #else
1213    sf->bwAlloced = 0;
1214    /* Fix for ccpu00123918*/
1215    sf->type2Start = 0;
1216    /* LTE_ADV_FLAG_REMOVED_START */
1217    /* dsfr_pal_fixes ** 21-March-2013 ** SKS */
1218    if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
1219    {
1220       memset(sf->rntpInfo.val, 0, sf->rntpInfo.len);
1221    }
1222    /* LTE_ADV_FLAG_REMOVED_END */
1223 #endif
1224    sf->txDone = FALSE;
1225    /*[ccpu00138609]-ADD-Reset the CCCH UE counter */
1226    sf->schdCcchUe = 0;
1227
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*/
1232 #ifndef LTEMAC_SPS
1233    sf->type2End   = 0;
1234 #else
1235    sf->type2End   = RGSCH_CEIL(sf->bwAlloced,cell->rbgSize);
1236 #endif
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 */
1242 #ifdef EMTC_ENABLE
1243    /* TODO we need to move this reset for emtc functions */
1244    if(!(cell->emtcEnable))
1245    {
1246       sf->bch.tb     = NULLP;
1247       sf->bch.tbSize = 0;
1248    }
1249 #else
1250    sf->bch.tb     = NULLP;
1251    sf->bch.tbSize = 0;
1252 #endif
1253    sf->bcch.pdcch = NULLP;
1254    sf->pcch.pdcch = NULLP;
1255 #ifdef LTE_TDD
1256    noRaRsps = RGSCH_MAX_TDD_RA_RSP_ALLOC;
1257 #else
1258    noRaRsps = RGSCH_MAX_RA_RSP_ALLOC;
1259 #endif
1260    for (i = 0; i < noRaRsps; i++)
1261    {
1262       sf->raRsp[i].pdcch = NULLP;
1263       cmLListInit(&(sf->raRsp[i].raRspLst));
1264    }
1265    /* LTE_ADV_FLAG_REMOVED_START */
1266    if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE)
1267    {
1268       rgSCHSFRUtlTotalPoolReset(cell, sf);
1269    }
1270    /* LTE_ADV_FLAG_REMOVED_END */
1271 #ifdef LTE_ADV
1272    cmLListInit(&sf->n1PucchResLst);
1273 #endif
1274
1275    sf->cceCnt = 0;
1276    sf->isCceFailure = FALSE;
1277    sf->dlUlBothCmplt = 0;
1278    return;
1279 }
1280
1281 \f
1282 /**
1283  * @brief This function computes log N (32 bit Unsigned) to the base 2
1284  *
1285  * @details
1286  *
1287  *     Function: rgSCHUtlLog32bitNbase2
1288  *     Purpose:  This function computes log N (32 bit Unsigned) to the base 2.
1289  *               For n= 0,1 ret = 0.
1290  *
1291  *     Invoked by: Scheduler
1292  *
1293  *  @param[in]  uint32_t       n
1294  *  @return  uint8_t
1295  *
1296  **/
1297 uint8_t rgSCHUtlLog32bitNbase2(uint32_t n)
1298 {
1299    uint32_t  b[] = {0x2, 0xc, 0xf0, 0xff00, 0xffff0000};
1300    uint32_t  s[] = {1, 2, 4, 8, 16};
1301    S16       i;
1302    uint8_t   ret = 0;
1303
1304    for (i=4; i >= 0; i--)
1305    {
1306       if (n & b[i])
1307       {
1308          n >>= s[i];
1309          ret |= s[i];
1310       }
1311    }
1312    return (ret);
1313 }
1314
1315 #ifdef LTEMAC_SPS
1316
1317 /**
1318  * @brief This function is a wrapper to call scheduler specific API.
1319  *
1320  * @details
1321  *
1322  *     Function: rgSCHUtlDlRelPdcchFbk
1323  *     Purpose:  Calls scheduler's handler for SPS release PDCCH feedback
1324  *     information.
1325  *
1326  *     Invoked by: DHM
1327  *
1328  *  @param[in]   RgSchCellCb     *cell
1329  *  @param[in]   RgSchUeCb       *ue
1330  *  @param[in]   uint8_t            isAck
1331  *  @return  Void
1332  *
1333  **/
1334 Void rgSCHUtlDlRelPdcchFbk(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t isAck)
1335 {
1336    cell->sc.apis->rgSCHDlRelPdcchFbk(cell, ue, isAck);
1337    return;
1338 }
1339
1340
1341
1342 /**
1343  * @brief This function is a wrapper to call scheduler specific API.
1344  *
1345  * @details
1346  *
1347  *     Function: rgSCHUtlDlProcAck
1348  *     Purpose:  Calls scheduler's handler to process Ack
1349  *     information.
1350  *
1351  *     Invoked by: DHM
1352  *
1353  *  @param[in]   RgSchCellCb     *cell
1354  *  @param[in]   RgSchDlHqProcCb *hqP
1355  *  @return  Void
1356  *
1357  **/
1358 Void rgSCHUtlDlProcAck(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
1359 {
1360    cell->sc.apis->rgSCHDlProcAck(cell, hqP);
1361    return;
1362 }
1363
1364 /**
1365  * @brief CRNTI CE Handler
1366  *
1367  * @details
1368  *
1369  *     Function : rgSCHUtlHdlCrntiCE
1370  *
1371  *     - Call scheduler common API
1372  *
1373  *
1374  *  @param[in]  RgSchCellCb   *cell
1375  *  @param[in]  RgSchUeCb     *ue
1376  *  @param[out] RgSchErrInfo  *err
1377  *  @return  Void
1378  **/
1379 Void rgSCHUtlHdlCrntiCE(RgSchCellCb  *cell,RgSchUeCb *ue)
1380 {
1381
1382    cell->sc.apis->rgSCHHdlCrntiCE(cell, ue);
1383    return;
1384 }  /* rgSCHUtlHdlCrntiCE */
1385 #endif /* LTEMAC_SPS */
1386
1387 /***********************************************************
1388  *
1389  *     Func : rgSCHUtlCalcTotalRegs
1390  *
1391  *     Desc : Calculate total REGs, given a bandwidth, CFI
1392  *            and number of antennas.
1393  *
1394  *     Ret  : Total REGs (uint16_t)
1395  *
1396  *     Notes: Could optimise if bw values are limited
1397  *            (taken from RRC spec) by indexing values from
1398  *            a table.
1399  *            Input values are not validated. CFI is assumed
1400  *            to be 1/2/3/4.
1401  *
1402  *     File :
1403  *
1404  **********************************************************/
1405 static uint16_t rgSCHUtlCalcTotalRegs(uint8_t bw,uint8_t cfi,uint8_t numAntna,Bool  isEcp)
1406 {
1407    uint16_t regs = 0;
1408
1409    /*ccpu00116757-  removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1410
1411    if (bw <= 10)
1412       ++cfi;
1413    switch (cfi)
1414    {
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
1419        * will have 3 REGS.
1420        */
1421       case 4:
1422          /*CR changes [ccpu00124416] - MOD*/
1423          if(isEcp)
1424          {
1425             regs =  bw * RGSCH_NUM_REGS_4TH_SYM_EXT_CP;
1426          }
1427          else
1428          {
1429             regs =  bw * RGSCH_NUM_REGS_4TH_SYM_NOR_CP;
1430          }
1431       case 3:
1432          regs += bw * RGSCH_NUM_REGS_3RD_SYM;
1433       case 2:
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;
1440    }
1441    return (regs);
1442 }
1443
1444 /***********************************************************
1445  *
1446  *     Func : rgSCHUtlCalcPhichRegs
1447  *
1448  *     Desc : Calculates number of PHICH REGs
1449  *
1450  *     Ret  : Number of PHICH REGs (uint8_t)
1451  *
1452  *     Notes: ng6 is Ng multiplied by 6
1453  *
1454  *     File :
1455  *
1456  **********************************************************/
1457 static uint16_t rgSCHUtlCalcPhichRegs(uint8_t bw,uint8_t ng6)
1458 {
1459    /* ccpu00115330: Corrected the calculation for number of PHICH groups*/
1460    return (RGSCH_CEIL((bw * ng6) ,(8 * 6)) * RGSCH_NUM_REG_PER_PHICH_GRP);
1461 }
1462
1463 #ifdef LTE_TDD
1464 /**
1465  * @brief Calculates total CCEs (N_cce)
1466  *
1467  * @details
1468  *
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.
1474  *
1475  *     Invoked by: Scheduler
1476  *
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)
1484  *
1485  **/
1486 uint8_t rgSCHUtlCalcNCce(uint8_t bw,RgrPhichNg ng,uint8_t cfi,uint8_t mPhich,uint8_t numAntna,Bool isEcp)
1487 {
1488    uint16_t totalRegs;
1489    uint16_t phichRegs;
1490    uint16_t cceRegs;
1491    uint8_t  ng6;
1492
1493    /*ccpu00116757-  removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1494
1495    switch (ng)
1496    {
1497       case RGR_NG_ONESIXTH:
1498          ng6 = 1;
1499          break;
1500       case RGR_NG_HALF:
1501          ng6 = 3;
1502          break;
1503       case RGR_NG_ONE:
1504          ng6 = 6;
1505          break;
1506       case RGR_NG_TWO:
1507       default:
1508          ng6 = 12;
1509          break;
1510    }
1511
1512    totalRegs = rgSCHUtlCalcTotalRegs(bw, cfi, numAntna, isEcp);
1513    phichRegs = rgSCHUtlCalcPhichRegs(bw, ng6);
1514    cceRegs   = totalRegs - mPhich*phichRegs - RGSCH_NUM_PCFICH_REG;
1515
1516    return ((uint8_t)(cceRegs/RGSCH_NUM_REG_PER_CCE));
1517 }
1518
1519 #else
1520 /**
1521  * @brief Calculates total CCEs (N_cce)
1522  *
1523  * @details
1524  *
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.
1530  *
1531  *     Invoked by: Scheduler
1532  *
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)
1538  *
1539  **/
1540 uint8_t rgSCHUtlCalcNCce(uint8_t bw,RgrPhichNg ng,uint8_t cfi,uint8_t numAntna,Bool isEcp)
1541 {
1542    uint16_t totalRegs;
1543    uint16_t phichRegs;
1544    uint16_t cceRegs;
1545    uint8_t  ng6;
1546
1547    /*ccpu00116757-  removed check for (ERRCLASS & ERRCLS_DEBUG)*/
1548
1549    switch (ng)
1550    {
1551       case RGR_NG_ONESIXTH:
1552          ng6 = 1;
1553          break;
1554       case RGR_NG_HALF:
1555          ng6 = 3;
1556          break;
1557       case RGR_NG_ONE:
1558          ng6 = 6;
1559          break;
1560       case RGR_NG_TWO:
1561       default:
1562          ng6 = 12;
1563          break;
1564    }
1565
1566    totalRegs = rgSCHUtlCalcTotalRegs(bw, cfi, numAntna, isEcp);
1567    phichRegs = rgSCHUtlCalcPhichRegs(bw, ng6);
1568    cceRegs   = totalRegs - phichRegs - RGSCH_NUM_PCFICH_REG;
1569
1570    return ((uint8_t)(cceRegs/RGSCH_NUM_REG_PER_CCE));
1571 }
1572 #endif
1573
1574 /**
1575  * @brief Returns PHICH info associated with an uplink
1576  *        HARQ process allocation
1577  *
1578  * @details
1579  *
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.
1584  *
1585  *  @param[in]  RgSchUlHqProcCb   *hqProc
1586  *  @param[out] uint8_t             *rbStartRef
1587  *  @param[out] uint8_t             *nDmrsRef
1588  *  @return  S16
1589  **/
1590 #ifdef LTE_TDD
1591 S16 rgSCHUtlGetPhichInfo(RgSchUlHqProcCb *hqProc,uint8_t *rbStartRef,uint8_t *nDmrsRef,uint8_t *iPhich)
1592 #else
1593 S16 rgSCHUtlGetPhichInfo(RgSchUlHqProcCb *hqProc,uint8_t *rbStartRef,uint8_t *nDmrsRef)
1594 #endif
1595 {
1596 /* ACC-TDD */
1597         S16 ret = RFAILED;
1598
1599         if ((hqProc != NULLP) && (hqProc->alloc != NULLP))
1600     {
1601        *rbStartRef = hqProc->alloc->grnt.rbStart;
1602        *nDmrsRef   = hqProc->alloc->grnt.nDmrs;
1603 #ifdef LTE_TDD
1604    *iPhich     = hqProc->iPhich;
1605 #endif
1606        ret = ROK;
1607     }
1608     return (ret);
1609 }
1610 #ifndef TFU_UPGRADE
1611 /**
1612  * @brief Returns uplink grant information required to permit
1613  *        PHY to receive data
1614  *
1615  * @details
1616  *
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:
1621  *               - RB start
1622  *               - Number of RBs
1623  *               - RV
1624  *
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
1635  *  @return  S16
1636  **/
1637 S16 rgSCHUtlAllocRcptInfo
1638 (
1639 RgSchUlAlloc   *alloc,
1640 CmLteRnti      *rnti,
1641 uint8_t        *iMcsRef,
1642 uint8_t        *rbStartRef,
1643 uint8_t        *numRbRef,
1644 uint8_t        *rvRef,
1645 uint16_t       *size,
1646 TfuModScheme   *modType,
1647 Bool           *isRtx,
1648 uint8_t        *nDmrs,
1649 Bool           *ndi,
1650 uint8_t        *hqPId
1651 )
1652 {
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;
1656
1657 #if (ERRCLASS & ERRCLS_DEBUG)
1658    if ((alloc == NULLP) || (alloc->hqProc == NULLP))
1659    {
1660       return RFAILED;
1661    }
1662 #endif
1663
1664    if ( !alloc->forMsg3 )
1665    {
1666       if ( ((alloc->ue) == NULLP) ||  (RG_SCH_CMN_GET_UE(alloc->ue, alloc->ue->cell) == NULLP))
1667       {
1668          DU_LOG("\nERROR  -->  SCH : Failed: ue->sch is null RNTI:%d,isRetx=%d",
1669                      alloc->rnti, alloc->grnt.isRtx);
1670          return RFAILED; 
1671       }
1672      ueCtgy =  (RG_SCH_CMN_GET_UE_CTGY(alloc->ue));
1673    }
1674
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)?
1683                          alloc->grnt.modOdr:
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;
1689
1690    return ROK;
1691 }
1692 #else
1693 /**
1694  * @brief Returns uplink grant information required to permit
1695  *        PHY to receive data
1696  *
1697  * @details
1698  *
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:
1703  *               - RB start
1704  *               - Number of RBs
1705  *               - RV
1706  *
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
1713  *  @return  S16
1714  **/
1715 S16 rgSCHUtlAllocRcptInfo(RgSchCellCb *cell,RgSchUlAlloc *alloc,CmLteTimingInfo *timeInfo,TfuUeUlSchRecpInfo *recpReq)
1716 {
1717 #if (ERRCLASS & ERRCLS_DEBUG)
1718    if ((alloc == NULLP) || (alloc->hqProc == NULLP))
1719    {
1720       return RFAILED;
1721    }
1722 #endif
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))));
1733 #else
1734    recpReq->modType        = (TfuModScheme)((alloc->forMsg3)?alloc->grnt.modOdr:
1735                              ((alloc->ue->ueCatEnum == CM_LTE_UE_CAT_5)?
1736                               alloc->grnt.modOdr:
1737                              (RGSCH_MIN(RGSCH_QM_QPSK,alloc->grnt.modOdr))));
1738 #endif
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];
1745 #ifndef LTE_TDD
1746    recpReq->harqProcId = alloc->hqProc->procId;
1747 #else
1748    recpReq->harqProcId = rgSCHCmnGetUlHqProcIdx(timeInfo, cell);
1749 #endif
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;
1754
1755    recpReq->mcs = alloc->grnt.iMcs;
1756 #ifdef RG_5GTF
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;
1765    if(alloc->ue)
1766    {
1767       recpReq->beamIndex = alloc->ue->ue5gtfCb.BeamId;
1768    }
1769 #endif
1770
1771 #ifdef TENB_STATS
1772    if (!alloc->forMsg3)
1773    {
1774       if (alloc->grnt.isRtx)
1775       {
1776          alloc->ue->tenbStats->stats.nonPersistent.sch[RG_SCH_CELLINDEX(alloc->ue->cell)].ulRetxOccns++;
1777       }
1778       else
1779       {
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 ++;
1787       }
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;
1790    }
1791 #endif
1792   /* ccpu00117050 - DEL - nSrs setting at rgSCHUtlAllocRcptInfo */
1793    return ROK;
1794 }
1795 #endif
1796
1797 #ifdef LTE_TDD
1798 /**
1799  * @brief This function initialises the PRACH slot occasions
1800  *
1801  * @details
1802  *
1803  *     Function: rgSCHUtlUpdPrachOcc
1804  *     Purpose:  This function updates the PRACH slots based on
1805  *               RGR configuration.
1806  *
1807  *     Invoked by: Scheduler
1808  *
1809  *  @param[in]  RgSchCellCb      *cell
1810  *  @param[in]  RgrTddPrachInfo  *cellCfg
1811  *  @return     Void
1812  *
1813  **/
1814 static Void rgSCHUtlUpdPrachOcc(RgSchCellCb *cell,RgrTddPrachInfo *cellCfg)
1815 {
1816    uint8_t    idx;
1817    uint8_t    count = 0;
1818    uint8_t    size;
1819    uint8_t    startIdx;
1820    uint8_t    endIdx;
1821
1822    /* In the 1st half frame */
1823    if(cellCfg->halfFrm == 0)
1824    {
1825       startIdx = 2;
1826       endIdx = 6;
1827    }
1828    /* In the 2nd half frame */
1829    else
1830    {
1831       startIdx = 6;
1832       endIdx = 10;
1833    }
1834    for(idx = startIdx; idx < endIdx; idx++)
1835    {
1836       if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
1837             == RG_SCH_TDD_UL_slot)
1838       {
1839          if(cellCfg->ulStartSfIdx == count)
1840          {
1841             size = cell->rachCfg.raOccasion.size;
1842             cell->rachCfg.raOccasion.slotNum[size] = idx;
1843             cell->rachCfg.raOccasion.size++;
1844             break;
1845          }
1846          count ++;
1847       }
1848    }
1849    return;
1850 }
1851
1852 /**
1853  * @brief This function initialises the PRACH occasions
1854  *
1855  * @details
1856  *
1857  *     Function: rgSCHUtlPrachCfgInit
1858  *     Purpose:  This function initialises the PRACH occasions based on
1859  *               RGR configuration.
1860  *
1861  *     Invoked by: Scheduler
1862  *
1863  *  @param[in]  RgSchCellCb       *cell
1864  *  @param[in]  RgrCellCfg        *cellCfg
1865  *  @return     Void
1866  *
1867  **/
1868 Void rgSCHUtlPrachCfgInit(RgSchCellCb *cell,RgrCellCfg *cellCfg)
1869 {
1870    uint8_t idx;
1871    uint8_t subfrmIdx;
1872    uint8_t splFrm;
1873
1874    if(cellCfg->prachRscInfo.numRsc <= 0)
1875    {
1876       DU_LOG("\nERROR  -->  SCH : Invalid"
1877                   "PRACH resources Configuration ");
1878       return;
1879    }
1880
1881    /* Update SFN occasions */
1882    cell->rachCfg.raOccasion.sfnEnum =
1883                      cellCfg->prachRscInfo.prachInfo[0].sfn;
1884
1885    cell->rachCfg.raOccasion.size = 0;
1886
1887    /* Update slot occasions */
1888    for(idx = 0; idx < cellCfg->prachRscInfo.numRsc; idx++)
1889    {
1890       if(cellCfg->prachRscInfo.prachInfo[idx].freqIdx == 0)
1891       {
1892          if(cellCfg->prachRscInfo.prachInfo[idx].halfFrm == 0)
1893          {
1894             splFrm = 1;
1895          }
1896          else
1897          {
1898             splFrm = 6;
1899          }
1900          if(cellCfg->prachRscInfo.prachInfo[idx].ulStartSfIdx ==
1901                                                 RGR_TDD_SPL_UL_IDX)
1902          {
1903             subfrmIdx = cell->rachCfg.raOccasion.size;
1904             cell->rachCfg.raOccasion.slotNum[subfrmIdx] = splFrm;
1905             cell->rachCfg.raOccasion.size++;
1906          }
1907          else
1908          {
1909             rgSCHUtlUpdPrachOcc(cell,
1910                   &cellCfg->prachRscInfo.prachInfo[idx]);
1911          }
1912       }
1913    }
1914    return;
1915 }
1916
1917 /**
1918  * @brief This function performs RGR cell initialization
1919  *
1920  * @details
1921  *
1922  *     Function: rgSCHUtlRgrCellCfg
1923  *     Purpose:  This function initialises the cell with RGR configuration
1924  *               and slot related initialization.
1925  *
1926  *     Invoked by: Scheduler
1927  *
1928  *  @param[in]  RgSchCellCb       *cell
1929  *  @param[in]  RgrCellCfg        *cellCfg
1930  *  @param[in]  RgSchErrInfo      *errInfo
1931  *  @return     Void
1932  *
1933  **/
1934 S16 rgSCHUtlRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *errInfo)
1935 {
1936    uint8_t         i;
1937    uint8_t         sfn=0;
1938    uint8_t         sfNum = 0;
1939    RgSchDlSf       *sf;
1940    CmLteTimingInfo frm;
1941    uint8_t         ulDlCfgIdx = cellCfg->ulDlCfgIdx;
1942    uint8_t         maxslots ;
1943    uint8_t         maxDlslots;
1944    S16             ret = ROK;
1945    uint16_t        bw;         /*!< Number of RBs in the cell */
1946    
1947    memset(&frm,0,sizeof(CmLteTimingInfo));
1948
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;
1956
1957    /* PRACH Occasions Initialization */
1958    rgSCHUtlPrachCfgInit(cell, cellCfg);
1959
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
1963     * DL BW */
1964    if (cell->bwCfg.dlTotalBw > 63)
1965    {
1966       cell->rbgSize  = 4;
1967    }
1968    else if (cell->bwCfg.dlTotalBw > 26)
1969    {
1970       cell->rbgSize  = 3;
1971    }
1972    else if (cell->bwCfg.dlTotalBw > 10)
1973    {
1974       cell->rbgSize  = 2;
1975    }
1976    else
1977    {
1978       cell->rbgSize  = 1;
1979    }
1980    cell->noOfRbgs = RGSCH_CEIL(cell->bwCfg.dlTotalBw, cell->rbgSize);
1981
1982    bw    = cell->bwCfg.dlTotalBw;
1983
1984    rgSCHUtlAllocSBuf(cell->instIdx,
1985                (Data **)&cell->subFrms, sizeof(RgSchDlSf *) * maxslots);
1986    if (cell->subFrms == NULLP)
1987    {
1988       return RFAILED;
1989    }
1990
1991    /* Create memory for each frame. */
1992    for(i = 0; i < maxslots; i++)
1993    {
1994       while(rgSchTddUlDlSubfrmTbl[ulDlCfgIdx][sfNum] ==
1995             RG_SCH_TDD_UL_slot)
1996       {
1997          sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES;
1998       }
1999
2000       rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf, sizeof(RgSchDlSf));
2001       if (sf == NULLP)
2002       {
2003          break;
2004       }
2005       memset(sf, 0, sizeof(*sf));
2006
2007 #ifdef LTE_ADV
2008       if (ROK != rgSCHLaaInitDlSfCb(cell, sf))
2009       {
2010          break;
2011       }
2012 #endif
2013       sf->sfNum = sfNum;
2014       sf->bw    = bw;
2015 #ifdef LTEMAC_SPS
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;
2021 #else
2022    sf->bwAlloced = 0;
2023    /* Fix for ccpu00123918*/
2024    sf->type2Start = 0;
2025 #endif /* LTEMAC_SPS */
2026       /* Initialize the ackNakRepQ here */
2027 #ifdef RG_MAC_MEASGAP
2028       cmLListInit (&(sf->ackNakRepQ));
2029 #endif
2030       cell->subFrms[i] = sf;
2031       sfNum = (sfNum+1) % RGSCH_NUM_SUB_FRAMES;
2032    }
2033    if (i != maxslots)
2034    {
2035       for (; i > 0; i--)
2036       {
2037          /* ccpu00117052 - MOD - Passing double pointer
2038          for proper NULLP assignment*/
2039          rgSCHUtlFreeSBuf(cell->instIdx,
2040                (Data **)(&(cell->subFrms[i-1])), sizeof(RgSchDlSf));
2041 #ifdef LTE_ADV
2042          rgSCHLaaDeInitDlSfCb(cell, sf);
2043 #endif
2044       }
2045       /* ccpu00117052 - MOD - Passing double pointer
2046       for proper NULLP assignment*/
2047       rgSCHUtlFreeSBuf(cell->instIdx,
2048             (Data **)(&(cell->subFrms)), sizeof(RgSchDlSf *) * maxslots);
2049
2050       return RFAILED;
2051    }
2052
2053    if (cell->sc.apis == NULLP)
2054    {
2055       cell->sc.apis = &rgSchCmnApis;
2056    }
2057    ret = cell->sc.apis->rgSCHRgrCellCfg(cell, cellCfg, errInfo);
2058
2059    if (ret != ROK)
2060    {
2061       /* ccpu00132286- Removed deletion of sf nodes as the deletion will be 
2062        * happening during CellDelete. Added return handling to provide negative
2063        * confirm*/
2064       return (ret);
2065    }
2066
2067    /* Release the slots and thereby perform the initialization */
2068    for (i = 0; i < maxslots; i++)
2069    {
2070      if((i > 0) && (i%maxDlslots == 0))
2071      {
2072       sfn++;
2073      }
2074      frm.sfn = sfn;
2075      frm.slot = cell->subFrms[i]->sfNum;
2076      rgSCHUtlDlRlsSubFrm(cell, frm);
2077    }
2078
2079    return (ret);
2080 }
2081
2082 #else
2083 \f
2084 /**
2085  * @brief This function performs scheduler related cell creation
2086  *
2087  * @details
2088  *
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.
2093  *
2094  *     Invoked by: Scheduler
2095  *
2096  *  @param[in]  RgSchCellCb          *cell
2097  *  @param[in]  RgrCellCfg        *cellCfg
2098  *  @param[in]  RgSchErrInfo         *errInfo
2099  *  @return     Void
2100  *
2101  **/
2102 S16 rgSCHUtlRgrCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *errInfo)
2103 {
2104    uint8_t         i;
2105    RgSchDlSf       *sf;
2106    CmLteTimingInfo frm;
2107    S16             ret;
2108    Inst            inst = cell->instIdx;
2109    /* LTE_ADV_FLAG_REMOVED_START */
2110    uint16_t        len;
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 */
2113
2114    memset(&frm,0,sizeof(CmLteTimingInfo));
2115
2116    /* determine the RBG size and no of RBGs for the configured
2117     * DL BW */
2118    if (cell->bwCfg.dlTotalBw > 63)
2119    {
2120       cell->rbgSize  = 4;
2121    }
2122    else if (cell->bwCfg.dlTotalBw > 26)
2123    {
2124       cell->rbgSize  = 3;
2125    }
2126    else if (cell->bwCfg.dlTotalBw > 10)
2127    {
2128       cell->rbgSize  = 2;
2129    }
2130    else
2131    {
2132       cell->rbgSize  = 1;
2133    }
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++)
2139    {
2140       rgSCHUtlAllocSBuf(inst, (Data **)&sf, sizeof(RgSchDlSf));
2141       if (sf == NULLP)
2142       {
2143          break;
2144       }
2145       memset(sf, 0, sizeof(*sf));
2146
2147 #ifdef LTE_ADV
2148       if (ROK != rgSCHLaaInitDlSfCb(cell, sf))
2149       {
2150          break;
2151       }
2152 #endif
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));
2159 #endif
2160       cell->subFrms[i] = sf;
2161       /* LTE_ADV_FLAG_REMOVED_START */
2162       if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
2163       {
2164          /*initialize the RNTP Buffer*/
2165          if(rgSchDSFRRntpInfoInit(&sf->rntpInfo, cell, sf->bw))
2166          {
2167             return RFAILED; 
2168          }
2169       }
2170
2171       if (cell->lteAdvCb.sfrCfg.status == RGR_ENABLE)
2172       {
2173          /*initialise the pools of CC and CE*/
2174          if(rgSchSFRTotalPoolInit(cell, sf))
2175          {
2176             return RFAILED; 
2177          }
2178       }
2179       /* LTE_ADV_FLAG_REMOVED_END */
2180    }
2181
2182    /* LTE_ADV_FLAG_REMOVED_START */
2183    /* Allocate memory for "scheduled UE" Info */
2184    if (cell->lteAdvCb.dsfrCfg.status == RGR_ENABLE)
2185    {    
2186       if((rgSCHUtlAllocSBuf(inst, (Data**)&(cell->rntpAggrInfo.val),
2187                   (len * sizeof(uint8_t)))) != ROK)
2188       {
2189          DU_LOG("\nERROR  -->  SCH : Memory allocation FAILED for RNTP Alloc");
2190          return RFAILED;
2191       }
2192       cell->rntpAggrInfo.pres = PRSNT_NODEF;
2193       cell->rntpAggrInfo.len  = len;
2194    }     
2195    /* LTE_ADV_FLAG_REMOVED_END */
2196
2197    /* Changing loop limit from
2198       RGSCH_NUM_SUB_FRAMES to RGSCH_NUM_DL_slotS */
2199    if (i != RGSCH_NUM_DL_slotS)
2200    {
2201       for (; i > 0; i--)
2202       {
2203          /* ccpu00117052 - MOD - Passing double pointer
2204          for proper NULLP assignment*/
2205          rgSCHUtlFreeSBuf(inst, (Data **)(&(cell->subFrms[i-1])),
2206                sizeof(RgSchDlSf));
2207 #ifdef LTE_ADV
2208          rgSCHLaaDeInitDlSfCb(cell, sf);
2209 #endif
2210       }
2211       return RFAILED;
2212    }
2213
2214    if (cell->sc.apis == NULLP)
2215    {
2216       cell->sc.apis = &rgSchCmnApis;
2217    }
2218
2219    /* Release the slots and thereby perform the initialization */
2220    for (i = 0; i < RGSCH_NUM_DL_slotS; i++)
2221    {
2222       if (i >= RGSCH_NUM_SUB_FRAMES)
2223       {
2224          /* [ccpu00123828]-MOD-The below statement sfn += 1incorrectly modified
2225           * the value of sfn for i>=10 thru 19. Correct way is to assign
2226           it to one */
2227          frm.sfn = 1;
2228       }
2229       frm.slot = i % RGSCH_NUM_SUB_FRAMES;
2230       rgSCHUtlDlRlsSubFrm(cell, frm);
2231    }
2232
2233    ret = cell->sc.apis->rgSCHRgrCellCfg(cell, cellCfg, errInfo);
2234    if (ret != ROK)
2235    {
2236       errInfo->errCause = RGSCHERR_SCH_CFG;
2237       return RFAILED;
2238    }
2239 #ifdef EMTC_ENABLE
2240       if(cell->emtcEnable)
2241       {
2242          /* TODO: Repetition framework in RGR and APP */
2243          if (rgSCHUtlEmtcResMngmtInit(
2244                   cell, 
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)
2248          {
2249             errInfo->errCause = RGSCHERR_SCH_CFG;
2250             return RFAILED;
2251          }
2252       }
2253 #endif
2254
2255    return (ret);
2256 }
2257 #endif
2258
2259 \f
2260 /**
2261  * @brief This function performs the cell reconfiguration at RGR interface
2262  *
2263  * @details
2264  *
2265  *     Function: rgSCHUtlRgrCellRecfg
2266  *     Purpose:  This function updates the reconfigurable parameters
2267  *               on the cell control block for the scheduler.
2268  *
2269  *     Invoked by: Scheduler
2270  *
2271  *  @param[in]  RgSchCellCb          *cell
2272  *  @param[in]  RgrCellCfg        *cellCfg
2273  *  @param[in]  RgSchErrInfo         *errInfo
2274  *  @return     Void
2275  *
2276  **/
2277 S16 rgSCHUtlRgrCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
2278 {
2279    return (cell->sc.apis->rgSCHRgrCellRecfg(cell, recfg, err));
2280 }
2281
2282
2283 \f
2284 /**
2285  * @brief This function returns the Y value of UE for a sub frame
2286  *
2287  * @details
2288  *
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.
2293  *
2294  *     Invoked by: Scheduler
2295  *
2296  *  @param[in]  RgSchCellCb          *cell
2297  *  @return     Void
2298  *
2299  **/
2300 S16 rgSCHUtlFreeCell(RgSchCellCb  *cell)
2301 {
2302    uint8_t          i;
2303    CmLListCp        *lst;
2304    RgSchPdcch       *pdcch;
2305    RgSchPdcchInfo   *pdcchInfo;
2306    RgSchPhichInfo   *phichInfo;
2307    RgSchPhich       *phich;
2308    Inst             inst = cell->instIdx;
2309    uint8_t          maxslots;
2310 #ifdef LTE_TDD
2311    RgSchRaReqInfo *raReqInfo;
2312    uint8_t         idx;
2313 #endif
2314
2315 #ifdef LTE_TDD
2316    maxslots = cell->numDlSubfrms;
2317 #else
2318    maxslots = RGSCH_NUM_DL_slotS;
2319 #endif
2320
2321
2322    /* Invoke the index for scheduler, cell deletion */
2323    cell->sc.apis->rgSCHFreeCell(cell);
2324
2325    /* Release the slots allocated               */
2326    for (i = 0; i < maxslots; i++)
2327    {
2328 #ifdef LTE_ADV
2329       rgSCHLaaDeInitDlSfCb(cell, cell->subFrms[i]);
2330 #endif
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)
2337       {
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));
2343       }
2344
2345       phichInfo = &cell->subFrms[i]->phichInfo;
2346       while(phichInfo->phichs.first != NULLP)
2347       {
2348          phich = (RgSchPhich *)phichInfo->phichs.first->node;
2349          cmLListDelFrm(&phichInfo->phichs, phichInfo->phichs.first);
2350          RGSCH_PHICH_FREE(inst, phich, sizeof(RgSchPhich));
2351       }
2352
2353       /* LTE_ADV_FLAG_REMOVED_START */
2354       /*releasing SFR pool entries*/
2355       rgSchSFRTotalPoolFree(&cell->subFrms[i]->sfrTotalPoolInfo, cell);
2356
2357       /*releasing dsfr rntp pattern info*/
2358       rgSchDSFRRntpInfoFree(&cell->subFrms[i]->rntpInfo, cell, 
2359                                        cell->bwCfg.dlTotalBw);
2360       /* LTE_ADV_FLAG_REMOVED_END */
2361
2362       /* ccpu00117052 - MOD - Passing double pointer
2363       for proper NULLP assignment*/
2364       rgSCHUtlFreeSBuf(inst, (Data **)(&(cell->subFrms[i])), sizeof(RgSchDlSf));
2365    }
2366 #ifdef LTE_TDD
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);
2372
2373    for(idx=0; idx < cell->raInfo.lstSize; idx++)
2374    {
2375       lst = &cell->raInfo.raReqLst[idx];
2376       while (lst->first != NULLP)
2377       {
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));
2383       }
2384    }
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));
2390 #endif
2391
2392    /* Release allocated pdcchs */
2393    lst = &cell->pdcchLst;
2394    while (lst->first != NULLP)
2395    {
2396       pdcch = (RgSchPdcch *)lst->first->node;
2397       cmLListDelFrm(lst, &pdcch->lnk);
2398 #ifdef EMTC_ENABLE
2399       if(cell->emtcEnable)
2400       {
2401          rgSCHEmtcPdcchFree(cell, pdcch);
2402          rgSCHUtlEmtcResMngmtDeinit(cell);
2403       }
2404 #endif
2405       /* ccpu00117052 - MOD - Passing double pointer
2406       for proper NULLP assignment*/
2407       rgSCHUtlFreeSBuf(inst,(Data **)&pdcch, sizeof(RgSchPdcch));
2408    }
2409 #ifdef LTE_ADV
2410    rgSCHLaaFreeLists(cell);
2411 #endif
2412
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 */
2417
2418    return ROK;
2419 }
2420
2421 \f
2422 /**
2423  * @brief This function adds the UE to scheduler
2424  *
2425  * @details
2426  *
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
2431  *
2432  *     Invoked by: Scheduler
2433  *
2434  *  @param[in]  RgSchCellCb          *cell
2435  *  @param[in]  RgSchUeCb            *ue
2436  *  @param[in]  RgrUeCfg             *cfg
2437  *  @param[in]  RgSchErrInfo            *err
2438  *  @return     S16
2439  *
2440  **/
2441 S16 rgSCHUtlRgrUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *cfg,RgSchErrInfo *err)
2442 {
2443
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)
2449    {
2450       /* DL MU-MIMO not supported */
2451       if (cfg->txMode.txModeEnum == RGR_UE_TM_5)
2452       {
2453          err->errCause = RGSCHERR_SCH_CFG;
2454          return RFAILED;
2455       }
2456       ue->mimoInfo.txMode = cfg->txMode.txModeEnum;
2457    }
2458    ue->ul.ulTxAntSel = cfg->ulTxAntSel;
2459    ue->mimoInfo.cdbkSbstRstrctn = cfg->ueCodeBookRstCfg;
2460 #ifdef TFU_UPGRADE
2461    ue->ueCatEnum = cfg->ueCatEnum;
2462    if ((cfg->puschDedCfg.bACKIdx > 15) ||
2463        (cfg->puschDedCfg.bCQIIdx > 15) ||
2464        (cfg->puschDedCfg.bRIIdx > 15))
2465    {
2466       err->errCause = RGSCHERR_SCH_CFG;
2467       return RFAILED;
2468    }
2469    ue->ul.betaHqOffst = cfg->puschDedCfg.bACKIdx;
2470    ue->ul.betaCqiOffst = cfg->puschDedCfg.bCQIIdx;
2471    ue->ul.betaRiOffst = cfg->puschDedCfg.bRIIdx;
2472 #endif
2473    ue->csgMmbrSta = cfg->csgMmbrSta;
2474 #ifdef RG_PFS_STATS
2475    memset(&ue->pfsStats, 0, sizeof(RgSchPfsStats));
2476 #endif
2477    /* Call the handler of the scheduler based on cell configuration */
2478    return (cell->sc.apis->rgSCHRgrUeCfg(cell, ue, cfg, err));
2479 }
2480 /* Start : LTEMAC_2.1_DEV_CFG */
2481 \f
2482 /**
2483  * @brief This function adds a service to scheduler
2484  *
2485  * @details
2486  *
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
2491  *
2492  *     Invoked by: Scheduler
2493  *
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
2499  *  @return     S16
2500  *
2501  **/
2502 S16 rgSCHUtlRgrLcCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchCfg *cfg,RgSchErrInfo *errInfo)
2503 {
2504    return (cell->sc.apis->rgSCHRgrLchCfg(cell, ue, dlLc, cfg, errInfo));
2505 }
2506
2507 \f
2508 /**
2509  * @brief This function modifies a service to scheduler
2510  *
2511  * @details
2512  *
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
2517  *
2518  *     Invoked by: Scheduler
2519  *
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
2525  *  @return     S16
2526  *
2527  **/
2528 S16 rgSCHUtlRgrLcRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchRecfg *recfg,RgSchErrInfo *err)
2529 {
2530    return (cell->sc.apis->rgSCHRgrLchRecfg(cell, ue, dlLc, recfg, err));
2531 }
2532
2533 /**
2534  * @brief This function deletes a Lc in scheduler
2535  *
2536  * @details
2537  *
2538  *     Function: rgSCHUtlRgrLcDel
2539  *     Purpose:  This function performs deletion of Lc in scheduler
2540  *
2541  *     Invoked by: Scheduler
2542  *
2543  *  @param[in]  RgSchCellCb   *cell
2544  *  @param[in]  RgSchUeCb     *ue
2545  *  @param[in]  CmLteLcId     lcId
2546  *  @param[in]  uint8_t            lcgId
2547  *  @return     S16
2548  *
2549  **/
2550 S16 rgSCHUtlRgrLcDel(RgSchCellCb *cell,RgSchUeCb *ue,CmLteLcId lcId,uint8_t lcgId)
2551 {
2552    cell->sc.apis->rgSCHRgrLchDel(cell, ue, lcId, lcgId);
2553
2554    return  (ROK);
2555 } /* rgSCHUtlRgrLcDel */
2556
2557 /**
2558  * @brief This function adds a service to scheduler
2559  *
2560  * @details
2561  *
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
2566  *
2567  *     Invoked by: Scheduler
2568  *
2569  *  @param[in]  RgSchCellCb          *cell
2570  *  @param[in]  RgSchUeCb            *ue
2571  *  @param[in]  RgrLchCfg            *cfg
2572  *  @param[in]  RgSchErrInfo         *err
2573  *  @return     S16
2574  *
2575  **/
2576 S16 rgSCHUtlRgrLcgCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrLcgCfg *cfg,RgSchErrInfo *errInfo)
2577 {
2578    return (cell->sc.apis->rgSCHRgrLcgCfg(cell, ue, &(ue->ul.lcgArr[cfg->ulInfo.lcgId]), cfg, errInfo));
2579 }
2580
2581 \f
2582 /**
2583  * @brief This function modifies a service to scheduler
2584  *
2585  * @details
2586  *
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
2591  *
2592  *     Invoked by: Scheduler
2593  *
2594  *  @param[in]  RgSchCellCb          *cell
2595  *  @param[in]  RgSchUeCb            *ue
2596  *  @param[in]  RgrLcgRecfg          *recfg
2597  *  @param[in]  RgSchErrInfo         *err
2598  *  @return     S16
2599  *
2600  **/
2601 S16 rgSCHUtlRgrLcgRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrLcgRecfg *recfg,RgSchErrInfo *err)
2602 {
2603    return (cell->sc.apis->rgSCHRgrLcgRecfg(cell, ue, &(ue->ul.lcgArr[recfg->ulRecfg.lcgId]), recfg, err));
2604 } /* rgSCHUtlRgrLcRecfg */
2605
2606 /**
2607  * @brief This function modifies a service to scheduler
2608  *
2609  * @details
2610  *
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
2615  *
2616  *     Invoked by: Scheduler
2617  *
2618  *  @param[in]  RgSchCellCb   *cell
2619  *  @param[in]  RgSchUeCb     *ue
2620  *  @param[in]  RgrDel        *lcDelInfo
2621  *  @return     S16
2622  *
2623  **/
2624 Void rgSCHUtlRgrLcgDel(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId)
2625 {
2626    cell->sc.apis->rgSCHFreeLcg(cell, ue, &ue->ul.lcgArr[lcgId]);
2627
2628   /* Stack Crash problem for TRACE5 changes. added the return below . */
2629  return;
2630
2631 } /* rgSCHUtlRgrLcgDel */
2632
2633
2634 /* End: LTEMAC_2.1_DEV_CFG */
2635
2636 /**
2637  * @brief This function is a wrapper to call scheduler specific API.
2638  *
2639  * @details
2640  *
2641  *     Function: rgSCHUtlDoaInd
2642  *     Purpose:  Updates the DOA for the UE
2643  *
2644  *     Invoked by: TOM
2645  *
2646  *  @param[in]  RgSchCellCb        *cell
2647  *  @param[in]  RgSchUeCb          *ue
2648  *  @param[in]  TfuDoaRpt          *doaRpt
2649  *  @return  Void
2650  *
2651  **/
2652 Void  rgSCHUtlDoaInd(RgSchCellCb  *cell,RgSchUeCb *ue,TfuDoaRpt *doaRpt)
2653 {
2654    ue->mimoInfo.doa.pres = PRSNT_NODEF;
2655    ue->mimoInfo.doa.val = doaRpt->doa;
2656    return;
2657 }
2658 \f
2659 /**
2660  * @brief This function is a wrapper to call scheduler specific API.
2661  *
2662  * @details
2663  *
2664  *     Function: rgSCHUtlDlCqiInd
2665  *     Purpose:  Updates the DL CQI for the UE
2666  *
2667  *     Invoked by: TOM
2668  *
2669  *  @param[in]  RgSchCellCb        *cell
2670  *  @param[in]  RgSchUeCb          *ue
2671  *  @param[in]  TfuDlCqiRpt        *dlCqiRpt
2672  *  @param[in]  CmLteTimingInfo    timingInfo
2673  *  @return  Void
2674  *
2675  **/
2676 Void rgSCHUtlDlCqiInd(RgSchCellCb *cell,RgSchUeCb  *ue,TfuDlCqiRpt *dlCqiRpt,CmLteTimingInfo timingInfo)
2677 {
2678    RgSchCellCb        *sCellCb = NULLP;
2679    if (dlCqiRpt->isPucchInfo)
2680    {
2681       sCellCb = ue->cellInfo[dlCqiRpt->dlCqiInfo.pucchCqi.cellIdx]->cell;
2682       sCellCb->sc.apis->rgSCHDlCqiInd(sCellCb, ue, dlCqiRpt->isPucchInfo, \
2683             (Void *)&dlCqiRpt->dlCqiInfo.pucchCqi, timingInfo);
2684    }
2685    else
2686    {
2687       uint32_t idx;
2688       for (idx = 0; idx < dlCqiRpt->dlCqiInfo.pusch.numOfCells; idx++)
2689       {
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);
2693       }
2694    }
2695    return;
2696 }
2697
2698 \f
2699 #ifdef TFU_UPGRADE
2700 /**
2701  * @brief This function is a wrapper to call scheduler specific API.
2702  *
2703  * @details
2704  *
2705  *     Function: rgSCHUtlSrsInd
2706  *     Purpose:  Updates the UL SRS for the UE
2707  *
2708  *     Invoked by: TOM
2709  *
2710  *  @param[in]  RgSchCellCb        *cell
2711  *  @param[in]  RgSchUeCb          *ue
2712  *  @param[in]  TfuSrsRpt*     srsRpt
2713  *  @param[in]  CmLteTimingInfo    timingInfo
2714  *  @return  Void
2715  *
2716  **/
2717 Void rgSCHUtlSrsInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuSrsRpt *srsRpt,CmLteTimingInfo timingInfo)
2718 {
2719    cell->sc.apis->rgSCHSrsInd(cell, ue, srsRpt, timingInfo);
2720    return;
2721 }
2722 #endif
2723
2724 /**
2725  * @brief This function is a wrapper to call scheduler specific API.
2726  *
2727  * @details
2728  *
2729  *     Function: rgSCHUtlDlTARpt
2730  *     Purpose:  Reports PHY TA for a UE.
2731  *
2732  *     Invoked by: TOM
2733  *
2734  *  @param[in]  RgSchCellCb        *cell
2735  *  @param[in]  RgSchUeCb          *ue
2736  *  @return  Void
2737  *
2738  **/
2739 Void rgSCHUtlDlTARpt(RgSchCellCb *cell,RgSchUeCb *ue)
2740 {
2741    cell->sc.apis->rgSCHDlTARpt(cell, ue);
2742    return;
2743 }
2744
2745 \f
2746 /**
2747  * @brief This function is a wrapper to call scheduler specific API.
2748  *
2749  * @details
2750  *
2751  *     Function: rgSCHUtlDlRlsSubFrm
2752  *     Purpose:  Releases scheduler Information from DL SubFrm.
2753  *
2754  *     Invoked by: DHM
2755  *
2756  *  @param[in]   RgSchCellCb     *cell
2757  *  @param[out]  CmLteTimingInfo subFrm
2758  *  @return  Void
2759  *
2760  **/
2761 Void rgSCHUtlDlRlsSubFrm(RgSchCellCb *cell,CmLteTimingInfo subFrm)
2762 {
2763    cell->sc.apis->rgSCHDlRlsSubFrm(cell, subFrm);
2764    return;
2765 }
2766
2767 #ifdef TFU_UPGRADE
2768 /**
2769  * @brief This API is invoked to update the AperCQI trigger
2770  *        weight.
2771  *
2772  * @details
2773  *
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.
2781  *
2782  *  @param[in]  RgSchUeCb       *ue
2783  *  @param[in]  uint8_t              isAck 
2784  *
2785  *  @return Void
2786  **/
2787 Void rgSCHUtlUpdACqiTrigWt(RgSchUeCb *ue,RgSchUeCellInfo *cellInfo,uint8_t isAck )
2788 {
2789 #ifdef LTE_ADV
2790    uint8_t triggerSet  = 0;
2791    uint8_t sIdx        = 0;
2792 #endif
2793
2794    if (isAck == TFU_HQFDB_ACK)
2795    {
2796       cellInfo->acqiCb.aCqiTrigWt += RG_APER_CQI_ACK_WGT;
2797    }
2798    else
2799    {
2800       cellInfo->acqiCb.aCqiTrigWt += RG_APER_CQI_NACK_WGT;
2801    }
2802
2803    if (cellInfo->acqiCb.aCqiTrigWt > RG_APER_CQI_THRESHOLD_WGT)
2804    {
2805       RgSchCellCb  *cell = ue->cell;
2806       RgSchErrInfo unUsed;
2807
2808       if(ue->dl.reqForCqi)
2809       {
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*/
2813          return;
2814       }
2815
2816      ue->dl.reqForCqi = TRUE;
2817 #ifdef LTE_ADV
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++)
2822       {
2823          /* The Aperiodic requested for SCell index sIdx */
2824          if ((triggerSet >> (7 - sIdx)) & 0x01)
2825          {
2826             /* The Aperiodic request for SCell index sIdx */
2827             ue->cellInfo[sIdx]->acqiCb.aCqiTrigWt = 0;
2828          }
2829       }
2830  
2831 #endif
2832       /* Force SCH to send UL grant by indicating fake SR.
2833        * If this UE already in UL SCH Qs this SR Ind will
2834        * be ignored */
2835       rgSCHUtlSrRcvd(cell, ue, cell->crntTime, &unUsed);
2836    }
2837
2838    return;
2839 }
2840 #endif
2841
2842 /**
2843  * @brief This API is invoked to indicate scheduler of a CRC indication.
2844  *
2845  * @details
2846  *
2847  *     Function : rgSCHUtlHdlUlTransInd
2848  *      This API is invoked to indicate scheduler of a CRC indication.
2849  *
2850  *  @param[in]  RgSchCellCb     *cell
2851  *  @param[in]  RgSchUeCb       *ue
2852  *  @param[in]  CmLteTimingInfo timingInfo
2853  *
2854  *  @return Void
2855  **/
2856 Void rgSCHUtlHdlUlTransInd(RgSchCellCb *cell,RgSchUeCb *ue,CmLteTimingInfo timingInfo)
2857 {
2858    cell->sc.apis->rgSCHHdlUlTransInd(cell, ue, timingInfo);
2859    return;
2860 }
2861 #ifdef LTEMAC_SPS
2862 /**
2863  * @brief This API is invoked to indicate scheduler of a CRC failure.
2864  *
2865  * @details
2866  *
2867  *     Function : rgSCHUtlHdlCrcInd
2868  *      This API is invoked to indicate CRC  to scheduler.
2869  *
2870  *  @param[in]  RgSchCellCb     *cell
2871  *  @param[in]  RgSchUeCb       *ue
2872  *  @param[in]  CmLteTimingInfo timingInfo
2873  *
2874  *  @return Void
2875  **/
2876 Void rgSCHUtlHdlCrcInd(RgSchCellCb *cell,RgSchUeCb  *ue,CmLteTimingInfo timingInfo)
2877 {
2878    cell->sc.apis->rgSCHUlCrcInd(cell, ue, timingInfo);
2879    return;
2880 } /* end of rgSCHUtlHdlCrcFailInd */
2881
2882 /**
2883  * @brief This API is invoked to indicate scheduler of a CRC failure.
2884  *
2885  * @details
2886  *
2887  *     Function : rgSCHUtlHdlCrcFailInd
2888  *      This API is invoked to indicate CRC failure to scheduler.
2889  *
2890  *  @param[in]  RgSchCellCb     *cell
2891  *  @param[in]  RgSchUeCb       *ue
2892  *  @param[in]  CmLteTimingInfo timingInfo
2893  *
2894  *  @return Void
2895  **/
2896 Void rgSCHUtlHdlCrcFailInd(RgSchCellCb *cell,RgSchUeCb  *ue,CmLteTimingInfo timingInfo)
2897 {
2898    cell->sc.apis->rgSCHUlCrcFailInd(cell, ue, timingInfo);
2899    return;
2900 } /* end of rgSCHUtlHdlCrcFailInd */
2901 #endif /* LTEMAC_SPS */
2902
2903 \f
2904 /**
2905  * @brief This function is a wrapper to call scheduler specific API.
2906  *
2907  * @details
2908  *
2909  *     Function: rgSCHUtlDlProcAddToRetx
2910  *     Purpose:  This function adds a HARQ process to retransmission
2911  *               queue. This may be performed when a HARQ ack is
2912  *               unsuccessful.
2913  *
2914  *     Invoked by: HARQ feedback processing
2915  *
2916  *  @param[in]  RgSchCellCb*     cell
2917  *  @param[in]  RgSchDlHqProc*   hqP
2918  *  @return  Void
2919  *
2920  **/
2921 Void rgSCHUtlDlProcAddToRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
2922 {
2923    cell->sc.apis->rgSCHDlProcAddToRetx(cell, hqP);
2924    return;
2925 }
2926
2927 \f
2928 /**
2929  * @brief This function adds a HARQ process TB to transmission
2930  *
2931  * @details
2932  *
2933  *     Function: rgSCHUtlDlHqPTbAddToTx
2934  *     Purpose:  This function a HarqProcess TB to the slot
2935  *               list.
2936  *
2937  *     Invoked by: Scheduler
2938  *
2939  *  @param[in]  RgSubFrm*     subFrm
2940  *  @param[in]  RgDlHqProc*   hqP
2941  *  @param[in]  uint8_t            tbIdx
2942  *  @return  Void
2943  *
2944  **/
2945 Void rgSCHUtlDlHqPTbAddToTx(RgSchDlSf *subFrm,RgSchDlHqProcCb *hqP,uint8_t tbIdx)
2946 {
2947    RgSchUeCb *ue = NULLP;
2948    RgSchCellCb *cell = hqP->hqE->cell;
2949    /* CA Dev Start */
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)
2953    {
2954       if (hqP->hqE->ue)
2955       {
2956          ue = hqP->hqE->ue;
2957          if(NULLP == ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].dlSfUeLnk.node)
2958          {
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);
2962
2963             ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].isPuschHarqRecpPres = FALSE;
2964
2965          }
2966
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); 
2971 #ifdef CA_DBG
2972          {
2973             uint32_t gSCellSchedCount,gPrimarySchedCount;
2974             if(RG_SCH_IS_CELL_SEC(hqP->hqE->ue,hqP->hqE->cell))
2975             {
2976                gSCellSchedCount++;
2977             }else
2978                gPrimarySchedCount++;
2979          }
2980 #endif
2981       }
2982       else if (hqP->hqE->msg4Proc == hqP)
2983       {
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);
2987       }
2988    }
2989    else
2990    {
2991       ue = hqP->hqE->ue; 
2992    }
2993    if((ue) && (HQ_TB_WAITING == hqP->tbInfo[tbIdx].state))
2994          
2995    {   
2996       ue->dl.dlSfHqInfo[cell->cellId][subFrm->dlIdx].totalTbCnt++;
2997    }
2998    /*totalTbCnt will hold the total number of TBs across all harq Proc from all 
2999     * cells*/
3000
3001    hqP->subFrm = subFrm; 
3002
3003    /* CA Dev End */
3004    return;
3005 }
3006
3007
3008 \f
3009 /**
3010  * @brief This function removes a HARQ process TB from transmission
3011  *
3012  * @details
3013  *
3014  *     Function: rgSCHUtlDlHqPTbRmvFrmTx
3015  *     Purpose:  This function removes a HarqProcess TB to the slot
3016  *               list.
3017  *
3018  *     Invoked by: Scheduler
3019  *
3020  *  @param[in]  RgSubFrm*     subFrm
3021  *  @param[in]  RgDlHqProc*   hqP
3022  *  @param[in]  uint8_t            tbIdx
3023  *  @param[in]  Bool          isRepeting
3024  *  @return  Void
3025  *
3026  **/
3027 Void rgSCHUtlDlHqPTbRmvFrmTx(RgSchDlSf *subFrm,RgSchDlHqProcCb  *hqP,uint8_t tbIdx,Bool isRepeting)
3028 {
3029    RgSchCellCb *cell = NULLP;
3030    /* Check with TDD */
3031    if ((isRepeting) &&
3032          (hqP->hqE->ue->ackNakRepCb.cfgRepCnt !=
3033           hqP->tbInfo[tbIdx].fbkRepCntr))
3034    {
3035       cmLListDelFrm(&subFrm->ackNakRepQ,
3036          &hqP->tbInfo[tbIdx].anRepLnk[hqP->tbInfo[tbIdx].fbkRepCntr]);
3037    }
3038    else
3039    {
3040       if (NULLP != hqP->hqPSfLnk.node)
3041       {
3042          /* CA dev Start */
3043          if (hqP->hqE->msg4Proc == hqP)
3044          {
3045             /* Msg4 will be scheduled on PCELL only hence delete directly from subFrm msg4HqpList */
3046             cmLListDelFrm(&subFrm->msg4HqPLst, &hqP->hqPSfLnk); 
3047          }
3048          else
3049          {
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)
3055             {
3056
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;
3061             }
3062          }
3063          hqP->hqPSfLnk.node = NULLP;
3064       }
3065       hqP->subFrm = NULLP;
3066    }
3067    return;
3068 }
3069
3070 #ifdef LTE_ADV
3071 /**
3072  * @brief Handler for accessing the existing SCellCb identified by the key
3073  * SCellId under the CellCb.
3074  *
3075  * @details
3076  *
3077  *     Function : rgSchUtlGetCellCb
3078  *     
3079  *           
3080  *  @param[in]  *cellCb
3081  *  @param[in]  ueId
3082  *  @return  RgSchUeCb*
3083  **/
3084 RgSchCellCb* rgSchUtlGetCellCb(Inst inst,uint16_t cellId)
3085 {
3086    RgSchCellCb  *cellCb = NULLP; 
3087    uint8_t      strtCellId;
3088    strtCellId = rgSchCb[inst].genCfg.startCellId;
3089    cellCb     = rgSchCb[inst].cells[cellId - strtCellId];
3090
3091    return (cellCb);
3092
3093 }  /* rgSchUtlGetCellCb */
3094
3095 /**
3096  * @brief Handler for deriving the servCellidx
3097  *
3098  * @details
3099  *
3100  *     Function : rgSchUtlGetServCellIdx
3101  *     
3102  *           
3103  *  @param[in]  *cellId
3104  *  @param[in]  RgSchUeCb *ue
3105  *  @return   uint8_t servCellIdx
3106  **/
3107 uint8_t rgSchUtlGetServCellIdx(Inst inst, uint16_t cellId, RgSchUeCb *ue)
3108 {
3109    uint8_t servCellIdx;
3110    uint16_t strtCellId;
3111
3112    strtCellId = rgSchCb[inst].genCfg.startCellId;
3113    servCellIdx = ue->cellIdToCellIdxMap[cellId - strtCellId];
3114    return (servCellIdx);
3115
3116 }  /* rgSchUtlGetCellCb */
3117
3118 /**
3119  * @brief Handler for validating the Cell Id received secondary Cell Addition
3120  *
3121  * @details
3122  *
3123  *     Function : rgSchUtlGetCellId
3124  *     
3125  *           
3126  *  @param[in]  *cellCb
3127  *  @param[in]  ueId
3128  *  @return  RgSchUeCb*
3129  **/
3130 S16 rgSchUtlVldtCellId(Inst inst,uint16_t cellId)
3131 {
3132    uint8_t              strtCellId;
3133
3134    strtCellId = rgSchCb[inst].genCfg.startCellId;
3135    if((cellId >= strtCellId) && ((cellId - strtCellId) < CM_LTE_MAX_CELLS))
3136    {
3137       return ROK;
3138    }
3139    return RFAILED;
3140 }  /* rgSchUtlVldtCellId */
3141
3142 #endif /* LTE_ADV*/
3143 /**
3144  * @brief UE reconfiguration for scheduler
3145  *
3146  * @details
3147  *
3148  *     Function : rgSCHUtlRgrUeRecfg
3149  *
3150  *     This functions updates UE specific scheduler
3151  *     information upon UE reconfiguration
3152  *
3153  *  @param[in]  RgSchCellCb  *cell
3154  *  @param[in]  RgSchUeCb    *ue
3155  *  @param[int] RgrUeRecfg   *ueRecfg
3156  *  @param[out] RgSchErrInfo *err
3157  *  @return  S16
3158  *      -# ROK
3159  *      -# RFAILED
3160  **/
3161 S16 rgSCHUtlRgrUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
3162 {
3163 /* Changes for UE Category Reconfiguration feature addition */
3164    RgSchCmnUe    *ueSch = RG_SCH_CMN_GET_UE(ue, cell);
3165
3166    /* Changes for UE Category Reconfiguration feature addition */
3167    if (ueRecfg->ueRecfgTypes & RGR_UE_UECAT_RECFG)
3168    {
3169       ueSch->cmn.ueCat = ueRecfg->ueCatEnum-1;
3170 #ifdef TFU_UPGRADE
3171       ue->ueCatEnum = ueRecfg->ueCatEnum;
3172 #endif
3173    } 
3174
3175    /* DL MU-MIMO not supported */
3176    if (ueRecfg->ueRecfgTypes & RGR_UE_TXMODE_RECFG)
3177    {
3178
3179       if (ueRecfg->txMode.pres == PRSNT_NODEF)
3180       {
3181          if (ueRecfg->txMode.txModeEnum == RGR_UE_TM_5)
3182          {
3183             err->errCause = RGSCHERR_SCH_CFG;
3184             return RFAILED;
3185          }
3186 #ifdef LTE_ADV
3187         if(ue->mimoInfo.txMode != ueRecfg->txMode.txModeEnum)
3188          {
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);
3193
3194
3195             DU_LOG("\nINFO  -->  SCH : UeReCfg A valie is %d\n",ue->f1bCsAVal);
3196          }
3197 #endif
3198          ue->mimoInfo.txMode = ueRecfg->txMode.txModeEnum;
3199       }
3200    }
3201 #ifdef TFU_UPGRADE
3202    /* [ccpu00123958]-ADD- Check for PUSCH related Reconfig from the bit mask  */
3203     if(ueRecfg->ueRecfgTypes & RGR_UE_PUSCH_RECFG)
3204     {
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;*/
3211     }
3212 #endif
3213    if (ueRecfg->ueRecfgTypes & RGR_UE_ULTXANTSEL_RECFG)
3214    {
3215       ue->ul.ulTxAntSel = ueRecfg->ulTxAntSel;
3216    }
3217    if (ueRecfg->ueRecfgTypes & RGR_UE_CDBKSBST_RECFG)
3218    {
3219       ue->mimoInfo.cdbkSbstRstrctn = ueRecfg->ueCodeBookRstRecfg;
3220    }
3221
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 */
3226
3227 /**
3228  * @brief This function deletes a service from scheduler
3229  *
3230  * @details
3231  *
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
3235  *
3236  *     Invoked by: BO and Scheduler
3237  *
3238  *  @param[in]  RgSchCellCb*  cell
3239  *  @param[in]  RgSchUeCb*    ue
3240  *  @param[in]  RgSchDlLcCb*  svc
3241  *  @return  Void
3242  **/
3243 Void rgSCHUtlFreeDlLc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb  *svc)
3244 {
3245    cell->sc.apis->rgSCHFreeDlLc(cell, ue, svc);
3246
3247   /* Stack Crash problem for TRACE5 changes. added the return below . */
3248  return;
3249
3250 }
3251
3252 /**
3253  * @brief UE deletion for scheduler
3254  *
3255  * @details
3256  *
3257  *     Function : rgSCHUtlFreeUe
3258  *
3259  *     This functions deletes all scheduler information
3260  *     pertaining to a UE
3261  *
3262  *  @param[in]  RgSchCellCb  *cell
3263  *  @param[in]  RgSchUeCb    *ue
3264  *  @return  Void
3265  **/
3266 Void rgSCHUtlFreeUe(RgSchCellCb *cell,RgSchUeCb *ue)
3267 {
3268 #ifdef LTE_TDD
3269    rgSCHUtlDelUeANFdbkInfo(ue,RGSCH_PCELL_INDEX);
3270 #endif
3271    cell->sc.apis->rgSCHFreeUe(cell, ue);
3272
3273   /* Stack Crash problem for TRACE5 changes. added the return below . */
3274  return;
3275
3276 }  /* rgSCHUtlFreeUe */
3277
3278 /**
3279  * @brief This function updates the scheduler with service for a UE
3280  *
3281  * @details
3282  *
3283  *     Function: rgSCHUtlDlDedBoUpd
3284  *     Purpose:  This function should be called whenever there is a
3285  *               change BO for a service.
3286  *
3287  *     Invoked by: BO and Scheduler
3288  *
3289  *  @param[in]  RgSchCellCb*  cell
3290  *  @param[in]  RgSchUeCb*    ue
3291  *  @param[in]  RgSchDlLcCb*  lc
3292  *  @return  Void
3293  **/
3294 Void rgSCHUtlDlDedBoUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *lc)
3295 {
3296    cell->sc.apis->rgSCHDlDedBoUpd(cell, ue, lc);
3297    return;
3298 }
3299 /**
3300  * @brief Record MSG3 allocation into the UE
3301  *
3302  * @details
3303  *
3304  *     Function : rgSCHUtlRecMsg3Alloc
3305  *
3306  *     This function is invoked to update record msg3 allocation information
3307  *    in the UE when UE is detected for RaCb
3308  *
3309  *  @param[in]  RgSchCellCb     *cell
3310  *  @param[in]  RgSchUeCb       *ue
3311  *  @param[in] RgSchRaCb       *raCb
3312  *
3313  **/
3314 Void rgSCHUtlRecMsg3Alloc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchRaCb *raCb)
3315 {
3316    cell->sc.apis->rgSCHUlRecMsg3Alloc(cell, ue, raCb);
3317    return;
3318
3319 }  /* rgSCHRecMsg3Alloc */
3320
3321 #ifdef RG_UNUSED
3322 /**
3323  * @brief Update harq process for allocation
3324  *
3325  * @details
3326  *
3327  *     Function : rgSCHUtlUpdUlHqProc
3328  *
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.
3332  *
3333  *  @param[in] RgSchCellCb      *cell
3334  *  @param[in] RgSchUlHqProcCb  *curProc
3335  *  @param[in] RgSchUlHqProcCb  *oldProc
3336  *  @return  S16
3337  *      -# ROK
3338  *      -# RFAILED
3339  **/
3340 S16 rgSCHUtlUpdUlHqProc(RgSchCellCb *cell,RgSchUlHqProcCb  *curProc,RgSchUlHqProcCb  *oldProc)
3341 {
3342    return (cell->sc.apis->rgSCHUpdUlHqProc(cell, curProc, oldProc));
3343 }  /* rgSCHUtlUpdUlHqProc */
3344 #endif
3345 /**
3346  * @brief UL grant for contention resolution
3347  *
3348  * @details
3349  *
3350  *     Function : rgSCHUtlContResUlGrant
3351  *
3352  *     Add UE to another queue specifically for CRNTI based contention
3353  *     resolution
3354  *
3355  *  @param[in]  RgSchCellCb *cell
3356  *  @param[in]  RgSchUeCb  *ue
3357  *  @param[out] RgSchErrInfo *err
3358  *  @return  S16
3359  *      -# ROK
3360  *      -# RFAILED
3361  **/
3362 S16 rgSCHUtlContResUlGrant(RgSchCellCb *cell,RgSchUeCb *ue,RgSchErrInfo *err)
3363 {
3364
3365    ue->isMsg4PdcchWithCrnti = TRUE; 
3366    return (cell->sc.apis->rgSCHContResUlGrant(cell, ue, err));
3367 }  /* rgSCHUtlContResUlGrant */
3368
3369 /**
3370  * @brief SR reception handling
3371  *
3372  * @details
3373  *
3374  *     Function : rgSCHUtlSrRcvd
3375  *
3376  *     - Handles SR reception for UE
3377  *
3378  *  @param[in]  RgSchCellCb  *cell
3379  *  @param[in]  RgSchUeCb    *ue
3380  *  @param[out] RgSchErrInfo *err
3381  *  @return  S16
3382  *      -# ROK
3383  *      -# RFAILED
3384  **/
3385 S16 rgSCHUtlSrRcvd(RgSchCellCb  *cell,RgSchUeCb *ue,CmLteTimingInfo frm,RgSchErrInfo *err)
3386 {
3387    return (cell->sc.apis->rgSCHSrRcvd(cell, ue, frm, err));
3388 }  /* rgSCHUtlSrRcvd */
3389
3390 /**
3391  * @brief Short BSR update
3392  *
3393  * @details
3394  *
3395  *     Function : rgSCHUtlUpdBsrShort
3396  *
3397  *     This functions does requisite updates to handle short BSR reporting
3398  *
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
3404  *  @return  Void
3405  *      -# ROK
3406  *      -# RFAILED
3407  **/
3408 Void rgSCHUtlUpdBsrShort(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t lcgId,uint8_t bsr,RgSchErrInfo *err)
3409 {
3410    cell->sc.apis->rgSCHUpdBsrShort(cell, ue, &ue->ul.lcgArr[lcgId], bsr, err);
3411    return;
3412 }  /* rgSCHUtlUpdBsrShort */
3413
3414
3415 /**
3416  * @brief Truncated BSR update
3417  *
3418  * @details
3419  *
3420  *     Function : rgSCHUtlUpdBsrTrunc
3421  *
3422  *     This functions does required updates to handle truncated BSR report
3423  *
3424  *
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
3430  *  @return  Void
3431  *      -# ROK
3432  *      -# RFAILED
3433  **/
3434 Void rgSCHUtlUpdBsrTrunc(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t  lcgId,uint8_t bsr,RgSchErrInfo *err)
3435 {
3436    cell->sc.apis->rgSCHUpdBsrTrunc(cell, ue, &ue->ul.lcgArr[lcgId], bsr, err);
3437    return; 
3438 }  /* rgSCHUtlUpdBsrTrunc */
3439
3440
3441 /**
3442  * @brief Long BSR update
3443  *
3444  * @details
3445  *
3446  *     Function : rgSCHUtlUpdBsrLong
3447  *
3448  *     - Update BSRs for all configured LCGs
3449  *     - Update priority of LCGs if needed
3450  *     - Update UE's position within/across uplink scheduling queues
3451  *
3452  *
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
3460  *  @return  Void
3461  *      -# ROK
3462  *      -# RFAILED
3463  **/
3464 Void rgSCHUtlUpdBsrLong(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t bsr0,uint8_t bsr1,uint8_t bsr2,uint8_t bsr3,RgSchErrInfo *err)
3465 {
3466    uint8_t bsArr[4];
3467    bsArr[0] = bsr0;
3468    bsArr[1] = bsr1;
3469    bsArr[2] = bsr2;
3470    bsArr[3] = bsr3;
3471    cell->sc.apis->rgSCHUpdBsrLong(cell, ue, bsArr, err);
3472    return;
3473 }  /* rgSCHUtlUpdBsrLong */
3474
3475 /**
3476  * @brief EXT PHR update
3477  *
3478  * @details
3479  *
3480  *     Function : rgSCHUtlUpdExtPhr
3481  *
3482  *     Updates extended power headroom info for a UE
3483  *
3484  *  @param[in]  RgSchCellCb  *cell
3485  *  @param[in]  RgSchUeCb    *ue
3486  *  @param[in]  uint8_t           phr
3487  *  @param[out] RgSchErrInfo *err
3488  *  @return  S16
3489  *      -# ROK
3490  *      -# RFAILED
3491  **/
3492 S16 rgSCHUtlUpdExtPhr(RgSchCellCb *cell,RgSchUeCb *ue,RgInfExtPhrCEInfo *extPhr,RgSchErrInfo *err)
3493 {
3494    return (cell->sc.apis->rgSCHUpdExtPhr(cell, ue, extPhr, err));
3495 }  /* rgSCHUtlUpdExtPhr */
3496
3497
3498
3499 /**
3500  * @brief PHR update
3501  *
3502  * @details
3503  *
3504  *     Function : rgSCHUtlUpdPhr
3505  *
3506  *     Updates power headroom info for a UE
3507  *
3508  *  @param[in]  RgSchCellCb  *cell
3509  *  @param[in]  RgSchUeCb    *ue
3510  *  @param[in]  uint8_t           phr
3511  *  @param[out] RgSchErrInfo *err
3512  *  @return  S16
3513  *      -# ROK
3514  *      -# RFAILED
3515  **/
3516 S16 rgSCHUtlUpdPhr(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t phr,RgSchErrInfo *err)
3517 {
3518    return (cell->sc.apis->rgSCHUpdPhr(cell, ue, phr, err));
3519 }  /* rgSCHUtlUpdPhr */
3520
3521
3522 /**
3523  * @brief Indication of UL CQI
3524  *
3525  * @details
3526  *
3527  *     Function : rgSCHUtlUlCqiInd
3528  *
3529  *     - Updates uplink CQI information for the UE. Computes and
3530  *       stores the lowest CQI of CQIs reported in all subbands
3531  *
3532  *  @param[in]  RgSchCellCb         *cell
3533  *  @param[in]  RgSchUeCb           *ue
3534  *  @param[in]  TfuUlCqiRpt         *ulCqiInfo
3535  *  @return  Void
3536  **/
3537 Void rgSCHUtlUlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuUlCqiRpt *ulCqiInfo)
3538 {
3539    cell->sc.apis->rgSCHUlCqiInd(cell, ue, ulCqiInfo);
3540    return;
3541 }  /* rgSCHUtlUlCqiInd */
3542
3543 /**
3544  * @brief Indication of PUCCH power adjustment
3545  *
3546  * @details
3547  *
3548  *     Function : rgSCHUtlPucchDeltaPwrInd
3549  *
3550  *     - Updates uplink CQI information for the UE. Computes and
3551  *       stores the lowest CQI of CQIs reported in all subbands
3552  *
3553  *  @param[in]  RgSchCellCb         *cell
3554  *  @param[in]  RgSchUeCb           *ue
3555  *  @param[in]  uint8_t                  delta
3556  *  @return  Void
3557  **/
3558 Void rgSCHUtlPucchDeltaPwrInd(RgSchCellCb *cell,RgSchUeCb *ue,S8 delta)
3559 {
3560    cell->sc.apis->rgSCHPucchDeltaPwrInd(cell, ue, delta);
3561    return;
3562 }  /* rgSCHUtlPucchDeltaPwrInd */
3563
3564 /* Start: LTEMAC_2.1_DEV_CFG */
3565 /**
3566  * @brief Ue Reset Request
3567  *
3568  * @details
3569  *
3570  *     Function : rgSCHUtlUeReset
3571  *
3572  *
3573  *  @param[in]  RgSchCellCb         *cell
3574  *  @param[in]  RgSchUeCb           *ue
3575  *  @return  S16
3576  **/
3577 Void rgSCHUtlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
3578 {
3579    ue->remBoCnt = 0;
3580    cell->sc.apis->rgSCHUeReset(cell, ue);
3581    return;
3582 }  /* rgSCHUtlUeReset */
3583 /* End: LTEMAC_2.1_DEV_CFG */
3584
3585 /**
3586  * @brief Returns HARQ proc for which data expected now
3587  *
3588  * @details
3589  *
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.
3595  *
3596  *     Invoked by: TOM
3597  *
3598  *  @param[in]  RgSchCellCb         *cell
3599  *  @param[in]  CmLteTimingInfo     frm
3600  *  @param[in]  RgSchUeCb           *ue
3601  *  @param[out] RgSchUlHqProcCb     **procRef
3602  *  @return  Void
3603  **/
3604 Void rgSCHUtlUlHqProcForUe(RgSchCellCb *cell,CmLteTimingInfo frm,RgSchUeCb *ue,RgSchUlHqProcCb **procRef)
3605 {
3606    cell->sc.apis->rgSCHUlHqProcForUe(cell, frm, ue, procRef);
3607
3608  /* Stack Crash problems for TRACE5 changes. added the return below */
3609  return;
3610
3611 }
3612
3613 /**
3614  * @brief Returns first uplink allocation to send reception
3615  *        request to PHY
3616  *
3617  * @details
3618  *
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
3623  *               request to PHY.
3624  *
3625  *     Invoked by: TOM
3626  *
3627  *  @param[in]  RgSchCellCb      *cell
3628  *  @return  RgSchUlAlloc*
3629  **/
3630 RgSchUlAlloc *rgSCHUtlFirstRcptnReq(RgSchCellCb *cell)
3631 {
3632    return (cell->sc.apis->rgSCHFirstRcptnReq(cell));
3633 }
3634
3635 /**
3636  * @brief Returns first uplink allocation to send reception
3637  *        request to PHY
3638  *
3639  * @details
3640  *
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
3645  *               request to PHY.
3646  *
3647  *     Invoked by: TOM
3648  *
3649  *  @param[in]  RgSchCellCb      *cell
3650  *  @return  RgSchUlAlloc*
3651  **/
3652 RgSchUlAlloc *rgSCHUtlNextRcptnReq(RgSchCellCb *cell,RgSchUlAlloc *alloc)
3653 {
3654    return (cell->sc.apis->rgSCHNextRcptnReq(cell, alloc));
3655 }
3656
3657 /**
3658  * @brief Returns first uplink allocation to send HARQ feedback
3659  *        request to PHY
3660  *
3661  * @details
3662  *
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
3667  *               feedback to PHY.
3668  *
3669  *     Invoked by: TOM
3670  *
3671  *  @param[in]  RgSchCellCb      *cell
3672  *  @param[in]  uint8_t                idx  
3673  *  @return  RgSchUlAlloc*
3674  **/
3675 RgSchUlAlloc *rgSCHUtlFirstHqFdbkAlloc(RgSchCellCb *cell,uint8_t idx)
3676 {
3677    return (cell->sc.apis->rgSCHFirstHqFdbkAlloc(cell, idx));
3678 }
3679
3680 \f
3681 /**
3682  * @brief Returns next allocation to send HARQ feedback for
3683  *
3684  * @details
3685  *
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.
3690  *
3691  *     Invoked by: TOM
3692  *
3693  *  @param[in]  RgSchCellCb      *cell
3694  *  @return  RgSchUlAlloc*
3695  **/
3696 RgSchUlAlloc *rgSCHUtlNextHqFdbkAlloc(RgSchCellCb *cell,RgSchUlAlloc *alloc,uint8_t idx)
3697 {
3698    return (cell->sc.apis->rgSCHNextHqFdbkAlloc(cell, alloc, idx));
3699 }
3700
3701 /***********************************************************
3702  *
3703  *     Func : rgSCHUtlResetSfAlloc
3704  *
3705  *     Desc : Utility Function to Reset slot allocation information.
3706  *
3707  *
3708  *     Ret  : ROK
3709  *            RFAILED
3710  *
3711  *
3712  *     File : rg_utl.c
3713  *
3714  **********************************************************/
3715 S16 rgSCHUtlResetSfAlloc(RgInfSfAlloc *sfAlloc,Bool resetCmnLcInfo,Bool restAlloc)
3716 {
3717    if(TRUE == restAlloc)
3718    {
3719       if(sfAlloc->ueInfo.numUes)
3720       {
3721          memset(sfAlloc->ueInfo.allocInfo,0x00,
3722                (sizeof(RgInfUeAlloc)*sfAlloc->ueInfo.numUes));
3723       }
3724       sfAlloc->ueInfo.numUes = 0;
3725       sfAlloc->rarInfo.numRaRntis = 0;
3726       sfAlloc->flowCntrlInfo.numUes = 0;
3727    }
3728    if(TRUE == resetCmnLcInfo)
3729    {
3730       sfAlloc->cmnLcInfo.bitMask = 0;
3731    }
3732    return ROK;
3733 }
3734
3735 /***********************************************************
3736  *
3737  *     Func : rgSCHUtlGetRlsHqAlloc
3738  *
3739  *     Desc : Utility Function to Allocate slot allocation information.
3740  *
3741  *
3742  *     Ret  : ROK
3743  *            RFAILED
3744  *
3745  *
3746  *     File : rg_utl.c
3747  *
3748  **********************************************************/
3749 S16 rgSCHUtlGetRlsHqAlloc(RgSchCellCb *cell)
3750 {
3751    uint8_t    idx = 0;
3752    Inst  inst = cell->instIdx;
3753    for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3754    {
3755       cell->rlsHqArr[idx].cellId = cell->cellId;
3756
3757       /* Allocating with additional location, to accommodate
3758          TA scheduling along with maximum no of UEs per SF */
3759
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)
3764       {
3765          DU_LOG("\nERROR  -->  SCH : Memory allocation FAILED for "
3766             "UE Alloc");
3767          return RFAILED;
3768       }
3769    }
3770
3771    return ROK;
3772
3773 }
3774
3775 /***********************************************************
3776  *
3777  *     Func : rgSCHUtlPutRlsHqAlloc
3778  *
3779  *     Desc : Utility Function to deallocate slot allocation information.
3780  *
3781  *
3782  *     Ret  : ROK
3783  *            RFAILED
3784  *
3785  *
3786  *     File : rg_utl.c
3787  *
3788  **********************************************************/
3789 S16 rgSCHUtlPutRlsHqAlloc(RgSchCellCb *cell)
3790 {
3791    uint8_t    idx = 0;
3792    Inst  inst = cell->instIdx;
3793
3794    for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3795    {
3796       /* Deallocate memory for "scheduled UE" Info */
3797       if (cell->rlsHqArr[idx].ueHqInfo != NULLP)
3798       {
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));
3806       }
3807    }
3808
3809    return ROK;
3810
3811 }
3812
3813
3814 /***********************************************************
3815  *
3816  *     Func : rgSCHUtlGetSfAlloc
3817  *
3818  *     Desc : Utility Function to Allocate slot allocation information.
3819  *
3820  *
3821  *     Ret  : ROK
3822  *            RFAILED
3823  *
3824  *
3825  *     File : rg_utl.c
3826  *
3827  **********************************************************/
3828 S16 rgSCHUtlGetSfAlloc(RgSchCellCb *cell)
3829 {
3830    uint8_t    idx;
3831    uint8_t    indx;
3832    Inst  inst = cell->instIdx;
3833    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
3834
3835 #ifdef LTE_TDD
3836    for(idx=0; idx < RGSCH_SF_ALLOC_SIZE; idx++)
3837 #else
3838    for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3839 #endif
3840    {
3841       cell->sfAllocArr[idx].cellId = cell->cellId;
3842
3843       /* Allocating with additional location, to accommodate
3844          TA scheduling along with maximum no of UEs per SF */
3845
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)
3850       {
3851          DU_LOG("\nERROR  -->  SCH : Memory allocation FAILED for "
3852             "UE Alloc");
3853          return RFAILED;
3854       }
3855
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)
3860       {
3861          DU_LOG("\nERROR  -->  SCH : Memory allocation FAILED for "
3862             "RARNTI");
3863          return RFAILED;
3864       }
3865       for(indx = 0; indx < RGSCH_MAX_RARNTI_PER_DL_SF; indx++)
3866       {
3867          if((rgSCHUtlAllocSBuf(inst,
3868             (Data**)&(cell->sfAllocArr[idx].rarInfo.raRntiInfo[indx].crntiInfo),
3869                    (sizeof(RgInfCrntiInfo)* (cellUl->maxMsg3PerUlSf)))) != ROK)
3870          {
3871             DU_LOG("\nERROR  -->  SCH : Memory allocation FAILED for "
3872                "RNTI");
3873             return RFAILED;
3874          }
3875       }
3876
3877    }
3878
3879 #ifdef EMTC_ENABLE
3880    rgSCHEmtcUtlGetSfAlloc(cell);
3881 #endif
3882
3883    return ROK;
3884
3885 }
3886
3887 /***********************************************************
3888  *
3889  *     Func : rgSCHUtlPutSfAlloc
3890  *
3891  *     Desc : Utility Function to deallocate slot allocation information.
3892  *
3893  *
3894  *     Ret  : ROK
3895  *            RFAILED
3896  *
3897  *
3898  *     File : rg_utl.c
3899  *
3900  **********************************************************/
3901 S16 rgSCHUtlPutSfAlloc(RgSchCellCb *cell)
3902 {
3903    uint8_t    idx;
3904    uint8_t    indx;
3905    Inst  inst = cell->instIdx;
3906    RgSchCmnUlCell *cellUl      = RG_SCH_CMN_GET_UL_CELL(cell);
3907
3908 #ifdef LTE_TDD
3909    for(idx=0; idx < RGSCH_SF_ALLOC_SIZE; idx++)
3910 #else
3911       for(idx=0; idx < RGSCH_NUM_SUB_FRAMES; idx++)
3912 #endif
3913       {
3914          if (cell->sfAllocArr[idx].rarInfo.raRntiInfo != NULLP)
3915          {
3916             for(indx = 0; indx < RGSCH_MAX_RARNTI_PER_DL_SF; indx++)
3917             {
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].\
3923                               crntiInfo)),
3924                         (sizeof(RgInfCrntiInfo)* (cellUl->maxMsg3PerUlSf)));
3925             }
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));
3932          }
3933          /* Deallocate memory for "scheduled UE" Info */
3934          if (cell->sfAllocArr[idx].ueInfo.allocInfo != NULLP)
3935          {
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));
3943          }
3944       }
3945
3946 #ifdef EMTC_ENABLE
3947    rgSCHEmtcUtlPutSfAlloc(cell);
3948 #endif
3949    return ROK;
3950
3951 }
3952
3953 /***********************************************************
3954  *
3955  *     Func : rgSCHUtlAllocSBuf
3956  *
3957  *     Desc : Utility Function to Allocate static buffer.
3958  *            Memory allocated is assumed contiguous.
3959  *
3960  *
3961  *     Ret  : ROK
3962  *            RFAILED
3963  *
3964  *     Notes: Caller doesnt need to raise the alarm in case of memory
3965  *            allocation gets failed.
3966  *
3967  *     File : rg_utl.c
3968  *
3969  **********************************************************/
3970 S16 rgSCHUtlAllocSBuf
3971 (
3972 Inst    inst,               /* Instance of the invoking scheduler */
3973 Data    **pData,            /* Pointer of the data to be returned */
3974 Size    size                /* size */
3975 )
3976 {
3977    /* Moving alarm diagnostics to available scope */
3978
3979    /* Initialize the param to NULLP */
3980    *pData = NULLP;
3981
3982    /* May not be necessary for data performance path */
3983 #ifndef NO_ERRCLS
3984    if (size == 0)
3985    {
3986       return RFAILED;
3987    }
3988 #endif
3989
3990    /* allocate buffer */
3991 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
3992    MS_BUF_ADD_ALLOC_CALLER();
3993 #endif /* */
3994    if (SGetSBuf(rgSchCb[inst].rgSchInit.region, rgSchCb[inst].rgSchInit.pool,
3995                       pData, size) != ROK)
3996    {
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");
4005      return RFAILED;
4006    }
4007
4008
4009    /* zero out the allocated memory */
4010    memset(*pData, 0x00, size);
4011
4012    return ROK;
4013
4014 } /* end of rgSCHUtlAllocSBuf */
4015
4016 \f
4017 /*
4018 *
4019 *       Fun:   rgSCHUtlFreeSBuf
4020 *
4021 *       Desc:  The argument to rgSCHUtlFreeSBuf() is a pointer to a block
4022 *              previously allocated by rgSCHUtlAllocSBuf() and size. It
4023 *              deallocates the memory.
4024 *
4025 *       Ret:   void
4026 *
4027 *       Notes: None
4028 *       File:  rg_utl.c
4029 */
4030 Void rgSCHUtlFreeSBuf
4031 (
4032 Inst inst,          /* Instance of the invoking scheduler */
4033 Data **data,         /* pointer to data */
4034 Size size           /* size */
4035 )
4036 {
4037
4038    S16 ret;
4039
4040    if ((data == NULLP) || (*data == NULLP) || (size == 0))
4041    {
4042       return;
4043    }
4044
4045
4046 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
4047    MS_BUF_ADD_CALLER();
4048 #endif /* */
4049    /* Deallocate buffer */
4050    ret = SPutSBuf(rgSchCb[inst].rgSchInit.region,
4051                   rgSchCb[inst].rgSchInit.pool, (*data), size);
4052
4053    if (ret != ROK)
4054    {
4055       DU_LOG("\nERROR  -->  SCH : rgSCHUtlFreeSBuf failed");
4056       return;
4057    }
4058
4059    /* ccpu00117052 - ADD - Assigning the pointer to NULLP */
4060    *data = NULLP;
4061
4062    return;
4063 } /* end of rgSCHUtlFreeSBuf */
4064
4065 \f
4066 #ifdef RGR_SI_SCH
4067 /*
4068 *
4069 *       Fun:   rgSCHUtlFreeWarningSiSeg
4070 *
4071 *       Desc:  This is used to deallocate Warning SI Seg.
4072 *
4073 *       Ret:   void
4074 *
4075 *       Notes: None
4076 *
4077 *       File:  rg_utl.c
4078 */
4079 Void rgSCHUtlFreeWarningSiSeg(Region reg,Pool pool,CmLListCp *siPduLst)
4080 {
4081    CmLList      *node;
4082    Buffer       *pdu;
4083
4084    while (siPduLst->first != NULLP)
4085    {
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));
4091       node = NULLP;
4092    }
4093
4094    return;
4095 } /* end of rgSCHUtlFreeWarningSiSeg */         
4096
4097 \f
4098 /*
4099 *
4100 *       Fun:   rgSCHUtlFreeWarningSiPdu
4101 *
4102 *       Desc:  This is used to deallocate Warning SI PDU.
4103 *
4104 *       Ret:   void
4105 *
4106 *       Notes: None
4107 *
4108 *       File:  rg_utl.c
4109 */
4110 Void rgSCHUtlFreeWarningSiPdu(RgSchCellCb  *cell)
4111 {
4112    CmLList            *node;
4113    Buffer             *pdu;
4114    RgSchWarningSiInfo *warningSi;
4115    RgSchWarningSiPdu  *warningSiPdu; 
4116
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);
4121    if (node == NULLP)
4122    {
4123       return;
4124    }
4125
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)
4132    {
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);
4139    }                                                                                 
4140
4141    return;
4142
4143 } /* end of rgSCHUtlFreeWarningSiPdu */         
4144  
4145 \f
4146 /*
4147 *
4148 *       Fun:   rgSCHUtlGetWarningSiPdu
4149 *
4150 *       Desc:  This is used to get Warning SI PDU for Scheduling. 
4151 *
4152 *       Ret:   
4153 *
4154 *       Notes: None
4155 *
4156 *       File:  rg_utl.c
4157 */
4158 Buffer *rgSCHUtlGetWarningSiPdu(RgSchCellCb *cell)
4159 {
4160    RgSchWarningSiInfo  *warningSi;
4161    RgSchWarningSiPdu  *warningSiPdu; 
4162    Buffer       *pdu;
4163    CmLList      *node;
4164
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);
4169    if (node != NULLP)
4170    {
4171       warningSiPdu = (RgSchWarningSiPdu *)node->node;
4172       pdu = warningSiPdu->pdu;
4173       return (pdu);
4174    }
4175    else
4176    {
4177       return (NULLP);
4178    }                                                  
4179 } /* rgSCHUtlGetWarningSiPdu  */    
4180
4181 \f
4182 /*
4183 *
4184 *       Fun:   rgSCHUtlGetMcsAndNPrb
4185 *
4186 *       Desc:  This is used to get mcs and nPrb value. 
4187 *
4188 *       Ret:   
4189 *
4190 *       Notes: None
4191 *
4192 *       File:  rg_utl.c
4193 */
4194 S16 rgSCHUtlGetMcsAndNPrb(RgSchCellCb *cell,uint8_t *nPrb,uint8_t *mcs,MsgLen  *msgLen)
4195 {
4196    RgSchWarningSiInfo  *warningSi;
4197    RgSchWarningSiPdu  *warningSiPdu; 
4198    CmLList      *node;
4199
4200    if(cell->siCb.siCtx.warningSiFlag == FALSE)
4201    {
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;
4205    }
4206    else
4207    {
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);
4212       if (node == NULLP)
4213       {
4214         return RFAILED;
4215       }
4216       
4217       warningSiPdu = (RgSchWarningSiPdu *)node->node;
4218       *mcs = warningSiPdu->mcs;
4219       *nPrb = warningSiPdu->nPrb;
4220       *msgLen = warningSiPdu->msgLen;
4221       return ROK;
4222             
4223    }
4224    return ROK;
4225 } /* rgSCHUtlGetMcsAndNPrb  */     
4226
4227 /*
4228 *
4229 *       Fun:   rgSCHUtlCalMacAndPrb
4230 *
4231 *       Desc:  This is used to Calculate mcs and nPrb value for SIB1 and SIs. 
4232 *
4233 *       Ret:   
4234 *
4235 *       Notes: None
4236 *
4237 *       File:  rg_utl.c
4238 */
4239 S16 rgSCHUtlCalMcsAndNPrb(RgSchCellCb *cell,uint8_t cfgType,MsgLen msgLen,uint8_t siId)
4240 {
4241    uint8_t mcs = 0;
4242    uint8_t nPrb = 0;
4243
4244       /*Get the nPrb and mcs parametr values */
4245    if (rgSCHUtlGetAllwdCchTbSz(msgLen*8, &nPrb, &mcs) != (msgLen*8))
4246       {
4247          DU_LOG("\nERROR  -->  SCH : msgLen does "
4248             "not match any valid TB Size");
4249          return RFAILED;
4250       }
4251
4252
4253    if(cfgType == RGR_SI_CFG_TYPE_SIB1 || cfgType == RGR_SI_CFG_TYPE_SIB1_PWS)
4254    {
4255
4256       if(cell->siCb.crntSiInfo.sib1Info.sib1 == NULLP)
4257       {
4258          cell->siCb.crntSiInfo.sib1Info.mcs = mcs;
4259          cell->siCb.crntSiInfo.sib1Info.nPrb = nPrb;
4260          cell->siCb.crntSiInfo.sib1Info.msgLen = msgLen;
4261       }
4262       else
4263       {
4264          cell->siCb.newSiInfo.sib1Info.mcs = mcs;
4265          cell->siCb.newSiInfo.sib1Info.nPrb= nPrb;
4266          cell->siCb.newSiInfo.sib1Info.msgLen = msgLen;
4267       }
4268    }
4269
4270     
4271    if(cfgType == RGR_SI_CFG_TYPE_SI)
4272    {
4273       if(cell->siCb.crntSiInfo.siInfo[siId-1].si == NULLP &&
4274          !(cell->siCb.siBitMask & RGSCH_SI_SICFG_UPD))
4275       {
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;
4279       }
4280       else
4281       {
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;
4285       }
4286    }
4287
4288    if(cfgType == RGR_SI_CFG_TYPE_SIB8_CDMA)
4289    {
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;
4293    }
4294
4295     return ROK;
4296 }
4297 #endif
4298
4299 /***********************************************************
4300  *
4301  *     Func : rgSCHUtlFillDgnParams
4302  *
4303  *     Desc : Utility Function to Fill Diagonostic params.
4304  *
4305  *     Ret  : None.
4306  *
4307  *     Notes: None.
4308  *
4309  *     File : rg_utl.c
4310  *
4311  **********************************************************/
4312 Void rgSCHUtlFillDgnParams(Inst inst,RgUstaDgn *dgn,uint8_t dgnType)
4313 {
4314
4315    switch(dgnType)
4316    {
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;
4321       break;
4322
4323       default:
4324       break;
4325    }
4326
4327    return;
4328 } /* end of rgSCHUtlFillDgnParams */
4329
4330 /***********************************************************
4331  *
4332  *     Func : rgSCHUtlGetPstToLyr
4333  *
4334  *     Desc : Utility Function to get the pst structure to post a message to MAC
4335  *
4336  *
4337  *     Ret  : ROK
4338  *            RFAILED
4339  *
4340  *     Notes: This function should be called while sending a msg from
4341  *     scheduler instance to MAC
4342  *
4343  *     File : rg_utl.c
4344  *
4345  **********************************************************/
4346 Void rgSCHUtlGetPstToLyr(Pst  *pst,RgSchCb *schCb,Inst macInst)
4347 {
4348
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;
4355
4356    pst->dstInst = macInst;
4357    pst->dstEnt = ENTMAC;
4358    pst->srcEnt = ENTMAC;
4359    pst->selector = 0;
4360    pst->prior     = PRIOR0;
4361    pst->intfVer   = 0;
4362    pst->route   = RTESPEC;
4363
4364    return;
4365 } /* end of rgSCHUtlGetPstToLyr */
4366
4367 /** @brief This function fills in the common lc information to be sent to MAC
4368  *
4369  * @details
4370  *
4371  *     Function: rgSCHUtlFillRgInfCmnLcInfo
4372  *       @param  RgSchDlSf       *sf,
4373  *       @param  RgInfSfAlloc    *sfAlloc,
4374  *       @param  CmLteLcId       lcId,
4375  *       @param  Bool            sendInd
4376  *
4377  * @return  S16
4378  *      -# ROK
4379  *      -# RFAILED
4380  */
4381 S16 rgSCHUtlFillRgInfCmnLcInfo(RgSchDlSf  *sf,RgInfSfAlloc *sfAlloc,CmLteLcId lcId,Bool sendInd)
4382 {
4383
4384    if((sf->bch.tbSize)&&
4385       !(sfAlloc->cmnLcInfo.bitMask & RGINF_BCH_INFO))
4386    {
4387 #ifndef RGR_SI_SCH
4388       sfAlloc->cmnLcInfo.bchInfo.lcId = lcId;
4389 #endif
4390       sfAlloc->cmnLcInfo.bitMask |= RGINF_BCH_INFO;
4391    }
4392    else if((sf->bcch.pdcch != NULLP)&&
4393       !(sfAlloc->cmnLcInfo.bitMask & RGINF_BCCH_INFO))
4394    {
4395       sfAlloc->cmnLcInfo.bcchInfo.rnti = RGSCH_SI_RNTI;
4396       rgSCHUtlFillPdschDciInfo(&(sfAlloc->cmnLcInfo.bcchInfo.dciInfo),
4397                                        &(sf->bcch.pdcch->dci));
4398 #ifndef RGR_SI_SCH
4399       sfAlloc->cmnLcInfo.bcchInfo.lcId = lcId;
4400       sfAlloc->cmnLcInfo.bcchInfo.sndStatInd = sendInd;
4401 #endif
4402       sfAlloc->cmnLcInfo.bitMask |= RGINF_BCCH_INFO;
4403    }
4404    else if((sf->pcch.pdcch != NULLP) &&
4405       !(sfAlloc->cmnLcInfo.bitMask & RGINF_PCCH_INFO))
4406    {
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;
4412    }
4413    return ROK;
4414 }
4415
4416 /** @brief This function fills in the RAR information to be sent to MAC
4417  *
4418  * @details
4419  *
4420  *     Function: rgSCHUtlFillRgInfRarInfo
4421  *
4422  * @param  RgSchCellCb  *cell 
4423  * @param  RgSchDlSf    *sf 
4424  * @param  RgInfSfAlloc *sfAlloc
4425  * @return  S16
4426  *      -# ROK
4427  *      -# RFAILED
4428  */
4429 S16 rgSCHUtlFillRgInfRarInfo(RgSchDlSf *sf,RgInfSfAlloc *sfAlloc,RgSchCellCb *cell)
4430 {
4431    uint8_t          idx;
4432    CmLListCp        *lnkLst;
4433    CmLList          *tmp;
4434    RgSchRaCb        *raCb;
4435    RgSchUeCb        *ue;
4436    RgInfRaRntiInfo  *raRntiAlloc;
4437    uint8_t          noRaRsps;
4438    RgSchCmnDlCell   *cellDl = RG_SCH_CMN_GET_DL_CELL(cell);
4439
4440 #ifdef LTE_TDD
4441    noRaRsps = RGSCH_MAX_TDD_RA_RSP_ALLOC;
4442 #else
4443    noRaRsps = RGSCH_MAX_RA_RSP_ALLOC;
4444 #endif
4445
4446    for(idx =0; idx < noRaRsps; idx++)
4447    {
4448       if (sf->raRsp[idx].pdcch == NULLP)
4449       {
4450          /* No further raResp Allocations. */
4451          break;
4452       }
4453       /* Added Dl TB count for RACH Response transmission*/
4454 #ifdef LTE_L2_MEAS
4455       cell->dlUlTbCnt.tbTransDlTotalCnt++;
4456 #endif      
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;
4465
4466       /* Fill for contention free UEs*/
4467       lnkLst = &(sf->raRsp[idx].contFreeUeLst);
4468       CM_LLIST_FIRST_NODE(lnkLst, tmp);
4469       while (tmp)
4470       {
4471          ue = (RgSchUeCb *)tmp->node;
4472          tmp = tmp->next;
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 =
4478                                                         ue->ul.rarGrnt.hop;
4479          raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.cqiBit =
4480                                                         ue->ul.rarGrnt.cqiReqBit;
4481 #endif
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 =
4488                                                         ue->ul.rarGrnt.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;
4495       }
4496       /* Fill for contention based UEs*/
4497       lnkLst = &(sf->raRsp[idx].raRspLst);
4498
4499       CM_LLIST_FIRST_NODE(lnkLst, tmp);
4500
4501       while((NULLP != tmp) && ((RgSchRaCb *)tmp->node != NULLP))
4502       {
4503          raCb     = (RgSchRaCb *)tmp->node;
4504
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 =
4512                                                         raCb->msg3Grnt.hop;
4513          raRntiAlloc->crntiInfo[raRntiAlloc->numCrnti].grnt.cqiBit = FALSE;
4514 #endif
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 =
4520                                                         raCb->msg3Grnt.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);
4529       }
4530    }
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;
4535
4536    return ROK;
4537 } /* end of rgSCHUtlFillRgInfRarInfo */
4538
4539 /** @brief This function fills in the pdsch data related allocation Info
4540  *         from the pdcch DCI info.
4541  * slot
4542  *
4543  * @details
4544  *
4545  *     Function: rgSCHUtlFillPdschDciInfo
4546  *
4547  *         Processing steps:
4548  *         - Depending upon the DCI Format, fill the appropriate fields.
4549  *
4550  * @param  [out] TfuPdschDciInfo *pdschDci
4551  * @param  [in]  TfuDciInfo      *pdcchDci
4552  * @return  S16
4553  *      -# ROK
4554  *      -# RFAILED
4555  */
4556 S16 rgSCHUtlFillPdschDciInfo(TfuPdschDciInfo *pdsch,TfuDciInfo *pdcchDci)
4557 {
4558
4559 #ifdef EMTC_ENABLE
4560   S16 ret = ROK; 
4561 #endif
4562    pdsch->format = pdcchDci->dciFormat;
4563    switch(pdcchDci->dciFormat)
4564    {
4565       case TFU_DCI_FORMAT_1:
4566          pdsch->u.format1AllocInfo = pdcchDci->u.format1Info.allocInfo;
4567          break;
4568       case TFU_DCI_FORMAT_1A:
4569          if (pdcchDci->u.format1aInfo.isPdcchOrder == FALSE)
4570          {
4571             pdsch->u.format1aAllocInfo = pdcchDci->u.format1aInfo.t.pdschInfo.allocInfo;
4572          }
4573          break;
4574       case TFU_DCI_FORMAT_1B:
4575          pdsch->u.format1bAllocInfo = pdcchDci->u.format1bInfo.allocInfo;
4576          break;
4577       case TFU_DCI_FORMAT_1C:
4578          pdsch->u.format1cAllocInfo = pdcchDci->u.format1cInfo;
4579          break;
4580       case TFU_DCI_FORMAT_1D:
4581          pdsch->u.format1dAllocInfo = pdcchDci->u.format1dInfo.allocInfo;
4582          break;
4583       case TFU_DCI_FORMAT_2:
4584          pdsch->u.format2AllocInfo = pdcchDci->u.format2Info.allocInfo;
4585          break;
4586       case TFU_DCI_FORMAT_2A:
4587          pdsch->u.format2AAllocInfo = pdcchDci->u.format2AInfo.allocInfo;
4588          break;
4589 #ifdef RG_5GTF
4590                 case TFU_DCI_FORMAT_B1:
4591          pdsch->u.formatB1Info = pdcchDci->u.formatB1Info;
4592          break;
4593       case TFU_DCI_FORMAT_B2:
4594          pdsch->u.formatB2Info = pdcchDci->u.formatB2Info;
4595          break;
4596 #endif
4597       default:
4598 #ifdef EMTC_ENABLE
4599  ret = rgSCHEmtcUtlFillPdschDciInfo(pdsch, pdcchDci);
4600  if(RFAILED == ret)
4601  {
4602       return RFAILED;
4603          }
4604 #else  
4605          return RFAILED;
4606 #endif
4607    }
4608    return ROK;
4609 }
4610
4611 /* LTE_ADV_FLAG_REMOVED_START */
4612 /**
4613  * @brief This function resets temporary variables in Pool
4614  * @details
4615  *
4616  *     Function: rgSchSFRResetPoolVariables
4617  *
4618  *     Invoked by: rgSCHSFRUtlTotalPoolInit
4619  *
4620  *  @param[in]  RgSchCellCb*     cell
4621  *  @param[in]  RgSubFrm*     subFrm
4622  *  @return  Void
4623  *
4624  **/
4625 Void rgSchDSFRPwrCheck(RgSchDlSf *sf,Bool *isAllUePwrHigh)
4626 {     
4627    RgSchSFRPoolInfo *sfrCCPool;
4628
4629    CmLListCp   *l;
4630    CmLList     *n;   
4631
4632    l = &sf->sfrTotalPoolInfo.ccPool;    
4633    n = cmLListFirst(l);
4634    while(n)
4635    {    
4636       sfrCCPool = (RgSchSFRPoolInfo*)n->node;
4637       if((sfrCCPool->poolstartRB == sfrCCPool->pwrHiCCRange.startRb) &&
4638             (sfrCCPool->poolendRB == sfrCCPool->pwrHiCCRange.endRb))
4639       {
4640          n = cmLListNext(l);
4641          if(n)
4642          {
4643             continue;
4644          }
4645          *isAllUePwrHigh = TRUE;
4646          break;
4647       }
4648       else
4649          break;   
4650    } 
4651 }
4652 /* LTE_ADV_FLAG_REMOVED_END */
4653 /***********************************************************
4654  *
4655  *     Func : rgSCHUtlFillRgInfTbInfo
4656  *
4657  *     Desc : Utility Function to fill the allocation info of each Tb
4658  *
4659  *
4660  *     Ret  :  void
4661  *
4662  *
4663  *     Notes: This function should be called while sending a msg from
4664  *     scheduler instance to MAC
4665  *
4666  *     File : rg_utl.c
4667  *
4668  **********************************************************/
4669 static Void rgSCHUtlFillRgInfTbInfo(RgSchDlHqProcCb *hqP,RgInfUeAlloc *allocInfo,RgSchCellCb *cell)
4670 {
4671    RgSchDlSf       *sf;
4672    uint8_t         idx;
4673    RgInfUeTbInfo   *tbInfo;
4674    uint8_t         tbCnt;
4675    /* LTE_ADV_FLAG_REMOVED_START */
4676 #ifdef TFU_UPGRADE
4677    static          uint32_t  tmpCnt = 0;
4678    Bool            isAllUePwrHigh = FALSE;
4679 #endif 
4680    /* LTE_ADV_FLAG_REMOVED_END */
4681    RgSchDlLcCb    *dlLcCb = NULLP;
4682    uint16_t       rlcHdrEstmt;
4683    uint8_t        lcId;
4684    /* RRM_RBC_X */
4685 #ifdef LTE_L2_MEAS
4686    uint8_t        prbUsed = 0;
4687 #endif
4688    /* RRM_RBC_Y */
4689
4690    CmLteTimingInfo        frm;
4691
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 */
4700 #ifdef LTE_ADV
4701    if ((rgSchCb[cell->instIdx].genCfg.forceCntrlSrbBoOnPCel) &&
4702          !RG_SCH_CMN_IS_PCELL_HQP(hqP))
4703    {
4704       allocInfo->fillCtrlPdu = FALSE;
4705    }
4706    else
4707    {
4708       allocInfo->fillCtrlPdu = TRUE;
4709    }
4710 #endif
4711
4712    allocInfo->tbStrtIdx = -1;
4713
4714
4715 #ifdef LTE_ADV
4716    allocInfo->tbReqInfo.sCellHqPId = 0xff;
4717    rgSCHLaaHndlFillRgInfTbInfo(cell, hqP, allocInfo);
4718 #endif
4719
4720    /*TODO:REEMA: Check and fill the isRetx */
4721    for(tbCnt = 0; tbCnt < 2; tbCnt++)
4722    {
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))*/)
4728       {
4729          ue = hqP->hqE->ue;
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)
4736          {
4737             hqP->tbInfo[tbCnt].taSnt = TRUE;
4738          }
4739 #ifdef TFU_UPGRADE
4740          if (RG_SCH_IS_PAPRSNT(ue,hqP->hqE->cell))
4741          {
4742             /*update pA value */
4743             allocInfo->pa = (RG_SCH_CMN_GET_PA(ue,hqP->hqE->cell)).val;
4744          }
4745 #endif
4746
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))
4750          {
4751             /* For Macro count number resource used in Non-ABS SF */
4752             if(RGR_ABS_MUTE == ue->cell->lteAdvCb.absCfg.absPatternType)
4753             {
4754                if(RG_SCH_ABS_ENABLED_NONABS_SF == ue->cell->lteAdvCb.absDlSfInfo)
4755                {
4756                   ue->cell->lteAdvCb.absLoadInfo[ue->cell->lteAdvCb.absPatternDlIdx]+=
4757                      hqP->tbInfo[tbCnt].dlGrnt.numRb;
4758                }
4759             }
4760             /* For pico count number resource used in ABS SF for ABS UE */
4761             else if(RGR_ABS_TRANSMIT == ue->cell->lteAdvCb.absCfg.absPatternType)
4762             {
4763                if(RG_SCH_ABS_ENABLED_ABS_SF == ue->cell->lteAdvCb.absDlSfInfo)
4764                {
4765                   if(TRUE == ue->lteAdvUeCb.rgrLteAdvUeCfg.isAbsUe)
4766                   {
4767                      ue->cell->lteAdvCb.absLoadInfo[ue->cell->lteAdvCb.absPatternDlIdx]+=
4768                         hqP->tbInfo[tbCnt].dlGrnt.numRb;
4769                   }
4770                }
4771             }
4772          } 
4773
4774 #ifdef TFU_UPGRADE         
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))
4779          {         
4780             rgSchDSFRPwrCheck(sf, &isAllUePwrHigh);          
4781          } 
4782          if(isAllUePwrHigh)
4783          {  
4784             allocInfo->pa = (uint8_t)ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;  /* KW fix for LTE_ADV */  
4785             if(tmpCnt++ == 100000)
4786             {
4787                DU_LOG("\nDEBUG  -->  SCH : DSFR::ll UEs can go HIGH, PHigh(%d) for UE(%d)",allocInfo->pa, ue->ueId);
4788                tmpCnt = 0;
4789             }
4790          }    
4791          else
4792          {  
4793             if (allocInfo->isEnbSFR)
4794             {
4795                /*Update pA to Plow if it is cell-centred ,else pA will be pHigh*/
4796                if (ue->lteAdvUeCb.rgrLteAdvUeCfg.isUeCellEdge == TRUE)
4797                {  
4798                   allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;
4799                   if(tmpCnt++ == 100000)
4800                   {
4801                      DU_LOG("\nDEBUG  -->  SCH : SFR::UE is CELL EDGE, PHigh(%d) for UE(%d)",allocInfo->pa, ue->ueId);
4802                      tmpCnt = 0;
4803                   }
4804
4805                }  
4806                else
4807                {
4808                   if(TRUE == ue->lteAdvUeCb.isCCUePHigh)
4809                   {
4810                      allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pHigh;
4811                      ue->lteAdvUeCb.isCCUePHigh = FALSE;
4812                   }
4813                   else
4814                   {
4815                      allocInfo->pa = ue->cell->lteAdvCb.sfrCfg.pwrThreshold.pLow;
4816                      if(tmpCnt++ == 100000)
4817                      {
4818                         DU_LOG("\nDEBUG  -->  SCH : SFR::UE is CELL CENTRE, PLow(%d) for UE(%d)\n",allocInfo->pa, ue->ueId);
4819                         tmpCnt = 0;
4820                      }
4821                   }
4822                }
4823             }
4824          }
4825          /* LTE_ADV_FLAG_REMOVED_END */
4826 #endif         
4827       }
4828       else
4829       {
4830          if (hqP->hqE->raCb)
4831          {
4832 #ifdef TFU_UPGRADE
4833             RgSchCmnDlCell   *cellDl = RG_SCH_CMN_GET_DL_CELL(cell);
4834 #endif 
4835 #ifdef LTEMAC_SPS
4836             allocInfo->pdcchRnti = hqP->hqE->raCb->tmpCrnti;
4837 #endif
4838             allocInfo->rnti  =  hqP->hqE->raCb->tmpCrnti;
4839 #ifdef TFU_UPGRADE
4840             /*ccpu00132314-ADD-Use a default pA value
4841               for msg4 */
4842             allocInfo->pa = cellDl->msg4pAVal; 
4843 #endif 
4844          }
4845       }
4846       /* If TB Is scheduled for this SF */
4847       if(hqP->tbInfo[tbCnt].state == HQ_TB_WAITING)
4848       {
4849          if (allocInfo->tbStrtIdx == -1){
4850             allocInfo->tbStrtIdx = tbCnt;
4851 #ifndef LTEMAC_SPS
4852             rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4853                                &(hqP->pdcch->dci));
4854 #else
4855             if (hqP->pdcch)
4856             {
4857                rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4858                      &(hqP->pdcch->dci));
4859             }
4860             else if ((ue) && (ue->dl.spsOccPdcch.rnti == ue->spsRnti))
4861             {
4862                rgSCHUtlFillPdschDciInfo(&(allocInfo->dciInfo),
4863                      &(ue->dl.spsOccPdcch.dci));
4864             }
4865 #endif /* ifndef LTEMAC_SPS */
4866          }
4867 #ifdef LTEMAC_SPS
4868             if (hqP->pdcch)
4869             {
4870                allocInfo->pdcchRnti = hqP->pdcch->rnti;
4871             }
4872             else if (ue)
4873             {
4874                allocInfo->pdcchRnti = ue->spsRnti;
4875             }
4876 #endif
4877          tbInfo = &(allocInfo->tbInfo[tbCnt]);
4878          allocInfo->nmbOfTBs++;
4879          allocInfo->hqProcId = hqP->procId;
4880          allocInfo->tbInfo[tbCnt].schdTbSz = hqP->tbInfo[tbCnt].tbSz;
4881
4882          tbInfo->disTb  = FALSE;
4883          if(!(hqP->tbInfo[tbCnt].txCntr))
4884          {
4885 #ifdef LTE_ADV
4886             if(!((rgSCHLaaCheckIfLAAProc(hqP)) && (TRUE ==
4887                         rgSCHLaaSCellEnabled(cell))))
4888 #endif
4889             {
4890                hqP->tbInfo[tbCnt].txCntr++;
4891             }
4892             for(idx = 0; idx < hqP->tbInfo[tbCnt].numLch; idx++)
4893             {
4894                tbInfo->schdDat[idx].lcId =\
4895                   hqP->tbInfo[tbCnt].lchSchdData[idx].lcId;
4896                tbInfo->schdDat[idx].numBytes =\
4897                   hqP->tbInfo[tbCnt].lchSchdData[idx].schdData;
4898                if(hqP->hqE->ue)
4899                {
4900                   lcId = hqP->tbInfo[tbCnt].lchSchdData[idx].lcId; 
4901                   if(lcId != 0)
4902                   {
4903                      dlLcCb = hqP->hqE->ue->dl.lcCb[lcId-1];
4904                      if(dlLcCb != NULLP)
4905                      {
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);
4911
4912                         /* RRM_RBC_X */
4913 #ifdef LTE_L2_MEAS
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)
4920                         {
4921                            RG_SCH_CALC_GBR_UTILIZATION(cell, dlLcCb, prbUsed);
4922                         }
4923 #endif                        /* RRM_RBC_Y */
4924
4925 #ifdef RG_PFS_STATS
4926                         //if(!(hqP->hqE->ue->pfsStats.lcStats[lcId-1].isLcCntSet))
4927                         if(tbCnt == 0)
4928                         {
4929                            uint8_t idx = 0;
4930                            if (hqP->hqE->ue->cell == hqP->hqE->cell)
4931                            {
4932                               idx = RGSCH_PCELL_INDEX;
4933                            }
4934                            else
4935                            {
4936                               idx = RG_SCH_GET_SCELL_INDEX((hqP->hqE->ue), (hqP->hqE->cell));
4937                            }
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++;
4940                         }   
4941 #endif
4942                      }
4943                   }
4944                }
4945             }
4946             /* Added Dl TB count for SRB/DRB data transmission*/
4947 #ifdef LTE_L2_MEAS 
4948             cell->dlUlTbCnt.tbTransDlTotalCnt++;  
4949 #endif            
4950             tbInfo->ta.pres = hqP->tbInfo[tbCnt].schdTa.pres;
4951             tbInfo->ta.val =  hqP->tbInfo[tbCnt].schdTa.val;
4952 #ifdef LTE_ADV
4953             tbInfo->sCellActCe = hqP->tbInfo[tbCnt].schdSCellActCe;
4954 #endif
4955             tbInfo->numSchLch = hqP->tbInfo[tbCnt].numLch;
4956             if(!(hqP->tbInfo[tbCnt].numLch))
4957             {
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;
4962             }
4963
4964             tbInfo->contResCe = hqP->tbInfo[tbCnt].contResCe;
4965             tbInfo->isReTx = FALSE;
4966          }
4967          else
4968          {
4969 #ifdef LTE_ADV
4970             if(!((rgSCHLaaCheckIfLAAProc(hqP)) && (TRUE ==
4971                         rgSCHLaaSCellEnabled(cell))))
4972 #endif
4973             {
4974                hqP->tbInfo[tbCnt].txCntr++;
4975             }
4976             tbInfo->isReTx = TRUE;
4977             /* RRM_RBC_X */
4978             /* As per 36.314, harq retransmission also considered for 
4979              * prb utilization calculation*/
4980             for(idx = 0; idx < hqP->tbInfo[tbCnt].numLch; idx++)
4981             {
4982 #ifdef LTE_L2_MEAS
4983                if(hqP->hqE->ue)
4984                {
4985                   lcId = hqP->tbInfo[tbCnt].lchSchdData[idx].lcId; 
4986                   if(lcId != 0)
4987                   {
4988                      dlLcCb = hqP->hqE->ue->dl.lcCb[lcId-1];
4989                      if(dlLcCb != NULLP)
4990                      {
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)
4996                         {
4997                            RG_SCH_CALC_GBR_UTILIZATION(cell, dlLcCb, prbUsed);
4998                         }
4999                      }
5000                   }
5001                }
5002 #endif
5003             }
5004             /* RRM_RBC_Y */
5005          }
5006       }
5007     }
5008 #ifdef LTE_ADV 
5009    rgSCHLaaResetDlHqProcCb(hqP);
5010 #endif
5011
5012    return;
5013 }
5014 /***********************************************************
5015  *
5016  *     Func : rgSCHUtlFillRgInfUeInfo
5017  *
5018  *     Desc : Utility Function to fill the allocation info of Ue
5019  *             : MIMO : Filling 2TB's of each UE
5020  *
5021  *     Ret  : ROK
5022  *            RFAILED
5023  *
5024  *     Notes: This function should be called while sending a msg from
5025  *     scheduler instance to MAC
5026  *
5027  *     File : rg_utl.c
5028  *
5029  **********************************************************/
5030   /* CA dev Start */
5031 Void rgSCHUtlFillRgInfUeInfo(RgSchDlSf *sf,RgSchCellCb *cell,CmLListCp *dlDrxInactvTmrLst,CmLListCp *dlInActvLst,CmLListCp  *ulInActvLst)
5032 {
5033    RgInfSfAlloc    *sfAlloc;
5034    CmLListCp       *lnkLst;   /* lnkLst assignment */
5035    CmLList         *tmp;
5036    CmLList         *hqPNode;
5037    RgSchUeCb       *ue = NULLP;
5038    RgInfUeInfo     *ueInfo = NULLP;
5039    RgInfUeAlloc    *ueAlloc = NULLP;
5040    RgSchDlHqProcCb *hqCb = NULLP;
5041
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;
5046
5047    lnkLst = &(sf->msg4HqPLst);
5048    CM_LLIST_FIRST_NODE(lnkLst, tmp);
5049    while(NULLP != tmp)
5050    {
5051       DU_LOG("\nINFO  -->  SCH : 5GTF_ERROR MSG4 Consolidation\n");
5052       hqCb = (RgSchDlHqProcCb *)(tmp->node);
5053       CM_LLIST_NEXT_NODE(lnkLst, tmp);
5054
5055       rgSCHUtlFillRgInfTbInfo(hqCb, &ueAlloc[ueInfo->numUes], cell);
5056
5057       ue = hqCb->hqE->ue;
5058
5059       if(ue != NULLP)
5060       {   
5061          if((!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE)) && (ue->isDrxEnabled))
5062          {   
5063             rgSCHUtlGetDrxSchdUesInDl(cell, ue, hqCb, &ueAlloc[ueInfo->numUes], 
5064                   dlDrxInactvTmrLst, dlInActvLst, ulInActvLst);
5065          }
5066       }
5067       ueInfo->numUes++;
5068    }
5069  
5070    lnkLst = &(sf->ueLst);
5071    CM_LLIST_FIRST_NODE(lnkLst, tmp);
5072    while(NULLP != tmp)
5073    {
5074 #if defined (TENB_STATS) && defined (RG_5GTF)
5075       cell->tenbStats->sch.dl5gtfPdschCons++;
5076 #endif
5077       ue = (RgSchUeCb *)(tmp->node);
5078       CM_LLIST_NEXT_NODE(lnkLst, tmp);
5079
5080       hqPNode = ue->dl.dlSfHqInfo[cell->cellId][sf->dlIdx].hqPLst.first;
5081       while (hqPNode)
5082       {
5083          hqCb = (RgSchDlHqProcCb *)hqPNode->node;
5084          hqPNode = hqPNode->next;
5085
5086          sfAlloc = &(hqCb->hqE->cell->sfAllocArr[hqCb->hqE->cell->crntSfIdx]);
5087          ueInfo = &(sfAlloc->ueInfo);
5088          ueAlloc = sfAlloc->ueInfo.allocInfo;
5089
5090          rgSCHUtlFillRgInfTbInfo(hqCb, &ueAlloc[ueInfo->numUes], 
5091                hqCb->hqE->cell);
5092
5093          if(ue->isDrxEnabled)
5094          {   
5095             rgSCHUtlGetDrxSchdUesInDl(cell, ue, hqCb, &ueAlloc[ueInfo->numUes], 
5096                   dlDrxInactvTmrLst, dlInActvLst, ulInActvLst);
5097          }
5098          ueInfo->numUes++;
5099       }
5100 #ifdef LTE_ADV
5101       if (rgSchCb[cell->instIdx].genCfg.isSCellActDeactAlgoEnable == TRUE)
5102       {
5103          /*If remaining BO is left then increment the count*/
5104          if(ue->totalBo > 0)
5105          {
5106             ue->remBoCnt++;
5107             /* Check if trigger for Activation is met or not */
5108             if(rgSCHIsActvReqd(cell, ue))
5109             {
5110                ue->remBoCnt = 0;
5111                /*Passing primary cell*/
5112                rgSCHSCellSelectAndActDeAct(ue->cell, ue, RGR_SCELL_ACT);
5113             }
5114          }
5115          else
5116          {
5117             /*If remaining BO is 0 then reset the count*/
5118             ue->remBoCnt = 0;
5119          }
5120       }
5121 #endif
5122    }
5123   
5124    return;
5125 } /* end of rgSCHUtlFillRgInfUeInfo */
5126   /* CA dev End */
5127
5128
5129 /** @brief This function  shall update the scheduler with the CEs and data rcvd
5130  *
5131  * @details
5132  *
5133  *     Function: rgSCHUtlUpdSch
5134  *
5135  *         Processing steps:
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.
5141  *
5142  * @param  [in] RgCellCb   *cellCb
5143  * @param  [in] RgUeCb     *ueCb
5144  * @param  [in] RgMacPdu   *pdu
5145  * @param  [in] RgSchErrInfo  *err
5146  *  @return  S16
5147  *      -# ROK
5148  *      -# RFAILED
5149  */
5150 S16 rgSCHUtlUpdSch(RgInfSfDatInd *subfrmInfo,RgSchCellCb *cellCb,RgSchUeCb *ueCb,RgInfUeDatInd  *pdu,RgSchErrInfo *err)
5151 {
5152
5153    S16               ret;
5154 #ifdef LTEMAC_SPS
5155    if (RGSCH_UL_SPS_ACT_PRSENT & pdu->ceInfo.bitMask)
5156    {
5157       /* SPS to be activated due to data on SPS LCG ID*/
5158       rgSCHUtlSpsActInd(cellCb, ueCb, pdu->ceInfo.spsSduSize);
5159    }
5160 #endif
5161    /* TODO : Temp Fix for crash due to UL SDU corruption*/
5162    if (RGSCH_PHR_CE_PRSNT & pdu->ceInfo.bitMask)
5163    {
5164       /* PHR present */
5165       RGSCHCPYTIMEINFO(subfrmInfo->timingInfo, ueCb->macCeRptTime);
5166       if ((ret = rgSCHUtlUpdPhr(cellCb, ueCb, pdu->ceInfo.ces.phr, err)) != ROK)
5167          return (ret);
5168    }
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 
5173     *       received.
5174     */
5175    cellCb->sc.apis->rgSCHUpdUeDataIndLcg(cellCb, ueCb, pdu);
5176
5177 #ifndef MAC_5GTF_UPDATE
5178    if (RGSCH_TRUNC_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5179    {
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); 
5186    }
5187    else
5188    {
5189       if (RGSCH_SHORT_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5190       {
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);
5197       }
5198       else
5199       {
5200          if (RGSCH_LONG_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5201 #else
5202          if (RGSCH_BSR_CE_PRSNT & pdu->ceInfo.bitMask)
5203 #endif
5204          {
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,
5213                         err);
5214          }
5215 #ifndef MAC_5GTF_UPDATE
5216       }
5217  
5218    }
5219 #endif
5220             
5221    return ROK;
5222 } /* end of rgSCHUtlUpdSch */
5223 #ifdef RGR_V1
5224 /**
5225  * @brief Handler for Updating Bo received in StaRsp
5226  *
5227  * @details
5228  *
5229  *     Function : rgSCHUtlAddUeToCcchSduLst
5230  *
5231  *     This function shall be invoked once it receives staRsp on CCCH
5232  *
5233  *  @param[in]     RgSchCellCb       *cell
5234  *  @param[in]     RgSchUeCb       *ueCb
5235  *  @return  S16
5236  *      -# ROK
5237  **/
5238 S16 rgSCHUtlAddUeToCcchSduLst(RgSchCellCb  *cell,RgSchUeCb *ueCb)
5239 {
5240    RgSchCmnDlUe  *ueDl = RG_SCH_CMN_GET_DL_UE(ueCb, cell);
5241    RgSchDlHqProcCb *hqP  = (RgSchDlHqProcCb *)ueDl->proc;
5242
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))))
5249    {
5250       DU_LOG("\nINFO  -->  SCH : RNTI:%d Unexpected CCCH SDU BO",
5251          ueCb->ueId);
5252       return ROK;
5253    }
5254
5255    ueCb->ccchSduLnk.node = (PTR)(ueCb);
5256    cmLListAdd2Tail(&(cell->ccchSduUeLst), &(ueCb->ccchSduLnk));
5257
5258    return ROK;
5259 }
5260 /**
5261  *
5262  * @details
5263  *
5264  *     Function : rgSCHUtlUpdtBo
5265  *
5266  *     This function shall be invoked once it receives staRsp on CCCH
5267  *
5268  *  @param[in]     RgSchCellCb       *cell
5269  *  @param[in]     RgRguCmnStaRsp *staRsp
5270  *  @return  S16
5271  *      -# ROK
5272  **/
5273 S16 rgSCHUtlUpdtBo(RgSchCellCb  *cell,RgInfCmnBoRpt *staRsp)
5274 {
5275    RgSchUeCb *ueCb;
5276
5277    if ((ueCb = rgSCHDbmGetUeCb(cell, staRsp->u.rnti)) == NULLP)
5278    {
5279       /* Handle Ue fetch failure */
5280       DU_LOG("\nERROR  -->  SCH : Invalid UEID:%d",staRsp->u.rnti);
5281       return RFAILED;
5282    }
5283    /* Update Bo in ueCb */
5284    ueCb->dlCcchInfo.bo = (uint32_t)(staRsp->bo);
5285 #ifdef EMTC_ENABLE
5286      if(ueCb->isEmtcUe)
5287      {
5288         rgSCHUtlAddUeToEmtcCcchSduLst(cell,ueCb);
5289      }
5290      else
5291 #endif
5292     {
5293       rgSCHUtlAddUeToCcchSduLst(cell, ueCb);
5294     }
5295
5296    return ROK;
5297 } /* rgSCHUtlUpdtBo */
5298
5299 #endif
5300 /**
5301  *
5302  * @details
5303  *     Function : rgSCHUtlHndlCcchBoUpdt
5304  *
5305  *     This function shall fetch the raCb with the given rnti and ask RAM to
5306  *     update BO
5307  *
5308  *
5309  *  @param[in]  RgSchCellCb    *cell
5310  *  @param[in]  RgInfCmnBoRpt *boRpt
5311  *  @return  S16
5312  *      -# ROK
5313  *      -# RFAILED
5314  **/
5315 S16 rgSCHUtlHndlCcchBoUpdt(RgSchCellCb *cell,RgInfCmnBoRpt *boRpt)
5316 {
5317    RgSchRaCb       *raCb;
5318    RgSchUeCb *ueCb;
5319
5320    if ((raCb = rgSCHDbmGetRaCb(cell, boRpt->u.rnti)) == NULLP)
5321    {
5322 #ifdef RGR_V1
5323    /* CR timer implementation changes*/
5324       /*If no raCb, schedule ueCb, ueCb is extracted in rgSCHUtlUpdtBo*/
5325       return (rgSCHUtlUpdtBo(cell, boRpt));
5326 #else
5327       /* Handle RaCb fetch failure */
5328       DU_LOG("\nERROR  -->  SCH : Invalid RNTI:%d to fetch raCb",boRpt->u.rnti);
5329       return RFAILED;
5330 #endif
5331    }
5332
5333 #ifdef RGR_V1
5334
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))
5339       {
5340 #ifdef EMTC_ENABLE
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)
5344          {
5345             rgSCHRamEmtcUpdtBo(cell, raCb, boRpt);
5346          }
5347          else
5348 #endif
5349          {
5350             cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
5351             raCb->contResTmrLnk.node=NULLP;               
5352             rgSCHRamUpdtBo(cell, raCb, boRpt);
5353          }
5354        }
5355       else
5356       {
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)
5361          {
5362             /* Handle Ue fetch failure */
5363             DU_LOG("\nERROR  -->  SCH : Invalid RNTI:%d",boRpt->u.rnti);
5364             return RFAILED;
5365          }
5366          /* Update Bo in ueCb */
5367          ueCb->dlCcchInfo.bo = (uint32_t)(boRpt->bo);     
5368       }
5369
5370 #else
5371       rgSCHRamUpdtBo(cell, raCb, boRpt);
5372 #endif
5373
5374    return ROK;
5375 } /* rgSCHUtlHndlCcchBoUpdt */
5376
5377 /**
5378  * @brief Validates BO received for BCCH or PCCH.
5379  *
5380  * @details
5381  *
5382  *     Function : rgSCHUtlGetAllwdCchTbSz
5383  *
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
5387  *     accordingly set.
5388  *
5389  *
5390  *  @param[in]  uint32_t            bo
5391  *  @param[out] uint8_t             *nPrb
5392  *  @return  S32
5393  *      -# ROK
5394  *      -# RFAILED
5395  **/
5396 S32 rgSCHUtlGetAllwdCchTbSz(uint32_t bo,uint8_t  *nPrb,uint8_t  *mcs)
5397 {
5398    S32 lt;
5399    S32 cn;
5400    S32 rt;
5401
5402    for (lt = 0, rt = 43; lt <= rt;)
5403    {
5404       cn = (lt + rt)/2;
5405       if (rgSchUtlBcchPcchTbSzTbl[cn].tbSz == bo)
5406       {
5407          *nPrb = rgSchUtlBcchPcchTbSzTbl[cn].rbIndex;
5408          *mcs  = rgSchUtlBcchPcchTbSzTbl[cn].mcs;
5409          return (rgSchUtlBcchPcchTbSzTbl[cn].tbSz);
5410       }
5411       else if (rgSchUtlBcchPcchTbSzTbl[cn].tbSz < bo)
5412          lt = cn + 1;
5413       else
5414          rt = cn - 1;
5415    }
5416    if (lt == 44)
5417    {
5418       return RFAILED;
5419    }
5420    *nPrb = rgSchUtlBcchPcchTbSzTbl[lt].rbIndex;
5421    *mcs  = rgSchUtlBcchPcchTbSzTbl[lt].mcs;
5422    return (rgSchUtlBcchPcchTbSzTbl[lt].tbSz);
5423 }
5424
5425 /**
5426  * @brief Handler for BO Updt received for BCCH or PCCH.
5427  *
5428  * @details
5429  *
5430  *     Function : rgSCHUtlHndlBcchPcchBoUpdt
5431  *
5432  *     This function shall store the buffer and time to transmit in lcCb
5433  *
5434  *
5435  *  @param[in]  RgSchCellCb    *cell
5436  *  @param[in]  RgInfCmnBoRpt  *boRpt
5437  *  @return  S16
5438  *      -# ROK
5439  *      -# RFAILED
5440  **/
5441 S16 rgSCHUtlHndlBcchPcchBoUpdt(RgSchCellCb *cell,RgInfCmnBoRpt *boUpdt)
5442 {
5443    RgSchClcDlLcCb *dlLc;
5444    RgSchClcBoRpt  *boRpt;
5445    Inst           inst = cell->instIdx;
5446    uint8_t             nPrb=0;
5447    uint8_t             mcs=0;
5448
5449    dlLc = rgSCHDbmGetBcchOnBch(cell);
5450    if (dlLc == NULLP)
5451    {
5452       DU_LOG("\nERROR  -->  SCH : No Logical Channel dlLc is NULLP for RNTI:%d LCID:%d",boUpdt->u.rnti,boUpdt->lcId);
5453       return RFAILED;
5454    }
5455    if (boUpdt->lcId != dlLc->lcId)
5456    {
5457       /* Added for dropping paging Message*/      
5458           /*suman*/
5459       if ((rgSCHChkBoUpdate(cell,boUpdt))== ROK)  /* Checking if received BO falls within the window of 5120 slots*/
5460       {
5461          if (rgSCHUtlGetAllwdCchTbSz(boUpdt->bo*8, &nPrb, &mcs) 
5462                != (boUpdt->bo*8))
5463          {
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);
5466             return RFAILED;
5467          }
5468       }/*end of rgSCHChkBoUpdate*/
5469       else
5470       {
5471           return ROK;
5472       } 
5473    }
5474    if ((dlLc = rgSCHDbmGetCmnLcCb(cell, boUpdt->lcId)) == NULLP)
5475    {
5476       /* Handle lcCb fetch failure */
5477       DU_LOG("\nERROR  -->  SCH : LCID:%d Invalid for RNTI:%d",boUpdt->lcId,boUpdt->u.rnti);
5478    }
5479
5480    if (((rgSCHUtlAllocSBuf(inst, (Data **)(&boRpt), sizeof(RgSchClcBoRpt))) ==RFAILED) ||
5481        (!boRpt))
5482    {
5483       DU_LOG("\nERROR  -->  SCH : Allocation of common bo %dreport "
5484          "failed  RNTI:%d LCID:%d", boUpdt->bo,boUpdt->u.rnti,boUpdt->lcId);
5485       return RFAILED;
5486    }
5487
5488    boRpt->bo = boUpdt->bo;
5489    boRpt->mcs = mcs;
5490    boRpt->timeToTx = boUpdt->u.timeToTx;
5491    boRpt->nPrb = nPrb;
5492 #ifdef EMTC_ENABLE
5493    if(cell->emtcEnable)
5494    {
5495       boRpt->emtcDIReason = boUpdt->emtcDIReason;
5496       boRpt->pnb = boUpdt->pnb;
5497    }
5498 #endif
5499    RG_SCH_ADD_TO_CRNT_TIME(boRpt->timeToTx, 
5500          boRpt->maxTimeToTx, cell->siCfg.siWinSize)
5501    if((NULLP != dlLc) && (dlLc->si))
5502    {
5503       boRpt->retxCnt = cell->siCfg.retxCnt;
5504    }
5505    else
5506    {
5507       boRpt->retxCnt = 0;
5508    }
5509    rgSCHDbmInsCmnLcBoRpt(dlLc, boRpt);
5510
5511    return ROK;
5512 } /* rgSCHUtlHndlBcchPcchBoUpdt */
5513
5514 /**
5515  * @brief API for sending bind confirm from Scheduler instance to RRM
5516  *
5517  * @details
5518  *
5519  *     Function: rgSCHUtlRgrBndCfm
5520  *
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.
5524  *
5525  *  @param[in]  SuId          suId
5526  *  @param[in]  uint8_t            status
5527  *  @return  S16
5528  *      -# ROK
5529  *      -# RFAILED
5530  **/
5531 S16 rgSCHUtlRgrBndCfm(Inst instId,SuId suId,uint8_t status)
5532 {
5533    S16  ret = ROK;
5534
5535    ret = RgUiRgrBndCfm(&rgSchCb[instId].rgrSap[suId].sapCfg.sapPst, rgSchCb[instId].rgrSap[suId].sapCfg.suId, status);
5536    if (ret != ROK)
5537    {
5538       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrBndCfm: RgUiRgrBndCfm Failed ");
5539       return (ret);
5540    }
5541    return (ret);
5542 }  /* rgSCHUtlRgrBndCfm*/
5543
5544 /**
5545  * @brief API for sending bind confirm from Scheduler instance to RRM via RGM
5546  *        interface
5547  *
5548  * @details
5549  *
5550  *     Function: rgSCHUtlRgmBndCfm
5551  *
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
5554  *
5555  *  @param[in]  SuId          suId
5556  *  @param[in]  uint8_t            status
5557  *  @return  S16
5558  *      -# ROK
5559  *      -# RFAILED
5560  **/
5561 S16 rgSCHUtlRgmBndCfm(Inst instId,SuId suId,uint8_t status)
5562 {
5563    S16  ret = ROK;
5564
5565    ret = RgUiRgmBndCfm(&rgSchCb[instId].rgmSap[suId].sapCfg.sapPst, rgSchCb[instId].rgmSap[suId].sapCfg.suId, status);
5566    if (ret != ROK)
5567    {
5568       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgmBndCfm: RgUiRgrBndCfm Failed ");
5569       return (ret);
5570    }
5571    return (ret);
5572 }  /* rgSCHUtlRgmBndCfm*/
5573
5574
5575
5576 /**
5577  * @brief API for sending configuration confirm from Scheduler to DU APP
5578  *
5579  * @details
5580  *
5581  *     Function: schSendCfgCfm 
5582  *
5583  *     This API is invoked to send configuration confirm from Scheduler to DU
5584  *     APP.
5585  *
5586  *  @param[in]  Pst           pst 
5587  *  @param[in]  RgrCfgTransId transId
5588  *  @param[in]  uint8_t            status
5589  *  @return  S16
5590  *      -# ROK
5591  *      -# RFAILED
5592  **/
5593 S16 schSendCfgCfm(Region reg,Pool pool,RgrCfgTransId transId,uint8_t status)
5594 {
5595    Pst cfmPst;
5596
5597    memset((&cfmPst), 0, sizeof(Pst));
5598
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;
5607    cfmPst.pool      = pool;
5608
5609    if(RgUiRgrCfgCfm(&cfmPst,transId, status) != ROK)
5610    {
5611       DU_LOG("\nERROR  -->  SCH : schSendCfgCfm: RgUiRgrCfgCfm Failed ");
5612       return RFAILED;
5613    }
5614    return ROK;
5615 }  /* schSendCfgCfm*/
5616 #ifdef RGR_RRM_TICK
5617 /**
5618  * @brief API for sending TTI indication from Scheduler to RRM.
5619  *
5620  * @details
5621  *
5622  *     Function: rgSCHUtlRgrTtiInd
5623  *
5624  *     This API is invoked to send TTI indication from Scheduler instance to RRM.
5625  *     This API fills in Pst structure and RgrTtiIndInfo
5626  *
5627  *  @param[in]  cell                   RgSchCellCb
5628  *  @param[in]  CmLteTimingInfo        status
5629  *  @return  S16
5630  *      -# ROK
5631  *      -# RFAILED
5632  **/
5633 S16 rgSCHUtlRgrTtiInd(RgSchCellCb *cell,RgrTtiIndInfo *rgrTti)
5634 {
5635    S16           ret = ROK;
5636    RgSchUpSapCb  *rgrSap;                    /*!< RGR SAP Control Block */
5637 #ifdef L2_L3_SPLIT
5638    Bool g_usettitmr;
5639    Void mtTmrHdlrPublic(void);
5640 #endif
5641
5642    rgrSap = cell->rgrSap;
5643    if (rgrSap->sapSta.sapState != LRG_BND)
5644    {
5645       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrTtiInd() Upper SAP not bound (%d) ",
5646                rgrSap->sapSta.sapState);
5647       return RFAILED;
5648    }
5649    RgUiRgrTtiInd(&(cell->rgrSap->sapCfg.sapPst),
5650          cell->rgrSap->sapCfg.suId, rgrTti);
5651 #ifdef L2_L3_SPLIT
5652    {
5653       g_usettitmr = TRUE;
5654       mtTmrHdlrPublic();
5655    }
5656 #endif
5657    return (ret);
5658 }  /* rgSCHUtlRgrTtiInd*/
5659 #endif
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
5662  * if present.
5663  *
5664  * @details
5665  *
5666  *     Function:
5667  *
5668  *         Processing steps:
5669  *         - Retrieves the RaCb with the rnti provided, if it doesnt exist
5670  *         return failure.
5671  *         - If UE exists then update the Schduler with any MAC CEs if present.
5672  *         - Invoke RAM module to do Msg3 related processing rgSCHRamProcMsg3
5673  *
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
5679  * @param
5680  *  @return  S16
5681  *      -# ROK
5682  *      -# RFAILED
5683  */
5684 S16 rgSCHUtlProcMsg3
5685 (
5686 RgInfSfDatInd    *subfrmInfo,
5687 RgSchCellCb      *cellCb,
5688 RgSchUeCb        *ueCb,
5689 CmLteRnti        rnti,
5690 RgInfUeDatInd    *pdu,
5691 RgSchErrInfo     *err
5692 )
5693 {
5694    S16               ret;
5695    RgSchRaCb         *raCb;
5696
5697    /* must have an raCb for this case */
5698    raCb = rgSCHDbmGetRaCb (cellCb, rnti);
5699    if (raCb == NULLP)
5700    {
5701       DU_LOG("\nERROR  -->  SCH : RNTI:%d Received MSG3, unable to "
5702          "find raCb",rnti);
5703       return RFAILED;
5704    }
5705
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);
5709    if (ret != ROK)
5710    {
5711       DU_LOG("\nERROR  -->  SCH : Processing failed in the RAM "
5712          "RNTI:%d ",rnti);
5713       return (ret);
5714    }
5715    /* if ueCb is present */
5716    if (ueCb != NULLP)
5717    {
5718       rgSCHUtlUpdSch (subfrmInfo, cellCb, ueCb, pdu, err);
5719    }
5720
5721    return ROK;
5722 }
5723 #ifdef LTEMAC_SPS
5724 /** @brief This function is called by RgMacSchSpsRelInd. This function invokes the
5725  * scheduler with the information of the received Data.
5726  *
5727  * @details
5728  *
5729  *     Function: rgSCHUtlSpsRelInd
5730  *
5731  *         Processing steps:
5732  *         TODO
5733  *
5734  * @param  [in] RgSchCellCb        *cellCb
5735  * @param  [in] RgSchUeCb          *ueCb
5736  * @param  [in] Bool               *isExplRel
5737  * @param
5738  *  @return  S16
5739  *      -# ROK
5740  *      -# RFAILED
5741  */
5742 S16 rgSCHUtlSpsRelInd(RgSchCellCb *cellCb,RgSchUeCb *ueCb,Bool isExplRel)
5743 {
5744    cellCb->sc.apis->rgSCHUlSpsRelInd(cellCb, ueCb, isExplRel);
5745    return ROK;
5746 } /* end of rgSCHUtlSpsRelInd */
5747
5748
5749 /** @brief This function is called by RgMacSchSpsRelInd. This function invokes the
5750  * scheduler with the information of the received Data.
5751  *
5752  * @details
5753  *
5754  *     Function: rgSCHUtlSpsActInd
5755  *
5756  *         Processing steps:
5757  *         TODO
5758  *
5759  * @param  [in] RgSchCellCb        *cellCb
5760  * @param  [in] RgSchUeCb          *ueCb
5761  * @param  [in] uint16_t                spsSduSize
5762  * @param
5763  *  @return  S16
5764  *      -# ROK
5765  *      -# RFAILED
5766  */
5767 S16 rgSCHUtlSpsActInd(RgSchCellCb *cellCb,RgSchUeCb *ueCb,uint16_t spsSduSize)
5768 {
5769    cellCb->sc.apis->rgSCHUlSpsActInd(cellCb, ueCb, spsSduSize);
5770    return ROK;
5771 } /* end of rgSCHUtlSpsActInd */
5772
5773
5774 #endif /* LTEMAC_SPS */
5775
5776 #ifdef RG_PHASE_2
5777 /**
5778  * @brief This API is invoked to send uplink group power control request to PHY.
5779  *
5780  * @details
5781  *
5782  *     Function : rgSCHUtlTfuGrpPwrCntrlReq
5783  *
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.
5787  *
5788  *  @param[in]  TfuGrpPwrCntrlReqInfo *grpPwrCntrlReq
5789  *  @return  S16
5790  *      -# ROK
5791  *      -# RFAILED
5792  **/
5793 S16 rgSCHUtlTfuGrpPwrCntrlReq(Inst inst,S16 sapId,TfuGrpPwrCntrlReqInfo *grpPwrCntrlReq)
5794 {
5795    S16             ret;
5796    RgSchLowSapCb  *tfuSap;
5797    Pst             pst;
5798
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)
5802    {
5803       DU_LOG("\nERROR  -->  SCH : rgSCHUtlTfuGrpPwrCntrlReq() Lower SAP not bound (%d) ",tfuSap->sapSta.sapState);
5804       return RFAILED;
5805    }
5806    memcpy (&pst, &(tfuSap->sapCfg.sapPst), sizeof(Pst));
5807    if((ret = RgLiTfuGrpPwrCntrlReq (&pst, tfuSap->sapCfg.spId, grpPwrCntrlReq)) != ROK)
5808    {
5809        DU_LOG("\nERROR  -->  SCH : rgSCHUtlTfuGrpPwrCntrlReq() Call to RgLiTfuGrpPwrCntrlReq() failed");
5810    }
5811    return (ret);
5812 }  /* rgSCHUtlTfuGrpPwrCntrlReq */
5813 #endif
5814
5815 /* FOR ACK NACK REP */
5816
5817 /**
5818  * @brief This API is invoked to tell the DL Scheduler to add the UE back into
5819  * its scheduling queues.
5820  *
5821  * @details
5822  *
5823  *     Function : rgSCHUtlDlActvtUe
5824  *
5825  *      This API is invoked from Measurement gap moduled.
5826  *
5827  *  @param[in]  RgSchCellCb    *cell
5828  *  @param[in]  RgSchUeCb        *ueCb
5829  *
5830  *  @return  S16
5831  *      -# ROK
5832  *      -# RFAILED
5833  **/
5834 S16 rgSCHUtlDlActvtUe(RgSchCellCb *cell,RgSchUeCb   *ue)
5835 {
5836    cell->sc.apis->rgSCHActvtDlUe(cell, ue);
5837    return ROK;
5838 }
5839
5840 /**
5841  * @brief This API is invoked to tell the UL Scheduler to add the UE back into
5842  * its scheduling queues.
5843  *
5844  * @details
5845  *
5846  *     Function : rgSCHUtlUlActvtUe
5847  *
5848  *      This API is invoked from Measurement gap moduled.
5849  *
5850  *  @param[in]  RgSchCellCb    *cell
5851  *  @param[in]  RgSchUeCb        *ueCb
5852  *
5853  *  @return  S16
5854  *      -# ROK
5855  *      -# RFAILED
5856  **/
5857 S16 rgSCHUtlUlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
5858 {
5859    cell->sc.apis->rgSCHActvtUlUe(cell, ue);
5860    return ROK;
5861 }
5862
5863  /** @brief This function Validates the SAP information received along with the
5864   * primitive from the lower layer.
5865   *
5866   * Function: rgSCHUtlValidateTfuSap
5867   *
5868   *                      Validates SAP information.
5869   * @param  suId The SAP Id
5870   * @return
5871   *   -# ROK
5872   *   -# RFAILED
5873   */
5874 S16 rgSCHUtlValidateTfuSap(Inst  inst,SuId  suId)
5875 {
5876    RgSchLowSapCb  *tfuSap;
5877
5878    if(suId >= rgSchCb[inst].numSaps)
5879    {
5880       DU_LOG("\nERROR  -->  SCH : Incorrect SuId");
5881       return RFAILED;
5882    }
5883    tfuSap = &(rgSchCb[inst].tfuSap[suId]);
5884
5885    /* First lets check the suId */
5886    if( suId != tfuSap->sapCfg.suId)
5887    {
5888       DU_LOG("\nERROR  -->  SCH : Incorrect SuId. Configured (%d) Recieved (%d)",
5889             tfuSap->sapCfg.suId, suId);
5890       return RFAILED;
5891    }
5892    if (tfuSap->sapSta.sapState != LRG_BND)
5893    {
5894       DU_LOG("\nERROR  -->  SCH : Lower SAP not enabled SuId (%d)",
5895             tfuSap->sapCfg.suId);
5896       return RFAILED;
5897    }
5898    return ROK;
5899 } /* end of rgSCHUtlValidateTfuSap */
5900
5901 /*
5902 *
5903 *       Fun:   rgSCHUtlAllocEventMem
5904 *
5905 *       Desc:  This function allocates event memory
5906 *
5907 *       Ret:   ROK      - on success
5908 *              RFAILED  - on failure
5909 *
5910 *       Notes: None
5911 *
5912 *       File:  rg_utl.c
5913 *
5914 */
5915 S16 rgSCHUtlAllocEventMem(Inst inst,Ptr *memPtr,Size memSize)
5916 {
5917    Mem  sMem;
5918    volatile uint32_t  startTime=0;
5919
5920
5921    sMem.region = rgSchCb[inst].rgSchInit.region;
5922    sMem.pool = rgSchCb[inst].rgSchInit.pool;
5923
5924 #if (ERRCLASS & ERRCLS_DEBUG)
5925    if (memSize<= 0)
5926    {
5927       DU_LOG("\nERROR  -->  SCH : rgAllocEventMem(): memSize invalid\n");
5928       return  (RFAILED);
5929    }
5930 #endif /* ERRCLASS & ERRCLS_DEBUG */
5931    /*starting Task*/
5932    SStartTask(&startTime, PID_SCHUTL_CMALLCEVT);
5933
5934 #ifdef MS_MBUF_CORRUPTION /* Should be enabled when debugging mbuf corruption */
5935    MS_BUF_ADD_ALLOC_CALLER();
5936 #endif /* */
5937 #ifdef TFU_ALLOC_EVENT_NO_INIT
5938    if(ROK != cmAllocEvntNoInit(memSize, TFU_MAX_MEMBLK_SIZE, &sMem, memPtr))
5939 #else
5940    if(ROK != cmAllocEvnt(memSize, TFU_MAX_MEMBLK_SIZE, &sMem, memPtr))
5941 #endif /* */
5942    {
5943       DU_LOG("\nERROR  -->  SCH : cmAllocEvnt Failed.");
5944       return RFAILED;
5945    }
5946    /*stoping Task*/
5947    SStopTask(startTime, PID_SCHUTL_CMALLCEVT);
5948    return ROK;
5949 } /* end of rgSCHUtlAllocEventMem*/
5950
5951 /*
5952 *
5953 *       Fun:   rgGetEventMem
5954 *
5955 *       Desc:  This function allocates event memory
5956 *
5957 *       Ret:   ROK      - on success
5958 *              RFAILED  - on failure
5959 *
5960 *       Notes: None
5961 *
5962 *       File:  rg_utl.c
5963 *
5964 */
5965 S16 rgSCHUtlGetEventMem(Ptr *ptr,Size len,Ptr memCp)
5966 {
5967    S16   ret;
5968
5969 #ifdef TFU_ALLOC_EVENT_NO_INIT
5970    ret = cmGetMemNoInit(memCp, len, (Ptr *)ptr);
5971 #else
5972    ret = cmGetMem(memCp, len, (Ptr *)ptr);
5973 #endif
5974    return (ret);
5975 } /* end of rgSCHUtlGetEventMem*/
5976
5977 #ifdef LTE_TDD
5978
5979
5980 /**
5981  * @brief Handler to allocate memory for ACK/NACk feedback information
5982  *
5983  * @details
5984  *
5985  *     Function : rgSCHUtlAllocUeANFdbkInfo
5986  *
5987  *   It allocates memory for the UE related ACK NACK information.
5988  *
5989  *  @param[in]  RgSchUeCb           *ue
5990  *  @return     S16
5991  **/
5992 S16 rgSCHUtlAllocUeANFdbkInfo(RgSchUeCb *ue,uint8_t servCellIdx)
5993 {
5994    uint8_t idx;
5995
5996    if (rgSCHUtlAllocSBuf(ue->cell->instIdx,
5997                (Data **) &(ue->cellInfo[servCellIdx]->anInfo), sizeof(RgSchTddANInfo) * \
5998    ue->cell->ackNackFdbkArrSize) != ROK)
5999    {
6000       return RFAILED;
6001    }
6002
6003    for(idx=0; idx < ue->cell->ackNackFdbkArrSize; idx++)
6004    {
6005       rgSCHUtlInitUeANFdbkInfo(&ue->cellInfo[servCellIdx]->anInfo[idx]);
6006    }
6007
6008    /* Set it to the first index */
6009    ue->cellInfo[servCellIdx]->nextFreeANIdx = 0;
6010    return ROK;
6011 } /* rgSCHUtlAllocUeANFdbkInfo */
6012
6013 /**
6014  * @brief Handler to release memory for ACK/NACk feedback information
6015  *
6016  * @details
6017  *
6018  *     Function : rgSCHUtlDelUeANFdbkInfo
6019  *
6020  *   It releases memory for the UE related ACK NACK information.
6021  *
6022  *  @param[in]  RgSchUeCb           *ue
6023  *  @return     Void
6024  **/
6025 Void rgSCHUtlDelUeANFdbkInfo(RgSchUeCb *ue,uint8_t servCellIdx)
6026 {
6027
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);
6033
6034    return;
6035 } /* rgSCHUtlDelUeANFdbkInfo */
6036
6037 /**
6038  * @brief Handler to initialise UE ACK/NACk feedback information
6039  *
6040  * @details
6041  *
6042  *     Function : rgSCHUtlInitUeANFdbkInfo
6043  *
6044  *   It initialises UE related ACK NACK information.
6045  *
6046  *  @param[in]  RgSchTddANInfo   *anFdInfo
6047  *  @return     S16
6048  **/
6049 S16 rgSCHUtlInitUeANFdbkInfo(RgSchTddANInfo *anFdInfo)
6050 {
6051
6052    anFdInfo->sfn = RGSCH_MAX_SFN+1; /* defensively setting invalid sfn */
6053    anFdInfo->slot = 0;
6054    anFdInfo->ulDai = RG_SCH_INVALID_DAI_VAL;
6055    anFdInfo->dlDai = RG_SCH_INVALID_DAI_VAL;
6056    anFdInfo->latestMIdx = RG_SCH_INVALID_M_VAL;
6057
6058    return ROK;
6059 } /* rgSCHUtlInitUeANFdbkInfo */
6060
6061 /**
6062  * @brief Handler to get UE related ACK NACK feedback information
6063  *
6064  * @details
6065  *
6066  *     Function : rgSCHUtlGetUeANFdbkInfo
6067  *
6068  *   It gets the UE related ACK NACK information based on
6069  *   SFN and slot number.
6070  *
6071  *  @param[in]  RgSchUeCb        *ueCb
6072  *  @param[in]  CmLteTimingInfo  *time
6073  *  @return     RgSchTddANInfo*
6074  **/
6075 RgSchTddANInfo* rgSCHUtlGetUeANFdbkInfo(RgSchUeCb *ueCb,CmLteTimingInfo *timeInfo,uint8_t servCellIdx)
6076 {
6077    uint8_t idx;
6078
6079    for (idx = 0; idx < ueCb->cell->ackNackFdbkArrSize; ++idx)
6080    {
6081        if( (timeInfo->sfn == ueCb->cellInfo[servCellIdx]->anInfo[idx].sfn) &&
6082                (timeInfo->slot == ueCb->cellInfo[servCellIdx]->anInfo[idx].slot))
6083        {
6084             return (&ueCb->cellInfo[servCellIdx]->anInfo[idx]);
6085        }
6086    }
6087
6088    return (NULLP);
6089 } /* rgSCHUtlGetUeANFdbkInfo */
6090
6091 /**
6092  * @brief To get downlink slot index
6093  *
6094  * @details
6095  *
6096  *     Function: rgSCHUtlGetDlSfIdx
6097  *     Purpose:  Gets downlink slot index based on SFN and slot no
6098  *
6099  *  @param[in]  CmLteTimingInfo  *timeInfo
6100  *  @param[in]  RgSchCellCb         *cell
6101  *  @return uint8_t
6102  *
6103  **/
6104 uint8_t  rgSCHUtlGetDlSfIdx(RgSchCellCb  *cell,CmLteTimingInfo *timeInfo)
6105 {
6106    uint16_t       idx = 0;
6107
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;
6113
6114    return ((uint8_t)idx);
6115 }
6116
6117 /**
6118  * @brief To get the next downlink slot
6119  *
6120  * @details
6121  *
6122  *     Function: rgSCHUtlGetNxtDlSfInfo
6123  *     Purpose:  Gets next downlink slot based on current DL slot
6124  *
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
6130  *  @return uint8_t
6131  *
6132  **/
6133 Void rgSCHUtlGetNxtDlSfInfo(CmLteTimingInfo curDlTime,RgSchCellCb  *cell,RgSchDlSf *dlSf,RgSchDlSf **nxtDlsf,CmLteTimingInfo *nxtDlTime)
6134 {
6135    uint16_t  idx = curDlTime.slot;
6136    uint8_t   count = 0;
6137
6138    while(TRUE)
6139    {
6140       do
6141       {
6142          idx = (idx + 1) % RGSCH_NUM_SUB_FRAMES;
6143          count++;
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)
6149       {
6150          break;
6151       }
6152    }
6153    return;
6154 }
6155
6156 /**
6157  * @brief To get the previous downlink slot
6158  *
6159  * @details
6160  *
6161  *     Function: rgSCHUtlGetPrevDlSfInfo
6162  *     Purpose:  Gets previous downlink slot based on current DL slot
6163  *
6164  *  @param[in]  RgSchCellCb      *cell
6165  *  @param[in]  CmLteTimingInfo  curDlTime
6166  *  @param[in]  CmLteTimingInfo  *prevDlTime
6167  *  @param[in]  uint8_t               *numSubfrm
6168  *  @return uint8_t
6169  *
6170  **/
6171 Void rgSCHUtlGetPrevDlSfInfo(RgSchCellCb *cell,CmLteTimingInfo curDlTime,CmLteTimingInfo *prevDlTime,uint8_t *numSubfrm)
6172 {
6173    S16 idx = curDlTime.slot;
6174    uint8_t  count = 0;
6175
6176    do
6177    {
6178       idx--;
6179       if(idx < 0)
6180       {
6181          idx = RGSCH_NUM_SUB_FRAMES-1;
6182       }
6183       count++;
6184    }while(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][idx]
6185          !=  RG_SCH_TDD_DL_slot);
6186    *numSubfrm = count;
6187    RGSCHDECRFRMCRNTTIME(curDlTime, (*prevDlTime), count);
6188    return;
6189 }
6190
6191 #endif
6192 /* Added Holes Management functions for Adaptive Re transmission */
6193 /******* </AllocHolesMemMgmnt>: START *****/
6194 /***********************************************************
6195  *
6196  *     Func : rgSCHUtlUlSfInit
6197  *
6198  *     Desc : UL slot init.
6199  *
6200  *     Ret  : S16
6201  *
6202  *     Notes:
6203  *
6204  *     File :
6205  *
6206  **********************************************************/
6207 S16 rgSCHUtlUlSfInit(RgSchCellCb  *cell,RgSchUlSf *sf,uint8_t idx,uint8_t maxUePerSf)
6208 {
6209    S16             ret=ROK;
6210
6211    sf->idx = idx;
6212 #ifdef RG_5GTF
6213    uint8_t index;
6214 #endif
6215
6216 #ifdef LTE_TDD   
6217    if(cell->ulDlCfgIdx == 0)
6218    {
6219       /* Store the Uplink slot number corresponding to the idx */
6220       sf->ulSfIdx = rgSchTddCfg0UlSfTbl[idx%6]; 
6221    }
6222 #endif   
6223    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf->allocDb,
6224                            sizeof(RgSchUlAllocDb));
6225    if (ret != ROK)
6226    {
6227       return (ret);
6228    }
6229    ret = rgSCHUtlUlAllocDbInit(cell, sf->allocDb, maxUePerSf);
6230    if (ret != ROK)
6231    {
6232       /* ccpu00117052 - MOD - Passing double pointer
6233       for proper NULLP assignment*/
6234       rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(sf->allocDb)),
6235                        sizeof(RgSchUlAllocDb));
6236       return (ret);
6237    }
6238    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&sf->holeDb,
6239          sizeof(RgSchUlHoleDb));
6240    if (ret != ROK)
6241    {
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));
6247       return (ret);
6248    }
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);
6252
6253    if (ret != ROK)
6254    {
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));
6262       return (ret);
6263    }
6264    cmLListInit(&sf->reTxLst);
6265
6266    /* Fix ccpu00120610*/
6267    sf->allocCountRef = &sf->allocDb->count;
6268
6269    /* initialize UL available subbands for current sub-frame */
6270    sf->availSubbands = cell->dynCfiCb.bwInfo[1].numSb;
6271 #ifdef RG_5GTF
6272    sf->numGrpPerTti = cell->cell5gtfCb.ueGrpPerTti;
6273    sf->numUePerGrp = cell->cell5gtfCb.uePerGrpPerTti;
6274    for(index = 0; index < MAX_5GTF_BEAMS; index++)
6275    {
6276       sf->sfBeamInfo[index].totVrbgAllocated = 0;
6277       sf->sfBeamInfo[index].totVrbgRequired = 0;
6278       sf->sfBeamInfo[index].vrbgStart = 0;
6279    }
6280 #endif
6281
6282    return (ret);
6283 }
6284
6285
6286 /***********************************************************
6287  *
6288  *     Func : rgSCHUtlUlSfDeinit
6289  *
6290  *     Desc : Deinitialises a slot
6291  *
6292  *     Ret  : Void
6293  *
6294  *     Notes:
6295  *
6296  *     File :
6297  *
6298  **********************************************************/
6299 Void rgSCHUtlUlSfDeinit(RgSchCellCb  *cell,RgSchUlSf  *sf)
6300 {
6301    if (sf->allocDb)
6302    {
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));
6310    }
6311    if (sf->holeDb)
6312    {
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));
6318    }
6319    return;
6320 }
6321
6322 /***********************************************************
6323  *
6324  *     Func : rgSCHUtlUlAllocDbInit
6325  *
6326  *     Desc : Initialise allocation DB
6327  *
6328  *     Ret  : S16 (ROK/RFAILED)
6329  *
6330  *     Notes:
6331  *
6332  *     File :
6333  *
6334  **********************************************************/
6335 static S16 rgSCHUtlUlAllocDbInit(RgSchCellCb *cell,RgSchUlAllocDb *allocDb,uint8_t maxAllocs)
6336 {
6337    S16 ret = rgSCHUtlUlAllocMemInit(cell, &allocDb->mem, maxAllocs);
6338    if (ret != ROK)
6339    {
6340       return (ret);
6341    }
6342    allocDb->count = 0;
6343    allocDb->first = NULLP;
6344    return ROK;
6345 }
6346
6347 /***********************************************************
6348  *
6349  *     Func : rgSCHUtlUlAllocDbDeinit
6350  *
6351  *     Desc : Deinitialises allocation DB
6352  *            sent to UE, for a UE with accumulation disabled
6353  *
6354  *     Ret  : Void
6355  *
6356  *     Notes:
6357  *
6358  *     File :
6359  *
6360  **********************************************************/
6361 static Void rgSCHUtlUlAllocDbDeinit(RgSchCellCb *cell,RgSchUlAllocDb *allocDb)
6362 {
6363    rgSCHUtlUlAllocMemDeinit(cell, &allocDb->mem);
6364    allocDb->count = 0;
6365    allocDb->first = NULLP;
6366    return;
6367 }
6368
6369 /***********************************************************
6370  *
6371  *     Func : rgSCHUtlUlHoleDbInit
6372  *
6373  *     Desc : Initialise hole DB
6374  *
6375  *     Ret  : S16 (ROK/RFAILED)
6376  *
6377  *     Notes:
6378  *
6379  *     File :
6380  *
6381  **********************************************************/
6382 static S16 rgSCHUtlUlHoleDbInit(RgSchCellCb *cell,RgSchUlHoleDb *holeDb,uint8_t maxHoles,uint8_t start,uint8_t num)
6383 {
6384    S16 ret;
6385    RgSchUlHole *hole = NULLP;
6386
6387    ret = rgSCHUtlUlHoleMemInit(cell, &holeDb->mem, maxHoles, &hole);
6388    if (ret != ROK)
6389    {
6390       return (ret);
6391    }
6392    holeDb->count = 1;
6393    holeDb->first = hole;
6394    hole->start = start;
6395    hole->num = num;
6396    hole->prv = hole->nxt = NULLP;
6397    return ROK;
6398 }
6399
6400 /***********************************************************
6401  *
6402  *     Func : rgSCHUtlUlHoleDbDeinit
6403  *
6404  *     Desc : Deinitialises hole DB
6405  *
6406  *     Ret  : Void
6407  *
6408  *     Notes:
6409  *
6410  *     File :
6411  *
6412  **********************************************************/
6413 static Void rgSCHUtlUlHoleDbDeinit(RgSchCellCb   *cell,RgSchUlHoleDb *holeDb)
6414 {
6415    rgSCHUtlUlHoleMemDeinit(cell, &holeDb->mem);
6416    holeDb->count = 0;
6417    holeDb->first = NULLP;
6418    return;
6419 }
6420
6421
6422 /***********************************************************
6423  *
6424  *     Func : rgSCHUtlUlAllocGetHole
6425  *
6426  *     Desc : Get allocation from hole
6427  *
6428  *     Ret  : RgSchUlAlloc *
6429  *
6430  *     Notes:
6431  *
6432  *     File :
6433  *
6434  **********************************************************/
6435 RgSchUlAlloc *rgSCHUtlUlAllocGetHole(RgSchUlSf *sf,uint8_t numSb,RgSchUlHole *hole)
6436 {
6437    if (numSb < hole->num)
6438    {
6439       return (rgSCHUtlUlAllocGetPartHole(sf, numSb, hole));
6440    }
6441    else
6442    {
6443       return (rgSCHUtlUlAllocGetCompHole(sf, hole));
6444    }
6445 }
6446
6447
6448 /***********************************************************
6449  *
6450  *     Func : rgSCHUtlUlAllocGetCompHole
6451  *
6452  *     Desc : Get an allocation corresponding to an entire hole
6453  *
6454  *     Ret  : RgSchUlAlloc *
6455  *
6456  *     Notes:
6457  *
6458  *     File :
6459  *
6460  **********************************************************/
6461 RgSchUlAlloc *rgSCHUtlUlAllocGetCompHole(RgSchUlSf   *sf,RgSchUlHole *hole)
6462 {
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;
6469
6470    if (prv)
6471    {
6472       if (hole->start == prv->nxtHole->start)
6473       {
6474          prv->nxtHole = NULLP;
6475       }
6476       alloc = rgSCHUtlUlAllocGetAdjNxt(sf->allocDb, prv);
6477    }
6478    else
6479    {
6480       alloc = rgSCHUtlUlAllocGetFirst(sf->allocDb);
6481    }
6482
6483    RGSCH_NULL_CHECK( 0, alloc);
6484    alloc->prvHole = NULLP;
6485    alloc->nxtHole = NULLP;
6486
6487    alloc->sbStart = hole->start;
6488    alloc->numSb = hole->num;
6489
6490    if (nxt)
6491    {
6492       nxt->prvHole = NULLP;
6493    }
6494
6495    rgSCHUtlUlHoleRls(sf->holeDb, hole);
6496
6497    /* UL_ALLOC_CHANGES*/
6498    alloc->allocDbRef = (void*)sf->allocDb;
6499    alloc->holeDbRef  = (void*)sf->holeDb;
6500    return (alloc);
6501 }
6502
6503 /***********************************************************
6504  *
6505  *     Func : rgSCHUtlUlAllocGetPartHole
6506  *
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.
6510  *
6511  *     Ret  : RgSchUlAlloc *
6512  *
6513  *     Notes:
6514  *
6515  *     File :
6516  *
6517  **********************************************************/
6518 RgSchUlAlloc *rgSCHUtlUlAllocGetPartHole(RgSchUlSf *sf,uint8_t numSb,RgSchUlHole *hole)
6519 {
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;
6525
6526    if (prv)
6527    {
6528       if (hole->start == prv->nxtHole->start)
6529       {
6530          prv->nxtHole = NULLP;
6531       }
6532       alloc = rgSCHUtlUlAllocGetAdjNxt(sf->allocDb, prv);
6533    }
6534    else
6535    {
6536       alloc = rgSCHUtlUlAllocGetFirst(sf->allocDb);
6537    }
6538
6539    RGSCH_NULL_CHECK( 0, alloc);
6540    alloc->prvHole = NULLP;
6541    alloc->nxtHole = hole;
6542    hole->prvAlloc = alloc;
6543
6544    alloc->sbStart = hole->start;
6545    alloc->numSb = numSb;
6546    hole->start += numSb;
6547    hole->num -= numSb;
6548
6549    rgSCHUtlUlHoleDecr(sf->holeDb, hole);
6550
6551    /* UL_ALLOC_CHANGES*/
6552    alloc->allocDbRef = (void*)sf->allocDb;
6553    alloc->holeDbRef  = (void*)sf->holeDb;
6554
6555    return (alloc);
6556 }
6557
6558 /***********************************************************
6559  *
6560  *     Func : rgSCHUtlUlAllocFirst
6561  *
6562  *     Desc : Get first alloc in slot
6563  *
6564  *     Ret  : RgSchUlAlloc *
6565  *
6566  *     Notes:
6567  *
6568  *     File :
6569  *
6570  **********************************************************/
6571 RgSchUlAlloc *rgSCHUtlUlAllocFirst(RgSchUlSf *sf)
6572 {
6573    return (sf->allocDb->first);
6574 }
6575
6576 /***********************************************************
6577  *
6578  *     Func : rgSCHUtlUlAllocNxt
6579  *
6580  *     Desc : Get next alloc
6581  *
6582  *     Ret  : RgSchUlAlloc *
6583  *
6584  *     Notes:
6585  *
6586  *     File :
6587  *
6588  **********************************************************/
6589 RgSchUlAlloc *rgSCHUtlUlAllocNxt(RgSchUlSf    *sf,RgSchUlAlloc *alloc)
6590 {
6591    UNUSED(sf);
6592    return (alloc->nxt);
6593 }
6594
6595 /***********************************************************
6596  *
6597  *     Func : rgSCHUtlUlAllocGetAdjNxt
6598  *
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.
6606  *
6607  *     Ret  : RgSchUlAlloc *
6608  *
6609  *     Notes:
6610  *
6611  *     File :
6612  *
6613  **********************************************************/
6614 RgSchUlAlloc *rgSCHUtlUlAllocGetAdjNxt(RgSchUlAllocDb *db,RgSchUlAlloc   *prv)
6615 {
6616    RgSchUlAlloc *alloc = rgSCHUtlUlAllocMemGet(&db->mem);
6617    RgSchUlAlloc *nxt = prv->nxt;
6618
6619 #if (ERRCLASS & ERRCLS_DEBUG)
6620    if ( alloc == NULLP )
6621    {
6622        return  ( NULLP );
6623    }
6624 #endif
6625    alloc->prv = prv;
6626    alloc->nxt = nxt;
6627    prv->nxt = alloc;
6628    if (nxt)
6629    {
6630       nxt->prv = alloc;
6631    }
6632
6633    ++db->count;
6634
6635    return (alloc);
6636 }
6637
6638 /***********************************************************
6639  *
6640  *     Func : rgSCHUtlUlAllocGetFirst
6641  *
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.
6648  *
6649  *     Ret  : RgSchUlAlloc *
6650  *
6651  *     Notes:
6652  *
6653  *     File :
6654  *
6655  **********************************************************/
6656 RgSchUlAlloc *rgSCHUtlUlAllocGetFirst(RgSchUlAllocDb *db)
6657 {
6658    RgSchUlAlloc *alloc = rgSCHUtlUlAllocMemGet(&db->mem);
6659    RgSchUlAlloc *nxt = db->first;
6660
6661 #if (ERRCLASS & ERRCLS_DEBUG)
6662     if ( alloc == NULLP )
6663     {
6664        return  ( NULLP );
6665     }
6666 #endif
6667
6668    alloc->prv = NULLP;
6669    alloc->nxt = nxt;
6670    if (nxt)
6671    {
6672       nxt->prv = alloc;
6673    }
6674    db->first = alloc;
6675
6676    ++db->count;
6677
6678    return (alloc);
6679 }
6680
6681 /* UL_ALLOC_ENHANCEMENT */
6682 /***********************************************************
6683  *
6684  *     Func : rgSCHUtlUlHoleAddAllocation
6685  *
6686  *     Desc : On freeing an alloc, add to hole
6687  *
6688  *     Ret  : Void
6689  *
6690  *     Notes:
6691  *
6692  *     File :
6693  *
6694  **********************************************************/
6695 Void rgSCHUtlUlHoleAddAllocation(RgSchUlAlloc *alloc)
6696 {
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;
6706
6707    if (prv)
6708    {
6709       if (nxt)
6710       {
6711          rgSCHUtlUlHoleJoin(db, prv, nxt, alloc);
6712       }
6713       else
6714          rgSCHUtlUlHoleExtndRight(db, prv, alloc);
6715    }
6716    else
6717    {
6718       if (nxt)
6719       {
6720          rgSCHUtlUlHoleExtndLeft(db, nxt, alloc);
6721       }
6722       else
6723          rgSCHUtlUlHoleNew(db, alloc);
6724    }
6725    return;
6726 }
6727
6728
6729 /***********************************************************
6730  *
6731  *     Func : rgSCHUtlUlAllocRelease
6732  *
6733  *     Desc : Releases an uplink allocation, only take alloc ptr
6734  *
6735  *     Ret  : Void
6736  *
6737  *     Notes:
6738  *
6739  *     File :
6740  *
6741  **********************************************************/
6742 Void rgSCHUtlUlAllocRelease(RgSchUlAlloc *alloc)
6743 {
6744    RgSchUlAllocDb *allocDb = alloc->allocDbRef;
6745    RgSchUlAlloc   *prv = alloc->prv;
6746    RgSchUlAlloc   *nxt = alloc->nxt;
6747
6748    alloc->ue = NULLP;
6749    alloc->raCb = NULLP;
6750    alloc->isAdaptive = FALSE;
6751
6752    if (prv)
6753    {
6754       prv->nxt = nxt;
6755       if (nxt)           /* general case: this allocation lies btw two */
6756       {
6757          nxt->prv = prv;
6758       }
6759    }
6760    else
6761    {
6762       allocDb->first = nxt;
6763       if (nxt)
6764       {
6765          nxt->prv = NULLP;
6766       }
6767    }
6768    --allocDb->count;
6769    rgSCHUtlUlHoleAddAllocation(alloc);
6770    rgSCHUtlUlAllocMemRls(&allocDb->mem, alloc);
6771
6772    return;
6773 }
6774
6775
6776 /***********************************************************
6777  *
6778  *     Func : rgSCHUtlUlAllocRls
6779  *
6780  *     Desc : Releases an uplink allocation
6781  *
6782  *     Ret  : Void
6783  *
6784  *     Notes:
6785  *
6786  *     File :
6787  *
6788  **********************************************************/
6789 Void rgSCHUtlUlAllocRls(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6790 {
6791    RgSchUlAllocDb *allocDb = sf->allocDb;
6792    RgSchUlAlloc   *prv = alloc->prv;
6793    RgSchUlAlloc   *nxt = alloc->nxt;
6794
6795    alloc->ue = NULLP;
6796    alloc->raCb = NULLP;
6797    alloc->isAdaptive = FALSE;
6798
6799    if(allocDb->count)
6800    {
6801       if (prv)
6802       {
6803          prv->nxt = nxt;
6804          if (nxt)           /* general case: this allocation lies btw two */
6805          {
6806             nxt->prv = prv;
6807          }
6808       }
6809       else
6810       {
6811          allocDb->first = nxt;
6812          if (nxt)
6813          {
6814             nxt->prv = NULLP;
6815          }
6816       }
6817       --allocDb->count;
6818       rgSCHUtlUlHoleAddAlloc(sf, alloc);
6819       rgSCHUtlUlAllocMemRls(&allocDb->mem, alloc);
6820    }
6821    else
6822    {
6823
6824       DU_LOG("\nERROR  -->  SCH :  allocDb->count is ZERO ");
6825    }
6826
6827    //DU_LOG("\nallocDb->count:%u\n",allocDb->count);
6828
6829    return;
6830 }
6831
6832 /***********************************************************
6833  *
6834  *     Func : rgSCHUtlUlHoleFirst
6835  *
6836  *     Desc : Get first (largest) hole
6837  *
6838  *     Ret  : RgSchUlHole *
6839  *
6840  *     Notes:
6841  *
6842  *     File :
6843  *
6844  **********************************************************/
6845 RgSchUlHole *rgSCHUtlUlHoleFirst(RgSchUlSf *sf)
6846 {
6847    return (sf->holeDb->first);
6848 }
6849
6850 /***********************************************************
6851  *
6852  *     Func : rgSCHUtlUlHoleNxt
6853  *
6854  *     Desc : Get next largest hole
6855  *
6856  *     Ret  : RgSchUlHole *
6857  *
6858  *     Notes:
6859  *
6860  *     File :
6861  *
6862  **********************************************************/
6863 RgSchUlHole *rgSCHUtlUlHoleNxt(RgSchUlSf   *sf,RgSchUlHole *hole)
6864 {
6865    UNUSED(sf);
6866    return (hole->nxt);
6867 }
6868
6869 /***********************************************************
6870  *
6871  *     Func : rgSCHUtlUlHoleAddAlloc
6872  *
6873  *     Desc : On freeing an alloc, add to hole
6874  *
6875  *     Ret  : Void
6876  *
6877  *     Notes:
6878  *
6879  *     File :
6880  *
6881  **********************************************************/
6882 Void rgSCHUtlUlHoleAddAlloc(RgSchUlSf *sf,RgSchUlAlloc *alloc)
6883 {
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;
6893
6894    if (prv)
6895    {
6896       if (nxt)
6897       {
6898          rgSCHUtlUlHoleJoin(db, prv, nxt, alloc);
6899       }
6900       else
6901          rgSCHUtlUlHoleExtndRight(db, prv, alloc);
6902    }
6903    else
6904    {
6905       if (nxt)
6906       {
6907          rgSCHUtlUlHoleExtndLeft(db, nxt, alloc);
6908       }
6909       else
6910          rgSCHUtlUlHoleNew(db, alloc);
6911    }
6912
6913    /* increment the number of subbands getting freed to total available list */
6914    sf->availSubbands += alloc->numSb;
6915
6916    return;
6917 }
6918
6919 /***********************************************************
6920  *
6921  *     Func : rgSCHUtlUlHoleJoin
6922  *
6923  *     Desc : Join two holes (due to alloc being deleted)
6924  *
6925  *     Ret  : Void
6926  *
6927  *     Notes:
6928  *
6929  *     File :
6930  *
6931  **********************************************************/
6932 Void rgSCHUtlUlHoleJoin(RgSchUlHoleDb *db,RgSchUlHole *prv,RgSchUlHole *nxt,RgSchUlAlloc *alloc)
6933 {
6934    prv->num += alloc->numSb + nxt->num;
6935    rgSCHUtlUlHoleRls(db, nxt);
6936    rgSCHUtlUlHoleIncr(db, prv);
6937    rgSCHUtlUlHoleUpdAllocLnks(prv, alloc->prv, alloc->nxt);
6938
6939    return;
6940 }
6941
6942 /***********************************************************
6943  *
6944  *     Func : rgSCHUtlUlHoleExtndRight
6945  *
6946  *     Desc : Extend hole due to alloc coming 'after' the hole
6947  *            being deleted
6948  *
6949  *     Ret  : Void
6950  *
6951  *     Notes:
6952  *
6953  *     File :
6954  *
6955  **********************************************************/
6956 Void rgSCHUtlUlHoleExtndRight(RgSchUlHoleDb *db,RgSchUlHole *prv,RgSchUlAlloc *alloc)
6957 {
6958    prv->num += alloc->numSb;
6959    rgSCHUtlUlHoleIncr(db, prv);
6960    rgSCHUtlUlHoleUpdAllocLnks(prv, alloc->prv, alloc->nxt);
6961    return;
6962 }
6963
6964 /***********************************************************
6965  *
6966  *     Func : rgSCHUtlUlHoleExtndLeft
6967  *
6968  *     Desc : Extend hole due to alloc coming 'before' the hole
6969  *            being deleted
6970  *
6971  *     Ret  : Void
6972  *
6973  *     Notes:
6974  *
6975  *     File :
6976  *
6977  **********************************************************/
6978 Void rgSCHUtlUlHoleExtndLeft(RgSchUlHoleDb *db,RgSchUlHole   *nxt,RgSchUlAlloc  *alloc)
6979 {
6980    nxt->num += alloc->numSb;
6981    nxt->start = alloc->sbStart;
6982    rgSCHUtlUlHoleIncr(db, nxt);
6983    rgSCHUtlUlHoleUpdAllocLnks(nxt, alloc->prv, alloc->nxt);
6984    return;
6985 }
6986
6987 /***********************************************************
6988  *
6989  *     Func : rgSCHUtlUlHoleNew
6990  *
6991  *     Desc : Create new hole due to alloc being deleted
6992  *
6993  *     Ret  : Void
6994  *
6995  *     Notes:
6996  *
6997  *     File :
6998  *
6999  **********************************************************/
7000 Void rgSCHUtlUlHoleNew(RgSchUlHoleDb *db,RgSchUlAlloc  *alloc)
7001 {
7002    RgSchUlHole *hole = rgSCHUtlUlHoleMemGet(&db->mem);
7003 #if (ERRCLASS & ERRCLS_DEBUG)
7004    if ( hole == NULLP )
7005    {
7006       return;
7007    }
7008 #endif
7009    hole->start = alloc->sbStart;
7010    hole->num = alloc->numSb;
7011    ++db->count;
7012    rgSCHUtlUlHoleIns(db, hole);
7013    rgSCHUtlUlHoleUpdAllocLnks(hole, alloc->prv, alloc->nxt);
7014    return;
7015 }
7016
7017 /***********************************************************
7018  *
7019  *     Func : rgSCHUtlUlHoleUpdAllocLnks
7020  *
7021  *     Desc : Update alloc links in hole
7022  *
7023  *     Ret  : Void
7024  *
7025  *     Notes:
7026  *
7027  *     File :
7028  *
7029  **********************************************************/
7030 Void rgSCHUtlUlHoleUpdAllocLnks(RgSchUlHole  *hole,RgSchUlAlloc *prvAlloc,RgSchUlAlloc *nxtAlloc)
7031 {
7032    if (prvAlloc)
7033    {
7034       prvAlloc->nxtHole = hole;
7035    }
7036    if (nxtAlloc)
7037    {
7038       nxtAlloc->prvHole = hole;
7039    }
7040    hole->prvAlloc = prvAlloc;
7041    hole->nxtAlloc = nxtAlloc;
7042    return;
7043 }
7044
7045
7046 /***********************************************************
7047  *
7048  *     Func : rgSCHUtlUlHoleIns
7049  *
7050  *     Desc : Insert (newly created) hole in sorted list of holes.
7051  *            Searches linearly, beginning with the largest hole.
7052  *
7053  *     Ret  : Void
7054  *
7055  *     Notes:
7056  *
7057  *     File :
7058  *
7059  **********************************************************/
7060 Void rgSCHUtlUlHoleIns(RgSchUlHoleDb *db,RgSchUlHole   *hole)
7061 {
7062    RgSchUlHole *cur;
7063
7064    if ((cur = db->first) != NULLP)
7065    {
7066       RgSchUlHole *nxt;
7067       if (cur->num < hole->num)
7068       {
7069          /* Add at front */
7070          hole->nxt = cur;
7071          cur->prv = hole;
7072          db->first = hole;
7073          hole->prv = NULLP;
7074          return;
7075       }
7076
7077       for (nxt = cur->nxt; nxt; cur = nxt, nxt = nxt->nxt)
7078       {
7079          if (nxt->num < hole->num)
7080          {
7081             /* Insert hole:  cur <-> hole <-> nxt */
7082             cur->nxt = hole;
7083             hole->prv = cur;
7084             hole->nxt = nxt;
7085             nxt->prv = hole;
7086             return;
7087          }
7088       }
7089
7090       /* Add at end */
7091       cur->nxt = hole;
7092       hole->prv = cur;
7093       hole->nxt = NULLP;
7094       return;
7095    }
7096
7097    /* This is the first hole */
7098    db->first = hole;
7099    hole->prv = NULLP; /* may not be needed */
7100    hole->nxt = NULLP;
7101    return;
7102 }
7103
7104
7105 /***********************************************************
7106  *
7107  *     Func : rgSCHUtlUlHoleIncr
7108  *
7109  *     Desc : hole->num has increeased, reposition in sorted
7110  *            list if needed
7111  *
7112  *     Ret  : Void
7113  *
7114  *     Notes:
7115  *
7116  *     File :
7117  *
7118  **********************************************************/
7119 Void rgSCHUtlUlHoleIncr(RgSchUlHoleDb *db,RgSchUlHole   *hole)
7120 {
7121    RgSchUlHole *cur;
7122
7123    if ((cur = hole->prv) != NULLP)
7124    {
7125       RgSchUlHole *prv;
7126
7127       if (cur->num > hole->num)
7128       {
7129          return;
7130       }
7131
7132       /* Remove hole from current position */
7133       cur->nxt = hole->nxt;
7134       if (hole->nxt)
7135       {
7136          hole->nxt->prv = cur;
7137       }
7138
7139       for (prv = cur->prv; prv; cur = prv, prv = prv->prv)
7140       {
7141          if (prv->num > hole->num)
7142          {
7143             /* Insert hole:  prv <-> hole <-> cur */
7144             prv->nxt = hole;
7145             hole->prv = prv;
7146             hole->nxt = cur;
7147             cur->prv = hole;
7148             return;
7149          }
7150       }
7151
7152       /* Add at front */
7153       hole->nxt = cur;
7154       cur->prv = hole;
7155       db->first = hole;
7156       hole->prv = NULLP;
7157       return;
7158    }
7159    return;
7160 }
7161
7162 /***********************************************************
7163  *
7164  *     Func : rgSCHUtlUlHoleDecr
7165  *
7166  *     Desc : hole->num has decreeased, reposition in sorted
7167  *            list if needed
7168  *
7169  *     Ret  : Void
7170  *
7171  *     Notes:
7172  *
7173  *     File :
7174  *
7175  **********************************************************/
7176 Void rgSCHUtlUlHoleDecr(RgSchUlHoleDb *db,RgSchUlHole   *hole)
7177 {
7178    RgSchUlHole *cur;
7179
7180    if ((cur = hole->nxt) != NULLP)
7181    {
7182       RgSchUlHole *nxt;
7183
7184       if (cur->num < hole->num)
7185       {
7186          return;
7187       }
7188
7189       /* Remove hole from current position */
7190       cur->prv = hole->prv;
7191       if (hole->prv)
7192       {
7193          hole->prv->nxt = cur;
7194       }
7195       else /* no prv, so cur to replace hole as first in list */
7196       {
7197          db->first = cur;
7198       }
7199
7200       for (nxt = cur->nxt; nxt; cur = nxt, nxt = nxt->nxt)
7201       {
7202          if (nxt->num < hole->num)
7203          {
7204             /* Insert hole:  cur <-> hole <-> nxt */
7205             cur->nxt = hole;
7206             hole->prv = cur;
7207             hole->nxt = nxt;
7208             nxt->prv = hole;
7209             return;
7210          }
7211       }
7212
7213       /* Add at end */
7214       cur->nxt = hole;
7215       hole->prv = cur;
7216       hole->nxt = NULLP;
7217       return;
7218    }
7219    return;
7220 }
7221
7222 /***********************************************************
7223  *
7224  *     Func : rgSCHUtlUlHoleRls
7225  *
7226  *     Desc : Releases hole.
7227  *            1. Decrements hole count.
7228  *            2. Deletes hole from list.
7229  *            3. Frees hole (hole memory release).
7230  *
7231  *     Ret  : Void
7232  *
7233  *     Notes:
7234  *
7235  *     File :
7236  *
7237  **********************************************************/
7238 Void rgSCHUtlUlHoleRls(RgSchUlHoleDb *db,RgSchUlHole   *hole)
7239 {
7240    RgSchUlHole *prv = hole->prv;
7241    RgSchUlHole *nxt = hole->nxt;
7242
7243    --db->count;
7244    if (prv)
7245    {
7246       prv->nxt = nxt;
7247       if (nxt)
7248       {
7249          nxt->prv = prv;
7250       }
7251    }
7252    else
7253    {
7254       db->first = nxt;
7255       if (nxt)
7256       {
7257          nxt->prv = NULLP;
7258       }
7259    }
7260
7261    rgSCHUtlUlHoleMemRls(&db->mem, hole);
7262    return;
7263 }
7264
7265
7266 /***********************************************************
7267  *
7268  *     Func : rgSCHUtlUlAllocMemInit
7269  *
7270  *     Desc : Initialises alloc free pool
7271  *
7272  *     Ret  : S16 (ROK/RFAILED)
7273  *
7274  *     Notes:
7275  *
7276  *     File :
7277  *
7278  **********************************************************/
7279 S16 rgSCHUtlUlAllocMemInit(RgSchCellCb *cell,RgSchUlAllocMem *mem,uint8_t maxAllocs)
7280 {
7281    S16 ret;
7282    RgSchUlAlloc *allocs;
7283
7284    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&allocs,
7285                            maxAllocs * sizeof(*allocs));
7286    if (ret != ROK)
7287    {
7288       return (ret);
7289    }
7290    mem->allocs = allocs;
7291    mem->maxAllocs = maxAllocs;
7292    if (mem->maxAllocs == 1)
7293    {
7294       allocs[0].prv = NULLP;
7295       allocs[0].nxt = NULLP;
7296    }
7297    else
7298    {
7299       uint8_t i;
7300       allocs[0].prv = NULLP;
7301       allocs[0].nxt = &allocs[1];
7302       for (i = 1; i < mem->maxAllocs - 1; ++i)
7303       {
7304          allocs[i].prv = &allocs[i-1];
7305          allocs[i].nxt = &allocs[i+1];
7306       }
7307       allocs[i].prv = &allocs[i-1];
7308       allocs[i].nxt = NULLP;
7309    }
7310    mem->firstFree = &allocs[0];
7311    return ROK;
7312 }
7313
7314 /***********************************************************
7315  *
7316  *     Func : rgSCHUtlUlAllocMemDeinit
7317  *
7318  *     Desc : Deinitialises alloc free pool
7319  *
7320  *     Ret  : Void
7321  *
7322  *     Notes:
7323  *
7324  *     File :
7325  *
7326  **********************************************************/
7327 Void rgSCHUtlUlAllocMemDeinit(RgSchCellCb     *cell,RgSchUlAllocMem *mem)
7328 {
7329    /* ccpu00117052 - MOD - Passing double pointer
7330    for proper NULLP assignment*/
7331    rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(mem->allocs)),
7332                     mem->maxAllocs * sizeof(*mem->allocs));
7333    mem->maxAllocs = 0;
7334    mem->firstFree = NULLP;
7335    return;
7336 }
7337
7338 /***********************************************************
7339  *
7340  *     Func : rgSCHUtlUlHoleMemInit
7341  *
7342  *     Desc : Initialises hole free pool. Assumes maxHoles
7343  *            to be at least 2.
7344  *
7345  *     Ret  : S16 (ROK/RFAILED)
7346  *
7347  *     Notes:
7348  *
7349  *     File :
7350  *
7351  **********************************************************/
7352 S16 rgSCHUtlUlHoleMemInit(RgSchCellCb  *cell,RgSchUlHoleMem *mem,uint8_t  maxHoles,RgSchUlHole **holeRef)
7353 {
7354    S16 ret;
7355    RgSchUlHole *holes;
7356
7357    ret = rgSCHUtlAllocSBuf(cell->instIdx, (Data **)&holes,
7358                            maxHoles * sizeof(*holes));
7359    if (ret != ROK)
7360    {
7361       return (ret);
7362    }
7363
7364    mem->holes = holes;
7365    mem->maxHoles = maxHoles;
7366
7367    /* first hole is taken up */
7368    holes[0].prv = NULLP; /* not needed */
7369    holes[0].nxt = NULLP; /* not needed */
7370    *holeRef = &holes[0];
7371
7372    if (mem->maxHoles == 2)
7373    {
7374       holes[1].prv = NULLP; /* may not be needed */
7375       holes[1].nxt = NULLP; /* may not be needed */
7376    }
7377    else
7378    {
7379       uint8_t i;
7380       holes[1].prv = NULLP;
7381       holes[0].nxt = &holes[1];
7382       for (i = 1; i < mem->maxHoles - 1; ++i)
7383       {
7384          holes[i].prv = &holes[i-1];
7385          holes[i].nxt = &holes[i+1];
7386       }
7387       holes[i].prv = &holes[i-1];
7388       holes[i].nxt = NULLP;
7389    }
7390    mem->firstFree = &holes[1];
7391
7392    return ROK;
7393 }
7394
7395 /***********************************************************
7396  *
7397  *     Func : rgSCHUtlUlHoleMemDeinit
7398  *
7399  *     Desc : Deinitialises hole free pool
7400  *
7401  *     Ret  : Void
7402  *
7403  *     Notes:
7404  *
7405  *     File :
7406  *
7407  **********************************************************/
7408 Void rgSCHUtlUlHoleMemDeinit(RgSchCellCb  *cell,RgSchUlHoleMem *mem)
7409 {
7410    /* ccpu00117052 - MOD - Passing double pointer
7411    for proper NULLP assignment*/
7412    rgSCHUtlFreeSBuf(cell->instIdx, (Data **)(&(mem->holes)),
7413                     mem->maxHoles * sizeof(*mem->holes));
7414    mem->maxHoles = 0;
7415    mem->firstFree = NULLP;
7416    return;
7417 }
7418
7419 /***********************************************************
7420  *
7421  *     Func : rgSCHUtlUlAllocMemGet
7422  *
7423  *     Desc : Gets an 'alloc' from the free pool
7424  *
7425  *     Ret  : RgSchUlAlloc *
7426  *
7427  *     Notes:
7428  *
7429  *     File :
7430  *
7431  **********************************************************/
7432 RgSchUlAlloc *rgSCHUtlUlAllocMemGet(RgSchUlAllocMem *mem)
7433 {
7434    RgSchUlAlloc *alloc;
7435
7436 #if (ERRCLASS & ERRCLS_DEBUG)
7437    if (mem->firstFree == NULLP)
7438    {
7439       return (NULLP);
7440    }
7441 #endif
7442
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 */
7447
7448    return (alloc);
7449 }
7450
7451 /***********************************************************
7452  *
7453  *     Func : rgSCHUtlUlAllocMemRls
7454  *
7455  *     Desc : Returns an 'alloc' to the free pool
7456  *
7457  *     Ret  :
7458  *
7459  *     Notes:
7460  *
7461  *     File :
7462  *
7463  **********************************************************/
7464 Void rgSCHUtlUlAllocMemRls(RgSchUlAllocMem *mem,RgSchUlAlloc  *alloc)
7465 {
7466    alloc->prv = NULLP;
7467
7468    alloc->nxt = mem->firstFree;
7469    if (mem->firstFree != NULLP)
7470    {
7471       mem->firstFree->prv = alloc;
7472    }
7473    mem->firstFree = alloc;
7474    return;
7475 }
7476
7477 /***********************************************************
7478  *
7479  *     Func : rgSCHUtlUlHoleMemGet
7480  *
7481  *     Desc : Gets a 'hole' from the free pool
7482  *
7483  *     Ret  : RgSchUlHole *
7484  *
7485  *     Notes:
7486  *
7487  *     File :
7488  *
7489  **********************************************************/
7490 RgSchUlHole *rgSCHUtlUlHoleMemGet(RgSchUlHoleMem *mem)
7491 {
7492    RgSchUlHole *hole;
7493
7494 #if (ERRCLASS & ERRCLS_DEBUG)
7495    if (mem->firstFree == NULLP)
7496    {
7497       return (NULLP);
7498    }
7499 #endif
7500
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 */
7506
7507    return (hole);
7508 }
7509
7510 /***********************************************************
7511  *
7512  *     Func : rgSCHUtlUlHoleMemRls
7513  *
7514  *     Desc : Returns a 'hole' to the free pool
7515  *
7516  *     Ret  : Void
7517  *
7518  *     Notes:
7519  *
7520  *     File :
7521  *
7522  **********************************************************/
7523 Void rgSCHUtlUlHoleMemRls(RgSchUlHoleMem *mem,RgSchUlHole    *hole)
7524 {
7525    hole->prv = NULLP;
7526
7527    hole->nxt = mem->firstFree;
7528    if (mem->firstFree != NULLP)
7529    {
7530       mem->firstFree->prv = hole;
7531    }
7532    mem->firstFree = hole;
7533    return;
7534 }
7535
7536 /**
7537  * @brief Get an alloc from the specified position in the BW.
7538  *
7539  * @details
7540  *
7541  *     Function : rgSCHUtlUlGetSpfcAlloc
7542  *
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.
7549  *
7550  *  @param[in]  RgSchUlSf     *sf
7551  *  @param[in]  uint8_t            startSb
7552  *  @param[in]  uint8_t            numSb
7553  *  @return  RgSchUlAlloc*
7554  **/
7555 RgSchUlAlloc *rgSCHUtlUlGetSpfcAlloc(RgSchUlSf *sf,uint8_t startSb,uint8_t  numSb)
7556 {
7557    RgSchUlHole     *hole, *nxtHole;
7558    RgSchUlAlloc    *alloc = NULLP;
7559
7560    if ((hole = rgSCHUtlUlHoleFirst(sf)) == NULLP)
7561    {
7562       return (NULLP);
7563    }
7564    do
7565    {
7566       nxtHole = rgSCHUtlUlHoleNxt(sf, hole);
7567       if ((startSb >= hole->start) &&
7568           (startSb+numSb <= hole->start+hole->num))
7569       {
7570          if (startSb != hole->start)
7571          {
7572             /* Create a new hole to accomodate Subbands between
7573              * hole start and req alloc start */
7574             RgSchUlHole *newHole = rgSCHUtlUlHoleMemGet(&(sf->holeDb->mem));
7575
7576 #if (ERRCLASS & ERRCLS_DEBUG)
7577             if ( newHole == NULLP )
7578             {
7579                 return ( NULLP );
7580             }
7581 #endif
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)
7591             {
7592                newHole->prvAlloc->nxtHole = newHole;
7593             }
7594             if (numSb == hole->num)
7595             {
7596                alloc = rgSCHUtlUlAllocGetCompHole(sf, hole);
7597             }
7598             else
7599             {
7600                alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole);
7601             }
7602             alloc->prvHole = newHole;
7603             newHole->nxtAlloc = alloc;
7604          }
7605          else /* Hole start and req alloc start are same */
7606          {
7607             if (numSb == hole->num)
7608             {
7609                alloc = rgSCHUtlUlAllocGetCompHole(sf, hole);
7610             }
7611             else
7612             {
7613                alloc = rgSCHUtlUlAllocGetPartHole(sf, numSb, hole);
7614             }
7615          }
7616          break;
7617       }
7618    } while ((hole = nxtHole) != NULLP);
7619    return (alloc);
7620 }
7621 #ifdef LTE_L2_MEAS
7622 /**
7623  * @brief  Validates the qci values
7624  *
7625  * @details
7626  *
7627  *     Function :rgSCHUtlValidateQci
7628  *
7629  *  @param[in]  RgSchCellCb     *cellCb
7630  *  @param[in]  uint8_t              numQci
7631  *  @param[out] uint8_t              *qci
7632  *  @return  S16
7633  *           ROK
7634  *           RFAILED
7635  **/
7636 static S16 rgSCHUtlValidateQci(RgSchCellCb  *cellCb,uint8_t numQci,uint8_t *qci)
7637 {
7638    uint8_t        qciIdx;
7639    uint8_t        qciVal;
7640
7641    for(qciIdx = 0; qciIdx < numQci; qciIdx++)
7642    {
7643       qciVal = qci[qciIdx];
7644       if(qciVal == 0 || qciVal > 9)
7645       {
7646          return RFAILED;
7647       }
7648       if(qciVal != cellCb->qciArray[qciVal].qci)
7649       {
7650          return RFAILED;
7651       }
7652    }
7653
7654    return ROK;
7655 }/* rgSCHUtlValidateQci */
7656 /**
7657  * @brief  Validates the measurement request parameters.
7658  *
7659  * @details
7660  *
7661  *     Function :rgSCHUtlValidateMeasReq
7662  *
7663  *  @param[in]  RgSchCellCb        *cellCb
7664  *  @param[in]  LrgSchMeasReqInfo  *schL2MeasInfo
7665  *  @param[out] RgSchErrInfo       *err
7666  *  @return  RgSchUlAlloc*
7667  **/
7668 S16 rgSCHUtlValidateMeasReq(RgSchCellCb *cellCb, LrgSchMeasReqInfo *schL2MeasInfo,RgSchErrInfo *err)
7669 {
7670    uint16_t    measType;
7671    S16   ret;
7672
7673    measType = schL2MeasInfo->measType;
7674    if((measType == 0) ||
7675        measType > 2047)
7676    {
7677       err->errType = RGSCHERR_SCH_INVALID_MEAS_TYPE;
7678       err->errCause = RGSCHERR_SCH_L2MEAS;
7679       return RFAILED;
7680    }
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)))
7685    {
7686       err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7687       err->errCause = RGSCHERR_SCH_L2MEAS;
7688       return RFAILED;
7689    }
7690    if((schL2MeasInfo->timePrd !=0) &&
7691      (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_UL) &&
7692       (schL2MeasInfo->avgPrbQciUl.numQci > LRG_MAX_QCI_PER_REQ)) 
7693    {
7694       err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7695       err->errCause = RGSCHERR_SCH_L2MEAS;
7696       return RFAILED;
7697    }
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)))
7704    {
7705       err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7706       err->errCause = RGSCHERR_SCH_L2MEAS;
7707       return RFAILED;
7708    }
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)))
7715    {
7716       err->errType = RGSCHERR_SCH_INVALID_PARAM_RANGE;
7717       err->errCause = RGSCHERR_SCH_L2MEAS;
7718       return RFAILED;
7719    }
7720    if((schL2MeasInfo->timePrd !=0) &&
7721        (measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL))
7722    {
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);
7727       if(ret != ROK)
7728       {
7729           err->errType = RGSCHERR_SCH_INVALID_QCI_VAL;
7730           err->errCause = RGSCHERR_SCH_L2MEAS;
7731           return RFAILED;
7732       }
7733    }
7734    return ROK;
7735 }/* rgSCHUtlValidateMeasReq */
7736 #endif /* LTE_L2_MEAS */
7737 /******* </AllocHolesMemMgmnt>: END *****/
7738 #ifdef RGR_SI_SCH
7739 /**
7740  * @brief API for sending SI configuration confirm from Scheduler to RRM
7741  *
7742  * @details
7743  *
7744  *     Function: rgSCHUtlRgrSiCfgCfm
7745  *
7746  *     This API is invoked to send SI configuration confirm from Scheduler
7747  *     to RRM.
7748  *     This API fills in Pst structure and SAP Ids and invokes
7749  *     config confirm API towards RRM.
7750  *
7751  *  @param[in]  RgrCfgTransId transId
7752  *  @param[in]  uint8_t            status
7753  *  @return  S16
7754  *      -# ROK
7755  *      -# RFAILED
7756  **/
7757 S16 rgSCHUtlRgrSiCfgCfm(Inst instId,SpId  spId,RgrCfgTransId transId,uint8_t status)
7758 {
7759    uint8_t        prntTrans[RGR_CFG_TRANSID_SIZE+1];
7760
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)
7766    {
7767       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrSiCfgCfm: "
7768                 "RgUiRgrSiCfgCfm Failed ");
7769       return RFAILED;
7770    }
7771
7772    return ROK;
7773 }  /* rgSCHUtlRgrSiCfgCfm */
7774
7775 \f
7776 /**
7777  * @brief API for sending Warning SI configuration confirm from 
7778  * Scheduler to RRM
7779  *
7780  * @details
7781  *
7782  *
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.
7787  *
7788  *  @param[in]  RgrCfgTransId transId
7789  *  @param[in]  uint8_t            status
7790  *  @return  S16
7791  *      -# ROK
7792  *      -# RFAILED
7793  **/
7794 S16 rgSCHUtlRgrWarningSiCfgCfm(Inst instId,SpId spId,uint8_t siId,RgrCfgTransId transId,uint8_t  status)
7795 {
7796    uint8_t        prntTrans[RGR_CFG_TRANSID_SIZE+1];
7797
7798    memcpy(prntTrans, transId.trans, RGR_CFG_TRANSID_SIZE);
7799    prntTrans[RGR_CFG_TRANSID_SIZE] = '\0';
7800    
7801    if(RgUiRgrWarningSiCfgCfm(&rgSchCb[instId].rgrSap[spId].sapCfg.sapPst,
7802                     rgSchCb[instId].rgrSap[spId].sapCfg.suId, 
7803                     transId, siId, status) != ROK)
7804    {
7805       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrSiCfgCfm: "
7806                 "RgUiRgrSiCfgCfm Failed ");
7807       return RFAILED;
7808    }
7809
7810    return ROK;
7811 }  /* rgSCHUtlRgrWarningSiCfgCfm */
7812
7813 /***********************************************************
7814  *
7815  *     Func : rgSCHUtlPutSiInfo
7816  *
7817  *     Desc : Utility Function to deallocate SI information
7818  *
7819  *
7820  *            RFAILED
7821  *
7822  *
7823  *     File : rg_utl.c
7824  *
7825  **********************************************************/
7826 Void rgSCHUtlPutSiInfo(RgSchCellCb *cell)
7827 {
7828    uint8_t    idx = 0;
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)
7833    
7834    sizeOfSiInfo = sizeof(cell->siCb.crntSiInfo.siInfo)/sizeof(cell->siCb.crntSiInfo.siInfo[0]);
7835    
7836    for(idx=0; idx < sizeOfSiInfo; idx++)
7837    {
7838       RGSCH_FREE_MSG(cell->siCb.crntSiInfo.siInfo[idx].si)
7839    }
7840
7841    /*Free the buffers in newSiInfo */
7842    RGSCH_FREE_MSG(cell->siCb.newSiInfo.mib)
7843    RGSCH_FREE_MSG(cell->siCb.newSiInfo.sib1Info.sib1)
7844
7845    sizeOfSiInfo = sizeof(cell->siCb.newSiInfo.siInfo)/sizeof(cell->siCb.newSiInfo.siInfo[0]);
7846
7847    for(idx=0; idx < sizeOfSiInfo; idx++)
7848    {
7849       RGSCH_FREE_MSG(cell->siCb.newSiInfo.siInfo[idx].si)
7850    }
7851
7852    return;
7853 }
7854 #endif /*RGR_SI_SCH */
7855
7856
7857
7858 /***********************************************************
7859  *
7860  *     Func : rgSCHUtlGetDrxSchdUesInDl
7861  *
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.
7865  *
7866  *     Ret  : ROK
7867  *            RFAILED
7868  *
7869  *     Notes:
7870  *
7871  *     File : rg_utl.c
7872  *
7873  **********************************************************/
7874 S16 rgSCHUtlGetDrxSchdUesInDl
7875 (
7876 RgSchCellCb     *cellCb,
7877 RgSchUeCb       *ueCb,
7878 RgSchDlHqProcCb *dlHq,
7879 RgInfUeAlloc    *allocInfo,
7880 CmLListCp       *dlDrxInactvTmrLst,
7881 CmLListCp       *dlInActvLst,
7882 CmLListCp       *ulInActvLst
7883 )
7884 {
7885    Bool                  isNewTx = FALSE;
7886    uint8_t                    idx;
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;
7893
7894    for(idx = 0; idx < allocInfo->nmbOfTBs; idx++)
7895    {
7896       if(allocInfo->tbInfo[idx].isReTx == FALSE)
7897       {
7898          isNewTx = TRUE;
7899          /* Removing break here, since in 2 TB case if 2nd TB is proceeding with 
7900             retx then drxretx timer should be stopped.*/
7901       }
7902       else
7903       {
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)
7912          {  
7913             /* This condition should never occur */      
7914             if(drxHq->reTxIndx >= RG_SCH_MAX_DRXQ_SIZE)
7915             {
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);
7919             }
7920
7921             drxUe->drxDlInactvMaskPerCell[cellIdx]  |= (RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId);
7922             drxUe->drxUlInactvMaskPerCell[cellIdx]  |= (RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId);
7923
7924             dlInactvMask = RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId;
7925             ulInactvMask = RG_SCH_DRX_DLHQ_BITMASK << dlHq->procId;
7926
7927             for(cellIdx = 0; cellIdx < CM_LTE_MAX_CELLS; cellIdx++)
7928             {
7929                dlInactvMask &= drxUe->drxDlInactvMaskPerCell[cellIdx];
7930                ulInactvMask &= drxUe->drxUlInactvMaskPerCell[cellIdx];
7931             }
7932
7933             drxUe->drxDlInactvMask |= dlInactvMask;
7934             drxUe->drxUlInactvMask |= ulInactvMask;
7935
7936             /* if no other condition is keeping ue active,
7937              * inactivate the Ue
7938              */
7939             if(!RG_SCH_DRX_DL_IS_UE_ACTIVE(drxUe))
7940             {
7941                /* BUG 2 : HARQ_RTT, changed for consistency */
7942                ueCb->dl.dlInactvMask |= (RG_DRX_INACTIVE);
7943
7944                /* Add to DL inactive list */
7945                cmLListAdd2Tail(dlInActvLst,&(ueCb->dlDrxInactvLnk));
7946                ueCb->dlDrxInactvLnk.node = (PTR)ueCb;
7947             }
7948
7949             if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
7950             {
7951                /*BUG 2: HARQ_RTT changed for consistency */
7952                ueCb->ul.ulInactvMask |= (RG_DRX_INACTIVE);
7953
7954                cmLListAdd2Tail(ulInActvLst,&(ueCb->ulDrxInactvLnk));
7955                ueCb->ulDrxInactvLnk.node  = (PTR)ueCb;
7956             }
7957
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)
7962             {
7963                cmLListDelFrm (&(cellCb->drxCb->drxQ[drxHq->rttIndx].harqRTTQ),
7964                      &(drxHq->harqRTTEnt));
7965
7966                drxHq->rttIndx = DRX_INVALID;
7967             }   
7968
7969             cmLListDelFrm (&(drxCell->drxQ[drxHq->reTxIndx].harqRetxQ),
7970                   &(drxHq->harqRetxEnt));
7971             drxHq->reTxIndx = DRX_INVALID;
7972          }
7973       }
7974    }
7975
7976    if(isNewTx == TRUE)
7977    {
7978       if(ueCb->drxCb->raRcvd == TRUE)
7979       {
7980          ueCb->drxCb->raRcvd = FALSE;
7981
7982          /* mark the ra bit */
7983          ueCb->drxCb->drxUlInactvMask |= RG_SCH_DRX_RA_BITMASK;
7984          ueCb->drxCb->drxDlInactvMask |= RG_SCH_DRX_RA_BITMASK;
7985
7986       }/*if(ra->rcvd) == TRUE */
7987
7988       if(ueCb->dlDrxInactvTmrLnk.node == NULLP)
7989       {   
7990          cmLListAdd2Tail(dlDrxInactvTmrLst,&(ueCb->dlDrxInactvTmrLnk));
7991          ueCb->dlDrxInactvTmrLnk.node = (PTR)ueCb;
7992       }
7993    }/*if(isNewTx == TRUE) */
7994
7995    return ROK;
7996 }/* rgSCHUtlGetSchdUes*/
7997 \f
7998 /* ccpu00117452 - MOD - Changed macro name from
7999    RGR_RRM_DLPWR_CNTRL to RGR_CQI_REPT */
8000 #ifdef RGR_CQI_REPT
8001 /**
8002  * @brief This function fills StaInd struct
8003  *
8004  * @details
8005  *
8006  *     Function: rgSCHUtlFillSndStaInd
8007  *     Purpose:  Fills StaInd struct and sends the
8008  *               StaInd to RRM
8009  *
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
8014  *  @return  Void
8015  *
8016  **/
8017 S16 rgSCHUtlFillSndStaInd(RgSchCellCb *cell,RgSchUeCb *ue,RgrStaIndInfo *staInfo,uint8_t numCqiRept)
8018 {
8019    uint8_t idxStart;
8020
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 */
8025
8026    /* Fill the Cell Id of PCC of the UE */
8027    staInfo->cellId = ue->cell->cellId;
8028    staInfo->crnti = ue->ueId;
8029
8030    idxStart = ue->schCqiInfo.cqiCount - numCqiRept;
8031
8032    memcpy (&(staInfo->ueCqiInfo.cqiRept),
8033             &(ue->schCqiInfo.cqiRept[idxStart]),
8034             numCqiRept * sizeof(RgrUeCqiRept));
8035
8036    staInfo->ueCqiInfo.numCqiRept = numCqiRept;
8037
8038    ue->schCqiInfo.cqiCount = 0;
8039
8040    /* Call utility function (rgSCHUtlRgrStaInd) to send rpts to RRM */
8041    if(rgSCHUtlRgrStaInd(cell, staInfo) != ROK)
8042    {
8043       DU_LOG("\nERROR  -->  SCH : Could not send "
8044          "CQI reports for RNTI:%d",ue->ueId);
8045       return RFAILED;
8046    }
8047
8048    return ROK;
8049
8050 }/* End of rgSCHUtlFillSndStaInd */
8051
8052
8053 \f
8054 /**
8055  * @brief API for sending STA indication from Scheduler to RRM.
8056  *
8057  * @details
8058  *
8059  *     Function: rgSCHUtlRgrStaInd
8060  *
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.
8064  *
8065  *  @param[in]  cell                   RgSchCellCb
8066  *  @param[in]  RgrStsIndInfo          *rgrSta
8067  *  @return  S16
8068  *      -# ROK
8069  *      -# RFAILED
8070  **/
8071 S16 rgSCHUtlRgrStaInd(RgSchCellCb *cell,RgrStaIndInfo *rgrSta)
8072 {
8073    S16           ret = ROK;
8074    RgSchUpSapCb  *rgrSap;                    /*!< RGR SAP Control Block */
8075    
8076    rgrSap = cell->rgrSap;
8077    if (rgrSap->sapSta.sapState != LRG_BND)
8078    {
8079       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrStaInd() Upper SAP not bound (%d) ",
8080                rgrSap->sapSta.sapState);
8081       return RFAILED;
8082    }
8083    RgUiRgrStaInd(&(cell->rgrSap->sapCfg.sapPst),
8084          cell->rgrSap->sapCfg.suId, rgrSta);
8085    return (ret);
8086 }  /* rgSCHUtlRgrStaInd*/
8087 #endif /* End of RGR_CQI_REPT */
8088
8089 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
8090 /**
8091  * @brief Indicates MAC to release any rnti context it has.
8092  *
8093  * @details
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.
8099  *     
8100  *    
8101  *           
8102  *  @param[in]     RgSchCellCb    *cell
8103  *  @param[in]     CmLteRnti      rnti 
8104  *  @param[in]     Bool           ueIdChng
8105  *  @param[in]     CmLteRnti      newRnti
8106  *  @return  Void
8107  *      -# ROK 
8108  **/
8109 Void rgSCHUtlIndRntiRls2Mac(RgSchCellCb *cell,CmLteRnti  rnti,Bool ueIdChng,CmLteRnti newRnti)
8110 {
8111    Pst          pst;
8112    Inst         inst = cell->instIdx;
8113    RgInfRlsRnti rntiInfo;
8114
8115
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 
8121     * is dummy */          
8122    rntiInfo.ueIdChng = ueIdChng;
8123    rntiInfo.newRnti  = newRnti;
8124 #ifdef LTE_ADV
8125    rntiInfo.isUeSCellDel = FALSE;
8126 #endif
8127    /* Invoke MAC to release the rnti */
8128    rgSCHUtlGetPstToLyr(&pst, &rgSchCb[inst], cell->macInst);
8129    RgSchMacRlsRnti(&pst, &rntiInfo);
8130    return;
8131 }
8132
8133 /* LTE_ADV_FLAG_REMOVED_START */
8134 /**
8135  * @brief API for sending LOAD INF indication from Scheduler to RRM.
8136  * @details
8137  *
8138  *     Function: rgSCHUtlRgrLoadInfInd
8139  *
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.
8143  *
8144  *  @param[in]  cell                    RgSchCellCb
8145  *  @param[in]  RgrLoadInfIndInfo       *rgrLoadInf
8146  *  @return  S16
8147  *      -# ROK
8148  *      -# RFAILED
8149  **/
8150 S16 rgSCHUtlRgrLoadInfInd(RgSchCellCb *cell,RgrLoadInfIndInfo *rgrLoadInf)
8151 {
8152    S16           ret = ROK;
8153    RgSchUpSapCb  *rgrSap;                    /*!< RGR SAP Control Block */
8154
8155    rgrSap = cell->rgrSap;
8156    if (rgrSap->sapSta.sapState != LRG_BND)
8157    {
8158       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrLoadInfInd() Upper SAP not bound (%d) ",
8159                rgrSap->sapSta.sapState);
8160       return RFAILED;
8161    }
8162    RgUiRgrLoadInfInd(&(cell->rgrSap->sapCfg.sapPst),
8163          cell->rgrSap->sapCfg.suId, rgrLoadInf);
8164    return (ret);
8165 }  /* rgSCHUtlRgrLoadInfInd*/
8166 /* LTE_ADV_FLAG_REMOVED_END */
8167
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
8173 /**
8174  * @brief API for sending STA indication from Scheduler to RRM.
8175  *
8176  * @details
8177  *
8178  *     Function: rgSCHUtlRlsRnti
8179  *
8180  *     This API is invoked to indicate MAC to release rnti
8181  *
8182  *  @param[in]  RgSchCellCb    *cellCb                   
8183  *  @param[in]  RgSchRntiLnk   *rntiLnk,
8184  *  @param[in]  Bool           ueIdChngd,
8185  *  @param[in]  CmLteRnti      newRnti
8186  *  @return  Void
8187  **/
8188
8189 Void rgSCHUtlRlsRnti(RgSchCellCb *cell,RgSchRntiLnk  *rntiLnk,Bool ueIdChngd,CmLteRnti newRnti)
8190 {
8191
8192    uint8_t isLegacy = 0;
8193 #ifdef EMTC_ENABLE
8194    if(cell->emtcEnable)
8195    {
8196       rgSCHEmtcUtlRlsRnti(cell, rntiLnk, &isLegacy);
8197    }
8198 #endif
8199    if(!isLegacy)
8200    {
8201       /*Add to Guard Pool*/
8202       cmLListAdd2Tail(&cell->rntiDb.rntiGuardPool, &rntiLnk->rntiGrdPoolLnk);
8203       rntiLnk->rntiGrdPoolLnk.node = (PTR)rntiLnk;
8204    }
8205    /* Fix: syed Explicitly Inidcate MAC to release RNTI */
8206    rgSCHUtlIndRntiRls2Mac(cell, rntiLnk->rnti, ueIdChngd, newRnti);
8207
8208    return;
8209 }
8210
8211
8212 /**
8213  * @brief This function fills StaInd struct
8214  *
8215  * @details
8216  *
8217  *     Function: rgSCHUtlFillSndUeStaInd
8218  *     Purpose:  Fills StaInd struct and sends the
8219  *               StaInd to RRM
8220  *
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
8224  *  @return  Void
8225  *
8226  **/
8227 S16 rgSCHUtlFillSndUeStaInd(RgSchCellCb *cell,RgSchUeCb  *ue,RgrUeStaIndInfo  *ueStaInfo)
8228 {
8229
8230    ueStaInfo->cellId = cell->cellId;
8231    ueStaInfo->crnti = ue->ueId;
8232
8233    /* Call utility function (rgSCHUtlRgrUeStaInd) to send rpts to RRM */
8234    if(rgSCHUtlRgrUeStaInd(cell, ueStaInfo) != ROK)
8235    {
8236       DU_LOG("\nERROR  -->  SCH : Could not send "
8237          "UE Sta reports CRNTI:%d",ue->ueId);
8238       return RFAILED;
8239    }
8240
8241    return ROK;
8242
8243 }/* End of rgSCHUtlFillSndStaInd */
8244
8245
8246 \f
8247 /**
8248  * @brief API for sending STA indication from Scheduler to RRM.
8249  *
8250  * @details
8251  *
8252  *     Function: rgSCHUtlRgrStaInd
8253  *
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.
8257  *
8258  *  @param[in]  cell                   RgSchCellCb
8259  *  @param[in]  RgrStsIndInfo          *rgrSta
8260  *  @return  S16
8261  *      -# ROK
8262  *      -# RFAILED
8263  **/
8264 S16 rgSCHUtlRgrUeStaInd(RgSchCellCb *cell,RgrUeStaIndInfo *rgrUeSta)
8265 {
8266    S16           ret = ROK;
8267    RgSchUpSapCb  *rgrSap;                    /*!< RGR SAP Control Block */
8268
8269    rgrSap = cell->rgrSap;
8270    if (rgrSap->sapSta.sapState != LRG_BND)
8271    {
8272       DU_LOG("\nERROR  -->  SCH : rgSCHUtlRgrUeStaInd() Upper SAP not bound (%d) ",
8273                rgrSap->sapSta.sapState);
8274       return RFAILED;
8275    }
8276    RgUiRgrUeStaInd(&(cell->rgrSap->sapCfg.sapPst),
8277          cell->rgrSap->sapCfg.suId, rgrUeSta);
8278    return (ret);
8279 }  /* rgSCHUtlRgrStaInd*/
8280
8281 /* RRM_RBC_X */
8282 /**
8283  * @brief function to report DL and UL PRB usage to RRM.
8284  *
8285  *
8286  *     Function: rgSCHUtlUpdAvgPrbUsage
8287  *               This function sends the PRB usage report to 
8288  *               RRM with the interval configured by RRM.
8289  *
8290  *  @param[in]  cell       *RgSchCellCb
8291  *  @return  S16
8292  *      -# ROK
8293  *      -# RFAILED
8294  **/
8295 S16 rgSCHUtlUpdAvgPrbUsage(RgSchCellCb  *cell)
8296 {
8297    CmLteTimingInfo  frm;
8298    RgmPrbRprtInd    *prbRprtInd;
8299    S16              ret = ROK;
8300    uint32_t              idx;
8301 #ifdef DBG_MAC_RRM_PRB_PRINT
8302    static uint32_t       count = 0;
8303    const uint32_t reprotForEvery20Sec = 20000/cell->prbUsage.rprtPeriod;
8304
8305    count++;
8306 #endif
8307
8308    frm   = cell->crntTime;
8309    RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
8310
8311    uint16_t numDlSf;
8312    uint16_t numUlSf;
8313 #ifdef LTE_TDD
8314   
8315    if(cell->prbUsage.rprtPeriod >= RGSCH_NUM_SUB_FRAMES)
8316    {
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;
8324    }
8325    else
8326    {
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];
8330    }
8331 #else
8332      numDlSf = cell->prbUsage.rprtPeriod;
8333      numUlSf = cell->prbUsage.rprtPeriod;
8334 #endif
8335
8336    if(SGetSBuf(cell->rgmSap->sapCfg.sapPst.region, 
8337                cell->rgmSap->sapCfg.sapPst.pool, (Data**)&prbRprtInd, 
8338                sizeof(RgmPrbRprtInd)) != ROK)
8339    {
8340       return RFAILED;
8341    }
8342
8343    memset(&prbRprtInd->stQciPrbRpts[0],
8344             0,
8345             (RGM_MAX_QCI_REPORTS * sizeof(RgmPrbRptPerQci)));
8346
8347    prbRprtInd->bCellId            = cell->cellId;
8348
8349    if(numDlSf > 0)
8350    {
8351       prbRprtInd->bPrbUsageMask |= RGM_PRB_USAGE_DL; 
8352       for (idx = 0; idx < RGM_MAX_QCI_REPORTS; idx++ )
8353       {
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;
8359       }
8360    }
8361
8362    if(numUlSf > 0)
8363    {
8364       prbRprtInd->bPrbUsageMask |= RGM_PRB_USAGE_UL; 
8365       for (idx = 0; idx < RGM_MAX_QCI_REPORTS; idx++ )
8366       {
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;
8372       }
8373    }
8374
8375 #ifdef DBG_MAC_RRM_PRB_PRINT
8376    if((count % reprotForEvery20Sec) == 0 )
8377    {
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);
8390    }
8391 #endif
8392    RgUiRgmSendPrbRprtInd(&(cell->rgmSap->sapCfg.sapPst), 
8393                     cell->rgmSap->sapCfg.suId, prbRprtInd);
8394
8395
8396    return (ret);
8397 }
8398 /* RRM_RBC_Y */
8399
8400 /**
8401  * @brief This function resends the Ta in case of 
8402  *        max retx failure or DTX for the Ta transmitted 
8403  *
8404  * @details
8405  *
8406  *     Function: rgSCHUtlReTxTa
8407  *     Purpose:  
8408  *                
8409  *  @param[in]  RgSchCellCb           *cell
8410  *  @param[in]  RgSchUeCb             *ue
8411  *  @return  Void 
8412  *
8413  **/
8414 Void rgSCHUtlReTxTa(RgSchCellCb *cellCb,RgSchUeCb *ueCb)
8415 {
8416
8417    /* If TA Timer is running. Stop it */
8418    if (ueCb->taTmr.tmrEvnt != TMR_NONE)
8419    {
8420       rgSCHTmrStopTmr(cellCb, ueCb->taTmr.tmrEvnt, ueCb);
8421    }
8422    /*[ccpu00121813]-ADD-If maxretx is reached then 
8423     * use outstanding TA val for scheduling again */
8424    if(ueCb->dl.taCb.outStndngTa == TRUE)
8425    {
8426       ueCb->dl.taCb.ta = ueCb->dl.taCb.outStndngTaval;
8427       ueCb->dl.taCb.outStndngTaval = RGSCH_NO_TA_RQD;
8428       ueCb->dl.taCb.outStndngTa = FALSE;
8429
8430    }
8431    /* Fix : syed TA state updation missing */
8432    ueCb->dl.taCb.state = RGSCH_TA_TOBE_SCHEDULED;
8433    rgSCHUtlDlTARpt(cellCb, ueCb); 
8434
8435    return;
8436 }
8437
8438 /* Added function for dropping Paging Message*/
8439 /**
8440  * @brief Handler for BO Updt received for BCCH or PCCH.
8441  *
8442  * @details
8443  *
8444  *     Function : rgSCHChkBoUpdate
8445  *
8446  *     This function shall check for BO received falls within the scheduling window or not
8447  *
8448  *
8449  *  @param[in]  RgSchCellCb    *cell
8450  *  @return  S16
8451  *      -# ROK 
8452  *      -# RFAILED
8453  **/
8454 static S16 rgSCHChkBoUpdate(RgSchCellCb *cell,RgInfCmnBoRpt  *boUpdt)
8455 {
8456
8457    uint32_t crntTimeInSubFrms = 0;
8458    uint32_t boUpdTimeInSubFrms = 0;
8459    uint32_t distance = 0;
8460
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;
8465
8466
8467    distance = boUpdTimeInSubFrms > crntTimeInSubFrms ? \
8468               boUpdTimeInSubFrms - crntTimeInSubFrms : \
8469               (RGSCH_MAX_SUBFRM_5G - crntTimeInSubFrms + boUpdTimeInSubFrms);
8470
8471    if (distance > RGSCH_PCCHBCCH_WIN)
8472    {
8473            return RFAILED;
8474    }
8475    return ROK;
8476
8477 }/*rgSCHChkBoUpdate*/
8478
8479
8480 #ifdef LTE_TDD
8481 /**
8482  * @brief  Utility function to calculate the UL reTxIdx in TDD cfg0
8483  *
8484  * @details
8485  *
8486  *     Function : rgSchUtlCfg0ReTxIdx
8487  *
8488  *     Update the reTxIdx according to the rules mentioned
8489  *     in 3GPP TS 36.213 section 8 for TDD Cfg0
8490  *
8491  *  @param[in]  RgSchCellCb     *cell
8492  *  @param[in]  CmLteTimingInfo  phichTime 
8493  *  @param[in]  uint8_t               hqFdbkIdx
8494  *  @return     uint8_t
8495  **/
8496 uint8_t rgSchUtlCfg0ReTxIdx(RgSchCellCb    *cell,CmLteTimingInfo phichTime,uint8_t hqFdbkIdx)
8497 {
8498    uint8_t reTxIdx = RGSCH_INVALID_INFO;
8499    uint8_t iPhich = 0; 
8500    RgSchCmnUlCell  *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
8501    RgSchUlSf       *ulSf;   
8502    uint8_t               ulSF; /* UL SF in the TDD frame */
8503          
8504    ulSf = &cellUl->ulSfArr[hqFdbkIdx];
8505    ulSF = ulSf->ulSfIdx;
8506     
8507    /* Check for the UL SF 4 or 9 */
8508    if(ulSF == 9 || ulSF == 4)
8509    {
8510      iPhich = 1;  
8511    }
8512    if(phichTime.slot == 0 || phichTime.slot == 5)
8513    {    
8514       if(iPhich == 0)
8515       {
8516          /* Retx will happen according to the Pusch k table */
8517          reTxIdx = cellUl->schdIdx;
8518       }
8519       if(iPhich == 1)
8520       {
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);
8525       }   
8526    }
8527    else if(phichTime.slot == 1 || phichTime.slot == 6) 
8528    { 
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);
8533    }
8534    return (reTxIdx);
8535 }
8536 #endif
8537
8538 /**
8539  * @brief  Utility function to calculate total num of PRBs required to
8540  *         satisfy DL BO for TM1/TM2/TM6/TM7
8541  *
8542  * @details
8543  *
8544  *     Function : rgSchUtlDlCalc1CwPrb
8545  *
8546  *    Calculate PRBs required for UE to satisfy BO in DL
8547  *   
8548  *    Note : Total calculated PRBs will be assigned to *prbReqrd
8549  *    
8550  *
8551  *  @param[in]  RgSchCellCb     *cell
8552  *  @param[in]  RgSchUeCb       *ue 
8553  *  @param[in]  uint32_t              bo 
8554  *  @param[out] uint32_t             *prbReqrd 
8555  *  @return Void
8556  **/
8557 Void rgSchUtlDlCalc1CwPrb(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t  *prbReqrd)
8558 {
8559    RgSchCmnDlCell *dlCell  = RG_SCH_CMN_GET_DL_CELL(cell); 
8560    RgSchCmnDlUe   *dlUe  = RG_SCH_CMN_GET_DL_UE(ue, cell); 
8561    uint32_t       eff;
8562    uint32_t       noRes;
8563    uint8_t        iTbs;
8564    uint8_t        cfi = dlCell->currCfi;               
8565
8566    iTbs  = dlUe->mimoInfo.cwInfo[0].iTbs[0];
8567    eff   = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[0][cfi]))[iTbs];
8568
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]);
8575
8576    return;
8577 } /* rgSchUtlDlCalc1CwPrb*/
8578
8579 /**
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)
8582  *         for TM3/TM4
8583  *
8584  * @details
8585  *
8586  *     Function : rgSchUtlDlCalc2CwPrb
8587  *
8588  *    Calculate PRBs required for UE to satisfy BO in DL
8589  *   
8590  *    Note : Total calculated PRBs will be assigned to *prbReqrd
8591  *    
8592  *
8593  *  @param[in]  RgSchCellCb     *cell
8594  *  @param[in]  RgSchUeCb       *ue 
8595  *  @param[in]  uint32_t              bo 
8596  *  @param[out] uint32_t             *prbReqrd 
8597  *  @return Void
8598  **/
8599 Void rgSchUtlDlCalc2CwPrb(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8600 {
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;
8604    uint32_t            noRes;
8605    uint8_t             noLyr1, noLyr2;
8606    uint8_t             iTbs1, iTbs2;
8607    uint8_t             cfi = dlCell->currCfi;               
8608
8609    if ((dlUe->mimoInfo.forceTD) ||/* Transmit Diversity (TD) */
8610        (dlUe->mimoInfo.ri < 2))/* 1 layer precoding */
8611    {
8612       iTbs1  = dlUe->mimoInfo.cwInfo[0].iTbs[0];
8613       eff1   = (*(RgSchCmnTbSzEff *)(dlCell->cqiToEffTbl[0][cfi]))[iTbs1];
8614
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]);
8621    }
8622    else
8623    {
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];
8630
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]);
8637    }
8638    return;
8639 } /* rgSchUtlDlCalc2CwPrb */
8640
8641 /**
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)
8644  *
8645  * @details
8646  *
8647  *     Function : rgSchUtlCalcTotalPrbReq
8648  *
8649  *    This function calls TM specific routine to calculate PRB
8650  *   
8651  *
8652  *  @param[in]  RgSchCellCb     *cell
8653  *  @param[in]  RgSchUeCb       *ue 
8654  *  @param[in]  uint32_t              bo 
8655  *  @param[out] uint32_t             *prbReqrd 
8656  *  @return Void
8657  **/
8658 Void rgSchUtlCalcTotalPrbReq(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t bo,uint32_t *prbReqrd)
8659 {
8660    /* Call TM specific Prb calculation routine */
8661    (dlCalcPrbFunc[ue->mimoInfo.txMode - 1])(cell, ue, bo, prbReqrd);
8662
8663    return;
8664 } /* rgSchUtlCalcTotalPrbReq */
8665 #ifdef UNUSE_FUN
8666 #ifdef TFU_UPGRADE
8667 /***********************************************************
8668  *
8669  *     Func : rgSCHUtlFetchPcqiBitSz
8670  *
8671  *
8672  *     Desc : Fetch the CQI/PMI bits for a UE based on the mode, periodicity.
8673  *
8674  *     Ret  : uint8_t
8675  *            ROK - Success
8676  *
8677  *     Notes:
8678  *
8679  *     File :
8680  *
8681  **********************************************************/
8682 static uint8_t rgSCHUtlFetchPcqiBitSz(RgSchCellCb *cell, RgSchUeCb *ueCb,uint8_t numTxAnt)
8683 {
8684    uint8_t   confRepMode;
8685    uint8_t   pcqiSz;
8686    uint8_t   ri;
8687    RgSchUePCqiCb *cqiCb = RG_SCH_GET_UE_CELL_CQI_CB(ueCb,cell);
8688
8689    confRepMode = cqiCb->cqiCfg.cqiSetup.prdModeEnum;
8690    if((ueCb->mimoInfo.txMode != RGR_UE_TM_3) && 
8691          (ueCb->mimoInfo.txMode != RGR_UE_TM_4))
8692    {
8693       ri =1;
8694    }
8695    else
8696    {
8697       ri = cqiCb->perRiVal;
8698    }
8699    switch(confRepMode)
8700    {
8701       case RGR_PRD_CQI_MOD10:
8702       {
8703          pcqiSz = 4;
8704       }
8705       break;
8706
8707       case RGR_PRD_CQI_MOD11:
8708       {
8709          if(numTxAnt == 2)
8710          {
8711             if (ri ==1)
8712             {
8713                pcqiSz = 6;
8714             }
8715             else
8716             {
8717                pcqiSz = 8;
8718             }
8719          }
8720          else if(numTxAnt == 4)
8721          {
8722             if (ri ==1)
8723             {
8724                pcqiSz = 8;
8725             }
8726             else
8727             {
8728                pcqiSz = 11;
8729             }
8730          }
8731          else
8732          {
8733             /* This is number of antenna case 1.
8734              * This is not applicable for Mode 1-1. 
8735              * So setting it to invalid value */
8736             pcqiSz = 0;
8737          }
8738       }
8739       break;
8740
8741       case RGR_PRD_CQI_MOD20:
8742       {
8743          if(cqiCb->isWb)
8744          {
8745             pcqiSz = 4;
8746          }
8747          else
8748          {
8749             pcqiSz = 4 + cqiCb->label;
8750          }
8751       }
8752       break;
8753
8754       case RGR_PRD_CQI_MOD21:
8755       {
8756          if(cqiCb->isWb)
8757          {
8758              if(numTxAnt == 2)
8759              {
8760                 if (ri ==1)
8761                 {
8762                     pcqiSz = 6;
8763                 }
8764                 else
8765                 {
8766                     pcqiSz = 8;
8767                 }
8768              }
8769              else if(numTxAnt == 4)
8770              {
8771                 if (ri ==1)
8772                 {
8773                     pcqiSz = 8;
8774                 }
8775                 else
8776                 {
8777                     pcqiSz = 11;
8778                 }
8779              }
8780              else
8781              {
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.*/
8785                 pcqiSz = 0;
8786              }
8787           }
8788           else
8789           {
8790              if (ri ==1)
8791              {
8792                  pcqiSz = 4 + cqiCb->label;
8793              }
8794              else
8795              {
8796                  pcqiSz = 7 + cqiCb->label;
8797              }
8798           }
8799       }
8800       break;
8801
8802       default:
8803          pcqiSz = 0;
8804       break;
8805    }
8806    
8807    return (pcqiSz);
8808 }
8809 #endif
8810 #endif
8811 /**
8812  * @brief  Utility function to returns the number of subbands based on the 
8813  *         requested bytes.
8814  *
8815  * @details
8816  *
8817  *     Function : rgSchUtlGetNumSbs
8818  *
8819  *     Calculate the number of PRBs
8820  *     Update the subbandRequired based on the nPrbs and subband size
8821  *
8822  *  @param[in]  RgSchCellCb  *cell
8823  *  @param[in]  RgSchUeCb    *ue
8824  *  @param[in]  uint32_t          *numSbs
8825  *  @return     uint8_t
8826  **/
8827 uint8_t rgSchUtlGetNumSbs(RgSchCellCb *cell,RgSchUeCb *ue,uint32_t *numSbs)
8828 {
8829    uint32_t  nPrb;
8830    //Currently hardcoding MAX prb for each UE
8831    nPrb = ue->ue5gtfCb.maxPrb;
8832    (*numSbs) = RGSCH_CEIL(nPrb, MAX_5GTF_VRBG_SIZE);
8833    return ROK;
8834 }
8835
8836 /**
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.
8839  *
8840  * @details
8841  *
8842  *     Function : rgSchUtlSortInsUeLst
8843  *
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
8847  *
8848  *  @param[in]  RgSchCellCb  *cell
8849  *  @param[in]  RgSchUeCb    *ue
8850  *  @return     uint8_t
8851  **/
8852 uint8_t rgSchUtlSortInsUeLst(RgSchCellCb *cell,CmLListCp *ueLst,CmLList *node,uint8_t vrbgRequired)
8853 {
8854    CmLList      *ueInLst;
8855    CmLList      *firstUeInLst;
8856    CmLList      *lastUeInLst;
8857    RgSchUeCb    *tempUe;
8858    RgSchCmnUlUe *ueUl;
8859
8860    //firstUeInLst = cmLListFirst(ueLst);
8861    CM_LLIST_FIRST_NODE(ueLst,firstUeInLst);
8862    if(NULLP == firstUeInLst)
8863    {
8864       /* first node to be added to the list */
8865       cmLListAdd2Tail(ueLst, node);
8866    }
8867    else
8868    {
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);
8872
8873       if(vrbgRequired <= ueUl->vrbgRequired)
8874       {
8875          cmLListInsCrnt(ueLst, (node));
8876       }
8877       else
8878       {
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)
8883          {
8884             cmLListAdd2Tail(ueLst, (node));
8885          }
8886          else
8887          {
8888             /* This UE needs to be in the middle. Search and insert the UE */
8889             ueInLst = cmLListFirst(ueLst);
8890             do
8891             {
8892                tempUe = (RgSchUeCb *)(ueInLst->node);
8893
8894                if(vrbgRequired <= ueUl->vrbgRequired)
8895                {
8896                   cmLListInsCrnt(ueLst, (node));
8897                   break;
8898                }
8899
8900                ueInLst = cmLListNext(ueLst);
8901
8902             } while(NULLP != ueInLst && ueInLst != firstUeInLst);
8903          }
8904       }
8905    }
8906
8907    return ROK;
8908 }
8909
8910 /**
8911  * @brief Function to Send LCG GBR register to MAC
8912  *
8913  * @details
8914  *
8915  *     Function: rgSCHUtlBuildNSendLcgReg
8916  *
8917  *     Handler for sending LCG GBR registration 
8918  *
8919  *     Invoked by: 
8920  *         SCHD
8921  *
8922  *     Processing Steps:
8923  *           
8924  *  @param[in] RgSchCellCb       *cell
8925  *  @param[in] CmLteRnti         crnti
8926  *  @param[in] uint8_t                lcgId
8927  *  @param[in] Bool              isGbr
8928  *  @return  S16
8929  *      -# ROK 
8930  **/
8931 S16 rgSCHUtlBuildNSendLcgReg(RgSchCellCb  *cell,CmLteRnti  crnti,uint8_t lcgId,Bool isGbr)
8932 {
8933    Pst            pst;
8934    RgInfLcgRegReq lcgRegReq;
8935
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);
8944
8945    return ROK;
8946 }
8947
8948 #ifdef TFU_UPGRADE
8949 #ifdef LTE_ADV
8950 #ifndef TFU_TDD
8951 /**
8952  * @brief Function to map RGR pucch type to TFU type
8953  *
8954  * @details
8955  *
8956  *     Function: rgSchUtlGetFdbkMode
8957  *
8958  *
8959  *     Invoked by: 
8960  *         SCHD
8961  *
8962  *     Processing Steps:
8963  *           
8964  *  @param[in] RgrSchFrmt1b3TypEnum
8965  *  @return  TfuAckNackMode
8966  *      -# ROK 
8967  **/
8968 TfuAckNackMode rgSchUtlGetFdbkMode(RgrSchFrmt1b3TypEnum fdbkType)
8969 {
8970
8971    TfuAckNackMode mode = TFU_UCI_FORMAT_1A_1B;
8972
8973    switch(fdbkType)
8974    {
8975      case RG_SCH_UCI_FORMAT_NON_CA:
8976      case RG_SCH_UCI_FORMAT1A_1B:
8977      {
8978         mode = TFU_UCI_FORMAT_1A_1B;
8979      }
8980      break;
8981      case RG_SCH_UCI_FORMAT1B_CS:
8982      {
8983         mode = TFU_UCI_FORMAT_1B_CS;
8984      }
8985      break;
8986      case RG_SCH_UCI_FORMAT3:
8987      {
8988         mode = TFU_UCI_FORMAT_3;
8989      }
8990      break;
8991    }
8992    return (mode);
8993 }
8994 #endif /* TFU_TDD */
8995 #endif /* LTE_ADV */
8996 #endif /*TFU_UPGRADE */
8997
8998 #ifdef LTE_ADV
8999 /**
9000  * @brief Send Ue SCell delete to SMAC.
9001  *
9002  * @details
9003  *
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.
9008  *     
9009  *    
9010  *           
9011  *  @param[in]     RgSchCellCb    *cell
9012  *  @param[in]     CmLteRnti      rnti 
9013  *  @return  Void
9014  *      -# ROK 
9015  **/
9016 Void rgSCHUtlSndUeSCellDel2Mac(RgSchCellCb *cell,CmLteRnti rnti)
9017 {
9018    Pst          pst;
9019    Inst         inst = cell->instIdx;
9020    RgInfRlsRnti rntiInfo;
9021
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 
9028     * is dummy */          
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);
9035    return;
9036 }
9037
9038 /**
9039  * @brief Returns max TB supported by a given txMode
9040  *
9041  * @details
9042  *
9043  *     Function : rgSCHUtlGetMaxTbSupp
9044  *     Max TB supported for TM Modes (1,2,5,6 and 7) is 1
9045  *     and 2 for others
9046  *    
9047  *           
9048  *  @param[in]     RgrTxMode  txMode
9049  *  @return        uint8_t maxTbCount; 
9050  *      -# ROK 
9051  **/
9052 uint8_t rgSCHUtlGetMaxTbSupp(RgrTxMode txMode)
9053 {
9054    uint8_t maxTbCount;
9055
9056    /* Primary Cell */
9057
9058    switch(txMode)
9059    {
9060       case RGR_UE_TM_1:
9061       case RGR_UE_TM_2:
9062       case RGR_UE_TM_5:
9063       case RGR_UE_TM_6:
9064       case RGR_UE_TM_7:
9065          maxTbCount = 1;
9066          break;
9067       case RGR_UE_TM_3:
9068       case RGR_UE_TM_4:
9069       case RGR_UE_TM_8:
9070       case RGR_UE_TM_9:
9071          maxTbCount = 2;
9072          break;
9073       default:
9074          maxTbCount = 0;
9075          break;
9076    }
9077
9078    return (maxTbCount);
9079 }
9080
9081 /**
9082  * @brief Send Ue SCell delete to SMAC.
9083  *
9084  * @details
9085  *
9086  *     Function : rgSCHTomUtlGetTrigSet 
9087  *      This function gets the triggerset based on cqiReq 
9088  *     
9089  *  @param[in]     RgSchCellCb    *cell
9090  *  @param[in]     RgSchUeCb      ueCb 
9091  *  @param[in]     uint8_t             cqiReq,
9092  *  @param[out]    uint8_t             *triggerSet
9093  *
9094  *  @return  Void
9095  *      -# ROK 
9096  **/
9097 Void rgSCHTomUtlGetTrigSet(RgSchCellCb *cell,RgSchUeCb  *ueCb,uint8_t cqiReq,uint8_t *triggerSet)
9098 {
9099    RgSchUeCellInfo *pCellInfo = RG_SCH_CMN_GET_PCELL_INFO(ueCb);
9100    switch(cqiReq)
9101    {
9102       case RG_SCH_APCQI_SERVING_CC:
9103          {
9104             /* APeriodic CQI request for Current Carrier.*/
9105             uint8_t sCellIdx = ueCb->cellIdToCellIdxMap[RG_SCH_CELLINDEX(cell)];
9106             *triggerSet = 1 << (7 - sCellIdx);
9107             break;
9108          }
9109       case RG_SCH_APCQI_1ST_SERVING_CCS_SET:
9110          {
9111             *triggerSet = pCellInfo->acqiCb.aCqiCfg.triggerSet1;
9112             break;
9113          }
9114       case RG_SCH_APCQI_2ND_SERVING_CCS_SET:
9115          {
9116             *triggerSet = pCellInfo->acqiCb.aCqiCfg.triggerSet2;
9117             break;
9118          }
9119       default:
9120          {
9121             /* BUG */
9122             break;
9123          }
9124    }
9125    return;
9126 }
9127 #endif
9128 /**
9129  * @brief This function updates the value of UE specific DCI sizes
9130  *
9131  * @details
9132  *
9133  *     Function: rgSCHUtlUpdUeDciSize
9134  *     Purpose:  This function calculates and updates DCI Sizes in bits.
9135  *
9136  *     Invoked by: Scheduler
9137  *
9138  *  @param[in]  RgSchCellCb       *cell
9139  *  @param[in]  RgSchUeCb         *ueCb
9140  *  @param[in]  isCsi2Bit         *isCsi2Bit: is 1 bit or 2 bit CSI
9141  *  @return     Void
9142  *
9143  **/
9144 Void rgSCHUtlUpdUeDciSize(RgSchCellCb *cell,RgSchUeCb *ueCb,Bool isCsi2Bit)
9145 {
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))
9149    {
9150       dci01aCmnSize += 1; /* Resource Allocation Type DCI 0 */
9151       dci01aDedSize += 1; /* Resource Allocation Type DCI 0 */
9152    }
9153    if (isCsi2Bit == TRUE)
9154    {
9155       dci01aDedSize += 2; /* 2 bit CSI DCI 0 */
9156    }
9157    else
9158    {
9159       dci01aDedSize += 1; /* 1 bit CSI DCI 0 */
9160    }
9161    
9162    /* Common CSI is always 1 bit DCI 0 */
9163    dci01aCmnSize += 1; /* 1 bit CSI DCI 0 */
9164
9165    /* Compare the sizes of DCI 0 with DCI 1A and consider the greater */
9166    if (dci01aCmnSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9167    {
9168       dci01aCmnSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9169    }
9170    if (dci01aDedSize < cell->dciSize.baseSize[TFU_DCI_FORMAT_1A])
9171    {
9172       dci01aDedSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9173    }
9174
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];
9178
9179    ueCb->dciSize.cmnSize[TFU_DCI_FORMAT_0]  = dci01aCmnSize;
9180    ueCb->dciSize.cmnSize[TFU_DCI_FORMAT_1A] = dci01aCmnSize;
9181    
9182    ueCb->dciSize.dedSize[TFU_DCI_FORMAT_0]  = dci01aDedSize;
9183    ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1A] = dci01aDedSize;
9184
9185    ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] = cell->dciSize.baseSize[TFU_DCI_FORMAT_1];
9186    do {
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])
9192       {
9193          ueCb->dciSize.dedSize[TFU_DCI_FORMAT_1] += 1;
9194       }
9195
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]);
9202
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];
9208
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];
9214    do {
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])
9220       {
9221          ueCb->dciSize.noUlCcSize[TFU_DCI_FORMAT_1] += 1;
9222       }
9223
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]);
9230 #ifdef EMTC_ENABLE
9231    rgSCHEmtcUtlUpdUeDciSize(cell, ueCb); 
9232 #endif      
9233 }
9234
9235 /**
9236  * @brief This function initialises the DCI Size table
9237  *
9238  * @details
9239  *
9240  *     Function: rgSCHUtlCalcDciSizes
9241  *     Purpose:  This function calculates and initialises DCI Sizes in bits.
9242  *
9243  *     Invoked by: Scheduler
9244  *
9245  *  @param[in]  RgSchCellCb       *cell
9246  *  @return     Void
9247  *
9248  **/
9249 Void rgSCHUtlCalcDciSizes(RgSchCellCb *cell)
9250 {
9251    uint8_t dciSize = 0;
9252    uint8_t dci01aSize = 0;
9253    uint32_t bits = 0, idx = 0;
9254
9255    switch(TFU_DCI_FORMAT_0) /* Switch case for the purpose of readability */
9256    {
9257       case TFU_DCI_FORMAT_0:
9258          {
9259             /* DCI 0: Spec 36.212 Section 5.3.3.1.1 */
9260             dciSize = 0;
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)
9265             {
9266                bits <<= 1;
9267                idx++;
9268             }
9269             bits = 16 - idx;
9270
9271             dciSize = 1 /* DCI 0 bit indicator */ + \
9272                       1 /* Frequency hoping enable bit field */ + \
9273                       (uint8_t)bits /* For frequency Hopping */ + \
9274                       5 /* MCS */ + \
9275                       1 /* NDI */ + \
9276                       2 /* TPC */ + \
9277                       3 /* DMRS */
9278 #ifdef TFU_TDD
9279                       + \
9280                       2 /* UL Index Config 0 or DAI Config 1-6 */
9281 #endif
9282                       ;
9283
9284             cell->dciSize.baseSize[TFU_DCI_FORMAT_0] = dciSize;
9285
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 */
9288             {
9289                cell->dciSize.dci0HopSize = 1;
9290             }
9291             else
9292             {
9293                cell->dciSize.dci0HopSize = 2;
9294             }
9295
9296             /* Update common non-CRNTI scrambled DCI 0/1A flag */
9297             dci01aSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_0] + 1; /* 1 bit CSI */
9298          }
9299       case TFU_DCI_FORMAT_1A:
9300          {
9301             /* DCI 1A: Spec 36.212 Section 5.3.3.1.3 */
9302             dciSize = 0;
9303             idx = 0;
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)
9308             {
9309                bits <<= 1;
9310                idx++;
9311             }
9312             bits = 16 - idx;
9313
9314             dciSize += 1 /* Format 1A */ + \
9315                        1 /* Local or Distributed */ + \
9316                        (uint8_t)bits /* Resource block Assignment */ + \
9317                        5 /* MCS */ + 
9318 #ifdef TFU_TDD
9319                        4 /* HARQ Proc Id */ + 
9320 #else
9321                        3 /* HARQ Proc Id */ + 
9322 #endif
9323                        1 /* NDI */ + \
9324                        2 /* RV */ + \
9325                        2 /* TPC CMD */
9326 #ifdef TFU_TDD
9327                        + \
9328                        2 /* DAI */
9329 #endif
9330                        ;
9331             cell->dciSize.baseSize[TFU_DCI_FORMAT_1A] = dciSize;
9332
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])
9338             {
9339                dci01aSize = cell->dciSize.baseSize[TFU_DCI_FORMAT_1A];
9340             }
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;
9345          }
9346       case TFU_DCI_FORMAT_1:
9347          {
9348             /* DCI 1: Spec 36.212 Section 5.3.3.1.2 */
9349             dciSize = 0;
9350             if (cell->bwCfg.dlTotalBw > 10)
9351             {
9352                dciSize = 1; /* Resource Allocation header bit */
9353             }
9354             
9355             /* Resouce allocation bits Type 0 and Type 1 */
9356             bits = (cell->bwCfg.dlTotalBw/cell->rbgSize);
9357             if ((cell->bwCfg.dlTotalBw % cell->rbgSize) != 0)
9358             {
9359                bits++;
9360             }
9361
9362             dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9363                        5 /* MCS */ + 
9364 #ifdef TFU_TDD
9365                        4 /* HARQ TDD */ + 
9366 #else
9367                        3 /* HARQ FDD */ + 
9368 #endif
9369                        1 /* NDI */ + \
9370                        2 /* Redunancy Version */ + \
9371                        2 /* TPC Cmd */
9372 #ifdef TFU_TDD
9373                        + \
9374                        2 /* DAI */
9375 #endif
9376                        ;
9377
9378             
9379             cell->dciSize.baseSize[TFU_DCI_FORMAT_1] = dciSize;
9380
9381             cell->dciSize.size[TFU_DCI_FORMAT_1] = dciSize;
9382             
9383             do {
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 
9387                 * to format 1. */
9388                if (dci01aSize == cell->dciSize.size[TFU_DCI_FORMAT_1])
9389                {
9390                   cell->dciSize.size[TFU_DCI_FORMAT_1] += 1;
9391                }
9392
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);
9399          }
9400       case TFU_DCI_FORMAT_2:
9401          {
9402             /* DCI 2: Spec 36.212 Section 5.3.3.1.5 */
9403             dciSize = 0;
9404             if (cell->bwCfg.dlTotalBw > 10)
9405             {
9406                dciSize = 1; /* Resource Allocation bit */
9407             }
9408
9409             dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9410                        2 /* TPC */ + 
9411 #ifdef TFU_TDD
9412                        2 /* DAI */ + \
9413                        4 /* HARQ */ + 
9414 #else
9415                        3 /* HARQ */ +
9416 #endif
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 */+ \
9423                        2 /* RV for TB2 */;
9424             if (cell->numTxAntPorts == 2)
9425             {
9426                dciSize += 3;
9427             }
9428             else if (cell->numTxAntPorts == 4)
9429             {
9430                dciSize += 6;
9431             }
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]];
9434          }
9435       case TFU_DCI_FORMAT_2A:
9436          {
9437             /* DCI 2A: Spec 36.212 Section 5.3.3.1.5A */
9438             dciSize = 0;
9439             if (cell->bwCfg.dlTotalBw > 10)
9440             {
9441                dciSize = 1; /* Resource Allocation bit */
9442             }
9443
9444             dciSize += (uint8_t)bits /* Resource Allocation bits */ + \
9445                          2 /* TPC */ + 
9446 #ifdef TFU_TDD
9447                          2 /* DAI */ + \
9448                          4 /* HARQ */ + 
9449 #else
9450                          3 /* HARQ */ +
9451 #endif
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 */+ \
9458                          2 /* RV for TB2 */;
9459             if (cell->numTxAntPorts == 4)
9460             {
9461                dciSize += 2;
9462             }
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 */
9466          }
9467       case TFU_DCI_FORMAT_3:
9468          {
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)
9472             {
9473                cell->dciSize.size[TFU_DCI_FORMAT_3]++;
9474             }
9475          }
9476       case TFU_DCI_FORMAT_3A:
9477          {
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];
9480          }
9481 #ifdef EMTC_ENABLE
9482       case TFU_DCI_FORMAT_6_0A:
9483          {
9484             rgSCHEmtcGetDciFrmt60ASize(cell);
9485          }
9486          case TFU_DCI_FORMAT_6_1A:
9487          {
9488             rgSCHEmtcGetDciFrmt61ASize(cell);
9489          }
9490 #endif                  
9491       default:
9492          {
9493             /* DCI format not supported */
9494             break;
9495          }
9496    }
9497 }
9498
9499 /**
9500  * @brief Handler for the CPU OvrLd related state adjustment.
9501  *
9502  * @details
9503  *
9504  *     Function : rgSCHUtlCpuOvrLdAdjItbsCap
9505  *
9506  *     Processing Steps:
9507  *      - Record dl/ulTpts 
9508  *      - Adjust maxItbs to acheive target throughputs
9509  *
9510  *  @param[in]  RgSchCellCb *cell
9511  *  @return  Void 
9512  **/
9513 Void rgSCHUtlCpuOvrLdAdjItbsCap( RgSchCellCb *cell)
9514 {
9515    uint32_t tptDelta;
9516
9517    if ((cell->cpuOvrLdCntrl.cpuOvrLdIns) & (RGR_CPU_OVRLD_DL_TPT_UP | 
9518             RGR_CPU_OVRLD_DL_TPT_DOWN))
9519    {
9520       /* Regulate DL Tpt for CPU overload */
9521       if (cell->measurements.dlTpt > cell->cpuOvrLdCntrl.tgtDlTpt)
9522       {
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)
9526          {
9527             cell->thresholds.maxDlItbs = RGSCH_MAX((cell->thresholds.maxDlItbs-1), 1);
9528          }
9529       }
9530       else
9531       {
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)
9535          {
9536             cell->thresholds.maxDlItbs = RGSCH_MIN((cell->thresholds.maxDlItbs+1), RG_SCH_DL_MAX_ITBS);
9537          }
9538       }
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);
9542 #endif
9543    }
9544
9545    if ((cell->cpuOvrLdCntrl.cpuOvrLdIns) & (RGR_CPU_OVRLD_UL_TPT_UP | 
9546             RGR_CPU_OVRLD_UL_TPT_DOWN))
9547    {
9548       /* Regualte DL Tpt for CPU overload */
9549       if (cell->measurements.ulTpt > cell->cpuOvrLdCntrl.tgtUlTpt)
9550       {
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)
9554          {
9555             cell->thresholds.maxUlItbs = RGSCH_MAX((cell->thresholds.maxUlItbs-1), 1);
9556          }
9557       }
9558       else
9559       {
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)
9563          {
9564             cell->thresholds.maxUlItbs = RGSCH_MIN((cell->thresholds.maxUlItbs+1), RG_SCH_UL_MAX_ITBS);
9565          }
9566       }
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);
9570 #endif
9571    }
9572
9573    return;
9574 }
9575 /**
9576  * @brief Handler for the num UE per TTI based CPU OvrLd instr updating
9577  *
9578  * @details
9579  *
9580  *     Function : rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr
9581  *
9582  *     Processing Steps:
9583  *      - Validate the config params.
9584  *      - Update numUEperTTi CPU OL related information.
9585  *      - If successful, return ROK else RFAILED.
9586  *
9587  *  @param[in]  RgSchCellCb *cell
9588  *  @param[in]  uint8_t          cnrtCpuOvrLdIns 
9589  *  @return     Void
9590  **/
9591 static Void rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr(RgSchCellCb *cell,uint8_t crntCpuOvrLdIns)
9592 {
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 
9599    uint8_t                 idx = 0;
9600 #endif
9601    uint8_t                 maxDlDecCnt;
9602    uint8_t                 maxUlDecCnt;
9603
9604    cellSch = RG_SCH_CMN_GET_CELL(cell);
9605
9606    maxUeNewDlTxPerTti = cellSch->dl.maxUeNewTxPerTti; 
9607    maxUeNewUlTxPerTti = cellSch->ul.maxUeNewTxPerTti;
9608   
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);
9612
9613    /* Check for DL CPU Commands */
9614    if ( crntCpuOvrLdIns &  RGR_CPU_OVRLD_DL_DEC_NUM_UE_PER_TTI ) 
9615    {
9616       /* Decrement till 90% of maxUeNewDlTxPerTti */
9617       if ( cpuInstr->dlNxtIndxDecNumUeTti < maxDlDecCnt )
9618       {
9619          tmpslot = (cpuInstr->dlNxtIndxDecNumUeTti) % 10;
9620          cpuInstr->dlNxtIndxDecNumUeTti++;
9621          if ( cpuInstr->maxUeNewTxPerTti[tmpslot] > 1 )
9622          {
9623             cpuInstr->maxUeNewTxPerTti[tmpslot]--;
9624          }
9625          else
9626          {
9627 #ifdef CPU_OL_DBG_PRINTS
9628             DU_LOG("\nERROR  -->  SCH : CPU_OL_TTI__ERROR\n");
9629 #endif
9630             DU_LOG("\nERROR  -->  SCH : Invalid CPU OL");
9631          }
9632       }
9633 #ifdef CPU_OL_DBG_PRINTS
9634      DU_LOG("\nDEBUG  -->  SCH : dlNxtIndxDecNumUeTti = %d\n", cpuInstr->dlNxtIndxDecNumUeTti);
9635 #endif
9636       DU_LOG("\nDEBUG  -->  SCH : dlNxtIndxDecNumUeTti = %d",
9637          cpuInstr->dlNxtIndxDecNumUeTti);
9638    }
9639    else if ( crntCpuOvrLdIns &  RGR_CPU_OVRLD_DL_INC_NUM_UE_PER_TTI )
9640    {
9641       if ( cpuInstr->dlNxtIndxDecNumUeTti >  0) 
9642       {
9643          cpuInstr->dlNxtIndxDecNumUeTti--;
9644          tmpslot = (cpuInstr->dlNxtIndxDecNumUeTti) % 10;
9645          if ( cpuInstr->maxUeNewTxPerTti[tmpslot] < maxUeNewDlTxPerTti )
9646          {
9647             cpuInstr->maxUeNewTxPerTti[tmpslot]++;
9648          }
9649          else
9650          {
9651 #ifdef CPU_OL_DBG_PRINTS
9652              DU_LOG("\nERROR  -->  SCH : CPU_OL_TTI__ERROR\n");
9653 #endif
9654              DU_LOG("\nERROR  -->  SCH : Invalid CPU OL");
9655          }
9656       }
9657 #ifdef CPU_OL_DBG_PRINTS
9658       DU_LOG("\nDEBUG  -->  SCH : dlNxtIndxDecNumUeTti = %d\n", cpuInstr->dlNxtIndxDecNumUeTti);
9659 #endif
9660       DU_LOG("\nERROR  -->  SCH : dlNxtIndxDecNumUeTti = %d",
9661          cpuInstr->dlNxtIndxDecNumUeTti);
9662    }
9663    /* Check for UL CPU commands */
9664    if ( crntCpuOvrLdIns &  RGR_CPU_OVRLD_UL_DEC_NUM_UE_PER_TTI )
9665    {
9666       /* Decrement till 90% of maxUeNewDlTxPerTti */
9667       if ( cpuInstr->ulNxtIndxDecNumUeTti < maxUlDecCnt )
9668       {
9669          tmpslot = (cpuInstr->ulNxtIndxDecNumUeTti) % 10;
9670          cpuInstr->ulNxtIndxDecNumUeTti++;
9671          if ( cpuInstr->maxUeNewRxPerTti[tmpslot] > 1 )
9672          {
9673             cpuInstr->maxUeNewRxPerTti[tmpslot]--;
9674          }
9675          else
9676          {
9677 #ifdef CPU_OL_DBG_PRINTS
9678             DU_LOG("\nERROR  -->  SCH : CPU_OL_TTI__ERROR\n");
9679 #endif
9680             DU_LOG("\nERROR  -->  SCH : Invalid CPU OL");
9681          }
9682       }
9683 #ifdef CPU_OL_DBG_PRINTS
9684       DU_LOG("\nDEBUG  -->  SCH : ulNxtIndxDecNumUeTti = %d\n", cpuInstr->ulNxtIndxDecNumUeTti);
9685 #endif
9686       DU_LOG("\nDEBUG  -->  SCH : dlNxtIndxDecNumUeTti = %d",
9687          cpuInstr->dlNxtIndxDecNumUeTti);
9688    }
9689    else if ( crntCpuOvrLdIns &  RGR_CPU_OVRLD_UL_INC_NUM_UE_PER_TTI )
9690    {
9691       if ( cpuInstr->ulNxtIndxDecNumUeTti >  0) 
9692       {
9693          cpuInstr->ulNxtIndxDecNumUeTti--;
9694          tmpslot = (cpuInstr->ulNxtIndxDecNumUeTti) % 10;
9695          if ( cpuInstr->maxUeNewRxPerTti[tmpslot] < maxUeNewUlTxPerTti )
9696          {
9697             cpuInstr->maxUeNewRxPerTti[tmpslot]++;
9698          }
9699          else
9700          {
9701 #ifdef CPU_OL_DBG_PRINTS
9702             DU_LOG("\nERROR  -->  SCH : CPU_OL_TTI__ERROR\n");
9703 #endif
9704             DU_LOG("\nERROR  -->  SCH : Invalid CPU OL");
9705          }
9706       }
9707 #ifdef CPU_OL_DBG_PRINTS
9708       DU_LOG("\nDEBUG  -->  SCH : ulNxtIndxDecNumUeTti = %d\n", cpuInstr->ulNxtIndxDecNumUeTti);
9709 #endif
9710       DU_LOG("\nDEBUG  -->  SCH : dlNxtIndxDecNumUeTti = %d",
9711          cpuInstr->dlNxtIndxDecNumUeTti);
9712    }
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 ++ )
9718    {
9719       DU_LOG("  %d", cpuInstr->maxUeNewTxPerTti[idx]);  
9720    }
9721    DU_LOG("\nINFO  -->  SCH : UL Sf numUePerTti:");
9722    for ( idx = 0; idx < 10 ; idx ++ )
9723    {
9724       DU_LOG("  %d", cpuInstr->maxUeNewRxPerTti[idx]);  
9725    }
9726    DU_LOG("\n");
9727 #endif
9728
9729    return;
9730 } /* rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr */
9731
9732 /**
9733  * @brief Handler for the CPU OvrLd related cell Recfg.
9734  *
9735  * @details
9736  *
9737  *     Function : rgSCHUtlResetCpuOvrLdState
9738  *
9739  *     Processing Steps:
9740  *      - Validate the config params.
9741  *      - Update CPU OL related state information.
9742  *      - If successful, return ROK else RFAILED.
9743  *
9744  *  @param[in]  RgSchCellCb *cell
9745  *  @param[in]  uint8_t          cnrtCpuOvrLdIns 
9746  *  @return  S16
9747  *      -# ROK
9748  *      -# RFAILED
9749  **/
9750 S16 rgSCHUtlResetCpuOvrLdState(RgSchCellCb *cell,uint8_t crntCpuOvrLdIns)
9751 {
9752    uint8_t      crntDlCpuOL=0;
9753    uint8_t      crntUlCpuOL=0;
9754    RgSchCmnCell *schCmnCell = (RgSchCmnCell *)(cell->sc.sch);
9755    uint8_t idx;
9756
9757 #ifdef CPU_OL_DBG_PRINTS
9758    DU_LOG("\nDEBUG  -->  SCH : CPU OVR LD Ins Rcvd = %d\n", (int)crntCpuOvrLdIns);
9759 #endif
9760    DU_LOG("\nINFO  -->  SCH : CPU OVR LD Ins Rcvd");
9761
9762    if ( RGR_CPU_OVRLD_RESET == crntCpuOvrLdIns )
9763    {
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");
9767 #endif
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++ )
9777       {
9778          cell->cpuOvrLdCntrl.maxUeNewTxPerTti[idx] = 
9779             schCmnCell->dl.maxUeNewTxPerTti;
9780          cell->cpuOvrLdCntrl.maxUeNewRxPerTti[idx] = 
9781             schCmnCell->ul.maxUeNewTxPerTti;
9782       }
9783
9784       return ROK;
9785    }
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 )  
9790    {
9791       rgSCHUtlChkAndUpdNumUePerTtiCpuOvInstr(cell, crntCpuOvrLdIns);
9792       /* If need to have both TP and numUePerTti instrcution together in
9793        * one command then dont return from here */
9794       return ROK;
9795    }
9796
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))
9801    {
9802       /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9803       return RFAILED;
9804    }
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))
9809    {
9810       /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9811       return RFAILED;
9812    }
9813    if ((crntDlCpuOL == 0) && (crntUlCpuOL == 0))
9814    {
9815       /* Cfg validation failed. Invalid Command. Either UP/DOWN is allowed */
9816       return RFAILED;
9817    }
9818
9819    cell->cpuOvrLdCntrl.cpuOvrLdIns = crntCpuOvrLdIns;
9820
9821    if (crntUlCpuOL)
9822    {
9823       if (crntUlCpuOL == RGR_CPU_OVRLD_UL_TPT_DOWN)
9824       {
9825          cell->cpuOvrLdCntrl.tgtUlTpt = cell->measurements.ulTpt - \
9826             (cell->measurements.ulTpt * 3 )/100;
9827       }
9828       else
9829       {
9830          cell->cpuOvrLdCntrl.tgtUlTpt = cell->measurements.ulTpt + \
9831             (cell->measurements.ulTpt * 2 )/100;
9832       }
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);
9838 #endif
9839    }
9840
9841    if (crntDlCpuOL)
9842    {
9843       if (crntDlCpuOL == RGR_CPU_OVRLD_DL_TPT_DOWN)
9844       {
9845          cell->cpuOvrLdCntrl.tgtDlTpt = cell->measurements.dlTpt - \
9846                                         (cell->measurements.dlTpt * 1 )/100;
9847       }
9848       else
9849       {
9850          cell->cpuOvrLdCntrl.tgtDlTpt = cell->measurements.dlTpt + \
9851             (cell->measurements.dlTpt * 1 )/100;
9852       }
9853       DU_LOG("\nDEBUG  -->  SCH : CPU OVR LD DL Reset to "
9854             "%d, %u, %u", (int)crntDlCpuOL, cell->cpuOvrLdCntrl.tgtDlTpt,cell->measurements.dlTpt);
9855
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);
9859 #endif
9860    }
9861    rgSCHUtlCpuOvrLdAdjItbsCap(cell);
9862    return ROK;
9863 }
9864 #ifdef EMTC_ENABLE
9865 S16 rgSCHUtlAddToResLst
9866 (
9867  CmLListCp   *cp,  
9868  RgSchIotRes *iotRes
9869  )
9870 {
9871    cmLListAdd2Tail(cp, &iotRes->resLnk);
9872    iotRes->resLnk.node = (PTR)iotRes;
9873    return ROK;
9874 }
9875 S16 rgSCHUtlDelFrmResLst
9876 (
9877 RgSchUeCb *ue,
9878 RgSchIotRes *iotRes
9879 )
9880 {
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)
9885    {
9886       cp = &emtcUe->ulResLst;
9887    }else if(iotRes->resType == RG_SCH_EMTC_PDSCH_RES)
9888    {
9889       cp = &emtcUe->dlResLst;
9890    }else
9891    {
9892       DU_LOG("\nINFO  -->  SCH : *****restype mismatch");
9893    }
9894    if(cp != NULLP )
9895    { 
9896       if(cp->count == 0)
9897       {
9898          DU_LOG("\nINFO  -->  SCH : ****error count*****\n");
9899          return ROK;
9900       }
9901    }
9902    cmLListDelFrm(cp, &iotRes->resLnk);
9903    iotRes->resLnk.node = NULLP;
9904    return ROK;
9905 }
9906 #endif
9907 /**********************************************************************
9908
9909          End of file
9910 **********************************************************************/