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 static S16 rgSCHSc1RgrDlCellRecfg ARGS((
78 /*--------------------------*
79 * DL SCHED STATIC declarations START
80 *---------------------------*/
81 static Void rgSCHSc1DlSvcAddToSchd ARGS((
85 static Void rgSCHSc1DlAdd2UeSchdSvcs ARGS((
90 static Void rgSCHSc1DlRmvUeFrmPrioQs ARGS((
94 static Void rgSCHSc1DlSuspendUe ARGS((
98 static Void rgSCHSc1DlInactvtUe ARGS((
102 static Void rgSCHSc1DlProcRmvFrmCellRetx ARGS((
106 static Void rgSCHSc1DlProcRmvFrmUeRetx ARGS((
111 static Void rgSCHSc1DlMngPrio0SvcPosn ARGS((
116 static Void rgSCHSc1DlMngGbrSvcPosn ARGS((
121 static Void rgSCHSc1DlMngAmbrSvcPosn ARGS((
126 static Void rgSCHSc1DlMngSvcPosn ARGS((
131 static Void rgSCHSc1DlUeAddToSchd ARGS((
135 static Void rgSCHSc1DlTaCmd ARGS((
137 RgSchCmnDlRbAllocInfo *allocInfo
139 static Void rgSCHSc1DlInitQueues ARGS((
140 RgSchSc1DlCell *cellDl
142 static Void rgSCHSc1DlDeinitQueues ARGS((
143 RgSchSc1DlCell *cellDl
145 static Void rgSCHSc1DlAdd2UeLcsWithData ARGS((
150 static Void rgSCHSc1DlRmFrmUeLcsWithData ARGS((
155 /*--------------------------*
156 * UL SCHED STATIC declarations START
157 *---------------------------*/
158 static Void rgSCHSc1UlPosnUeInQ ARGS((
162 static Void rgSCHSc1UlSchdUeTxLst ARGS((
165 RgSchCmnUlRbAllocInfo *allocInfo,
168 static Void rgSCHSc1DlProcRmvFrmRetx ARGS((
173 Void rgSCHSc1DlScanUpdPdbPrio ARGS((
176 S16 rgSCHSc1DlFillFlowCntrlInfo ARGS((
178 RgInfSfAlloc *sfAlloc
181 static Void rgSCHSc1DlPreSchd ARGS ((
184 static 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 **********************************************************/
211 Void rgSCHSc1DlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
214 rgSCHSc1DlSuspendUe(cell, ue);
220 /***********************************************************
222 * Func : rgSCHSc1DlActvtUe
224 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
225 * and Svc in respective Prio Qs.
234 **********************************************************/
235 Void rgSCHSc1DlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
237 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
240 RgSchDlHqProcCb *hqP;
244 /* Add UE's HqProcs From UERetxLst to CellRetxLst */
245 lst = &ueDl->retxHqProcs;
249 hqP = (RgSchDlHqProcCb *)node->node;
251 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
252 rgSCHSc1DlProcAddToCellRetx(cell, hqP);
255 /* Iterate over all the Services if bo != 0 then add */
256 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
258 svc = ue->dl.lcCb[idx];
263 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
266 /* Add UE to AMBR Prio Q */
269 rgSCHSc1DlUeAddToSchd(cell, ue);
276 /***********************************************************
278 * Func : rgSCHSc1DlUeRefresh
280 * Desc : Handle 'refresh' for Downlink
281 * (ie UE's downlink AMBR and downlink GBR LCGs are
282 * refreshed at this point)
290 **********************************************************/
291 Void rgSCHSc1DlUeRefresh(RgSchCellCb *cell,RgSchUeCb *ue)
293 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
294 /*cell added as part of CA dev*/
295 RgSchCmnDlSvc *svcCmn;
296 RgSchSc1DlSvc *svcSc1;
303 ueDl->ambr = ue->dl.ambrCfgd;
307 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
310 if (ueDl->ambrSvc != NULLP)
312 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, ueDl->ambrSvc->bo);
313 /* Update UEs position in the Queue */
314 rgSCHSc1DlUeAddToSchd(cell, ue);
317 lst = &ueDl->gbrSvcs;
319 while (node != NULLP)
321 svc = (RgSchDlLcCb *)node->node;
322 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
323 svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
325 svcSc1->gbr = svcCmn->gbr;
326 svcSc1->mbr = svcCmn->mbr;
327 /* Update the SVC's positioning in the Queue */
328 rgSCHSc1DlMngGbrSvcPosn(cell, ue, svc);
335 * @brief This function removes a HARQ process from the retx
339 * Function: rgSCHSc1DlProcRmvFrmCellRetx
340 * Purpose: This function removes a HARQ process from retransmission
341 * queue. This may be performed when a HARQ ack is successful
342 * for a retransmission or when the scheduling determines
343 * to throw out the process due to poor conditions
345 * Invoked by: LIM and Scheduler
347 * @param[in] RgSchSc1Cb* cell
348 * @param[in] RgDlHqProc* hqP
352 static Void rgSCHSc1DlProcRmvFrmCellRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
354 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
355 RgSchCmnDlHqProc *hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
357 if (hqProcDl->retxLnk.node != NULLP)
359 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
360 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
361 hqProcDl->retxLnk.node = NULLP;
368 * @brief This function removes a HARQ process from the UE retx
372 * Function: rgSCHSc1DlProcRmvFrmUeRetx
373 * Purpose: This function removes a HARQ process from UE retransmission
376 * Invoked by: LIM and Scheduler
378 * @param[in] RgSchUeCb* ue
379 * @param[in] RgDlHqProc* hqP
383 static Void rgSCHSc1DlProcRmvFrmUeRetx(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
385 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
386 RgSchSc1DlHqProc *hqProcDl = RG_GET_SC1_HQP_DL(hqP);
388 if (hqProcDl->retxLnkUe.node != NULLP)
390 cmLListDelFrm(&sc1Ue->retxHqProcs,
391 &(hqProcDl->retxLnkUe));
392 hqProcDl->retxLnkUe.node = NULLP;
399 * @brief This function adds a HARQ process for UEs retxLst
403 * Function: rgSCHSc1DlProcAddToUeRetx
404 * Purpose: This function adds a HARQ process to UE retransmission
405 * queue. This is performed when UE is suspended due
406 * to measurement gap.
408 * Invoked by: HARQ feedback processing
410 * @param[in] RgSchUeCb* ue
411 * @param[in] RgSchDlHqProc* hqP
415 static Void rgSCHSc1DlProcAddToUeRetx(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
417 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
418 RgSchSc1DlHqProc *cmnHqDl = RG_GET_SC1_HQP_DL(hqP);
420 cmLListAdd2Tail(&sc1Ue->retxHqProcs,
421 &(cmnHqDl->retxLnkUe));
422 cmnHqDl->retxLnkUe.node = (PTR)hqP;
428 * @brief This function adds a HARQ process for retx
432 * Function: rgSCHSc1DlProcAddToCellRetx
433 * Purpose: This function adds a HARQ process to retransmission
434 * queue. This may be performed when a HARQ ack is
437 * Invoked by: HARQ feedback processing
439 * @param[in] RgSchCellCb* cell
440 * @param[in] RgSchDlHqProc* hqP
444 Void rgSCHSc1DlProcAddToCellRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
446 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
447 RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
450 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(hqP->hqE->ue))
452 rgSCHSc1DlProcAddToUeRetx(cell, hqP->hqE->ue, hqP);
455 cmLListAdd2Tail(&sc1CellDl->retxLst[((RgSchSc1DlHqProc *)\
456 (cmnHqDl->schSpfc))->prio], &(cmnHqDl->retxLnk));
457 cmnHqDl->retxLnk.node = (PTR)hqP;
463 * @brief This function implements DL RETRANSMISSION allocation
467 * Function: rgSCHSc1DlRetxAlloc
468 * Purpose: This function implements downlink scheduler's
469 * retransmission allocation.
471 * Invoked by: Scheduler
473 * @param[in] RgSchCellCb *cell
474 * @param[in] RgSchDlSf *subFrm
475 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
479 static Void rgSCHSc1DlRetxAlloc(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchCmnDlRbAllocInfo *allocInfo)
484 RgSchDlHqProcCb *hqP;
485 RgSchSc1DlCell *sc1CellDl;
486 RgSchSc1DlUe *sc1DlUe;
487 RgSchCmnDlUe *cmnUeDl;
488 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
489 CmLteTimingInfo schdTime;
492 RgSchUeCb *ue = NULLP;
494 Bool dlAllowed = FALSE;
496 RgSchDlRbAlloc *dlAllocCb;
498 sc1CellDl = RG_GET_SC1_CELL_DL(cell);
499 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
500 schdTime = cell->crntTime;
502 /* Increment by DL DELTA to determine the time for which scheduling
504 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
506 for (i = 0; i < RG_SCH_SC1_DL_PRIOS; i++)
508 retxLst = &sc1CellDl->retxLst[i];
509 /* allocate bw for the retransmission..should be same are previous */
510 /* If CQI gets worse, as we cannot find same TB size for another */
511 /* MCS, we just remove this from the retransmission queue */
512 node = retxLst->first;
513 while (node != NULLP)
515 hqP = (RgSchDlHqProcCb *)node->node;
520 if((0 == schdTime.slot) || (5 == schdTime.slot))
523 rgSCHCmnChkRetxAllowDtx(cell, ue, hqP, &reTxAllw);
524 if(FALSE == reTxAllw)
533 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
534 if (dlAllowed == FALSE)
540 /* This UE is already scheduled for transmission */
541 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
542 /*cell added as part of CA dev*/
544 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
549 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
554 /* Extra check: indicate if there is furtherScope for NewTx
555 * addition for a HqProc. This information will
556 * be utilized by common scheduler, in case of SM
557 * UEs with only one of the TBs retransmitting and the
558 * other TB can be used for clubbing new TX. */
559 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
560 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
561 if (sc1DlUe->lcsWithData.first != NULLP)
563 dlAllocCb->mimoAllocInfo.hasNewTxData = TRUE;
565 /* 3.1 MIMO : last parameter changed */
566 if (rgSCHCmnDlAllocRetxRb(cell, subFrm, ue, 0, &effBo, hqP, allocInfo) !=\
569 /* SF/RETX Bandwidth expired */
577 if ((hqP->tbInfo[0].state == HQ_TB_ACKED)
578 && (hqP->tbInfo[1].state == HQ_TB_ACKED))
580 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
585 /* 3.1 MIMO moving this call in cmn scheduler */
586 /*rgSCHCmnDlRbInfoAddUeRetx(allocInfo, ue);*/
592 /***********************************************************
594 * Func : rgSCHSc1RlsHqProc
596 * Desc : Toggles the NDI and releases the harq proc.
604 **********************************************************/
605 static Void rgSCHSc1RlsHqProc(RgSchDlHqProcCb *hqProc)
607 rgSCHDhmRlsHqProc(hqProc);
612 * @brief This function implements dedicated logical channel data scheduling
616 * Function: rgSCHSc1DlDedSvcAlloc
617 * Purpose: This function implements dedicated logical
618 * channel data scheduling
620 * Invoked by: Scheduler
622 * @param[in] RgSchCellCb *cell
623 * @param[in] RgSchDlSf *subFrm
624 * @param[in] RgSchDlLcCb *svc
625 * @param[in] uint32_t bo
626 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
630 static S16 rgSCHSc1DlDedSvcAlloc(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchDlLcCb *svc,uint32_t bo,RgSchCmnDlRbAllocInfo *allocInfo)
633 RgSchDlHqProcCb *proc;
634 uint16_t rlcHdrEstmt;
636 RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell);
637 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
638 RgSchSc1DlSvc *svcSc1;
640 RgSchSc1DlHqProc *sc1HqDl;
641 RgSchCmnDlHqProc *cmnHqDl;
643 CmLteTimingInfo schdTime;
646 Bool dlAllowed = FALSE;
651 /* Get the UE to which this service belongs to */
656 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
657 if (dlAllowed == FALSE)
663 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
664 /*cell added as part of CA dev*/
666 schdTime = cell->crntTime;
668 /* Increment by DL DELTA to determine the time for which scheduling
670 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
671 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
676 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
678 proc = (RgSchDlHqProcCb *)(ueDl->proc);
679 /* This UE is selected for retransmission. Hence no further */
680 /* scheduling may be done for this UE */
681 if (RG_SCH_CMN_PROC_SLCTD_FOR_RETX(proc))
683 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,"CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
684 "Ue retransmitting",ue->ueId);
687 /* UE is scheduled for either other services or TA */
688 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
689 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
690 if (sc1HqDl->prio > svcCmn->prio)
692 sc1HqDl->prio = svcCmn->prio;
695 else /* First consideration of this UE for scheduling */
697 if (rgSCHDhmGetAvlHqProc(cell, ue, cmnCellDl->time, &proc) != ROK)
699 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
700 " No HARQ Proc available", ue->ueId);
703 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
704 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
705 cmnHqDl->totBytes = 0;
706 /* Initialize some of the parameters of the HQ proc */
707 sc1HqDl->prio = svcCmn->prio;
710 /* Including each SDU's header size */
711 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
714 ret = rgSCHCmnDlAllocTxRb(cell, subFrm, ue, bo, &effBo, proc, allocInfo);
715 if ((ret != ROK) || (effBo == 0))
717 /* If no allocations so far, meaning proc obtained now */
718 if (cmnHqDl->totBytes == 0)
720 rgSCHSc1RlsHqProc(proc);
721 /* Added the handling for removing
722 * UE from txHqPLst and resetting outStndAlloc.*/
723 if(proc->reqLnk.node != (PTR)NULLP)
725 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
726 proc->reqLnk.node = (PTR)NULLP;
728 /*Re-set the outstanding alloc information.*/
729 ueDl->outStndAlloc = 0;
731 /* ccpu00126519: proc should be set to NULLP in UE's DL scratch pad info as well. */
736 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
737 svcSc1->hdrEstimate = rlcHdrEstmt;
738 svcSc1->reqBytes = bo;
740 cmnHqDl->totBytes += effBo;
742 rgSCHSc1DlAdd2UeSchdSvcs(cell, ue, svc);
743 /* 3.1 MIMO moving this call to cmn scheduler */
744 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue); */
749 * @brief This function adds a SVC to UE's schdSvcsLst.
753 * Function: rgSCHSc1DlAdd2UeSchdSvcs
754 * Purpose: This function adds a SVC to UE's schdSvcsLst.
756 * Invoked by: Specific Scheduler
758 * @param[out] RgSchUeCb *ue
759 * @param[in] RgSchDlLcCb *svc
763 static Void rgSCHSc1DlAdd2UeSchdSvcs(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
765 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
766 RgSchSc1DlUe *ueSc1 = RG_GET_SC1_UE_DL(ue, cell);
768 /* checking SVC's presence in this lst is unnecessary */
769 cmLListAdd2Tail(&ueSc1->schdSvcs, &svcSc1->schdSvcLnk);
770 svcSc1->schdSvcLnk.node = (PTR)svc;
776 * @brief This function performs new allocations for UEs
780 * Function: rgSCHSc1DlDedTx
781 * Purpose: This function implements scheduler for DL allocation for
782 * new transmissions of UEs.
783 * 1. It performs across 9 priorities that it supports -
784 * This is from 3GPP specifications
785 * 2. There are known number of GBR/MBR queues
786 * 3. The first queue is highest priority queue and is
787 * satisfied completely prior to any other queues. This
788 * queue is for RRC signalling.
789 * 4. Futher GBR/MBR queues are satisfied for GBR and then MBR
790 * 5. Subsequently all other queues are looked at for AMBR
792 * Invoked by: Scheduler
794 * @param[in] RgSchCellCb* cell
795 * @param[in] RgSchDlSf *subFrm
796 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
800 static Void rgSCHSc1DlDedTx(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchCmnDlRbAllocInfo *allocInfo)
804 RgSchUeCb *ue = NULLP;
807 RgSchSc1DlSvc *svcSc1;
809 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
812 /* Process the first queue that is for RRC signalling and is of */
813 /* highest priority. */
814 lst = &sc1CellDl->prioLst[0];
818 /* Getting service instead of UE */
819 svc = (RgSchDlLcCb *)node->node;
821 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
823 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->bo, allocInfo) != ROK)
830 /* Perform allocation for the GBR transmissions */
831 for(i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
833 lst = &sc1CellDl->prioLst[i];
837 /* Getting service instead of UE */
838 svc = (RgSchDlLcCb *)node->node;
840 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
842 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->effMbr, allocInfo) != ROK)
850 /* To implement AMBR svc scheduling */
851 for(i = RG_SCH_SC1_DL_GBR_PRIO_END + 1; i < RG_SCH_SC1_DL_PRIOS; i++)
853 lst = &sc1CellDl->prioLst[i];
857 ue = (RgSchUeCb *)node->node;
858 ueDl = RG_GET_SC1_UE_DL(ue, cell);
860 /* Get the Curr ambr svc for which allocation is to be made */
862 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, ueDl->effAmbr, allocInfo) != ROK)
873 * @brief scheduling for a cell
877 * Function : rgSCHSc1DlPreSchd
880 * - Nothing to be done in case of RR
882 * @param[in] Inst schInst
885 static Void rgSCHSc1DlPreSchd( RgSchCellCb *cell)
891 * @brief scheduling for a cell
895 * Function : rgSCHSc1DlPstSchd
898 * - Nothing to be done in case of RR
900 * @param[in] Inst schInst
903 static Void rgSCHSc1DlPstSchd(Inst schInst)
911 * @brief This function implements scheduler DL allocation
915 * Function: rgSCHSc1DlDedNewTx
916 * Purpose: This function implements scheduler for DL allocation for
919 * Invoked by: Scheduler
921 * @param[in] RgSchCellCb *cell
922 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
926 static Void rgSCHSc1DlDedNewTx(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
928 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
930 Inst inst = cell->instIdx;
932 RGSCHDBGPRM(inst, (rgSchPBuf(inst), "rgSCHSc1DlDedNewTx\n"));
934 /* Now perform the new UE selections */
935 rgSCHSc1DlDedTx(cell, subFrm, allocInfo);
937 /* Stack Crash problem for TRACE5 changes. Added the return below */
942 * @brief This function implements scheduler DL allocation
946 * Function: rgSCHSc1DlDedRetx
947 * Purpose: This function implements scheduler for DL allocation for
950 * Invoked by: Scheduler
952 * @param[in] RgSchCellCb *cell
953 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
957 static Void rgSCHSc1DlDedRetx(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
959 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
961 Inst inst = cell->instIdx;
963 RGSCHDBGPRM(inst, (rgSchPBuf(inst), "rgSCHSc1DlDedRetx\n"));
965 rgSCHSc1DlRetxAlloc(cell, subFrm, allocInfo);
974 * @brief This function adds a service to scheduler
978 * Function: rgSCHSc1DlSvcAddToSchd
979 * Purpose: This function adds a service to the list of services
980 * based on the priority of the services.
982 * Invoked by: BO and Scheduler
984 * @param[in] RgSchCellCb* cell
985 * @param[in] RgSchUeCb* ue
989 static Void rgSCHSc1DlSvcAddToSchd(RgSchCellCb *cell,RgSchDlLcCb *svc)
994 RgSchSc1DlSvc *svcSc1;
995 RgSchSc1DlSvc *lSvcSc1;
996 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
997 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1000 svcSc1 = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
1001 /* The service is already in the scheduler */
1002 if (svcSc1->prioLnk.node != NULLP)
1007 /* If the priority = 0, it is the highest priority with infinite */
1008 /* allowance and the priority is time bound and hence just place */
1009 /* it at the end of the queue */
1010 if (svcCmn->prio == 0)
1012 lst = &(sc1CellDl->prioLst[0]);
1013 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1014 svcSc1->prioLnk.node = (PTR)svc;
1015 /* If a svc is put in to cell wide priority Qs
1016 * then add the same to UE's lcsWithData List */
1017 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1021 /* Handle GBR services. We have them of next importance */
1022 /* check changed from .._START to .._END */
1023 if (svcCmn->prio <= RG_SCH_SC1_DL_GBR_PRIO_END)
1025 if (!RG_SC1_SVC_HAS_DATA(svc,cell))
1027 lst = &(sc1CellDl->prioLst[svcCmn->prio]);
1031 lSvc = (RgSchDlLcCb *)(node->node);
1032 lSvcSc1 = RG_GET_SC1_SVC_DL(lSvc->ue,lSvc,cell);
1033 if (((svcSc1->effGbr > 0) &&
1034 (lSvcSc1->effGbr <= svcSc1->effGbr)) ||
1035 ((lSvcSc1->effGbr == 0) && (svcSc1->effMbr > 0) &&
1036 (lSvcSc1->effMbr <= svcSc1->effMbr)))
1044 /* We have come to the end of the queue. Let's place it */
1045 /* here irresepctive of effGbr or effMBr */
1046 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1047 svcSc1->prioLnk.node = (PTR)svc;
1052 cmLListInsCrnt(lst, &svcSc1->prioLnk);
1053 svcSc1->prioLnk.node = (PTR)svc;
1055 /* If a svc is put in to cell wide priority Qs
1056 * then add the same to UE's lcsWithData List */
1057 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1065 * @brief This function removes a UE from scheduler Queue
1069 * Function: rgSCHSc1DlUeRmvFrmSchd
1070 * Purpose: This function removes a UE from the list of UEs
1071 * based on the priority of the UEs Current AMBR SVC.
1073 * Invoked by: BO and Scheduler
1075 * @param[in] RgSchCellCb* cell
1076 * @param[in] RgSchUeCb* ue
1080 static Void rgSCHSc1DlUeRmvFrmSchd(RgSchCellCb *cell,RgSchUeCb *ue)
1082 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1083 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1087 lst = &cellDl->prioLst[ueDl->prio];
1088 if (ueDl->prioLnk.node != NULLP)
1090 cmLListDelFrm(lst, &ueDl->prioLnk);
1091 ueDl->prioLnk.node = (PTR)NULLP;
1092 /* If a svc is removed from cell wide priority Qs
1093 * then remove the same from UE's lcsWithData List */
1094 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1101 * @brief This function removes a SVC from UEs AMBR LIST
1105 * Function: rgSCHSc1DlSvcRmvFrmUeAmbrLst
1106 * Purpose: This function removes a SVC from UEs AMBR List.
1108 * Invoked by: BO and Scheduler
1110 * @param[in] RgSchUeCb* ue
1111 * @param[in] RgSchDlLcCb* svc
1115 static Void rgSCHSc1DlSvcRmvFrmUeAmbrLst(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1117 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1118 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1121 lst = &ueDl->ambrLst;
1122 if (svcSc1->prioLnk.node != NULLP)
1124 cmLListDelFrm(lst, &svcSc1->prioLnk);
1125 svcSc1->prioLnk.node = (PTR)NULLP;
1132 * @brief This function adds a SVC to UEs AMBR LIST
1136 * Function: rgSCHSc1DlSvcAddToUeAmbrLst
1137 * Purpose: This function adds a SVC to UEs AMBR List.
1139 * Invoked by: BO and Scheduler
1141 * @param[in] RgSchUeCb* ue
1142 * @param[in] RgSchDlLcCb* svc
1146 static Void rgSCHSc1DlSvcAddToUeAmbrLst(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1148 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1151 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1152 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1155 /* If svc already present in AMBR List return */
1156 if (svcSc1->prioLnk.node != NULLP)
1159 node = ueDl->ambrLst.first;
1162 lsvc = (RgSchDlLcCb *)(node->node);
1163 if (((RgSchCmnDlSvc*)(lsvc->sch))->prio > svcCmn->prio)
1171 cmLListAdd2Tail(&ueDl->ambrLst, &svcSc1->prioLnk);
1172 svcSc1->prioLnk.node = (PTR)svc;
1176 ueDl->ambrLst.crnt = node;
1177 cmLListInsCrnt(&ueDl->ambrLst, &svcSc1->prioLnk);
1178 svcSc1->prioLnk.node = (PTR)svc;
1186 * @brief This function removes a service from scheduler
1190 * Function: rgSCHSc1DlSvcRmvFrmSchd
1191 * Purpose: This function removes the SVC from the scheduler Qs.
1193 * Invoked by: BO and Scheduler
1195 * @param[in] RgSchCellCb* cell
1196 * @param[in] RgSchUeCb* ue
1200 static Void rgSCHSc1DlSvcRmvFrmSchd(RgSchCellCb *cell,RgSchDlLcCb *svc)
1202 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1203 RgSchSc1DlSvc *svcDl = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
1204 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1208 lst = &(cellDl->prioLst[svcCmn->prio]);
1209 if (svcDl->prioLnk.node != NULLP)
1211 cmLListDelFrm(lst, &svcDl->prioLnk);
1212 svcDl->prioLnk.node = NULLP;
1213 /* If a svc is removed from cell wide priority Qs
1214 * then remove the same from UE's lcsWithData List */
1215 rgSCHSc1DlRmFrmUeLcsWithData(cell, svc->ue, svc);
1222 * @brief This function adds a service to scheduler for a UE
1226 * Function: rgSCHSc1DlSvcAdd
1227 * Purpose: This function is made available through a FP for
1228 * making scheduler aware of a service added to UE
1230 * Invoked by: BO and Scheduler
1232 * @param[in] RgSchUeCb* ue
1233 * @param[in] RgSchDlLcCb* svc
1234 * @param[in] CrgDlLchCfg* qos
1238 static Void rgSCHSc1DlSvcAdd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc,RgrDlLchCfg *cfg)
1240 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1241 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1242 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1246 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1248 svcSc1->gbr = svcCmn->gbr;
1249 svcSc1->mbr = svcCmn->mbr;
1250 cmLListAdd2Tail(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1251 svcSc1->gbrLnk.node = (PTR)svc;
1258 * @brief This function deletes a service from scheduler
1262 * Function: rgSCHSc1DlLcRmv
1263 * Purpose: This function is made available through a FP for
1264 * making scheduler aware of a service being deleted from UE
1266 * Invoked by: BO and Scheduler
1268 * @param[in] RgSchCellCb* cell
1269 * @param[in] RgSchUeCb* ue
1270 * @param[in] RgSchDlLcCb* svc
1274 Void rgSCHSc1DlLcRmv(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1277 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1278 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1281 if (svcSc1 == NULLP)
1285 ueDl = RG_GET_SC1_UE_DL(ue, cell);
1287 if (svcCmn->prio == 0)
1289 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1291 else if (RG_SCH_CMN_SVC_IS_GBR(svc))
1293 if (svcSc1->gbrLnk.node != NULLP)
1295 cmLListDelFrm(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1296 svcSc1->gbrLnk.node = NULLP;
1298 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1300 else /* if AMBR service */
1302 if (ueDl->ambrSvc == svc)
1304 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1305 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1306 ueDl->ambrSvc = NULLP;
1307 if (ueDl->ambrLst.first != NULLP)
1309 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1310 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svc->bo);
1313 rgSCHSc1DlUeAddToSchd(cell, ue);
1319 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1322 /* ccpu00117052 - MOD - Passing double pointer
1323 for proper NULLP assignment*/
1324 rgSCHUtlFreeSBuf(cell->instIdx,
1325 (Data**)(&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,svc,cell))), (sizeof(RgSchSc1DlSvc)));
1330 * @brief This function is invoked as part of SVC reconfig
1334 * Function: rgSCHSc1DlSvcMod
1335 * Purpose: This function is made available through a FP for
1336 * making scheduler aware of a service reconfiguration.
1338 * Invoked by: Scheduler
1340 * @param[in] RgSchDlLcCb* svc
1341 * @param[in] CrgLchRecfg* recfg
1345 static Void rgSCHSc1DlSvcMod(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc,RgrLchRecfg *recfg)
1347 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1348 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1350 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1352 /* Convert the QOS to handle the refresh duration */
1353 svcSc1->gbr = svcCmn->gbr;
1354 svcSc1->mbr = svcCmn->mbr;
1360 * @brief This function adds UE to scheduler for an AMBR service
1364 * Function: rgSCHSc1DlUeAddToSchd
1365 * Purpose: This function adds a UE to scheduler for the AMBR
1366 * service of highest priority.
1368 * Invoked by: BO and Scheduler
1370 * @param[in] RgSchCellCb* cell
1371 * @param[in] RgSchUeCb* ue
1375 static Void rgSCHSc1DlUeAddToSchd(RgSchCellCb *cell,RgSchUeCb *ue)
1377 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1378 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1379 RgSchSc1DlUe *lueDl;
1382 RgSchUeCb *nodeUe = NULLP;
1384 ueDl->prio = ((RgSchCmnDlSvc *)(ueDl->ambrSvc->sch))->prio;
1385 lst = &cellDl->prioLst[ueDl->prio];
1386 /* if UE already in list, remove and
1388 if (ueDl->prioLnk.node != NULLP)
1390 cmLListDelFrm(lst, &ueDl->prioLnk);
1391 ueDl->prioLnk.node = NULLP;
1392 /* If a svc is removed from cell wide priority Qs
1393 * then remove the same from UE's lcsWithData List */
1394 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1399 nodeUe = (RgSchUeCb *)(node->node);
1400 lueDl = RG_GET_SC1_UE_DL(nodeUe, cell);
1401 if (lueDl->effAmbr < ueDl->effAmbr)
1407 cmLListAdd2Tail(lst, &ueDl->prioLnk);
1408 ueDl->prioLnk.node = (PTR)ue;
1413 cmLListInsCrnt(lst, &ueDl->prioLnk);
1414 ueDl->prioLnk.node = (PTR)ue;
1416 /* If a svc is put in to cell wide priority Qs
1417 * then add the same to UE's lcsWithData List */
1418 rgSCHSc1DlAdd2UeLcsWithData(cell, ue, ueDl->ambrSvc);
1424 * @brief This function implements managing BO for an ABMR service
1428 * Function: rgSCHSc1DlMngAmbrSvcPosn
1429 * Purpose: This function should be called whenever there is a
1430 * change BO for a AMBR service.
1432 * Invoked by: BO and Scheduler
1434 * @param[in] RgSchCellCb* cell
1435 * @param[in] RgSchUeCb* ue
1436 * @param[in] RgSchDlLcCb* svc
1440 static Void rgSCHSc1DlMngAmbrSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1442 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1443 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1445 if (svcSc1->bo == 0)
1447 if (ueDl->ambrSvc == svc)
1449 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1450 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1451 ueDl->ambrSvc = NULLP;
1452 if (ueDl->ambrLst.first != NULLP)
1454 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1455 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1458 rgSCHSc1DlUeAddToSchd(cell, ue);
1464 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1467 else /* svcSc1->bo != 0 */
1469 if (svcSc1->prioLnk.node != NULLP)
1471 if (svc == ueDl->ambrSvc)
1473 ueDl->effAmbr = RGSCH_MIN(svcSc1->bo, ueDl->ambr);
1474 /* Update UE's position in the scheduler */
1477 rgSCHSc1DlUeAddToSchd(cell, ue);
1481 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1486 rgSCHSc1DlSvcAddToUeAmbrLst(cell, ue, svc);
1487 /* Current ambr svc is always the first node of ambrLst.*/
1488 if (ueDl->ambrLst.first->node == (PTR)svc)
1490 if(ueDl->ambrSvc != svc)
1494 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1496 ueDl->ambrSvc = svc;
1497 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1500 rgSCHSc1DlUeAddToSchd(cell, ue);
1510 * @brief This function updates the scheduler with service for a UE
1514 * Function: rgSCHSc1DlLcBoUpd
1515 * Purpose: This function should be called whenever there is a
1516 * change BO for a service.
1518 * Invoked by: BO and Scheduler
1520 * @param[in] RgSchCellCb* cell
1521 * @param[in] RgSchUeCb* ue
1522 * @param[in] RgSchDlLcCb* svc
1526 Void rgSCHSc1DlLcBoUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1528 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1530 if (svcSc1->bo == svc->bo)
1534 svcSc1->bo = svc->bo;
1535 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(ue))
1539 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
1541 /* Stack Crash problem for TRACE5 changes. Added the return below */
1548 * @brief This function updates the scheduler with Prio0 service for a UE
1552 * Function: rgSCHSc1DlMngPrio0SvcPosn
1553 * Purpose: This func shall be triggered whenever there is a
1554 * change in the "Bo yet to be satisfied" field of the service.
1555 * Appropriately positions the svc in its prio Q.
1556 * Removes the SVC from the Q if BO is completely satisfied.
1558 * Invoked by: BO and Scheduler
1560 * @param[in] RgSchCellCb* cell
1561 * @param[in] RgSchUeCb* ue
1562 * @param[in] RgSchDlLcCb* svc
1566 static Void rgSCHSc1DlMngPrio0SvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1568 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1570 /* In this priority, we just add or remove to the queue */
1573 rgSCHSc1DlSvcAddToSchd(cell, svc);
1577 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1584 * @brief This function updates the scheduler with GBR service for a UE
1588 * Function: rgSCHSc1DlMngGbrSvcPosn
1589 * Purpose: This func shall be triggered whenever there is a
1590 * change in the "Bo yet to be satisfied" field of the service.
1591 * Appropriately positions the svc in its prio Q.
1592 * Removes the SVC from the Q if BO is completely satisfied.
1594 * Invoked by: BO and Scheduler
1596 * @param[in] RgSchCellCb* cell
1597 * @param[in] RgSchUeCb* ue
1598 * @param[in] RgSchDlLcCb* svc
1602 static Void rgSCHSc1DlMngGbrSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1604 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1606 /* Handle a GBR service. */
1607 svcSc1->effGbr = RGSCH_MIN(svcSc1->bo, svcSc1->gbr);
1608 svcSc1->effMbr = RGSCH_MIN(svcSc1->bo, svcSc1->mbr);
1609 /* Adjust the SVC priority within the queue */
1610 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1611 rgSCHSc1DlSvcAddToSchd(cell, svc);
1617 * @brief This function updates the scheduler with service for a UE
1621 * Function: rgSCHSc1DlMngSvcPosn
1622 * Purpose: This func shall be triggered whenever there is a
1623 * change in the "Bo yet to be satisfied" field of the service.
1624 * Appropriately positions the svc in its prio Q.
1625 * Removes the SVC from the Q if BO is completely satisfied.
1627 * Invoked by: BO and Scheduler
1629 * @param[in] RgSchCellCb* cell
1630 * @param[in] RgSchUeCb* ue
1631 * @param[in] RgSchDlLcCb* svc
1635 static Void rgSCHSc1DlMngSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1637 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1638 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1640 (cellDl->svcMngFunc[svcCmn->prio])(cell, ue, svc);
1644 /*--------------------------*
1645 * DL specific functions END
1646 *---------------------------*/
1651 * @brief Scheduler processing on cell configuration
1655 * Function : rgSCHSc1RgrDlCellCfg
1657 * This function does requisite initialisation
1658 * and setup for scheduler1 when a cell is
1661 * @param[in] RgSchCellCb *cell
1662 * @param[in] RgrCellCfg *cellCfg
1663 * @param[out] RgSchErrInfo *err
1668 S16 rgSCHSc1RgrDlCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
1671 RgSchSc1DlCell *cellDl;
1673 if((ret = rgSCHUtlAllocSBuf(cell->instIdx,
1674 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc), \
1675 (sizeof(RgSchSc1DlCell)))) != ROK)
1677 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
1678 "Memory allocation FAILED");
1679 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
1683 cellDl = RG_GET_SC1_CELL_DL(cell);
1684 /* Now perform downlink Queues related initializations */
1685 rgSCHSc1DlInitQueues(cellDl);
1687 } /* rgSCHSc1RgrDlCellCfg */
1689 /***********************************************************
1691 * Func : rgSCHSc1DlDeinitQueues
1693 * Desc : De-initialise downlink scheduler queues
1701 **********************************************************/
1702 static Void rgSCHSc1DlDeinitQueues(RgSchSc1DlCell *cellDl)
1706 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
1708 cmLListInit(&cellDl->prioLst[i]);
1709 cmLListInit(&cellDl->retxLst[i]);
1716 * @brief Scheduler processing for cell delete
1720 * Function : rgSCHSc1DlCellDel
1722 * This functions de-initialises and frees memory
1723 * taken up by scheduler1 for the entire cell.
1725 * @param[in] RgSchCellCb *cell
1728 Void rgSCHSc1DlCellDel(RgSchCellCb *cell)
1731 if (((RgSchSc1DlCell *)((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc) \
1737 /* Perform the deinit for the DL scheduler */
1738 rgSCHSc1DlDeinitQueues(RG_GET_SC1_CELL_DL(cell));
1739 /* ccpu00117052 - MOD - Passing double pointer
1740 for proper NULLP assignment*/
1741 rgSCHUtlFreeSBuf(cell->instIdx,
1742 (Data**)(&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc)),
1743 (sizeof(RgSchSc1DlCell)));
1745 } /* rgSCHSc1DlCellDel */
1748 * @brief UE initialisation for scheduler
1752 * Function : rgSCHSc1RgrDlUeCfg
1754 * This functions intialises UE specific scheduler
1757 * @param[in] RgSchCellCb *cell
1758 * @param[in] RgSchUeCb *ue
1759 * @param[int] RgrUeCfg *ueCfg
1760 * @param[out] RgSchErrInfo *err
1765 S16 rgSCHSc1RgrDlUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg,RgSchErrInfo *err)
1767 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
1768 Inst inst = cell->instIdx;
1772 if((rgSCHUtlAllocSBuf(inst,
1773 (Data**)&(ueSchCmn->dl.schSpfc), (sizeof(RgSchSc1DlUe))) != ROK))
1775 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId, "Memory allocation FAILED"
1776 "CRNTI:%d",ue->ueId);
1777 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
1780 ueDl = (RgSchSc1DlUe *)ueSchCmn->dl.schSpfc;
1781 if (ue->dl.ambrCfgd)
1783 ueDl->ambr = ue->dl.ambrCfgd;
1787 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
1789 cmLListInit(&ueDl->lcsWithData);
1790 cmLListInit(&ueDl->gbrSvcs);
1791 cmLListInit(&ueDl->ambrLst);
1792 cmLListInit(&ueDl->schdSvcs);
1793 cmLListInit(&ueDl->retxHqProcs);
1795 } /* rgSCHSc1RgrDlUeCfg */
1799 * @brief Dl Harq Entity initialization for SC1
1803 * Function : rgSCHSc1DlUeHqEntInit
1806 * - Create SC1 related information per Harq Entity
1808 * @param[in] RgrSchCellCb *cell
1809 * @param[in] RgSchUeCb *ue
1814 S16 rgSCHSc1DlUeHqEntInit(RgSchCellCb *cell,RgSchDlHqEnt *hqEnt)
1816 RgSchSc1DlHqProc *hqSpcSch;
1817 RgSchDlHqProcCb *hqP;
1819 /* making use of hqE->sch for one shot allocation
1820 * of RgSchSc1DlHqProc structures */
1821 if (rgSCHUtlAllocSBuf(cell->instIdx,
1822 (Data**)&(hqEnt->sch),
1823 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc))) != ROK)
1825 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
1826 "Memory allocation FAILED CRNTI:%d",hqEnt->ue->ueId);
1829 hqSpcSch = (RgSchSc1DlHqProc *)(hqEnt->sch);
1830 for(cnt = 0; cnt < hqEnt->numHqPrcs; cnt++)
1832 hqP = &hqEnt->procs[cnt];
1833 ((RgSchCmnDlHqProc *)((hqP)->sch))->schSpfc = \
1840 * @brief Dl Harq Entity deletion for Sc1
1844 * Function : rgSCHSc1DlUeHqEntDeInit
1847 * - Free SC1 related information per Harq Entity
1849 * @param[in] RgrSchCellCb *cell
1850 * @param[in] RgSchDlHqEnt *hqE
1853 S16 rgSCHSc1DlUeHqEntDeInit(RgSchCellCb *cell,RgSchDlHqEnt *hqE)
1858 rgSCHUtlFreeSBuf(cell->instIdx,
1859 (Data**)(&(hqE->sch)),
1860 (hqE->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
1869 * @brief UE reconfiguration for scheduler
1873 * Function : rgSCHSc1RgrDlUeRecfg
1875 * This functions updates UE specific scheduler
1876 * information upon UE reconfiguration
1878 * @param[in] RgSchCellCb *cell
1879 * @param[in] RgSchUeCb *ue
1880 * @param[int] RgrUeRecfg *ueRecfg
1881 * @param[out] RgSchErrInfo *err
1886 S16 rgSCHSc1RgrDlUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
1888 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1889 RgSchCmnDlUe *ueCmnDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
1890 /*cell added as part of CA dev*/
1891 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1893 if (ue->dl.ambrCfgd)
1895 ueDl->ambr = ue->dl.ambrCfgd;
1899 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
1902 /* Discarding TB2's context from scheduling Queues.
1903 * Since TB2 transmission needs signalling using
1904 * TM specific formats. And since during this transient
1905 * period of UE TM Recfg, SCH always uses Format 1A,
1906 * the TB2s are discarded. */
1907 if (ueCmnDl->mimoInfo.forceTD & RG_SCH_CMN_TD_TXMODE_RECFG)
1909 /* If HqP is in retx queue only for TB2 retx scheduling
1910 * then remove the harp proc from retx Queue */
1912 /* If Hqp is in retx queue for retx allocation of
1913 * both TB1 and TB2, then reset TB2's state as ACKED */
1914 RgSchDlHqProcCb *hqP;
1916 RgInfRlsHqInfo *rlsHqBufs = &(cell->rlsHqArr[cell->crntHqIdx]);
1919 /* Prepare TB2 release information to be sent to MAC */
1920 rlsHqBufs->numUes = 0;
1921 for(i = 0; i < hqEnt->numHqPrcs; i++)
1923 hqP = &hqEnt->procs[i];
1924 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = ue->ueId;
1925 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = hqP->procId;
1926 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
1928 if (hqP->tbInfo[0].state != HQ_TB_NACKED)
1930 /* Remove the HqP from retx Queue.
1932 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
1933 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
1935 rgSCHDhmRlsHqpTb(hqP, 1, TRUE);
1936 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[0] = 2;
1937 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 1;
1939 rlsHqBufs->numUes++;
1941 /* Send the hqProc list for MAC to clear TB1 contents */
1942 if (rlsHqBufs->numUes)
1944 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
1945 RgSchMacRlsHq (&pst, rlsHqBufs);
1949 } /* rgSCHSc1RgrDlUeRecfg */
1952 * @brief Removes UEs context from Priority Qs.
1956 * Function : rgSCHSc1DlRmvUeFrmPrioQs
1959 * @param[in] RgSchCellCb *cell
1960 * @param[in] RgSchUeCb *ue
1963 static Void rgSCHSc1DlRmvUeFrmPrioQs(RgSchCellCb *cell,RgSchUeCb *ue)
1965 RgSchSc1DlUe *sc1Ue;
1970 sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
1972 /* Remove UE From DL priority queues */
1973 if (sc1Ue->ambrSvc != NULLP)
1975 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1978 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
1980 svc = ue->dl.lcCb[idx];
1985 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1989 } /* rgSCHSc1DlRmvUeFrmPrioQs */
1992 * @brief Inactivate UE reason : measgap, acknaprept, poInactv.
1996 * Function : rgSCHSc1DlInactvtUe
1999 * @param[in] RgSchCellCb *cell
2000 * @param[in] RgSchUeCb *ue
2003 static Void rgSCHSc1DlInactvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
2005 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
2006 RgSchDlHqProcCb *hqP;
2007 RgSchCmnDlHqProc *hqProcDl;
2009 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2012 /* ccpu00130170: UE related HARQ Procs are cleared only
2013 if UE's Re-establishment procedure is not in progress*/
2014 if(!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE))
2016 /* remove all in use HARQ processes from the subframes.
2017 * Store them in UEs hqProc Lst. Add back to cell's
2018 * retx lst when UE is activated again. */
2019 for(i = 0; i < hqEnt->numHqPrcs; i++)
2021 hqP = &hqEnt->procs[i];
2022 hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
2023 /* Remove retx procs from cell's list and
2024 * add them to UE's List */
2027 !(RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)) &&
2029 hqProcDl->retxLnk.node != NULLP)
2031 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
2032 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
2033 hqProcDl->retxLnk.node = NULLP;
2034 rgSCHSc1DlProcAddToUeRetx(cell, ue, hqP);
2039 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2042 } /* rgSCHSc1DlInactvtUe */
2046 * @brief UE suspension.
2050 * Function : rgSCHSc1DlSuspendUe
2052 * Removes UE, its SVCs and its HqPs from CELL WIDE
2053 * PrioQs and Retx Qs Respectively.
2055 * @param[in] RgSchCellCb *cell
2056 * @param[in] RgSchUeCb *ue
2059 static Void rgSCHSc1DlSuspendUe(RgSchCellCb *cell,RgSchUeCb *ue)
2061 RgSchDlHqProcCb *hqP;
2064 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2067 /* remove all in use HARQ processes from the subframes.
2068 * Store them in UEs hqProc Lst. Add back to cell's
2069 * retx lst when UE is activated again. */
2070 for(i = 0; i < hqEnt->numHqPrcs; i++)
2072 hqP = &hqEnt->procs[i];
2073 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2074 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
2075 /* Removing the Harq Proc from subframes list */
2076 if (hqP->hqPSfLnk.node != NULLP)
2080 cmLListDelFrm(&hqP->subFrm->pdcchInfo.pdcchs,
2082 cmLListAdd2Tail(&cell->pdcchLst, &hqP->pdcch->lnk);
2086 rgSCHUtlDlHqPTbRmvFrmTx(hqP->subFrm,hqP,0,FALSE);
2088 for (j = 0; j < 2; j++)
2090 if (hqP->tbInfo[j].state == HQ_TB_WAITING)
2092 rgSCHDhmRlsHqpTb(hqP, j, TRUE);
2097 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2100 } /* rgSCHSc1DlSuspendUe */
2102 /***********************************************************
2104 * Func : rgSCHSc1DlScanUpdPdbPrio
2106 * Desc : Increment the pivot and reposition the LCs under the pivot to
2107 * new location according to thieir PDB and elapsed time.
2115 **********************************************************/
2116 Void rgSCHSc1DlScanUpdPdbPrio(RgSchCellCb *cell)
2123 * @brief Function to update Flow control information
2124 * to be sent to MAC.
2128 * Function: rgSCHSc1DlFillFlowCntrlInfo
2130 * update Flow control information
2137 * @param[in] RgSchCellCb *cell
2138 RgInfSfAlloc *sfAlloc;
2142 S16 rgSCHSc1DlFillFlowCntrlInfo(RgSchCellCb *cell,RgInfSfAlloc *sfAlloc)
2147 * @brief UE deletion for scheduler
2151 * Function : rgSCHSc1DlUeDel
2153 * This functions deletes all scheduler information
2154 * pertaining to a UE
2156 * @param[in] RgSchCellCb *cell
2157 * @param[in] RgSchUeCb *ue
2160 Void rgSCHSc1DlUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
2162 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2163 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
2166 if (sc1DlUe == NULLP)
2172 /* Remove UEs scheduler context */
2173 rgSCHSc1DlSuspendUe(cell, ue);
2175 /* Free all SC1 specific control blocks */
2176 if (hqEnt->sch != NULLP)
2178 /* ccpu00117052 - MOD - Passing double pointer
2179 for proper NULLP assignment*/
2180 rgSCHUtlFreeSBuf(cell->instIdx,
2181 (Data**)(&(hqEnt->sch)),
2182 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
2186 /* ccpu00117052 - MOD - Passing double pointer
2187 for proper NULLP assignment*/
2188 rgSCHUtlFreeSBuf(cell->instIdx, (Data**)(&sc1DlUe), (sizeof(RgSchSc1DlUe)));
2191 } /* rgSCHSc1DlUeDel */
2194 * @brief Scheduler invocation on Downlink logical channel addition
2198 * Function : rgSCHSc1RgrLcCfg
2200 * This functions does required processing when a new
2201 * (dedicated) logical channel is added.
2203 * @param[in] RgSchCellCb *cell
2204 * @param[in] RgSchUeCb *ue
2205 * @param[in] RgSchDlLcCb *dlLc
2206 * @param[int] RgrLchCfg *lcCfg
2207 * @param[out] RgSchErrInfo *err
2212 S16 rgSCHSc1RgrLcCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchCfg *lcCfg,RgSchErrInfo *err)
2216 ret = rgSCHUtlAllocSBuf(cell->instIdx,
2217 (Data**)&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,dlLc,cell)), \
2218 (sizeof(RgSchSc1DlSvc)));
2221 RLOG_ARG2(L_ERROR,DBG_CELLID,cell->cellId, "rgSCHSc1CrgLcCfg():"
2222 "SCH struct alloc failed CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId);
2223 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
2227 rgSCHSc1DlSvcAdd(cell, ue, dlLc, &lcCfg->dlInfo);
2229 } /* rgSCHSc1RgrLcCfg */
2233 * @brief Scheduler invocation on logical channel addition
2237 * Function : rgSCHSc1RgrLcRecfg
2239 * This functions does required processing when an existing
2240 * (dedicated) logical channel is reconfigured. Assumes lcg
2241 * pointer in ulLc is set to the old value.
2242 * Independent of whether new LCG is meant to be configured,
2243 * the new LCG scheduler info is accessed and possibly modified.
2245 * @param[in] RgSchCellCb *cell
2246 * @param[in] RgSchUeCb *ue
2247 * @param[in] RgSchDlLcCb *dlLc
2248 * @param[int] RgrLchRecfg *lcRecfg
2249 * @param[out] RgSchErrInfo *err
2254 S16 rgSCHSc1RgrLcRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchRecfg *lcRecfg,RgSchErrInfo *err)
2259 rgSCHSc1DlSvcMod(cell,ue,dlLc, lcRecfg);
2262 } /* rgSCHSc1RgrLcRecfg */
2266 * @brief This function handles the reconfiguration of cell
2270 * Function: rgSCHSc1RgrDlCellRecfg
2271 * Purpose: Update the reconfiguration parameters.
2273 * Invoked by: Scheduler
2275 * @param[in] RgSchCellCb* cell
2279 static S16 rgSCHSc1RgrDlCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
2287 * @brief This function implements scheduler DL allocation
2291 * Function: rgSCHSc1DlTaCmd
2292 * Purpose: This function implements scheduler for TA cmd alloc for
2293 * UEs. The hq proc availed as part of this alloc can be used
2294 * by the UEs Dedicated CH transmission allocation.
2296 * Invoked by: Scheduler
2298 * @param[in] RgSchCellCb* cell
2299 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
2303 static Void rgSCHSc1DlTaCmd(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2307 RgSchDlHqProcCb *proc;
2310 RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell);
2311 RgSchCmnDlUe *cmnUeDl;
2313 RgSchCmnDlHqProc *cmnHqDl;
2314 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
2316 Bool dlAllowed = FALSE;
2319 lst = &cellCmnDl->taLst;
2323 ue = (RgSchUeCb *)node->node;
2328 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
2329 if (dlAllowed == FALSE)
2335 /* If Ue is inactive in DL then ignore */
2336 if (ue->dl.dlInactvMask)
2340 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2341 /*cell added as part of CA dev*/
2342 ueDl = RG_GET_SC1_UE_DL(ue, cell);
2344 if (rgSCHDhmGetAvlHqProc(cell, ue, cellCmnDl->time, &proc) != ROK)
2348 /* Initialize some of the parameters of the HQ proc */
2349 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
2353 cmnHqDl->totBytes = 0;
2354 rgSCHCmnDlAllocTxRb(cell, subFrm, ue, RGSCH_TA_SIZE, &effBo, proc, allocInfo);
2357 /* If no allocations so far, meaning proc obtained now */
2358 if (cmnHqDl->totBytes == 0)
2360 rgSCHSc1RlsHqProc(proc);
2361 /* Added the handling for removing
2362 * UE from txHqPLst and resetting outStndalloc.*/
2363 if(proc->reqLnk.node != (PTR)NULLP)
2365 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
2366 proc->reqLnk.node = (PTR)NULLP;
2368 /*Re-set the outstanding alloc information.*/
2369 cmnUeDl->outStndAlloc = 0;
2371 /* Avl BW could not satisfy even TA so break */
2374 ueDl->taReqBytes = RGSCH_TA_SIZE;
2375 cmnUeDl->proc = proc;
2376 cmnHqDl->totBytes += effBo;
2377 /* 3.1 MIMO moving this call to cmn scheduler */
2378 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue);*/
2384 * @brief Scheduler invocation
2388 * Function: rgSCHSc1DlHndlInActUes
2389 * Purpose: The list of inactive UEs present in inactvLst should
2390 * be removed from the scheduling Qs.
2392 * Invoked by: Common Scheduler (TTI processing)
2394 * @param[in] RgSchCellCb *cell
2395 * @param[out] CmLListCp *inactvLst
2398 Void rgSCHSc1DlHndlInActUes(RgSchCellCb *cell,CmLListCp *inactvLst)
2403 node = inactvLst->first;
2406 ue = (RgSchUeCb *)node->node;
2408 /* Suspend this UE from further scheduling
2409 * till it is activated again. */
2410 rgSCHSc1DlInactvtUe(cell, ue);
2416 * @brief This function initializes all the data for the scheduler
2420 * Function: rgSCHSc1DlInit
2421 * Purpose: This function initializes the following information
2422 * 1. Efficiency table
2423 * 2. CQI to table index - It is one row for upto 3 RBs
2424 * and another row for greater than 3 RBs
2426 * currently extended prefix is compiled out.
2427 * Invoked by: MAC intialization code..may be ActvInit
2432 Void rgSCHSc1DlInit(RgDlSchdApis *rgSchDlApis)
2434 /* Init the function pointers */
2435 rgSchDlApis->rgSCHRgrDlUeCfg = rgSCHSc1RgrDlUeCfg;
2436 rgSchDlApis->rgSCHRgrDlUeRecfg = rgSCHSc1RgrDlUeRecfg;
2437 rgSchDlApis->rgSCHFreeDlUe = rgSCHSc1DlUeDel;
2438 rgSchDlApis->rgSCHRgrDlCellCfg = rgSCHSc1RgrDlCellCfg;
2439 rgSchDlApis->rgSCHRgrDlCellRecfg = rgSCHSc1RgrDlCellRecfg;
2440 rgSchDlApis->rgSCHFreeDlCell = rgSCHSc1DlCellDel;
2441 rgSchDlApis->rgSCHRgrDlLcCfg = rgSCHSc1RgrLcCfg;
2442 rgSchDlApis->rgSCHRgrDlLcRecfg = rgSCHSc1RgrLcRecfg;
2443 rgSchDlApis->rgSCHFreeDlLc = rgSCHSc1DlLcRmv;
2444 rgSchDlApis->rgSCHDlNewSched = rgSCHSc1DlDedNewTx;
2445 rgSchDlApis->rgSCHDlPreSched = rgSCHSc1DlPreSchd;
2446 rgSchDlApis->rgSCHDlPstSched = rgSCHSc1DlPstSchd;
2447 rgSchDlApis->rgSCHDlRetxSched = rgSCHSc1DlDedRetx;
2448 rgSchDlApis->rgSCHDlCeSched = rgSCHSc1DlTaCmd;
2449 rgSchDlApis->rgSCHDlDedBoUpd = rgSCHSc1DlLcBoUpd;
2450 rgSchDlApis->rgSCHDlProcAddToRetx = rgSCHSc1DlProcAddToCellRetx;
2451 rgSchDlApis->rgSCHDlAllocFnlz = rgSCHSc1DlAllocFnlz;
2452 rgSchDlApis->rgSCHDlCqiInd = rgSCHSc1DlCqiInd;
2453 rgSchDlApis->rgSCHDlUeRefresh = rgSCHSc1DlUeRefresh;
2454 rgSchDlApis->rgSCHDlUeReset = rgSCHSc1DlUeReset;
2455 rgSchDlApis->rgSCHDlActvtUe = rgSCHSc1DlActvtUe;
2456 rgSchDlApis->rgSCHDlInactvtUes = rgSCHSc1DlHndlInActUes;
2457 rgSchDlApis->rgSCHDlUeHqEntInit = rgSCHSc1DlUeHqEntInit;
2458 rgSchDlApis->rgSCHDlUeHqEntDeInit = rgSCHSc1DlUeHqEntDeInit;
2459 rgSchDlApis->rgSCHDlProcRmvFrmRetx = rgSCHSc1DlProcRmvFrmRetx;
2460 rgSchDlApis->rgSCHDlTickForPdbTrkng = rgSCHSc1DlScanUpdPdbPrio;
2461 rgSchDlApis->rgSCHDlFillFlwCtrlInfo = rgSCHSc1DlFillFlowCntrlInfo;
2469 /***********************************************************
2471 * Func : rgSCHSc1DlInitQueues
2473 * Desc : Initial downlink scheduler queues
2481 **********************************************************/
2482 static Void rgSCHSc1DlInitQueues(RgSchSc1DlCell *cellDl)
2486 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
2488 cmLListInit(&cellDl->prioLst[i]);
2489 cmLListInit(&cellDl->retxLst[i]);
2491 /* Set appropriate "manage svc positioning" function based on
2492 * svc priority as array index */
2494 for (i = 0; i < RG_SCH_SC1_DL_GBR_PRIO_START; i++)
2496 cellDl->svcMngFunc[i] = rgSCHSc1DlMngPrio0SvcPosn;
2499 for (i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
2501 cellDl->svcMngFunc[i] = rgSCHSc1DlMngGbrSvcPosn;
2503 /* for Non-GBR svcs */
2504 for (i = RG_SCH_SC1_DL_GBR_PRIO_END+1; i <= RG_SCH_CMN_MAX_PRIO; i++)
2506 cellDl->svcMngFunc[i] = rgSCHSc1DlMngAmbrSvcPosn;
2515 * @brief This function Processes the Final Allocations
2516 * made by the RB Allocator against the requested
2521 * Function: rgSCHSc1DlRetxAllocFnlz
2522 * Purpose : Remove the Retx Hq Proc from the Cell's
2523 * Retx list, if allocation is successful.
2524 * Fill the HqProc and PDCCH and append it to the SubFrm.
2528 * Invoked by: Common Scheduler
2530 * @param[in] RgSchCellCb *cell
2531 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
2535 static Void rgSCHSc1DlRetxAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2539 RgSchDlHqProcCb *hqP;
2540 RgSchDlRbAlloc *dlAllocCb = NULLP;
2542 node = allocInfo->dedAlloc.schdRetxHqPLst.first;
2545 hqP = (RgSchDlHqProcCb *)node->node;
2548 /* Fill PDCCH and assign it to HqP */
2549 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
2551 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
2555 rgSCHCmnHdFddUpdDLMark(cell, ue);
2558 /* Extra Check: Retain the hqProc in the RETX Queue if one/more
2559 * TBs of the HqProc are yet to be scheduled for RETX.
2560 * Note: Here we are not tracking at TB Level, the priority Q
2561 * to which it belongs to. The retx prio of transmission is still
2562 * being maintained at hqProc level, rather than at TB level */
2563 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
2564 (hqP->tbInfo[1].state != HQ_TB_NACKED)) {
2565 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2567 /* reset the UE allocation Information */
2568 rgSCHCmnDlUeResetTemp(ue, hqP);
2571 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
2572 node = allocInfo->dedAlloc.nonSchdRetxHqPLst.first;
2575 hqP = (RgSchDlHqProcCb *)node->node;
2578 /* reset the UE allocation Information */
2579 rgSCHCmnDlUeResetTemp(ue, hqP);
2584 /* 3.1 MIMO Alloc distribution functions being performed
2588 /***********************************************************
2590 * Func : rgSCHSc1DlSprTxTbDstn
2592 * Desc : Perform Actual allocation distribution among
2593 * UEs schd svcs and TA for a given spare TB "tbInfo" allocation.
2594 * spare TB allocation is as a result of 1 RETX TB allocation, when
2595 * conditions are favourable for 2 TB spatial multiplexing.
2603 **********************************************************/
2604 static Void rgSCHSc1DlSprTxTbDstn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqTbCb *tbInfo,uint32_t *effAlloc,CmLList **node)
2607 RgSchSc1DlSvc *svcSc1;
2608 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2610 RgSchLchAllocInfo lchSchdData;
2612 uint32_t rlcHdrEstmt;
2615 while((*node) && (*effAlloc > 0))
2617 svc = (RgSchDlLcCb *)(*node)->node;
2618 *node = (*node)->next;
2619 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
2621 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
2622 /* Update the SVC QOS Param */
2623 if (RG_SCH_CMN_SVC_IS_GBR(svc))
2625 effBo = svcSc1->effMbr + rlcHdrEstmt;
2626 bytes = RGSCH_MIN(*effAlloc, effBo);
2627 /* Determine How much BO is satisfied */
2628 if (bytes <= rlcHdrEstmt)
2632 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2634 (svcSc1->bo -= bytes-rlcHdrEstmt);
2635 svc->bo = svcSc1->bo;
2639 /* Increment qciActiveLCs once since this LCs buffer will be present
2641 if (svc->lcType == CM_LTE_LCH_DTCH)
2643 ue->qciActiveLCs[svc->qciCb->qci]++;
2646 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
2648 if (ue->qciActiveLCs[svc->qciCb->qci])
2650 ue->qciActiveLCs[svc->qciCb->qci]--;
2652 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
2654 svc->qciCb->dlUeCount--;
2658 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
2659 (svcSc1->gbr -= bytes);
2660 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
2661 (svcSc1->mbr -= bytes);
2663 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
2665 effBo = ueDl->effAmbr + rlcHdrEstmt;
2666 bytes = RGSCH_MIN(*effAlloc, effBo);
2667 /* Determine How much BO is satisfied */
2668 if (bytes <= rlcHdrEstmt)
2672 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2674 (svcSc1->bo -= bytes-rlcHdrEstmt);
2676 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
2677 (ueDl->ambr -= bytes);
2679 else /* Prio 0 SVC */
2681 effBo = svcSc1->bo + rlcHdrEstmt;
2682 bytes = RGSCH_MIN(*effAlloc, effBo);
2683 /* Determine How much BO is satisfied */
2684 if (bytes <= rlcHdrEstmt)
2688 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2690 (svcSc1->bo -= bytes-rlcHdrEstmt);
2692 /* Position the service accordingly */
2693 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
2694 /* Update effAlloc */
2697 /* Update DHM for this SVC */
2698 lchSchdData.lcId = svc->lcId;
2699 lchSchdData.schdData = bytes;
2700 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
2706 /***********************************************************
2708 * Func : rgSCHSc1DlNewTxTbDstn
2710 * Desc : Perform Actual allocation distribution among
2711 * UEs schd svcs and TA for a given TB "tbInfo" allocation.
2712 * Assumption: TA is given higher priority in Alloc Distribution.
2720 **********************************************************/
2721 static Void rgSCHSc1DlNewTxTbDstn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqTbCb *tbInfo,uint32_t *effAlloc,CmLList **node)
2724 RgSchSc1DlSvc *svcSc1 = NULLP;
2725 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2727 RgSchLchAllocInfo lchSchdData;
2728 CmLList *prev = NULLP;
2731 if (ueDl->taReqBytes)
2733 if (ueDl->taReqBytes < *effAlloc)
2735 /*TA satisfied, hence remove from TA Lst */
2736 rgSCHCmnRmvFrmTaLst(cell, ue);
2737 /* Indicate to DHM that TA has been scheduled */
2738 rgSCHDhmSchdTa(ue, tbInfo);
2739 *effAlloc -= ueDl->taReqBytes;
2741 /* Reset the TA Req Bytes Field */
2742 ueDl->taReqBytes = 0;
2744 while((*node) && (*effAlloc > 0))
2746 svc = (RgSchDlLcCb *)(*node)->node;
2748 *node = (*node)->next;
2749 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
2750 if (*effAlloc > svcSc1->reqBytes)
2752 bytes = svcSc1->reqBytes;
2753 if (bytes <= svcSc1->hdrEstimate)
2757 /* 3.1 MIMO updating the reqBytes field */
2758 svcSc1->reqBytes = 0;
2764 if (bytes <= svcSc1->hdrEstimate)
2768 /* 3.1 MIMO updating the reqBytes field */
2769 svcSc1->reqBytes -= bytes;
2770 (svcSc1->bo <= bytes-svcSc1->hdrEstimate)?\
2772 (svcSc1->bo -= bytes-svcSc1->hdrEstimate);
2774 svc->bo = svcSc1->bo;
2779 /* Increment qciActiveLCs once since this LCs buffer will be present
2781 if (svc->lcType == CM_LTE_LCH_DTCH)
2783 ue->qciActiveLCs[svc->qciCb->qci]++;
2786 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
2788 if (ue->qciActiveLCs[svc->qciCb->qci])
2790 ue->qciActiveLCs[svc->qciCb->qci]--;
2792 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
2794 svc->qciCb->dlUeCount--;
2799 /* Update the SVC QOS Param */
2800 if (RG_SCH_CMN_SVC_IS_GBR(svc))
2802 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
2803 (svcSc1->gbr -= bytes);
2804 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
2805 (svcSc1->mbr -= bytes);
2807 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
2809 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
2810 (ueDl->ambr -= bytes);
2812 /* Position the service accordingly */
2813 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
2814 /* Update effAlloc */
2817 /* Update DHM for this SVC */
2818 lchSchdData.lcId = svc->lcId;
2819 lchSchdData.schdData = bytes;
2820 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
2822 /* If no more scheduled LCs for TB data distribution
2823 * then distribute the spare TB data among the LCs
2824 * of the UE with non-zero BO. This is effective for
2825 * schedulers work on LC level priorities rather than
2827 if ((*node == NULLP) && (svcSc1) && (svcSc1->reqBytes == 0))
2829 rgSCHSc1DlSprTxTbDstn(cell, ue, tbInfo, effAlloc,
2830 &ueDl->lcsWithData.first);
2834 /* make sure node points to the svc not completely
2836 * make sure if not served completely then
2837 * the other TB allocation accomodates the same */
2844 /***********************************************************
2846 * Func : rgSCHSc1DlNewTxUeFnlz
2848 * Desc : Perform allocation Distribution from scheduled TB
2849 * among the list of services considered for scheduling.
2857 **********************************************************/
2858 static Void rgSCHSc1DlNewTxUeFnlz (RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo,RgSchUeCb *ue)
2861 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2862 RgSchCmnDlUe *cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2863 /*cell added as part of CA dev*/
2864 /* 3.1 MIMO Distribute data of each TB across services */
2865 RgSchDlRbAlloc *dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
2866 uint32_t remTb1Bytes = dlAllocCb->tbInfo[0].bytesAlloc;
2867 uint32_t remTb2Bytes = dlAllocCb->tbInfo[1].bytesAlloc;
2868 uint32_t effAlloc = 0;
2869 /*ccpu00120365-ADD-added to code to check if second TB is utilized */
2870 uint32_t tb2Bytes = 0;
2874 /* 3.1 MIMO Consider the allocation of New TX TB for distribution */
2875 /* Handle schd services */
2876 node = ueDl->schdSvcs.first;
2878 effAlloc += remTb1Bytes;
2879 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[0],\
2880 &remTb1Bytes, &node);
2881 /* In the event that TB1 is not completely filled by the DL LCs
2882 * BO, consider the reducing the iMcs for increasing redundancy
2883 * and hence reception quality at UE */
2884 rgSCHCmnRdcImcsTxTb(dlAllocCb, 0,
2885 dlAllocCb->tbInfo[0].bytesAlloc - remTb1Bytes);
2888 /*ccpu00120365-ADD-assigning value of remTb2Bytes before utilization */
2889 tb2Bytes = remTb2Bytes;
2891 /* Extra check for a non SM UE allocation */
2893 effAlloc += remTb2Bytes;
2894 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[1],\
2895 &remTb2Bytes, &node);
2896 /* In the event that TB2 is not completely filled by the DL LCs
2897 * BO, consider the reducing the iMcs for increasing redundancy
2898 * and hence reception quality at UE */
2899 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1,
2900 dlAllocCb->tbInfo[1].bytesAlloc - remTb2Bytes);
2903 /* ccpu00120365-ADD-Disable the second TB as the second TB is not
2905 if ( remTb2Bytes && ( tb2Bytes == remTb2Bytes) )
2907 dlAllocCb->mimoAllocInfo.precIdxInfo = 0;
2908 dlAllocCb->mimoAllocInfo.numTxLyrs = 1;
2909 dlAllocCb->tbInfo[1].schdlngForTb = FALSE;
2910 dlAllocCb->tbInfo[1].isDisabled = TRUE;
2913 if (effAlloc == (remTb1Bytes + remTb2Bytes))
2915 /* Allocation such that Nothing could be satisfied */
2916 /* Return the grabbed PDCCH */
2917 rgSCHUtlPdcchPut(cell, &dlAllocCb->dlSf->pdcchInfo,
2919 rgSCHSc1RlsHqProc(cmnUeDl->proc);
2923 /* Fill PDCCH and assign it to HqP */
2924 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, cmnUeDl->proc);
2931 * @brief This function Processes the Final Allocations
2932 * made by the RB Allocator against the requested
2933 * New TX allocations.
2937 * Function: rgSCHSc1DlNewTxAllocFnlz
2938 * Purpose : Distribute the allocation among the Scheduled SVCs.
2939 * Fill pdcch and HqP for UEs will allocations.
2940 * Release HqP for UE with no allocation.
2942 * Invoked by: Common Scheduler
2944 * @param[in] RgSchCellCb *cell
2945 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
2949 static Void rgSCHSc1DlNewTxAllocFnlz (RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2953 RgSchCmnDlUe *cmnUeDl;
2954 RgSchDlHqProcCb *hqP;
2956 node = allocInfo->dedAlloc.schdTxHqPLst.first;
2959 hqP = (RgSchDlHqProcCb *)node->node;
2962 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2963 /*cell added as part of CA dev*/
2965 rgSCHSc1DlNewTxUeFnlz(cell, allocInfo, ue);
2969 rgSCHCmnHdFddUpdDLMark(cell, ue);
2972 /* reset the UE allocation Information */
2973 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
2974 rgSCHCmnDlUeResetTemp(ue, hqP);
2977 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
2978 node = allocInfo->dedAlloc.nonSchdTxHqPLst.first;
2981 hqP = (RgSchDlHqProcCb *)node->node;
2984 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue, cell);
2986 /* Release HqProc */
2987 rgSCHSc1RlsHqProc(hqP);
2988 /* reset the UE allocation Information */
2989 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
2990 rgSCHCmnDlUeResetTemp(ue, hqP);
2995 /* 3.1 Added new function to handle TX+RETX alloc fnlz'n */
2998 * @brief This function Processes the Final Allocations
2999 * made by the RB Allocator against the requested
3000 * RETX+New TX allocations. The NewTx TB allocation
3001 * is considered for distribution among LCs.
3005 * Function: rgSCHSc1DlRetxNewTxAllocFnlz
3006 * Purpose : 1. Reached here due to 1 RETX TB allocation for a
3007 * SM UE, which is capable to accomodate a newTX
3009 * 2. Distribute NewTX TB allocation among the
3010 * SVCs present in lcsWithData list of UE.
3013 * Invoked by: Common Scheduler
3015 * @param[in] RgSchCellCb *cell
3016 * @param[in] RgSchCmnDlRbAllocInfo *cellAllocInfo
3020 static Void rgSCHSc1DlRetxNewTxAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *cellAllocInfo)
3024 RgSchSc1DlUe *sc1DlUe;
3025 RgSchDlHqProcCb *hqP;
3026 RgSchDlHqTbCb *newTxTbInfo;
3028 uint32_t remTbBytes;
3029 RgSchDlRbAlloc *ueAllocInfo;
3030 RgSchDlRbAlloc *dlAllocCb;
3033 node = cellAllocInfo->dedAlloc.schdTxRetxHqPLst.first;
3036 hqP = (RgSchDlHqProcCb *)node->node;
3039 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3040 ueAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3041 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3042 /* Index 0 of ueAllocInfo->tbInfo will always hold the
3043 * RETX TB and index 1 will hold the NewTX TB in case of
3044 * RETX+TX allocation. */
3045 newTxTbInfo = ueAllocInfo->tbInfo[1].tbCb;
3046 effAlloc = remTbBytes = ueAllocInfo->tbInfo[1].bytesAlloc;
3047 rgSCHSc1DlSprTxTbDstn(cell, ue, newTxTbInfo,\
3048 &remTbBytes, &(sc1DlUe->lcsWithData.first));
3049 /* Trying to reduce mcs of TX TB to increase reception quality at UE.
3050 * In case of RETX+TX allocation, TX TB allocation was irrespective
3051 * of actual requirement by UE, hence in case if consumption is
3052 * less than allocation, consider reducing the iMcs of this TX TB. */
3053 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1, effAlloc - remTbBytes);
3054 /* 3.1 MIMO Remove/Retain from/in cell RETX List */
3055 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
3056 /* Fill PDCCH and assign it to HqP */
3057 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
3061 rgSCHCmnHdFddUpdDLMark(cell, ue);
3064 /* reset the UE allocation Information */
3065 rgSCHCmnDlUeResetTemp(ue, hqP);
3068 /* Traverse the nonSchdTxRetxHqPLst and reset the UE allocation Info */
3069 node = cellAllocInfo->dedAlloc.nonSchdTxRetxHqPLst.first;
3072 hqP = (RgSchDlHqProcCb *)node->node;
3075 /* reset the UE allocation Information */
3076 rgSCHCmnDlUeResetTemp(ue, hqP);
3082 * @brief This function Processes the Final Allocations
3083 * made by the RB Allocator against the requested.
3087 * Function: rgSCHSc1DlAllocFnlz
3088 * Purpose: This function Processes the Final Allocations
3089 * made by the RB Allocator against the requested.
3090 * 1. Loop through scheduled TX and RETX lists.
3091 * Fill in the corresponding PDCCH and HqProcs.
3092 * In case of TX If actual Alloc < requested, then perform
3093 * an appropriate distribution among the schdSvcs.
3094 * If TA is satisfied, then remove UE from TA Lst.
3095 * 2. Loop through UnScheduled TX and RETX Lists.
3096 * Release grabbed HqProcs.
3097 * Put back SVCs from schdSvcsLst to their corresponding Qs.
3100 * Invoked by: Common Scheduler
3102 * @param[in] RgSchCellCb *cell
3103 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
3107 Void rgSCHSc1DlAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
3110 rgSCHSc1DlRetxAllocFnlz(cell, allocInfo);
3112 rgSCHSc1DlNewTxAllocFnlz(cell, allocInfo);
3114 /*3.1 MIMO new Function added to handle TX+RETX
3115 * harq process scheduling finalization */
3116 rgSCHSc1DlRetxNewTxAllocFnlz(cell, allocInfo);
3123 * @brief This function Updates the DL CQI for the UE.
3127 * Function: rgSCHSc1DlCqiInd
3128 * Purpose: Updates the DL CQI for the UE
3130 * Invoked by: Common Scheduler. SC1 does nothing.
3132 * @param[in] RgSchCellCb *cell
3133 * @param[in] RgSchUeCb *ue
3134 * @param[in] TfuDlCqiRpt *dlCqiRpt
3138 Void rgSCHSc1DlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,Bool isPucchInfo,Void *dlCqi)
3145 * @brief This function adds a service to UE's list of lcsWithData.
3149 * Function: rgSCHSc1DlAdd2UeLcsWithData
3150 * Purpose: 1. This is to maintain a snapshot view of the
3151 * DL SVCs distributions among the cellwide priority
3153 * 2. This snapshot view is maintained in the order
3154 * of priority of the SVCs with in UE.
3155 * 3. Addition of SVC to a cellwide priority Queue
3156 * triggers this function.
3158 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3159 * to cellwide priority Queues.
3161 * @param[in] RgSchUeCb* ue
3162 * @param[in] RgSchDlLcCb* svc
3166 static Void rgSCHSc1DlAdd2UeLcsWithData(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3170 RgSchCmnDlSvc *cmnDlSvc = RG_SCH_CMN_GET_DL_SVC(svc);
3171 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3172 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3173 RgSchCmnDlSvc *cmnDlLstSvc;
3176 lst = &(sc1DlUe->lcsWithData);
3180 cmnDlLstSvc = RG_SCH_CMN_GET_DL_SVC(((RgSchDlLcCb *)(node->node)));
3181 if (cmnDlSvc->prio <= cmnDlLstSvc->prio)
3189 cmLListAdd2Tail(lst, &sc1DlSvc->lcWithDataLnk);
3190 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3195 cmLListInsCrnt(lst, &sc1DlSvc->lcWithDataLnk);
3196 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3203 * @brief This function adds a service to UE's list of lcsWithData.
3207 * Function: rgSCHSc1DlRmFrmUeLcsWithData
3208 * Purpose: 1. This is to maintain a snapshot view of the
3209 * DL SVCs distributions among the cellwide priority
3211 * 2. This snapshot view is maintained in the order
3212 * of priority of the SVCs with in UE.
3213 * 3. Addition of SVC to a cellwide priority Queue
3214 * triggers this function.
3216 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3217 * to cellwide priority Queues.
3219 * @param[in] RgSchUeCb* ue
3220 * @param[in] RgSchDlLcCb* svc
3224 static Void rgSCHSc1DlRmFrmUeLcsWithData(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3226 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3227 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3230 cmLListDelFrm(&(sc1DlUe->lcsWithData), &sc1DlSvc->lcWithDataLnk);
3231 sc1DlSvc->lcWithDataLnk.node = NULLP;
3234 /***************** SC1 DL SCHEDULER FUNCTION DEFNs END HERE ****************/
3236 /***************************************************************************/
3238 /***************** SC1 UL SCHEDULER FUNCTION DEFNs START HERE **************/
3240 /*--------------------------*
3241 * UL specific functions START
3242 *---------------------------*/
3245 * @brief UE Lc Config for RR
3249 * Function : rgSCHSc1UlLchCfg
3251 * Processing Steps: Dummy function
3253 * @param[in] RgrSchCellCb *cell
3254 * @param[in] RgSchUeCb *ue
3255 * @param[in] RgrLchCfg *cfg
3256 * @param[in] RgSchErrInfo *err
3260 S16 rgSCHSc1UlLchCfg
3271 * @brief UE Lc Reconfig for RR
3275 * Function : rgSCHSc1UlLchRecfg
3277 * Processing Steps: Dummy function
3279 * @param[in] RgrSchCellCb *cell
3280 * @param[in] RgSchUeCb *ue
3281 * @param[in] RgrLchRecfg *recfg
3282 * @param[in] RgSchErrInfo *err
3286 S16 rgSCHSc1UlLchRecfg
3297 * @brief LC deletion for PFS
3301 * Function : rgSCHSc1UlLchDel
3303 * Processing Steps: Dummy function
3305 * @param[in] RgrSchCellCb *cell
3306 * @param[in] RgSchUeCb *ue
3307 * @param[in] CmLteLcId lcId
3311 S16 rgSCHSc1UlLchDel(RgSchCellCb *cell,RgSchUeCb *ue,CmLteLcId lcId,uint8_t lcgId)
3317 * @brief This function initializes all the data for the scheduler
3321 * Function: rgSCHSc1UlInit
3322 * Purpose: This function initializes the following information
3323 * 1. Efficiency table
3324 * 2. CQI to table index - It is one row for upto 3 RBs
3325 * and another row for greater than 3 RBs
3327 * currently extended prefix is compiled out.
3328 * Invoked by: MAC intialization code..may be ActvInit
3333 Void rgSCHSc1UlInit(RgUlSchdApis *rgSchUlApis)
3335 /* Init the function pointers */
3336 rgSchUlApis->rgSCHRgrUlUeCfg = rgSCHSc1RgrUlUeCfg;
3337 rgSchUlApis->rgSCHRgrUlUeRecfg = rgSCHSc1RgrUlUeRecfg;
3338 rgSchUlApis->rgSCHFreeUlUe = rgSCHSc1UlUeDel;
3339 rgSchUlApis->rgSCHRgrUlCellCfg = rgSCHSc1RgrUlCellCfg;
3340 rgSchUlApis->rgSCHRgrUlCellRecfg = rgSCHSc1RgrUlCellRecfg;
3341 rgSchUlApis->rgSCHFreeUlCell = rgSCHSc1UlCellDel;
3342 rgSchUlApis->rgSCHRgrUlLcCfg = rgSCHSc1UlLchCfg;
3343 rgSchUlApis->rgSCHRgrUlLcRecfg = rgSCHSc1UlLchRecfg;
3344 rgSchUlApis->rgSCHRgrUlLcgCfg = rgSCHSc1RgrLcgCfg;
3345 rgSchUlApis->rgSCHRgrUlLcgRecfg = rgSCHSc1RgrLcgRecfg;
3346 rgSchUlApis->rgSCHFreeUlLcg = rgSCHSc1LcgDel;
3347 rgSchUlApis->rgSCHRgrUlLchDel = rgSCHSc1UlLchDel;
3348 rgSchUlApis->rgSCHUlSched = rgSCHSc1UlSched;
3349 rgSchUlApis->rgSCHUpdBsrShort = rgSCHSc1UpdBsrShort;
3350 rgSchUlApis->rgSCHUpdBsrTrunc = rgSCHSc1UpdBsrTrunc;
3351 rgSchUlApis->rgSCHUpdBsrLong = rgSCHSc1UpdBsrLong;
3352 rgSchUlApis->rgSCHContResUlGrant = rgSCHSc1ContResUlGrant;
3353 rgSchUlApis->rgSCHSrRcvd = rgSCHSc1SrRcvd;
3354 rgSchUlApis->rgSCHUlCqiInd = rgSCHSc1UlCqiInd;
3355 rgSchUlApis->rgSCHUlUeRefresh = rgSCHSc1UlUeRefresh;
3356 rgSchUlApis->rgSCHUlAllocFnlz = rgSCHSc1UlAllocFnlz;
3357 rgSchUlApis->rgSCHUlInactvtUes = rgSCHSc1UlHndlInActUes;
3358 rgSchUlApis->rgSCHUlActvtUe = rgSCHSc1UlActvtUe;
3359 rgSchUlApis->rgSCHUlUeReset = rgSCHSc1UlUeReset;
3360 rgSchUlApis->rgSCHRgrUlLcgUpd = rgSCHSc1UlLcgUpd;
3365 * @brief UE initialisation for scheduler
3369 * Function : rgSCHSc1RgrUlUeCfg
3371 * This functions intialises UE specific scheduler
3374 * @param[in] RgSchCellCb *cell
3375 * @param[in] RgSchUeCb *ue
3376 * @param[int] RgrUeCfg *ueCfg
3377 * @param[out] RgSchErrInfo *err
3382 S16 rgSCHSc1RgrUlUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg,RgSchErrInfo *err)
3385 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
3387 if(rgSCHUtlAllocSBuf(cell->instIdx,
3388 (Data**)&(ueSchCmn->ul.schSpfc), (sizeof(RgSchSc1UlUe))) != ROK)
3390 RLOG_ARG1(L_ERROR,DBG_CELLID,cell->cellId,
3391 "Memory allocation FAILED CRNTI:%d",ue->ueId);
3392 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
3397 } /* rgSCHSc1RgrUlUeCfg */
3400 * @brief UE reconfiguration for scheduler
3404 * Function : rgSCHSc1RgrUlUeRecfg
3406 * This functions updates UE specific scheduler
3407 * information upon UE reconfiguration
3409 * @param[in] RgSchCellCb *cell
3410 * @param[in] RgSchUeCb *ue
3411 * @param[int] RgrUeRecfg *ueRecfg
3412 * @param[out] RgSchErrInfo *err
3417 S16 rgSCHSc1RgrUlUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
3420 } /* rgSCHSc1RgrUeRecfg */
3423 * @brief UE deletion for scheduler
3427 * Function : rgSCHSc1UlUeDel
3429 * This functions deletes all scheduler information
3430 * pertaining to a UE
3432 * @param[in] RgSchCellCb *cell
3433 * @param[in] RgSchUeCb *ue
3436 Void rgSCHSc1UlUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
3438 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3439 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3446 if(ueUl->txLnk.node)
3448 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3449 ueUl->txLnk.node = NULLP;
3451 if(ueUl->contResLnk.node)
3453 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
3454 ueUl->contResLnk.node = NULLP;
3456 /* ccpu00117052 - MOD - Passing double pointer
3457 for proper NULLP assignment*/
3458 rgSCHUtlFreeSBuf(cell->instIdx,
3459 (Data**)(&(ueUl)), (sizeof(RgSchSc1UlUe)));
3462 } /* rgSCHSc1UlUeDel */
3465 * @brief UE Reset for scheduler
3469 * Function : rgSCHSc1UlUeReset
3471 * Remove this UE from all Scheduling Priority Qs
3473 * @param[in] RgSchCellCb *cell
3474 * @param[in] RgSchUeCb *ue
3477 Void rgSCHSc1UlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
3479 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3480 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3483 ueUl->srRcvd = FALSE;
3485 if(ueUl->txLnk.node)
3487 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3488 ueUl->txLnk.node = NULLP;
3490 if(ueUl->contResLnk.node)
3492 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
3493 ueUl->contResLnk.node = NULLP;
3496 } /* rgSCHSc1UlUeReset */
3500 * @brief Scheduler processing on cell configuration
3504 * Function : rgSCHSc1RgrUlCellCfg
3506 * This function does requisite initialisation
3507 * and setup for scheduler1 when a cell is
3510 * @param[in] RgSchCellCb *cell
3511 * @param[in] RgrCellCfg *cellCfg
3512 * @param[out] RgSchErrInfo *err
3517 S16 rgSCHSc1RgrUlCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
3519 RgSchSc1UlCell *cellUl;
3521 if((rgSCHUtlAllocSBuf(cell->instIdx,
3522 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->ul.schSpfc), \
3523 (sizeof(RgSchSc1UlCell))) != ROK))
3525 RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,
3526 "Memory allocation FAILED");
3527 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
3530 cellUl = RG_GET_SC1_CELL_UL(cell);
3531 cmLListInit(&cellUl->contResLst);
3532 cmLListInit(&cellUl->ueTxLst[0]);
3533 cmLListInit(&cellUl->ueTxLst[1]);
3536 } /* rgSCHSc1RgrUlCellCfg */
3540 * @brief This function handles the reconfiguration of cell
3544 * Function: rgSCHSc1RgrUlCellRecfg
3545 * Purpose: Update the reconfiguration parameters.
3547 * Invoked by: Scheduler
3549 * @param[in] RgSchCellCb* cell
3553 S16 rgSCHSc1RgrUlCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
3559 * @brief Scheduler processing for cell delete
3563 * Function : rgSCHSc1UlCellDel
3565 * This functions de-initialises and frees memory
3566 * taken up by scheduler1 for the entire cell.
3568 * @param[in] RgSchCellCb *cell
3571 Void rgSCHSc1UlCellDel(RgSchCellCb *cell)
3573 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3576 if (cellUl == NULLP)
3580 /* ccpu00117052 - MOD - Passing double pointer
3581 for proper NULLP assignment*/
3582 rgSCHUtlFreeSBuf(cell->instIdx,
3583 (Data**)(&(cellUl)), (sizeof(RgSchSc1UlCell)));
3586 } /* rgSCHSc1UlCellDel */
3589 * @brief Scheduler invocation on logical channel Group addition
3593 * Function : rgSCHSc1RgrLcgCfg
3595 * This functions does required processing when a new
3596 * (dedicated) logical channel is added. Assumes lcg
3597 * pointer in ulLc is set.
3599 * @param[in] RgSchCellCb *cell
3600 * @param[in] RgSchUeCb *ue
3601 * @param[in] RgSchLcgCb *lcg
3602 * @param[int] RgrLcgCfg *lcgCfg
3603 * @param[out] RgSchErrInfo *err
3608 S16 rgSCHSc1RgrLcgCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,RgrLcgCfg *lcgCfg,RgSchErrInfo *err)
3611 } /* rgSCHSc1RgrLcgCfg */
3614 * @brief Scheduler invocation on logical channel addition
3618 * Function : rgSCHSc1RgrLcgRecfg
3620 * This functions does required processing when an existing
3621 * (dedicated) logical channel is reconfigured. Assumes lcg
3622 * pointer in ulLc is set to the old value.
3623 * Independent of whether new LCG is meant to be configured,
3624 * the new LCG scheduler info is accessed and possibly modified.
3626 * @param[in] RgSchCellCb *cell,
3627 * @param[in] RgSchUeCb *ue,
3628 * @param[in] RgSchLcgCb *lcg,
3629 * @param[in] RgrLcgRecfg *reCfg,
3630 * @param[out] RgSchErrInfo *err
3635 S16 rgSCHSc1RgrLcgRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,RgrLcgRecfg *reCfg,RgSchErrInfo *err)
3638 } /* rgSCHSc1RgrLcgRecfg */
3640 /***********************************************************
3642 * Func : rgSCHSc1LcgDel
3644 * Desc : Scheduler handling for a (dedicated)
3645 * uplink lcg being deleted
3653 **********************************************************/
3654 Void rgSCHSc1LcgDel(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg)
3656 rgSCHSc1UlPosnUeInQ(cell, ue);
3661 * @brief Perform alloction for this UE
3665 * Function : rgSCHSc1UlSchdUe
3667 * Processing Steps: cater to as much as UE needs, with
3668 * a limitation on maxBits per scheduling instance(per TTI)
3669 * per UE. Return failure, if UE is not considered
3670 * for scheduling (case, where it is already selected for a
3674 * @param[in] RgSchUeCb *ue
3677 static Void rgSCHSc1UlSchdUe(RgSchUeCb *ue,RgSchCellCb *cell)
3679 RgSchCmnUlUe *cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
3680 /*cell added as part of CA dev*/
3681 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
3684 if(ulUe->srRcvd == TRUE)
3686 cmnUlUe->alloc.reqBytes = RGSCH_MAX(RG_SCH_CMN_UL_SR_BYTES, \
3691 cmnUlUe->alloc.reqBytes = ue->ul.effBsr;
3697 * @brief Scheduler invocation
3701 * Function: rgSCHSc1UlSchdForDataTrans
3702 * Purpose: Uplink Scheduling for UE data Transmission.
3705 * Invoked by: Scheduler
3707 * @param[in] RgSchCellCb *cell
3708 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3709 * @param[in] uint8_t remUe
3712 static Void rgSCHSc1UlSchdForDataTrans(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t remUe)
3714 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
3720 /* Allocate UEs with LCG0 data pending */
3721 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[0], allocInfo, &remUe);
3727 /* Allocate UEs with other LCGs data pending */
3728 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[1], allocInfo, &remUe);
3734 * @brief Scheduler invocation
3738 * Function: rgSCHSc1UlSchdUeTxLst
3739 * Purpose: Uplink Scheduling for UE data Transmission.
3742 * Invoked by: Scheduler
3744 * @param[in] CmLListCp *ueTxLst
3745 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3746 * @param[in] uint8_t *remUe
3749 static Void rgSCHSc1UlSchdUeTxLst(RgSchCellCb *cell,CmLListCp *ueTxLst,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t *remUe)
3754 Bool ulAllowed = FALSE;
3758 node = ueTxLst->first;
3759 while ((node) && (*remUe))
3761 ue = (RgSchUeCb *)node->node;
3766 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
3767 if (ulAllowed == FALSE)
3774 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
3776 /* UE already scheduled in this subframe (for retx)
3777 * OR is inactive for UL Transmission.*/
3780 /* Added support for SPS*/
3782 else if (RG_SCH_CMN_IS_SPS_SCHD(ue, cell))
3784 /*-- Already Scheduled by SPS --*/
3789 rgSCHSc1UlSchdUe(ue,cell);/*cell added as part of CA dev*/
3791 rgSCHCmnUlAdd2UeLst(cell, allocInfo, ue);
3800 * @brief Scheduler invocation
3804 * Function: rgSCHSc1UlSchdForContRes
3805 * Purpose: Uplink Scheduling for Contention Resolution.
3808 * Invoked by: Scheduler
3810 * @param[in] RgSchCellCb *cell
3811 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3812 * @param[out] uint8_t *remUe
3815 static Void rgSCHSc1UlSchdForContRes(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t *remUe)
3817 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
3820 RgSchCmnUlUe *cmnUlUe;
3822 Bool ulAllowed = FALSE;
3826 node = sc1UlCell->contResLst.first;
3827 while ((node) && (*remUe))
3829 ue = (RgSchUeCb *)node->node;
3830 cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
3831 /*cell added as part of CA dev*/
3836 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
3837 if (ulAllowed == FALSE)
3843 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
3845 /* UE already scheduled in this subframe (for retx)
3846 * OR is inactive for UL Transmission.*/
3849 cmnUlUe->alloc.reqBytes = RG_SCH_CMN_MAX_UL_CONTRES_GRNT;
3850 rgSCHCmnUlAdd2CntResLst(allocInfo, ue);
3852 /* Node removal deferred to ULAllocFinalization */
3859 * @brief Scheduler invocation
3863 * Function: rgSCHSc1UlNewTx
3864 * Purpose: Uplink Scheduling for New Transmissions.
3867 * Invoked by: Scheduler
3869 * @param[in] RgSchCellCb *cell
3870 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3873 static Void rgSCHSc1UlNewTx(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
3875 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3876 uint8_t remUe = cellUl->maxUeNewTxPerTti;
3879 rgSCHSc1UlSchdForContRes(cell, allocInfo, &remUe);
3880 rgSCHSc1UlSchdForDataTrans(cell, allocInfo, remUe);
3885 * @brief Scheduler invocation
3889 * Function: rgSCHSc1UlSched
3890 * Purpose: This function implements an UL scheduler for LTE. This is
3891 * made available as a function pointer to be called
3892 * at the time of TTI processing by the MAC.
3894 * Invoked by: Common Scheduler (TTI processing)
3896 * @param[in] RgSchCellCb *cell
3897 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3900 Void rgSCHSc1UlSched(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
3902 rgSCHSc1UlNewTx(cell, allocInfo);
3907 * @brief UEs Buffer Status Has changed so reposition it.
3911 * Function : rgSCHSc1UlInsUeInQ
3913 * In UE in the list in Descending order of effBsr.
3916 * @param[in] CmLListCp *lst
3917 * @param[in] RgSchUeCb *ue
3920 static Void rgSCHSc1UlInsUeInQ(CmLListCp *lst,RgSchUeCb *ue,RgSchCellCb *cell)
3922 /*cell added as part of CA dev*/
3923 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3931 lUe = (RgSchUeCb *)(node->node);
3932 if (lUe->ul.effBsr <= ue->ul.effBsr)
3940 /* We have come to the end of the queue, so Append */
3941 cmLListAdd2Tail(lst, &ueUl->txLnk);
3942 ueUl->txLnk.node = (PTR)ue;
3947 cmLListInsCrnt(lst, &ueUl->txLnk);
3948 ueUl->txLnk.node = (PTR)ue;
3954 * @brief UEs Buffer Status Has changed so reposition it.
3958 * Function : rgSCHSc1UlPosnUeInQ
3960 * -Ues bs value for its LCG has changed, due to either
3961 * allocation or BSR report OR the effUeBR, i.e the byteRate
3962 * has changed due to some allocation, so add/reposition/remove
3963 * it from Qs based on this new bs and/or effUeBR value.
3964 * -If UE has non-zero lcg0 bs value, but the byteRate is
3965 * consumed totally, UE is still schedulable for this control data.
3966 * -If UE's LCG0 has pending bs then position this UE in
3968 * -If Ue has pending BSR to be satisfied, but lcg0's BS
3969 * is 0, then position it in ueTxLst[1].
3970 * -In any of these 2 Qs, insertion is such that UEs are
3971 * positioned in Descending order of their Pending BS.
3974 * @param[in] RgSchCellCb *cell
3975 * @param[in] RgSchUeCb *ue
3978 static Void rgSCHSc1UlPosnUeInQ(RgSchCellCb *cell,RgSchUeCb *ue)
3980 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3981 /*cell added as part of CA dev*/
3982 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3983 RgSchCmnLcg *cmnLcg0 = RG_SCH_CMN_GET_UL_LCG(&ue->ul.lcgArr[0]);
3987 if (!RG_SCH_CMN_UL_IS_UE_ACTIVE(ue))
3992 /* Remove the UE from its existing position */
3993 if (ueUl->txLnk.node)
3995 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3996 ueUl->txLnk.node = (PTR)NULLP;
3998 /* If UE has still bs left for scheduling
3999 * then reposition it */
4000 if ((ue->ul.effBsr > 0) || (ueUl->srRcvd == TRUE))
4002 /* Select the Queue where UE would be Placed */
4003 if (cmnLcg0->bs > 0)
4005 lst = &cellUl->ueTxLst[0];
4010 lst = &cellUl->ueTxLst[1];
4013 /* Insert the UE in the Q */
4014 rgSCHSc1UlInsUeInQ(lst, ue, cell);/*cell added as part of CA dev*/
4017 else if(ue->ul.totalBsr != 0)
4019 if (ue->bsrTmr.tmrEvnt != TMR_NONE)
4021 rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue);
4023 if (ue->ul.bsrTmrCfg.isPrdBsrTmrPres)
4025 rgSCHTmrStartTmr(cell, ue, RG_SCH_TMR_BSR,
4026 ue->ul.bsrTmrCfg.prdBsrTmr);
4035 * @brief Short BSR update
4039 * Function : rgSCHSc1UpdBsrShort
4041 * This functions does requisite updates to handle short BSR reporting
4043 * @param[in] RgSchCellCb *cell
4044 * @param[in] RgSchUeCb *ue
4045 * @param[in] RgSchLcgCb *lcg
4046 * @param[in] uint8_t bsr
4049 Void rgSCHSc1UpdBsrShort(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,uint8_t bsr)
4051 rgSCHSc1UlPosnUeInQ(cell, ue);
4053 } /* rgSCHSc1UpdBsrShort */
4056 * @brief Truncated BSR update
4060 * Function : rgSCHSc1UpdBsrTrunc
4062 * This functions does required updates to handle truncated BSR report
4065 * @param[in] RgSchCellCb *cell
4066 * @param[in] RgSchUeCb *ue
4067 * @param[in] RgSchLcgCb *lcg
4068 * @param[in] uint8_t bsr
4071 Void rgSCHSc1UpdBsrTrunc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,uint8_t bsr)
4073 rgSCHSc1UlPosnUeInQ(cell, ue);
4075 } /* rgSCHSc1UpdBsrTrunc */
4078 * @brief Long BSR update
4082 * Function : rgSCHSc1UpdBsrLong
4084 * - Update UE's position within/across uplink scheduling queues
4087 * @param[in] RgSchCellCb *cell
4088 * @param[in] RgSchUeCb *ue
4089 * @param[in] uint8_t bsArr[]
4092 Void rgSCHSc1UpdBsrLong(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t *bsArr)
4094 rgSCHSc1UlPosnUeInQ(cell, ue);
4096 } /* rgSCHSc1UpdBsrLong */
4099 * @brief UL grant for contention resolution
4103 * Function : rgSCHSc1ContResUlGrant
4105 * Add UE to another queue specifically for CRNTI based contention
4109 * @param[in] RgSchCellCb *cell
4110 * @param[in] RgSchUeCb *ue
4113 Void rgSCHSc1ContResUlGrant(RgSchCellCb *cell,RgSchUeCb *ue)
4115 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4116 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4119 if (ueUl->contResLnk.node)
4124 /* Remove the UE from other Qs */
4125 if(ueUl->txLnk.node)
4127 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
4128 ueUl->txLnk.node = NULLP;
4131 cmLListAdd2Tail(&cellUl->contResLst, &ueUl->contResLnk);
4132 ueUl->contResLnk.node = (PTR)ue;
4134 } /* rgSCHSc1ContResUlGrant */
4137 * @brief SR reception handling
4141 * Function : rgSCHSc1SrRcvd
4142 * Shift the UE with SrInd in to the lcgO queue.
4145 * @param[in] RgSchCellCb *cell
4146 * @param[in] RgSchUeCb *ue
4149 Void rgSCHSc1SrRcvd(RgSchCellCb *cell,RgSchUeCb *ue)
4151 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
4152 RgSchSc1UlCell *ulCell = RG_GET_SC1_CELL_UL(cell);
4155 ulUe->srRcvd = TRUE;
4157 if (ulUe->txLnk.node != NULLP)
4161 /* Already present in lcg0 Q */
4164 cmLListDelFrm(&(ulCell->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
4166 /* Adding the UE to the LCG0 list for SR IND */
4167 cmLListAdd2Tail(&ulCell->ueTxLst[0], &ulUe->txLnk);
4168 ulUe->txLnk.node = (PTR)ue;
4172 } /* rgSCHSc1SrRcvd */
4175 * @brief Indication of UL CQI
4179 * Function : rgSCHSc1UlCqiInd
4181 * - Common Scheduler. SC1 does nothing.
4183 * @param[in] RgSchCellCb *cell
4184 * @param[in] RgSchUeCb *ue
4185 * @param[in] TfuUlCqiRpt *ulCqiInfo
4188 Void rgSCHSc1UlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuUlCqiRpt *ulCqiInfo)
4191 /* Stack Crash problem for TRACE5 changes. Added the return below */
4197 * @brief UL Lcg received data updation
4201 * Function : rgSCHSc1UlLcgUpd
4203 * Processing Steps:Sc1 Does nothing
4205 * @param[in] RgSchCellCb *cell
4206 * @param[in] RgSchUeCb *ue
4207 * @param[in] RgInfUeDatInd *datInd
4210 S16 rgSCHSc1UlLcgUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgInfUeDatInd *datInd)
4217 /***********************************************************
4219 * Func : rgSCHSc1UlUeRefresh
4221 * Desc : Handle 'refresh' for uplink part of a UE
4222 * (ie UE's uplink AMBR and uplink GBR LCGs are
4223 * refreshed at this point)
4231 **********************************************************/
4232 Void rgSCHSc1UlUeRefresh(RgSchCellCb *cell,RgSchUeCb *ue)
4234 rgSCHSc1UlPosnUeInQ(cell, ue);
4239 * @brief This function Processes the Final Allocations
4240 * made by the RB Allocator against the requested
4241 * UE data Trans Allocations.
4245 * Function: rgSCHSc1UlDatTransAllocFnlz
4246 * Purpose: This function Processes the Final Allocations
4247 * made by the RB Allocator against the requested
4248 * UE data Trans Allocations .
4250 * Invoked by: Scheduler
4252 * @param[in] RgSchCellCb *cell
4253 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4257 static Void rgSCHSc1UlDatTransAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4262 RgSchDrxUeCb *drxUe = NULLP;
4263 CmLListCp ulInactvLst; /* list of UE's becoming UL-inactive */
4265 cmLListInit(&ulInactvLst);
4266 node = allocInfo->schdUeLst.first;
4269 ue = (RgSchUeCb *)node->node;
4271 ueUl = RG_GET_SC1_UE_UL(ue, cell);
4273 if (ue->isDrxEnabled)
4275 if(ueUl->srRcvd == TRUE)
4277 drxUe = RG_SCH_DRX_GET_UE(ue);
4278 drxUe->drxUlInactvMask |= RG_SCH_DRX_SR_BITMASK;
4280 if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
4282 ue->ul.ulInactvMask |= RG_DRX_INACTIVE;
4283 /* Add to Ul inactive List */
4284 ue->ulDrxInactvLnk.node = (PTR)ue;
4285 cmLListAdd2Tail(&ulInactvLst,&(ue->ulDrxInactvLnk));
4287 drxUe->srRcvd = FALSE;
4290 /* Reset no matter */
4291 ueUl->srRcvd = FALSE;
4292 /* Reposition UE in Qs */
4293 rgSCHSc1UlPosnUeInQ(cell, ue);
4297 rgSCHCmnHdFddUpdULMark (cell,ue);
4300 /* reset the UE UL allocation Information */
4301 rgSCHCmnUlUeResetTemp(cell, ue);
4303 rgSCHSc1UlHndlInActUes(cell, &ulInactvLst);
4304 node = allocInfo->nonSchdUeLst.first;
4307 ue = (RgSchUeCb *)node->node;
4309 /* reset the UE UL allocation Information */
4310 rgSCHCmnUlUeResetTemp(cell, ue);
4317 * @brief This function Processes the Final Allocations
4318 * made by the RB Allocator against the requested
4319 * cont res Allocations.
4323 * Function: rgSCHSc1UlContResAllocFnlz
4324 * Purpose: This function Processes the Final Allocations
4325 * made by the RB Allocator against the requested
4326 * cont res Allocations .
4328 * Invoked by: Scheduler
4330 * @param[in] RgSchCellCb *cell
4331 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4335 static Void rgSCHSc1UlContResAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4337 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
4342 node = allocInfo->schdContResLst.first;
4345 ue = (RgSchUeCb *)node->node;
4350 rgSCHCmnHdFddUpdULMark (cell,ue);
4353 ueUl = RG_GET_SC1_UE_UL(ue, cell);
4355 /* Remove UE from Cont Res Q */
4356 cmLListDelFrm(&sc1UlCell->contResLst,
4358 ueUl->contResLnk.node = NULLP;
4359 /* reset the UE UL allocation Information */
4360 rgSCHCmnUlUeResetTemp(cell, ue);
4363 node = allocInfo->nonSchdContResLst.first;
4366 ue = (RgSchUeCb *)node->node;
4368 /* reset the UE UL allocation Information */
4369 rgSCHCmnUlUeResetTemp(cell, ue);
4376 * @brief This function Processes the Final Allocations
4377 * made by the RB Allocator against the requested.
4381 * Function: rgSCHSc1UlAllocFnlz
4382 * Purpose: This function Processes the Final Allocations
4383 * made by the RB Allocator against the requested.
4385 * Invoked by: Common Scheduler
4387 * @param[in] RgSchCellCb *cell
4388 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4392 Void rgSCHSc1UlAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4395 rgSCHSc1UlContResAllocFnlz(cell, allocInfo);
4396 rgSCHSc1UlDatTransAllocFnlz(cell, allocInfo);
4403 * @brief Scheduler invocation
4407 * Function: rgSCHSc1UlActvtUe
4408 * Purpose: Put back the UE in to appropriate Qs.
4410 * Invoked by: Common Scheduler
4412 * @param[in] RgSchCellCb *cell
4413 * @param[in] RgSchUeCb *ue
4416 Void rgSCHSc1UlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
4419 rgSCHSc1UlPosnUeInQ(cell, ue);
4424 * @brief Scheduler invocation
4428 * Function: rgSCHSc1UlHndlInActUes
4429 * Purpose: The list of inactive UEs present in inactvLst should
4430 * be removed from the scheduling Qs.
4431 * But store the information pertaining to which Qs,
4432 * were they belonging to. This information shall be used
4433 * to put them back in appropriate Qs when their Activation
4436 * Invoked by: Common Scheduler (TTI processing)
4438 * @param[in] RgSchCellCb *cell
4439 * @param[out] CmLListCp *inactvLst
4442 Void rgSCHSc1UlHndlInActUes(RgSchCellCb *cell,CmLListCp *inactvLst)
4446 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4447 CmLList *node = inactvLst->first;
4451 ue = (RgSchUeCb *)node->node;
4453 ulUe = RG_GET_SC1_UE_UL(ue, cell);
4454 if(ulUe->txLnk.node)
4456 cmLListDelFrm(&(cellUl->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
4457 /* This is required as lcg bs might change during
4458 * inactivity to activity. So we need to recompute
4460 ulUe->txLnk.node = NULLP;
4462 /* Do not remove UE from contResLst */
4467 * @brief Scheduler invocation
4471 * Function: rgSCHSc1DlProcRmvFrmRetx
4472 * Purpose: To remove the Harq process from the cell and from the UE
4473 * retransmission list
4475 * Invoked by: Common Scheduler (TTI processing)
4477 * @param[in] RgSchCellCb *cell
4478 * @param[in] RgSchUeCb *ue;
4479 * @param[in] RgSchDlHqProcCb *hqP
4483 Void rgSCHSc1DlProcRmvFrmRetx(
4486 RgSchDlHqProcCb *hqP
4490 /* Remove the HqP from retx Queue.
4492 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
4493 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
4500 /**********************************************************************
4503 **********************************************************************/