+/*******************************************************************************
+################################################################################
+# Copyright (c) [2017-2019] [Radisys] #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+################################################################################
+ *******************************************************************************/
+
+/************************************************************************
+
+Name: 5G NR SCH layer
+
+Type: C source file
+
+Desc: C source code for scheduling based on First Come First Serve
+ algorithm
+
+File: sch_fcfs.c
+
+ **********************************************************************/
+
+/** @file sch_slot_ind.c
+ @brief This module processes slot indications
+ */
+#include "common_def.h"
+#include "tfu.h"
+#include "lrg.h"
+#include "tfu.x"
+#include "lrg.x"
+#include "du_log.h"
+#include "du_app_mac_inf.h"
+#include "mac_sch_interface.h"
+#include "sch.h"
+#include "sch_utils.h"
+#include "sch_fcfs.h"
+#ifdef NR_DRX
+#include "sch_drx.h"
+#endif
+
+/*******************************************************************
+ *
+ * @brief Function to handle Cell configuration request
+ *
+ * @details
+ *
+ * Function : schFcfsCellCfgReq
+ *
+ * Functionality: This function configures cell paremeters
+ * required for FCFS scheduling
+ *
+ * @params[in] SchCellCb *cellCb, Cell control block
+ * @return ROK
+ * RFAILED
+ *
+ * ****************************************************************/
+uint8_t schFcfsCellCfgReq(SchCellCb *cellCb)
+{
+ SchFcfsCellCb *fcfsCellCb = NULLP;
+
+ SCH_ALLOC(fcfsCellCb, sizeof(SchFcfsCellCb));
+ if(!fcfsCellCb)
+ {
+ DU_LOG("\nERROR --> SCH: Memory allocation failed in schFcfsCellCfgReq");
+ return RFAILED;
+ }
+ cmLListInit(&fcfsCellCb->ueToBeScheduled);
+ cellCb->schSpcCell = (void *)fcfsCellCb;
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Function to handle Cell configuration request
+ *
+ * @details
+ *
+ * Function : schFcfsCellDelReq
+ *
+ * Functionality: This function deletes/frees cell params
+ * specific to FCFS scheduling
+ *
+ * @params[in] Pointer to Cell control block
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsCellDelReq(SchCellCb *cellCb)
+{
+ SchFcfsCellCb *fcfsCellCb = NULLP;
+ CmLList *node=NULL, *next=NULL;
+
+ fcfsCellCb = (SchFcfsCellCb *)cellCb->schSpcCell;
+ /* Remove all UE from ueToBeScheduled list and deallocate */
+ node = fcfsCellCb->ueToBeScheduled.first;
+ while(node)
+ {
+ next = node->next;
+ SCH_FREE(node->node, sizeof(uint8_t));
+ cmLListDelFrm(&fcfsCellCb->ueToBeScheduled, node);
+ SCH_FREE(node, sizeof(CmLList));
+ node = next;
+ }
+ SCH_FREE(fcfsCellCb, sizeof(SchFcfsCellCb));
+ cellCb->schSpcCell = NULLP;
+}
+
+/*******************************************************************
+ *
+ * @brief Function to handle UE configuration request
+ *
+ * @details
+ *
+ * Function : SchFcfsAddUeConfigReq
+ *
+ * Functionality: Adds/Configures UE parameters required for
+ * FCFS scheduling
+ *
+ * @params[in] Pointer to UE control block
+ * @return ROK
+ * RFAILED
+ *
+ * ****************************************************************/
+uint8_t SchFcfsAddUeConfigReq(SchUeCb *ueCb)
+{
+ SchFcfsUeCb *ueFcfsCb;
+
+ SCH_ALLOC(ueFcfsCb, sizeof(SchFcfsHqCb));
+ if(!ueFcfsCb)
+ {
+ DU_LOG("\nERROR --> SCH: Memory allocation failed in SchFcfsAddUeConfigReq");
+ return RFAILED;
+ }
+
+ cmLListInit(&ueFcfsCb->hqRetxCb.ulRetxHqList);
+ cmLListInit(&ueFcfsCb->hqRetxCb.dlRetxHqList);
+ ueCb->schSpcUeCb = (void *)ueFcfsCb;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Handles UE reconfiguration request
+ *
+ * @details
+ *
+ * Function : SchFcfsModUeConfigReq
+ *
+ * Functionality:
+ *
+ * @params[in] Pointer to UE control block
+ * @return void
+ *
+ * ****************************************************************/
+void SchFcfsModUeConfigReq(SchUeCb *ueCb)
+{
+ /*TBD: No action required for FCFS*/
+ return;
+}
+
+/*******************************************************************
+ *
+ * @brief Handles UE Delete Request
+ *
+ * @details
+ *
+ * Function : SchFcfsUeDeleteReq
+ *
+ * Functionality: Deletes/Frees UE parameters specific to
+ * FCFS scheduling
+ *
+ * @params[in] Pointer to UE control block
+ * @return void
+ *
+ * ****************************************************************/
+void SchFcfsUeDeleteReq(SchUeCb *ueCb)
+{
+ SchFcfsCellCb *fcfsCellCb = NULLP;
+ SchFcfsUeCb *ueFcfsCb = NULLP;
+ CmLList *node=NULL, *next=NULL;
+ uint8_t ueId = 0;
+
+ fcfsCellCb = (SchFcfsCellCb *)ueCb->cellCb->schSpcCell;
+ /* Remove all UE from ueToBeScheduled list and deallocate */
+ node = fcfsCellCb->ueToBeScheduled.first;
+ while(node)
+ {
+ next = node->next;
+ ueId = *(uint8_t *)node->node;
+ if(ueId == ueCb->ueId)
+ {
+ SCH_FREE(node->node, sizeof(uint8_t));
+ cmLListDelFrm(&fcfsCellCb->ueToBeScheduled, node);
+ SCH_FREE(node, sizeof(CmLList));
+ break;
+ }
+ node = next;
+ }
+
+ ueFcfsCb = (SchFcfsUeCb *)ueCb->schSpcUeCb;
+ cmLListDeleteLList(&ueFcfsCb->hqRetxCb.ulRetxHqList);
+ cmLListDeleteLList(&ueFcfsCb->hqRetxCb.dlRetxHqList);
+
+ SCH_FREE(ueFcfsCb, sizeof(SchFcfsUeCb));
+ ueCb->schSpcUeCb = NULLP;
+ return;
+}
+
+/*******************************************************************
+ *
+ * @brief Intializes HARQ Process control block
+ *
+ * @details
+ *
+ * Function : schFcfsInitDlHqProcCb
+ *
+ * Functionality: Intitialized parameters of HARQ process control
+ * block specific to FCFS scheduling in Downlink
+ *
+ * @params[in] Pointer to Downlink HARQ Process control block
+ * @return ROK
+ * RFAILED
+ *
+ * ****************************************************************/
+uint8_t schFcfsInitDlHqProcCb(SchDlHqProcCb *hqP)
+{
+ SchFcfsHqProcCb *fcfsHqP;
+
+ SCH_ALLOC(fcfsHqP, sizeof(SchFcfsHqProcCb));
+ if(!fcfsHqP)
+ {
+ DU_LOG("\nERROR --> SCH: Memory allocation failed in schFcfsInitDlHqProcCb");
+ return RFAILED;
+ }
+
+ cmLListInit(&fcfsHqP->lcCb.dedLcList);
+ cmLListInit(&fcfsHqP->lcCb.defLcList);
+ hqP->schSpcDlHqProcCb = (void *)fcfsHqP;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Handles HARQ Process delete request
+ *
+ * @details
+ *
+ * Function : schFcfsDeleteDlHqProcCb
+ *
+ * Functionality: Deletes HARQ Process parameters specific to
+ * FCFS scheduling in Downlink
+ *
+ * @params[in] Pointer to Downlink HARQ Process control block
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsDeleteDlHqProcCb(SchDlHqProcCb *hqP)
+{
+ SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcDlHqProcCb;
+ cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
+ cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
+ SCH_FREE(fcfsHqP, sizeof(SchFcfsHqProcCb));
+ hqP->schSpcDlHqProcCb = NULLP;
+}
+
+/*******************************************************************
+ *
+ * @brief Intializes HARQ Process control block
+ *
+ * @details
+ *
+ * Function : schFcfsInitUlHqProcCb
+ *
+ * Functionality: Intitialized parameters of HARQ process control
+ * block specific to FCFS scheduling in Uplink
+ *
+ * @params[in] Pointer to Uplink HARQ Process control block
+ * @return ROK
+ * RFAILED
+ *
+ * ****************************************************************/
+uint8_t schFcfsInitUlHqProcCb(SchUlHqProcCb *hqP)
+{
+ SchFcfsHqProcCb *fcfsHqP;
+
+ SCH_ALLOC(fcfsHqP, sizeof(SchFcfsHqProcCb));
+ if(!fcfsHqP)
+ {
+ DU_LOG("\nERROR --> SCH: Memory allocation failed in schFcfsInitUlHqProcCb");
+ return RFAILED;
+ }
+ cmLListInit(&fcfsHqP->lcCb.dedLcList);
+ cmLListInit(&fcfsHqP->lcCb.defLcList);
+ hqP->schSpcUlHqProcCb = (void *)fcfsHqP;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Handled Deletion of HARQ Process control block
+ *
+ * @details
+ *
+ * Function : schFcfsDeleteUlHqProcCb
+ *
+ * Functionality: Deletes HARQ Process parameters specific to
+ * FCFS scheduling in Uplink
+ *
+ * @params[in] Pointer to Uplink HARQ Process Control block
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsDeleteUlHqProcCb(SchUlHqProcCb *hqP)
+{
+ SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcUlHqProcCb;
+ cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
+ cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
+ SCH_FREE(fcfsHqP, sizeof(SchFcfsHqProcCb));
+ hqP->schSpcUlHqProcCb = NULLP;
+}
+
+/*******************************************************************
+ *
+ * @brief Handles freeing of HARQ Process
+ *
+ * @details
+ *
+ * Function : schFcfsFreeDlHqProcCb
+ *
+ * Functionality: Frees HARQ Process parameters specific to
+ * FCFS scheduling in Downlink when HARQ process becomes free
+ *
+ * @params[in] Pointer to HARQ process control block
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsFreeDlHqProcCb(SchDlHqProcCb *hqP)
+{
+ SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcDlHqProcCb;
+
+ cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
+ cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
+}
+
+/*******************************************************************
+ *
+ * @brief Handles freeing of HARQ Process
+ *
+ * @details
+ *
+ * Function : schFcfsFreeUlHqProcCb
+ *
+ * Functionality: Frees HARQ Process parameters specific to
+ * FCFS scheduling in Uplink when HARQ process becomes free
+ *
+ * @params[in] Pointer to HARQ process control block
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsFreeUlHqProcCb(SchUlHqProcCb *hqP)
+{
+ SchFcfsHqProcCb *fcfsHqP = (SchFcfsHqProcCb *)hqP->schSpcUlHqProcCb;
+
+ cmLListDeleteLList(&fcfsHqP->lcCb.dedLcList);
+ cmLListDeleteLList(&fcfsHqP->lcCb.defLcList);
+}
+
+/*******************************************************************
+ *
+ * @brief Adds HARQ process to retransmission list
+ *
+ * @details
+ *
+ * Function : schFcfsAddToDlHqRetxList
+ *
+ * Functionality: Adds HARQ process to retransmission list
+ *
+ * @params[in] Pointer to Downlink HARQ Process
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsAddToDlHqRetxList(SchDlHqProcCb *hqP)
+{
+ SchFcfsUeCb *fcfsUeCb;
+
+ fcfsUeCb = (SchFcfsUeCb *)hqP->hqEnt->ue->schSpcUeCb;
+ cmLListAdd2Tail(&(fcfsUeCb->hqRetxCb.dlRetxHqList),&hqP->dlHqProcLink);
+#ifdef NR_DRX
+ if(hqP->hqEnt->ue->ueDrxInfoPres == true)
+ {
+ schDrxStrtDlHqRttTmr(hqP);
+ }
+ else
+#endif
+ {
+ schFcfsAddUeToSchedule(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Adds HARQ process to retransmission list
+ *
+ * @details
+ *
+ * Function : schFcfsAddToUlHqRetxList
+ *
+ * Functionality: Adds HARQ process to retransmission list
+ *
+ * @params[in] Pointer to Uplink HARQ Process
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsAddToUlHqRetxList(SchUlHqProcCb *hqP)
+{
+ SchFcfsUeCb *fcfsUeCb;
+
+ fcfsUeCb = (SchFcfsUeCb *)hqP->hqEnt->ue->schSpcUeCb;
+ cmLListAdd2Tail(&(fcfsUeCb->hqRetxCb.ulRetxHqList),&hqP->ulHqProcLink);
+#ifdef NR_DRX
+ if(hqP->hqEnt->ue->ueDrxInfoPres == true)
+ {
+ schDrxStrtUlHqRttTmr(hqP);
+ }
+ else
+#endif
+ {
+ schFcfsAddUeToSchedule(hqP->hqEnt->cell, hqP->hqEnt->ue->ueId);
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Add UE to ueToBeScheduled List
+ *
+ * @details
+ *
+ * Function : schFcfsAddUeToSchedule
+ *
+ * Functionality:
+ * Search if UE entry present in the list
+ * If yes, return.
+ * If no, add UE to the list
+ *
+ * @params[in] Cell control block
+ * Ue Id to be added
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t schFcfsAddUeToSchedule(SchCellCb *cellCb, uint16_t ueIdToAdd)
+{
+ SchFcfsCellCb *fcfsCellCb = NULLP;
+ uint8_t *ueId;
+ CmLList *node;
+
+ fcfsCellCb = (SchFcfsCellCb *)cellCb->schSpcCell;
+ /* Search if UE entry is already present in ueToBeScheduled list.
+ * If yes, another entry for same UE not needed. Hence, return */
+ node = fcfsCellCb->ueToBeScheduled.first;
+ while(node)
+ {
+ ueId = (uint8_t *)node->node;
+ if(*ueId == ueIdToAdd)
+ return ROK;
+ node = node->next;
+ }
+
+ /* If UE entry not present already, add UE to the end of ueToBeScheduled list */
+ SCH_ALLOC(ueId, sizeof(uint8_t));
+ if(!ueId)
+ {
+ DU_LOG("\nERROR --> SCH : Memory allocation failure in schFcfsAddUeToSchedule");
+ return RFAILED;
+ }
+ *ueId = ueIdToAdd;
+ if(addNodeToLList(&fcfsCellCb->ueToBeScheduled, ueId, NULLP) != ROK)
+ {
+ DU_LOG("\nERROR --> SCH : Failed to add ueId [%d] to cell->ueToBeScheduled list", *ueId);
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Handled CRC Indication
+ *
+ * @details
+ *
+ * Function : schFcfsProcessCrcInd
+ *
+ * Functionality: Processes CRC Indication as required for FCFS
+ * scheduling
+ *
+ * @params[in] Pointer to Cell control block
+ * UE Id
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsProcessCrcInd(SchCellCb *cellCb, uint16_t ueId)
+{
+ schFcfsAddUeToSchedule(cellCb, ueId);
+}
+
+/*******************************************************************
+ *
+ * @brief Processes Buffer Occupancy report from RLC
+ *
+ * @details
+ *
+ * Function : schFcfsDlRlcBoInfo
+ *
+ * Functionality: Process buffer occupany report
+ *
+ * @params[in]
+ * @return
+ *
+ * ****************************************************************/
+void schFcfsDlRlcBoInfo(SchCellCb *cellCb, uint16_t ueId)
+{
+ schFcfsAddUeToSchedule(cellCb, ueId);
+}
+
+/*******************************************************************
+ *
+ * @brief Processes BSR request
+ *
+ * @details
+ *
+ * Function : schFcfsBsr
+ *
+ * Functionality: Processes BSR as per FCFS scheduling
+ *
+ * @params[in] Pointer to Cell
+ * UE ID
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsBsr(SchCellCb *cellCb, uint16_t ueId)
+{
+ schFcfsAddUeToSchedule(cellCb, ueId);
+}
+
+/*******************************************************************
+ *
+ * @brief Processed UCI Indication
+ *
+ * @details
+ *
+ * Function : schFcfsSrUciInd
+ *
+ * Functionality: Processing of UCI indication specific to
+ * FCFS scheduling
+ *
+ * @params[in] Pointer to Cell
+ * UE Id
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsSrUciInd(SchCellCb *cellCb, uint16_t ueId)
+{
+ schFcfsAddUeToSchedule(cellCb, ueId);
+}
+
+/*******************************************************************
+ *
+ * @brief Processing of RACH Indication
+ *
+ * @details
+ *
+ * Function : schFcfsProcessRachInd
+ *
+ * Functionality: Processing of RACH Indication specific to
+ * FCFS scheduling
+ *
+ * @params[in] Pointer to Cell Cb
+ * UE Id
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsProcessRachInd(SchCellCb *cellCb, uint16_t ueId)
+{
+ schFcfsAddUeToSchedule(cellCb, ueId);
+}
+
+/*******************************************************************
+ *
+ * @brief Processing of DL HARQ Indication
+ *
+ * @details
+ *
+ * Function : SchFcfsDlHarqInd
+ *
+ * Functionality:
+ *
+ * @params[in]
+ * @return void
+ *
+ * ****************************************************************/
+void SchFcfsDlHarqInd()
+{
+ return;
+}
+
+/*******************************************************************
+ *
+ * @brief Processing of Paging indication
+ *
+ * @details
+ *
+ * Function : schFcfsPagingInd
+ *
+ * Functionality:
+ *
+ * @params[in]
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsPagingInd()
+{
+ return;
+}
+
+/*******************************************************************
+ *
+ * @brief Processing of RACH Resource Request
+ *
+ * @details
+ *
+ * Function : schFcfsRachRsrcReq
+ *
+ * Functionality:
+ *
+ * @params[in]
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsRachRsrcReq()
+{
+ return;
+}
+
+/*******************************************************************
+ *
+ * @brief Processing of RACH Resource Release
+ *
+ * @details
+ *
+ * Function : schFcfsRachRsrcRel
+ *
+ * Functionality:
+ *
+ * @params[in]
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsRachRsrcRel()
+{
+ return;
+}
+
+/*******************************************************************
+ *
+ * @brief Remove entry from HARQ retransmission list
+ *
+ * @details
+ *
+ * Function : schFcfsRemoveFrmDlHqRetxList
+ *
+ * Functionality: Remove entry from HARQ retransmission list
+ *
+ * @params[in] Pointer to UE
+ * Node to be deleted
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsRemoveFrmDlHqRetxList(SchUeCb *ueCb, CmLList *node)
+{
+ SchFcfsUeCb *fcfsUeCb;
+
+ fcfsUeCb = (SchFcfsUeCb *)ueCb->schSpcUeCb;
+ cmLListDelFrm(&fcfsUeCb->hqRetxCb.dlRetxHqList, node);
+}
+
+/*******************************************************************
+ *
+ * @brief Remove entry from HARQ retransmission list
+ *
+ * @details
+ *
+ * Function : schFcfsRemoveFrmUlHqRetxList
+ *
+ * Functionality: Remove entry from HARQ retransmission list
+ *
+ * @params[in] Pointer to UE
+ * Node to be deleted
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsRemoveFrmUlHqRetxList(SchUeCb *ueCb, CmLList *node)
+{
+ SchFcfsUeCb *fcfsUeCb;
+
+ fcfsUeCb = (SchFcfsUeCb *)ueCb->schSpcUeCb;
+ cmLListDelFrm(&fcfsUeCb->hqRetxCb.ulRetxHqList, node);
+}
+
+/*******************************************************************
+ *
+ * @brief Remove UE from Scheduling List
+ *
+ * @details
+ *
+ * Function : schFcfsRemoveUeFrmScheduleLst
+ *
+ * Functionality: Remove UE from Scheduling List
+ *
+ * @params[in] Pointer to Cell
+ * Node to be removed
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsRemoveUeFrmScheduleLst(SchCellCb *cell, CmLList *node)
+{
+ SchFcfsCellCb *fcfsCell;
+
+ fcfsCell = (SchFcfsCellCb *)cell->schSpcCell;
+ SCH_FREE(node->node, sizeof(uint8_t));
+ deleteNodeFromLList(&fcfsCell->ueToBeScheduled, node);
+}
+
+/*******************************************************************
+ *
+ * @brief Handler to calculate TBS size for BSR requested
+ *
+ * @details
+ *
+ * Function : schCalculateUlTbs
+ *
+ * Functionality: Function will note the required TBS for each LCGIDX and use
+ * the Priority LCG List and RRM policy to allocate the TBS size
+ *
+ * @params [in] ueCb (Pointer to UE CB)
+ * [in] puschTime (Time slot where PUSCH will be sent)
+ * [in] symbLen (No of Symbols used for PUSCH transmission)
+ * [out] startPrb(Pointer to startPRB which will be calculated while
+ * finding the best Free Block)
+ * [out] totTBS(Pointer to total TBS size)
+ * [in] isRetx (to indicate retransmission)
+ * [in] hqP (UL Harq process pointer)
+ *
+ * @return uint8_t : ROK > Scheduling of UL grant is successful
+ * RFAILED > vice versa
+ *
+ * ****************************************************************/
+uint8_t schCalculateUlTbs(SchUeCb *ueCb, SlotTimingInfo puschTime, uint8_t symbLen,\
+ uint16_t *startPrb, uint32_t *totTBS, bool isRetx, SchUlHqProcCb *hqP, SchFcfsHqProcCb *fcfsHqP)
+{
+ uint16_t mcsIdx = 0;
+ CmLListCp *lcLL = NULLP;
+ uint16_t lcgIdx = 0, lcId =0, maxFreePRB = 0;
+ uint16_t rsvdDedicatedPRB;
+ *startPrb = 0;
+ *totTBS = 0;
+
+ /* check for BSR */
+ for(lcgIdx=0; lcgIdx<MAX_NUM_LOGICAL_CHANNEL_GROUPS; lcgIdx++)
+ {
+ if(ueCb->bsrInfo[lcgIdx].dataVol == 0)
+ {
+ continue;
+ }
+
+ /*TODO: lcgIdx and LCID has been implemented as one to one mapping.
+ * Need to check the mapping to figure out the LCID and lcgIdx once L2
+ * spec specifies any logic*/
+ lcId = lcgIdx;
+ if(ueCb->ulInfo.ulLcCtxt[lcId].isDedicated)
+ {
+ lcLL = &(fcfsHqP->lcCb.dedLcList);
+ rsvdDedicatedPRB = ueCb->ulInfo.ulLcCtxt[lcId].rsvdDedicatedPRB;
+ }
+ else
+ {
+ lcLL = &(fcfsHqP->lcCb.defLcList);
+ }
+
+ /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
+ if(updateLcListReqPRB(lcLL, lcId, ueCb->bsrInfo[lcgIdx].dataVol) != ROK)
+ {
+ DU_LOG("\nERROR --> SCH: LcgId:%d updation failed",lcId);
+ return RFAILED;
+ }
+ }
+
+ if ((fcfsHqP->lcCb.defLcList.count == 0) && (fcfsHqP->lcCb.dedLcList.count == 0))
+ {
+ if( (ueCb->srRcvd) || (isRetx) )
+ {
+ *startPrb = MAX_NUM_RB;
+ *totTBS = schCalcTbSize(UL_GRANT_SIZE);
+ }
+ /*Returning true when NO Grant is there for UE as this is not scheduling
+ * error*/
+ return ROK;
+ }
+
+ maxFreePRB = searchLargestFreeBlock(ueCb->cellCb, puschTime, startPrb, DIR_UL);
+
+ /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
+ * the list based on RRM policy*/
+
+ /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or
+ * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
+ if(maxFreePRB != 0)
+ {
+ mcsIdx = ueCb->ueCfg.ulModInfo.mcsIndex;
+ if((fcfsHqP->lcCb.dedLcList.count == 0) || ((maxFreePRB < rsvdDedicatedPRB)))
+ {
+ fcfsHqP->lcCb.sharedNumPrb = maxFreePRB;
+ DU_LOG("\nDEBUG --> SCH : UL Only Default Slice is scheduled, sharedPRB Count:%d",\
+ fcfsHqP->lcCb.sharedNumPrb);
+
+ /*PRB Alloc for Default LCs*/
+ prbAllocUsingRRMPolicy(&(fcfsHqP->lcCb.defLcList), FALSE, mcsIdx, symbLen,\
+ &(fcfsHqP->lcCb.sharedNumPrb), NULLP, NULLP,&(ueCb->srRcvd));
+ }
+ else
+ {
+ fcfsHqP->lcCb.sharedNumPrb = maxFreePRB - rsvdDedicatedPRB;
+
+ /*PRB Alloc for Dedicated LCs*/
+ prbAllocUsingRRMPolicy(&(fcfsHqP->lcCb.dedLcList), TRUE, mcsIdx, symbLen,\
+ &(fcfsHqP->lcCb.sharedNumPrb), &(rsvdDedicatedPRB),\
+ NULLP, &(ueCb->srRcvd));
+
+ /*PRB Alloc for Default LCs*/
+ prbAllocUsingRRMPolicy(&(fcfsHqP->lcCb.defLcList), FALSE, mcsIdx, symbLen, \
+ &(fcfsHqP->lcCb.sharedNumPrb), &(rsvdDedicatedPRB),\
+ NULLP,&(ueCb->srRcvd));
+ }
+ }
+ /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
+ * using allocated BO per LC and Update dlMsgAlloc(BO report for MAC*/
+ if(fcfsHqP->lcCb.dedLcList.count != 0)
+ updateGrantSizeForBoRpt(&(fcfsHqP->lcCb.dedLcList), NULLP, ueCb->bsrInfo, totTBS);
+
+ updateGrantSizeForBoRpt(&(fcfsHqP->lcCb.defLcList), NULLP, ueCb->bsrInfo, totTBS);
+
+ /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
+ if (*totTBS == 0)
+ {
+ if(maxFreePRB == 0)
+ {
+ DU_LOG("\nERROR --> SCH : NO FREE PRB!!");
+ }
+ else
+ {
+ /*Schedule the LC for next slot*/
+ DU_LOG("\nDEBUG --> SCH : No LC has been scheduled");
+ }
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Grants resources to LC in uplink
+ *
+ * @details
+ *
+ * Function : schProcessSrOrBsrReq
+ *
+ * Functionality:
+ * Grants resources to LC in uplink
+ *
+ * @params[in] PDCCH Time
+ * PUSCH Time
+ * Start Symbol
+ * Number of symbols
+ * Is retransmission
+ * HARQ process
+ * @return ROK
+ * RFAILED
+ *
+ *******************************************************************/
+uint8_t schFcfsScheduleUlLc(SlotTimingInfo dciTime, SlotTimingInfo puschTime, uint8_t startSymb , uint8_t symbLen, bool isRetx, SchUlHqProcCb **hqP)
+{
+ SchCellCb *cell;
+ SchFcfsHqProcCb *fcfsHqProcCb;
+ uint8_t ret = RFAILED;
+ uint16_t startPrb = 0;
+ uint32_t totDataReq = 0; /* in bytes */
+ SchUeCb *ueCb;
+ SchPuschInfo *puschInfo;
+ DciInfo *dciInfo = NULLP;
+
+ cell = (*hqP)->hqEnt->cell;
+ ueCb = (*hqP)->hqEnt->ue;
+ fcfsHqProcCb = (SchFcfsHqProcCb *)(*hqP)->schSpcUlHqProcCb;
+ ret = schCalculateUlTbs(ueCb, puschTime, symbLen, &startPrb, &totDataReq, isRetx, *hqP, fcfsHqProcCb);
+
+ if(totDataReq > 0 && ret == ROK)
+ {
+ SCH_ALLOC(dciInfo, sizeof(DciInfo));
+ if(!dciInfo)
+ {
+ DU_LOG("\nERROR --> SCH : Memory Allocation failed for dciInfo alloc");
+ if(isRetx != TRUE)
+ {
+ if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
+ updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, RFAILED);
+
+ updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, RFAILED);
+ }
+ return RFAILED;
+ }
+ cell->schDlSlotInfo[dciTime.slot]->ulGrant = dciInfo;
+ memset(dciInfo,0,sizeof(DciInfo));
+
+ /* Update PUSCH allocation */
+ if(schFillPuschAlloc(ueCb, puschTime, totDataReq, startSymb, symbLen, startPrb, isRetx, *hqP) == ROK)
+ {
+ if(cell->schUlSlotInfo[puschTime.slot]->schPuschInfo)
+ {
+ puschInfo = cell->schUlSlotInfo[puschTime.slot]->schPuschInfo;
+ if(puschInfo != NULLP)
+ {
+ /* Fill DCI for UL grant */
+ schFillUlDci(ueCb, puschInfo, dciInfo, isRetx, *hqP);
+ memcpy(&dciInfo->slotIndInfo, &dciTime, sizeof(SlotTimingInfo));
+ ueCb->srRcvd = false;
+ ueCb->bsrRcvd = false;
+ cell->schUlSlotInfo[puschTime.slot]->puschUe = ueCb->ueId;
+ if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
+ updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, ROK);
+ updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, ROK);
+ cmLListAdd2Tail(&(ueCb->hqUlmap[puschTime.slot]->hqList), &(*hqP)->ulSlotLnk);
+ return ROK;
+ }
+ }
+ }
+ if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
+ updateBsrAndLcList(&(fcfsHqProcCb->lcCb.dedLcList), ueCb->bsrInfo, RFAILED);
+ updateBsrAndLcList(&(fcfsHqProcCb->lcCb.defLcList), ueCb->bsrInfo, RFAILED);
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Grants resources to LC in downlink
+ *
+ * @details
+ *
+ * Function : schFcfsScheduleDlLc
+ *
+ * Functionality: Grants resources to LC in uplink
+ *
+ * @params[in] PDCCH Time
+ *
+ * @return ROK
+ * RFAILED
+ *
+ * ****************************************************************/
+uint32_t schFcfsScheduleDlLc(SlotTimingInfo pdcchTime, SlotTimingInfo pdschTime, uint8_t pdschNumSymbols, bool isRetx, SchDlHqProcCb **hqP)
+{
+ SchFcfsHqProcCb *fcfsHqProcCb;
+ SchUeCb *ueCb;
+ uint8_t lcIdx = 0;
+ uint16_t startPrb = 0, maxFreePRB = 0;
+ uint16_t mcsIdx = 0;
+ uint32_t accumalatedSize = 0;
+ CmLListCp *lcLL = NULLP;
+ uint16_t rsvdDedicatedPRB = 0;
+ DlMsgAlloc *dciSlotAlloc;
+
+ /* TX_PAYLOAD_HDR_LEN: Overhead which is to be Added once for any UE while estimating Accumulated TB Size
+ * Following flag added to keep the record whether TX_PAYLOAD_HDR_LEN is added to the first Node getting allocated.
+ * If both Dedicated and Default LC lists are present then First LC in Dedicated List will include this overhead
+ * else if only Default list is present then first node in this List will add this overhead len*/
+ bool isTxPayloadLenAdded = FALSE;
+
+ ueCb = (*hqP)->hqEnt->ue;
+ dciSlotAlloc = (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1];
+ fcfsHqProcCb = (SchFcfsHqProcCb *)((*hqP)->schSpcDlHqProcCb);
+
+ if (isRetx == FALSE)
+ {
+ /*Re-Initalization per UE*/
+ /* scheduled LC data fill */
+ dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo].numLc = 0;
+ isTxPayloadLenAdded = FALSE; /*Re-initlaize the flag for every UE*/
+ accumalatedSize = 0;
+
+ for(lcIdx = 0; lcIdx < MAX_NUM_LC; lcIdx++)
+ {
+ if(ueCb->dlInfo.dlLcCtxt[lcIdx].bo)
+ {
+ /*Check the LC is Dedicated or default and accordingly LCList will
+ * be used*/
+ if(ueCb->dlInfo.dlLcCtxt[lcIdx].isDedicated)
+ {
+ lcLL = &(fcfsHqProcCb->lcCb.dedLcList);
+ rsvdDedicatedPRB = ueCb->dlInfo.dlLcCtxt[lcIdx].rsvdDedicatedPRB;
+ }
+ else
+ {
+ lcLL = &(fcfsHqProcCb->lcCb.defLcList);
+ }
+
+ /*[Step2]: Update the reqPRB and Payloadsize for this LC in the appropriate List*/
+ if(updateLcListReqPRB(lcLL, ueCb->dlInfo.dlLcCtxt[lcIdx].lcId,\
+ (ueCb->dlInfo.dlLcCtxt[lcIdx].bo + MAC_HDR_SIZE)) != ROK)
+ {
+ DU_LOG("\nERROR --> SCH : Updation in LC List Failed");
+ /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
+ if(dciSlotAlloc->numSchedInfo == 0)
+ {
+ SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
+ (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1] = NULL;
+ }
+ else
+ memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
+ return false;
+ }
+ }
+ ueCb->dlInfo.dlLcCtxt[lcIdx].bo = 0;
+ }//End of for loop
+
+ if ((fcfsHqProcCb->lcCb.defLcList.count == 0) && (fcfsHqProcCb->lcCb.dedLcList.count == 0))
+ {
+ DU_LOG("\nDEBUG --> SCH : No pending BO for any LC id\n");
+ UNSET_ONE_BIT((*hqP)->hqEnt->ue->ueId, (*hqP)->hqEnt->cell->boIndBitMap);
+
+ /* Free the dl ded msg info allocated in macSchDlRlcBoInfo */
+ if(dciSlotAlloc->numSchedInfo == 0)
+ {
+ SCH_FREE(dciSlotAlloc, sizeof(DlMsgAlloc));
+ (*hqP)->hqEnt->cell->schDlSlotInfo[pdcchTime.slot]->dlMsgAlloc[ueCb->ueId -1] = NULL;
+ }
+ else
+ memset(&dciSlotAlloc->dlMsgSchedInfo[dciSlotAlloc->numSchedInfo], 0, sizeof(DlMsgSchInfo));
+
+ /*TRUE because this UE has nothing to be scheduled*/
+ return true;
+ }
+ }
+
+ /*[Step3]: Calculate Best FREE BLOCK with MAX PRB count*/
+ maxFreePRB = searchLargestFreeBlock((*hqP)->hqEnt->cell, pdschTime, &startPrb, DIR_DL);
+
+ /*[Step4]: Estimation of PRB and BO which can be allocated to each LC in
+ * the list based on RRM policy*/
+
+ /*Either this UE contains no reservedPRB pool fir dedicated S-NSSAI or
+ * Num of Free PRB available is not enough to reserve Dedicated PRBs*/
+ if(isRetx == FALSE)
+ {
+ if(maxFreePRB != 0)
+ {
+ mcsIdx = ueCb->ueCfg.dlModInfo.mcsIndex;
+
+ if((fcfsHqProcCb->lcCb.dedLcList.count == NULLP) || ((maxFreePRB < rsvdDedicatedPRB)))
+ {
+ fcfsHqProcCb->lcCb.sharedNumPrb = maxFreePRB;
+ DU_LOG("\nDEBUG --> SCH : DL Only Default Slice is scheduled, sharedPRB Count:%d",\
+ fcfsHqProcCb->lcCb.sharedNumPrb);
+
+ /*PRB Alloc for Default LCs*/
+ prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.defLcList), FALSE, mcsIdx, pdschNumSymbols,\
+ &(fcfsHqProcCb->lcCb.sharedNumPrb), NULLP, &isTxPayloadLenAdded, NULLP);
+ }
+ else
+ {
+ fcfsHqProcCb->lcCb.sharedNumPrb = maxFreePRB - rsvdDedicatedPRB;
+ /*PRB Alloc for Dedicated LCs*/
+ prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.dedLcList), TRUE, mcsIdx, pdschNumSymbols,\
+ &(fcfsHqProcCb->lcCb.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
+
+ /*PRB Alloc for Default LCs*/
+ prbAllocUsingRRMPolicy(&(fcfsHqProcCb->lcCb.defLcList), FALSE, mcsIdx, pdschNumSymbols, \
+ &(fcfsHqProcCb->lcCb.sharedNumPrb), &(rsvdDedicatedPRB), &isTxPayloadLenAdded, NULLP);
+ }
+ }
+ }
+
+ /*[Step5]:Traverse each LCID in LcList to calculate the exact Scheduled Bytes
+ * using allocated BO per LC and Update dlMsgAlloc BO report for MAC */
+ if (isRetx == FALSE)
+ {
+ if(fcfsHqProcCb->lcCb.dedLcList.count != 0)
+ updateGrantSizeForBoRpt(&(fcfsHqProcCb->lcCb.dedLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
+
+ updateGrantSizeForBoRpt(&(fcfsHqProcCb->lcCb.defLcList), dciSlotAlloc, NULLP, &(accumalatedSize));
+ }
+ else
+ {
+ accumalatedSize = (*hqP)->tbInfo[0].tbSzReq;
+ }
+
+ /*Below case will hit if NO LC(s) are allocated due to resource crunch*/
+ if (!accumalatedSize)
+ {
+ if(maxFreePRB == 0)
+ {
+ DU_LOG("\nERROR --> SCH : NO FREE PRB!!");
+ }
+ else
+ {
+ /*Schedule the LC for next slot*/
+ DU_LOG("\nDEBUG --> SCH : No LC has been scheduled");
+ }
+ /* Not Freeing dlMsgAlloc as ZERO BO REPORT to be sent to RLC so that
+ * Allocation can be done in next slot*/
+ accumalatedSize = 0;
+ }
+
+ return accumalatedSize;
+}
+
+/*******************************************************************
+ *
+ * @brief Scheduling of Slots in UL And DL
+ *
+ * @details
+ *
+ * Function : schFcfsScheduleSlot
+ *
+ * Functionality: Scheduling of slots in UL and DL specific to
+ * FCFS scheduling
+ *
+ * @params[in] Pointer to Cell
+ * Slot timing info
+ * Scheduler instance
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsScheduleSlot(SchCellCb *cell, SlotTimingInfo *slotInd, Inst schInst)
+{
+ SchFcfsCellCb *fcfsCell;
+ SchFcfsUeCb *fcfsUeCb;
+ SchDlHqProcCb *hqP = NULLP;
+ SchUlHqProcCb *ulHqP = NULLP;
+ CmLList *pendingUeNode;
+ CmLList *node;
+ uint8_t ueId;
+ bool isRarPending = false, isRarScheduled = false;
+ bool isMsg4Pending = false, isMsg4Scheduled = false;
+ bool isDlMsgPending = false, isDlMsgScheduled = false;
+ bool isUlGrantPending = false, isUlGrantScheduled = false;
+
+ fcfsCell = (SchFcfsCellCb *)cell->schSpcCell;
+
+ /* Select first UE in the linked list to be scheduled next */
+ pendingUeNode = fcfsCell->ueToBeScheduled.first;
+ if(pendingUeNode)
+ {
+ if(pendingUeNode->node)
+ {
+ ueId = *(uint8_t *)(pendingUeNode->node);
+ fcfsUeCb = (SchFcfsUeCb *)cell->ueCb[ueId-1].schSpcUeCb;
+
+ /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and
+ * PUSCH to receive MSG3 as per k0-k2 configuration*/
+ if(cell->raReq[ueId-1] != NULLP)
+ {
+ isRarPending = true;
+ isRarScheduled = schProcessRaReq(schInst, cell, *slotInd, ueId);
+ }
+
+ /*MSG3 retransmisson*/
+ if(cell->raCb[ueId-1].retxMsg3HqProc)
+ {
+ schMsg3RetxSchedulingForUe(&(cell->raCb[ueId-1]));
+ }
+
+ /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and
+ * PUCCH to receive UL msg as per k0-k1 configuration */
+ if (cell->ueCb[ueId-1].retxMsg4HqProc) //should work from dlmap later tbd
+ {
+ /* Retransmission of MSG4 */
+ isMsg4Pending = true;
+ if(schProcessMsg4Req(cell, *slotInd, ueId, TRUE, &cell->ueCb[ueId-1].retxMsg4HqProc) == ROK)
+ isMsg4Scheduled = true;
+ }
+ else
+ {
+ /* First transmission of MSG4 */
+ if(cell->raCb[ueId-1].msg4recvd)
+ {
+ isMsg4Pending = true;
+ if(schProcessMsg4Req(cell, *slotInd, ueId, FALSE, &cell->ueCb[ueId-1].msg4HqProc) == ROK)
+ isMsg4Scheduled = true;
+
+ /* If MSG4 scheduling failed, free the newly assigned HARQ process */
+ if(!isMsg4Scheduled)
+ schDlReleaseHqProcess(cell->ueCb[ueId-1].msg4HqProc);
+ }
+ }
+
+ if(isRarPending || isMsg4Pending)
+ {
+ /* If RAR or MSG is successfully scheduled then
+ * remove UE from linked list since no pending msgs for this UE */
+ if(isRarScheduled || isMsg4Scheduled)
+ {
+ schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
+ }
+ /* If RAR/MSG4 is pending but couldnt be scheduled then,
+ * put this UE at the end of linked list to be scheduled later */
+ else
+ {
+ cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
+ }
+ }
+
+#ifdef NR_DRX
+ if((cell->ueCb[ueId-1].ueDrxInfoPres == true) && (cell->ueCb[ueId-1].drxUeCb.drxDlUeActiveStatus != true))
+ {
+ if(pendingUeNode->node)
+ {
+ cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
+ }
+ }
+ else
+#endif
+ {
+
+ /* DL Data */
+ node = NULLP;
+ if(fcfsUeCb)
+ node = fcfsUeCb->hqRetxCb.dlRetxHqList.first;
+ if(node != NULLP)
+ {
+ /* DL Data ReTransmisson */
+ isDlMsgPending = true;
+ isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, TRUE, ((SchDlHqProcCb**) &(node->node)));
+ if(isDlMsgScheduled)
+ {
+#ifdef NR_DRX
+ schDrxStopDlHqRetxTmr(cell, &cell->ueCb[ueId-1], ((SchDlHqProcCb**) &(node->node)));
+#endif
+ schFcfsRemoveFrmDlHqRetxList(&cell->ueCb[ueId-1], node);
+ }
+ }
+ else
+ {
+ /* DL Data new transmission */
+ if((cell->boIndBitMap) & (1<<ueId))
+ {
+ isDlMsgPending = true;
+ isDlMsgScheduled = schFillBoGrantDlSchedInfo(cell, *slotInd, ueId, FALSE, &hqP);
+
+ /* If DL scheduling failed, free the newly assigned HARQ process */
+ if(!isDlMsgScheduled)
+ schDlReleaseHqProcess(hqP);
+ else
+ {
+#ifdef NR_DRX
+ schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], PHY_DELTA_DL + SCHED_DELTA);
+#endif
+ }
+ }
+ }
+
+ /* Scheduling of UL grant */
+ node = NULLP;
+ if(fcfsUeCb)
+ node = fcfsUeCb->hqRetxCb.ulRetxHqList.first;
+ if(node != NULLP)
+ {
+ /* UL Data ReTransmisson */
+ isUlGrantPending = true;
+ isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, TRUE, (SchUlHqProcCb**) &(node->node));
+ if(isUlGrantScheduled)
+ {
+#ifdef NR_DRX
+ schDrxStopUlHqRetxTmr(cell, &cell->ueCb[ueId-1], ((SchUlHqProcCb**) &(node->node)));
+#endif
+ schFcfsRemoveFrmUlHqRetxList(&cell->ueCb[ueId-1], node);
+ }
+ }
+ else
+ {
+ /* UL Data new transmission */
+ if(cell->ueCb[ueId-1].srRcvd || cell->ueCb[ueId-1].bsrRcvd)
+ {
+ isUlGrantPending = true;
+ isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, FALSE, &ulHqP);
+ if(!isUlGrantScheduled)
+ schUlReleaseHqProcess(ulHqP, FALSE);
+ else
+ {
+#ifdef NR_DRX
+ schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], PHY_DELTA_UL + SCHED_DELTA);
+#endif
+ }
+ }
+ }
+
+ if(!isUlGrantPending && !isDlMsgPending)
+ {
+ /* No action required */
+ }
+ else if((isUlGrantPending && !isUlGrantScheduled) || (isDlMsgPending && !isDlMsgScheduled))
+ {
+ cmLListAdd2Tail(&fcfsCell->ueToBeScheduled, cmLListDelFrm(&fcfsCell->ueToBeScheduled, pendingUeNode));
+ }
+ else
+ {
+ schFcfsRemoveUeFrmScheduleLst(cell, pendingUeNode);
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Initializes all function pointers to FCFS function handler
+ *
+ * @details
+ *
+ * Function : schFcfsAllApisInit
+ *
+ * Functionality: Initializes all function pointers to FCFS
+ * function handler
+ *
+ * @params[in] Function pointer array
+ * @return void
+ *
+ * ****************************************************************/
+void schFcfsAllApisInit(SchAllApis *allFcfsApi)
+{
+ /* Interface API function pointers */
+ allFcfsApi->SchCellCfgReq = schFcfsCellCfgReq;
+ allFcfsApi->SchCellDeleteReq = schFcfsCellDelReq;
+ allFcfsApi->SchAddUeConfigReq = SchFcfsAddUeConfigReq;
+ allFcfsApi->SchModUeConfigReq = SchFcfsModUeConfigReq;
+ allFcfsApi->SchUeDeleteReq = SchFcfsUeDeleteReq;
+ allFcfsApi->SchDlHarqInd = SchFcfsDlHarqInd;
+ allFcfsApi->SchCrcInd = schFcfsProcessCrcInd;
+ allFcfsApi->SchRachInd = schFcfsProcessRachInd;
+ allFcfsApi->SchPagingInd = schFcfsPagingInd;
+ allFcfsApi->SchRachRsrcReq = schFcfsRachRsrcReq;
+ allFcfsApi->SchRachRsrcRel = schFcfsRachRsrcRel;
+ allFcfsApi->SchDlRlcBoInfo = schFcfsDlRlcBoInfo;
+ allFcfsApi->SchSrUciInd = schFcfsSrUciInd;
+ allFcfsApi->SchBsr = schFcfsBsr;
+
+ /* Internal API function pointers */
+ allFcfsApi->SchAddToDlHqRetxList = schFcfsAddToDlHqRetxList;
+ allFcfsApi->SchAddToUlHqRetxList = schFcfsAddToUlHqRetxList;
+ allFcfsApi->SchRemoveFrmDlHqRetxList = schFcfsRemoveFrmDlHqRetxList;
+ allFcfsApi->SchRemoveFrmUlHqRetxList = schFcfsRemoveFrmUlHqRetxList;
+ allFcfsApi->SchAddUeToSchedule = schFcfsAddUeToSchedule;
+ allFcfsApi->SchRemoveUeFrmScheduleLst = schFcfsRemoveUeFrmScheduleLst;
+ allFcfsApi->SchInitDlHqProcCb = schFcfsInitDlHqProcCb;
+ allFcfsApi->SchInitUlHqProcCb = schFcfsInitUlHqProcCb;
+ allFcfsApi->SchFreeDlHqProcCb = schFcfsFreeDlHqProcCb;
+ allFcfsApi->SchFreeUlHqProcCb = schFcfsFreeUlHqProcCb;
+ allFcfsApi->SchDeleteDlHqProcCb = schFcfsDeleteDlHqProcCb;
+ allFcfsApi->SchDeleteUlHqProcCb = schFcfsDeleteUlHqProcCb;
+ allFcfsApi->SchScheduleSlot = schFcfsScheduleSlot;
+ allFcfsApi->SchScheduleDlLc = schFcfsScheduleDlLc;
+ allFcfsApi->SchScheduleUlLc = schFcfsScheduleUlLc;
+}
+/**********************************************************************
+ End of file
+**********************************************************************/
+