[Epic-ID: ODUHIGH-462][Task-ID: ODUHIGH-472] Handling of drx timer in SCH [storing...
[o-du/l2.git] / src / 5gnrsch / sch_drx.c
1
2 /*******************************************************************************
3 ################################################################################
4 #   Copyright (c) [2017-2019] [Radisys]                                        #
5 #                                                                              #
6 #   Licensed under the Apache License, Version 2.0 (the "License");            #
7 #   you may not use this file except in compliance with the License.           #
8 #   You may obtain a copy of the License at                                    #
9 #                                                                              #
10 #       http://www.apache.org/licenses/LICENSE-2.0                             #
11 #                                                                              #
12 #   Unless required by applicable law or agreed to in writing, software        #
13 #   distributed under the License is distributed on an "AS IS" BASIS,          #
14 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
15 #   See the License for the specific language governing permissions and        #
16 #   limitations under the License.                                             #
17 ################################################################################
18  *******************************************************************************/
19 #ifdef NR_DRX
20 #include "common_def.h"
21 #include "tfu.h"
22 #include "lrg.h"
23 #include "tfu.x"
24 #include "lrg.x"
25 #include "du_log.h"
26 #include "du_app_mac_inf.h"
27 #include "mac_sch_interface.h"
28 #include "sch.h"
29 #include "sch_utils.h"
30 #include "sch_drx.h"
31
32 /**
33  * @brief intialize the SchDrxHarqCb structre 
34  *
35  * @details
36  *
37  *     Function :schInitDrxHarqCb 
38  *      
39  *     intialize the SchDrxHarqCb structre 
40  *           
41  *  @param[in] SchDrxHarqCb *hqCb 
42  *  @return  
43  *      -# ROK
44  *      -# RFAILED
45  **/
46
47 void schInitDrxHarqCb(SchDrxHarqCb *hqDrxCb)
48 {
49    memset(hqDrxCb, 0, sizeof(SchDrxHarqCb));
50    hqDrxCb->retxExpDistance  = SCH_DRX_INVALID_DISTANCE;
51    hqDrxCb->retxStrtIndex    = SCH_DRX_INVALID_INDEX;
52    hqDrxCb->rttIndex         = SCH_DRX_INVALID_INDEX;
53    hqDrxCb->retxIndex        = SCH_DRX_INVALID_INDEX;
54 }
55
56 /**
57  * @brief intialize the SchDrxUeCb structre 
58  *
59  * @details
60  *
61  *     Function : schInitDrxUeCb 
62  *      
63  *     intialize the SchDrxUeCb structre 
64  *           
65  *  @param[in]  SchUeCb *ueCb 
66  *  @return  
67  *      -# ROK
68  *      -# RFAILED
69  **/
70
71 void schInitDrxUeCb(SchUeCb *ueCb)
72 {
73    memset(&ueCb->drxUeCb, 0, sizeof(SchDrxUeCb));
74    ueCb->drxUeCb.onDurationStartIndex  = SCH_DRX_INVALID_INDEX;
75    ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
76    ueCb->drxUeCb.inActvExpiryIndex     = SCH_DRX_INVALID_INDEX;
77    ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
78    ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
79    ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE;
80    ueCb->drxUeCb.inActiveTmrExpiryDistance = SCH_DRX_INVALID_DISTANCE;
81    ueCb->drxUeCb.drxDlUeActiveStatus = false; 
82    ueCb->drxUeCb.drxUlUeActiveStatus = false; 
83 }
84
85 /* will uncomment this function in next gerrit */
86 #if 0
87 /**
88  * @brief delete Dl harq drx timers and information 
89  *
90  * @details
91  *
92  *     Function : schDeleteDlHarqDrxTimer
93  *      
94  *     delete Dl harq drx timers and information 
95  *           
96  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
97  *  @return  
98  *      -# ROK
99  *      -# RFAILED
100  **/
101  void schDeleteDlHarqDrxTimer(SchCellCb  *cell, SchDlHqEnt *dlHqEnt)
102  {
103     uint8_t idx, numHqPrcs;
104     uint16_t tmrIdx = 0;
105     SchDlHqProcCb *procs;
106     CmLList  *node = NULLP;
107    
108     numHqPrcs = dlHqEnt->numHqPrcs;
109     for(idx =0; idx<numHqPrcs; idx++)
110     {
111        procs = &dlHqEnt->procs[idx];
112        tmrIdx = procs->dlDrxHarqCb.retxStrtIndex;
113        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
114        if(node)
115        {
116           cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
117           SCH_FREE(node, sizeof(CmLList));
118        }
119
120        tmrIdx = procs->dlDrxHarqCb.rttIndex;
121        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
122        if(node)
123        {
124           cmLListDelFrm(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
125           SCH_FREE(node, sizeof(CmLList));
126        }
127
128        tmrIdx = procs->dlDrxHarqCb.retxIndex;
129        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
130        if(node)
131        {
132           cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
133           SCH_FREE(node, sizeof(CmLList));
134        }
135        schInitDrxHarqCb(&procs->dlDrxHarqCb);
136     }
137  }
138
139 /**
140  * @brief delete UL harq drx timers and information 
141  *
142  * @details
143  *
144  *     Function : schDeleteUlHarqDrxTimer
145  *      
146  *     delete Ul harq drx timers and information 
147  *           
148  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
149  *  @return  
150  *      -# ROK
151  *      -# RFAILED
152  **/
153  void schDeleteUlHarqDrxTimer(SchCellCb  *cell, SchUlHqEnt *ulHqEnt)
154  {
155     uint8_t idx, numHqPrcs;
156     uint16_t tmrIdx = 0;
157     CmLList  *node = NULLP;
158     SchUlHqProcCb *procs;
159
160     numHqPrcs = ulHqEnt->numHqPrcs;
161     for(idx =0; idx<numHqPrcs; idx++)
162     {
163        procs = &ulHqEnt->procs[idx];
164        tmrIdx = procs->ulDrxHarqCb.retxStrtIndex;
165        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
166        if(node)
167        {
168           cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
169           SCH_FREE(node, sizeof(CmLList));
170        }
171
172        tmrIdx = procs->ulDrxHarqCb.rttIndex;
173        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
174        if(node)
175        {
176           cmLListDelFrm(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
177           SCH_FREE(node, sizeof(CmLList));
178        }
179
180        tmrIdx = procs->ulDrxHarqCb.retxIndex;
181        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
182        if(node)
183        {
184           cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
185           SCH_FREE(node, sizeof(CmLList));
186        }
187        schInitDrxHarqCb(&procs->ulDrxHarqCb);
188     }
189  }
190 #endif
191
192 /**
193  * @brief delete UE drx timers and information 
194  *
195  * @details
196  *
197  *     Function : schDeleteUeDrxInfo
198  *      
199  *     delete UE drx timers and information 
200  *           
201  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
202  *  @return  void
203  *
204  **/
205
206 void schDeleteUeDrxInfo(SchCellCb  *cell, SchUeCb *ueCb)
207 {
208    SchDrxUeCb *drxUeCb;
209
210    if(ueCb->ueDrxInfoPres == true)
211    {
212       drxUeCb = &ueCb->drxUeCb;
213       
214       /* delete on duration start timer from ueCb */
215       if(drxUeCb->onDurationStartIndex != SCH_DRX_INVALID_INDEX)
216       {
217          cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationStartIndex].onDurationStartList, drxUeCb->onDurationStartNodeInfo);
218          SCH_FREE(drxUeCb->onDurationStartNodeInfo, sizeof(CmLList));
219       }
220       
221       /* delete on duration expiry timer from ueCb */
222       if(drxUeCb->onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
223       {
224          cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationExpiryIndex].onDurationExpiryList, drxUeCb->onDurationExpiryNodeInfo);
225          SCH_FREE(drxUeCb->onDurationExpiryNodeInfo, sizeof(CmLList));
226       }
227       
228       /* delete inActv Expiry Index timer from ueCb */
229       if(drxUeCb->inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
230       {
231          cmLListDelFrm(&cell->drxCb[drxUeCb->inActvExpiryIndex].inActvTmrExpiryList, drxUeCb->inActvTimerExpiryNodeInfo);
232          SCH_FREE(drxUeCb->inActvTimerExpiryNodeInfo, sizeof(CmLList));
233       }
234       
235       /* delete short cycle expiry timer from ueCb */
236       if(drxUeCb->shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
237       {
238          cmLListDelFrm(&cell->drxCb[drxUeCb->shortCycleExpiryIndex].shortCycleExpiryList, drxUeCb->shortCycleTmrExpiryNodeInfo);
239          SCH_FREE(drxUeCb->shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
240       }
241       /* TODO - will uncomment this function in next gerrit */
242       //schDeleteDlHarqDrxTimer(cell, &ueCb->dlHqEnt);
243       //schDeleteUlHarqDrxTimer(cell, &ueCb->ulHqEnt);
244       schInitDrxUeCb(ueCb);
245    }
246 }
247
248 /**
249  * @brief fill drxUeCb structure with the help of ue cfg/recfg information
250  *
251  * @details
252  *
253  *     Function : schFillDrxUeCb
254  *      
255  *      fill drxUeCb structure with the help of ue cfg/recfg information
256  *           
257  *  @param[in] SchDrxCfg drxCfg ->configuration received from ue cfg/recfg api
258  *             SchDrxUeCb *drxUeCb -> structure that need to be fill
259  *  @return  
260  *      -# ROK
261  *      -# RFAILED
262  **/
263
264 void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb)
265 {
266    if(drxCfg.drxOnDurationTimer.onDurationTimerValInMs) 
267    {
268       SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.milliSeconds, numerology); 
269    }
270    else
271    {
272       SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds, numerology);
273       drxUeCb->onDurationLen = drxUeCb->onDurationLen >> 5;
274    }   
275    SCH_CNVRT_MS_TO_SLOT(drxUeCb->inActvTimerLen, drxCfg.drxInactivityTimer, numerology);
276    SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttDlTimerLen, drxCfg.drxHarqRttTimerDl);
277    SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttUlTimerLen, drxCfg.drxHarqRttTimerUl);
278    drxUeCb->retransDlTimerLen = drxCfg.drxRetransmissionTimerDl;
279    drxUeCb->retransUlTimerLen = drxCfg.drxRetransmissionTimerUl;
280    SCH_CNVRT_MS_TO_SLOT(drxUeCb->longCycleLen, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice, numerology);
281    SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxStartOffset, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetVal, numerology);
282    if(drxCfg.shortDrxPres)
283    {
284       drxUeCb->shortCyclePresent = true;                   
285       SCH_CNVRT_MS_TO_SLOT(drxUeCb->shortCycleLen, drxCfg.shortDrx.drxShortCycle, numerology);   
286       drxUeCb->shortCycleTmrLen = drxUeCb->shortCycleLen*drxCfg.shortDrx.drxShortCycleTimer;    
287    }
288    drxUeCb->longCycleToBeUsed = true;
289    SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxSlotOffset, drxCfg.drxSlotOffset, numerology);  
290    drxUeCb->drxSlotOffset = drxUeCb->drxSlotOffset>>5; 
291 }
292
293 /**
294  * @brief Add new entry into the drx timer list
295  *
296  * @details
297  *
298  *     Function : schAddDrxTimerIntoList 
299  *      
300  *      Add new entry into the drx timer list
301  *           
302  *  @param[in] CmLListCp *drxTimerList -> List in which new entery have to add
303  *             void * ueInfo -> ue information which is need to the added into list
304  *  @return  
305  *      -# ROK
306  *      -# RFAILED
307  **/
308
309 uint8_t schAddDrxTimerIntoList(CmLListCp *drxTimerList,void * nodeInfo, CmLList *drxNodeInfo)
310 {
311    CmLList  *currentNodeInfo = NULLP;
312
313    SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
314    if(!currentNodeInfo)
315    {
316       DU_LOG("\nERROR  --> SCH : schAddDrxTimerIntoList() : Memory allocation failed");
317       return RFAILED;
318    }
319
320    currentNodeInfo->node = (PTR)nodeInfo;
321    
322    cmLListAdd2Tail(drxTimerList, currentNodeInfo);
323    drxNodeInfo = currentNodeInfo;
324    DU_LOG("\nINFO --> SCH : Drx node added into the list");
325    return ROK;
326 }
327
328 /**
329  * @brief This function is used to find the next onduration start timing
330  *
331  * @details
332  *
333  *     Function : findNextOndurationOccurance 
334  *      
335  *      This function is used to find the next onduration start timing
336  *           
337  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
338  *  uint8_t delta
339  *             
340  *  @return  
341  *      -# void
342  **/
343
344 void findNextOndurationOccurance(SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur, uint8_t delta)
345 {
346    uint16_t   tmpDistance, numOfCycles;
347    uint32_t   curTime, cycleLen, nxtDist;
348    SlotTimingInfo  tmpTime;
349    
350    if (ueDrxCb->longCycleToBeUsed == true)
351    {
352       cycleLen = ueDrxCb->longCycleLen;
353    }
354    else
355    {
356       cycleLen = ueDrxCb->shortCycleLen;
357    }
358
359    /* Add delta to current time */
360    ADD_DELTA_TO_TIME(cell->slotInfo, tmpTime, delta, cell->numSlots);
361    
362    /* Convert tmpTime to number of slots */
363    curTime = ((tmpTime.sfn * cell->numSlots) + tmpTime.slot);
364    
365    /* as per 38.321,  if the criterion below is satisfied, then that sfn and
366     * slot are the correct ones for the on-duration timer.
367     * if the Short DRX Cycle is used, and [(SFN × 10) + subframe number] modulo
368     * (drx-ShortCycle) = (drxStartOffset) modulo (drx-ShortCycle); or
369     * if the Long DRX Cycle is used, and [(SFN × 10) + subframe number] modulo
370     * (drx-LongCycle) = drxStartOffset  */
371    if ( curTime <= ueDrxCb->drxStartOffset)
372    {
373       /* offset is the nextOnDur */
374       nxtDist = ((((ueDrxCb->drxStartOffset / cell->numSlots)) & (MAX_SFN - 1)) * cell->numSlots) + (ueDrxCb->drxStartOffset % cell->numSlots);
375    }
376    else
377    {
378       tmpDistance = curTime - ueDrxCb->drxStartOffset;
379       numOfCycles = tmpDistance / cycleLen;
380
381       if (0 == (tmpDistance % cycleLen))
382       {
383          /* Perfect match pick up the current time */
384          nxtDist = ((((curTime / cell->numSlots)) & (MAX_SFN - 1)) * cell->numSlots) + (curTime % cell->numSlots);
385       }
386       else
387       {
388          nxtDist  = ueDrxCb->drxStartOffset + (numOfCycles + 1) * cycleLen;
389       }
390    }
391
392    /* If slot offset is non-zero then Add slot offset to the calculated onDur
393     * distance */
394    if(ueDrxCb->drxSlotOffset)
395    {
396       nxtDist = nxtDist + ueDrxCb->drxSlotOffset;
397    }
398    /*If next On Duration is less than DL DELTA ahead, we will miss it and
399     * hence need to move to the On-Duration after that.*/
400    if((nxtDist - (curTime - delta)) <= SCH_DRX_MAX_DELTA)
401    {
402       nxtDist = nxtDist + cycleLen;
403    }
404    
405    nxtOnDur->sfn = ((nxtDist / cell->numSlots) & (MAX_SFN - 1));
406    nxtOnDur->slot = (nxtDist % cell->numSlots);
407 }
408
409 /**
410  * @brief Add entry into  the on duration list and short cycle list
411  *
412  * @details
413  *
414  *     Function : schDrxUeReCfgTimer 
415  *      
416  *      This function is used to Add entry into  the on duration list and short
417  *      cycle list
418  *           
419  *  @param[in] SchCellCb *cell,   SchUeCb *ueCb
420  *  uint8_t delta
421  *             
422  *  @return void 
423  **/
424
425 void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb)
426 {
427    uint8_t  currentSlotIndx;
428    uint32_t onDurTime, onDurExpSlotTime, currentSlotTime;
429    uint32_t cycleLen;
430    SlotTimingInfo onDurationOccurance;
431
432    if(ueCb->drxUeCb.shortCyclePresent == false)   
433    {
434       /* if short cycle configuration are not recived as a part of UE Recfg then if there is any entry present in short cycle timer list 
435        * remove the entry from the list */ 
436       if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
437       {
438          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex ].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
439          SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
440          ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
441          ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
442       }
443    }
444    /* If there is any entry present in on duration start list then remove the
445     * entry from the list and recaluate the nect onduration cucurance */
446    if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
447    {
448       cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
449       SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
450       ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
451       ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
452    }
453
454    findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, 0);
455    onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
456    
457    /* If Onduration timer of old configuration is already running then next onduration 
458     * starts once it expires*/
459    if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX))
460    {
461        currentSlotTime = cell->slotInfo.sfn * cell->numSlots + cell->slotInfo.slot;
462        currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE;
463        if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex )
464        {
465          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) +\
466          (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
467        }
468        else
469        {
470          
471          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) +\
472          (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
473        }
474        if(onDurTime <= onDurExpSlotTime)
475        {
476           if(ueCb->drxUeCb.longCycleToBeUsed == true)
477              cycleLen = ueCb->drxUeCb.longCycleLen;
478           else
479              cycleLen = ueCb->drxUeCb.shortCycleLen;
480
481           onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen;
482        }
483    }
484    SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
485    ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
486    schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
487 }
488
489 /**
490  * @brief Add entry into  the on duration list 
491  *
492  * @details
493  *
494  *     Function : schAddUeInOndurationList
495  *      
496  *      This function is used to Add entry into  the on duration list 
497  *           
498  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
499  *  uint8_t delta
500  *             
501  *  @return  
502  *      -# void
503  **/
504
505 void schAddUeInOndurationList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
506 {
507    uint32_t onDurTime;
508    SlotTimingInfo onDurationOccurance;
509
510    if(ueCb->ueDrxInfoPres)
511    {
512       findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, delta);
513       onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
514       SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
515       ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
516       schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
517
518    }
519 }
520
521 #endif
522 /**********************************************************************
523   End of file
524  **********************************************************************/