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.
36 /* header include files -- defines (.h) */
37 #include "common_def.h"
43 #include "rg_sch_inf.h"
44 #include "rg_sch_err.h"
46 #include "rg_sch_cmn.h"
47 #include "rg_sch_sc1.h"
48 #include "rl_interface.h"
49 #include "rl_common.h"
51 /* header/extern include files (.x) */
52 #include "tfu.x" /* RGU types */
53 #include "lrg.x" /* layer management typedefs for MAC */
54 #include "rgr.x" /* layer management typedefs for MAC */
55 #include "rgm.x" /* layer management typedefs for MAC */
56 #include "rg_sch_inf.x" /* typedefs for Scheduler */
57 #include "rg_sch.x" /* typedefs for Scheduler */
58 #include "rg_sch_cmn.x"
59 #include "rg_sch_sc1.x" /* typedefs for SC1 Scheduler */
66 #endif /* __cplusplus */
68 /* Functions called from outside */
69 static S16 rgSCHSc1RgrDlCellRecfg ARGS((
75 /*--------------------------*
76 * DL SCHED STATIC declarations START
77 *---------------------------*/
78 static Void rgSCHSc1DlSvcAddToSchd ARGS((
82 static Void rgSCHSc1DlAdd2UeSchdSvcs ARGS((
87 static Void rgSCHSc1DlRmvUeFrmPrioQs ARGS((
91 static Void rgSCHSc1DlSuspendUe ARGS((
95 static Void rgSCHSc1DlInactvtUe ARGS((
99 static Void rgSCHSc1DlProcRmvFrmCellRetx ARGS((
103 static Void rgSCHSc1DlProcRmvFrmUeRetx ARGS((
108 static Void rgSCHSc1DlMngPrio0SvcPosn ARGS((
113 static Void rgSCHSc1DlMngGbrSvcPosn ARGS((
118 static Void rgSCHSc1DlMngAmbrSvcPosn ARGS((
123 static Void rgSCHSc1DlMngSvcPosn ARGS((
128 static Void rgSCHSc1DlUeAddToSchd ARGS((
132 static Void rgSCHSc1DlTaCmd ARGS((
134 RgSchCmnDlRbAllocInfo *allocInfo
136 static Void rgSCHSc1DlInitQueues ARGS((
137 RgSchSc1DlCell *cellDl
139 static Void rgSCHSc1DlDeinitQueues ARGS((
140 RgSchSc1DlCell *cellDl
142 static Void rgSCHSc1DlAdd2UeLcsWithData ARGS((
147 static Void rgSCHSc1DlRmFrmUeLcsWithData ARGS((
152 /*--------------------------*
153 * UL SCHED STATIC declarations START
154 *---------------------------*/
155 static Void rgSCHSc1UlPosnUeInQ ARGS((
159 static Void rgSCHSc1UlSchdUeTxLst ARGS((
162 RgSchCmnUlRbAllocInfo *allocInfo,
165 static Void rgSCHSc1DlProcRmvFrmRetx ARGS((
170 Void rgSCHSc1DlScanUpdPdbPrio ARGS((
173 S16 rgSCHSc1DlFillFlowCntrlInfo ARGS((
175 RgInfSfAlloc *sfAlloc
178 static Void rgSCHSc1DlPreSchd ARGS ((
181 static Void rgSCHSc1DlPstSchd ARGS ((
186 #endif /* __cplusplus */
191 /***************** SC1 DL SCHEDULER FUNCTION DEFNs START HERE ********/
193 /***********************************************************
195 * Func : rgSCHSc1DlUeReset
197 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
198 * and Svc in respective Prio Qs.
207 **********************************************************/
208 Void rgSCHSc1DlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
211 rgSCHSc1DlSuspendUe(cell, ue);
217 /***********************************************************
219 * Func : rgSCHSc1DlActvtUe
221 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
222 * and Svc in respective Prio Qs.
231 **********************************************************/
232 Void rgSCHSc1DlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
234 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
237 RgSchDlHqProcCb *hqP;
241 /* Add UE's HqProcs From UERetxLst to CellRetxLst */
242 lst = &ueDl->retxHqProcs;
246 hqP = (RgSchDlHqProcCb *)node->node;
248 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
249 rgSCHSc1DlProcAddToCellRetx(cell, hqP);
252 /* Iterate over all the Services if bo != 0 then add */
253 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
255 svc = ue->dl.lcCb[idx];
260 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
263 /* Add UE to AMBR Prio Q */
266 rgSCHSc1DlUeAddToSchd(cell, ue);
273 /***********************************************************
275 * Func : rgSCHSc1DlUeRefresh
277 * Desc : Handle 'refresh' for Downlink
278 * (ie UE's downlink AMBR and downlink GBR LCGs are
279 * refreshed at this point)
287 **********************************************************/
288 Void rgSCHSc1DlUeRefresh(RgSchCellCb *cell,RgSchUeCb *ue)
290 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
291 /*cell added as part of CA dev*/
292 RgSchCmnDlSvc *svcCmn;
293 RgSchSc1DlSvc *svcSc1;
300 ueDl->ambr = ue->dl.ambrCfgd;
304 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
307 if (ueDl->ambrSvc != NULLP)
309 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, ueDl->ambrSvc->bo);
310 /* Update UEs position in the Queue */
311 rgSCHSc1DlUeAddToSchd(cell, ue);
314 lst = &ueDl->gbrSvcs;
316 while (node != NULLP)
318 svc = (RgSchDlLcCb *)node->node;
319 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
320 svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
322 svcSc1->gbr = svcCmn->gbr;
323 svcSc1->mbr = svcCmn->mbr;
324 /* Update the SVC's positioning in the Queue */
325 rgSCHSc1DlMngGbrSvcPosn(cell, ue, svc);
332 * @brief This function removes a HARQ process from the retx
336 * Function: rgSCHSc1DlProcRmvFrmCellRetx
337 * Purpose: This function removes a HARQ process from retransmission
338 * queue. This may be performed when a HARQ ack is successful
339 * for a retransmission or when the scheduling determines
340 * to throw out the process due to poor conditions
342 * Invoked by: LIM and Scheduler
344 * @param[in] RgSchSc1Cb* cell
345 * @param[in] RgDlHqProc* hqP
349 static Void rgSCHSc1DlProcRmvFrmCellRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
351 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
352 RgSchCmnDlHqProc *hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
354 if (hqProcDl->retxLnk.node != NULLP)
356 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
357 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
358 hqProcDl->retxLnk.node = NULLP;
365 * @brief This function removes a HARQ process from the UE retx
369 * Function: rgSCHSc1DlProcRmvFrmUeRetx
370 * Purpose: This function removes a HARQ process from UE retransmission
373 * Invoked by: LIM and Scheduler
375 * @param[in] RgSchUeCb* ue
376 * @param[in] RgDlHqProc* hqP
380 static Void rgSCHSc1DlProcRmvFrmUeRetx(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
382 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
383 RgSchSc1DlHqProc *hqProcDl = RG_GET_SC1_HQP_DL(hqP);
385 if (hqProcDl->retxLnkUe.node != NULLP)
387 cmLListDelFrm(&sc1Ue->retxHqProcs,
388 &(hqProcDl->retxLnkUe));
389 hqProcDl->retxLnkUe.node = NULLP;
396 * @brief This function adds a HARQ process for UEs retxLst
400 * Function: rgSCHSc1DlProcAddToUeRetx
401 * Purpose: This function adds a HARQ process to UE retransmission
402 * queue. This is performed when UE is suspended due
403 * to measurement gap.
405 * Invoked by: HARQ feedback processing
407 * @param[in] RgSchUeCb* ue
408 * @param[in] RgSchDlHqProc* hqP
412 static Void rgSCHSc1DlProcAddToUeRetx(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
414 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
415 RgSchSc1DlHqProc *cmnHqDl = RG_GET_SC1_HQP_DL(hqP);
417 cmLListAdd2Tail(&sc1Ue->retxHqProcs,
418 &(cmnHqDl->retxLnkUe));
419 cmnHqDl->retxLnkUe.node = (PTR)hqP;
425 * @brief This function adds a HARQ process for retx
429 * Function: rgSCHSc1DlProcAddToCellRetx
430 * Purpose: This function adds a HARQ process to retransmission
431 * queue. This may be performed when a HARQ ack is
434 * Invoked by: HARQ feedback processing
436 * @param[in] RgSchCellCb* cell
437 * @param[in] RgSchDlHqProc* hqP
441 Void rgSCHSc1DlProcAddToCellRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
443 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
444 RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
447 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(hqP->hqE->ue))
449 rgSCHSc1DlProcAddToUeRetx(cell, hqP->hqE->ue, hqP);
452 cmLListAdd2Tail(&sc1CellDl->retxLst[((RgSchSc1DlHqProc *)\
453 (cmnHqDl->schSpfc))->prio], &(cmnHqDl->retxLnk));
454 cmnHqDl->retxLnk.node = (PTR)hqP;
460 * @brief This function implements DL RETRANSMISSION allocation
464 * Function: rgSCHSc1DlRetxAlloc
465 * Purpose: This function implements downlink scheduler's
466 * retransmission allocation.
468 * Invoked by: Scheduler
470 * @param[in] RgSchCellCb *cell
471 * @param[in] RgSchDlSf *subFrm
472 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
476 static Void rgSCHSc1DlRetxAlloc(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchCmnDlRbAllocInfo *allocInfo)
481 RgSchDlHqProcCb *hqP;
482 RgSchSc1DlCell *sc1CellDl;
483 RgSchSc1DlUe *sc1DlUe;
484 RgSchCmnDlUe *cmnUeDl;
485 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
486 CmLteTimingInfo schdTime;
489 RgSchUeCb *ue = NULLP;
491 Bool dlAllowed = FALSE;
493 RgSchDlRbAlloc *dlAllocCb;
495 sc1CellDl = RG_GET_SC1_CELL_DL(cell);
496 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
497 schdTime = cell->crntTime;
499 /* Increment by DL DELTA to determine the time for which scheduling
501 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
503 for (i = 0; i < RG_SCH_SC1_DL_PRIOS; i++)
505 retxLst = &sc1CellDl->retxLst[i];
506 /* allocate bw for the retransmission..should be same are previous */
507 /* If CQI gets worse, as we cannot find same TB size for another */
508 /* MCS, we just remove this from the retransmission queue */
509 node = retxLst->first;
510 while (node != NULLP)
512 hqP = (RgSchDlHqProcCb *)node->node;
517 if((0 == schdTime.slot) || (5 == schdTime.slot))
520 rgSCHCmnChkRetxAllowDtx(cell, ue, hqP, &reTxAllw);
521 if(FALSE == reTxAllw)
530 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
531 if (dlAllowed == FALSE)
537 /* This UE is already scheduled for transmission */
538 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
539 /*cell added as part of CA dev*/
541 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
546 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
551 /* Extra check: indicate if there is furtherScope for NewTx
552 * addition for a HqProc. This information will
553 * be utilized by common scheduler, in case of SM
554 * UEs with only one of the TBs retransmitting and the
555 * other TB can be used for clubbing new TX. */
556 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
557 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
558 if (sc1DlUe->lcsWithData.first != NULLP)
560 dlAllocCb->mimoAllocInfo.hasNewTxData = TRUE;
562 /* 3.1 MIMO : last parameter changed */
563 if (rgSCHCmnDlAllocRetxRb(cell, subFrm, ue, 0, &effBo, hqP, allocInfo) !=\
566 /* SF/RETX Bandwidth expired */
574 if ((hqP->tbInfo[0].state == HQ_TB_ACKED)
575 && (hqP->tbInfo[1].state == HQ_TB_ACKED))
577 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
582 /* 3.1 MIMO moving this call in cmn scheduler */
583 /*rgSCHCmnDlRbInfoAddUeRetx(allocInfo, ue);*/
589 /***********************************************************
591 * Func : rgSCHSc1RlsHqProc
593 * Desc : Toggles the NDI and releases the harq proc.
601 **********************************************************/
602 static Void rgSCHSc1RlsHqProc(RgSchDlHqProcCb *hqProc)
604 rgSCHDhmRlsHqProc(hqProc);
609 * @brief This function implements dedicated logical channel data scheduling
613 * Function: rgSCHSc1DlDedSvcAlloc
614 * Purpose: This function implements dedicated logical
615 * channel data scheduling
617 * Invoked by: Scheduler
619 * @param[in] RgSchCellCb *cell
620 * @param[in] RgSchDlSf *subFrm
621 * @param[in] RgSchDlLcCb *svc
622 * @param[in] uint32_t bo
623 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
627 static S16 rgSCHSc1DlDedSvcAlloc(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchDlLcCb *svc,uint32_t bo,RgSchCmnDlRbAllocInfo *allocInfo)
630 RgSchDlHqProcCb *proc;
631 uint16_t rlcHdrEstmt;
633 RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell);
634 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
635 RgSchSc1DlSvc *svcSc1;
637 RgSchSc1DlHqProc *sc1HqDl;
638 RgSchCmnDlHqProc *cmnHqDl;
640 CmLteTimingInfo schdTime;
643 Bool dlAllowed = FALSE;
648 /* Get the UE to which this service belongs to */
653 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
654 if (dlAllowed == FALSE)
660 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
661 /*cell added as part of CA dev*/
663 schdTime = cell->crntTime;
665 /* Increment by DL DELTA to determine the time for which scheduling
667 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
668 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
673 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
675 proc = (RgSchDlHqProcCb *)(ueDl->proc);
676 /* This UE is selected for retransmission. Hence no further */
677 /* scheduling may be done for this UE */
678 if (RG_SCH_CMN_PROC_SLCTD_FOR_RETX(proc))
680 DU_LOG("\nERROR --> SCH : CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
681 "Ue retransmitting",ue->ueId);
684 /* UE is scheduled for either other services or TA */
685 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
686 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
687 if (sc1HqDl->prio > svcCmn->prio)
689 sc1HqDl->prio = svcCmn->prio;
692 else /* First consideration of this UE for scheduling */
694 if (rgSCHDhmGetAvlHqProc(cell, ue, cmnCellDl->time, &proc) != ROK)
696 DU_LOG("\nERROR --> SCH : CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
697 " No HARQ Proc available", ue->ueId);
700 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
701 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
702 cmnHqDl->totBytes = 0;
703 /* Initialize some of the parameters of the HQ proc */
704 sc1HqDl->prio = svcCmn->prio;
707 /* Including each SDU's header size */
708 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
711 ret = rgSCHCmnDlAllocTxRb(cell, subFrm, ue, bo, &effBo, proc, allocInfo);
712 if ((ret != ROK) || (effBo == 0))
714 /* If no allocations so far, meaning proc obtained now */
715 if (cmnHqDl->totBytes == 0)
717 rgSCHSc1RlsHqProc(proc);
718 /* Added the handling for removing
719 * UE from txHqPLst and resetting outStndAlloc.*/
720 if(proc->reqLnk.node != (PTR)NULLP)
722 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
723 proc->reqLnk.node = (PTR)NULLP;
725 /*Re-set the outstanding alloc information.*/
726 ueDl->outStndAlloc = 0;
728 /* ccpu00126519: proc should be set to NULLP in UE's DL scratch pad info as well. */
733 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
734 svcSc1->hdrEstimate = rlcHdrEstmt;
735 svcSc1->reqBytes = bo;
737 cmnHqDl->totBytes += effBo;
739 rgSCHSc1DlAdd2UeSchdSvcs(cell, ue, svc);
740 /* 3.1 MIMO moving this call to cmn scheduler */
741 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue); */
746 * @brief This function adds a SVC to UE's schdSvcsLst.
750 * Function: rgSCHSc1DlAdd2UeSchdSvcs
751 * Purpose: This function adds a SVC to UE's schdSvcsLst.
753 * Invoked by: Specific Scheduler
755 * @param[out] RgSchUeCb *ue
756 * @param[in] RgSchDlLcCb *svc
760 static Void rgSCHSc1DlAdd2UeSchdSvcs(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
762 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
763 RgSchSc1DlUe *ueSc1 = RG_GET_SC1_UE_DL(ue, cell);
765 /* checking SVC's presence in this lst is unnecessary */
766 cmLListAdd2Tail(&ueSc1->schdSvcs, &svcSc1->schdSvcLnk);
767 svcSc1->schdSvcLnk.node = (PTR)svc;
773 * @brief This function performs new allocations for UEs
777 * Function: rgSCHSc1DlDedTx
778 * Purpose: This function implements scheduler for DL allocation for
779 * new transmissions of UEs.
780 * 1. It performs across 9 priorities that it supports -
781 * This is from 3GPP specifications
782 * 2. There are known number of GBR/MBR queues
783 * 3. The first queue is highest priority queue and is
784 * satisfied completely prior to any other queues. This
785 * queue is for RRC signalling.
786 * 4. Futher GBR/MBR queues are satisfied for GBR and then MBR
787 * 5. Subsequently all other queues are looked at for AMBR
789 * Invoked by: Scheduler
791 * @param[in] RgSchCellCb* cell
792 * @param[in] RgSchDlSf *subFrm
793 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
797 static Void rgSCHSc1DlDedTx(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchCmnDlRbAllocInfo *allocInfo)
801 RgSchUeCb *ue = NULLP;
804 RgSchSc1DlSvc *svcSc1;
806 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
809 /* Process the first queue that is for RRC signalling and is of */
810 /* highest priority. */
811 lst = &sc1CellDl->prioLst[0];
815 /* Getting service instead of UE */
816 svc = (RgSchDlLcCb *)node->node;
818 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
820 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->bo, allocInfo) != ROK)
827 /* Perform allocation for the GBR transmissions */
828 for(i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
830 lst = &sc1CellDl->prioLst[i];
834 /* Getting service instead of UE */
835 svc = (RgSchDlLcCb *)node->node;
837 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
839 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->effMbr, allocInfo) != ROK)
847 /* To implement AMBR svc scheduling */
848 for(i = RG_SCH_SC1_DL_GBR_PRIO_END + 1; i < RG_SCH_SC1_DL_PRIOS; i++)
850 lst = &sc1CellDl->prioLst[i];
854 ue = (RgSchUeCb *)node->node;
855 ueDl = RG_GET_SC1_UE_DL(ue, cell);
857 /* Get the Curr ambr svc for which allocation is to be made */
859 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, ueDl->effAmbr, allocInfo) != ROK)
870 * @brief scheduling for a cell
874 * Function : rgSCHSc1DlPreSchd
877 * - Nothing to be done in case of RR
879 * @param[in] Inst schInst
882 static Void rgSCHSc1DlPreSchd( RgSchCellCb *cell)
888 * @brief scheduling for a cell
892 * Function : rgSCHSc1DlPstSchd
895 * - Nothing to be done in case of RR
897 * @param[in] Inst schInst
900 static Void rgSCHSc1DlPstSchd(Inst schInst)
908 * @brief This function implements scheduler DL allocation
912 * Function: rgSCHSc1DlDedNewTx
913 * Purpose: This function implements scheduler for DL allocation for
916 * Invoked by: Scheduler
918 * @param[in] RgSchCellCb *cell
919 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
923 static Void rgSCHSc1DlDedNewTx(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
925 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
926 DU_LOG("\nDEBUG --> SCH : rgSCHSc1DlDedNewTx\n");
928 /* Now perform the new UE selections */
929 rgSCHSc1DlDedTx(cell, subFrm, allocInfo);
931 /* Stack Crash problem for TRACE5 changes. Added the return below */
936 * @brief This function implements scheduler DL allocation
940 * Function: rgSCHSc1DlDedRetx
941 * Purpose: This function implements scheduler for DL allocation for
944 * Invoked by: Scheduler
946 * @param[in] RgSchCellCb *cell
947 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
951 static Void rgSCHSc1DlDedRetx(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
953 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
954 DU_LOG("\nDEBUG --> SCH : rgSCHSc1DlDedRetx\n");
956 rgSCHSc1DlRetxAlloc(cell, subFrm, allocInfo);
965 * @brief This function adds a service to scheduler
969 * Function: rgSCHSc1DlSvcAddToSchd
970 * Purpose: This function adds a service to the list of services
971 * based on the priority of the services.
973 * Invoked by: BO and Scheduler
975 * @param[in] RgSchCellCb* cell
976 * @param[in] RgSchUeCb* ue
980 static Void rgSCHSc1DlSvcAddToSchd(RgSchCellCb *cell,RgSchDlLcCb *svc)
985 RgSchSc1DlSvc *svcSc1;
986 RgSchSc1DlSvc *lSvcSc1;
987 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
988 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
991 svcSc1 = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
992 /* The service is already in the scheduler */
993 if (svcSc1->prioLnk.node != NULLP)
998 /* If the priority = 0, it is the highest priority with infinite */
999 /* allowance and the priority is time bound and hence just place */
1000 /* it at the end of the queue */
1001 if (svcCmn->prio == 0)
1003 lst = &(sc1CellDl->prioLst[0]);
1004 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1005 svcSc1->prioLnk.node = (PTR)svc;
1006 /* If a svc is put in to cell wide priority Qs
1007 * then add the same to UE's lcsWithData List */
1008 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1012 /* Handle GBR services. We have them of next importance */
1013 /* check changed from .._START to .._END */
1014 if (svcCmn->prio <= RG_SCH_SC1_DL_GBR_PRIO_END)
1016 if (!RG_SC1_SVC_HAS_DATA(svc,cell))
1018 lst = &(sc1CellDl->prioLst[svcCmn->prio]);
1022 lSvc = (RgSchDlLcCb *)(node->node);
1023 lSvcSc1 = RG_GET_SC1_SVC_DL(lSvc->ue,lSvc,cell);
1024 if (((svcSc1->effGbr > 0) &&
1025 (lSvcSc1->effGbr <= svcSc1->effGbr)) ||
1026 ((lSvcSc1->effGbr == 0) && (svcSc1->effMbr > 0) &&
1027 (lSvcSc1->effMbr <= svcSc1->effMbr)))
1035 /* We have come to the end of the queue. Let's place it */
1036 /* here irresepctive of effGbr or effMBr */
1037 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1038 svcSc1->prioLnk.node = (PTR)svc;
1043 cmLListInsCrnt(lst, &svcSc1->prioLnk);
1044 svcSc1->prioLnk.node = (PTR)svc;
1046 /* If a svc is put in to cell wide priority Qs
1047 * then add the same to UE's lcsWithData List */
1048 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1056 * @brief This function removes a UE from scheduler Queue
1060 * Function: rgSCHSc1DlUeRmvFrmSchd
1061 * Purpose: This function removes a UE from the list of UEs
1062 * based on the priority of the UEs Current AMBR SVC.
1064 * Invoked by: BO and Scheduler
1066 * @param[in] RgSchCellCb* cell
1067 * @param[in] RgSchUeCb* ue
1071 static Void rgSCHSc1DlUeRmvFrmSchd(RgSchCellCb *cell,RgSchUeCb *ue)
1073 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1074 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1078 lst = &cellDl->prioLst[ueDl->prio];
1079 if (ueDl->prioLnk.node != NULLP)
1081 cmLListDelFrm(lst, &ueDl->prioLnk);
1082 ueDl->prioLnk.node = (PTR)NULLP;
1083 /* If a svc is removed from cell wide priority Qs
1084 * then remove the same from UE's lcsWithData List */
1085 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1092 * @brief This function removes a SVC from UEs AMBR LIST
1096 * Function: rgSCHSc1DlSvcRmvFrmUeAmbrLst
1097 * Purpose: This function removes a SVC from UEs AMBR List.
1099 * Invoked by: BO and Scheduler
1101 * @param[in] RgSchUeCb* ue
1102 * @param[in] RgSchDlLcCb* svc
1106 static Void rgSCHSc1DlSvcRmvFrmUeAmbrLst(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1108 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1109 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1112 lst = &ueDl->ambrLst;
1113 if (svcSc1->prioLnk.node != NULLP)
1115 cmLListDelFrm(lst, &svcSc1->prioLnk);
1116 svcSc1->prioLnk.node = (PTR)NULLP;
1123 * @brief This function adds a SVC to UEs AMBR LIST
1127 * Function: rgSCHSc1DlSvcAddToUeAmbrLst
1128 * Purpose: This function adds a SVC to UEs AMBR List.
1130 * Invoked by: BO and Scheduler
1132 * @param[in] RgSchUeCb* ue
1133 * @param[in] RgSchDlLcCb* svc
1137 static Void rgSCHSc1DlSvcAddToUeAmbrLst(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1139 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1142 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1143 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1146 /* If svc already present in AMBR List return */
1147 if (svcSc1->prioLnk.node != NULLP)
1150 node = ueDl->ambrLst.first;
1153 lsvc = (RgSchDlLcCb *)(node->node);
1154 if (((RgSchCmnDlSvc*)(lsvc->sch))->prio > svcCmn->prio)
1162 cmLListAdd2Tail(&ueDl->ambrLst, &svcSc1->prioLnk);
1163 svcSc1->prioLnk.node = (PTR)svc;
1167 ueDl->ambrLst.crnt = node;
1168 cmLListInsCrnt(&ueDl->ambrLst, &svcSc1->prioLnk);
1169 svcSc1->prioLnk.node = (PTR)svc;
1177 * @brief This function removes a service from scheduler
1181 * Function: rgSCHSc1DlSvcRmvFrmSchd
1182 * Purpose: This function removes the SVC from the scheduler Qs.
1184 * Invoked by: BO and Scheduler
1186 * @param[in] RgSchCellCb* cell
1187 * @param[in] RgSchUeCb* ue
1191 static Void rgSCHSc1DlSvcRmvFrmSchd(RgSchCellCb *cell,RgSchDlLcCb *svc)
1193 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1194 RgSchSc1DlSvc *svcDl = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
1195 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1199 lst = &(cellDl->prioLst[svcCmn->prio]);
1200 if (svcDl->prioLnk.node != NULLP)
1202 cmLListDelFrm(lst, &svcDl->prioLnk);
1203 svcDl->prioLnk.node = NULLP;
1204 /* If a svc is removed from cell wide priority Qs
1205 * then remove the same from UE's lcsWithData List */
1206 rgSCHSc1DlRmFrmUeLcsWithData(cell, svc->ue, svc);
1213 * @brief This function adds a service to scheduler for a UE
1217 * Function: rgSCHSc1DlSvcAdd
1218 * Purpose: This function is made available through a FP for
1219 * making scheduler aware of a service added to UE
1221 * Invoked by: BO and Scheduler
1223 * @param[in] RgSchUeCb* ue
1224 * @param[in] RgSchDlLcCb* svc
1225 * @param[in] CrgDlLchCfg* qos
1229 static Void rgSCHSc1DlSvcAdd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc,RgrDlLchCfg *cfg)
1231 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1232 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1233 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1237 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1239 svcSc1->gbr = svcCmn->gbr;
1240 svcSc1->mbr = svcCmn->mbr;
1241 cmLListAdd2Tail(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1242 svcSc1->gbrLnk.node = (PTR)svc;
1249 * @brief This function deletes a service from scheduler
1253 * Function: rgSCHSc1DlLcRmv
1254 * Purpose: This function is made available through a FP for
1255 * making scheduler aware of a service being deleted from UE
1257 * Invoked by: BO and Scheduler
1259 * @param[in] RgSchCellCb* cell
1260 * @param[in] RgSchUeCb* ue
1261 * @param[in] RgSchDlLcCb* svc
1265 Void rgSCHSc1DlLcRmv(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1268 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1269 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1272 if (svcSc1 == NULLP)
1276 ueDl = RG_GET_SC1_UE_DL(ue, cell);
1278 if (svcCmn->prio == 0)
1280 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1282 else if (RG_SCH_CMN_SVC_IS_GBR(svc))
1284 if (svcSc1->gbrLnk.node != NULLP)
1286 cmLListDelFrm(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1287 svcSc1->gbrLnk.node = NULLP;
1289 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1291 else /* if AMBR service */
1293 if (ueDl->ambrSvc == svc)
1295 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1296 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1297 ueDl->ambrSvc = NULLP;
1298 if (ueDl->ambrLst.first != NULLP)
1300 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1301 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svc->bo);
1304 rgSCHSc1DlUeAddToSchd(cell, ue);
1310 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1313 /* ccpu00117052 - MOD - Passing double pointer
1314 for proper NULLP assignment*/
1315 rgSCHUtlFreeSBuf(cell->instIdx,
1316 (Data**)(&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,svc,cell))), (sizeof(RgSchSc1DlSvc)));
1321 * @brief This function is invoked as part of SVC reconfig
1325 * Function: rgSCHSc1DlSvcMod
1326 * Purpose: This function is made available through a FP for
1327 * making scheduler aware of a service reconfiguration.
1329 * Invoked by: Scheduler
1331 * @param[in] RgSchDlLcCb* svc
1332 * @param[in] CrgLchRecfg* recfg
1336 static Void rgSCHSc1DlSvcMod(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc,RgrLchRecfg *recfg)
1338 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1339 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1341 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1343 /* Convert the QOS to handle the refresh duration */
1344 svcSc1->gbr = svcCmn->gbr;
1345 svcSc1->mbr = svcCmn->mbr;
1351 * @brief This function adds UE to scheduler for an AMBR service
1355 * Function: rgSCHSc1DlUeAddToSchd
1356 * Purpose: This function adds a UE to scheduler for the AMBR
1357 * service of highest priority.
1359 * Invoked by: BO and Scheduler
1361 * @param[in] RgSchCellCb* cell
1362 * @param[in] RgSchUeCb* ue
1366 static Void rgSCHSc1DlUeAddToSchd(RgSchCellCb *cell,RgSchUeCb *ue)
1368 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1369 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1370 RgSchSc1DlUe *lueDl;
1373 RgSchUeCb *nodeUe = NULLP;
1375 ueDl->prio = ((RgSchCmnDlSvc *)(ueDl->ambrSvc->sch))->prio;
1376 lst = &cellDl->prioLst[ueDl->prio];
1377 /* if UE already in list, remove and
1379 if (ueDl->prioLnk.node != NULLP)
1381 cmLListDelFrm(lst, &ueDl->prioLnk);
1382 ueDl->prioLnk.node = NULLP;
1383 /* If a svc is removed from cell wide priority Qs
1384 * then remove the same from UE's lcsWithData List */
1385 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1390 nodeUe = (RgSchUeCb *)(node->node);
1391 lueDl = RG_GET_SC1_UE_DL(nodeUe, cell);
1392 if (lueDl->effAmbr < ueDl->effAmbr)
1398 cmLListAdd2Tail(lst, &ueDl->prioLnk);
1399 ueDl->prioLnk.node = (PTR)ue;
1404 cmLListInsCrnt(lst, &ueDl->prioLnk);
1405 ueDl->prioLnk.node = (PTR)ue;
1407 /* If a svc is put in to cell wide priority Qs
1408 * then add the same to UE's lcsWithData List */
1409 rgSCHSc1DlAdd2UeLcsWithData(cell, ue, ueDl->ambrSvc);
1415 * @brief This function implements managing BO for an ABMR service
1419 * Function: rgSCHSc1DlMngAmbrSvcPosn
1420 * Purpose: This function should be called whenever there is a
1421 * change BO for a AMBR service.
1423 * Invoked by: BO and Scheduler
1425 * @param[in] RgSchCellCb* cell
1426 * @param[in] RgSchUeCb* ue
1427 * @param[in] RgSchDlLcCb* svc
1431 static Void rgSCHSc1DlMngAmbrSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1433 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1434 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1436 if (svcSc1->bo == 0)
1438 if (ueDl->ambrSvc == svc)
1440 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1441 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1442 ueDl->ambrSvc = NULLP;
1443 if (ueDl->ambrLst.first != NULLP)
1445 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1446 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1449 rgSCHSc1DlUeAddToSchd(cell, ue);
1455 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1458 else /* svcSc1->bo != 0 */
1460 if (svcSc1->prioLnk.node != NULLP)
1462 if (svc == ueDl->ambrSvc)
1464 ueDl->effAmbr = RGSCH_MIN(svcSc1->bo, ueDl->ambr);
1465 /* Update UE's position in the scheduler */
1468 rgSCHSc1DlUeAddToSchd(cell, ue);
1472 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1477 rgSCHSc1DlSvcAddToUeAmbrLst(cell, ue, svc);
1478 /* Current ambr svc is always the first node of ambrLst.*/
1479 if (ueDl->ambrLst.first->node == (PTR)svc)
1481 if(ueDl->ambrSvc != svc)
1485 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1487 ueDl->ambrSvc = svc;
1488 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1491 rgSCHSc1DlUeAddToSchd(cell, ue);
1501 * @brief This function updates the scheduler with service for a UE
1505 * Function: rgSCHSc1DlLcBoUpd
1506 * Purpose: This function should be called whenever there is a
1507 * change BO for a service.
1509 * Invoked by: BO and Scheduler
1511 * @param[in] RgSchCellCb* cell
1512 * @param[in] RgSchUeCb* ue
1513 * @param[in] RgSchDlLcCb* svc
1517 Void rgSCHSc1DlLcBoUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1519 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1521 if (svcSc1->bo == svc->bo)
1525 svcSc1->bo = svc->bo;
1526 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(ue))
1530 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
1532 /* Stack Crash problem for TRACE5 changes. Added the return below */
1539 * @brief This function updates the scheduler with Prio0 service for a UE
1543 * Function: rgSCHSc1DlMngPrio0SvcPosn
1544 * Purpose: This func shall be triggered whenever there is a
1545 * change in the "Bo yet to be satisfied" field of the service.
1546 * Appropriately positions the svc in its prio Q.
1547 * Removes the SVC from the Q if BO is completely satisfied.
1549 * Invoked by: BO and Scheduler
1551 * @param[in] RgSchCellCb* cell
1552 * @param[in] RgSchUeCb* ue
1553 * @param[in] RgSchDlLcCb* svc
1557 static Void rgSCHSc1DlMngPrio0SvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1559 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1561 /* In this priority, we just add or remove to the queue */
1564 rgSCHSc1DlSvcAddToSchd(cell, svc);
1568 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1575 * @brief This function updates the scheduler with GBR service for a UE
1579 * Function: rgSCHSc1DlMngGbrSvcPosn
1580 * Purpose: This func shall be triggered whenever there is a
1581 * change in the "Bo yet to be satisfied" field of the service.
1582 * Appropriately positions the svc in its prio Q.
1583 * Removes the SVC from the Q if BO is completely satisfied.
1585 * Invoked by: BO and Scheduler
1587 * @param[in] RgSchCellCb* cell
1588 * @param[in] RgSchUeCb* ue
1589 * @param[in] RgSchDlLcCb* svc
1593 static Void rgSCHSc1DlMngGbrSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1595 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1597 /* Handle a GBR service. */
1598 svcSc1->effGbr = RGSCH_MIN(svcSc1->bo, svcSc1->gbr);
1599 svcSc1->effMbr = RGSCH_MIN(svcSc1->bo, svcSc1->mbr);
1600 /* Adjust the SVC priority within the queue */
1601 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1602 rgSCHSc1DlSvcAddToSchd(cell, svc);
1608 * @brief This function updates the scheduler with service for a UE
1612 * Function: rgSCHSc1DlMngSvcPosn
1613 * Purpose: This func shall be triggered whenever there is a
1614 * change in the "Bo yet to be satisfied" field of the service.
1615 * Appropriately positions the svc in its prio Q.
1616 * Removes the SVC from the Q if BO is completely satisfied.
1618 * Invoked by: BO and Scheduler
1620 * @param[in] RgSchCellCb* cell
1621 * @param[in] RgSchUeCb* ue
1622 * @param[in] RgSchDlLcCb* svc
1626 static Void rgSCHSc1DlMngSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1628 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1629 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1631 (cellDl->svcMngFunc[svcCmn->prio])(cell, ue, svc);
1635 /*--------------------------*
1636 * DL specific functions END
1637 *---------------------------*/
1642 * @brief Scheduler processing on cell configuration
1646 * Function : rgSCHSc1RgrDlCellCfg
1648 * This function does requisite initialisation
1649 * and setup for scheduler1 when a cell is
1652 * @param[in] RgSchCellCb *cell
1653 * @param[in] RgrCellCfg *cellCfg
1654 * @param[out] RgSchErrInfo *err
1659 S16 rgSCHSc1RgrDlCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
1662 RgSchSc1DlCell *cellDl;
1664 if((ret = rgSCHUtlAllocSBuf(cell->instIdx,
1665 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc), \
1666 (sizeof(RgSchSc1DlCell)))) != ROK)
1668 DU_LOG("\nERROR --> SCH : Memory allocation FAILED");
1669 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
1673 cellDl = RG_GET_SC1_CELL_DL(cell);
1674 /* Now perform downlink Queues related initializations */
1675 rgSCHSc1DlInitQueues(cellDl);
1677 } /* rgSCHSc1RgrDlCellCfg */
1679 /***********************************************************
1681 * Func : rgSCHSc1DlDeinitQueues
1683 * Desc : De-initialise downlink scheduler queues
1691 **********************************************************/
1692 static Void rgSCHSc1DlDeinitQueues(RgSchSc1DlCell *cellDl)
1696 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
1698 cmLListInit(&cellDl->prioLst[i]);
1699 cmLListInit(&cellDl->retxLst[i]);
1706 * @brief Scheduler processing for cell delete
1710 * Function : rgSCHSc1DlCellDel
1712 * This functions de-initialises and frees memory
1713 * taken up by scheduler1 for the entire cell.
1715 * @param[in] RgSchCellCb *cell
1718 Void rgSCHSc1DlCellDel(RgSchCellCb *cell)
1721 if (((RgSchSc1DlCell *)((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc) \
1727 /* Perform the deinit for the DL scheduler */
1728 rgSCHSc1DlDeinitQueues(RG_GET_SC1_CELL_DL(cell));
1729 /* ccpu00117052 - MOD - Passing double pointer
1730 for proper NULLP assignment*/
1731 rgSCHUtlFreeSBuf(cell->instIdx,
1732 (Data**)(&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc)),
1733 (sizeof(RgSchSc1DlCell)));
1735 } /* rgSCHSc1DlCellDel */
1738 * @brief UE initialisation for scheduler
1742 * Function : rgSCHSc1RgrDlUeCfg
1744 * This functions intialises UE specific scheduler
1747 * @param[in] RgSchCellCb *cell
1748 * @param[in] RgSchUeCb *ue
1749 * @param[int] RgrUeCfg *ueCfg
1750 * @param[out] RgSchErrInfo *err
1755 S16 rgSCHSc1RgrDlUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg,RgSchErrInfo *err)
1757 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
1758 Inst inst = cell->instIdx;
1762 if((rgSCHUtlAllocSBuf(inst,
1763 (Data**)&(ueSchCmn->dl.schSpfc), (sizeof(RgSchSc1DlUe))) != ROK))
1765 DU_LOG("\nERROR --> SCH : Memory allocation FAILED"
1766 "CRNTI:%d",ue->ueId);
1767 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
1770 ueDl = (RgSchSc1DlUe *)ueSchCmn->dl.schSpfc;
1771 if (ue->dl.ambrCfgd)
1773 ueDl->ambr = ue->dl.ambrCfgd;
1777 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
1779 cmLListInit(&ueDl->lcsWithData);
1780 cmLListInit(&ueDl->gbrSvcs);
1781 cmLListInit(&ueDl->ambrLst);
1782 cmLListInit(&ueDl->schdSvcs);
1783 cmLListInit(&ueDl->retxHqProcs);
1785 } /* rgSCHSc1RgrDlUeCfg */
1789 * @brief Dl Harq Entity initialization for SC1
1793 * Function : rgSCHSc1DlUeHqEntInit
1796 * - Create SC1 related information per Harq Entity
1798 * @param[in] RgrSchCellCb *cell
1799 * @param[in] RgSchUeCb *ue
1804 S16 rgSCHSc1DlUeHqEntInit(RgSchCellCb *cell,RgSchDlHqEnt *hqEnt)
1806 RgSchSc1DlHqProc *hqSpcSch;
1807 RgSchDlHqProcCb *hqP;
1809 /* making use of hqE->sch for one shot allocation
1810 * of RgSchSc1DlHqProc structures */
1811 if (rgSCHUtlAllocSBuf(cell->instIdx,
1812 (Data**)&(hqEnt->sch),
1813 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc))) != ROK)
1815 DU_LOG("\nERROR --> SCH : Memory allocation FAILED CRNTI:%d",hqEnt->ue->ueId);
1818 hqSpcSch = (RgSchSc1DlHqProc *)(hqEnt->sch);
1819 for(cnt = 0; cnt < hqEnt->numHqPrcs; cnt++)
1821 hqP = &hqEnt->procs[cnt];
1822 ((RgSchCmnDlHqProc *)((hqP)->sch))->schSpfc = \
1829 * @brief Dl Harq Entity deletion for Sc1
1833 * Function : rgSCHSc1DlUeHqEntDeInit
1836 * - Free SC1 related information per Harq Entity
1838 * @param[in] RgrSchCellCb *cell
1839 * @param[in] RgSchDlHqEnt *hqE
1842 S16 rgSCHSc1DlUeHqEntDeInit(RgSchCellCb *cell,RgSchDlHqEnt *hqE)
1847 rgSCHUtlFreeSBuf(cell->instIdx,
1848 (Data**)(&(hqE->sch)),
1849 (hqE->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
1858 * @brief UE reconfiguration for scheduler
1862 * Function : rgSCHSc1RgrDlUeRecfg
1864 * This functions updates UE specific scheduler
1865 * information upon UE reconfiguration
1867 * @param[in] RgSchCellCb *cell
1868 * @param[in] RgSchUeCb *ue
1869 * @param[int] RgrUeRecfg *ueRecfg
1870 * @param[out] RgSchErrInfo *err
1875 S16 rgSCHSc1RgrDlUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
1877 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1878 RgSchCmnDlUe *ueCmnDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
1879 /*cell added as part of CA dev*/
1880 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1882 if (ue->dl.ambrCfgd)
1884 ueDl->ambr = ue->dl.ambrCfgd;
1888 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
1891 /* Discarding TB2's context from scheduling Queues.
1892 * Since TB2 transmission needs signalling using
1893 * TM specific formats. And since during this transient
1894 * period of UE TM Recfg, SCH always uses Format 1A,
1895 * the TB2s are discarded. */
1896 if (ueCmnDl->mimoInfo.forceTD & RG_SCH_CMN_TD_TXMODE_RECFG)
1898 /* If HqP is in retx queue only for TB2 retx scheduling
1899 * then remove the harp proc from retx Queue */
1901 /* If Hqp is in retx queue for retx allocation of
1902 * both TB1 and TB2, then reset TB2's state as ACKED */
1903 RgSchDlHqProcCb *hqP;
1905 RgInfRlsHqInfo *rlsHqBufs = &(cell->rlsHqArr[cell->crntHqIdx]);
1908 /* Prepare TB2 release information to be sent to MAC */
1909 rlsHqBufs->numUes = 0;
1910 for(i = 0; i < hqEnt->numHqPrcs; i++)
1912 hqP = &hqEnt->procs[i];
1913 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = ue->ueId;
1914 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = hqP->procId;
1915 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
1917 if (hqP->tbInfo[0].state != HQ_TB_NACKED)
1919 /* Remove the HqP from retx Queue.
1921 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
1922 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
1924 rgSCHDhmRlsHqpTb(hqP, 1, TRUE);
1925 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[0] = 2;
1926 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 1;
1928 rlsHqBufs->numUes++;
1930 /* Send the hqProc list for MAC to clear TB1 contents */
1931 if (rlsHqBufs->numUes)
1933 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
1934 RgSchMacRlsHq (&pst, rlsHqBufs);
1938 } /* rgSCHSc1RgrDlUeRecfg */
1941 * @brief Removes UEs context from Priority Qs.
1945 * Function : rgSCHSc1DlRmvUeFrmPrioQs
1948 * @param[in] RgSchCellCb *cell
1949 * @param[in] RgSchUeCb *ue
1952 static Void rgSCHSc1DlRmvUeFrmPrioQs(RgSchCellCb *cell,RgSchUeCb *ue)
1954 RgSchSc1DlUe *sc1Ue;
1959 sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
1961 /* Remove UE From DL priority queues */
1962 if (sc1Ue->ambrSvc != NULLP)
1964 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1967 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
1969 svc = ue->dl.lcCb[idx];
1974 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1978 } /* rgSCHSc1DlRmvUeFrmPrioQs */
1981 * @brief Inactivate UE reason : measgap, acknaprept, poInactv.
1985 * Function : rgSCHSc1DlInactvtUe
1988 * @param[in] RgSchCellCb *cell
1989 * @param[in] RgSchUeCb *ue
1992 static Void rgSCHSc1DlInactvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
1994 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1995 RgSchDlHqProcCb *hqP;
1996 RgSchCmnDlHqProc *hqProcDl;
1998 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2001 /* ccpu00130170: UE related HARQ Procs are cleared only
2002 if UE's Re-establishment procedure is not in progress*/
2003 if(!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE))
2005 /* remove all in use HARQ processes from the subframes.
2006 * Store them in UEs hqProc Lst. Add back to cell's
2007 * retx lst when UE is activated again. */
2008 for(i = 0; i < hqEnt->numHqPrcs; i++)
2010 hqP = &hqEnt->procs[i];
2011 hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
2012 /* Remove retx procs from cell's list and
2013 * add them to UE's List */
2016 !(RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)) &&
2018 hqProcDl->retxLnk.node != NULLP)
2020 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
2021 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
2022 hqProcDl->retxLnk.node = NULLP;
2023 rgSCHSc1DlProcAddToUeRetx(cell, ue, hqP);
2028 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2031 } /* rgSCHSc1DlInactvtUe */
2035 * @brief UE suspension.
2039 * Function : rgSCHSc1DlSuspendUe
2041 * Removes UE, its SVCs and its HqPs from CELL WIDE
2042 * PrioQs and Retx Qs Respectively.
2044 * @param[in] RgSchCellCb *cell
2045 * @param[in] RgSchUeCb *ue
2048 static Void rgSCHSc1DlSuspendUe(RgSchCellCb *cell,RgSchUeCb *ue)
2050 RgSchDlHqProcCb *hqP;
2053 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2056 /* remove all in use HARQ processes from the subframes.
2057 * Store them in UEs hqProc Lst. Add back to cell's
2058 * retx lst when UE is activated again. */
2059 for(i = 0; i < hqEnt->numHqPrcs; i++)
2061 hqP = &hqEnt->procs[i];
2062 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2063 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
2064 /* Removing the Harq Proc from subframes list */
2065 if (hqP->hqPSfLnk.node != NULLP)
2069 cmLListDelFrm(&hqP->subFrm->pdcchInfo.pdcchs,
2071 cmLListAdd2Tail(&cell->pdcchLst, &hqP->pdcch->lnk);
2075 rgSCHUtlDlHqPTbRmvFrmTx(hqP->subFrm,hqP,0,FALSE);
2077 for (j = 0; j < 2; j++)
2079 if (hqP->tbInfo[j].state == HQ_TB_WAITING)
2081 rgSCHDhmRlsHqpTb(hqP, j, TRUE);
2086 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2089 } /* rgSCHSc1DlSuspendUe */
2091 /***********************************************************
2093 * Func : rgSCHSc1DlScanUpdPdbPrio
2095 * Desc : Increment the pivot and reposition the LCs under the pivot to
2096 * new location according to thieir PDB and elapsed time.
2104 **********************************************************/
2105 Void rgSCHSc1DlScanUpdPdbPrio(RgSchCellCb *cell)
2112 * @brief Function to update Flow control information
2113 * to be sent to MAC.
2117 * Function: rgSCHSc1DlFillFlowCntrlInfo
2119 * update Flow control information
2126 * @param[in] RgSchCellCb *cell
2127 RgInfSfAlloc *sfAlloc;
2131 S16 rgSCHSc1DlFillFlowCntrlInfo(RgSchCellCb *cell,RgInfSfAlloc *sfAlloc)
2136 * @brief UE deletion for scheduler
2140 * Function : rgSCHSc1DlUeDel
2142 * This functions deletes all scheduler information
2143 * pertaining to a UE
2145 * @param[in] RgSchCellCb *cell
2146 * @param[in] RgSchUeCb *ue
2149 Void rgSCHSc1DlUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
2151 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2152 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
2155 if (sc1DlUe == NULLP)
2161 /* Remove UEs scheduler context */
2162 rgSCHSc1DlSuspendUe(cell, ue);
2164 /* Free all SC1 specific control blocks */
2165 if (hqEnt->sch != NULLP)
2167 /* ccpu00117052 - MOD - Passing double pointer
2168 for proper NULLP assignment*/
2169 rgSCHUtlFreeSBuf(cell->instIdx,
2170 (Data**)(&(hqEnt->sch)),
2171 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
2175 /* ccpu00117052 - MOD - Passing double pointer
2176 for proper NULLP assignment*/
2177 rgSCHUtlFreeSBuf(cell->instIdx, (Data**)(&sc1DlUe), (sizeof(RgSchSc1DlUe)));
2180 } /* rgSCHSc1DlUeDel */
2183 * @brief Scheduler invocation on Downlink logical channel addition
2187 * Function : rgSCHSc1RgrLcCfg
2189 * This functions does required processing when a new
2190 * (dedicated) logical channel is added.
2192 * @param[in] RgSchCellCb *cell
2193 * @param[in] RgSchUeCb *ue
2194 * @param[in] RgSchDlLcCb *dlLc
2195 * @param[int] RgrLchCfg *lcCfg
2196 * @param[out] RgSchErrInfo *err
2201 S16 rgSCHSc1RgrLcCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchCfg *lcCfg,RgSchErrInfo *err)
2205 ret = rgSCHUtlAllocSBuf(cell->instIdx,
2206 (Data**)&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,dlLc,cell)), \
2207 (sizeof(RgSchSc1DlSvc)));
2210 DU_LOG("\nERROR --> SCH : rgSCHSc1CrgLcCfg():"
2211 "SCH struct alloc failed CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId);
2212 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
2216 rgSCHSc1DlSvcAdd(cell, ue, dlLc, &lcCfg->dlInfo);
2218 } /* rgSCHSc1RgrLcCfg */
2222 * @brief Scheduler invocation on logical channel addition
2226 * Function : rgSCHSc1RgrLcRecfg
2228 * This functions does required processing when an existing
2229 * (dedicated) logical channel is reconfigured. Assumes lcg
2230 * pointer in ulLc is set to the old value.
2231 * Independent of whether new LCG is meant to be configured,
2232 * the new LCG scheduler info is accessed and possibly modified.
2234 * @param[in] RgSchCellCb *cell
2235 * @param[in] RgSchUeCb *ue
2236 * @param[in] RgSchDlLcCb *dlLc
2237 * @param[int] RgrLchRecfg *lcRecfg
2238 * @param[out] RgSchErrInfo *err
2243 S16 rgSCHSc1RgrLcRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchRecfg *lcRecfg,RgSchErrInfo *err)
2248 rgSCHSc1DlSvcMod(cell,ue,dlLc, lcRecfg);
2251 } /* rgSCHSc1RgrLcRecfg */
2255 * @brief This function handles the reconfiguration of cell
2259 * Function: rgSCHSc1RgrDlCellRecfg
2260 * Purpose: Update the reconfiguration parameters.
2262 * Invoked by: Scheduler
2264 * @param[in] RgSchCellCb* cell
2268 static S16 rgSCHSc1RgrDlCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
2276 * @brief This function implements scheduler DL allocation
2280 * Function: rgSCHSc1DlTaCmd
2281 * Purpose: This function implements scheduler for TA cmd alloc for
2282 * UEs. The hq proc availed as part of this alloc can be used
2283 * by the UEs Dedicated CH transmission allocation.
2285 * Invoked by: Scheduler
2287 * @param[in] RgSchCellCb* cell
2288 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
2292 static Void rgSCHSc1DlTaCmd(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2296 RgSchDlHqProcCb *proc;
2299 RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell);
2300 RgSchCmnDlUe *cmnUeDl;
2302 RgSchCmnDlHqProc *cmnHqDl;
2303 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
2305 Bool dlAllowed = FALSE;
2308 lst = &cellCmnDl->taLst;
2312 ue = (RgSchUeCb *)node->node;
2317 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
2318 if (dlAllowed == FALSE)
2324 /* If Ue is inactive in DL then ignore */
2325 if (ue->dl.dlInactvMask)
2329 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2330 /*cell added as part of CA dev*/
2331 ueDl = RG_GET_SC1_UE_DL(ue, cell);
2333 if (rgSCHDhmGetAvlHqProc(cell, ue, cellCmnDl->time, &proc) != ROK)
2337 /* Initialize some of the parameters of the HQ proc */
2338 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
2342 cmnHqDl->totBytes = 0;
2343 rgSCHCmnDlAllocTxRb(cell, subFrm, ue, RGSCH_TA_SIZE, &effBo, proc, allocInfo);
2346 /* If no allocations so far, meaning proc obtained now */
2347 if (cmnHqDl->totBytes == 0)
2349 rgSCHSc1RlsHqProc(proc);
2350 /* Added the handling for removing
2351 * UE from txHqPLst and resetting outStndalloc.*/
2352 if(proc->reqLnk.node != (PTR)NULLP)
2354 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
2355 proc->reqLnk.node = (PTR)NULLP;
2357 /*Re-set the outstanding alloc information.*/
2358 cmnUeDl->outStndAlloc = 0;
2360 /* Avl BW could not satisfy even TA so break */
2363 ueDl->taReqBytes = RGSCH_TA_SIZE;
2364 cmnUeDl->proc = proc;
2365 cmnHqDl->totBytes += effBo;
2366 /* 3.1 MIMO moving this call to cmn scheduler */
2367 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue);*/
2373 * @brief Scheduler invocation
2377 * Function: rgSCHSc1DlHndlInActUes
2378 * Purpose: The list of inactive UEs present in inactvLst should
2379 * be removed from the scheduling Qs.
2381 * Invoked by: Common Scheduler (TTI processing)
2383 * @param[in] RgSchCellCb *cell
2384 * @param[out] CmLListCp *inactvLst
2387 Void rgSCHSc1DlHndlInActUes(RgSchCellCb *cell,CmLListCp *inactvLst)
2392 node = inactvLst->first;
2395 ue = (RgSchUeCb *)node->node;
2397 /* Suspend this UE from further scheduling
2398 * till it is activated again. */
2399 rgSCHSc1DlInactvtUe(cell, ue);
2405 * @brief This function initializes all the data for the scheduler
2409 * Function: rgSCHSc1DlInit
2410 * Purpose: This function initializes the following information
2411 * 1. Efficiency table
2412 * 2. CQI to table index - It is one row for upto 3 RBs
2413 * and another row for greater than 3 RBs
2415 * currently extended prefix is compiled out.
2416 * Invoked by: MAC intialization code..may be ActvInit
2421 Void rgSCHSc1DlInit(RgDlSchdApis *rgSchDlApis)
2423 /* Init the function pointers */
2424 rgSchDlApis->rgSCHRgrDlUeCfg = rgSCHSc1RgrDlUeCfg;
2425 rgSchDlApis->rgSCHRgrDlUeRecfg = rgSCHSc1RgrDlUeRecfg;
2426 rgSchDlApis->rgSCHFreeDlUe = rgSCHSc1DlUeDel;
2427 rgSchDlApis->rgSCHRgrDlCellCfg = rgSCHSc1RgrDlCellCfg;
2428 rgSchDlApis->rgSCHRgrDlCellRecfg = rgSCHSc1RgrDlCellRecfg;
2429 rgSchDlApis->rgSCHFreeDlCell = rgSCHSc1DlCellDel;
2430 rgSchDlApis->rgSCHRgrDlLcCfg = rgSCHSc1RgrLcCfg;
2431 rgSchDlApis->rgSCHRgrDlLcRecfg = rgSCHSc1RgrLcRecfg;
2432 rgSchDlApis->rgSCHFreeDlLc = rgSCHSc1DlLcRmv;
2433 rgSchDlApis->rgSCHDlNewSched = rgSCHSc1DlDedNewTx;
2434 rgSchDlApis->rgSCHDlPreSched = rgSCHSc1DlPreSchd;
2435 rgSchDlApis->rgSCHDlPstSched = rgSCHSc1DlPstSchd;
2436 rgSchDlApis->rgSCHDlRetxSched = rgSCHSc1DlDedRetx;
2437 rgSchDlApis->rgSCHDlCeSched = rgSCHSc1DlTaCmd;
2438 rgSchDlApis->rgSCHDlDedBoUpd = rgSCHSc1DlLcBoUpd;
2439 rgSchDlApis->rgSCHDlProcAddToRetx = rgSCHSc1DlProcAddToCellRetx;
2440 rgSchDlApis->rgSCHDlAllocFnlz = rgSCHSc1DlAllocFnlz;
2441 rgSchDlApis->rgSCHDlCqiInd = rgSCHSc1DlCqiInd;
2442 rgSchDlApis->rgSCHDlUeRefresh = rgSCHSc1DlUeRefresh;
2443 rgSchDlApis->rgSCHDlUeReset = rgSCHSc1DlUeReset;
2444 rgSchDlApis->rgSCHDlActvtUe = rgSCHSc1DlActvtUe;
2445 rgSchDlApis->rgSCHDlInactvtUes = rgSCHSc1DlHndlInActUes;
2446 rgSchDlApis->rgSCHDlUeHqEntInit = rgSCHSc1DlUeHqEntInit;
2447 rgSchDlApis->rgSCHDlUeHqEntDeInit = rgSCHSc1DlUeHqEntDeInit;
2448 rgSchDlApis->rgSCHDlProcRmvFrmRetx = rgSCHSc1DlProcRmvFrmRetx;
2449 rgSchDlApis->rgSCHDlTickForPdbTrkng = rgSCHSc1DlScanUpdPdbPrio;
2450 rgSchDlApis->rgSCHDlFillFlwCtrlInfo = rgSCHSc1DlFillFlowCntrlInfo;
2458 /***********************************************************
2460 * Func : rgSCHSc1DlInitQueues
2462 * Desc : Initial downlink scheduler queues
2470 **********************************************************/
2471 static Void rgSCHSc1DlInitQueues(RgSchSc1DlCell *cellDl)
2475 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
2477 cmLListInit(&cellDl->prioLst[i]);
2478 cmLListInit(&cellDl->retxLst[i]);
2480 /* Set appropriate "manage svc positioning" function based on
2481 * svc priority as array index */
2483 for (i = 0; i < RG_SCH_SC1_DL_GBR_PRIO_START; i++)
2485 cellDl->svcMngFunc[i] = rgSCHSc1DlMngPrio0SvcPosn;
2488 for (i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
2490 cellDl->svcMngFunc[i] = rgSCHSc1DlMngGbrSvcPosn;
2492 /* for Non-GBR svcs */
2493 for (i = RG_SCH_SC1_DL_GBR_PRIO_END+1; i <= RG_SCH_CMN_MAX_PRIO; i++)
2495 cellDl->svcMngFunc[i] = rgSCHSc1DlMngAmbrSvcPosn;
2504 * @brief This function Processes the Final Allocations
2505 * made by the RB Allocator against the requested
2510 * Function: rgSCHSc1DlRetxAllocFnlz
2511 * Purpose : Remove the Retx Hq Proc from the Cell's
2512 * Retx list, if allocation is successful.
2513 * Fill the HqProc and PDCCH and append it to the SubFrm.
2517 * Invoked by: Common Scheduler
2519 * @param[in] RgSchCellCb *cell
2520 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
2524 static Void rgSCHSc1DlRetxAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2528 RgSchDlHqProcCb *hqP;
2529 RgSchDlRbAlloc *dlAllocCb = NULLP;
2531 node = allocInfo->dedAlloc.schdRetxHqPLst.first;
2534 hqP = (RgSchDlHqProcCb *)node->node;
2537 /* Fill PDCCH and assign it to HqP */
2538 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
2540 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
2544 rgSCHCmnHdFddUpdDLMark(cell, ue);
2547 /* Extra Check: Retain the hqProc in the RETX Queue if one/more
2548 * TBs of the HqProc are yet to be scheduled for RETX.
2549 * Note: Here we are not tracking at TB Level, the priority Q
2550 * to which it belongs to. The retx prio of transmission is still
2551 * being maintained at hqProc level, rather than at TB level */
2552 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
2553 (hqP->tbInfo[1].state != HQ_TB_NACKED)) {
2554 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2556 /* reset the UE allocation Information */
2557 rgSCHCmnDlUeResetTemp(ue, hqP);
2560 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
2561 node = allocInfo->dedAlloc.nonSchdRetxHqPLst.first;
2564 hqP = (RgSchDlHqProcCb *)node->node;
2567 /* reset the UE allocation Information */
2568 rgSCHCmnDlUeResetTemp(ue, hqP);
2573 /* 3.1 MIMO Alloc distribution functions being performed
2577 /***********************************************************
2579 * Func : rgSCHSc1DlSprTxTbDstn
2581 * Desc : Perform Actual allocation distribution among
2582 * UEs schd svcs and TA for a given spare TB "tbInfo" allocation.
2583 * spare TB allocation is as a result of 1 RETX TB allocation, when
2584 * conditions are favourable for 2 TB spatial multiplexing.
2592 **********************************************************/
2593 static Void rgSCHSc1DlSprTxTbDstn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqTbCb *tbInfo,uint32_t *effAlloc,CmLList **node)
2596 RgSchSc1DlSvc *svcSc1;
2597 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2599 RgSchLchAllocInfo lchSchdData;
2601 uint32_t rlcHdrEstmt;
2604 while((*node) && (*effAlloc > 0))
2606 svc = (RgSchDlLcCb *)(*node)->node;
2607 *node = (*node)->next;
2608 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
2610 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
2611 /* Update the SVC QOS Param */
2612 if (RG_SCH_CMN_SVC_IS_GBR(svc))
2614 effBo = svcSc1->effMbr + rlcHdrEstmt;
2615 bytes = RGSCH_MIN(*effAlloc, effBo);
2616 /* Determine How much BO is satisfied */
2617 if (bytes <= rlcHdrEstmt)
2621 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2623 (svcSc1->bo -= bytes-rlcHdrEstmt);
2624 svc->bo = svcSc1->bo;
2628 /* Increment qciActiveLCs once since this LCs buffer will be present
2630 if (svc->lcType == CM_LTE_LCH_DTCH)
2632 ue->qciActiveLCs[svc->qciCb->qci]++;
2635 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
2637 if (ue->qciActiveLCs[svc->qciCb->qci])
2639 ue->qciActiveLCs[svc->qciCb->qci]--;
2641 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
2643 svc->qciCb->dlUeCount--;
2647 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
2648 (svcSc1->gbr -= bytes);
2649 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
2650 (svcSc1->mbr -= bytes);
2652 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
2654 effBo = ueDl->effAmbr + rlcHdrEstmt;
2655 bytes = RGSCH_MIN(*effAlloc, effBo);
2656 /* Determine How much BO is satisfied */
2657 if (bytes <= rlcHdrEstmt)
2661 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2663 (svcSc1->bo -= bytes-rlcHdrEstmt);
2665 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
2666 (ueDl->ambr -= bytes);
2668 else /* Prio 0 SVC */
2670 effBo = svcSc1->bo + rlcHdrEstmt;
2671 bytes = RGSCH_MIN(*effAlloc, effBo);
2672 /* Determine How much BO is satisfied */
2673 if (bytes <= rlcHdrEstmt)
2677 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2679 (svcSc1->bo -= bytes-rlcHdrEstmt);
2681 /* Position the service accordingly */
2682 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
2683 /* Update effAlloc */
2686 /* Update DHM for this SVC */
2687 lchSchdData.lcId = svc->lcId;
2688 lchSchdData.schdData = bytes;
2689 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
2695 /***********************************************************
2697 * Func : rgSCHSc1DlNewTxTbDstn
2699 * Desc : Perform Actual allocation distribution among
2700 * UEs schd svcs and TA for a given TB "tbInfo" allocation.
2701 * Assumption: TA is given higher priority in Alloc Distribution.
2709 **********************************************************/
2710 static Void rgSCHSc1DlNewTxTbDstn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqTbCb *tbInfo,uint32_t *effAlloc,CmLList **node)
2713 RgSchSc1DlSvc *svcSc1 = NULLP;
2714 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2716 RgSchLchAllocInfo lchSchdData;
2717 CmLList *prev = NULLP;
2720 if (ueDl->taReqBytes)
2722 if (ueDl->taReqBytes < *effAlloc)
2724 /*TA satisfied, hence remove from TA Lst */
2725 rgSCHCmnRmvFrmTaLst(cell, ue);
2726 /* Indicate to DHM that TA has been scheduled */
2727 rgSCHDhmSchdTa(ue, tbInfo);
2728 *effAlloc -= ueDl->taReqBytes;
2730 /* Reset the TA Req Bytes Field */
2731 ueDl->taReqBytes = 0;
2733 while((*node) && (*effAlloc > 0))
2735 svc = (RgSchDlLcCb *)(*node)->node;
2737 *node = (*node)->next;
2738 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
2739 if (*effAlloc > svcSc1->reqBytes)
2741 bytes = svcSc1->reqBytes;
2742 if (bytes <= svcSc1->hdrEstimate)
2746 /* 3.1 MIMO updating the reqBytes field */
2747 svcSc1->reqBytes = 0;
2753 if (bytes <= svcSc1->hdrEstimate)
2757 /* 3.1 MIMO updating the reqBytes field */
2758 svcSc1->reqBytes -= bytes;
2759 (svcSc1->bo <= bytes-svcSc1->hdrEstimate)?\
2761 (svcSc1->bo -= bytes-svcSc1->hdrEstimate);
2763 svc->bo = svcSc1->bo;
2768 /* Increment qciActiveLCs once since this LCs buffer will be present
2770 if (svc->lcType == CM_LTE_LCH_DTCH)
2772 ue->qciActiveLCs[svc->qciCb->qci]++;
2775 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
2777 if (ue->qciActiveLCs[svc->qciCb->qci])
2779 ue->qciActiveLCs[svc->qciCb->qci]--;
2781 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
2783 svc->qciCb->dlUeCount--;
2788 /* Update the SVC QOS Param */
2789 if (RG_SCH_CMN_SVC_IS_GBR(svc))
2791 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
2792 (svcSc1->gbr -= bytes);
2793 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
2794 (svcSc1->mbr -= bytes);
2796 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
2798 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
2799 (ueDl->ambr -= bytes);
2801 /* Position the service accordingly */
2802 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
2803 /* Update effAlloc */
2806 /* Update DHM for this SVC */
2807 lchSchdData.lcId = svc->lcId;
2808 lchSchdData.schdData = bytes;
2809 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
2811 /* If no more scheduled LCs for TB data distribution
2812 * then distribute the spare TB data among the LCs
2813 * of the UE with non-zero BO. This is effective for
2814 * schedulers work on LC level priorities rather than
2816 if ((*node == NULLP) && (svcSc1) && (svcSc1->reqBytes == 0))
2818 rgSCHSc1DlSprTxTbDstn(cell, ue, tbInfo, effAlloc,
2819 &ueDl->lcsWithData.first);
2823 /* make sure node points to the svc not completely
2825 * make sure if not served completely then
2826 * the other TB allocation accomodates the same */
2833 /***********************************************************
2835 * Func : rgSCHSc1DlNewTxUeFnlz
2837 * Desc : Perform allocation Distribution from scheduled TB
2838 * among the list of services considered for scheduling.
2846 **********************************************************/
2847 static Void rgSCHSc1DlNewTxUeFnlz (RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo,RgSchUeCb *ue)
2850 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2851 RgSchCmnDlUe *cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2852 /*cell added as part of CA dev*/
2853 /* 3.1 MIMO Distribute data of each TB across services */
2854 RgSchDlRbAlloc *dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
2855 uint32_t remTb1Bytes = dlAllocCb->tbInfo[0].bytesAlloc;
2856 uint32_t remTb2Bytes = dlAllocCb->tbInfo[1].bytesAlloc;
2857 uint32_t effAlloc = 0;
2858 /*ccpu00120365-ADD-added to code to check if second TB is utilized */
2859 uint32_t tb2Bytes = 0;
2863 /* 3.1 MIMO Consider the allocation of New TX TB for distribution */
2864 /* Handle schd services */
2865 node = ueDl->schdSvcs.first;
2867 effAlloc += remTb1Bytes;
2868 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[0],\
2869 &remTb1Bytes, &node);
2870 /* In the event that TB1 is not completely filled by the DL LCs
2871 * BO, consider the reducing the iMcs for increasing redundancy
2872 * and hence reception quality at UE */
2873 rgSCHCmnRdcImcsTxTb(dlAllocCb, 0,
2874 dlAllocCb->tbInfo[0].bytesAlloc - remTb1Bytes);
2877 /*ccpu00120365-ADD-assigning value of remTb2Bytes before utilization */
2878 tb2Bytes = remTb2Bytes;
2880 /* Extra check for a non SM UE allocation */
2882 effAlloc += remTb2Bytes;
2883 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[1],\
2884 &remTb2Bytes, &node);
2885 /* In the event that TB2 is not completely filled by the DL LCs
2886 * BO, consider the reducing the iMcs for increasing redundancy
2887 * and hence reception quality at UE */
2888 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1,
2889 dlAllocCb->tbInfo[1].bytesAlloc - remTb2Bytes);
2892 /* ccpu00120365-ADD-Disable the second TB as the second TB is not
2894 if ( remTb2Bytes && ( tb2Bytes == remTb2Bytes) )
2896 dlAllocCb->mimoAllocInfo.precIdxInfo = 0;
2897 dlAllocCb->mimoAllocInfo.numTxLyrs = 1;
2898 dlAllocCb->tbInfo[1].schdlngForTb = FALSE;
2899 dlAllocCb->tbInfo[1].isDisabled = TRUE;
2902 if (effAlloc == (remTb1Bytes + remTb2Bytes))
2904 /* Allocation such that Nothing could be satisfied */
2905 /* Return the grabbed PDCCH */
2906 rgSCHUtlPdcchPut(cell, &dlAllocCb->dlSf->pdcchInfo,
2908 rgSCHSc1RlsHqProc(cmnUeDl->proc);
2912 /* Fill PDCCH and assign it to HqP */
2913 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, cmnUeDl->proc);
2920 * @brief This function Processes the Final Allocations
2921 * made by the RB Allocator against the requested
2922 * New TX allocations.
2926 * Function: rgSCHSc1DlNewTxAllocFnlz
2927 * Purpose : Distribute the allocation among the Scheduled SVCs.
2928 * Fill pdcch and HqP for UEs will allocations.
2929 * Release HqP for UE with no allocation.
2931 * Invoked by: Common Scheduler
2933 * @param[in] RgSchCellCb *cell
2934 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
2938 static Void rgSCHSc1DlNewTxAllocFnlz (RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2942 RgSchCmnDlUe *cmnUeDl;
2943 RgSchDlHqProcCb *hqP;
2945 node = allocInfo->dedAlloc.schdTxHqPLst.first;
2948 hqP = (RgSchDlHqProcCb *)node->node;
2951 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2952 /*cell added as part of CA dev*/
2954 rgSCHSc1DlNewTxUeFnlz(cell, allocInfo, ue);
2958 rgSCHCmnHdFddUpdDLMark(cell, ue);
2961 /* reset the UE allocation Information */
2962 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
2963 rgSCHCmnDlUeResetTemp(ue, hqP);
2966 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
2967 node = allocInfo->dedAlloc.nonSchdTxHqPLst.first;
2970 hqP = (RgSchDlHqProcCb *)node->node;
2973 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue, cell);
2975 /* Release HqProc */
2976 rgSCHSc1RlsHqProc(hqP);
2977 /* reset the UE allocation Information */
2978 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
2979 rgSCHCmnDlUeResetTemp(ue, hqP);
2984 /* 3.1 Added new function to handle TX+RETX alloc fnlz'n */
2987 * @brief This function Processes the Final Allocations
2988 * made by the RB Allocator against the requested
2989 * RETX+New TX allocations. The NewTx TB allocation
2990 * is considered for distribution among LCs.
2994 * Function: rgSCHSc1DlRetxNewTxAllocFnlz
2995 * Purpose : 1. Reached here due to 1 RETX TB allocation for a
2996 * SM UE, which is capable to accomodate a newTX
2998 * 2. Distribute NewTX TB allocation among the
2999 * SVCs present in lcsWithData list of UE.
3002 * Invoked by: Common Scheduler
3004 * @param[in] RgSchCellCb *cell
3005 * @param[in] RgSchCmnDlRbAllocInfo *cellAllocInfo
3009 static Void rgSCHSc1DlRetxNewTxAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *cellAllocInfo)
3013 RgSchSc1DlUe *sc1DlUe;
3014 RgSchDlHqProcCb *hqP;
3015 RgSchDlHqTbCb *newTxTbInfo;
3017 uint32_t remTbBytes;
3018 RgSchDlRbAlloc *ueAllocInfo;
3019 RgSchDlRbAlloc *dlAllocCb;
3022 node = cellAllocInfo->dedAlloc.schdTxRetxHqPLst.first;
3025 hqP = (RgSchDlHqProcCb *)node->node;
3028 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3029 ueAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3030 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3031 /* Index 0 of ueAllocInfo->tbInfo will always hold the
3032 * RETX TB and index 1 will hold the NewTX TB in case of
3033 * RETX+TX allocation. */
3034 newTxTbInfo = ueAllocInfo->tbInfo[1].tbCb;
3035 effAlloc = remTbBytes = ueAllocInfo->tbInfo[1].bytesAlloc;
3036 rgSCHSc1DlSprTxTbDstn(cell, ue, newTxTbInfo,\
3037 &remTbBytes, &(sc1DlUe->lcsWithData.first));
3038 /* Trying to reduce mcs of TX TB to increase reception quality at UE.
3039 * In case of RETX+TX allocation, TX TB allocation was irrespective
3040 * of actual requirement by UE, hence in case if consumption is
3041 * less than allocation, consider reducing the iMcs of this TX TB. */
3042 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1, effAlloc - remTbBytes);
3043 /* 3.1 MIMO Remove/Retain from/in cell RETX List */
3044 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
3045 /* Fill PDCCH and assign it to HqP */
3046 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
3050 rgSCHCmnHdFddUpdDLMark(cell, ue);
3053 /* reset the UE allocation Information */
3054 rgSCHCmnDlUeResetTemp(ue, hqP);
3057 /* Traverse the nonSchdTxRetxHqPLst and reset the UE allocation Info */
3058 node = cellAllocInfo->dedAlloc.nonSchdTxRetxHqPLst.first;
3061 hqP = (RgSchDlHqProcCb *)node->node;
3064 /* reset the UE allocation Information */
3065 rgSCHCmnDlUeResetTemp(ue, hqP);
3071 * @brief This function Processes the Final Allocations
3072 * made by the RB Allocator against the requested.
3076 * Function: rgSCHSc1DlAllocFnlz
3077 * Purpose: This function Processes the Final Allocations
3078 * made by the RB Allocator against the requested.
3079 * 1. Loop through scheduled TX and RETX lists.
3080 * Fill in the corresponding PDCCH and HqProcs.
3081 * In case of TX If actual Alloc < requested, then perform
3082 * an appropriate distribution among the schdSvcs.
3083 * If TA is satisfied, then remove UE from TA Lst.
3084 * 2. Loop through UnScheduled TX and RETX Lists.
3085 * Release grabbed HqProcs.
3086 * Put back SVCs from schdSvcsLst to their corresponding Qs.
3089 * Invoked by: Common Scheduler
3091 * @param[in] RgSchCellCb *cell
3092 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
3096 Void rgSCHSc1DlAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
3099 rgSCHSc1DlRetxAllocFnlz(cell, allocInfo);
3101 rgSCHSc1DlNewTxAllocFnlz(cell, allocInfo);
3103 /*3.1 MIMO new Function added to handle TX+RETX
3104 * harq process scheduling finalization */
3105 rgSCHSc1DlRetxNewTxAllocFnlz(cell, allocInfo);
3112 * @brief This function Updates the DL CQI for the UE.
3116 * Function: rgSCHSc1DlCqiInd
3117 * Purpose: Updates the DL CQI for the UE
3119 * Invoked by: Common Scheduler. SC1 does nothing.
3121 * @param[in] RgSchCellCb *cell
3122 * @param[in] RgSchUeCb *ue
3123 * @param[in] TfuDlCqiRpt *dlCqiRpt
3127 Void rgSCHSc1DlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,Bool isPucchInfo,Void *dlCqi)
3134 * @brief This function adds a service to UE's list of lcsWithData.
3138 * Function: rgSCHSc1DlAdd2UeLcsWithData
3139 * Purpose: 1. This is to maintain a snapshot view of the
3140 * DL SVCs distributions among the cellwide priority
3142 * 2. This snapshot view is maintained in the order
3143 * of priority of the SVCs with in UE.
3144 * 3. Addition of SVC to a cellwide priority Queue
3145 * triggers this function.
3147 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3148 * to cellwide priority Queues.
3150 * @param[in] RgSchUeCb* ue
3151 * @param[in] RgSchDlLcCb* svc
3155 static Void rgSCHSc1DlAdd2UeLcsWithData(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3159 RgSchCmnDlSvc *cmnDlSvc = RG_SCH_CMN_GET_DL_SVC(svc);
3160 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3161 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3162 RgSchCmnDlSvc *cmnDlLstSvc;
3165 lst = &(sc1DlUe->lcsWithData);
3169 cmnDlLstSvc = RG_SCH_CMN_GET_DL_SVC(((RgSchDlLcCb *)(node->node)));
3170 if (cmnDlSvc->prio <= cmnDlLstSvc->prio)
3178 cmLListAdd2Tail(lst, &sc1DlSvc->lcWithDataLnk);
3179 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3184 cmLListInsCrnt(lst, &sc1DlSvc->lcWithDataLnk);
3185 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3192 * @brief This function adds a service to UE's list of lcsWithData.
3196 * Function: rgSCHSc1DlRmFrmUeLcsWithData
3197 * Purpose: 1. This is to maintain a snapshot view of the
3198 * DL SVCs distributions among the cellwide priority
3200 * 2. This snapshot view is maintained in the order
3201 * of priority of the SVCs with in UE.
3202 * 3. Addition of SVC to a cellwide priority Queue
3203 * triggers this function.
3205 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3206 * to cellwide priority Queues.
3208 * @param[in] RgSchUeCb* ue
3209 * @param[in] RgSchDlLcCb* svc
3213 static Void rgSCHSc1DlRmFrmUeLcsWithData(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3215 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3216 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3219 cmLListDelFrm(&(sc1DlUe->lcsWithData), &sc1DlSvc->lcWithDataLnk);
3220 sc1DlSvc->lcWithDataLnk.node = NULLP;
3223 /***************** SC1 DL SCHEDULER FUNCTION DEFNs END HERE ****************/
3225 /***************************************************************************/
3227 /***************** SC1 UL SCHEDULER FUNCTION DEFNs START HERE **************/
3229 /*--------------------------*
3230 * UL specific functions START
3231 *---------------------------*/
3234 * @brief UE Lc Config for RR
3238 * Function : rgSCHSc1UlLchCfg
3240 * Processing Steps: Dummy function
3242 * @param[in] RgrSchCellCb *cell
3243 * @param[in] RgSchUeCb *ue
3244 * @param[in] RgrLchCfg *cfg
3245 * @param[in] RgSchErrInfo *err
3249 S16 rgSCHSc1UlLchCfg
3260 * @brief UE Lc Reconfig for RR
3264 * Function : rgSCHSc1UlLchRecfg
3266 * Processing Steps: Dummy function
3268 * @param[in] RgrSchCellCb *cell
3269 * @param[in] RgSchUeCb *ue
3270 * @param[in] RgrLchRecfg *recfg
3271 * @param[in] RgSchErrInfo *err
3275 S16 rgSCHSc1UlLchRecfg
3286 * @brief LC deletion for PFS
3290 * Function : rgSCHSc1UlLchDel
3292 * Processing Steps: Dummy function
3294 * @param[in] RgrSchCellCb *cell
3295 * @param[in] RgSchUeCb *ue
3296 * @param[in] CmLteLcId lcId
3300 S16 rgSCHSc1UlLchDel(RgSchCellCb *cell,RgSchUeCb *ue,CmLteLcId lcId,uint8_t lcgId)
3306 * @brief This function initializes all the data for the scheduler
3310 * Function: rgSCHSc1UlInit
3311 * Purpose: This function initializes the following information
3312 * 1. Efficiency table
3313 * 2. CQI to table index - It is one row for upto 3 RBs
3314 * and another row for greater than 3 RBs
3316 * currently extended prefix is compiled out.
3317 * Invoked by: MAC intialization code..may be ActvInit
3322 Void rgSCHSc1UlInit(RgUlSchdApis *rgSchUlApis)
3324 /* Init the function pointers */
3325 rgSchUlApis->rgSCHRgrUlUeCfg = rgSCHSc1RgrUlUeCfg;
3326 rgSchUlApis->rgSCHRgrUlUeRecfg = rgSCHSc1RgrUlUeRecfg;
3327 rgSchUlApis->rgSCHFreeUlUe = rgSCHSc1UlUeDel;
3328 rgSchUlApis->rgSCHRgrUlCellCfg = rgSCHSc1RgrUlCellCfg;
3329 rgSchUlApis->rgSCHRgrUlCellRecfg = rgSCHSc1RgrUlCellRecfg;
3330 rgSchUlApis->rgSCHFreeUlCell = rgSCHSc1UlCellDel;
3331 rgSchUlApis->rgSCHRgrUlLcCfg = rgSCHSc1UlLchCfg;
3332 rgSchUlApis->rgSCHRgrUlLcRecfg = rgSCHSc1UlLchRecfg;
3333 rgSchUlApis->rgSCHRgrUlLcgCfg = rgSCHSc1RgrLcgCfg;
3334 rgSchUlApis->rgSCHRgrUlLcgRecfg = rgSCHSc1RgrLcgRecfg;
3335 rgSchUlApis->rgSCHFreeUlLcg = rgSCHSc1LcgDel;
3336 rgSchUlApis->rgSCHRgrUlLchDel = rgSCHSc1UlLchDel;
3337 rgSchUlApis->rgSCHUlSched = rgSCHSc1UlSched;
3338 rgSchUlApis->rgSCHUpdBsrShort = rgSCHSc1UpdBsrShort;
3339 rgSchUlApis->rgSCHUpdBsrTrunc = rgSCHSc1UpdBsrTrunc;
3340 rgSchUlApis->rgSCHUpdBsrLong = rgSCHSc1UpdBsrLong;
3341 rgSchUlApis->rgSCHContResUlGrant = rgSCHSc1ContResUlGrant;
3342 rgSchUlApis->rgSCHSrRcvd = rgSCHSc1SrRcvd;
3343 rgSchUlApis->rgSCHUlCqiInd = rgSCHSc1UlCqiInd;
3344 rgSchUlApis->rgSCHUlUeRefresh = rgSCHSc1UlUeRefresh;
3345 rgSchUlApis->rgSCHUlAllocFnlz = rgSCHSc1UlAllocFnlz;
3346 rgSchUlApis->rgSCHUlInactvtUes = rgSCHSc1UlHndlInActUes;
3347 rgSchUlApis->rgSCHUlActvtUe = rgSCHSc1UlActvtUe;
3348 rgSchUlApis->rgSCHUlUeReset = rgSCHSc1UlUeReset;
3349 rgSchUlApis->rgSCHRgrUlLcgUpd = rgSCHSc1UlLcgUpd;
3354 * @brief UE initialisation for scheduler
3358 * Function : rgSCHSc1RgrUlUeCfg
3360 * This functions intialises UE specific scheduler
3363 * @param[in] RgSchCellCb *cell
3364 * @param[in] RgSchUeCb *ue
3365 * @param[int] RgrUeCfg *ueCfg
3366 * @param[out] RgSchErrInfo *err
3371 S16 rgSCHSc1RgrUlUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg,RgSchErrInfo *err)
3374 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
3376 if(rgSCHUtlAllocSBuf(cell->instIdx,
3377 (Data**)&(ueSchCmn->ul.schSpfc), (sizeof(RgSchSc1UlUe))) != ROK)
3379 DU_LOG("\nERROR --> SCH : Memory allocation FAILED CRNTI:%d",ue->ueId);
3380 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
3385 } /* rgSCHSc1RgrUlUeCfg */
3388 * @brief UE reconfiguration for scheduler
3392 * Function : rgSCHSc1RgrUlUeRecfg
3394 * This functions updates UE specific scheduler
3395 * information upon UE reconfiguration
3397 * @param[in] RgSchCellCb *cell
3398 * @param[in] RgSchUeCb *ue
3399 * @param[int] RgrUeRecfg *ueRecfg
3400 * @param[out] RgSchErrInfo *err
3405 S16 rgSCHSc1RgrUlUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
3408 } /* rgSCHSc1RgrUeRecfg */
3411 * @brief UE deletion for scheduler
3415 * Function : rgSCHSc1UlUeDel
3417 * This functions deletes all scheduler information
3418 * pertaining to a UE
3420 * @param[in] RgSchCellCb *cell
3421 * @param[in] RgSchUeCb *ue
3424 Void rgSCHSc1UlUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
3426 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3427 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3434 if(ueUl->txLnk.node)
3436 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3437 ueUl->txLnk.node = NULLP;
3439 if(ueUl->contResLnk.node)
3441 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
3442 ueUl->contResLnk.node = NULLP;
3444 /* ccpu00117052 - MOD - Passing double pointer
3445 for proper NULLP assignment*/
3446 rgSCHUtlFreeSBuf(cell->instIdx,
3447 (Data**)(&(ueUl)), (sizeof(RgSchSc1UlUe)));
3450 } /* rgSCHSc1UlUeDel */
3453 * @brief UE Reset for scheduler
3457 * Function : rgSCHSc1UlUeReset
3459 * Remove this UE from all Scheduling Priority Qs
3461 * @param[in] RgSchCellCb *cell
3462 * @param[in] RgSchUeCb *ue
3465 Void rgSCHSc1UlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
3467 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3468 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3471 ueUl->srRcvd = FALSE;
3473 if(ueUl->txLnk.node)
3475 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3476 ueUl->txLnk.node = NULLP;
3478 if(ueUl->contResLnk.node)
3480 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
3481 ueUl->contResLnk.node = NULLP;
3484 } /* rgSCHSc1UlUeReset */
3488 * @brief Scheduler processing on cell configuration
3492 * Function : rgSCHSc1RgrUlCellCfg
3494 * This function does requisite initialisation
3495 * and setup for scheduler1 when a cell is
3498 * @param[in] RgSchCellCb *cell
3499 * @param[in] RgrCellCfg *cellCfg
3500 * @param[out] RgSchErrInfo *err
3505 S16 rgSCHSc1RgrUlCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
3507 RgSchSc1UlCell *cellUl;
3509 if((rgSCHUtlAllocSBuf(cell->instIdx,
3510 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->ul.schSpfc), \
3511 (sizeof(RgSchSc1UlCell))) != ROK))
3513 DU_LOG("\nERROR --> SCH : Memory allocation FAILED");
3514 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
3517 cellUl = RG_GET_SC1_CELL_UL(cell);
3518 cmLListInit(&cellUl->contResLst);
3519 cmLListInit(&cellUl->ueTxLst[0]);
3520 cmLListInit(&cellUl->ueTxLst[1]);
3523 } /* rgSCHSc1RgrUlCellCfg */
3527 * @brief This function handles the reconfiguration of cell
3531 * Function: rgSCHSc1RgrUlCellRecfg
3532 * Purpose: Update the reconfiguration parameters.
3534 * Invoked by: Scheduler
3536 * @param[in] RgSchCellCb* cell
3540 S16 rgSCHSc1RgrUlCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
3546 * @brief Scheduler processing for cell delete
3550 * Function : rgSCHSc1UlCellDel
3552 * This functions de-initialises and frees memory
3553 * taken up by scheduler1 for the entire cell.
3555 * @param[in] RgSchCellCb *cell
3558 Void rgSCHSc1UlCellDel(RgSchCellCb *cell)
3560 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3563 if (cellUl == NULLP)
3567 /* ccpu00117052 - MOD - Passing double pointer
3568 for proper NULLP assignment*/
3569 rgSCHUtlFreeSBuf(cell->instIdx,
3570 (Data**)(&(cellUl)), (sizeof(RgSchSc1UlCell)));
3573 } /* rgSCHSc1UlCellDel */
3576 * @brief Scheduler invocation on logical channel Group addition
3580 * Function : rgSCHSc1RgrLcgCfg
3582 * This functions does required processing when a new
3583 * (dedicated) logical channel is added. Assumes lcg
3584 * pointer in ulLc is set.
3586 * @param[in] RgSchCellCb *cell
3587 * @param[in] RgSchUeCb *ue
3588 * @param[in] RgSchLcgCb *lcg
3589 * @param[int] RgrLcgCfg *lcgCfg
3590 * @param[out] RgSchErrInfo *err
3595 S16 rgSCHSc1RgrLcgCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,RgrLcgCfg *lcgCfg,RgSchErrInfo *err)
3598 } /* rgSCHSc1RgrLcgCfg */
3601 * @brief Scheduler invocation on logical channel addition
3605 * Function : rgSCHSc1RgrLcgRecfg
3607 * This functions does required processing when an existing
3608 * (dedicated) logical channel is reconfigured. Assumes lcg
3609 * pointer in ulLc is set to the old value.
3610 * Independent of whether new LCG is meant to be configured,
3611 * the new LCG scheduler info is accessed and possibly modified.
3613 * @param[in] RgSchCellCb *cell,
3614 * @param[in] RgSchUeCb *ue,
3615 * @param[in] RgSchLcgCb *lcg,
3616 * @param[in] RgrLcgRecfg *reCfg,
3617 * @param[out] RgSchErrInfo *err
3622 S16 rgSCHSc1RgrLcgRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,RgrLcgRecfg *reCfg,RgSchErrInfo *err)
3625 } /* rgSCHSc1RgrLcgRecfg */
3627 /***********************************************************
3629 * Func : rgSCHSc1LcgDel
3631 * Desc : Scheduler handling for a (dedicated)
3632 * uplink lcg being deleted
3640 **********************************************************/
3641 Void rgSCHSc1LcgDel(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg)
3643 rgSCHSc1UlPosnUeInQ(cell, ue);
3648 * @brief Perform alloction for this UE
3652 * Function : rgSCHSc1UlSchdUe
3654 * Processing Steps: cater to as much as UE needs, with
3655 * a limitation on maxBits per scheduling instance(per TTI)
3656 * per UE. Return failure, if UE is not considered
3657 * for scheduling (case, where it is already selected for a
3661 * @param[in] RgSchUeCb *ue
3664 static Void rgSCHSc1UlSchdUe(RgSchUeCb *ue,RgSchCellCb *cell)
3666 RgSchCmnUlUe *cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
3667 /*cell added as part of CA dev*/
3668 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
3671 if(ulUe->srRcvd == TRUE)
3673 cmnUlUe->alloc.reqBytes = RGSCH_MAX(RG_SCH_CMN_UL_SR_BYTES, \
3678 cmnUlUe->alloc.reqBytes = ue->ul.effBsr;
3684 * @brief Scheduler invocation
3688 * Function: rgSCHSc1UlSchdForDataTrans
3689 * Purpose: Uplink Scheduling for UE data Transmission.
3692 * Invoked by: Scheduler
3694 * @param[in] RgSchCellCb *cell
3695 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3696 * @param[in] uint8_t remUe
3699 static Void rgSCHSc1UlSchdForDataTrans(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t remUe)
3701 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
3707 /* Allocate UEs with LCG0 data pending */
3708 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[0], allocInfo, &remUe);
3714 /* Allocate UEs with other LCGs data pending */
3715 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[1], allocInfo, &remUe);
3721 * @brief Scheduler invocation
3725 * Function: rgSCHSc1UlSchdUeTxLst
3726 * Purpose: Uplink Scheduling for UE data Transmission.
3729 * Invoked by: Scheduler
3731 * @param[in] CmLListCp *ueTxLst
3732 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3733 * @param[in] uint8_t *remUe
3736 static Void rgSCHSc1UlSchdUeTxLst(RgSchCellCb *cell,CmLListCp *ueTxLst,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t *remUe)
3741 Bool ulAllowed = FALSE;
3745 node = ueTxLst->first;
3746 while ((node) && (*remUe))
3748 ue = (RgSchUeCb *)node->node;
3753 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
3754 if (ulAllowed == FALSE)
3761 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
3763 /* UE already scheduled in this subframe (for retx)
3764 * OR is inactive for UL Transmission.*/
3767 /* Added support for SPS*/
3769 else if (RG_SCH_CMN_IS_SPS_SCHD(ue, cell))
3771 /*-- Already Scheduled by SPS --*/
3776 rgSCHSc1UlSchdUe(ue,cell);/*cell added as part of CA dev*/
3778 rgSCHCmnUlAdd2UeLst(cell, allocInfo, ue);
3787 * @brief Scheduler invocation
3791 * Function: rgSCHSc1UlSchdForContRes
3792 * Purpose: Uplink Scheduling for Contention Resolution.
3795 * Invoked by: Scheduler
3797 * @param[in] RgSchCellCb *cell
3798 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3799 * @param[out] uint8_t *remUe
3802 static Void rgSCHSc1UlSchdForContRes(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t *remUe)
3804 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
3807 RgSchCmnUlUe *cmnUlUe;
3809 Bool ulAllowed = FALSE;
3813 node = sc1UlCell->contResLst.first;
3814 while ((node) && (*remUe))
3816 ue = (RgSchUeCb *)node->node;
3817 cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
3818 /*cell added as part of CA dev*/
3823 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
3824 if (ulAllowed == FALSE)
3830 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
3832 /* UE already scheduled in this subframe (for retx)
3833 * OR is inactive for UL Transmission.*/
3836 cmnUlUe->alloc.reqBytes = RG_SCH_CMN_MAX_UL_CONTRES_GRNT;
3837 rgSCHCmnUlAdd2CntResLst(allocInfo, ue);
3839 /* Node removal deferred to ULAllocFinalization */
3846 * @brief Scheduler invocation
3850 * Function: rgSCHSc1UlNewTx
3851 * Purpose: Uplink Scheduling for New Transmissions.
3854 * Invoked by: Scheduler
3856 * @param[in] RgSchCellCb *cell
3857 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3860 static Void rgSCHSc1UlNewTx(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
3862 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3863 uint8_t remUe = cellUl->maxUeNewTxPerTti;
3866 rgSCHSc1UlSchdForContRes(cell, allocInfo, &remUe);
3867 rgSCHSc1UlSchdForDataTrans(cell, allocInfo, remUe);
3872 * @brief Scheduler invocation
3876 * Function: rgSCHSc1UlSched
3877 * Purpose: This function implements an UL scheduler for LTE. This is
3878 * made available as a function pointer to be called
3879 * at the time of TTI processing by the MAC.
3881 * Invoked by: Common Scheduler (TTI processing)
3883 * @param[in] RgSchCellCb *cell
3884 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3887 Void rgSCHSc1UlSched(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
3889 rgSCHSc1UlNewTx(cell, allocInfo);
3894 * @brief UEs Buffer Status Has changed so reposition it.
3898 * Function : rgSCHSc1UlInsUeInQ
3900 * In UE in the list in Descending order of effBsr.
3903 * @param[in] CmLListCp *lst
3904 * @param[in] RgSchUeCb *ue
3907 static Void rgSCHSc1UlInsUeInQ(CmLListCp *lst,RgSchUeCb *ue,RgSchCellCb *cell)
3909 /*cell added as part of CA dev*/
3910 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3918 lUe = (RgSchUeCb *)(node->node);
3919 if (lUe->ul.effBsr <= ue->ul.effBsr)
3927 /* We have come to the end of the queue, so Append */
3928 cmLListAdd2Tail(lst, &ueUl->txLnk);
3929 ueUl->txLnk.node = (PTR)ue;
3934 cmLListInsCrnt(lst, &ueUl->txLnk);
3935 ueUl->txLnk.node = (PTR)ue;
3941 * @brief UEs Buffer Status Has changed so reposition it.
3945 * Function : rgSCHSc1UlPosnUeInQ
3947 * -Ues bs value for its LCG has changed, due to either
3948 * allocation or BSR report OR the effUeBR, i.e the byteRate
3949 * has changed due to some allocation, so add/reposition/remove
3950 * it from Qs based on this new bs and/or effUeBR value.
3951 * -If UE has non-zero lcg0 bs value, but the byteRate is
3952 * consumed totally, UE is still schedulable for this control data.
3953 * -If UE's LCG0 has pending bs then position this UE in
3955 * -If Ue has pending BSR to be satisfied, but lcg0's BS
3956 * is 0, then position it in ueTxLst[1].
3957 * -In any of these 2 Qs, insertion is such that UEs are
3958 * positioned in Descending order of their Pending BS.
3961 * @param[in] RgSchCellCb *cell
3962 * @param[in] RgSchUeCb *ue
3965 static Void rgSCHSc1UlPosnUeInQ(RgSchCellCb *cell,RgSchUeCb *ue)
3967 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3968 /*cell added as part of CA dev*/
3969 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3970 RgSchCmnLcg *cmnLcg0 = RG_SCH_CMN_GET_UL_LCG(&ue->ul.lcgArr[0]);
3974 if (!RG_SCH_CMN_UL_IS_UE_ACTIVE(ue))
3979 /* Remove the UE from its existing position */
3980 if (ueUl->txLnk.node)
3982 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3983 ueUl->txLnk.node = (PTR)NULLP;
3985 /* If UE has still bs left for scheduling
3986 * then reposition it */
3987 if ((ue->ul.effBsr > 0) || (ueUl->srRcvd == TRUE))
3989 /* Select the Queue where UE would be Placed */
3990 if (cmnLcg0->bs > 0)
3992 lst = &cellUl->ueTxLst[0];
3997 lst = &cellUl->ueTxLst[1];
4000 /* Insert the UE in the Q */
4001 rgSCHSc1UlInsUeInQ(lst, ue, cell);/*cell added as part of CA dev*/
4004 else if(ue->ul.totalBsr != 0)
4006 if (ue->bsrTmr.tmrEvnt != TMR_NONE)
4008 rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue);
4010 if (ue->ul.bsrTmrCfg.isPrdBsrTmrPres)
4012 rgSCHTmrStartTmr(cell, ue, RG_SCH_TMR_BSR,
4013 ue->ul.bsrTmrCfg.prdBsrTmr);
4022 * @brief Short BSR update
4026 * Function : rgSCHSc1UpdBsrShort
4028 * This functions does requisite updates to handle short BSR reporting
4030 * @param[in] RgSchCellCb *cell
4031 * @param[in] RgSchUeCb *ue
4032 * @param[in] RgSchLcgCb *lcg
4033 * @param[in] uint8_t bsr
4036 Void rgSCHSc1UpdBsrShort(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,uint8_t bsr)
4038 rgSCHSc1UlPosnUeInQ(cell, ue);
4040 } /* rgSCHSc1UpdBsrShort */
4043 * @brief Truncated BSR update
4047 * Function : rgSCHSc1UpdBsrTrunc
4049 * This functions does required updates to handle truncated BSR report
4052 * @param[in] RgSchCellCb *cell
4053 * @param[in] RgSchUeCb *ue
4054 * @param[in] RgSchLcgCb *lcg
4055 * @param[in] uint8_t bsr
4058 Void rgSCHSc1UpdBsrTrunc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,uint8_t bsr)
4060 rgSCHSc1UlPosnUeInQ(cell, ue);
4062 } /* rgSCHSc1UpdBsrTrunc */
4065 * @brief Long BSR update
4069 * Function : rgSCHSc1UpdBsrLong
4071 * - Update UE's position within/across uplink scheduling queues
4074 * @param[in] RgSchCellCb *cell
4075 * @param[in] RgSchUeCb *ue
4076 * @param[in] uint8_t bsArr[]
4079 Void rgSCHSc1UpdBsrLong(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t *bsArr)
4081 rgSCHSc1UlPosnUeInQ(cell, ue);
4083 } /* rgSCHSc1UpdBsrLong */
4086 * @brief UL grant for contention resolution
4090 * Function : rgSCHSc1ContResUlGrant
4092 * Add UE to another queue specifically for CRNTI based contention
4096 * @param[in] RgSchCellCb *cell
4097 * @param[in] RgSchUeCb *ue
4100 Void rgSCHSc1ContResUlGrant(RgSchCellCb *cell,RgSchUeCb *ue)
4102 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4103 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4106 if (ueUl->contResLnk.node)
4111 /* Remove the UE from other Qs */
4112 if(ueUl->txLnk.node)
4114 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
4115 ueUl->txLnk.node = NULLP;
4118 cmLListAdd2Tail(&cellUl->contResLst, &ueUl->contResLnk);
4119 ueUl->contResLnk.node = (PTR)ue;
4121 } /* rgSCHSc1ContResUlGrant */
4124 * @brief SR reception handling
4128 * Function : rgSCHSc1SrRcvd
4129 * Shift the UE with SrInd in to the lcgO queue.
4132 * @param[in] RgSchCellCb *cell
4133 * @param[in] RgSchUeCb *ue
4136 Void rgSCHSc1SrRcvd(RgSchCellCb *cell,RgSchUeCb *ue)
4138 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
4139 RgSchSc1UlCell *ulCell = RG_GET_SC1_CELL_UL(cell);
4142 ulUe->srRcvd = TRUE;
4144 if (ulUe->txLnk.node != NULLP)
4148 /* Already present in lcg0 Q */
4151 cmLListDelFrm(&(ulCell->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
4153 /* Adding the UE to the LCG0 list for SR IND */
4154 cmLListAdd2Tail(&ulCell->ueTxLst[0], &ulUe->txLnk);
4155 ulUe->txLnk.node = (PTR)ue;
4159 } /* rgSCHSc1SrRcvd */
4162 * @brief Indication of UL CQI
4166 * Function : rgSCHSc1UlCqiInd
4168 * - Common Scheduler. SC1 does nothing.
4170 * @param[in] RgSchCellCb *cell
4171 * @param[in] RgSchUeCb *ue
4172 * @param[in] TfuUlCqiRpt *ulCqiInfo
4175 Void rgSCHSc1UlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuUlCqiRpt *ulCqiInfo)
4178 /* Stack Crash problem for TRACE5 changes. Added the return below */
4184 * @brief UL Lcg received data updation
4188 * Function : rgSCHSc1UlLcgUpd
4190 * Processing Steps:Sc1 Does nothing
4192 * @param[in] RgSchCellCb *cell
4193 * @param[in] RgSchUeCb *ue
4194 * @param[in] RgInfUeDatInd *datInd
4197 S16 rgSCHSc1UlLcgUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgInfUeDatInd *datInd)
4204 /***********************************************************
4206 * Func : rgSCHSc1UlUeRefresh
4208 * Desc : Handle 'refresh' for uplink part of a UE
4209 * (ie UE's uplink AMBR and uplink GBR LCGs are
4210 * refreshed at this point)
4218 **********************************************************/
4219 Void rgSCHSc1UlUeRefresh(RgSchCellCb *cell,RgSchUeCb *ue)
4221 rgSCHSc1UlPosnUeInQ(cell, ue);
4226 * @brief This function Processes the Final Allocations
4227 * made by the RB Allocator against the requested
4228 * UE data Trans Allocations.
4232 * Function: rgSCHSc1UlDatTransAllocFnlz
4233 * Purpose: This function Processes the Final Allocations
4234 * made by the RB Allocator against the requested
4235 * UE data Trans Allocations .
4237 * Invoked by: Scheduler
4239 * @param[in] RgSchCellCb *cell
4240 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4244 static Void rgSCHSc1UlDatTransAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4249 RgSchDrxUeCb *drxUe = NULLP;
4250 CmLListCp ulInactvLst; /* list of UE's becoming UL-inactive */
4252 cmLListInit(&ulInactvLst);
4253 node = allocInfo->schdUeLst.first;
4256 ue = (RgSchUeCb *)node->node;
4258 ueUl = RG_GET_SC1_UE_UL(ue, cell);
4260 if (ue->isDrxEnabled)
4262 if(ueUl->srRcvd == TRUE)
4264 drxUe = RG_SCH_DRX_GET_UE(ue);
4265 drxUe->drxUlInactvMask |= RG_SCH_DRX_SR_BITMASK;
4267 if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
4269 ue->ul.ulInactvMask |= RG_DRX_INACTIVE;
4270 /* Add to Ul inactive List */
4271 ue->ulDrxInactvLnk.node = (PTR)ue;
4272 cmLListAdd2Tail(&ulInactvLst,&(ue->ulDrxInactvLnk));
4274 drxUe->srRcvd = FALSE;
4277 /* Reset no matter */
4278 ueUl->srRcvd = FALSE;
4279 /* Reposition UE in Qs */
4280 rgSCHSc1UlPosnUeInQ(cell, ue);
4284 rgSCHCmnHdFddUpdULMark (cell,ue);
4287 /* reset the UE UL allocation Information */
4288 rgSCHCmnUlUeResetTemp(cell, ue);
4290 rgSCHSc1UlHndlInActUes(cell, &ulInactvLst);
4291 node = allocInfo->nonSchdUeLst.first;
4294 ue = (RgSchUeCb *)node->node;
4296 /* reset the UE UL allocation Information */
4297 rgSCHCmnUlUeResetTemp(cell, ue);
4304 * @brief This function Processes the Final Allocations
4305 * made by the RB Allocator against the requested
4306 * cont res Allocations.
4310 * Function: rgSCHSc1UlContResAllocFnlz
4311 * Purpose: This function Processes the Final Allocations
4312 * made by the RB Allocator against the requested
4313 * cont res Allocations .
4315 * Invoked by: Scheduler
4317 * @param[in] RgSchCellCb *cell
4318 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4322 static Void rgSCHSc1UlContResAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4324 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
4329 node = allocInfo->schdContResLst.first;
4332 ue = (RgSchUeCb *)node->node;
4337 rgSCHCmnHdFddUpdULMark (cell,ue);
4340 ueUl = RG_GET_SC1_UE_UL(ue, cell);
4342 /* Remove UE from Cont Res Q */
4343 cmLListDelFrm(&sc1UlCell->contResLst,
4345 ueUl->contResLnk.node = NULLP;
4346 /* reset the UE UL allocation Information */
4347 rgSCHCmnUlUeResetTemp(cell, ue);
4350 node = allocInfo->nonSchdContResLst.first;
4353 ue = (RgSchUeCb *)node->node;
4355 /* reset the UE UL allocation Information */
4356 rgSCHCmnUlUeResetTemp(cell, ue);
4363 * @brief This function Processes the Final Allocations
4364 * made by the RB Allocator against the requested.
4368 * Function: rgSCHSc1UlAllocFnlz
4369 * Purpose: This function Processes the Final Allocations
4370 * made by the RB Allocator against the requested.
4372 * Invoked by: Common Scheduler
4374 * @param[in] RgSchCellCb *cell
4375 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4379 Void rgSCHSc1UlAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4382 rgSCHSc1UlContResAllocFnlz(cell, allocInfo);
4383 rgSCHSc1UlDatTransAllocFnlz(cell, allocInfo);
4390 * @brief Scheduler invocation
4394 * Function: rgSCHSc1UlActvtUe
4395 * Purpose: Put back the UE in to appropriate Qs.
4397 * Invoked by: Common Scheduler
4399 * @param[in] RgSchCellCb *cell
4400 * @param[in] RgSchUeCb *ue
4403 Void rgSCHSc1UlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
4406 rgSCHSc1UlPosnUeInQ(cell, ue);
4411 * @brief Scheduler invocation
4415 * Function: rgSCHSc1UlHndlInActUes
4416 * Purpose: The list of inactive UEs present in inactvLst should
4417 * be removed from the scheduling Qs.
4418 * But store the information pertaining to which Qs,
4419 * were they belonging to. This information shall be used
4420 * to put them back in appropriate Qs when their Activation
4423 * Invoked by: Common Scheduler (TTI processing)
4425 * @param[in] RgSchCellCb *cell
4426 * @param[out] CmLListCp *inactvLst
4429 Void rgSCHSc1UlHndlInActUes(RgSchCellCb *cell,CmLListCp *inactvLst)
4433 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4434 CmLList *node = inactvLst->first;
4438 ue = (RgSchUeCb *)node->node;
4440 ulUe = RG_GET_SC1_UE_UL(ue, cell);
4441 if(ulUe->txLnk.node)
4443 cmLListDelFrm(&(cellUl->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
4444 /* This is required as lcg bs might change during
4445 * inactivity to activity. So we need to recompute
4447 ulUe->txLnk.node = NULLP;
4449 /* Do not remove UE from contResLst */
4454 * @brief Scheduler invocation
4458 * Function: rgSCHSc1DlProcRmvFrmRetx
4459 * Purpose: To remove the Harq process from the cell and from the UE
4460 * retransmission list
4462 * Invoked by: Common Scheduler (TTI processing)
4464 * @param[in] RgSchCellCb *cell
4465 * @param[in] RgSchUeCb *ue;
4466 * @param[in] RgSchDlHqProcCb *hqP
4470 Void rgSCHSc1DlProcRmvFrmRetx(
4473 RgSchDlHqProcCb *hqP
4477 /* Remove the HqP from retx Queue.
4479 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
4480 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
4487 /**********************************************************************
4490 **********************************************************************/