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