[Epic-ID: ODUHIGH-462][Task-ID: ODUHIGH-472] Implementation of drx timer
[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 void schInitDrxHarqCb(SchDrxHarqCb *hqDrxCb)
47 {
48    memset(hqDrxCb, 0, sizeof(SchDrxHarqCb));
49    hqDrxCb->retxExpDistance  = SCH_DRX_INVALID_DISTANCE;
50    hqDrxCb->retxStrtIndex    = SCH_DRX_INVALID_INDEX;
51    hqDrxCb->rttIndex         = SCH_DRX_INVALID_INDEX;
52    hqDrxCb->retxIndex        = SCH_DRX_INVALID_INDEX;
53 }
54
55 /**
56  * @brief intialize the SchDrxUeCb structre 
57  *
58  * @details
59  *
60  *     Function : schInitDrxUeCb 
61  *      
62  *     intialize the SchDrxUeCb structre 
63  *           
64  *  @param[in]  SchUeCb *ueCb 
65  *  @return  
66  *      -# ROK
67  *      -# RFAILED
68  **/
69 void schInitDrxUeCb(SchUeCb *ueCb)
70 {
71    memset(&ueCb->drxUeCb, 0, sizeof(SchDrxUeCb));
72    ueCb->drxUeCb.onDurationStartIndex  = SCH_DRX_INVALID_INDEX;
73    ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
74    ueCb->drxUeCb.inActvExpiryIndex     = SCH_DRX_INVALID_INDEX;
75    ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
76    ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
77    ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE;
78    ueCb->drxUeCb.inActiveTmrExpiryDistance = SCH_DRX_INVALID_DISTANCE;
79    ueCb->drxUeCb.drxDlUeActiveStatus = false; 
80    ueCb->drxUeCb.drxUlUeActiveStatus = false; 
81 }
82 #if 0
83 /* will uncomment this function in next gerrit */
84 /**
85  * @brief delete Dl harq drx timers and information 
86  *
87  * @details
88  *
89  *     Function : schDeleteDlHarqDrxTimer
90  *      
91  *     delete Dl harq drx timers and information 
92  *           
93  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
94  *  @return  
95  *      -# ROK
96  *      -# RFAILED
97  **/
98  void schDeleteDlHarqDrxTimer(SchCellCb  *cell, SchDlHqEnt *dlHqEnt)
99  {
100     uint8_t idx, numHqPrcs;
101     uint16_t tmrIdx = 0;
102     SchDlHqProcCb *procs;
103     CmLList  *node = NULLP;
104    
105     numHqPrcs = dlHqEnt->numHqPrcs;
106     for(idx =0; idx<numHqPrcs; idx++)
107     {
108        procs = &dlHqEnt->procs[idx];
109        tmrIdx = procs->drxHarqCb.retxStrtIndex;
110        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
111        if(node)
112        {
113           cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
114           SCH_FREE(node, sizeof(CmLList));
115        }
116
117        tmrIdx = procs->drxHarqCb.rttIndex;
118        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
119        if(node)
120        {
121           cmLListDelFrm(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
122           SCH_FREE(node, sizeof(CmLList));
123        }
124
125        tmrIdx = procs->drxHarqCb.retxIndex;
126        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
127        if(node)
128        {
129           cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
130           SCH_FREE(node, sizeof(CmLList));
131        }
132        schInitDrxHarqCb(&procs->drxHarqCb);
133     }
134  }
135
136 /**
137  * @brief delete UL harq drx timers and information 
138  *
139  * @details
140  *
141  *     Function : schDeleteUlHarqDrxTimer
142  *      
143  *     delete Ul harq drx timers and information 
144  *           
145  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
146  *  @return  
147  *      -# ROK
148  *      -# RFAILED
149  **/
150  void schDeleteUlHarqDrxTimer(SchCellCb  *cell, SchUlHqEnt *ulHqEnt)
151  {
152     uint8_t idx, numHqPrcs;
153     uint16_t tmrIdx = 0;
154     CmLList  *node = NULLP;
155     SchUlHqProcCb *procs;
156
157     numHqPrcs = ulHqEnt->numHqPrcs;
158     for(idx =0; idx<numHqPrcs; idx++)
159     {
160        procs = &ulHqEnt->procs[idx];
161        tmrIdx = procs->drxHarqCb.retxStrtIndex;
162        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
163        if(node)
164        {
165           cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
166           SCH_FREE(node, sizeof(CmLList));
167        }
168
169        tmrIdx = procs->drxHarqCb.rttIndex;
170        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
171        if(node)
172        {
173           cmLListDelFrm(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
174           SCH_FREE(node, sizeof(CmLList));
175        }
176
177        tmrIdx = procs->drxHarqCb.retxIndex;
178        CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
179        if(node)
180        {
181           cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
182           SCH_FREE(node, sizeof(CmLList));
183        }
184        schInitDrxHarqCb(&procs->drxHarqCb);
185     }
186  }
187 #endif
188 /**
189  * @brief delete UE drx timers and information 
190  *
191  * @details
192  *
193  *     Function : schDeleteUeDrxInfo
194  *      
195  *     delete UE drx timers and information 
196  *           
197  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
198  *  @return  
199  *      -# ROK
200  *      -# RFAILED
201  **/
202 void schDeleteUeDrxInfo(SchCellCb  *cell, SchUeCb *ueCb)
203 {
204    SchDrxUeCb *drxUeCb;
205
206    if(ueCb->ueDrxInfoPres == true)
207    {
208       drxUeCb = &ueCb->drxUeCb;
209       
210       /* delete on duration start timer from ueCb */
211       if(drxUeCb->onDurationStartIndex != SCH_DRX_INVALID_INDEX)
212       {
213          cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationStartIndex].onDurationStartList, drxUeCb->onDurationStartNodeInfo);
214          SCH_FREE(drxUeCb->onDurationStartNodeInfo, sizeof(CmLList));
215       }
216       
217       /* delete on duration expiry timer from ueCb */
218       if(drxUeCb->onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
219       {
220          cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationExpiryIndex].onDurationExpiryList, drxUeCb->onDurationExpiryNodeInfo);
221          SCH_FREE(drxUeCb->onDurationExpiryNodeInfo, sizeof(CmLList));
222       }
223       
224       /* delete inActv Expiry Index timer from ueCb */
225       if(drxUeCb->inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
226       {
227          cmLListDelFrm(&cell->drxCb[drxUeCb->inActvExpiryIndex].inActvTmrExpiryList, drxUeCb->inActvTimerExpiryNodeInfo);
228          SCH_FREE(drxUeCb->inActvTimerExpiryNodeInfo, sizeof(CmLList));
229       }
230       
231       /* delete short cycle expiry timer from ueCb */
232       if(drxUeCb->shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
233       {
234          cmLListDelFrm(&cell->drxCb[drxUeCb->shortCycleExpiryIndex].shortCycleExpiryList, drxUeCb->shortCycleTmrExpiryNodeInfo);
235          SCH_FREE(drxUeCb->shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
236       }
237       /* TODO - will uncomment this function in next gerrit */
238       //schDeleteDlHarqDrxTimer(cell, &ueCb->dlHqEnt);
239       //schDeleteUlHarqDrxTimer(cell, &ueCb->ulHqEnt);
240       schInitDrxUeCb(ueCb);
241    }
242 }
243
244 /**
245  * @brief fill drxUeCb structure with the help of ue cfg/recfg information
246  *
247  * @details
248  *
249  *     Function : schFillDrxUeCb
250  *      
251  *      fill drxUeCb structure with the help of ue cfg/recfg information
252  *           
253  *  @param[in] SchDrxCfg drxCfg ->configuration received from ue cfg/recfg api
254  *             SchDrxUeCb *drxUeCb -> structure that need to be fill
255  *  @return  
256  *      -# ROK
257  *      -# RFAILED
258  **/
259 void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb)
260 {
261    if(drxCfg.drxOnDurationTimer.onDurationTimerValInMs) 
262    {
263       SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.milliSeconds, numerology); 
264    }
265    else
266    {
267       SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds, numerology);
268       drxUeCb->onDurationLen = drxUeCb->onDurationLen >> 5;
269    }   
270    SCH_CNVRT_MS_TO_SLOT(drxUeCb->inActvTimerLen, drxCfg.drxInactivityTimer, numerology);
271    SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttDlTimerLen, drxCfg.drxHarqRttTimerDl);
272    SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttUlTimerLen, drxCfg.drxHarqRttTimerUl);
273    SCH_CNVRT_MS_TO_SLOT(drxUeCb->retransDlTimerLen, drxCfg.drxRetransmissionTimerDl, numerology);
274    SCH_CNVRT_MS_TO_SLOT(drxUeCb->retransUlTimerLen, drxCfg.drxRetransmissionTimerUl, numerology);
275    SCH_CNVRT_MS_TO_SLOT(drxUeCb->longCycleLen, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice, numerology);
276    drxUeCb->drxStartOffset =  drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetVal;
277    if(drxCfg.shortDrxPres)
278    {
279       drxUeCb->shortCyclePresent = true;                   
280       SCH_CNVRT_MS_TO_SLOT(drxUeCb->shortCycleLen, drxCfg.shortDrx.drxShortCycle, numerology);   
281       drxUeCb->shortCycleTmrLen = drxCfg.shortDrx.drxShortCycleTimer;   
282    }
283    else
284       drxUeCb->longCycleToBeUsed = true;
285    SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxSlotOffset, drxCfg.drxSlotOffset, numerology);  
286    drxUeCb->drxSlotOffset = drxUeCb->drxSlotOffset>>5; 
287 }
288
289 /**
290  * @brief Add new entry into the drx timer list
291  *
292  * @details
293  *
294  *     Function : schAddDrxTimerIntoList 
295  *      
296  *      Add new entry into the drx timer list
297  *           
298  *  @param[in] CmLListCp *drxTimerList -> List in which new entery have to add
299  *             void * ueInfo -> ue information which is need to the added into list
300  *  @return  
301  *      -# ROK
302  *      -# RFAILED
303  **/
304 uint8_t schAddDrxTimerIntoList(CmLListCp *drxTimerList,void * nodeInfo, CmLList *drxNodeInfo)
305 {
306    CmLList  *currentNodeInfo = NULLP;
307
308    SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
309    if(!currentNodeInfo)
310    {
311       DU_LOG("\nERROR  --> SCH : schAddDrxTimerIntoList() : Memory allocation failed");
312       return RFAILED;
313    }
314
315    currentNodeInfo->node = (PTR)nodeInfo;
316    
317    cmLListAdd2Tail(drxTimerList, currentNodeInfo);
318    drxNodeInfo = currentNodeInfo;
319    return ROK;
320 }
321
322 /**
323  * @brief This function is used to find the next onduration start timing
324  *
325  * @details
326  *
327  *     Function : findNextOndurationOccurance 
328  *      
329  *      This function is used to find the next onduration start timing
330  *           
331  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
332  *  uint8_t delta
333  *             
334  *  @return  
335  *      -# void
336  **/
337 void findNextOndurationOccurance(SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur, uint8_t delta)
338 {
339    uint16_t   resultX, reusltY, idx;
340    uint32_t   curTime, cycleLen, nxtDist;
341    SlotTimingInfo  tmpTime;
342
343    if (ueDrxCb->longCycleToBeUsed == true)
344    {
345       cycleLen = ueDrxCb->longCycleLen;
346    }
347    else
348    {
349       cycleLen = ueDrxCb->shortCycleLen;
350    }
351
352    /* Add delta to current time */
353    ADD_DELTA_TO_TIME(cell->slotInfo, tmpTime, delta);
354    
355    /* Convert tmpTime to number of slots */
356    curTime = ((tmpTime.sfn * MAX_SLOTS) + tmpTime.slot);
357    
358    /* as per 38.321,  if the criterion below is satisfied, then that sfn and
359     * slot are the correct ones for the on-duration timer.
360     * if the Short DRX Cycle is used, and [(SFN Ã— 10) + subframe number] modulo
361     * (drx-ShortCycle) = (drxStartOffset) modulo (drx-ShortCycle); or
362     * if the Long DRX Cycle is used, and [(SFN Ã— 10) + subframe number] modulo
363     * (drx-LongCycle) = drxStartOffset  */
364    for(idx =1; idx<MAX_DRX_SIZE; idx++)
365    {
366       resultX = (tmpTime.sfn *10+tmpTime.slot) % cycleLen;
367       if (TRUE != ueDrxCb->shortCyclePresent)
368          reusltY = ueDrxCb->drxStartOffset;
369       else
370          reusltY = ueDrxCb->drxStartOffset % cycleLen;
371       if(resultX == reusltY)
372       {
373          memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo));
374          nxtDist = ((nxtOnDur->sfn * MAX_SLOTS) + nxtOnDur->slot);
375          break;
376       }
377       else
378       {
379          ADD_DELTA_TO_TIME(tmpTime, tmpTime, 1);
380       }
381    }
382
383    /* If slot offset is non-zero then Add slot offset to the calculated onDur
384     * distance */
385    if(ueDrxCb->drxSlotOffset)
386    {
387       nxtDist = nxtDist + ueDrxCb->drxSlotOffset;
388       ADD_DELTA_TO_TIME(tmpTime, tmpTime, ueDrxCb->drxSlotOffset);
389       memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo));
390    }
391    /*If next On Duration is less than DL DELTA ahead, we will miss it and
392     * hence need to move to the On-Duration after that.*/
393    if((nxtDist - (curTime - delta)) <= SCH_DRX_MAX_DELTA)
394    {
395       ADD_DELTA_TO_TIME(tmpTime, tmpTime, cycleLen);
396       memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo));
397    }
398 }
399
400 /**
401  * @brief Add entry into  the on duration list and short cycle list
402  *
403  * @details
404  *
405  *     Function : schDrxUeReCfgTimer 
406  *      
407  *      This function is used to Add entry into  the on duration list and short
408  *      cycle list
409  *           
410  *  @param[in] SchCellCb *cell,   SchUeCb *ueCb
411  *  uint8_t delta
412  *             
413  *  @return  
414  **/
415 void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb)
416 {
417    uint8_t  onDurIndx, currentSlotIndx;
418    uint32_t onDurTime, onDurExpSlotTime, currentSlotTime;
419    uint32_t cycleLen;
420    SlotTimingInfo onDurationOccurance;
421
422    if(ueCb->drxUeCb.shortCyclePresent == false)   
423    {
424       /* 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 
425        * remove the entry from the list */ 
426       if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
427       {
428          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex ].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
429          SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
430          ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
431          ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
432       }
433    }
434    /* If there is any entry present in on duration start list then remove the
435     * entry from the list and recaluate the nect onduration cucurance */
436    if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
437    {
438       cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
439       SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
440       ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
441       ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
442    }
443
444    findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, 0);
445    onDurTime = onDurationOccurance.sfn*MAX_SLOTS+onDurationOccurance.slot;
446    onDurIndx = onDurTime%MAX_DRX_SIZE;
447    /* If Onduration timer of old configuration is already running then next onduration 
448     * starts once it expires*/
449    if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex == SCH_DRX_INVALID_INDEX))
450    {
451        currentSlotTime = cell->slotInfo.sfn * MAX_SLOTS + cell->slotInfo.slot;
452        currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE;
453        if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex )
454        {
455          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) + (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
456        }
457        else
458        {
459          
460          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) + (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
461        }
462        if(onDurTime <= onDurExpSlotTime)
463        {
464           if(ueCb->drxUeCb.longCycleToBeUsed == true)
465              cycleLen = ueCb->drxUeCb.longCycleLen;
466           else
467              cycleLen = ueCb->drxUeCb.shortCycleLen;
468
469           onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen;
470        }
471    }
472    onDurIndx = onDurTime%MAX_DRX_SIZE;
473    ueCb->drxUeCb.onDurationStartIndex = onDurIndx;
474    ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, MAX_SLOTS)/MAX_DRX_SIZE;
475    schAddDrxTimerIntoList(&cell->drxCb[onDurIndx].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
476    if((TRUE == ueCb->drxUeCb.shortCyclePresent) &&(ueCb->drxUeCb.longCycleToBeUsed == false))
477    {
478       /* Starting Short Cycle Timer */
479       ueCb->drxUeCb.shortCycleDistance = (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen) / MAX_DRX_SIZE;
480       ueCb->drxUeCb.shortCycleExpiryIndex = (onDurTime + (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen)) % MAX_DRX_SIZE;
481       schAddDrxTimerIntoList(&cell->drxCb[ ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
482       DU_LOG("\nPBORLA ShortCycleE Added %d",ueCb->drxUeCb.shortCycleExpiryIndex);
483    }
484 }
485 /**
486  * @brief Add entry into  the on duration list and short cycle list
487  *
488  * @details
489  *
490  *     Function : schAddUeInOndurationAndShortCycleList
491  *      
492  *      This function is used to Add entry into  the on duration list and short
493  *      cycle list
494  *           
495  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
496  *  uint8_t delta
497  *             
498  *  @return  
499  *      -# void
500  **/
501 void schAddUeInOndurationAndShortCycleList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
502 {
503    uint8_t  onDurIndx;
504    uint32_t onDurTime;
505    SlotTimingInfo onDurationOccurance;
506
507    if(ueCb->ueDrxInfoPres)
508    {
509       findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, delta);
510       onDurTime = onDurationOccurance.sfn*MAX_SLOTS+onDurationOccurance.slot;
511       onDurIndx = onDurTime%MAX_DRX_SIZE;
512       ueCb->drxUeCb.onDurationStartIndex = onDurIndx;
513       ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, MAX_SLOTS)/MAX_DRX_SIZE;
514       schAddDrxTimerIntoList(&cell->drxCb[onDurIndx].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
515
516       if((TRUE == ueCb->drxUeCb.shortCyclePresent) &&(ueCb->drxUeCb.longCycleToBeUsed == false))
517       {
518          /* Starting Short Cycle Timer */
519          ueCb->drxUeCb.shortCycleDistance = (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen) / MAX_DRX_SIZE;
520          ueCb->drxUeCb.shortCycleExpiryIndex = (onDurTime + (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen)) % MAX_DRX_SIZE;
521          schAddDrxTimerIntoList(&cell->drxCb[ ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
522          DU_LOG("\nPBORLA ShortCycleE Added %d",ueCb->drxUeCb.shortCycleExpiryIndex);
523       }
524    }
525 }
526 /**
527  * @brief Handling of On duration drx start timer
528  *
529  * @details
530  *
531  *     Function : schHdlDrxOnDurStrtTimerForUlandDlDirection
532  *
533  *      Handling of On duration drx start timer
534  *
535  *  @param[in] SchCellCb  *cell
536  *  @return
537  *      -# ROK
538  *      -# RFAILED
539  **/
540 void schHdlDrxOnDurStrtTimerForUlandDlDirection(SchCellCb  *cell, uint16_t currListIndx, bool isDlDirection)
541 {
542    uint16_t onDurationExpiry=0;
543    CmLList  *drxCurrNode = NULLP;
544    SchUeCb *ueCb = NULLP;
545
546    drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
547    if(drxCurrNode)
548    {
549       /* Handling of dl On duration drx start list */
550       while(drxCurrNode)
551       {
552          ueCb = (SchUeCb*)drxCurrNode->node;
553          ueCb->drxUeCb.onDurationStartDistance--;
554          if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
555          {
556             continue;
557          }
558          else
559          {
560             if(isDlDirection == true)
561                ueCb->drxUeCb.drxDlUeActiveStatus = true;
562             else
563                ueCb->drxUeCb.drxUlUeActiveStatus = true;
564
565             DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d",  ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
566                
567             /* If there is any entery present in onDurationExpiry list remove
568              * the entery from the list and recalculate the
569              * onDurationExpiry time and add it to list */
570             if(ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX) 
571             {
572                cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
573                SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
574                ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
575             }
576
577             /* onDurationExpiry  = (current slot + onduration length) % MAX_DRX_SIZE*/
578             onDurationExpiry = (currListIndx + ueCb->drxUeCb.onDurationLen)%MAX_DRX_SIZE;
579             ueCb->drxUeCb.onDurationExpiryDistance =  (ueCb->drxUeCb.onDurationLen)/MAX_DRX_SIZE;
580             schAddDrxTimerIntoList(&cell->drxCb[onDurationExpiry].onDurationExpiryList, ueCb, ueCb->drxUeCb.onDurationExpiryNodeInfo);
581             ueCb->drxUeCb.onDurationExpiryIndex = onDurationExpiry;
582             
583             /* if there is any entry present in onduration list remove the entry from the list  */
584             DU_LOG("\nPBORLA ONDURATION START HIT %d %d startIndx %d [%d %d]",\
585                   currListIndx, ueCb->drxUeCb.onDurationStartDistance,ueCb->drxUeCb.onDurationStartIndex, cell->slotInfo.sfn,cell->slotInfo.slot);
586             cmLListDelFrm(&cell->drxCb[currListIndx].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
587             SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
588             ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
589             /* if there long cycle length is used as the cycle length for  onduration calculation then based on that calculating next onduration occurance 
590              * other wise next onduration is calcuated based on short cycle
591              * timer */
592             if(ueCb->drxUeCb.longCycleToBeUsed)
593             {
594                schAddUeInOndurationAndShortCycleList(cell, ueCb, 0);
595             }
596          }
597          drxCurrNode = drxCurrNode->next;
598       }
599    }
600 }
601 /**
602  * @brief Handling of On duration drx start timer
603  *
604  * @details
605  *
606  *     Function : schHdlDrxOnDurStrtTimer
607  *
608  *      Handling of On duration drx start timer
609  *
610  *  @param[in] SchCellCb  *cell
611  *  @return
612  *      -# ROK
613  *      -# RFAILED
614  **/
615 void schHdlDrxOnDurStrtTimer(SchCellCb  *cell)
616 {
617    uint16_t dlIndx = 0, ulIndx=0;
618    SlotTimingInfo dlSlotInfo, ulSlotInfo;
619
620    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo,  PHY_DELTA_DL + SCHED_DELTA);
621    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo,  PHY_DELTA_UL + SCHED_DELTA);
622    
623    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
624    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
625    schHdlDrxOnDurStrtTimerForUlandDlDirection(cell, dlIndx, true);
626    schHdlDrxOnDurStrtTimerForUlandDlDirection(cell, ulIndx, false);
627 }
628 /**
629  * @brief Handling of short cycle drx start timer
630  *
631  * @details
632  *
633  *     Function : schHdlDrxStartShortCycleTimer 
634  *
635  *      Handling of short cycle drx start timer
636  *
637  *  @param[in] SchCellCb  *cell
638  *  @return
639  *      -# ROK
640  *      -# RFAILED
641  **/
642  void schHdlDrxStartShortCycleTimer(SchCellCb  *cell, SchUeCb *ueCb)
643  {
644    ueCb->drxUeCb.longCycleToBeUsed = false; 
645    schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
646  }
647 /**
648  * @brief Handling of the  DRX inactv timers start
649  *
650  * @details
651  *
652  *     Function : schHdlDrxInActvStrtTmr  
653  *
654  *      Handling of DRX in active timers start
655  *
656  *  @param[in] SchCellCb  *cell
657  *  @return
658  *      -# ROK
659  *      -# RFAILED
660  **/
661  void schHdlDrxInActvStrtTmr(SchCellCb  *cell,  SchUeCb *ueCb, uint8_t delta)
662  {
663     uint16_t slotIndx = 0;
664     SlotTimingInfo tmpSlotInfo;
665     
666     if(ueCb->drxUeCb.inActvTimerLen == 0)
667     {
668        return;
669     }
670     ADD_DELTA_TO_TIME(cell->slotInfo, tmpSlotInfo,  delta);
671     slotIndx = (tmpSlotInfo.sfn*MAX_SLOTS+tmpSlotInfo.slot)%MAX_DRX_SIZE;
672
673     DU_LOG("\nPBORLA IN ACTV START HIT %d %d", cell->slotInfo.sfn, cell->slotInfo.slot); 
674     /* if there is nay old entry present in the list remove the entry*/
675     if(ueCb->drxUeCb.inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
676     {
677        cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
678        SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
679        ueCb->drxUeCb.inActvExpiryIndex= SCH_DRX_INVALID_INDEX;
680        ueCb->drxUeCb.inActiveTmrExpiryDistance= SCH_DRX_INVALID_DISTANCE;
681     }
682     /* Adding the new entry in in activity timer list */
683     ueCb->drxUeCb.inActvExpiryIndex = (slotIndx + ueCb->drxUeCb.inActvTimerLen) % MAX_DRX_SIZE;
684     ueCb->drxUeCb.inActiveTmrExpiryDistance = (ueCb->drxUeCb.inActvTimerLen) / MAX_DRX_SIZE;
685     schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
686
687     /* Set the UE active for UL And Dl transfer */
688     ueCb->drxUeCb.drxDlUeActiveStatus = true;
689     ueCb->drxUeCb.drxUlUeActiveStatus = true;
690     DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d",  ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
691
692  }
693 /**
694  * @brief Handling of the  DRX timers start
695  *
696  * @details
697  *
698  *     Function : schHandleStartDrxTimer
699  *
700  *      Handling of DRX timers start
701  *
702  *  @param[in] SchCellCb  *cell
703  *  @return
704  *      -# ROK
705  *      -# RFAILED
706  **/
707 void schHandleStartDrxTimer(SchCellCb  *cell)
708 {
709    /* Handling the onduration start timea*/
710    schHdlDrxOnDurStrtTimer(cell);
711 }
712
713 /**
714  * @brief Handling of the expiry ShortCycle DRX timers
715  *
716  * @details
717  *
718  *     Function : schHdlDrxShortCycleExpiryTimerForUlandDlDirection 
719  *
720  *      Handling of expiry ShortCycle 
721  *
722  *  @param[in] SchCellCb  *cell
723  *  @return
724  *      -# ROK
725  *      -# RFAILED
726  **/
727 void schHdlDrxShortCycleExpiryTimerForUlandDlDirection(SchCellCb  *cell, uint16_t currListIndx, bool isDlDirection)
728 {
729    CmLList  *drxCurrNode = NULLP;
730    SchUeCb *ueCb = NULLP;
731    SchUeCb *tempUeCb = NULLP;
732
733    drxCurrNode = cell->drxCb[currListIndx].shortCycleExpiryList.first;
734    if(drxCurrNode)
735    {
736       /* Handling of dl On duration drx start list */
737       while(drxCurrNode)
738       {
739          ueCb = (SchUeCb*)drxCurrNode->node;
740          if(ueCb->ueDrxInfoPres)
741          {
742             if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
743                ueCb->drxUeCb.shortCycleDistance--;
744
745             if(ueCb->drxUeCb.shortCycleDistance== SCH_DRX_INVALID_DISTANCE)
746             {
747                DU_LOG("\nPBORLA ShortCycleE EXP HIT %d",currListIndx);
748                ueCb->drxUeCb.longCycleToBeUsed = true;
749                /* Remove Short Cycle timer from the list */
750                cmLListDelFrm(&cell->drxCb[currListIndx].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
751                SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
752                ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
753                
754                /* calculating the next duration event 
755                If another entry is found in the On duration list, it must first be removed 
756                before the next On duration occurrences may be calculated  */
757                if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
758                {
759                   cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
760                   SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
761                   tempUeCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
762                   tempUeCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
763                }
764                if(isDlDirection == true)
765                   schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
766                else
767                   schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
768
769             }
770             else
771                continue;
772          }
773          drxCurrNode = drxCurrNode->next;
774       }
775    }
776 }
777
778
779 /**
780  * @brief Handling of the expiry ShortCycle DRX timers
781  *
782  * @details
783  *
784  *     Function :schHdlDrxShortCycleExpiryTimer 
785  *
786  *      Handling of expiry ShortCycle 
787  *
788  *  @param[in] SchCellCb  *cell
789  *  @return
790  *      -# ROK
791  *      -# RFAILED
792  **/
793 void schHdlDrxShortCycleExpiryTimer(SchCellCb  *cell)
794 {
795    uint16_t dlIndx = 0, ulIndx= 0;
796    SlotTimingInfo dlSlotInfo, ulSlotInfo;
797
798    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
799    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
800    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
801    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
802    
803    schHdlDrxShortCycleExpiryTimerForUlandDlDirection(cell, dlIndx, true);
804    schHdlDrxShortCycleExpiryTimerForUlandDlDirection(cell, ulIndx, false);
805 }
806
807 /**
808  * @brief Handling of the expiry onduration DRX timers for specific direction
809  *
810  * @details
811  *
812  *     Function :schHdlDrxOnDurExpiryTimerForUlandDlDirection 
813  *
814  *      Handling of expiry onduration DRX timers
815  *
816  *  @param[in] SchCellCb  *cell
817  *  @return
818  *      -# ROK
819  *      -# RFAILED
820  **/
821 void schHdlDrxOnDurExpiryTimerForUlandDlDirection(SchCellCb  *cell, uint16_t currListIndx, bool isDlDirection)
822 {
823    CmLList  *drxCurrNode;
824    SchUeCb *ueCb = NULLP;
825
826    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
827    if(drxCurrNode)
828    {
829       /* Handling of dl On duration drx start list */
830       while(drxCurrNode)
831       {
832          ueCb = (SchUeCb*)drxCurrNode->node;
833          if(ueCb->ueDrxInfoPres)
834          {
835             ueCb->drxUeCb.onDurationExpiryDistance--;
836
837             if(ueCb->drxUeCb.onDurationExpiryDistance== SCH_DRX_INVALID_DISTANCE)
838             {
839
840                DU_LOG("\nPBORLA ONDURATION EXP HIT %d[%d:%d]",currListIndx, cell->slotInfo.sfn, cell->slotInfo.slot);
841
842                /* delete on duration expiry timer from ueCb */
843                if(drxCurrNode->node)
844                {
845                   cmLListDelFrm(&cell->drxCb[currListIndx].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
846                   SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
847                   ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
848                }
849                if(isDlDirection == true)
850                   ueCb->drxUeCb.drxDlUeActiveStatus = false;
851                else
852                   ueCb->drxUeCb.drxUlUeActiveStatus = false;
853                DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d",  ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
854             }
855             else
856                continue;
857          }
858          drxCurrNode = drxCurrNode->next;
859       }
860    }
861 }
862
863
864 /**
865  * @brief Handling of the expiry onduration DRX timers
866  *
867  * @details
868  *
869  *     Function : schHdlDrxOnDurExpiryTimer 
870  *
871  *      Handling of expiry onduration DRX timers
872  *
873  *  @param[in] SchCellCb  *cell
874  *  @return
875  *      -# ROK
876  *      -# RFAILED
877  **/
878 void schHdlDrxOnDurExpiryTimer(SchCellCb  *cell)
879 {
880    uint16_t dlIndx = 0, ulIndx = 0;
881    SlotTimingInfo dlSlotInfo, ulSlotInfo;
882
883    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
884    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
885    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
886    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
887    
888    schHdlDrxOnDurExpiryTimerForUlandDlDirection(cell, dlIndx, true);
889    schHdlDrxOnDurExpiryTimerForUlandDlDirection(cell, ulIndx, false);
890 }
891 /**
892  * @brief Handling of the expiry in active DRX timers in Dl and Ul direction
893  *
894  * @details
895  *
896  *     Function : schHdlDrxInActvExpiryTimerForUlandDlDirection
897  *
898  *      Handling of expiry in active  DRX timers in DLand Ul  direction
899  *
900  *  @param[in] SchCellCb  *cell, uint16_t dlIndx
901  *  @return
902  *      -# ROK
903  *      -# RFAILED
904  **/
905 void schHdlDrxInActvExpiryTimerForUlandDlDirection(SchCellCb  *cell, uint16_t listIndx, bool isDlDirection)
906 {
907    CmLList  *drxNode;
908    SchUeCb *ueCb = NULLP;
909
910    drxNode = cell->drxCb[listIndx].inActvTmrExpiryList.first;
911    if(drxNode)
912    {
913       /* Handling of dl On duration drx start list */
914       while(drxNode)
915       {
916          ueCb = (SchUeCb*)drxNode->node;
917          ueCb->drxUeCb.inActiveTmrExpiryDistance--;
918
919          if(ueCb->drxUeCb.onDurationExpiryDistance== SCH_DRX_INVALID_DISTANCE)
920          {
921             DU_LOG("\nPBORLA IN ACTV EXP HIT %d[%d:%d]",listIndx, cell->slotInfo.sfn, cell->slotInfo.slot);
922             /*Delete the current entry from list */
923             if(drxNode->node)
924             {
925                cmLListDelFrm(&cell->drxCb[listIndx].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
926                SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
927                ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
928             }
929
930             /* If short cycle is configured then start the short cycle timer */
931             if(ueCb->drxUeCb.shortCyclePresent)
932             {
933                schHdlDrxStartShortCycleTimer(cell, ueCb);
934             }
935             else
936             {
937                ueCb->drxUeCb.longCycleToBeUsed = true;
938             }
939             /* Set the drx ue status as inactive once the in active timer gets
940              * expire */
941             if(isDlDirection == true)
942                ueCb->drxUeCb.drxDlUeActiveStatus = false;
943             else
944                ueCb->drxUeCb.drxUlUeActiveStatus = false;
945             DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d",  ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
946
947          }
948          else
949             continue;
950          drxNode = drxNode->next;
951       }
952    }
953
954 }
955 /**
956  * @brief Handling of the expiry in active DRX timers
957  *
958  * @details
959  *
960  *     Function :schHdlDrxInActvExpiryTimer 
961  *
962  *      Handling of expiry in active  DRX timers
963  *
964  *  @param[in] SchCellCb  *cell
965  *  @return
966  *      -# ROK
967  *      -# RFAILED
968  **/
969 void schHdlDrxInActvExpiryTimer(SchCellCb  *cell)
970 {
971    uint16_t dlIndx = 0, ulIndx = 0;
972    SlotTimingInfo dlSlotInfo, ulSlotInfo;
973
974    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
975    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
976    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
977    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
978    
979    schHdlDrxInActvExpiryTimerForUlandDlDirection(cell, dlIndx, true);
980    schHdlDrxInActvExpiryTimerForUlandDlDirection(cell, ulIndx, false);
981 }/**
982  * @brief Handling of the expiry  DRX timers
983  *
984  * @details
985  *
986  *     Function : schHandleExpiryDrxTimer
987  *
988  *      Handling of expiry  DRX timers
989  *
990  *  @param[in] SchCellCb  *cell
991  *  @return
992  *      -# ROK
993  *      -# RFAILED
994  **/
995 void schHandleExpiryDrxTimer(SchCellCb  *cell)
996 {
997    /* Handling the onduration start timer */
998    schHdlDrxShortCycleExpiryTimer(cell);
999    schHdlDrxOnDurExpiryTimer(cell);
1000    schHdlDrxInActvExpiryTimer(cell);
1001 }
1002
1003
1004 #endif
1005 /**********************************************************************
1006   End of file
1007  **********************************************************************/