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
46 void schInitDrxHarqCb(SchDrxHarqCb *hqDrxCb)
48 memset(hqDrxCb, 0, sizeof(SchDrxHarqCb));
49 hqDrxCb->retxExpDistance = SCH_DRX_INVALID_DISTANCE;
50 hqDrxCb->retxStrtIndex = SCH_DRX_INVALID_INDEX;
51 hqDrxCb->rttIndex = SCH_DRX_INVALID_INDEX;
52 hqDrxCb->retxIndex = SCH_DRX_INVALID_INDEX;
56 * @brief intialize the SchDrxUeCb structre
60 * Function : schInitDrxUeCb
62 * intialize the SchDrxUeCb structre
64 * @param[in] SchUeCb *ueCb
69 void schInitDrxUeCb(SchUeCb *ueCb)
71 memset(&ueCb->drxUeCb, 0, sizeof(SchDrxUeCb));
72 ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
73 ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
74 ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
75 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
76 ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
77 ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE;
78 ueCb->drxUeCb.inActiveTmrExpiryDistance = SCH_DRX_INVALID_DISTANCE;
79 ueCb->drxUeCb.drxDlUeActiveStatus = false;
80 ueCb->drxUeCb.drxUlUeActiveStatus = false;
83 /* will uncomment this function in next gerrit */
85 * @brief delete Dl harq drx timers and information
89 * Function : schDeleteDlHarqDrxTimer
91 * delete Dl harq drx timers and information
93 * @param[in] SchCellCb *cell, SchUeCb *ueCb
98 void schDeleteDlHarqDrxTimer(SchCellCb *cell, SchDlHqEnt *dlHqEnt)
100 uint8_t idx, numHqPrcs;
102 SchDlHqProcCb *procs;
103 CmLList *node = NULLP;
105 numHqPrcs = dlHqEnt->numHqPrcs;
106 for(idx =0; idx<numHqPrcs; idx++)
108 procs = &dlHqEnt->procs[idx];
109 tmrIdx = procs->drxHarqCb.retxStrtIndex;
110 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
113 cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node);
114 SCH_FREE(node, sizeof(CmLList));
117 tmrIdx = procs->drxHarqCb.rttIndex;
118 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
121 cmLListDelFrm(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node);
122 SCH_FREE(node, sizeof(CmLList));
125 tmrIdx = procs->drxHarqCb.retxIndex;
126 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
129 cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransExpiryList, node);
130 SCH_FREE(node, sizeof(CmLList));
132 schInitDrxHarqCb(&procs->drxHarqCb);
137 * @brief delete UL harq drx timers and information
141 * Function : schDeleteUlHarqDrxTimer
143 * delete Ul harq drx timers and information
145 * @param[in] SchCellCb *cell, SchUeCb *ueCb
150 void schDeleteUlHarqDrxTimer(SchCellCb *cell, SchUlHqEnt *ulHqEnt)
152 uint8_t idx, numHqPrcs;
154 CmLList *node = NULLP;
155 SchUlHqProcCb *procs;
157 numHqPrcs = ulHqEnt->numHqPrcs;
158 for(idx =0; idx<numHqPrcs; idx++)
160 procs = &ulHqEnt->procs[idx];
161 tmrIdx = procs->drxHarqCb.retxStrtIndex;
162 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
165 cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node);
166 SCH_FREE(node, sizeof(CmLList));
169 tmrIdx = procs->drxHarqCb.rttIndex;
170 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
173 cmLListDelFrm(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node);
174 SCH_FREE(node, sizeof(CmLList));
177 tmrIdx = procs->drxHarqCb.retxIndex;
178 CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
181 cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransExpiryList, node);
182 SCH_FREE(node, sizeof(CmLList));
184 schInitDrxHarqCb(&procs->drxHarqCb);
189 * @brief delete UE drx timers and information
193 * Function : schDeleteUeDrxInfo
195 * delete UE drx timers and information
197 * @param[in] SchCellCb *cell, SchUeCb *ueCb
202 void schDeleteUeDrxInfo(SchCellCb *cell, SchUeCb *ueCb)
206 if(ueCb->ueDrxInfoPres == true)
208 drxUeCb = &ueCb->drxUeCb;
210 /* delete on duration start timer from ueCb */
211 if(drxUeCb->onDurationStartIndex != SCH_DRX_INVALID_INDEX)
213 cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationStartIndex].onDurationStartList, drxUeCb->onDurationStartNodeInfo);
214 SCH_FREE(drxUeCb->onDurationStartNodeInfo, sizeof(CmLList));
217 /* delete on duration expiry timer from ueCb */
218 if(drxUeCb->onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
220 cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationExpiryIndex].onDurationExpiryList, drxUeCb->onDurationExpiryNodeInfo);
221 SCH_FREE(drxUeCb->onDurationExpiryNodeInfo, sizeof(CmLList));
224 /* delete inActv Expiry Index timer from ueCb */
225 if(drxUeCb->inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
227 cmLListDelFrm(&cell->drxCb[drxUeCb->inActvExpiryIndex].inActvTmrExpiryList, drxUeCb->inActvTimerExpiryNodeInfo);
228 SCH_FREE(drxUeCb->inActvTimerExpiryNodeInfo, sizeof(CmLList));
231 /* delete short cycle expiry timer from ueCb */
232 if(drxUeCb->shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
234 cmLListDelFrm(&cell->drxCb[drxUeCb->shortCycleExpiryIndex].shortCycleExpiryList, drxUeCb->shortCycleTmrExpiryNodeInfo);
235 SCH_FREE(drxUeCb->shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
237 /* TODO - will uncomment this function in next gerrit */
238 //schDeleteDlHarqDrxTimer(cell, &ueCb->dlHqEnt);
239 //schDeleteUlHarqDrxTimer(cell, &ueCb->ulHqEnt);
240 schInitDrxUeCb(ueCb);
245 * @brief fill drxUeCb structure with the help of ue cfg/recfg information
249 * Function : schFillDrxUeCb
251 * fill drxUeCb structure with the help of ue cfg/recfg information
253 * @param[in] SchDrxCfg drxCfg ->configuration received from ue cfg/recfg api
254 * SchDrxUeCb *drxUeCb -> structure that need to be fill
259 void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb)
261 if(drxCfg.drxOnDurationTimer.onDurationTimerValInMs)
263 SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.milliSeconds, numerology);
267 SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds, numerology);
268 drxUeCb->onDurationLen = drxUeCb->onDurationLen >> 5;
270 SCH_CNVRT_MS_TO_SLOT(drxUeCb->inActvTimerLen, drxCfg.drxInactivityTimer, numerology);
271 SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttDlTimerLen, drxCfg.drxHarqRttTimerDl);
272 SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttUlTimerLen, drxCfg.drxHarqRttTimerUl);
273 SCH_CNVRT_MS_TO_SLOT(drxUeCb->retransDlTimerLen, drxCfg.drxRetransmissionTimerDl, numerology);
274 SCH_CNVRT_MS_TO_SLOT(drxUeCb->retransUlTimerLen, drxCfg.drxRetransmissionTimerUl, numerology);
275 SCH_CNVRT_MS_TO_SLOT(drxUeCb->longCycleLen, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice, numerology);
276 drxUeCb->drxStartOffset = drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetVal;
277 if(drxCfg.shortDrxPres)
279 drxUeCb->shortCyclePresent = true;
280 SCH_CNVRT_MS_TO_SLOT(drxUeCb->shortCycleLen, drxCfg.shortDrx.drxShortCycle, numerology);
281 drxUeCb->shortCycleTmrLen = drxCfg.shortDrx.drxShortCycleTimer;
284 drxUeCb->longCycleToBeUsed = true;
285 SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxSlotOffset, drxCfg.drxSlotOffset, numerology);
286 drxUeCb->drxSlotOffset = drxUeCb->drxSlotOffset>>5;
290 * @brief Add new entry into the drx timer list
294 * Function : schAddDrxTimerIntoList
296 * Add new entry into the drx timer list
298 * @param[in] CmLListCp *drxTimerList -> List in which new entery have to add
299 * void * ueInfo -> ue information which is need to the added into list
304 uint8_t schAddDrxTimerIntoList(CmLListCp *drxTimerList,void * nodeInfo, CmLList *drxNodeInfo)
306 CmLList *currentNodeInfo = NULLP;
308 SCH_ALLOC(currentNodeInfo, sizeof(CmLList));
311 DU_LOG("\nERROR --> SCH : schAddDrxTimerIntoList() : Memory allocation failed");
315 currentNodeInfo->node = (PTR)nodeInfo;
317 cmLListAdd2Tail(drxTimerList, currentNodeInfo);
318 drxNodeInfo = currentNodeInfo;
323 * @brief This function is used to find the next onduration start timing
327 * Function : findNextOndurationOccurance
329 * This function is used to find the next onduration start timing
331 * @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur,
337 void findNextOndurationOccurance(SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur, uint8_t delta)
339 uint16_t resultX, reusltY, idx;
340 uint32_t curTime, cycleLen, nxtDist;
341 SlotTimingInfo tmpTime;
343 if (ueDrxCb->longCycleToBeUsed == true)
345 cycleLen = ueDrxCb->longCycleLen;
349 cycleLen = ueDrxCb->shortCycleLen;
352 /* Add delta to current time */
353 ADD_DELTA_TO_TIME(cell->slotInfo, tmpTime, delta);
355 /* Convert tmpTime to number of slots */
356 curTime = ((tmpTime.sfn * MAX_SLOTS) + tmpTime.slot);
358 /* as per 38.321, if the criterion below is satisfied, then that sfn and
359 * slot are the correct ones for the on-duration timer.
360 * if the Short DRX Cycle is used, and [(SFN × 10) + subframe number] modulo
361 * (drx-ShortCycle) = (drxStartOffset) modulo (drx-ShortCycle); or
362 * if the Long DRX Cycle is used, and [(SFN × 10) + subframe number] modulo
363 * (drx-LongCycle) = drxStartOffset */
364 for(idx =1; idx<MAX_DRX_SIZE; idx++)
366 resultX = (tmpTime.sfn *10+tmpTime.slot) % cycleLen;
367 if (TRUE != ueDrxCb->shortCyclePresent)
368 reusltY = ueDrxCb->drxStartOffset;
370 reusltY = ueDrxCb->drxStartOffset % cycleLen;
371 if(resultX == reusltY)
373 memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo));
374 nxtDist = ((nxtOnDur->sfn * MAX_SLOTS) + nxtOnDur->slot);
379 ADD_DELTA_TO_TIME(tmpTime, tmpTime, 1);
383 /* If slot offset is non-zero then Add slot offset to the calculated onDur
385 if(ueDrxCb->drxSlotOffset)
387 nxtDist = nxtDist + ueDrxCb->drxSlotOffset;
388 ADD_DELTA_TO_TIME(tmpTime, tmpTime, ueDrxCb->drxSlotOffset);
389 memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo));
391 /*If next On Duration is less than DL DELTA ahead, we will miss it and
392 * hence need to move to the On-Duration after that.*/
393 if((nxtDist - (curTime - delta)) <= SCH_DRX_MAX_DELTA)
395 ADD_DELTA_TO_TIME(tmpTime, tmpTime, cycleLen);
396 memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo));
401 * @brief Add entry into the on duration list and short cycle list
405 * Function : schDrxUeReCfgTimer
407 * This function is used to Add entry into the on duration list and short
410 * @param[in] SchCellCb *cell, SchUeCb *ueCb
415 void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb)
417 uint8_t onDurIndx, currentSlotIndx;
418 uint32_t onDurTime, onDurExpSlotTime, currentSlotTime;
420 SlotTimingInfo onDurationOccurance;
422 if(ueCb->drxUeCb.shortCyclePresent == false)
424 /* if short cycle configuration are not recived as a part of UE Recfg then if there is any entry present in short cycle timer list
425 * remove the entry from the list */
426 if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX)
428 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex ].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
429 SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
430 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
431 ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE;
434 /* If there is any entry present in on duration start list then remove the
435 * entry from the list and recaluate the nect onduration cucurance */
436 if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
438 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
439 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
440 ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
441 ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
444 findNextOndurationOccurance(cell, &ueCb->drxUeCb, &onDurationOccurance, 0);
445 onDurTime = onDurationOccurance.sfn*MAX_SLOTS+onDurationOccurance.slot;
446 onDurIndx = onDurTime%MAX_DRX_SIZE;
447 /* If Onduration timer of old configuration is already running then next onduration
448 * starts once it expires*/
449 if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex == SCH_DRX_INVALID_INDEX))
451 currentSlotTime = cell->slotInfo.sfn * MAX_SLOTS + cell->slotInfo.slot;
452 currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE;
453 if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex )
455 onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) + (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
460 onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) + (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA);
462 if(onDurTime <= onDurExpSlotTime)
464 if(ueCb->drxUeCb.longCycleToBeUsed == true)
465 cycleLen = ueCb->drxUeCb.longCycleLen;
467 cycleLen = ueCb->drxUeCb.shortCycleLen;
469 onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen;
472 onDurIndx = onDurTime%MAX_DRX_SIZE;
473 ueCb->drxUeCb.onDurationStartIndex = onDurIndx;
474 ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, MAX_SLOTS)/MAX_DRX_SIZE;
475 schAddDrxTimerIntoList(&cell->drxCb[onDurIndx].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
476 if((TRUE == ueCb->drxUeCb.shortCyclePresent) &&(ueCb->drxUeCb.longCycleToBeUsed == false))
478 /* Starting Short Cycle Timer */
479 ueCb->drxUeCb.shortCycleDistance = (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen) / MAX_DRX_SIZE;
480 ueCb->drxUeCb.shortCycleExpiryIndex = (onDurTime + (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen)) % MAX_DRX_SIZE;
481 schAddDrxTimerIntoList(&cell->drxCb[ ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
482 DU_LOG("\nPBORLA ShortCycleE Added %d",ueCb->drxUeCb.shortCycleExpiryIndex);
486 * @brief Add entry into the on duration list and short cycle list
490 * Function : schAddUeInOndurationAndShortCycleList
492 * This function is used to Add entry into the on duration list and short
495 * @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur,
501 void schAddUeInOndurationAndShortCycleList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
505 SlotTimingInfo onDurationOccurance;
507 if(ueCb->ueDrxInfoPres)
509 findNextOndurationOccurance(cell, &ueCb->drxUeCb, &onDurationOccurance, delta);
510 onDurTime = onDurationOccurance.sfn*MAX_SLOTS+onDurationOccurance.slot;
511 onDurIndx = onDurTime%MAX_DRX_SIZE;
512 ueCb->drxUeCb.onDurationStartIndex = onDurIndx;
513 ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, MAX_SLOTS)/MAX_DRX_SIZE;
514 schAddDrxTimerIntoList(&cell->drxCb[onDurIndx].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo);
516 if((TRUE == ueCb->drxUeCb.shortCyclePresent) &&(ueCb->drxUeCb.longCycleToBeUsed == false))
518 /* Starting Short Cycle Timer */
519 ueCb->drxUeCb.shortCycleDistance = (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen) / MAX_DRX_SIZE;
520 ueCb->drxUeCb.shortCycleExpiryIndex = (onDurTime + (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen)) % MAX_DRX_SIZE;
521 schAddDrxTimerIntoList(&cell->drxCb[ ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
522 DU_LOG("\nPBORLA ShortCycleE Added %d",ueCb->drxUeCb.shortCycleExpiryIndex);
527 * @brief Handling of On duration drx start timer
531 * Function : schHdlDrxOnDurStrtTimerForUlandDlDirection
533 * Handling of On duration drx start timer
535 * @param[in] SchCellCb *cell
540 void schHdlDrxOnDurStrtTimerForUlandDlDirection(SchCellCb *cell, uint16_t currListIndx, bool isDlDirection)
542 uint16_t onDurationExpiry=0;
543 CmLList *drxCurrNode = NULLP;
544 SchUeCb *ueCb = NULLP;
546 drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first;
549 /* Handling of dl On duration drx start list */
552 ueCb = (SchUeCb*)drxCurrNode->node;
553 ueCb->drxUeCb.onDurationStartDistance--;
554 if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE)
560 if(isDlDirection == true)
561 ueCb->drxUeCb.drxDlUeActiveStatus = true;
563 ueCb->drxUeCb.drxUlUeActiveStatus = true;
565 DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
567 /* If there is any entery present in onDurationExpiry list remove
568 * the entery from the list and recalculate the
569 * onDurationExpiry time and add it to list */
570 if(ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX)
572 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
573 SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
574 ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
577 /* onDurationExpiry = (current slot + onduration length) % MAX_DRX_SIZE*/
578 onDurationExpiry = (currListIndx + ueCb->drxUeCb.onDurationLen)%MAX_DRX_SIZE;
579 ueCb->drxUeCb.onDurationExpiryDistance = (ueCb->drxUeCb.onDurationLen)/MAX_DRX_SIZE;
580 schAddDrxTimerIntoList(&cell->drxCb[onDurationExpiry].onDurationExpiryList, ueCb, ueCb->drxUeCb.onDurationExpiryNodeInfo);
581 ueCb->drxUeCb.onDurationExpiryIndex = onDurationExpiry;
583 /* if there is any entry present in onduration list remove the entry from the list */
584 DU_LOG("\nPBORLA ONDURATION START HIT %d %d startIndx %d [%d %d]",\
585 currListIndx, ueCb->drxUeCb.onDurationStartDistance,ueCb->drxUeCb.onDurationStartIndex, cell->slotInfo.sfn,cell->slotInfo.slot);
586 cmLListDelFrm(&cell->drxCb[currListIndx].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
587 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
588 ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
589 /* if there long cycle length is used as the cycle length for onduration calculation then based on that calculating next onduration occurance
590 * other wise next onduration is calcuated based on short cycle
592 if(ueCb->drxUeCb.longCycleToBeUsed)
594 schAddUeInOndurationAndShortCycleList(cell, ueCb, 0);
597 drxCurrNode = drxCurrNode->next;
602 * @brief Handling of On duration drx start timer
606 * Function : schHdlDrxOnDurStrtTimer
608 * Handling of On duration drx start timer
610 * @param[in] SchCellCb *cell
615 void schHdlDrxOnDurStrtTimer(SchCellCb *cell)
617 uint16_t dlIndx = 0, ulIndx=0;
618 SlotTimingInfo dlSlotInfo, ulSlotInfo;
620 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA);
621 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA);
623 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
624 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
625 schHdlDrxOnDurStrtTimerForUlandDlDirection(cell, dlIndx, true);
626 schHdlDrxOnDurStrtTimerForUlandDlDirection(cell, ulIndx, false);
629 * @brief Handling of short cycle drx start timer
633 * Function : schHdlDrxStartShortCycleTimer
635 * Handling of short cycle drx start timer
637 * @param[in] SchCellCb *cell
642 void schHdlDrxStartShortCycleTimer(SchCellCb *cell, SchUeCb *ueCb)
644 ueCb->drxUeCb.longCycleToBeUsed = false;
645 schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
648 * @brief Handling of the DRX inactv timers start
652 * Function : schHdlDrxInActvStrtTmr
654 * Handling of DRX in active timers start
656 * @param[in] SchCellCb *cell
661 void schHdlDrxInActvStrtTmr(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta)
663 uint16_t slotIndx = 0;
664 SlotTimingInfo tmpSlotInfo;
666 if(ueCb->drxUeCb.inActvTimerLen == 0)
670 ADD_DELTA_TO_TIME(cell->slotInfo, tmpSlotInfo, delta);
671 slotIndx = (tmpSlotInfo.sfn*MAX_SLOTS+tmpSlotInfo.slot)%MAX_DRX_SIZE;
673 DU_LOG("\nPBORLA IN ACTV START HIT %d %d", cell->slotInfo.sfn, cell->slotInfo.slot);
674 /* if there is nay old entry present in the list remove the entry*/
675 if(ueCb->drxUeCb.inActvExpiryIndex != SCH_DRX_INVALID_INDEX)
677 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
678 SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
679 ueCb->drxUeCb.inActvExpiryIndex= SCH_DRX_INVALID_INDEX;
680 ueCb->drxUeCb.inActiveTmrExpiryDistance= SCH_DRX_INVALID_DISTANCE;
682 /* Adding the new entry in in activity timer list */
683 ueCb->drxUeCb.inActvExpiryIndex = (slotIndx + ueCb->drxUeCb.inActvTimerLen) % MAX_DRX_SIZE;
684 ueCb->drxUeCb.inActiveTmrExpiryDistance = (ueCb->drxUeCb.inActvTimerLen) / MAX_DRX_SIZE;
685 schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
687 /* Set the UE active for UL And Dl transfer */
688 ueCb->drxUeCb.drxDlUeActiveStatus = true;
689 ueCb->drxUeCb.drxUlUeActiveStatus = true;
690 DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
694 * @brief Handling of the DRX timers start
698 * Function : schHandleStartDrxTimer
700 * Handling of DRX timers start
702 * @param[in] SchCellCb *cell
707 void schHandleStartDrxTimer(SchCellCb *cell)
709 /* Handling the onduration start timea*/
710 schHdlDrxOnDurStrtTimer(cell);
714 * @brief Handling of the expiry ShortCycle DRX timers
718 * Function : schHdlDrxShortCycleExpiryTimerForUlandDlDirection
720 * Handling of expiry ShortCycle
722 * @param[in] SchCellCb *cell
727 void schHdlDrxShortCycleExpiryTimerForUlandDlDirection(SchCellCb *cell, uint16_t currListIndx, bool isDlDirection)
729 CmLList *drxCurrNode = NULLP;
730 SchUeCb *ueCb = NULLP;
731 SchUeCb *tempUeCb = NULLP;
733 drxCurrNode = cell->drxCb[currListIndx].shortCycleExpiryList.first;
736 /* Handling of dl On duration drx start list */
739 ueCb = (SchUeCb*)drxCurrNode->node;
740 if(ueCb->ueDrxInfoPres)
742 if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE)
743 ueCb->drxUeCb.shortCycleDistance--;
745 if(ueCb->drxUeCb.shortCycleDistance== SCH_DRX_INVALID_DISTANCE)
747 DU_LOG("\nPBORLA ShortCycleE EXP HIT %d",currListIndx);
748 ueCb->drxUeCb.longCycleToBeUsed = true;
749 /* Remove Short Cycle timer from the list */
750 cmLListDelFrm(&cell->drxCb[currListIndx].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo);
751 SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList));
752 ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX;
754 /* calculating the next duration eventÂ
755 If another entry is found in the On duration list, it must first be removed
756 before the next On duration occurrences may be calculated */
757 if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX)
759 cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo);
760 SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList));
761 tempUeCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE;
762 tempUeCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX;
764 if(isDlDirection == true)
765 schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
767 schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
773 drxCurrNode = drxCurrNode->next;
780 * @brief Handling of the expiry ShortCycle DRX timers
784 * Function :schHdlDrxShortCycleExpiryTimer
786 * Handling of expiry ShortCycle
788 * @param[in] SchCellCb *cell
793 void schHdlDrxShortCycleExpiryTimer(SchCellCb *cell)
795 uint16_t dlIndx = 0, ulIndx= 0;
796 SlotTimingInfo dlSlotInfo, ulSlotInfo;
798 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
799 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
800 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
801 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
803 schHdlDrxShortCycleExpiryTimerForUlandDlDirection(cell, dlIndx, true);
804 schHdlDrxShortCycleExpiryTimerForUlandDlDirection(cell, ulIndx, false);
808 * @brief Handling of the expiry onduration DRX timers for specific direction
812 * Function :schHdlDrxOnDurExpiryTimerForUlandDlDirection
814 * Handling of expiry onduration DRX timers
816 * @param[in] SchCellCb *cell
821 void schHdlDrxOnDurExpiryTimerForUlandDlDirection(SchCellCb *cell, uint16_t currListIndx, bool isDlDirection)
823 CmLList *drxCurrNode;
824 SchUeCb *ueCb = NULLP;
826 drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first;
829 /* Handling of dl On duration drx start list */
832 ueCb = (SchUeCb*)drxCurrNode->node;
833 if(ueCb->ueDrxInfoPres)
835 ueCb->drxUeCb.onDurationExpiryDistance--;
837 if(ueCb->drxUeCb.onDurationExpiryDistance== SCH_DRX_INVALID_DISTANCE)
840 DU_LOG("\nPBORLA ONDURATION EXP HIT %d[%d:%d]",currListIndx, cell->slotInfo.sfn, cell->slotInfo.slot);
842 /* delete on duration expiry timer from ueCb */
843 if(drxCurrNode->node)
845 cmLListDelFrm(&cell->drxCb[currListIndx].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo);
846 SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList));
847 ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX;
849 if(isDlDirection == true)
850 ueCb->drxUeCb.drxDlUeActiveStatus = false;
852 ueCb->drxUeCb.drxUlUeActiveStatus = false;
853 DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
858 drxCurrNode = drxCurrNode->next;
865 * @brief Handling of the expiry onduration DRX timers
869 * Function : schHdlDrxOnDurExpiryTimer
871 * Handling of expiry onduration DRX timers
873 * @param[in] SchCellCb *cell
878 void schHdlDrxOnDurExpiryTimer(SchCellCb *cell)
880 uint16_t dlIndx = 0, ulIndx = 0;
881 SlotTimingInfo dlSlotInfo, ulSlotInfo;
883 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
884 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
885 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
886 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
888 schHdlDrxOnDurExpiryTimerForUlandDlDirection(cell, dlIndx, true);
889 schHdlDrxOnDurExpiryTimerForUlandDlDirection(cell, ulIndx, false);
892 * @brief Handling of the expiry in active DRX timers in Dl and Ul direction
896 * Function : schHdlDrxInActvExpiryTimerForUlandDlDirection
898 * Handling of expiry in active DRX timers in DLand Ul direction
900 * @param[in] SchCellCb *cell, uint16_t dlIndx
905 void schHdlDrxInActvExpiryTimerForUlandDlDirection(SchCellCb *cell, uint16_t listIndx, bool isDlDirection)
908 SchUeCb *ueCb = NULLP;
910 drxNode = cell->drxCb[listIndx].inActvTmrExpiryList.first;
913 /* Handling of dl On duration drx start list */
916 ueCb = (SchUeCb*)drxNode->node;
917 ueCb->drxUeCb.inActiveTmrExpiryDistance--;
919 if(ueCb->drxUeCb.onDurationExpiryDistance== SCH_DRX_INVALID_DISTANCE)
921 DU_LOG("\nPBORLA IN ACTV EXP HIT %d[%d:%d]",listIndx, cell->slotInfo.sfn, cell->slotInfo.slot);
922 /*Delete the current entry from list */
925 cmLListDelFrm(&cell->drxCb[listIndx].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo);
926 SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList));
927 ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX;
930 /* If short cycle is configured then start the short cycle timer */
931 if(ueCb->drxUeCb.shortCyclePresent)
933 schHdlDrxStartShortCycleTimer(cell, ueCb);
937 ueCb->drxUeCb.longCycleToBeUsed = true;
939 /* Set the drx ue status as inactive once the in active timer gets
941 if(isDlDirection == true)
942 ueCb->drxUeCb.drxDlUeActiveStatus = false;
944 ueCb->drxUeCb.drxUlUeActiveStatus = false;
945 DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__);
950 drxNode = drxNode->next;
956 * @brief Handling of the expiry in active DRX timers
960 * Function :schHdlDrxInActvExpiryTimer
962 * Handling of expiry in active DRX timers
964 * @param[in] SchCellCb *cell
969 void schHdlDrxInActvExpiryTimer(SchCellCb *cell)
971 uint16_t dlIndx = 0, ulIndx = 0;
972 SlotTimingInfo dlSlotInfo, ulSlotInfo;
974 ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
975 ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA);
976 dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE;
977 ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE;
979 schHdlDrxInActvExpiryTimerForUlandDlDirection(cell, dlIndx, true);
980 schHdlDrxInActvExpiryTimerForUlandDlDirection(cell, ulIndx, false);
982 * @brief Handling of the expiry DRX timers
986 * Function : schHandleExpiryDrxTimer
988 * Handling of expiry DRX timers
990 * @param[in] SchCellCb *cell
995 void schHandleExpiryDrxTimer(SchCellCb *cell)
997 /* Handling the onduration start timer */
998 schHdlDrxShortCycleExpiryTimer(cell);
999 schHdlDrxOnDurExpiryTimer(cell);
1000 schHdlDrxInActvExpiryTimer(cell);
1005 /**********************************************************************
1007 **********************************************************************/