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"
50 /* header/extern include files (.x) */
52 #include "rgr.x" /* RGR Interface includes */
53 #include "rgm.x" /* RGR Interface includes */
54 #include "tfu.x" /* TFU Interface includes */
55 #include "lrg.x" /* LRG Interface includes */
57 #include "rg_sch_inf.x" /* typedefs for Scheduler */
58 #include "rg_sch.x" /* Scheduler includes */
59 #include "rg_sch_cmn.x"
61 Bool rgSCHRamVldtRgrEmtcUeCfg ARGS((
66 S16 rgSCHRamRmvAllFrmEmtcRaInfoSchdLst
70 Void rgSCHEmtcUtlUpdCmnNb
74 Void rgSCHEmtcHqPAlloc
82 static Void rgSCHRamUlFreeAllocation ARGS((RgSchUlSf *sf,RgSchUlAlloc *alloc,
83 RgSchCellCb *cell,Bool isEmtc));
85 static S16 rgSCHRamContResCrnti ARGS((RgSchCellCb *cell, RgSchUeCb *ue,
86 RgSchRaCb *raCb, RgSchErrInfo *err));
87 static S16 rgSCHRamContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
90 S16 rgSCHEmtcRamContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
91 S16 rgSCHRamEmtcContResCcchsdu ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
92 Void rgSCHChkEmtcContResGrdTmrExp ARGS((RgSchCellCb *cell));
93 Void rgSCHChkEmtcContResTmrExp ARGS((RgSchCellCb *cell));
94 Void rgSCHEmtcRaInfoFree ARGS((RgSchCellCb *cell, RgSchRaCb *raCb));
97 static Void rgSCHChkContResGrdTmrExp ARGS((RgSchCellCb *cell));
98 static Void rgSCHChkContResTmrExp ARGS((RgSchCellCb *cell));
99 static Void rgSCHRamProcContResExp ARGS((RgSchCellCb *cell,
101 static Void rgSCHRamProcContResGrdExp ARGS((RgSchCellCb *cell,
104 Void rgSCHChkEmtcContResGrdTmrExp ARGS((RgSchCellCb *cell));
105 Void rgSCHChkEmtcContResTmrExp ARGS((RgSchCellCb *cell));
108 /* forward references */
111 * @brief Check configured preamble id not colliding with non dedicated or PDCCH
112 * order preamble sets. When valid preamble id given check that C-RNTI given
113 * in configuration is not amongst the C-RNTI'smanaged by scheduler
117 * Function : rgSCHRamVldtUeCfg
119 * Processing Steps: Check configured preamble id not colliding with non dedicated or PDCCH
120 * order preamble sets. When valid preamble id given check that C-RNTI given
121 * in configuration is not amongst the C-RNTI'smanaged by scheduler
123 * @param[in] RgSchCellCb *cell
124 * @param[in] RgrUeCfg *ueCfg
129 S16 rgSCHRamVldtUeCfg(RgSchCellCb *cell,RgrUeCfg *ueCfg)
131 if (ueCfg->dedPreambleId.pres == PRSNT_NODEF)
133 if ((ueCfg->dedPreambleId.val < cell->rachCfg.numRaPreamble) ||
134 (ueCfg->dedPreambleId.val >= RGSCH_MAX_NUM_RA_PREAMBLE) ||
135 ((ueCfg->dedPreambleId.val >= cell->macPreambleSet.start) &&
136 (ueCfg->dedPreambleId.val <= cell->macPreambleSet.start +
137 cell->macPreambleSet.size - 1)) ||
138 ((ueCfg->crnti >= cell->rntiDb.rntiStart) &&
139 (ueCfg->crnti < cell->rntiDb.rntiStart + cell->rntiDb.maxRntis-1))
141 || (rgSCHRamVldtRgrEmtcUeCfg(cell,ueCfg))
152 * @brief Handler for Random Access Request
156 * Function : rgSCHRamProcRaReq
158 * -# Create a node for each TfuRaReqInfo element received
159 * -# Initialize the list with the above elements at the raRnti index
163 * @param[in] RgSchCellCb *cell
164 * @param[in] CmLteRnti raRnti
165 * @param[in] RgTfuRaReqInd *raReqInd
166 * @param[out] RgSchErrInfo *err
171 S16 rgSCHRamProcRaReq
176 TfuRachInfo *raReqInd,
177 CmLteTimingInfo timingInfo,
182 RgSchRaReqInfo *raReqInfo;
191 /* SR_RACH_STATS : RACH REQ */
192 rgNumPrachRecvd += raReqInd->numRaReqInfo;
194 /* ccpu00132523- Moved out this from for loop as updating of raIndex is
195 * relates to only raRnti and all preambles having same raRnti*/
197 /* UL subframes do not occupy all the subframes in a radio frame.
198 * So RA Rnti index to be calculated based on actual UL subframe index. */
199 /* Get the actual subframe number */
200 tid = (raRnti-1)%RGSCH_NUM_SUB_FRAMES;
201 /* Get the frequency index in the subframe */
202 fid = ((raRnti-1) / RGSCH_NUM_SUB_FRAMES)* RGSCH_NUM_SUB_FRAMES;
203 /* Get the index of RA RNTI in the array */
204 raIndex = ((timingInfo.sfn % cell->raInfo.maxRaSize) \
205 * RGSCH_MAX_RA_RNTI_PER_SUBFRM * RGSCH_NUM_SUB_FRAMES) + \
207 /* Fixes for RACH handling in TDD: Removed deletion of queued RaReq */
209 /* ccpu00132523- Placing the raReq into array based on RA SFN */
210 raIndex = (timingInfo.sfn & 1) * RGSCH_MAX_RA_RNTI + raRnti-1;
213 /* allocate new raReqInfos and enqueue them */
214 if (raReqInd->raReqInfoArr[raReqCnt].rapId >= RGSCH_MAX_NUM_RA_PREAMBLE)
216 DU_LOG("\nERROR --> SCH : RARNTI:%d rgSCHTomRaReqInd(): RAM processing failed", raReqInd->raRnti);
220 /* SR_RACH_STATS : DED PREAMB*/
221 if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
228 if (raReqInd->raReqInfoArr[raReqCnt].rapId < cell->rachCfg.sizeRaPreambleGrpA)
230 cell->raPrmbs.preamGrpA++;
232 else if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
234 cell->raPrmbs.dedPream++;
238 cell->raPrmbs.preamGrpB++;
242 if((rgSCHUtlAllocSBuf(cell->instIdx, (Data **)(&raReqInfo),
243 sizeof(RgSchRaReqInfo))) == RFAILED)
245 DU_LOG("\nERROR --> SCH : rgSCHRamProcRaReq(): Allocation"
246 " of RaReq failed RARNTI:%d",raRnti);
247 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
251 /* Insert the given raReqInfo */
253 raReqInfo->timingInfo = timingInfo;
254 raReqInfo->raReq = raReqInd->raReqInfoArr[raReqCnt];
255 raReqInfo->raReqLstEnt.next = NULLP;
256 raReqInfo->raReqLstEnt.prev = NULLP;
257 raReqInfo->raReqLstEnt.node = (PTR)raReqInfo;
262 RGSCH_ARRAY_BOUND_CHECK(cell->instIdx, cell->raInfo.raReqLst, raIndex);
264 /* RACHO: If dedicated preamble, then give preference by appending at front */
265 if (RGSCH_IS_DEDPRM(cell, raReqInd->raReqInfoArr[raReqCnt].rapId))
267 cmLListFirst(&cell->raInfo.raReqLst[raIndex]);
268 cmLListInsCrnt(&cell->raInfo.raReqLst[raIndex], &raReqInfo->raReqLstEnt);
272 cmLListAdd2Tail(&cell->raInfo.raReqLst[raIndex], &raReqInfo->raReqLstEnt);
276 } /* rgSCHRamProcRaReq */
279 * @brief Handler for Random Access control block creation
283 * Function : rgSCHRamCreateRaCb
284 * Creates a raCb and gives the same to scheduler for its updation
287 * @param[in] RgSchCellCb *cell
288 * @param[in, out] RgSchRaCb **raCb
289 * @param[out] RgSchErrInfo *err
294 S16 rgSCHRamCreateRaCb
301 RgSchRntiLnk *rntiLnk;
302 Inst inst = cell->instIdx;
305 if((rgSCHUtlAllocSBuf(inst, (Data **)(raCb),
306 sizeof(RgSchRaCb))) == RFAILED)
308 DU_LOG("\nERROR --> SCH : rgSCHRamCreateRaCb(): Allocation of "
310 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
314 rntiLnk = rgSCHDbmGetRnti(cell);
317 (*raCb)->rntiLnk = rntiLnk;
318 (*raCb)->tmpCrnti = rntiLnk->rnti;
323 /* SR_RACH_STATS: RNTI POOL Exhaution */
324 rgNumRarFailDuetoRntiExhaustion++;
326 /* No rnti available! */
327 DU_LOG("\nERROR --> SCH : rgSCHRamCreateRaCb(): Allocation of "
328 "temporary RNTI failed at MAC(CRNTI exhausted)");
329 /* ccpu00117052 - MOD - Passing double pointer
330 for proper NULLP assignment*/
331 rgSCHUtlFreeSBuf(inst, (Data **)(raCb), sizeof(RgSchRaCb));
332 err->errCause = RGSCHERR_RAM_RNTI_EXHAUST;
336 /* Allocate and initialize the DL HARQ portion of the RACB */
337 (*raCb)->dlHqE = rgSCHDhmHqEntInit(cell);
338 if ((*raCb)->dlHqE == NULLP)
340 /* No memory available! */
341 DU_LOG("\nERROR --> SCH : rgSCHRamCreateRaCb(): Creation of"
343 /* ccpu00117052 - MOD - Passing double pointer
344 for proper NULLP assignment*/
345 rgSCHUtlFreeSBuf(inst, (Data **)(raCb), sizeof(RgSchRaCb));
346 err->errCause = RGSCHERR_RAM_MEM_EXHAUST;
350 (*raCb)->isEmtcRaCb = FALSE;
351 rgSCHEmtcHqPAlloc(cell, (*raCb)->dlHqE);
353 (*raCb)->dlHqE->raCb = (*raCb);
354 /* Initialize RaCb's contents */
355 (*raCb)->timingInfo = cell->crntTime;
356 (*raCb)->raState = RGSCH_RA_MSG3_PENDING;
357 (*raCb)->toDel = FALSE;
358 (*raCb)->phr.pres = FALSE;
360 /* Insert the created raCb into raCb list of cell */
361 (*raCb)->raCbLnk.node = (PTR)(*raCb);
362 cmLListAdd2Tail(&cell->raInfo.raCbLst, &(*raCb)->raCbLnk);
365 } /* rgSCHRamCreateRaCb */
368 * @brief Handler for Ue Configuration Request
372 * Function : rgSCHRamRgrUeCfg
374 * This function handles the UE config received based on the state of the
376 * -# If raCb is in RGSCH_RA_MSG4_PENDING state, it shall update the harq
377 * information to UeCb and update the references.
378 * -# If raCb is in RGSCH_RA_MSG4_DONE, then it shall free the raCb
381 * @param[in] RgSchCellCb *cell
382 * @param[in,out] RgSchUeCb *ue
383 * @param[in,out] RgSchRaCb *raCb
384 * @param[out] RgSchErrInfo *err
397 /* Releasing HARQ processes of old UE when ue
398 * reconfig with new crnti */
400 RgSchDlHqEnt **hqEnt = &(RG_SCH_CMN_GET_UE_HQE(ue, cell));
401 RgSchCmnUlUe *ueUl = RG_SCH_CMN_GET_UL_UE(ue, cell);
404 /* Fix : set UE inactive in DL until UE is reinitialization completed */
405 ue->dl.dlInactvMask |= RG_HQENT_INACTIVE;
406 ue->ul.ulInactvMask |= RG_HQENT_INACTIVE;
408 if(raCb->raState == RGSCH_RA_MSG4_PENDING)
411 ue->rntiLnk = raCb->rntiLnk;
412 /* Update UL Harq process information */
413 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
414 ueUl->hqEnt.hqProcCb[raCb->msg3HqProcId].ndi = raCb->msg3HqProc.ndi;
416 else if(raCb->raState == RGSCH_RA_MSG4_DONE)
418 ue->rntiLnk = raCb->rntiLnk;
419 /* Update UL Harq process information */
420 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
421 ueUl->hqEnt.hqProcCb[raCb->msg3HqProcId].ndi = raCb->msg3HqProc.ndi;
422 /* Fix : syed Assign hqEnt to UE only if msg4 is done */
423 rgSCHDhmAssgnUeHqEntFrmRaCb(ue, raCb);
427 err->errCause = RGSCHERR_RAM_NO_MSG3_RCVD;
429 raCb->dlHqE->ue = NULLP;
434 } /* rgSCHRamRgrUeCfg */
438 * @brief Handler for C-RNTI based contention resolution
442 * Function : rgSCHRamContResCrnti
444 * This function shall be invoked once Msg3 indicates C-RNTI based
445 * contention resolution.This shall indicate the scheduler regarding
446 * C-RNTI based uplink grant.
449 * @param[in,out] RgSchCellCb *cell
450 * @param[in,out] RgSchUeCb *ue
451 * @param[in,out] RgSchRaCb *raCb
455 static S16 rgSCHRamContResCrnti
463 TfuUlCqiRpt ulCqiRpt;
464 RgSchCmnCell *cellSch= (RgSchCmnCell *)(cell->sc.sch);
467 /* Fix: syed It is incorrect to copy over msg3HqProc to ueCb's
468 * UL harq proc. In case of Crnti based RACH, ueCb has valid context which
469 * cannot be over written. It was leading to a crash. */
471 rgSCHUtlRecMsg3Alloc(cell, ue, raCb);
473 /* Fix for ccpu00123908: Reset the UL CQI to the cell default value here */
474 ulCqiRpt.isTxPort0 = TRUE;
475 ulCqiRpt.numSubband = 0;
476 /* Fix : syed HO UE does not have a valid ue->rntiLnk */
477 ulCqiRpt.rnti = ue->ueId;
478 /* rg002.301:[ccpu00124018]-MOD- Avoiding hard coding of CQI and retriving from cell config*/
479 ulCqiRpt.wideCqi = cellSch->ul.dfltUlCqi;
480 rgSCHUtlUlCqiInd(cell, ue, &ulCqiRpt);
483 /* Invoke scheduler to indicate UL grant req for contention resolution */
484 rgSCHUtlContResUlGrant(cell, ue, err);
486 if (raCb->phr.pres == TRUE)
488 rgSCHUtlUpdPhr(cell, ue, raCb->phr.val, err);
490 /* No need of raCb any more */
491 rgSCHRamDelRaCb(cell, raCb, TRUE);
494 } /* rgSCHRamContResCrnti */
498 * @brief Handler for CCCH SDU based contention resolution
502 * Function : rgSCHRamContResCcchsdu
504 * This function shall be invoked once Msg3 indicates contention resolution
505 * based on CCCH sdu. This shall update the raCb state to
506 * RGSCH_RA_MSG4_PENDING.
509 * @param[in,out] RgSchRaCb *raCb
513 static S16 rgSCHRamContResCcchsdu
520 CmLteTimingInfo expTime = {0};
521 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
523 if(raCb->raState != RGSCH_RA_MSG3_PENDING)
525 DU_LOG("\nERROR --> SCH : RNTI:%d RaCb in wrong State %d Drop Msg 3",
531 raCb->raState = RGSCH_RA_MSG4_PENDING;
534 if(cell->rachCfg.contResTmr - cellSch->dl.msg4TxDelay > 0)
536 /* Set the contension resolution guard timer =
537 Cont Res Timer - Max msg4 Tx Delay */
538 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, expTime,
539 (cell->rachCfg.contResTmr - cellSch->dl.msg4TxDelay));
543 /* Schedule the CRI CE in the next Sf itself */
544 RG_SCH_ADD_TO_CRNT_TIME(cell->crntTime, expTime, 1);
546 raCb->expiryTime = expTime;
547 raCb->contResTmrLnk.node = (PTR)(raCb);
548 cmLListAdd2Tail(&(cell->contResGrdTmrLst), &(raCb->contResTmrLnk));
551 } /* rgSCHRamContResCcchsdu */
555 * @brief Handler for Msg3
559 * Function : rgSCHRamProcMsg3
561 * This function processes the received Msg3 and identifies the type of
562 * contention resolution and act accordingly.
565 * @param[in,out] RgSchCellCb *cell
566 * @param[in,out] RgSchUeCb *ue
567 * @param[in,out] RgSchRaCb *raCb
582 /* Update raCb with PHR if received along with Msg3 */
583 if (pdu->ceInfo.bitMask & RGSCH_PHR_CE_PRSNT)
586 raCb->phr.pres = TRUE;
587 raCb->phr.val = pdu->ceInfo.ces.phr;
591 rgSCHRamContResCrnti(cell, ue, raCb, err);
596 if(TRUE == raCb->isEmtcRaCb)
598 /* starting the emtc Contention resolution timer */
599 rgSCHRamEmtcContResCcchsdu(cell,raCb);
604 rgSCHRamContResCcchsdu(cell, raCb);
609 } /* rgSCHRamProcMsg3 */
613 * @brief Handler for Updating Bo received in StaRsp
617 * Function : rgSCHRamUpdtBo
619 * This function shall be invoked by RAM once it receives staRsp on CCCH
621 * @param[in] RgSchCellCb *cell
622 * @param[in,out] RgSchRaCb *raCb
623 * @param[in] RgRguCmnStaRsp *staRsp
631 RgInfCmnBoRpt *staRsp
635 /* Update Bo in RaCb */
636 raCb->dlCcchInfo.bo = (uint32_t)(staRsp->bo);
637 /* SR_RACH_STATS : MSG4 WITH CCCH SDU */
638 rgNumMsg4WithCCCHSdu++;
640 /* add this to the "tobeSchdLst" */
642 rgSCHRamAddToRaInfoSchdLst(cell, raCb);
646 } /* rgSCHRamUpdtBo */
649 * @brief Handler for Msg3 Feedback indication
653 * Function : rgSCHRamMsg3DatInd
655 * This function shall be invoked by TOM once the transmission of Msg4 is
657 * This shall invoke UHM to set ACK for Msg3 reception.
659 * @param[in,out] RgSchRaCb *raCb
663 S16 rgSCHRamMsg3DatInd(RgSchRaCb *raCb)
666 /* SR_RACH_STATS : MSG3 ACK*/
667 rgNumMsg3CrcPassed++;
668 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
669 rgSCHUhmProcMsg3DatInd(&(raCb->msg3HqProc));
672 } /* rgSCHRamMsg3DatInd */
675 * @brief Handler for Msg3 Feedback indication
679 * Function : rgSCHRamMsg3FailureInd
681 * This function shall be invoked by TOM once the transmission of Msg4 is
683 * This shall invoke UHM to set ACK for Msg3 reception.
685 * @param[in,out] RgSchRaCb *raCb
689 S16 rgSCHRamMsg3FailureInd(RgSchRaCb *raCb)
692 /*ccpu00128820 - MOD - Msg3 alloc double delete issue*/
693 rgSCHUhmProcMsg3Failure(&(raCb->msg3HqProc));
696 } /* rgSCHRamMsg3FailureInd */
699 * @brief Handler for Msg4 Feedback indication
703 * Function : rgSCHRamMsg4FdbkInd
705 * This function shall be invoked by TOM once the transmission of Msg4 is
707 * This shall invoke UHM to set ACK for Msg3 reception.
709 * @param[in,out] RgSchRaCb *raCb
713 S16 rgSCHRamMsg4FdbkInd(RgSchRaCb *raCb)
717 } /* rgSCHRamMsg4FdbkInd */
721 * @brief Handler for Msg4 state updation
725 * Function : rgSCHRamMsg4Done
727 * This function shall be invoked by DHM once the transmission of Msg4 is
728 * done. This shall delete the raCb if there is a valid Ue or if this is to
729 * be deleted. If not this shall update the state of the raCb.
732 * @param[in] RgSchCellCb *cell
733 * @param[in,out] RgSchRaCb *raCb
737 S16 rgSCHRamMsg4Done(RgSchCellCb *cell,RgSchRaCb *raCb)
740 DU_LOG("\nDEBUG --> SCH : rgSCHRamMsg4Done(): tmpCRNTI = %u",
743 if(raCb->ue != NULLP)
745 /* Fix : syed Let this funtion decide on releasing
746 * hqP than the caller of this function otherwise sometimes it
747 * might lead to incorrec NDI setting. */
748 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
749 /* Fix : syed Assign hqEnt to UE only if msg4 is done */
750 rgSCHDhmAssgnUeHqEntFrmRaCb(raCb->ue, raCb);
752 if(TRUE == raCb->isEmtcRaCb)
754 rgSCHEmtcUtlUpdCmnNb(raCb);
757 /* MS_FIX :Proceed to CCCH scheduling irrespective of
759 if (raCb->ue->dlCcchInfo.bo)
762 /*if CR-ID Ack has been received ,Add emtc Ue to cchSduUeLst*/
763 if(TRUE == raCb->isEmtcRaCb)
765 rgSCHUtlAddUeToEmtcCcchSduLst(cell, raCb->ue);
770 rgSCHUtlAddUeToCcchSduLst(cell, raCb->ue);
773 /* Rnti shall not be released as Ue exists with this rnti */
774 rgSCHRamDelRaCb(cell, raCb, FALSE);
776 else if(raCb->toDel == TRUE)
778 #ifdef XEON_SPECIFIC_CHANGES
779 DU_LOG("\nDEBUG --> SCH : Deleting RacB:%d\n", raCb->tmpCrnti);
781 /* Delete RACB and release RNTI */
782 rgSCHRamDelRaCb(cell, raCb, TRUE);
786 #ifdef XEON_SPECIFIC_CHANGES
787 DU_LOG("\nDEBUG --> SCH : Releasing Harq of RacB:%d\n", raCb->tmpCrnti);
789 raCb->raState = RGSCH_RA_MSG4_DONE;
790 /* Release harq process as final feedback is received for Msg4. In other
791 * cases, delRaCb will take care of releasing the harq process */
792 DU_LOG("\nDEBUG --> SCH : Harq process released ");
793 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
797 } /* rgSCHRamMsg4Done */
801 * @brief Handler for deletion
805 * Function : rgSCHRamDelRaCb
807 * This function shall be invoked whenever a raCb needs to be deleted.
808 * Invoked by both RAM and downlink scheduler
810 * @param[in] RgSchCellCb *cell
811 * @param[in,out] RgSchRaCb *raCb
812 * @param[in] Bool rlsRnti
817 S16 rgSCHRamDelRaCb(RgSchCellCb *cell,RgSchRaCb *raCb,Bool rlsRnti)
819 Inst inst = cell->instIdx;
822 /* Delete from all the lists it is enqueued */
823 cmLListDelFrm(&(cell->raInfo.raCbLst),&(raCb->raCbLnk));
825 /*ue Type is EMTC, then Delete the toBeSchedLst and stop the Guard Timer */
826 if(TRUE == raCb->isEmtcRaCb)
828 rgSCHRamEmtcDelRaCb(cell,raCb);
834 if (raCb->schdLnk.node == (PTR)raCb)
836 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb);
839 else if(raCb->contResTmrLnk.node != NULLP)
841 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
842 raCb->contResTmrLnk.node = NULLP;
849 rgSCHUtlRlsRnti(cell, raCb->rntiLnk, FALSE, 0);
852 /* Check if msg4 Hq Proc has been released. If not, release it */
855 if (raCb->dlHqE->msg4Proc != NULLP)
857 /* Fix: syed Remove the msg4Proc if it waiting in sf->tbs list for
859 if ((raCb->dlHqE->msg4Proc->subFrm != NULLP) &&
860 (raCb->dlHqE->msg4Proc->hqPSfLnk.node != NULLP))
862 DU_LOG("\nERROR --> SCH : TMP CRNTI:%d RACH FAILURE!! "
863 "msg4proc removed from SF", raCb->tmpCrnti);
864 rgSCHUtlDlHqPTbRmvFrmTx(raCb->dlHqE->msg4Proc->subFrm,
865 raCb->dlHqE->msg4Proc, 0, FALSE);
867 /* Fix: syed Remove the msg4Proc from cell
868 * msg4Retx Queue. I have used CMN scheduler function
869 * directly. Please define a new API and call this
870 * function through that. */
871 rgSCHCmnDlMsg4ProcRmvFrmRetx(cell, raCb->dlHqE->msg4Proc);
872 rgSCHDhmRlsHqpTb(raCb->dlHqE->msg4Proc, 0, TRUE);
875 /* Mark the raCb pointer in dlHqE to NULLP */
876 raCb->dlHqE->raCb = NULLP;
878 rgSCHDhmDelHqEnt(cell, &raCb->dlHqE);
880 /* Fix: syed Adaptive Msg3 Retx crash. Remove the harqProc
881 * from adaptive retx List. Free the alloc if it exists. */
882 if (raCb->msg3HqProc.reTxLnk.node)
884 //TODO_SID: Need to take care of retxLst
885 //cmLListDelFrm(raCb->msg3HqProc.reTxAlloc.reTxLst, &raCb->msg3HqProc.reTxLnk);
886 raCb->msg3HqProc.reTxLnk.node = (PTR)NULLP;
889 if (raCb->msg3HqProc.alloc)
891 /* Fix: syed During GPR, please write an API instead of direct
892 * call to cmn scheduler function */
893 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
894 /*ccpu00130356 - MOD- To avoid segmentation problem because of double
895 free due to recursive calling of rgSCHRamDelRaCb*/
896 rgSCHRamUlFreeAllocation(&cellUl->ulSfArr[raCb->msg3HqProc.ulSfIdx],
897 raCb->msg3HqProc.alloc,
902 if(TRUE == raCb->isEmtcRaCb)
904 rgSCHEmtcRaInfoFree(cell, raCb);
907 rgSCHUtlFreeSBuf(inst, (Data **)&raCb, sizeof(RgSchRaCb));
910 } /* rgSCHRamDelRaCb */
914 * @brief TTI Handler for RAM module
918 * Function : rgSCHRamTtiHndlr
920 * This function shall be invoked upon TtiInd by TOM
922 * - remove RaReqs added to the queue for a raRnti for which PHY may
923 * give the requests in the next subframe
924 * - remove raCbs which are not yet processed once the
925 * counter for raCb processing expires.
928 * @param[in,out] RgSchCellCb *cell
932 S16 rgSCHRamTtiHndlr(RgSchCellCb *cell)
937 uint16_t dist; /* Number of frames between raCb's creation and crnt frame */
943 RgSchRaReqInfo *raReqInfo;
950 crntSfn = cell->crntTime.sfn;
953 /*Check if Contention resolution guard timer expiring in the TTI*/
954 rgSCHChkContResGrdTmrExp(cell);
955 /*Check if Contention resolution timer expiring in the TTI*/
956 rgSCHChkContResTmrExp(cell);
958 /*Check if EMTC Contention resolution guard timer expiring in the TTI*/
959 rgSCHChkEmtcContResGrdTmrExp(cell);
960 /*Check if EMTC Contention resolution timer expiring in the TTI*/
961 rgSCHChkEmtcContResTmrExp(cell);
966 /* Delete the RA requests for which RAR window expired in this subframe
967 * And were not considered for RAR scheduling*/
968 winGap = (rgRaPrmblToRaFrmTbl[cell->rachCfg.preambleFormat]-1)+
969 (cell->rachCfg.raWinSize -1 ) + RGSCH_RARSP_WAIT_PERIOD;
971 raIdx = (((crntSfn & 1) * RGSCH_MAX_RA_RNTI+ cell->crntTime.slot
972 + RG_SCH_CMN_DL_DELTA - winGap)+ RGSCH_RAREQ_ARRAY_SIZE )
973 % RGSCH_RAREQ_ARRAY_SIZE;
975 /* Flush the already existing raReqs against the given raRnti */
977 maxCnt = cell->raInfo.raReqLst[raIdx].count;
978 for (idx = 0; idx < maxCnt; idx++)
980 raReqInfo = (RgSchRaReqInfo *)(cell->raInfo.raReqLst[raIdx].first->node);
981 cmLListDelFrm(&(cell->raInfo.raReqLst[raIdx]),&(raReqInfo->raReqLstEnt));
982 /* ccpu00117052 - MOD - Passing double pointer
983 for proper NULLP assignment*/
984 rgSCHUtlFreeSBuf(cell->instIdx, (Data **)&raReqInfo,
985 sizeof(RgSchRaReqInfo));
988 /* Fixes for RACH handling: Added deletion of queued RaReq */
989 frm = cell->crntTime;
990 RGSCH_INCR_SUB_FRAME(frm, RG_SCH_CMN_DL_DELTA);
991 if(rgSchTddUlDlSubfrmTbl[cell->ulDlCfgIdx][frm.slot] !=
992 RG_SCH_TDD_UL_SUBFRAME)
994 raIdx = rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][frm.slot]-1;
995 rgSCHRamDelRaReq(cell, cell->crntTime, raIdx);
999 /* Remove the RACBs which are timed out */
1000 /* ccpu00132536:MOD- racb timeout will be verified in each SFN such that
1001 * the RACB whose processing is not completed in RG_MAX_RA_PRC_FRM
1003 if (cell->crntTime.slot == 0)
1005 maxCnt = cell->raInfo.raCbLst.count;
1006 for (idx = 0; idx < maxCnt; idx++)
1008 raCb = (RgSchRaCb *)(cell->raInfo.raCbLst.first->node);
1009 /* Calculate number of frames between raCb's creation and crnt frame */
1010 raSfn = raCb->timingInfo.sfn;
1011 dist = (crntSfn + (RGSCH_MAX_SFN - raSfn)) % RGSCH_MAX_SFN;
1012 /* Delete RaCbs whose processing is not complete within
1013 * "cell->t300TmrVal" frames */
1014 /* raCb not to be deleted if msg4 is not completed */
1015 /* raCb should not be deleted(RNTI should not be released) if UE is present
1016 * as it means the application still holds the RNTI. raCb will get deleted
1017 * as part of UE deletion. raCb will anyway get deleted without releasing RNTI on success/failure of MSG4*/
1019 if (dist >= cell->t300TmrVal)
1021 if ((raCb->dlHqE->msg4Proc == NULLP) && (raCb->dlHqE->ue == NULLP))
1023 rgSCHRamDelRaCb(cell, raCb, TRUE);
1034 } /* rgSCHRamTtiHndlr */
1038 * @brief Function for handling cell delete
1042 * Function : rgSCHRamFreeCell
1044 * This function shall be invoked whenever a cell needs to be deleted.
1045 * This shall remove raCbs and raReqs stored in cell.
1048 * @param[in,out] RgSchCellCb *cell
1052 S16 rgSCHRamFreeCell(RgSchCellCb *cell)
1054 RgSchRaReqInfo *raReqInfo;
1058 Inst inst = cell->instIdx;
1061 uint8_t maxUlSubframes;
1062 uint8_t maxDlSubframes;
1070 rgSchTddNumUlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1072 rgSchTddNumDlSubfrmTbl[cell->ulDlCfgIdx][RGSCH_NUM_SUB_FRAMES-1];
1073 lstSz = cell->raInfo.maxRaSize * RGSCH_MAX_RA_RNTI_PER_SUBFRM * \
1076 /* ccpu00133557- MEM LEAK FIX- Need to free all the nodes in RA Array list */
1077 lstSz = RGSCH_RAREQ_ARRAY_SIZE;
1080 for (idx = 0; idx < lstSz; idx++)
1082 /* Delete and free raReqs stored */
1083 /* ccpu00133557- MEM LEAK FIX- Need to be freed till the count is non-zero */
1084 while(cell->raInfo.raReqLst[idx].count)
1086 raReqInfo = (RgSchRaReqInfo *)(cell->raInfo.raReqLst[idx].first->node);
1087 cmLListDelFrm(&(cell->raInfo.raReqLst[idx]),&(raReqInfo->raReqLstEnt));
1088 /* ccpu00117052 - MOD - Passing double pointer
1089 for proper NULLP assignment*/
1090 rgSCHUtlFreeSBuf(inst, (Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
1095 /* Delete the RACH response list*/
1096 /* ccpu00117052 - MOD - Passing double pointer
1097 for proper NULLP assignment*/
1098 rgSCHUtlFreeSBuf(inst,
1099 (Data **)(&(cell->rachRspLst)), sizeof(RgSchTddRachRspLst) * \
1103 /* Delete raCbs in the "to be scheduled" list */
1104 /* ccpu00133557- MEM LEAK FIX- Need to be freed till the count is non-zero */
1105 while(cell->raInfo.toBeSchdLst.count)
1107 raCb = (RgSchRaCb *)(cell->raInfo.toBeSchdLst.first->node);
1108 /* MSG4 Fix Start */
1110 rgSCHRamRmvFrmRaInfoSchdLst(cell, raCb);
1114 /* Delete raCbs in the "Emtc to be scheduled" list */
1115 if(cell->emtcEnable)
1117 rgSCHRamRmvAllFrmEmtcRaInfoSchdLst(cell);
1121 raCbCnt = cell->raInfo.raCbLst.count;
1123 /* Delete and free raCbs stored */
1124 for (idx = 0; idx < raCbCnt; idx++)
1126 raCb = (RgSchRaCb *)(cell->raInfo.raCbLst.first->node);
1127 rgSCHRamDelRaCb(cell, raCb, TRUE);
1131 } /* rgSCHRamFreeCell */
1133 static Void rgSCHRamProcContResExp(RgSchCellCb *cell,RgSchRaCb *raCb)
1135 raCb->expiryTime.sfn = RGSCH_CONTRES_EXP;
1139 /* UE exists and RNTI will be released as part of UE DEL */
1140 rgSCHRamDelRaCb(cell, raCb, FALSE);
1144 /* Calling Release RNTI, which would perform Racb deletion
1145 * RNTI removal and RNTI release indication to MAC. */
1146 /* Delete RACB and release RNTI */
1147 rgSCHRamDelRaCb(cell, raCb, TRUE);
1152 static Void rgSCHRamProcContResGrdExp(RgSchCellCb *cell,RgSchRaCb *raCb)
1156 /*Guard timer has expired, schedule only the contention REsolution CE with
1158 raCb->dlCcchInfo.bo = 0;
1159 /* SR_RACH_STATS : MSG4 WO CCCH SDU */
1160 rgNumMsg4WoCCCHSdu++;
1162 /* add this to the "tobeSchdLst" */
1163 raCb->schdLnk.node = (PTR)(raCb);
1165 cmLListDelFrm(&cell->contResGrdTmrLst, &(raCb->contResTmrLnk));
1166 raCb->contResTmrLnk.node = NULLP;
1168 /* MSG4 Fix Start */
1169 DU_LOG("\nDEBUG --> SCH : Con Res Grd Tmr exp RNTI:%d",
1170 raCb->rntiLnk->rnti);
1171 rgSCHRamAddToRaInfoSchdLst(cell, raCb);
1177 * @brief Check the Contention Resolution Guard Timer Expiry.
1181 * Function: rgSCHChkContResTmrExp
1184 * Invoked by: Scheduler
1185 * @param[in] RgSchCellCb *cell
1190 static Void rgSCHChkContResTmrExp(RgSchCellCb *cell)
1192 CmLList *chkLnk = NULLP;
1193 RgSchRaCb *raCb = NULLP;
1196 chkLnk = cmLListFirst(&(cell->contResTmrLst));
1198 for (; chkLnk; chkLnk = chkLnk->next)
1200 raCb = (RgSchRaCb *)(chkLnk->node);
1202 if(RGSCH_TIMEINFO_SAME(raCb->expiryTime, cell->crntTime))
1204 /*If timer expired, call the handler function*/
1205 rgSCHRamProcContResExp(cell, raCb);
1207 /*Fix: Need to traverse till end of list as the entries may not be in ascending order*/
1215 * @brief Check the Contention Resolution Guard Timer Expiry.
1219 * Function: rgSCHChkContResGrdTmrExp
1222 * Invoked by: Scheduler
1223 * @param[in] RgSchCellCb *cell
1228 static Void rgSCHChkContResGrdTmrExp(RgSchCellCb *cell)
1230 CmLList *chkLnk = NULLP;
1231 RgSchRaCb *raCb = NULLP;
1234 chkLnk = cmLListFirst(&(cell->contResGrdTmrLst));
1236 /*[ccpu00131941]-MOD-List traversal should be done using the listCp */
1237 for (; chkLnk; chkLnk = cmLListNext(&cell->contResGrdTmrLst))
1239 raCb = (RgSchRaCb *)(chkLnk->node);
1241 if(RGSCH_TIMEINFO_SAME(raCb->expiryTime, cell->crntTime))
1243 /*If timer expired, call the handler function*/
1244 rgSCHRamProcContResGrdExp(cell, raCb);
1255 * @brief Function for handling RACH Request deletion
1259 * Function : rgSCHRamDelRaReq
1261 * This function shall be invoked to delete the RACH Requests
1262 * that is not scheduled within the RA window size.
1265 * @param[in,out] RgSchCellCb *cell
1266 * @param[in] CmLteTimingInfo timingInfo
1267 * @param[in] uint8_t raIdx
1271 S16 rgSCHRamDelRaReq
1274 CmLteTimingInfo timingInfo,
1279 RgSchTddRachRspLst *rachRsp;
1283 RgSchRaReqInfo *raReqInfo;
1291 rachRsp = &cell->rachRspLst[raIdx];
1292 /* Get the SFN Index to be deleted */
1293 calcSfn = timingInfo.sfn - rachRsp->delInfo.sfnOffset;
1296 sfnIdx = (calcSfn + RGSCH_MAX_SFN) % cell->raInfo.maxRaSize;
1303 /* Iterate through all the subframes to be delted in the SFN */
1304 for(subfrmIdx=0; subfrmIdx < rachRsp->delInfo.numSubfrms; subfrmIdx++)
1306 subfrm = rachRsp->delInfo.subframe[subfrmIdx];
1307 /* Get the subframe Index to be deleted */
1308 /* Fixes for RACH handling in TDD:
1309 * Corrected the computation of raRntiIdx
1311 raRntiIdx = ((sfnIdx % cell->raInfo.maxRaSize) * \
1312 RGSCH_MAX_RA_RNTI_PER_SUBFRM * \
1313 RGSCH_NUM_SUB_FRAMES) + subfrm;
1315 /* Iterate through all the RNTIs in the subframe */
1316 for(i=0; i < RGSCH_MAX_RA_RNTI_PER_SUBFRM; i++)
1318 raRnti = raRntiIdx + (i*RGSCH_NUM_SUB_FRAMES);
1319 for (idx = 0; idx < cell->raInfo.raReqLst[raRnti].count; idx++)
1322 (RgSchRaReqInfo *)(cell->raInfo.raReqLst[raRnti].first->node);
1323 cmLListDelFrm(&(cell->raInfo.raReqLst[raRnti]),
1324 &(raReqInfo->raReqLstEnt));
1325 /* ccpu00117052 - MOD - Passing double pointer
1326 for proper NULLP assignment*/
1327 rgSCHUtlFreeSBuf(cell->instIdx,
1328 (Data **)&raReqInfo, sizeof(RgSchRaReqInfo));
1338 S16 rgSCHRamAddToRaInfoSchdLst(RgSchCellCb *cell,RgSchRaCb *raCb)
1340 CmLteTimingInfo expTime ={0};
1341 RgSchCmnCell *cellSch = RG_SCH_CMN_GET_CELL(cell);
1344 /*Fix: This can be called even when guard timer is not expired.
1345 * In this case CR timer expiry should be guard timer expiry time + Guard timer time*/
1346 RG_SCH_ADD_TO_CRNT_TIME(raCb->expiryTime, expTime, cellSch->dl.msg4TxDelay);
1347 raCb->expiryTime = expTime;
1348 raCb->schdLnk.node = (PTR)(raCb);
1349 cmLListAdd2Tail(&(cell->raInfo.toBeSchdLst), &(raCb->schdLnk));
1350 raCb->contResTmrLnk.node = (PTR)(raCb);
1351 cmLListAdd2Tail(&(cell->contResTmrLst), &(raCb->contResTmrLnk));
1353 } /* rgSCHRamAddToRaInfoSchdLst */
1357 S16 rgSCHRamRmvFrmRaInfoSchdLst(RgSchCellCb *cell,RgSchRaCb *raCb)
1360 cmLListDelFrm(&(cell->raInfo.toBeSchdLst), &(raCb->schdLnk));
1361 raCb->schdLnk.node = NULLP;
1362 cmLListDelFrm(&(cell->contResTmrLst), &(raCb->contResTmrLnk));
1363 raCb->contResTmrLnk.node = NULLP;
1365 } /* rgSCHRamRmvFrmRaInfoSchdLst */
1369 /***********************************************************
1371 * Func : rgSCHRamUlFreeAllocation
1373 * Desc : Free an allocation - invokes UHM and releases
1382 **********************************************************/
1383 static Void rgSCHRamUlFreeAllocation
1386 RgSchUlAlloc *alloc,
1392 rgSCHUhmFreeProc(alloc->hqProc, cell);
1395 rgSCHUtlUlAllocRls(sf, alloc);
1400 /**********************************************************************
1403 **********************************************************************/