02e6f10504516628e4d9ae0a6199be374996b965
[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 = 0; 
82    ueCb->drxUeCb.drxUlUeActiveStatus = 0; 
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
455    findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, 0);
456    onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
457    
458    /* If Onduration timer of old configuration is already running then next onduration 
459     * starts once it expires*/
460    if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX))
461    {
462        currentSlotTime = cell->slotInfo.sfn * cell->numSlots + cell->slotInfo.slot;
463        currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE;
464        if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex )
465        {
466          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) +\
467          (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
468        }
469        else
470        {
471          
472          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) +\
473          (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
474        }
475        if(onDurTime <= onDurExpSlotTime)
476        {
477           if(ueCb->drxUeCb.longCycleToBeUsed == true)
478              cycleLen = ueCb->drxUeCb.longCycleLen;
479           else
480              cycleLen = ueCb->drxUeCb.shortCycleLen;
481
482           onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen;
483        }
484    }
485    SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
486    ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
487    schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
488 }
489
490 /**
491  * @brief Add entry into  the on duration list 
492  *
493  * @details
494  *
495  *     Function : schAddUeInOndurationList
496  *      
497  *      This function is used to Add entry into  the on duration list 
498  *           
499  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
500  *  uint8_t delta
501  *             
502  *  @return  
503  *      -# void
504  **/
505
506 void schAddUeInOndurationList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
507 {
508    uint32_t onDurTime;
509    SlotTimingInfo onDurationOccurance;
510
511    if(ueCb->ueDrxInfoPres)
512    {
513       findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, delta);
514       onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
515       SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
516       ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
517       schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
518
519    }
520 }
521
522 /**
523  * @brief Handling of On duration drx start timer
524  *
525  * @details
526  *
527  *     Function : schHdlDrxOnDurStrtTimerForDlDirection
528  *
529  *      Handling of On duration drx start timer
530  *
531  *  @param[in] SchCellCb  *cell
532  *  @return
533  *      -# ROK
534  *      -# RFAILED
535  **/
536
537 void schHdlDrxOnDurStrtTimerForDlDirection(SchCellCb  *cell, uint16_t currListIndx)
538 {
539    uint16_t onDurationExpiry=0;
540    CmLList  *drxCurrNode = NULLP;
541    SchUeCb *ueCb = NULLP;
542
543    drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
544    if(drxCurrNode)
545    {
546       /* Handling of dl On duration drx start list */
547       while(drxCurrNode)
548       {
549          ueCb = (SchUeCb*)drxCurrNode->node;
550          drxCurrNode = drxCurrNode->next;
551          
552          ueCb->drxUeCb.onDurationStartDistance--;
553          
554          if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
555          {
556             continue;
557          }
558          else
559          {
560             ueCb->drxUeCb.drxDlUeActiveStatus |= UE_ACTIVE_FOR_ONDURATION;
561             
562             /* If there is any entery present in onDurationExpiry list remove
563              * the entery from the list and recalculate the
564              * onDurationExpiry time and add it to list */
565             if(ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
566             {
567                cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
568                SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
569                ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
570                ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE; 
571             }
572
573             /* onDurationExpiry  = (current slot + onduration length) % MAX_DRX_SIZE*/
574             onDurationExpiry = (currListIndx + ueCb->drxUeCb.onDurationLen)%MAX_DRX_SIZE;
575             ueCb->drxUeCb.onDurationExpiryDistance =  (ueCb->drxUeCb.onDurationLen)/MAX_DRX_SIZE;
576             schAddDrxTimerIntoList(&cell->drxCb[onDurationExpiry].onDurationExpiryList, ueCb, ueCb->drxUeCb.onDurationExpiryNodeInfo);
577             ueCb->drxUeCb.onDurationExpiryIndex = onDurationExpiry;
578
579          }
580       }
581    }
582 }
583
584 /**
585  * @brief Handling of On duration drx start timer
586  *
587  * @details
588  *
589  *     Function : schHdlDrxOnDurStrtTimerForUlDirection
590  *
591  *      Handling of On duration drx start timer
592  *
593  *  @param[in] SchCellCb  *cell
594  *  @return
595  *      -# ROK
596  *      -# RFAILED
597  **/
598
599 void schHdlDrxOnDurStrtTimerForUlDirection(SchCellCb  *cell, uint16_t currListIndx)
600 {
601    uint16_t onDurTime=0;
602    CmLList  *drxCurrNode = NULLP;
603    SchUeCb *ueCb = NULLP;
604
605    drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
606    if(drxCurrNode)
607    {
608       /* Handling of dl On duration drx start list */
609       while(drxCurrNode)
610       {
611          ueCb = (SchUeCb*)drxCurrNode->node;
612          drxCurrNode = drxCurrNode->next;
613          
614          if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
615          {
616             continue;
617          }
618          ueCb->drxUeCb.drxUlUeActiveStatus |= UE_ACTIVE_FOR_ONDURATION;
619
620
621          /* if there short cycle length is used as the cycle length for onduration calculation then based on the short cycle else long cycle is used for calculating next onduration */
622          cmLListDelFrm(&cell->drxCb[currListIndx].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
623          SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
624          ueCb->drxUeCb.onDurationStartIndex= SCH_DRX_INVALID_INDEX; 
625
626          if(ueCb->drxUeCb.longCycleToBeUsed)
627          {
628             onDurTime = currListIndx +  ueCb->drxUeCb.longCycleLen;
629          }
630          else
631          {
632             onDurTime = currListIndx +  ueCb->drxUeCb.shortCycleLen;
633          }
634          SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
635          ueCb->drxUeCb.onDurationStartDistance = ueCb->drxUeCb.longCycleLen/MAX_DRX_SIZE;
636          schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
637       }
638    }
639 }
640
641 /**
642  * @brief Handling of On duration drx start timer
643  *
644  * @details
645  *
646  *     Function : schHdlDrxOnDurStrtTimer
647  *
648  *      Handling of On duration drx start timer
649  *
650  *  @param[in] SchCellCb  *cell
651  *  @return
652  *      -# ROK
653  *      -# RFAILED
654  **/
655 void schHdlDrxOnDurStrtTimer(SchCellCb  *cell)
656 {
657    uint16_t dlIndx = 0, ulIndx=0;
658    SlotTimingInfo dlSlotInfo, ulSlotInfo;
659
660    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo,  PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
661    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo,  PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
662
663    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
664    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
665    schHdlDrxOnDurStrtTimerForDlDirection(cell, dlIndx);
666    schHdlDrxOnDurStrtTimerForUlDirection(cell, ulIndx);
667 }
668
669 /**
670  * @brief Handling of the  DRX timers start
671  *
672  * @details
673  *
674  *     Function : schHandleStartDrxTimer
675  *
676  *      Handling of DRX timers start
677  *
678  *  @param[in] SchCellCb  *cell
679  *  @return
680  *      -# ROK
681  *      -# RFAILED
682  **/
683 void schHandleStartDrxTimer(SchCellCb  *cell)
684 {
685    /* Handling the onduration start timer */
686    schHdlDrxOnDurStrtTimer(cell);
687 }
688
689 /**
690  * @brief Handling of the expiry onduration timer in dl direction
691  *
692  * @details
693  *
694  *     Function : schHdlDrxOnDurExpiryTimerForDlDirection
695  *
696  *      Handling of expiry onduration DRX timers in dl direction
697  *
698  *  @param[in] SchCellCb  *cell
699  *  @return
700  *      -# ROK
701  *      -# RFAILED
702  **/
703 void schHdlDrxOnDurExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t currListIndx)
704 {
705    CmLList  *drxCurrNode;
706    SchUeCb *ueCb = NULLP;
707
708    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
709    if(drxCurrNode)
710    {
711       /* Handling of dl On duration drx start list */
712       while(drxCurrNode)
713       {
714          ueCb = (SchUeCb*)drxCurrNode->node;
715          drxCurrNode = drxCurrNode->next;
716          
717          ueCb->drxUeCb.onDurationExpiryDistance--;
718
719          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
720          {
721             continue;
722          }
723          ueCb->drxUeCb.drxDlUeActiveStatus &= ~UE_ACTIVE_FOR_ONDURATION;
724       }
725    }
726 }
727
728 /**
729  * @brief Handling of the expiry onduration DRX timers for Ul direction
730  *
731  * @details
732  *
733  *     Function  schHdlDrxOnDurExpiryTimerForUlDirection:
734  *
735  *      Handling of expiry onduration DRX timers in Ul direction
736  *
737  *  @param[in] SchCellCb  *cell
738  *  @return
739  *      -# ROK
740  *      -# RFAILED
741  **/
742 void schHdlDrxOnDurExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t currListIndx)
743 {
744    CmLList  *drxCurrNode;
745    SchUeCb *ueCb = NULLP;
746
747    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
748    if(drxCurrNode)
749    {
750       /* Handling of dl On duration drx start list */
751       while(drxCurrNode)
752       {
753          ueCb = (SchUeCb*)drxCurrNode->node;
754          drxCurrNode = drxCurrNode->next;
755
756          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
757          {
758             continue;
759          }
760
761          ueCb->drxUeCb.drxUlUeActiveStatus &= ~UE_ACTIVE_FOR_ONDURATION;
762          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
763          SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
764          ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX; 
765       }
766    }
767 }
768 /**
769  * @brief Handling of the expiry onduration DRX timers
770  *
771  * @details
772  *
773  *     Function : schHdlDrxOnDurExpiryTimer
774  *
775  *      Handling of expiry onduration DRX timers
776  *
777  *  @param[in] SchCellCb  *cell
778  *  @return
779  *      -# ROK
780  *      -# RFAILED
781  **/
782 void schHdlDrxOnDurExpiryTimer(SchCellCb  *cell)
783 {
784    uint16_t dlIndx = 0, ulIndx = 0;
785    SlotTimingInfo dlSlotInfo, ulSlotInfo;
786
787    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
788    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
789    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
790    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
791
792    schHdlDrxOnDurExpiryTimerForDlDirection(cell, dlIndx);
793    schHdlDrxOnDurExpiryTimerForUlDirection(cell, ulIndx);
794 }
795
796 /**
797  * @brief Handling of the expiry  DRX timers
798  *
799  * @details
800  *
801  *     Function : schHandleExpiryDrxTimer
802  *
803  *      Handling of expiry  DRX timers
804  *
805  *  @param[in] SchCellCb  *cell
806  *  @return
807  *      -# ROK
808  *      -# RFAILED
809  **/
810 void schHandleExpiryDrxTimer(SchCellCb  *cell)
811 {
812    /* Handling the onduration start timer */
813    schHdlDrxOnDurExpiryTimer(cell);
814 }
815
816 #endif
817 /**********************************************************************
818   End of file
819  **********************************************************************/