[Epic-ID: ODUHIGH-464][Task-ID: ODUHIGH-483] Memeory related fix in FDD and TDD mode
[o-du/l2.git] / src / 5gnrsch / rg_sch_l2m.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 L2 Measurement fucntions
26   
27      File:     rg_sch_l2m.c
28   
29 **********************************************************************/
30
31 /** @file rg_sch_l2m.c
32 @brief This file implements the L2 Measurement feature code.
33 */
34
35 /* header include files -- defines (.h) */
36 #include "common_def.h"
37 #include "lrg.h"
38 #include "rgr.h"
39 #include "rgm.h"
40 #include "tfu.h"
41 #include "rg_env.h"
42 #include "rg_sch.h"
43 #include "rg_sch_cmn.h"
44 #include "rg_sch_inf.h"         /* typedefs for Scheduler */
45 #include "rg_sch_err.h"
46
47 /* header/extern include files (.x) */
48 #include "tfu.x"           /* TFU types */
49 #include "lrg.x"           /* layer management typedefs for MAC */
50 #include "rgr.x"           /* layer management typedefs for MAC */
51 #include "rgm.x"           /* layer management typedefs for MAC */
52 #include "rg_sch_inf.x"    /* typedefs for Scheduler */
53 #include "rg_sch.x"        /* typedefs for Scheduler */
54 #include "rg_sch_cmn.x"    /* typedefs for Scheduler */
55 /* local defines */
56 uint32_t dlPrbCnt;
57 #ifdef LTE_L2_MEAS
58
59
60 static S16 rgSchL2mInsertMeasCb ARGS((
61          RgSchCellCb       *cell,
62          RgSchL2MeasCb     *measCb,
63          LrgSchMeasReqInfo *measInfo ));
64
65 static RgSchL2MeasCb * rgSchL2mAllocMeasCb ARGS((
66          RgSchCellCb       *cell,
67          LrgSchMeasReqInfo *measInfo,
68          RgSchErrInfo      err));
69
70 /* Function definitions */
71
72 /** @brief This function fills the L2 measurement confirm structure
73  *
74  * @details
75  *
76  *     Function: rgSchFillL2MeasCfm
77  *
78  * @param  [in] RgSchCellCb *cell 
79  * @param  [in] RgSchL2MeasCb *measCb
80  * @param  [out] LrgSchMeasCfmInfo *measCfm
81  * @param  [in] measTime
82  * @return  Void
83  */
84 S16 rgSchFillL2MeasCfm
85 (
86 RgSchCellCb       *cell,
87 RgSchL2MeasCb     *measCb,
88 LrgSchMeasCfmInfo *cfm,
89 uint32_t          measTime   
90 )
91 {
92    uint8_t            idx;
93    LrgSchMeasReqInfo  *measInfo;
94    uint8_t            qciVal = 0;
95    uint32_t           sampOc = 0;
96
97    measInfo = &measCb->measReq;   
98
99    cfm->hdr.transId  = measInfo->hdr.transId;
100    cfm->measType     = measInfo->measType;
101    cfm->cellId       = measInfo->cellId;
102    cfm->cfm.status   = LCM_PRIM_OK;
103    if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_DL) &&
104                                     (measCb->dlTotalBw))
105    {
106        cfm->avgPrbDl.prbPerc = ((cell->avgPrbDl.prbCount * 100) /
107                                  measCb->dlTotalBw);
108        /* Resetting the prbCount to 0,  fix for ccpu00125002 */
109        cell->avgPrbDl.prbCount = 0;
110    }
111    if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_UL) &&
112                                     (measCb->ulTotalBw))
113    {
114        cfm->avgPrbUl.prbPerc = ((cell->avgPrbUl.prbCount * 100) /
115                                  measCb->ulTotalBw);
116        /* Resetting the prbCount to 0,  fix for ccpu00125002 */
117        cell->avgPrbUl.prbCount = 0;
118    }
119    if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL) &&
120                                     (measCb->dlTotalBw))
121    {
122        cfm->avgPrbQciDlCfm.numQci = measCb->measReq.avgPrbQciDl.numQci;
123        for(idx = 0; idx < measCb->measReq.avgPrbQciDl.numQci; idx++)
124        {
125           qciVal = measCb->measReq.avgPrbQciDl.qci[idx];
126           cfm->avgPrbQciDlCfm.prbPercQci[idx].prbPercQci = 
127           ((cell->qciArray[qciVal].dlPrbCount * 100) /
128             measCb->dlTotalBw);
129             cfm->avgPrbQciDlCfm.prbPercQci[idx].qciValue = qciVal;
130           cell->qciArray[qciVal].dlPrbCount = 0;
131        }
132    }
133    if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_PER_QCI_UL) && 
134                                     (measCb->ulTotalBw))
135    {
136        cfm->avgPrbQciUlCfm.numQci = measCb->measReq.avgPrbQciUl.numQci;
137        for(idx = 0; idx < measCb->measReq.avgPrbQciUl.numQci; idx++)
138        {
139           cfm->avgPrbQciUlCfm.prbPercQci[idx].qciValue = 
140                                  measCb->avgPrbQciUl.prbUsage[idx].qciValue;
141
142           if(measCb->avgPrbQciUl.prbUsage[idx].prbUsage > measCb->ulTotalBw)
143           {
144              measCb->avgPrbQciUl.prbUsage[idx].prbUsage = measCb->ulTotalBw;
145           }   
146
147           cfm->avgPrbQciUlCfm.prbPercQci[idx].prbPercQci = 
148              ((measCb->avgPrbQciUl.prbUsage[idx].prbUsage * 100) /
149                measCb->ulTotalBw);
150        }
151    }
152    if(measCb->measReq.measType & LRG_L2MEAS_RA_PREAMBLE)
153    {
154        cfm->raPrmbsCfm.dedPreambles        = cell->raPrmbs.dedPream;
155        cfm->raPrmbsCfm.randSelPreLowRange  = cell->raPrmbs.preamGrpA;
156        cfm->raPrmbsCfm.randSelPreHighRange = cell->raPrmbs.preamGrpB;
157        cell->raPrmbs.dedPream              = 0;
158        cell->raPrmbs.preamGrpA             = 0;
159        cell->raPrmbs.preamGrpB             = 0;
160    }
161    if(measCb->measReq.measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_DL)
162    {
163        cfm->numUeQciDlCfm.numQci = measInfo->nmbActvUeQciDl.numQci;
164        sampOc = (measTime / measInfo->nmbActvUeQciDl.sampPrd);
165        
166        if(sampOc)
167        {   
168           if (measCb->measReq.nmbActvUeQciDl.numQci)
169           {
170              for(idx = 0; idx < measCb->measReq.nmbActvUeQciDl.numQci; idx++)
171              {
172                 qciVal = measCb->measReq.nmbActvUeQciDl.qci[idx];
173                 /* L2_COUNTERS */
174                 cell->qciArray[qciVal].dlTotal_UeCount +=
175                    cell->qciArray[qciVal].dlUeCount;
176                 cfm->numUeQciDlCfm.numActvUeQci[idx].numActvUeQci =
177                    cell->qciArray[qciVal].dlTotal_UeCount / sampOc;
178                 cfm->numUeQciDlCfm.numActvUeQci[idx].qciValue = qciVal;
179                 
180                 DU_LOG("\nDEBUG  -->  SCH : L2_MEAS:CFM DL QCI %u TOTAL Count %lu Active UE %d ",
181                       qciVal,cell->qciArray[qciVal].dlTotal_UeCount,
182                       cfm->numUeQciDlCfm.numActvUeQci[idx].numActvUeQci);
183                 
184                 cell->qciArray[qciVal].dlTotal_UeCount = 0;
185              }
186           }
187           else
188           {
189              idx = 0;
190              for(qciVal = 1; qciVal < LRG_MAX_QCI_PER_REQ; qciVal++)
191              {
192                 /* L2_COUNTERS */
193                 cell->qciArray[qciVal].dlTotal_UeCount +=
194                    cell->qciArray[qciVal].dlUeCount;
195                 if (cell->qciArray[qciVal].dlTotal_UeCount)
196                 {
197                    cfm->numUeQciDlCfm.numActvUeQci[idx].numActvUeQci =
198                       cell->qciArray[qciVal].dlTotal_UeCount / sampOc;
199                    cfm->numUeQciDlCfm.numActvUeQci[idx].qciValue = qciVal;
200
201                    DU_LOG("\nDEBUG  -->  SCH : L2_MEAS:CFM DL QCI %u TOTAL Count %lu Active UE %d ",
202                          qciVal,cell->qciArray[qciVal].dlTotal_UeCount,
203                          cfm->numUeQciDlCfm.numActvUeQci[idx].numActvUeQci);
204
205                    cell->qciArray[qciVal].dlTotal_UeCount = 0;
206                    idx++;
207                 }
208              }
209              cfm->numUeQciDlCfm.numQci = idx;
210           }
211        }
212    }
213    if(measCb->measReq.measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_UL)
214    {
215        cfm->numUeQciUlCfm.numQci = measInfo->nmbActvUeQciUl.numQci;
216        sampOc = (measTime / measInfo->nmbActvUeQciUl.sampPrd);
217        
218        
219        if(sampOc)
220        {   
221           if (measCb->measReq.nmbActvUeQciUl.numQci)
222           {
223              for(idx = 0; idx < measCb->measReq.nmbActvUeQciUl.numQci; idx++)
224              {
225                 cell->qciArray[qciVal].ulTotal_UeCount +=
226                    cell->qciArray[qciVal].ulUeCount;
227                 qciVal = measCb->measReq.nmbActvUeQciUl.qci[idx]; 
228                 cfm->numUeQciUlCfm.numActvUeQci[idx].numActvUeQci =
229                    cell->qciArray[qciVal].ulTotal_UeCount/ sampOc;
230                 cfm->numUeQciUlCfm.numActvUeQci[idx].qciValue = qciVal;
231                 
232                 DU_LOG("\nDEBUG  -->  SCH : L2_MEAS:CFM UL QCI %d TOTAL Count %lu Active UE %d ",
233                       qciVal,cell->qciArray[qciVal].ulTotal_UeCount,
234                       cfm->numUeQciUlCfm.numActvUeQci[idx].numActvUeQci);
235                 
236                 cell->qciArray[qciVal].ulTotal_UeCount = 0;
237              }
238           }
239           else
240           {
241              idx = 0;
242              for(qciVal = 1; qciVal < LRG_MAX_QCI_PER_REQ; qciVal++)
243              {
244                 cell->qciArray[qciVal].ulTotal_UeCount +=
245                    cell->qciArray[qciVal].ulUeCount;
246                 if (cell->qciArray[qciVal].ulTotal_UeCount)
247                 {
248                    cfm->numUeQciUlCfm.numActvUeQci[idx].numActvUeQci =
249                       cell->qciArray[qciVal].ulTotal_UeCount/ sampOc;
250                    cfm->numUeQciUlCfm.numActvUeQci[idx].qciValue = qciVal;
251
252                    DU_LOG("\nDEBUG  -->  SCH : L2_MEAS:CFM UL QCI %d TOTAL Count %lu Active UE %d ",
253                          qciVal,cell->qciArray[qciVal].ulTotal_UeCount,
254                          cfm->numUeQciUlCfm.numActvUeQci[idx].numActvUeQci);
255
256                    cell->qciArray[qciVal].ulTotal_UeCount = 0;
257                    idx++;
258                 }
259              }
260              cfm->numUeQciUlCfm.numQci = idx;
261           }
262        }
263    }
264    if(measCb->measReq.measType & LRG_L2MEAS_TB_TRANS_DL_COUNT)
265    {
266       cfm->tbTransDlTotalCnt = cell->dlUlTbCnt.tbTransDlTotalCnt;
267       cell->dlUlTbCnt.tbTransDlTotalCnt = 0;
268    }   
269    if(measCb->measReq.measType & LRG_L2MEAS_TB_TRANS_DL_FAULTY_COUNT)
270    {
271       cfm->tbTransDlFaulty = cell->dlUlTbCnt.tbTransDlFaulty;
272       cell->dlUlTbCnt.tbTransDlFaulty = 0;
273    }   
274    if(measCb->measReq.measType & LRG_L2MEAS_TB_TRANS_UL_COUNT)
275    {
276       cfm->tbTransUlTotalCnt = cell->dlUlTbCnt.tbTransUlTotalCnt;
277       cell->dlUlTbCnt.tbTransUlTotalCnt = 0;
278    }   
279    if(measCb->measReq.measType & LRG_L2MEAS_TB_TRANS_UL_FAULTY_COUNT)
280    {
281       cfm->tbTransUlFaulty = cell->dlUlTbCnt.tbTransUlFaulty;
282       cell->dlUlTbCnt.tbTransUlFaulty = 0;
283    }
284
285    measCb->dlTotalBw = 0;
286    measCb->ulTotalBw = 0;
287
288    return ROK;
289 } /* rgSchFillL2MeasCfm */
290
291 /** @brief This function sends the L2 measurement confirm to LM 
292  * from Shceduler
293  *
294  * @details
295  *
296  *     Function: rgSchL2mSndCfm
297  *
298  * @param  [in] Pst   *pst
299  * @param  [in] RgSchL2MeasCb *measCb
300  * @param  [in] Bool     isErr
301  * @return  Void
302  */
303 S16 rgSchL2mSndCfm
304 (
305 Pst               *pst,
306 RgSchL2MeasCb     *measCb,
307 LrgSchMeasReqInfo *measInfo,
308 Bool              isErr
309 )
310 {
311    LrgSchMeasCfmInfo   cfm;
312
313    memset(&cfm, 0, sizeof(LrgSchMeasCfmInfo));
314    cfm.hdr.transId  = measInfo->hdr.transId;
315    cfm.measType     = measInfo->measType;
316    cfm.cellId       = measInfo->cellId;
317    cfm.cfm.status   = LCM_PRIM_OK;
318    if(isErr == TRUE)
319    {
320       cfm.cfm.status   = LCM_PRIM_NOK;
321       cfm.cfm.reason   = LCM_REASON_INVALID_PAR_VAL;
322       RgMiLrgSchL2MeasCfm(pst, &cfm);
323       return ROK;
324    }
325    return ROK;
326 } /* rgSchL2mSndCfm */
327
328 /** @brief This function fills the LM confirmation pst structure 
329  *
330  * @details
331  *
332  *     Function: rgSchL2mFillCfmPst
333  *
334  * @param  [in] Pst    *pst
335  * @param  [out] Pst    *cfmPst
336  * @param  [in] LrgSchMeasReqInfo *measInfo
337  * @return  Void
338  */
339 Void rgSchL2mFillCfmPst
340 (
341 Pst    *pst,
342 Pst    *cfmPst,
343 LrgSchMeasReqInfo *measInfo 
344 )
345 {
346  
347    cfmPst->srcEnt    = pst->dstEnt;
348    cfmPst->srcInst   = pst->dstInst;
349    cfmPst->srcProcId = pst->dstProcId;
350    cfmPst->dstEnt    = pst->srcEnt;
351    cfmPst->dstInst   = pst->srcInst;
352    cfmPst->dstProcId = pst->srcProcId;
353
354    cfmPst->selector  = measInfo->hdr.response.selector;
355    cfmPst->prior     = measInfo->hdr.response.prior;
356    cfmPst->route     = measInfo->hdr.response.route;
357    cfmPst->region    = measInfo->hdr.response.mem.region;
358    cfmPst->pool      = measInfo->hdr.response.mem.pool;
359
360    return;
361 } /* rgSchL2mFillCfmPst */
362
363 /** @brief This function inserts the MeasCb in to data base
364  *
365  * @details
366  *
367  *     Function: rgSchL2mInsertMeasCb
368  *
369  * @param  [in] RgSchCellCb       *cell
370  * @param  [in] RgSchL2MeasCb     *measCb
371  * @param  [in] LrgSchMeasReqInfo *measInfo
372  * @return  S16
373  *      -# ROK 
374  *      -# RFAILED 
375  */
376 static S16 rgSchL2mInsertMeasCb
377 (
378 RgSchCellCb       *cell,
379 RgSchL2MeasCb     *measCb,
380 LrgSchMeasReqInfo *measInfo
381 )
382 {
383    CmLList   *lnk, *node;
384    RgSchL2MeasCb   *oldMeasCb;
385    uint32_t        diffTime;
386    
387    /* 
388     * 1. Check if l2mList has any entries.
389     * 2. If yes 
390     *       1. Take the first entrie's time period and find the diff with
391     *       cell->crntTime.
392     *       2. If the diff is > measInfo->timePeriod then insert before this
393     *       entry.
394     *       3. Else take the next entry in list
395     *       4. If reached without adding to list . Append at the end of list.
396     * 3. If no entries in l2mList add at the first.
397     */
398    lnk = cell->l2mList.first;
399    node = &measCb->measLnk;
400    node->node = (PTR)measCb;
401    while(lnk != NULLP )
402    {
403       oldMeasCb = (RgSchL2MeasCb *)lnk->node;
404       diffTime = (oldMeasCb->measReq.timePrd - 
405                  (RGSCH_CALC_SF_DIFF(cell->crntTime, oldMeasCb->startTime)));
406       if (diffTime > measInfo->timePrd)
407       {
408          cell->l2mList.crnt = lnk;
409          cmLListInsCrnt(&(cell->l2mList), node);
410          return ROK;
411       }
412       else
413       {
414          lnk = lnk->next;
415       }
416    }  /* End of While */
417    cmLListAdd2Tail(&(cell->l2mList), node);
418    return ROK;
419 } /* rgSchL2mInsertMeasCb */
420
421 /** @brief This function calculates the Down link prb count 
422  * for a DlSf
423  *
424  * @details
425  *
426  *     Function: rgSchL2CalDlPrbCount
427  *
428  * @param  [in] RgSchCellCb       *cell
429  */
430 static Void rgSchL2CalDlPrbCount(RgSchCellCb *cell)
431 {
432    CmLteTimingInfo    frm;
433    RgSchDlSf          *sf = NULLP;
434 #ifdef LTE_TDD
435    uint8_t            idx;
436 #endif
437
438    frm   = cell->crntTime;
439    RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
440    sf = rgSCHUtlSubFrmGet(cell, frm);
441 #ifdef LTE_TDD
442    idx = (cell->crntTime.slot + RG_SCH_CMN_DL_DELTA) % 
443                   RGSCH_NUM_SUB_FRAMES;
444    if(RG_SCH_CMN_CHK_DL_DATA_ALLOWED(cell, idx)) 
445    {
446       cell->avgPrbDl.prbCount += sf->bwAssigned;
447       dlPrbCnt += sf->bwAssigned;
448    }
449 #else
450    cell->avgPrbDl.prbCount += sf->bwAssigned;
451 #endif
452    return;
453 }
454
455 /** @brief This function calculates the up link prb count 
456  * for a UlSf
457  *
458  * @details
459  *
460  *     Function: rgSchL2CalUlPrbCount
461  *
462  * @param  [in] RgSchCellCb       *cell
463  */
464 static Void rgSchL2CalUlPrbCount(RgSchCellCb  *cell)
465 {
466    RgSchUlSf        *sf = NULLP;
467    RgSchCmnUlCell   *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
468 #ifdef LTE_TDD
469    uint8_t  idx;
470 #endif
471
472 #ifdef LTE_TDD
473    idx = cellUl->schdIdx;
474    if(idx < cellUl->numUlSubfrms)
475    {
476       sf = &cellUl->ulSfArr[idx];
477       cell->avgPrbUl.prbCount += sf->totPrb;
478    }
479 #else
480    sf = &cellUl->ulSfArr[cellUl->schdIdx];
481    cell->avgPrbUl.prbCount += sf->totPrb;
482 #endif
483    return;
484 }
485 /** @brief This function allocates memory from the heap
486  *
487  * @details
488  *
489  *     Function: rgSchL2mAllocMeasCb
490  *
491  * @param  [in] RgSchCellCb       *cell
492  * @param  [in] RgSchL2MeasCb     *measInfo
493  * @param  [out] RgSchErrInfo      *err
494  * @return  RgSchL2MeasCb *
495  */
496 static RgSchL2MeasCb * rgSchL2mAllocMeasCb
497 (
498 RgSchCellCb       *cell,
499 LrgSchMeasReqInfo *measInfo,
500 RgSchErrInfo      err
501 )
502 {
503    RgSchL2MeasCb       *measCb = NULLP;
504    Inst                inst = cell->instIdx;
505    UNUSED(err);
506
507    if((rgSCHUtlAllocSBuf(inst, (Data **)&measCb,
508                    sizeof(RgSchL2MeasCb))) == RFAILED)
509    {
510       DU_LOG("\nERROR  -->  SCH : Allocation of RgSchL2MeasCb failed");
511       return (NULLP);
512    }
513    memcpy(&measCb->measReq, measInfo, sizeof(LrgSchMeasReqInfo));
514    RGSCHCPYTIMEINFO(cell->crntTime, measCb->startTime);
515
516    measCb->dlTotalBw = 0;
517    measCb->ulTotalBw = 0;
518
519    return (measCb);
520 } /* rgSchL2mAllocMeasCb */
521
522 /**
523  * @brief Layer Manager Measurement request handler. 
524  *
525  * @details
526  *
527  *     Function : rgSchL2mMeasReq
528  *     
529  *     This function handles  measurement request received at scheduler instance
530  *     from the Layer Manager.
531  *     -# Measurement request will be stored in the list in ascending order of
532  *     their time period.
533  *     
534  *  @param[in]  Pst *pst, the post structure     
535  *  @param[in]  LrgSchMeasReqInfo *measInfo, the measurement request structure
536  *  @param[out] RgSchErrInfo   *err, error information
537  *  @return  S16
538  *      -# ROK
539  *      -# RFAILED
540  **/
541 S16 rgSchL2mMeasReq 
542 (
543 RgSchCellCb       *cell,
544 LrgSchMeasReqInfo *measInfo,
545 RgSchErrInfo      err
546 )
547 {
548    RgSchL2MeasCb *measCb;
549    uint8_t       idx;
550    uint8_t       qciVal;
551
552
553    qciVal = 0;
554    if ((measCb = rgSchL2mAllocMeasCb(cell, measInfo, err)) == NULLP)
555    {
556        RGSCHFILLERR(err, RGSCHERR_L2M_MEASREQ,
557                     RGSCHERR_SCH_ALLOC_FAILED);
558        DU_LOG("\nERROR  -->  SCH : Allocation of RgSchL2MeasCb failed");
559        return RFAILED;
560    }
561    /*memcpy(&measCb->measReq, measInfo,\
562              sizeof(LrgSchMeasReqInfo));*/
563    rgSchL2mInsertMeasCb(cell, measCb, measInfo);
564   
565    if (measInfo->timePrd == 0)
566    {
567       cell->sndL2Meas = FALSE;
568       if (measInfo->measType & LRG_L2MEAS_AVG_PRB_PER_QCI_DL)
569       {
570          for (idx = 0; idx < measInfo->avgPrbQciDl.numQci; idx++)
571          {
572             qciVal = measInfo->avgPrbQciDl.qci[idx];
573             cell->qciArray[qciVal].qci = qciVal;
574          }
575       }
576       if (measInfo->measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_DL)
577       {
578          for (idx = 0; idx < measInfo->nmbActvUeQciDl.numQci; idx++)
579          {
580             qciVal = measInfo->nmbActvUeQciDl.qci[idx];
581             cell->qciArray[qciVal].qci = qciVal;
582          }
583       }
584       if (measInfo->measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_UL)
585       {
586          for (idx = 0; idx < measInfo->nmbActvUeQciUl.numQci; idx++)
587          {
588             qciVal = measInfo->nmbActvUeQciUl.qci[idx];
589             cell->qciArray[qciVal].qci = qciVal;
590          }
591       }
592    }
593    /* Here post the message to MAC */
594    if(measInfo->measType & LRG_L2MEAS_AVG_PRB_PER_QCI_UL)
595    {
596       RgInfL2MeasReq    measReq;
597       Pst               pst;
598       memset(&measReq, 0, sizeof(RgInfL2MeasReq));
599       measReq.transId  = measInfo->hdr.transId;
600       measReq.measType = measInfo->measType;
601       measReq.timePrd  = measInfo->timePrd;
602       measReq.cellId   = measInfo->cellId;
603       measReq.t.prbReq.numQci = measInfo->avgPrbQciUl.numQci;
604       for (idx = 0; idx < measInfo->avgPrbQciUl.numQci; idx++)
605       {
606         measReq.t.prbReq.qci[idx] = measInfo->avgPrbQciUl.qci[idx]; 
607       }
608       /* Send measReq to MAC */
609       rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
610       RgSchMacL2Meas(&pst, &measReq);
611    }
612    return ROK;
613 } /* rgSchL2mMeasReq */
614
615 /**
616  * @brief This function calculates the measurement for differnt measurement type
617  * and send the end result to the layer manager
618  *
619  * @details
620  *
621  *     Function : rgSCHL2Meas
622  *     
623  *  @param[in] RgSchCellCb  *cell
624  *  @return  S16
625  *      -# ROK
626  *      -# RFAILED
627  **/
628 S16 rgSCHL2Meas
629 (
630 RgSchCellCb  *cell,
631 uint8_t isCalrCrcInd
632 )
633 {
634    CmLList           *node = NULLP;
635    RgSchL2MeasCb     *measCb = NULLP;
636    uint8_t           idx;
637    LrgSchMeasCfmInfo measCfm;
638    uint8_t           qciVal = 0;
639    uint32_t          sfDiff;
640    uint32_t          meas;
641 #ifdef LTE_TDD
642    uint8_t           sfIdx;
643    Bool              isDlDataAllowed;  
644    uint8_t           rem;
645    uint32_t          numDlSf;
646    uint32_t          numUlSf;
647 #endif
648
649    node = cell->l2mList.first;
650    memset(&measCfm, 0, sizeof(LrgSchMeasCfmInfo));
651    while(node != NULLP)
652    {
653       measCb = (RgSchL2MeasCb *)node->node;
654       node = node->next;
655       if(cell->crntTime.sfn == 1023 && cell->crntTime.slot == 9)  
656       {
657          /*calculates diff between crnt time and start time*/
658          meas = RGSCH_CALC_SFN_SF_DIFF(cell->crntTime, 
659                measCb->sfnCycle, measCb->startTime);
660          measCb->sfnCycle++;
661       }
662       else
663       {
664          /*calculates diff between crnt time and start time*/
665          meas = RGSCH_CALC_SFN_SF_DIFF(cell->crntTime, 
666                measCb->sfnCycle, measCb->startTime);
667       }
668
669       if (cell->sndL2Meas || meas == measCb->measReq.timePrd)
670       {
671 #ifdef LTE_TDD
672          rem = meas % RGSCH_NUM_SUB_FRAMES;
673          /* Get the total number of DL and UL subframes within the reporting period*/
674          numDlSf = (meas / RGSCH_NUM_SUB_FRAMES) * rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
675          numUlSf = (meas / RGSCH_NUM_SUB_FRAMES) * rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
676
677          sfIdx = (measCb->startTime.slot + 1) % RGSCH_NUM_SUB_FRAMES;
678
679          while(rem)
680          {
681             isDlDataAllowed = RG_SCH_CMN_CHK_DL_DATA_ALLOWED(cell, sfIdx); 
682             if(isDlDataAllowed)
683             {
684                numDlSf++;
685             }   
686             else if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][sfIdx] == 
687                   RG_SCH_TDD_UL_SUBFRAME)
688             {
689                numUlSf++;
690             }     
691             sfIdx = (sfIdx + 1) % RGSCH_NUM_SUB_FRAMES;
692             rem--;
693          }   
694
695          measCb->dlTotalBw = numDlSf * cell->bwCfg.dlTotalBw;
696          measCb->ulTotalBw = numUlSf * cell->bwCfg.ulTotalBw;
697
698 #else            
699          measCb->dlTotalBw = meas * cell->bwCfg.dlTotalBw;
700          measCb->ulTotalBw = meas * cell->bwCfg.ulTotalBw;
701 #endif            
702          if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_PER_QCI_UL))
703          {
704             if(measCb->cfmRcvd)
705             {
706                rgSchFillL2MeasCfm(cell, measCb, &measCfm, meas);
707             }
708             else
709             {
710                continue;
711             }
712          }
713          else
714          {
715             rgSchFillL2MeasCfm(cell, measCb, &measCfm, meas);
716          }
717          RgMiLrgSchL2MeasCfm(&(rgSchCb[cell->instIdx].rgSchInit.lmPst),
718                &measCfm);
719          memset(&measCfm, 0, sizeof(LrgSchMeasCfmInfo));
720          
721          /* Delete this measCb from the list */
722          if(measCb->measReq.timePrd > 0)
723          {
724             cmLListDelFrm(&cell->l2mList, &measCb->measLnk);
725             rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&measCb,
726                   sizeof(RgSchL2MeasCb));
727          }
728          else/*do not delete measCb, will use for next measurement*/
729          {
730             measCb->startTime = cell->crntTime;
731             measCb->sfnCycle = 0;
732             measCb->cfmRcvd = FALSE;
733             memset(&measCb->avgPrbQciUl, 0, sizeof(LrgAvgPrbQCICfm));
734             cell->sndL2Meas = FALSE;
735          } 
736          /* ccpu00117052 - MOD - Passing double pointer
737             for proper NULLP assignment*/
738       }
739       else
740       {
741          /* Just update the AVERAGE UL PRB counter here and return
742           * if the caller is CRCIndication() and the UL scheduling happens
743           * as a part of it*/
744 #ifdef RG_ULSCHED_AT_CRC 
745          if(isCalrCrcInd)
746          {
747             if(measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_UL)
748             {
749                rgSchL2CalUlPrbCount(cell);
750             }
751             continue;
752          }
753 #else
754          /* UL PRB counter gets updated as a part of CRC indication 
755           * if the UL scheduling happens there */
756          if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_UL))
757          {
758             rgSchL2CalUlPrbCount(cell);
759          }
760 #endif
761          if((measCb->measReq.measType & LRG_L2MEAS_AVG_PRB_DL))
762          {
763             rgSchL2CalDlPrbCount(cell);
764          }
765          if(measCb->measReq.measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_DL)
766          {
767             sfDiff = RGSCH_CALC_SF_DIFF(cell->crntTime, measCb->startTime);
768
769             if((sfDiff % measCb->measReq.nmbActvUeQciDl.sampPrd) == 0)
770             {
771                if (measCb->measReq.nmbActvUeQciDl.numQci)
772                {
773                   for (idx = 0; idx < measCb->measReq.nmbActvUeQciDl.numQci; 
774                         idx++)
775                   {
776                      qciVal = measCb->measReq.nmbActvUeQciDl.qci[idx];
777                      cell->qciArray[qciVal].dlTotal_UeCount +=
778                         cell->qciArray[qciVal].dlUeCount;
779                   }
780                }
781                else
782                {
783                   for (qciVal = 1; qciVal < LRG_MAX_QCI_PER_REQ; qciVal++)
784                   {
785                      cell->qciArray[qciVal].dlTotal_UeCount +=
786                         cell->qciArray[qciVal].dlUeCount;
787                   }
788                }
789             }
790          }
791          if(measCb->measReq.measType & LRG_L2MEAS_NMB_ACTV_UE_PER_QCI_UL)
792          {
793             sfDiff = RGSCH_CALC_SF_DIFF(cell->crntTime , measCb->startTime);
794             if((sfDiff % measCb->measReq.nmbActvUeQciUl.sampPrd) == 0)
795             {
796                if (measCb->measReq.nmbActvUeQciUl.numQci)
797                {
798                   for (idx = 0; idx < measCb->measReq.nmbActvUeQciUl.numQci; 
799                         idx++)
800                   {
801                      qciVal = measCb->measReq.nmbActvUeQciUl.qci[idx];
802                      cell->qciArray[qciVal].ulTotal_UeCount += 
803                         cell->qciArray[qciVal].ulUeCount;
804                   }
805                }
806                else
807                {
808                   for (qciVal = 1; qciVal < LRG_MAX_QCI_PER_REQ; qciVal++)
809                   {
810                      cell->qciArray[qciVal].ulTotal_UeCount += 
811                         cell->qciArray[qciVal].ulUeCount;
812                   }
813                }
814             }
815          }
816       }
817    }/* end of while */
818    return ROK;
819 } /* rgSCHL2MEas */
820 #endif /* LTE_L2_MEAS */
821 /**********************************************************************
822  
823          End of file
824 **********************************************************************/