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"
49 /* header/extern include files (.x) */
50 #include "tfu.x" /* RGU types */
51 #include "lrg.x" /* layer management typedefs for MAC */
52 #include "rgr.x" /* layer management typedefs for MAC */
53 #include "rgm.x" /* layer management typedefs for MAC */
54 #include "rg_sch_inf.x" /* typedefs for Scheduler */
55 #include "rg_sch.x" /* typedefs for Scheduler */
56 #include "rg_sch_cmn.x"
57 #include "rg_sch_sc1.x" /* typedefs for SC1 Scheduler */
64 #endif /* __cplusplus */
66 /* Functions called from outside */
67 static S16 rgSCHSc1RgrDlCellRecfg ARGS((
73 /*--------------------------*
74 * DL SCHED STATIC declarations START
75 *---------------------------*/
76 static Void rgSCHSc1DlSvcAddToSchd ARGS((
80 static Void rgSCHSc1DlAdd2UeSchdSvcs ARGS((
85 static Void rgSCHSc1DlRmvUeFrmPrioQs ARGS((
89 static Void rgSCHSc1DlSuspendUe ARGS((
93 static Void rgSCHSc1DlInactvtUe ARGS((
97 static Void rgSCHSc1DlProcRmvFrmCellRetx ARGS((
101 static Void rgSCHSc1DlProcRmvFrmUeRetx ARGS((
106 static Void rgSCHSc1DlMngPrio0SvcPosn ARGS((
111 static Void rgSCHSc1DlMngGbrSvcPosn ARGS((
116 static Void rgSCHSc1DlMngAmbrSvcPosn ARGS((
121 static Void rgSCHSc1DlMngSvcPosn ARGS((
126 static Void rgSCHSc1DlUeAddToSchd ARGS((
130 static Void rgSCHSc1DlTaCmd ARGS((
132 RgSchCmnDlRbAllocInfo *allocInfo
134 static Void rgSCHSc1DlInitQueues ARGS((
135 RgSchSc1DlCell *cellDl
137 static Void rgSCHSc1DlDeinitQueues ARGS((
138 RgSchSc1DlCell *cellDl
140 static Void rgSCHSc1DlAdd2UeLcsWithData ARGS((
145 static Void rgSCHSc1DlRmFrmUeLcsWithData ARGS((
150 /*--------------------------*
151 * UL SCHED STATIC declarations START
152 *---------------------------*/
153 static Void rgSCHSc1UlPosnUeInQ ARGS((
157 static Void rgSCHSc1UlSchdUeTxLst ARGS((
160 RgSchCmnUlRbAllocInfo *allocInfo,
163 static Void rgSCHSc1DlProcRmvFrmRetx ARGS((
168 Void rgSCHSc1DlScanUpdPdbPrio ARGS((
171 S16 rgSCHSc1DlFillFlowCntrlInfo ARGS((
173 RgInfSfAlloc *sfAlloc
176 static Void rgSCHSc1DlPreSchd ARGS ((
179 static Void rgSCHSc1DlPstSchd ARGS ((
184 #endif /* __cplusplus */
189 /***************** SC1 DL SCHEDULER FUNCTION DEFNs START HERE ********/
191 /***********************************************************
193 * Func : rgSCHSc1DlUeReset
195 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
196 * and Svc in respective Prio Qs.
205 **********************************************************/
206 Void rgSCHSc1DlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
209 rgSCHSc1DlSuspendUe(cell, ue);
215 /***********************************************************
217 * Func : rgSCHSc1DlActvtUe
219 * Desc : Out of Meas Gap. Reposition the UEs Retx Hq Procs,
220 * and Svc in respective Prio Qs.
229 **********************************************************/
230 Void rgSCHSc1DlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
232 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
235 RgSchDlHqProcCb *hqP;
239 /* Add UE's HqProcs From UERetxLst to CellRetxLst */
240 lst = &ueDl->retxHqProcs;
244 hqP = (RgSchDlHqProcCb *)node->node;
246 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
247 rgSCHSc1DlProcAddToCellRetx(cell, hqP);
250 /* Iterate over all the Services if bo != 0 then add */
251 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
253 svc = ue->dl.lcCb[idx];
258 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
261 /* Add UE to AMBR Prio Q */
264 rgSCHSc1DlUeAddToSchd(cell, ue);
271 /***********************************************************
273 * Func : rgSCHSc1DlUeRefresh
275 * Desc : Handle 'refresh' for Downlink
276 * (ie UE's downlink AMBR and downlink GBR LCGs are
277 * refreshed at this point)
285 **********************************************************/
286 Void rgSCHSc1DlUeRefresh(RgSchCellCb *cell,RgSchUeCb *ue)
288 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
289 /*cell added as part of CA dev*/
290 RgSchCmnDlSvc *svcCmn;
291 RgSchSc1DlSvc *svcSc1;
298 ueDl->ambr = ue->dl.ambrCfgd;
302 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
305 if (ueDl->ambrSvc != NULLP)
307 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, ueDl->ambrSvc->bo);
308 /* Update UEs position in the Queue */
309 rgSCHSc1DlUeAddToSchd(cell, ue);
312 lst = &ueDl->gbrSvcs;
314 while (node != NULLP)
316 svc = (RgSchDlLcCb *)node->node;
317 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
318 svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
320 svcSc1->gbr = svcCmn->gbr;
321 svcSc1->mbr = svcCmn->mbr;
322 /* Update the SVC's positioning in the Queue */
323 rgSCHSc1DlMngGbrSvcPosn(cell, ue, svc);
330 * @brief This function removes a HARQ process from the retx
334 * Function: rgSCHSc1DlProcRmvFrmCellRetx
335 * Purpose: This function removes a HARQ process from retransmission
336 * queue. This may be performed when a HARQ ack is successful
337 * for a retransmission or when the scheduling determines
338 * to throw out the process due to poor conditions
340 * Invoked by: LIM and Scheduler
342 * @param[in] RgSchSc1Cb* cell
343 * @param[in] RgDlHqProc* hqP
347 static Void rgSCHSc1DlProcRmvFrmCellRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
349 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
350 RgSchCmnDlHqProc *hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
352 if (hqProcDl->retxLnk.node != NULLP)
354 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
355 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
356 hqProcDl->retxLnk.node = NULLP;
363 * @brief This function removes a HARQ process from the UE retx
367 * Function: rgSCHSc1DlProcRmvFrmUeRetx
368 * Purpose: This function removes a HARQ process from UE retransmission
371 * Invoked by: LIM and Scheduler
373 * @param[in] RgSchUeCb* ue
374 * @param[in] RgDlHqProc* hqP
378 static Void rgSCHSc1DlProcRmvFrmUeRetx(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
380 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
381 RgSchSc1DlHqProc *hqProcDl = RG_GET_SC1_HQP_DL(hqP);
383 if (hqProcDl->retxLnkUe.node != NULLP)
385 cmLListDelFrm(&sc1Ue->retxHqProcs,
386 &(hqProcDl->retxLnkUe));
387 hqProcDl->retxLnkUe.node = NULLP;
394 * @brief This function adds a HARQ process for UEs retxLst
398 * Function: rgSCHSc1DlProcAddToUeRetx
399 * Purpose: This function adds a HARQ process to UE retransmission
400 * queue. This is performed when UE is suspended due
401 * to measurement gap.
403 * Invoked by: HARQ feedback processing
405 * @param[in] RgSchUeCb* ue
406 * @param[in] RgSchDlHqProc* hqP
410 static Void rgSCHSc1DlProcAddToUeRetx(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqProcCb *hqP)
412 RgSchSc1DlUe *sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
413 RgSchSc1DlHqProc *cmnHqDl = RG_GET_SC1_HQP_DL(hqP);
415 cmLListAdd2Tail(&sc1Ue->retxHqProcs,
416 &(cmnHqDl->retxLnkUe));
417 cmnHqDl->retxLnkUe.node = (PTR)hqP;
423 * @brief This function adds a HARQ process for retx
427 * Function: rgSCHSc1DlProcAddToCellRetx
428 * Purpose: This function adds a HARQ process to retransmission
429 * queue. This may be performed when a HARQ ack is
432 * Invoked by: HARQ feedback processing
434 * @param[in] RgSchCellCb* cell
435 * @param[in] RgSchDlHqProc* hqP
439 Void rgSCHSc1DlProcAddToCellRetx(RgSchCellCb *cell,RgSchDlHqProcCb *hqP)
441 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
442 RgSchCmnDlHqProc *cmnHqDl = RG_SCH_CMN_GET_DL_HQP(hqP);
445 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(hqP->hqE->ue))
447 rgSCHSc1DlProcAddToUeRetx(cell, hqP->hqE->ue, hqP);
450 cmLListAdd2Tail(&sc1CellDl->retxLst[((RgSchSc1DlHqProc *)\
451 (cmnHqDl->schSpfc))->prio], &(cmnHqDl->retxLnk));
452 cmnHqDl->retxLnk.node = (PTR)hqP;
458 * @brief This function implements DL RETRANSMISSION allocation
462 * Function: rgSCHSc1DlRetxAlloc
463 * Purpose: This function implements downlink scheduler's
464 * retransmission allocation.
466 * Invoked by: Scheduler
468 * @param[in] RgSchCellCb *cell
469 * @param[in] RgSchDlSf *subFrm
470 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
474 static Void rgSCHSc1DlRetxAlloc(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchCmnDlRbAllocInfo *allocInfo)
479 RgSchDlHqProcCb *hqP;
480 RgSchSc1DlCell *sc1CellDl;
481 RgSchSc1DlUe *sc1DlUe;
482 RgSchCmnDlUe *cmnUeDl;
483 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
484 CmLteTimingInfo schdTime;
487 RgSchUeCb *ue = NULLP;
489 Bool dlAllowed = FALSE;
491 RgSchDlRbAlloc *dlAllocCb;
493 sc1CellDl = RG_GET_SC1_CELL_DL(cell);
494 #if (defined(LTEMAC_SPS) || (!defined(LTE_TDD)))
495 schdTime = cell->crntTime;
497 /* Increment by DL DELTA to determine the time for which scheduling
499 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
501 for (i = 0; i < RG_SCH_SC1_DL_PRIOS; i++)
503 retxLst = &sc1CellDl->retxLst[i];
504 /* allocate bw for the retransmission..should be same are previous */
505 /* If CQI gets worse, as we cannot find same TB size for another */
506 /* MCS, we just remove this from the retransmission queue */
507 node = retxLst->first;
508 while (node != NULLP)
510 hqP = (RgSchDlHqProcCb *)node->node;
515 if((0 == schdTime.slot) || (5 == schdTime.slot))
518 rgSCHCmnChkRetxAllowDtx(cell, ue, hqP, &reTxAllw);
519 if(FALSE == reTxAllw)
528 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
529 if (dlAllowed == FALSE)
535 /* This UE is already scheduled for transmission */
536 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
537 /*cell added as part of CA dev*/
539 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
544 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
549 /* Extra check: indicate if there is furtherScope for NewTx
550 * addition for a HqProc. This information will
551 * be utilized by common scheduler, in case of SM
552 * UEs with only one of the TBs retransmitting and the
553 * other TB can be used for clubbing new TX. */
554 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
555 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
556 if (sc1DlUe->lcsWithData.first != NULLP)
558 dlAllocCb->mimoAllocInfo.hasNewTxData = TRUE;
560 /* 3.1 MIMO : last parameter changed */
561 if (rgSCHCmnDlAllocRetxRb(cell, subFrm, ue, 0, &effBo, hqP, allocInfo) !=\
564 /* SF/RETX Bandwidth expired */
572 if ((hqP->tbInfo[0].state == HQ_TB_ACKED)
573 && (hqP->tbInfo[1].state == HQ_TB_ACKED))
575 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
580 /* 3.1 MIMO moving this call in cmn scheduler */
581 /*rgSCHCmnDlRbInfoAddUeRetx(allocInfo, ue);*/
587 /***********************************************************
589 * Func : rgSCHSc1RlsHqProc
591 * Desc : Toggles the NDI and releases the harq proc.
599 **********************************************************/
600 static Void rgSCHSc1RlsHqProc(RgSchDlHqProcCb *hqProc)
602 rgSCHDhmRlsHqProc(hqProc);
607 * @brief This function implements dedicated logical channel data scheduling
611 * Function: rgSCHSc1DlDedSvcAlloc
612 * Purpose: This function implements dedicated logical
613 * channel data scheduling
615 * Invoked by: Scheduler
617 * @param[in] RgSchCellCb *cell
618 * @param[in] RgSchDlSf *subFrm
619 * @param[in] RgSchDlLcCb *svc
620 * @param[in] uint32_t bo
621 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
625 static S16 rgSCHSc1DlDedSvcAlloc(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchDlLcCb *svc,uint32_t bo,RgSchCmnDlRbAllocInfo *allocInfo)
628 RgSchDlHqProcCb *proc;
629 uint16_t rlcHdrEstmt;
631 RgSchCmnDlCell *cmnCellDl = RG_SCH_CMN_GET_DL_CELL(cell);
632 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
633 RgSchSc1DlSvc *svcSc1;
635 RgSchSc1DlHqProc *sc1HqDl;
636 RgSchCmnDlHqProc *cmnHqDl;
638 CmLteTimingInfo schdTime;
641 Bool dlAllowed = FALSE;
646 /* Get the UE to which this service belongs to */
651 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
652 if (dlAllowed == FALSE)
658 ueDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
659 /*cell added as part of CA dev*/
661 schdTime = cell->crntTime;
663 /* Increment by DL DELTA to determine the time for which scheduling
665 RGSCH_INCR_SUB_FRAME(schdTime, RG_SCH_CMN_DL_DELTA);
666 if (RG_SCH_CMN_IS_UE_SPS_SCHDLD(ue, cell, schdTime))
671 if (RG_SCH_CMN_IS_UE_SCHDLD(ue, cell))
673 proc = (RgSchDlHqProcCb *)(ueDl->proc);
674 /* This UE is selected for retransmission. Hence no further */
675 /* scheduling may be done for this UE */
676 if (RG_SCH_CMN_PROC_SLCTD_FOR_RETX(proc))
678 DU_LOG("\nERROR --> SCH : CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
679 "Ue retransmitting",ue->ueId);
682 /* UE is scheduled for either other services or TA */
683 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
684 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
685 if (sc1HqDl->prio > svcCmn->prio)
687 sc1HqDl->prio = svcCmn->prio;
690 else /* First consideration of this UE for scheduling */
692 if (rgSCHDhmGetAvlHqProc(cell, ue, cmnCellDl->time, &proc) != ROK)
694 DU_LOG("\nERROR --> SCH : CRNTI:%d rgSCHSc1DlDedSvcAlloc():"
695 " No HARQ Proc available", ue->ueId);
698 sc1HqDl = RG_GET_SC1_HQP_DL(proc);
699 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
700 cmnHqDl->totBytes = 0;
701 /* Initialize some of the parameters of the HQ proc */
702 sc1HqDl->prio = svcCmn->prio;
705 /* Including each SDU's header size */
706 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
709 ret = rgSCHCmnDlAllocTxRb(cell, subFrm, ue, bo, &effBo, proc, allocInfo);
710 if ((ret != ROK) || (effBo == 0))
712 /* If no allocations so far, meaning proc obtained now */
713 if (cmnHqDl->totBytes == 0)
715 rgSCHSc1RlsHqProc(proc);
716 /* Added the handling for removing
717 * UE from txHqPLst and resetting outStndAlloc.*/
718 if(proc->reqLnk.node != (PTR)NULLP)
720 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
721 proc->reqLnk.node = (PTR)NULLP;
723 /*Re-set the outstanding alloc information.*/
724 ueDl->outStndAlloc = 0;
726 /* ccpu00126519: proc should be set to NULLP in UE's DL scratch pad info as well. */
731 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
732 svcSc1->hdrEstimate = rlcHdrEstmt;
733 svcSc1->reqBytes = bo;
735 cmnHqDl->totBytes += effBo;
737 rgSCHSc1DlAdd2UeSchdSvcs(cell, ue, svc);
738 /* 3.1 MIMO moving this call to cmn scheduler */
739 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue); */
744 * @brief This function adds a SVC to UE's schdSvcsLst.
748 * Function: rgSCHSc1DlAdd2UeSchdSvcs
749 * Purpose: This function adds a SVC to UE's schdSvcsLst.
751 * Invoked by: Specific Scheduler
753 * @param[out] RgSchUeCb *ue
754 * @param[in] RgSchDlLcCb *svc
758 static Void rgSCHSc1DlAdd2UeSchdSvcs(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
760 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
761 RgSchSc1DlUe *ueSc1 = RG_GET_SC1_UE_DL(ue, cell);
763 /* checking SVC's presence in this lst is unnecessary */
764 cmLListAdd2Tail(&ueSc1->schdSvcs, &svcSc1->schdSvcLnk);
765 svcSc1->schdSvcLnk.node = (PTR)svc;
771 * @brief This function performs new allocations for UEs
775 * Function: rgSCHSc1DlDedTx
776 * Purpose: This function implements scheduler for DL allocation for
777 * new transmissions of UEs.
778 * 1. It performs across 9 priorities that it supports -
779 * This is from 3GPP specifications
780 * 2. There are known number of GBR/MBR queues
781 * 3. The first queue is highest priority queue and is
782 * satisfied completely prior to any other queues. This
783 * queue is for RRC signalling.
784 * 4. Futher GBR/MBR queues are satisfied for GBR and then MBR
785 * 5. Subsequently all other queues are looked at for AMBR
787 * Invoked by: Scheduler
789 * @param[in] RgSchCellCb* cell
790 * @param[in] RgSchDlSf *subFrm
791 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
795 static Void rgSCHSc1DlDedTx(RgSchCellCb *cell,RgSchDlSf *subFrm,RgSchCmnDlRbAllocInfo *allocInfo)
799 RgSchUeCb *ue = NULLP;
802 RgSchSc1DlSvc *svcSc1;
804 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
807 /* Process the first queue that is for RRC signalling and is of */
808 /* highest priority. */
809 lst = &sc1CellDl->prioLst[0];
813 /* Getting service instead of UE */
814 svc = (RgSchDlLcCb *)node->node;
816 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
818 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->bo, allocInfo) != ROK)
825 /* Perform allocation for the GBR transmissions */
826 for(i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
828 lst = &sc1CellDl->prioLst[i];
832 /* Getting service instead of UE */
833 svc = (RgSchDlLcCb *)node->node;
835 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
837 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, svcSc1->effMbr, allocInfo) != ROK)
845 /* To implement AMBR svc scheduling */
846 for(i = RG_SCH_SC1_DL_GBR_PRIO_END + 1; i < RG_SCH_SC1_DL_PRIOS; i++)
848 lst = &sc1CellDl->prioLst[i];
852 ue = (RgSchUeCb *)node->node;
853 ueDl = RG_GET_SC1_UE_DL(ue, cell);
855 /* Get the Curr ambr svc for which allocation is to be made */
857 if (rgSCHSc1DlDedSvcAlloc(cell, subFrm, svc, ueDl->effAmbr, allocInfo) != ROK)
868 * @brief scheduling for a cell
872 * Function : rgSCHSc1DlPreSchd
875 * - Nothing to be done in case of RR
877 * @param[in] Inst schInst
880 static Void rgSCHSc1DlPreSchd( RgSchCellCb *cell)
886 * @brief scheduling for a cell
890 * Function : rgSCHSc1DlPstSchd
893 * - Nothing to be done in case of RR
895 * @param[in] Inst schInst
898 static Void rgSCHSc1DlPstSchd(Inst schInst)
906 * @brief This function implements scheduler DL allocation
910 * Function: rgSCHSc1DlDedNewTx
911 * Purpose: This function implements scheduler for DL allocation for
914 * Invoked by: Scheduler
916 * @param[in] RgSchCellCb *cell
917 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
921 static Void rgSCHSc1DlDedNewTx(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
923 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
924 DU_LOG("\nDEBUG --> SCH : rgSCHSc1DlDedNewTx\n");
926 /* Now perform the new UE selections */
927 rgSCHSc1DlDedTx(cell, subFrm, allocInfo);
929 /* Stack Crash problem for TRACE5 changes. Added the return below */
934 * @brief This function implements scheduler DL allocation
938 * Function: rgSCHSc1DlDedRetx
939 * Purpose: This function implements scheduler for DL allocation for
942 * Invoked by: Scheduler
944 * @param[in] RgSchCellCb *cell
945 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
949 static Void rgSCHSc1DlDedRetx(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
951 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
952 DU_LOG("\nDEBUG --> SCH : rgSCHSc1DlDedRetx\n");
954 rgSCHSc1DlRetxAlloc(cell, subFrm, allocInfo);
963 * @brief This function adds a service to scheduler
967 * Function: rgSCHSc1DlSvcAddToSchd
968 * Purpose: This function adds a service to the list of services
969 * based on the priority of the services.
971 * Invoked by: BO and Scheduler
973 * @param[in] RgSchCellCb* cell
974 * @param[in] RgSchUeCb* ue
978 static Void rgSCHSc1DlSvcAddToSchd(RgSchCellCb *cell,RgSchDlLcCb *svc)
983 RgSchSc1DlSvc *svcSc1;
984 RgSchSc1DlSvc *lSvcSc1;
985 RgSchSc1DlCell *sc1CellDl = RG_GET_SC1_CELL_DL(cell);
986 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
989 svcSc1 = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
990 /* The service is already in the scheduler */
991 if (svcSc1->prioLnk.node != NULLP)
996 /* If the priority = 0, it is the highest priority with infinite */
997 /* allowance and the priority is time bound and hence just place */
998 /* it at the end of the queue */
999 if (svcCmn->prio == 0)
1001 lst = &(sc1CellDl->prioLst[0]);
1002 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1003 svcSc1->prioLnk.node = (PTR)svc;
1004 /* If a svc is put in to cell wide priority Qs
1005 * then add the same to UE's lcsWithData List */
1006 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1010 /* Handle GBR services. We have them of next importance */
1011 /* check changed from .._START to .._END */
1012 if (svcCmn->prio <= RG_SCH_SC1_DL_GBR_PRIO_END)
1014 if (!RG_SC1_SVC_HAS_DATA(svc,cell))
1016 lst = &(sc1CellDl->prioLst[svcCmn->prio]);
1020 lSvc = (RgSchDlLcCb *)(node->node);
1021 lSvcSc1 = RG_GET_SC1_SVC_DL(lSvc->ue,lSvc,cell);
1022 if (((svcSc1->effGbr > 0) &&
1023 (lSvcSc1->effGbr <= svcSc1->effGbr)) ||
1024 ((lSvcSc1->effGbr == 0) && (svcSc1->effMbr > 0) &&
1025 (lSvcSc1->effMbr <= svcSc1->effMbr)))
1033 /* We have come to the end of the queue. Let's place it */
1034 /* here irresepctive of effGbr or effMBr */
1035 cmLListAdd2Tail(lst, &svcSc1->prioLnk);
1036 svcSc1->prioLnk.node = (PTR)svc;
1041 cmLListInsCrnt(lst, &svcSc1->prioLnk);
1042 svcSc1->prioLnk.node = (PTR)svc;
1044 /* If a svc is put in to cell wide priority Qs
1045 * then add the same to UE's lcsWithData List */
1046 rgSCHSc1DlAdd2UeLcsWithData(cell, svc->ue, svc);
1054 * @brief This function removes a UE from scheduler Queue
1058 * Function: rgSCHSc1DlUeRmvFrmSchd
1059 * Purpose: This function removes a UE from the list of UEs
1060 * based on the priority of the UEs Current AMBR SVC.
1062 * Invoked by: BO and Scheduler
1064 * @param[in] RgSchCellCb* cell
1065 * @param[in] RgSchUeCb* ue
1069 static Void rgSCHSc1DlUeRmvFrmSchd(RgSchCellCb *cell,RgSchUeCb *ue)
1071 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1072 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1076 lst = &cellDl->prioLst[ueDl->prio];
1077 if (ueDl->prioLnk.node != NULLP)
1079 cmLListDelFrm(lst, &ueDl->prioLnk);
1080 ueDl->prioLnk.node = (PTR)NULLP;
1081 /* If a svc is removed from cell wide priority Qs
1082 * then remove the same from UE's lcsWithData List */
1083 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1090 * @brief This function removes a SVC from UEs AMBR LIST
1094 * Function: rgSCHSc1DlSvcRmvFrmUeAmbrLst
1095 * Purpose: This function removes a SVC from UEs AMBR List.
1097 * Invoked by: BO and Scheduler
1099 * @param[in] RgSchUeCb* ue
1100 * @param[in] RgSchDlLcCb* svc
1104 static Void rgSCHSc1DlSvcRmvFrmUeAmbrLst(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1106 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1107 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1110 lst = &ueDl->ambrLst;
1111 if (svcSc1->prioLnk.node != NULLP)
1113 cmLListDelFrm(lst, &svcSc1->prioLnk);
1114 svcSc1->prioLnk.node = (PTR)NULLP;
1121 * @brief This function adds a SVC to UEs AMBR LIST
1125 * Function: rgSCHSc1DlSvcAddToUeAmbrLst
1126 * Purpose: This function adds a SVC to UEs AMBR List.
1128 * Invoked by: BO and Scheduler
1130 * @param[in] RgSchUeCb* ue
1131 * @param[in] RgSchDlLcCb* svc
1135 static Void rgSCHSc1DlSvcAddToUeAmbrLst(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1137 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1140 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1141 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1144 /* If svc already present in AMBR List return */
1145 if (svcSc1->prioLnk.node != NULLP)
1148 node = ueDl->ambrLst.first;
1151 lsvc = (RgSchDlLcCb *)(node->node);
1152 if (((RgSchCmnDlSvc*)(lsvc->sch))->prio > svcCmn->prio)
1160 cmLListAdd2Tail(&ueDl->ambrLst, &svcSc1->prioLnk);
1161 svcSc1->prioLnk.node = (PTR)svc;
1165 ueDl->ambrLst.crnt = node;
1166 cmLListInsCrnt(&ueDl->ambrLst, &svcSc1->prioLnk);
1167 svcSc1->prioLnk.node = (PTR)svc;
1175 * @brief This function removes a service from scheduler
1179 * Function: rgSCHSc1DlSvcRmvFrmSchd
1180 * Purpose: This function removes the SVC from the scheduler Qs.
1182 * Invoked by: BO and Scheduler
1184 * @param[in] RgSchCellCb* cell
1185 * @param[in] RgSchUeCb* ue
1189 static Void rgSCHSc1DlSvcRmvFrmSchd(RgSchCellCb *cell,RgSchDlLcCb *svc)
1191 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1192 RgSchSc1DlSvc *svcDl = RG_GET_SC1_SVC_DL(svc->ue,svc,cell);
1193 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1197 lst = &(cellDl->prioLst[svcCmn->prio]);
1198 if (svcDl->prioLnk.node != NULLP)
1200 cmLListDelFrm(lst, &svcDl->prioLnk);
1201 svcDl->prioLnk.node = NULLP;
1202 /* If a svc is removed from cell wide priority Qs
1203 * then remove the same from UE's lcsWithData List */
1204 rgSCHSc1DlRmFrmUeLcsWithData(cell, svc->ue, svc);
1211 * @brief This function adds a service to scheduler for a UE
1215 * Function: rgSCHSc1DlSvcAdd
1216 * Purpose: This function is made available through a FP for
1217 * making scheduler aware of a service added to UE
1219 * Invoked by: BO and Scheduler
1221 * @param[in] RgSchUeCb* ue
1222 * @param[in] RgSchDlLcCb* svc
1223 * @param[in] CrgDlLchCfg* qos
1227 static Void rgSCHSc1DlSvcAdd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc,RgrDlLchCfg *cfg)
1229 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1230 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1231 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1235 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1237 svcSc1->gbr = svcCmn->gbr;
1238 svcSc1->mbr = svcCmn->mbr;
1239 cmLListAdd2Tail(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1240 svcSc1->gbrLnk.node = (PTR)svc;
1247 * @brief This function deletes a service from scheduler
1251 * Function: rgSCHSc1DlLcRmv
1252 * Purpose: This function is made available through a FP for
1253 * making scheduler aware of a service being deleted from UE
1255 * Invoked by: BO and Scheduler
1257 * @param[in] RgSchCellCb* cell
1258 * @param[in] RgSchUeCb* ue
1259 * @param[in] RgSchDlLcCb* svc
1263 Void rgSCHSc1DlLcRmv(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1266 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1267 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1270 if (svcSc1 == NULLP)
1274 ueDl = RG_GET_SC1_UE_DL(ue, cell);
1276 if (svcCmn->prio == 0)
1278 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1280 else if (RG_SCH_CMN_SVC_IS_GBR(svc))
1282 if (svcSc1->gbrLnk.node != NULLP)
1284 cmLListDelFrm(&ueDl->gbrSvcs, &svcSc1->gbrLnk);
1285 svcSc1->gbrLnk.node = NULLP;
1287 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1289 else /* if AMBR service */
1291 if (ueDl->ambrSvc == svc)
1293 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1294 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1295 ueDl->ambrSvc = NULLP;
1296 if (ueDl->ambrLst.first != NULLP)
1298 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1299 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svc->bo);
1302 rgSCHSc1DlUeAddToSchd(cell, ue);
1308 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1311 /* ccpu00117052 - MOD - Passing double pointer
1312 for proper NULLP assignment*/
1313 rgSCHUtlFreeSBuf(cell->instIdx,
1314 (Data**)(&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,svc,cell))), (sizeof(RgSchSc1DlSvc)));
1319 * @brief This function is invoked as part of SVC reconfig
1323 * Function: rgSCHSc1DlSvcMod
1324 * Purpose: This function is made available through a FP for
1325 * making scheduler aware of a service reconfiguration.
1327 * Invoked by: Scheduler
1329 * @param[in] RgSchDlLcCb* svc
1330 * @param[in] CrgLchRecfg* recfg
1334 static Void rgSCHSc1DlSvcMod(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc,RgrLchRecfg *recfg)
1336 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1337 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1339 if (RG_SCH_CMN_SVC_IS_GBR(svc))
1341 /* Convert the QOS to handle the refresh duration */
1342 svcSc1->gbr = svcCmn->gbr;
1343 svcSc1->mbr = svcCmn->mbr;
1349 * @brief This function adds UE to scheduler for an AMBR service
1353 * Function: rgSCHSc1DlUeAddToSchd
1354 * Purpose: This function adds a UE to scheduler for the AMBR
1355 * service of highest priority.
1357 * Invoked by: BO and Scheduler
1359 * @param[in] RgSchCellCb* cell
1360 * @param[in] RgSchUeCb* ue
1364 static Void rgSCHSc1DlUeAddToSchd(RgSchCellCb *cell,RgSchUeCb *ue)
1366 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1367 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1368 RgSchSc1DlUe *lueDl;
1371 RgSchUeCb *nodeUe = NULLP;
1373 ueDl->prio = ((RgSchCmnDlSvc *)(ueDl->ambrSvc->sch))->prio;
1374 lst = &cellDl->prioLst[ueDl->prio];
1375 /* if UE already in list, remove and
1377 if (ueDl->prioLnk.node != NULLP)
1379 cmLListDelFrm(lst, &ueDl->prioLnk);
1380 ueDl->prioLnk.node = NULLP;
1381 /* If a svc is removed from cell wide priority Qs
1382 * then remove the same from UE's lcsWithData List */
1383 rgSCHSc1DlRmFrmUeLcsWithData(cell, ue, ueDl->ambrSvc);
1388 nodeUe = (RgSchUeCb *)(node->node);
1389 lueDl = RG_GET_SC1_UE_DL(nodeUe, cell);
1390 if (lueDl->effAmbr < ueDl->effAmbr)
1396 cmLListAdd2Tail(lst, &ueDl->prioLnk);
1397 ueDl->prioLnk.node = (PTR)ue;
1402 cmLListInsCrnt(lst, &ueDl->prioLnk);
1403 ueDl->prioLnk.node = (PTR)ue;
1405 /* If a svc is put in to cell wide priority Qs
1406 * then add the same to UE's lcsWithData List */
1407 rgSCHSc1DlAdd2UeLcsWithData(cell, ue, ueDl->ambrSvc);
1413 * @brief This function implements managing BO for an ABMR service
1417 * Function: rgSCHSc1DlMngAmbrSvcPosn
1418 * Purpose: This function should be called whenever there is a
1419 * change BO for a AMBR service.
1421 * Invoked by: BO and Scheduler
1423 * @param[in] RgSchCellCb* cell
1424 * @param[in] RgSchUeCb* ue
1425 * @param[in] RgSchDlLcCb* svc
1429 static Void rgSCHSc1DlMngAmbrSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1431 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1432 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1434 if (svcSc1->bo == 0)
1436 if (ueDl->ambrSvc == svc)
1438 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1439 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1440 ueDl->ambrSvc = NULLP;
1441 if (ueDl->ambrLst.first != NULLP)
1443 ueDl->ambrSvc = (RgSchDlLcCb *)(ueDl->ambrLst.first->node);
1444 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1447 rgSCHSc1DlUeAddToSchd(cell, ue);
1453 rgSCHSc1DlSvcRmvFrmUeAmbrLst(cell, ue, svc);
1456 else /* svcSc1->bo != 0 */
1458 if (svcSc1->prioLnk.node != NULLP)
1460 if (svc == ueDl->ambrSvc)
1462 ueDl->effAmbr = RGSCH_MIN(svcSc1->bo, ueDl->ambr);
1463 /* Update UE's position in the scheduler */
1466 rgSCHSc1DlUeAddToSchd(cell, ue);
1470 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1475 rgSCHSc1DlSvcAddToUeAmbrLst(cell, ue, svc);
1476 /* Current ambr svc is always the first node of ambrLst.*/
1477 if (ueDl->ambrLst.first->node == (PTR)svc)
1479 if(ueDl->ambrSvc != svc)
1483 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1485 ueDl->ambrSvc = svc;
1486 ueDl->effAmbr = RGSCH_MIN(ueDl->ambr, svcSc1->bo);
1489 rgSCHSc1DlUeAddToSchd(cell, ue);
1499 * @brief This function updates the scheduler with service for a UE
1503 * Function: rgSCHSc1DlLcBoUpd
1504 * Purpose: This function should be called whenever there is a
1505 * change BO for a service.
1507 * Invoked by: BO and Scheduler
1509 * @param[in] RgSchCellCb* cell
1510 * @param[in] RgSchUeCb* ue
1511 * @param[in] RgSchDlLcCb* svc
1515 Void rgSCHSc1DlLcBoUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1517 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1519 if (svcSc1->bo == svc->bo)
1523 svcSc1->bo = svc->bo;
1524 if (!RG_SCH_CMN_DL_IS_UE_ACTIVE(ue))
1528 rgSCHSc1DlMngSvcPosn(cell, ue, svc);
1530 /* Stack Crash problem for TRACE5 changes. Added the return below */
1537 * @brief This function updates the scheduler with Prio0 service for a UE
1541 * Function: rgSCHSc1DlMngPrio0SvcPosn
1542 * Purpose: This func shall be triggered whenever there is a
1543 * change in the "Bo yet to be satisfied" field of the service.
1544 * Appropriately positions the svc in its prio Q.
1545 * Removes the SVC from the Q if BO is completely satisfied.
1547 * Invoked by: BO and Scheduler
1549 * @param[in] RgSchCellCb* cell
1550 * @param[in] RgSchUeCb* ue
1551 * @param[in] RgSchDlLcCb* svc
1555 static Void rgSCHSc1DlMngPrio0SvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1557 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1559 /* In this priority, we just add or remove to the queue */
1562 rgSCHSc1DlSvcAddToSchd(cell, svc);
1566 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1573 * @brief This function updates the scheduler with GBR service for a UE
1577 * Function: rgSCHSc1DlMngGbrSvcPosn
1578 * Purpose: This func shall be triggered whenever there is a
1579 * change in the "Bo yet to be satisfied" field of the service.
1580 * Appropriately positions the svc in its prio Q.
1581 * Removes the SVC from the Q if BO is completely satisfied.
1583 * Invoked by: BO and Scheduler
1585 * @param[in] RgSchCellCb* cell
1586 * @param[in] RgSchUeCb* ue
1587 * @param[in] RgSchDlLcCb* svc
1591 static Void rgSCHSc1DlMngGbrSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1593 RgSchSc1DlSvc *svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
1595 /* Handle a GBR service. */
1596 svcSc1->effGbr = RGSCH_MIN(svcSc1->bo, svcSc1->gbr);
1597 svcSc1->effMbr = RGSCH_MIN(svcSc1->bo, svcSc1->mbr);
1598 /* Adjust the SVC priority within the queue */
1599 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1600 rgSCHSc1DlSvcAddToSchd(cell, svc);
1606 * @brief This function updates the scheduler with service for a UE
1610 * Function: rgSCHSc1DlMngSvcPosn
1611 * Purpose: This func shall be triggered whenever there is a
1612 * change in the "Bo yet to be satisfied" field of the service.
1613 * Appropriately positions the svc in its prio Q.
1614 * Removes the SVC from the Q if BO is completely satisfied.
1616 * Invoked by: BO and Scheduler
1618 * @param[in] RgSchCellCb* cell
1619 * @param[in] RgSchUeCb* ue
1620 * @param[in] RgSchDlLcCb* svc
1624 static Void rgSCHSc1DlMngSvcPosn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
1626 RgSchCmnDlSvc *svcCmn = RG_SCH_CMN_GET_DL_SVC(svc);
1627 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1629 (cellDl->svcMngFunc[svcCmn->prio])(cell, ue, svc);
1633 /*--------------------------*
1634 * DL specific functions END
1635 *---------------------------*/
1640 * @brief Scheduler processing on cell configuration
1644 * Function : rgSCHSc1RgrDlCellCfg
1646 * This function does requisite initialisation
1647 * and setup for scheduler1 when a cell is
1650 * @param[in] RgSchCellCb *cell
1651 * @param[in] RgrCellCfg *cellCfg
1652 * @param[out] RgSchErrInfo *err
1657 S16 rgSCHSc1RgrDlCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
1660 RgSchSc1DlCell *cellDl;
1662 if((ret = rgSCHUtlAllocSBuf(cell->instIdx,
1663 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc), \
1664 (sizeof(RgSchSc1DlCell)))) != ROK)
1666 DU_LOG("\nERROR --> SCH : Memory allocation FAILED");
1667 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
1671 cellDl = RG_GET_SC1_CELL_DL(cell);
1672 /* Now perform downlink Queues related initializations */
1673 rgSCHSc1DlInitQueues(cellDl);
1675 } /* rgSCHSc1RgrDlCellCfg */
1677 /***********************************************************
1679 * Func : rgSCHSc1DlDeinitQueues
1681 * Desc : De-initialise downlink scheduler queues
1689 **********************************************************/
1690 static Void rgSCHSc1DlDeinitQueues(RgSchSc1DlCell *cellDl)
1694 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
1696 cmLListInit(&cellDl->prioLst[i]);
1697 cmLListInit(&cellDl->retxLst[i]);
1704 * @brief Scheduler processing for cell delete
1708 * Function : rgSCHSc1DlCellDel
1710 * This functions de-initialises and frees memory
1711 * taken up by scheduler1 for the entire cell.
1713 * @param[in] RgSchCellCb *cell
1716 Void rgSCHSc1DlCellDel(RgSchCellCb *cell)
1719 if (((RgSchSc1DlCell *)((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc) \
1725 /* Perform the deinit for the DL scheduler */
1726 rgSCHSc1DlDeinitQueues(RG_GET_SC1_CELL_DL(cell));
1727 /* ccpu00117052 - MOD - Passing double pointer
1728 for proper NULLP assignment*/
1729 rgSCHUtlFreeSBuf(cell->instIdx,
1730 (Data**)(&(((RgSchCmnCell*)((cell)->sc.sch))->dl.schSpfc)),
1731 (sizeof(RgSchSc1DlCell)));
1733 } /* rgSCHSc1DlCellDel */
1736 * @brief UE initialisation for scheduler
1740 * Function : rgSCHSc1RgrDlUeCfg
1742 * This functions intialises UE specific scheduler
1745 * @param[in] RgSchCellCb *cell
1746 * @param[in] RgSchUeCb *ue
1747 * @param[int] RgrUeCfg *ueCfg
1748 * @param[out] RgSchErrInfo *err
1753 S16 rgSCHSc1RgrDlUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg,RgSchErrInfo *err)
1755 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
1756 Inst inst = cell->instIdx;
1760 if((rgSCHUtlAllocSBuf(inst,
1761 (Data**)&(ueSchCmn->dl.schSpfc), (sizeof(RgSchSc1DlUe))) != ROK))
1763 DU_LOG("\nERROR --> SCH : Memory allocation FAILED"
1764 "CRNTI:%d",ue->ueId);
1765 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
1768 ueDl = (RgSchSc1DlUe *)ueSchCmn->dl.schSpfc;
1769 if (ue->dl.ambrCfgd)
1771 ueDl->ambr = ue->dl.ambrCfgd;
1775 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
1777 cmLListInit(&ueDl->lcsWithData);
1778 cmLListInit(&ueDl->gbrSvcs);
1779 cmLListInit(&ueDl->ambrLst);
1780 cmLListInit(&ueDl->schdSvcs);
1781 cmLListInit(&ueDl->retxHqProcs);
1783 } /* rgSCHSc1RgrDlUeCfg */
1787 * @brief Dl Harq Entity initialization for SC1
1791 * Function : rgSCHSc1DlUeHqEntInit
1794 * - Create SC1 related information per Harq Entity
1796 * @param[in] RgrSchCellCb *cell
1797 * @param[in] RgSchUeCb *ue
1802 S16 rgSCHSc1DlUeHqEntInit(RgSchCellCb *cell,RgSchDlHqEnt *hqEnt)
1804 RgSchSc1DlHqProc *hqSpcSch;
1805 RgSchDlHqProcCb *hqP;
1807 /* making use of hqE->sch for one shot allocation
1808 * of RgSchSc1DlHqProc structures */
1809 if (rgSCHUtlAllocSBuf(cell->instIdx,
1810 (Data**)&(hqEnt->sch),
1811 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc))) != ROK)
1813 DU_LOG("\nERROR --> SCH : Memory allocation FAILED CRNTI:%d",hqEnt->ue->ueId);
1816 hqSpcSch = (RgSchSc1DlHqProc *)(hqEnt->sch);
1817 for(cnt = 0; cnt < hqEnt->numHqPrcs; cnt++)
1819 hqP = &hqEnt->procs[cnt];
1820 ((RgSchCmnDlHqProc *)((hqP)->sch))->schSpfc = \
1827 * @brief Dl Harq Entity deletion for Sc1
1831 * Function : rgSCHSc1DlUeHqEntDeInit
1834 * - Free SC1 related information per Harq Entity
1836 * @param[in] RgrSchCellCb *cell
1837 * @param[in] RgSchDlHqEnt *hqE
1840 S16 rgSCHSc1DlUeHqEntDeInit(RgSchCellCb *cell,RgSchDlHqEnt *hqE)
1845 rgSCHUtlFreeSBuf(cell->instIdx,
1846 (Data**)(&(hqE->sch)),
1847 (hqE->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
1856 * @brief UE reconfiguration for scheduler
1860 * Function : rgSCHSc1RgrDlUeRecfg
1862 * This functions updates UE specific scheduler
1863 * information upon UE reconfiguration
1865 * @param[in] RgSchCellCb *cell
1866 * @param[in] RgSchUeCb *ue
1867 * @param[int] RgrUeRecfg *ueRecfg
1868 * @param[out] RgSchErrInfo *err
1873 S16 rgSCHSc1RgrDlUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
1875 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
1876 RgSchCmnDlUe *ueCmnDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
1877 /*cell added as part of CA dev*/
1878 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1880 if (ue->dl.ambrCfgd)
1882 ueDl->ambr = ue->dl.ambrCfgd;
1886 ueDl->ambr = RG_SC1_MAX_DL_AMBR;
1889 /* Discarding TB2's context from scheduling Queues.
1890 * Since TB2 transmission needs signalling using
1891 * TM specific formats. And since during this transient
1892 * period of UE TM Recfg, SCH always uses Format 1A,
1893 * the TB2s are discarded. */
1894 if (ueCmnDl->mimoInfo.forceTD & RG_SCH_CMN_TD_TXMODE_RECFG)
1896 /* If HqP is in retx queue only for TB2 retx scheduling
1897 * then remove the harp proc from retx Queue */
1899 /* If Hqp is in retx queue for retx allocation of
1900 * both TB1 and TB2, then reset TB2's state as ACKED */
1901 RgSchDlHqProcCb *hqP;
1903 RgInfRlsHqInfo *rlsHqBufs = &(cell->rlsHqArr[cell->crntHqIdx]);
1906 /* Prepare TB2 release information to be sent to MAC */
1907 rlsHqBufs->numUes = 0;
1908 for(i = 0; i < hqEnt->numHqPrcs; i++)
1910 hqP = &hqEnt->procs[i];
1911 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].rnti = ue->ueId;
1912 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].hqProcId = hqP->procId;
1913 if (hqP->tbInfo[1].state == HQ_TB_NACKED)
1915 if (hqP->tbInfo[0].state != HQ_TB_NACKED)
1917 /* Remove the HqP from retx Queue.
1919 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
1920 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
1922 rgSCHDhmRlsHqpTb(hqP, 1, TRUE);
1923 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].tbId[0] = 2;
1924 rlsHqBufs->ueHqInfo[rlsHqBufs->numUes].numOfTBs = 1;
1926 rlsHqBufs->numUes++;
1928 /* Send the hqProc list for MAC to clear TB1 contents */
1929 if (rlsHqBufs->numUes)
1931 rgSCHUtlGetPstToLyr(&pst, &rgSchCb[cell->instIdx], cell->macInst);
1932 RgSchMacRlsHq (&pst, rlsHqBufs);
1936 } /* rgSCHSc1RgrDlUeRecfg */
1939 * @brief Removes UEs context from Priority Qs.
1943 * Function : rgSCHSc1DlRmvUeFrmPrioQs
1946 * @param[in] RgSchCellCb *cell
1947 * @param[in] RgSchUeCb *ue
1950 static Void rgSCHSc1DlRmvUeFrmPrioQs(RgSchCellCb *cell,RgSchUeCb *ue)
1952 RgSchSc1DlUe *sc1Ue;
1957 sc1Ue = RG_GET_SC1_UE_DL(ue, cell);
1959 /* Remove UE From DL priority queues */
1960 if (sc1Ue->ambrSvc != NULLP)
1962 rgSCHSc1DlUeRmvFrmSchd(cell, ue);
1965 for (idx = 0; idx < RGSCH_MAX_LC_PER_UE; ++idx)
1967 svc = ue->dl.lcCb[idx];
1972 rgSCHSc1DlSvcRmvFrmSchd(cell, svc);
1976 } /* rgSCHSc1DlRmvUeFrmPrioQs */
1979 * @brief Inactivate UE reason : measgap, acknaprept, poInactv.
1983 * Function : rgSCHSc1DlInactvtUe
1986 * @param[in] RgSchCellCb *cell
1987 * @param[in] RgSchUeCb *ue
1990 static Void rgSCHSc1DlInactvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
1992 RgSchSc1DlCell *cellDl = RG_GET_SC1_CELL_DL(cell);
1993 RgSchDlHqProcCb *hqP;
1994 RgSchCmnDlHqProc *hqProcDl;
1996 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
1999 /* ccpu00130170: UE related HARQ Procs are cleared only
2000 if UE's Re-establishment procedure is not in progress*/
2001 if(!(ue->dl.dlInactvMask & RG_HQENT_INACTIVE))
2003 /* remove all in use HARQ processes from the subframes.
2004 * Store them in UEs hqProc Lst. Add back to cell's
2005 * retx lst when UE is activated again. */
2006 for(i = 0; i < hqEnt->numHqPrcs; i++)
2008 hqP = &hqEnt->procs[i];
2009 hqProcDl = RG_SCH_CMN_GET_DL_HQP(hqP);
2010 /* Remove retx procs from cell's list and
2011 * add them to UE's List */
2014 !(RG_SCH_CMN_SPS_DL_IS_SPS_HQP(hqP)) &&
2016 hqProcDl->retxLnk.node != NULLP)
2018 cmLListDelFrm(&cellDl->retxLst[((RgSchSc1DlHqProc *)\
2019 (hqProcDl->schSpfc))->prio], &(hqProcDl->retxLnk));
2020 hqProcDl->retxLnk.node = NULLP;
2021 rgSCHSc1DlProcAddToUeRetx(cell, ue, hqP);
2026 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2029 } /* rgSCHSc1DlInactvtUe */
2033 * @brief UE suspension.
2037 * Function : rgSCHSc1DlSuspendUe
2039 * Removes UE, its SVCs and its HqPs from CELL WIDE
2040 * PrioQs and Retx Qs Respectively.
2042 * @param[in] RgSchCellCb *cell
2043 * @param[in] RgSchUeCb *ue
2046 static Void rgSCHSc1DlSuspendUe(RgSchCellCb *cell,RgSchUeCb *ue)
2048 RgSchDlHqProcCb *hqP;
2051 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2054 /* remove all in use HARQ processes from the subframes.
2055 * Store them in UEs hqProc Lst. Add back to cell's
2056 * retx lst when UE is activated again. */
2057 for(i = 0; i < hqEnt->numHqPrcs; i++)
2059 hqP = &hqEnt->procs[i];
2060 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2061 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
2062 /* Removing the Harq Proc from subframes list */
2063 if (hqP->hqPSfLnk.node != NULLP)
2067 cmLListDelFrm(&hqP->subFrm->pdcchInfo.pdcchs,
2069 cmLListAdd2Tail(&cell->pdcchLst, &hqP->pdcch->lnk);
2073 rgSCHUtlDlHqPTbRmvFrmTx(hqP->subFrm,hqP,0,FALSE);
2075 for (j = 0; j < 2; j++)
2077 if (hqP->tbInfo[j].state == HQ_TB_WAITING)
2079 rgSCHDhmRlsHqpTb(hqP, j, TRUE);
2084 rgSCHSc1DlRmvUeFrmPrioQs(cell, ue);
2087 } /* rgSCHSc1DlSuspendUe */
2089 /***********************************************************
2091 * Func : rgSCHSc1DlScanUpdPdbPrio
2093 * Desc : Increment the pivot and reposition the LCs under the pivot to
2094 * new location according to thieir PDB and elapsed time.
2102 **********************************************************/
2103 Void rgSCHSc1DlScanUpdPdbPrio(RgSchCellCb *cell)
2110 * @brief Function to update Flow control information
2111 * to be sent to MAC.
2115 * Function: rgSCHSc1DlFillFlowCntrlInfo
2117 * update Flow control information
2124 * @param[in] RgSchCellCb *cell
2125 RgInfSfAlloc *sfAlloc;
2129 S16 rgSCHSc1DlFillFlowCntrlInfo(RgSchCellCb *cell,RgInfSfAlloc *sfAlloc)
2134 * @brief UE deletion for scheduler
2138 * Function : rgSCHSc1DlUeDel
2140 * This functions deletes all scheduler information
2141 * pertaining to a UE
2143 * @param[in] RgSchCellCb *cell
2144 * @param[in] RgSchUeCb *ue
2147 Void rgSCHSc1DlUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
2149 RgSchDlHqEnt *hqEnt = RG_SCH_CMN_GET_UE_HQE(ue, cell);
2150 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
2153 if (sc1DlUe == NULLP)
2159 /* Remove UEs scheduler context */
2160 rgSCHSc1DlSuspendUe(cell, ue);
2162 /* Free all SC1 specific control blocks */
2163 if (hqEnt->sch != NULLP)
2165 /* ccpu00117052 - MOD - Passing double pointer
2166 for proper NULLP assignment*/
2167 rgSCHUtlFreeSBuf(cell->instIdx,
2168 (Data**)(&(hqEnt->sch)),
2169 (hqEnt->numHqPrcs * sizeof(RgSchSc1DlHqProc)));
2173 /* ccpu00117052 - MOD - Passing double pointer
2174 for proper NULLP assignment*/
2175 rgSCHUtlFreeSBuf(cell->instIdx, (Data**)(&sc1DlUe), (sizeof(RgSchSc1DlUe)));
2178 } /* rgSCHSc1DlUeDel */
2181 * @brief Scheduler invocation on Downlink logical channel addition
2185 * Function : rgSCHSc1RgrLcCfg
2187 * This functions does required processing when a new
2188 * (dedicated) logical channel is added.
2190 * @param[in] RgSchCellCb *cell
2191 * @param[in] RgSchUeCb *ue
2192 * @param[in] RgSchDlLcCb *dlLc
2193 * @param[int] RgrLchCfg *lcCfg
2194 * @param[out] RgSchErrInfo *err
2199 S16 rgSCHSc1RgrLcCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchCfg *lcCfg,RgSchErrInfo *err)
2203 ret = rgSCHUtlAllocSBuf(cell->instIdx,
2204 (Data**)&(RG_SCH_CMN_GET_LC_SCH_SPFC(ue,dlLc,cell)), \
2205 (sizeof(RgSchSc1DlSvc)));
2208 DU_LOG("\nERROR --> SCH : rgSCHSc1CrgLcCfg():"
2209 "SCH struct alloc failed CRNTI:%d LCID:%d",ue->ueId,lcCfg->lcId);
2210 err->errCause = RGSCHERR_SCH_SC1_DL_CFG;
2214 rgSCHSc1DlSvcAdd(cell, ue, dlLc, &lcCfg->dlInfo);
2216 } /* rgSCHSc1RgrLcCfg */
2220 * @brief Scheduler invocation on logical channel addition
2224 * Function : rgSCHSc1RgrLcRecfg
2226 * This functions does required processing when an existing
2227 * (dedicated) logical channel is reconfigured. Assumes lcg
2228 * pointer in ulLc is set to the old value.
2229 * Independent of whether new LCG is meant to be configured,
2230 * the new LCG scheduler info is accessed and possibly modified.
2232 * @param[in] RgSchCellCb *cell
2233 * @param[in] RgSchUeCb *ue
2234 * @param[in] RgSchDlLcCb *dlLc
2235 * @param[int] RgrLchRecfg *lcRecfg
2236 * @param[out] RgSchErrInfo *err
2241 S16 rgSCHSc1RgrLcRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *dlLc,RgrLchRecfg *lcRecfg,RgSchErrInfo *err)
2246 rgSCHSc1DlSvcMod(cell,ue,dlLc, lcRecfg);
2249 } /* rgSCHSc1RgrLcRecfg */
2253 * @brief This function handles the reconfiguration of cell
2257 * Function: rgSCHSc1RgrDlCellRecfg
2258 * Purpose: Update the reconfiguration parameters.
2260 * Invoked by: Scheduler
2262 * @param[in] RgSchCellCb* cell
2266 static S16 rgSCHSc1RgrDlCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
2274 * @brief This function implements scheduler DL allocation
2278 * Function: rgSCHSc1DlTaCmd
2279 * Purpose: This function implements scheduler for TA cmd alloc for
2280 * UEs. The hq proc availed as part of this alloc can be used
2281 * by the UEs Dedicated CH transmission allocation.
2283 * Invoked by: Scheduler
2285 * @param[in] RgSchCellCb* cell
2286 * @param[out] RgSchCmnDlRbAllocInfo *allocInfo
2290 static Void rgSCHSc1DlTaCmd(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2294 RgSchDlHqProcCb *proc;
2297 RgSchCmnDlCell *cellCmnDl = RG_SCH_CMN_GET_DL_CELL(cell);
2298 RgSchCmnDlUe *cmnUeDl;
2300 RgSchCmnDlHqProc *cmnHqDl;
2301 RgSchDlSf *subFrm = allocInfo->dedAlloc.dedDlSf;
2303 Bool dlAllowed = FALSE;
2306 lst = &cellCmnDl->taLst;
2310 ue = (RgSchUeCb *)node->node;
2315 rgSCHCmnHdFddChkDlAllow ( cell, ue, &dlAllowed);
2316 if (dlAllowed == FALSE)
2322 /* If Ue is inactive in DL then ignore */
2323 if (ue->dl.dlInactvMask)
2327 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2328 /*cell added as part of CA dev*/
2329 ueDl = RG_GET_SC1_UE_DL(ue, cell);
2331 if (rgSCHDhmGetAvlHqProc(cell, ue, cellCmnDl->time, &proc) != ROK)
2335 /* Initialize some of the parameters of the HQ proc */
2336 cmnHqDl = RG_SCH_CMN_GET_DL_HQP(proc);
2340 cmnHqDl->totBytes = 0;
2341 rgSCHCmnDlAllocTxRb(cell, subFrm, ue, RGSCH_TA_SIZE, &effBo, proc, allocInfo);
2344 /* If no allocations so far, meaning proc obtained now */
2345 if (cmnHqDl->totBytes == 0)
2347 rgSCHSc1RlsHqProc(proc);
2348 /* Added the handling for removing
2349 * UE from txHqPLst and resetting outStndalloc.*/
2350 if(proc->reqLnk.node != (PTR)NULLP)
2352 cmLListDelFrm(&allocInfo->dedAlloc.txHqPLst, &proc->reqLnk);
2353 proc->reqLnk.node = (PTR)NULLP;
2355 /*Re-set the outstanding alloc information.*/
2356 cmnUeDl->outStndAlloc = 0;
2358 /* Avl BW could not satisfy even TA so break */
2361 ueDl->taReqBytes = RGSCH_TA_SIZE;
2362 cmnUeDl->proc = proc;
2363 cmnHqDl->totBytes += effBo;
2364 /* 3.1 MIMO moving this call to cmn scheduler */
2365 /*rgSCHCmnDlRbInfoAddUeTx(allocInfo, ue);*/
2371 * @brief Scheduler invocation
2375 * Function: rgSCHSc1DlHndlInActUes
2376 * Purpose: The list of inactive UEs present in inactvLst should
2377 * be removed from the scheduling Qs.
2379 * Invoked by: Common Scheduler (TTI processing)
2381 * @param[in] RgSchCellCb *cell
2382 * @param[out] CmLListCp *inactvLst
2385 Void rgSCHSc1DlHndlInActUes(RgSchCellCb *cell,CmLListCp *inactvLst)
2390 node = inactvLst->first;
2393 ue = (RgSchUeCb *)node->node;
2395 /* Suspend this UE from further scheduling
2396 * till it is activated again. */
2397 rgSCHSc1DlInactvtUe(cell, ue);
2403 * @brief This function initializes all the data for the scheduler
2407 * Function: rgSCHSc1DlInit
2408 * Purpose: This function initializes the following information
2409 * 1. Efficiency table
2410 * 2. CQI to table index - It is one row for upto 3 RBs
2411 * and another row for greater than 3 RBs
2413 * currently extended prefix is compiled out.
2414 * Invoked by: MAC intialization code..may be ActvInit
2419 Void rgSCHSc1DlInit(RgDlSchdApis *rgSchDlApis)
2421 /* Init the function pointers */
2422 rgSchDlApis->rgSCHRgrDlUeCfg = rgSCHSc1RgrDlUeCfg;
2423 rgSchDlApis->rgSCHRgrDlUeRecfg = rgSCHSc1RgrDlUeRecfg;
2424 rgSchDlApis->rgSCHFreeDlUe = rgSCHSc1DlUeDel;
2425 rgSchDlApis->rgSCHRgrDlCellCfg = rgSCHSc1RgrDlCellCfg;
2426 rgSchDlApis->rgSCHRgrDlCellRecfg = rgSCHSc1RgrDlCellRecfg;
2427 rgSchDlApis->rgSCHFreeDlCell = rgSCHSc1DlCellDel;
2428 rgSchDlApis->rgSCHRgrDlLcCfg = rgSCHSc1RgrLcCfg;
2429 rgSchDlApis->rgSCHRgrDlLcRecfg = rgSCHSc1RgrLcRecfg;
2430 rgSchDlApis->rgSCHFreeDlLc = rgSCHSc1DlLcRmv;
2431 rgSchDlApis->rgSCHDlNewSched = rgSCHSc1DlDedNewTx;
2432 rgSchDlApis->rgSCHDlPreSched = rgSCHSc1DlPreSchd;
2433 rgSchDlApis->rgSCHDlPstSched = rgSCHSc1DlPstSchd;
2434 rgSchDlApis->rgSCHDlRetxSched = rgSCHSc1DlDedRetx;
2435 rgSchDlApis->rgSCHDlCeSched = rgSCHSc1DlTaCmd;
2436 rgSchDlApis->rgSCHDlDedBoUpd = rgSCHSc1DlLcBoUpd;
2437 rgSchDlApis->rgSCHDlProcAddToRetx = rgSCHSc1DlProcAddToCellRetx;
2438 rgSchDlApis->rgSCHDlAllocFnlz = rgSCHSc1DlAllocFnlz;
2439 rgSchDlApis->rgSCHDlCqiInd = rgSCHSc1DlCqiInd;
2440 rgSchDlApis->rgSCHDlUeRefresh = rgSCHSc1DlUeRefresh;
2441 rgSchDlApis->rgSCHDlUeReset = rgSCHSc1DlUeReset;
2442 rgSchDlApis->rgSCHDlActvtUe = rgSCHSc1DlActvtUe;
2443 rgSchDlApis->rgSCHDlInactvtUes = rgSCHSc1DlHndlInActUes;
2444 rgSchDlApis->rgSCHDlUeHqEntInit = rgSCHSc1DlUeHqEntInit;
2445 rgSchDlApis->rgSCHDlUeHqEntDeInit = rgSCHSc1DlUeHqEntDeInit;
2446 rgSchDlApis->rgSCHDlProcRmvFrmRetx = rgSCHSc1DlProcRmvFrmRetx;
2447 rgSchDlApis->rgSCHDlTickForPdbTrkng = rgSCHSc1DlScanUpdPdbPrio;
2448 rgSchDlApis->rgSCHDlFillFlwCtrlInfo = rgSCHSc1DlFillFlowCntrlInfo;
2456 /***********************************************************
2458 * Func : rgSCHSc1DlInitQueues
2460 * Desc : Initial downlink scheduler queues
2468 **********************************************************/
2469 static Void rgSCHSc1DlInitQueues(RgSchSc1DlCell *cellDl)
2473 for (i = 0; i < RG_SC1_DL_NUM_Q; ++i)
2475 cmLListInit(&cellDl->prioLst[i]);
2476 cmLListInit(&cellDl->retxLst[i]);
2478 /* Set appropriate "manage svc positioning" function based on
2479 * svc priority as array index */
2481 for (i = 0; i < RG_SCH_SC1_DL_GBR_PRIO_START; i++)
2483 cellDl->svcMngFunc[i] = rgSCHSc1DlMngPrio0SvcPosn;
2486 for (i = RG_SCH_SC1_DL_GBR_PRIO_START; i <= RG_SCH_SC1_DL_GBR_PRIO_END; i++)
2488 cellDl->svcMngFunc[i] = rgSCHSc1DlMngGbrSvcPosn;
2490 /* for Non-GBR svcs */
2491 for (i = RG_SCH_SC1_DL_GBR_PRIO_END+1; i <= RG_SCH_CMN_MAX_PRIO; i++)
2493 cellDl->svcMngFunc[i] = rgSCHSc1DlMngAmbrSvcPosn;
2502 * @brief This function Processes the Final Allocations
2503 * made by the RB Allocator against the requested
2508 * Function: rgSCHSc1DlRetxAllocFnlz
2509 * Purpose : Remove the Retx Hq Proc from the Cell's
2510 * Retx list, if allocation is successful.
2511 * Fill the HqProc and PDCCH and append it to the SubFrm.
2515 * Invoked by: Common Scheduler
2517 * @param[in] RgSchCellCb *cell
2518 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
2522 static Void rgSCHSc1DlRetxAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2526 RgSchDlHqProcCb *hqP;
2527 RgSchDlRbAlloc *dlAllocCb = NULLP;
2529 node = allocInfo->dedAlloc.schdRetxHqPLst.first;
2532 hqP = (RgSchDlHqProcCb *)node->node;
2535 /* Fill PDCCH and assign it to HqP */
2536 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
2538 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
2542 rgSCHCmnHdFddUpdDLMark(cell, ue);
2545 /* Extra Check: Retain the hqProc in the RETX Queue if one/more
2546 * TBs of the HqProc are yet to be scheduled for RETX.
2547 * Note: Here we are not tracking at TB Level, the priority Q
2548 * to which it belongs to. The retx prio of transmission is still
2549 * being maintained at hqProc level, rather than at TB level */
2550 if ((hqP->tbInfo[0].state != HQ_TB_NACKED) &&
2551 (hqP->tbInfo[1].state != HQ_TB_NACKED)) {
2552 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
2554 /* reset the UE allocation Information */
2555 rgSCHCmnDlUeResetTemp(ue, hqP);
2558 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
2559 node = allocInfo->dedAlloc.nonSchdRetxHqPLst.first;
2562 hqP = (RgSchDlHqProcCb *)node->node;
2565 /* reset the UE allocation Information */
2566 rgSCHCmnDlUeResetTemp(ue, hqP);
2571 /* 3.1 MIMO Alloc distribution functions being performed
2575 /***********************************************************
2577 * Func : rgSCHSc1DlSprTxTbDstn
2579 * Desc : Perform Actual allocation distribution among
2580 * UEs schd svcs and TA for a given spare TB "tbInfo" allocation.
2581 * spare TB allocation is as a result of 1 RETX TB allocation, when
2582 * conditions are favourable for 2 TB spatial multiplexing.
2590 **********************************************************/
2591 static Void rgSCHSc1DlSprTxTbDstn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqTbCb *tbInfo,uint32_t *effAlloc,CmLList **node)
2594 RgSchSc1DlSvc *svcSc1;
2595 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2597 RgSchLchAllocInfo lchSchdData;
2599 uint32_t rlcHdrEstmt;
2602 while((*node) && (*effAlloc > 0))
2604 svc = (RgSchDlLcCb *)(*node)->node;
2605 *node = (*node)->next;
2606 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
2608 RG_SCH_CMN_DL_GET_HDR_EST(svc, rlcHdrEstmt);
2609 /* Update the SVC QOS Param */
2610 if (RG_SCH_CMN_SVC_IS_GBR(svc))
2612 effBo = svcSc1->effMbr + rlcHdrEstmt;
2613 bytes = RGSCH_MIN(*effAlloc, effBo);
2614 /* Determine How much BO is satisfied */
2615 if (bytes <= rlcHdrEstmt)
2619 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2621 (svcSc1->bo -= bytes-rlcHdrEstmt);
2622 svc->bo = svcSc1->bo;
2626 /* Increment qciActiveLCs once since this LCs buffer will be present
2628 if (svc->lcType == CM_LTE_LCH_DTCH)
2630 ue->qciActiveLCs[svc->qciCb->qci]++;
2633 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
2635 if (ue->qciActiveLCs[svc->qciCb->qci])
2637 ue->qciActiveLCs[svc->qciCb->qci]--;
2639 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
2641 svc->qciCb->dlUeCount--;
2645 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
2646 (svcSc1->gbr -= bytes);
2647 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
2648 (svcSc1->mbr -= bytes);
2650 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
2652 effBo = ueDl->effAmbr + rlcHdrEstmt;
2653 bytes = RGSCH_MIN(*effAlloc, effBo);
2654 /* Determine How much BO is satisfied */
2655 if (bytes <= rlcHdrEstmt)
2659 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2661 (svcSc1->bo -= bytes-rlcHdrEstmt);
2663 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
2664 (ueDl->ambr -= bytes);
2666 else /* Prio 0 SVC */
2668 effBo = svcSc1->bo + rlcHdrEstmt;
2669 bytes = RGSCH_MIN(*effAlloc, effBo);
2670 /* Determine How much BO is satisfied */
2671 if (bytes <= rlcHdrEstmt)
2675 (svcSc1->bo <= bytes-rlcHdrEstmt)?\
2677 (svcSc1->bo -= bytes-rlcHdrEstmt);
2679 /* Position the service accordingly */
2680 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
2681 /* Update effAlloc */
2684 /* Update DHM for this SVC */
2685 lchSchdData.lcId = svc->lcId;
2686 lchSchdData.schdData = bytes;
2687 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
2693 /***********************************************************
2695 * Func : rgSCHSc1DlNewTxTbDstn
2697 * Desc : Perform Actual allocation distribution among
2698 * UEs schd svcs and TA for a given TB "tbInfo" allocation.
2699 * Assumption: TA is given higher priority in Alloc Distribution.
2707 **********************************************************/
2708 static Void rgSCHSc1DlNewTxTbDstn(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlHqTbCb *tbInfo,uint32_t *effAlloc,CmLList **node)
2711 RgSchSc1DlSvc *svcSc1 = NULLP;
2712 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2714 RgSchLchAllocInfo lchSchdData;
2715 CmLList *prev = NULLP;
2718 if (ueDl->taReqBytes)
2720 if (ueDl->taReqBytes < *effAlloc)
2722 /*TA satisfied, hence remove from TA Lst */
2723 rgSCHCmnRmvFrmTaLst(cell, ue);
2724 /* Indicate to DHM that TA has been scheduled */
2725 rgSCHDhmSchdTa(ue, tbInfo);
2726 *effAlloc -= ueDl->taReqBytes;
2728 /* Reset the TA Req Bytes Field */
2729 ueDl->taReqBytes = 0;
2731 while((*node) && (*effAlloc > 0))
2733 svc = (RgSchDlLcCb *)(*node)->node;
2735 *node = (*node)->next;
2736 svcSc1 = RG_GET_SC1_SVC_DL(ue,svc,cell);
2737 if (*effAlloc > svcSc1->reqBytes)
2739 bytes = svcSc1->reqBytes;
2740 if (bytes <= svcSc1->hdrEstimate)
2744 /* 3.1 MIMO updating the reqBytes field */
2745 svcSc1->reqBytes = 0;
2751 if (bytes <= svcSc1->hdrEstimate)
2755 /* 3.1 MIMO updating the reqBytes field */
2756 svcSc1->reqBytes -= bytes;
2757 (svcSc1->bo <= bytes-svcSc1->hdrEstimate)?\
2759 (svcSc1->bo -= bytes-svcSc1->hdrEstimate);
2761 svc->bo = svcSc1->bo;
2766 /* Increment qciActiveLCs once since this LCs buffer will be present
2768 if (svc->lcType == CM_LTE_LCH_DTCH)
2770 ue->qciActiveLCs[svc->qciCb->qci]++;
2773 if ((svc->bo == 0) && (svc->lcType == CM_LTE_LCH_DTCH))
2775 if (ue->qciActiveLCs[svc->qciCb->qci])
2777 ue->qciActiveLCs[svc->qciCb->qci]--;
2779 if (!(ue->qciActiveLCs[svc->qciCb->qci]))
2781 svc->qciCb->dlUeCount--;
2786 /* Update the SVC QOS Param */
2787 if (RG_SCH_CMN_SVC_IS_GBR(svc))
2789 (svcSc1->gbr <= bytes)? (svcSc1->gbr = 0):
2790 (svcSc1->gbr -= bytes);
2791 (svcSc1->mbr <= bytes)? (svcSc1->mbr = 0):
2792 (svcSc1->mbr -= bytes);
2794 else if(RG_SCH_CMN_SVC_IS_AMBR(svc))
2796 (ueDl->ambr <= bytes)? (ueDl->ambr = 0):
2797 (ueDl->ambr -= bytes);
2799 /* Position the service accordingly */
2800 rgSCHSc1DlMngSvcPosn(cell, svc->ue, svc);
2801 /* Update effAlloc */
2804 /* Update DHM for this SVC */
2805 lchSchdData.lcId = svc->lcId;
2806 lchSchdData.schdData = bytes;
2807 rgSCHDhmAddLcData(cell->instIdx, &lchSchdData, tbInfo);
2809 /* If no more scheduled LCs for TB data distribution
2810 * then distribute the spare TB data among the LCs
2811 * of the UE with non-zero BO. This is effective for
2812 * schedulers work on LC level priorities rather than
2814 if ((*node == NULLP) && (svcSc1) && (svcSc1->reqBytes == 0))
2816 rgSCHSc1DlSprTxTbDstn(cell, ue, tbInfo, effAlloc,
2817 &ueDl->lcsWithData.first);
2821 /* make sure node points to the svc not completely
2823 * make sure if not served completely then
2824 * the other TB allocation accomodates the same */
2831 /***********************************************************
2833 * Func : rgSCHSc1DlNewTxUeFnlz
2835 * Desc : Perform allocation Distribution from scheduled TB
2836 * among the list of services considered for scheduling.
2844 **********************************************************/
2845 static Void rgSCHSc1DlNewTxUeFnlz (RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo,RgSchUeCb *ue)
2848 RgSchSc1DlUe *ueDl = RG_GET_SC1_UE_DL(ue, cell);
2849 RgSchCmnDlUe *cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2850 /*cell added as part of CA dev*/
2851 /* 3.1 MIMO Distribute data of each TB across services */
2852 RgSchDlRbAlloc *dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
2853 uint32_t remTb1Bytes = dlAllocCb->tbInfo[0].bytesAlloc;
2854 uint32_t remTb2Bytes = dlAllocCb->tbInfo[1].bytesAlloc;
2855 uint32_t effAlloc = 0;
2856 /*ccpu00120365-ADD-added to code to check if second TB is utilized */
2857 uint32_t tb2Bytes = 0;
2861 /* 3.1 MIMO Consider the allocation of New TX TB for distribution */
2862 /* Handle schd services */
2863 node = ueDl->schdSvcs.first;
2865 effAlloc += remTb1Bytes;
2866 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[0],\
2867 &remTb1Bytes, &node);
2868 /* In the event that TB1 is not completely filled by the DL LCs
2869 * BO, consider the reducing the iMcs for increasing redundancy
2870 * and hence reception quality at UE */
2871 rgSCHCmnRdcImcsTxTb(dlAllocCb, 0,
2872 dlAllocCb->tbInfo[0].bytesAlloc - remTb1Bytes);
2875 /*ccpu00120365-ADD-assigning value of remTb2Bytes before utilization */
2876 tb2Bytes = remTb2Bytes;
2878 /* Extra check for a non SM UE allocation */
2880 effAlloc += remTb2Bytes;
2881 rgSCHSc1DlNewTxTbDstn(cell, ue, &cmnUeDl->proc->tbInfo[1],\
2882 &remTb2Bytes, &node);
2883 /* In the event that TB2 is not completely filled by the DL LCs
2884 * BO, consider the reducing the iMcs for increasing redundancy
2885 * and hence reception quality at UE */
2886 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1,
2887 dlAllocCb->tbInfo[1].bytesAlloc - remTb2Bytes);
2890 /* ccpu00120365-ADD-Disable the second TB as the second TB is not
2892 if ( remTb2Bytes && ( tb2Bytes == remTb2Bytes) )
2894 dlAllocCb->mimoAllocInfo.precIdxInfo = 0;
2895 dlAllocCb->mimoAllocInfo.numTxLyrs = 1;
2896 dlAllocCb->tbInfo[1].schdlngForTb = FALSE;
2897 dlAllocCb->tbInfo[1].isDisabled = TRUE;
2900 if (effAlloc == (remTb1Bytes + remTb2Bytes))
2902 /* Allocation such that Nothing could be satisfied */
2903 /* Return the grabbed PDCCH */
2904 rgSCHUtlPdcchPut(cell, &dlAllocCb->dlSf->pdcchInfo,
2906 rgSCHSc1RlsHqProc(cmnUeDl->proc);
2910 /* Fill PDCCH and assign it to HqP */
2911 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, cmnUeDl->proc);
2918 * @brief This function Processes the Final Allocations
2919 * made by the RB Allocator against the requested
2920 * New TX allocations.
2924 * Function: rgSCHSc1DlNewTxAllocFnlz
2925 * Purpose : Distribute the allocation among the Scheduled SVCs.
2926 * Fill pdcch and HqP for UEs will allocations.
2927 * Release HqP for UE with no allocation.
2929 * Invoked by: Common Scheduler
2931 * @param[in] RgSchCellCb *cell
2932 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
2936 static Void rgSCHSc1DlNewTxAllocFnlz (RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
2940 RgSchCmnDlUe *cmnUeDl;
2941 RgSchDlHqProcCb *hqP;
2943 node = allocInfo->dedAlloc.schdTxHqPLst.first;
2946 hqP = (RgSchDlHqProcCb *)node->node;
2949 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue,cell);
2950 /*cell added as part of CA dev*/
2952 rgSCHSc1DlNewTxUeFnlz(cell, allocInfo, ue);
2956 rgSCHCmnHdFddUpdDLMark(cell, ue);
2959 /* reset the UE allocation Information */
2960 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
2961 rgSCHCmnDlUeResetTemp(ue, hqP);
2964 /* Traverse the nonSchdTxUeLst and reset the UE allocation Info */
2965 node = allocInfo->dedAlloc.nonSchdTxHqPLst.first;
2968 hqP = (RgSchDlHqProcCb *)node->node;
2971 cmnUeDl = RG_SCH_CMN_GET_DL_UE(ue, cell);
2973 /* Release HqProc */
2974 rgSCHSc1RlsHqProc(hqP);
2975 /* reset the UE allocation Information */
2976 cmLListInit(&((RgSchSc1DlUe *)(cmnUeDl->schSpfc))->schdSvcs);
2977 rgSCHCmnDlUeResetTemp(ue, hqP);
2982 /* 3.1 Added new function to handle TX+RETX alloc fnlz'n */
2985 * @brief This function Processes the Final Allocations
2986 * made by the RB Allocator against the requested
2987 * RETX+New TX allocations. The NewTx TB allocation
2988 * is considered for distribution among LCs.
2992 * Function: rgSCHSc1DlRetxNewTxAllocFnlz
2993 * Purpose : 1. Reached here due to 1 RETX TB allocation for a
2994 * SM UE, which is capable to accomodate a newTX
2996 * 2. Distribute NewTX TB allocation among the
2997 * SVCs present in lcsWithData list of UE.
3000 * Invoked by: Common Scheduler
3002 * @param[in] RgSchCellCb *cell
3003 * @param[in] RgSchCmnDlRbAllocInfo *cellAllocInfo
3007 static Void rgSCHSc1DlRetxNewTxAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *cellAllocInfo)
3011 RgSchSc1DlUe *sc1DlUe;
3012 RgSchDlHqProcCb *hqP;
3013 RgSchDlHqTbCb *newTxTbInfo;
3015 uint32_t remTbBytes;
3016 RgSchDlRbAlloc *ueAllocInfo;
3017 RgSchDlRbAlloc *dlAllocCb;
3020 node = cellAllocInfo->dedAlloc.schdTxRetxHqPLst.first;
3023 hqP = (RgSchDlHqProcCb *)node->node;
3026 sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3027 ueAllocInfo = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3028 dlAllocCb = RG_SCH_CMN_GET_ALLOCCB_FRM_UE(ue, cell);
3029 /* Index 0 of ueAllocInfo->tbInfo will always hold the
3030 * RETX TB and index 1 will hold the NewTX TB in case of
3031 * RETX+TX allocation. */
3032 newTxTbInfo = ueAllocInfo->tbInfo[1].tbCb;
3033 effAlloc = remTbBytes = ueAllocInfo->tbInfo[1].bytesAlloc;
3034 rgSCHSc1DlSprTxTbDstn(cell, ue, newTxTbInfo,\
3035 &remTbBytes, &(sc1DlUe->lcsWithData.first));
3036 /* Trying to reduce mcs of TX TB to increase reception quality at UE.
3037 * In case of RETX+TX allocation, TX TB allocation was irrespective
3038 * of actual requirement by UE, hence in case if consumption is
3039 * less than allocation, consider reducing the iMcs of this TX TB. */
3040 rgSCHCmnRdcImcsTxTb(dlAllocCb, 1, effAlloc - remTbBytes);
3041 /* 3.1 MIMO Remove/Retain from/in cell RETX List */
3042 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
3043 /* Fill PDCCH and assign it to HqP */
3044 rgSCHCmnFillHqPPdcch(cell, dlAllocCb, hqP);
3048 rgSCHCmnHdFddUpdDLMark(cell, ue);
3051 /* reset the UE allocation Information */
3052 rgSCHCmnDlUeResetTemp(ue, hqP);
3055 /* Traverse the nonSchdTxRetxHqPLst and reset the UE allocation Info */
3056 node = cellAllocInfo->dedAlloc.nonSchdTxRetxHqPLst.first;
3059 hqP = (RgSchDlHqProcCb *)node->node;
3062 /* reset the UE allocation Information */
3063 rgSCHCmnDlUeResetTemp(ue, hqP);
3069 * @brief This function Processes the Final Allocations
3070 * made by the RB Allocator against the requested.
3074 * Function: rgSCHSc1DlAllocFnlz
3075 * Purpose: This function Processes the Final Allocations
3076 * made by the RB Allocator against the requested.
3077 * 1. Loop through scheduled TX and RETX lists.
3078 * Fill in the corresponding PDCCH and HqProcs.
3079 * In case of TX If actual Alloc < requested, then perform
3080 * an appropriate distribution among the schdSvcs.
3081 * If TA is satisfied, then remove UE from TA Lst.
3082 * 2. Loop through UnScheduled TX and RETX Lists.
3083 * Release grabbed HqProcs.
3084 * Put back SVCs from schdSvcsLst to their corresponding Qs.
3087 * Invoked by: Common Scheduler
3089 * @param[in] RgSchCellCb *cell
3090 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
3094 Void rgSCHSc1DlAllocFnlz(RgSchCellCb *cell,RgSchCmnDlRbAllocInfo *allocInfo)
3097 rgSCHSc1DlRetxAllocFnlz(cell, allocInfo);
3099 rgSCHSc1DlNewTxAllocFnlz(cell, allocInfo);
3101 /*3.1 MIMO new Function added to handle TX+RETX
3102 * harq process scheduling finalization */
3103 rgSCHSc1DlRetxNewTxAllocFnlz(cell, allocInfo);
3110 * @brief This function Updates the DL CQI for the UE.
3114 * Function: rgSCHSc1DlCqiInd
3115 * Purpose: Updates the DL CQI for the UE
3117 * Invoked by: Common Scheduler. SC1 does nothing.
3119 * @param[in] RgSchCellCb *cell
3120 * @param[in] RgSchUeCb *ue
3121 * @param[in] TfuDlCqiRpt *dlCqiRpt
3125 Void rgSCHSc1DlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,Bool isPucchInfo,Void *dlCqi)
3132 * @brief This function adds a service to UE's list of lcsWithData.
3136 * Function: rgSCHSc1DlAdd2UeLcsWithData
3137 * Purpose: 1. This is to maintain a snapshot view of the
3138 * DL SVCs distributions among the cellwide priority
3140 * 2. This snapshot view is maintained in the order
3141 * of priority of the SVCs with in UE.
3142 * 3. Addition of SVC to a cellwide priority Queue
3143 * triggers this function.
3145 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3146 * to cellwide priority Queues.
3148 * @param[in] RgSchUeCb* ue
3149 * @param[in] RgSchDlLcCb* svc
3153 static Void rgSCHSc1DlAdd2UeLcsWithData(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3157 RgSchCmnDlSvc *cmnDlSvc = RG_SCH_CMN_GET_DL_SVC(svc);
3158 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3159 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3160 RgSchCmnDlSvc *cmnDlLstSvc;
3163 lst = &(sc1DlUe->lcsWithData);
3167 cmnDlLstSvc = RG_SCH_CMN_GET_DL_SVC(((RgSchDlLcCb *)(node->node)));
3168 if (cmnDlSvc->prio <= cmnDlLstSvc->prio)
3176 cmLListAdd2Tail(lst, &sc1DlSvc->lcWithDataLnk);
3177 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3182 cmLListInsCrnt(lst, &sc1DlSvc->lcWithDataLnk);
3183 sc1DlSvc->lcWithDataLnk.node = (PTR)svc;
3190 * @brief This function adds a service to UE's list of lcsWithData.
3194 * Function: rgSCHSc1DlRmFrmUeLcsWithData
3195 * Purpose: 1. This is to maintain a snapshot view of the
3196 * DL SVCs distributions among the cellwide priority
3198 * 2. This snapshot view is maintained in the order
3199 * of priority of the SVCs with in UE.
3200 * 3. Addition of SVC to a cellwide priority Queue
3201 * triggers this function.
3203 * Invoked by: Functions of DL SC1 which add SVC or UE(for ambr svc)
3204 * to cellwide priority Queues.
3206 * @param[in] RgSchUeCb* ue
3207 * @param[in] RgSchDlLcCb* svc
3211 static Void rgSCHSc1DlRmFrmUeLcsWithData(RgSchCellCb *cell,RgSchUeCb *ue,RgSchDlLcCb *svc)
3213 RgSchSc1DlSvc *sc1DlSvc = RG_GET_SC1_SVC_DL(ue,svc,cell);
3214 RgSchSc1DlUe *sc1DlUe = RG_GET_SC1_UE_DL(ue, cell);
3217 cmLListDelFrm(&(sc1DlUe->lcsWithData), &sc1DlSvc->lcWithDataLnk);
3218 sc1DlSvc->lcWithDataLnk.node = NULLP;
3221 /***************** SC1 DL SCHEDULER FUNCTION DEFNs END HERE ****************/
3223 /***************************************************************************/
3225 /***************** SC1 UL SCHEDULER FUNCTION DEFNs START HERE **************/
3227 /*--------------------------*
3228 * UL specific functions START
3229 *---------------------------*/
3232 * @brief UE Lc Config for RR
3236 * Function : rgSCHSc1UlLchCfg
3238 * Processing Steps: Dummy function
3240 * @param[in] RgrSchCellCb *cell
3241 * @param[in] RgSchUeCb *ue
3242 * @param[in] RgrLchCfg *cfg
3243 * @param[in] RgSchErrInfo *err
3247 S16 rgSCHSc1UlLchCfg
3258 * @brief UE Lc Reconfig for RR
3262 * Function : rgSCHSc1UlLchRecfg
3264 * Processing Steps: Dummy function
3266 * @param[in] RgrSchCellCb *cell
3267 * @param[in] RgSchUeCb *ue
3268 * @param[in] RgrLchRecfg *recfg
3269 * @param[in] RgSchErrInfo *err
3273 S16 rgSCHSc1UlLchRecfg
3284 * @brief LC deletion for PFS
3288 * Function : rgSCHSc1UlLchDel
3290 * Processing Steps: Dummy function
3292 * @param[in] RgrSchCellCb *cell
3293 * @param[in] RgSchUeCb *ue
3294 * @param[in] CmLteLcId lcId
3298 S16 rgSCHSc1UlLchDel(RgSchCellCb *cell,RgSchUeCb *ue,CmLteLcId lcId,uint8_t lcgId)
3304 * @brief This function initializes all the data for the scheduler
3308 * Function: rgSCHSc1UlInit
3309 * Purpose: This function initializes the following information
3310 * 1. Efficiency table
3311 * 2. CQI to table index - It is one row for upto 3 RBs
3312 * and another row for greater than 3 RBs
3314 * currently extended prefix is compiled out.
3315 * Invoked by: MAC intialization code..may be ActvInit
3320 Void rgSCHSc1UlInit(RgUlSchdApis *rgSchUlApis)
3322 /* Init the function pointers */
3323 rgSchUlApis->rgSCHRgrUlUeCfg = rgSCHSc1RgrUlUeCfg;
3324 rgSchUlApis->rgSCHRgrUlUeRecfg = rgSCHSc1RgrUlUeRecfg;
3325 rgSchUlApis->rgSCHFreeUlUe = rgSCHSc1UlUeDel;
3326 rgSchUlApis->rgSCHRgrUlCellCfg = rgSCHSc1RgrUlCellCfg;
3327 rgSchUlApis->rgSCHRgrUlCellRecfg = rgSCHSc1RgrUlCellRecfg;
3328 rgSchUlApis->rgSCHFreeUlCell = rgSCHSc1UlCellDel;
3329 rgSchUlApis->rgSCHRgrUlLcCfg = rgSCHSc1UlLchCfg;
3330 rgSchUlApis->rgSCHRgrUlLcRecfg = rgSCHSc1UlLchRecfg;
3331 rgSchUlApis->rgSCHRgrUlLcgCfg = rgSCHSc1RgrLcgCfg;
3332 rgSchUlApis->rgSCHRgrUlLcgRecfg = rgSCHSc1RgrLcgRecfg;
3333 rgSchUlApis->rgSCHFreeUlLcg = rgSCHSc1LcgDel;
3334 rgSchUlApis->rgSCHRgrUlLchDel = rgSCHSc1UlLchDel;
3335 rgSchUlApis->rgSCHUlSched = rgSCHSc1UlSched;
3336 rgSchUlApis->rgSCHUpdBsrShort = rgSCHSc1UpdBsrShort;
3337 rgSchUlApis->rgSCHUpdBsrTrunc = rgSCHSc1UpdBsrTrunc;
3338 rgSchUlApis->rgSCHUpdBsrLong = rgSCHSc1UpdBsrLong;
3339 rgSchUlApis->rgSCHContResUlGrant = rgSCHSc1ContResUlGrant;
3340 rgSchUlApis->rgSCHSrRcvd = rgSCHSc1SrRcvd;
3341 rgSchUlApis->rgSCHUlCqiInd = rgSCHSc1UlCqiInd;
3342 rgSchUlApis->rgSCHUlUeRefresh = rgSCHSc1UlUeRefresh;
3343 rgSchUlApis->rgSCHUlAllocFnlz = rgSCHSc1UlAllocFnlz;
3344 rgSchUlApis->rgSCHUlInactvtUes = rgSCHSc1UlHndlInActUes;
3345 rgSchUlApis->rgSCHUlActvtUe = rgSCHSc1UlActvtUe;
3346 rgSchUlApis->rgSCHUlUeReset = rgSCHSc1UlUeReset;
3347 rgSchUlApis->rgSCHRgrUlLcgUpd = rgSCHSc1UlLcgUpd;
3352 * @brief UE initialisation for scheduler
3356 * Function : rgSCHSc1RgrUlUeCfg
3358 * This functions intialises UE specific scheduler
3361 * @param[in] RgSchCellCb *cell
3362 * @param[in] RgSchUeCb *ue
3363 * @param[int] RgrUeCfg *ueCfg
3364 * @param[out] RgSchErrInfo *err
3369 S16 rgSCHSc1RgrUlUeCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeCfg *ueCfg,RgSchErrInfo *err)
3372 RgSchCmnUe *ueSchCmn = RG_SCH_CMN_GET_UE(ue, cell);
3374 if(rgSCHUtlAllocSBuf(cell->instIdx,
3375 (Data**)&(ueSchCmn->ul.schSpfc), (sizeof(RgSchSc1UlUe))) != ROK)
3377 DU_LOG("\nERROR --> SCH : Memory allocation FAILED CRNTI:%d",ue->ueId);
3378 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
3383 } /* rgSCHSc1RgrUlUeCfg */
3386 * @brief UE reconfiguration for scheduler
3390 * Function : rgSCHSc1RgrUlUeRecfg
3392 * This functions updates UE specific scheduler
3393 * information upon UE reconfiguration
3395 * @param[in] RgSchCellCb *cell
3396 * @param[in] RgSchUeCb *ue
3397 * @param[int] RgrUeRecfg *ueRecfg
3398 * @param[out] RgSchErrInfo *err
3403 S16 rgSCHSc1RgrUlUeRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgrUeRecfg *ueRecfg,RgSchErrInfo *err)
3406 } /* rgSCHSc1RgrUeRecfg */
3409 * @brief UE deletion for scheduler
3413 * Function : rgSCHSc1UlUeDel
3415 * This functions deletes all scheduler information
3416 * pertaining to a UE
3418 * @param[in] RgSchCellCb *cell
3419 * @param[in] RgSchUeCb *ue
3422 Void rgSCHSc1UlUeDel(RgSchCellCb *cell,RgSchUeCb *ue)
3424 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3425 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3432 if(ueUl->txLnk.node)
3434 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3435 ueUl->txLnk.node = NULLP;
3437 if(ueUl->contResLnk.node)
3439 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
3440 ueUl->contResLnk.node = NULLP;
3442 /* ccpu00117052 - MOD - Passing double pointer
3443 for proper NULLP assignment*/
3444 rgSCHUtlFreeSBuf(cell->instIdx,
3445 (Data**)(&(ueUl)), (sizeof(RgSchSc1UlUe)));
3448 } /* rgSCHSc1UlUeDel */
3451 * @brief UE Reset for scheduler
3455 * Function : rgSCHSc1UlUeReset
3457 * Remove this UE from all Scheduling Priority Qs
3459 * @param[in] RgSchCellCb *cell
3460 * @param[in] RgSchUeCb *ue
3463 Void rgSCHSc1UlUeReset(RgSchCellCb *cell,RgSchUeCb *ue)
3465 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3466 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3469 ueUl->srRcvd = FALSE;
3471 if(ueUl->txLnk.node)
3473 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3474 ueUl->txLnk.node = NULLP;
3476 if(ueUl->contResLnk.node)
3478 cmLListDelFrm(&(cellUl->contResLst), &(ueUl->contResLnk));
3479 ueUl->contResLnk.node = NULLP;
3482 } /* rgSCHSc1UlUeReset */
3486 * @brief Scheduler processing on cell configuration
3490 * Function : rgSCHSc1RgrUlCellCfg
3492 * This function does requisite initialisation
3493 * and setup for scheduler1 when a cell is
3496 * @param[in] RgSchCellCb *cell
3497 * @param[in] RgrCellCfg *cellCfg
3498 * @param[out] RgSchErrInfo *err
3503 S16 rgSCHSc1RgrUlCellCfg(RgSchCellCb *cell,RgrCellCfg *cellCfg,RgSchErrInfo *err)
3505 RgSchSc1UlCell *cellUl;
3507 if((rgSCHUtlAllocSBuf(cell->instIdx,
3508 (Data**)&(((RgSchCmnCell*)((cell)->sc.sch))->ul.schSpfc), \
3509 (sizeof(RgSchSc1UlCell))) != ROK))
3511 DU_LOG("\nERROR --> SCH : Memory allocation FAILED");
3512 err->errCause = RGSCHERR_SCH_SC1_UL_CFG;
3515 cellUl = RG_GET_SC1_CELL_UL(cell);
3516 cmLListInit(&cellUl->contResLst);
3517 cmLListInit(&cellUl->ueTxLst[0]);
3518 cmLListInit(&cellUl->ueTxLst[1]);
3521 } /* rgSCHSc1RgrUlCellCfg */
3525 * @brief This function handles the reconfiguration of cell
3529 * Function: rgSCHSc1RgrUlCellRecfg
3530 * Purpose: Update the reconfiguration parameters.
3532 * Invoked by: Scheduler
3534 * @param[in] RgSchCellCb* cell
3538 S16 rgSCHSc1RgrUlCellRecfg(RgSchCellCb *cell,RgrCellRecfg *recfg,RgSchErrInfo *err)
3544 * @brief Scheduler processing for cell delete
3548 * Function : rgSCHSc1UlCellDel
3550 * This functions de-initialises and frees memory
3551 * taken up by scheduler1 for the entire cell.
3553 * @param[in] RgSchCellCb *cell
3556 Void rgSCHSc1UlCellDel(RgSchCellCb *cell)
3558 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3561 if (cellUl == NULLP)
3565 /* ccpu00117052 - MOD - Passing double pointer
3566 for proper NULLP assignment*/
3567 rgSCHUtlFreeSBuf(cell->instIdx,
3568 (Data**)(&(cellUl)), (sizeof(RgSchSc1UlCell)));
3571 } /* rgSCHSc1UlCellDel */
3574 * @brief Scheduler invocation on logical channel Group addition
3578 * Function : rgSCHSc1RgrLcgCfg
3580 * This functions does required processing when a new
3581 * (dedicated) logical channel is added. Assumes lcg
3582 * pointer in ulLc is set.
3584 * @param[in] RgSchCellCb *cell
3585 * @param[in] RgSchUeCb *ue
3586 * @param[in] RgSchLcgCb *lcg
3587 * @param[int] RgrLcgCfg *lcgCfg
3588 * @param[out] RgSchErrInfo *err
3593 S16 rgSCHSc1RgrLcgCfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,RgrLcgCfg *lcgCfg,RgSchErrInfo *err)
3596 } /* rgSCHSc1RgrLcgCfg */
3599 * @brief Scheduler invocation on logical channel addition
3603 * Function : rgSCHSc1RgrLcgRecfg
3605 * This functions does required processing when an existing
3606 * (dedicated) logical channel is reconfigured. Assumes lcg
3607 * pointer in ulLc is set to the old value.
3608 * Independent of whether new LCG is meant to be configured,
3609 * the new LCG scheduler info is accessed and possibly modified.
3611 * @param[in] RgSchCellCb *cell,
3612 * @param[in] RgSchUeCb *ue,
3613 * @param[in] RgSchLcgCb *lcg,
3614 * @param[in] RgrLcgRecfg *reCfg,
3615 * @param[out] RgSchErrInfo *err
3620 S16 rgSCHSc1RgrLcgRecfg(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,RgrLcgRecfg *reCfg,RgSchErrInfo *err)
3623 } /* rgSCHSc1RgrLcgRecfg */
3625 /***********************************************************
3627 * Func : rgSCHSc1LcgDel
3629 * Desc : Scheduler handling for a (dedicated)
3630 * uplink lcg being deleted
3638 **********************************************************/
3639 Void rgSCHSc1LcgDel(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg)
3641 rgSCHSc1UlPosnUeInQ(cell, ue);
3646 * @brief Perform alloction for this UE
3650 * Function : rgSCHSc1UlSchdUe
3652 * Processing Steps: cater to as much as UE needs, with
3653 * a limitation on maxBits per scheduling instance(per TTI)
3654 * per UE. Return failure, if UE is not considered
3655 * for scheduling (case, where it is already selected for a
3659 * @param[in] RgSchUeCb *ue
3662 static Void rgSCHSc1UlSchdUe(RgSchUeCb *ue,RgSchCellCb *cell)
3664 RgSchCmnUlUe *cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
3665 /*cell added as part of CA dev*/
3666 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
3669 if(ulUe->srRcvd == TRUE)
3671 cmnUlUe->alloc.reqBytes = RGSCH_MAX(RG_SCH_CMN_UL_SR_BYTES, \
3676 cmnUlUe->alloc.reqBytes = ue->ul.effBsr;
3682 * @brief Scheduler invocation
3686 * Function: rgSCHSc1UlSchdForDataTrans
3687 * Purpose: Uplink Scheduling for UE data Transmission.
3690 * Invoked by: Scheduler
3692 * @param[in] RgSchCellCb *cell
3693 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3694 * @param[in] uint8_t remUe
3697 static Void rgSCHSc1UlSchdForDataTrans(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t remUe)
3699 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
3705 /* Allocate UEs with LCG0 data pending */
3706 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[0], allocInfo, &remUe);
3712 /* Allocate UEs with other LCGs data pending */
3713 rgSCHSc1UlSchdUeTxLst(cell, &sc1UlCell->ueTxLst[1], allocInfo, &remUe);
3719 * @brief Scheduler invocation
3723 * Function: rgSCHSc1UlSchdUeTxLst
3724 * Purpose: Uplink Scheduling for UE data Transmission.
3727 * Invoked by: Scheduler
3729 * @param[in] CmLListCp *ueTxLst
3730 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3731 * @param[in] uint8_t *remUe
3734 static Void rgSCHSc1UlSchdUeTxLst(RgSchCellCb *cell,CmLListCp *ueTxLst,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t *remUe)
3739 Bool ulAllowed = FALSE;
3743 node = ueTxLst->first;
3744 while ((node) && (*remUe))
3746 ue = (RgSchUeCb *)node->node;
3751 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
3752 if (ulAllowed == FALSE)
3759 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
3761 /* UE already scheduled in this subframe (for retx)
3762 * OR is inactive for UL Transmission.*/
3765 /* Added support for SPS*/
3767 else if (RG_SCH_CMN_IS_SPS_SCHD(ue, cell))
3769 /*-- Already Scheduled by SPS --*/
3774 rgSCHSc1UlSchdUe(ue,cell);/*cell added as part of CA dev*/
3776 rgSCHCmnUlAdd2UeLst(cell, allocInfo, ue);
3785 * @brief Scheduler invocation
3789 * Function: rgSCHSc1UlSchdForContRes
3790 * Purpose: Uplink Scheduling for Contention Resolution.
3793 * Invoked by: Scheduler
3795 * @param[in] RgSchCellCb *cell
3796 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3797 * @param[out] uint8_t *remUe
3800 static Void rgSCHSc1UlSchdForContRes(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo,uint8_t *remUe)
3802 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
3805 RgSchCmnUlUe *cmnUlUe;
3807 Bool ulAllowed = FALSE;
3811 node = sc1UlCell->contResLst.first;
3812 while ((node) && (*remUe))
3814 ue = (RgSchUeCb *)node->node;
3815 cmnUlUe = RG_SCH_CMN_GET_UL_UE(ue, cell);
3816 /*cell added as part of CA dev*/
3821 rgSCHCmnHdFddChkUlAllow (cell, ue, &ulAllowed);
3822 if (ulAllowed == FALSE)
3828 if (RG_SCH_CMN_IS_UL_UE_RETX(ue, cell))
3830 /* UE already scheduled in this subframe (for retx)
3831 * OR is inactive for UL Transmission.*/
3834 cmnUlUe->alloc.reqBytes = RG_SCH_CMN_MAX_UL_CONTRES_GRNT;
3835 rgSCHCmnUlAdd2CntResLst(allocInfo, ue);
3837 /* Node removal deferred to ULAllocFinalization */
3844 * @brief Scheduler invocation
3848 * Function: rgSCHSc1UlNewTx
3849 * Purpose: Uplink Scheduling for New Transmissions.
3852 * Invoked by: Scheduler
3854 * @param[in] RgSchCellCb *cell
3855 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3858 static Void rgSCHSc1UlNewTx(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
3860 RgSchCmnUlCell *cellUl = RG_SCH_CMN_GET_UL_CELL(cell);
3861 uint8_t remUe = cellUl->maxUeNewTxPerTti;
3864 rgSCHSc1UlSchdForContRes(cell, allocInfo, &remUe);
3865 rgSCHSc1UlSchdForDataTrans(cell, allocInfo, remUe);
3870 * @brief Scheduler invocation
3874 * Function: rgSCHSc1UlSched
3875 * Purpose: This function implements an UL scheduler for LTE. This is
3876 * made available as a function pointer to be called
3877 * at the time of TTI processing by the MAC.
3879 * Invoked by: Common Scheduler (TTI processing)
3881 * @param[in] RgSchCellCb *cell
3882 * @param[out] RgSchCmnUlRbAllocInfo *allocInfo
3885 Void rgSCHSc1UlSched(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
3887 rgSCHSc1UlNewTx(cell, allocInfo);
3892 * @brief UEs Buffer Status Has changed so reposition it.
3896 * Function : rgSCHSc1UlInsUeInQ
3898 * In UE in the list in Descending order of effBsr.
3901 * @param[in] CmLListCp *lst
3902 * @param[in] RgSchUeCb *ue
3905 static Void rgSCHSc1UlInsUeInQ(CmLListCp *lst,RgSchUeCb *ue,RgSchCellCb *cell)
3907 /*cell added as part of CA dev*/
3908 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3916 lUe = (RgSchUeCb *)(node->node);
3917 if (lUe->ul.effBsr <= ue->ul.effBsr)
3925 /* We have come to the end of the queue, so Append */
3926 cmLListAdd2Tail(lst, &ueUl->txLnk);
3927 ueUl->txLnk.node = (PTR)ue;
3932 cmLListInsCrnt(lst, &ueUl->txLnk);
3933 ueUl->txLnk.node = (PTR)ue;
3939 * @brief UEs Buffer Status Has changed so reposition it.
3943 * Function : rgSCHSc1UlPosnUeInQ
3945 * -Ues bs value for its LCG has changed, due to either
3946 * allocation or BSR report OR the effUeBR, i.e the byteRate
3947 * has changed due to some allocation, so add/reposition/remove
3948 * it from Qs based on this new bs and/or effUeBR value.
3949 * -If UE has non-zero lcg0 bs value, but the byteRate is
3950 * consumed totally, UE is still schedulable for this control data.
3951 * -If UE's LCG0 has pending bs then position this UE in
3953 * -If Ue has pending BSR to be satisfied, but lcg0's BS
3954 * is 0, then position it in ueTxLst[1].
3955 * -In any of these 2 Qs, insertion is such that UEs are
3956 * positioned in Descending order of their Pending BS.
3959 * @param[in] RgSchCellCb *cell
3960 * @param[in] RgSchUeCb *ue
3963 static Void rgSCHSc1UlPosnUeInQ(RgSchCellCb *cell,RgSchUeCb *ue)
3965 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
3966 /*cell added as part of CA dev*/
3967 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
3968 RgSchCmnLcg *cmnLcg0 = RG_SCH_CMN_GET_UL_LCG(&ue->ul.lcgArr[0]);
3972 if (!RG_SCH_CMN_UL_IS_UE_ACTIVE(ue))
3977 /* Remove the UE from its existing position */
3978 if (ueUl->txLnk.node)
3980 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
3981 ueUl->txLnk.node = (PTR)NULLP;
3983 /* If UE has still bs left for scheduling
3984 * then reposition it */
3985 if ((ue->ul.effBsr > 0) || (ueUl->srRcvd == TRUE))
3987 /* Select the Queue where UE would be Placed */
3988 if (cmnLcg0->bs > 0)
3990 lst = &cellUl->ueTxLst[0];
3995 lst = &cellUl->ueTxLst[1];
3998 /* Insert the UE in the Q */
3999 rgSCHSc1UlInsUeInQ(lst, ue, cell);/*cell added as part of CA dev*/
4002 else if(ue->ul.totalBsr != 0)
4004 if (ue->bsrTmr.tmrEvnt != TMR_NONE)
4006 rgSCHTmrStopTmr(cell, ue->bsrTmr.tmrEvnt, ue);
4008 if (ue->ul.bsrTmrCfg.isPrdBsrTmrPres)
4010 rgSCHTmrStartTmr(cell, ue, RG_SCH_TMR_BSR,
4011 ue->ul.bsrTmrCfg.prdBsrTmr);
4020 * @brief Short BSR update
4024 * Function : rgSCHSc1UpdBsrShort
4026 * This functions does requisite updates to handle short BSR reporting
4028 * @param[in] RgSchCellCb *cell
4029 * @param[in] RgSchUeCb *ue
4030 * @param[in] RgSchLcgCb *lcg
4031 * @param[in] uint8_t bsr
4034 Void rgSCHSc1UpdBsrShort(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,uint8_t bsr)
4036 rgSCHSc1UlPosnUeInQ(cell, ue);
4038 } /* rgSCHSc1UpdBsrShort */
4041 * @brief Truncated BSR update
4045 * Function : rgSCHSc1UpdBsrTrunc
4047 * This functions does required updates to handle truncated BSR report
4050 * @param[in] RgSchCellCb *cell
4051 * @param[in] RgSchUeCb *ue
4052 * @param[in] RgSchLcgCb *lcg
4053 * @param[in] uint8_t bsr
4056 Void rgSCHSc1UpdBsrTrunc(RgSchCellCb *cell,RgSchUeCb *ue,RgSchLcgCb *lcg,uint8_t bsr)
4058 rgSCHSc1UlPosnUeInQ(cell, ue);
4060 } /* rgSCHSc1UpdBsrTrunc */
4063 * @brief Long BSR update
4067 * Function : rgSCHSc1UpdBsrLong
4069 * - Update UE's position within/across uplink scheduling queues
4072 * @param[in] RgSchCellCb *cell
4073 * @param[in] RgSchUeCb *ue
4074 * @param[in] uint8_t bsArr[]
4077 Void rgSCHSc1UpdBsrLong(RgSchCellCb *cell,RgSchUeCb *ue,uint8_t *bsArr)
4079 rgSCHSc1UlPosnUeInQ(cell, ue);
4081 } /* rgSCHSc1UpdBsrLong */
4084 * @brief UL grant for contention resolution
4088 * Function : rgSCHSc1ContResUlGrant
4090 * Add UE to another queue specifically for CRNTI based contention
4094 * @param[in] RgSchCellCb *cell
4095 * @param[in] RgSchUeCb *ue
4098 Void rgSCHSc1ContResUlGrant(RgSchCellCb *cell,RgSchUeCb *ue)
4100 RgSchSc1UlUe *ueUl = RG_GET_SC1_UE_UL(ue, cell);
4101 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4104 if (ueUl->contResLnk.node)
4109 /* Remove the UE from other Qs */
4110 if(ueUl->txLnk.node)
4112 cmLListDelFrm(&(cellUl->ueTxLst[ueUl->qId]), &(ueUl->txLnk));
4113 ueUl->txLnk.node = NULLP;
4116 cmLListAdd2Tail(&cellUl->contResLst, &ueUl->contResLnk);
4117 ueUl->contResLnk.node = (PTR)ue;
4119 } /* rgSCHSc1ContResUlGrant */
4122 * @brief SR reception handling
4126 * Function : rgSCHSc1SrRcvd
4127 * Shift the UE with SrInd in to the lcgO queue.
4130 * @param[in] RgSchCellCb *cell
4131 * @param[in] RgSchUeCb *ue
4134 Void rgSCHSc1SrRcvd(RgSchCellCb *cell,RgSchUeCb *ue)
4136 RgSchSc1UlUe *ulUe = RG_GET_SC1_UE_UL(ue, cell);
4137 RgSchSc1UlCell *ulCell = RG_GET_SC1_CELL_UL(cell);
4140 ulUe->srRcvd = TRUE;
4142 if (ulUe->txLnk.node != NULLP)
4146 /* Already present in lcg0 Q */
4149 cmLListDelFrm(&(ulCell->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
4151 /* Adding the UE to the LCG0 list for SR IND */
4152 cmLListAdd2Tail(&ulCell->ueTxLst[0], &ulUe->txLnk);
4153 ulUe->txLnk.node = (PTR)ue;
4157 } /* rgSCHSc1SrRcvd */
4160 * @brief Indication of UL CQI
4164 * Function : rgSCHSc1UlCqiInd
4166 * - Common Scheduler. SC1 does nothing.
4168 * @param[in] RgSchCellCb *cell
4169 * @param[in] RgSchUeCb *ue
4170 * @param[in] TfuUlCqiRpt *ulCqiInfo
4173 Void rgSCHSc1UlCqiInd(RgSchCellCb *cell,RgSchUeCb *ue,TfuUlCqiRpt *ulCqiInfo)
4176 /* Stack Crash problem for TRACE5 changes. Added the return below */
4182 * @brief UL Lcg received data updation
4186 * Function : rgSCHSc1UlLcgUpd
4188 * Processing Steps:Sc1 Does nothing
4190 * @param[in] RgSchCellCb *cell
4191 * @param[in] RgSchUeCb *ue
4192 * @param[in] RgInfUeDatInd *datInd
4195 S16 rgSCHSc1UlLcgUpd(RgSchCellCb *cell,RgSchUeCb *ue,RgInfUeDatInd *datInd)
4202 /***********************************************************
4204 * Func : rgSCHSc1UlUeRefresh
4206 * Desc : Handle 'refresh' for uplink part of a UE
4207 * (ie UE's uplink AMBR and uplink GBR LCGs are
4208 * refreshed at this point)
4216 **********************************************************/
4217 Void rgSCHSc1UlUeRefresh(RgSchCellCb *cell,RgSchUeCb *ue)
4219 rgSCHSc1UlPosnUeInQ(cell, ue);
4224 * @brief This function Processes the Final Allocations
4225 * made by the RB Allocator against the requested
4226 * UE data Trans Allocations.
4230 * Function: rgSCHSc1UlDatTransAllocFnlz
4231 * Purpose: This function Processes the Final Allocations
4232 * made by the RB Allocator against the requested
4233 * UE data Trans Allocations .
4235 * Invoked by: Scheduler
4237 * @param[in] RgSchCellCb *cell
4238 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4242 static Void rgSCHSc1UlDatTransAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4247 RgSchDrxUeCb *drxUe = NULLP;
4248 CmLListCp ulInactvLst; /* list of UE's becoming UL-inactive */
4250 cmLListInit(&ulInactvLst);
4251 node = allocInfo->schdUeLst.first;
4254 ue = (RgSchUeCb *)node->node;
4256 ueUl = RG_GET_SC1_UE_UL(ue, cell);
4258 if (ue->isDrxEnabled)
4260 if(ueUl->srRcvd == TRUE)
4262 drxUe = RG_SCH_DRX_GET_UE(ue);
4263 drxUe->drxUlInactvMask |= RG_SCH_DRX_SR_BITMASK;
4265 if(!RG_SCH_DRX_UL_IS_UE_ACTIVE(drxUe))
4267 ue->ul.ulInactvMask |= RG_DRX_INACTIVE;
4268 /* Add to Ul inactive List */
4269 ue->ulDrxInactvLnk.node = (PTR)ue;
4270 cmLListAdd2Tail(&ulInactvLst,&(ue->ulDrxInactvLnk));
4272 drxUe->srRcvd = FALSE;
4275 /* Reset no matter */
4276 ueUl->srRcvd = FALSE;
4277 /* Reposition UE in Qs */
4278 rgSCHSc1UlPosnUeInQ(cell, ue);
4282 rgSCHCmnHdFddUpdULMark (cell,ue);
4285 /* reset the UE UL allocation Information */
4286 rgSCHCmnUlUeResetTemp(cell, ue);
4288 rgSCHSc1UlHndlInActUes(cell, &ulInactvLst);
4289 node = allocInfo->nonSchdUeLst.first;
4292 ue = (RgSchUeCb *)node->node;
4294 /* reset the UE UL allocation Information */
4295 rgSCHCmnUlUeResetTemp(cell, ue);
4302 * @brief This function Processes the Final Allocations
4303 * made by the RB Allocator against the requested
4304 * cont res Allocations.
4308 * Function: rgSCHSc1UlContResAllocFnlz
4309 * Purpose: This function Processes the Final Allocations
4310 * made by the RB Allocator against the requested
4311 * cont res Allocations .
4313 * Invoked by: Scheduler
4315 * @param[in] RgSchCellCb *cell
4316 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4320 static Void rgSCHSc1UlContResAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4322 RgSchSc1UlCell *sc1UlCell = RG_GET_SC1_CELL_UL(cell);
4327 node = allocInfo->schdContResLst.first;
4330 ue = (RgSchUeCb *)node->node;
4335 rgSCHCmnHdFddUpdULMark (cell,ue);
4338 ueUl = RG_GET_SC1_UE_UL(ue, cell);
4340 /* Remove UE from Cont Res Q */
4341 cmLListDelFrm(&sc1UlCell->contResLst,
4343 ueUl->contResLnk.node = NULLP;
4344 /* reset the UE UL allocation Information */
4345 rgSCHCmnUlUeResetTemp(cell, ue);
4348 node = allocInfo->nonSchdContResLst.first;
4351 ue = (RgSchUeCb *)node->node;
4353 /* reset the UE UL allocation Information */
4354 rgSCHCmnUlUeResetTemp(cell, ue);
4361 * @brief This function Processes the Final Allocations
4362 * made by the RB Allocator against the requested.
4366 * Function: rgSCHSc1UlAllocFnlz
4367 * Purpose: This function Processes the Final Allocations
4368 * made by the RB Allocator against the requested.
4370 * Invoked by: Common Scheduler
4372 * @param[in] RgSchCellCb *cell
4373 * @param[in] RgSchCmnDlRbAllocInfo *allocInfo
4377 Void rgSCHSc1UlAllocFnlz(RgSchCellCb *cell,RgSchCmnUlRbAllocInfo *allocInfo)
4380 rgSCHSc1UlContResAllocFnlz(cell, allocInfo);
4381 rgSCHSc1UlDatTransAllocFnlz(cell, allocInfo);
4388 * @brief Scheduler invocation
4392 * Function: rgSCHSc1UlActvtUe
4393 * Purpose: Put back the UE in to appropriate Qs.
4395 * Invoked by: Common Scheduler
4397 * @param[in] RgSchCellCb *cell
4398 * @param[in] RgSchUeCb *ue
4401 Void rgSCHSc1UlActvtUe(RgSchCellCb *cell,RgSchUeCb *ue)
4404 rgSCHSc1UlPosnUeInQ(cell, ue);
4409 * @brief Scheduler invocation
4413 * Function: rgSCHSc1UlHndlInActUes
4414 * Purpose: The list of inactive UEs present in inactvLst should
4415 * be removed from the scheduling Qs.
4416 * But store the information pertaining to which Qs,
4417 * were they belonging to. This information shall be used
4418 * to put them back in appropriate Qs when their Activation
4421 * Invoked by: Common Scheduler (TTI processing)
4423 * @param[in] RgSchCellCb *cell
4424 * @param[out] CmLListCp *inactvLst
4427 Void rgSCHSc1UlHndlInActUes(RgSchCellCb *cell,CmLListCp *inactvLst)
4431 RgSchSc1UlCell *cellUl = RG_GET_SC1_CELL_UL(cell);
4432 CmLList *node = inactvLst->first;
4436 ue = (RgSchUeCb *)node->node;
4438 ulUe = RG_GET_SC1_UE_UL(ue, cell);
4439 if(ulUe->txLnk.node)
4441 cmLListDelFrm(&(cellUl->ueTxLst[ulUe->qId]), &(ulUe->txLnk));
4442 /* This is required as lcg bs might change during
4443 * inactivity to activity. So we need to recompute
4445 ulUe->txLnk.node = NULLP;
4447 /* Do not remove UE from contResLst */
4452 * @brief Scheduler invocation
4456 * Function: rgSCHSc1DlProcRmvFrmRetx
4457 * Purpose: To remove the Harq process from the cell and from the UE
4458 * retransmission list
4460 * Invoked by: Common Scheduler (TTI processing)
4462 * @param[in] RgSchCellCb *cell
4463 * @param[in] RgSchUeCb *ue;
4464 * @param[in] RgSchDlHqProcCb *hqP
4468 Void rgSCHSc1DlProcRmvFrmRetx(
4471 RgSchDlHqProcCb *hqP
4475 /* Remove the HqP from retx Queue.
4477 rgSCHSc1DlProcRmvFrmCellRetx(cell, hqP);
4478 rgSCHSc1DlProcRmvFrmUeRetx(cell, ue, hqP);
4485 /**********************************************************************
4488 **********************************************************************/