[Epic-ID: ODUHIGH-462][Task-ID: ODUHIGH-472] Implementation of Ul Harq Rtt 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 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    schHdlDrxUlHqRetxStrtTimer(cell);
957 }
958
959 /**
960  * @brief Handling of the Dl harq Rtt start DRX timers
961  *
962  * @details
963  *
964  *     Function : schDrxStrtDlHqRttTmr
965  *
966  *      Handling of the Dl harq Rtt start DRX timers
967  *
968  *  @param[in] SchCellCb  *cell
969  *  @return
970  *      -# ROK
971  *      -# RFAILED
972  **/
973
974 void schDrxStrtDlHqRttTmr(SchDlHqProcCb *hqP)
975 {
976    uint16_t harqRttExpTimer=0;
977    SchDrxUeCb *drxUeCb;
978    
979    drxUeCb = &hqP->hqEnt->ue->drxUeCb;
980    
981    harqRttExpTimer =  (hqP->pucchTime.sfn * MAX_SLOTS + hqP->pucchTime.slot + drxUeCb->harqRttDlTimerLen)%MAX_DRX_SIZE;
982    hqP->dlDrxHarqCb.rttExpIndex = harqRttExpTimer;
983    schAddDrxNodeIntoHarqTimerList(&hqP->hqEnt->cell->drxCb[harqRttExpTimer].dlHarqRttExpiryList, hqP, &hqP->dlDrxHarqCb.rttExpNode);
984 }
985
986 /**
987  * @brief Handling of the Ul harq DRX timers start for Dl scheduling
988  *
989  * @details
990  *
991  *     Function : schHdlUlHqRetxStrtTimerForDl
992  *
993  *      Handling of Ul harq DRX timers start for Dl scheduling
994  *
995  *  @param[in] SchCellCb *cell, uint16_t currIdx
996  *  @return
997  *     void
998 **/
999  
1000 void schHdlUlHqRetxStrtTimerForDl(SchCellCb *cell, uint16_t currIndx)
1001 {
1002    uint32_t retxExpIndx;
1003    CmLList *currNode;
1004    SchUlHqProcCb *hqP;
1005    SchUeCb *ueCb;
1006    
1007    currNode = cell->drxCb[currIndx].ulRetransTmrStartList.first;
1008    
1009    while(currNode)
1010    {
1011       hqP  = (SchUlHqProcCb*)currNode->node;
1012       currNode = currNode->next;
1013       addUeToBeScheduled(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
1014       ueCb = hqP->hqEnt->ue;
1015       
1016       /* calculate the retransmission exp index */
1017       retxExpIndx =  (currIndx + ueCb->drxUeCb.retransUlTimerLen)%MAX_DRX_SIZE;
1018       if(hqP->ulDrxHarqCb.retxExpIndex == SCH_DRX_INVALID_INDEX)
1019       {
1020          hqP->ulDrxHarqCb.retxExpIndex = retxExpIndx;
1021          schAddDrxNodeIntoHarqTimerList(&cell->drxCb[retxExpIndx].ulRetransExpiryList, hqP, &hqP->ulDrxHarqCb.retxExpNode);
1022       }
1023       
1024       /* Mark the UE active for downlink */
1025       ueCb->drxUeCb.drxUlUeActiveMaskForHarq |= (SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
1026       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1027    }
1028 }
1029
1030 /**
1031  * @brief Handling of the Ul harq DRX timers start for Ul scheduling
1032  *
1033  * @details
1034  *
1035  *     Function : schHdlUlHqRetxStrtTimerForUl
1036  *
1037  *      Handling of Ul harq DRX timers start for Ul scheduling
1038  *
1039  *  @param[in] SchCellCb *cell, uint16_t currIdx
1040  *  @return
1041  *     void
1042  **/
1043  
1044 void schHdlUlHqRetxStrtTimerForUl(SchCellCb *cell, uint16_t currIndx)
1045 {
1046    CmLList *currNode;
1047    SchUlHqProcCb *hqP;
1048    SchUeCb *ueCb;
1049
1050    currNode = cell->drxCb[currIndx].ulRetransTmrStartList.first;
1051    
1052    while(currNode)
1053    {
1054       hqP  = (SchUlHqProcCb*)currNode->node;
1055       currNode = currNode->next;
1056       ueCb = hqP->hqEnt->ue;
1057       
1058       /* Mark the UE active for uplink */
1059       ueCb->drxUeCb.drxUlUeActiveMaskForHarq |= (SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
1060       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1061       
1062       /* Delete the node */
1063       cmLListDelFrm(&cell->drxCb[currIndx].ulRetransTmrStartList, hqP->ulDrxHarqCb.retxStrtNode);
1064       SCH_FREE(hqP->ulDrxHarqCb.retxStrtNode, sizeof(CmLList));
1065       hqP->ulDrxHarqCb.retxStrtIndex = SCH_DRX_INVALID_INDEX;
1066    }
1067 }
1068
1069 /**
1070  * @brief Handling of the Ul harq DRX timers start
1071  *
1072  * @details
1073  *
1074  *     Function : schHdlDrxUlHqRetxStrtTimer
1075  *
1076  *      Handling of Ul harq DRX timers start
1077  *
1078  *  @param[in] SchCellCb  *cell
1079  *  @return
1080  *      -# ROK
1081  *      -# RFAILED
1082  **/
1083
1084 void schHdlDrxUlHqRetxStrtTimer(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
1092    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1093    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1094
1095    schHdlUlHqRetxStrtTimerForDl(cell, dlIndx);
1096    schHdlUlHqRetxStrtTimerForUl(cell, ulIndx);
1097 }
1098
1099 /**
1100  * @brief Handling of the Ul harq Rtt start DRX timers
1101  *
1102  * @details
1103  *
1104  *     Function : schDrxStrtUlHqRttTmr
1105  *
1106  *      Handling of the Ul harq Rtt start DRX timers
1107  *
1108  *  @param[in] SchCellCb  *cell
1109  *  @return
1110  *      -# ROK
1111  *      -# RFAILED
1112  **/
1113
1114 void schDrxStrtUlHqRttTmr(SchUlHqProcCb *hqP)
1115 {
1116    uint16_t harqRttExpTimer=0;
1117    SchDrxUeCb *drxUeCb;
1118    
1119    drxUeCb = &hqP->hqEnt->ue->drxUeCb;
1120    
1121    harqRttExpTimer =  (hqP->puschTime.sfn * MAX_SLOTS + hqP->puschTime.slot + drxUeCb->harqRttUlTimerLen)%MAX_DRX_SIZE;
1122    hqP->ulDrxHarqCb.rttExpIndex = harqRttExpTimer;
1123    schAddDrxNodeIntoHarqTimerList(&hqP->hqEnt->cell->drxCb[harqRttExpTimer].ulHarqRttExpiryList, hqP, &hqP->ulDrxHarqCb.rttExpNode);
1124 }
1125
1126 /**
1127  * @brief Handling of the expiry onduration timer in dl direction
1128  *
1129  * @details
1130  *
1131  *     Function : schHdlDrxOnDurExpiryTimerForDlDirection
1132  *
1133  *      Handling of expiry onduration DRX timers in dl direction
1134  *
1135  *  @param[in] SchCellCb  *cell
1136  *  @return
1137  *      -# ROK
1138  *      -# RFAILED
1139  **/
1140
1141 void schHdlDrxOnDurExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t currListIndx)
1142 {
1143    CmLList  *drxCurrNode;
1144    SchUeCb *ueCb = NULLP;
1145
1146    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
1147    if(drxCurrNode)
1148    {
1149       /* Handling of dl On duration drx start list */
1150       while(drxCurrNode)
1151       {
1152          ueCb = (SchUeCb*)drxCurrNode->node;
1153          drxCurrNode = drxCurrNode->next;
1154          
1155          ueCb->drxUeCb.onDurationExpiryDistance--;
1156
1157          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1158          {
1159             continue;
1160          }
1161          ueCb->drxUeCb.drxDlUeActiveMask &= ~UE_ACTIVE_FOR_ONDURATION;
1162          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1163       }
1164    }
1165 }
1166
1167 /**
1168  * @brief Handling of the expiry onduration DRX timers for Ul direction
1169  *
1170  * @details
1171  *
1172  *     Function  schHdlDrxOnDurExpiryTimerForUlDirection:
1173  *
1174  *      Handling of expiry onduration DRX timers in Ul direction
1175  *
1176  *  @param[in] SchCellCb  *cell
1177  *  @return
1178  *      -# ROK
1179  *      -# RFAILED
1180  **/
1181
1182 void schHdlDrxOnDurExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t currListIndx)
1183 {
1184    CmLList  *drxCurrNode;
1185    SchUeCb *ueCb = NULLP;
1186
1187    drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
1188    if(drxCurrNode)
1189    {
1190       /* Handling of dl On duration drx start list */
1191       while(drxCurrNode)
1192       {
1193          ueCb = (SchUeCb*)drxCurrNode->node;
1194          drxCurrNode = drxCurrNode->next;
1195
1196          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1197          {
1198             continue;
1199          }
1200
1201          ueCb->drxUeCb.drxUlUeActiveMask &= ~UE_ACTIVE_FOR_ONDURATION;
1202          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1203          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
1204          SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
1205          ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX; 
1206       }
1207    }
1208 }
1209
1210 /**
1211  * @brief Handling of the expiry onduration DRX timers
1212  *
1213  * @details
1214  *
1215  *     Function : schHdlDrxOnDurExpiryTimer
1216  *
1217  *      Handling of expiry onduration DRX timers
1218  *
1219  *  @param[in] SchCellCb  *cell
1220  *  @return
1221  *      -# ROK
1222  *      -# RFAILED
1223  **/
1224
1225 void schHdlDrxOnDurExpiryTimer(SchCellCb  *cell)
1226 {
1227    uint16_t dlIndx = 0, ulIndx = 0;
1228    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1229
1230    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1231    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1232    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1233    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1234
1235    schHdlDrxOnDurExpiryTimerForDlDirection(cell, dlIndx);
1236    schHdlDrxOnDurExpiryTimerForUlDirection(cell, ulIndx);
1237 }
1238
1239 /**
1240  * @brief Handling of the expiry of in-active DRX timers in Dl
1241  *
1242  * @details
1243  *
1244  *     Function : schHdlDrxInActvExpiryTimerForDlDirection
1245  *
1246  *      Handling of expiry of in-active DRX timers at Dl index
1247  *
1248  *  @param[in] SchCellCb  *cell,  uint16_t dlIndx
1249  *  @return
1250  *      -# ROK
1251  *      -# RFAILED
1252  **/
1253
1254 void schHdlDrxInActvExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t dlIndx)
1255 {
1256    CmLList  *drxNode;
1257    SchUeCb *ueCb = NULLP;
1258
1259    drxNode = cell->drxCb[dlIndx].inActvTmrExpiryList.first;
1260    if(drxNode)
1261    {
1262       /* Handling of dl On duration drx start list */
1263       while(drxNode)
1264       {
1265          ueCb = (SchUeCb*)drxNode->node;
1266          drxNode = drxNode->next;
1267          ueCb->drxUeCb.inActiveTmrExpiryDistance--;
1268
1269          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1270          {  
1271             continue;
1272          }
1273          
1274          ueCb->drxUeCb.drxDlUeActiveMask &= ~UE_ACTIVE_FOR_INACTIVE_TIMER;
1275          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1276       }
1277    }
1278 }
1279
1280 /**
1281  * @brief Handling of the expiry of in-active DRX timers in Ul
1282  *
1283  * @details
1284  *
1285  *     Function : schHdlDrxInActvExpiryTimerForUlDirection
1286  *
1287  *      Handling of expiry of in-active DRX timers at Ul index
1288  *
1289  *  @param[in] SchCellCb  *cell,  uint16_t ulIndx
1290  *  @return
1291  *      -# ROK
1292  *      -# RFAILED
1293  **/
1294
1295 void schHdlDrxInActvExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t ulIndx)
1296 {
1297    CmLList  *drxNode;
1298    SchUeCb *ueCb = NULLP;
1299
1300    drxNode = cell->drxCb[ulIndx].inActvTmrExpiryList.first;
1301    if(drxNode)
1302    {
1303       /* Handling of dl On duration drx start list */
1304       while(drxNode)
1305       {
1306          ueCb = (SchUeCb*)drxNode->node;
1307          drxNode = drxNode->next;
1308
1309          if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
1310          {  
1311             continue;
1312          }
1313          
1314          ueCb->drxUeCb.drxUlUeActiveMask &= ~UE_ACTIVE_FOR_INACTIVE_TIMER;
1315          setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1316          
1317          /* Remove the entry from the in-active exp timer list */
1318          cmLListDelFrm(&cell->drxCb[ulIndx].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
1319          SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
1320          ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
1321
1322          if(ueCb->drxUeCb.shortCyclePresent)
1323          {  
1324             /* Start short cycle timer */
1325             schHdlDrxStartShortCycleTimer(cell, ueCb);
1326          }
1327       }
1328    }
1329 }
1330
1331 /**
1332  * @brief Handling of the expiry of in-active DRX timers
1333  *
1334  * @details
1335  *
1336  *     Function :schHdlDrxInActvExpiryTimer
1337  *
1338  *      Handling of expiry  of in-active DRX timers
1339  *
1340  *  @param[in] SchCellCb  *cell
1341  *  @return
1342  *      -# ROK
1343  *      -# RFAILED
1344  **/
1345
1346 void schHdlDrxInActvExpiryTimer(SchCellCb  *cell)
1347 {
1348    uint16_t dlIndx = 0, ulIndx = 0;
1349    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1350
1351    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1352    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1353    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1354    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1355
1356    schHdlDrxInActvExpiryTimerForDlDirection(cell, dlIndx);
1357    schHdlDrxInActvExpiryTimerForUlDirection(cell, ulIndx);
1358 }
1359
1360 /**
1361  * @brief Handling of the expiry ShortCycle DRX timers in DL
1362  *
1363  * @details
1364  *
1365  *     Function : schHdlDrxShortCycleExpiryTimerForDlDirection
1366  *
1367  *      Handling of expiry ShortCycle
1368  *
1369  *  @param[in] SchCellCb  *cell
1370  *  @return
1371  *      -# ROK
1372  *      -# RFAILED
1373  **/
1374
1375 void schHdlDrxShortCycleExpiryTimerForDlDirection(SchCellCb  *cell, uint16_t dlIndx)
1376 {
1377    CmLList  *drxCurrNode = NULLP;
1378    SchUeCb *ueCb = NULLP;
1379
1380    drxCurrNode = cell->drxCb[dlIndx].shortCycleExpiryList.first;
1381    if(drxCurrNode)
1382    {
1383       /* Handling of short cycle expiry in Dl */
1384       while(drxCurrNode)
1385       {
1386          ueCb = (SchUeCb*)drxCurrNode->node;
1387          drxCurrNode = drxCurrNode->next;
1388
1389          ueCb->drxUeCb.shortCycleDistance--;
1390
1391          if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
1392          {
1393             continue;
1394          }
1395
1396          /* once short cycle timer gets expire we will recalculate on-duration start with long cycle */ 
1397          ueCb->drxUeCb.longCycleToBeUsed = true;
1398
1399          /* delete the entry from on-duration start */
1400          cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
1401          SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
1402          ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; 
1403          ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE; 
1404
1405          /* Recalculate on-duration with  long cycle */
1406          schAddUeInOndurationList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA);
1407       }
1408    }
1409 }
1410
1411 /**
1412  * @brief Handling of the expiry ShortCycle DRX timers in UL
1413  *
1414  * @details
1415  *
1416  *     Function : schHdlDrxShortCycleExpiryTimerForUlDirection
1417  *
1418  *      Handling of expiry ShortCycle
1419  *
1420  *  @param[in] SchCellCb  *cell
1421  *  @return
1422  *      -# ROK
1423  *      -# RFAILED
1424  **/
1425
1426 void schHdlDrxShortCycleExpiryTimerForUlDirection(SchCellCb  *cell, uint16_t ulIndx)
1427 {
1428    CmLList  *drxCurrNode = NULLP;
1429    SchUeCb *ueCb = NULLP;
1430
1431    drxCurrNode = cell->drxCb[ulIndx].shortCycleExpiryList.first;
1432    if(drxCurrNode)
1433    {
1434       /* Handling of short cycle expiry in Ul */
1435       while(drxCurrNode)
1436       {
1437          ueCb = (SchUeCb*)drxCurrNode->node;
1438          drxCurrNode = drxCurrNode->next;
1439          
1440          if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
1441          {
1442             continue;
1443          }
1444          
1445          cmLListDelFrm(&cell->drxCb[ulIndx].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
1446          SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
1447          ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
1448
1449       }
1450    }
1451 }
1452
1453 /**
1454  * @brief Handling of the expiry ShortCycle DRX timers
1455  *
1456  * @details
1457  *
1458  *     Function :schHdlDrxShortCycleExpiryTimer
1459  *
1460  *      Handling of expiry ShortCycle
1461  *
1462  *  @param[in] SchCellCb  *cell
1463  *  @return
1464  *      -# ROK
1465  *      -# RFAILED
1466  **/
1467
1468 void schHdlDrxShortCycleExpiryTimer(SchCellCb  *cell)
1469 {
1470    uint16_t dlIndx = 0, ulIndx= 0;
1471    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1472
1473    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1474    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1475    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1476    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1477
1478    schHdlDrxShortCycleExpiryTimerForDlDirection(cell, dlIndx);
1479    schHdlDrxShortCycleExpiryTimerForUlDirection(cell, ulIndx);
1480 }
1481
1482 /**
1483  * @brief Handling of the expiry Dl harq rrt DRX timers
1484  *
1485  * @details
1486  *
1487  *     Function : schHdlDlHqRttExpiryTimerForDl
1488  *
1489  *      Handling of expiry Dl harq rrt DRX timers
1490  *
1491  *  @param[in] SchCellCb  *cell
1492  *  @return
1493  *      -# ROK
1494  *      -# RFAILED
1495  **/
1496
1497 void schHdlDlHqRttExpiryTimerForDl(SchCellCb  *cell, uint16_t currIdx)
1498 {
1499    SchDlHqProcCb *hqP;
1500    CmLList *drxCurrNode;
1501
1502    drxCurrNode = cell->drxCb[currIdx].dlHarqRttExpiryList.first;
1503    
1504    while(drxCurrNode)
1505    {
1506       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1507       drxCurrNode = drxCurrNode->next;
1508       
1509      /* Add ue to dlRetransTmrStartList list */
1510      if(hqP->dlDrxHarqCb.retxStrtIndex == SCH_DRX_INVALID_INDEX)
1511      {
1512        schAddDrxNodeIntoHarqTimerList(&cell->drxCb[currIdx + 1].dlRetransTmrStartList, hqP, &hqP->dlDrxHarqCb.retxStrtNode);
1513        hqP->dlDrxHarqCb.retxStrtIndex = currIdx + 1;
1514      }
1515    }
1516 }
1517
1518 /**
1519  * @brief Handling of the expiry Dl harq retransmission DRX timers
1520  *
1521  * @details
1522  *
1523  *     Function : schHdlDlHqRetxExpiryTimerForDl
1524  *
1525  *      Handling of expiry Dl harq retransmission DRX timers
1526  *
1527  *  @param[in] SchCellCb  *cell
1528  *  @return
1529  *      -# ROK
1530  *      -# RFAILED
1531 **/
1532
1533 void schHdlDlHqRetxExpiryTimerForDl(SchCellCb  *cell, uint16_t currIdx)
1534 {
1535    SchDlHqProcCb *hqP;
1536    SchUeCb *ueCb;
1537    CmLList *drxCurrNode;
1538
1539    drxCurrNode = cell->drxCb[currIdx].dlRetransExpiryList.first;
1540    
1541    while(drxCurrNode)
1542    {
1543       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1544       drxCurrNode = drxCurrNode->next;
1545       ueCb = hqP->hqEnt->ue;
1546       
1547       ueCb->drxUeCb.drxDlUeActiveMaskForHarq &= ~(SCH_DRX_DL_HARQ_BITMASK << hqP->procId);
1548       
1549       /* Set the Ue status as inactive */
1550       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1551    } 
1552 }
1553
1554 /**
1555  * @brief Handling of the expiry Dl harq rrt DRX timers for Ul scheduling
1556  *
1557  * @details
1558  *
1559  *     Function : schHdlDlHqRttExpiryTimerForUl
1560  *
1561  *      Handling of expiry Dl harq rrt DRX timers for Ul scheduling
1562  *
1563  *  @param[in] SchCellCb  *cell
1564  *  @return
1565  *      -# ROK
1566  *      -# RFAILED
1567 **/
1568
1569 void schHdlDlHqRttExpiryTimerForUl(SchCellCb  *cell, uint16_t currIdx)
1570 {
1571    SchDlHqProcCb *hqP;
1572    CmLList *drxCurrNode;
1573
1574    drxCurrNode = cell->drxCb[currIdx].dlHarqRttExpiryList.first;
1575    
1576    while(drxCurrNode)
1577    {
1578       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1579       drxCurrNode = drxCurrNode->next;
1580       
1581       /* Delete the node from list */
1582       cmLListDelFrm(&cell->drxCb[currIdx].dlHarqRttExpiryList, hqP->dlDrxHarqCb.rttExpNode);
1583       SCH_FREE(hqP->dlDrxHarqCb.rttExpNode, sizeof(CmLList));
1584       hqP->dlDrxHarqCb.rttExpIndex = SCH_DRX_INVALID_INDEX;
1585    } 
1586 }
1587
1588 /**
1589  * @brief Handling of the expiry Dl harq retransmission DRX timers for Ul scheduling
1590  *
1591  * @details
1592  *
1593  *     Function : schHdlDlHqRetxExpiryTimerForUl
1594  *
1595  *      Handling of expiry Dl harq retransmission DRX timers for Ul scheduling
1596  *
1597  *  @param[in] SchCellCb  *cell
1598  *  @return
1599  *      -# ROK
1600  *      -# RFAILED
1601 **/
1602
1603 void schHdlDlHqRetxExpiryTimerForUl(SchCellCb  *cell, uint16_t currIdx)
1604 {
1605    SchDlHqProcCb *hqP;
1606    SchUeCb *ueCb;
1607    CmLList *drxCurrNode;
1608
1609    drxCurrNode = cell->drxCb[currIdx].dlRetransExpiryList.first;
1610    
1611    while(drxCurrNode)
1612    {
1613       hqP  = (SchDlHqProcCb*)drxCurrNode->node;
1614       ueCb = hqP->hqEnt->ue;
1615       drxCurrNode = drxCurrNode->next;
1616       
1617       /* Set the Ue status as inactive for uplink */
1618       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
1619       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1620       
1621       /* Delete the UE */
1622       cmLListDelFrm(&cell->drxCb[currIdx].dlRetransExpiryList, hqP->dlDrxHarqCb.retxExpNode);
1623       SCH_FREE(hqP->dlDrxHarqCb.retxExpNode, sizeof(CmLList));
1624       hqP->dlDrxHarqCb.retxExpIndex = SCH_DRX_INVALID_INDEX;
1625       
1626    } 
1627 }
1628
1629 /**
1630  * @brief Handling of the expiry of Dl harq DRX timers
1631  *
1632  * @details
1633  *
1634  *     Function : schHdlDrxDlHarqExpireTimer
1635  *
1636  *      Handling of expiry of Dl harq DRX timers
1637  *
1638  *  @param[in] SchCellCb  *cell
1639  *  @return
1640  *      -# void
1641  
1642  **/
1643
1644 void schHdlDrxDlHarqExpireTimer(SchCellCb  *cell)
1645 {
1646    uint16_t dlIndx = 0, ulIndx = 0;
1647    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1648
1649    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1650    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1651    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1652    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1653    
1654    schHdlDlHqRttExpiryTimerForDl(cell, dlIndx);
1655    schHdlDlHqRetxExpiryTimerForDl(cell, dlIndx);
1656    schHdlDlHqRttExpiryTimerForUl(cell, ulIndx );
1657    schHdlDlHqRetxExpiryTimerForUl(cell, ulIndx);
1658 }
1659
1660 /**
1661  * @brief Handling of the expiry of harq DRX timers
1662  *
1663  * @details
1664  *
1665  *     Function : schDrxStopDlHqRetxTmr
1666  *
1667  *      Handling of expiry  DRX timers
1668  *
1669  *  @param[in] SchCellCb  *cell
1670  *  @return
1671  *      -# ROK
1672  *      -# RFAILED
1673  **/
1674
1675 void schDrxStopDlHqRetxTmr(SchCellCb  *cell, SchUeCb *ueCb, SchDlHqProcCb **hqP)
1676 {
1677     
1678    if((*hqP)->dlDrxHarqCb.retxExpIndex != SCH_DRX_INVALID_INDEX)
1679    {
1680       ueCb->drxUeCb.drxDlUeActiveMaskForHarq &= ~(SCH_DRX_DL_HARQ_BITMASK << (*hqP)->procId);
1681       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << (*hqP)->procId);
1682
1683       /* Change the UE status to Inactive */
1684       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1685       
1686       /* If there is any node present in rtt list then remove the node from list */
1687       if((*hqP)->dlDrxHarqCb.rttExpIndex != SCH_DRX_INVALID_INDEX)
1688       {
1689          cmLListDelFrm(&cell->drxCb[(*hqP)->dlDrxHarqCb.rttExpIndex].dlHarqRttExpiryList, (*hqP)->dlDrxHarqCb.rttExpNode);
1690          SCH_FREE((*hqP)->dlDrxHarqCb.rttExpNode, sizeof(CmLList));
1691          (*hqP)->dlDrxHarqCb.rttExpIndex = SCH_DRX_INVALID_INDEX;
1692       }
1693       
1694       /* If there is any node present in retx list then remove the node from list */
1695       if((*hqP)->dlDrxHarqCb.retxStrtIndex != SCH_DRX_INVALID_INDEX)
1696       {
1697          cmLListDelFrm(&cell->drxCb[(*hqP)->dlDrxHarqCb.retxStrtIndex].dlRetransTmrStartList, (*hqP)->dlDrxHarqCb.retxStrtNode);
1698          SCH_FREE((*hqP)->dlDrxHarqCb.retxStrtNode, sizeof(CmLList));
1699          (*hqP)->dlDrxHarqCb.retxStrtIndex  = SCH_DRX_INVALID_INDEX;
1700       }
1701
1702       cmLListDelFrm(&cell->drxCb[(*hqP)->dlDrxHarqCb.retxExpIndex].dlRetransExpiryList, (*hqP)->dlDrxHarqCb.retxExpNode);
1703       SCH_FREE((*hqP)->dlDrxHarqCb.retxExpNode, sizeof(CmLList));
1704       (*hqP)->dlDrxHarqCb.retxExpIndex  = SCH_DRX_INVALID_INDEX;
1705    }
1706 }
1707
1708 /**
1709  * @brief Handling of the expiry Ul harq rrt DRX timers
1710  *
1711  * @details
1712  *
1713  *     Function : schHdlUlHqRttExpiryTimerForDl
1714  *
1715  *      Handling of expiry ul harq rrt DRX timers
1716  *
1717  *  @param[in] SchCellCb  *cell
1718  *  @return
1719  *      -# ROK
1720  *      -# RFAILED
1721  **/
1722
1723 void schHdlUlHqRttExpiryTimerForDl(SchCellCb  *cell, uint16_t currIdx)
1724 {
1725    SchUlHqProcCb *hqP;
1726    CmLList *drxCurrNode;
1727
1728    drxCurrNode = cell->drxCb[currIdx].ulHarqRttExpiryList.first;
1729    
1730    while(drxCurrNode)
1731    {
1732       hqP  = (SchUlHqProcCb*)drxCurrNode->node;
1733       drxCurrNode = drxCurrNode->next;
1734       
1735      /* Add ue to ulRetransTmrStartList list */
1736      if(hqP->ulDrxHarqCb.retxStrtIndex == SCH_DRX_INVALID_INDEX)
1737      {
1738        schAddDrxNodeIntoHarqTimerList(&cell->drxCb[currIdx + 1].ulRetransTmrStartList, hqP, &hqP->ulDrxHarqCb.retxStrtNode);
1739        hqP->ulDrxHarqCb.retxStrtIndex = currIdx + 1;
1740      }
1741    }
1742 }
1743
1744 /**
1745  * @brief Handling of the expiry ul harq retransmission DRX timers
1746  *
1747  * @details
1748  *
1749  *     Function : schHdlUlHqRetxExpiryTimerForDl
1750  *
1751  *      Handling of expiry Ul harq retransmission DRX timers
1752  *
1753  *  @param[in] SchCellCb  *cell
1754  *  @return
1755  *      -# ROK
1756  *      -# RFAILED
1757 **/
1758
1759 void schHdlUlHqRetxExpiryTimerForDl(SchCellCb  *cell, uint16_t currIdx)
1760 {
1761    SchUlHqProcCb *hqP;
1762    SchUeCb *ueCb;
1763    CmLList *drxCurrNode;
1764
1765    drxCurrNode = cell->drxCb[currIdx].ulRetransExpiryList.first;
1766    
1767    while(drxCurrNode)
1768    {
1769       hqP  = (SchUlHqProcCb*)drxCurrNode->node;
1770       drxCurrNode = drxCurrNode->next;
1771       ueCb = hqP->hqEnt->ue;
1772       
1773       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
1774       
1775       /* Set the Ue status as inactive */
1776       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1777    } 
1778 }
1779
1780 /**
1781  * @brief Handling of the expiry ul harq rrt DRX timers for Ul scheduling
1782  *
1783  * @details
1784  *
1785  *     Function : schHdlUlHqRttExpiryTimerForUl
1786  *
1787  *      Handling of expiry Ul harq rrt DRX timers for Ul scheduling
1788  *
1789  *  @param[in] SchCellCb  *cell
1790  *  @return
1791  *      -# ROK
1792  *      -# RFAILED
1793 **/
1794
1795 void schHdlUlHqRttExpiryTimerForUl(SchCellCb  *cell, uint16_t currIdx)
1796 {
1797    SchUlHqProcCb *hqP;
1798    CmLList *drxCurrNode;
1799
1800    drxCurrNode = cell->drxCb[currIdx].ulHarqRttExpiryList.first;
1801    
1802    while(drxCurrNode)
1803    {
1804       hqP  = (SchUlHqProcCb*)drxCurrNode->node;
1805       drxCurrNode = drxCurrNode->next;
1806       
1807       /* Delete the node from list */
1808       cmLListDelFrm(&cell->drxCb[currIdx].ulHarqRttExpiryList, hqP->ulDrxHarqCb.rttExpNode);
1809       SCH_FREE(hqP->ulDrxHarqCb.rttExpNode, sizeof(CmLList));
1810       hqP->ulDrxHarqCb.rttExpIndex = SCH_DRX_INVALID_INDEX;
1811    } 
1812 }
1813
1814 /**
1815  * @brief Handling of the expiry Ul harq retransmission DRX timers for Ul scheduling
1816  *
1817  * @details
1818  *
1819  *     Function : schHdlUlHqRetxExpiryTimerForUl
1820  *
1821  *      Handling of expiry Ul harq retransmission DRX timers for Ul scheduling
1822  *
1823  *  @param[in] SchCellCb  *cell
1824  *  @return
1825  *      -# ROK
1826  *      -# RFAILED
1827 **/
1828
1829 void schHdlUlHqRetxExpiryTimerForUl(SchCellCb  *cell, uint16_t currIdx)
1830 {
1831    SchUlHqProcCb *hqP;
1832    SchUeCb *ueCb;
1833    CmLList *drxCurrNode;
1834
1835    drxCurrNode = cell->drxCb[currIdx].ulRetransExpiryList.first;
1836    
1837    while(drxCurrNode)
1838    {
1839       hqP  = (SchUlHqProcCb*)drxCurrNode->node;
1840       ueCb = hqP->hqEnt->ue;
1841       drxCurrNode = drxCurrNode->next;
1842       
1843       /* Set the Ue status as inactive for uplink */
1844       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << hqP->procId);
1845       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1846       
1847       /* Delete the UE */
1848       cmLListDelFrm(&cell->drxCb[currIdx].ulRetransExpiryList, hqP->ulDrxHarqCb.retxExpNode);
1849       SCH_FREE(hqP->ulDrxHarqCb.retxExpNode, sizeof(CmLList));
1850       hqP->ulDrxHarqCb.retxExpIndex = SCH_DRX_INVALID_INDEX;
1851       
1852    } 
1853 }
1854
1855 /**
1856  * @brief Handling of the expiry of Ul harq DRX timers
1857  *
1858  * @details
1859  *
1860  *     Function : schHdlDrxUlHarqExpireTimer
1861  *
1862  *      Handling of expiry of Ul harq DRX timers
1863  *
1864  *  @param[in] SchCellCb  *cell
1865  *  @return
1866  *      -# void
1867  
1868  **/
1869
1870 void schHdlDrxUlHarqExpireTimer(SchCellCb  *cell)
1871 {
1872    uint16_t dlIndx = 0, ulIndx = 0;
1873    SlotTimingInfo dlSlotInfo, ulSlotInfo;
1874
1875    ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1876    ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1877    dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1878    ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1879    
1880    schHdlUlHqRttExpiryTimerForDl(cell, dlIndx);
1881    schHdlUlHqRetxExpiryTimerForDl(cell, dlIndx);
1882    schHdlUlHqRttExpiryTimerForUl(cell, ulIndx );
1883    schHdlUlHqRetxExpiryTimerForUl(cell, ulIndx);
1884 }
1885
1886 /**
1887  * @brief Hanuling of the expiry of harq DRX timers
1888  *
1889  * @details
1890  *
1891  *     Function : schDrxStopUlHqRetxTmr
1892  *
1893  *      Hanuling of expiry DRX timers
1894  *
1895  *  @param[in] SchCellCb  *cell
1896  *  @return
1897  *      -# ROK
1898  *      -# RFAILED
1899  **/
1900
1901 void schDrxStopUlHqRetxTmr(SchCellCb  *cell, SchUeCb *ueCb, SchUlHqProcCb **hqP)
1902 {
1903     
1904    if((*hqP)->ulDrxHarqCb.retxExpIndex != SCH_DRX_INVALID_INDEX)
1905    {
1906       ueCb->drxUeCb.drxDlUeActiveMaskForHarq &= ~(SCH_DRX_DL_HARQ_BITMASK << (*hqP)->procId);
1907       ueCb->drxUeCb.drxUlUeActiveMaskForHarq &= ~(SCH_DRX_UL_HARQ_BITMASK << (*hqP)->procId);
1908
1909       /* Change the UE status to Inactive */
1910       setDrxUeStatusForDlandUl(&ueCb->drxUeCb);
1911       
1912       /* If there is any node present in rtt list then remove the node from list */
1913       if((*hqP)->ulDrxHarqCb.rttExpIndex != SCH_DRX_INVALID_INDEX)
1914       {
1915          cmLListDelFrm(&cell->drxCb[(*hqP)->ulDrxHarqCb.rttExpIndex].ulHarqRttExpiryList, (*hqP)->ulDrxHarqCb.rttExpNode);
1916          SCH_FREE((*hqP)->ulDrxHarqCb.rttExpNode, sizeof(CmLList));
1917          (*hqP)->ulDrxHarqCb.rttExpIndex = SCH_DRX_INVALID_INDEX;
1918       }
1919       
1920       /* If there is any node present in retx list then remove the node from list */
1921       if((*hqP)->ulDrxHarqCb.retxStrtIndex != SCH_DRX_INVALID_INDEX)
1922       {
1923          cmLListDelFrm(&cell->drxCb[(*hqP)->ulDrxHarqCb.retxStrtIndex].ulRetransTmrStartList, (*hqP)->ulDrxHarqCb.retxStrtNode);
1924          SCH_FREE((*hqP)->ulDrxHarqCb.retxStrtNode, sizeof(CmLList));
1925          (*hqP)->ulDrxHarqCb.retxStrtIndex  = SCH_DRX_INVALID_INDEX;
1926       }
1927
1928       cmLListDelFrm(&cell->drxCb[(*hqP)->ulDrxHarqCb.retxExpIndex].ulRetransExpiryList, (*hqP)->ulDrxHarqCb.retxExpNode);
1929       SCH_FREE((*hqP)->ulDrxHarqCb.retxExpNode, sizeof(CmLList));
1930       (*hqP)->ulDrxHarqCb.retxExpIndex  = SCH_DRX_INVALID_INDEX;
1931    }
1932 }
1933
1934 /**
1935  * @brief Handling of the expiry  DRX timers
1936  *
1937  * @details
1938  *
1939  *     Function : schHandleExpiryDrxTimer
1940  *
1941  *      Handling of expiry  DRX timers
1942  *
1943  *  @param[in] SchCellCb  *cell
1944  *  @return
1945  *      -# ROK
1946  *      -# RFAILED
1947  **/
1948
1949 void schHandleExpiryDrxTimer(SchCellCb  *cell)
1950 {
1951    schHdlDrxShortCycleExpiryTimer(cell);
1952    schHdlDrxOnDurExpiryTimer(cell);
1953    schHdlDrxInActvExpiryTimer(cell);
1954    schHdlDrxDlHarqExpireTimer(cell);
1955    schHdlDrxUlHarqExpireTimer(cell);
1956 }
1957
1958 #endif
1959 /**********************************************************************
1960   End of file
1961  **********************************************************************/