2 /*******************************************************************************
3 ################################################################################
4 # Copyright (c) [2017-2019] [Radisys] #
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 #
10 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
20 #include "common_def.h"
26 #include "du_app_mac_inf.h"
27 #include "mac_sch_interface.h"
29 #include "sch_utils.h"
33 * @brief intialize the SchDrxHarqCb structre
37 * Function :schInitDrxHarqCb
39 * intialize the SchDrxHarqCb structre
41 * @param[in] SchDrxHarqCb *hqCb
47 void schInitDrxHarqCb(SchDrxHarqCb *hqDrxCb)
49 memset(hqDrxCb, 0, sizeof(SchDrxHarqCb));
50 hqDrxCb->retxExpDistance = SCH_DRX_INVALID_DISTANCE;
51 hqDrxCb->retxStrtIndex = SCH_DRX_INVALID_INDEX;
52 hqDrxCb->rttIndex = SCH_DRX_INVALID_INDEX;
53 hqDrxCb->retxIndex = SCH_DRX_INVALID_INDEX;
57 * @brief intialize the SchDrxUeCb structre
61 * Function : schInitDrxUeCb
63 * intialize the SchDrxUeCb structre
65 * @param[in] SchUeCb *ueCb
71 void schInitDrxUeCb(SchUeCb *ueCb)
73 memset(&ueCb->drxUeCb, 0, sizeof(SchDrxUeCb));
74 ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
75 ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
76 ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
77 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
78 ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
79 ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE;
80 ueCb->drxUeCb.inActiveTmrExpiryDistance = SCH_DRX_INVALID_DISTANCE;
81 ueCb->drxUeCb.drxDlUeActiveStatus = 0;
82 ueCb->drxUeCb.drxUlUeActiveStatus = 0;
85 /* will uncomment this function in next gerrit */
88 * @brief delete Dl harq drx timers and information
92 * Function : schDeleteDlHarqDrxTimer
94 * delete Dl harq drx timers and information
96 * @param[in] SchCellCb *cell, SchUeCb *ueCb
101 void schDeleteDlHarqDrxTimer(SchCellCb *cell, SchDlHqEnt *dlHqEnt)
103 uint8_t idx, numHqPrcs;
105 SchDlHqProcCb *procs;
106 CmLList *node = NULLP;
108 numHqPrcs = dlHqEnt->numHqPrcs;
109 for(idx =0; idx<numHqPrcs; idx++)
111 procs = &dlHqEnt->procs[idx];
112 tmrIdx = procs->dlDrxHarqCb.retxStrtIndex;
113 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
116 cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
117 SCH_FREE(node, sizeof(CmLList));
120 tmrIdx = procs->dlDrxHarqCb.rttIndex;
121 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
124 cmLListDelFrm(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
125 SCH_FREE(node, sizeof(CmLList));
128 tmrIdx = procs->dlDrxHarqCb.retxIndex;
129 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
132 cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
133 SCH_FREE(node, sizeof(CmLList));
135 schInitDrxHarqCb(&procs->dlDrxHarqCb);
140 * @brief delete UL harq drx timers and information
144 * Function : schDeleteUlHarqDrxTimer
146 * delete Ul harq drx timers and information
148 * @param[in] SchCellCb *cell, SchUeCb *ueCb
153 void schDeleteUlHarqDrxTimer(SchCellCb *cell, SchUlHqEnt *ulHqEnt)
155 uint8_t idx, numHqPrcs;
157 CmLList *node = NULLP;
158 SchUlHqProcCb *procs;
160 numHqPrcs = ulHqEnt->numHqPrcs;
161 for(idx =0; idx<numHqPrcs; idx++)
163 procs = &ulHqEnt->procs[idx];
164 tmrIdx = procs->ulDrxHarqCb.retxStrtIndex;
165 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
168 cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
169 SCH_FREE(node, sizeof(CmLList));
172 tmrIdx = procs->ulDrxHarqCb.rttIndex;
173 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
176 cmLListDelFrm(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
177 SCH_FREE(node, sizeof(CmLList));
180 tmrIdx = procs->ulDrxHarqCb.retxIndex;
181 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
184 cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
185 SCH_FREE(node, sizeof(CmLList));
187 schInitDrxHarqCb(&procs->ulDrxHarqCb);
193 * @brief delete UE drx timers and information
197 * Function : schDeleteUeDrxInfo
199 * delete UE drx timers and information
201 * @param[in] SchCellCb *cell, SchUeCb *ueCb
206 void schDeleteUeDrxInfo(SchCellCb *cell, SchUeCb *ueCb)
210 if(ueCb->ueDrxInfoPres == true)
212 drxUeCb = &ueCb->drxUeCb;
214 /* delete on duration start timer from ueCb */
215 if(drxUeCb->onDurationStartIndex != SCH_DRX_INVALID_INDEX)
217 cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationStartIndex].onDurationStartList, drxUeCb->onDurationStartNodeInfo);
218 SCH_FREE(drxUeCb->onDurationStartNodeInfo, sizeof(CmLList));
221 /* delete on duration expiry timer from ueCb */
222 if(drxUeCb->onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
224 cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationExpiryIndex].onDurationExpiryList, drxUeCb->onDurationExpiryNodeInfo);
225 SCH_FREE(drxUeCb->onDurationExpiryNodeInfo, sizeof(CmLList));
228 /* delete inActv Expiry Index timer from ueCb */
229 if(drxUeCb->inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
231 cmLListDelFrm(&cell->drxCb[drxUeCb->inActvExpiryIndex].inActvTmrExpiryList, drxUeCb->inActvTimerExpiryNodeInfo);
232 SCH_FREE(drxUeCb->inActvTimerExpiryNodeInfo, sizeof(CmLList));
235 /* delete short cycle expiry timer from ueCb */
236 if(drxUeCb->shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
238 cmLListDelFrm(&cell->drxCb[drxUeCb->shortCycleExpiryIndex].shortCycleExpiryList, drxUeCb->shortCycleTmrExpiryNodeInfo);
239 SCH_FREE(drxUeCb->shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
241 /* TODO - will uncomment this function in next gerrit */
242 //schDeleteDlHarqDrxTimer(cell, &ueCb->dlHqEnt);
243 //schDeleteUlHarqDrxTimer(cell, &ueCb->ulHqEnt);
244 schInitDrxUeCb(ueCb);
249 * @brief fill drxUeCb structure with the help of ue cfg/recfg information
253 * Function : schFillDrxUeCb
255 * fill drxUeCb structure with the help of ue cfg/recfg information
257 * @param[in] SchDrxCfg drxCfg ->configuration received from ue cfg/recfg api
258 * SchDrxUeCb *drxUeCb -> structure that need to be fill
264 void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb)
266 if(drxCfg.drxOnDurationTimer.onDurationTimerValInMs)
268 SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.milliSeconds, numerology);
272 SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds, numerology);
273 drxUeCb->onDurationLen = drxUeCb->onDurationLen >> 5;
275 SCH_CNVRT_MS_TO_SLOT(drxUeCb->inActvTimerLen, drxCfg.drxInactivityTimer, numerology);
276 SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttDlTimerLen, drxCfg.drxHarqRttTimerDl);
277 SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttUlTimerLen, drxCfg.drxHarqRttTimerUl);
278 drxUeCb->retransDlTimerLen = drxCfg.drxRetransmissionTimerDl;
279 drxUeCb->retransUlTimerLen = drxCfg.drxRetransmissionTimerUl;
280 SCH_CNVRT_MS_TO_SLOT(drxUeCb->longCycleLen, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice, numerology);
281 SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxStartOffset, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetVal, numerology);
282 if(drxCfg.shortDrxPres)
284 drxUeCb->shortCyclePresent = true;
285 SCH_CNVRT_MS_TO_SLOT(drxUeCb->shortCycleLen, drxCfg.shortDrx.drxShortCycle, numerology);
286 drxUeCb->shortCycleTmrLen = drxUeCb->shortCycleLen*drxCfg.shortDrx.drxShortCycleTimer;
288 drxUeCb->longCycleToBeUsed = true;
289 SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxSlotOffset, drxCfg.drxSlotOffset, numerology);
290 drxUeCb->drxSlotOffset = drxUeCb->drxSlotOffset>>5;
294 * @brief Add new entry into the drx timer list
298 * Function : schAddDrxTimerIntoList
300 * Add new entry into the drx timer list
302 * @param[in] CmLListCp *drxTimerList -> List in which new entery have to add
303 * void * ueInfo -> ue information which is need to the added into list
309 uint8_t schAddDrxTimerIntoList(CmLListCp *drxTimerList,void * nodeInfo, CmLList *drxNodeInfo)
311 CmLList *currentNodeInfo = NULLP;
313 SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
316 DU_LOG("\nERROR --> SCH : schAddDrxTimerIntoList() : Memory allocation failed");
320 currentNodeInfo->node = (PTR)nodeInfo;
322 cmLListAdd2Tail(drxTimerList, currentNodeInfo);
323 drxNodeInfo = currentNodeInfo;
324 DU_LOG("\nINFO --> SCH : Drx node added into the list");
329 * @brief This function is used to find the next onduration start timing
333 * Function : findNextOndurationOccurance
335 * This function is used to find the next onduration start timing
337 * @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur,
344 void findNextOndurationOccurance(SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur, uint8_t delta)
346 uint16_t tmpDistance, numOfCycles;
347 uint32_t curTime, cycleLen, nxtDist;
348 SlotTimingInfo tmpTime;
350 if (ueDrxCb->longCycleToBeUsed == true)
352 cycleLen = ueDrxCb->longCycleLen;
356 cycleLen = ueDrxCb->shortCycleLen;
359 /* Add delta to current time */
360 ADD_DELTA_TO_TIME(cell->slotInfo, tmpTime, delta, cell->numSlots);
362 /* Convert tmpTime to number of slots */
363 curTime = ((tmpTime.sfn * cell->numSlots) + tmpTime.slot);
365 /* as per 38.321, if the criterion below is satisfied, then that sfn and
366 * slot are the correct ones for the on-duration timer.
367 * if the Short DRX Cycle is used, and [(SFN × 10) + subframe number] modulo
368 * (drx-ShortCycle) = (drxStartOffset) modulo (drx-ShortCycle); or
369 * if the Long DRX Cycle is used, and [(SFN × 10) + subframe number] modulo
370 * (drx-LongCycle) = drxStartOffset */
371 if ( curTime <= ueDrxCb->drxStartOffset)
373 /* offset is the nextOnDur */
374 nxtDist = ((((ueDrxCb->drxStartOffset / cell->numSlots)) & (MAX_SFN - 1)) * cell->numSlots) + (ueDrxCb->drxStartOffset % cell->numSlots);
378 tmpDistance = curTime - ueDrxCb->drxStartOffset;
379 numOfCycles = tmpDistance / cycleLen;
381 if (0 == (tmpDistance % cycleLen))
383 /* Perfect match pick up the current time */
384 nxtDist = ((((curTime / cell->numSlots)) & (MAX_SFN - 1)) * cell->numSlots) + (curTime % cell->numSlots);
388 nxtDist = ueDrxCb->drxStartOffset + (numOfCycles + 1) * cycleLen;
392 /* If slot offset is non-zero then Add slot offset to the calculated onDur
394 if(ueDrxCb->drxSlotOffset)
396 nxtDist = nxtDist + ueDrxCb->drxSlotOffset;
398 /*If next On Duration is less than DL DELTA ahead, we will miss it and
399 * hence need to move to the On-Duration after that.*/
400 if((nxtDist - (curTime - delta)) <= SCH_DRX_MAX_DELTA)
402 nxtDist = nxtDist + cycleLen;
405 nxtOnDur->sfn = ((nxtDist / cell->numSlots) & (MAX_SFN - 1));
406 nxtOnDur->slot = (nxtDist % cell->numSlots);
410 * @brief Add entry into the on duration list and short cycle list
414 * Function : schDrxUeReCfgTimer
416 * This function is used to Add entry into the on duration list and short
419 * @param[in] SchCellCb *cell, SchUeCb *ueCb
425 void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb)
427 uint8_t currentSlotIndx;
428 uint32_t onDurTime, onDurExpSlotTime, currentSlotTime;
430 SlotTimingInfo onDurationOccurance;
432 if(ueCb->drxUeCb.shortCyclePresent == false)
434 /* if short cycle configuration are not recived as a part of UE Recfg then if there is any entry present in short cycle timer list
435 * remove the entry from the list */
436 if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
438 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex ].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
439 SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
440 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
441 ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
444 /* If there is any entry present in on duration start list then remove the
445 * entry from the list and recaluate the nect onduration cucurance */
446 if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
448 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
449 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
450 ueCb->drxUeCb.onDurationStartIndex= SCH_DRX_INVALID_INDEX;
451 ueCb->drxUeCb.onDurationStartDistance= SCH_DRX_INVALID_DISTANCE;
455 findNextOndurationOccurance(cell, &ueCb->drxUeCb, &onDurationOccurance, 0);
456 onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
458 /* If Onduration timer of old configuration is already running then next onduration
459 * starts once it expires*/
460 if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX))
462 currentSlotTime = cell->slotInfo.sfn * cell->numSlots + cell->slotInfo.slot;
463 currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE;
464 if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex )
466 onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) +\
467 (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
472 onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) +\
473 (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
475 if(onDurTime <= onDurExpSlotTime)
477 if(ueCb->drxUeCb.longCycleToBeUsed == true)
478 cycleLen = ueCb->drxUeCb.longCycleLen;
480 cycleLen = ueCb->drxUeCb.shortCycleLen;
482 onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen;
485 SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
486 ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
487 schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
491 * @brief Add entry into the on duration list
495 * Function : schAddUeInOndurationList
497 * This function is used to Add entry into the on duration list
499 * @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur,
506 void schAddUeInOndurationList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
509 SlotTimingInfo onDurationOccurance;
511 if(ueCb->ueDrxInfoPres)
513 findNextOndurationOccurance(cell, &ueCb->drxUeCb, &onDurationOccurance, delta);
514 onDurTime = onDurationOccurance.sfn*cell->numSlots+onDurationOccurance.slot;
515 SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
516 ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, cell->numSlots)/MAX_DRX_SIZE;
517 schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
523 * @brief Handling of On duration drx start timer
527 * Function : schHdlDrxOnDurStrtTimerForDlDirection
529 * Handling of On duration drx start timer
531 * @param[in] SchCellCb *cell
537 void schHdlDrxOnDurStrtTimerForDlDirection(SchCellCb *cell, uint16_t currListIndx)
539 uint16_t onDurationExpiry=0;
540 CmLList *drxCurrNode = NULLP;
541 SchUeCb *ueCb = NULLP;
543 drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
546 /* Handling of dl On duration drx start list */
549 ueCb = (SchUeCb*)drxCurrNode->node;
550 drxCurrNode = drxCurrNode->next;
552 ueCb->drxUeCb.onDurationStartDistance--;
554 if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
560 ueCb->drxUeCb.drxDlUeActiveStatus |= UE_ACTIVE_FOR_ONDURATION;
562 /* If there is any entery present in onDurationExpiry list remove
563 * the entery from the list and recalculate the
564 * onDurationExpiry time and add it to list */
565 if(ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
567 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
568 SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
569 ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
570 ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE;
573 /* onDurationExpiry = (current slot + onduration length) % MAX_DRX_SIZE*/
574 onDurationExpiry = (currListIndx + ueCb->drxUeCb.onDurationLen)%MAX_DRX_SIZE;
575 ueCb->drxUeCb.onDurationExpiryDistance = (ueCb->drxUeCb.onDurationLen)/MAX_DRX_SIZE;
576 schAddDrxTimerIntoList(&cell->drxCb[onDurationExpiry].onDurationExpiryList, ueCb, ueCb->drxUeCb.onDurationExpiryNodeInfo);
577 ueCb->drxUeCb.onDurationExpiryIndex = onDurationExpiry;
585 * @brief Handling of On duration drx start timer
589 * Function : schHdlDrxOnDurStrtTimerForUlDirection
591 * Handling of On duration drx start timer
593 * @param[in] SchCellCb *cell
599 void schHdlDrxOnDurStrtTimerForUlDirection(SchCellCb *cell, uint16_t currListIndx)
601 uint16_t onDurTime=0;
602 CmLList *drxCurrNode = NULLP;
603 SchUeCb *ueCb = NULLP;
605 drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
608 /* Handling of dl On duration drx start list */
611 ueCb = (SchUeCb*)drxCurrNode->node;
612 drxCurrNode = drxCurrNode->next;
614 if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
618 ueCb->drxUeCb.drxUlUeActiveStatus |= UE_ACTIVE_FOR_ONDURATION;
621 /* if there short cycle length is used as the cycle length for onduration calculation then based on the short cycle else long cycle is used for calculating next onduration */
622 cmLListDelFrm(&cell->drxCb[currListIndx].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
623 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
624 ueCb->drxUeCb.onDurationStartIndex= SCH_DRX_INVALID_INDEX;
626 if(ueCb->drxUeCb.longCycleToBeUsed)
628 onDurTime = currListIndx + ueCb->drxUeCb.longCycleLen;
632 onDurTime = currListIndx + ueCb->drxUeCb.shortCycleLen;
634 SCH_CALCULATE_TIMER_INDEX(onDurTime, ueCb->drxUeCb.onDurationStartIndex);
635 ueCb->drxUeCb.onDurationStartDistance = ueCb->drxUeCb.longCycleLen/MAX_DRX_SIZE;
636 schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
642 * @brief Handling of On duration drx start timer
646 * Function : schHdlDrxOnDurStrtTimer
648 * Handling of On duration drx start timer
650 * @param[in] SchCellCb *cell
655 void schHdlDrxOnDurStrtTimer(SchCellCb *cell)
657 uint16_t dlIndx = 0, ulIndx=0;
658 SlotTimingInfo dlSlotInfo, ulSlotInfo;
660 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
661 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
663 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
664 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
665 schHdlDrxOnDurStrtTimerForDlDirection(cell, dlIndx);
666 schHdlDrxOnDurStrtTimerForUlDirection(cell, ulIndx);
670 * @brief Handling of the DRX in-active start timer
676 * Handling of DRX in-active start timer
678 * @param[in] SchCellCb *cell
684 void schHdlDrxInActvStrtTmr(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
686 uint16_t slotIndx = 0;
687 SlotTimingInfo tmpSlotInfo;
689 if(ueCb->drxUeCb.inActvTimerLen == 0)
694 ADD_DELTA_TO_TIME(cell->slotInfo, tmpSlotInfo, delta, cell->numSlots);
695 slotIndx = (tmpSlotInfo.sfn*MAX_SLOTS+tmpSlotInfo.slot)%MAX_DRX_SIZE;
697 /* if there is any entry present in the in-active exp list then remove the entry */
698 if(ueCb->drxUeCb.inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
700 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
701 SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
702 ueCb->drxUeCb.inActvExpiryIndex= SCH_DRX_INVALID_INDEX;
703 ueCb->drxUeCb.inActiveTmrExpiryDistance= SCH_DRX_INVALID_DISTANCE;
706 /* Adding the new entry in in-activity timer list */
707 ueCb->drxUeCb.inActvExpiryIndex = (slotIndx + ueCb->drxUeCb.inActvTimerLen) % MAX_DRX_SIZE;
708 ueCb->drxUeCb.inActiveTmrExpiryDistance = (ueCb->drxUeCb.inActvTimerLen) / MAX_DRX_SIZE;
709 schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
711 /* Set the UE active for UL And Dl transfer */
712 ueCb->drxUeCb.drxDlUeActiveStatus |= UE_ACTIVE_FOR_INACTIVE_TIMER;
713 ueCb->drxUeCb.drxUlUeActiveStatus |= UE_ACTIVE_FOR_INACTIVE_TIMER;
717 * @brief Handling of short cycle drx start timer
721 * Function : schHdlDrxStartShortCycleTimer
723 * Handling of short cycle drx start timer
725 * @param[in] SchCellCb *cell
731 void schHdlDrxStartShortCycleTimer(SchCellCb *cell, SchUeCb *ueCb)
733 ueCb->drxUeCb.longCycleToBeUsed = false;
735 /* if there is any present in on-duration start list, remove the entry from on duration start list */
736 if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
738 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
739 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
740 ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
741 ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
744 /* recalculate the new index of on duration start based on short cycle */
745 schAddUeInOndurationList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA);
747 /* if any node is present in short cycle exp list then remove the node from list */
748 if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX && ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
750 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
751 SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
752 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
753 ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
756 /* recalculate the new index for shortCycleExpiryList */
757 ueCb->drxUeCb.shortCycleExpiryIndex = (ueCb->drxUeCb.onDurationStartIndex + ueCb->drxUeCb.shortCycleTmrLen) % MAX_DRX_SIZE;
758 ueCb->drxUeCb.shortCycleDistance = ueCb->drxUeCb.shortCycleTmrLen / MAX_DRX_SIZE;
759 schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
763 * @brief Handling of the DRX timers start
767 * Function : schHandleStartDrxTimer
769 * Handling of DRX timers start
771 * @param[in] SchCellCb *cell
776 void schHandleStartDrxTimer(SchCellCb *cell)
778 /* Handling the onduration start timer */
779 schHdlDrxOnDurStrtTimer(cell);
783 * @brief Handling of the expiry onduration timer in dl direction
787 * Function : schHdlDrxOnDurExpiryTimerForDlDirection
789 * Handling of expiry onduration DRX timers in dl direction
791 * @param[in] SchCellCb *cell
796 void schHdlDrxOnDurExpiryTimerForDlDirection(SchCellCb *cell, uint16_t currListIndx)
798 CmLList *drxCurrNode;
799 SchUeCb *ueCb = NULLP;
801 drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
804 /* Handling of dl On duration drx start list */
807 ueCb = (SchUeCb*)drxCurrNode->node;
808 drxCurrNode = drxCurrNode->next;
810 ueCb->drxUeCb.onDurationExpiryDistance--;
812 if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
816 ueCb->drxUeCb.drxDlUeActiveStatus &= ~UE_ACTIVE_FOR_ONDURATION;
822 * @brief Handling of the expiry onduration DRX timers for Ul direction
826 * Function schHdlDrxOnDurExpiryTimerForUlDirection:
828 * Handling of expiry onduration DRX timers in Ul direction
830 * @param[in] SchCellCb *cell
835 void schHdlDrxOnDurExpiryTimerForUlDirection(SchCellCb *cell, uint16_t currListIndx)
837 CmLList *drxCurrNode;
838 SchUeCb *ueCb = NULLP;
840 drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
843 /* Handling of dl On duration drx start list */
846 ueCb = (SchUeCb*)drxCurrNode->node;
847 drxCurrNode = drxCurrNode->next;
849 if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
854 ueCb->drxUeCb.drxUlUeActiveStatus &= ~UE_ACTIVE_FOR_ONDURATION;
855 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
856 SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
857 ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
862 * @brief Handling of the expiry onduration DRX timers
866 * Function : schHdlDrxOnDurExpiryTimer
868 * Handling of expiry onduration DRX timers
870 * @param[in] SchCellCb *cell
875 void schHdlDrxOnDurExpiryTimer(SchCellCb *cell)
877 uint16_t dlIndx = 0, ulIndx = 0;
878 SlotTimingInfo dlSlotInfo, ulSlotInfo;
880 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
881 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
882 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
883 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
885 schHdlDrxOnDurExpiryTimerForDlDirection(cell, dlIndx);
886 schHdlDrxOnDurExpiryTimerForUlDirection(cell, ulIndx);
890 * @brief Handling of the expiry of in-active DRX timers in Dl
894 * Function : schHdlDrxInActvExpiryTimerForDlDirection
896 * Handling of expiry of in-active DRX timers at Dl index
898 * @param[in] SchCellCb *cell, uint16_t dlIndx
904 void schHdlDrxInActvExpiryTimerForDlDirection(SchCellCb *cell, uint16_t dlIndx)
907 SchUeCb *ueCb = NULLP;
909 drxNode = cell->drxCb[dlIndx].inActvTmrExpiryList.first;
912 /* Handling of dl On duration drx start list */
915 ueCb = (SchUeCb*)drxNode->node;
916 drxNode = drxNode->next;
917 ueCb->drxUeCb.inActiveTmrExpiryDistance--;
919 if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
924 ueCb->drxUeCb.drxDlUeActiveStatus &= ~UE_ACTIVE_FOR_INACTIVE_TIMER;
930 * @brief Handling of the expiry of in-active DRX timers in Ul
934 * Function : schHdlDrxInActvExpiryTimerForUlDirection
936 * Handling of expiry of in-active DRX timers at Ul index
938 * @param[in] SchCellCb *cell, uint16_t ulIndx
944 void schHdlDrxInActvExpiryTimerForUlDirection(SchCellCb *cell, uint16_t ulIndx)
947 SchUeCb *ueCb = NULLP;
949 drxNode = cell->drxCb[ulIndx].inActvTmrExpiryList.first;
952 /* Handling of dl On duration drx start list */
955 ueCb = (SchUeCb*)drxNode->node;
956 drxNode = drxNode->next;
958 if(ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE)
963 ueCb->drxUeCb.drxUlUeActiveStatus &= ~UE_ACTIVE_FOR_INACTIVE_TIMER;
965 /* Remove the entry from the in-active exp timer list */
966 cmLListDelFrm(&cell->drxCb[ulIndx].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
967 SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
968 ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
970 if(ueCb->drxUeCb.shortCyclePresent)
972 /* Start short cycle timer */
973 schHdlDrxStartShortCycleTimer(cell, ueCb);
980 * @brief Handling of the expiry of in-active DRX timers
984 * Function :schHdlDrxInActvExpiryTimer
986 * Handling of expiry of in-active DRX timers
988 * @param[in] SchCellCb *cell
993 void schHdlDrxInActvExpiryTimer(SchCellCb *cell)
995 uint16_t dlIndx = 0, ulIndx = 0;
996 SlotTimingInfo dlSlotInfo, ulSlotInfo;
998 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
999 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1000 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1001 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1003 schHdlDrxInActvExpiryTimerForDlDirection(cell, dlIndx);
1004 schHdlDrxInActvExpiryTimerForUlDirection(cell, ulIndx);
1008 * @brief Handling of the expiry ShortCycle DRX timers in DL
1012 * Function : schHdlDrxShortCycleExpiryTimerForDlDirection
1014 * Handling of expiry ShortCycle
1016 * @param[in] SchCellCb *cell
1022 void schHdlDrxShortCycleExpiryTimerForDlDirection(SchCellCb *cell, uint16_t dlIndx)
1024 CmLList *drxCurrNode = NULLP;
1025 SchUeCb *ueCb = NULLP;
1027 drxCurrNode = cell->drxCb[dlIndx].shortCycleExpiryList.first;
1030 /* Handling of short cycle expiry in Dl */
1033 ueCb = (SchUeCb*)drxCurrNode->node;
1034 drxCurrNode = drxCurrNode->next;
1036 ueCb->drxUeCb.shortCycleDistance--;
1038 if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
1043 /* once short cycle timer gets expire we will recalculate on-duration start with long cycle */
1044 ueCb->drxUeCb.longCycleToBeUsed = true;
1046 /* delete the entry from on-duration start */
1047 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
1048 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
1049 ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
1050 ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
1052 /* Recalculate on-duration with long cycle */
1053 schAddUeInOndurationList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA);
1059 * @brief Handling of the expiry ShortCycle DRX timers in UL
1063 * Function : schHdlDrxShortCycleExpiryTimerForUlDirection
1065 * Handling of expiry ShortCycle
1067 * @param[in] SchCellCb *cell
1073 void schHdlDrxShortCycleExpiryTimerForUlDirection(SchCellCb *cell, uint16_t ulIndx)
1075 CmLList *drxCurrNode = NULLP;
1076 SchUeCb *ueCb = NULLP;
1078 drxCurrNode = cell->drxCb[ulIndx].shortCycleExpiryList.first;
1081 /* Handling of short cycle expiry in Ul */
1084 ueCb = (SchUeCb*)drxCurrNode->node;
1085 drxCurrNode = drxCurrNode->next;
1087 if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
1092 cmLListDelFrm(&cell->drxCb[ulIndx].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
1093 SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
1094 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
1101 * @brief Handling of the expiry ShortCycle DRX timers
1105 * Function :schHdlDrxShortCycleExpiryTimer
1107 * Handling of expiry ShortCycle
1109 * @param[in] SchCellCb *cell
1114 void schHdlDrxShortCycleExpiryTimer(SchCellCb *cell)
1116 uint16_t dlIndx = 0, ulIndx= 0;
1117 SlotTimingInfo dlSlotInfo, ulSlotInfo;
1119 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA, cell->numSlots);
1120 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA, cell->numSlots);
1121 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
1122 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
1124 schHdlDrxShortCycleExpiryTimerForDlDirection(cell, dlIndx);
1125 schHdlDrxShortCycleExpiryTimerForUlDirection(cell, ulIndx);
1129 * @brief Handling of the expiry DRX timers
1133 * Function : schHandleExpiryDrxTimer
1135 * Handling of expiry DRX timers
1137 * @param[in] SchCellCb *cell
1142 void schHandleExpiryDrxTimer(SchCellCb *cell)
1144 schHdlDrxShortCycleExpiryTimer(cell);
1145 schHdlDrxOnDurExpiryTimer(cell);
1146 schHdlDrxInActvExpiryTimer(cell);
1150 /**********************************************************************
1152 **********************************************************************/