1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
5 # Licensed under the Apache License, Version 2.0 (the "License"); #
6 # you may not use this file except in compliance with the License. #
7 # You may obtain a copy of the License at #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
11 # Unless required by applicable law or agreed to in writing, software #
12 # distributed under the License is distributed on an "AS IS" BASIS, #
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
14 # See the License for the specific language governing permissions and #
15 # limitations under the License. #
16 ################################################################################
17 *******************************************************************************/
19 /************************************************************************
25 Desc: C source code for Entry point fucntions
29 **********************************************************************/
31 /** @file rg_sch_ram.c
32 @brief This file has APIs to handle the random access procedure functionality for the scheduler.
36 /* header include files (.h) */
37 #include "common_def.h"
39 #include "rg_env.h" /* MAC Environment Defines */
40 #include "rgr.h" /* RGR Interface defines */
41 #include "rgm.h" /* RGR Interface defines */
42 #include "tfu.h" /* TFU Interface defines */
43 #include "lrg.h" /* LRG Interface defines */
44 #include "rg_env.h" /* Scheduler error defines */
45 #include "rg_sch_inf.h" /* Scheduler defines */
46 #include "rg_sch_err.h" /* Scheduler error defines */
47 #include "rg_sch.h" /* Scheduler defines */
48 #include "rg_sch_cmn.h"
49 #include "rl_interface.h"
50 #include "rl_common.h"
52 /* header/extern include files (.x) */
54 #include "rgr.x" /* RGR Interface includes */
55 #include "rgm.x" /* RGR Interface includes */
56 #include "tfu.x" /* TFU Interface includes */
57 #include "lrg.x" /* LRG Interface includes */
59 #include "rg_sch_inf.x" /* typedefs for Scheduler */
60 #include "rg_sch.x" /* Scheduler includes */
61 #include "rg_sch_cmn.x"
63 Bool rgSCHRamVldtRgrEmtcUeCfg ARGS((
68 S16 rgSCHRamRmvAllFrmEmtcRaInfoSchdLst
72 Void rgSCHEmtcUtlUpdCmnNb
76 Void rgSCHEmtcHqPAlloc
84 static Void rgSCHRamUlFreeAllocation ARGS((RgSchUlSf *sf,RgSchUlAlloc *alloc,
85 RgSchCellCb *cell,Bool isEmtc));
87 static S16 rgSCHRamContResCrnti ARGS((RgSchCellCb *cell, RgSchUeCb *ue,
88 RgSchRaCb *raCb, RgSchErrInfo *err));
89 static S16 rgSCHRamContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
92 S16 rgSCHEmtcRamContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
93 S16 rgSCHRamEmtcContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
94 Void rgSCHChkEmtcContResGrdTmrExp ARGS((RgSchCellCb *cell));
95 Void rgSCHChkEmtcContResTmrExp ARGS((RgSchCellCb *cell));
96 Void rgSCHEmtcRaInfoFree ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
99 static Void rgSCHChkContResGrdTmrExp ARGS((RgSchCellCb *cell));
100 static Void rgSCHChkContResTmrExp ARGS((RgSchCellCb *cell));
101 static Void rgSCHRamProcContResExp ARGS((RgSchCellCb *cell,
103 static Void rgSCHRamProcContResGrdExp ARGS((RgSchCellCb *cell,
106 Void rgSCHChkEmtcContResGrdTmrExp ARGS((RgSchCellCb *cell));
107 Void rgSCHChkEmtcContResTmrExp ARGS((RgSchCellCb *cell));
110 /* forward references */
113 * @brief Check configured preamble id not colliding with non dedicated or PDCCH
114 * order preamble sets. When valid preamble id given check that C-RNTI given
115 * in configuration is not amongst the C-RNTI'smanaged by scheduler
119 * Function : rgSCHRamVldtUeCfg
121 * Processing Steps: Check configured preamble id not colliding with non dedicated or PDCCH
122 * order preamble sets. When valid preamble id given check that C-RNTI given
123 * in configuration is not amongst the C-RNTI'smanaged by scheduler
125 * @param[in] RgSchCellCb *cell
126 * @param[in] RgrUeCfg *ueCfg
131 S16 rgSCHRamVldtUeCfg(RgSchCellCb *cell,RgrUeCfg *ueCfg)
133 if (ueCfg->dedPreambleId.pres == PRSNT_NODEF)
135 if ((ueCfg->dedPreambleId.val < cell->rachCfg.numRaPreamble) ||
136 (ueCfg->dedPreambleId.val >= RGSCH_MAX_NUM_RA_PREAMBLE) ||
137 ((ueCfg->dedPreambleId.val >= cell->macPreambleSet.start) &&
138 (ueCfg->dedPreambleId.val <= cell->macPreambleSet.start +
139 cell->macPreambleSet.size - 1)) ||
140 ((ueCfg->crnti >= cell->rntiDb.rntiStart) &&
141 (ueCfg->crnti < cell->rntiDb.rntiStart + cell->rntiDb.maxRntis-1))
143 || (rgSCHRamVldtRgrEmtcUeCfg(cell,ueCfg))
154 * @brief Handler for Random Access Request
158 * Function : rgSCHRamProcRaReq
160 * -# Create a node for each TfuRaReqInfo element received
161 * -# Initialize the list with the above elements at the raRnti index
165 * @param[in] RgSchCellCb *cell
166 * @param[in] CmLteRnti raRnti
167 * @param[in] RgTfuRaReqInd *raReqInd
168 * @param[out] RgSchErrInfo *err
173 S16 rgSCHRamProcRaReq
178 TfuRachInfo *raReqInd,
179 CmLteTimingInfo timingInfo,
184 RgSchRaReqInfo *raReqInfo;
193 /* SR_RACH_STATS : RACH REQ */
194 rgNumPrachRecvd += raReqInd->numRaReqInfo;
196 /* ccpu00132523- Moved out this from for loop as updating of raIndex is
197 * relates to only raRnti and all preambles having same raRnti*/
199 /* UL subframes do not occupy all the subframes in a radio frame.
200 * So RA Rnti index to be calculated based on actual UL subframe index. */
201 /* Get the actual subframe number */
202 tid = (raRnti-1)%RGSCH_NUM_SUB_FRAMES;
203 /* Get the frequency index in the subframe */
204 fid = ((raRnti-1) / RGSCH_NUM_SUB_FRAMES)* RGSCH_NUM_SUB_FRAMES;
205 /* Get the index of RA RNTI in the array */
206 raIndex = ((timingInfo.sfn % cell->raInfo.maxRaSize) \
207 * RGSCH_MAX_RA_RNTI_PER_SUBFRM * RGSCH_NUM_SUB_FRAMES) + \
209 /* Fixes for RACH handling in TDD: Removed deletion of queued RaReq */
211 /* ccpu00132523- Placing the raReq into array based on RA SFN */
212 raIndex = (timingInfo.sfn & 1) * RGSCH_MAX_RA_RNTI + raRnti-1;
215 /* allocate new raReqInfos and enqueue them */
216 if (raReqInd->raReqInfoArr[raReqCnt].rapId >= RGSCH_MAX_NUM_RA_PREAMBLE)
218 DU_LOG("\nERROR --> SCH : RARNTI:%d rgSCHTomRaReqInd(): RAM processing failed", raReqInd->raRnti);
222 /* SR_RACH_STATS : DED PREAMB*/
223 if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
230 if (raReqInd->raReqInfoArr[raReqCnt].rapId < cell->rachCfg.sizeRaPreambleGrpA)
232 cell->raPrmbs.preamGrpA++;
234 else if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
236 cell->raPrmbs.dedPream++;
240 cell->raPrmbs.preamGrpB++;
244 if((rgSCHUtlAllocSBuf(cell->instIdx, (Data **)(&raReqInfo),
245 sizeof(RgSchRaReqInfo))) == RFAILED)
247 DU_LOG("\nERROR --> SCH : rgSCHRamProcRaReq(): Allocation"
248 " of RaReq failed RARNTI:%d",raRnti);
249 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
253 /* Insert the given raReqInfo */
255 raReqInfo->timingInfo = timingInfo;
256 raReqInfo->raReq = raReqInd->raReqInfoArr[raReqCnt];
257 raReqInfo->raReqLstEnt.next = NULLP;
258 raReqInfo->raReqLstEnt.prev = NULLP;
259 raReqInfo->raReqLstEnt.node = (PTR)raReqInfo;
264 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->raInfo.raReqLst, raIndex);
266 /* RACHO: If dedicated preamble, then give preference by appending at front */
267 if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
269 cmLListFirst(&cell->raInfo.raReqLst[raIndex]);
270 cmLListInsCrnt(&cell->raInfo.raReqLst[raIndex], &raReqInfo->raReqLstEnt);
274 cmLListAdd2Tail(&cell->raInfo.raReqLst[raIndex], &raReqInfo->raReqLstEnt);
278 } /* rgSCHRamProcRaReq */
281 * @brief Handler for Random Access control block creation
285 * Function : rgSCHRamCreateRaCb
286 * Creates a raCb and gives the same to scheduler for its updation
289 * @param[in] RgSchCellCb *cell
290 * @param[in, out] RgSchRaCb **raCb
291 * @param[out] RgSchErrInfo *err
296 S16 rgSCHRamCreateRaCb
303 RgSchRntiLnk *rntiLnk;
304 Inst inst = cell->instIdx;
307 if((rgSCHUtlAllocSBuf(inst, (Data **)(raCb),
308 sizeof(RgSchRaCb))) == RFAILED)
310 DU_LOG("\nERROR --> SCH : rgSCHRamCreateRaCb(): Allocation of "
312 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
316 rntiLnk = rgSCHDbmGetRnti(cell);
319 (*raCb)->rntiLnk = rntiLnk;
320 (*raCb)->tmpCrnti = rntiLnk->rnti;
325 /* SR_RACH_STATS: RNTI POOL Exhaution */
326 rgNumRarFailDuetoRntiExhaustion++;
328 /* No rnti available! */
329 DU_LOG("\nERROR --> SCH : rgSCHRamCreateRaCb(): Allocation of "
330 "temporary RNTI failed at MAC(CRNTI exhausted)");
331 /* ccpu00117052 - MOD - Passing double pointer
332 for proper NULLP assignment*/
333 rgSCHUtlFreeSBuf(inst, (Data **)(raCb), sizeof(RgSchRaCb));
334 err->errCause = RGSCHERR_RAM_RNTI_EXHAUST;
338 /* Allocate and initialize the DL HARQ portion of the RACB */
339 (*raCb)->dlHqE = rgSCHDhmHqEntInit(cell);
340 if ((*raCb)->dlHqE == NULLP)
342 /* No memory available! */
343 DU_LOG("\nERROR --> SCH : rgSCHRamCreateRaCb(): Creation of"
345 /* ccpu00117052 - MOD - Passing double pointer
346 for proper NULLP assignment*/
347 rgSCHUtlFreeSBuf(inst, (Data **)(raCb), sizeof(RgSchRaCb));
348 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
352 (*raCb)->isEmtcRaCb = FALSE;
353 rgSCHEmtcHqPAlloc(cell, (*raCb)->dlHqE);
355 (*raCb)->dlHqE->raCb = (*raCb);
356 /* Initialize RaCb's contents */
357 (*raCb)->timingInfo = cell->crntTime;
358 (*raCb)->raState = RGSCH_RA_MSG3_PENDING;
359 (*raCb)->toDel = FALSE;
360 (*raCb)->phr.pres = FALSE;
362 /* Insert the created raCb into raCb list of cell */
363 (*raCb)->raCbLnk.node = (PTR)(*raCb);
364 cmLListAdd2Tail(&cell->raInfo.raCbLst, &(*raCb)->raCbLnk);
367 } /* rgSCHRamCreateRaCb */
370 * @brief Handler for Ue Configuration Request
374 * Function : rgSCHRamRgrUeCfg
376 * This function handles the UE config received based on the state of the
378 * -# If raCb is in RGSCH_RA_MSG4_PENDING state, it shall update the harq
379 * information to UeCb and update the references.
380 * -# If raCb is in RGSCH_RA_MSG4_DONE, then it shall free the raCb
383 * @param[in] RgSchCellCb *cell
384 * @param[in,out] RgSchUeCb *ue
385 * @param[in,out] RgSchRaCb *raCb
386 * @param[out] RgSchErrInfo *err
399 /* Releasing HARQ processes of old UE when ue
400 * reconfig with new crnti */
402 RgSchDlHqEnt **hqEnt = &(RG_SCH_CMN_GET_UE_HQE(ue, cell));
403 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
406 /* Fix : set UE inactive in DL until UE is reinitialization completed */
407 ue->dl.dlInactvMask |= RG_HQENT_INACTIVE;
408 ue->ul.ulInactvMask |= RG_HQENT_INACTIVE;
410 if(raCb->raState == RGSCH_RA_MSG4_PENDING)
413 ue->rntiLnk = raCb->rntiLnk;
414 /* Update UL Harq process information */
415 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
416 ueUl->hqEnt.hqProcCb[raCb->msg3HqProcId].ndi = raCb->msg3HqProc.ndi;
418 else if(raCb->raState == RGSCH_RA_MSG4_DONE)
420 ue->rntiLnk = raCb->rntiLnk;
421 /* Update UL Harq process information */
422 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
423 ueUl->hqEnt.hqProcCb[raCb->msg3HqProcId].ndi = raCb->msg3HqProc.ndi;
424 /* Fix : syed Assign hqEnt to UE only if msg4 is done */
425 rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb);
429 err->errCause = RGSCHERR_RAM_NO_MSG3_RCVD;
431 raCb->dlHqE->ue = NULLP;
436 } /* rgSCHRamRgrUeCfg */
440 * @brief Handler for C-RNTI based contention resolution
444 * Function : rgSCHRamContResCrnti
446 * This function shall be invoked once Msg3 indicates C-RNTI based
447 * contention resolution.This shall indicate the scheduler regarding
448 * C-RNTI based uplink grant.
451 * @param[in,out] RgSchCellCb *cell
452 * @param[in,out] RgSchUeCb *ue
453 * @param[in,out] RgSchRaCb *raCb
457 static S16 rgSCHRamContResCrnti
465 TfuUlCqiRpt ulCqiRpt;
466 RgSchCmnCell *cellSch= (RgSchCmnCell *)(cell->sc.sch);
469 /* Fix: syed It is incorrect to copy over msg3HqProc to ueCb's
470 * UL harq proc. In case of Crnti based RACH, ueCb has valid context which
471 * cannot be over written. It was leading to a crash. */
473 rgSCHUtlRecMsg3Alloc(cell, ue, raCb);
475 /* Fix for ccpu00123908: Reset the UL CQI to the cell default value here */
476 ulCqiRpt.isTxPort0 = TRUE;
477 ulCqiRpt.numSubband = 0;
478 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
479 ulCqiRpt.rnti = ue->ueId;
480 /* rg002.301:[ccpu00124018]-MOD- Avoiding hard coding of CQI and retriving from cell config*/
481 ulCqiRpt.wideCqi = cellSch->ul.dfltUlCqi;
482 rgSCHUtlUlCqiInd(cell, ue, &ulCqiRpt);
485 /* Invoke scheduler to indicate UL grant req for contention resolution */
486 rgSCHUtlContResUlGrant(cell, ue, err);
488 if (raCb->phr.pres == TRUE)
490 rgSCHUtlUpdPhr(cell, ue, raCb->phr.val, err);
492 /* No need of raCb any more */
493 rgSCHRamDelRaCb(cell, raCb, TRUE);
496 } /* rgSCHRamContResCrnti */
500 * @brief Handler for CCCH SDU based contention resolution
504 * Function : rgSCHRamContResCcchsdu
506 * This function shall be invoked once Msg3 indicates contention resolution
507 * based on CCCH sdu. This shall update the raCb state to
508 * RGSCH_RA_MSG4_PENDING.
511 * @param[in,out] RgSchRaCb *raCb
515 static S16 rgSCHRamContResCcchsdu
522 CmLteTimingInfo expTime = {0};
523 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
525 if(raCb->raState != RGSCH_RA_MSG3_PENDING)
527 DU_LOG("\nERROR --> SCH : RNTI:%d RaCb in wrong State %d Drop Msg 3",
533 raCb->raState = RGSCH_RA_MSG4_PENDING;
536 if(cell->rachCfg.contResTmr - cellSch->dl.msg4TxDelay > 0)
538 /* Set the contension resolution guard timer =
539 Cont Res Timer - Max msg4 Tx Delay */
540 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, expTime,
541 (cell->rachCfg.contResTmr - cellSch->dl.msg4TxDelay));
545 /* Schedule the CRI CE in the next Sf itself */
546 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, expTime, 1);
548 raCb->expiryTime = expTime;
549 raCb->contResTmrLnk.node = (PTR)(raCb);
550 cmLListAdd2Tail(&(cell->contResGrdTmrLst), &(raCb->contResTmrLnk));
553 } /* rgSCHRamContResCcchsdu */
557 * @brief Handler for Msg3
561 * Function : rgSCHRamProcMsg3
563 * This function processes the received Msg3 and identifies the type of
564 * contention resolution and act accordingly.
567 * @param[in,out] RgSchCellCb *cell
568 * @param[in,out] RgSchUeCb *ue
569 * @param[in,out] RgSchRaCb *raCb
584 /* Update raCb with PHR if received along with Msg3 */
585 if (pdu->ceInfo.bitMask & RGSCH_PHR_CE_PRSNT)
588 raCb->phr.pres = TRUE;
589 raCb->phr.val = pdu->ceInfo.ces.phr;
593 rgSCHRamContResCrnti(cell, ue, raCb, err);
598 if(TRUE == raCb->isEmtcRaCb)
600 /* starting the emtc Contention resolution timer */
601 rgSCHRamEmtcContResCcchsdu(cell,raCb);
606 rgSCHRamContResCcchsdu(cell, raCb);
611 } /* rgSCHRamProcMsg3 */
615 * @brief Handler for Updating Bo received in StaRsp
619 * Function : rgSCHRamUpdtBo
621 * This function shall be invoked by RAM once it receives staRsp on CCCH
623 * @param[in] RgSchCellCb *cell
624 * @param[in,out] RgSchRaCb *raCb
625 * @param[in] RgRguCmnStaRsp *staRsp
633 RgInfCmnBoRpt *staRsp
637 /* Update Bo in RaCb */
638 raCb->dlCcchInfo.bo = (uint32_t)(staRsp->bo);
639 /* SR_RACH_STATS : MSG4 WITH CCCH SDU */
640 rgNumMsg4WithCCCHSdu++;
642 /* add this to the "tobeSchdLst" */
644 rgSCHRamAddToRaInfoSchdLst(cell, raCb);
648 } /* rgSCHRamUpdtBo */
651 * @brief Handler for Msg3 Feedback indication
655 * Function : rgSCHRamMsg3DatInd
657 * This function shall be invoked by TOM once the transmission of Msg4 is
659 * This shall invoke UHM to set ACK for Msg3 reception.
661 * @param[in,out] RgSchRaCb *raCb
665 S16 rgSCHRamMsg3DatInd(RgSchRaCb *raCb)
668 /* SR_RACH_STATS : MSG3 ACK*/
669 rgNumMsg3CrcPassed++;
670 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
671 rgSCHUhmProcMsg3DatInd(&(raCb->msg3HqProc));
674 } /* rgSCHRamMsg3DatInd */
677 * @brief Handler for Msg3 Feedback indication
681 * Function : rgSCHRamMsg3FailureInd
683 * This function shall be invoked by TOM once the transmission of Msg4 is
685 * This shall invoke UHM to set ACK for Msg3 reception.
687 * @param[in,out] RgSchRaCb *raCb
691 S16 rgSCHRamMsg3FailureInd(RgSchRaCb *raCb)
694 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
695 rgSCHUhmProcMsg3Failure(&(raCb->msg3HqProc));
698 } /* rgSCHRamMsg3FailureInd */
701 * @brief Handler for Msg4 Feedback indication
705 * Function : rgSCHRamMsg4FdbkInd
707 * This function shall be invoked by TOM once the transmission of Msg4 is
709 * This shall invoke UHM to set ACK for Msg3 reception.
711 * @param[in,out] RgSchRaCb *raCb
715 S16 rgSCHRamMsg4FdbkInd(RgSchRaCb *raCb)
719 } /* rgSCHRamMsg4FdbkInd */
723 * @brief Handler for Msg4 state updation
727 * Function : rgSCHRamMsg4Done
729 * This function shall be invoked by DHM once the transmission of Msg4 is
730 * done. This shall delete the raCb if there is a valid Ue or if this is to
731 * be deleted. If not this shall update the state of the raCb.
734 * @param[in] RgSchCellCb *cell
735 * @param[in,out] RgSchRaCb *raCb
739 S16 rgSCHRamMsg4Done(RgSchCellCb *cell,RgSchRaCb *raCb)
742 DU_LOG("\nDEBUG --> SCH : rgSCHRamMsg4Done(): tmpCRNTI = %u",
745 if(raCb->ue != NULLP)
747 /* Fix : syed Let this funtion decide on releasing
748 * hqP than the caller of this function otherwise sometimes it
749 * might lead to incorrec NDI setting. */
750 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
751 /* Fix : syed Assign hqEnt to UE only if msg4 is done */
752 rgSCHDhmAssgnUeHqEntFrmRaCb(raCb->ue, raCb);
754 if(TRUE == raCb->isEmtcRaCb)
756 rgSCHEmtcUtlUpdCmnNb(raCb);
759 /* MS_FIX :Proceed to CCCH scheduling irrespective of
761 if (raCb->ue->dlCcchInfo.bo)
764 /*if CR-ID Ack has been received ,Add emtc Ue to cchSduUeLst*/
765 if(TRUE == raCb->isEmtcRaCb)
767 rgSCHUtlAddUeToEmtcCcchSduLst(cell, raCb->ue);
772 rgSCHUtlAddUeToCcchSduLst(cell, raCb->ue);
775 /* Rnti shall not be released as Ue exists with this rnti */
776 rgSCHRamDelRaCb(cell, raCb, FALSE);
778 else if(raCb->toDel == TRUE)
780 #ifdef XEON_SPECIFIC_CHANGES
781 DU_LOG("\nDEBUG --> SCH : Deleting RacB:%d\n", raCb->tmpCrnti);
783 /* Delete RACB and release RNTI */
784 rgSCHRamDelRaCb(cell, raCb, TRUE);
788 #ifdef XEON_SPECIFIC_CHANGES
789 DU_LOG("\nDEBUG --> SCH : Releasing Harq of RacB:%d\n", raCb->tmpCrnti);
791 raCb->raState = RGSCH_RA_MSG4_DONE;
792 /* Release harq process as final feedback is received for Msg4. In other
793 * cases, delRaCb will take care of releasing the harq process */
794 DU_LOG("\nDEBUG --> SCH : Harq process released ");
795 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
799 } /* rgSCHRamMsg4Done */
803 * @brief Handler for deletion
807 * Function : rgSCHRamDelRaCb
809 * This function shall be invoked whenever a raCb needs to be deleted.
810 * Invoked by both RAM and downlink scheduler
812 * @param[in] RgSchCellCb *cell
813 * @param[in,out] RgSchRaCb *raCb
814 * @param[in] Bool rlsRnti
819 S16 rgSCHRamDelRaCb(RgSchCellCb *cell,RgSchRaCb *raCb,Bool rlsRnti)
821 Inst inst = cell->instIdx;
824 /* Delete from all the lists it is enqueued */
825 cmLListDelFrm(&(cell->raInfo.raCbLst),&(raCb->raCbLnk));
827 /*ue Type is EMTC, then Delete the toBeSchedLst and stop the Guard Timer */
828 if(TRUE == raCb->isEmtcRaCb)
830 rgSCHRamEmtcDelRaCb(cell,raCb);
836 if (raCb->schdLnk.node == (PTR)raCb)
838 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb);
841 else if(raCb->contResTmrLnk.node != NULLP)
843 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
844 raCb->contResTmrLnk.node = NULLP;
851 rgSCHUtlRlsRnti(cell, raCb->rntiLnk, FALSE, 0);
854 /* Check if msg4 Hq Proc has been released. If not, release it */
857 if (raCb->dlHqE->msg4Proc != NULLP)
859 /* Fix: syed Remove the msg4Proc if it waiting in sf->tbs list for
861 if ((raCb->dlHqE->msg4Proc->subFrm != NULLP) &&
862 (raCb->dlHqE->msg4Proc->hqPSfLnk.node != NULLP))
864 DU_LOG("\nERROR --> SCH : TMP CRNTI:%d RACH FAILURE!! "
865 "msg4proc removed from SF", raCb->tmpCrnti);
866 rgSCHUtlDlHqPTbRmvFrmTx(raCb->dlHqE->msg4Proc->subFrm,
867 raCb->dlHqE->msg4Proc, 0, FALSE);
869 /* Fix: syed Remove the msg4Proc from cell
870 * msg4Retx Queue. I have used CMN scheduler function
871 * directly. Please define a new API and call this
872 * function through that. */
873 rgSCHCmnDlMsg4ProcRmvFrmRetx(cell, raCb->dlHqE->msg4Proc);
874 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
877 /* Mark the raCb pointer in dlHqE to NULLP */
878 raCb->dlHqE->raCb = NULLP;
880 rgSCHDhmDelHqEnt(cell, &raCb->dlHqE);
882 /* Fix: syed Adaptive Msg3 Retx crash. Remove the harqProc
883 * from adaptive retx List. Free the alloc if it exists. */
884 if (raCb->msg3HqProc.reTxLnk.node)
886 //TODO_SID: Need to take care of retxLst
887 //cmLListDelFrm(raCb->msg3HqProc.reTxAlloc.reTxLst, &raCb->msg3HqProc.reTxLnk);
888 raCb->msg3HqProc.reTxLnk.node = (PTR)NULLP;
891 if (raCb->msg3HqProc.alloc)
893 /* Fix: syed During GPR, please write an API instead of direct
894 * call to cmn scheduler function */
895 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
896 /*ccpu00130356 - MOD- To avoid segmentation problem because of double
897 free due to recursive calling of rgSCHRamDelRaCb*/
898 rgSCHRamUlFreeAllocation(&cellUl->ulSfArr[raCb->msg3HqProc.ulSfIdx],
899 raCb->msg3HqProc.alloc,
904 if(TRUE == raCb->isEmtcRaCb)
906 rgSCHEmtcRaInfoFree(cell, raCb);
909 rgSCHUtlFreeSBuf(inst, (Data **)&raCb, sizeof(RgSchRaCb));
912 } /* rgSCHRamDelRaCb */
916 * @brief TTI Handler for RAM module
920 * Function : rgSCHRamTtiHndlr
922 * This function shall be invoked upon TtiInd by TOM
924 * - remove RaReqs added to the queue for a raRnti for which PHY may
925 * give the requests in the next subframe
926 * - remove raCbs which are not yet processed once the
927 * counter for raCb processing expires.
930 * @param[in,out] RgSchCellCb *cell
934 S16 rgSCHRamTtiHndlr(RgSchCellCb *cell)
939 uint16_t dist; /* Number of frames between raCb's creation and crnt frame */
945 RgSchRaReqInfo *raReqInfo;
952 crntSfn = cell->crntTime.sfn;
955 /*Check if Contention resolution guard timer expiring in the TTI*/
956 rgSCHChkContResGrdTmrExp(cell);
957 /*Check if Contention resolution timer expiring in the TTI*/
958 rgSCHChkContResTmrExp(cell);
960 /*Check if EMTC Contention resolution guard timer expiring in the TTI*/
961 rgSCHChkEmtcContResGrdTmrExp(cell);
962 /*Check if EMTC Contention resolution timer expiring in the TTI*/
963 rgSCHChkEmtcContResTmrExp(cell);
968 /* Delete the RA requests for which RAR window expired in this subframe
969 * And were not considered for RAR scheduling*/
970 winGap = (rgRaPrmblToRaFrmTbl[cell->rachCfg.preambleFormat]-1)+
971 (cell->rachCfg.raWinSize -1 ) + RGSCH_RARSP_WAIT_PERIOD;
973 raIdx = (((crntSfn & 1) * RGSCH_MAX_RA_RNTI+ cell->crntTime.slot
974 + RG_SCH_CMN_DL_DELTA - winGap)+ RGSCH_RAREQ_ARRAY_SIZE )
975 % RGSCH_RAREQ_ARRAY_SIZE;
977 /* Flush the already existing raReqs against the given raRnti */
979 maxCnt = cell->raInfo.raReqLst[raIdx].count;
980 for (idx = 0; idx < maxCnt; idx++)
982 raReqInfo = (RgSchRaReqInfo *)(cell->raInfo.raReqLst[raIdx].first->node);
983 cmLListDelFrm(&(cell->raInfo.raReqLst[raIdx]),&(raReqInfo->raReqLstEnt));
984 /* ccpu00117052 - MOD - Passing double pointer
985 for proper NULLP assignment*/
986 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&raReqInfo,
987 sizeof(RgSchRaReqInfo));
990 /* Fixes for RACH handling: Added deletion of queued RaReq */
991 frm = cell->crntTime;
992 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
993 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][frm.slot] !=
994 RG_SCH_TDD_UL_SUBFRAME)
996 raIdx = rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][frm.slot]-1;
997 rgSCHRamDelRaReq(cell, cell->crntTime, raIdx);
1001 /* Remove the RACBs which are timed out */
1002 /* ccpu00132536:MOD- racb timeout will be verified in each SFN such that
1003 * the RACB whose processing is not completed in RG_MAX_RA_PRC_FRM
1005 if (cell->crntTime.slot == 0)
1007 maxCnt = cell->raInfo.raCbLst.count;
1008 for (idx = 0; idx < maxCnt; idx++)
1010 raCb = (RgSchRaCb *)(cell->raInfo.raCbLst.first->node);
1011 /* Calculate number of frames between raCb's creation and crnt frame */
1012 raSfn = raCb->timingInfo.sfn;
1013 dist = (crntSfn + (RGSCH_MAX_SFN - raSfn)) % RGSCH_MAX_SFN;
1014 /* Delete RaCbs whose processing is not complete within
1015 * "cell->t300TmrVal" frames */
1016 /* raCb not to be deleted if msg4 is not completed */
1017 /* raCb should not be deleted(RNTI should not be released) if UE is present
1018 * as it means the application still holds the RNTI. raCb will get deleted
1019 * as part of UE deletion. raCb will anyway get deleted without releasing RNTI on success/failure of MSG4*/
1021 if (dist >= cell->t300TmrVal)
1023 if ((raCb->dlHqE->msg4Proc == NULLP) && (raCb->dlHqE->ue == NULLP))
1025 rgSCHRamDelRaCb(cell, raCb, TRUE);
1036 } /* rgSCHRamTtiHndlr */
1040 * @brief Function for handling cell delete
1044 * Function : rgSCHRamFreeCell
1046 * This function shall be invoked whenever a cell needs to be deleted.
1047 * This shall remove raCbs and raReqs stored in cell.
1050 * @param[in,out] RgSchCellCb *cell
1054 S16 rgSCHRamFreeCell(RgSchCellCb *cell)
1056 RgSchRaReqInfo *raReqInfo;
1060 Inst inst = cell->instIdx;
1063 uint8_t maxUlSubframes;
1064 uint8_t maxDlSubframes;
1072 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1074 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1075 lstSz = cell->raInfo.maxRaSize * RGSCH_MAX_RA_RNTI_PER_SUBFRM * \
1078 /* ccpu00133557- MEM LEAK FIX- Need to free all the nodes in RA Array list */
1079 lstSz = RGSCH_RAREQ_ARRAY_SIZE;
1082 for (idx = 0; idx < lstSz; idx++)
1084 /* Delete and free raReqs stored */
1085 /* ccpu00133557- MEM LEAK FIX- Need to be freed till the count is non-zero */
1086 while(cell->raInfo.raReqLst[idx].count)
1088 raReqInfo = (RgSchRaReqInfo *)(cell->raInfo.raReqLst[idx].first->node);
1089 cmLListDelFrm(&(cell->raInfo.raReqLst[idx]),&(raReqInfo->raReqLstEnt));
1090 /* ccpu00117052 - MOD - Passing double pointer
1091 for proper NULLP assignment*/
1092 rgSCHUtlFreeSBuf(inst, (Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
1097 /* Delete the RACH response list*/
1098 /* ccpu00117052 - MOD - Passing double pointer
1099 for proper NULLP assignment*/
1100 rgSCHUtlFreeSBuf(inst,
1101 (Data **)(&(cell->rachRspLst)), sizeof(RgSchTddRachRspLst) * \
1105 /* Delete raCbs in the "to be scheduled" list */
1106 /* ccpu00133557- MEM LEAK FIX- Need to be freed till the count is non-zero */
1107 while(cell->raInfo.toBeSchdLst.count)
1109 raCb = (RgSchRaCb *)(cell->raInfo.toBeSchdLst.first->node);
1110 /* MSG4 Fix Start */
1112 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb);
1116 /* Delete raCbs in the "Emtc to be scheduled" list */
1117 if(cell->emtcEnable)
1119 rgSCHRamRmvAllFrmEmtcRaInfoSchdLst(cell);
1123 raCbCnt = cell->raInfo.raCbLst.count;
1125 /* Delete and free raCbs stored */
1126 for (idx = 0; idx < raCbCnt; idx++)
1128 raCb = (RgSchRaCb *)(cell->raInfo.raCbLst.first->node);
1129 rgSCHRamDelRaCb(cell, raCb, TRUE);
1133 } /* rgSCHRamFreeCell */
1135 static Void rgSCHRamProcContResExp(RgSchCellCb *cell,RgSchRaCb *raCb)
1137 raCb->expiryTime.sfn = RGSCH_CONTRES_EXP;
1141 /* UE exists and RNTI will be released as part of UE DEL */
1142 rgSCHRamDelRaCb(cell, raCb, FALSE);
1146 /* Calling Release RNTI, which would perform Racb deletion
1147 * RNTI removal and RNTI release indication to MAC. */
1148 /* Delete RACB and release RNTI */
1149 rgSCHRamDelRaCb(cell, raCb, TRUE);
1154 static Void rgSCHRamProcContResGrdExp(RgSchCellCb *cell,RgSchRaCb *raCb)
1158 /*Guard timer has expired, schedule only the contention REsolution CE with
1160 raCb->dlCcchInfo.bo = 0;
1161 /* SR_RACH_STATS : MSG4 WO CCCH SDU */
1162 rgNumMsg4WoCCCHSdu++;
1164 /* add this to the "tobeSchdLst" */
1165 raCb->schdLnk.node = (PTR)(raCb);
1167 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
1168 raCb->contResTmrLnk.node = NULLP;
1170 /* MSG4 Fix Start */
1171 DU_LOG("\nDEBUG --> SCH : Con Res Grd Tmr exp RNTI:%d",
1172 raCb->rntiLnk->rnti);
1173 rgSCHRamAddToRaInfoSchdLst(cell, raCb);
1179 * @brief Check the Contention Resolution Guard Timer Expiry.
1183 * Function: rgSCHChkContResTmrExp
1186 * Invoked by: Scheduler
1187 * @param[in] RgSchCellCb *cell
1192 static Void rgSCHChkContResTmrExp(RgSchCellCb *cell)
1194 CmLList *chkLnk = NULLP;
1195 RgSchRaCb *raCb = NULLP;
1198 chkLnk = cmLListFirst(&(cell->contResTmrLst));
1200 for (; chkLnk; chkLnk = chkLnk->next)
1202 raCb = (RgSchRaCb *)(chkLnk->node);
1204 if(RGSCH_TIMEINFO_SAME(raCb->expiryTime, cell->crntTime))
1206 /*If timer expired, call the handler function*/
1207 rgSCHRamProcContResExp(cell, raCb);
1209 /*Fix: Need to traverse till end of list as the entries may not be in ascending order*/
1217 * @brief Check the Contention Resolution Guard Timer Expiry.
1221 * Function: rgSCHChkContResGrdTmrExp
1224 * Invoked by: Scheduler
1225 * @param[in] RgSchCellCb *cell
1230 static Void rgSCHChkContResGrdTmrExp(RgSchCellCb *cell)
1232 CmLList *chkLnk = NULLP;
1233 RgSchRaCb *raCb = NULLP;
1236 chkLnk = cmLListFirst(&(cell->contResGrdTmrLst));
1238 /*[ccpu00131941]-MOD-List traversal should be done using the listCp */
1239 for (; chkLnk; chkLnk = cmLListNext(&cell->contResGrdTmrLst))
1241 raCb = (RgSchRaCb *)(chkLnk->node);
1243 if(RGSCH_TIMEINFO_SAME(raCb->expiryTime, cell->crntTime))
1245 /*If timer expired, call the handler function*/
1246 rgSCHRamProcContResGrdExp(cell, raCb);
1257 * @brief Function for handling RACH Request deletion
1261 * Function : rgSCHRamDelRaReq
1263 * This function shall be invoked to delete the RACH Requests
1264 * that is not scheduled within the RA window size.
1267 * @param[in,out] RgSchCellCb *cell
1268 * @param[in] CmLteTimingInfo timingInfo
1269 * @param[in] uint8_t raIdx
1273 S16 rgSCHRamDelRaReq
1276 CmLteTimingInfo timingInfo,
1281 RgSchTddRachRspLst *rachRsp;
1285 RgSchRaReqInfo *raReqInfo;
1293 rachRsp = &cell->rachRspLst[raIdx];
1294 /* Get the SFN Index to be deleted */
1295 calcSfn = timingInfo.sfn - rachRsp->delInfo.sfnOffset;
1298 sfnIdx = (calcSfn + RGSCH_MAX_SFN) % cell->raInfo.maxRaSize;
1305 /* Iterate through all the subframes to be delted in the SFN */
1306 for(subfrmIdx=0; subfrmIdx < rachRsp->delInfo.numSubfrms; subfrmIdx++)
1308 subfrm = rachRsp->delInfo.subframe[subfrmIdx];
1309 /* Get the subframe Index to be deleted */
1310 /* Fixes for RACH handling in TDD:
1311 * Corrected the computation of raRntiIdx
1313 raRntiIdx = ((sfnIdx % cell->raInfo.maxRaSize) * \
1314 RGSCH_MAX_RA_RNTI_PER_SUBFRM * \
1315 RGSCH_NUM_SUB_FRAMES) + subfrm;
1317 /* Iterate through all the RNTIs in the subframe */
1318 for(i=0; i < RGSCH_MAX_RA_RNTI_PER_SUBFRM; i++)
1320 raRnti = raRntiIdx + (i*RGSCH_NUM_SUB_FRAMES);
1321 for (idx = 0; idx < cell->raInfo.raReqLst[raRnti].count; idx++)
1324 (RgSchRaReqInfo *)(cell->raInfo.raReqLst[raRnti].first->node);
1325 cmLListDelFrm(&(cell->raInfo.raReqLst[raRnti]),
1326 &(raReqInfo->raReqLstEnt));
1327 /* ccpu00117052 - MOD - Passing double pointer
1328 for proper NULLP assignment*/
1329 rgSCHUtlFreeSBuf(cell->instIdx,
1330 (Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
1340 S16 rgSCHRamAddToRaInfoSchdLst(RgSchCellCb *cell,RgSchRaCb *raCb)
1342 CmLteTimingInfo expTime ={0};
1343 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
1346 /*Fix: This can be called even when guard timer is not expired.
1347 * In this case CR timer expiry should be guard timer expiry time + Guard timer time*/
1348 RG_SCH_ADD_TO_CRNT_TIME(raCb->expiryTime, expTime, cellSch->dl.msg4TxDelay);
1349 raCb->expiryTime = expTime;
1350 raCb->schdLnk.node = (PTR)(raCb);
1351 cmLListAdd2Tail(&(cell->raInfo.toBeSchdLst), &(raCb->schdLnk));
1352 raCb->contResTmrLnk.node = (PTR)(raCb);
1353 cmLListAdd2Tail(&(cell->contResTmrLst), &(raCb->contResTmrLnk));
1355 } /* rgSCHRamAddToRaInfoSchdLst */
1359 S16 rgSCHRamRmvFrmRaInfoSchdLst(RgSchCellCb *cell,RgSchRaCb *raCb)
1362 cmLListDelFrm(&(cell->raInfo.toBeSchdLst), &(raCb->schdLnk));
1363 raCb->schdLnk.node = NULLP;
1364 cmLListDelFrm(&(cell->contResTmrLst), &(raCb->contResTmrLnk));
1365 raCb->contResTmrLnk.node = NULLP;
1367 } /* rgSCHRamRmvFrmRaInfoSchdLst */
1371 /***********************************************************
1373 * Func : rgSCHRamUlFreeAllocation
1375 * Desc : Free an allocation - invokes UHM and releases
1384 **********************************************************/
1385 static Void rgSCHRamUlFreeAllocation
1388 RgSchUlAlloc *alloc,
1394 rgSCHUhmFreeProc(alloc->hqProc, cell);
1397 rgSCHUtlUlAllocRls(sf, alloc);
1402 /**********************************************************************
1405 **********************************************************************/