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