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 scheduler 1
29 **********************************************************************/
31 /** @file rg_sch_sc1.c
32 @brief The scheduling functionality is implemented in this file.
35 static const char* RLOG_MODULE_NAME="MAC";
36 static int RLOG_MODULE_ID=4096;
37 static int RLOG_FILE_ID=173;
39 /* header include files -- defines (.h) */
40 #include "common_def.h"
46 #include "rg_sch_inf.h"
47 #include "rg_sch_err.h"
49 #include "rg_sch_cmn.h"
50 #include "rg_sch_sc1.h"
51 #include "rl_interface.h"
52 #include "rl_common.h"
54 /* header/extern include files (.x) */
55 #include "tfu.x" /* RGU types */
56 #include "lrg.x" /* layer management typedefs for MAC */
57 #include "rgr.x" /* layer management typedefs for MAC */
58 #include "rgm.x" /* layer management typedefs for MAC */
59 #include "rg_sch_inf.x" /* typedefs for Scheduler */
60 #include "rg_sch.x" /* typedefs for Scheduler */
61 #include "rg_sch_cmn.x"
62 #include "rg_sch_sc1.x" /* typedefs for SC1 Scheduler */
69 #endif /* __cplusplus */
71 /* Functions called from outside */
72 PRIVATE S16 rgSCHSc1RgrDlCellRecfg ARGS((
78 /*--------------------------*
79 * DL SCHED STATIC declarations START
80 *---------------------------*/
81 PRIVATE Void rgSCHSc1DlSvcAddToSchd ARGS((
85 PRIVATE Void rgSCHSc1DlAdd2UeSchdSvcs ARGS((
90 PRIVATE Void rgSCHSc1DlRmvUeFrmPrioQs ARGS((
94 PRIVATE Void rgSCHSc1DlSuspendUe ARGS((
98 PRIVATE Void rgSCHSc1DlInactvtUe ARGS((
102 PRIVATE Void rgSCHSc1DlProcRmvFrmCellRetx ARGS((
106 PRIVATE Void rgSCHSc1DlProcRmvFrmUeRetx ARGS((
111 PRIVATE Void rgSCHSc1DlMngPrio0SvcPosn ARGS((
116 PRIVATE Void rgSCHSc1DlMngGbrSvcPosn ARGS((
121 PRIVATE Void rgSCHSc1DlMngAmbrSvcPosn ARGS((
126 PRIVATE Void rgSCHSc1DlMngSvcPosn ARGS((
131 PRIVATE Void rgSCHSc1DlUeAddToSchd ARGS((
135 PRIVATE Void rgSCHSc1DlTaCmd ARGS((
137 RgSchCmnDlRbAllocInfo *allocInfo
139 PRIVATE Void rgSCHSc1DlInitQueues ARGS((
140 RgSchSc1DlCell *cellDl
142 PRIVATE Void rgSCHSc1DlDeinitQueues ARGS((
143 RgSchSc1DlCell *cellDl
145 PRIVATE Void rgSCHSc1DlAdd2UeLcsWithData ARGS((
150 PRIVATE Void rgSCHSc1DlRmFrmUeLcsWithData ARGS((
155 /*--------------------------*
156 * UL SCHED STATIC declarations START
157 *---------------------------*/
158 PRIVATE Void rgSCHSc1UlPosnUeInQ ARGS((
162 PRIVATE Void rgSCHSc1UlSchdUeTxLst ARGS((
165 RgSchCmnUlRbAllocInfo *allocInfo,
168 PRIVATE Void rgSCHSc1DlProcRmvFrmRetx ARGS((
173 Void rgSCHSc1DlScanUpdPdbPrio ARGS((
176 S16 rgSCHSc1DlFillFlowCntrlInfo ARGS((
178 RgInfSfAlloc *sfAlloc
181 PRIVATE Void rgSCHSc1DlPreSchd ARGS ((
184 PRIVATE Void rgSCHSc1DlPstSchd ARGS ((
189 #endif /* __cplusplus */
194 /***************** SC1 DL SCHEDULER FUNCTION DEFNs START HERE ********/
196 /***********************************************************
198 * Func : rgSCHSc1DlUeReset
200 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
201 * and Svc in respective Prio Qs.
210 **********************************************************/
212 Void rgSCHSc1DlUeReset
218 Void rgSCHSc1DlUeReset(cell, ue)
224 rgSCHSc1DlSuspendUe(cell, ue);
230 /***********************************************************
232 * Func : rgSCHSc1DlActvtUe
234 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
235 * and Svc in respective Prio Qs.
244 **********************************************************/
246 Void rgSCHSc1DlActvtUe
252 Void rgSCHSc1DlActvtUe(cell, ue)
257 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
260 RgSchDlHqProcCb *hqP;
264 /* Add UE's HqProcs From UERetxLst to CellRetxLst */
265 lst = &ueDl->retxHqProcs;
269 hqP = (RgSchDlHqProcCb *)node->node;
271 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
272 rgSCHSc1DlProcAddToCellRetx(cell, hqP);
275 /* Iterate over all the Services if bo != 0 then add */
276 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
278 svc = ue->dl.lcCb[idx];
283 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
286 /* Add UE to AMBR Prio Q */
289 rgSCHSc1DlUeAddToSchd(cell, ue);
296 /***********************************************************
298 * Func : rgSCHSc1DlUeRefresh
300 * Desc : Handle 'refresh' for Downlink
301 * (ie UE's downlink AMBR and downlink GBR LCGs are
302 * refreshed at this point)
310 **********************************************************/
312 Void rgSCHSc1DlUeRefresh
318 Void rgSCHSc1DlUeRefresh(cell, ue)
323 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
324 /*cell added as part of CA dev*/
325 RgSchCmnDlSvc *svcCmn;
326 RgSchSc1DlSvc *svcSc1;
333 ueDl->ambr = ue->dl.ambrCfgd;
337 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
340 if (ueDl->ambrSvc != NULLP)
342 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, ueDl->ambrSvc->bo);
343 /* Update UEs position in the Queue */
344 rgSCHSc1DlUeAddToSchd(cell, ue);
347 lst = &ueDl->gbrSvcs;
349 while (node != NULLP)
351 svc = (RgSchDlLcCb *)node->node;
352 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
353 svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
355 svcSc1->gbr = svcCmn->gbr;
356 svcSc1->mbr = svcCmn->mbr;
357 /* Update the SVC's positioning in the Queue */
358 rgSCHSc1DlMngGbrSvcPosn(cell, ue, svc);
365 * @brief This function removes a HARQ process from the retx
369 * Function: rgSCHSc1DlProcRmvFrmCellRetx
370 * Purpose: This function removes a HARQ process from retransmission
371 * queue. This may be performed when a HARQ ack is successful
372 * for a retransmission or when the scheduling determines
373 * to throw out the process due to poor conditions
375 * Invoked by: LIM and Scheduler
377 * @param[in] RgSchSc1Cb* cell
378 * @param[in] RgDlHqProc* hqP
383 PRIVATE Void rgSCHSc1DlProcRmvFrmCellRetx
389 PRIVATE Void rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP)
391 RgSchDlHqProcCb *hqP;
394 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
395 RgSchCmnDlHqProc *hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
398 if (hqProcDl->retxLnk.node != NULLP)
400 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
401 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
402 hqProcDl->retxLnk.node = NULLP;
409 * @brief This function removes a HARQ process from the UE retx
413 * Function: rgSCHSc1DlProcRmvFrmUeRetx
414 * Purpose: This function removes a HARQ process from UE retransmission
417 * Invoked by: LIM and Scheduler
419 * @param[in] RgSchUeCb* ue
420 * @param[in] RgDlHqProc* hqP
425 PRIVATE Void rgSCHSc1DlProcRmvFrmUeRetx
432 PRIVATE Void rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP)
435 RgSchDlHqProcCb *hqP;
438 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
439 RgSchSc1DlHqProc *hqProcDl = RG_GET_SC1_HQP_DL(hqP);
442 if (hqProcDl->retxLnkUe.node != NULLP)
444 cmLListDelFrm(&sc1Ue->retxHqProcs,
445 &(hqProcDl->retxLnkUe));
446 hqProcDl->retxLnkUe.node = NULLP;
453 * @brief This function adds a HARQ process for UEs retxLst
457 * Function: rgSCHSc1DlProcAddToUeRetx
458 * Purpose: This function adds a HARQ process to UE retransmission
459 * queue. This is performed when UE is suspended due
460 * to measurement gap.
462 * Invoked by: HARQ feedback processing
464 * @param[in] RgSchUeCb* ue
465 * @param[in] RgSchDlHqProc* hqP
470 PRIVATE Void rgSCHSc1DlProcAddToUeRetx
477 PRIVATE Void rgSCHSc1DlProcAddToUeRetx(cell, ue, hqP)
480 RgSchDlHqProcCb *hqP;
483 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
484 RgSchSc1DlHqProc *cmnHqDl = RG_GET_SC1_HQP_DL(hqP);
487 cmLListAdd2Tail(&sc1Ue->retxHqProcs,
488 &(cmnHqDl->retxLnkUe));
489 cmnHqDl->retxLnkUe.node = (PTR)hqP;
495 * @brief This function adds a HARQ process for retx
499 * Function: rgSCHSc1DlProcAddToCellRetx
500 * Purpose: This function adds a HARQ process to retransmission
501 * queue. This may be performed when a HARQ ack is
504 * Invoked by: HARQ feedback processing
506 * @param[in] RgSchCellCb* cell
507 * @param[in] RgSchDlHqProc* hqP
512 Void rgSCHSc1DlProcAddToCellRetx
518 Void rgSCHSc1DlProcAddToCellRetx(cell, hqP)
520 RgSchDlHqProcCb *hqP;
523 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
524 RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
527 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(hqP->hqE->ue))
529 rgSCHSc1DlProcAddToUeRetx(cell, hqP->hqE->ue, hqP);
532 cmLListAdd2Tail(&sc1CellDl->retxLst[((RgSchSc1DlHqProc *)\
533 (cmnHqDl->schSpfc))->prio], &(cmnHqDl->retxLnk));
534 cmnHqDl->retxLnk.node = (PTR)hqP;
540 * @brief This function implements DL RETRANSMISSION allocation
544 * Function: rgSCHSc1DlRetxAlloc
545 * Purpose: This function implements downlink scheduler's
546 * retransmission allocation.
548 * Invoked by: Scheduler
550 * @param[in] RgSchCellCb *cell
551 * @param[in] RgSchDlSf *subFrm
552 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
557 PRIVATE Void rgSCHSc1DlRetxAlloc
561 RgSchCmnDlRbAllocInfo *allocInfo
564 PRIVATE Void rgSCHSc1DlRetxAlloc(cell, subFrm, allocInfo)
567 RgSchCmnDlRbAllocInfo *allocInfo;
573 RgSchDlHqProcCb *hqP;
574 RgSchSc1DlCell *sc1CellDl;
575 RgSchSc1DlUe *sc1DlUe;
576 RgSchCmnDlUe *cmnUeDl;
577 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
578 CmLteTimingInfo schdTime;
581 RgSchUeCb *ue = NULLP;
583 Bool dlAllowed = FALSE;
585 RgSchDlRbAlloc *dlAllocCb;
587 sc1CellDl = RG_GET_SC1_CELL_DL(cell);
588 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
589 schdTime = cell->crntTime;
591 /* Increment by DL DELTA to determine the time for which scheduling
593 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
595 for (i = 0; i < RG_SCH_SC1_DL_PRIOS; i++)
597 retxLst = &sc1CellDl->retxLst[i];
598 /* allocate bw for the retransmission..should be same are previous */
599 /* If CQI gets worse, as we cannot find same TB size for another */
600 /* MCS, we just remove this from the retransmission queue */
601 node = retxLst->first;
602 while (node != NULLP)
604 hqP = (RgSchDlHqProcCb *)node->node;
609 if((0 == schdTime.slot) || (5 == schdTime.slot))
612 rgSCHCmnChkRetxAllowDtx(cell, ue, hqP, &reTxAllw);
613 if(FALSE == reTxAllw)
622 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
623 if (dlAllowed == FALSE)
629 /* This UE is already scheduled for transmission */
630 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
631 /*cell added as part of CA dev*/
633 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
638 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
643 /* Extra check: indicate if there is furtherScope for NewTx
644 * addition for a HqProc. This information will
645 * be utilized by common scheduler, in case of SM
646 * UEs with only one of the TBs retransmitting and the
647 * other TB can be used for clubbing new TX. */
648 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
649 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
650 if (sc1DlUe->lcsWithData.first != NULLP)
652 dlAllocCb->mimoAllocInfo.hasNewTxData = TRUE;
654 /* 3.1 MIMO : last parameter changed */
655 if (rgSCHCmnDlAllocRetxRb(cell, subFrm, ue, 0, &effBo, hqP, allocInfo) !=\
658 /* SF/RETX Bandwidth expired */
666 if ((hqP->tbInfo[0].state == HQ_TB_ACKED)
667 && (hqP->tbInfo[1].state == HQ_TB_ACKED))
669 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
674 /* 3.1 MIMO moving this call in cmn scheduler */
675 /*rgSCHCmnDlRbInfoAddUeRetx(allocInfo, ue);*/
681 /***********************************************************
683 * Func : rgSCHSc1RlsHqProc
685 * Desc : Toggles the NDI and releases the harq proc.
693 **********************************************************/
695 PRIVATE Void rgSCHSc1RlsHqProc
697 RgSchDlHqProcCb *hqProc
700 PRIVATE Void rgSCHSc1RlsHqProc(hqProc)
701 RgSchDlHqProcCb *hqProc;
704 rgSCHDhmRlsHqProc(hqProc);
709 * @brief This function implements dedicated logical channel data scheduling
713 * Function: rgSCHSc1DlDedSvcAlloc
714 * Purpose: This function implements dedicated logical
715 * channel data scheduling
717 * Invoked by: Scheduler
719 * @param[in] RgSchCellCb *cell
720 * @param[in] RgSchDlSf *subFrm
721 * @param[in] RgSchDlLcCb *svc
722 * @param[in] uint32_t bo
723 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
728 PRIVATE S16 rgSCHSc1DlDedSvcAlloc
734 RgSchCmnDlRbAllocInfo *allocInfo
737 PRIVATE S16 rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, bo, allocInfo)
742 RgSchCmnDlRbAllocInfo *allocInfo;
746 RgSchDlHqProcCb *proc;
747 uint16_t rlcHdrEstmt;
749 RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell);
750 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
751 RgSchSc1DlSvc *svcSc1;
753 RgSchSc1DlHqProc *sc1HqDl;
754 RgSchCmnDlHqProc *cmnHqDl;
756 CmLteTimingInfo schdTime;
759 Bool dlAllowed = FALSE;
764 /* Get the UE to which this service belongs to */
769 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
770 if (dlAllowed == FALSE)
776 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
777 /*cell added as part of CA dev*/
779 schdTime = cell->crntTime;
781 /* Increment by DL DELTA to determine the time for which scheduling
783 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
784 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
789 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
791 proc = (RgSchDlHqProcCb *)(ueDl->proc);
792 /* This UE is selected for retransmission. Hence no further */
793 /* scheduling may be done for this UE */
794 if (RG_SCH_CMN_PROC_SLCTD_FOR_RETX(proc))
796 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
797 "Ue retransmitting",ue->ueId);
800 /* UE is scheduled for either other services or TA */
801 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
802 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
803 if (sc1HqDl->prio > svcCmn->prio)
805 sc1HqDl->prio = svcCmn->prio;
808 else /* First consideration of this UE for scheduling */
810 if (rgSCHDhmGetAvlHqProc(cell, ue, cmnCellDl->time, &proc) != ROK)
812 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
813 " No HARQ Proc available", ue->ueId);
816 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
817 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
818 cmnHqDl->totBytes = 0;
819 /* Initialize some of the parameters of the HQ proc */
820 sc1HqDl->prio = svcCmn->prio;
823 /* Including each SDU's header size */
824 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
827 ret = rgSCHCmnDlAllocTxRb(cell, subFrm, ue, bo, &effBo, proc, allocInfo);
828 if ((ret != ROK) || (effBo == 0))
830 /* If no allocations so far, meaning proc obtained now */
831 if (cmnHqDl->totBytes == 0)
833 rgSCHSc1RlsHqProc(proc);
834 /* Added the handling for removing
835 * UE from txHqPLst and resetting outStndAlloc.*/
836 if(proc->reqLnk.node != (PTR)NULLP)
838 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
839 proc->reqLnk.node = (PTR)NULLP;
841 /*Re-set the outstanding alloc information.*/
842 ueDl->outStndAlloc = 0;
844 /* ccpu00126519: proc should be set to NULLP in UE's DL scratch pad info as well. */
849 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
850 svcSc1->hdrEstimate = rlcHdrEstmt;
851 svcSc1->reqBytes = bo;
853 cmnHqDl->totBytes += effBo;
855 rgSCHSc1DlAdd2UeSchdSvcs(cell, ue, svc);
856 /* 3.1 MIMO moving this call to cmn scheduler */
857 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue); */
862 * @brief This function adds a SVC to UE's schdSvcsLst.
866 * Function: rgSCHSc1DlAdd2UeSchdSvcs
867 * Purpose: This function adds a SVC to UE's schdSvcsLst.
869 * Invoked by: Specific Scheduler
871 * @param[out] RgSchUeCb *ue
872 * @param[in] RgSchDlLcCb *svc
877 PRIVATE Void rgSCHSc1DlAdd2UeSchdSvcs
884 PRIVATE Void rgSCHSc1DlAdd2UeSchdSvcs(cell, ue, svc)
890 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
891 RgSchSc1DlUe *ueSc1 = RG_GET_SC1_UE_DL(ue, cell);
893 /* checking SVC's presence in this lst is unnecessary */
894 cmLListAdd2Tail(&ueSc1->schdSvcs, &svcSc1->schdSvcLnk);
895 svcSc1->schdSvcLnk.node = (PTR)svc;
901 * @brief This function performs new allocations for UEs
905 * Function: rgSCHSc1DlDedTx
906 * Purpose: This function implements scheduler for DL allocation for
907 * new transmissions of UEs.
908 * 1. It performs across 9 priorities that it supports -
909 * This is from 3GPP specifications
910 * 2. There are known number of GBR/MBR queues
911 * 3. The first queue is highest priority queue and is
912 * satisfied completely prior to any other queues. This
913 * queue is for RRC signalling.
914 * 4. Futher GBR/MBR queues are satisfied for GBR and then MBR
915 * 5. Subsequently all other queues are looked at for AMBR
917 * Invoked by: Scheduler
919 * @param[in] RgSchCellCb* cell
920 * @param[in] RgSchDlSf *subFrm
921 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
926 PRIVATE Void rgSCHSc1DlDedTx
930 RgSchCmnDlRbAllocInfo *allocInfo
933 PRIVATE Void rgSCHSc1DlDedTx(cell, subFrm, allocInfo)
936 RgSchCmnDlRbAllocInfo *allocInfo;
941 RgSchUeCb *ue = NULLP;
944 RgSchSc1DlSvc *svcSc1;
946 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
949 /* Process the first queue that is for RRC signalling and is of */
950 /* highest priority. */
951 lst = &sc1CellDl->prioLst[0];
955 /* Getting service instead of UE */
956 svc = (RgSchDlLcCb *)node->node;
958 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
960 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->bo, allocInfo) != ROK)
967 /* Perform allocation for the GBR transmissions */
968 for(i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
970 lst = &sc1CellDl->prioLst[i];
974 /* Getting service instead of UE */
975 svc = (RgSchDlLcCb *)node->node;
977 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
979 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->effMbr, allocInfo) != ROK)
987 /* To implement AMBR svc scheduling */
988 for(i = RG_SCH_SC1_DL_GBR_PRIO_END + 1; i < RG_SCH_SC1_DL_PRIOS; i++)
990 lst = &sc1CellDl->prioLst[i];
994 ue = (RgSchUeCb *)node->node;
995 ueDl = RG_GET_SC1_UE_DL(ue, cell);
997 /* Get the Curr ambr svc for which allocation is to be made */
999 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, ueDl->effAmbr, allocInfo) != ROK)
1010 * @brief scheduling for a cell
1014 * Function : rgSCHSc1DlPreSchd
1017 * - Nothing to be done in case of RR
1019 * @param[in] Inst schInst
1023 PRIVATE Void rgSCHSc1DlPreSchd
1028 Void rgSCHSc1DlPreSchd(cell)
1036 * @brief scheduling for a cell
1040 * Function : rgSCHSc1DlPstSchd
1043 * - Nothing to be done in case of RR
1045 * @param[in] Inst schInst
1049 PRIVATE Void rgSCHSc1DlPstSchd
1054 Void rgSCHSc1DlPstSchd(schInst)
1064 * @brief This function implements scheduler DL allocation
1068 * Function: rgSCHSc1DlDedNewTx
1069 * Purpose: This function implements scheduler for DL allocation for
1072 * Invoked by: Scheduler
1074 * @param[in] RgSchCellCb *cell
1075 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
1080 PRIVATE Void rgSCHSc1DlDedNewTx
1083 RgSchCmnDlRbAllocInfo *allocInfo
1086 PRIVATE Void rgSCHSc1DlDedNewTx(cell, allocInfo)
1088 RgSchCmnDlRbAllocInfo *allocInfo;
1091 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
1093 Inst inst = cell->instIdx;
1095 RGSCHDBGPRM(inst, (rgSchPBuf(inst), "rgSCHSc1DlDedNewTx\n"));
1097 /* Now perform the new UE selections */
1098 rgSCHSc1DlDedTx(cell, subFrm, allocInfo);
1100 /* Stack Crash problem for TRACE5 changes. Added the return below */
1105 * @brief This function implements scheduler DL allocation
1109 * Function: rgSCHSc1DlDedRetx
1110 * Purpose: This function implements scheduler for DL allocation for
1113 * Invoked by: Scheduler
1115 * @param[in] RgSchCellCb *cell
1116 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
1121 PRIVATE Void rgSCHSc1DlDedRetx
1124 RgSchCmnDlRbAllocInfo *allocInfo
1127 PRIVATE Void rgSCHSc1DlDedRetx(cell, allocInfo)
1129 RgSchCmnDlRbAllocInfo *allocInfo;
1132 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
1134 Inst inst = cell->instIdx;
1136 RGSCHDBGPRM(inst, (rgSchPBuf(inst), "rgSCHSc1DlDedRetx\n"));
1138 rgSCHSc1DlRetxAlloc(cell, subFrm, allocInfo);
1147 * @brief This function adds a service to scheduler
1151 * Function: rgSCHSc1DlSvcAddToSchd
1152 * Purpose: This function adds a service to the list of services
1153 * based on the priority of the services.
1155 * Invoked by: BO and Scheduler
1157 * @param[in] RgSchCellCb* cell
1158 * @param[in] RgSchUeCb* ue
1163 PRIVATE Void rgSCHSc1DlSvcAddToSchd
1169 PRIVATE Void rgSCHSc1DlSvcAddToSchd(cell, svc)
1177 RgSchSc1DlSvc *svcSc1;
1178 RgSchSc1DlSvc *lSvcSc1;
1179 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
1180 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1183 svcSc1 = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
1184 /* The service is already in the scheduler */
1185 if (svcSc1->prioLnk.node != NULLP)
1190 /* If the priority = 0, it is the highest priority with infinite */
1191 /* allowance and the priority is time bound and hence just place */
1192 /* it at the end of the queue */
1193 if (svcCmn->prio == 0)
1195 lst = &(sc1CellDl->prioLst[0]);
1196 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1197 svcSc1->prioLnk.node = (PTR)svc;
1198 /* If a svc is put in to cell wide priority Qs
1199 * then add the same to UE's lcsWithData List */
1200 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1204 /* Handle GBR services. We have them of next importance */
1205 /* check changed from .._START to .._END */
1206 if (svcCmn->prio <= RG_SCH_SC1_DL_GBR_PRIO_END)
1208 if (!RG_SC1_SVC_HAS_DATA(svc,cell))
1210 lst = &(sc1CellDl->prioLst[svcCmn->prio]);
1214 lSvc = (RgSchDlLcCb *)(node->node);
1215 lSvcSc1 = RG_GET_SC1_SVC_DL(lSvc->ue,lSvc,cell);
1216 if (((svcSc1->effGbr > 0) &&
1217 (lSvcSc1->effGbr <= svcSc1->effGbr)) ||
1218 ((lSvcSc1->effGbr == 0) && (svcSc1->effMbr > 0) &&
1219 (lSvcSc1->effMbr <= svcSc1->effMbr)))
1227 /* We have come to the end of the queue. Let's place it */
1228 /* here irresepctive of effGbr or effMBr */
1229 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1230 svcSc1->prioLnk.node = (PTR)svc;
1235 cmLListInsCrnt(lst, &svcSc1->prioLnk);
1236 svcSc1->prioLnk.node = (PTR)svc;
1238 /* If a svc is put in to cell wide priority Qs
1239 * then add the same to UE's lcsWithData List */
1240 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1248 * @brief This function removes a UE from scheduler Queue
1252 * Function: rgSCHSc1DlUeRmvFrmSchd
1253 * Purpose: This function removes a UE from the list of UEs
1254 * based on the priority of the UEs Current AMBR SVC.
1256 * Invoked by: BO and Scheduler
1258 * @param[in] RgSchCellCb* cell
1259 * @param[in] RgSchUeCb* ue
1264 PRIVATE Void rgSCHSc1DlUeRmvFrmSchd
1270 PRIVATE Void rgSCHSc1DlUeRmvFrmSchd(cell, ue)
1275 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1276 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1280 lst = &cellDl->prioLst[ueDl->prio];
1281 if (ueDl->prioLnk.node != NULLP)
1283 cmLListDelFrm(lst, &ueDl->prioLnk);
1284 ueDl->prioLnk.node = (PTR)NULLP;
1285 /* If a svc is removed from cell wide priority Qs
1286 * then remove the same from UE's lcsWithData List */
1287 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1294 * @brief This function removes a SVC from UEs AMBR LIST
1298 * Function: rgSCHSc1DlSvcRmvFrmUeAmbrLst
1299 * Purpose: This function removes a SVC from UEs AMBR List.
1301 * Invoked by: BO and Scheduler
1303 * @param[in] RgSchUeCb* ue
1304 * @param[in] RgSchDlLcCb* svc
1309 PRIVATE Void rgSCHSc1DlSvcRmvFrmUeAmbrLst
1316 PRIVATE Void rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc)
1322 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1323 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1326 lst = &ueDl->ambrLst;
1327 if (svcSc1->prioLnk.node != NULLP)
1329 cmLListDelFrm(lst, &svcSc1->prioLnk);
1330 svcSc1->prioLnk.node = (PTR)NULLP;
1337 * @brief This function adds a SVC to UEs AMBR LIST
1341 * Function: rgSCHSc1DlSvcAddToUeAmbrLst
1342 * Purpose: This function adds a SVC to UEs AMBR List.
1344 * Invoked by: BO and Scheduler
1346 * @param[in] RgSchUeCb* ue
1347 * @param[in] RgSchDlLcCb* svc
1352 PRIVATE Void rgSCHSc1DlSvcAddToUeAmbrLst
1359 PRIVATE Void rgSCHSc1DlSvcAddToUeAmbrLst(cell, ue, svc)
1365 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1368 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1369 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1372 /* If svc already present in AMBR List return */
1373 if (svcSc1->prioLnk.node != NULLP)
1376 node = ueDl->ambrLst.first;
1379 lsvc = (RgSchDlLcCb *)(node->node);
1380 if (((RgSchCmnDlSvc*)(lsvc->sch))->prio > svcCmn->prio)
1388 cmLListAdd2Tail(&ueDl->ambrLst, &svcSc1->prioLnk);
1389 svcSc1->prioLnk.node = (PTR)svc;
1393 ueDl->ambrLst.crnt = node;
1394 cmLListInsCrnt(&ueDl->ambrLst, &svcSc1->prioLnk);
1395 svcSc1->prioLnk.node = (PTR)svc;
1403 * @brief This function removes a service from scheduler
1407 * Function: rgSCHSc1DlSvcRmvFrmSchd
1408 * Purpose: This function removes the SVC from the scheduler Qs.
1410 * Invoked by: BO and Scheduler
1412 * @param[in] RgSchCellCb* cell
1413 * @param[in] RgSchUeCb* ue
1418 PRIVATE Void rgSCHSc1DlSvcRmvFrmSchd
1424 PRIVATE Void rgSCHSc1DlSvcRmvFrmSchd(cell, svc)
1429 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1430 RgSchSc1DlSvc *svcDl = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
1431 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1435 lst = &(cellDl->prioLst[svcCmn->prio]);
1436 if (svcDl->prioLnk.node != NULLP)
1438 cmLListDelFrm(lst, &svcDl->prioLnk);
1439 svcDl->prioLnk.node = NULLP;
1440 /* If a svc is removed from cell wide priority Qs
1441 * then remove the same from UE's lcsWithData List */
1442 rgSCHSc1DlRmFrmUeLcsWithData(cell, svc->ue, svc);
1449 * @brief This function adds a service to scheduler for a UE
1453 * Function: rgSCHSc1DlSvcAdd
1454 * Purpose: This function is made available through a FP for
1455 * making scheduler aware of a service added to UE
1457 * Invoked by: BO and Scheduler
1459 * @param[in] RgSchUeCb* ue
1460 * @param[in] RgSchDlLcCb* svc
1461 * @param[in] CrgDlLchCfg* qos
1466 PRIVATE Void rgSCHSc1DlSvcAdd
1474 PRIVATE Void rgSCHSc1DlSvcAdd(cell, ue, svc, cfg)
1481 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1482 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1483 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1487 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1489 svcSc1->gbr = svcCmn->gbr;
1490 svcSc1->mbr = svcCmn->mbr;
1491 cmLListAdd2Tail(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1492 svcSc1->gbrLnk.node = (PTR)svc;
1499 * @brief This function deletes a service from scheduler
1503 * Function: rgSCHSc1DlLcRmv
1504 * Purpose: This function is made available through a FP for
1505 * making scheduler aware of a service being deleted from UE
1507 * Invoked by: BO and Scheduler
1509 * @param[in] RgSchCellCb* cell
1510 * @param[in] RgSchUeCb* ue
1511 * @param[in] RgSchDlLcCb* svc
1516 Void rgSCHSc1DlLcRmv
1523 Void rgSCHSc1DlLcRmv(cell, ue, svc)
1530 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1531 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1534 if (svcSc1 == NULLP)
1538 ueDl = RG_GET_SC1_UE_DL(ue, cell);
1540 if (svcCmn->prio == 0)
1542 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1544 else if (RG_SCH_CMN_SVC_IS_GBR(svc))
1546 if (svcSc1->gbrLnk.node != NULLP)
1548 cmLListDelFrm(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1549 svcSc1->gbrLnk.node = NULLP;
1551 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1553 else /* if AMBR service */
1555 if (ueDl->ambrSvc == svc)
1557 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1558 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1559 ueDl->ambrSvc = NULLP;
1560 if (ueDl->ambrLst.first != NULLP)
1562 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1563 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svc->bo);
1566 rgSCHSc1DlUeAddToSchd(cell, ue);
1572 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1575 /* ccpu00117052 - MOD - Passing double pointer
1576 for proper NULLP assignment*/
1577 rgSCHUtlFreeSBuf(cell->instIdx,
1578 (Data**)(&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,svc,cell))), (sizeof(RgSchSc1DlSvc)));
1583 * @brief This function is invoked as part of SVC reconfig
1587 * Function: rgSCHSc1DlSvcMod
1588 * Purpose: This function is made available through a FP for
1589 * making scheduler aware of a service reconfiguration.
1591 * Invoked by: Scheduler
1593 * @param[in] RgSchDlLcCb* svc
1594 * @param[in] CrgLchRecfg* recfg
1599 PRIVATE Void rgSCHSc1DlSvcMod
1607 PRIVATE Void rgSCHSc1DlSvcMod(cell,ue,svc, recfg)
1614 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1615 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1617 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1619 /* Convert the QOS to handle the refresh duration */
1620 svcSc1->gbr = svcCmn->gbr;
1621 svcSc1->mbr = svcCmn->mbr;
1627 * @brief This function adds UE to scheduler for an AMBR service
1631 * Function: rgSCHSc1DlUeAddToSchd
1632 * Purpose: This function adds a UE to scheduler for the AMBR
1633 * service of highest priority.
1635 * Invoked by: BO and Scheduler
1637 * @param[in] RgSchCellCb* cell
1638 * @param[in] RgSchUeCb* ue
1643 PRIVATE Void rgSCHSc1DlUeAddToSchd
1649 PRIVATE Void rgSCHSc1DlUeAddToSchd(cell, ue)
1654 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1655 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1656 RgSchSc1DlUe *lueDl;
1659 RgSchUeCb *nodeUe = NULLP;
1661 ueDl->prio = ((RgSchCmnDlSvc *)(ueDl->ambrSvc->sch))->prio;
1662 lst = &cellDl->prioLst[ueDl->prio];
1663 /* if UE already in list, remove and
1665 if (ueDl->prioLnk.node != NULLP)
1667 cmLListDelFrm(lst, &ueDl->prioLnk);
1668 ueDl->prioLnk.node = NULLP;
1669 /* If a svc is removed from cell wide priority Qs
1670 * then remove the same from UE's lcsWithData List */
1671 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1676 nodeUe = (RgSchUeCb *)(node->node);
1677 lueDl = RG_GET_SC1_UE_DL(nodeUe, cell);
1678 if (lueDl->effAmbr < ueDl->effAmbr)
1684 cmLListAdd2Tail(lst, &ueDl->prioLnk);
1685 ueDl->prioLnk.node = (PTR)ue;
1690 cmLListInsCrnt(lst, &ueDl->prioLnk);
1691 ueDl->prioLnk.node = (PTR)ue;
1693 /* If a svc is put in to cell wide priority Qs
1694 * then add the same to UE's lcsWithData List */
1695 rgSCHSc1DlAdd2UeLcsWithData(cell, ue, ueDl->ambrSvc);
1701 * @brief This function implements managing BO for an ABMR service
1705 * Function: rgSCHSc1DlMngAmbrSvcPosn
1706 * Purpose: This function should be called whenever there is a
1707 * change BO for a AMBR service.
1709 * Invoked by: BO and Scheduler
1711 * @param[in] RgSchCellCb* cell
1712 * @param[in] RgSchUeCb* ue
1713 * @param[in] RgSchDlLcCb* svc
1718 PRIVATE Void rgSCHSc1DlMngAmbrSvcPosn
1725 PRIVATE Void rgSCHSc1DlMngAmbrSvcPosn(cell, ue, svc)
1731 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1732 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1734 if (svcSc1->bo == 0)
1736 if (ueDl->ambrSvc == svc)
1738 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1739 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1740 ueDl->ambrSvc = NULLP;
1741 if (ueDl->ambrLst.first != NULLP)
1743 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1744 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1747 rgSCHSc1DlUeAddToSchd(cell, ue);
1753 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1756 else /* svcSc1->bo != 0 */
1758 if (svcSc1->prioLnk.node != NULLP)
1760 if (svc == ueDl->ambrSvc)
1762 ueDl->effAmbr = RGSCH_MIN(svcSc1->bo, ueDl->ambr);
1763 /* Update UE's position in the scheduler */
1766 rgSCHSc1DlUeAddToSchd(cell, ue);
1770 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1775 rgSCHSc1DlSvcAddToUeAmbrLst(cell, ue, svc);
1776 /* Current ambr svc is always the first node of ambrLst.*/
1777 if (ueDl->ambrLst.first->node == (PTR)svc)
1779 if(ueDl->ambrSvc != svc)
1783 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1785 ueDl->ambrSvc = svc;
1786 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1789 rgSCHSc1DlUeAddToSchd(cell, ue);
1799 * @brief This function updates the scheduler with service for a UE
1803 * Function: rgSCHSc1DlLcBoUpd
1804 * Purpose: This function should be called whenever there is a
1805 * change BO for a service.
1807 * Invoked by: BO and Scheduler
1809 * @param[in] RgSchCellCb* cell
1810 * @param[in] RgSchUeCb* ue
1811 * @param[in] RgSchDlLcCb* svc
1816 Void rgSCHSc1DlLcBoUpd
1823 Void rgSCHSc1DlLcBoUpd(cell, ue, svc)
1829 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1831 if (svcSc1->bo == svc->bo)
1835 svcSc1->bo = svc->bo;
1836 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(ue))
1840 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
1842 /* Stack Crash problem for TRACE5 changes. Added the return below */
1849 * @brief This function updates the scheduler with Prio0 service for a UE
1853 * Function: rgSCHSc1DlMngPrio0SvcPosn
1854 * Purpose: This func shall be triggered whenever there is a
1855 * change in the "Bo yet to be satisfied" field of the service.
1856 * Appropriately positions the svc in its prio Q.
1857 * Removes the SVC from the Q if BO is completely satisfied.
1859 * Invoked by: BO and Scheduler
1861 * @param[in] RgSchCellCb* cell
1862 * @param[in] RgSchUeCb* ue
1863 * @param[in] RgSchDlLcCb* svc
1868 PRIVATE Void rgSCHSc1DlMngPrio0SvcPosn
1875 PRIVATE Void rgSCHSc1DlMngPrio0SvcPosn(cell, ue, svc)
1881 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1883 /* In this priority, we just add or remove to the queue */
1886 rgSCHSc1DlSvcAddToSchd(cell, svc);
1890 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1897 * @brief This function updates the scheduler with GBR service for a UE
1901 * Function: rgSCHSc1DlMngGbrSvcPosn
1902 * Purpose: This func shall be triggered whenever there is a
1903 * change in the "Bo yet to be satisfied" field of the service.
1904 * Appropriately positions the svc in its prio Q.
1905 * Removes the SVC from the Q if BO is completely satisfied.
1907 * Invoked by: BO and Scheduler
1909 * @param[in] RgSchCellCb* cell
1910 * @param[in] RgSchUeCb* ue
1911 * @param[in] RgSchDlLcCb* svc
1916 PRIVATE Void rgSCHSc1DlMngGbrSvcPosn
1923 PRIVATE Void rgSCHSc1DlMngGbrSvcPosn(cell, ue, svc)
1929 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1931 /* Handle a GBR service. */
1932 svcSc1->effGbr = RGSCH_MIN(svcSc1->bo, svcSc1->gbr);
1933 svcSc1->effMbr = RGSCH_MIN(svcSc1->bo, svcSc1->mbr);
1934 /* Adjust the SVC priority within the queue */
1935 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1936 rgSCHSc1DlSvcAddToSchd(cell, svc);
1942 * @brief This function updates the scheduler with service for a UE
1946 * Function: rgSCHSc1DlMngSvcPosn
1947 * Purpose: This func shall be triggered whenever there is a
1948 * change in the "Bo yet to be satisfied" field of the service.
1949 * Appropriately positions the svc in its prio Q.
1950 * Removes the SVC from the Q if BO is completely satisfied.
1952 * Invoked by: BO and Scheduler
1954 * @param[in] RgSchCellCb* cell
1955 * @param[in] RgSchUeCb* ue
1956 * @param[in] RgSchDlLcCb* svc
1961 PRIVATE Void rgSCHSc1DlMngSvcPosn
1968 PRIVATE Void rgSCHSc1DlMngSvcPosn(cell, ue, svc)
1974 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1975 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1977 (cellDl->svcMngFunc[svcCmn->prio])(cell, ue, svc);
1981 /*--------------------------*
1982 * DL specific functions END
1983 *---------------------------*/
1988 * @brief Scheduler processing on cell configuration
1992 * Function : rgSCHSc1RgrDlCellCfg
1994 * This function does requisite initialisation
1995 * and setup for scheduler1 when a cell is
1998 * @param[in] RgSchCellCb *cell
1999 * @param[in] RgrCellCfg *cellCfg
2000 * @param[out] RgSchErrInfo *err
2006 S16 rgSCHSc1RgrDlCellCfg
2009 RgrCellCfg *cellCfg,
2013 S16 rgSCHSc1RgrDlCellCfg(cell, cellCfg, err)
2015 RgrCellCfg *cellCfg;
2020 RgSchSc1DlCell *cellDl;
2023 if((ret = rgSCHUtlAllocSBuf(cell->instIdx,
2024 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc), \
2025 (sizeof(RgSchSc1DlCell)))) != ROK)
2027 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
2028 "Memory allocation FAILED");
2029 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
2033 cellDl = RG_GET_SC1_CELL_DL(cell);
2034 /* Now perform downlink Queues related initializations */
2035 rgSCHSc1DlInitQueues(cellDl);
2037 } /* rgSCHSc1RgrDlCellCfg */
2039 /***********************************************************
2041 * Func : rgSCHSc1DlDeinitQueues
2043 * Desc : De-initialise downlink scheduler queues
2051 **********************************************************/
2053 PRIVATE Void rgSCHSc1DlDeinitQueues
2055 RgSchSc1DlCell *cellDl
2058 PRIVATE Void rgSCHSc1DlDeinitQueues(cellDl)
2059 RgSchSc1DlCell *cellDl;
2064 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
2066 cmLListInit(&cellDl->prioLst[i]);
2067 cmLListInit(&cellDl->retxLst[i]);
2074 * @brief Scheduler processing for cell delete
2078 * Function : rgSCHSc1DlCellDel
2080 * This functions de-initialises and frees memory
2081 * taken up by scheduler1 for the entire cell.
2083 * @param[in] RgSchCellCb *cell
2087 Void rgSCHSc1DlCellDel
2092 Void rgSCHSc1DlCellDel(cell)
2097 if (((RgSchSc1DlCell *)((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc) \
2103 /* Perform the deinit for the DL scheduler */
2104 rgSCHSc1DlDeinitQueues(RG_GET_SC1_CELL_DL(cell));
2105 /* ccpu00117052 - MOD - Passing double pointer
2106 for proper NULLP assignment*/
2107 rgSCHUtlFreeSBuf(cell->instIdx,
2108 (Data**)(&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc)),
2109 (sizeof(RgSchSc1DlCell)));
2111 } /* rgSCHSc1DlCellDel */
2114 * @brief UE initialisation for scheduler
2118 * Function : rgSCHSc1RgrDlUeCfg
2120 * This functions intialises UE specific scheduler
2123 * @param[in] RgSchCellCb *cell
2124 * @param[in] RgSchUeCb *ue
2125 * @param[int] RgrUeCfg *ueCfg
2126 * @param[out] RgSchErrInfo *err
2132 S16 rgSCHSc1RgrDlUeCfg
2140 S16 rgSCHSc1RgrDlUeCfg(cell, ue, ueCfg, err)
2147 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
2148 Inst inst = cell->instIdx;
2152 if((rgSCHUtlAllocSBuf(inst,
2153 (Data**)&(ueSchCmn->dl.schSpfc), (sizeof(RgSchSc1DlUe))) != ROK))
2155 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Memory allocation FAILED"
2156 "CRNTI:%d",ue->ueId);
2157 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
2160 ueDl = (RgSchSc1DlUe *)ueSchCmn->dl.schSpfc;
2161 if (ue->dl.ambrCfgd)
2163 ueDl->ambr = ue->dl.ambrCfgd;
2167 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
2169 cmLListInit(&ueDl->lcsWithData);
2170 cmLListInit(&ueDl->gbrSvcs);
2171 cmLListInit(&ueDl->ambrLst);
2172 cmLListInit(&ueDl->schdSvcs);
2173 cmLListInit(&ueDl->retxHqProcs);
2175 } /* rgSCHSc1RgrDlUeCfg */
2179 * @brief Dl Harq Entity initialization for SC1
2183 * Function : rgSCHSc1DlUeHqEntInit
2186 * - Create SC1 related information per Harq Entity
2188 * @param[in] RgrSchCellCb *cell
2189 * @param[in] RgSchUeCb *ue
2195 S16 rgSCHSc1DlUeHqEntInit
2201 S16 rgSCHSc1DlUeHqEntInit(cell, hqEnt)
2206 RgSchSc1DlHqProc *hqSpcSch;
2207 RgSchDlHqProcCb *hqP;
2209 /* making use of hqE->sch for one shot allocation
2210 * of RgSchSc1DlHqProc structures */
2211 if (rgSCHUtlAllocSBuf(cell->instIdx,
2212 (Data**)&(hqEnt->sch),
2213 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc))) != ROK)
2215 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
2216 "Memory allocation FAILED CRNTI:%d",hqEnt->ue->ueId);
2219 hqSpcSch = (RgSchSc1DlHqProc *)(hqEnt->sch);
2220 for(cnt = 0; cnt < hqEnt->numHqPrcs; cnt++)
2222 hqP = &hqEnt->procs[cnt];
2223 ((RgSchCmnDlHqProc *)((hqP)->sch))->schSpfc = \
2230 * @brief Dl Harq Entity deletion for Sc1
2234 * Function : rgSCHSc1DlUeHqEntDeInit
2237 * - Free SC1 related information per Harq Entity
2239 * @param[in] RgrSchCellCb *cell
2240 * @param[in] RgSchDlHqEnt *hqE
2244 S16 rgSCHSc1DlUeHqEntDeInit
2250 S16 rgSCHSc1DlUeHqEntDeInit(cell, hqE)
2258 rgSCHUtlFreeSBuf(cell->instIdx,
2259 (Data**)(&(hqE->sch)),
2260 (hqE->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
2269 * @brief UE reconfiguration for scheduler
2273 * Function : rgSCHSc1RgrDlUeRecfg
2275 * This functions updates UE specific scheduler
2276 * information upon UE reconfiguration
2278 * @param[in] RgSchCellCb *cell
2279 * @param[in] RgSchUeCb *ue
2280 * @param[int] RgrUeRecfg *ueRecfg
2281 * @param[out] RgSchErrInfo *err
2287 S16 rgSCHSc1RgrDlUeRecfg
2291 RgrUeRecfg *ueRecfg,
2295 S16 rgSCHSc1RgrDlUeRecfg(cell, ue, ueRecfg, err)
2298 RgrUeRecfg *ueRecfg;
2302 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2303 RgSchCmnDlUe *ueCmnDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2304 /*cell added as part of CA dev*/
2305 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2307 if (ue->dl.ambrCfgd)
2309 ueDl->ambr = ue->dl.ambrCfgd;
2313 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
2316 /* Discarding TB2's context from scheduling Queues.
2317 * Since TB2 transmission needs signalling using
2318 * TM specific formats. And since during this transient
2319 * period of UE TM Recfg, SCH always uses Format 1A,
2320 * the TB2s are discarded. */
2321 if (ueCmnDl->mimoInfo.forceTD & RG_SCH_CMN_TD_TXMODE_RECFG)
2323 /* If HqP is in retx queue only for TB2 retx scheduling
2324 * then remove the harp proc from retx Queue */
2326 /* If Hqp is in retx queue for retx allocation of
2327 * both TB1 and TB2, then reset TB2's state as ACKED */
2328 RgSchDlHqProcCb *hqP;
2330 RgInfRlsHqInfo *rlsHqBufs = &(cell->rlsHqArr[cell->crntHqIdx]);
2333 /* Prepare TB2 release information to be sent to MAC */
2334 rlsHqBufs->numUes = 0;
2335 for(i = 0; i < hqEnt->numHqPrcs; i++)
2337 hqP = &hqEnt->procs[i];
2338 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = ue->ueId;
2339 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = hqP->procId;
2340 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
2342 if (hqP->tbInfo[0].state != HQ_TB_NACKED)
2344 /* Remove the HqP from retx Queue.
2346 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2347 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
2349 rgSCHDhmRlsHqpTb(hqP, 1, TRUE);
2350 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[0] = 2;
2351 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 1;
2353 rlsHqBufs->numUes++;
2355 /* Send the hqProc list for MAC to clear TB1 contents */
2356 if (rlsHqBufs->numUes)
2358 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
2359 RgSchMacRlsHq (&pst, rlsHqBufs);
2363 } /* rgSCHSc1RgrDlUeRecfg */
2366 * @brief Removes UEs context from Priority Qs.
2370 * Function : rgSCHSc1DlRmvUeFrmPrioQs
2373 * @param[in] RgSchCellCb *cell
2374 * @param[in] RgSchUeCb *ue
2378 PRIVATE Void rgSCHSc1DlRmvUeFrmPrioQs
2384 PRIVATE Void rgSCHSc1DlRmvUeFrmPrioQs(cell, ue)
2389 RgSchSc1DlUe *sc1Ue;
2394 sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
2396 /* Remove UE From DL priority queues */
2397 if (sc1Ue->ambrSvc != NULLP)
2399 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
2402 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
2404 svc = ue->dl.lcCb[idx];
2409 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
2413 } /* rgSCHSc1DlRmvUeFrmPrioQs */
2416 * @brief Inactivate UE reason : measgap, acknaprept, poInactv.
2420 * Function : rgSCHSc1DlInactvtUe
2423 * @param[in] RgSchCellCb *cell
2424 * @param[in] RgSchUeCb *ue
2428 PRIVATE Void rgSCHSc1DlInactvtUe
2434 PRIVATE Void rgSCHSc1DlInactvtUe(cell, ue)
2439 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
2440 RgSchDlHqProcCb *hqP;
2441 RgSchCmnDlHqProc *hqProcDl;
2443 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2446 /* ccpu00130170: UE related HARQ Procs are cleared only
2447 if UE's Re-establishment procedure is not in progress*/
2448 if(!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE))
2450 /* remove all in use HARQ processes from the subframes.
2451 * Store them in UEs hqProc Lst. Add back to cell's
2452 * retx lst when UE is activated again. */
2453 for(i = 0; i < hqEnt->numHqPrcs; i++)
2455 hqP = &hqEnt->procs[i];
2456 hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
2457 /* Remove retx procs from cell's list and
2458 * add them to UE's List */
2461 !(RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)) &&
2463 hqProcDl->retxLnk.node != NULLP)
2465 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
2466 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
2467 hqProcDl->retxLnk.node = NULLP;
2468 rgSCHSc1DlProcAddToUeRetx(cell, ue, hqP);
2473 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2476 } /* rgSCHSc1DlInactvtUe */
2480 * @brief UE suspension.
2484 * Function : rgSCHSc1DlSuspendUe
2486 * Removes UE, its SVCs and its HqPs from CELL WIDE
2487 * PrioQs and Retx Qs Respectively.
2489 * @param[in] RgSchCellCb *cell
2490 * @param[in] RgSchUeCb *ue
2494 PRIVATE Void rgSCHSc1DlSuspendUe
2500 PRIVATE Void rgSCHSc1DlSuspendUe(cell, ue)
2505 RgSchDlHqProcCb *hqP;
2508 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2511 /* remove all in use HARQ processes from the subframes.
2512 * Store them in UEs hqProc Lst. Add back to cell's
2513 * retx lst when UE is activated again. */
2514 for(i = 0; i < hqEnt->numHqPrcs; i++)
2516 hqP = &hqEnt->procs[i];
2517 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2518 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
2519 /* Removing the Harq Proc from subframes list */
2520 if (hqP->hqPSfLnk.node != NULLP)
2524 cmLListDelFrm(&hqP->subFrm->pdcchInfo.pdcchs,
2526 cmLListAdd2Tail(&cell->pdcchLst, &hqP->pdcch->lnk);
2530 rgSCHUtlDlHqPTbRmvFrmTx(hqP->subFrm,hqP,0,FALSE);
2532 for (j = 0; j < 2; j++)
2534 if (hqP->tbInfo[j].state == HQ_TB_WAITING)
2536 rgSCHDhmRlsHqpTb(hqP, j, TRUE);
2541 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2544 } /* rgSCHSc1DlSuspendUe */
2546 /***********************************************************
2548 * Func : rgSCHSc1DlScanUpdPdbPrio
2550 * Desc : Increment the pivot and reposition the LCs under the pivot to
2551 * new location according to thieir PDB and elapsed time.
2559 **********************************************************/
2561 Void rgSCHSc1DlScanUpdPdbPrio
2566 Void rgSCHSc1DlScanUpdPdbPrio (cell)
2575 * @brief Function to update Flow control information
2576 * to be sent to MAC.
2580 * Function: rgSCHSc1DlFillFlowCntrlInfo
2582 * update Flow control information
2589 * @param[in] RgSchCellCb *cell
2590 RgInfSfAlloc *sfAlloc;
2595 S16 rgSCHSc1DlFillFlowCntrlInfo
2598 RgInfSfAlloc *sfAlloc
2601 S16 rgSCHSc1DlFillFlowCntrlInfo(cell,sfAlloc)
2603 RgInfSfAlloc *sfAlloc;
2609 * @brief UE deletion for scheduler
2613 * Function : rgSCHSc1DlUeDel
2615 * This functions deletes all scheduler information
2616 * pertaining to a UE
2618 * @param[in] RgSchCellCb *cell
2619 * @param[in] RgSchUeCb *ue
2623 Void rgSCHSc1DlUeDel
2629 Void rgSCHSc1DlUeDel(cell, ue)
2634 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2635 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
2638 if (sc1DlUe == NULLP)
2644 /* Remove UEs scheduler context */
2645 rgSCHSc1DlSuspendUe(cell, ue);
2647 /* Free all SC1 specific control blocks */
2648 if (hqEnt->sch != NULLP)
2650 /* ccpu00117052 - MOD - Passing double pointer
2651 for proper NULLP assignment*/
2652 rgSCHUtlFreeSBuf(cell->instIdx,
2653 (Data**)(&(hqEnt->sch)),
2654 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
2658 /* ccpu00117052 - MOD - Passing double pointer
2659 for proper NULLP assignment*/
2660 rgSCHUtlFreeSBuf(cell->instIdx, (Data**)(&sc1DlUe), (sizeof(RgSchSc1DlUe)));
2663 } /* rgSCHSc1DlUeDel */
2666 * @brief Scheduler invocation on Downlink logical channel addition
2670 * Function : rgSCHSc1RgrLcCfg
2672 * This functions does required processing when a new
2673 * (dedicated) logical channel is added.
2675 * @param[in] RgSchCellCb *cell
2676 * @param[in] RgSchUeCb *ue
2677 * @param[in] RgSchDlLcCb *dlLc
2678 * @param[int] RgrLchCfg *lcCfg
2679 * @param[out] RgSchErrInfo *err
2685 S16 rgSCHSc1RgrLcCfg
2694 S16 rgSCHSc1RgrLcCfg(cell, ue, dlLc, lcCfg, err)
2704 ret = rgSCHUtlAllocSBuf(cell->instIdx,
2705 (Data**)&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,dlLc,cell)), \
2706 (sizeof(RgSchSc1DlSvc)));
2709 RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHSc1CrgLcCfg():"
2710 "SCH struct alloc failed CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId);
2711 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
2715 rgSCHSc1DlSvcAdd(cell, ue, dlLc, &lcCfg->dlInfo);
2717 } /* rgSCHSc1RgrLcCfg */
2721 * @brief Scheduler invocation on logical channel addition
2725 * Function : rgSCHSc1RgrLcRecfg
2727 * This functions does required processing when an existing
2728 * (dedicated) logical channel is reconfigured. Assumes lcg
2729 * pointer in ulLc is set to the old value.
2730 * Independent of whether new LCG is meant to be configured,
2731 * the new LCG scheduler info is accessed and possibly modified.
2733 * @param[in] RgSchCellCb *cell
2734 * @param[in] RgSchUeCb *ue
2735 * @param[in] RgSchDlLcCb *dlLc
2736 * @param[int] RgrLchRecfg *lcRecfg
2737 * @param[out] RgSchErrInfo *err
2743 S16 rgSCHSc1RgrLcRecfg
2748 RgrLchRecfg *lcRecfg,
2752 S16 rgSCHSc1RgrLcRecfg(cell, ue, dlLc, lcRecfg, err)
2756 RgrLchRecfg *lcRecfg;
2763 rgSCHSc1DlSvcMod(cell,ue,dlLc, lcRecfg);
2766 } /* rgSCHSc1RgrLcRecfg */
2770 * @brief This function handles the reconfiguration of cell
2774 * Function: rgSCHSc1RgrDlCellRecfg
2775 * Purpose: Update the reconfiguration parameters.
2777 * Invoked by: Scheduler
2779 * @param[in] RgSchCellCb* cell
2784 PRIVATE S16 rgSCHSc1RgrDlCellRecfg
2787 RgrCellRecfg *recfg,
2791 PRIVATE S16 rgSCHSc1RgrDlCellRecfg(cell, recfg, err)
2793 RgrCellRecfg *recfg;
2803 * @brief This function implements scheduler DL allocation
2807 * Function: rgSCHSc1DlTaCmd
2808 * Purpose: This function implements scheduler for TA cmd alloc for
2809 * UEs. The hq proc availed as part of this alloc can be used
2810 * by the UEs Dedicated CH transmission allocation.
2812 * Invoked by: Scheduler
2814 * @param[in] RgSchCellCb* cell
2815 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
2820 PRIVATE Void rgSCHSc1DlTaCmd
2823 RgSchCmnDlRbAllocInfo *allocInfo
2826 PRIVATE Void rgSCHSc1DlTaCmd(cell, allocInfo)
2828 RgSchCmnDlRbAllocInfo *allocInfo;
2833 RgSchDlHqProcCb *proc;
2836 RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell);
2837 RgSchCmnDlUe *cmnUeDl;
2839 RgSchCmnDlHqProc *cmnHqDl;
2840 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
2842 Bool dlAllowed = FALSE;
2845 lst = &cellCmnDl->taLst;
2849 ue = (RgSchUeCb *)node->node;
2854 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
2855 if (dlAllowed == FALSE)
2861 /* If Ue is inactive in DL then ignore */
2862 if (ue->dl.dlInactvMask)
2866 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2867 /*cell added as part of CA dev*/
2868 ueDl = RG_GET_SC1_UE_DL(ue, cell);
2870 if (rgSCHDhmGetAvlHqProc(cell, ue, cellCmnDl->time, &proc) != ROK)
2874 /* Initialize some of the parameters of the HQ proc */
2875 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
2879 cmnHqDl->totBytes = 0;
2880 rgSCHCmnDlAllocTxRb(cell, subFrm, ue, RGSCH_TA_SIZE, &effBo, proc, allocInfo);
2883 /* If no allocations so far, meaning proc obtained now */
2884 if (cmnHqDl->totBytes == 0)
2886 rgSCHSc1RlsHqProc(proc);
2887 /* Added the handling for removing
2888 * UE from txHqPLst and resetting outStndalloc.*/
2889 if(proc->reqLnk.node != (PTR)NULLP)
2891 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
2892 proc->reqLnk.node = (PTR)NULLP;
2894 /*Re-set the outstanding alloc information.*/
2895 cmnUeDl->outStndAlloc = 0;
2897 /* Avl BW could not satisfy even TA so break */
2900 ueDl->taReqBytes = RGSCH_TA_SIZE;
2901 cmnUeDl->proc = proc;
2902 cmnHqDl->totBytes += effBo;
2903 /* 3.1 MIMO moving this call to cmn scheduler */
2904 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue);*/
2910 * @brief Scheduler invocation
2914 * Function: rgSCHSc1DlHndlInActUes
2915 * Purpose: The list of inactive UEs present in inactvLst should
2916 * be removed from the scheduling Qs.
2918 * Invoked by: Common Scheduler (TTI processing)
2920 * @param[in] RgSchCellCb *cell
2921 * @param[out] CmLListCp *inactvLst
2925 Void rgSCHSc1DlHndlInActUes
2928 CmLListCp *inactvLst
2931 Void rgSCHSc1DlHndlInActUes(cell, inactvLst)
2933 CmLListCp *inactvLst;
2940 node = inactvLst->first;
2943 ue = (RgSchUeCb *)node->node;
2945 /* Suspend this UE from further scheduling
2946 * till it is activated again. */
2947 rgSCHSc1DlInactvtUe(cell, ue);
2953 * @brief This function initializes all the data for the scheduler
2957 * Function: rgSCHSc1DlInit
2958 * Purpose: This function initializes the following information
2959 * 1. Efficiency table
2960 * 2. CQI to table index - It is one row for upto 3 RBs
2961 * and another row for greater than 3 RBs
2963 * currently extended prefix is compiled out.
2964 * Invoked by: MAC intialization code..may be ActvInit
2972 RgDlSchdApis *rgSchDlApis
2975 Void rgSCHSc1DlInit(rgSchDlApis)
2976 RgDlSchdApis *rgSchDlApis;
2979 /* Init the function pointers */
2980 rgSchDlApis->rgSCHRgrDlUeCfg = rgSCHSc1RgrDlUeCfg;
2981 rgSchDlApis->rgSCHRgrDlUeRecfg = rgSCHSc1RgrDlUeRecfg;
2982 rgSchDlApis->rgSCHFreeDlUe = rgSCHSc1DlUeDel;
2983 rgSchDlApis->rgSCHRgrDlCellCfg = rgSCHSc1RgrDlCellCfg;
2984 rgSchDlApis->rgSCHRgrDlCellRecfg = rgSCHSc1RgrDlCellRecfg;
2985 rgSchDlApis->rgSCHFreeDlCell = rgSCHSc1DlCellDel;
2986 rgSchDlApis->rgSCHRgrDlLcCfg = rgSCHSc1RgrLcCfg;
2987 rgSchDlApis->rgSCHRgrDlLcRecfg = rgSCHSc1RgrLcRecfg;
2988 rgSchDlApis->rgSCHFreeDlLc = rgSCHSc1DlLcRmv;
2989 rgSchDlApis->rgSCHDlNewSched = rgSCHSc1DlDedNewTx;
2990 rgSchDlApis->rgSCHDlPreSched = rgSCHSc1DlPreSchd;
2991 rgSchDlApis->rgSCHDlPstSched = rgSCHSc1DlPstSchd;
2992 rgSchDlApis->rgSCHDlRetxSched = rgSCHSc1DlDedRetx;
2993 rgSchDlApis->rgSCHDlCeSched = rgSCHSc1DlTaCmd;
2994 rgSchDlApis->rgSCHDlDedBoUpd = rgSCHSc1DlLcBoUpd;
2995 rgSchDlApis->rgSCHDlProcAddToRetx = rgSCHSc1DlProcAddToCellRetx;
2996 rgSchDlApis->rgSCHDlAllocFnlz = rgSCHSc1DlAllocFnlz;
2997 rgSchDlApis->rgSCHDlCqiInd = rgSCHSc1DlCqiInd;
2998 rgSchDlApis->rgSCHDlUeRefresh = rgSCHSc1DlUeRefresh;
2999 rgSchDlApis->rgSCHDlUeReset = rgSCHSc1DlUeReset;
3000 rgSchDlApis->rgSCHDlActvtUe = rgSCHSc1DlActvtUe;
3001 rgSchDlApis->rgSCHDlInactvtUes = rgSCHSc1DlHndlInActUes;
3002 rgSchDlApis->rgSCHDlUeHqEntInit = rgSCHSc1DlUeHqEntInit;
3003 rgSchDlApis->rgSCHDlUeHqEntDeInit = rgSCHSc1DlUeHqEntDeInit;
3004 rgSchDlApis->rgSCHDlProcRmvFrmRetx = rgSCHSc1DlProcRmvFrmRetx;
3005 rgSchDlApis->rgSCHDlTickForPdbTrkng = rgSCHSc1DlScanUpdPdbPrio;
3006 rgSchDlApis->rgSCHDlFillFlwCtrlInfo = rgSCHSc1DlFillFlowCntrlInfo;
3014 /***********************************************************
3016 * Func : rgSCHSc1DlInitQueues
3018 * Desc : Initial downlink scheduler queues
3026 **********************************************************/
3028 PRIVATE Void rgSCHSc1DlInitQueues
3030 RgSchSc1DlCell *cellDl
3033 PRIVATE Void rgSCHSc1DlInitQueues(cellDl)
3034 RgSchSc1DlCell *cellDl;
3039 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
3041 cmLListInit(&cellDl->prioLst[i]);
3042 cmLListInit(&cellDl->retxLst[i]);
3044 /* Set appropriate "manage svc positioning" function based on
3045 * svc priority as array index */
3047 for (i = 0; i < RG_SCH_SC1_DL_GBR_PRIO_START; i++)
3049 cellDl->svcMngFunc[i] = rgSCHSc1DlMngPrio0SvcPosn;
3052 for (i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
3054 cellDl->svcMngFunc[i] = rgSCHSc1DlMngGbrSvcPosn;
3056 /* for Non-GBR svcs */
3057 for (i = RG_SCH_SC1_DL_GBR_PRIO_END+1; i <= RG_SCH_CMN_MAX_PRIO; i++)
3059 cellDl->svcMngFunc[i] = rgSCHSc1DlMngAmbrSvcPosn;
3068 * @brief This function Processes the Final Allocations
3069 * made by the RB Allocator against the requested
3074 * Function: rgSCHSc1DlRetxAllocFnlz
3075 * Purpose : Remove the Retx Hq Proc from the Cell's
3076 * Retx list, if allocation is successful.
3077 * Fill the HqProc and PDCCH and append it to the SubFrm.
3081 * Invoked by: Common Scheduler
3083 * @param[in] RgSchCellCb *cell
3084 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
3089 PRIVATE Void rgSCHSc1DlRetxAllocFnlz
3092 RgSchCmnDlRbAllocInfo *allocInfo
3095 PRIVATE Void rgSCHSc1DlRetxAllocFnlz(cell, allocInfo)
3097 RgSchCmnDlRbAllocInfo *allocInfo;
3102 RgSchDlHqProcCb *hqP;
3103 RgSchDlRbAlloc *dlAllocCb = NULLP;
3105 node = allocInfo->dedAlloc.schdRetxHqPLst.first;
3108 hqP = (RgSchDlHqProcCb *)node->node;
3111 /* Fill PDCCH and assign it to HqP */
3112 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3114 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
3118 rgSCHCmnHdFddUpdDLMark(cell, ue);
3121 /* Extra Check: Retain the hqProc in the RETX Queue if one/more
3122 * TBs of the HqProc are yet to be scheduled for RETX.
3123 * Note: Here we are not tracking at TB Level, the priority Q
3124 * to which it belongs to. The retx prio of transmission is still
3125 * being maintained at hqProc level, rather than at TB level */
3126 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
3127 (hqP->tbInfo[1].state != HQ_TB_NACKED)) {
3128 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
3130 /* reset the UE allocation Information */
3131 rgSCHCmnDlUeResetTemp(ue, hqP);
3134 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
3135 node = allocInfo->dedAlloc.nonSchdRetxHqPLst.first;
3138 hqP = (RgSchDlHqProcCb *)node->node;
3141 /* reset the UE allocation Information */
3142 rgSCHCmnDlUeResetTemp(ue, hqP);
3147 /* 3.1 MIMO Alloc distribution functions being performed
3151 /***********************************************************
3153 * Func : rgSCHSc1DlSprTxTbDstn
3155 * Desc : Perform Actual allocation distribution among
3156 * UEs schd svcs and TA for a given spare TB "tbInfo" allocation.
3157 * spare TB allocation is as a result of 1 RETX TB allocation, when
3158 * conditions are favourable for 2 TB spatial multiplexing.
3166 **********************************************************/
3168 PRIVATE Void rgSCHSc1DlSprTxTbDstn
3172 RgSchDlHqTbCb *tbInfo,
3177 PRIVATE Void rgSCHSc1DlSprTxTbDstn(cell, ue, tbInfo, effAlloc, node)
3180 RgSchDlHqTbCb *tbInfo;
3186 RgSchSc1DlSvc *svcSc1;
3187 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
3189 RgSchLchAllocInfo lchSchdData;
3191 uint32_t rlcHdrEstmt;
3194 while((*node) && (*effAlloc > 0))
3196 svc = (RgSchDlLcCb *)(*node)->node;
3197 *node = (*node)->next;
3198 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
3200 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
3201 /* Update the SVC QOS Param */
3202 if (RG_SCH_CMN_SVC_IS_GBR(svc))
3204 effBo = svcSc1->effMbr + rlcHdrEstmt;
3205 bytes = RGSCH_MIN(*effAlloc, effBo);
3206 /* Determine How much BO is satisfied */
3207 if (bytes <= rlcHdrEstmt)
3211 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
3213 (svcSc1->bo -= bytes-rlcHdrEstmt);
3214 svc->bo = svcSc1->bo;
3218 /* Increment qciActiveLCs once since this LCs buffer will be present
3220 if (svc->lcType == CM_LTE_LCH_DTCH)
3222 ue->qciActiveLCs[svc->qciCb->qci]++;
3225 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
3227 if (ue->qciActiveLCs[svc->qciCb->qci])
3229 ue->qciActiveLCs[svc->qciCb->qci]--;
3231 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
3233 svc->qciCb->dlUeCount--;
3237 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
3238 (svcSc1->gbr -= bytes);
3239 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
3240 (svcSc1->mbr -= bytes);
3242 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
3244 effBo = ueDl->effAmbr + rlcHdrEstmt;
3245 bytes = RGSCH_MIN(*effAlloc, effBo);
3246 /* Determine How much BO is satisfied */
3247 if (bytes <= rlcHdrEstmt)
3251 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
3253 (svcSc1->bo -= bytes-rlcHdrEstmt);
3255 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
3256 (ueDl->ambr -= bytes);
3258 else /* Prio 0 SVC */
3260 effBo = svcSc1->bo + rlcHdrEstmt;
3261 bytes = RGSCH_MIN(*effAlloc, effBo);
3262 /* Determine How much BO is satisfied */
3263 if (bytes <= rlcHdrEstmt)
3267 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
3269 (svcSc1->bo -= bytes-rlcHdrEstmt);
3271 /* Position the service accordingly */
3272 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
3273 /* Update effAlloc */
3276 /* Update DHM for this SVC */
3277 lchSchdData.lcId = svc->lcId;
3278 lchSchdData.schdData = bytes;
3279 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
3285 /***********************************************************
3287 * Func : rgSCHSc1DlNewTxTbDstn
3289 * Desc : Perform Actual allocation distribution among
3290 * UEs schd svcs and TA for a given TB "tbInfo" allocation.
3291 * Assumption: TA is given higher priority in Alloc Distribution.
3299 **********************************************************/
3301 PRIVATE Void rgSCHSc1DlNewTxTbDstn
3305 RgSchDlHqTbCb *tbInfo,
3310 PRIVATE Void rgSCHSc1DlNewTxTbDstn(cell, ue, tbInfo, effAlloc, node)
3313 RgSchDlHqTbCb *tbInfo;
3319 RgSchSc1DlSvc *svcSc1 = NULLP;
3320 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
3322 RgSchLchAllocInfo lchSchdData;
3323 CmLList *prev = NULLP;
3326 if (ueDl->taReqBytes)
3328 if (ueDl->taReqBytes < *effAlloc)
3330 /*TA satisfied, hence remove from TA Lst */
3331 rgSCHCmnRmvFrmTaLst(cell, ue);
3332 /* Indicate to DHM that TA has been scheduled */
3333 rgSCHDhmSchdTa(ue, tbInfo);
3334 *effAlloc -= ueDl->taReqBytes;
3336 /* Reset the TA Req Bytes Field */
3337 ueDl->taReqBytes = 0;
3339 while((*node) && (*effAlloc > 0))
3341 svc = (RgSchDlLcCb *)(*node)->node;
3343 *node = (*node)->next;
3344 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
3345 if (*effAlloc > svcSc1->reqBytes)
3347 bytes = svcSc1->reqBytes;
3348 if (bytes <= svcSc1->hdrEstimate)
3352 /* 3.1 MIMO updating the reqBytes field */
3353 svcSc1->reqBytes = 0;
3359 if (bytes <= svcSc1->hdrEstimate)
3363 /* 3.1 MIMO updating the reqBytes field */
3364 svcSc1->reqBytes -= bytes;
3365 (svcSc1->bo <= bytes-svcSc1->hdrEstimate)?\
3367 (svcSc1->bo -= bytes-svcSc1->hdrEstimate);
3369 svc->bo = svcSc1->bo;
3374 /* Increment qciActiveLCs once since this LCs buffer will be present
3376 if (svc->lcType == CM_LTE_LCH_DTCH)
3378 ue->qciActiveLCs[svc->qciCb->qci]++;
3381 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
3383 if (ue->qciActiveLCs[svc->qciCb->qci])
3385 ue->qciActiveLCs[svc->qciCb->qci]--;
3387 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
3389 svc->qciCb->dlUeCount--;
3394 /* Update the SVC QOS Param */
3395 if (RG_SCH_CMN_SVC_IS_GBR(svc))
3397 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
3398 (svcSc1->gbr -= bytes);
3399 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
3400 (svcSc1->mbr -= bytes);
3402 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
3404 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
3405 (ueDl->ambr -= bytes);
3407 /* Position the service accordingly */
3408 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
3409 /* Update effAlloc */
3412 /* Update DHM for this SVC */
3413 lchSchdData.lcId = svc->lcId;
3414 lchSchdData.schdData = bytes;
3415 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
3417 /* If no more scheduled LCs for TB data distribution
3418 * then distribute the spare TB data among the LCs
3419 * of the UE with non-zero BO. This is effective for
3420 * schedulers work on LC level priorities rather than
3422 if ((*node == NULLP) && (svcSc1) && (svcSc1->reqBytes == 0))
3424 rgSCHSc1DlSprTxTbDstn(cell, ue, tbInfo, effAlloc,
3425 &ueDl->lcsWithData.first);
3429 /* make sure node points to the svc not completely
3431 * make sure if not served completely then
3432 * the other TB allocation accomodates the same */
3439 /***********************************************************
3441 * Func : rgSCHSc1DlNewTxUeFnlz
3443 * Desc : Perform allocation Distribution from scheduled TB
3444 * among the list of services considered for scheduling.
3452 **********************************************************/
3454 PRIVATE Void rgSCHSc1DlNewTxUeFnlz
3457 RgSchCmnDlRbAllocInfo *allocInfo,
3461 PRIVATE Void rgSCHSc1DlNewTxUeFnlz(cell, allocInfo, ue)
3463 RgSchCmnDlRbAllocInfo *allocInfo;
3468 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
3469 RgSchCmnDlUe *cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
3470 /*cell added as part of CA dev*/
3471 /* 3.1 MIMO Distribute data of each TB across services */
3472 RgSchDlRbAlloc *dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3473 uint32_t remTb1Bytes = dlAllocCb->tbInfo[0].bytesAlloc;
3474 uint32_t remTb2Bytes = dlAllocCb->tbInfo[1].bytesAlloc;
3475 uint32_t effAlloc = 0;
3476 /*ccpu00120365-ADD-added to code to check if second TB is utilized */
3477 uint32_t tb2Bytes = 0;
3481 /* 3.1 MIMO Consider the allocation of New TX TB for distribution */
3482 /* Handle schd services */
3483 node = ueDl->schdSvcs.first;
3485 effAlloc += remTb1Bytes;
3486 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[0],\
3487 &remTb1Bytes, &node);
3488 /* In the event that TB1 is not completely filled by the DL LCs
3489 * BO, consider the reducing the iMcs for increasing redundancy
3490 * and hence reception quality at UE */
3491 rgSCHCmnRdcImcsTxTb(dlAllocCb, 0,
3492 dlAllocCb->tbInfo[0].bytesAlloc - remTb1Bytes);
3495 /*ccpu00120365-ADD-assigning value of remTb2Bytes before utilization */
3496 tb2Bytes = remTb2Bytes;
3498 /* Extra check for a non SM UE allocation */
3500 effAlloc += remTb2Bytes;
3501 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[1],\
3502 &remTb2Bytes, &node);
3503 /* In the event that TB2 is not completely filled by the DL LCs
3504 * BO, consider the reducing the iMcs for increasing redundancy
3505 * and hence reception quality at UE */
3506 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1,
3507 dlAllocCb->tbInfo[1].bytesAlloc - remTb2Bytes);
3510 /* ccpu00120365-ADD-Disable the second TB as the second TB is not
3512 if ( remTb2Bytes && ( tb2Bytes == remTb2Bytes) )
3514 dlAllocCb->mimoAllocInfo.precIdxInfo = 0;
3515 dlAllocCb->mimoAllocInfo.numTxLyrs = 1;
3516 dlAllocCb->tbInfo[1].schdlngForTb = FALSE;
3517 dlAllocCb->tbInfo[1].isDisabled = TRUE;
3520 if (effAlloc == (remTb1Bytes + remTb2Bytes))
3522 /* Allocation such that Nothing could be satisfied */
3523 /* Return the grabbed PDCCH */
3524 rgSCHUtlPdcchPut(cell, &dlAllocCb->dlSf->pdcchInfo,
3526 rgSCHSc1RlsHqProc(cmnUeDl->proc);
3530 /* Fill PDCCH and assign it to HqP */
3531 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, cmnUeDl->proc);
3538 * @brief This function Processes the Final Allocations
3539 * made by the RB Allocator against the requested
3540 * New TX allocations.
3544 * Function: rgSCHSc1DlNewTxAllocFnlz
3545 * Purpose : Distribute the allocation among the Scheduled SVCs.
3546 * Fill pdcch and HqP for UEs will allocations.
3547 * Release HqP for UE with no allocation.
3549 * Invoked by: Common Scheduler
3551 * @param[in] RgSchCellCb *cell
3552 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
3557 PRIVATE Void rgSCHSc1DlNewTxAllocFnlz
3560 RgSchCmnDlRbAllocInfo *allocInfo
3563 PRIVATE Void rgSCHSc1DlNewTxAllocFnlz(cell, allocInfo)
3565 RgSchCmnDlRbAllocInfo *allocInfo;
3570 RgSchCmnDlUe *cmnUeDl;
3571 RgSchDlHqProcCb *hqP;
3573 node = allocInfo->dedAlloc.schdTxHqPLst.first;
3576 hqP = (RgSchDlHqProcCb *)node->node;
3579 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
3580 /*cell added as part of CA dev*/
3582 rgSCHSc1DlNewTxUeFnlz(cell, allocInfo, ue);
3586 rgSCHCmnHdFddUpdDLMark(cell, ue);
3589 /* reset the UE allocation Information */
3590 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
3591 rgSCHCmnDlUeResetTemp(ue, hqP);
3594 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
3595 node = allocInfo->dedAlloc.nonSchdTxHqPLst.first;
3598 hqP = (RgSchDlHqProcCb *)node->node;
3601 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue, cell);
3603 /* Release HqProc */
3604 rgSCHSc1RlsHqProc(hqP);
3605 /* reset the UE allocation Information */
3606 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
3607 rgSCHCmnDlUeResetTemp(ue, hqP);
3612 /* 3.1 Added new function to handle TX+RETX alloc fnlz'n */
3615 * @brief This function Processes the Final Allocations
3616 * made by the RB Allocator against the requested
3617 * RETX+New TX allocations. The NewTx TB allocation
3618 * is considered for distribution among LCs.
3622 * Function: rgSCHSc1DlRetxNewTxAllocFnlz
3623 * Purpose : 1. Reached here due to 1 RETX TB allocation for a
3624 * SM UE, which is capable to accomodate a newTX
3626 * 2. Distribute NewTX TB allocation among the
3627 * SVCs present in lcsWithData list of UE.
3630 * Invoked by: Common Scheduler
3632 * @param[in] RgSchCellCb *cell
3633 * @param[in] RgSchCmnDlRbAllocInfo *cellAllocInfo
3638 PRIVATE Void rgSCHSc1DlRetxNewTxAllocFnlz
3641 RgSchCmnDlRbAllocInfo *cellAllocInfo
3644 PRIVATE Void rgSCHSc1DlRetxNewTxAllocFnlz(cell, cellAllocInfo)
3646 RgSchCmnDlRbAllocInfo *cellAllocInfo;
3651 RgSchSc1DlUe *sc1DlUe;
3652 RgSchDlHqProcCb *hqP;
3653 RgSchDlHqTbCb *newTxTbInfo;
3655 uint32_t remTbBytes;
3656 RgSchDlRbAlloc *ueAllocInfo;
3657 RgSchDlRbAlloc *dlAllocCb;
3660 node = cellAllocInfo->dedAlloc.schdTxRetxHqPLst.first;
3663 hqP = (RgSchDlHqProcCb *)node->node;
3666 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3667 ueAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3668 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3669 /* Index 0 of ueAllocInfo->tbInfo will always hold the
3670 * RETX TB and index 1 will hold the NewTX TB in case of
3671 * RETX+TX allocation. */
3672 newTxTbInfo = ueAllocInfo->tbInfo[1].tbCb;
3673 effAlloc = remTbBytes = ueAllocInfo->tbInfo[1].bytesAlloc;
3674 rgSCHSc1DlSprTxTbDstn(cell, ue, newTxTbInfo,\
3675 &remTbBytes, &(sc1DlUe->lcsWithData.first));
3676 /* Trying to reduce mcs of TX TB to increase reception quality at UE.
3677 * In case of RETX+TX allocation, TX TB allocation was irrespective
3678 * of actual requirement by UE, hence in case if consumption is
3679 * less than allocation, consider reducing the iMcs of this TX TB. */
3680 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1, effAlloc - remTbBytes);
3681 /* 3.1 MIMO Remove/Retain from/in cell RETX List */
3682 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
3683 /* Fill PDCCH and assign it to HqP */
3684 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
3688 rgSCHCmnHdFddUpdDLMark(cell, ue);
3691 /* reset the UE allocation Information */
3692 rgSCHCmnDlUeResetTemp(ue, hqP);
3695 /* Traverse the nonSchdTxRetxHqPLst and reset the UE allocation Info */
3696 node = cellAllocInfo->dedAlloc.nonSchdTxRetxHqPLst.first;
3699 hqP = (RgSchDlHqProcCb *)node->node;
3702 /* reset the UE allocation Information */
3703 rgSCHCmnDlUeResetTemp(ue, hqP);
3709 * @brief This function Processes the Final Allocations
3710 * made by the RB Allocator against the requested.
3714 * Function: rgSCHSc1DlAllocFnlz
3715 * Purpose: This function Processes the Final Allocations
3716 * made by the RB Allocator against the requested.
3717 * 1. Loop through scheduled TX and RETX lists.
3718 * Fill in the corresponding PDCCH and HqProcs.
3719 * In case of TX If actual Alloc < requested, then perform
3720 * an appropriate distribution among the schdSvcs.
3721 * If TA is satisfied, then remove UE from TA Lst.
3722 * 2. Loop through UnScheduled TX and RETX Lists.
3723 * Release grabbed HqProcs.
3724 * Put back SVCs from schdSvcsLst to their corresponding Qs.
3727 * Invoked by: Common Scheduler
3729 * @param[in] RgSchCellCb *cell
3730 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
3735 Void rgSCHSc1DlAllocFnlz
3738 RgSchCmnDlRbAllocInfo *allocInfo
3741 Void rgSCHSc1DlAllocFnlz(cell, allocInfo)
3743 RgSchCmnDlRbAllocInfo *allocInfo;
3747 rgSCHSc1DlRetxAllocFnlz(cell, allocInfo);
3749 rgSCHSc1DlNewTxAllocFnlz(cell, allocInfo);
3751 /*3.1 MIMO new Function added to handle TX+RETX
3752 * harq process scheduling finalization */
3753 rgSCHSc1DlRetxNewTxAllocFnlz(cell, allocInfo);
3760 * @brief This function Updates the DL CQI for the UE.
3764 * Function: rgSCHSc1DlCqiInd
3765 * Purpose: Updates the DL CQI for the UE
3767 * Invoked by: Common Scheduler. SC1 does nothing.
3769 * @param[in] RgSchCellCb *cell
3770 * @param[in] RgSchUeCb *ue
3771 * @param[in] TfuDlCqiRpt *dlCqiRpt
3776 Void rgSCHSc1DlCqiInd
3784 Void rgSCHSc1DlCqiInd(cell, ue, isPucchInfo, dlCqi)
3796 * @brief This function adds a service to UE's list of lcsWithData.
3800 * Function: rgSCHSc1DlAdd2UeLcsWithData
3801 * Purpose: 1. This is to maintain a snapshot view of the
3802 * DL SVCs distributions among the cellwide priority
3804 * 2. This snapshot view is maintained in the order
3805 * of priority of the SVCs with in UE.
3806 * 3. Addition of SVC to a cellwide priority Queue
3807 * triggers this function.
3809 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3810 * to cellwide priority Queues.
3812 * @param[in] RgSchUeCb* ue
3813 * @param[in] RgSchDlLcCb* svc
3818 PRIVATE Void rgSCHSc1DlAdd2UeLcsWithData
3825 PRIVATE Void rgSCHSc1DlAdd2UeLcsWithData(cell, ue, svc)
3833 RgSchCmnDlSvc *cmnDlSvc = RG_SCH_CMN_GET_DL_SVC(svc);
3834 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3835 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3836 RgSchCmnDlSvc *cmnDlLstSvc;
3839 lst = &(sc1DlUe->lcsWithData);
3843 cmnDlLstSvc = RG_SCH_CMN_GET_DL_SVC(((RgSchDlLcCb *)(node->node)));
3844 if (cmnDlSvc->prio <= cmnDlLstSvc->prio)
3852 cmLListAdd2Tail(lst, &sc1DlSvc->lcWithDataLnk);
3853 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3858 cmLListInsCrnt(lst, &sc1DlSvc->lcWithDataLnk);
3859 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3866 * @brief This function adds a service to UE's list of lcsWithData.
3870 * Function: rgSCHSc1DlRmFrmUeLcsWithData
3871 * Purpose: 1. This is to maintain a snapshot view of the
3872 * DL SVCs distributions among the cellwide priority
3874 * 2. This snapshot view is maintained in the order
3875 * of priority of the SVCs with in UE.
3876 * 3. Addition of SVC to a cellwide priority Queue
3877 * triggers this function.
3879 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3880 * to cellwide priority Queues.
3882 * @param[in] RgSchUeCb* ue
3883 * @param[in] RgSchDlLcCb* svc
3888 PRIVATE Void rgSCHSc1DlRmFrmUeLcsWithData
3895 PRIVATE Void rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, svc)
3901 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3902 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3905 cmLListDelFrm(&(sc1DlUe->lcsWithData), &sc1DlSvc->lcWithDataLnk);
3906 sc1DlSvc->lcWithDataLnk.node = NULLP;
3909 /***************** SC1 DL SCHEDULER FUNCTION DEFNs END HERE ****************/
3911 /***************************************************************************/
3913 /***************** SC1 UL SCHEDULER FUNCTION DEFNs START HERE **************/
3915 /*--------------------------*
3916 * UL specific functions START
3917 *---------------------------*/
3920 * @brief UE Lc Config for RR
3924 * Function : rgSCHSc1UlLchCfg
3926 * Processing Steps: Dummy function
3928 * @param[in] RgrSchCellCb *cell
3929 * @param[in] RgSchUeCb *ue
3930 * @param[in] RgrLchCfg *cfg
3931 * @param[in] RgSchErrInfo *err
3935 S16 rgSCHSc1UlLchCfg
3946 * @brief UE Lc Reconfig for RR
3950 * Function : rgSCHSc1UlLchRecfg
3952 * Processing Steps: Dummy function
3954 * @param[in] RgrSchCellCb *cell
3955 * @param[in] RgSchUeCb *ue
3956 * @param[in] RgrLchRecfg *recfg
3957 * @param[in] RgSchErrInfo *err
3961 S16 rgSCHSc1UlLchRecfg
3972 * @brief LC deletion for PFS
3976 * Function : rgSCHSc1UlLchDel
3978 * Processing Steps: Dummy function
3980 * @param[in] RgrSchCellCb *cell
3981 * @param[in] RgSchUeCb *ue
3982 * @param[in] CmLteLcId lcId
3987 S16 rgSCHSc1UlLchDel
3995 S16 rgSCHRrUlLchDel(cell, ue, lcId, lcgId)
4006 * @brief This function initializes all the data for the scheduler
4010 * Function: rgSCHSc1UlInit
4011 * Purpose: This function initializes the following information
4012 * 1. Efficiency table
4013 * 2. CQI to table index - It is one row for upto 3 RBs
4014 * and another row for greater than 3 RBs
4016 * currently extended prefix is compiled out.
4017 * Invoked by: MAC intialization code..may be ActvInit
4025 RgUlSchdApis *rgSchUlApis
4028 Void rgSCHSc1UlInit(rgSchUlApis)
4029 RgUlSchdApis *rgSchUlApis;
4032 /* Init the function pointers */
4033 rgSchUlApis->rgSCHRgrUlUeCfg = rgSCHSc1RgrUlUeCfg;
4034 rgSchUlApis->rgSCHRgrUlUeRecfg = rgSCHSc1RgrUlUeRecfg;
4035 rgSchUlApis->rgSCHFreeUlUe = rgSCHSc1UlUeDel;
4036 rgSchUlApis->rgSCHRgrUlCellCfg = rgSCHSc1RgrUlCellCfg;
4037 rgSchUlApis->rgSCHRgrUlCellRecfg = rgSCHSc1RgrUlCellRecfg;
4038 rgSchUlApis->rgSCHFreeUlCell = rgSCHSc1UlCellDel;
4039 rgSchUlApis->rgSCHRgrUlLcCfg = rgSCHSc1UlLchCfg;
4040 rgSchUlApis->rgSCHRgrUlLcRecfg = rgSCHSc1UlLchRecfg;
4041 rgSchUlApis->rgSCHRgrUlLcgCfg = rgSCHSc1RgrLcgCfg;
4042 rgSchUlApis->rgSCHRgrUlLcgRecfg = rgSCHSc1RgrLcgRecfg;
4043 rgSchUlApis->rgSCHFreeUlLcg = rgSCHSc1LcgDel;
4044 rgSchUlApis->rgSCHRgrUlLchDel = rgSCHSc1UlLchDel;
4045 rgSchUlApis->rgSCHUlSched = rgSCHSc1UlSched;
4046 rgSchUlApis->rgSCHUpdBsrShort = rgSCHSc1UpdBsrShort;
4047 rgSchUlApis->rgSCHUpdBsrTrunc = rgSCHSc1UpdBsrTrunc;
4048 rgSchUlApis->rgSCHUpdBsrLong = rgSCHSc1UpdBsrLong;
4049 rgSchUlApis->rgSCHContResUlGrant = rgSCHSc1ContResUlGrant;
4050 rgSchUlApis->rgSCHSrRcvd = rgSCHSc1SrRcvd;
4051 rgSchUlApis->rgSCHUlCqiInd = rgSCHSc1UlCqiInd;
4052 rgSchUlApis->rgSCHUlUeRefresh = rgSCHSc1UlUeRefresh;
4053 rgSchUlApis->rgSCHUlAllocFnlz = rgSCHSc1UlAllocFnlz;
4054 rgSchUlApis->rgSCHUlInactvtUes = rgSCHSc1UlHndlInActUes;
4055 rgSchUlApis->rgSCHUlActvtUe = rgSCHSc1UlActvtUe;
4056 rgSchUlApis->rgSCHUlUeReset = rgSCHSc1UlUeReset;
4057 rgSchUlApis->rgSCHRgrUlLcgUpd = rgSCHSc1UlLcgUpd;
4062 * @brief UE initialisation for scheduler
4066 * Function : rgSCHSc1RgrUlUeCfg
4068 * This functions intialises UE specific scheduler
4071 * @param[in] RgSchCellCb *cell
4072 * @param[in] RgSchUeCb *ue
4073 * @param[int] RgrUeCfg *ueCfg
4074 * @param[out] RgSchErrInfo *err
4080 S16 rgSCHSc1RgrUlUeCfg
4088 S16 rgSCHSc1RgrUlUeCfg(cell, ue, ueCfg, err)
4096 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
4098 if(rgSCHUtlAllocSBuf(cell->instIdx,
4099 (Data**)&(ueSchCmn->ul.schSpfc), (sizeof(RgSchSc1UlUe))) != ROK)
4101 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
4102 "Memory allocation FAILED CRNTI:%d",ue->ueId);
4103 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
4108 } /* rgSCHSc1RgrUlUeCfg */
4111 * @brief UE reconfiguration for scheduler
4115 * Function : rgSCHSc1RgrUlUeRecfg
4117 * This functions updates UE specific scheduler
4118 * information upon UE reconfiguration
4120 * @param[in] RgSchCellCb *cell
4121 * @param[in] RgSchUeCb *ue
4122 * @param[int] RgrUeRecfg *ueRecfg
4123 * @param[out] RgSchErrInfo *err
4129 S16 rgSCHSc1RgrUlUeRecfg
4133 RgrUeRecfg *ueRecfg,
4137 S16 rgSCHSc1RgrUlUeRecfg(cell, ue, ueRecfg, err)
4140 RgrUeRecfg *ueRecfg;
4145 } /* rgSCHSc1RgrUeRecfg */
4148 * @brief UE deletion for scheduler
4152 * Function : rgSCHSc1UlUeDel
4154 * This functions deletes all scheduler information
4155 * pertaining to a UE
4157 * @param[in] RgSchCellCb *cell
4158 * @param[in] RgSchUeCb *ue
4162 Void rgSCHSc1UlUeDel
4168 Void rgSCHSc1UlUeDel(cell, ue)
4173 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4174 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4181 if(ueUl->txLnk.node)
4183 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
4184 ueUl->txLnk.node = NULLP;
4186 if(ueUl->contResLnk.node)
4188 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
4189 ueUl->contResLnk.node = NULLP;
4191 /* ccpu00117052 - MOD - Passing double pointer
4192 for proper NULLP assignment*/
4193 rgSCHUtlFreeSBuf(cell->instIdx,
4194 (Data**)(&(ueUl)), (sizeof(RgSchSc1UlUe)));
4197 } /* rgSCHSc1UlUeDel */
4200 * @brief UE Reset for scheduler
4204 * Function : rgSCHSc1UlUeReset
4206 * Remove this UE from all Scheduling Priority Qs
4208 * @param[in] RgSchCellCb *cell
4209 * @param[in] RgSchUeCb *ue
4213 Void rgSCHSc1UlUeReset
4219 Void rgSCHSc1UlUeReset(cell, ue)
4224 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4225 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4228 ueUl->srRcvd = FALSE;
4230 if(ueUl->txLnk.node)
4232 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
4233 ueUl->txLnk.node = NULLP;
4235 if(ueUl->contResLnk.node)
4237 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
4238 ueUl->contResLnk.node = NULLP;
4241 } /* rgSCHSc1UlUeReset */
4245 * @brief Scheduler processing on cell configuration
4249 * Function : rgSCHSc1RgrUlCellCfg
4251 * This function does requisite initialisation
4252 * and setup for scheduler1 when a cell is
4255 * @param[in] RgSchCellCb *cell
4256 * @param[in] RgrCellCfg *cellCfg
4257 * @param[out] RgSchErrInfo *err
4263 S16 rgSCHSc1RgrUlCellCfg
4266 RgrCellCfg *cellCfg,
4270 S16 rgSCHSc1RgrUlCellCfg(cell, cellCfg, err)
4272 RgrCellCfg *cellCfg;
4276 RgSchSc1UlCell *cellUl;
4279 if((rgSCHUtlAllocSBuf(cell->instIdx,
4280 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->ul.schSpfc), \
4281 (sizeof(RgSchSc1UlCell))) != ROK))
4283 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
4284 "Memory allocation FAILED");
4285 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
4288 cellUl = RG_GET_SC1_CELL_UL(cell);
4289 cmLListInit(&cellUl->contResLst);
4290 cmLListInit(&cellUl->ueTxLst[0]);
4291 cmLListInit(&cellUl->ueTxLst[1]);
4294 } /* rgSCHSc1RgrUlCellCfg */
4298 * @brief This function handles the reconfiguration of cell
4302 * Function: rgSCHSc1RgrUlCellRecfg
4303 * Purpose: Update the reconfiguration parameters.
4305 * Invoked by: Scheduler
4307 * @param[in] RgSchCellCb* cell
4312 S16 rgSCHSc1RgrUlCellRecfg
4315 RgrCellRecfg *recfg,
4319 S16 rgSCHSc1RgrUlCellRecfg(cell, recfg, err)
4321 RgrCellRecfg *recfg;
4329 * @brief Scheduler processing for cell delete
4333 * Function : rgSCHSc1UlCellDel
4335 * This functions de-initialises and frees memory
4336 * taken up by scheduler1 for the entire cell.
4338 * @param[in] RgSchCellCb *cell
4342 Void rgSCHSc1UlCellDel
4347 Void rgSCHSc1UlCellDel(cell)
4351 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4354 if (cellUl == NULLP)
4358 /* ccpu00117052 - MOD - Passing double pointer
4359 for proper NULLP assignment*/
4360 rgSCHUtlFreeSBuf(cell->instIdx,
4361 (Data**)(&(cellUl)), (sizeof(RgSchSc1UlCell)));
4364 } /* rgSCHSc1UlCellDel */
4367 * @brief Scheduler invocation on logical channel Group addition
4371 * Function : rgSCHSc1RgrLcgCfg
4373 * This functions does required processing when a new
4374 * (dedicated) logical channel is added. Assumes lcg
4375 * pointer in ulLc is set.
4377 * @param[in] RgSchCellCb *cell
4378 * @param[in] RgSchUeCb *ue
4379 * @param[in] RgSchLcgCb *lcg
4380 * @param[int] RgrLcgCfg *lcgCfg
4381 * @param[out] RgSchErrInfo *err
4387 S16 rgSCHSc1RgrLcgCfg
4396 S16 rgSCHSc1RgrLcgCfg(cell, ue, lcg, lcgCfg, err)
4405 } /* rgSCHSc1RgrLcgCfg */
4408 * @brief Scheduler invocation on logical channel addition
4412 * Function : rgSCHSc1RgrLcgRecfg
4414 * This functions does required processing when an existing
4415 * (dedicated) logical channel is reconfigured. Assumes lcg
4416 * pointer in ulLc is set to the old value.
4417 * Independent of whether new LCG is meant to be configured,
4418 * the new LCG scheduler info is accessed and possibly modified.
4420 * @param[in] RgSchCellCb *cell,
4421 * @param[in] RgSchUeCb *ue,
4422 * @param[in] RgSchLcgCb *lcg,
4423 * @param[in] RgrLcgRecfg *reCfg,
4424 * @param[out] RgSchErrInfo *err
4430 S16 rgSCHSc1RgrLcgRecfg
4439 S16 rgSCHSc1RgrLcgRecfg(cell, ue, lcg, reCfg, err)
4448 } /* rgSCHSc1RgrLcgRecfg */
4450 /***********************************************************
4452 * Func : rgSCHSc1LcgDel
4454 * Desc : Scheduler handling for a (dedicated)
4455 * uplink lcg being deleted
4463 **********************************************************/
4472 Void rgSCHSc1LcgDel(cell, ue, lcg)
4478 rgSCHSc1UlPosnUeInQ(cell, ue);
4483 * @brief Perform alloction for this UE
4487 * Function : rgSCHSc1UlSchdUe
4489 * Processing Steps: cater to as much as UE needs, with
4490 * a limitation on maxBits per scheduling instance(per TTI)
4491 * per UE. Return failure, if UE is not considered
4492 * for scheduling (case, where it is already selected for a
4496 * @param[in] RgSchUeCb *ue
4500 PRIVATE Void rgSCHSc1UlSchdUe
4506 PRIVATE Void rgSCHSc1UlSchdUe(ue,cell)
4511 RgSchCmnUlUe *cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
4512 /*cell added as part of CA dev*/
4513 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
4516 if(ulUe->srRcvd == TRUE)
4518 cmnUlUe->alloc.reqBytes = RGSCH_MAX(RG_SCH_CMN_UL_SR_BYTES, \
4523 cmnUlUe->alloc.reqBytes = ue->ul.effBsr;
4529 * @brief Scheduler invocation
4533 * Function: rgSCHSc1UlSchdForDataTrans
4534 * Purpose: Uplink Scheduling for UE data Transmission.
4537 * Invoked by: Scheduler
4539 * @param[in] RgSchCellCb *cell
4540 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
4541 * @param[in] uint8_t remUe
4545 PRIVATE Void rgSCHSc1UlSchdForDataTrans
4548 RgSchCmnUlRbAllocInfo *allocInfo,
4552 PRIVATE Void rgSCHSc1UlSchdForDataTrans(cell, allocInfo, remUe)
4554 RgSchCmnUlRbAllocInfo *allocInfo;
4558 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
4565 /* Allocate UEs with LCG0 data pending */
4566 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[0], allocInfo, &remUe);
4572 /* Allocate UEs with other LCGs data pending */
4573 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[1], allocInfo, &remUe);
4579 * @brief Scheduler invocation
4583 * Function: rgSCHSc1UlSchdUeTxLst
4584 * Purpose: Uplink Scheduling for UE data Transmission.
4587 * Invoked by: Scheduler
4589 * @param[in] CmLListCp *ueTxLst
4590 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
4591 * @param[in] uint8_t *remUe
4595 PRIVATE Void rgSCHSc1UlSchdUeTxLst
4599 RgSchCmnUlRbAllocInfo *allocInfo,
4603 PRIVATE Void rgSCHSc1UlSchdUeTxLst(cell, ueTxLst, allocInfo, remUe)
4606 RgSchCmnUlRbAllocInfo *allocInfo;
4613 Bool ulAllowed = FALSE;
4617 node = ueTxLst->first;
4618 while ((node) && (*remUe))
4620 ue = (RgSchUeCb *)node->node;
4625 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
4626 if (ulAllowed == FALSE)
4633 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
4635 /* UE already scheduled in this subframe (for retx)
4636 * OR is inactive for UL Transmission.*/
4639 /* Added support for SPS*/
4641 else if (RG_SCH_CMN_IS_SPS_SCHD(ue, cell))
4643 /*-- Already Scheduled by SPS --*/
4648 rgSCHSc1UlSchdUe(ue,cell);/*cell added as part of CA dev*/
4650 rgSCHCmnUlAdd2UeLst(cell, allocInfo, ue);
4659 * @brief Scheduler invocation
4663 * Function: rgSCHSc1UlSchdForContRes
4664 * Purpose: Uplink Scheduling for Contention Resolution.
4667 * Invoked by: Scheduler
4669 * @param[in] RgSchCellCb *cell
4670 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
4671 * @param[out] uint8_t *remUe
4675 PRIVATE Void rgSCHSc1UlSchdForContRes
4678 RgSchCmnUlRbAllocInfo *allocInfo,
4682 PRIVATE Void rgSCHSc1UlSchdForContRes(cell, allocInfo, remUe)
4684 RgSchCmnUlRbAllocInfo *allocInfo;
4688 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
4691 RgSchCmnUlUe *cmnUlUe;
4693 Bool ulAllowed = FALSE;
4697 node = sc1UlCell->contResLst.first;
4698 while ((node) && (*remUe))
4700 ue = (RgSchUeCb *)node->node;
4701 cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
4702 /*cell added as part of CA dev*/
4707 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
4708 if (ulAllowed == FALSE)
4714 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
4716 /* UE already scheduled in this subframe (for retx)
4717 * OR is inactive for UL Transmission.*/
4720 cmnUlUe->alloc.reqBytes = RG_SCH_CMN_MAX_UL_CONTRES_GRNT;
4721 rgSCHCmnUlAdd2CntResLst(allocInfo, ue);
4723 /* Node removal deferred to ULAllocFinalization */
4730 * @brief Scheduler invocation
4734 * Function: rgSCHSc1UlNewTx
4735 * Purpose: Uplink Scheduling for New Transmissions.
4738 * Invoked by: Scheduler
4740 * @param[in] RgSchCellCb *cell
4741 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
4745 PRIVATE Void rgSCHSc1UlNewTx
4748 RgSchCmnUlRbAllocInfo *allocInfo
4751 PRIVATE Void rgSCHSc1UlNewTx(cell, allocInfo)
4753 RgSchCmnUlRbAllocInfo *allocInfo;
4756 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
4757 uint8_t remUe = cellUl->maxUeNewTxPerTti;
4760 rgSCHSc1UlSchdForContRes(cell, allocInfo, &remUe);
4761 rgSCHSc1UlSchdForDataTrans(cell, allocInfo, remUe);
4766 * @brief Scheduler invocation
4770 * Function: rgSCHSc1UlSched
4771 * Purpose: This function implements an UL scheduler for LTE. This is
4772 * made available as a function pointer to be called
4773 * at the time of TTI processing by the MAC.
4775 * Invoked by: Common Scheduler (TTI processing)
4777 * @param[in] RgSchCellCb *cell
4778 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
4782 Void rgSCHSc1UlSched
4785 RgSchCmnUlRbAllocInfo *allocInfo
4788 Void rgSCHSc1UlSched(cell, allocInfo)
4790 RgSchCmnUlRbAllocInfo *allocInfo;
4793 rgSCHSc1UlNewTx(cell, allocInfo);
4798 * @brief UEs Buffer Status Has changed so reposition it.
4802 * Function : rgSCHSc1UlInsUeInQ
4804 * In UE in the list in Descending order of effBsr.
4807 * @param[in] CmLListCp *lst
4808 * @param[in] RgSchUeCb *ue
4812 PRIVATE Void rgSCHSc1UlInsUeInQ
4819 PRIVATE Void rgSCHSc1UlInsUeInQ(lst, ue, cell)
4825 /*cell added as part of CA dev*/
4826 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4834 lUe = (RgSchUeCb *)(node->node);
4835 if (lUe->ul.effBsr <= ue->ul.effBsr)
4843 /* We have come to the end of the queue, so Append */
4844 cmLListAdd2Tail(lst, &ueUl->txLnk);
4845 ueUl->txLnk.node = (PTR)ue;
4850 cmLListInsCrnt(lst, &ueUl->txLnk);
4851 ueUl->txLnk.node = (PTR)ue;
4857 * @brief UEs Buffer Status Has changed so reposition it.
4861 * Function : rgSCHSc1UlPosnUeInQ
4863 * -Ues bs value for its LCG has changed, due to either
4864 * allocation or BSR report OR the effUeBR, i.e the byteRate
4865 * has changed due to some allocation, so add/reposition/remove
4866 * it from Qs based on this new bs and/or effUeBR value.
4867 * -If UE has non-zero lcg0 bs value, but the byteRate is
4868 * consumed totally, UE is still schedulable for this control data.
4869 * -If UE's LCG0 has pending bs then position this UE in
4871 * -If Ue has pending BSR to be satisfied, but lcg0's BS
4872 * is 0, then position it in ueTxLst[1].
4873 * -In any of these 2 Qs, insertion is such that UEs are
4874 * positioned in Descending order of their Pending BS.
4877 * @param[in] RgSchCellCb *cell
4878 * @param[in] RgSchUeCb *ue
4882 PRIVATE Void rgSCHSc1UlPosnUeInQ
4888 PRIVATE Void rgSCHSc1UlPosnUeInQ(cell, ue)
4893 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4894 /*cell added as part of CA dev*/
4895 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4896 RgSchCmnLcg *cmnLcg0 = RG_SCH_CMN_GET_UL_LCG(&ue->ul.lcgArr[0]);
4900 if (!RG_SCH_CMN_UL_IS_UE_ACTIVE(ue))
4905 /* Remove the UE from its existing position */
4906 if (ueUl->txLnk.node)
4908 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
4909 ueUl->txLnk.node = (PTR)NULLP;
4911 /* If UE has still bs left for scheduling
4912 * then reposition it */
4913 if ((ue->ul.effBsr > 0) || (ueUl->srRcvd == TRUE))
4915 /* Select the Queue where UE would be Placed */
4916 if (cmnLcg0->bs > 0)
4918 lst = &cellUl->ueTxLst[0];
4923 lst = &cellUl->ueTxLst[1];
4926 /* Insert the UE in the Q */
4927 rgSCHSc1UlInsUeInQ(lst, ue, cell);/*cell added as part of CA dev*/
4930 else if(ue->ul.totalBsr != 0)
4932 if (ue->bsrTmr.tmrEvnt != TMR_NONE)
4934 rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue);
4936 if (ue->ul.bsrTmrCfg.isPrdBsrTmrPres)
4938 rgSCHTmrStartTmr(cell, ue, RG_SCH_TMR_BSR,
4939 ue->ul.bsrTmrCfg.prdBsrTmr);
4948 * @brief Short BSR update
4952 * Function : rgSCHSc1UpdBsrShort
4954 * This functions does requisite updates to handle short BSR reporting
4956 * @param[in] RgSchCellCb *cell
4957 * @param[in] RgSchUeCb *ue
4958 * @param[in] RgSchLcgCb *lcg
4959 * @param[in] uint8_t bsr
4963 Void rgSCHSc1UpdBsrShort
4971 Void rgSCHSc1UpdBsrShort(cell, ue, lcg, bsr)
4978 rgSCHSc1UlPosnUeInQ(cell, ue);
4980 } /* rgSCHSc1UpdBsrShort */
4983 * @brief Truncated BSR update
4987 * Function : rgSCHSc1UpdBsrTrunc
4989 * This functions does required updates to handle truncated BSR report
4992 * @param[in] RgSchCellCb *cell
4993 * @param[in] RgSchUeCb *ue
4994 * @param[in] RgSchLcgCb *lcg
4995 * @param[in] uint8_t bsr
4999 Void rgSCHSc1UpdBsrTrunc
5007 Void rgSCHSc1UpdBsrTrunc(cell, ue, lcg, bsr)
5014 rgSCHSc1UlPosnUeInQ(cell, ue);
5016 } /* rgSCHSc1UpdBsrTrunc */
5019 * @brief Long BSR update
5023 * Function : rgSCHSc1UpdBsrLong
5025 * - Update UE's position within/across uplink scheduling queues
5028 * @param[in] RgSchCellCb *cell
5029 * @param[in] RgSchUeCb *ue
5030 * @param[in] uint8_t bsArr[]
5034 Void rgSCHSc1UpdBsrLong
5041 Void rgSCHSc1UpdBsrLong(cell, ue, bsArr)
5047 rgSCHSc1UlPosnUeInQ(cell, ue);
5049 } /* rgSCHSc1UpdBsrLong */
5052 * @brief UL grant for contention resolution
5056 * Function : rgSCHSc1ContResUlGrant
5058 * Add UE to another queue specifically for CRNTI based contention
5062 * @param[in] RgSchCellCb *cell
5063 * @param[in] RgSchUeCb *ue
5067 Void rgSCHSc1ContResUlGrant
5073 Void rgSCHSc1ContResUlGrant(cell, ue)
5078 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
5079 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
5082 if (ueUl->contResLnk.node)
5087 /* Remove the UE from other Qs */
5088 if(ueUl->txLnk.node)
5090 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
5091 ueUl->txLnk.node = NULLP;
5094 cmLListAdd2Tail(&cellUl->contResLst, &ueUl->contResLnk);
5095 ueUl->contResLnk.node = (PTR)ue;
5097 } /* rgSCHSc1ContResUlGrant */
5100 * @brief SR reception handling
5104 * Function : rgSCHSc1SrRcvd
5105 * Shift the UE with SrInd in to the lcgO queue.
5108 * @param[in] RgSchCellCb *cell
5109 * @param[in] RgSchUeCb *ue
5119 Void rgSCHSc1SrRcvd(cell, ue)
5124 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
5125 RgSchSc1UlCell *ulCell = RG_GET_SC1_CELL_UL(cell);
5128 ulUe->srRcvd = TRUE;
5130 if (ulUe->txLnk.node != NULLP)
5134 /* Already present in lcg0 Q */
5137 cmLListDelFrm(&(ulCell->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
5139 /* Adding the UE to the LCG0 list for SR IND */
5140 cmLListAdd2Tail(&ulCell->ueTxLst[0], &ulUe->txLnk);
5141 ulUe->txLnk.node = (PTR)ue;
5145 } /* rgSCHSc1SrRcvd */
5148 * @brief Indication of UL CQI
5152 * Function : rgSCHSc1UlCqiInd
5154 * - Common Scheduler. SC1 does nothing.
5156 * @param[in] RgSchCellCb *cell
5157 * @param[in] RgSchUeCb *ue
5158 * @param[in] TfuUlCqiRpt *ulCqiInfo
5162 Void rgSCHSc1UlCqiInd
5166 TfuUlCqiRpt *ulCqiInfo
5169 Void rgSCHSc1UlCqiInd(cell, ue, ulCqiInfo)
5172 TfuUlCqiRpt *ulCqiInfo;
5176 /* Stack Crash problem for TRACE5 changes. Added the return below */
5182 * @brief UL Lcg received data updation
5186 * Function : rgSCHSc1UlLcgUpd
5188 * Processing Steps:Sc1 Does nothing
5190 * @param[in] RgSchCellCb *cell
5191 * @param[in] RgSchUeCb *ue
5192 * @param[in] RgInfUeDatInd *datInd
5196 S16 rgSCHSc1UlLcgUpd
5200 RgInfUeDatInd *datInd
5203 S16 rgSCHSc1UlLcgUpd(cell, ue)
5206 RgInfUeDatInd *datInd;
5215 /***********************************************************
5217 * Func : rgSCHSc1UlUeRefresh
5219 * Desc : Handle 'refresh' for uplink part of a UE
5220 * (ie UE's uplink AMBR and uplink GBR LCGs are
5221 * refreshed at this point)
5229 **********************************************************/
5231 Void rgSCHSc1UlUeRefresh
5237 Void rgSCHSc1UlUeRefresh(cell, ue)
5242 rgSCHSc1UlPosnUeInQ(cell, ue);
5247 * @brief This function Processes the Final Allocations
5248 * made by the RB Allocator against the requested
5249 * UE data Trans Allocations.
5253 * Function: rgSCHSc1UlDatTransAllocFnlz
5254 * Purpose: This function Processes the Final Allocations
5255 * made by the RB Allocator against the requested
5256 * UE data Trans Allocations .
5258 * Invoked by: Scheduler
5260 * @param[in] RgSchCellCb *cell
5261 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
5266 PRIVATE Void rgSCHSc1UlDatTransAllocFnlz
5269 RgSchCmnUlRbAllocInfo *allocInfo
5272 PRIVATE Void rgSCHSc1UlDatTransAllocFnlz(cell, allocInfo)
5274 RgSchCmnUlRbAllocInfo *allocInfo;
5280 RgSchDrxUeCb *drxUe = NULLP;
5281 CmLListCp ulInactvLst; /* list of UE's becoming UL-inactive */
5283 cmLListInit(&ulInactvLst);
5284 node = allocInfo->schdUeLst.first;
5287 ue = (RgSchUeCb *)node->node;
5289 ueUl = RG_GET_SC1_UE_UL(ue, cell);
5291 if (ue->isDrxEnabled)
5293 if(ueUl->srRcvd == TRUE)
5295 drxUe = RG_SCH_DRX_GET_UE(ue);
5296 drxUe->drxUlInactvMask |= RG_SCH_DRX_SR_BITMASK;
5298 if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
5300 ue->ul.ulInactvMask |= RG_DRX_INACTIVE;
5301 /* Add to Ul inactive List */
5302 ue->ulDrxInactvLnk.node = (PTR)ue;
5303 cmLListAdd2Tail(&ulInactvLst,&(ue->ulDrxInactvLnk));
5305 drxUe->srRcvd = FALSE;
5308 /* Reset no matter */
5309 ueUl->srRcvd = FALSE;
5310 /* Reposition UE in Qs */
5311 rgSCHSc1UlPosnUeInQ(cell, ue);
5315 rgSCHCmnHdFddUpdULMark (cell,ue);
5318 /* reset the UE UL allocation Information */
5319 rgSCHCmnUlUeResetTemp(cell, ue);
5321 rgSCHSc1UlHndlInActUes(cell, &ulInactvLst);
5322 node = allocInfo->nonSchdUeLst.first;
5325 ue = (RgSchUeCb *)node->node;
5327 /* reset the UE UL allocation Information */
5328 rgSCHCmnUlUeResetTemp(cell, ue);
5335 * @brief This function Processes the Final Allocations
5336 * made by the RB Allocator against the requested
5337 * cont res Allocations.
5341 * Function: rgSCHSc1UlContResAllocFnlz
5342 * Purpose: This function Processes the Final Allocations
5343 * made by the RB Allocator against the requested
5344 * cont res Allocations .
5346 * Invoked by: Scheduler
5348 * @param[in] RgSchCellCb *cell
5349 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
5354 PRIVATE Void rgSCHSc1UlContResAllocFnlz
5357 RgSchCmnUlRbAllocInfo *allocInfo
5360 PRIVATE Void rgSCHSc1UlContResAllocFnlz(cell, allocInfo)
5362 RgSchCmnUlRbAllocInfo *allocInfo;
5365 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
5370 node = allocInfo->schdContResLst.first;
5373 ue = (RgSchUeCb *)node->node;
5378 rgSCHCmnHdFddUpdULMark (cell,ue);
5381 ueUl = RG_GET_SC1_UE_UL(ue, cell);
5383 /* Remove UE from Cont Res Q */
5384 cmLListDelFrm(&sc1UlCell->contResLst,
5386 ueUl->contResLnk.node = NULLP;
5387 /* reset the UE UL allocation Information */
5388 rgSCHCmnUlUeResetTemp(cell, ue);
5391 node = allocInfo->nonSchdContResLst.first;
5394 ue = (RgSchUeCb *)node->node;
5396 /* reset the UE UL allocation Information */
5397 rgSCHCmnUlUeResetTemp(cell, ue);
5404 * @brief This function Processes the Final Allocations
5405 * made by the RB Allocator against the requested.
5409 * Function: rgSCHSc1UlAllocFnlz
5410 * Purpose: This function Processes the Final Allocations
5411 * made by the RB Allocator against the requested.
5413 * Invoked by: Common Scheduler
5415 * @param[in] RgSchCellCb *cell
5416 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
5421 Void rgSCHSc1UlAllocFnlz
5424 RgSchCmnUlRbAllocInfo *allocInfo
5427 Void rgSCHSc1UlAllocFnlz(cell, allocInfo)
5429 RgSchCmnUlRbAllocInfo *allocInfo;
5433 rgSCHSc1UlContResAllocFnlz(cell, allocInfo);
5434 rgSCHSc1UlDatTransAllocFnlz(cell, allocInfo);
5441 * @brief Scheduler invocation
5445 * Function: rgSCHSc1UlActvtUe
5446 * Purpose: Put back the UE in to appropriate Qs.
5448 * Invoked by: Common Scheduler
5450 * @param[in] RgSchCellCb *cell
5451 * @param[in] RgSchUeCb *ue
5455 Void rgSCHSc1UlActvtUe
5461 Void rgSCHSc1UlActvtUe(cell, ue)
5467 rgSCHSc1UlPosnUeInQ(cell, ue);
5472 * @brief Scheduler invocation
5476 * Function: rgSCHSc1UlHndlInActUes
5477 * Purpose: The list of inactive UEs present in inactvLst should
5478 * be removed from the scheduling Qs.
5479 * But store the information pertaining to which Qs,
5480 * were they belonging to. This information shall be used
5481 * to put them back in appropriate Qs when their Activation
5484 * Invoked by: Common Scheduler (TTI processing)
5486 * @param[in] RgSchCellCb *cell
5487 * @param[out] CmLListCp *inactvLst
5491 Void rgSCHSc1UlHndlInActUes
5494 CmLListCp *inactvLst
5497 Void rgSCHSc1UlHndlInActUes(cell, inactvLst)
5499 CmLListCp *inactvLst;
5504 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
5505 CmLList *node = inactvLst->first;
5510 ue = (RgSchUeCb *)node->node;
5512 ulUe = RG_GET_SC1_UE_UL(ue, cell);
5513 if(ulUe->txLnk.node)
5515 cmLListDelFrm(&(cellUl->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
5516 /* This is required as lcg bs might change during
5517 * inactivity to activity. So we need to recompute
5519 ulUe->txLnk.node = NULLP;
5521 /* Do not remove UE from contResLst */
5526 * @brief Scheduler invocation
5530 * Function: rgSCHSc1DlProcRmvFrmRetx
5531 * Purpose: To remove the Harq process from the cell and from the UE
5532 * retransmission list
5534 * Invoked by: Common Scheduler (TTI processing)
5536 * @param[in] RgSchCellCb *cell
5537 * @param[in] RgSchUeCb *ue;
5538 * @param[in] RgSchDlHqProcCb *hqP
5543 Void rgSCHSc1DlProcRmvFrmRetx(
5546 RgSchDlHqProcCb *hqP
5549 Void rgSCHSc1DlProcRmvFrmRetx(cell, ue, hqP)
5552 RgSchDlHqProcCb *hqP;
5556 /* Remove the HqP from retx Queue.
5558 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
5559 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
5566 /**********************************************************************
5569 **********************************************************************/