6230ccb207e841e55c1affbfdbe72e7ed448d1fa
[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 set the final Ue drx status 
34  *
35  * @details
36  *
37  *     Function : setDrxUeStatusForDlandUl
38  *      
39  *    set the final Ue drx status to active or inactive 
40  *           
41  *  @param[in] SchDrxUeCb *drxUeCb 
42  *  @return  
43  *      -#void 
44  **/
45
46 void setDrxUeStatusForDlandUl(SchDrxUeCb *drxUeCb)
47 {
48     /* Setting the Dl Ue status */
49     if(drxUeCb->drxDlUeActiveMask || drxUeCb->drxDlUeActiveMaskForHarq)
50     {
51        drxUeCb->drxDlUeActiveStatus = true;
52     }
53     else
54     {
55        drxUeCb->drxDlUeActiveStatus = false;
56     }
57     /* Setting the Ul Ue status */
58     if(drxUeCb->drxUlUeActiveMask || drxUeCb->drxUlUeActiveMaskForHarq)
59     {
60        drxUeCb->drxUlUeActiveStatus = true;
61     }
62     else
63     {
64        drxUeCb->drxUlUeActiveStatus = false;
65     }
66 }
67
68 /**
69  * @brief intialize the SchDrxHarqCb structre 
70  *
71  * @details
72  *
73  *     Function :schInitDrxHarqCb 
74  *      
75  *     intialize the SchDrxHarqCb structre 
76  *           
77  *  @param[in] SchDrxHarqCb *hqCb 
78  *  @return  
79  *      -# ROK
80  *      -# RFAILED
81  **/
82
83 void schInitDrxHarqCb(SchDrxHarqCb *hqDrxCb)
84 {
85    memset(hqDrxCb, 0, sizeof(SchDrxHarqCb));
86    hqDrxCb->retxStrtIndex    = SCH_DRX_INVALID_INDEX;
87    hqDrxCb->rttExpIndex         = SCH_DRX_INVALID_INDEX;
88    hqDrxCb->retxExpIndex        = SCH_DRX_INVALID_INDEX;
89 }
90
91 /**
92  * @brief intialize the SchDrxUeCb structre 
93  *
94  * @details
95  *
96  *     Function : schInitDrxUeCb 
97  *      
98  *     intialize the SchDrxUeCb structre 
99  *           
100  *  @param[in]  SchUeCb *ueCb 
101  *  @return  
102  *      -# ROK
103  *      -# RFAILED
104  **/
105
106 void schInitDrxUeCb(SchUeCb *ueCb)
107 {
108    memset(&ueCb->drxUeCb, 0, sizeof(SchDrxUeCb));
109    ueCb->drxUeCb.onDurationStartIndex  = SCH_DRX_INVALID_INDEX;
110    ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
111    ueCb->drxUeCb.inActvExpiryIndex     = SCH_DRX_INVALID_INDEX;
112    ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
113    ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
114    ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE;
115    ueCb->drxUeCb.inActiveTmrExpiryDistance = SCH_DRX_INVALID_DISTANCE;
116 }
117
118 /**
119  * @brief delete Dl harq drx timers and information 
120  *
121  * @details
122  *
123  *     Function : schDeleteDlHarqDrxTimer
124  *      
125  *     delete Dl harq drx timers and information 
126  *           
127  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
128  *  @return  
129  *      -# ROK
130  *      -# RFAILED
131  **/
132
133 void schDeleteDlHarqDrxTimer(SchCellCb  *cell, SchDlHqEnt *dlHqEnt)
134 {
135    uint8_t idx, numHqPrcs;
136    SchDlHqProcCb *dlProc;
137
138    numHqPrcs = dlHqEnt->numHqPrcs;
139    for(idx =0; idx<numHqPrcs; idx++)
140    {
141       dlProc = &dlHqEnt->procs[idx];
142
143       if(dlProc->dlDrxHarqCb.retxStrtIndex != SCH_DRX_INVALID_INDEX)
144       {
145          cmLListDelFrm(&cell->drxCb[dlProc->dlDrxHarqCb.retxStrtIndex].dlRetransTmrStartList, dlProc->dlDrxHarqCb.retxStrtNode);
146          SCH_FREE(dlProc->dlDrxHarqCb.retxStrtNode, sizeof(CmLList));
147       }
148
149       if(dlProc->dlDrxHarqCb.rttExpIndex != SCH_DRX_INVALID_INDEX)
150       {
151          cmLListDelFrm(&cell->drxCb[dlProc->dlDrxHarqCb.rttExpIndex ].dlHarqRttExpiryList, dlProc->dlDrxHarqCb.rttExpNode);
152          SCH_FREE(dlProc->dlDrxHarqCb.rttExpNode, sizeof(CmLList));
153       }
154
155       if(dlProc->dlDrxHarqCb.retxExpIndex != SCH_DRX_INVALID_INDEX)
156       {
157          cmLListDelFrm(&cell->drxCb[dlProc->dlDrxHarqCb.retxExpIndex].dlRetransExpiryList, dlProc->dlDrxHarqCb.retxExpNode);
158          SCH_FREE(dlProc->dlDrxHarqCb.retxExpNode, sizeof(CmLList));
159       }
160       schInitDrxHarqCb(&dlProc->dlDrxHarqCb);
161    }
162 }
163
164 /**
165  * @brief delete UL harq drx timers and information 
166  *
167  * @details
168  *
169  *     Function : schDeleteUlHarqDrxTimer
170  *      
171  *     delete Ul harq drx timers and information 
172  *           
173  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
174  *  @return  
175  *      -# ROK
176  *      -# RFAILED
177 **/
178
179 void schDeleteUlHarqDrxTimer(SchCellCb  *cell, SchUlHqEnt *ulHqEnt)
180 {
181    uint8_t idx, numHqPrcs;
182    SchUlHqProcCb *ulProc;
183
184    numHqPrcs = ulHqEnt->numHqPrcs;
185    for(idx =0; idx<numHqPrcs; idx++)
186    {
187       ulProc = &ulHqEnt->procs[idx];
188
189       if(ulProc->ulDrxHarqCb.retxStrtIndex != SCH_DRX_INVALID_INDEX)
190       {
191          cmLListDelFrm(&cell->drxCb[ulProc->ulDrxHarqCb.retxStrtIndex].ulRetransTmrStartList, ulProc->ulDrxHarqCb.retxStrtNode);
192          SCH_FREE(ulProc->ulDrxHarqCb.retxStrtNode, sizeof(CmLList));
193       }
194
195       if(ulProc->ulDrxHarqCb.rttExpIndex != SCH_DRX_INVALID_INDEX)
196       {
197          cmLListDelFrm(&cell->drxCb[ulProc->ulDrxHarqCb.rttExpIndex ].ulHarqRttExpiryList, ulProc->ulDrxHarqCb.rttExpNode);
198          SCH_FREE(ulProc->ulDrxHarqCb.rttExpNode, sizeof(CmLList));
199       }
200
201       if(ulProc->ulDrxHarqCb.retxExpIndex != SCH_DRX_INVALID_INDEX)
202       {
203          cmLListDelFrm(&cell->drxCb[ulProc->ulDrxHarqCb.retxExpIndex].ulRetransExpiryList, ulProc->ulDrxHarqCb.retxExpNode);
204          SCH_FREE(ulProc->ulDrxHarqCb.retxExpNode, sizeof(CmLList));
205       }
206       schInitDrxHarqCb(&ulProc->ulDrxHarqCb);
207    }
208 }
209
210 /**
211  * @brief delete UE drx timers and information 
212  *
213  * @details
214  *
215  *     Function : schDeleteUeDrxInfo
216  *      
217  *     delete UE drx timers and information 
218  *           
219  *  @param[in] SchCellCb  *cell, SchUeCb *ueCb 
220  *  @return  void
221  *
222  **/
223
224 void schDeleteUeDrxInfo(SchCellCb  *cell, SchUeCb *ueCb)
225 {
226    SchDrxUeCb *drxUeCb;
227
228    if(ueCb->ueDrxInfoPres == true)
229    {
230       drxUeCb = &ueCb->drxUeCb;
231       
232       /* delete on duration start timer from ueCb */
233       if(drxUeCb->onDurationStartIndex != SCH_DRX_INVALID_INDEX)
234       {
235          cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationStartIndex].onDurationStartList, drxUeCb->onDurationStartNodeInfo);
236          SCH_FREE(drxUeCb->onDurationStartNodeInfo, sizeof(CmLList));
237       }
238       
239       /* delete on duration expiry timer from ueCb */
240       if(drxUeCb->onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
241       {
242          cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationExpiryIndex].onDurationExpiryList, drxUeCb->onDurationExpiryNodeInfo);
243          SCH_FREE(drxUeCb->onDurationExpiryNodeInfo, sizeof(CmLList));
244       }
245       
246       /* delete inActv Expiry Index timer from ueCb */
247       if(drxUeCb->inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
248       {
249          cmLListDelFrm(&cell->drxCb[drxUeCb->inActvExpiryIndex].inActvTmrExpiryList, drxUeCb->inActvTimerExpiryNodeInfo);
250          SCH_FREE(drxUeCb->inActvTimerExpiryNodeInfo, sizeof(CmLList));
251       }
252       
253       /* delete short cycle expiry timer from ueCb */
254       if(drxUeCb->shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
255       {
256          cmLListDelFrm(&cell->drxCb[drxUeCb->shortCycleExpiryIndex].shortCycleExpiryList, drxUeCb->shortCycleTmrExpiryNodeInfo);
257          SCH_FREE(drxUeCb->shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
258       }
259       
260       schDeleteDlHarqDrxTimer(cell, &ueCb->dlHqEnt);
261       schDeleteUlHarqDrxTimer(cell, &ueCb->ulHqEnt);
262       schInitDrxUeCb(ueCb);
263    }
264 }
265
266 /**
267  * @brief fill drxUeCb structure with the help of ue cfg/recfg information
268  *
269  * @details
270  *
271  *     Function : schFillDrxUeCb
272  *      
273  *      fill drxUeCb structure with the help of ue cfg/recfg information
274  *           
275  *  @param[in] SchDrxCfg drxCfg ->configuration received from ue cfg/recfg api
276  *             SchDrxUeCb *drxUeCb -> structure that need to be fill
277  *  @return  
278  *      -# ROK
279  *      -# RFAILED
280  **/
281
282 void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb)
283 {
284    if(drxCfg.drxOnDurationTimer.onDurationTimerValInMs) 
285    {
286       SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.milliSeconds, numerology); 
287    }
288    else
289    {
290       SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds, numerology);
291       drxUeCb->onDurationLen = drxUeCb->onDurationLen >> 5;
292    }   
293    SCH_CNVRT_MS_TO_SLOT(drxUeCb->inActvTimerLen, drxCfg.drxInactivityTimer, numerology);
294    SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttDlTimerLen, drxCfg.drxHarqRttTimerDl);
295    SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttUlTimerLen, drxCfg.drxHarqRttTimerUl);
296    drxUeCb->retransDlTimerLen = drxCfg.drxRetransmissionTimerDl;
297    drxUeCb->retransUlTimerLen = drxCfg.drxRetransmissionTimerUl;
298    SCH_CNVRT_MS_TO_SLOT(drxUeCb->longCycleLen, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice, numerology);
299    SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxStartOffset, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetVal, numerology);
300    if(drxCfg.shortDrxPres)
301    {
302       drxUeCb->shortCyclePresent = true;                   
303       SCH_CNVRT_MS_TO_SLOT(drxUeCb->shortCycleLen, drxCfg.shortDrx.drxShortCycle, numerology);   
304       drxUeCb->shortCycleTmrLen = drxUeCb->shortCycleLen*drxCfg.shortDrx.drxShortCycleTimer;    
305    }
306    drxUeCb->longCycleToBeUsed = true;
307    SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxSlotOffset, drxCfg.drxSlotOffset, numerology);  
308    drxUeCb->drxSlotOffset = drxUeCb->drxSlotOffset>>5; 
309 }
310
311 /**
312  * @brief Add new entry into the drx timer list
313  *
314  * @details
315  *
316  *     Function : schAddDrxTimerIntoList 
317  *      
318  *      Add new entry into the drx timer list
319  *           
320  *  @param[in] CmLListCp *drxTimerList -> List in which new entery have to add
321  *             void * ueInfo -> ue information which is need to the added into list
322  *  @return  
323  *      -# ROK
324  *      -# RFAILED
325  **/
326
327 uint8_t schAddDrxTimerIntoList(CmLListCp *drxTimerList,void * nodeInfo, CmLList *drxNodeInfo)
328 {
329    CmLList  *currentNodeInfo = NULLP;
330
331    SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
332    if(!currentNodeInfo)
333    {
334       DU_LOG("\nERROR  --> SCH : schAddDrxTimerIntoList() : Memory allocation failed");
335       return RFAILED;
336    }
337
338    currentNodeInfo->node = (PTR)nodeInfo;
339    
340    cmLListAdd2Tail(drxTimerList, currentNodeInfo);
341    drxNodeInfo = currentNodeInfo;
342    DU_LOG("\nINFO --> SCH : Drx node added into the list");
343    return ROK;
344 }
345
346 /**
347  * @brief Add new entry into the drx harq timer list
348  *
349  * @details
350  *
351  *     Function : schAddDrxNodeIntoHarqTimerList 
352  *      
353  *      Add new entry into the drx harq timer list
354  *           
355  *  @param[in] CmLListCp *drxTimerList -> List in which new entery have to add
356  *             void * nodeInfo-> ue information which is need to the added into list
357  *              CmLList **drxNodeInfo -> pointer to the node
358  *  @return  
359  *      -# ROK
360  *      -# RFAILED
361  **/
362
363 uint8_t schAddDrxNodeIntoHarqTimerList(CmLListCp *drxTimerList,void * nodeInfo, CmLList **drxNodeInfo)
364 {
365    CmLList  *currentNodeInfo = NULLP;
366
367    SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
368    if(!currentNodeInfo)
369    {
370       DU_LOG("\nERROR  --> SCH : schAddDrxTimerIntoList() : Memory allocation failed");
371       return RFAILED;
372    }
373
374    currentNodeInfo->node = (PTR)nodeInfo;
375    
376    cmLListAdd2Tail(drxTimerList, currentNodeInfo);
377    (*drxNodeInfo) = currentNodeInfo;
378    DU_LOG("\nINFO --> SCH : Drx node added into the list");
379
380    return ROK;
381 }
382
383 /**
384  * @brief This function is used to find the next onduration start timing
385  *
386  * @details
387  *
388  *     Function : findNextOndurationOccurance 
389  *      
390  *      This function is used to find the next onduration start timing
391  *           
392  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
393  *  uint8_t delta
394  *             
395  *  @return  
396  *      -# void
397  **/
398
399 void findNextOndurationOccurance(SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur, uint8_t delta)
400 {
401    uint16_t   tmpDistance, numOfCycles;
402    uint32_t   curTime, cycleLen, nxtDist;
403    SlotTimingInfo  tmpTime;
404    
405    if (ueDrxCb->longCycleToBeUsed == true)
406    {
407       cycleLen = ueDrxCb->longCycleLen;
408    }
409    else
410    {
411       cycleLen = ueDrxCb->shortCycleLen;
412    }
413
414    /* Add delta to current time */
415    ADD_DELTA_TO_TIME(cell->slotInfo, tmpTime, delta, cell->numSlots);
416    
417    /* Convert tmpTime to number of slots */
418    curTime = ((tmpTime.sfn * cell->numSlots) + tmpTime.slot);
419    
420    /* as per 38.321,  if the criterion below is satisfied, then that sfn and
421     * slot are the correct ones for the on-duration timer.
422     * if the Short DRX Cycle is used, and [(SFN Ã— 10) + subframe number] modulo
423     * (drx-ShortCycle) = (drxStartOffset) modulo (drx-ShortCycle); or
424     * if the Long DRX Cycle is used, and [(SFN Ã— 10) + subframe number] modulo
425     * (drx-LongCycle) = drxStartOffset  */
426    if ( curTime <= ueDrxCb->drxStartOffset)
427    {
428       /* offset is the nextOnDur */
429       nxtDist = ((((ueDrxCb->drxStartOffset / cell->numSlots)) & (MAX_SFN - 1)) * cell->numSlots) + (ueDrxCb->drxStartOffset % cell->numSlots);
430    }
431    else
432    {
433       tmpDistance = curTime - ueDrxCb->drxStartOffset;
434       numOfCycles = tmpDistance / cycleLen;
435
436       if (0 == (tmpDistance % cycleLen))
437       {
438          /* Perfect match pick up the current time */
439          nxtDist = ((((curTime / cell->numSlots)) & (MAX_SFN - 1)) * cell->numSlots) + (curTime % cell->numSlots);
440       }
441       else
442       {
443          nxtDist  = ueDrxCb->drxStartOffset + (numOfCycles + 1) * cycleLen;
444       }
445    }
446
447    /* If slot offset is non-zero then Add slot offset to the calculated onDur
448     * distance */
449    if(ueDrxCb->drxSlotOffset)
450    {
451       nxtDist = nxtDist + ueDrxCb->drxSlotOffset;
452    }
453    /*If next On Duration is less than DL DELTA ahead, we will miss it and
454     * hence need to move to the On-Duration after that.*/
455    if((nxtDist - (curTime - delta)) <= SCH_DRX_MAX_DELTA)
456    {
457       nxtDist = nxtDist + cycleLen;
458    }
459    
460    nxtOnDur->sfn = ((nxtDist / cell->numSlots) & (MAX_SFN - 1));
461    nxtOnDur->slot = (nxtDist % cell->numSlots);
462 }
463
464 /**
465  * @brief Add entry into  the on duration list and short cycle list
466  *
467  * @details
468  *
469  *     Function : schDrxUeReCfgTimer 
470  *      
471  *      This function is used to Add entry into  the on duration list and short
472  *      cycle list
473  *           
474  *  @param[in] SchCellCb *cell,   SchUeCb *ueCb
475  *  uint8_t delta
476  *             
477  *  @return void 
478  **/
479
480 void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb)
481 {
482    uint8_t  currentSlotIndx;
483    uint32_t onDurTime, onDurExpSlotTime, currentSlotTime;
484    uint32_t cycleLen;
485    SlotTimingInfo onDurationOccurance;
486    
487    if(ueCb->drxUeCb.shortCyclePresent == false)   
488    {
489       /* 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 
490        * remove the entry from the list */ 
491       if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
492       {
493          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex ].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
494          SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
495          ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
496          ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
497       }
498    }
499    /* If there is any entry present in on duration start list then remove the
500     * entry from the list and recaluate the nect onduration cucurance */
501    if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
502    {
503       cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
504       SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
505       ueCb->drxUeCb.onDurationStartIndex= SCH_DRX_INVALID_INDEX; 
506       ueCb->drxUeCb.onDurationStartDistance= SCH_DRX_INVALID_DISTANCE; 
507       
508    }
509
510    findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, 0);
511    onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
512    
513    /* If Onduration timer of old configuration is already running then next onduration 
514     * starts once it expires*/
515    if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX))
516    {
517        currentSlotTime = cell->slotInfo.sfn * cell->numSlots + cell->slotInfo.slot;
518        currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE;
519        if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex )
520        {
521          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) +\
522          (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
523        }
524        else
525        {
526          
527          onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) +\
528          (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
529        }
530        if(onDurTime <= onDurExpSlotTime)
531        {
532           if(ueCb->drxUeCb.longCycleToBeUsed == true)
533              cycleLen = ueCb->drxUeCb.longCycleLen;
534           else
535              cycleLen = ueCb->drxUeCb.shortCycleLen;
536
537           onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen;
538        }
539    }
540    SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
541    ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
542    schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
543 }
544
545 /**
546  * @brief Add entry into  the on duration list 
547  *
548  * @details
549  *
550  *     Function : schAddUeInOndurationList
551  *      
552  *      This function is used to Add entry into  the on duration list 
553  *           
554  *  @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo  *nxtOnDur,
555  *  uint8_t delta
556  *             
557  *  @return  
558  *      -# void
559  **/
560
561 void schAddUeInOndurationList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
562 {
563    uint32_t onDurTime;
564    SlotTimingInfo onDurationOccurance;
565
566    if(ueCb->ueDrxInfoPres)
567    {
568       findNextOndurationOccurance(cell,  &ueCb->drxUeCb, &onDurationOccurance, delta);
569       onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
570       SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
571       ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
572       schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
573
574    }
575 }
576
577 /**
578  * @brief Handling of On duration drx start timer
579  *
580  * @details
581  *
582  *     Function : schHdlDrxOnDurStrtTimerForDlDirection
583  *
584  *      Handling of On duration drx start timer
585  *
586  *  @param[in] SchCellCb  *cell
587  *  @return
588  *      -# ROK
589  *      -# RFAILED
590  **/
591
592 void schHdlDrxOnDurStrtTimerForDlDirection(SchCellCb  *cell, uint16_t currListIndx)
593 {
594    uint16_t onDurationExpiry=0;
595    CmLList  *drxCurrNode = NULLP;
596    SchUeCb *ueCb = NULLP;
597
598    drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
599    if(drxCurrNode)
600    {
601       /* Handling of dl On duration drx start list */
602       while(drxCurrNode)
603       {
604          ueCb = (SchUeCb*)drxCurrNode->node;
605          drxCurrNode = drxCurrNode->next;
606          
607          ueCb->drxUeCb.onDurationStartDistance--;
608          
609          if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
610          {
611             continue;
612          }
613          else
614          {
615             ueCb->drxUeCb.drxDlUeActiveMask |= UE_ACTIVE_FOR_ONDURATION;
616             
617             /* set the Ue status as active or inactive*/
618             setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
619             
620             /* If there is any entery present in onDurationExpiry list remove
621              * the entery from the list and recalculate the
622              * onDurationExpiry time and add it to list */
623             if(ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
624             {
625                cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
626                SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
627                ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
628                ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE; 
629             }
630
631             /* onDurationExpiry  = (current slot + onduration length) % MAX_DRX_SIZE*/
632             onDurationExpiry = (currListIndx + ueCb->drxUeCb.onDurationLen)%MAX_DRX_SIZE;
633             ueCb->drxUeCb.onDurationExpiryDistance =  (ueCb->drxUeCb.onDurationLen)/MAX_DRX_SIZE;
634             schAddDrxTimerIntoList(&cell->drxCb[onDurationExpiry].onDurationExpiryList, ueCb, ueCb->drxUeCb.onDurationExpiryNodeInfo);
635             ueCb->drxUeCb.onDurationExpiryIndex = onDurationExpiry;
636
637          }
638       }
639    }
640 }
641
642 /**
643  * @brief Handling of On duration drx start timer
644  *
645  * @details
646  *
647  *     Function : schHdlDrxOnDurStrtTimerForUlDirection
648  *
649  *      Handling of On duration drx start timer
650  *
651  *  @param[in] SchCellCb  *cell
652  *  @return
653  *      -# ROK
654  *      -# RFAILED
655  **/
656
657 void schHdlDrxOnDurStrtTimerForUlDirection(SchCellCb  *cell, uint16_t currListIndx)
658 {
659    uint16_t onDurTime=0;
660    CmLList  *drxCurrNode = NULLP;
661    SchUeCb *ueCb = NULLP;
662
663    drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
664    if(drxCurrNode)
665    {
666       /* Handling of dl On duration drx start list */
667       while(drxCurrNode)
668       {
669          ueCb = (SchUeCb*)drxCurrNode->node;
670          drxCurrNode = drxCurrNode->next;
671          
672          if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
673          {
674             continue;
675          }
676          ueCb->drxUeCb.drxUlUeActiveMask |= UE_ACTIVE_FOR_ONDURATION;
677          /* set the final Ue status as active or inactive */
678          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
679          
680          /* 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 */
681          cmLListDelFrm(&cell->drxCb[currListIndx].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
682          SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
683          ueCb->drxUeCb.onDurationStartIndex= SCH_DRX_INVALID_INDEX; 
684
685          if(ueCb->drxUeCb.longCycleToBeUsed)
686          {
687             onDurTime = currListIndx +  ueCb->drxUeCb.longCycleLen;
688          }
689          else
690          {
691             onDurTime = currListIndx +  ueCb->drxUeCb.shortCycleLen;
692          }
693          SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
694          ueCb->drxUeCb.onDurationStartDistance = ueCb->drxUeCb.longCycleLen/MAX_DRX_SIZE;
695          schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
696       }
697    }
698 }
699
700 /**
701  * @brief Handling of On duration drx start timer
702  *
703  * @details
704  *
705  *     Function : schHdlDrxOnDurStrtTimer
706  *
707  *      Handling of On duration drx start timer
708  *
709  *  @param[in] SchCellCb  *cell
710  *  @return
711  *      -# ROK
712  *      -# RFAILED
713  **/
714
715 void schHdlDrxOnDurStrtTimer(SchCellCb  *cell)
716 {
717    uint16_t dlIndx = 0, ulIndx=0;
718    SlotTimingInfo dlSlotInfo, ulSlotInfo;
719
720    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo,  PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
721    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo,  PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
722
723    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
724    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
725    schHdlDrxOnDurStrtTimerForDlDirection(cell, dlIndx);
726    schHdlDrxOnDurStrtTimerForUlDirection(cell, ulIndx);
727 }
728
729 /**
730  * @brief Handling of the DRX in-active start timer
731  *
732  * @details
733  *
734  *     Function : 
735  *
736  *      Handling of DRX in-active start timer
737  *
738  *  @param[in] SchCellCb  *cell
739  *  @return
740  *      -# ROK
741  *      -# RFAILED
742  **/
743
744 void schHdlDrxInActvStrtTmr(SchCellCb  *cell,  SchUeCb *ueCb, uint8_t delta)
745 {
746    uint16_t slotIndx = 0;
747    SlotTimingInfo tmpSlotInfo;
748    
749    if(ueCb->drxUeCb.inActvTimerLen == 0)
750    {
751       return;
752    }
753
754    ADD_DELTA_TO_TIME(cell->slotInfo, tmpSlotInfo,  delta, cell->numSlots);
755    slotIndx = (tmpSlotInfo.sfn*MAX_SLOTS+tmpSlotInfo.slot)%MAX_DRX_SIZE;
756
757    /* if there is any entry present in the in-active exp list then remove the entry */
758    if(ueCb->drxUeCb.inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
759    {
760       cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
761       SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
762       ueCb->drxUeCb.inActvExpiryIndex= SCH_DRX_INVALID_INDEX;
763       ueCb->drxUeCb.inActiveTmrExpiryDistance= SCH_DRX_INVALID_DISTANCE;
764    }
765
766    /* Adding the new entry in in-activity timer list */
767    ueCb->drxUeCb.inActvExpiryIndex = (slotIndx + ueCb->drxUeCb.inActvTimerLen) % MAX_DRX_SIZE;
768    ueCb->drxUeCb.inActiveTmrExpiryDistance = (ueCb->drxUeCb.inActvTimerLen) / MAX_DRX_SIZE;
769    schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
770
771    /* Set the UE active for UL And Dl transfer */
772    ueCb->drxUeCb.drxDlUeActiveMask |= UE_ACTIVE_FOR_INACTIVE_TIMER;
773    ueCb->drxUeCb.drxUlUeActiveMask |= UE_ACTIVE_FOR_INACTIVE_TIMER;
774    setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
775 }
776
777 /**
778  * @brief Handling of short cycle drx start timer
779  *
780  * @details
781  *
782  *     Function : schHdlDrxStartShortCycleTimer
783  *
784  *      Handling of short cycle drx start timer
785  *
786  *  @param[in] SchCellCb  *cell
787  *  @return
788  *      -# ROK
789  *      -# RFAILED
790  **/
791
792 void schHdlDrxStartShortCycleTimer(SchCellCb  *cell, SchUeCb *ueCb)
793 {
794    ueCb->drxUeCb.longCycleToBeUsed = false;
795
796    /* if there is any present in on-duration start list, remove the entry from on duration start list */
797    if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
798    {
799       cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
800       SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
801       ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; 
802       ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE; 
803    } 
804
805    /* recalculate the new index of on duration start based on short cycle */
806    schAddUeInOndurationList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA);
807
808    /* if any node is present in short cycle exp list then remove the node from list  */
809    if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX && ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
810    {
811       cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
812       SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
813       ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
814       ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
815    }
816
817    /* recalculate the new index for shortCycleExpiryList */
818    ueCb->drxUeCb.shortCycleExpiryIndex = (ueCb->drxUeCb.onDurationStartIndex + ueCb->drxUeCb.shortCycleTmrLen) % MAX_DRX_SIZE;
819    ueCb->drxUeCb.shortCycleDistance = ueCb->drxUeCb.shortCycleTmrLen / MAX_DRX_SIZE;
820    schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
821 }
822
823 /**
824  * @brief Handling of the Dl harq DRX timers start for Dl scheduling
825  *
826  * @details
827  *
828  *     Function : schHdlDlHqRetxStrtTimerForDl
829  *
830  *      Handling of Dl harq DRX timers start for Dl scheduling
831  *
832  *  @param[in] SchCellCb *cell, uint16_t currIdx
833  *  @return
834  *     void
835 **/
836  
837 void schHdlDlHqRetxStrtTimerForDl(SchCellCb *cell, uint16_t currIndx)
838 {
839    uint32_t retxExpIndx;
840    CmLList *currNode;
841    SchDlHqProcCb *hqP;
842    SchUeCb *ueCb;
843    
844    currNode = cell->drxCb[currIndx].dlRetransTmrStartList.first;
845    
846    while(currNode)
847    {
848       hqP  = (SchDlHqProcCb*)currNode->node;
849       currNode = currNode->next;
850       addUeToBeScheduled(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
851       ueCb = hqP->hqEnt->ue;
852       
853       /* calculate the retransmission exp index */
854       retxExpIndx =  (currIndx + ueCb->drxUeCb.retransDlTimerLen)%MAX_DRX_SIZE;
855       if(hqP->dlDrxHarqCb.retxExpIndex == SCH_DRX_INVALID_INDEX)
856       {
857          hqP->dlDrxHarqCb.retxExpIndex = retxExpIndx;
858          schAddDrxNodeIntoHarqTimerList(&cell->drxCb[retxExpIndx].dlRetransExpiryList, hqP, &hqP->dlDrxHarqCb.retxExpNode);
859       }
860       
861       /* Mark the UE active for downlink */
862       ueCb->drxUeCb.drxDlUeActiveMaskForHarq |= (SCH_DRX_DL_HARQ_BITMASK << hqP->procId);
863       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
864    }
865 }
866
867 /**
868  * @brief Handling of the Dl harq DRX timers start for Ul scheduling
869  *
870  * @details
871  *
872  *     Function : schHdlDlHqRetxStrtTimerForUl
873  *
874  *      Handling of Dl harq DRX timers start for Ul scheduling
875  *
876  *  @param[in] SchCellCb *cell, uint16_t currIdx
877  *  @return
878  *     void
879  **/
880  
881 void schHdlDlHqRetxStrtTimerForUl(SchCellCb *cell, uint16_t currIndx)
882 {
883    CmLList *currNode;
884    SchDlHqProcCb *hqP;
885    SchUeCb *ueCb;
886
887    currNode = cell->drxCb[currIndx].dlRetransTmrStartList.first;
888    
889    while(currNode)
890    {
891       hqP  = (SchDlHqProcCb*)currNode->node;
892       currNode = currNode->next;
893       ueCb = hqP->hqEnt->ue;
894       
895       /* Mark the UE active for uplink */
896       ueCb->drxUeCb.drxUlUeActiveMaskForHarq |= (SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
897       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
898       
899       /* Delete the node */
900       cmLListDelFrm(&cell->drxCb[currIndx].dlRetransTmrStartList, hqP->dlDrxHarqCb.retxStrtNode);
901       SCH_FREE(hqP->dlDrxHarqCb.retxStrtNode, sizeof(CmLList));
902       hqP->dlDrxHarqCb.retxStrtIndex = SCH_DRX_INVALID_INDEX;
903    }
904 }
905
906 /**
907  * @brief Handling of the Dl harq DRX timers start
908  *
909  * @details
910  *
911  *     Function : schHdlDrxDlHqRetxStrtTimer
912  *
913  *      Handling of Dl harq DRX timers start
914  *
915  *  @param[in] SchCellCb  *cell
916  *  @return
917  *      -# ROK
918  *      -# RFAILED
919  **/
920
921 void schHdlDrxDlHqRetxStrtTimer(SchCellCb  *cell)
922 {
923    uint16_t dlIndx = 0, ulIndx=0;
924    SlotTimingInfo dlSlotInfo, ulSlotInfo;
925
926    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo,  PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
927    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo,  PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
928
929    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
930    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
931
932    schHdlDlHqRetxStrtTimerForDl(cell, dlIndx);
933    schHdlDlHqRetxStrtTimerForUl(cell, ulIndx);
934 }
935
936 /**
937  * @brief Handling of the  DRX timers start
938  *
939  * @details
940  *
941  *     Function : schHandleStartDrxTimer
942  *
943  *      Handling of DRX timers start
944  *
945  *  @param[in] SchCellCb  *cell
946  *  @return
947  *      -# ROK
948  *      -# RFAILED
949  **/
950
951 void schHandleStartDrxTimer(SchCellCb  *cell)
952 {
953    /* Handling the onduration start timer */
954    schHdlDrxOnDurStrtTimer(cell);
955    schHdlDrxDlHqRetxStrtTimer(cell);
956 }
957
958 /**
959  * @brief Handling of the Dl harq Rtt start DRX timers
960  *
961  * @details
962  *
963  *     Function : schDrxStrtDlHqRttTmr
964  *
965  *      Handling of the Dl harq Rtt start DRX timers
966  *
967  *  @param[in] SchCellCb  *cell
968  *  @return
969  *      -# ROK
970  *      -# RFAILED
971  **/
972
973 void schDrxStrtDlHqRttTmr(SchDlHqProcCb *hqP)
974 {
975    uint16_t harqRttExpTimer=0;
976    SchDrxUeCb *drxUeCb;
977    
978    drxUeCb = &hqP->hqEnt->ue->drxUeCb;
979    
980    harqRttExpTimer =  (hqP->pucchTime.sfn * MAX_SLOTS + hqP->pucchTime.slot + drxUeCb->harqRttDlTimerLen)%MAX_DRX_SIZE;
981    hqP->dlDrxHarqCb.rttExpIndex = harqRttExpTimer;
982    schAddDrxNodeIntoHarqTimerList(&hqP->hqEnt->cell->drxCb[harqRttExpTimer].dlHarqRttExpiryList, hqP, &hqP->dlDrxHarqCb.rttExpNode);
983 }
984
985 /**
986  * @brief Handling of the expiry onduration timer in dl direction
987  *
988  * @details
989  *
990  *     Function : schHdlDrxOnDurExpiryTimerForDlDirection
991  *
992  *      Handling of expiry onduration DRX timers in dl direction
993  *
994  *  @param[in] SchCellCb  *cell
995  *  @return
996  *      -# ROK
997  *      -# RFAILED
998  **/
999
1000 void schHdlDrxOnDurExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t currListIndx)
1001 {
1002    CmLList  *drxCurrNode;
1003    SchUeCb *ueCb = NULLP;
1004
1005    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
1006    if(drxCurrNode)
1007    {
1008       /* Handling of dl On duration drx start list */
1009       while(drxCurrNode)
1010       {
1011          ueCb = (SchUeCb*)drxCurrNode->node;
1012          drxCurrNode = drxCurrNode->next;
1013          
1014          ueCb->drxUeCb.onDurationExpiryDistance--;
1015
1016          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1017          {
1018             continue;
1019          }
1020          ueCb->drxUeCb.drxDlUeActiveMask &= ~UE_ACTIVE_FOR_ONDURATION;
1021          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1022       }
1023    }
1024 }
1025
1026 /**
1027  * @brief Handling of the expiry onduration DRX timers for Ul direction
1028  *
1029  * @details
1030  *
1031  *     Function  schHdlDrxOnDurExpiryTimerForUlDirection:
1032  *
1033  *      Handling of expiry onduration DRX timers in Ul direction
1034  *
1035  *  @param[in] SchCellCb  *cell
1036  *  @return
1037  *      -# ROK
1038  *      -# RFAILED
1039  **/
1040
1041 void schHdlDrxOnDurExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t currListIndx)
1042 {
1043    CmLList  *drxCurrNode;
1044    SchUeCb *ueCb = NULLP;
1045
1046    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
1047    if(drxCurrNode)
1048    {
1049       /* Handling of dl On duration drx start list */
1050       while(drxCurrNode)
1051       {
1052          ueCb = (SchUeCb*)drxCurrNode->node;
1053          drxCurrNode = drxCurrNode->next;
1054
1055          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1056          {
1057             continue;
1058          }
1059
1060          ueCb->drxUeCb.drxUlUeActiveMask &= ~UE_ACTIVE_FOR_ONDURATION;
1061          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1062          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
1063          SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
1064          ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX; 
1065       }
1066    }
1067 }
1068
1069 /**
1070  * @brief Handling of the expiry onduration DRX timers
1071  *
1072  * @details
1073  *
1074  *     Function : schHdlDrxOnDurExpiryTimer
1075  *
1076  *      Handling of expiry onduration DRX timers
1077  *
1078  *  @param[in] SchCellCb  *cell
1079  *  @return
1080  *      -# ROK
1081  *      -# RFAILED
1082  **/
1083
1084 void schHdlDrxOnDurExpiryTimer(SchCellCb  *cell)
1085 {
1086    uint16_t dlIndx = 0, ulIndx = 0;
1087    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1088
1089    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1090    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1091    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1092    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1093
1094    schHdlDrxOnDurExpiryTimerForDlDirection(cell, dlIndx);
1095    schHdlDrxOnDurExpiryTimerForUlDirection(cell, ulIndx);
1096 }
1097
1098 /**
1099  * @brief Handling of the expiry of in-active DRX timers in Dl
1100  *
1101  * @details
1102  *
1103  *     Function : schHdlDrxInActvExpiryTimerForDlDirection
1104  *
1105  *      Handling of expiry of in-active DRX timers at Dl index
1106  *
1107  *  @param[in] SchCellCb  *cell,  uint16_t dlIndx
1108  *  @return
1109  *      -# ROK
1110  *      -# RFAILED
1111  **/
1112
1113 void schHdlDrxInActvExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t dlIndx)
1114 {
1115    CmLList  *drxNode;
1116    SchUeCb *ueCb = NULLP;
1117
1118    drxNode = cell->drxCb[dlIndx].inActvTmrExpiryList.first;
1119    if(drxNode)
1120    {
1121       /* Handling of dl On duration drx start list */
1122       while(drxNode)
1123       {
1124          ueCb = (SchUeCb*)drxNode->node;
1125          drxNode = drxNode->next;
1126          ueCb->drxUeCb.inActiveTmrExpiryDistance--;
1127
1128          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1129          {  
1130             continue;
1131          }
1132          
1133          ueCb->drxUeCb.drxDlUeActiveMask &= ~UE_ACTIVE_FOR_INACTIVE_TIMER;
1134          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1135       }
1136    }
1137 }
1138
1139 /**
1140  * @brief Handling of the expiry of in-active DRX timers in Ul
1141  *
1142  * @details
1143  *
1144  *     Function : schHdlDrxInActvExpiryTimerForUlDirection
1145  *
1146  *      Handling of expiry of in-active DRX timers at Ul index
1147  *
1148  *  @param[in] SchCellCb  *cell,  uint16_t ulIndx
1149  *  @return
1150  *      -# ROK
1151  *      -# RFAILED
1152  **/
1153
1154 void schHdlDrxInActvExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t ulIndx)
1155 {
1156    CmLList  *drxNode;
1157    SchUeCb *ueCb = NULLP;
1158
1159    drxNode = cell->drxCb[ulIndx].inActvTmrExpiryList.first;
1160    if(drxNode)
1161    {
1162       /* Handling of dl On duration drx start list */
1163       while(drxNode)
1164       {
1165          ueCb = (SchUeCb*)drxNode->node;
1166          drxNode = drxNode->next;
1167
1168          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1169          {  
1170             continue;
1171          }
1172          
1173          ueCb->drxUeCb.drxUlUeActiveMask &= ~UE_ACTIVE_FOR_INACTIVE_TIMER;
1174          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1175          
1176          /* Remove the entry from the in-active exp timer list */
1177          cmLListDelFrm(&cell->drxCb[ulIndx].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
1178          SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
1179          ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
1180
1181          if(ueCb->drxUeCb.shortCyclePresent)
1182          {  
1183             /* Start short cycle timer */
1184             schHdlDrxStartShortCycleTimer(cell, ueCb);
1185          }
1186       }
1187    }
1188 }
1189
1190 /**
1191  * @brief Handling of the expiry of in-active DRX timers
1192  *
1193  * @details
1194  *
1195  *     Function :schHdlDrxInActvExpiryTimer
1196  *
1197  *      Handling of expiry  of in-active DRX timers
1198  *
1199  *  @param[in] SchCellCb  *cell
1200  *  @return
1201  *      -# ROK
1202  *      -# RFAILED
1203  **/
1204
1205 void schHdlDrxInActvExpiryTimer(SchCellCb  *cell)
1206 {
1207    uint16_t dlIndx = 0, ulIndx = 0;
1208    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1209
1210    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1211    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1212    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1213    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1214
1215    schHdlDrxInActvExpiryTimerForDlDirection(cell, dlIndx);
1216    schHdlDrxInActvExpiryTimerForUlDirection(cell, ulIndx);
1217 }
1218
1219 /**
1220  * @brief Handling of the expiry ShortCycle DRX timers in DL
1221  *
1222  * @details
1223  *
1224  *     Function : schHdlDrxShortCycleExpiryTimerForDlDirection
1225  *
1226  *      Handling of expiry ShortCycle
1227  *
1228  *  @param[in] SchCellCb  *cell
1229  *  @return
1230  *      -# ROK
1231  *      -# RFAILED
1232  **/
1233
1234 void schHdlDrxShortCycleExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t dlIndx)
1235 {
1236    CmLList  *drxCurrNode = NULLP;
1237    SchUeCb *ueCb = NULLP;
1238
1239    drxCurrNode = cell->drxCb[dlIndx].shortCycleExpiryList.first;
1240    if(drxCurrNode)
1241    {
1242       /* Handling of short cycle expiry in Dl */
1243       while(drxCurrNode)
1244       {
1245          ueCb = (SchUeCb*)drxCurrNode->node;
1246          drxCurrNode = drxCurrNode->next;
1247
1248          ueCb->drxUeCb.shortCycleDistance--;
1249
1250          if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
1251          {
1252             continue;
1253          }
1254
1255          /* once short cycle timer gets expire we will recalculate on-duration start with long cycle */ 
1256          ueCb->drxUeCb.longCycleToBeUsed = true;
1257
1258          /* delete the entry from on-duration start */
1259          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
1260          SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
1261          ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; 
1262          ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE; 
1263
1264          /* Recalculate on-duration with  long cycle */
1265          schAddUeInOndurationList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA);
1266       }
1267    }
1268 }
1269
1270 /**
1271  * @brief Handling of the expiry ShortCycle DRX timers in UL
1272  *
1273  * @details
1274  *
1275  *     Function : schHdlDrxShortCycleExpiryTimerForUlDirection
1276  *
1277  *      Handling of expiry ShortCycle
1278  *
1279  *  @param[in] SchCellCb  *cell
1280  *  @return
1281  *      -# ROK
1282  *      -# RFAILED
1283  **/
1284
1285 void schHdlDrxShortCycleExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t ulIndx)
1286 {
1287    CmLList  *drxCurrNode = NULLP;
1288    SchUeCb *ueCb = NULLP;
1289
1290    drxCurrNode = cell->drxCb[ulIndx].shortCycleExpiryList.first;
1291    if(drxCurrNode)
1292    {
1293       /* Handling of short cycle expiry in Ul */
1294       while(drxCurrNode)
1295       {
1296          ueCb = (SchUeCb*)drxCurrNode->node;
1297          drxCurrNode = drxCurrNode->next;
1298          
1299          if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
1300          {
1301             continue;
1302          }
1303          
1304          cmLListDelFrm(&cell->drxCb[ulIndx].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
1305          SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
1306          ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
1307
1308       }
1309    }
1310 }
1311
1312 /**
1313  * @brief Handling of the expiry ShortCycle DRX timers
1314  *
1315  * @details
1316  *
1317  *     Function :schHdlDrxShortCycleExpiryTimer
1318  *
1319  *      Handling of expiry ShortCycle
1320  *
1321  *  @param[in] SchCellCb  *cell
1322  *  @return
1323  *      -# ROK
1324  *      -# RFAILED
1325  **/
1326
1327 void schHdlDrxShortCycleExpiryTimer(SchCellCb  *cell)
1328 {
1329    uint16_t dlIndx = 0, ulIndx= 0;
1330    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1331
1332    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1333    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1334    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1335    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1336
1337    schHdlDrxShortCycleExpiryTimerForDlDirection(cell, dlIndx);
1338    schHdlDrxShortCycleExpiryTimerForUlDirection(cell, ulIndx);
1339 }
1340
1341 /**
1342  * @brief Handling of the expiry Dl harq rrt DRX timers
1343  *
1344  * @details
1345  *
1346  *     Function : schHdlDlHqRttExpiryTimerForDl
1347  *
1348  *      Handling of expiry Dl harq rrt DRX timers
1349  *
1350  *  @param[in] SchCellCb  *cell
1351  *  @return
1352  *      -# ROK
1353  *      -# RFAILED
1354  **/
1355
1356 void schHdlDlHqRttExpiryTimerForDl(SchCellCb  *cell, uint16_t currIdx)
1357 {
1358    SchDlHqProcCb *hqP;
1359    CmLList *drxCurrNode;
1360
1361    drxCurrNode = cell->drxCb[currIdx].dlHarqRttExpiryList.first;
1362    
1363    while(drxCurrNode)
1364    {
1365       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1366       drxCurrNode = drxCurrNode->next;
1367       
1368      /* Add ue to dlRetransTmrStartList list */
1369      if(hqP->dlDrxHarqCb.retxStrtIndex == SCH_DRX_INVALID_INDEX)
1370      {
1371        schAddDrxNodeIntoHarqTimerList(&cell->drxCb[currIdx + 1].dlRetransTmrStartList, hqP, &hqP->dlDrxHarqCb.retxStrtNode);
1372        hqP->dlDrxHarqCb.retxStrtIndex = currIdx + 1;
1373      }
1374    }
1375 }
1376
1377 /**
1378  * @brief Handling of the expiry Dl harq retransmission DRX timers
1379  *
1380  * @details
1381  *
1382  *     Function : schHdlDlHqRetxExpiryTimerForDl
1383  *
1384  *      Handling of expiry Dl harq retransmission DRX timers
1385  *
1386  *  @param[in] SchCellCb  *cell
1387  *  @return
1388  *      -# ROK
1389  *      -# RFAILED
1390 **/
1391
1392 void schHdlDlHqRetxExpiryTimerForDl(SchCellCb  *cell, uint16_t currIdx)
1393 {
1394    SchDlHqProcCb *hqP;
1395    SchUeCb *ueCb;
1396    CmLList *drxCurrNode;
1397
1398    drxCurrNode = cell->drxCb[currIdx].dlRetransExpiryList.first;
1399    
1400    while(drxCurrNode)
1401    {
1402       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1403       drxCurrNode = drxCurrNode->next;
1404       ueCb = hqP->hqEnt->ue;
1405       
1406       ueCb->drxUeCb.drxDlUeActiveMaskForHarq &= ~(SCH_DRX_DL_HARQ_BITMASK << hqP->procId);
1407       
1408       /* Set the Ue status as inactive */
1409       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1410    } 
1411 }
1412
1413 /**
1414  * @brief Handling of the expiry Dl harq rrt DRX timers for Ul scheduling
1415  *
1416  * @details
1417  *
1418  *     Function : schHdlDlHqRttExpiryTimerForUl
1419  *
1420  *      Handling of expiry Dl harq rrt DRX timers for Ul scheduling
1421  *
1422  *  @param[in] SchCellCb  *cell
1423  *  @return
1424  *      -# ROK
1425  *      -# RFAILED
1426 **/
1427
1428 void schHdlDlHqRttExpiryTimerForUl(SchCellCb  *cell, uint16_t currIdx)
1429 {
1430    SchDlHqProcCb *hqP;
1431    CmLList *drxCurrNode;
1432
1433    drxCurrNode = cell->drxCb[currIdx].dlHarqRttExpiryList.first;
1434    
1435    while(drxCurrNode)
1436    {
1437       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1438       drxCurrNode = drxCurrNode->next;
1439       
1440       /* Delete the node from list */
1441       cmLListDelFrm(&cell->drxCb[currIdx].dlHarqRttExpiryList, hqP->dlDrxHarqCb.rttExpNode);
1442       SCH_FREE(hqP->dlDrxHarqCb.rttExpNode, sizeof(CmLList));
1443       hqP->dlDrxHarqCb.rttExpIndex = SCH_DRX_INVALID_INDEX;
1444    } 
1445 }
1446
1447 /**
1448  * @brief Handling of the expiry Dl harq retransmission DRX timers for Ul scheduling
1449  *
1450  * @details
1451  *
1452  *     Function : schHdlDlHqRetxExpiryTimerForUl
1453  *
1454  *      Handling of expiry Dl harq retransmission DRX timers for Ul scheduling
1455  *
1456  *  @param[in] SchCellCb  *cell
1457  *  @return
1458  *      -# ROK
1459  *      -# RFAILED
1460 **/
1461
1462 void schHdlDlHqRetxExpiryTimerForUl(SchCellCb  *cell, uint16_t currIdx)
1463 {
1464    SchDlHqProcCb *hqP;
1465    SchUeCb *ueCb;
1466    CmLList *drxCurrNode;
1467
1468    drxCurrNode = cell->drxCb[currIdx].dlRetransExpiryList.first;
1469    
1470    while(drxCurrNode)
1471    {
1472       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1473       ueCb = hqP->hqEnt->ue;
1474       drxCurrNode = drxCurrNode->next;
1475       
1476       /* Set the Ue status as inactive for uplink */
1477       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
1478       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1479       
1480       /* Delete the UE */
1481       cmLListDelFrm(&cell->drxCb[currIdx].dlRetransExpiryList, hqP->dlDrxHarqCb.retxExpNode);
1482       SCH_FREE(hqP->dlDrxHarqCb.retxExpNode, sizeof(CmLList));
1483       hqP->dlDrxHarqCb.retxExpIndex = SCH_DRX_INVALID_INDEX;
1484       
1485    } 
1486 }
1487
1488 /**
1489  * @brief Handling of the expiry of Dl harq DRX timers
1490  *
1491  * @details
1492  *
1493  *     Function : schHdlDrxHarqExpireTimer
1494  *
1495  *      Handling of expiry of Dl harq DRX timers
1496  *
1497  *  @param[in] SchCellCb  *cell
1498  *  @return
1499  *      -# void
1500  
1501  **/
1502
1503 void schHdlDrxHarqExpireTimer(SchCellCb  *cell)
1504 {
1505    uint16_t dlIndx = 0, ulIndx = 0;
1506    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1507
1508    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1509    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1510    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1511    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1512    
1513    schHdlDlHqRttExpiryTimerForDl(cell, dlIndx);
1514    schHdlDlHqRetxExpiryTimerForDl(cell, dlIndx);
1515    schHdlDlHqRttExpiryTimerForUl(cell, ulIndx );
1516    schHdlDlHqRetxExpiryTimerForUl(cell, ulIndx);
1517 }
1518
1519 /**
1520  * @brief Handling of the expiry of harq DRX timers
1521  *
1522  * @details
1523  *
1524  *     Function : schDrxStopDlHqRetxTmr
1525  *
1526  *      Handling of expiry  DRX timers
1527  *
1528  *  @param[in] SchCellCb  *cell
1529  *  @return
1530  *      -# ROK
1531  *      -# RFAILED
1532  **/
1533
1534 void schDrxStopDlHqRetxTmr(SchCellCb  *cell, SchUeCb *ueCb, SchDlHqProcCb **hqP)
1535 {
1536     
1537    if((*hqP)->dlDrxHarqCb.retxExpIndex != SCH_DRX_INVALID_INDEX)
1538    {
1539       ueCb->drxUeCb.drxDlUeActiveMaskForHarq &= ~(SCH_DRX_DL_HARQ_BITMASK << (*hqP)->procId);
1540       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << (*hqP)->procId);
1541
1542       /* Change the UE status to Inactive */
1543       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1544       
1545       /* If there is any node present in rtt list then remove the node from list */
1546       if((*hqP)->dlDrxHarqCb.rttExpIndex != SCH_DRX_INVALID_INDEX)
1547       {
1548          cmLListDelFrm(&cell->drxCb[(*hqP)->dlDrxHarqCb.rttExpIndex].dlHarqRttExpiryList, (*hqP)->dlDrxHarqCb.rttExpNode);
1549          SCH_FREE((*hqP)->dlDrxHarqCb.rttExpNode, sizeof(CmLList));
1550          (*hqP)->dlDrxHarqCb.rttExpIndex = SCH_DRX_INVALID_INDEX;
1551       }
1552       
1553       /* If there is any node present in retx list then remove the node from list */
1554       if((*hqP)->dlDrxHarqCb.retxStrtIndex != SCH_DRX_INVALID_INDEX)
1555       {
1556          cmLListDelFrm(&cell->drxCb[(*hqP)->dlDrxHarqCb.retxStrtIndex].dlRetransTmrStartList, (*hqP)->dlDrxHarqCb.retxStrtNode);
1557          SCH_FREE((*hqP)->dlDrxHarqCb.retxStrtNode, sizeof(CmLList));
1558          (*hqP)->dlDrxHarqCb.retxStrtIndex  = SCH_DRX_INVALID_INDEX;
1559       }
1560
1561       cmLListDelFrm(&cell->drxCb[(*hqP)->dlDrxHarqCb.retxExpIndex].dlRetransExpiryList, (*hqP)->dlDrxHarqCb.retxExpNode);
1562       SCH_FREE((*hqP)->dlDrxHarqCb.retxExpNode, sizeof(CmLList));
1563       (*hqP)->dlDrxHarqCb.retxExpIndex  = SCH_DRX_INVALID_INDEX;
1564    }
1565 }
1566
1567 /**
1568  * @brief Handling of the expiry  DRX timers
1569  *
1570  * @details
1571  *
1572  *     Function : schHandleExpiryDrxTimer
1573  *
1574  *      Handling of expiry  DRX timers
1575  *
1576  *  @param[in] SchCellCb  *cell
1577  *  @return
1578  *      -# ROK
1579  *      -# RFAILED
1580  **/
1581
1582 void schHandleExpiryDrxTimer(SchCellCb  *cell)
1583 {
1584    schHdlDrxShortCycleExpiryTimer(cell);
1585    schHdlDrxOnDurExpiryTimer(cell);
1586    schHdlDrxInActvExpiryTimer(cell);
1587    schHdlDrxHarqExpireTimer(cell);
1588 }
1589
1590 #endif
1591 /**********************************************************************
1592   End of file
1593  **********************************************************************/